summaryrefslogtreecommitdiffstats
path: root/private/windbg
diff options
context:
space:
mode:
Diffstat (limited to 'private/windbg')
-rw-r--r--private/windbg/common.src36
-rw-r--r--private/windbg/dirs28
-rw-r--r--private/windbg/doc/newuser.docbin0 -> 103424 bytes
-rw-r--r--private/windbg/doc/newuser.txt258
-rw-r--r--private/windbg/doc/od.docbin0 -> 70923 bytes
-rw-r--r--private/windbg/doc/tools/c2rtf.c723
-rw-r--r--private/windbg/doc/tools/makefile6
-rw-r--r--private/windbg/doc/tools/sources33
-rw-r--r--private/windbg/doc/wrkspace.bmpbin0 -> 70198 bytes
-rw-r--r--private/windbg/driver/crash/crash.bmpbin0 -> 2166 bytes
-rw-r--r--private/windbg/driver/crash/crash.c538
-rw-r--r--private/windbg/driver/crash/crash.icobin0 -> 1046 bytes
-rw-r--r--private/windbg/driver/crash/crash.rc30
-rw-r--r--private/windbg/driver/crash/crash.wavbin0 -> 50176 bytes
-rw-r--r--private/windbg/driver/crash/crashdrv.dbgbin0 -> 95588 bytes
-rw-r--r--private/windbg/driver/crash/crashdrv.sysbin0 -> 5312 bytes
-rw-r--r--private/windbg/driver/crash/crashrc.h7
-rw-r--r--private/windbg/driver/crash/makefile6
-rw-r--r--private/windbg/driver/crash/makefile.inc7
-rw-r--r--private/windbg/driver/crash/sources18
-rw-r--r--private/windbg/driver/crashdrv/crashdrv.c225
-rw-r--r--private/windbg/driver/crashdrv/crashdrv.h58
-rw-r--r--private/windbg/driver/crashdrv/crashdrv.rc11
-rw-r--r--private/windbg/driver/crashdrv/dirs1
-rw-r--r--private/windbg/driver/crashdrv/driver/makefile6
-rw-r--r--private/windbg/driver/crashdrv/driver/sources12
-rw-r--r--private/windbg/driver/crashdrv/tests.c266
-rw-r--r--private/windbg/driver/crashdrv/tests/install.c83
-rw-r--r--private/windbg/driver/crashdrv/tests/install.rc11
-rw-r--r--private/windbg/driver/crashdrv/tests/makefile6
-rw-r--r--private/windbg/driver/crashdrv/tests/makefile.inc3
-rw-r--r--private/windbg/driver/crashdrv/tests/sources17
-rw-r--r--private/windbg/driver/crashdrv/tests/test.c295
-rw-r--r--private/windbg/driver/crashdrv/tests/test.rc11
-rw-r--r--private/windbg/driver/dirs1
-rw-r--r--private/windbg/eecan/common.inc50
-rw-r--r--private/windbg/eecan/cxassert.h38
-rw-r--r--private/windbg/eecan/debapi.c1812
-rw-r--r--private/windbg/eecan/debbind.c7616
-rw-r--r--private/windbg/eecan/debdef.h115
-rw-r--r--private/windbg/eecan/deberr.c83
-rw-r--r--private/windbg/eecan/debeval.c5441
-rw-r--r--private/windbg/eecan/debexpr.h1247
-rw-r--r--private/windbg/eecan/debfmt.c1890
-rw-r--r--private/windbg/eecan/deblex.c963
-rw-r--r--private/windbg/eecan/deblexer.c330
-rw-r--r--private/windbg/eecan/debops.h138
-rw-r--r--private/windbg/eecan/debparse.c1187
-rw-r--r--private/windbg/eecan/debsrch.c1143
-rw-r--r--private/windbg/eecan/debsup.c2049
-rw-r--r--private/windbg/eecan/debsym.c6674
-rw-r--r--private/windbg/eecan/debsym.h44
-rw-r--r--private/windbg/eecan/debtree.c335
-rw-r--r--private/windbg/eecan/debtyper.c1696
-rw-r--r--private/windbg/eecan/debutil.c2142
-rw-r--r--private/windbg/eecan/debwalk.c1010
-rw-r--r--private/windbg/eecan/dirs19
-rw-r--r--private/windbg/eecan/eeformat.c642
-rw-r--r--private/windbg/eecan/errors.h76
-rw-r--r--private/windbg/eecan/expr2.z274
-rw-r--r--private/windbg/eecan/fmtstr.h141
-rw-r--r--private/windbg/eecan/p_alpha/debapi.c4
-rw-r--r--private/windbg/eecan/p_alpha/debbind.c4
-rw-r--r--private/windbg/eecan/p_alpha/deberr.c4
-rw-r--r--private/windbg/eecan/p_alpha/debeval.c4
-rw-r--r--private/windbg/eecan/p_alpha/debfmt.c4
-rw-r--r--private/windbg/eecan/p_alpha/deblex.c4
-rw-r--r--private/windbg/eecan/p_alpha/deblexer.c4
-rw-r--r--private/windbg/eecan/p_alpha/debparse.c4
-rw-r--r--private/windbg/eecan/p_alpha/debsrch.c4
-rw-r--r--private/windbg/eecan/p_alpha/debsup.c4
-rw-r--r--private/windbg/eecan/p_alpha/debsym.c4
-rw-r--r--private/windbg/eecan/p_alpha/debtree.c4
-rw-r--r--private/windbg/eecan/p_alpha/debtyper.c4
-rw-r--r--private/windbg/eecan/p_alpha/debutil.c4
-rw-r--r--private/windbg/eecan/p_alpha/debwalk.c4
-rw-r--r--private/windbg/eecan/p_alpha/eecan.rc14
-rw-r--r--private/windbg/eecan/p_alpha/eecanalp.def4
-rw-r--r--private/windbg/eecan/p_alpha/eeformat.c4
-rw-r--r--private/windbg/eecan/p_alpha/makefile6
-rw-r--r--private/windbg/eecan/p_alpha/makefile.inc26
-rw-r--r--private/windbg/eecan/p_alpha/precomp.h57
-rw-r--r--private/windbg/eecan/p_alpha/r10math.c4
-rw-r--r--private/windbg/eecan/p_alpha/sources76
-rw-r--r--private/windbg/eecan/p_i386/debapi.c4
-rw-r--r--private/windbg/eecan/p_i386/debbind.c4
-rw-r--r--private/windbg/eecan/p_i386/deberr.c4
-rw-r--r--private/windbg/eecan/p_i386/debeval.c4
-rw-r--r--private/windbg/eecan/p_i386/debfmt.c4
-rw-r--r--private/windbg/eecan/p_i386/deblex.c4
-rw-r--r--private/windbg/eecan/p_i386/deblexer.c4
-rw-r--r--private/windbg/eecan/p_i386/debparse.c4
-rw-r--r--private/windbg/eecan/p_i386/debsrch.c4
-rw-r--r--private/windbg/eecan/p_i386/debsup.c4
-rw-r--r--private/windbg/eecan/p_i386/debsym.c4
-rw-r--r--private/windbg/eecan/p_i386/debtree.c4
-rw-r--r--private/windbg/eecan/p_i386/debtyper.c4
-rw-r--r--private/windbg/eecan/p_i386/debutil.c4
-rw-r--r--private/windbg/eecan/p_i386/debwalk.c4
-rw-r--r--private/windbg/eecan/p_i386/eecan.rc14
-rw-r--r--private/windbg/eecan/p_i386/eecanx86.def4
-rw-r--r--private/windbg/eecan/p_i386/eeformat.c4
-rw-r--r--private/windbg/eecan/p_i386/makefile6
-rw-r--r--private/windbg/eecan/p_i386/makefile.inc26
-rw-r--r--private/windbg/eecan/p_i386/precomp.h57
-rw-r--r--private/windbg/eecan/p_i386/r10math.c4
-rw-r--r--private/windbg/eecan/p_i386/sources76
-rw-r--r--private/windbg/eecan/p_mips/debapi.c4
-rw-r--r--private/windbg/eecan/p_mips/debbind.c4
-rw-r--r--private/windbg/eecan/p_mips/deberr.c4
-rw-r--r--private/windbg/eecan/p_mips/debeval.c4
-rw-r--r--private/windbg/eecan/p_mips/debfmt.c4
-rw-r--r--private/windbg/eecan/p_mips/deblex.c4
-rw-r--r--private/windbg/eecan/p_mips/deblexer.c4
-rw-r--r--private/windbg/eecan/p_mips/debparse.c4
-rw-r--r--private/windbg/eecan/p_mips/debsrch.c4
-rw-r--r--private/windbg/eecan/p_mips/debsup.c4
-rw-r--r--private/windbg/eecan/p_mips/debsym.c4
-rw-r--r--private/windbg/eecan/p_mips/debtree.c4
-rw-r--r--private/windbg/eecan/p_mips/debtyper.c4
-rw-r--r--private/windbg/eecan/p_mips/debutil.c4
-rw-r--r--private/windbg/eecan/p_mips/debwalk.c4
-rw-r--r--private/windbg/eecan/p_mips/eecan.rc14
-rw-r--r--private/windbg/eecan/p_mips/eecanmip.def4
-rw-r--r--private/windbg/eecan/p_mips/eeformat.c4
-rw-r--r--private/windbg/eecan/p_mips/makefile6
-rw-r--r--private/windbg/eecan/p_mips/makefile.inc26
-rw-r--r--private/windbg/eecan/p_mips/precomp.h57
-rw-r--r--private/windbg/eecan/p_mips/r10math.c4
-rw-r--r--private/windbg/eecan/p_mips/sources75
-rw-r--r--private/windbg/eecan/p_ppc/debapi.c4
-rw-r--r--private/windbg/eecan/p_ppc/debbind.c4
-rw-r--r--private/windbg/eecan/p_ppc/deberr.c4
-rw-r--r--private/windbg/eecan/p_ppc/debeval.c4
-rw-r--r--private/windbg/eecan/p_ppc/debfmt.c4
-rw-r--r--private/windbg/eecan/p_ppc/deblex.c4
-rw-r--r--private/windbg/eecan/p_ppc/deblexer.c4
-rw-r--r--private/windbg/eecan/p_ppc/debparse.c4
-rw-r--r--private/windbg/eecan/p_ppc/debsrch.c4
-rw-r--r--private/windbg/eecan/p_ppc/debsup.c4
-rw-r--r--private/windbg/eecan/p_ppc/debsym.c4
-rw-r--r--private/windbg/eecan/p_ppc/debtree.c4
-rw-r--r--private/windbg/eecan/p_ppc/debtyper.c4
-rw-r--r--private/windbg/eecan/p_ppc/debutil.c4
-rw-r--r--private/windbg/eecan/p_ppc/debwalk.c4
-rw-r--r--private/windbg/eecan/p_ppc/eecan.rc14
-rw-r--r--private/windbg/eecan/p_ppc/eecanppc.def4
-rw-r--r--private/windbg/eecan/p_ppc/eeformat.c4
-rw-r--r--private/windbg/eecan/p_ppc/makefile6
-rw-r--r--private/windbg/eecan/p_ppc/makefile.inc26
-rw-r--r--private/windbg/eecan/p_ppc/precomp.h56
-rw-r--r--private/windbg/eecan/p_ppc/r10math.c4
-rw-r--r--private/windbg/eecan/p_ppc/sources76
-rw-r--r--private/windbg/eecan/r10math.c575
-rw-r--r--private/windbg/eecan/r10math.h15
-rw-r--r--private/windbg/eecan/shfunc.h186
-rw-r--r--private/windbg/eecxx/dirs19
-rw-r--r--private/windbg/eecxx/p_alpha/debapi.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debbind.c4
-rw-r--r--private/windbg/eecxx/p_alpha/deberr.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debeval.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debfmt.c4
-rw-r--r--private/windbg/eecxx/p_alpha/deblex.c4
-rw-r--r--private/windbg/eecxx/p_alpha/deblexer.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debparse.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debsrch.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debsup.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debsym.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debtree.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debtyper.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debutil.c4
-rw-r--r--private/windbg/eecxx/p_alpha/debwalk.c4
-rw-r--r--private/windbg/eecxx/p_alpha/eecxx.rc14
-rw-r--r--private/windbg/eecxx/p_alpha/eecxxalp.def4
-rw-r--r--private/windbg/eecxx/p_alpha/eeformat.c4
-rw-r--r--private/windbg/eecxx/p_alpha/makefile6
-rw-r--r--private/windbg/eecxx/p_alpha/makefile.inc26
-rw-r--r--private/windbg/eecxx/p_alpha/precomp.h56
-rw-r--r--private/windbg/eecxx/p_alpha/r10math.c4
-rw-r--r--private/windbg/eecxx/p_alpha/sources75
-rw-r--r--private/windbg/eecxx/p_i386/debapi.c4
-rw-r--r--private/windbg/eecxx/p_i386/debbind.c4
-rw-r--r--private/windbg/eecxx/p_i386/deberr.c4
-rw-r--r--private/windbg/eecxx/p_i386/debeval.c4
-rw-r--r--private/windbg/eecxx/p_i386/debfmt.c4
-rw-r--r--private/windbg/eecxx/p_i386/deblex.c4
-rw-r--r--private/windbg/eecxx/p_i386/deblexer.c4
-rw-r--r--private/windbg/eecxx/p_i386/debparse.c4
-rw-r--r--private/windbg/eecxx/p_i386/debsrch.c4
-rw-r--r--private/windbg/eecxx/p_i386/debsup.c4
-rw-r--r--private/windbg/eecxx/p_i386/debsym.c4
-rw-r--r--private/windbg/eecxx/p_i386/debtree.c4
-rw-r--r--private/windbg/eecxx/p_i386/debtyper.c4
-rw-r--r--private/windbg/eecxx/p_i386/debutil.c4
-rw-r--r--private/windbg/eecxx/p_i386/debwalk.c4
-rw-r--r--private/windbg/eecxx/p_i386/eecxx.rc14
-rw-r--r--private/windbg/eecxx/p_i386/eecxxx86.def4
-rw-r--r--private/windbg/eecxx/p_i386/eeformat.c4
-rw-r--r--private/windbg/eecxx/p_i386/makefile6
-rw-r--r--private/windbg/eecxx/p_i386/makefile.inc26
-rw-r--r--private/windbg/eecxx/p_i386/precomp.h56
-rw-r--r--private/windbg/eecxx/p_i386/r10math.c4
-rw-r--r--private/windbg/eecxx/p_i386/sources74
-rw-r--r--private/windbg/eecxx/p_mips/debapi.c4
-rw-r--r--private/windbg/eecxx/p_mips/debbind.c4
-rw-r--r--private/windbg/eecxx/p_mips/deberr.c4
-rw-r--r--private/windbg/eecxx/p_mips/debeval.c4
-rw-r--r--private/windbg/eecxx/p_mips/debfmt.c4
-rw-r--r--private/windbg/eecxx/p_mips/deblex.c4
-rw-r--r--private/windbg/eecxx/p_mips/deblexer.c4
-rw-r--r--private/windbg/eecxx/p_mips/debparse.c4
-rw-r--r--private/windbg/eecxx/p_mips/debsrch.c4
-rw-r--r--private/windbg/eecxx/p_mips/debsup.c4
-rw-r--r--private/windbg/eecxx/p_mips/debsym.c4
-rw-r--r--private/windbg/eecxx/p_mips/debtree.c4
-rw-r--r--private/windbg/eecxx/p_mips/debtyper.c4
-rw-r--r--private/windbg/eecxx/p_mips/debutil.c4
-rw-r--r--private/windbg/eecxx/p_mips/debwalk.c4
-rw-r--r--private/windbg/eecxx/p_mips/eecxx.rc14
-rw-r--r--private/windbg/eecxx/p_mips/eecxxmip.def4
-rw-r--r--private/windbg/eecxx/p_mips/eeformat.c4
-rw-r--r--private/windbg/eecxx/p_mips/makefile6
-rw-r--r--private/windbg/eecxx/p_mips/makefile.inc26
-rw-r--r--private/windbg/eecxx/p_mips/precomp.h56
-rw-r--r--private/windbg/eecxx/p_mips/r10math.c4
-rw-r--r--private/windbg/eecxx/p_mips/sources74
-rw-r--r--private/windbg/eecxx/p_ppc/debapi.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debbind.c4
-rw-r--r--private/windbg/eecxx/p_ppc/deberr.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debeval.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debfmt.c4
-rw-r--r--private/windbg/eecxx/p_ppc/deblex.c4
-rw-r--r--private/windbg/eecxx/p_ppc/deblexer.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debparse.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debsrch.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debsup.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debsym.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debtree.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debtyper.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debutil.c4
-rw-r--r--private/windbg/eecxx/p_ppc/debwalk.c4
-rw-r--r--private/windbg/eecxx/p_ppc/eecxx.rc14
-rw-r--r--private/windbg/eecxx/p_ppc/eecxxppc.def4
-rw-r--r--private/windbg/eecxx/p_ppc/eeformat.c4
-rw-r--r--private/windbg/eecxx/p_ppc/makefile6
-rw-r--r--private/windbg/eecxx/p_ppc/makefile.inc26
-rw-r--r--private/windbg/eecxx/p_ppc/precomp.h56
-rw-r--r--private/windbg/eecxx/p_ppc/r10math.c4
-rw-r--r--private/windbg/eecxx/p_ppc/sources74
-rw-r--r--private/windbg/em/biavst.h158
-rw-r--r--private/windbg/em/common.inc39
-rw-r--r--private/windbg/em/dirs20
-rw-r--r--private/windbg/em/em.rc14
-rw-r--r--private/windbg/em/emdata.h286
-rw-r--r--private/windbg/em/emdp.c3971
-rw-r--r--private/windbg/em/emdp2.c2528
-rw-r--r--private/windbg/em/emdp3.c1233
-rw-r--r--private/windbg/em/emerror.h61
-rw-r--r--private/windbg/em/emproto.h214
-rw-r--r--private/windbg/em/p_alpha/asm.c780
-rw-r--r--private/windbg/em/p_alpha/asmfront.c102
-rw-r--r--private/windbg/em/p_alpha/d3.c890
-rw-r--r--private/windbg/em/p_alpha/em.rc1
-rw-r--r--private/windbg/em/p_alpha/emalp.def5
-rw-r--r--private/windbg/em/p_alpha/emdp.c4
-rw-r--r--private/windbg/em/p_alpha/emdp2.c4
-rw-r--r--private/windbg/em/p_alpha/emdp3.c4
-rw-r--r--private/windbg/em/p_alpha/emdpdev.c1254
-rw-r--r--private/windbg/em/p_alpha/flags.h10
-rw-r--r--private/windbg/em/p_alpha/kdalpha.h5
-rw-r--r--private/windbg/em/p_alpha/makefile6
-rw-r--r--private/windbg/em/p_alpha/makefile.inc25
-rw-r--r--private/windbg/em/p_alpha/ntasm.h25
-rw-r--r--private/windbg/em/p_alpha/ntdis.h191
-rw-r--r--private/windbg/em/p_alpha/optable.c1289
-rw-r--r--private/windbg/em/p_alpha/optable.h123
-rw-r--r--private/windbg/em/p_alpha/precomp.h67
-rw-r--r--private/windbg/em/p_alpha/regs.h77
-rw-r--r--private/windbg/em/p_alpha/sources66
-rw-r--r--private/windbg/em/p_alpha/strings.h423
-rw-r--r--private/windbg/em/p_alpha/wintrans.c4
-rw-r--r--private/windbg/em/p_i386/asm.c1116
-rw-r--r--private/windbg/em/p_i386/asm.h202
-rw-r--r--private/windbg/em/p_i386/asmexp.c1576
-rw-r--r--private/windbg/em/p_i386/asmtpl.c1660
-rw-r--r--private/windbg/em/p_i386/d3.c1834
-rw-r--r--private/windbg/em/p_i386/d3.h1287
-rw-r--r--private/windbg/em/p_i386/d3em.c262
-rw-r--r--private/windbg/em/p_i386/em.rc1
-rw-r--r--private/windbg/em/p_i386/emdp.c4
-rw-r--r--private/windbg/em/p_i386/emdp2.c4
-rw-r--r--private/windbg/em/p_i386/emdp3.c4
-rw-r--r--private/windbg/em/p_i386/emdpdev.c1802
-rw-r--r--private/windbg/em/p_i386/emx86.def4
-rw-r--r--private/windbg/em/p_i386/flags.h9
-rw-r--r--private/windbg/em/p_i386/makefile6
-rw-r--r--private/windbg/em/p_i386/makefile.inc27
-rw-r--r--private/windbg/em/p_i386/precomp.h67
-rw-r--r--private/windbg/em/p_i386/regs.h71
-rw-r--r--private/windbg/em/p_i386/sources63
-rw-r--r--private/windbg/em/p_i386/strings.c4
-rw-r--r--private/windbg/em/p_i386/strings.h119
-rw-r--r--private/windbg/em/p_i386/wintrans.c4
-rw-r--r--private/windbg/em/p_mips/asm.c12
-rw-r--r--private/windbg/em/p_mips/d3.c1442
-rw-r--r--private/windbg/em/p_mips/d3.h1238
-rw-r--r--private/windbg/em/p_mips/em.rc1
-rw-r--r--private/windbg/em/p_mips/emdp.c4
-rw-r--r--private/windbg/em/p_mips/emdp2.c4
-rw-r--r--private/windbg/em/p_mips/emdp3.c4
-rw-r--r--private/windbg/em/p_mips/emdpdev.c1107
-rw-r--r--private/windbg/em/p_mips/emmip.def4
-rw-r--r--private/windbg/em/p_mips/flags.h69
-rw-r--r--private/windbg/em/p_mips/makefile6
-rw-r--r--private/windbg/em/p_mips/makefile.inc25
-rw-r--r--private/windbg/em/p_mips/ntdis.h277
-rw-r--r--private/windbg/em/p_mips/precomp.h75
-rw-r--r--private/windbg/em/p_mips/regs.h120
-rw-r--r--private/windbg/em/p_mips/sources61
-rw-r--r--private/windbg/em/p_mips/strings.c4
-rw-r--r--private/windbg/em/p_mips/strings.h185
-rw-r--r--private/windbg/em/p_mips/wintrans.c4
-rw-r--r--private/windbg/em/p_ppc/asm.c13
-rw-r--r--private/windbg/em/p_ppc/d3.c1097
-rw-r--r--private/windbg/em/p_ppc/d3.h1238
-rw-r--r--private/windbg/em/p_ppc/em.rc1
-rw-r--r--private/windbg/em/p_ppc/emdp.c4
-rw-r--r--private/windbg/em/p_ppc/emdp2.c4
-rw-r--r--private/windbg/em/p_ppc/emdp3.c4
-rw-r--r--private/windbg/em/p_ppc/emdpdev.c1135
-rw-r--r--private/windbg/em/p_ppc/emppc.def4
-rw-r--r--private/windbg/em/p_ppc/flags.h8
-rw-r--r--private/windbg/em/p_ppc/makefile6
-rw-r--r--private/windbg/em/p_ppc/makefile.inc25
-rw-r--r--private/windbg/em/p_ppc/ntdis.h277
-rw-r--r--private/windbg/em/p_ppc/ntdisppc.h398
-rw-r--r--private/windbg/em/p_ppc/precomp.h74
-rw-r--r--private/windbg/em/p_ppc/regs.h79
-rw-r--r--private/windbg/em/p_ppc/sources61
-rw-r--r--private/windbg/em/p_ppc/strings.c4
-rw-r--r--private/windbg/em/p_ppc/strings.h130
-rw-r--r--private/windbg/em/p_ppc/wintrans.c4
-rw-r--r--private/windbg/em/strings.c17
-rw-r--r--private/windbg/em/win32msg.h183
-rw-r--r--private/windbg/em/wintrans.c629
-rw-r--r--private/windbg/lib/assrt.c31
-rw-r--r--private/windbg/lib/atold.c54
-rw-r--r--private/windbg/lib/cfin.c73
-rw-r--r--private/windbg/lib/cfout.c132
-rw-r--r--private/windbg/lib/constpow.c161
-rw-r--r--private/windbg/lib/cv.h518
-rw-r--r--private/windbg/lib/cvt.c768
-rw-r--r--private/windbg/lib/heap.c106
-rw-r--r--private/windbg/lib/intrncvt.c703
-rw-r--r--private/windbg/lib/makefile6
-rw-r--r--private/windbg/lib/mantold.c184
-rw-r--r--private/windbg/lib/rtlproto.h88
-rw-r--r--private/windbg/lib/sources48
-rw-r--r--private/windbg/lib/strgtold.c393
-rw-r--r--private/windbg/lib/strtoli.c242
-rw-r--r--private/windbg/lib/tenpow.c240
-rw-r--r--private/windbg/lib/x10fout.c464
-rw-r--r--private/windbg/newdm/align.h2
-rw-r--r--private/windbg/newdm/alpmach.c783
-rw-r--r--private/windbg/newdm/biavst.h203
-rw-r--r--private/windbg/newdm/bp.c1346
-rw-r--r--private/windbg/newdm/bp.h80
-rw-r--r--private/windbg/newdm/cache.c1254
-rw-r--r--private/windbg/newdm/com.c473
-rw-r--r--private/windbg/newdm/common.inc60
-rw-r--r--private/windbg/newdm/dbgpnt.h164
-rw-r--r--private/windbg/newdm/debug.h36
-rw-r--r--private/windbg/newdm/dirs20
-rw-r--r--private/windbg/newdm/dm.h1334
-rw-r--r--private/windbg/newdm/dmkd.rc11
-rw-r--r--private/windbg/newdm/dmx32.c7162
-rw-r--r--private/windbg/newdm/event.c338
-rw-r--r--private/windbg/newdm/funccall.c476
-rw-r--r--private/windbg/newdm/funccall.h49
-rw-r--r--private/windbg/newdm/i386d3dm.c145
-rw-r--r--private/windbg/newdm/i386mach.c1617
-rw-r--r--private/windbg/newdm/kd.h427
-rw-r--r--private/windbg/newdm/kdapi.c3768
-rw-r--r--private/windbg/newdm/kdwow.c238
-rw-r--r--private/windbg/newdm/list.h133
-rw-r--r--private/windbg/newdm/mipsmach.c883
-rw-r--r--private/windbg/newdm/p_alpha/dmkd.rc3
-rw-r--r--private/windbg/newdm/p_alpha/dmkdalp.def8
-rw-r--r--private/windbg/newdm/p_alpha/makefile6
-rw-r--r--private/windbg/newdm/p_alpha/makefile.inc27
-rw-r--r--private/windbg/newdm/p_alpha/ntdis.h190
-rw-r--r--private/windbg/newdm/p_alpha/precomp.h55
-rw-r--r--private/windbg/newdm/p_alpha/sources76
-rw-r--r--private/windbg/newdm/p_i386/dmkd.rc3
-rw-r--r--private/windbg/newdm/p_i386/dmkdx86.def8
-rw-r--r--private/windbg/newdm/p_i386/makefile6
-rw-r--r--private/windbg/newdm/p_i386/makefile.inc29
-rw-r--r--private/windbg/newdm/p_i386/precomp.h62
-rw-r--r--private/windbg/newdm/p_i386/sources76
-rw-r--r--private/windbg/newdm/p_mips/dmkd.rc3
-rw-r--r--private/windbg/newdm/p_mips/dmkdmip.def8
-rw-r--r--private/windbg/newdm/p_mips/makefile6
-rw-r--r--private/windbg/newdm/p_mips/makefile.inc27
-rw-r--r--private/windbg/newdm/p_mips/precomp.h56
-rw-r--r--private/windbg/newdm/p_mips/sources75
-rw-r--r--private/windbg/newdm/p_ppc/dmkd.rc3
-rw-r--r--private/windbg/newdm/p_ppc/dmkdppc.def8
-rw-r--r--private/windbg/newdm/p_ppc/makefile6
-rw-r--r--private/windbg/newdm/p_ppc/makefile.inc28
-rw-r--r--private/windbg/newdm/p_ppc/precomp.h56
-rw-r--r--private/windbg/newdm/p_ppc/sources75
-rw-r--r--private/windbg/newdm/packet.c1129
-rw-r--r--private/windbg/newdm/ppcmach.c913
-rw-r--r--private/windbg/newdm/procem.c2490
-rw-r--r--private/windbg/newdm/step.c2968
-rw-r--r--private/windbg/newdm/support.c2396
-rw-r--r--private/windbg/newdm/user/dm.def7
-rw-r--r--private/windbg/newdm/user/dm.rc14
-rw-r--r--private/windbg/newdm/user/makefile6
-rw-r--r--private/windbg/newdm/user/makefile.inc23
-rw-r--r--private/windbg/newdm/user/precomp.h81
-rw-r--r--private/windbg/newdm/user/process.c335
-rw-r--r--private/windbg/newdm/user/sources89
-rw-r--r--private/windbg/newdm/user/userapi.c2041
-rw-r--r--private/windbg/newdm/user/wow.c1175
-rw-r--r--private/windbg/newdm/util.c658
-rw-r--r--private/windbg/newdm/walk.c2073
-rw-r--r--private/windbg/osdebug/bsexcpt.h376
-rw-r--r--private/windbg/osdebug/cc.h23
-rw-r--r--private/windbg/osdebug/cchpt.h25
-rw-r--r--private/windbg/osdebug/defs.h47
-rw-r--r--private/windbg/osdebug/include/bpprotos.h91
-rw-r--r--private/windbg/osdebug/include/bptypes.h316
-rw-r--r--private/windbg/osdebug/include/cp.h51
-rw-r--r--private/windbg/osdebug/include/ctxptrs.h97
-rw-r--r--private/windbg/osdebug/include/cvexefmt.h364
-rw-r--r--private/windbg/osdebug/include/cvinfo.h3221
-rw-r--r--private/windbg/osdebug/include/cvtypes.h295
-rw-r--r--private/windbg/osdebug/include/cvtypes.hxx264
-rw-r--r--private/windbg/osdebug/include/dbapiver.h6
-rw-r--r--private/windbg/osdebug/include/dbgver.h135
-rw-r--r--private/windbg/osdebug/include/eeapi.h395
-rw-r--r--private/windbg/osdebug/include/emdm.h432
-rw-r--r--private/windbg/osdebug/include/heap.h16
-rw-r--r--private/windbg/osdebug/include/ll.h9
-rw-r--r--private/windbg/osdebug/include/llproto.h70
-rw-r--r--private/windbg/osdebug/include/lltypes.h22
-rw-r--r--private/windbg/osdebug/include/od.h1160
-rw-r--r--private/windbg/osdebug/include/odmsg.h244
-rw-r--r--private/windbg/osdebug/include/osdem.h190
-rw-r--r--private/windbg/osdebug/include/shapi.h386
-rw-r--r--private/windbg/osdebug/include/shapi.hxx411
-rw-r--r--private/windbg/osdebug/include/types.h257
-rw-r--r--private/windbg/osdebug/include/vcver.h6
-rw-r--r--private/windbg/osdebug/include/version.h5
-rw-r--r--private/windbg/osdebug/lb.h17
-rw-r--r--private/windbg/osdebug/lbhpt.h12
-rw-r--r--private/windbg/osdebug/llhpt.h14
-rw-r--r--private/windbg/osdebug/makefile6
-rw-r--r--private/windbg/osdebug/mh.h15
-rw-r--r--private/windbg/osdebug/mhhpt.h8
-rw-r--r--private/windbg/osdebug/mm.h55
-rw-r--r--private/windbg/osdebug/newexe.h105
-rw-r--r--private/windbg/osdebug/od.c4293
-rw-r--r--private/windbg/osdebug/od2.h49
-rw-r--r--private/windbg/osdebug/osassert.h34
-rw-r--r--private/windbg/osdebug/sources44
-rw-r--r--private/windbg/osdebug/tl.h60
-rw-r--r--private/windbg/remote/dirs19
-rw-r--r--private/windbg/remote/pipe/control.c751
-rw-r--r--private/windbg/remote/pipe/makefile6
-rw-r--r--private/windbg/remote/pipe/sources47
-rw-r--r--private/windbg/remote/pipe/tlpipe.c1280
-rw-r--r--private/windbg/remote/pipe/tlpipe.def5
-rw-r--r--private/windbg/remote/pipe/tlpipe.h80
-rw-r--r--private/windbg/remote/pipe/tlpipe.rc9
-rw-r--r--private/windbg/remote/serial/makefile6
-rw-r--r--private/windbg/remote/serial/sources45
-rw-r--r--private/windbg/remote/serial/tlser.c758
-rw-r--r--private/windbg/remote/serial/tlser.def5
-rw-r--r--private/windbg/remote/serial/tlser.h73
-rw-r--r--private/windbg/remote/serial/tlser.rc9
-rw-r--r--private/windbg/remote/shell/connect.icobin0 -> 766 bytes
-rw-r--r--private/windbg/remote/shell/dbgdll.c675
-rw-r--r--private/windbg/remote/shell/debugger.c384
-rw-r--r--private/windbg/remote/shell/gui.c221
-rw-r--r--private/windbg/remote/shell/kdopt.c241
-rw-r--r--private/windbg/remote/shell/makefile6
-rw-r--r--private/windbg/remote/shell/registry.c607
-rw-r--r--private/windbg/remote/shell/resource.h51
-rw-r--r--private/windbg/remote/shell/sources50
-rw-r--r--private/windbg/remote/shell/windbgrm.c704
-rw-r--r--private/windbg/remote/shell/windbgrm.dlg64
-rw-r--r--private/windbg/remote/shell/windbgrm.h107
-rw-r--r--private/windbg/remote/shell/windbgrm.icobin0 -> 1086 bytes
-rw-r--r--private/windbg/remote/shell/windbgrm.rc44
-rw-r--r--private/windbg/remote/xport/makefile6
-rw-r--r--private/windbg/remote/xport/sources36
-rw-r--r--private/windbg/remote/xport/xport.c1143
-rw-r--r--private/windbg/remote/xport/xport.h136
-rw-r--r--private/windbg/symcvt/dirs17
-rw-r--r--private/windbg/symcvt/include/cofftocv.h7
-rw-r--r--private/windbg/symcvt/include/cv.h69
-rw-r--r--private/windbg/symcvt/include/cvcommon.h15
-rw-r--r--private/windbg/symcvt/include/symcvt.h91
-rw-r--r--private/windbg/symcvt/include/symtocv.h7
-rw-r--r--private/windbg/symcvt/symcvt/cofftocv.c847
-rw-r--r--private/windbg/symcvt/symcvt/cvcommon.c784
-rw-r--r--private/windbg/symcvt/symcvt/file.c467
-rw-r--r--private/windbg/symcvt/symcvt/makefile6
-rw-r--r--private/windbg/symcvt/symcvt/sources49
-rw-r--r--private/windbg/symcvt/symcvt/symcvt.c128
-rw-r--r--private/windbg/symcvt/symcvt/symcvt.def9
-rw-r--r--private/windbg/symcvt/symcvt/symcvt.rc11
-rw-r--r--private/windbg/symcvt/symcvt/symtocv.c482
-rw-r--r--private/windbg/symcvt/symedit/makefile6
-rw-r--r--private/windbg/symcvt/symedit/makefile.inc4
-rw-r--r--private/windbg/symcvt/symedit/sources47
-rw-r--r--private/windbg/symcvt/symedit/strings.c2
-rw-r--r--private/windbg/symcvt/symedit/strings.h37
-rw-r--r--private/windbg/symcvt/symedit/symedit.c1381
-rw-r--r--private/windbg/symcvt/symedit/symedit.mak16
-rw-r--r--private/windbg/symcvt/symedit/symedit.rc12
-rw-r--r--private/windbg/tlloc/makefile6
-rw-r--r--private/windbg/tlloc/sources44
-rw-r--r--private/windbg/tlloc/tlloc.def5
-rw-r--r--private/windbg/tlloc/tlloc.rc14
-rw-r--r--private/windbg/tlloc/tllp.c571
-rw-r--r--private/windbg/windbg/apisupp.c1593
-rw-r--r--private/windbg/windbg/arrange.c602
-rw-r--r--private/windbg/windbg/bitmaps/asm-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asm-dda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asm-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asm-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asm.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asmda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asmdn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/asmup.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosn.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosn.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosn.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosp.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosp.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/atosp.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/blank.bvgbin0 -> 214 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakn.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakn.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakn.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakp.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakp.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/breakp.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/brkpt-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/brkpt-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/brkpt-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildn.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildn.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildn.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildp.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildp.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/buildp.bvmbin0 -> 421476 bytes
-rw-r--r--private/windbg/windbg/bitmaps/clflder.bmpbin0 -> 118 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compn.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compn.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compn.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compp.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compp.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/compp.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/cpuwin.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/cpuwin2.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/curflder.bmpbin0 -> 118 bytes
-rw-r--r--private/windbg/windbg/bitmaps/document.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/fmt.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/formatg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/formatn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/formatp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/gog.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/gon.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/gop.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/help.curbin0 -> 326 bytes
-rw-r--r--private/windbg/windbg/bitmaps/localwin.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/memory.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/minus.bmpbin0 -> 214 bytes
-rw-r--r--private/windbg/windbg/bitmaps/minus.bvgbin0 -> 214 bytes
-rw-r--r--private/windbg/windbg/bitmaps/opflder.bmpbin0 -> 118 bytes
-rw-r--r--private/windbg/windbg/bitmaps/opt-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/opt-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/opt-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/optg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/optn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/optp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/plus.bmpbin0 -> 214 bytes
-rw-r--r--private/windbg/windbg/bitmaps/plus.bvgbin0 -> 214 bytes
-rw-r--r--private/windbg/windbg/bitmaps/plusmin.bmpbin0 -> 2918 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcerr.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcerror.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcfloat.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qclocal.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcmem.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcprod.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp1.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp2.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp3.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp4.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp5.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp6.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp7.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcqp8.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcreg.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcsource.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qcwatch.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/quickc.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/quickc2.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchn.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchn.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchn.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchp.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchp.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/qwatchp.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/retrn-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/retrn-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/retrn-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/run-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/run-dda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/run-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/run-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/runda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/rundn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/runup.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/source.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/src-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/src-dda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/src-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/src-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/step-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/step-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/step-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepn.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepn.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepn.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepp.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepp.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stepp.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stop-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stop-dda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stop-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stop-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stopg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stopn.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stopp.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stpda.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stpdn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/stpup.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/trace-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/trace-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/trace-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/traceg.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/traceg.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/traceg.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/traceg.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracen.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracen.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracen.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracen.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracep.bcgbin0 -> 226 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracep.begbin0 -> 310 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracep.bvgbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/tracep.bvmbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/watchwin.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wfapp.bmpbin0 -> 298 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wfcdrom.bmpbin0 -> 390 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wffile.bmpbin0 -> 298 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wffloppy.bmpbin0 -> 390 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wfhard.bmpbin0 -> 390 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wfnet.bmpbin0 -> 390 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wfram.bmpbin0 -> 390 bytes
-rw-r--r--private/windbg/windbg/bitmaps/windbg.icobin0 -> 766 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wtch-da.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wtch-dn.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/bitmaps/wtch-up.bmpbin0 -> 382 bytes
-rw-r--r--private/windbg/windbg/breakpts.c834
-rw-r--r--private/windbg/windbg/brkpt0.c6614
-rw-r--r--private/windbg/windbg/calls.c241
-rw-r--r--private/windbg/windbg/callswin.c2453
-rw-r--r--private/windbg/windbg/cl.c587
-rw-r--r--private/windbg/windbg/cmdexec0.c3363
-rw-r--r--private/windbg/windbg/cmdexec1.c4127
-rw-r--r--private/windbg/windbg/cmdexec2.c3297
-rw-r--r--private/windbg/windbg/cmdwin.c2206
-rw-r--r--private/windbg/windbg/codemgr.c5830
-rw-r--r--private/windbg/windbg/colors.c887
-rw-r--r--private/windbg/windbg/confirm.c143
-rw-r--r--private/windbg/windbg/cp.c1162
-rw-r--r--private/windbg/windbg/cpuwin.c755
-rw-r--r--private/windbg/windbg/cvextras.c498
-rw-r--r--private/windbg/windbg/data.c319
-rw-r--r--private/windbg/windbg/dbgext.c1581
-rw-r--r--private/windbg/windbg/dbugdll.c1648
-rw-r--r--private/windbg/windbg/dbugexcp.c1484
-rw-r--r--private/windbg/windbg/dbugrun.c167
-rw-r--r--private/windbg/windbg/dialogs.dlg920
-rw-r--r--private/windbg/windbg/disasm.c1062
-rw-r--r--private/windbg/windbg/docfile.c1247
-rw-r--r--private/windbg/windbg/document.c2319
-rw-r--r--private/windbg/windbg/edit.c4849
-rw-r--r--private/windbg/windbg/editutil.c196
-rw-r--r--private/windbg/windbg/environ.c244
-rw-r--r--private/windbg/windbg/find.c227
-rw-r--r--private/windbg/windbg/findnext.c113
-rw-r--r--private/windbg/windbg/findrep.c1223
-rw-r--r--private/windbg/windbg/fonts.c288
-rw-r--r--private/windbg/windbg/fs.c118
-rw-r--r--private/windbg/windbg/function.c421
-rw-r--r--private/windbg/windbg/include/apisupp.h106
-rw-r--r--private/windbg/windbg/include/bpitypes.h115
-rw-r--r--private/windbg/windbg/include/bptypes.h196
-rw-r--r--private/windbg/windbg/include/breakpts.h302
-rw-r--r--private/windbg/windbg/include/callswin.h89
-rw-r--r--private/windbg/windbg/include/change.h12
-rw-r--r--private/windbg/windbg/include/cl.h82
-rw-r--r--private/windbg/windbg/include/cmdexec.h239
-rw-r--r--private/windbg/windbg/include/cmdwin.h36
-rw-r--r--private/windbg/windbg/include/cmgrhigh.h108
-rw-r--r--private/windbg/windbg/include/cmgrlow.h65
-rw-r--r--private/windbg/windbg/include/codemgr.h79
-rw-r--r--private/windbg/windbg/include/colors.h169
-rw-r--r--private/windbg/windbg/include/cp.h51
-rw-r--r--private/windbg/windbg/include/cpuwin.h31
-rw-r--r--private/windbg/windbg/include/cvextras.h47
-rw-r--r--private/windbg/windbg/include/dbugdll.h46
-rw-r--r--private/windbg/windbg/include/dbugexcp.h65
-rw-r--r--private/windbg/windbg/include/debug.h19
-rw-r--r--private/windbg/windbg/include/debugger.h78
-rw-r--r--private/windbg/windbg/include/dialogs.h443
-rw-r--r--private/windbg/windbg/include/disasm.h39
-rw-r--r--private/windbg/windbg/include/docfile.h13
-rw-r--r--private/windbg/windbg/include/document.h99
-rw-r--r--private/windbg/windbg/include/edit.h26
-rw-r--r--private/windbg/windbg/include/editutil.h36
-rw-r--r--private/windbg/windbg/include/eeproto.h42
-rw-r--r--private/windbg/windbg/include/export.h41
-rw-r--r--private/windbg/windbg/include/extern.h346
-rw-r--r--private/windbg/windbg/include/filedll.h179
-rw-r--r--private/windbg/windbg/include/findrep.h32
-rw-r--r--private/windbg/windbg/include/fonts.h110
-rw-r--r--private/windbg/windbg/include/global.h104
-rw-r--r--private/windbg/windbg/include/helpid.h208
-rw-r--r--private/windbg/windbg/include/imports.h64
-rw-r--r--private/windbg/windbg/include/inifile.h15
-rw-r--r--private/windbg/windbg/include/init.h64
-rw-r--r--private/windbg/windbg/include/linklist.h43
-rw-r--r--private/windbg/windbg/include/localwin.h7
-rw-r--r--private/windbg/windbg/include/makeeng.h273
-rw-r--r--private/windbg/windbg/include/memwin.h87
-rw-r--r--private/windbg/windbg/include/menu.h484
-rw-r--r--private/windbg/windbg/include/mstools.h14
-rw-r--r--private/windbg/windbg/include/panemgr.h132
-rw-r--r--private/windbg/windbg/include/pidtid.h20
-rw-r--r--private/windbg/windbg/include/program.h34
-rw-r--r--private/windbg/windbg/include/quickw.h10
-rw-r--r--private/windbg/windbg/include/re.h125
-rw-r--r--private/windbg/windbg/include/remi.h60
-rw-r--r--private/windbg/windbg/include/remote.h58
-rw-r--r--private/windbg/windbg/include/res_str.h968
-rw-r--r--private/windbg/windbg/include/resource.h47
-rw-r--r--private/windbg/windbg/include/ribbon.h23
-rw-r--r--private/windbg/windbg/include/sbconst.h108
-rw-r--r--private/windbg/windbg/include/settings.h16
-rw-r--r--private/windbg/windbg/include/shproto.h101
-rw-r--r--private/windbg/windbg/include/status.h7
-rw-r--r--private/windbg/windbg/include/syntax.h8
-rw-r--r--private/windbg/windbg/include/systemw3.h30
-rw-r--r--private/windbg/windbg/include/undoredo.h44
-rw-r--r--private/windbg/windbg/include/userctrl.h79
-rw-r--r--private/windbg/windbg/include/userdll.h77
-rw-r--r--private/windbg/windbg/include/util.h558
-rw-r--r--private/windbg/windbg/include/util2.h100
-rw-r--r--private/windbg/windbg/include/vapi.h50
-rw-r--r--private/windbg/windbg/include/vib.h189
-rw-r--r--private/windbg/windbg/include/watchwin.h18
-rw-r--r--private/windbg/windbg/include/windbg.h1272
-rw-r--r--private/windbg/windbg/include/winpck.h95
-rw-r--r--private/windbg/windbg/include/wrkspace.h148
-rw-r--r--private/windbg/windbg/init.c1681
-rw-r--r--private/windbg/windbg/kdopt.c596
-rw-r--r--private/windbg/windbg/line.c70
-rw-r--r--private/windbg/windbg/linklist.c1245
-rw-r--r--private/windbg/windbg/localwin.c667
-rw-r--r--private/windbg/windbg/makeeng.c251
-rw-r--r--private/windbg/windbg/makefile6
-rw-r--r--private/windbg/windbg/makefile.inc9
-rw-r--r--private/windbg/windbg/memory.c282
-rw-r--r--private/windbg/windbg/memwin.c1892
-rw-r--r--private/windbg/windbg/menu.c820
-rw-r--r--private/windbg/windbg/panemgr.c2339
-rw-r--r--private/windbg/windbg/paneopt.c209
-rw-r--r--private/windbg/windbg/paneuser.c1583
-rw-r--r--private/windbg/windbg/pidtid.c530
-rw-r--r--private/windbg/windbg/precomp.h90
-rw-r--r--private/windbg/windbg/process.c357
-rw-r--r--private/windbg/windbg/program.c1609
-rw-r--r--private/windbg/windbg/quickw.c466
-rw-r--r--private/windbg/windbg/re_mi.c1110
-rw-r--r--private/windbg/windbg/remote.c1039
-rw-r--r--private/windbg/windbg/reparse.c1364
-rw-r--r--private/windbg/windbg/replace.c175
-rw-r--r--private/windbg/windbg/ribbon.c573
-rw-r--r--private/windbg/windbg/rundebug.c501
-rw-r--r--private/windbg/windbg/setbreak.c2092
-rw-r--r--private/windbg/windbg/sources122
-rw-r--r--private/windbg/windbg/status.c528
-rw-r--r--private/windbg/windbg/tasklist.c155
-rw-r--r--private/windbg/windbg/thread.c402
-rw-r--r--private/windbg/windbg/undoredo.c1199
-rw-r--r--private/windbg/windbg/userctrl.c706
-rw-r--r--private/windbg/windbg/userdll.c1462
-rw-r--r--private/windbg/windbg/util.c3329
-rw-r--r--private/windbg/windbg/util2.c4224
-rw-r--r--private/windbg/windbg/vib.c1894
-rw-r--r--private/windbg/windbg/watch.c704
-rw-r--r--private/windbg/windbg/watchwin.c817
-rw-r--r--private/windbg/windbg/windbg.c2545
-rw-r--r--private/windbg/windbg/windbg.rc296
-rw-r--r--private/windbg/windbg/wrkspace.c5923
860 files changed, 254083 insertions, 0 deletions
diff --git a/private/windbg/common.src b/private/windbg/common.src
new file mode 100644
index 000000000..c1b935100
--- /dev/null
+++ b/private/windbg/common.src
@@ -0,0 +1,36 @@
+MSC_WARNING_LEVEL=/WX /W3
+
+C_DEFINES = -DWIN32 -DTARGET32 -DHOST32 \
+ -DADDR_MIXED -DNT_BUILD -D_CROSS_PLATFORM_
+
+C_DEFINES = $(C_DEFINES) -DDBCS -DFE_IME
+
+MIPS_FLAGS = -DHOST_MIPS
+386_FLAGS = -DHOST_i386
+ALPHA_FLAGS= -DHOST_ALPHA
+PPC_FLAGS = -DHOST_PPC
+
+USE_CRTDLL = 1
+
+MORE_LIBS= \
+ $(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib
+
+!if "$(NTDEBUG)" == "" || "$(NTDEBUG)" == "ntsdnodbg" || "$(NTDEBUG)" == "retail"
+C_DEFINES = $(C_DEFINES) -DNDEBUG
+!else
+C_DEFINES = $(C_DEFINES) -DDEBUGVER
+!endif
+
+!IFDEF CALL_PROFILE
+MORE_LIBS=$(MORE_LIBS) $(BASEDIR)\public\sdk\lib\*\cap.lib
+MSC_OPTIMIZATION=$(MSC_OPTIMIZATION) /Od /Gh
+!ENDIF
+
+!IFDEF HEAP_CHECKING
+MORE_LIBS=$(MORE_LIBS) ..\..\heap\obj\*\heap.lib
+C_DEFINES=$(C_DEFINES) -DUSE_HEAP_CHECKING=1
+!ENDIF
+
+# SUBSYSTEM_VERSION=3.50
diff --git a/private/windbg/dirs b/private/windbg/dirs
new file mode 100644
index 000000000..9023b9b89
--- /dev/null
+++ b/private/windbg/dirs
@@ -0,0 +1,28 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= \
+ lib \
+ osdebug \
+ newdm \
+ eecxx \
+ em \
+ symcvt \
+ tlloc \
+ remote \
+ windbg \
+ driver
+
+
diff --git a/private/windbg/doc/newuser.doc b/private/windbg/doc/newuser.doc
new file mode 100644
index 000000000..6434d5459
--- /dev/null
+++ b/private/windbg/doc/newuser.doc
Binary files differ
diff --git a/private/windbg/doc/newuser.txt b/private/windbg/doc/newuser.txt
new file mode 100644
index 000000000..a75c86f88
--- /dev/null
+++ b/private/windbg/doc/newuser.txt
@@ -0,0 +1,258 @@
+WinDbg New User Document
+
+This document serves to describe the fundamentals of using WinDbg, the NT hosted source level debugger.
+WinDbg supports the following types of debugging:
+1. user mode applications
+2. csr and all server side
+3. user mode drivers (video, etc.)
+4. wow applications, dos (real mode & v86 mode) on i386 only
+5. kernel debugging (kernel, drivers, etc.)
+6. kernel mode crash debugging (NT style core dumps)
+7. remote debugging (net based named pipes & serial)
+
+Where Do I Get The Current Version Of WinDbg?
+
+The latest build is the best place to get your copy of WinDbg. If you do not want to update to the latest build or cannot you can still get the latest WinDbg very easily. Copy the script GWINDBG.CMD from \\kernel\scratch\wesw. It will copy the WinDbg binaries from any build release server to any directory on your machine or directly to your mstools directory. The syntax for the script is:
+
+GWINDBG [share point] [destination directory]
+Example: gwindbg \\ntx864\freebins.544 d:\windbg // this copies to a specific dir
+ gwindbg \\ntx864\freebins.544 // this copies to your mstools dir
+
+If you are one of those people that like to live on the edge the you can always get binaries from \\kernel\scratch\wesw\windbg. The binaries for each platform are located in separate machine directories. You do not need the above mentioned script, just copy the all the files from the appropriate machine directory. If you do this I suggest that you put the binaries into a separate directory so that your mstools binaries are preserved.
+
+There is one special consideration for kernel debugging and that is the kernel extensions. The extensions MUST match the system that you are debugging. Therefore if you copy down new WinDbg binaries be sure to use the correct extensions DLL. You may want to save different versions if the extensions DLLs for each build that you are debugging. There are currently 3 extension DLLs, one for each platform: wextsalp.dll, wextsmip.dll, wextsx86.dll.
+
+Building Your Project For WinDbg
+
+WinDbg uses symbolic debugging information that is generated by the compiler to relate memory addresses to variable names and source line numbers. WinDbg supports the following types of symbolic debugging information:
+1. COFF, global publics and line numbers
+2. CodeView, NB08 and NB09 style
+3. 16 bit SYM files for WOW debugging
+4. NT images that have the debug data striped to a DBG file
+
+To get the best use of Windbg you should set your build environment as follows:
+set NTDEBUG=ntsd
+set NTDEBUGTYPE=windbg
+set MSC_OPTIMIZATION=/Od /Oi
+
+Ultimately these build environment settings cause the compiler and linker to get the following flags set:
+Compiler: /Z7 /Od /Oi
+Linker: debug:full debugtype:cv
+
+Setting the optimization flag to /Od /Oi causes optimizations to be turned off with the exception of intrinsics. Leaving intrinsics on is necessary for some directories because CRT functions like strcpy, strlen, etc. are used but libc is not linked in the project. The removal of optimizations is necessary for correct source stepping and local variable display. When optimizations are turned on the compiler schedules instructions and may leave local variables in registers, both can play havoc on WinDbg. We may be able to correct this in the future by changing the symbolic debug information that is generated by the compiler/packer.
+
+If you are debugging a component that you didn't build, one that came with the build, you can debug it with WinDbg and get the same results as from NTSD/KD.
+
+For building WINSRV/GDI/USER/etc you must use native C++ not CFRONT, to do that you must set BLDCRT=1 in your environment. You should also use precompiled headers, to that do the following:
+1. copy gre\precomp.pre gre\precomp.hxx
+2. edit gre\sources
+line 43: prepend '#' to !IF 0 --> #!IF 0
+line 49: prepend '#' to !ENDIF --> #!ENDIF
+SOURCES= line, add precomp.hxx as FIRST file in file list
+3. if you are use native C++ also: copy client\mfrec.nat client\mfrec.cxx
+
+For building a X86 kernel with WinDbg symbols you must delete 2 lines from makefile.def so that the kernel will be linked as a relocatable image. To change makefile.def do the following:
+Search for "-base:0x80100000"
+Delete the line that was found and the previous line that specifies "-fixed"
+Save the makefile.def and re-link your kernel.
+
+
+Setting Up Your WinDbg Environment
+
+Unlike NTSD/KD Windbg does not use environment variables to communicate options information. Because WinDbg is a Windows hosted debugger it uses it's ui to setup the necessary options and then stores the configuration information in the registry. All configuration data is stored under \\hkey_current_user\software\microsoft\windbg\0012. The last key is a registry version number and only changes if there are radical changes made to the format of the data that WinDbg stores. You can use REGEDT32 to save your WinDbg registry data to a disk file and then load the file after you have updated to a newer build.
+
+WinDbg uses the concept of a 'workspace' to save user configurations. Workspaces are organized as a 2 level hierarchy. The first level is the program that is being debugged and the second level is the workspace name:
+
+This gives you the flexibility to have multiple workspaces for a given program, allowing you to save different configurations for different debugging scenarios.
+
+WinDbg saves the entire state of the debugger in the workspace. This includes window positions and sizes, colors, debug options, breakpoints, remote debugging options, and much more. The workspace is NOT saved or created for you, you must explicitly save the workspace before exiting the debugger.
+
+ Notice that the above diagram shows 2 special workspaces, common workspace and <attached process>. These 2 workspaces are always present. The common workspace is the root workspace that all other workspaces are derived from. When you start WinDbg without specifying a workspace it loads the common workspace. It is not a good idea to simply save your state to the common workspace all the time. The common workspace should contain those options that are common to all debugging scenarios but not specific to one individual program. For example saving breakpoints to the common workspace is really the wrong thing to do. The <attached process> workspace is reserved for the case when you have attached to a faulting process. The reason WinDbg uses this reserved workspace is because we may not have a program name during process attach.
+
+The common options that most users need to modify the first time using WinDbg are accessed by using the Options.Debug menu item in WinDbg. The following list shows the options that most uses modify:
+1. Case sensitivity
+on = WinDbg cares about the case of symbols (default value)
+off = doesn't care
+2. Verbose output
+on = print all module load/unload notifications
+off = do not print (default value)
+3. Ignore bad symbols
+on = Load debug data even if the checksum/timestamp mismatches
+off = Prompt for a user response (default value)
+4. Abbreviated context
+on = Print NTSD style context ( FOO!_main )
+off = Print WinDbg style context ( {,foo.c,foo.exe}_main ) (default value)
+5. Radix
+default is decimal but can be set to hexadecimal
+6. Register trace
+on = Print a register dump and disasm of current instruction after every debug event. Also enables command repeat by just pushing the enter key.
+off = none of this behavior. (default value)
+7. If you are doing CSR debugging the you must do:
+
+sxd 0xc0000037 // this disables an exception that occurs everytime a server side thread goes away.
+
+The last thing you need to change is the symbol path. This is the path that WinDbg uses to locate the images that contain the symbolic debug information. The path is specified in the Options.UserDlls menu item. This menu item presents a dialog that contains an edit box that is titled "Symbol Search Path". Change this to contain the correct path. You may enter multiple paths separated by ';' characters. Environment variable expansion is also supported, so the path "%systemroot%\symbols" is expanded to the correct value. You may also enter UNC paths to the source servers if you wish.
+Summary:
+So the first time you use WinDbg you should do the following:
+1. Run WinDbg
+2. Change all of the options that you want.
+3. Open a command window (Window.Command)
+4. Save to the common workspace
+5. End WinDbg.
+
+You are now ready to use WinDbg for you debugging pleasure.
+
+
+Helpful Hints To Remember
+
+A complete online WinDbg reference is available through the help facility. Use the HELP menu item to get complete online help. For help in the command window you can use the HELP command. Issuing the HELP command alone lists all of the available commands. You can then use the HELP command to get help on a specific command, i.e. HELP BP gives help for the breakpoint command.
+
+WinDbg defers symbol loading until the symbolic information in needed. This speeds up the startup time for debuggees and boot times for kernel debugging. If at any time you would like to force the loading of previously deferred symbols you can use the "ld" command. The ld command takes one argument, the module name. Example: "ld scsiport" will cause symbols to scsiport.sys to be loaded.
+
+WinDbg allows you to set breakpoints in modules that have not yet been loaded. This is a feature that NTSD/KD never had but is very useful. WinDbg remembers the breakpoint for the future and when ever a module is loaded it looks to see if the breakpoint can be resolved in that module. If the breakpoint cannot be resolved WinDbg shows a popup that asks what should be done with the outstanding breakpoint. Among the choices are "Clear", "Defer", and "Quiet Defer". I recommend that you select "Quiet Defer", this will tell WinDbg to never ask you again what to do and will keep trying to resolve the breakpoint.
+
+WinDbg uses a complete C/C++ expression evaluator and all expressions are assumed to be C/C++ expressions. This means the following:
+ dd ntglobalflag - dumps address of ntglobalflag
+ dd &ntglobalflag - dumps the data in ntglobalflag
+
+Generally it is better to use the '?' operator. The above becomes:
+?ntglobalflag - dumps the data in ntglobalflag
+?ntglobalflag=0x54321 - changes the data in ntglobalflag
+
+ bp dcobj::method - works only for windbg symbols
+ bp dcobj__method - works for ntsd symbols
+
+in a source window or disassembly window:
+ F9 - set breakpoint on line with cursor
+ F7 - goto cursor
+ F8 - trace into
+ F10 - step over
+
+
+To get an up-to-date stack trace as you debug use the Calls Window. It will even display source information, file and line number for each stack frame. Most debugger windows have options associated with them and can be accessed by clicking on the last icon on the toolbar or using Options.Window_Name from the menu.
+
+WinDbg's 'K' command supports a variety of modifiers to display additional information:
+ 1. B display return address, frame pointer, & params
+ 2. V display runtime function information
+ 3. S display file and line number
+
+One or all of the modifiers may be used on a 'K' command, i.e. KB or KBS, or KBV, etc.
+
+When WinDbg gets an exception of any kind, access violation, breakpoint, etc., it tries to locate source line number information for the current address of execution. If source line number information can be found WinDbg will open a source window and position the caret on the source line that corresponds to the current address. WinDbg tries to correctly locate the C/C++ source file by examining the symbolic debug information. The debug data contains the full path to the source file for the machine on which it was compiled. This means that if you build an app on drive d: and running on a machine that has the source tree on drive e: you will have to tell WinDbg where to find the source code. You can do this in 2 ways.
+
+First, you can do nothing and when WinDbg cannot find the source it will ask you to browse for the source. This works fine but if you have source for alot of sub-directories it can be bothersome. If you choose this method be sure to check the checkbox on the common file open dialog that is labeled "add to search path?", this will allow WinDbg to look in this path the next time it cannot find source.
+
+Second, you can change the source search path that WinDbg uses to find your source code files. To do this do the following:
+
+Choose the Options.Debug menu item.
+Tab to the edit box labeled "Source search path".
+Change this to contain the necessary source path for your project.
+Save your workspace.
+
+
+
+WinDbg Command Line Options
+
+-h Causes child processes to inherit access to WinDbg's handles
+-i Load the default workspace, just like running without any registry data
+-w[n] Load a workspace, n is the workspace name
+-p[pid] Attach to a running process, pid is the process id
+-e[event] Event id required for WinDbg as an AE debugger
+-g Go now flag, starts executing the process
+-k[platform,port,speed]
+ Run as a kernel debugger using the arguments as kernel debugger options.
+ Platform is the target machine type, I386, mips, alpha.
+ Port is the com port, com1...n
+ Speed is the com port speed, 9600, 19200, 57600, etc.
+-s[pipe] Start a remote.exe server, pipe is the pipe name
+-m Start WinDbg minimized
+-y[path] Specify a symbol search path, path is the path name
+-a Ignore all bad symbols, still prints a warning message
+-l[text] Sets the window title for WinDbg
+-v Verbose mode on, causes WinDbg to print module load/unload messages
+
+
+Remote Debugging
+
+WinDbg supports remote debugging through 2 different transport layers, named pipes and serial. Named pipes is the preferred transport because of its speed and ease of use. This discussion is oriented towards that transport as a working version of the serial transport is not yet available. Mail will be sent as soon as it is available.
+
+Named pipes remote debugging is slightly more complicated than local debugging but once configured it is very easy to use. When using remote debugging there are 2 machines involved, a host and a target. The host is the machine that "hosts" WinDbg and the target machine is the machine that executes the process that is debugged. The debugger is distributed between the 2 machines with the 2 machines communicating through a series of pipes. Starting a debug session requires the initiation of 2 debuggers, WinDbg and WInDbgRm. Windbg executes on the host machine and WinDbgRm executes on the target machine.
+
+To start a remote debug session do the following:
+TARGET MACHINE
+1. start WinDbgRm
+
+HOST MACHINE
+1. start WinDbg foo.exe (foo.exe is the app you want to debug)
+2. Choose the Options.Debugger_DLLs menu item
+3. Pull down the Transport Layer combo box
+4. Choose PIPES entry
+5. Click in the Change button
+6. Tab to the Parameters edit box
+7. Change targethost to the machine name of the target machine
+8. Click on the Ok button
+9. Click on the Ok button
+10. Save the workspace as your remote debugging workspace
+11. Type go in the command window
+*** A debugger connection is now established and your application is running.
+*** In the case of CSR debugging you would not start windbg with an application name as an argument. Instead you would type ".attach -1" in the command window. This connects to the remote machine and attaches to the CSR process.
+
+There are some special comments worth noting about remote debugging. There are a few features that are especially useful. You can establish a remote connection and then disconnect and later reconnect. Furthermore, another user may reconnect to your debug session. Also, another user may "break in" and take over your remote debug session. If you are doing CSR debugging you MUST set the "Disconnect On Exit" option. This causes WinDbg to disconnect from the target machine instead of terminating the process on the target machine. This option is found on the Options.Debug dialog.
+
+To disconnect from a remote debug session you can type the ".disconnect" command in the command window or set the "Disconnect On Exit" option and terminate WinDbg.
+
+To re-connect to a disconnected target machine type the ".attach" command in the command window.
+
+To "break in" to a remote debug session that someone else is using change the targethost name in the Options.Debugger_Dlls to the machine that is desired and do a ".attach" command. The current host machine will get a popup indicating that you are going to break in and the user will have 20 seconds to deny permission, otherwise the current user will be disconnected and you will be connected.
+
+REMOTE.EXE Server in WinDbg
+
+WinDbg can act as a REMOTE.EXE server. This is analogous to running "REMOTE /S" and then running NTSD in the remote shell. This gives access to the WinDbg command window to remote users through the use of REMOTE.EXE as a client. To start the REMOTE.EXE server in WinDbg execute the "remote pipename" command in the command window. There is one argument to the "remote" command and that is the pipename.
+
+Example:
+
+IN THE WINDBG COMMAND WINDOW: (machine name is mymachine)
+
+ remote foo
+
+ON SOME REMOTE MACHINE IN A CMD SHELL:
+ remote /c mymachine foo
+ *** Now this user has complete access to the WinDbg command window.
+
+Kernel Debugging
+
+When doing Kernel Debugging you must start windbg with it's first argument as NTOSKRNL or NTOSNRNL.EXE. Example: start windbg ntoskrnl.exe
+
+To setup WinDbg for Kernel Debugging requires that you set the options in the Options.Kernel_Debugger dialog. These options are all the ones that you normally set for KD in a series of environment variables. The options that are required to be set are as follows:
+1. Baud Rate
+2. Port
+3. Platform
+
+The other options on this dialog are optional and you may set them as desired.
+
+After setting the Kernel Debugger options be sure to save your workspace. Then change focus to the command window and type "go". WinDbg will display the following messages:
+Thread Create: Process=0, Thread=0 Kernel debugger waiting to connect...
+When the target system boots and establishes a connection WinDbg will display:
+Kernel Debugger connection established
+
+After this message is displayed you can use WinDbg just as you would KD. To break in to the kernel use CTRL-C just as you would in KD. If you selected the "Initial Breakpoint" option in the Kernel Debugger options then you will stop at the initial bp just like KD.
+
+To attach to a dead machine or a running machine to the following:
+1. start WinDbg ntoskrnl
+2. Either set the options as above or load a workspace
+3. In the command window type the "l" or "go" command
+4. If the machine is stopped the you will get an exception, otherwise
+you will have to break in.
+All your favorite kernel extensions are available exactly as they are in KD.
+
+WinDbg also supports the debugging of crash dumps. A crash dump is a NT style core dump that is generated when a machine bug checks. The facility to generate the dump is coming in a build soon. To debug a crash dump simply name the crash dump file in the Kernel Debugger options. All the rest is the same!
+
+***Note: KD allowed an aliased context of NT! to specify the kernel context. WinDbg does not allow this and you must use NTOSKRNL! as the context operator.
+
+
+How Do I Report Problems?
+
+The fastest way to a problem resolution is to send mail to the WINDBG alias. All of the developers for WinDbg monitor this alias daily. You can always raise a bug in RAID too. If you do raise a bug please send mail too.
+
+When you send mail include a complete description of the problem and how we can reproduce it. If WinDbg is crashing then the most helpful data is a DrWatson log file. If you have a retail install then you should automatically get a DrWatson log, otherwise you will need to install DrWatson as you crash debugger. You can do this by issuing the command "drwtsn32 -I" from a command prompt or from program manager. The log file is called DRWTSN32.LOG and is located in your windows directory (%systemroot%\drwtsn32.log). Simply attach the log file to your mail message or include it in the raid bug entry. If you cannot create a DrWatson log file then get a stack trace from NTSD or WINDBG.
+
diff --git a/private/windbg/doc/od.doc b/private/windbg/doc/od.doc
new file mode 100644
index 000000000..5bc4dae2b
--- /dev/null
+++ b/private/windbg/doc/od.doc
Binary files differ
diff --git a/private/windbg/doc/tools/c2rtf.c b/private/windbg/doc/tools/c2rtf.c
new file mode 100644
index 000000000..31e81d46e
--- /dev/null
+++ b/private/windbg/doc/tools/c2rtf.c
@@ -0,0 +1,723 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define IN
+#define OUT
+#define MAX_COMMENT_SIZE 10000
+#define isalpha(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
+#define isnum(c) (c >= '0' && c <= '9')
+#define ISWHITESPACE(c) (c == ' ' || c == '\t')
+
+char *Header[] = {
+"{\\rtf1\\pc {\\info{\\revtim\\mo07\\dy31\\yr1989}{\\creatim\\mo07\\dy31\\yr1989}",
+"{\\nofchars9564}}\\deff0{\\fonttbl{\\f0\\fmodern pica;}",
+"{\\f1\\fmodern Courier;}{\\f2\\fmodern elite;}{\\f3\\fmodern prestige;}",
+"{\\f4\\fmodern lettergothic;}{\\f5\\fmodern gothicPS;}",
+"{\\f6\\fmodern cubicPS;}{\\f7\\fmodern lineprinter;}",
+"{\\f8\\fswiss Helvetica;}{\\f9\\fmodern avantegarde;}",
+"{\\f10\\fmodern spartan;}{\\f11\\fmodern metro;}",
+"{\\f12\\fmodern presentation;}{\\f13\\fmodern APL;}{\\f14\\fmodern OCRA;}",
+"{\\f15\\fmodern OCRB;}{\\f16\\froman boldPS;}{\\f17\\froman emperorPS;}",
+"{\\f18\\froman madaleine;}{\\f19\\froman zapf humanist;}",
+"{\\f20\\froman classic;}{\\f21\\froman roman f;}{\\f22\\froman roman g;}",
+"{\\f23\\froman roman h;}{\\f24\\froman timesroman;}{\\f25\\froman century;}",
+"{\\f26\\froman palantino;}{\\f27\\froman souvenir;}{\\f28\\froman garamond;}",
+"{\\f29\\froman caledonia;}{\\f30\\froman bodini;}{\\f31\\froman university;}",
+"{\\f32\\fscript script;}{\\f33\\fscript scriptPS;}{\\f34\\fscript script c;}",
+"{\\f35\\fscript script d;}{\\f36\\fscript commercial script;}",
+"{\\f37\\fscript park avenue;}{\\f38\\fscript coronet;}",
+"{\\f39\\fscript script h;}{\\f40\\fscript greek;}{\\f41\\froman kana;}",
+"{\\f42\\froman hebrew;}{\\f43\\froman roman s;}{\\f44\\froman russian;}",
+"{\\f45\\froman roman u;}{\\f46\\froman roman v;}{\\f47\\froman roman w;}",
+"{\\f48\\fdecor narrator;}{\\f49\\fdecor emphasis;}",
+"{\\f50\\fdecor zapf chancery;}{\\f51\\fdecor decor d;}",
+"{\\f52\\fdecor old english;}{\\f53\\fdecor decor f;}{\\f54\\fdecor decor g;}",
+"{\\f55\\fdecor cooper black;}{\\f56\\ftech Symbol;}{\\f57\\ftech linedraw;}",
+"{\\f58\\ftech math7;}{\\f59\\ftech math8;}{\\f60\\ftech bar3of9;}",
+"{\\f61\\ftech EAN;}{\\f62\\ftech pcline;}{\\f63\\ftech tech h;}}",
+"{\\stylesheet {\\*\\cs1\\b\\f16 CT;}{\\*\\cs2\\b\\f16 CP;}{\\*\\cs3\\b\\f16 CD;}",
+"{\\*\\cs4\\i\\f16 CI;}{\\*\\cs5\\f16\\ul CR;}{\\*\\s30\\sl-240\\sa240 \\f16",
+"Normal;}{\\*\\s31\\li720\\fi-720\\sl-240\\sa240\\tqr\\tx432\\tx720 \\f16 L1;}",
+"{\\*\\s32\\li1440\\fi-1440\\sl-240\\sa240\\tqr\\tx1152\\tx1440 \\f16 L2;}{\\*\\s33",
+"\\li1152\\sl-240\\sa240 \\b\\f16\\ul P3;}{\\*\\s34\\li1728\\fi-576\\sl-240\\sa240",
+"\\f16 P4;}{\\*\\s35\\li720\\sl-240\\sa240 \\f16 S1;}{\\*\\s36",
+"\\li1440\\sl-240\\sa240 \\f16 S2;}{\\*\\s42\\ri576\\li576\\sl-240\\sa240 \\i\\f16",
+"N1;}{\\*\\s43\\ri576\\li1296\\sl-240\\sa240 \\i\\f16 N2;}{\\*\\s44",
+"\\li1152\\fi-576\\sl-240 \\f16 NL;}{\\*\\s52\\sl-240\\tx576\\tx1152\\tx1728",
+"\\f16 PP;}{\\*\\s53\\li1152\\fi-576\\sl-240\\sa240 \\f16 PL;}{\\*\\s54",
+"\\li1152\\sl-240\\sa240 \\f16 P2;}{\\*\\s62\\sl-240\\tqr\\tx9936 \\b\\f16 RH;}",
+"{\\*\\s63\\qc\\sl-240 \\b\\f16 RF;}{\\*\\s64\\sl-240\\sa240 \\b\\f16 TN;}{\\*\\s65",
+"\\sl-240\\sa240 \\i\\f16 TA;}{\\*\\s66\\sl-240 \\i\\f16 TR;}{\\*\\s72",
+"\\li576\\fi-576\\sl-240\\sa240 \\f16 PT;}{\\*\\s73",
+"\\li576\\sl-240\\tx1152\\tx1728\\tx2304\\tx2880\\tx3456\\tx4032\\tx4608\\tx5184\\tx5760\\tx6336\\tx6912",
+"\\f7\\fs17 PC;}{\\*\\s74\\keep\\sl-240 \\f1 PD;}{\\*\\s88\\keepn\\sl-240\\sa240",
+"\\b\\f16 heading 1;}{\\*\\s89\\keepn\\sl-240\\sa240 \\b\\f16 heading 2;}{\\*\\s90",
+"\\keepn\\sl-240\\sa240 \\b\\f16 heading 3;}{\\*\\s91\\keepn\\sl-240\\sa240",
+"\\b\\f16 heading 4;}{\\*\\s99",
+"\\li288\\fi-288\\sl-240\\sb240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 1;}",
+"{\\*\\s100\\li576\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 2;}",
+"{\\*\\s101\\li864\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 3;}",
+"{\\*\\s102\\li1152\\fi-288\\sl-240\\tldot\\tx8064\\tqr\\tx8640 \\f16 toc 4;}",
+"{\\*\\ds105\\linex576\\endnhere\\pgnrestart standard division;}{\\*\\ds106",
+"\\pgnlcrm\\linex576\\endnhere\\pgnrestart DT;}}",
+"\0"
+};
+
+FILE *InputFile;
+char FileName[50],Function[50];
+char GetWord(char * word, char todo);
+void DoFormat(),GlobalFormat();
+int GetComment(),strpos();
+char Comment[MAX_COMMENT_SIZE];
+char *cp; /* pointer to current value in Comment */
+
+int _cdecl
+main(
+ int argc,
+ char **argv
+ )
+{
+ int i,nummods;
+ char *modules[255];
+
+
+ nummods = 0;
+ if(argc != 3 && argc != 1) {
+ fprintf(stderr,"Usage: c2rtf [program function]\n");
+ exit(1);
+ }
+
+ i = 0;
+ while(*Header[i] != '\0') {
+ printf("%s\n",Header[i++]);
+ }
+ printf("\\ftnbj\\ftnrestart\\widowctrl \\sectd \\linex576\\endnhere");
+ printf(" \\pard \\sl-240\n");
+
+ if(argc == 3) {
+ InputFile = fopen(argv[1],"r");
+ if(InputFile == NULL) {
+ fprintf(stderr,"c2rtf: Error opening file %s.\n",argv[1]);
+ exit(2);
+ }
+
+ strcpy(Function,argv[2]);
+ strcpy(FileName,argv[1]);
+ DoFormat();
+
+ fclose(InputFile);
+ } else {
+ if(scanf("%s",FileName) == EOF) {
+ exit(1);
+ }
+ InputFile = fopen(FileName,"r");
+ if(InputFile == NULL) {
+ fprintf(stderr,"c2rtf: Error opening file %s.\n",FileName);
+ } else {
+ modules[nummods] = (char *)malloc((strlen(FileName) + 1) * sizeof(char));
+ strcpy(modules[nummods++],FileName);
+ GlobalFormat();
+ }
+ fclose(InputFile);
+ while(scanf("%s",Function) != EOF) {
+ if(!strncmp(strchr(Function,'\0')-2,".c",2) ||
+ !strncmp(strchr(Function,'\0')-2,".s",2) ||
+ !strncmp(strchr(Function,'\0')-2,".h",2)) {
+ strcpy(FileName,Function);
+ InputFile = fopen(FileName,"r");
+ if(InputFile == NULL) {
+ fprintf(stderr,"c2rtf: Error opening file %s.\n",FileName);
+ continue;
+ }
+ for(i = 0; i < nummods; i++) {
+ if(!strcmp(modules[i],FileName)) {
+ break;
+ }
+ }
+ if(i == nummods) {
+ modules[nummods] = (char *)malloc((strlen(FileName) + 1) * sizeof(char));
+ strcpy(modules[nummods++],FileName);
+ GlobalFormat();
+ }
+ fclose(InputFile);
+ if(scanf("%s",Function) == EOF) {
+ exit(0);
+ }
+ }
+ InputFile = fopen(FileName,"r");
+ if(InputFile == NULL) {
+ fprintf(stderr,"c2rtf: Error opening file %s for %s.\n",FileName,Function);
+ continue;
+ }
+
+ DoFormat();
+
+ fclose(InputFile);
+ }
+ }
+
+ printf("}\n");
+ return 0;
+}
+
+int
+KillWhiteSpace(
+ char *killchars
+ )
+/*++
+
+Routine Description:
+
+ Removes white space from InputFile until non-whitespace character
+ is reached.
+
+Arguments:
+
+ killchars - characters to be removed; generally some of ' ', '\t', '\n'.
+
+Return Value:
+
+ Number of characters removed.
+
+--*/
+
+{
+ int i = 0;
+ char c;
+
+ c = getc(InputFile);
+ while(strpos(killchars,c) != -1) {
+ i++;
+ c = getc(InputFile);
+ }
+ ungetc(c,InputFile);
+ return(i);
+}
+
+char
+GetWord(
+ OUT char *word,
+ IN char todo
+ )
+/*++
+
+Routine Description:
+
+ Finds the next string of alphabetic characters in InputFile.
+ Only letters are used.
+
+Arguments:
+
+ word - pointer to space where the string is placed
+
+ todo - a character that determines whether to get the next word
+ from the input or the previous word (stored in the static last).
+
+Return value:
+
+ EOF if the end of file is reached before a word is found, 0 otherwise.
+
+--*/
+
+{
+ char c;
+ char *w;
+ static char last[500];
+
+ /* if todo is 'l' then return the previous word instead of next */
+ if(todo == 'l') {
+ strcpy(word,last);
+ return(1);
+ }
+
+ strcpy(last,word);
+ w = word;
+ c = getc(InputFile);
+ while(c != EOF && !(isalpha(c) || c == '_' || c == '*')) {
+ c = getc(InputFile);
+ }
+ if(c != EOF) {
+ *w++ = c;
+ }
+ while((c = getc(InputFile)) != EOF && (isalpha(c) || c == '_' || c == '*' || isnum(c))) {
+ *w++ = c;
+ }
+ ungetc(c,InputFile);
+ *w = '\0';
+ if(strlen(word) == 0)
+ return(EOF);
+ else
+ return(0);
+}
+
+void
+DoFormat(
+ )
+/*++
+
+Routine Description:
+
+ Performs actual parsing and output formating.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+
+{
+ char word[500],c;
+ char prevline[500];
+ char *p;
+ int isfuncdef;
+
+ isfuncdef = 0;
+ *prevline = 0;
+
+ do {
+ if (GetWord(word, 'c') == EOF) {
+ fprintf(stderr,
+ "c2rtf: Function %s not found in %s.\n",
+ Function,
+ FileName);
+ return;
+ }
+
+ if (strcmp(word, Function)) {
+
+ // not the function; collect line
+ strcpy(prevline, word);
+ p = prevline + strlen(prevline);
+ while ((c = getc(InputFile)) != '\n' && c != EOF) {
+ *p++ = c;
+ }
+ *p = 0;
+
+ } else {
+
+ KillWhiteSpace("\n\t ");
+
+ if (getc(InputFile) == '(') {
+ KillWhiteSpace("\t /");
+ c = getc(InputFile);
+ if (c == '\n') {
+ isfuncdef = 1;
+ } else if (c == ')') {
+ KillWhiteSpace(" \t\n");
+ c = getc(InputFile);
+ if(c != ';') {
+ ungetc(c,InputFile);
+ isfuncdef = 2;
+ }
+ }
+ }
+ if (!isfuncdef) {
+ *prevline = 0;
+ }
+ }
+ }
+ while(!isfuncdef);
+
+ printf("\\s89\\keepn\\sl-240\\sa240 \\plain \\b\\f16 %s\\par\n",Function);
+
+ printf("\\pard \\s30\\sl-240\\sa0 \\plain \\b\\f16 %s\\par\n",prevline);
+ if(isfuncdef != 1) {
+ printf("%s()\\par\n",Function);
+ } else {
+ printf("%s(\\par\n",Function);
+ do {
+ int wstate = 0;
+ *word = 0;
+ printf("\\tab ");
+ KillWhiteSpace("\t\n ");
+ do {
+ KillWhiteSpace("\t ");
+ c = getc(InputFile);
+ if (c != '\n' && c != ',') {
+
+ if (*word) {
+ printf("%s ",word);
+ wstate = 1;
+ }
+ ungetc(c, InputFile);
+ GetWord(word, 'c');
+
+ } else {
+
+ if (*word) {
+ if (wstate == 0) {
+ printf(" %s",word);
+ } else {
+ printf("\\plain \\i\\f16 %s\\plain \\b\\f16 ",word);
+ }
+ }
+ if (c == '\n') {
+ printf("\\par\n\\tab )\\par");
+ } else if (c == ',') {
+ printf(",\\par\n");
+ }
+ }
+ }
+ while(c != '\n' && c != ',');
+ }
+ while(c != '\n');
+ }
+
+ if(GetComment()) {
+ printf("\\par \\pard\n");
+ return;
+ }
+
+ while(strncmp("Routine Description:",cp,20)) {
+ cp++;
+ if(*cp == '\0') {
+ fprintf(stderr,"c2rtf: Function %s in %s has no routine description.\n",Function,FileName);
+ printf("\\pard\n");
+ return;
+ }
+ }
+
+ printf("\\par\n");
+ printf("\\plain \\f16\\ul Routine Description:\\plain \\f16 \\par \\par\n");
+ printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 ");
+ for(cp += 22; strchr(" \t\n/",*cp) != NULL; cp++);
+
+ while(strncmp("Arguments:",cp,10)) {
+ if(*cp == '\n') {
+ if(*(cp + 1) == '\n' || !strncmp(cp + 1, "//\n",3)) {
+ printf("\\par\n");
+ for(cp++; strchr(" \t\n/",*cp) != NULL; cp++);
+ continue;
+ } else {
+ putchar(' ');
+ for(cp++; strchr(" \t/",*cp) != NULL; cp++);
+ continue;
+ }
+ }
+ putchar(*cp);
+ cp++;
+
+ if(*cp == '\0') {
+ fprintf(stderr,"c2rtf: Function %s in %s lacks 'Arguments:'.\n",Function,FileName);
+ printf("\\pard\n");
+ return;
+ }
+ }
+
+ printf("\\pard \\plain \\f16\\ul Parameters:\\plain \\f16 \\par \\par\n");
+ printf("\\pard \\s53\\li1152\\fi-576\\sl-240\\sa240 ");
+ for(cp += 11; strchr(" \t\n/",*cp) != NULL; cp++);
+ printf("\\plain \\i\\f16 ");
+ do {
+ putchar(*cp++);
+ }
+ while(isalpha(*cp));
+ printf("\\plain \\f16 ");
+
+ while(strncmp("Return Value",cp,12)) {
+ if(*cp == '\n') {
+ for(cp++; strchr(" \t/",*cp) != NULL; cp++);
+ if(*cp == '\n') {
+ while(strchr(" \t\n/",*cp) != NULL) {
+ cp++;
+ }
+ if(!strncmp("Return Value",cp,12)) {
+ continue;
+ }
+ printf("\\par\n");
+ printf("\\plain \\i\\f16 ");
+ do {
+ putchar(*cp++);
+ }
+ while(isalpha(*cp));
+ printf("\\plain \\f16 ");
+ continue;
+ } else {
+ while(strchr(" \t\n/",*cp) != NULL) {
+ cp++;
+ }
+ putchar(' ');
+ putchar(*cp);
+ }
+ } else {
+ putchar(*cp);
+ }
+ cp++;
+ if(*cp == '\0') {
+ fprintf(stderr,"c2rtf: Function %s in %s lacks 'Return Value'.\n",Function,FileName);
+ printf("\\pard\n");
+ return;
+ }
+
+ }
+
+ printf("\\par \\pard\n");
+ printf("\\plain \\f16\\ul Return Value:\\plain \\f16 \\par \\par\n");
+ printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 ");
+ for(cp += 14; strchr(" \t\n/",*cp) != NULL; cp++);
+
+ while(*cp != '\0' && strncmp(cp,"Environment",11)) {
+ if(*cp == '\n') {
+ for(cp++; strchr(" \t/",*cp) != NULL; cp++);
+ if(*cp == '\n') {
+ printf("\\par\n");
+ for(cp++; strchr(" \n\t/",*cp) != NULL && *cp != EOF; cp++) {
+ if(*cp == '\0') {
+ break;
+ }
+ }
+ continue;
+ } else {
+ putchar(' ');
+ continue;
+ }
+ }
+ putchar(*cp);
+ cp++;
+ }
+
+ if(*cp == '\0') {
+ printf("\\pard \\plain\n");
+ return;
+ }
+
+ printf("\\pard\n");
+ printf("\\plain \\f16\\ul Environment:\\plain \\f16 \\par \\par\n");
+ printf("\\pard \\s53\\li576\\fi0\\sl-240\\sa240 ");
+ for(cp += 14; strchr(" \t\n/",*cp) != NULL; cp++);
+
+ while(*cp != '\0') {
+ if(*cp == '\n') {
+ for(cp++; strchr(" \t/",*cp) != NULL; cp++);
+ if(*cp == '\n') {
+ printf("\\par\n");
+ for(cp++; strchr(" \n\t/",*cp) != NULL && *cp != EOF; cp++) {
+ if(*cp == '\0') {
+ break;
+ }
+ }
+ continue;
+ } else {
+ putchar(' ');
+ continue;
+ }
+ }
+ putchar(*cp);
+ cp++;
+ }
+ printf("\\pard \\plain\n");
+}
+
+int
+GetComment(
+ )
+/*++
+
+Routine Description:
+
+ This routine loads the next comment in the input, defined in the normal C
+ manner with / *++ and --* / (no spaces in there) into the Comment[]
+ array.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ 0 if successful
+ 1 if { precedes the next comment
+ 2 if the comment is not ended
+ 3 if comment size is larger than MAX_COMMENT_SIZE
+
+--*/
+{
+ int index,i;
+ char temp[5];
+
+
+ for(i = 0; i<4; i++) {
+ if((temp[i] = getc(InputFile)) == EOF) {
+ fprintf(stderr,"No comment found.\n");
+ return(1);
+ }
+ }
+ temp[4] = '\0';
+
+ while(strcmp(temp,"/*++") && strcmp(temp + 2,"//")) {
+ temp[0] = temp[1];
+ temp[1] = temp[2];
+ temp[2] = temp[3];
+ temp[3] = getc(InputFile);
+ if(temp[3] == EOF || temp[3] == '{') {
+ fprintf(stderr,"c2rtf: No comment found in %s of %s.\n",Function,FileName);
+ return(1);
+ }
+ }
+
+ for(i = 0; i<4; i++) {
+ if((temp[i] = getc(InputFile)) == EOF) {
+ fprintf(stderr,"c2rtf: Comment not ended in %s of %s.\n",Function,FileName);
+ return(1);
+ }
+ }
+ temp[4] = '\0';
+
+ index = 0;
+ while(strcmp(temp,"--*/") && strcmp(temp,"//--")) {
+ if(temp[0] == '\t') {
+ for(i=0; i<8; i++) {
+ Comment[index++] = ' ';
+ }
+ } else {
+ Comment[index++] = temp[0];
+ }
+ temp[0] = temp[1];
+ temp[1] = temp[2];
+ temp[2] = temp[3];
+ temp[3] = getc(InputFile);
+ if(temp[3] == EOF) {
+ fprintf(stderr,"c2rtf: Comment not ended in %s of %s.\n",Function,FileName);
+ return(2);
+ }
+ if(index >= MAX_COMMENT_SIZE) {
+ fprintf(stderr,"c2rtf: Comment too large in %s of %s.\n",Function,FileName);
+ return(3);
+ }
+ }
+
+ Comment[index] = '\0';
+ cp = Comment;
+ return(0);
+}
+
+int
+strpos(
+ char *s,
+ char c
+ )
+
+/*++
+
+Routine Description:
+
+ Finds the location of the character c in the string s. See section
+ 15.5 of _C: A Reference Manual_, page 300, for complete description.
+
+Parameters:
+
+ s - "haystack" of characters to search for.
+
+ c - character to search for.
+
+Return Value:
+
+ The position of c in s or -1 if c is not in s.
+
+--*/
+
+{
+ int i;
+
+ for(i = 0; *s != '\0'; s++,i++) {
+ if(c == *s) {
+ return(i);
+ }
+ }
+ return(-1);
+}
+
+void GlobalFormat(
+ )
+
+/*++
+
+Routine Description:
+
+ Formats the abstract of a module into RTF format.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ char c,word[50],basename[75],*s;
+ int i;
+
+ do {
+ if(GetWord(word,'c') == EOF) {
+ fprintf(stderr,"Module %s lacks an abstract.\n");
+ return;
+ }
+ }
+ while(strcmp("Abstract",word));
+
+ while((c = getchar()) == ' ' || c == '\t' || c == '\n') {
+ i++;
+ }
+
+ i = 0;
+ if(c == '\"') {
+ while((c = getchar()) != '\"') {
+ basename[i++] = c;
+ }
+ basename[i] = '\0';
+ } else {
+ ungetc(c,stdin);
+ for(s = FileName; *s != '\0'; s++) {
+ if(*s == '\\') {
+ i = 0;
+ } else {
+ basename[i++] = *s;
+ }
+ }
+ basename[i] = '\0';
+ }
+
+ if(!strcmp("continue",basename)) {
+ return;
+ }
+
+ printf("\\page\n");
+ printf("\\pard \\s88\\keepn\\sl-240\\sa240 \\plain \\b\\f16 %s\\par",basename);
+ printf("\\pard \\li576\\sl-240\\sa240 \\plain \\f16\n");
+
+ strcpy(word,"\0");
+ KillWhiteSpace(" \t\n/:");
+ do {
+ c = getc(InputFile);
+ if(c == '\n') {
+ putchar(' ');
+ KillWhiteSpace(" \t/");
+ c = getc(InputFile);
+ if(c == '\n') {
+ printf("\\par\n");
+ KillWhiteSpace(" \t\n/");
+ GetWord(word,'c');
+ if(strcmp(word,"Author")) {
+ printf("%s",word);
+ }
+ } else {
+ putchar(c);
+ }
+ } else {
+ putchar(c);
+ }
+ }
+ while(strcmp(word,"Author"));
+
+ printf("\\pard\n");
+
+ return;
+
+}
diff --git a/private/windbg/doc/tools/makefile b/private/windbg/doc/tools/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/doc/tools/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/doc/tools/sources b/private/windbg/doc/tools/sources
new file mode 100644
index 000000000..1f99cd997
--- /dev/null
+++ b/private/windbg/doc/tools/sources
@@ -0,0 +1,33 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ build template for logoff
+
+Author:
+
+ Kent Forschmiedt (a-kentf) 03-Mar-1993
+
+!ENDIF
+
+
+
+MAJORCOMP=utils
+MINORCOMP=c2rtf
+
+TARGETNAME=c2rtf
+TARGETPATH=obj
+TARGETTYPE=UMAPPL_NOLIB
+USE_CRTDLL=1
+
+SOURCES=c2rtf.c
+
+UMTYPE=console
+UMAPPL=c2rtf
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\user32.lib
diff --git a/private/windbg/doc/wrkspace.bmp b/private/windbg/doc/wrkspace.bmp
new file mode 100644
index 000000000..a7b829da6
--- /dev/null
+++ b/private/windbg/doc/wrkspace.bmp
Binary files differ
diff --git a/private/windbg/driver/crash/crash.bmp b/private/windbg/driver/crash/crash.bmp
new file mode 100644
index 000000000..57e14678b
--- /dev/null
+++ b/private/windbg/driver/crash/crash.bmp
Binary files differ
diff --git a/private/windbg/driver/crash/crash.c b/private/windbg/driver/crash/crash.c
new file mode 100644
index 000000000..ebd3902fb
--- /dev/null
+++ b/private/windbg/driver/crash/crash.c
@@ -0,0 +1,538 @@
+#include <windows.h>
+#include <winioctl.h>
+#include <mmsystem.h>
+#include <stdio.h>
+#include <crashrc.h>
+#include "crashdrv.h"
+
+
+#if DBG
+#define DBGMSG(s) {\
+ char __buf[80]; \
+ OutputDebugString("************************\n"); \
+ OutputDebugString(s); \
+ sprintf(__buf,"Errorcode = %d\n",GetLastError());\
+ OutputDebugString( __buf ); \
+ OutputDebugString("************************\n"); \
+ }
+#else
+#define DBGMSG(s)
+#endif
+
+#define SERVICE_NAME "CrashDrv"
+#define DRIVER_NAME "\\systemroot\\system32\\drivers\\crashdrv.sys"
+#define CRASHDRV_DEVICE "\\\\.\\CrashDrv"
+
+
+HINSTANCE hInst;
+DWORD IoctlBuf[16];
+HBITMAP hBmp;
+
+
+
+LRESULT CrashWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+BOOL InstallDriver(VOID);
+BOOL CrashTheSystem(VOID);
+BOOL StartCrashDrvService(VOID);
+VOID SyncAllVolumes(VOID);
+BOOL IsUserAdmin(VOID);
+
+
+int _cdecl
+main(
+ int argc,
+ char *argv[]
+ )
+{
+ HWND hwnd;
+ MSG msg;
+ WNDCLASS wndclass;
+
+
+ hInst = GetModuleHandle( NULL );
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = CrashWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = DLGWINDOWEXTRA;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(APPICON) );
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = "CrashDialog";
+ RegisterClass( &wndclass );
+
+ hwnd = CreateDialog( hInst,
+ MAKEINTRESOURCE( CRASHDLG ),
+ 0,
+ CrashWndProc
+ );
+
+ ShowWindow( hwnd, SW_SHOWNORMAL );
+
+ while (GetMessage (&msg, NULL, 0, 0)) {
+ if (!IsDialogMessage( hwnd, &msg )) {
+ TranslateMessage (&msg) ;
+ DispatchMessage (&msg) ;
+ }
+ }
+
+ return 0;
+}
+
+
+LRESULT
+CrashWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == WM_INITDIALOG) {
+ hBmp = LoadBitmap( hInst, MAKEINTRESOURCE(CRASHBMP) );
+ return 1;
+ }
+
+ if (message == WM_PAINT) {
+ PAINTSTRUCT ps;
+ HDC hdc;
+ HDC hdcMem;
+ RECT rect;
+
+ hdc = BeginPaint( hwnd, &ps );
+
+ hdcMem = CreateCompatibleDC( hdc );
+ SelectObject( hdcMem, hBmp );
+ GetClientRect( hwnd, &rect );
+
+ StretchBlt(
+ hdc,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ hdcMem,
+ 0,
+ 0,
+ 64,
+ 64,
+ SRCCOPY );
+ DeleteDC(hdcMem);
+
+ EndPaint( hwnd, &ps );
+ return 1;
+ }
+
+ if (message == WM_COMMAND) {
+ if (wParam == ID_CRASH) {
+ if (!IsUserAdmin()) {
+ MessageBeep( 0 );
+ MessageBox(
+ hwnd,
+ "You must be an administrator to crash the system!",
+ "Crash Error",
+ MB_SETFOREGROUND | MB_ICONSTOP | MB_OK );
+ } else {
+ if (!CrashTheSystem()) {
+ MessageBox(
+ hwnd,
+ "An error occurred while trying to crash the system!",
+ "Crash Error",
+ MB_SETFOREGROUND | MB_ICONSTOP | MB_OK );
+ }
+ }
+ } else if (wParam == IDCANCEL) {
+ SendMessage( hwnd, WM_CLOSE, 0, 0 );
+ }
+ }
+
+ if (message == WM_DESTROY) {
+ PostQuitMessage( 0 );
+ return 0;
+ }
+
+ return DefWindowProc( hwnd, message, wParam, lParam );
+}
+
+
+BOOL
+CrashTheSystem(
+ VOID
+ )
+{
+ HANDLE hCrashDrv;
+ DWORD ReturnedByteCount;
+ HGLOBAL hResource;
+ LPVOID lpResource;
+
+
+ if (!StartCrashDrvService()) {
+ return FALSE;
+ }
+
+ SyncAllVolumes();
+
+ hCrashDrv = CreateFile( CRASHDRV_DEVICE,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (hCrashDrv == INVALID_HANDLE_VALUE) {
+ DBGMSG( "createfile() failed\n" );
+ return FALSE;
+ }
+
+ if (waveOutGetNumDevs()) {
+ hResource = LoadResource(
+ hInst,
+ FindResource( hInst, MAKEINTRESOURCE(CRASHWAV), MAKEINTRESOURCE(BINARY) ) );
+ if (hResource) {
+ lpResource = LockResource( hResource );
+ sndPlaySound( lpResource, SND_MEMORY );
+ FreeResource( hResource );
+ }
+ }
+
+ if (!DeviceIoControl(
+ hCrashDrv,
+ (DWORD)IOCTL_CRASHDRV_BUGCHECK,
+ NULL,
+ 0,
+ IoctlBuf,
+ sizeof(IoctlBuf),
+ &ReturnedByteCount,
+ NULL
+ )) {
+ DBGMSG( "deviceiocontrol() failed\n" );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL
+CopyResourceToDriver(
+ VOID
+ )
+{
+ HGLOBAL hResource;
+ LPVOID lpResource;
+ DWORD size;
+ PIMAGE_DOS_HEADER dh;
+ PIMAGE_NT_HEADERS nh;
+ PIMAGE_SECTION_HEADER sh;
+ HANDLE hFile;
+ CHAR buf[MAX_PATH];
+
+
+ hResource = LoadResource(
+ hInst,
+ FindResource( hInst, MAKEINTRESOURCE(CRASHDRVDRIVER), MAKEINTRESOURCE(BINARY) ) );
+
+ if (!hResource) {
+ DBGMSG( "load/findresource() failed\n" );
+ return FALSE;
+ }
+
+ lpResource = LockResource( hResource );
+
+ if (!lpResource) {
+ FreeResource( hResource );
+ DBGMSG( "lockresource() failed\n" );
+ return FALSE;
+ }
+
+ dh = (PIMAGE_DOS_HEADER) lpResource;
+ nh = (PIMAGE_NT_HEADERS) (dh->e_lfanew + (DWORD)lpResource);
+ sh = (PIMAGE_SECTION_HEADER) ((DWORD)nh + sizeof(IMAGE_NT_HEADERS) +
+ ((nh->FileHeader.NumberOfSections - 1) *
+ sizeof(IMAGE_SECTION_HEADER)));
+ size = sh->PointerToRawData + sh->SizeOfRawData;
+
+ GetEnvironmentVariable( "systemroot", buf, sizeof(buf) );
+ strcat( buf, "\\system32\\drivers\\CrashDrv.sys" );
+
+ hFile = CreateFile(
+ buf,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ 0,
+ NULL
+ );
+ if (hFile == INVALID_HANDLE_VALUE) {
+ FreeResource( hResource );
+ DBGMSG( "createfile() failed\n" );
+ return FALSE;
+ }
+
+ WriteFile( hFile, lpResource, size, &size, NULL );
+ CloseHandle( hFile );
+
+ FreeResource( hResource );
+
+ return TRUE;
+}
+
+BOOL
+InstallDriver(
+ VOID
+ )
+{
+ SC_HANDLE hService;
+ SC_HANDLE hOldService;
+ SERVICE_STATUS ServStat;
+
+
+ if (!CopyResourceToDriver()) {
+ DBGMSG( "copyresourcetodriver() failed\n" );
+ return FALSE;
+ }
+
+ if( !( hService = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ) ) ) {
+ DBGMSG( "openscmanager() failed\n" );
+ return FALSE;
+ }
+ if( hOldService = OpenService( hService, SERVICE_NAME, SERVICE_ALL_ACCESS ) ) {
+ if( ! ControlService( hOldService, SERVICE_CONTROL_STOP, & ServStat ) ) {
+ int fError = GetLastError();
+ if( ( fError != ERROR_SERVICE_NOT_ACTIVE ) && ( fError != ERROR_INVALID_SERVICE_CONTROL ) ) {
+ DBGMSG( "controlservice() failed\n" );
+ return FALSE;
+ }
+ }
+ if( ! DeleteService( hOldService ) ) {
+ DBGMSG( "deleteservice() failed\n" );
+ return FALSE;
+ }
+ if( ! CloseServiceHandle( hOldService ) ) {
+ DBGMSG( "closeservicehandle() failed\n" );
+ return FALSE;
+ }
+ }
+ if( ! CreateService( hService, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL, DRIVER_NAME, "Extended base", NULL, NULL, NULL, NULL ) ) {
+ int fError = GetLastError();
+ if( fError != ERROR_SERVICE_EXISTS ) {
+ DBGMSG( "createservice() failed\n" );
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+StartCrashDrvService(
+ VOID
+ )
+{
+ SERVICE_STATUS ssStatus;
+ DWORD dwOldCheckPoint;
+ DWORD ec;
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+
+ schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
+ if (schSCManager == NULL) {
+ DBGMSG( "openscmanager() failed\n" );
+ return FALSE;
+ }
+
+ schService = OpenService( schSCManager, "CrashDrv", SERVICE_ALL_ACCESS );
+ if (schService == NULL) {
+install_driver:
+ if (InstallDriver()) {
+ schService = OpenService( schSCManager, "CrashDrv", SERVICE_ALL_ACCESS );
+ if (schService == NULL) {
+ DBGMSG( "openservice() failed\n" );
+ return FALSE;
+ }
+ } else {
+ DBGMSG( "installdriver() failed\n" );
+ return FALSE;
+ }
+ }
+
+ if (!StartService( schService, 0, NULL )) {
+ ec = GetLastError();
+ CloseServiceHandle( schService );
+ if (ec == ERROR_SERVICE_ALREADY_RUNNING) {
+ return TRUE;
+ }
+ if (ec == ERROR_FILE_NOT_FOUND) {
+ goto install_driver;
+ }
+ DBGMSG( "startservice failed\n" );
+ return FALSE;
+ }
+
+ if (!QueryServiceStatus( schService, &ssStatus)) {
+ DBGMSG( "queryservice failed\n" );
+ CloseServiceHandle( schService );
+ return FALSE;
+ }
+
+ while (ssStatus.dwCurrentState != SERVICE_RUNNING) {
+ dwOldCheckPoint = ssStatus.dwCheckPoint;
+ Sleep(ssStatus.dwWaitHint);
+ if (!QueryServiceStatus( schService, &ssStatus)) {
+ break;
+ }
+ if (dwOldCheckPoint >= ssStatus.dwCheckPoint) {
+ break;
+ }
+ }
+
+ CloseServiceHandle(schService);
+}
+
+
+BOOL
+SyncVolume(
+ CHAR c
+ )
+{
+ CHAR VolumeName[16];
+ HANDLE hVolume;
+
+
+ VolumeName[0] = '\\';
+ VolumeName[1] = '\\';
+ VolumeName[2] = '.';
+ VolumeName[3] = '\\';
+ VolumeName[4] = c;
+ VolumeName[5] = ':';
+ VolumeName[6] = '\0';
+
+ hVolume = CreateFile(
+ VolumeName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+
+ if (hVolume == INVALID_HANDLE_VALUE) {
+ return FALSE;
+ }
+
+ FlushFileBuffers( hVolume );
+
+ CloseHandle( hVolume );
+
+ return TRUE;
+}
+
+
+VOID
+SyncAllVolumes(
+ VOID
+ )
+{
+ DWORD i;
+
+
+ for(i=2; i<26; i++){
+ SyncVolume( (CHAR)((CHAR)i + (CHAR)'a') );
+ }
+}
+
+
+BOOL
+IsUserAdmin(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns TRUE if the caller's process is a
+ member of the Administrators local group.
+
+ Caller is NOT expected to be impersonating anyone and IS
+ expected to be able to open their own process and process
+ token.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE - Caller has Administrators local group.
+
+ FALSE - Caller does not have Administrators local group.
+
+--*/
+
+{
+ HANDLE Token;
+ DWORD BytesRequired;
+ PTOKEN_GROUPS Groups;
+ BOOL b;
+ DWORD i;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
+ PSID AdministratorsGroup;
+
+ //
+ // Open the process token.
+ //
+ if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) {
+ return(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED); // Chicago
+ }
+
+ b = FALSE;
+ Groups = NULL;
+
+ //
+ // Get group information.
+ //
+ if(!GetTokenInformation(Token,TokenGroups,NULL,0,&BytesRequired)
+ && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ && (Groups = (PTOKEN_GROUPS)LocalAlloc(LPTR,BytesRequired))
+ && GetTokenInformation(Token,TokenGroups,Groups,BytesRequired,&BytesRequired)) {
+
+ b = AllocateAndInitializeSid(
+ &NtAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &AdministratorsGroup
+ );
+
+ if(b) {
+
+ //
+ // See if the user has the administrator group.
+ //
+ b = FALSE;
+ for(i=0; i<Groups->GroupCount; i++) {
+ if(EqualSid(Groups->Groups[i].Sid,AdministratorsGroup)) {
+ b = TRUE;
+ break;
+ }
+ }
+
+ FreeSid(AdministratorsGroup);
+ }
+ }
+
+ //
+ // Clean up and return.
+ //
+
+ if(Groups) {
+ LocalFree((HLOCAL)Groups);
+ }
+
+ CloseHandle(Token);
+
+ return(b);
+}
diff --git a/private/windbg/driver/crash/crash.ico b/private/windbg/driver/crash/crash.ico
new file mode 100644
index 000000000..d7196cfb6
--- /dev/null
+++ b/private/windbg/driver/crash/crash.ico
Binary files differ
diff --git a/private/windbg/driver/crash/crash.rc b/private/windbg/driver/crash/crash.rc
new file mode 100644
index 000000000..0ce121a18
--- /dev/null
+++ b/private/windbg/driver/crash/crash.rc
@@ -0,0 +1,30 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Kernel Crasher"
+
+#define VER_INTERNALNAME_STR "crash.exe"
+#define VER_ORIGINALFILENAME_STR "crash.exe"
+
+#include <common.ver>
+
+#include <crashrc.h>
+
+APPICON ICON "crash.ico"
+CRASHDRVDRIVER BINARY "crashdrv.sys"
+CRASHBMP BITMAP "crash.bmp"
+CRASHWAV BINARY "crash.wav"
+
+
+CRASHDLG DIALOG 21, 26, 101, 68
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION
+FONT 14, "Lucida Console"
+CLASS "CrashDialog"
+BEGIN
+ DEFPUSHBUTTON "E&xit", IDCANCEL, 56, 52, 34, 13, NOT WS_TABSTOP
+ PUSHBUTTON "&Crash", IDOK, 11, 52, 34, 13, NOT WS_TABSTOP
+END
diff --git a/private/windbg/driver/crash/crash.wav b/private/windbg/driver/crash/crash.wav
new file mode 100644
index 000000000..5ffc56dc5
--- /dev/null
+++ b/private/windbg/driver/crash/crash.wav
Binary files differ
diff --git a/private/windbg/driver/crash/crashdrv.dbg b/private/windbg/driver/crash/crashdrv.dbg
new file mode 100644
index 000000000..2cb6c7ae4
--- /dev/null
+++ b/private/windbg/driver/crash/crashdrv.dbg
Binary files differ
diff --git a/private/windbg/driver/crash/crashdrv.sys b/private/windbg/driver/crash/crashdrv.sys
new file mode 100644
index 000000000..ade67debf
--- /dev/null
+++ b/private/windbg/driver/crash/crashdrv.sys
Binary files differ
diff --git a/private/windbg/driver/crash/crashrc.h b/private/windbg/driver/crash/crashrc.h
new file mode 100644
index 000000000..265b09206
--- /dev/null
+++ b/private/windbg/driver/crash/crashrc.h
@@ -0,0 +1,7 @@
+#define ID_CRASH IDOK
+#define CRASHDLG 500
+#define APPICON 501
+#define CRASHDRVDRIVER 502
+#define CRASHBMP 503
+#define CRASHWAV 504
+#define BINARY 1024
diff --git a/private/windbg/driver/crash/makefile b/private/windbg/driver/crash/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/driver/crash/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/driver/crash/makefile.inc b/private/windbg/driver/crash/makefile.inc
new file mode 100644
index 000000000..fa4f4b4a9
--- /dev/null
+++ b/private/windbg/driver/crash/makefile.inc
@@ -0,0 +1,7 @@
+obj\$(TARGET_DIRECTORY)\crashdrv.sys : crash.rc
+ copy ..\crashdrv\driver\obj\$(TARGET_DIRECTORY)\crashdrv.sys crashdrv.sys
+ copy ..\crashdrv\driver\obj\$(TARGET_DIRECTORY)\crashdrv.sys obj\$(TARGET_DIRECTORY)\crashdrv.sys
+ touch obj\$(TARGET_DIRECTORY)\crashdrv.sys
+ splitsym -a crashdrv.sys
+
+obj\$(TARGET_DIRECTORY)\crash.res : obj\$(TARGET_DIRECTORY)\crashdrv.sys
diff --git a/private/windbg/driver/crash/sources b/private/windbg/driver/crash/sources
new file mode 100644
index 000000000..890e4427e
--- /dev/null
+++ b/private/windbg/driver/crash/sources
@@ -0,0 +1,18 @@
+MAJORCOMP=windbg
+MINORCOMP=crash
+
+TARGETNAME=crash
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+INCLUDES=..\crashdrv;.
+
+SOURCES=crash.rc crash.c
+
+UMTYPE=windows
+
+NTTARGETFILE0=obj\$(TARGET_DIRECTORY)\crashdrv.sys
+
+# NTKEEPRESOURCETMPFILES=1
+
+LINKLIBS=$(BASEDIR)\public\sdk\lib\*\winmm.lib
diff --git a/private/windbg/driver/crashdrv/crashdrv.c b/private/windbg/driver/crashdrv/crashdrv.c
new file mode 100644
index 000000000..e81655b9c
--- /dev/null
+++ b/private/windbg/driver/crashdrv/crashdrv.c
@@ -0,0 +1,225 @@
+#include <ntddk.h>
+#include <string.h>
+#include "crashdrv.h"
+
+
+#define MEMSIZE 4096
+#define FCN(cc) ((cc >> 2) & 0xFFFFFF)
+#define DEVICE_NAME L"\\Device\\CrashDrv"
+#define DOSDEVICE_NAME L"\\DosDevices\\CrashDrv"
+
+
+typedef VOID (*PTESTFUNC)(PULONG ub);
+
+PTESTFUNC tests[] =
+ {
+ NULL,
+ CrashDrvBugCheck,
+ CrashDrvStackOverFlow,
+ CrashDrvSimpleTest,
+ CrashDrvExceptionTest,
+ CrashDrvHardError,
+ CrashSpecial
+ };
+
+#define MaxTests (sizeof(tests)/sizeof(PTESTFUNC))
+
+ULONG CrashDrvRequest;
+KEVENT CrashEvent;
+ULONG CrashRequest;
+PULONG Funk;
+
+
+NTSTATUS
+CrashDrvOpenClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+CrashDrvUnload(
+ IN PDRIVER_OBJECT DriverObject
+ );
+
+NTSTATUS
+CrashDrvIoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+CrashThread(
+ PVOID Context
+ );
+
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+{
+ UNICODE_STRING DeviceName;
+ PDEVICE_OBJECT deviceObject;
+ NTSTATUS status;
+ UNICODE_STRING LinkObject;
+ WCHAR LinkName[80];
+ ULONG DeviceSize;
+ HANDLE ThreadHandle;
+
+
+ RtlInitUnicodeString( &DeviceName, DEVICE_NAME );
+ status = IoCreateDevice( DriverObject,
+ 0,
+ &DeviceName,
+ FILE_DEVICE_NULL,
+ 0,
+ FALSE,
+ &deviceObject );
+ if (!NT_SUCCESS( status )) {
+ return status;
+ }
+
+ LinkName[0] = UNICODE_NULL;
+
+ RtlInitUnicodeString(&LinkObject, LinkName);
+
+ LinkObject.MaximumLength = sizeof(LinkName);
+
+ RtlAppendUnicodeToString(&LinkObject, L"\\DosDevices");
+
+ DeviceSize = sizeof(L"\\Device") - sizeof(UNICODE_NULL);
+ DeviceName.Buffer += DeviceSize / sizeof(WCHAR);
+ DeviceName.Length -= (USHORT)DeviceSize;
+
+ RtlAppendUnicodeStringToString(&LinkObject, &DeviceName);
+
+ DeviceName.Buffer -= DeviceSize / sizeof(WCHAR);
+ DeviceName.Length += (USHORT)DeviceSize;
+
+ status = IoCreateSymbolicLink(&LinkObject, &DeviceName);
+
+ if (!NT_SUCCESS(status)) {
+ IoDeleteDevice( deviceObject );
+ return status;
+ }
+
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = CrashDrvOpenClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = CrashDrvOpenClose;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CrashDrvIoControl;
+ DriverObject->DriverUnload = CrashDrvUnload;
+
+ KeInitializeEvent( &CrashEvent, NotificationEvent, FALSE );
+
+ Funk = ExAllocatePool( PagedPool, MEMSIZE );
+
+ status = PsCreateSystemThread(
+ &ThreadHandle,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ CrashThread,
+ NULL
+ );
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CrashDrvOpenClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ Irp->IoStatus.Status = status;
+ Irp->IoStatus.Information = 0;
+ status = Irp->IoStatus.Status;
+ IoCompleteRequest( Irp, 0 );
+
+ return status;
+}
+
+VOID
+CrashDrvUnload(
+ IN PDRIVER_OBJECT DriverObject
+ )
+{
+ PDEVICE_OBJECT currentDevice = DriverObject->DeviceObject;
+ UNICODE_STRING fullLinkName;
+
+ while (currentDevice) {
+
+ RtlInitUnicodeString( &fullLinkName, DOSDEVICE_NAME );
+ IoDeleteSymbolicLink(&fullLinkName);
+ IoDeleteDevice(currentDevice);
+
+ currentDevice = DriverObject->DeviceObject;
+
+ }
+}
+
+NTSTATUS
+CrashDrvIoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ PULONG ub;
+
+
+ ub = (PULONG) MmGetSystemAddressForMdl( Irp->MdlAddress );
+
+ if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CRASHDRV_CHECK_REQUEST) {
+ ub[0] = CrashDrvRequest;
+ CrashDrvRequest = 0;
+ } else {
+ if (FCN(IrpSp->Parameters.DeviceIoControl.IoControlCode) > MaxTests) {
+ DbgBreakPoint();
+ } else {
+ tests[FCN(IrpSp->Parameters.DeviceIoControl.IoControlCode)]( ub );
+ }
+ }
+
+ Irp->IoStatus.Information = 0L;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest( Irp, 0 );
+
+ return Status;
+}
+
+
+VOID
+CrashThread(
+ PVOID Context
+ )
+{
+ while( TRUE ) {
+ KeWaitForSingleObject( &CrashEvent, Executive, KernelMode, FALSE, NULL );
+ KeResetEvent( &CrashEvent );
+ switch( CrashRequest ) {
+ case KMODE_EXCEPTION_NOT_HANDLED:
+ {
+ ULONG i,j;
+ i = 0;
+ j = 0;
+ i = j / i;
+ }
+ break;
+
+ case IRQL_NOT_LESS_OR_EQUAL:
+ {
+ KIRQL irql;
+ KeRaiseIrql( DISPATCH_LEVEL, &irql );
+ Funk[0] = 0;
+ KeLowerIrql( irql );
+ }
+ break;
+ }
+ }
+}
diff --git a/private/windbg/driver/crashdrv/crashdrv.h b/private/windbg/driver/crashdrv/crashdrv.h
new file mode 100644
index 000000000..e9d5e4027
--- /dev/null
+++ b/private/windbg/driver/crashdrv/crashdrv.h
@@ -0,0 +1,58 @@
+//
+// CrashDrv driver/test constants
+//
+
+#define FILE_DEVICE_CRASHDRV 0x00008000
+
+
+#define TEST_CHECK_REQUEST 0
+#define TEST_BUGCHECK 1
+#define TEST_STACK_OVERFLOW 2
+#define TEST_SIMPLE 3
+#define TEST_EXCEPTION 4
+#define TEST_HARDERR 5
+#define TEST_SPECIAL 6
+
+#define IOCTL_CRASHDRV_CHECK_REQUEST CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_CHECK_REQUEST, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+#define IOCTL_CRASHDRV_BUGCHECK CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_BUGCHECK, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+#define IOCTL_CRASHDRV_STACK_OVERFLOW CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_STACK_OVERFLOW, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+#define IOCTL_CRASHDRV_SIMPLE CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_SIMPLE, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+#define IOCTL_CRASHDRV_EXCEPTION CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_EXCEPTION, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+#define IOCTL_CRASHDRV_HARDERR CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_HARDERR, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+#define IOCTL_CRASHDRV_SPECIAL CTL_CODE(FILE_DEVICE_CRASHDRV, TEST_SPECIAL, METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
+
+
+//
+// prototypes
+//
+
+VOID
+CrashDrvStackOverFlow(
+ PULONG ub
+ );
+
+VOID
+CrashDrvBugCheck(
+ PULONG ub
+ );
+
+VOID
+CrashDrvSimpleTest(
+ PULONG ub
+ );
+
+VOID
+CrashDrvExceptionTest(
+ PULONG ub
+ );
+
+VOID
+CrashDrvHardError(
+ PULONG ub
+ );
+
+VOID
+CrashSpecial(
+ PULONG ub
+ );
+
diff --git a/private/windbg/driver/crashdrv/crashdrv.rc b/private/windbg/driver/crashdrv/crashdrv.rc
new file mode 100644
index 000000000..4eeecf024
--- /dev/null
+++ b/private/windbg/driver/crashdrv/crashdrv.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "Crash Driver"
+#define VER_INTERNALNAME_STR "crashdrv.sys"
+
+#include "common.ver"
+
diff --git a/private/windbg/driver/crashdrv/dirs b/private/windbg/driver/crashdrv/dirs
new file mode 100644
index 000000000..b84056424
--- /dev/null
+++ b/private/windbg/driver/crashdrv/dirs
@@ -0,0 +1 @@
+DIRS=driver tests
diff --git a/private/windbg/driver/crashdrv/driver/makefile b/private/windbg/driver/crashdrv/driver/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/driver/crashdrv/driver/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/driver/crashdrv/driver/sources b/private/windbg/driver/crashdrv/driver/sources
new file mode 100644
index 000000000..b0b9ea22f
--- /dev/null
+++ b/private/windbg/driver/crashdrv/driver/sources
@@ -0,0 +1,12 @@
+MAJORCOMP=windbg
+MINORCOMP=driver
+
+TARGETNAME=crashdrv
+TARGETPATH=obj
+TARGETTYPE=DRIVER
+
+INCLUDES=$(BASEDIR)\private\ntos\inc
+
+SOURCES=..\crashdrv.c ..\tests.c ..\crashdrv.rc
+
+LINKER_FLAGS=-miscrdata
diff --git a/private/windbg/driver/crashdrv/tests.c b/private/windbg/driver/crashdrv/tests.c
new file mode 100644
index 000000000..d9e5143e1
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests.c
@@ -0,0 +1,266 @@
+#include <ntos.h>
+#include <nturtl.h>
+#include <ntexapi.h>
+
+extern KEVENT CrashEvent;
+extern ULONG CrashRequest;
+
+unsigned int fExcept1 = 0;
+unsigned int cTry1 = 0;
+unsigned int cRaise1pre = 0;
+unsigned int cRaise1post = 0;
+unsigned int cExcept1 = 0;
+unsigned int cFilter1 = 0;
+
+unsigned int fExcept2 = 0;
+unsigned int cTry2 = 0;
+unsigned int cRaise2pre = 0;
+unsigned int cRaise2post = 0;
+unsigned int cFinally2 = 0;
+
+unsigned int fExcept3 = 0;
+unsigned int cTry3 = 0;
+unsigned int cRaise3pre = 0;
+unsigned int cRaise3post = 0;
+unsigned int cExcept3 = 0;
+unsigned int cFilter3 = 0;
+
+unsigned int fExcept4 = 0;
+unsigned int cTry4 = 0;
+unsigned int cRaise4pre = 0;
+unsigned int cRaise4post = 0;
+unsigned int cFinally4 = 0;
+
+unsigned int fExcept5 = 0;
+unsigned int cTry5 = 0;
+unsigned int cRaise5pre = 0;
+unsigned int cRaise5post = 0;
+unsigned int cExcept5 = 0;
+unsigned int cFilter5 = 0;
+
+unsigned long GlobalVar = 0;
+
+int ExceptFilterFn5 (int ExceptCode)
+{
+ DbgPrint( "CrashDrv exception filter\n" );
+ cFilter5 ++;
+ return ExceptCode == 0x00003344 ? EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_EXECUTION ;
+}
+
+void function5 ()
+{
+ _try
+ {
+ cTry5 ++;
+ if (fExcept5)
+ {
+ cRaise5pre ++;
+ ExRaiseStatus( fExcept4 );
+ cRaise5post ++;
+ }
+ }
+ _except (ExceptFilterFn5 (GetExceptionCode ()))
+ {
+ cExcept5 ++;
+ }
+}
+
+void function4 ()
+{
+ _try
+ {
+ cTry4 ++;
+ function5 ();
+ if (fExcept4)
+ {
+ cRaise4pre ++;
+ ExRaiseStatus( fExcept4 );
+ cRaise4post ++;
+ }
+ }
+ _finally
+ {
+ cFinally4 ++;
+ }
+}
+
+int ExceptFilterFn3 (int ExceptCode)
+{
+ cFilter3 ++;
+ return ExceptCode == 0x00005678 ? EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_CONTINUE_SEARCH ;
+}
+
+void function3 ()
+{
+ _try
+ {
+ cTry3 ++;
+ function4 ();
+ if (fExcept3)
+ {
+ cRaise3pre ++;
+ ExRaiseStatus( fExcept3 );
+ cRaise3post ++;
+ }
+ }
+ _except (ExceptFilterFn3 (GetExceptionCode ()))
+ {
+ cExcept3 ++;
+ }
+}
+
+void function2 ()
+{
+ _try
+ {
+ cTry2 ++;
+ function3 ();
+ if (fExcept2)
+ {
+ cRaise2pre ++;
+ ExRaiseStatus( fExcept2 );
+ cRaise2post ++;
+ }
+ }
+ _finally
+ {
+ cFinally2 ++;
+ }
+}
+
+int ExceptFilterMain (int ExceptCode)
+{
+ cFilter1 ++;
+ return ExceptCode == 0x00001010 ? EXCEPTION_EXECUTE_HANDLER :
+ ExceptCode == 0x00005678 ? EXCEPTION_CONTINUE_EXECUTION :
+ EXCEPTION_CONTINUE_SEARCH ;
+}
+
+VOID
+CrashDrvExceptionTest(
+ PULONG ub
+ )
+{
+ int i = 0;
+
+ while ( i++ < 10 ) {
+ _try {
+ cTry1 ++;
+ function2 ();
+ if (fExcept1) {
+ cRaise1pre ++;
+ ExRaiseStatus( fExcept1 );
+ cRaise1post ++;
+ }
+ }
+ _except (ExceptFilterMain (GetExceptionCode ())) {
+ cExcept1 ++;
+ }
+ fExcept1 = 0;
+ fExcept2 = 0;
+ fExcept3 = 0;
+ fExcept4 = 0;
+ fExcept5 = 0;
+ }
+}
+
+VOID
+CrashDrvSimpleTest(
+ PULONG ub
+ )
+{
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ GlobalVar = 69;
+ i = 1;
+ j = 2;
+ k = 3;
+}
+
+VOID
+CrashDrvStackOverFlow(
+ PULONG ub
+ )
+{
+}
+
+VOID
+CrashDrvBugCheck(
+ PULONG ub
+ )
+{
+ KeBugCheck( 0x69696969 );
+}
+
+VOID
+CrashDrvHardError(
+ PULONG ub
+ )
+{
+ NTSTATUS Status;
+ NTSTATUS ErrorCode;
+ ULONG Response;
+
+
+ ErrorCode = STATUS_SYSTEM_PROCESS_TERMINATED;
+
+ Status = ExRaiseHardError(
+ ErrorCode,
+ 0,
+ 0,
+ NULL,
+ OptionShutdownSystem,
+ &Response
+ );
+
+ return;
+}
+
+
+ULONG CurrentWatchPoint=0;
+
+VOID
+AsyncSetBreakPoint(
+ ULONG LinearAddress
+ )
+{
+#ifdef i386
+ CurrentWatchPoint = LinearAddress;
+
+ _asm {
+ mov eax, LinearAddress
+ mov dr0, eax
+ mov eax, 10303h
+ mov dr7, eax
+ }
+#endif
+}
+
+VOID
+AsyncRemoveBreakPoint(
+ ULONG LinearAddress
+ )
+{
+#ifdef i386
+ CurrentWatchPoint = 0;
+
+ _asm {
+ mov eax, 0
+ mov dr7, eax
+ }
+#endif
+}
+
+#pragma optimize ( "", on )
+
+VOID
+CrashSpecial(
+ PULONG ub
+ )
+{
+ CrashRequest = ub[0];
+ KeSetEvent( &CrashEvent, 0, FALSE );
+}
diff --git a/private/windbg/driver/crashdrv/tests/install.c b/private/windbg/driver/crashdrv/tests/install.c
new file mode 100644
index 000000000..1f67de05d
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/install.c
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ install.c
+
+Abstract:
+
+ This module contains the code that implements a driver installation
+
+Author:
+
+ Wesley Witt (wesw) 1-Oct-1993
+
+Environment:
+
+ User mode
+
+Notes:
+
+Revision History:
+
+
+--*/
+
+#include <windows.h>
+#include <winsvc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SERVICE_NAME "CrashDrv"
+#define DRIVER_NAME "\\systemroot\\system32\\drivers\\CrashDrv.sys"
+
+
+void _cdecl main( void )
+{
+ SC_HANDLE hService;
+ SC_HANDLE hOldService;
+ SERVICE_STATUS ServStat;
+ CHAR buf[MAX_PATH];
+
+
+ if( !( hService = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ) ) ) {
+ printf( "Error: Could not open handle to service manager for CrashDrv driver; error code = %u\n", GetLastError() );
+ return;
+ }
+ if( hOldService = OpenService( hService, SERVICE_NAME, SERVICE_ALL_ACCESS ) ) {
+ if( ! ControlService( hOldService, SERVICE_CONTROL_STOP, & ServStat ) ) {
+ int fError = GetLastError();
+ if( ( fError != ERROR_SERVICE_NOT_ACTIVE ) && ( fError != ERROR_INVALID_SERVICE_CONTROL ) ) {
+ printf( "Error: Could not stop %s service; error code = %u\n", SERVICE_NAME, fError );
+ return;
+ }
+ }
+ if( ! DeleteService( hOldService ) ) {
+ printf( "Error: Could not delete old service for %s driver; error code = %u\n", SERVICE_NAME, GetLastError() );
+ return;
+ }
+ if( ! CloseServiceHandle( hOldService ) ) {
+ printf( "Error: Could not delete old service for %s driver; error code = %u\n", SERVICE_NAME, GetLastError() );
+ return;
+ }
+ }
+ if( ! CreateService( hService, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL, DRIVER_NAME, "Extended base", NULL, NULL, NULL, NULL ) ) {
+ int fError = GetLastError();
+ if( fError != ERROR_SERVICE_EXISTS ) {
+ printf( "Error: Could not create %s service; error code = %u\n", SERVICE_NAME, fError );
+ return;
+ }
+ }
+ if( ! CloseServiceHandle( hService ) ) {
+ printf( "Error: Could not close handle to service manager for %s driver; error code = %u\n", SERVICE_NAME, GetLastError() );
+ return;
+ }
+
+ GetEnvironmentVariable( "systemroot", buf, sizeof(buf) );
+ strcat( buf, "\\system32\\drivers\\CrashDrv.sys" );
+ CopyFile( "CrashDrv.sys", buf, FALSE );
+}
diff --git a/private/windbg/driver/crashdrv/tests/install.rc b/private/windbg/driver/crashdrv/tests/install.rc
new file mode 100644
index 000000000..34b3cfa93
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/install.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Kernel Crash Driver Install Utility"
+
+#define VER_INTERNALNAME_STR "install.exe"
+#define VER_ORIGINALFILENAME_STR "install.exe"
+
+#include <common.ver>
diff --git a/private/windbg/driver/crashdrv/tests/makefile b/private/windbg/driver/crashdrv/tests/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/driver/crashdrv/tests/makefile.inc b/private/windbg/driver/crashdrv/tests/makefile.inc
new file mode 100644
index 000000000..577865208
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/makefile.inc
@@ -0,0 +1,3 @@
+obj\$(TARGET_DIRECTORY)\test.res: test.rc
+
+obj\$(TARGET_DIRECTORY)\install.res: install.rc
diff --git a/private/windbg/driver/crashdrv/tests/sources b/private/windbg/driver/crashdrv/tests/sources
new file mode 100644
index 000000000..049a81ec4
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/sources
@@ -0,0 +1,17 @@
+MAJORCOMP=windbg
+MINORCOMP=driver
+
+TARGETNAME=crashdrv
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=$(BASEDIR)\private\ntos\inc;..\
+
+SOURCES=
+
+UMTYPE=console
+UMAPPL=test*install
+UMRES=$(@R).res
+
+NTTARGETFILE0=obj\*\test.res \
+ obj\*\install.res
diff --git a/private/windbg/driver/crashdrv/tests/test.c b/private/windbg/driver/crashdrv/tests/test.c
new file mode 100644
index 000000000..68b13fad8
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/test.c
@@ -0,0 +1,295 @@
+#include <windows.h>
+#include <winioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "crashdrv.h"
+
+#define CRASHDRV_DEVICE "\\\\.\\CrashDrv"
+#define KMODE_EXCEPTION_NOT_HANDLED ((ULONG)0x0000001EL)
+#define IRQL_NOT_LESS_OR_EQUAL ((ULONG)0x0000000AL)
+
+typedef struct _TESTINFO {
+ DWORD CtlCode;
+ DWORD TestNum;
+ LPSTR Description;
+} TESTINFO, *LPTESTINFO;
+
+TESTINFO TestInformation[] =
+ {
+ 0, 0, NULL,
+ (DWORD)IOCTL_CRASHDRV_BUGCHECK, TEST_BUGCHECK, "Bugcheck",
+ (DWORD)IOCTL_CRASHDRV_STACK_OVERFLOW, TEST_STACK_OVERFLOW, "Stack overflow",
+ (DWORD)IOCTL_CRASHDRV_SIMPLE, TEST_SIMPLE, "Simple",
+ (DWORD)IOCTL_CRASHDRV_EXCEPTION, TEST_EXCEPTION, "Exception",
+ (DWORD)IOCTL_CRASHDRV_HARDERR, TEST_HARDERR, "Hard error",
+ (DWORD)IOCTL_CRASHDRV_SPECIAL, TEST_SPECIAL, "Special"
+ };
+
+#define MaxTests (sizeof(TestInformation)/sizeof(TESTINFO))
+
+DWORD IoctlBuf[16];
+DWORD TestNumber;
+
+VOID GetCommandLineArgs(VOID);
+VOID Usage(VOID);
+DWORD CrashDrvCheckRequest(HANDLE);
+BOOL StartCrashDrvService(VOID);
+
+void _cdecl
+main( void )
+{
+ HANDLE hCrashDrv;
+ DWORD rq;
+ DWORD ReturnedByteCount;
+
+
+ ZeroMemory( IoctlBuf, sizeof(IoctlBuf) );
+
+ GetCommandLineArgs();
+
+ if (!StartCrashDrvService()) {
+ return;
+ }
+
+ hCrashDrv = CreateFile( CRASHDRV_DEVICE,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if ( hCrashDrv == INVALID_HANDLE_VALUE ) {
+ printf("Could not open the CrashDrv device (%d)\n",GetLastError());
+ ExitProcess(1);
+ }
+
+ printf("Successfuly opened the CrashDrv device\n");
+
+ if (TestNumber) {
+ if (TestNumber > MaxTests) {
+ printf( "invalid test number\n" );
+ Usage();
+ }
+ if (!DeviceIoControl(
+ hCrashDrv,
+ TestInformation[TestNumber].CtlCode,
+ NULL,
+ 0,
+ IoctlBuf,
+ sizeof(IoctlBuf),
+ &ReturnedByteCount,
+ NULL
+ )) {
+ printf( "call to driver failed <ec=%d>\n", GetLastError() );
+ }
+ return;
+ }
+
+ while( TRUE ) {
+
+ rq = CrashDrvCheckRequest( hCrashDrv );
+
+ if (rq) {
+ if (!DeviceIoControl(
+ hCrashDrv,
+ CTL_CODE(FILE_DEVICE_CRASHDRV, rq, METHOD_BUFFERED,FILE_ANY_ACCESS),
+ NULL,
+ 0,
+ IoctlBuf,
+ sizeof(IoctlBuf),
+ &ReturnedByteCount,
+ NULL
+ )) {
+ printf( "call to driver failed <ec=%d>\n", GetLastError() );
+ }
+ }
+
+ Sleep(500);
+ }
+
+ CloseHandle( hCrashDrv );
+ return;
+}
+
+
+DWORD
+CrashDrvCheckRequest(
+ HANDLE hCrashDrv
+ )
+{
+ DWORD ReturnedByteCount;
+ BOOL rc;
+
+
+ ZeroMemory( IoctlBuf, sizeof(IoctlBuf) );
+
+ rc = DeviceIoControl(
+ hCrashDrv,
+ (DWORD)IOCTL_CRASHDRV_CHECK_REQUEST,
+ NULL,
+ 0,
+ IoctlBuf,
+ sizeof(IoctlBuf),
+ &ReturnedByteCount,
+ NULL
+ );
+
+ return IoctlBuf[0];
+}
+
+
+VOID
+Usage(
+ VOID
+ )
+{
+ DWORD i;
+
+ printf( "usage: TEST [options]\n" );
+ printf( " [-?] Display this message\n" );
+ printf( " [-t test-number] Execute a test\n" );
+ for (i=1; i<MaxTests; i++) {
+ printf( " #%d %s\n", i, TestInformation[i].Description );
+ }
+ ExitProcess(0);
+}
+
+
+VOID
+GetCommandLineArgs(
+ VOID
+ )
+{
+ char *lpstrCmd = GetCommandLine();
+ UCHAR ch;
+ DWORD i = 0;
+ char buf[10];
+
+ // skip over program name
+ do {
+ ch = *lpstrCmd++;
+ }
+ while (ch != ' ' && ch != '\t' && ch != '\0');
+
+ // skip over any following white space
+ while (ch == ' ' || ch == '\t') {
+ ch = *lpstrCmd++;
+ }
+
+ // process each switch character '-' as encountered
+
+ while (ch == '-' || ch == '/') {
+ ch = tolower(*lpstrCmd++);
+ // process multiple switch characters as needed
+ do {
+ switch (ch) {
+ case 't':
+ i=0;
+ ch = *lpstrCmd++;
+ while (ch == ' ' || ch == '\t') {
+ ch = *lpstrCmd++;
+ }
+ while (ch != ' ' && ch != '\0' && ch != ',') {
+ buf[i++] = ch;
+ ch = *lpstrCmd++;
+ }
+ buf[i] = 0;
+ TestNumber = atoi( buf );
+ if (ch == ',') {
+ i=0;
+ ch = *lpstrCmd++;
+ while (ch != ' ' && ch != '\0') {
+ buf[i++] = ch;
+ ch = *lpstrCmd++;
+ }
+ buf[i] = 0;
+ IoctlBuf[0] = atoi( buf );
+ if (TestNumber == TEST_SPECIAL) {
+ if (IoctlBuf[0] == 1) {
+ IoctlBuf[0] = KMODE_EXCEPTION_NOT_HANDLED;
+ }
+ if (IoctlBuf[0] == 2) {
+ IoctlBuf[0] = IRQL_NOT_LESS_OR_EQUAL;
+ }
+ }
+ }
+ break;
+
+ case '?':
+ Usage();
+ ch = *lpstrCmd++;
+ break;
+
+ default:
+ return;
+ }
+ } while (ch != ' ' && ch != '\t' && ch != '\0');
+
+ while (ch == ' ' || ch == '\t') {
+ ch = *lpstrCmd++;
+ }
+ }
+
+ return;
+}
+
+
+BOOL
+StartCrashDrvService(
+ VOID
+ )
+{
+ SERVICE_STATUS ssStatus;
+ DWORD dwOldCheckPoint;
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+
+
+ schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
+ if (schSCManager == NULL) {
+ printf( "could not open service controller database\n" );
+ return FALSE;
+ }
+
+ schService = OpenService( schSCManager, "CrashDrv", SERVICE_ALL_ACCESS );
+ if (schService == NULL) {
+ printf( "CrashDrv service is not installed, run install.exe\n" );
+ return FALSE;
+ }
+
+ if (!StartService( schService, 0, NULL )) {
+ if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
+ printf( "CrashDrv service already running\n" );
+ return TRUE;
+ }
+ printf( "CrashDrv service could not be started\n" );
+ return FALSE;
+ }
+
+ if (!QueryServiceStatus( schService, &ssStatus)) {
+ printf( "CrashDrv service could not be started\n" );
+ return FALSE;
+ }
+
+ while (ssStatus.dwCurrentState != SERVICE_RUNNING) {
+ dwOldCheckPoint = ssStatus.dwCheckPoint;
+ Sleep(ssStatus.dwWaitHint);
+ if (!QueryServiceStatus( schService, &ssStatus)) {
+ break;
+ }
+ if (dwOldCheckPoint >= ssStatus.dwCheckPoint) {
+ break;
+ }
+ }
+
+ if (ssStatus.dwCurrentState == SERVICE_RUNNING)
+ printf("CrashDrv service started\n");
+ else {
+ printf("CrashDrv service not started: \n");
+ }
+
+ CloseServiceHandle(schService);
+}
diff --git a/private/windbg/driver/crashdrv/tests/test.rc b/private/windbg/driver/crashdrv/tests/test.rc
new file mode 100644
index 000000000..8c4cc9dc4
--- /dev/null
+++ b/private/windbg/driver/crashdrv/tests/test.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Kernel Crash Driver Tester"
+
+#define VER_INTERNALNAME_STR "test.exe"
+#define VER_ORIGINALFILENAME_STR "test.exe"
+
+#include <common.ver>
diff --git a/private/windbg/driver/dirs b/private/windbg/driver/dirs
new file mode 100644
index 000000000..8e56f9344
--- /dev/null
+++ b/private/windbg/driver/dirs
@@ -0,0 +1 @@
+dirs=crashdrv crash
diff --git a/private/windbg/eecan/common.inc b/private/windbg/eecan/common.inc
new file mode 100644
index 000000000..8555f41d0
--- /dev/null
+++ b/private/windbg/eecan/common.inc
@@ -0,0 +1,50 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ common.inc
+
+Abstract:
+
+ This is an include file for makefile.inc in each of the
+ directories which has c files that are wrappers for the
+ files in this directory. The WRAPPEDCOBJECTS macro contains
+ a list of the objects which are dependent on the files
+ in this directory.
+
+ SRCDIR must be defined in each makefile.inc, and will
+ always point to the directory that this file is in.
+
+
+Author:
+
+ Kent Forschmiedt
+
+!ENDIF
+
+
+WRAPPEDCOBJECTS = obj\*\debapi.obj \
+ obj\*\debbind.obj \
+ obj\*\deberr.obj \
+ obj\*\debeval.obj \
+ obj\*\debfmt.obj \
+ obj\*\deblex.obj \
+ obj\*\deblexer.obj \
+ obj\*\debparse.obj \
+ obj\*\debsrch.obj \
+ obj\*\debsup.obj \
+ obj\*\debsym.obj \
+ obj\*\debtree.obj \
+ obj\*\debtyper.obj \
+ obj\*\debutil.obj \
+ obj\*\debwalk.obj \
+ obj\*\eeformat.obj \
+ obj\*\r10math.obj
+
+
+$(WRAPPEDCOBJECTS:*=i386): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=mips): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=alpha): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=ppc): $(SRCDIR)\$$(@B).c
diff --git a/private/windbg/eecan/cxassert.h b/private/windbg/eecan/cxassert.h
new file mode 100644
index 000000000..0b3962ee6
--- /dev/null
+++ b/private/windbg/eecan/cxassert.h
@@ -0,0 +1,38 @@
+/***
+*assert.h - define the assert macro
+*
+* Copyright (c) 1985-1987, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the assert(exp) macro.
+* [ANSI/System V]
+*
+*Modified:
+* Allent 3/14/88 - call Quit instead of abort
+*******************************************************************************/
+#ifndef _ASSERT_DEFINED
+
+#if DBG
+
+#ifdef MIPS_C
+#define assert(exp) { \
+ if (!(exp)) { \
+ assert_out("exp", __FILE__, __LINE__); \
+ } \
+ }
+#else
+#define assert(exp) {\
+ if (!(exp)) {\
+ assert_out(#exp, __FILE__, __LINE__);\
+ } \
+ }
+#endif
+#else
+
+#define assert(exp)
+
+#endif /* DBG */
+
+#define _ASSERT_DEFINED
+
+#endif /* _ASSERT_DEFINED */
diff --git a/private/windbg/eecan/debapi.c b/private/windbg/eecan/debapi.c
new file mode 100644
index 000000000..13ddbdda8
--- /dev/null
+++ b/private/windbg/eecan/debapi.c
@@ -0,0 +1,1812 @@
+/*** debapi.c - api interface to expression evaluator
+ *
+ * API interface between C and C++ expression evaluator and debugger
+ * kernel.
+ */
+
+
+
+
+LOCAL EESTATUS ParseBind (EEHSTR, HTM, PHTM, uint *, uint, SHFLAG, uint);
+
+// defines for version string
+
+#if defined (C_ONLY)
+#define LANG "Ansi C "
+#define LANGID "C"
+#else
+#define LANG "C/C++ "
+#define LANGID "CPP"
+#endif
+
+#if (rmm <= 9)
+#define rmmpad "0"
+#else
+#define rmmpad
+#endif
+
+#if (rup <= 9)
+#define ruppad "00"
+#elif (rup <= 99)
+#define ruppad "0"
+#else
+#define ruppad
+#endif
+
+//#define SZVER1(a,b,c) #a "." rmmpad #b "." ruppad #c
+#define SZVER1(a,b,c) ".."
+#define SZVER2(a,b,c) SZVER1(a, b, c)
+#define SZVER SZVER2(rmj,rmm,rup)
+#define OPSYS "Windows NT"
+
+// version string.
+
+
+char EETitle[] = LANGID;
+char EECopyright[] = LANG "expression evaluator for " OPSYS "version " SZVER
+"\nCopyright(c) 1992 Microsoft Corporation\n"
+"\0" __DATE__ " " __TIME__ "\xE0\xEA""01";
+
+
+
+
+PCVF pCVF; // callback routine map
+PCRF pCRF;
+
+bool_t FInEvaluate = FALSE; // Catch Re-entrancy problems
+bool_t FNtsdEvalType = FALSE;
+
+uchar Evaluating = FALSE; // set not in evaluation phase
+uchar BindingBP = FALSE; // true if binding a breakpoint expression
+pexstate_t pExState = NULL; // address of locked expression state structure
+pstree_t pTree = NULL; // address of locked syntax or evaluation tree
+bnode_t bArgList = 0; // based pointer to argument list
+HDEP hEStack = 0; // handle of evaluation stack if not zero
+pelem_t pEStack = NULL; // address of locked evaluation stack
+belem_t StackLen; // length of evaluation stack buffer
+belem_t StackMax; // maximum length reached by evaluation stack
+belem_t StackOffset; // offset in stack to next element
+belem_t StackCkPoint; // checkpointed evaluation stack offset
+peval_t ST; // pointer to evaluation stack top
+peval_t STP; // pointer to evaluation stack previous
+PCXT pCxt = NULL; // pointer to current cxt for bind
+bnode_t bnCxt = 0; // based pointer to node containing {...} context
+char *pExStr = NULL; // pointer to expression string
+CV_typ_t ClassExp = 0; // current explicit class
+CV_typ_t ClassImp = 0; // implicit class (set if current context is method)
+long ClassThisAdjust = 0;// cmplicit class this adjustor
+char *vfuncptr = "\x07""__vfptr";
+char *vbaseptr = "\x07""__vbptr";
+HTM *pTMList; // pointer to breakpoint return list
+PTML pTMLbp; // global pointer to TML for breakpoint
+HDEP hBPatch = 0; // handle to back patch data during BP bind
+ushort iBPatch; // index into pTMLbp for backpatch data
+bool_t GettingChild = FALSE; // true if in EEGetChildTM
+BOOL fAutoClassCast;
+
+char Suffix = '\0'; // Suffix for symbol search.
+
+// global handle to the CXT list buffer
+
+HCXTL hCxtl = 0; // handle for context list buffer during GetCXTL
+PCXTL pCxtl = NULL; // pointer to context list buffer during GetCXTL
+ushort mCxtl = 0; // maximum number of elements in context list
+PCXT pBindBPCxt = NULL; // pointer to Bp Binding context
+
+extern EESTATUS EEFormatMemory();
+extern EESTATUS EEUnformatMemory();
+extern EESTATUS EEFormatEnumerate();
+
+
+#ifdef DEBUGVER
+DEBUG_VERSION('E','E',"Expression Evaluator")
+#else
+RELEASE_VERSION('E','E',"Expression Evaluator")
+#endif
+
+DBGVERSIONCHECK()
+
+void EEInitializeExpr (PCI pCVInfo, PEI pExprinfo)
+{
+static EXF EXF = {
+ EEFreeStr,
+ EEGetError,
+ EEParse,
+ EEBindTM,
+ EEvaluateTM,
+ EEGetExprFromTM,
+ EEGetValueFromTM,
+ EEGetNameFromTM,
+ EEGetTypeFromTM,
+ EEFormatCXTFromPCXT,
+ EEFreeTM,
+ EEParseBP,
+ EEFreeTML,
+ EEInfoFromTM,
+ EEFreeTI,
+ EEGetCXTLFromTM,
+ EEFreeCXTL,
+ EEAssignTMToTM,
+ EEIsExpandable,
+ EEAreTypesEqual,
+ EEcChildrenTM,
+ EEGetChildTM,
+ EEDereferenceTM,
+ EEcParamTM,
+ EEGetParmTM,
+ EEGetTMFromHSYM,
+ EEFormatAddress,
+ EEGetHSYMList,
+ EEFreeHSYMList,
+ EEFormatAddr,
+ EEUnFormatAddr,
+ NULL,
+ NULL,
+ NULL,
+ EEFormatMemory,
+ EEUnformatMemory,
+ EEFormatEnumerate,
+ EEGetHtypeFromTM,
+ EESetSuffix
+ };
+
+ // assign the callback routines
+
+ pCVF = pCVInfo->pStructCVAPI;
+ pCRF = pCVInfo->pStructCRuntime;
+
+ pExprinfo->Version = 1;
+ pExprinfo->pStructExprAPI = &EXF;
+ pExprinfo->Language = 0;
+ pExprinfo->IdCharacters = "_$";
+ pExprinfo->EETitle = EETitle;
+#if defined (C_ONLY)
+ pExprinfo->EESuffixes = ".c.h";
+#else
+ pExprinfo->EESuffixes = ".cpp.cxx.c.hpp.hxx.h";
+#endif
+ pExprinfo->Assign = "\x001""=";
+}
+
+
+/** Set suffix
+ */
+void EESetSuffix (char c)
+{
+ Suffix = c;
+}
+
+
+
+/** EEAreTypesEqual - are TM types equal
+ *
+ * flag = EEAreTypesEqual (phTMLeft, phTMRight);
+ *
+ * Entry phTMLeft = pointer to handle of left TM
+ * phTMRight = pointer to handle of right TM
+ *
+ * Exit none
+ *
+ * Returns TRUE if TMs have identical types
+ */
+
+
+SHFLAG EEAreTypesEqual (PHTM phTMLeft, PHTM phTMRight)
+{
+ return (AreTypesEqual (*phTMLeft, *phTMRight));
+}
+
+
+/** EEGetHtypeFromTM - Get a HTYPE from a TM
+ *
+ * hType = EEGetHtypeFromTM ( phTM );
+ *
+ * Entry phTM = pointer to handle of TM
+ *
+ * Exit none
+ *
+ * Returns The HTYPE of the TM result or 0
+ */
+
+
+HTYPE EEGetHtypeFromTM(PHTM phTM )
+{
+ return ( GetHtypeFromTM(*phTM) );
+}
+
+
+
+
+/** EEAssignTMToTM - assign TMRight to TMLeft
+ *
+ * No longer used
+ *
+ * Exit none
+ *
+ * Returns EECATASTROPHIC
+ */
+
+
+EESTATUS EEAssignTMToTM (PHTM phTMLeft, PHTM phTMRight)
+{
+ Unreferenced(phTMLeft);
+ Unreferenced(phTMRight);
+
+ return(EECATASTROPHIC);
+}
+
+
+
+
+/** EEBindTM - bind syntax tree to a context
+ *
+ * ushort EEBindTM (phExState, pCXT, fForceBind, fEnableProlog);
+ *
+ * Entry phExState = pointer to expression state structure
+ * pCXT = pointer to context packet
+ * fForceBind = TRUE if rebind required.
+ * fForceBind = FALSE if rebind decision left to expression evaluator.
+ * fEnableProlog = FALSE if function scoped symbols only after prolog
+ * fEnableProlog = TRUE if function scoped symbols during prolog
+ *
+ * Exit tree rebound if necessary
+ *
+ * Returns EENOERROR if no error in bind
+ * EECATASTROPHIC if null TM pointer
+ * EENOMEMORY if unable to get memory for buffers
+ * EEGENERAL if error (pExState->err_num is error)
+ */
+
+
+EESTATUS
+EEBindTM(
+ PHTM phTM,
+ PCXT pcxt,
+ SHFLAG fForceBind,
+ SHFLAG fEnableProlog,
+ BOOL fSpecialBind
+ )
+{
+ uint flags = 0;
+ EESTATUS status;
+
+ DASSERT( !FInEvaluate )
+ if ( FInEvaluate ) return(EECATASTROPHIC);
+ FInEvaluate = TRUE;
+
+ // bind without suppressing overloaded operators
+ if (fForceBind == TRUE) {
+ flags |= BIND_fForceBind;
+ }
+ if (fEnableProlog == TRUE) {
+ flags |= BIND_fEnableProlog;
+ }
+
+ /*
+ * Insure that the address in the context field is really in
+ * the correct format for the symbol handler
+ */
+
+ if (!ADDR_IS_LI(pcxt->addr)) {
+ SHUnFixupAddr(&pcxt->addr);
+ }
+
+ FNtsdEvalType = fSpecialBind;
+
+ status = DoBind (phTM, pcxt, flags);
+ FInEvaluate = FALSE;
+ return ( status );
+}
+
+
+
+
+/** EEcChildren - return number of children for the TM
+ *
+ * void EEcChildrenTM (phTM, pcChildren)
+ *
+ * Entry phTM = pointer to handle of TM
+ * pcChildren = pointer to location to store count
+ *
+ * Exit *pcChildren = number of children for TM
+ *
+ * Returns EENOERROR if no error
+ * non-zero if error
+ */
+
+
+
+EESTATUS EEcChildrenTM (PHTM phTM, long *pcChildren, PSHFLAG pVar)
+{
+ return (cChildrenTM (phTM, pcChildren, pVar));
+}
+
+
+
+
+/** EEcParamTM - return count of parameters for TM
+ *
+ * ushort EEcParamTM (phTM, pcParam, pVarArg)
+ *
+ * Entry phTM = pointer to TM
+ * pcParam = pointer return count
+ * pVarArg = pointer to vararg flags
+ *
+ * Exit *pcParam = count of number of parameters
+ * *pVarArgs = TRUE if function has varargs
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * EENOERROR if no error
+ */
+
+
+EESTATUS EEcParamTM (PHTM phTM, ushort *pcParam, PSHFLAG pVarArg)
+{
+ return (cParamTM (*phTM, pcParam, pVarArg));
+}
+
+
+
+
+/** EEDereferenceTM - generate TM from pointer to data TM
+ *
+ * ushort EEDereferenceTM (phTMIn, phTMOut, pEnd)
+ *
+ * Entry phTMIn = pointer to handle to TM to dereference
+ * phTMOut = pointer to handle to dereferencing TM
+ * pEnd = pointer to int to receive index of char that ended parse
+ * fCase = case sensitivity (TRUE is case sensitive)
+ *
+ * Exit *phTMOut = TM referencing pointer data
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * EEGENERAL if TM not dereferencable
+ * EENOERROR if TM generated
+ */
+
+
+EESTATUS EEDereferenceTM (PHTM phTMIn, PHTM phTMOut,
+ uint *pEnd, SHFLAG fCase)
+{
+ register EESTATUS retval;
+ EEHSTR hDStr = 0;
+
+ if ((retval = DereferenceTM (*phTMIn, &hDStr)) == EENOERROR) {
+
+ // bind with prolog disabled and with operloaded operators suppressed
+
+ if ((retval = ParseBind (hDStr, *phTMIn, phTMOut, pEnd,
+ BIND_fSupOvlOps | BIND_fSupBase, fCase, 10)) == EENOERROR) {
+ // the result of dereferencing a pointer does not have a name
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTMOut);
+ pExState->state.noname = TRUE;
+ pExState->state.childtm = TRUE;
+ MHMemUnLock (*phTMOut);
+ pExState = NULL;
+ }
+ }
+ return (retval);
+}
+
+
+
+
+/** EEvaluateTM - evaluate syntax tree
+ *
+ * ushort EEvaluateTM (phExState, pFrame, style);
+ *
+ * Entry phExState = pointer to expression state structure
+ * pFrame = pointer to context frame
+ * style = EEHORIZONTAL for horizontal (command) display
+ * EEVERTICAL for vertical (watch) display
+ * EEBPADDRESS for bp address (suppresses fcn evaluation)
+ *
+ * Exit abstract syntax tree evaluated with the saved
+ * context and current frame and the result node stored
+ * in the expression state structure
+ *
+ * Returns EENOERROR if no error in evaluation
+ * error number if error
+ */
+
+
+EESTATUS EEvaluateTM (PHTM phTM, PFRAME pFrame, EEDSP style)
+{
+ EESTATUS status;
+
+ DASSERT( !FInEvaluate )
+ if ( FInEvaluate ) return(EECATASTROPHIC);
+ FInEvaluate = TRUE;
+
+ status = DoEval (phTM, pFrame, style);
+
+ FInEvaluate = FALSE;
+ return ( status );
+}
+
+
+
+
+/** EEFormatAddress - format address as an ASCII string
+ *
+ * EEFormatAddress (seg, offset, pbuf, flags)
+ *
+ * Entry Seg = segment portion of address
+ * Off = offset portion of address
+ * pbuf = pointer to buffer for formatted address
+ * (must be 20 bytes long)
+ * flags = flags controling formatting
+ * EEFMT_32 - 32-bit offset
+ * EEFMT_SEG - display segment
+ *
+ * Exit buf = formatted address
+ *
+ * Returns EENONE if no errors and EEGENERAL if buffer is not long enough
+ */
+
+
+EESTATUS EEFormatAddress (SHSEG Seg, UOFFSET Off, char *szAddr, uint cch, uint flags)
+{
+ char buf[20];
+ char chx = (flags & EEFMT_REAL) ? '#' : ':';
+
+ if (flags & EEFMT_32) {
+ if (flags & EEFMT_SEG) {
+ if (flags & EEFMT_LOWER) {
+ sprintf (buf, "0x%04x%c0x%08x", Seg, chx, Off);
+ } else {
+ sprintf (buf, "0x%04X%c0x%08X", Seg, chx, Off);
+ }
+ } else {
+ if (flags & EEFMT_LOWER) {
+ sprintf (buf, "0x%08x", Off);
+ } else {
+ sprintf (buf, "0x%08X", Off);
+ }
+ }
+ } else {
+ sprintf (buf, "0x%04X%c0x%04X", Seg, chx, Off);
+ }
+
+ /*
+ * copy the zero terminated string from the buffer to the buffer
+ */
+
+ if (strlen(buf)+1 >= cch) {
+ return EEGENERAL;
+ }
+
+ _fstrcpy (szAddr, buf);
+
+ return EENOERROR;
+} /* EEFormatAddress() */
+
+
+
+
+EESTATUS
+EEFormatAddr(
+ LPADDR lpaddr,
+ char * lpch,
+ uint cch,
+ uint flags
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes an ADDR packet and formats it into an ANSI
+ string. The routine will check for the 32-bit flag in the addr
+ packet and use this to determine if it is a 32-bit or 16-bit offset.
+
+
+Arguments:
+
+ lpaddr - Supplies the pointer to the address packet to format
+ lpch - Supplies the buffer to format the string into
+ cch - count of bytes in the lpch buffer
+ flags - flags controling the formatting
+ EEFMT_32 - override the 32-bit flag in the
+ addr packet and print as a 32-bit offset
+ EEFMT_SEG - if 32-bit then print segment as well.
+
+Return Value:
+
+ EENOERROR - no errors occured
+ EEGENERAL - result does not fit in buffer
+
+--*/
+
+{
+ if (!ADDR_IS_FLAT(*lpaddr)) {
+ flags |= EEFMT_SEG;
+ }
+
+ if (ADDR_IS_OFF32(*lpaddr)) {
+ flags |= EEFMT_32;
+ }
+
+ if (ADDR_IS_REAL(*lpaddr)) {
+ flags |= EEFMT_REAL;
+ }
+
+ return EEFormatAddress( GetAddrSeg(*lpaddr), GetAddrOff(*lpaddr),
+ lpch, cch, flags );
+} /* EEFormatAddr() */
+
+
+EESTATUS
+EEUnFormatAddr(
+ LPADDR lpaddr,
+ char * lpsz
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes an address string and converts it into an
+ ADDR packet. The assumption is that the address is in one of the
+ following formats:
+
+ XXXX:XXXX 16:16 address ( 9)
+ 0xXXXX:0xXXXX 16:16 address (13)
+ XXXX:XXXXXXXX 16:32 address (13)
+ 0xXXXX:0xXXXXXXXX 16:32 address (17)
+ 0xXXXXXXXX 0:32 address (10)
+ XXXXXXXX 0:32 address ( 8)
+
+Arguments:
+
+ lpaddr - Supplies the address packet to be filled in
+ lpsz - Supplies the string to be converted into an addr packet.
+ .
+
+Return Value:
+
+ EENOERROR - no errors
+ EEGENERAL - unable to do unformatting
+
+--*/
+
+{
+ int i;
+ SEGMENT seg = 0;
+ OFFSET off = 0;
+ BOOL fReal = FALSE;
+
+ memset(lpaddr, 0, sizeof(*lpaddr));
+
+ if (lpsz == NULL) {
+ return EEGENERAL;
+ }
+
+ switch( strlen(lpsz) ) {
+ case 9:
+ for (i=0; i<9; i++) {
+ switch( i ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ seg = seg * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ seg = seg * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ seg = seg * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+
+ case 4:
+ if (lpsz[i] == '#') {
+ ADDR_IS_REAL(*lpaddr) = TRUE;
+ } else if (lpsz[i] != ':') {
+ return EEGENERAL;
+ }
+ break;
+
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ off = off * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ off = off * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ off = off * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+ }
+ }
+
+ SetAddrSeg(lpaddr, seg);
+ SetAddrOff(lpaddr, off);
+ break;
+
+
+ case 13:
+ if (lpsz[1] == 'x') {
+ for (i=0; i<13; i++) {
+ switch( i ) {
+ case 0:
+ case 7:
+ if (lpsz[i] != '0') {
+ return EEGENERAL;
+ }
+ break;
+
+ case 1:
+ case 8:
+ if ((lpsz[i] != 'x') && (lpsz[i] != 'X')) {
+ return EEGENERAL;
+ }
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ seg = seg * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ seg = seg * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ seg = seg * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+
+ case 6:
+ if (lpsz[i] == '#') {
+ ADDR_IS_REAL(*lpaddr) = TRUE;
+ } else if (lpsz[i] != ':') {
+ return EEGENERAL;
+ }
+ break;
+
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ off = off * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ off = off * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ off = off * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+ }
+ }
+
+ SetAddrSeg(lpaddr, seg);
+ SetAddrOff(lpaddr, off);
+ } else {
+ for (i=0; i<13; i++) {
+ switch( i ) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ seg = seg * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ seg = seg * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ seg = seg * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+
+ case 4:
+ if (lpsz[i] == '#') {
+ fReal = TRUE;
+ } else if (lpsz[i] != ':') {
+ return EEGENERAL;
+ }
+ break;
+
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ off = off * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ off = off * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ off = off * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+ }
+ }
+
+ SetAddrSeg(lpaddr, seg);
+ SetAddrOff(lpaddr, off);
+ ADDR_IS_OFF32(*lpaddr) = TRUE;
+ ADDR_IS_FLAT(*lpaddr) = FALSE;
+ }
+ break;
+
+
+
+ case 17:
+ for (i=0; i<17; i++) {
+ switch( i ) {
+ case 0:
+ case 7:
+ if (lpsz[i] != '0') {
+ return EEGENERAL;
+
+ }
+ break;
+
+ case 1:
+ case 8:
+ if ((lpsz[i] != 'x') && (lpsz[i] != 'X')) {
+ return EEGENERAL;
+ }
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ seg = seg * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ seg = seg * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ seg = seg * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+
+ case 6:
+ if (lpsz[i] != ':') {
+ return EEGENERAL;
+ }
+ break;
+
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ off = off * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ off = off * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ off = off * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+ }
+ }
+
+ SetAddrSeg(lpaddr, seg);
+ SetAddrOff(lpaddr, off);
+ ADDR_IS_OFF32(*lpaddr) = TRUE;
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ break;
+
+
+ case 10:
+ for (i=0; i<10; i++) {
+ switch( i ) {
+ case 0:
+ if (lpsz[i] != '0') {
+ return EEGENERAL;
+
+ }
+ break;
+
+ case 1:
+ if ((lpsz[i] != 'x') && (lpsz[i] != 'X')) {
+ return EEGENERAL;
+ }
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ off = off * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ off = off * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ off = off * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ break;
+ }
+ }
+
+ SetAddrSeg(lpaddr, seg);
+ SetAddrOff(lpaddr, off);
+ ADDR_IS_OFF32(*lpaddr) = TRUE;
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ break;
+
+
+ case 8:
+ for (i=0; i<8; i++) {
+ if (('0' <= lpsz[i]) && (lpsz[i] <= '9')) {
+ off = off * 16 + lpsz[i] - '0';
+ } else if (('a' <= lpsz[i]) && lpsz[i] <= 'f') {
+ off = off * 16 + lpsz[i] - 'a' + 10;
+ } else if (('A' <= lpsz[i]) && lpsz[i] <= 'F') {
+ off = off * 16 + lpsz[i] - 'A' + 10;
+ } else {
+ return EEGENERAL;
+ }
+ }
+
+ SetAddrSeg(lpaddr, seg);
+ SetAddrOff(lpaddr, off);
+ ADDR_IS_OFF32(*lpaddr) = TRUE;
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ break;
+
+
+ default:
+ return EEGENERAL;
+ }
+
+ return EENOERROR;
+} /* EEUnFormatAddr() */
+
+
+/** EEFormatCXTFromPCXT - format a context operator from a PCXT
+ *
+ * ushort EEFormatCXTFromPCXT (pCXT, phStr)
+ *
+ * Entry pCXT = pointer to CXT packet
+ * phStr = pointer for handle for formatted string buffer
+ *
+ * Exit *phStr = handle of formatted string buffer
+ * *phStr = 0 if buffer not allocated
+ *
+ * Returns EENOERROR if no error
+ * error code if error
+ */
+
+
+EESTATUS EEFormatCXTFromPCXT (PCXT pCXT, PEEHSTR phStr, BOOL fAbbreviated)
+{
+ register ushort retval = EECATASTROPHIC;
+
+ DASSERT (pCXT != 0);
+ if (pCXT != 0) {
+ retval = FormatCXT (pCXT, phStr, fAbbreviated);
+ }
+ return (retval);
+}
+
+
+
+
+/** EEFreeCXTL - Free CXT list
+ *
+ * EEFreeCXTL (phCXTL)
+ *
+ * Entry phCXTL = pointer to the CXT list handle
+ *
+ * Exit *phCXTL = 0;
+ *
+ * Returns none
+ */
+
+
+void EEFreeCXTL (PHCXTL phCXTL)
+{
+ DASSERT (phCXTL != NULL);
+ if (*phCXTL != 0) {
+#ifdef DEBUGKERNEL
+ DASSERT (!MHIsMemLocked (*phCXTL));
+ while (MHIsMemLocked (*phCXTL)) {
+ MHMemUnLock (*phCXTL);
+ }
+#endif
+ MHMemFree (*phCXTL);
+ *phCXTL = 0;
+ }
+}
+
+
+
+
+/** EEFreeHSYMList - Free HSYM list
+ *
+ * EEFreeCXTL (phSYML)
+ *
+ * Entry phSYML = pointer to the HSYM list handle
+ *
+ * Exit *phSYML = 0;
+ *
+ * Returns none
+ */
+
+
+void EEFreeHSYMList (HDEP *phSYML)
+{
+ PHSL_HEAD pList;
+
+ DASSERT (phSYML != NULL);
+ if (*phSYML != 0) {
+#ifdef DEBUGKERNEL
+ DASSERT (!MHIsMemLocked (*phSYML));
+ while (MHIsMemLocked (*phSYML)) {
+ MHMemUnLock (*phSYML);
+ }
+#endif
+
+ // lock the buffer and free the restart buffer if necessary
+
+ pList = MHMemLock (*phSYML);
+ if (pList->restart != 0) {
+#ifdef DEBUGKERNEL
+ DASSERT (!MHIsMemLocked (pList->restart));
+ while (MHIsMemLocked (pList->restart)) {
+ MHMemUnLock (pList->restart);
+ }
+#endif
+ MHMemFree (pList->restart);
+ }
+ MHMemUnLock (*phSYML);
+ MHMemFree (*phSYML);
+ *phSYML = 0;
+ }
+}
+
+
+
+
+
+/** EEFreeStr - free string buffer memory
+ *
+ * ushort EEFreeStr (hszStr);
+ *
+ * Entry hszExpr = handle to string buffer
+ *
+ * Exit string buffer freed
+ *
+ * Returns none
+ */
+
+
+void EEFreeStr (EEHSTR hszStr)
+{
+ if (hszStr != 0) {
+#ifdef DEBUGKERNEL
+ DASSERT (!MHIsMemLocked (hszStr));
+ while (MHIsMemLocked (hszStr)) {
+ MHMemUnLock (hszStr);
+ }
+#endif
+ MHMemFree (hszStr);
+ }
+}
+
+
+
+
+/** EEFreeTM - free expression state structure
+ *
+ * void EEFreeTM (phTM);
+ *
+ * Entry phTM = pointer to the handle for the expression state structure
+ *
+ * Exit expression state structure freed and the handle cleared
+ *
+ * Returns none.
+ */
+
+
+void EEFreeTM (PHTM phTM)
+{
+ if (*phTM != 0) {
+ // DASSERT (!MHIsMemLocked (*phTM));
+
+ // lock the expression state structure and free the components
+ // every component must have no locks active
+
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ if (pExState->hExStr != 0) {
+ // DASSERT (!MHIsMemLocked (pExState->hExStr));
+ MHMemFree (pExState->hExStr);
+ }
+ if (pExState->hCName != 0) {
+ // DASSERT (!MHIsMemLocked (pExState->hCName));
+ MHMemFree (pExState->hCName);
+ }
+ if (pExState->hSTree != 0) {
+ // DASSERT (!MHIsMemLocked (pExState->hSTree));
+ MHMemFree (pExState->hSTree);
+ }
+ if (pExState->hETree != 0) {
+ // DASSERT (!MHIsMemLocked (pExState->hETree));
+ MHMemFree (pExState->hETree);
+ }
+ MHMemUnLock (*phTM);
+ MHMemFree (*phTM);
+ *phTM = 0;
+ pExState = NULL;
+ }
+}
+
+
+
+
+/** EEFreeTI - free TM Info buffer
+ *
+ * void EEFreeTI (hTI);
+ *
+ * Entry hTI = handle to TI Info buffer
+ *
+ * Exit TI Info buffer freed
+ *
+ * Returns none
+ */
+
+
+void EEFreeTI (PHTI phTI)
+{
+ if (*phTI != 0) {
+#ifdef DEBUGKERNEL
+ DASSERT (!MHIsMemLocked (*phTI));
+ while (MHIsMemLocked (*phTI)) {
+ MHMemUnLock (*phTI);
+ }
+#endif
+ MHMemFree (*phTI);
+ *phTI = 0;
+ }
+}
+
+
+
+
+/** EEFreeTML - free TM list
+ *
+ * void EEFreeTML (phTML);
+ *
+ * Entry phTML = pointer to the handle for the TM list
+ *
+ * Exit TM list freed and the handle cleared
+ *
+ * Returns none.
+ */
+
+
+void EEFreeTML (PTML pTML)
+{
+ uint i;
+ ushort cTM = 0;
+
+ if (pTML != NULL) {
+ pTMList = (HTM *)MHMemLock (pTML->hTMList);
+ for (i = 0; i < pTML->cTMListMax; i++) {
+ if (pTMList[i] != 0) {
+ EEFreeTM (&pTMList[i]);
+ cTM++;
+ }
+ }
+//
+// DASSERT (cTM == pTML->cTMListAct);
+ MHMemUnLock (pTML->hTMList);
+ MHMemFree (pTML->hTMList);
+ pTML->hTMList = 0;
+ }
+}
+
+
+
+
+/** EEGetChildTM - get TM representing ith child
+ *
+ * status = EEGetChildTM (phTMParent, iChild, phTMChild)
+ *
+ * Entry phTMParent = pointer to handle of parent TM
+ * iChild = child to get TM for
+ * phTMChild = pointer to handle for returned child
+ * pEnd = pointer to int to receive index of char that ended parse
+ * fCase = case sensitivity (TRUE is case sensitive)
+ *
+ * Exit *phTMChild = handle of child TM if allocated
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if no error
+ * non-zero if error
+ */
+
+
+EESTATUS EEGetChildTM (PHTM phTMIn, long iChild, PHTM phTMOut,
+ uint *pEnd, SHFLAG fCase, uint radix )
+{
+ register EESTATUS retval;
+ EEHSTR hDStr = 0;
+ EEHSTR hName = 0;
+
+ if ((retval = GetChildTM (*phTMIn, iChild, &hDStr, &hName, radix)) == EENOERROR) {
+ DASSERT (hDStr != 0);
+
+ // bind with prolog disabled and with operloaded operators suppressed
+
+ if ((retval = ParseBind (hDStr, *phTMIn, phTMOut, pEnd,
+ BIND_fSupOvlOps | BIND_fSupBase, fCase, radix)) == EENOERROR) {
+ // the result of dereferencing a pointer does not have a name
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTMOut);
+ pExState->state.childtm = TRUE;
+ if ((pExState->hCName = hName) == 0) {
+ pExState->state.noname = TRUE;
+ }
+ MHMemUnLock (*phTMOut);
+ pExState = NULL;
+ }
+ }
+ else {
+ if (hName != 0) {
+ MHMemFree (hName);
+ }
+ }
+ return (retval);
+}
+
+
+
+
+/** EEGetCXTLFromTM - Gets a list of symbols and contexts for expression
+ *
+ * status = EEGetCXTLFromTM (phTM, phCXTL)
+ *
+ * Entry phTM = pointer to handle to expression state structure
+ * phCXTL = pointer to handle for CXT list buffer
+ *
+ * Exit *phCXTL = handle for CXT list buffer
+ *
+ * Returns EENOERROR if no error
+ * status code if error
+ */
+
+
+EESTATUS EEGetCXTLFromTM (PHTM phTM, PHCXTL phCXTL)
+{
+ return (DoGetCXTL (phTM, phCXTL));
+}
+
+
+
+
+EESTATUS EEGetError (PHTM phTM, EESTATUS Status, PEEHSTR phError)
+{
+ return (GetErrorText (phTM, Status, phError));
+}
+
+
+
+
+/** EEGetExprFromTM - get expression representing TM
+ *
+ * void EEGetExprFromTM (phTM, radix, phStr, pEnd)
+ *
+ * Entry phTM = pointer to handle of TM
+ * radix = radix to use for formatting
+ * phStr = pointer to handle for returned string
+ * pEnd = pointer to int to receive index of char that ended parse
+ *
+ * Exit *phStr = handle of formatted string if allocated
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if no error
+ * non-zero if error
+ */
+
+
+EESTATUS
+EEGetExprFromTM (
+ PHTM phTM,
+ PEERADIX pRadix,
+ PEEHSTR phStr,
+ ushort * pEnd
+ )
+{
+ return GetExpr(phTM, *pRadix, phStr, pEnd);
+}
+
+
+
+
+/** EEGetHSYMList - Get a list of handle to symbols
+ *
+ * status = EEGetHSYMList (phSYML, pCXT, mask, pRE, fEnableProlog)
+ *
+ * Entry phSYML = pointer to handle to symbol list
+ * pCXT = pointer to context
+ * mask = selection mask
+ * pRE = pointer to regular expression
+ * fEnableProlog = FALSE if function scoped symbols only after prolog
+ * fEnableProlog = TRUE if function scoped symbols during prolog
+ *
+ * Exit *phMem = handle for HSYM list buffer
+ *
+ * Returns EENOERROR if no error
+ * status code if error
+ */
+
+
+EESTATUS EEGetHSYMList (HDEP *phSYML, PCXT pCxt, ushort mask,
+ uchar * pRE, SHFLAG fEnableProlog)
+{
+ return (GetHSYMList (phSYML, pCxt, mask, pRE, fEnableProlog));
+}
+
+
+
+
+
+/** EEGetNameFromTM - get name from TM
+ *
+ * ushort EEGetNameFromTM (phExState, phszName);
+ *
+ * Entry phExState = pointer to expression state structure
+ * phszName = pointer to handle for string buffer
+ *
+ * Exit phszName = handle for string buffer
+ *
+ * Returns 0 if no error in evaluation
+ * error number if error
+ */
+
+
+EESTATUS EEGetNameFromTM (PHTM phTM, PEEHSTR phszName)
+{
+ return (GetSymName (phTM, phszName));
+}
+
+
+
+
+/** EEGetParamTM - get TM representing ith parameter
+ *
+ * status = EEGetParamTM (phTMParent, iChild, phTMChild)
+ *
+ * Entry phTMparent = pointer to handle of parent TM
+ * iParam = parameter to get TM for
+ * phTMParam = pointer to handle for returned parameter
+ * pEnd = pointer to int to receive index of char that ended parse
+ * fCase = case sensitivity (TRUE is case sensitive)
+ *
+ * Exit *phTMParam = handle of child TM if allocated
+ * *pEnd = index of character that terminated parse
+ *
+ *
+ * Returns EENOERROR if no error
+ * non-zero if error
+ */
+
+
+EESTATUS EEGetParmTM (PHTM phTMIn, uint iParam,
+ PHTM phTMOut, uint *pEnd, SHFLAG fCase, uint radix )
+{
+ register EESTATUS retval;
+ EEHSTR hDStr = 0;
+ EEHSTR hName = 0;
+
+ if ((retval = GetChildTM (*phTMIn, iParam, &hDStr, &hName, radix)) == EENOERROR) {
+ DASSERT (hDStr != 0);
+ if ((retval = ParseBind (hDStr, *phTMIn, phTMOut, pEnd,
+ BIND_fSupOvlOps | BIND_fSupBase | BIND_fEnableProlog, fCase, radix)) == EENOERROR) {
+ // the result of dereferencing a pointer does not have a name
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTMOut);
+ pExState->state.childtm = TRUE;
+ if ((pExState->hCName = hName) == 0) {
+ pExState->state.noname = TRUE;
+ }
+ MHMemUnLock (*phTMOut);
+ pExState = NULL;
+ }
+ }
+ else {
+ if (hName != 0) {
+ MHMemFree (hName);
+ }
+ }
+ return (retval);
+}
+
+
+
+
+/** EEGetTMFromHSYM - create bound TM from handle to symbol
+ *
+ * EESTATUS EEGetTMFromHSYM (hSym, pCxt, phTM, pEnd, fEnableProlog);
+ *
+ * Entry hSym = symbol handle
+ * pcxt = pointer to context
+ * phTM = pointer to the handle for the expression state structure
+ * pEnd = pointer to int to receive index of char that ended parse
+ * fEnableProlog = FALSE if function scoped symbols only after prolog
+ * fEnableProlog = TRUE if function scoped symbols during prolog
+ *
+ * Exit bound TM created
+ * *phTM = handle of TM buffer
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * 0 if no error
+ */
+
+
+EESTATUS EEGetTMFromHSYM (HSYM hSym, PCXT pcxt, PHTM phTM,
+ uint *pEnd, SHFLAG fEnableProlog)
+{
+ register EESTATUS retval;
+
+ // allocate, lock and clear expression state structure
+
+ DASSERT (hSym != 0);
+ if (hSym == 0) {
+ return (EECATASTROPHIC);
+ }
+ if ((*phTM = MHMemAllocate (sizeof (struct exstate_t))) == 0) {
+ return (EECATASTROPHIC);
+ }
+
+ // lock expression state structure, clear and allocate components
+
+ DASSERT(pExState == NULL);
+ pExState = (pexstate_t)MHMemLock (*phTM);
+ _fmemset (pExState, 0, sizeof (exstate_t));
+
+ // allocate buffer for input string and copy
+
+ pExState->ExLen = sizeof (char) + sizeof (HSYM);
+ if ((pExState->hExStr = MHMemAllocate ((uint) pExState->ExLen + 1)) == 0) {
+ // clean up after error in allocation of input string buffer
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ EEFreeTM (phTM);
+ return (EECATASTROPHIC);
+ }
+ pExStr = MHMemLock (pExState->hExStr);
+ *pExStr++ = (unsigned char)0xff;
+ *((HSYM UNALIGNED *)(pExStr)) = hSym;
+ pExStr += sizeof (HSYM);
+ *pExStr = 0;
+ MHMemUnLock (pExState->hExStr);
+ pExStr = NULL;
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ if ((retval = DoParse (phTM, 10, TRUE, pEnd)) == EENOERROR) {
+ retval = EEBindTM (phTM, pcxt, TRUE, fEnableProlog, FALSE);
+ }
+ return (retval);
+}
+
+
+
+
+/** EEGetTypeFromTM - get type name from TM
+ *
+ * ushort EEGetTypeFromTM (phExState, hszName, phszType, select);
+ *
+ * Entry phExState = pointer to expression state structure
+ * hszName = handle to name to insert into string if non-null
+ * phszType = pointer to handle for type string buffer
+ * select = selection mask
+ *
+ * Exit phszType = handle for type string buffer
+ *
+ * Returns EENOERROR if no error in evaluation
+ * error number if error
+ */
+
+
+EESTATUS EEGetTypeFromTM (PHTM phTM, EEHSTR hszName,
+ PEEHSTR phszType, ulong select)
+{
+ char *buf;
+ uint buflen = TYPESTRMAX - 1 + sizeof (HDR_TYPE);
+ char *pName;
+ PHDR_TYPE pHdr;
+
+ DASSERT (*phTM != 0);
+ if (*phTM == 0) {
+ return (EECATASTROPHIC);
+ }
+ if ((*phszType = MHMemAllocate (TYPESTRMAX + sizeof (HDR_TYPE))) == 0) {
+ // unable to allocate memory for type string
+ return (EECATASTROPHIC);
+ }
+ buf = (char *)MHMemLock (*phszType);
+ _fmemset (buf, 0, TYPESTRMAX + sizeof (HDR_TYPE));
+ pHdr = (PHDR_TYPE)buf;
+ buf += sizeof (HDR_TYPE);
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ pCxt = &pExState->cxt;
+ bnCxt = 0;
+ if (hszName != 0) {
+ pName = MHMemLock (hszName);
+ }
+ else {
+ pName = NULL;
+ }
+ FormatType (&pExState->result, &buf, &buflen, &pName, select, pHdr);
+ if (hszName != 0) {
+ MHMemUnLock (hszName);
+ }
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ MHMemUnLock (*phszType);
+ return (EENOERROR);
+}
+
+
+
+
+/** EEGetValueFromTM - format result of evaluation
+ *
+ * ushort EEGetValueFromTM (phTM, radix, pFormat, phValue);
+ *
+ * Entry phTM = pointer to handle to TM
+ * radix = default radix for formatting
+ * pFormat = pointer to format string
+ * phValue = pointer to handle for display string
+ *
+ * Exit evaluation result formatted
+ *
+ * Returns EENOERROR if no error in formatting
+ * error number if error
+ */
+
+
+
+EESTATUS EEGetValueFromTM (PHTM phTM, uint Radix, PEEFORMAT pFormat, PEEHSTR phszValue)
+{
+ return (FormatNode (phTM, Radix, pFormat, phszValue));
+}
+
+
+
+
+/** EEInfoFromTM - return information about TM
+ *
+ * EESTATUS EEInfoFromTM (phTM, pReqInfo, phTMInfo);
+ *
+ * Entry phTM = pointer to the handle for the expression state structure
+ * reqInfo = info request structure
+ * phTMInfo = pointer to handle for request info data structure
+ *
+ * Exit *phTMInfo = handle of info structure
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * 0 if no error
+ */
+
+
+EESTATUS EEInfoFromTM (PHTM phTM, PRI pReqInfo, PHTI phTMInfo)
+{
+ return (InfoFromTM (phTM, pReqInfo, phTMInfo));
+}
+
+
+
+
+
+/** EEIsExpandable - does TM represent expandable item
+ *
+ * fSuccess EEIsExpandable (pHTM);
+ *
+ * Entry phTM = pointer to TM handle
+ *
+ * Exit none
+ *
+ * Returns FALSE if TM does not represent expandable item
+ * TRUE if TM represents expandable item
+ * bounded arrays, structs, unions, classes,
+ * pointers to compound items.
+ *
+ */
+
+
+EEPDTYP EEIsExpandable (PHTM phTM)
+{
+ eval_t evalT;
+ peval_t pvT = &evalT;
+ register ushort retval = EENOTEXP;
+
+// DASSERT (*phTM != 0);
+ if (*phTM != 0) {
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ *pvT = pExState->result;
+#if !defined (C_only)
+ if (EVAL_IS_REF (pvT)) {
+ RemoveIndir (pvT);
+ }
+#endif
+ if (EVAL_STATE (pvT) == EV_type) {
+ if (EVAL_IS_FCN (pvT) || (
+ CV_IS_PRIMITIVE (EVAL_TYP (pvT)) && !EVAL_IS_PTR (pvT))) {
+ retval = EETYPENOTEXP;
+ }
+ else {
+ retval = EETYPE;
+ }
+ }
+ else if (EVAL_IS_ENUM (pvT)) {
+ retval = EENOTEXP;
+ }
+ else if (EVAL_IS_CLASS (pvT) ||
+ (EVAL_IS_ARRAY (pvT) && (PTR_ARRAYLEN (pvT) != 0))) {
+ retval = EEAGGREGATE;
+ }
+ else {
+ retval = IsExpandablePtr (pvT);
+ }
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ }
+ return (retval);
+}
+
+
+
+
+
+/** EEParse - parse expression string to abstract syntax tree
+ *
+ * ushort EEParse (szExpr, radix, fCase, phTM);
+ *
+ * Entry szExpr = pointer to expression string
+ * radix = default number radix for conversions
+ * fCase = case sensitive search if TRUE
+ * phTM = pointer to handle of expression state structure
+ * pEnd = pointer to int to receive index of char that ended parse
+ *
+ * Exit *phTM = handle of expression state structure if allocated
+ * *phTM = 0 if expression state structure could not be allocated
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if no error in parse
+ * EECATASTROPHIC if unable to initialize
+ * error number if error
+ */
+
+
+EESTATUS EEParse (char *szExpr, uint radix, SHFLAG fCase,
+ PHTM phTM, uint *pEnd)
+{
+ EESTATUS status;
+
+ DASSERT( !FInEvaluate )
+ if ( FInEvaluate ) return(EECATASTROPHIC);
+ FInEvaluate = TRUE;
+
+ status = Parse( szExpr, radix, fCase, phTM, pEnd );
+
+ FInEvaluate = FALSE;
+ return ( status );
+}
+
+
+
+
+/** EEParseBP - parse breakpoint strings
+ *
+ * ushort EEParseBP (pExpr, radix, fCase, pcxf, pTML, select, End, fEnableProlog)
+ *
+ * Entry pExpr = pointer to breakpoint expression
+ * radix = default numeric radix
+ * fCase = case sensitive search if TRUE
+ * pcxt = pointer to initial context for evaluation
+ * pTML = pointer to TM list for results
+ * select = selection mask
+ * pEnd = pointer to int to receive index of char that ended parse
+ * fEnableProlog = FALSE if function scoped symbols only after prolog
+ * fEnableProlog = TRUE if function scoped symbols during prolog
+ *
+ * Exit *pTML = breakpoint information
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if no error in parse
+ * EECATASTROPHIC if unable to initialize
+ * EEGENERAL if error
+ */
+
+
+EESTATUS
+EEParseBP (
+ char *pExpr,
+ uint radix,
+ SHFLAG fCase,
+ PCXF pCxf,
+ PTML pTML,
+ ulong select,
+ uint *pEnd,
+ SHFLAG fEnableProlog
+ )
+{
+ register EESTATUS retval = EECATASTROPHIC;
+ ushort i;
+
+ Unreferenced(select);
+
+ if ((pCxf == NULL) || (pTML == NULL)) {
+ return (EECATASTROPHIC);
+ }
+
+ // note that pTML is not a pointer to a handle but rather a pointer to an
+ // actual structure allocated by the caller
+
+ pTMLbp = pTML;
+ _fmemset (pTMLbp, 0, sizeof (TML));
+
+ // allocate and initialize the initial list of TMs for overloaded
+ // entries. The TMList is an array of handles to exstate_t's.
+ // This list of handles will grow if it is filled.
+
+ if ((pTMLbp->hTMList = MHMemAllocate (TMLISTCNT * sizeof (HTM))) != 0) {
+ pTMList = (HTM *)MHMemLock (pTMLbp->hTMList);
+ _fmemset (pTMList, 0, TMLISTCNT * sizeof (HTM));
+ pTMLbp->cTMListMax = TMLISTCNT;
+
+ // parse the break point expression
+
+ retval = EEParse (pExpr, radix, fCase, &pTMList[0], pEnd);
+ pTMLbp->cTMListAct++;
+
+ // initialize the backpatch index into PTML. If this number remains
+ // 1 this means that an ambiguous breakpoint was not detected during
+ // the bind phase. As the binder finds ambiguous symbols, information
+ // sufficient to resolve each ambiguity is stored in allocated memory
+ // and the handle is saved in PTML by AmbToList
+
+ iBPatch = 1;
+ if (retval == EENOERROR) {
+ // bind the breakpoint expression if no parse error
+ BindingBP = TRUE;
+ if ((retval = EEBindTM (&pTMList[0], SHpCXTFrompCXF (pCxf),
+ TRUE, fEnableProlog, FALSE)) != EENOERROR) {
+
+ // The binder used the pTMList as a location to
+ // store information about backpatching. If there
+ // is an error in the bind, go down the list and
+ // free all backpatch structure handles.
+
+ for (i = 1; i < iBPatch; i++) {
+ // note that the back patch structure cannot contain
+ // handles to allocated memory that have to be freed up
+ // here. Otherwise, memory will be lost
+
+ MHMemFree (pTMList[i]);
+ pTMList[i] = 0;
+ }
+ }
+ else {
+ // the first form of the expression bound correctly.
+ // Go down the list, duplicate the expression state
+ // and rebind using the backpatch symbol information
+ // to resolve the ambiguous symbol. SearchSym uses the
+ // fact that hBPatch is non-zero to decide to handle the
+ // next ambiguous symbol.
+
+ for (i = 1; i < iBPatch; i++) {
+ hBPatch = pTMList[i];
+ pTMList[i] = 0;
+ if (DupTM (&pTMList[0], &pTMList[i]) == EENOERROR) {
+ pTMLbp->cTMListAct++;
+ EEBindTM (&pTMList[i], SHpCXTFrompCXF (pCxf),
+ TRUE, fEnableProlog, FALSE);
+ }
+ MHMemFree (hBPatch);
+ hBPatch = 0;
+ }
+ }
+ }
+ BindingBP = FALSE;
+ MHMemUnLock (pTMLbp->hTMList);
+ }
+ // return the result of parsing and binding the initial expression.
+ // There may have been errors binding subsequent ambiguous breakpoints.
+ // It is the caller's responsibility to handle the errors.
+
+ return (retval);
+}
+
+
+
+
+/** ParseBind - parse and bind generated expression
+ *
+ * flag = ParseBind (hExpr, hTMIn, phTMOut, pEnd, flags, fCase)
+ *
+ * Entry hExpr = handle of generated expression
+ * hTMIn = handle to TM dereferenced
+ * phTMOut = pointer to handle to dereferencing TM
+ * pEnd = pointer to int to receive index of char that ended parse
+ * flags.BIND_fForceBind = TRUE if bind to be forced
+ * flags.BIND_fForceBind = FALSE if rebind decision left to binder
+ * flags.BIND_fEnableProlog = TRUE if function scope searched during prolog
+ * flags.BIND_fEnableProlog = FALSE if function scope not searched during prolog
+ * flags.BIND_fSupOvlOps = FALSE if overloaded operator search enabled
+ * flags.BIND_fSupOvlOps = TRUE if overloaded operator search suppressed
+ * flags.BIND_fSupBase = FALSE if base searching is not suppressed
+ * flags.BIND_fSupBase = TRUE if base searching is suppressed
+ * fCase = case sensitivity (TRUE is case sensitive)
+ *
+ * Exit *phTMOut = TM referencing pointer data
+ * hExpr buffer freed
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * EEGENERAL if TM not dereferencable
+ * EENOERROR if TM generated
+ */
+
+
+LOCAL EESTATUS ParseBind (EEHSTR hExpr, HTM hTMIn,
+ PHTM phTMOut, uint *pEnd, uint flags, SHFLAG fCase, uint radix)
+{
+ pexstate_t pTMIn;
+ register EESTATUS retval;
+
+ DASSERT( !FInEvaluate )
+ if ( FInEvaluate ) return(EECATASTROPHIC);
+ FInEvaluate = TRUE;
+
+ pTMIn = MHMemLock (hTMIn);
+ if ((retval = Parse (MHMemLock (hExpr), radix, fCase, phTMOut, pEnd)) == EENOERROR) {
+ retval = DoBind (phTMOut, &pTMIn->cxt, flags);
+ }
+ MHMemUnLock (hTMIn);
+ MHMemUnLock (hExpr);
+ MHMemFree (hExpr);
+
+ FInEvaluate = FALSE;
+ return (retval);
+}
+
+int eedllinit ( HANDLE hMod, ULONG Reason, char * lpch)
+{
+ Unreferenced( hMod );
+ Unreferenced( Reason );
+ Unreferenced( lpch );
+ return TRUE;
+}
diff --git a/private/windbg/eecan/debbind.c b/private/windbg/eecan/debbind.c
new file mode 100644
index 000000000..4641235ef
--- /dev/null
+++ b/private/windbg/eecan/debbind.c
@@ -0,0 +1,7616 @@
+/* debbind.c - Expression evaluator bind routines
+ *
+ * GLOBAL
+ * Bind Main evaluation routine
+ *
+ *
+ * DESCRIPTION
+ * Routines to bind the expression tree.
+ *
+ */
+
+
+#define TY_SIGNED 0x000001
+#define TY_UNSIGNED 0x000002
+#define TY_CHAR 0x000004
+#define TY_SHORT 0x000008
+#define TY_LONG 0x000010
+#define TY_FLOAT 0x000020
+#define TY_DOUBLE 0x000040
+#define TY_SEGMENT 0x000080
+#define TY_CLASS 0x000100
+#define TY_STRUCT 0x000200
+#define TY_UNION 0x000400
+#define TY_REF 0x000800
+#define TY_NEAR 0x001000
+#define TY_FAR 0x002000
+#define TY_HUGE 0x004000
+#define TY_POINTER 0x008000
+#define TY_UDT 0x010000
+#define TY_VOID 0x020000
+#define TY_CONST 0x040000
+#define TY_VOLATILE 0x080000
+#define TY_INT 0x100000
+
+#define TY_ARITH (TY_SIGNED | TY_UNSIGNED | TY_CHAR | TY_SHORT | TY_LONG | TY_FLOAT | TY_DOUBLE)
+#define TY_INTEGRAL (TY_CHAR | TY_SHORT | TY_LONG | TY_INT)
+#define TY_REAL (TY_FLOAT | TY_DOUBLE)
+#define TY_NOTREAL (TY_SIGNED | TY_UNSIGNED | TY_CHAR | TY_SHORT | TY_INT)
+#define TY_PTR (TY_NEAR | TY_FAR | TY_HUGE | TY_POINTER)
+#define TY_AGGR (TY_CLASS | TY_STRUCT | TY_UNION)
+#define TY_SIGN (TY_SIGNED | TY_UNSIGNED)
+
+#ifdef TARGET_PPC
+static char szAltSymName[512];
+#endif
+
+struct typrec {
+ uchar token[10];
+ unsigned long flags;
+};
+static struct typrec Predef[] = {
+ { "\006""signed", TY_SIGNED},
+ { "\010""unsigned", TY_UNSIGNED},
+ { "\004""void", TY_VOID},
+ { "\004""char", TY_CHAR},
+ { "\003""int", TY_INT},
+ { "\005""short", TY_SHORT},
+ { "\004""long", TY_LONG},
+ { "\005""float", TY_FLOAT},
+ { "\006""double", TY_DOUBLE},
+ { "\010""_segment", TY_SEGMENT},
+ { "\006""struct", TY_STRUCT},
+ { "\005""class", TY_CLASS},
+ { "\005""union", TY_UNION},
+ { "\001""*", TY_POINTER},
+ { "\001""&", TY_REF},
+ { "\004""near", TY_NEAR},
+ { "\005""_near", TY_NEAR},
+ { "\003""far", TY_FAR},
+ { "\004""_far", TY_FAR},
+ { "\004""huge", TY_HUGE},
+ { "\005""_huge", TY_HUGE},
+ { "\005""const", TY_CONST},
+#if 0
+ /*
+ * For the present we are going to ignore the volatile keyword. This
+ * has some implications for C++ which we are going to ignore but
+ * may become importain later. We need to solve the problem of
+ * differning between:
+ * char volatile * (character is volatile) and
+ * char * volatile (pointer is volatile)
+ */
+ { "\010""volatile", TY_VOLATILE},
+#else
+ { "\010""volatile", 0},
+#endif
+ { "", 0}
+};
+
+
+// Table to map from assignment operator to evaluation operator
+// Depends upon number and order of assignment operators
+
+CV_typ_t eqop[OP_oreq + 1 - OP_multeq] = {
+ OP_mult,
+ OP_div,
+ OP_mod,
+ OP_plus,
+ OP_minus,
+ OP_shl,
+ OP_shr,
+ OP_and,
+ OP_xor,
+ OP_or
+ };
+
+#define Arith Arith_E
+#define PlusMinus PlushMinus_E
+#define PrePost PrePost_E
+#define Unary Unary_E
+
+LOCAL bool_t FASTCALL AddrOf (bnode_t);
+LOCAL bool_t FASTCALL Arith (op_t);
+LOCAL bool_t BinaryOverload (bnode_t);
+LOCAL bool_t FASTCALL Bind (bnode_t);
+LOCAL bool_t FASTCALL BindLChild (bnode_t);
+LOCAL bool_t FASTCALL BindRchild (bnode_t);
+LOCAL bool_t FASTCALL BindAddrOf (bnode_t);
+LOCAL bool_t FASTCALL BindBinary (bnode_t);
+LOCAL bool_t FASTCALL BindArray (bnode_t);
+LOCAL bool_t FASTCALL BindAssign (bnode_t);
+LOCAL bool_t FASTCALL BindBang (bnode_t);
+LOCAL bool_t FASTCALL BindBasePtr (bnode_t);
+LOCAL bool_t FASTCALL BindByteOps(bnode_t);
+LOCAL bool_t FASTCALL BindCast (bnode_t);
+LOCAL bool_t FASTCALL BindConst (bnode_t);
+LOCAL bool_t FASTCALL BindContext (bnode_t);
+LOCAL bool_t FASTCALL BindExeContext (bnode_t);
+LOCAL bool_t FASTCALL BindDot (bnode_t bn);
+LOCAL bool_t FASTCALL BindFetch (bnode_t);
+LOCAL bool_t FASTCALL BindFunction (bnode_t);
+LOCAL bool_t FASTCALL BindDMember (bnode_t);
+LOCAL bool_t FASTCALL BindPlusMinus (bnode_t);
+LOCAL bool_t FASTCALL BindPMember (bnode_t);
+LOCAL bool_t FASTCALL BindPointsTo (bnode_t);
+LOCAL bool_t FASTCALL BindPostIncDec (bnode_t);
+LOCAL bool_t FASTCALL BindPreIncDec (bnode_t);
+LOCAL bool_t FASTCALL BindRelat (bnode_t);
+LOCAL bool_t FASTCALL BindBScope (bnode_t);
+LOCAL bool_t FASTCALL BindSegOp (bnode_t);
+LOCAL bool_t FASTCALL BindSizeOf (bnode_t);
+LOCAL bool_t FASTCALL BindSymbol (bnode_t);
+LOCAL bool_t FASTCALL BindUnary (bnode_t);
+LOCAL bool_t FASTCALL BuildType (CV_typ_t *, ulong *, ushort *, ushort *, ushort *);
+LOCAL bool_t FASTCALL BindUScope (bnode_t);
+LOCAL bool_t FASTCALL CastBinary (op_t);
+LOCAL bool_t CastPtrToPtr (bnode_t);
+LOCAL bool_t FASTCALL ContextToken (char * *, char * *, short *);
+LOCAL HDEP DupETree (ushort, pstree_t *);
+LOCAL bool_t FASTCALL FastCallReg (pargd_t, peval_t, ushort *);
+LOCAL bool_t FASTCALL FcnCast (bnode_t bn);
+LOCAL bool_t FASTCALL Fetch (void);
+LOCAL bool_t FindUDT (bnode_t, peval_t, char *, char *, uchar);
+LOCAL bool_t FASTCALL Function (bnode_t);
+LOCAL uchar FASTCALL GetID (char *);
+LOCAL bool_t FASTCALL GetStructTDef (char *, int, pnode_t);
+LOCAL bool_t FASTCALL MipsCallReg (pargd_t, peval_t, uint *);
+LOCAL bool_t FASTCALL AlphaCallReg (pargd_t, peval_t, uint *);
+LOCAL bool_t FASTCALL PPCCallReg (pargd_t, peval_t, uint *);
+LOCAL bool_t FASTCALL ParseType (bnode_t);
+LOCAL bool_t FASTCALL PlusMinus(op_t);
+LOCAL bool_t FASTCALL PrePost (op_t);
+LOCAL bool_t FASTCALL PushCArgs (peval_t, pnode_t, UOFFSET *, int, peval_t);
+LOCAL bool_t FASTCALL PushFArgs (peval_t, pnode_t, UOFFSET *, peval_t);
+LOCAL bool_t FASTCALL PushMArgs (peval_t, pnode_t, UOFFSET *, peval_t);
+LOCAL bool_t FASTCALL PushMArgs2 (peval_t, pnode_t, UOFFSET *, int, uint, peval_t);
+LOCAL bool_t FASTCALL PushAArgs (peval_t, pnode_t, UOFFSET *, peval_t);
+LOCAL bool_t FASTCALL PushAArgs2 (peval_t, pnode_t, UOFFSET *, int, uint, peval_t);
+LOCAL bool_t FASTCALL PushPPCArgs (peval_t, pnode_t, UOFFSET *, peval_t);
+LOCAL bool_t FASTCALL PushPPCArgs2 (peval_t, pnode_t, UOFFSET *, int, uint *, peval_t);
+LOCAL bool_t FASTCALL PushPArgs (peval_t, pnode_t, UOFFSET *, peval_t);
+LOCAL bool_t FASTCALL PushTArgs (peval_t, pnode_t, UOFFSET *, int, peval_t);
+LOCAL bool_t FASTCALL SBitField (pnode_t);
+LOCAL bool_t FASTCALL SearchRight (bnode_t);
+LOCAL CV_typ_t SetImpClass (PCXT, long *);
+LOCAL bool_t FASTCALL Unary (op_t);
+LOCAL bool_t UnaryOverload (bnode_t);
+LOCAL bool_t PointsToOverload (bnode_t);
+
+LOCAL bool_t FASTCALL BindError (bnode_t);
+LOCAL bool_t FASTCALL BindTRUE (bnode_t);
+
+static bool_t BindingFuncArgs = FALSE;
+bnode_t bnOp; // based node pointer when binding the right side of
+ // ., ->,
+// Bind dispatch table
+
+LOCAL bool_t (FASTCALL *pBind[]) (bnode_t) = {
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk) opbind,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+
+
+
+/*
+ * Defines relating to the MIPS and ALPHA calling convention
+ * One nibble is used for each register argument position
+ * There are a max of four for MIPS, six for ALPHA, twenty-two
+ * for PPC
+ */
+
+
+#define PARAM_EMPTY 0
+#define PARAM_INT 1
+#define PARAM_FLOAT 2
+#define PARAM_DOUBLE 3
+#define PARAM_SKIPPED 4
+
+#ifdef TARGET_PPC
+#define IS_PARAM_TYPE(mask, n, type) ((mask[(n) >> 3] & (7 << 4*((n) & 0x7))) == type)
+#else
+#define IS_PARAM_TYPE(mask, n, type) ((*mask & (3 << 4*n)) == type)
+#endif
+#define IS_PARAM_EMPTY(mask, n) (IS_PARAM_TYPE(mask, n, PARAM_EMPTY))
+#define IS_PARAM_INT(mask, n) (IS_PARAM_TYPE(mask, n, PARAM_INT))
+#define IS_PARAM_FLOAT(mask, n) (IS_PARAM_TYPE(mask, n, PARAM_FLOAT))
+#define IS_PARAM_DOUBLE(mask, n) (IS_PARAM_TYPE(mask, n, PARAM_DOUBLE))
+#define IS_PARAM_SKIPPED(mask, n) (IS_PARAM_TYPE(mask, n, PARAM_SKIPPED))
+
+
+#ifdef TARGET_PPC
+#define SET_PARAM_TYPE(mask, n, type) (mask[(n) >> 3] |= (type << 4*((n) & 0x7)))
+#else
+#define SET_PARAM_TYPE(mask, n, type) (*mask |= (type << 4*n))
+#endif
+#define SET_PARAM_INT(mask, n) SET_PARAM_TYPE(mask, n, PARAM_INT)
+#define SET_PARAM_FLOAT(mask, n) SET_PARAM_TYPE(mask, n, PARAM_FLOAT)
+#define SET_PARAM_DOUBLE(mask, n) SET_PARAM_TYPE(mask, n, PARAM_DOUBLE)
+#define SET_PARAM_SKIPPED(mask, n) SET_PARAM_TYPE(mask, n, PARAM_SKIPPED)
+
+#if DBG
+ULONG fShowNodes;
+void
+PrintNodeOp(
+ int NodeOp
+ )
+{
+ char *szName;
+
+ switch (NodeOp) {
+ case OP_addrof : szName = "OP_addrof \n"; break;
+ case OP_lbrack : szName = "OP_lbrack \n"; break;
+ case OP_eq : szName = "OP_eq \n"; break;
+ case OP_multeq : szName = "OP_multeq \n"; break;
+ case OP_diveq : szName = "OP_diveq \n"; break;
+ case OP_modeq : szName = "OP_modeq \n"; break;
+ case OP_pluseq : szName = "OP_pluseq \n"; break;
+ case OP_minuseq : szName = "OP_minuseq \n"; break;
+ case OP_shleq : szName = "OP_shleq \n"; break;
+ case OP_shreq : szName = "OP_shreq \n"; break;
+ case OP_andeq : szName = "OP_andeq \n"; break;
+ case OP_xoreq : szName = "OP_xoreq \n"; break;
+ case OP_oreq : szName = "OP_oreq \n"; break;
+ case OP_bscope : szName = "OP_bscope \n"; break;
+ case OP_bang : szName = "OP_bang \n"; break;
+ case OP_baseptr : szName = "OP_baseptr \n"; break;
+ case OP_mult : szName = "OP_mult \n"; break;
+ case OP_div : szName = "OP_div \n"; break;
+ case OP_mod : szName = "OP_mod \n"; break;
+ case OP_shl : szName = "OP_shl \n"; break;
+ case OP_shr : szName = "OP_shr \n"; break;
+ case OP_and : szName = "OP_and \n"; break;
+ case OP_xor : szName = "OP_xor \n"; break;
+ case OP_or : szName = "OP_or \n"; break;
+ case OP_andand : szName = "OP_andand \n"; break;
+ case OP_oror : szName = "OP_oror \n"; break;
+ case OP_caststar : szName = "OP_caststar \n"; break;
+ case OP_castplus : szName = "OP_castplus \n"; break;
+ case OP_castminus : szName = "OP_castminus \n"; break;
+ case OP_castamp : szName = "OP_castamp \n"; break;
+ case OP_by : szName = "OP_by \n"; break;
+ case OP_wo : szName = "OP_wo \n"; break;
+ case OP_dw : szName = "OP_dw \n"; break;
+ case OP_cast : szName = "OP_cast \n"; break;
+ case OP_const : szName = "OP_const \n"; break;
+ case OP_context : szName = "OP_context \n"; break;
+ case OP_dotmember : szName = "OP_dotmember \n"; break;
+ case OP_dot : szName = "OP_dot \n"; break;
+ case OP_endofargs : szName = "OP_endofargs \n"; break;
+ case OP_grouped : szName = "OP_grouped \n"; break;
+ case OP_thisinit : szName = "OP_thisinit \n"; break;
+ case OP_thisconst : szName = "OP_thisconst \n"; break;
+ case OP_thisexpr : szName = "OP_thisexpr \n"; break;
+ case OP_noop : szName = "OP_noop \n"; break;
+ case OP_lparen : szName = "OP_lparen \n"; break;
+ case OP_rparen : szName = "OP_rparen \n"; break;
+ case OP_lcurly : szName = "OP_lcurly \n"; break;
+ case OP_rcurly : szName = "OP_rcurly \n"; break;
+ case OP_incr : szName = "OP_incr \n"; break;
+ case OP_decr : szName = "OP_decr \n"; break;
+ case OP_arg : szName = "OP_arg \n"; break;
+ case OP_fcnend : szName = "OP_fcnend \n"; break;
+ case OP_rbrack : szName = "OP_rbrack \n"; break;
+ case OP_lowprec : szName = "OP_lowprec \n"; break;
+ case OP_comma : szName = "OP_comma \n"; break;
+ case OP_execontext : szName = "OP_execontext \n"; break;
+ case OP_fetch : szName = "OP_fetch \n"; break;
+ case OP_function : szName = "OP_function \n"; break;
+ case OP_identFunc : szName = "OP_identFunc \n"; break;
+ case OP_pmember : szName = "OP_pmember \n"; break;
+ case OP_plus : szName = "OP_plus \n"; break;
+ case OP_minus : szName = "OP_minus \n"; break;
+ case OP_pointsto : szName = "OP_pointsto \n"; break;
+ case OP_postinc : szName = "OP_postinc \n"; break;
+ case OP_postdec : szName = "OP_postdec \n"; break;
+ case OP_preinc : szName = "OP_preinc \n"; break;
+ case OP_predec : szName = "OP_predec \n"; break;
+ case OP_lt : szName = "OP_lt \n"; break;
+ case OP_lteq : szName = "OP_lteq \n"; break;
+ case OP_gt : szName = "OP_gt \n"; break;
+ case OP_gteq : szName = "OP_gteq \n"; break;
+ case OP_eqeq : szName = "OP_eqeq \n"; break;
+ case OP_bangeq : szName = "OP_bangeq \n"; break;
+ case OP_segop : szName = "OP_segop \n"; break;
+ case OP_segopReal : szName = "OP_segopReal \n"; break;
+ case OP_sizeof : szName = "OP_sizeof \n"; break;
+ case OP_ident : szName = "OP_ident \n"; break;
+ case OP_hsym : szName = "OP_hsym \n"; break;
+ case OP_this : szName = "OP_this \n"; break;
+ case OP_Opmember : szName = "OP_Opmember \n"; break;
+ case OP_Orightequal : szName = "OP_Orightequal \n"; break;
+ case OP_Oleftequal : szName = "OP_Oleftequal \n"; break;
+ case OP_Ofunction : szName = "OP_Ofunction \n"; break;
+ case OP_Oarray : szName = "OP_Oarray \n"; break;
+ case OP_Oplusequal : szName = "OP_Oplusequal \n"; break;
+ case OP_Ominusequal : szName = "OP_Ominusequal \n"; break;
+ case OP_Otimesequal : szName = "OP_Otimesequal \n"; break;
+ case OP_Odivequal : szName = "OP_Odivequal \n"; break;
+ case OP_Opcentequal : szName = "OP_Opcentequal \n"; break;
+ case OP_Oandequal : szName = "OP_Oandequal \n"; break;
+ case OP_Oxorequal : szName = "OP_Oxorequal \n"; break;
+ case OP_Oorequal : szName = "OP_Oorequal \n"; break;
+ case OP_Oshl : szName = "OP_Oshl \n"; break;
+ case OP_Oshr : szName = "OP_Oshr \n"; break;
+ case OP_Oequalequal : szName = "OP_Oequalequal \n"; break;
+ case OP_Obangequal : szName = "OP_Obangequal \n"; break;
+ case OP_Olessequal : szName = "OP_Olessequal \n"; break;
+ case OP_Ogreatequal : szName = "OP_Ogreatequal \n"; break;
+ case OP_Oandand : szName = "OP_Oandand \n"; break;
+ case OP_Ooror : szName = "OP_Ooror \n"; break;
+ case OP_Oincrement : szName = "OP_Oincrement \n"; break;
+ case OP_Odecrement : szName = "OP_Odecrement \n"; break;
+ case OP_Opointsto : szName = "OP_Opointsto \n"; break;
+ case OP_Oplus : szName = "OP_Oplus \n"; break;
+ case OP_Ominus : szName = "OP_Ominus \n"; break;
+ case OP_Ostar : szName = "OP_Ostar \n"; break;
+ case OP_Odivide : szName = "OP_Odivide \n"; break;
+ case OP_Opercent : szName = "OP_Opercent \n"; break;
+ case OP_Oxor : szName = "OP_Oxor \n"; break;
+ case OP_Oand : szName = "OP_Oand \n"; break;
+ case OP_Oor : szName = "OP_Oor \n"; break;
+ case OP_Otilde : szName = "OP_Otilde \n"; break;
+ case OP_Obang : szName = "OP_Obang \n"; break;
+ case OP_Oequal : szName = "OP_Oequal \n"; break;
+ case OP_Oless : szName = "OP_Oless \n"; break;
+ case OP_Ogreater : szName = "OP_Ogreater \n"; break;
+ case OP_Ocomma : szName = "OP_Ocomma \n"; break;
+ case OP_Onew : szName = "OP_Onew \n"; break;
+ case OP_Odelete : szName = "OP_Odelete \n"; break;
+ case OP_typestr : szName = "OP_typestr \n"; break;
+ case OP_uscope : szName = "OP_uscope \n"; break;
+ case OP_tilde : szName = "OP_tilde \n"; break;
+ case OP_negate : szName = "OP_negate \n"; break;
+ case OP_uplus : szName = "OP_uplus \n"; break;
+ default : szName = "UNKNOWN \n"; break;
+ }
+ OutputDebugString(szName);
+}
+
+#endif // DBG
+
+/*** DoBind - bind evaluation tree tree
+ *
+ * DoBind is the public entry to this module. The bind copy of the
+ * parsed expression is initialized and the tree is bound in a
+ * leftmost bottom up order.
+ *
+ * error = DoBind (phTM, pcxt, flags)
+ *
+ * Entry phTM = pointer to handle for TM
+ * pcxt = pointer to context packet
+ * flags.fForceBind = TRUE if bind to be forced
+ * flags.fForceBind = FALSE if rebind decision left to binder
+ * flags.fEnableProlog = TRUE if function scope searched during prolog
+ * flags.fEnableProlog = FALSE if function scope not searched during prolog
+ * flags.fSupOvlOps = FALSE if overloaded operator search enabled
+ * flags.fSupOvlOps = TRUE if overloaded operator search suppressed
+ * flags.fSupBase = FALSE if base searching is not suppressed
+ * flags.fSupBase = TRUE if base searching is suppressed
+ *
+ * Exit pExState->hETree = handle of bound evaluation tree
+ * pExState->hETree->estacksize = size of evaluation stack
+ * pExState->state.eval_ok = FALSE
+ * pExState->state.bind_ok = TRUE if no errors
+ *
+ * Returns EENOERROR if syntax tree bound without error
+ * EENOMEMORY if unable to allocate memory
+ * EEGENERAL if error in bind (pExState->err_num = error)
+ */
+
+
+EESTATUS
+DoBind (
+ PHTM phTM,
+ PCXT pcxt,
+ uint flags
+ )
+{
+ pstree_t pSTree;
+ ushort error = EENOERROR;
+ int excess;
+
+ // lock the expression state structure and copy the context package
+
+ DASSERT (*phTM != 0);
+ if (*phTM == 0) {
+ return (EECATASTROPHIC);
+ }
+ DASSERT (*phTM != 0);
+ if (hEStack == 0) {
+ if ((hEStack = MHMemAllocate (ESTACK_DEFAULT * sizeof (elem_t))) == 0) {
+ return (EECATASTROPHIC);
+ }
+ StackLen = (uint) (ESTACK_DEFAULT * sizeof (elem_t));
+ }
+ pEStack = MHMemLock (hEStack);
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ pExState->state.fEProlog = (ushort) ((flags & BIND_fEnableProlog) == BIND_fEnableProlog);
+ pExState->state.fSupOvlOps = (ushort) ((flags & BIND_fSupOvlOps) == BIND_fSupOvlOps);
+ pExState->state.fSupBase = (ushort) ((flags & BIND_fSupBase) == BIND_fSupBase);
+ pExState->state.fFunction = FALSE;
+ if (pExState->state.parse_ok == TRUE) {
+ pExState->err_num = 0;
+ pExState->cxt = *pcxt;
+ if ((pExState->state.bind_ok == FALSE) ||
+ ((flags & BIND_fForceBind) == BIND_fForceBind) ||
+ (pExState->state.nullcontext == TRUE)) {
+ // the expression has not been successfully bound, the caller
+ // has forced the bind or the expression contains a null
+ // context {} that forces a bind. If none of these cases are
+ // true, then we can exit without rebinding
+
+ pExState->state.bind_ok = FALSE;
+ pExState->state.eval_ok = FALSE;
+ if (pExState->hETree != 0) {
+ // free current evaluation tree if it exists
+ MHMemFree (pExState->hETree);
+ }
+
+ // lock syntax tree and copy to evaluation tree for binding
+
+ DASSERT ( pExState->hSTree != 0 );
+ pSTree = MHMemLock (pExState->hSTree);
+ if ((pExState->hETree = MHMemAllocate (pSTree->size)) != 0) {
+
+ // if evaluation tree is allocated, initialize and bind
+
+ DASSERT ( pExState->hExStr != 0 );
+ pExStr = MHMemLock (pExState->hExStr);
+
+ DASSERT ( pExState->hETree != 0 );
+ pTree = MHMemLock (pExState->hETree);
+ memcpy (pTree, pSTree, pSTree->size);
+
+ // set pointer to context and flag fact that it is not
+ // a pointer into the expression tree
+
+ pCxt = &pExState->cxt;
+ bnCxt = 0;
+ ClassExp = T_NOTYPE;
+ ClassImp = SetImpClass (pCxt, &ClassThisAdjust);
+
+ // indicate that the stack is not in use by the parser
+
+ pTree->stack_base = 0;
+ pTree->stack_next = 0;
+
+ // set the evaluation stack to the default fixed buffer.
+ // bind will allocate a new buffer and move the pointers
+ // if the stack overflows. This work is effecient because
+ // most expressions consist of a single token.
+
+ StackOffset = 0;
+ StackCkPoint = 0;
+ StackMax = 0;
+ memset (pEStack, 0, (uint)StackLen);
+
+ // clear the stack top, stack top previous, function argument
+ // list pointer and based pointer to operand node
+
+ ST = NULL;
+ STP = NULL;
+ bArgList = 0;
+ bnOp = 0;
+ if (Bind ((bnode_t)pTree->start_node) == TRUE) {
+ pExState->state.bind_ok = TRUE;
+ pExState->err_num = 0;
+ // set bind result in case API user asks for expression type
+ pExState->result = *ST;
+ if ((EVAL_IS_PTR (ST) == FALSE) &&
+ ((excess = (uint)TypeSize (ST) - sizeof (val_t)) > 0)) {
+ // since the return value is larger than normal, we
+ // need to reallocate the size of the expression state
+ // structure to include the extra return data
+
+ DASSERT (*phTM != 0);
+ MHMemUnLock (*phTM);
+ if ((*phTM = MHMemReAlloc (*phTM, sizeof (exstate_t) + excess)) != 0) {
+
+ DASSERT ( *phTM != 0 );
+ pExState = MHMemLock (*phTM);
+ memcpy (&pExState->result, ST, sizeof (eval_t));
+ }
+ else {
+
+ DASSERT ( *phTM != 0 );
+ pExState = MHMemLock (*phTM);
+ pExState->err_num = ERR_NOMEMORY;
+ error = EEGENERAL;
+ }
+ }
+ if (EVAL_TYP (ST) == 0) {
+ error = EEGENERAL;
+ }
+ }
+ else {
+ error = EEGENERAL;
+ }
+ bArgList = 0;
+ bnCxt = 0;
+ DASSERT (pExState->hExStr != 0);
+ MHMemUnLock (pExState->hExStr);
+ DASSERT ( pExState->hETree!= 0);
+ MHMemUnLock (pExState->hETree);
+ }
+ else {
+ error = EENOMEMORY;
+ }
+ DASSERT ( pExState->hSTree!= 0);
+ MHMemUnLock (pExState->hSTree);
+ }
+ }
+ DASSERT ( *phTM != 0 );
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ MHMemUnLock (hEStack);
+ return (error);
+}
+
+
+
+/** SetImpClass - set implicit class
+ *
+ * type = SetImpClass (pCxt);
+ *
+ * Entry pCxt = pointer to context packet
+ * pThisAdjust = pointer to implicit this adjustor value
+ *
+ * Exit none
+ *
+ * Returns type index of implied class if context is method
+ * 0 if context is not method
+ */
+
+LOCAL CV_typ_t
+SetImpClass (
+ PCXT pCxt,
+ long *pThisAdjust
+ )
+{
+ HSYM hProc;
+ SYMPTR pProc;
+ CV_typ_t type;
+ CV_typ_t rettype = T_NOTYPE;
+ HTYPE hMFunc;
+ plfMFunc pMFunc;
+
+ *pThisAdjust = 0;
+ if ((hProc = (HSYM)SHHPROCFrompCXT (pCxt)) != (HSYM)0) {
+ // the current context is within some function. Set the node
+ // to the type of the function and see if it is a method of a class
+
+ pProc = (SYMPTR)MHOmfLock ((HDEP)hProc);
+ switch (pProc->rectyp) {
+ case S_LPROC16:
+ case S_GPROC16:
+ type = ((PROCPTR16)pProc)->typind;
+ break;
+
+ case S_LPROC32:
+ case S_GPROC32:
+ type = ((PROCPTR32)pProc)->typind;
+ break;
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ type = ((PROCPTRMIPS)pProc)->typind;
+ break;
+
+ default:
+ DASSERT (FALSE);
+ MHOmfUnLock ((HDEP)hProc);
+ return (0);
+ }
+ MHOmfUnLock ((HDEP)hProc);
+//
+// MBH - bugbug - our compiler is barfing if the cast is to a HVOID,
+// even though the typedef of an HTYPE is HVOID.
+//
+
+ if ((hMFunc = THGetTypeFromIndex (SHHMODFrompCXT (pCxt), type)) != (HTYPE) NULL) {
+ pMFunc = (plfMFunc)((&((TYPPTR)MHOmfLock ((HDEP)hMFunc))->leaf));
+ if (pMFunc->leaf == LF_MFUNCTION) {
+ rettype = pMFunc->classtype;
+ *pThisAdjust = pMFunc->thisadjust;
+ }
+ MHOmfUnLock ((HDEP)hMFunc);
+ }
+ }
+ return (rettype);
+}
+
+
+
+
+/** Bind - bind a node
+ *
+ * Call the bind routine indexed by the the node type. This could
+ * easily be a macro but is done as a function to save code space
+ *
+ * fSuccess = Bind (bn)
+ *
+ * Entry bn = base pointer to node in evaluation tree
+ *
+ * Exit node and all children of node bound
+ *
+ * Returns TRUE if no error in bind
+ * FALSE if error binding node or any child of node
+ */
+
+
+LOCAL bool_t FASTCALL
+Bind (
+ register bnode_t bn
+ )
+{
+#if DBG
+ if (fShowNodes) {
+ OutputDebugString("M: ");
+ PrintNodeOp(NODE_OP(pnodeOfbnode(bn)));
+ }
+#endif
+ return ((*pBind[NODE_OP(pnodeOfbnode(bn))])(bn));
+}
+
+
+
+/** BindLChild - bind the left child of a node
+ *
+ * Call the bind routine indexed by the the node type of the left
+ * child of this node. This could easily be a macro but
+ * is done as a function to save code space
+ *
+ * fSuccess = BindLChild (bn)
+ *
+ * Entry bn = base pointer to node in evaluation tree
+ *
+ * Exit left child and children of node bound
+ *
+ * Returns TRUE if no error in bind
+ * FALSE if error binding node or any child of node
+ */
+
+
+
+LOCAL bool_t FASTCALL
+BindLChild (
+ register bnode_t bn
+ )
+{
+ register bnode_t bnL = NODE_LCHILD (pnodeOfbnode(bn));
+#if DBG
+ if (fShowNodes) {
+ OutputDebugString("R: ");
+ PrintNodeOp(NODE_OP(pnodeOfbnode(bnL)));
+ }
+#endif
+
+ return ((*pBind[NODE_OP(pnodeOfbnode(bnL))])(bnL));
+}
+
+
+
+/** BindRChild - bind the right child of a node
+ *
+ * Call the bind routine indexed by the the node type of the right
+ * child of this node. This could easily be a macro but
+ * is done as a function to save code space
+ *
+ * fSuccess = BindRChild (bn)
+ *
+ * Entry bn = base pointer to node in evaluation tree
+ *
+ * Exit node and all children of node bound
+ *
+ * Returns TRUE if no error in bind
+ * FALSE if error binding left child of node or any child
+ */
+
+
+
+LOCAL bool_t FASTCALL
+BindRChild (
+ register bnode_t bn
+ )
+{
+ register bnode_t bnR = NODE_RCHILD (pnodeOfbnode(bn));
+#if DBG
+ if (fShowNodes) {
+ OutputDebugString("R: ");
+ PrintNodeOp(NODE_OP(pnodeOfbnode(bnR)));
+ }
+#endif
+
+ return ((*pBind[NODE_OP(pnodeOfbnode(bnR))])(bnR));
+}
+
+
+
+/** BindError - return bind error
+ *
+ * Return bind error for an attempt to bind a node. Normally this
+ * routine is the entry for a node type such as OP_rparen that
+ * should never appear in the final parse tree.
+ *
+ * FALSE = BindError (bn)
+ *
+ * Entry bn = base pointer to node in evaluation tree
+ *
+ * Exit none
+ *
+ * Returns FALSE
+ */
+
+
+
+LOCAL bool_t FASTCALL
+BindError (
+ register bnode_t bn
+ )
+{
+ Unreferenced( bn );
+
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+}
+
+
+
+
+/** BindTRUE - return bind successful
+ *
+ * Return bind error for an attempt to bind a node.
+ *
+ * TRUE = BindTRUE (bn)
+ *
+ * Entry bn = base pointer to node in evaluation tree
+ *
+ * Exit none
+ *
+ * Returns TRUE
+ */
+
+
+LOCAL bool_t FASTCALL
+BindTRUE (
+ register bnode_t bn
+ )
+{
+ Unreferenced( bn );
+
+ return (TRUE);
+}
+
+
+
+
+/*** BindAddrOf - Perform the address-of (&) operation
+ *
+ * fSuccess = BindAddrOf (bn)
+ *
+ * Entry pn = pointer to tree node
+ *
+ * Exit NODE_STYPE (bn) = type of stack top
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindAddrOf (
+ bnode_t bn
+ )
+{
+ CV_typ_t type = 0;
+
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) && EVAL_IS_CLASS (ST) && (
+ CLASS_PROP (ST).ovlops == TRUE)) {
+ if (UnaryOverload (bn) == TRUE) {
+ return (TRUE);
+ }
+ }
+ return (AddrOf (bn));
+}
+
+
+
+
+/*** BindArray - Perform an array access ([])
+ *
+ * fSuccess = BindArray (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit ST = value of array element
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindArray (
+ bnode_t bn
+ )
+{
+ eval_t evalT = {0};
+ peval_t pvT;
+ ushort index;
+ plfVTShape pShape;
+ uint desc;
+
+ if (BindLChild (bn) && BindRChild (bn)) {
+ if ((pExState->state.fSupOvlOps == FALSE) && EVAL_IS_CLASS (STP) &&
+ (CLASS_PROP (STP).ovlops == TRUE)) {
+ return (BinaryOverload (bn));
+ }
+ else
+ if (EVAL_IS_ARRAY (STP) || EVAL_IS_ARRAY (ST)) {
+ // above check is for array[3] or 3[array]
+ if (ValidateNodes (OP_lbrack, STP, ST) && PlusMinus (OP_plus)) {
+ return (Fetch ());
+ }
+ }
+ else if (EVAL_IS_PTR (STP)) {
+ pvT = &evalT;
+ *pvT = *STP;
+ SetNodeType (pvT, PTR_UTYPE (pvT));
+ if (EVAL_IS_VTSHAPE (pvT) && (EVAL_STATE (ST) == EV_constant) &&
+ ((index = EVAL_USHORT (ST)) < VTSHAPE_COUNT (pvT))) {
+ // we have a valid index into the shape table
+ // set the node to code address
+ pShape = (plfVTShape)(&((TYPPTR)MHOmfLock ((HDEP)EVAL_TYPDEF (pvT)))->data[0]);
+ desc = ((pShape->desc[index] >> 1) >> ((index & 1) * 4)) & 0x0f;
+ MHOmfUnLock ((HDEP)EVAL_TYPDEF (pvT));
+ CLEAR_EVAL_FLAGS (STP);
+ EVAL_IS_ADDR (STP);
+ return (PopStack ());
+ }
+ else {
+ if (ValidateNodes (OP_lbrack, STP, ST) && PlusMinus (OP_plus)) {
+ return (Fetch ());
+ }
+ }
+
+ }
+ }
+ return (FALSE);
+}
+
+
+
+
+
+/*** BindAssign - Bind an assignment operation
+ *
+ * fSuccess = BindAssign (op)
+ *
+ * Entry op = operation
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindAssign (
+ bnode_t bn
+ )
+{
+ CV_typ_t nop;
+ op_t op = NODE_OP (pnodeOfbnode(bn));
+
+ if (!BindLChild (bn) || !BindRChild (bn)) {
+ return (FALSE);
+ }
+
+ // Left operand must have evaluated to an lvalue
+
+ if (EVAL_STATE (STP) != EV_lvalue) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ return (FALSE);
+ }
+ if (EVAL_IS_CLASS (STP)) {
+ pExState->err_num = ERR_NOCLASSASSIGN;
+ return (FALSE);
+ }
+ if (EVAL_IS_REF (STP)) {
+ RemoveIndir (STP);
+ }
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ /*
+ * if the rhs is a bit-field then convert to the underlying type
+ */
+
+ if (EVAL_IS_BITF( ST )) {
+ EVAL_TYP( ST ) = BITF_UTYPE( ST );
+ }
+
+ if (NODE_OP (pnodeOfbnode(bn)) == OP_eq) {
+
+ // for simple assignment, load both nodes and do proper casting
+
+ if (EVAL_IS_BASED (ST) && (EVAL_IS_ADDR (ST) ||
+ (((EVAL_TYP (ST) == T_INT4) || (EVAL_TYP(ST) == T_UINT4)) &&
+ (EVAL_ULONG (ST) != 0L)) ||
+ (((EVAL_TYP (ST) == T_LONG) || (EVAL_TYP(ST) == T_ULONG)) &&
+ (EVAL_ULONG (ST) != 0L)))) {
+ //M00KLUDGE - this should go through CastNode
+ if (!DeNormalizePtr (ST, STP)) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_BASED (STP)) {
+ if (!NormalizeBase (STP)) {
+ return (FALSE);
+ }
+ }
+ }
+ else {
+ // map assignment operator to arithmetic operator
+ // push address and value onto top of stack and
+ // perform operation
+
+ if (!PushStack (STP) || !PushStack (STP)) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ switch (nop = eqop[op - OP_multeq]) {
+ case OP_plus:
+ case OP_minus:
+ PlusMinus (nop);
+ break;
+
+ default:
+ Arith (nop);
+ }
+ // The top of the stack now contains the value of the memory location
+ // modified by the value. Move the value to the right operand of the
+ // assignment operand.
+
+ // M00KLUDGE - this will not work with variable sized stack entries
+
+ *STP = *ST;
+ PopStack ();
+ }
+
+ // store result
+
+ if (EVAL_IS_BITF (STP)) {
+ }
+ else if (EVAL_IS_ADDR (STP)) {
+ if (!EVAL_IS_ADDR (ST)) {
+ // M00FLAT32 - assumes equivalence between pointer and long
+ // M00FLAT32 - this is a problem for 32 bit model
+
+ if (CastNode (ST, T_LONG, T_LONG) == FALSE) {
+ return (FALSE);
+ }
+ }
+ }
+ else if (EVAL_IS_PTR (STP)) {
+ if (CastNode (ST, EVAL_TYP (STP), PTR_UTYPE (STP)) == FALSE) {
+ return (FALSE);
+ }
+ }
+ else {
+ if (CastNode (ST, EVAL_TYP (STP), EVAL_TYP (STP)) == FALSE) {
+ return (FALSE);
+ }
+ }
+ *STP = *ST;
+ return (PopStack ());
+
+}
+
+
+
+/*** BindBang - bind logical negation operation
+ *
+ * fSuccess = BindBang (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if find successful
+ * FALSE if bind error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindBang (
+ bnode_t bn
+ )
+{
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+
+ // we need to check for a reference to a class without losing the fact
+ // that this is a reference
+
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) && EVAL_IS_CLASS (ST) &&
+ (CLASS_PROP (ST).ovlops == TRUE)) {
+ return (UnaryOverload (bn));
+ }
+ if (!ValidateNodes (OP_bang, ST, NULL)) {
+ return (FALSE);
+ }
+
+ // If the operand is not of pointer type, just pass it on to Unary
+
+ if (!EVAL_IS_PTR (ST)) {
+ return (Unary (OP_bang));
+ }
+
+ // The result is 1 if the pointer is a null pointer and 0 otherwise
+
+ EVAL_STATE (ST) = EV_rvalue;
+ SetNodeType (ST, T_USHORT);
+ return (TRUE);
+}
+
+
+
+
+/*** BindBasePtr - Perform a based pointer access (:>)
+ *
+ * fSuccess = BindBasePtr (bnRight)
+ *
+ * Entry bnRight = based pointer to right operand node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindBasePtr (
+ bnode_t bn
+ )
+{
+ return (BindSegOp (bn));
+}
+
+
+
+
+/** BindBinary - bind an unary arithmetic operation
+ *
+ * fSuccess = BindBinary (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindBinary (
+ bnode_t bn
+ )
+{
+ if (!BindLChild (bn) || !BindRChild (bn)) {
+ return (FALSE);
+ }
+ if (EVAL_IS_REF (STP)) {
+ RemoveIndir (STP);
+ }
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) &&
+ (EVAL_IS_CLASS (ST) && (CLASS_PROP (ST).ovlops == TRUE)) ||
+ (EVAL_IS_CLASS (STP) && (CLASS_PROP (STP).ovlops == TRUE))) {
+ return (BinaryOverload (bn));
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ //
+ // If the left hand side is a cast, patch the operator.
+ //
+ if (EVAL_STATE (STP) == EV_type) {
+ switch ( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_mult:
+ NODE_OP (pnodeOfbnode(bn)) = OP_caststar;
+ break;
+
+ case OP_and:
+ NODE_OP (pnodeOfbnode(bn)) = OP_castamp;
+ AddrOf( NODE_RCHILD(pnodeOfbnode(bn)) );
+ break;
+ }
+ return ( CastBinary (NODE_OP (pnodeOfbnode(bn))));
+
+ } else {
+ switch ( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_caststar:
+ NODE_OP (pnodeOfbnode(bn)) = OP_mult;
+ break;
+
+ case OP_castamp:
+ NODE_OP (pnodeOfbnode(bn)) = OP_and;
+ break;
+ }
+ return (Arith (NODE_OP (pnodeOfbnode(bn))));
+ }
+}
+
+
+
+
+/*** BindBScope - Bind binary :: scoping operator
+ *
+ * fSuccess = BindBScope (bn);
+ *
+ * Entry bn = based pointer to :: node
+ *
+ * Exit ST = evaluated class::ident
+ *
+ * Returns TRUE if bind successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindBScope (
+ bnode_t bn
+ )
+{
+ CV_typ_t oldClassExp;
+ bool_t retval;
+ bnode_t oldbnOp;
+ char *pbName;
+ ushort len;
+ CV_typ_t CurClass;
+ HTYPE hBase; // handle to type record for base class
+ uchar *pField; // pointer to field list
+ char *pc;
+ uint tSkip;
+ ushort cmpflag;
+ peval_t pv;
+ bool_t fGlobal = FALSE;
+ search_t Name;
+ HR_t sRet;
+ CV_typ_t oldClassImp;
+ bnode_t OldArgList;
+
+ // bind the left child using the current explicit class.
+ // set the explicit class to the type of the left child and
+ // bind the right hand side. Then move the right hand bind
+ // result over the left hand bind result and discard the stack
+ // top. This has the effect of bubbling the result of the right
+ // hand bind to the top.
+
+ // first we must check for pClass->Class::member or Class.Class::member
+
+ pv = &pnodeOfbnode(NODE_LCHILD (pnodeOfbnode(bn)))->v[0];
+ pbName = pExStr + EVAL_ITOK (pv);
+ len = EVAL_CBTOK (pv);
+ if (bnOp != 0) {
+ if ((ClassExp != T_NOTYPE) || (ClassImp != T_NOTYPE)) {
+ if (ClassExp != T_NOTYPE) {
+ // search an explicit class
+ CurClass = ClassExp;
+ }
+ else if (ClassImp != T_NOTYPE) {
+ CurClass = ClassImp;
+ }
+
+ // check to see if the left operand is the same class as the current
+ // explicit or implicit class
+
+ if ((hBase = THGetTypeFromIndex (pCxt->hMod, CurClass)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (FALSE);
+ }
+ pField = (uchar *)(&((TYPPTR)MHOmfLock ((HDEP)hBase))->leaf);
+ tSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = (char *)pField + tSkip;
+ if (len == (ushort)*pc) {
+ if (pExState->state.fCase == TRUE) {
+ cmpflag = strncmp (pbName, pc + 1, len);
+ }
+ else {
+ cmpflag = _strnicmp (pbName, pc + 1, len);
+ }
+ }
+ MHOmfUnLock ((HDEP)hBase);
+ if (cmpflag == 0) {
+ if (pvThisFromST (bnOp) == FALSE) {
+ return (FALSE);
+ }
+ PushStack (ST);
+ EVAL_STATE (ST) = EV_type;
+ goto found;
+ }
+ }
+ else {
+ fGlobal = TRUE;
+ }
+ }
+
+ OldArgList = bArgList;
+ bArgList =0;
+
+ if (BindLChild (bn) == FALSE) {
+ if (fGlobal == FALSE) {
+ // we searched an explicit or implicit class scope and did
+ // not find the left operand. we now must search outwards
+ // and find only global symbols
+
+ oldClassImp = ClassImp;
+ ClassImp = T_NOTYPE;
+ InitSearchSym (NODE_LCHILD (pnodeOfbnode(bn)),
+ &(pnodeOfbnode(NODE_LCHILD (pnodeOfbnode(bn)))->v[0]), &Name,
+ T_NOTYPE, SCP_module | SCP_global, CLS_defn);
+ sRet = SearchSym (&Name);
+ ClassImp = oldClassImp;
+ switch (sRet) {
+ case HR_rewrite:
+ case HR_error:
+ case HR_ambiguous:
+ case HR_notfound:
+ return (FALSE);
+
+ case HR_found:
+ // The symbol was in global scope and pushed onto
+ // the stack
+ fGlobal = TRUE;
+ break;
+ }
+ }
+ else {
+ // we did not find the symbol at global scope
+ return (FALSE);
+ }
+ }
+ else {
+ fGlobal = TRUE;
+ }
+ bArgList = OldArgList;
+
+found:
+ if (fGlobal == TRUE) {
+ // flag the fact that the left operand was not a nested type
+ pv = &(pnodeOfbnode(NODE_LCHILD (pnodeOfbnode(bn))))->v[0];
+ CLASS_GLOBALTYPE (pv) = TRUE;
+ EVAL_IS_MEMBER (&pnodeOfbnode(bn)->v[0]) = TRUE;
+ }
+ if ((EVAL_STATE (ST) != EV_type) || (!EVAL_IS_CLASS (ST))) {
+ pExState->err_num = ERR_BSCOPE;
+ return (FALSE);
+ }
+ oldClassExp = ClassExp;
+ ClassExp = EVAL_TYP (ST);
+ oldbnOp = bnOp;
+ bnOp = bn;
+ if ((retval = BindRChild (bn)) == FALSE) {
+ return (FALSE);
+ }
+ ClassExp = oldClassExp;
+ bnOp = oldbnOp;
+ if (retval == TRUE) {
+ if ((fGlobal == TRUE) &&
+ (bnOp == 0) &&
+ (EVAL_IS_METHOD (ST) == FALSE) &&
+ (EVAL_IS_STMEMBER (ST) == FALSE)) {
+ pExState->err_num = ERR_NOTSTATIC;
+ return (FALSE);
+ }
+ if ((EVAL_IS_METHOD (ST) == TRUE) && (FCN_NOTPRESENT (ST) == TRUE)) {
+ pExState->err_num = ERR_METHODNP;
+ return (FALSE);
+ }
+ *STP = *ST;
+ return (PopStack ());
+ }
+ return (retval);
+}
+
+
+
+
+/*** BindByteOps - Handle 'by', 'wo' and 'dw' operators
+ *
+ * fSuccess = BindByteOps (op)
+ *
+ * Entry op = operator (OP_by, OP_wo or OP_dw)
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * Description
+ * Evaluates the contents of the address operand as a byte
+ * ('by'), word ('wo') or dword ('dw'):
+ *
+ * Operand Result
+ * ------- ------
+ * <register> *(uchar *)<register>
+ * <address> *(uchar *)<address>
+ * <variable> *(uchar *)&variable
+ *
+ * Where (uchar *) is replaced by (uint *) for the 'wo' operator,
+ * or by (ulong *) for the 'dw' operator.
+ *
+ * NOTES
+ */
+
+
+LOCAL bool_t FASTCALL
+BindByteOps (
+ bnode_t bn
+ )
+{
+ op_t op;
+ CV_typ_t type;
+
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+
+ // Resolve identifiers and do type checking.
+
+ if (!ValidateNodes (op = NODE_OP (pnodeOfbnode(bn)), ST, NULL)) {
+ return(FALSE);
+ }
+
+ // If the operand is an lvalue and it is a register,
+ // load the value of the register. If the operand is an
+ // lvalue and is not a register, use the address of the variable.
+ //
+ // If the operand is not an lvalue, use its value as is.
+
+ if (EVAL_STATE (ST) == EV_lvalue) {
+ // if the value is a register, the code below will set up a pointer
+ // to the correct type and then dereference it. The evaluation phase
+ // will have to actually generate the pointer.
+
+ if (!EVAL_IS_REG (ST)) {
+ if (AddrOf (bn) == FALSE) {
+ return (FALSE);
+ }
+ }
+ }
+ else if (!EVAL_IS_PTR (ST)) {
+ if (CastNode (ST, T_PFUCHAR, T_PFUCHAR) == FALSE) {
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+ }
+
+ // Now cast the node to (char *), (int *) or
+ // (long *). If the type is char, uchar, short
+ // or ushort, we want to first cast to (char *) so
+ // that we properly DS-extend (casting (int)8 to (char
+ // *) will give the result 0:8).
+
+ type = EVAL_TYP (ST);
+
+ //DASSERT(CV_IS_PRIMITIVE (typ));
+
+ if (CV_TYP_IS_REAL (type)) {
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+ if (op == OP_by) {
+ type = T_PFUCHAR;
+ }
+ else if (op == OP_wo) {
+ type = T_PFUSHORT;
+ }
+ else if (op == OP_dw) {
+ type = T_PFULONG;
+ }
+ if (CastNode (ST, type, type) == FALSE) {
+ return (FALSE);
+ }
+ return (Fetch ());
+}
+
+
+
+
+/** BindCast - bind a cast
+ *
+ * fSuccess = BindCast (bn)
+ *
+ * Entry bn = based pointer to cast node
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindCast (
+ bnode_t bn
+ )
+{
+ peval_t pv;
+ bnode_t bnLeft;
+
+ // Bind right node which is the value
+
+ if (!BindRChild (bn)) {
+ return (FALSE);
+ }
+ bnLeft = NODE_LCHILD (pnodeOfbnode(bn));
+
+ // Check for casting a class to anything, not having a typestring or
+ // the typestring containing an error
+
+ if (EVAL_IS_CLASS (ST) ||
+ (NODE_OP (pnodeOfbnode(bnLeft)) != OP_typestr) ||
+ !ParseType (bnLeft)) {
+ pExState->err_num = ERR_TYPECAST;
+ return (FALSE);
+ }
+ if (EVAL_IS_BITF (ST)) {
+ // change the type of the node to the underlying type
+ EVAL_TYP (ST) = BITF_UTYPE (ST);
+ }
+
+ /*
+ * ansi says result is an rvalue
+ */
+
+ EVAL_STATE (ST) = EV_rvalue;
+
+ // copy the base type node up to the cast node and then try to find a
+ // way to cast the stack to to the base type
+
+ if (EVAL_IS_PTR (ST) && CastPtrToPtr (bn) == TRUE) {
+ // the desired type is a base class so we can just set the node type.
+ // the value portion of bn contains the data to cast right to left
+
+ pv = (peval_t)&pnodeOfbnode(bnLeft)->v[0];
+ return (SetNodeType (ST, EVAL_TYP (pv)));
+ }
+ else {
+ pv = (peval_t)&pnodeOfbnode(bnLeft)->v[0];
+ if (EVAL_MOD (ST) == 0) {
+ // this is because of (strct *)ds:0 which did not have a mod
+ EVAL_MOD (ST) = EVAL_MOD (pv);
+ }
+ if (EVAL_IS_PTR (pv)) {
+ return (CastNode (ST, EVAL_TYP (pv), PTR_UTYPE (pv)));
+ }
+ else {
+ return (CastNode (ST, EVAL_TYP (pv), EVAL_TYP (pv)));
+ }
+ }
+}
+
+
+
+
+
+/*** CastPtrToPtr - cast a pointer to derived to a pointer to base
+ *
+ * fSuccess = CastPtrToPtr (bn)
+ *
+ * Entry bn = based pointer to cast node
+ * ST = value to cast
+ *
+ * Exit value portion of node changed to member to indicate cast data
+ *
+ * Returns TRUE if possible to cast derived to base
+ * FALSE if not
+ */
+
+
+LOCAL bool_t
+CastPtrToPtr (
+ bnode_t bn
+ )
+{
+ static eval_t evalD = {0};
+ static eval_t evalB = {0};
+ peval_t pvD = &evalD;
+ peval_t pvB = &evalB;
+ search_t Name;
+
+ *pvD = *ST;
+ *pvB = *((peval_t)&(pnodeOfbnode(NODE_LCHILD (pnodeOfbnode(bn))))->v[0]);
+ if ((SetNodeType (pvD, PTR_UTYPE (pvD)) == FALSE) ||
+ (SetNodeType (pvB, PTR_UTYPE (pvB)) == FALSE) ||
+ !EVAL_IS_CLASS (pvD) ||
+ !EVAL_IS_CLASS (pvB)) {
+ // we do not have pointers to classes on both sides
+ return (FALSE);
+ }
+ InitSearchBase (bn, EVAL_TYP (pvD), EVAL_TYP (pvB), &Name, pvB);
+ switch (SearchSym (&Name)) {
+ case HR_notfound:
+ break;
+
+ case HR_found:
+ // remove the stack entry that was pushed by successful search
+ return (PopStack ());
+
+ case HR_rewrite:
+ DASSERT (FALSE);
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** BindConst - bind constant
+ *
+ * fSuccess = BindConst (bn)
+ *
+ * Entry bn = based pointer to tree node
+ *
+ * Exit ST = constant
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindConst (
+ bnode_t bn
+ )
+{
+ peval_t pv = &(pnodeOfbnode(bn))->v[0];
+
+ // Set the type flags back into the node, copy
+ // the flags and value into the evaluation stack and return
+ // The handle to module is set so that a cast of a constant to
+ // a user-defined type will work.
+
+ EVAL_MOD (pv) = SHHMODFrompCXT(pCxt);
+ if (BindingFuncArgs == FALSE && EVAL_TYP (pv) == T_PCHAR) {
+ // we are binding a string constant (ie. "foobar") but
+ // not for function args... this is not allowed, since
+ // we can never return a correct address to the string
+ // that we pushed on the stack
+
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return (FALSE);
+ }
+ if (SetNodeType (pv, EVAL_TYP (pv)) == TRUE) {
+ EVAL_STATE (pv) = EV_constant;
+ return (PushStack (pv));
+ }
+ else {
+ return (FALSE);
+ }
+}
+
+
+LOCAL bool_t FASTCALL
+CxtHelper (
+ bnode_t bn,
+ HMOD hMod,
+ HSF hsf,
+ int cMod,
+ int cProc,
+ char * pProc
+ )
+{
+ bool_t error;
+ eval_t evalT = {0};
+ PCXF nCxf;
+ search_t Name;
+ bnode_t oldAmb;
+ uchar oldBindingBP;
+ bnode_t oldbnCxt;
+ CV_typ_t oldClassImp;
+ PCXT oldCxt;
+ HR_t retval;
+ pnode_t pn;
+ peval_t pvT;
+ long oldThisAdjust;
+
+ /*
+ * initialize the context packet in the node to have the same contents
+ * as the current context. We will then set new fields in the order
+ * exe, module, proc.
+ */
+
+ nCxf = (PCXF)&(pnodeOfbnode(bn))->v[0];
+ *SHpCXTFrompCXF (nCxf) = *pCxt;
+ SHpCXTFrompCXF(nCxf)->hProc = 0;
+ SHpCXTFrompCXF(nCxf)->hBlk = 0;
+ *SHpFrameFrompCXF (nCxf) = pExState->frame;
+
+ /*
+ * set new context from handle to module
+ */
+
+ if (!SHGetCxtFromHmod ( hMod, SHpCXTFrompCXF (nCxf))) {
+ SHGetCxtFromHexe (SHHexeFromHmod( hMod ), SHpCXTFrompCXF (nCxf));
+ }
+
+ if(cMod > 0) {
+ WORD rgLn[2];
+ ADDR addr;
+ SHOFF cbLn;
+
+ /*
+ * If we have a source file, then we want to get the address
+ * of the first line in the source file. This is obtained
+ * by trying to get the address of line 1, and if does not
+ * exist then get the address of the first line after
+ * line 1 in the file.
+ */
+
+ if (SLFLineToAddr (hsf, 1, &addr, &cbLn, rgLn) ||
+ SLFLineToAddr (hsf, rgLn[1], &addr, &cbLn, NULL)) {
+ SHSetCxt (&addr, SHpCXTFrompCXF (nCxf));
+ }
+ }
+
+ if (cProc <= 0) {
+
+ SHpCXTFrompCXF(nCxf)->hProc = 0;
+ SHpCXTFrompCXF(nCxf)->hBlk = 0;
+
+ } else {
+ /*
+ * a proc was specified, initialize the context and search for
+ * the proc within the current context. Note that if a proc was
+ * not specified, the hProc and hBlk in nCxf are null.
+ *
+ * M00SYMBOL - doesn't allow for T::foo() as proc
+ */
+
+ oldCxt = pCxt;
+ pCxt = SHpCXTFrompCXF (nCxf);
+ pvT = &evalT;
+ EVAL_ITOK (pvT) = pProc - pExStr;
+ EVAL_CBTOK (pvT) = (uchar)cProc;
+
+ /*
+ * do not allow ambiguous symbols during context symbol searching
+ */
+
+ oldAmb = pExState->ambiguous;
+ pExState->ambiguous = 0;
+ oldBindingBP = BindingBP;
+ BindingBP = FALSE;
+ InitSearchSym (bn, pvT, &Name, 0,
+ SCP_lexical | SCP_module | SCP_global, CLS_method);
+ retval = SearchSym (&Name);
+ BindingBP = oldBindingBP;
+ if (pExState->ambiguous != 0) {
+ pExState->err_num = ERR_AMBCONTEXT;
+ return FALSE;
+ }
+ pExState->ambiguous = oldAmb;
+ switch (retval) {
+ case HR_rewrite:
+ DASSERT (FALSE);
+ return FALSE;
+
+ case HR_notfound:
+ return FALSE;
+
+ case HR_found:
+ /*
+ * if the symbol was found, it was pushed onto the stack
+ */
+
+ PopStack ();
+ if (!EVAL_IS_FCN (pvT)) {
+ /*
+ * name is not a procedure reachable from
+ * the specified context
+ */
+
+ return FALSE;
+ }
+ }
+
+ /*
+ * attempt to set the context to the specified instance of the
+ * function. If the attempt fails, then set the context to
+ * the address of the function
+ */
+
+ if (SHGetFuncCxf (&pvT->addr, nCxf) == NULL) {
+ if (SHSetCxt (&pvT->addr, SHpCXTFrompCXF (nCxf)) == NULL) {
+ return FALSE;
+ }
+ }
+ pCxt = oldCxt;
+ if (SHHPROCFrompCXT (SHpCXTFrompCXF (nCxf)) == 0) {
+ return FALSE;
+ }
+ }
+
+ /*
+ * save old context and implicit class and set new ones
+ */
+
+ oldCxt = pCxt;
+ oldbnCxt = bnCxt;
+ oldClassImp = ClassImp;
+ oldThisAdjust = ClassThisAdjust;
+ pCxt = SHpCXTFrompCXF (nCxf);
+
+ // BUGBUG: BRYANT-REVIEW
+ // Are the fixup/unfixup calls necessary for WOW? Also, should there be a
+ // BindingREG or BindingTLS test?
+
+ SHFixupAddr(SHpADDRFrompCXT(pCxt));
+ SHUnFixupAddr(SHpADDRFrompCXT(pCxt));
+ if (BindingBP && (cMod > 0))
+ pBindBPCxt = pCxt;
+ bnCxt = bn;
+ ClassImp = SetImpClass (pCxt, &ClassThisAdjust);
+ pn = pnodeOfbnode(bn);
+ pn->pcxf = nCxf;
+
+ error = BindLChild (bn);
+
+ /*
+ * if the result of the expression is bp relative, then we must
+ * load the value before returning to the original context
+ */
+
+ if ((error == TRUE) &&
+ (EVAL_STATE (ST) == EV_lvalue) &&
+ (EVAL_IS_BPREL (ST) || EVAL_IS_REGREL (ST) || EVAL_IS_TLSREL(ST))) {
+ if (EVAL_IS_REF (ST)) {
+ if (!Fetch ()) {
+ return (FALSE);
+ }
+ EVAL_IS_REF (ST) = FALSE;
+ }
+ EVAL_STATE (ST) = EV_rvalue;
+ }
+
+
+ /*
+ * restore previous context and implicit class
+ */
+
+ if ((bnCxt = oldbnCxt) != 0) {
+ /*
+ * the old context was pointing into the expression tree.
+ * since the expression tree could have been reallocated,
+ * we must recompute the context pointer
+ */
+
+ pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
+ }
+ else {
+ /*
+ * the context pointer is pointing into the expression state structure
+ */
+ pCxt = oldCxt;
+ }
+ ClassImp = oldClassImp;
+ ClassThisAdjust = oldThisAdjust;
+ return (error);
+} /* CxtHelper() */
+
+
+LOCAL bool_t FASTCALL
+BindContext(
+ bnode_t bn
+ )
+/*++
+
+Routine Description:
+
+ This function is used to bind a Context Operator from a parsed
+ expression. The routine will decompose the context operator into
+ its parts and then attempt to resolve them againist each other and
+ the rest of the expression tree rooted at the current node.
+
+ Globals used:
+
+ pCxt - Supplies a pointer to the current Context being used to
+ bind the expression
+ bnCxt - Supplies a based pointer to the node in the expression tree
+ which contains the last context operator or context restriction
+ operator (i.e. ::). If it is NULL then we have not yet seen one.
+
+ NOTES:
+ The form of the context operator is
+ {[[<number>] <proc>][,[<module>][,[<exe>]]]}
+
+ where:
+ <number> is a base 10 instance of the procedure on the stack.
+ n > 0 means count from top of stack down
+ n < 0 means count from current stack pointer up
+ n = 0 means take first instance up (will find current proc)
+ if no number is specfied it defaults to 0.
+ <proc> is the name of a procedure (if overloaded then argument
+ types must be given to disambiguate) which is to be found
+ on the stack.
+ <module> is the name of a module name in the exe to do the search in
+ <exe> is the .exe or .dll name to search in.
+
+ parenthesis may be used in any of the above to include commas, etc.
+
+Arguments:
+
+ bn - Supplies a pointer to the node to be bound.
+
+Return Value:
+
+ TRUE if the expression was succesfully bound and FALSE in the event
+ of an error.
+
+--*/
+
+{
+ int instance = 0;
+ bool_t isnegative = FALSE;
+ char * pProc;
+ short cProc;
+ char * pMod;
+ short cMod;
+ char * pExe;
+ short cExe;
+ char * pb;
+ HEXE hExe = 0;
+ HMOD hMod = 0;
+ char savedChar;
+
+ /*
+ * Insure that the token starts correctly
+ */
+
+ pb = pExStr + EVAL_ITOK (&(pnodeOfbnode(bn))->v[0]);
+ if (*pb++ != '{') /* } */ { // curly in comment is for editor
+ goto contextbad;
+ }
+
+ /*
+ * skip white space and process instance specification of instance number
+ * where the number is base 10 and can be signed
+ */
+
+ while ((*pb == ' ') || (*pb == '\t')) {
+ pb++;
+ }
+ if (*pb == '-') {
+ isnegative = TRUE;
+ pb++;
+ }
+ else if (*pb == '+') {
+ pb++;
+ }
+ while (isdigit (*pb)) {
+ instance = instance * 10 + (*pb++ - '0');
+ }
+ if (isnegative) {
+ instance = -instance;
+ }
+
+ /*
+ * set the pointer to the procedure and skip to a comma that is not
+ * enclosed in parenthesis
+ */
+
+ if (!ContextToken (&pb, &pProc, &cProc) ||
+ !ContextToken (&pb, &pMod, &cMod) ||
+ !ContextToken (&pb, &pExe, &cExe)) {
+ return (FALSE);
+ }
+
+ /*
+ * the null context {} forces a rebind
+ * this is not yet supported by the kernel so I am making this
+ * an error to reserve the meaning for future versions
+ */
+
+ if ((cProc == -1) && (cMod == -1) && (cExe == -1)) {
+ goto contextbad;
+ }
+
+ /*
+ * process exe name
+ */
+
+ if (cExe > 0) {
+ /*
+ * find the exe handle if {...,exe} was specified
+ */
+
+ savedChar = *(pExe + cExe);
+ *(pExe + cExe) = 0;
+ hExe = SHGethExeFromName (pExe);
+ *(pExe + cExe) = savedChar;
+ if (hExe == 0) {
+ goto contextbad;
+ }
+
+ /*
+ * if an exe is specified, then set module to first module in exe
+ * this provides us with a default in case no module was
+ * specified.
+ *
+ * if no modules then we have a bad set of debug info, or
+ * no debug info.
+ */
+ SHWantSymbols(hExe);
+ if ((hMod = SHGetNextMod (hExe, hMod)) == 0) {
+ goto contextbad;
+ }
+ }
+ /*
+ * No exe file was specified in the context string. We therefore
+ * need to come up with a default answer for the exe file.
+ * The default is just the current EXE.
+ *
+ * Note: We know that either the module or procedure was specified.
+ */
+ else if (cExe == -1) {
+ if ((hMod = SHHMODFrompCXT (pCxt)) == 0) {
+ /*
+ * there is no current module so get first module
+ * (from an arbitrary exe?)
+ *
+ * NOTENOTE:: jimsch -- since hExe and hMod are currently
+ * both 0 this will return 0!!!!
+ */
+
+ if ((hExe == 0) && (cProc != -1)) {
+ /*
+ * If a process name was specified -- use some arbitray
+ * exe -- it will get overridden later anyway
+ */
+ hExe = SHGetNextExe(hExe);
+ }
+
+ if ((hMod = SHGetNextMod (hExe, hMod)) == 0) {
+ /*
+ * error in context
+ */
+ goto contextbad;
+ }
+ }
+
+ /*
+ * Get the EXE for the current module
+ */
+
+ if ((hExe = SHHexeFromHmod (hMod)) == 0) {
+ /*
+ * If a procedure was specified --- who cares about the
+ * exe name -- chose some arbitrary value --- it will get
+ * overridden later
+ */
+
+ if (cProc == -1) {
+ goto contextbad;
+ }
+ hExe = SHGetNextExe(hExe);
+ if (hExe == 0) {
+ DASSERT(FALSE); // ???? --- may be a bad assert
+ goto contextbad;
+ }
+ }
+ }
+
+ /*
+ * An empty string was specified for the exe name, This is
+ * currently not a legal way of specifing things.
+ */
+ else {
+ goto contextbad;
+ }
+
+ /*
+ * process module specification. At this point we have the handle to the
+ * exe and either the handle to the first module or the handle to the
+ * current module
+ */
+
+ if (cMod <= 0) {
+
+ return CxtHelper(bn, hMod, 0, cMod, cProc, pProc);
+
+ } else {
+ HMOD hModTemp;
+ HSF hsfTemp;
+
+ /*
+ * find the module handle if {...,mod...} was specified
+ */
+
+ savedChar = *(pMod + cMod);
+ *(pMod + cMod) = 0;
+ hMod = hModTemp = (HMOD) NULL;
+ while (hModTemp = SHGetNextMod (hExe, hModTemp)) {
+ if (hsfTemp = SLHsfFromFile (hModTemp, pMod)) {
+ if (CxtHelper(bn, hModTemp, hsfTemp, cMod, cProc, pProc)) {
+ *(pMod + cMod) = savedChar;
+ return TRUE;
+ }
+ }
+ }
+ *(pMod + cMod) = savedChar;
+ if (hMod == 0) {
+ goto contextbad;
+ }
+ }
+
+contextbad:
+ pExState->err_num = ERR_BADCONTEXT;
+ return (FALSE);
+}
+
+
+
+LOCAL bool_t FASTCALL
+BindExeContext(
+ bnode_t bn
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ LSZ pb;
+ LSZ pb1;
+ char ch;
+ HEXE hExe = 0;
+ HMOD hMod = 0;
+
+ pb = pExStr + EVAL_ITOK (&(pnodeOfbnode(bn))->v[0]);
+
+ /*
+ * skip white space
+ */
+
+ while ((*pb == ' ') || (*pb == '\t')) {
+ pb++;
+ }
+ for (pb1=pb; *pb1 && *pb1 != '!'; ) {
+ pb1++;
+ }
+ ch = *pb1;
+ *pb1 = '\0';
+ hExe = SHGethExeFromModuleName (pb);
+ if (!hExe) {
+ hExe = SHGethExeFromName (pb);
+ }
+ *pb1 = ch;
+
+ if (hExe) {
+ SHWantSymbols(hExe);
+ hMod = SHGetNextMod (hExe, hMod);
+ return CxtHelper(bn, hMod, 0, 0, 0, 0);
+ } else {
+ pExState->err_num = ERR_BADCONTEXT;
+ return FALSE;
+ }
+}
+
+
+
+/*** BindDMember - Perform a dot member access (.*)
+ *
+ * fSuccess = BindDMember (bnRight)
+ *
+ * Entry bnRight = based pointer to right operand node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+LOCAL bool_t FASTCALL
+BindDMember (
+ bnode_t bn
+ )
+{
+ bool_t retval;
+ CV_typ_t oldClassExp;
+
+ pExState->err_num = ERR_OPNOTSUPP;
+ return (FALSE);
+
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+ if (EVAL_STATE (ST) != EV_lvalue) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ return (FALSE);
+ }
+ if (EVAL_IS_REF (ST)) {
+ if (!Fetch ()) {
+ return (FALSE);
+ }
+ EVAL_IS_REF (ST) = FALSE;
+ }
+ oldClassExp = ClassExp;
+ ClassExp = EVAL_TYP (ST);
+ retval = BindRChild (bn);
+ ClassExp = oldClassExp;
+ if (retval == TRUE) {
+ // move element descriptor to previous stack entry and pop stack
+ *STP = *ST;
+ PopStack ();
+ NOTTESTED (FALSE);
+ // M00SYMBOL - need to check that the stack top is a pointer to member
+ }
+ return (FALSE);
+
+}
+
+
+
+
+
+/*** BindDot - Perform the dot (.) operation
+ *
+ * fSuccess = BindDot (bn)
+ *
+ * Entry pn = pointer to tree node
+ * bnOp = based pointer to operand node
+ *
+ * Exit NODE_STYPE (bn) = type of stack top
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindDot (
+ bnode_t bn
+ )
+{
+ bool_t retval;
+ CV_typ_t oldClassExp;
+ ushort state;
+ bnode_t oldbnOp;
+ peval_t pv;
+ pnode_t pn;
+ pnode_t pnR;
+ pnode_t pnL;
+
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+
+ //
+ // propogate the context from the left node to the right node
+ //
+ pn = pnodeOfbnode(bn);
+ pnL = pnodeOfbnode(NODE_LCHILD(pnodeOfbnode(bn)));
+ pnR = pnodeOfbnode(NODE_RCHILD(pnodeOfbnode(bn)));
+ if (pnL && pnR) {
+ pnR->pcxf = pnL->pcxf;
+ }
+ if (pnL) {
+ pn->pcxf = pnL->pcxf;
+ }
+
+ if (EVAL_IS_REF (ST)) {
+ if (!Fetch ()) {
+ return (FALSE);
+ }
+ EVAL_IS_REF (ST) = FALSE;
+ }
+ if (!EVAL_IS_CLASS (ST)) {
+ pExState->err_num = ERR_NEEDSTRUCT;
+ return (FALSE);
+ }
+ oldClassExp = ClassExp;
+ ClassExp = EVAL_TYP (ST);
+ if ((NODE_OP (pnodeOfbnode(NODE_RCHILD (pnodeOfbnode(bn)))) == OP_bscope) ||
+ OP_IS_IDENT (NODE_OP (pnodeOfbnode(NODE_RCHILD (pnodeOfbnode(bn)))))) {
+ //
+ // set the based node pointer for the operator
+ //
+ oldbnOp = bnOp;
+ bnOp = bn;
+ retval = BindRChild (bn);
+ bnOp = oldbnOp;
+ }
+ else {
+ pExState->err_num = ERR_SYNTAX;
+ retval = FALSE;
+ }
+ ClassExp = oldClassExp;
+ if (retval == TRUE) {
+ //
+ // move element descriptor to previous stack entry and pop stack
+ //
+ state = EVAL_STATE (STP);
+ *STP = *ST;
+ if (state == EV_type) {
+ EVAL_STATE (STP) = EV_type;
+ }
+ else {
+ EVAL_STATE (STP) = EV_lvalue;
+ }
+
+ //
+ // Check for and correct a.b::c case
+ //
+ pn = pnodeOfbnode(NODE_RCHILD(pnodeOfbnode(bn)));
+ if (NODE_OP(pn) == OP_bscope) {
+ pv = &pnodeOfbnode(NODE_LCHILD(pn))->v[0];
+ if (EVAL_IS_CLASS(pv)) {
+ CLASS_GLOBALTYPE(pv) = FALSE;
+ }
+ }
+ return (PopStack ());
+ }
+ return (FALSE);
+}
+
+
+
+
+
+/*** BindFetch - Bind the fetch (*) operation
+ *
+ * fSuccess = BindFetch (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindFetch (
+ bnode_t bn
+ )
+{
+ pnode_t pn;
+ pnode_t pnL;
+
+
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+ //
+ // propogate the context from the left node to this node
+ //
+ pn = pnodeOfbnode(bn);
+ pnL = pnodeOfbnode(NODE_LCHILD(pnodeOfbnode(bn)));
+ if (pnL) {
+ pn->pcxf = pnL->pcxf;
+ }
+
+ return Fetch();
+}
+
+
+
+
+/** BindFunction - bind a function call and arguments
+ *
+ * fSuccess = BindFunction (bn)
+ *
+ * Entry bn = based pointer to function node
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindFunction (
+ bnode_t bn
+ )
+{
+ belem_t oldStackCkPoint = StackCkPoint;
+ ushort len;
+ uint OpDot;
+ ushort Right;
+ pnode_t pn = pnodeOfbnode(bn);
+
+ CkPointStack ();
+ if (Function (bn) == TRUE) {
+ StackCkPoint = oldStackCkPoint;
+ return (TRUE);
+ }
+
+ ResetStack ();
+ StackCkPoint = oldStackCkPoint;
+ if (pExState->err_num != ERR_CLASSNOTFCN) {
+ return (FALSE);
+ }
+
+ // rewrite object (arglist) as object.operator() (arglist)
+
+ OpDot = pTree->node_next;
+ Right = OpDot + sizeof (node_t) + sizeof (eval_t);
+ len = 2 * (sizeof (node_t) + sizeof (eval_t));
+ if ((ushort)(pTree->size - OpDot) < len) {
+ if (!GrowETree (len)) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ if (bnCxt != 0) {
+ // the context was pointing into the expression tree.
+ // since the expression tree could have been reallocated,
+ // we must recompute the context pointer
+
+ pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
+ }
+ }
+
+ // set operator node to OP_dot
+
+ pn = pnodeOfbnode(OpDot);
+ memset (pn, 0, sizeof (node_t) + sizeof (eval_t));
+ NODE_OP (pn) = OP_dot;
+ NODE_LCHILD (pn) = NODE_LCHILD (pnodeOfbnode(bn));
+ NODE_RCHILD (pn) = (bnode_t)Right;
+ NODE_LCHILD (pnodeOfbnode(bn)) = (bnode_t)OpDot;
+
+ // insert OP_Ofunction node as right node
+
+ pn = pnodeOfbnode((bnode_t)Right);
+ memset (pn, 0, sizeof (node_t) + sizeof (eval_t));
+ NODE_OP (pn) = OP_Ofunction;
+
+ pTree->node_next += len;
+ return (Function (bn));
+}
+
+
+
+
+
+/** Functions are bound assuming the following conventions:
+ *
+ * C calling sequence
+ * Arguments are pushed right to left. Varargs are not cast.
+ * If the function is a method, the this pointer is pushed after
+ * all of the actuals.
+ *
+ * Returns
+ * char al
+ * short ax
+ * long dx:ax
+ * float 4 bytes pointed to by ds:ax
+ * float 4 bytes pointed to by dx:ax
+ * double 8 bytes pointed to by ds:ax
+ * double 8 bytes pointed to by dx:ax
+ * long double numeric coprocessor st0
+ * struct() 1|2|4 bytes dx:ax
+ * struct() 3 & > 4 bytes bytes pointed to by ds:ax
+ * struct() 3 & > 4 bytes bytes pointed to by dx:ax
+ * pointer ax
+ * pointer dx:ax
+ *
+ * pascal calling sequence
+ * Arguments are pushed left to right. If the return value is a
+ * primitive type larger than 4 bytes or is real or is any user
+ * defined type that is not an alias for a primitive type, then
+ * the caller must allocate space on the stack and push the SS
+ * offset of this space as a hidden argument after all of the
+ * of this hidden argument after all of the actual arguments
+ * have been pushed. If the function is a method, then the this
+ * pointer is pushed as the last (hidden) argument. There must
+ * be an exact match on the number and types of arguments (after
+ * conversion). This is not a supported sequence for 32-bit systems.
+ *
+ * Returns
+ * char al
+ * short ax
+ * long dx:ax
+ * float 4 bytes pointed to by hidden argument
+ * double 8 bytes pointed to by hidden argument
+ * long double 10 bytes pointed to by hidden argument
+ * any UDT not primitive bytes pointed to by hidden argument
+ * pointer ax
+ * pointer dx:ax
+ *
+ * fastcall - 16 calling sequence
+ * Arguments are pushed left to right. If the return value is a
+ * real type, the it is returned in the numeric coprocessor st0.
+ * If the return value is a user defined type that is not an alias
+ * for a primitive type, then the caller must allocate space on the
+ * stack and push the last (hidden) argument as the SS offset of
+ * this space. There must be an exact match on the number and types
+ * of arguments (after conversion).
+ *
+ *
+ * Returns
+ * char al
+ * short ax
+ * long dx:ax
+ * all real values numeric coprocessor st0
+ * any UDT not primitive bytes pointed to by hidden argument
+ * pointer ax
+ * pointer dx:ax
+ *
+ * fastcall - 32 calling sequence
+ * Arguments are pushed right to left. If the return value is a
+ * real type, it is returned in the numeric coprocessor st0.
+ * If the return value is a user defined type that is not an alias
+ * for a primitive type, then the caller must allocate space on the
+ * stack and push the first (hidden) argument as the SS offset of
+ * this space. There must be an exact match on the number and types
+ * of arguments (after conversion).
+ *
+ * Returns:
+ * char al
+ * short ax
+ * long eax
+ * all real values numeric coprocessor st0
+ * any UDT not primiate bytes pointed to by hidden argument
+ * pointer eax
+ * pointer not valid
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+Function (
+ bnode_t bn
+ )
+{
+ bnode_t bnT;
+ pnode_t pnT;
+ pnode_t pnRight;
+ short argc = 0;
+ long retsize;
+ bnode_t OldArgList;
+ eval_t evalF = {0};
+ peval_t pvF;
+ eval_t evalRet = {0};
+ peval_t pvRet;
+ UOFFSET SPOff = 0;
+ bool_t retval;
+ pargd_t pa;
+ bnode_t bnRight = NODE_RCHILD (pnodeOfbnode(bn));
+ BOOL fTypeArgs = FALSE;
+ pnode_t pnTmp = pnodeOfbnode(bn);
+
+ // Bind argument nodes until end of arguments reached and count arguments
+
+ // set BindingFuncArgs to true; notifies anybody who cares that
+ // we are binding arguments (currently only BindConst cares)
+
+ BindingFuncArgs = TRUE;
+
+ for (bnT = bnRight, pnTmp = pnodeOfbnode(bnT);
+ NODE_OP (pnodeOfbnode(bnT)) != OP_endofargs;
+ bnT = NODE_RCHILD (pnodeOfbnode(bnT)), pnTmp = pnodeOfbnode(bnT)) {
+
+ // Check that this is an argument node. If not then we have an
+ // internal error
+
+ if (NODE_OP (pnodeOfbnode(bnT)) != OP_arg) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+
+ argc++;
+
+ /*
+ * If can't bind this child then the whole expression fails
+ */
+
+ if (!BindLChild (bnT)) {
+ return (FALSE);
+ } else {
+ if (EVAL_STATE (ST) == EV_type) {
+ /*
+ * Need to make sure we are not mixing and matching types
+ * and values
+ */
+
+ if ((argc > 1) && (!fTypeArgs)) {
+ pExState->err_num = ERR_MIXTYPEANDVALUE;
+ return FALSE;
+ }
+
+ fTypeArgs = TRUE;
+
+ if (EVAL_TYP (ST) == T_VOID) {
+ /*
+ * if the first argument is a type void, then there
+ * no arguments.
+ */
+
+ if (NODE_OP( pnodeOfbnode( NODE_RCHILD( pnodeOfbnode( bnT )))) != OP_endofargs) {
+ pExState->err_num = ERR_SYNTAX;
+ return (FALSE);
+ } else {
+ /*
+ * truncate the argument list
+ */
+
+ NODE_OP (pnodeOfbnode(bnT)) = OP_endofargs;
+ argc--;
+ break;
+ }
+ } else {
+ pnT = pnodeOfbnode(bnT);
+ pa = (pargd_t)&(pnT->v[0]);
+ pa->actual = EVAL_TYP (ST);
+ pa->flags.isconst = EVAL_IS_CONST (ST);
+ pa->flags.isvolatile = EVAL_IS_VOLATILE (ST);
+
+ /*
+ * tell MatchArgs that the argument is a type and
+ * that exact match is required.
+ */
+
+ pa->flags.istype = TRUE;
+ }
+ } else {
+ if ((argc > 1) && (fTypeArgs)) {
+ pExState->err_num = ERR_MIXTYPEANDVALUE;
+ return FALSE;
+ }
+
+ pnT = pnodeOfbnode(bnT);
+ pa = (pargd_t)&(pnT->v[0]);
+ pa->actual = EVAL_TYP (ST);
+ }
+ }
+ }
+
+ /*
+ * reset BindingFuncArgs
+ */
+
+ BindingFuncArgs = FALSE;
+
+ /*
+ * set the argument list address for overload resolution
+ * This is recursive because there can be function calls on the
+ * left hand side of the function tree
+ */
+
+ OldArgList = bArgList;
+ bArgList = bnRight;
+
+ /*
+ * the left child must resolve to a function address
+ */
+
+ /*
+ * NOTENOTE - jimsch - from languages
+ *
+ * M00SYMBOL - need to make sure symbol search returns method address
+ * M00SYMBOL - or vtable info
+ */
+
+ retval = BindLChild (bn);
+ bArgList = OldArgList;
+ if (retval == FALSE) {
+ return (FALSE);
+ }
+
+ pExState->state.fFunction = TRUE;
+ if (EVAL_STATE (ST) == EV_type) {
+ if (EVAL_IS_FCN (ST)) {
+ return (TRUE);
+ }
+
+ /*
+ * the function name resolved to a type. we now look for the
+ * name as apredefined type or a UDT and attempt to cast the
+ * argument toargument to that type. If the cast could be
+ * performed, the tree was rewrittento an OP_cast
+ */
+
+ if (FCN_NOTPRESENT (ST) == TRUE) {
+ return (TRUE);
+ }
+ if (argc == 1) {
+ return (FcnCast (bn));
+ }
+
+ // we must have at least one argument for a casting function
+
+ pExState->err_num = ERR_ARGLIST;
+ return (FALSE);
+ }
+
+ if (EVAL_IS_AMBIGUOUS (ST)) {
+ pExState->err_num = ERR_AMBIGUOUS;
+ return (FALSE);
+ }
+
+ if (FCN_NOTPRESENT (ST) == TRUE) {
+ pExState->err_num = ERR_METHODNP;
+ return (FALSE);
+ }
+
+ if (EVAL_IS_PTR (ST)) {
+ Fetch ();
+ }
+
+ if (EVAL_IS_CLASS (ST)) {
+ pExState->err_num = ERR_CLASSNOTFCN;
+ return (FALSE);
+ }
+
+ if ((EVAL_STATE (ST) != EV_lvalue) || !EVAL_IS_FCN (ST)) {
+ pExState->err_num = ERR_SYNTAX;
+ return (FALSE);
+ }
+
+ /*
+ * the stack top is the function address node. We save this information.
+ * The stack now contains the arguments left to right plus the function
+ * node.
+ */
+
+ pvF = &evalF;
+ *pvF = *ST;
+
+ /*
+ * If we specified only types as aguments, then we really only wanted
+ * to get the address of the method. This means that we need to pop
+ * off the arguments, and push on something representing an address
+ */
+
+ if (fTypeArgs) {
+ for (; argc >= 0; argc--) {
+ if (!PopStack()) {
+ DASSERT(FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return FALSE;
+ }
+ }
+
+ pnodeOfbnode(bn)->op = OP_identFunc;
+ SetNodeType( pvF, T_32PCHAR);
+ EVAL_STATE(pvF) = EV_rvalue;
+ return PushStack( pvF );
+ }
+
+ /*
+ * do the user's stack setup. On return, the OP_arg nodes will contain
+ * the type of the argument and the address field will contain the offset
+ * of the argument relative to the user's SP. If the argument type is
+ * zero, then the argument is a vararg and will be pushed uncasted onto
+ * user's stack.
+ */
+
+ pnRight = pnodeOfbnode(bnRight);
+
+ switch (FCN_CALL (pvF)) {
+#ifdef TARGET_i386
+ case FCN_STD:
+ case FCN_C:
+ retval = PushCArgs (pvF, pnRight, &SPOff, 0, ST);
+ break;
+
+ case FCN_PASCAL:
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ pExState->err_num = ERR_CALLSEQ;
+ return FALSE;
+ }
+ if (argc != FCN_PCOUNT (pvF)) {
+ retval = FALSE;
+ } else {
+ retval = PushPArgs (pvF, pnRight, &SPOff, ST);
+ }
+ break;
+
+ case FCN_FAST:
+ if (argc != FCN_PCOUNT (pvF)) {
+ retval = FALSE;
+ } else {
+ retval = PushFArgs (pvF, pnRight, &SPOff, ST);
+ }
+ break;
+
+ case FCN_THIS:
+ if (!ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ pExState->err_num = ERR_CALLSEQ;
+ return FALSE;
+ }
+ retval = PushTArgs( pvF, pnRight, &SPOff, 0, ST);
+ break;
+#endif
+
+#ifdef TARGET_MIPS
+ case FCN_MIPS:
+ retval = PushMArgs (pvF, pnRight, &SPOff, ST);
+ break;
+#endif
+
+#ifdef TARGET_ALPHA
+
+ case FCN_ALPHA:
+ retval = PushAArgs (pvF, pnRight, &SPOff, ST);
+ break;
+#endif
+
+#ifdef TARGET_PPC
+ case FCN_PPC:
+ retval = PushPPCArgs (pvF, pnRight, &SPOff, ST);
+ break;
+
+#endif
+
+ default:
+ pExState->err_num = ERR_CALLSEQ;
+ return (FALSE);
+ }
+
+ if (retval == FALSE) {
+ pExState->err_num = ERR_FCNERROR;
+ return (FALSE);
+ }
+
+ /*
+ * We pop function node and the actual arguments
+ */
+
+ for (; argc >= 0; argc--) {
+ if (!PopStack ()) {
+ DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ }
+
+ /*
+ * push the type of the return value from the function. If the return
+ * type is void, then later attempts to use the value will cause an error
+ */
+
+ pvRet = &evalRet;
+ *pvRet = *pvF;
+ SetNodeType (pvRet, FCN_RETURN (pvF));
+
+ if ((retsize = TypeSize (pvRet)) > MAXRETURN) {
+ pExState->err_num = ERR_FCNERROR;
+ return (FALSE);
+ }
+
+ EVAL_VALLEN (pvRet) = (ushort)retsize;
+ EVAL_STATE (pvRet) = EV_rvalue;
+
+ if (!PushStack (pvRet)) {
+ return (FALSE);
+ } else {
+ return (TRUE);
+ }
+
+}
+
+
+
+
+/*** BindPlusMinus - bind binary plus or minus
+ *
+ * fSuccess = BindPlusMinus (bn)
+ *
+ * Entry bn = based pointer to tree node
+ *
+ * Exit ST = STP +- ST
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindPlusMinus (
+ bnode_t bn
+ )
+{
+ if (!BindLChild (bn) || !BindRChild (bn)) {
+ return (FALSE);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) &&
+ (EVAL_IS_CLASS (ST) && (CLASS_PROP (ST).ovlops == TRUE)) ||
+ (EVAL_IS_CLASS (STP) && (CLASS_PROP (STP).ovlops == TRUE))) {
+ return (BinaryOverload (bn));
+ }
+
+ if (EVAL_STATE (STP) == EV_type) {
+ switch ( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_plus:
+ NODE_OP (pnodeOfbnode(bn)) = OP_castplus;
+ break;
+
+ case OP_minus:
+ NODE_OP (pnodeOfbnode(bn)) = OP_castminus;
+ break;
+
+ }
+ return ( CastBinary (NODE_OP (pnodeOfbnode(bn))));
+
+ } else {
+ switch ( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_castplus:
+ NODE_OP (pnodeOfbnode(bn)) = OP_plus;
+ break;
+
+ case OP_castminus:
+ NODE_OP (pnodeOfbnode(bn)) = OP_minus;
+ break;
+
+ }
+ return (PlusMinus (NODE_OP (pnodeOfbnode(bn))));
+ }
+}
+
+
+
+/*** BindPMember - Perform a pointer to member access (->*)
+ *
+ * fSuccess = BindPMember (bnRight)
+ *
+ * Entry bnRight = based pointer to node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindPMember (
+ bnode_t bn
+ )
+{
+ Unreferenced(bn);
+
+ pExState->err_num = ERR_OPNOTSUPP;
+ return (FALSE);
+}
+
+
+
+
+/*** BindPointsTo - Perform a structure access (->)
+ *
+ * fSuccess = BindPointsTo (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindPointsTo (
+ bnode_t bn
+ )
+{
+ eval_t evalT = {0};
+ peval_t pvT;
+ bool_t retval;
+ CV_typ_t oldClassExp;
+ bnode_t oldbnOp;
+ peval_t pv;
+ pnode_t pn;
+ pnode_t pnR;
+ pnode_t pnL;
+
+
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+
+ //
+ // propogate the context from the left node to the right node
+ //
+ pnL = pnodeOfbnode(NODE_LCHILD(pnodeOfbnode(bn)));
+ pnR = pnodeOfbnode(NODE_RCHILD(pnodeOfbnode(bn)));
+ if (pnL && pnR) {
+ pnR->pcxf = pnL->pcxf;
+ }
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+
+ if (EVAL_IS_CLASS (ST)) {
+ return (PointsToOverload (bn));
+ }
+
+ // Check to make sure the left operand is a struct/union pointer.
+ // To do this, remove a level of indirection from the node's type
+ // and see if it's a struct or union.
+
+ if (!EVAL_IS_PTR (ST)) {
+ pExState->err_num = ERR_NOTSTRUCTPTR;
+ return (FALSE);
+ }
+ pvT = &evalT;
+ *pvT = *ST;
+ RemoveIndir (pvT);
+ if (!EVAL_IS_CLASS (pvT)) {
+ pExState->err_num = ERR_NEEDSTRUCT;
+ return (FALSE);
+ }
+ if (!Fetch ()) {
+ return (FALSE);
+ }
+ if (EVAL_IS_REF (ST)) {
+ if (!Fetch ()) {
+ return (FALSE);
+ }
+ EVAL_IS_REF (ST) = FALSE;
+ }
+ oldClassExp = ClassExp;
+ ClassExp = EVAL_TYP (ST);
+ oldbnOp = bnOp;
+ bnOp = bn;
+ retval = BindRChild (bn);
+ ClassExp = oldClassExp;
+ bnOp = oldbnOp;
+ if (retval == TRUE) {
+ // move element descriptor to previous stack entry and pop stack
+ *STP = *ST;
+ EVAL_STATE (STP) = EV_lvalue;
+
+ /*
+ * Check for and correct a->b::c case
+ */
+
+
+ pn = pnodeOfbnode(NODE_RCHILD(pnodeOfbnode(bn)));
+ if (NODE_OP(pn) == OP_bscope) {
+ pv = &pnodeOfbnode(NODE_LCHILD(pn))->v[0];
+ if (EVAL_IS_CLASS(pv)) {
+ CLASS_GLOBALTYPE(pv) = FALSE;
+ }
+ }
+ return (PopStack ());
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** BindPostIncDec - Bind expr++ or expr--
+ *
+ * fSuccess = BindPostIncDec (bn);
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindPostIncDec (
+ bnode_t bn
+ )
+{
+ register op_t nop = OP_plus;
+
+ if (NODE_OP (pnodeOfbnode(bn)) == OP_postdec) {
+ nop = OP_minus;
+ }
+
+ // load left node and store as return value
+
+ if (!BindLChild (bn)) {
+ return(FALSE);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) && EVAL_IS_CLASS (ST) &&
+ (CLASS_PROP (ST).ovlops == TRUE)) {
+ return (BinaryOverload (bn));
+ }
+ if (!ValidateNodes (nop, ST, NULL)) {
+ return(FALSE);
+ }
+
+ /*
+ * Must have an lValue at this point
+ */
+
+ if (EVAL_STATE(ST) != EV_lvalue) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ return FALSE;
+ }
+
+ // do the post-increment or post-decrement operation and store
+
+ return (PrePost (nop));
+}
+
+
+
+
+/*** BindPreIncDec - Bind ++expr or --expr
+ *
+ * fSuccess = BindPreIncDec (op);
+ *
+ * Entry op = operator
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindPreIncDec (
+ bnode_t bn
+ )
+{
+ register op_t nop = OP_plus;
+
+ if (NODE_OP (pnodeOfbnode(bn)) == OP_predec) {
+ nop = OP_minus;
+ }
+ if (!BindLChild (bn)) {
+ return(FALSE);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) && EVAL_IS_CLASS (ST) &&
+ (CLASS_PROP (ST).ovlops == TRUE)) {
+ return (UnaryOverload (bn));
+ }
+ if (!ValidateNodes (nop, ST, NULL)) {
+ return(FALSE);
+ }
+
+ /*
+ * Must have an lValue at this point
+ */
+
+ if (EVAL_STATE(ST) != EV_lvalue) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ return FALSE;
+ }
+
+ // do the increment or decrement operation and return the result
+
+ return (PrePost (nop));
+}
+
+
+
+
+/** BindRelat - bind relational and equality operations
+ *
+ * fSuccess = BindRelat (op)
+ *
+ * Entry op = OP_lt, OP_lteq, OP_gt, OP_gteq, OP_eqeq, or OP_bangeq
+ *
+ * Returns TRUE if no evaluation error
+ * FALSE if evaluation error
+ *
+ * Description
+ * If both operands are arithmetic, passes them on to Arith().
+ * Otherwise (one or both operands pointers), does the evaluation
+ * here.
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindRelat (
+ bnode_t bn
+ )
+{
+ if (!BindLChild (bn) || !BindRChild (bn)) {
+ return (FALSE);
+ }
+
+ if (EVAL_IS_REF (STP)) {
+ RemoveIndir (STP);
+ }
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+
+ if ((pExState->state.fSupOvlOps == FALSE) &&
+ (EVAL_IS_CLASS (ST) && (CLASS_PROP (ST).ovlops == TRUE)) ||
+ (EVAL_IS_CLASS (STP) && (CLASS_PROP (STP).ovlops == TRUE))) {
+ return (BinaryOverload (bn));
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ // Check to see if either operand is a pointer
+ // If so, the operation is special. Otherwise,
+ // hand it to Arith ().
+
+ if (!EVAL_IS_PTR (STP) && !EVAL_IS_PTR (ST)) {
+ // neither side is a pointer or a reference to a pointer
+ return (Arith (NODE_OP (pnodeOfbnode(bn))));
+ }
+
+ // Both nodes should now be typed as either or
+ // pointers.
+
+ //DASSERT ((CV_TYP_IS_PTR (EVAL_TYP (STP))) && (CV_TYP_IS_PTR (EVAL_TYP (ST))));
+
+ // For the relational operators (<, <=, >, >=),
+ // only offsets are compared. For the equality operators (==, !=),
+ // both segments and offsets are compared.
+
+ EVAL_STATE (STP) = EV_rvalue;
+ SetNodeType ((peval_t)STP, (CV_typ_t)(ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? T_LONG : T_SHORT));
+ return (PopStack ());
+}
+
+
+
+
+/*** BindSegOp - Handle ':' segmentation operator
+ *
+ * fSuccess = BindSegOp (bn)
+ *
+ * Entry bn = based pointer to node
+ * STP = segment value
+ * ST = offset value
+ *
+ * Returns TRUE if successful
+ * FALSE is error
+ *
+ * DESCRIPTION
+ * Both operands must have integral values (but cannot
+ * be long or ulong). The result of op1:op2 is a (char
+ * *) with segment equal to op1 and offset equal to
+ * op2.
+ */
+
+
+LOCAL bool_t FASTCALL
+BindSegOp (
+ bnode_t bn
+ )
+{
+ /*
+ * OP_segop and OP_segopReal use the same validate code so
+ * just choose one arbitrarily
+ */
+
+ if (!BindLChild (bn) || !BindRChild (bn) ||
+ !ValidateNodes(OP_segop, STP, ST)) {
+ return(FALSE);
+ }
+
+ // In addition, check to make sure that neither
+ // operand is of type long or ulong.
+
+ //DASSERT((EVAL_TYP (STP) == T_SHORT) || (EVAL_TYP (STP) == T_USHORT));
+ //DASSERT((EVAL_TYP (ST) == T_SHORT) || (EVAL_TYP (ST) == T_USHORT));
+
+ EVAL_STATE (STP) = EV_rvalue;
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ SetNodeType ((peval_t)STP, T_32PFCHAR);
+ } else {
+ SetNodeType ((peval_t)STP, T_PFCHAR);
+ }
+ return (PopStack ());
+}
+
+
+
+
+
+/*** BindSizeOf - Bind sizeof operation
+ *
+ * fSuccess = BindSizeOf (bn)
+ *
+ * Entry bn = based pointer to operand node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindSizeOf (
+ bnode_t bn
+ )
+{
+ bnode_t bnLeft = NODE_LCHILD (pnodeOfbnode(bn));
+ CV_typ_t type;
+
+ type = ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? T_ULONG : T_USHORT;
+
+ if (NODE_OP (pnodeOfbnode(bnLeft)) == OP_typestr) {
+ // the operand of the sizeof was a type string not an expression
+ // we now need to parse the type string and push a type node onto
+ // the stack so the following code can determine the type
+ if (!ParseType (bnLeft)) {
+ pExState->err_num = ERR_SYNTAX;
+ return (FALSE);
+ }
+ else if (!PushStack (&(pnodeOfbnode(bnLeft))->v[0])) {
+ return (FALSE);
+ }
+ }
+ else {
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+ }
+
+ // The type of the result of a sizeof operation is unsigned int
+ // except for huge arrays which are long to get the full length
+
+ EVAL_STATE (ST) = EV_constant;
+ if (EVAL_IS_ARRAY (ST) && (PTR_ARRAYLEN (ST) > 0xffff)) {
+ type = T_ULONG;
+ }
+ EVAL_ULONG (ST) = TypeSize (ST);
+ SetNodeType (ST, type);
+ (pnodeOfbnode(bn))->v[0] = *ST;
+ return (TRUE);
+}
+
+
+
+
+/*** BindSymbol - bind symbol according to scope specification mask
+ *
+ * fSuccess = BindSymbol (bn)
+ *
+ * Entry bn = based pointer to tree node
+ *
+ * Exit ST = symbol
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ *
+ */
+
+
+LOCAL bool_t FASTCALL
+BindSymbol (
+ bnode_t bn
+ )
+{
+ search_t Name;
+ token_t Tok;
+ peval_t pv;
+#ifdef TARGET_PPC
+ bool_t fFirstPass = TRUE;
+#endif
+
+ if (ClassExp == T_NOTYPE) {
+
+ // look up the identifier using the current context and
+ // set the symbol information. If the symbol is a typedef
+ // then the state will be set to EV_type. Otherwise it will
+ // be set to EV_lvalue
+
+ InitSearchSym (bn, &pnodeOfbnode(bn)->v[0], &Name, ClassExp, SCP_all, CLS_defn);
+#ifdef TARGET_PPC
+SSStart:
+#endif
+ switch (SearchSym (&Name)) {
+ case HR_rewrite:
+ return (Bind (bn));
+
+ case HR_error:
+ case HR_ambiguous:
+ return (FALSE);
+
+ case HR_notfound:
+ // if symbol was not found, search for it as a primitive
+ if (!ParseType (bn)) {
+ // if the current radix is hex and the symbol potentially
+ // could be a number, then change the type of the node
+ if (ParseConst (Name.sstr.lpName, &Tok, pExState->radix) == ERR_NONE) {
+ if (Tok.pbEnd ==
+ (char *)Name.sstr.lpName + Name.sstr.cb) {
+ pExState->err_num = ERR_NONE;
+ NODE_OP (pnodeOfbnode(bn)) = OP_const;
+ pv = &(pnodeOfbnode(bn))->v[0];
+ EVAL_ULONG (pv) = VAL_ULONG (&Tok);
+ if (SetNodeType (pv, Tok.typ) == TRUE) {
+ EVAL_STATE (pv) = EV_constant;
+ return (PushStack (pv));
+ }
+ }
+ }
+#ifdef TARGET_PPC
+ // The first pass through didn't find the symbol. Try again,
+ // this time looking for the .. name. This is to fix the case
+ // where the linker discards the function descriptor and COFFtoCV
+ // wasn't able to generate a function record.
+
+ if (fFirstPass) {
+ InitSearchSym (bn, &pnodeOfbnode(bn)->v[0], &Name, ClassExp, SCP_all, CLS_defn);
+ if (Name.sstr.cb < (sizeof(szAltSymName) - 3)) {
+ memcpy(szAltSymName, "..", 2);
+ memcpy(szAltSymName + 2, Name.sstr.lpName, Name.sstr.cb);
+ *(szAltSymName + 2 + Name.sstr.cb) = '\0';
+ Name.sstr.lpName = szAltSymName;
+ Name.sstr.cb += 2;
+ }
+ fFirstPass = FALSE;
+ goto SSStart;
+ }
+#endif // TARGET_PPC
+ pExState->err_num = ERR_UNKNOWNSYMBOL;
+ return (FALSE);
+ }
+ return (PushStack (&pnodeOfbnode(bn)->v[0]));
+
+ case HR_found:
+ //
+ // if the symbol was found, it was pushed onto the stack
+ //
+ return (TRUE);
+ }
+ }
+ else {
+
+ // look up the identifier using the current context and
+ // set the symbol information. If the symbol is a typedef
+ // then the state will be set to EV_type. Otherwise it will
+ // be set to EV_lvalue
+
+ InitSearchRight (bnOp, bn, &Name, CLS_defn);
+ switch (SearchSym (&Name)) {
+ case HR_rewrite:
+ return (Bind (bn));
+
+ default:
+ case HR_ambiguous:
+ return (FALSE);
+
+ case HR_notfound:
+ // if symbol was not found, search for it as a primitive
+ if (!ParseType (bn)) {
+ pExState->err_num = ERR_UNKNOWNSYMBOL;
+ return (FALSE);
+ }
+ return (PushStack (&pnodeOfbnode(bn)->v[0]));
+
+ case HR_found:
+ //
+ // if the symbol was found, it was pushed onto the stack
+ //
+ return (TRUE);
+ }
+ }
+}
+
+
+
+
+/** BindUnary - bind an unary arithmetic operation
+ *
+ * fSuccess = BindUnary (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ * DESCRIPTION
+ * Binds the result of an arithmetic operation. The unary operators
+ * dealt with here are:
+ *
+ * ~ - +
+ *
+ * Pointer arithmetic is NOT handled; all operands must be of
+ * arithmetic type.
+ */
+
+
+LOCAL bool_t FASTCALL
+BindUnary (
+ bnode_t bn
+ )
+{
+ if (!BindLChild (bn)) {
+ return (FALSE);
+ }
+
+ // we need to check for a reference to a class without losing the fact
+ // that this is a reference
+
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+ if ((pExState->state.fSupOvlOps == FALSE) && EVAL_IS_CLASS (ST) &&
+ (CLASS_PROP (ST).ovlops == TRUE)) {
+ return (UnaryOverload (bn));
+ }
+ if (!ValidateNodes (NODE_OP (pnodeOfbnode(bn)), ST, NULL)) {
+ return (FALSE);
+ }
+ return (Unary (NODE_OP (pnodeOfbnode(bn))));
+}
+
+
+
+
+/*** BindUScope - Bind unary :: scoping
+ *
+ * fSuccess = BindUScope (bnRes);
+ *
+ * Entry bnRes = based pointer to unary scoping node
+ *
+ * Exit *ST = evaluated left node of pnRes
+ *
+ * Returns TRUE if evaluation successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+BindUScope (
+ bnode_t bn
+ )
+{
+ register bool_t retval;
+ CXT oldCxt;
+ CV_typ_t oldClassImp;
+
+ // save current context packet and set current context to module scope
+
+ oldCxt = *pCxt;
+ oldClassImp = ClassImp;
+ SHGetCxtFromHmod (SHHMODFrompCXT (pCxt), pCxt);
+ // the unary scoping operator specifically means no implicit class
+ ClassImp = 0;
+ retval = BindLChild (bn);
+ *pCxt = oldCxt;
+ ClassImp = oldClassImp;
+ return (retval);
+}
+
+
+
+/** Second level routines. These routines are called by the various
+ * Bind... routines.
+ */
+
+
+
+
+/** AddrOf - bind an address of node
+ *
+ * fSuccess = AddrOf (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ */
+
+LOCAL bool_t FASTCALL
+AddrOf (
+ bnode_t bn
+ )
+{
+ CV_typ_t type;
+ eval_t evalT = {0};
+ peval_t pvT;
+ CV_modifier_t Mod = {0};
+
+ if (!ValidateNodes (OP_addrof, ST, NULL))
+ return (FALSE);
+
+ // The operand must be an lvalue and cannot be a register variable
+
+ if ((EVAL_STATE (ST) != EV_lvalue) && (EVAL_STATE (ST) != EV_type)) {
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+
+// MBH - bugbug - we want to say something more intelligent to our users.
+// Can we tell the world this is in a register value?
+// Where is this value picked up in the evaluate stream?
+//
+
+ if (EVAL_IS_REG (ST)) {
+ pExState->err_num = ERR_ADDROFREG;
+ return (FALSE);
+ }
+
+ if (EVAL_IS_PTR (ST)) {
+ if (EVAL_IS_REF (ST)) {
+ // the address of a reference is a pointer to the value
+ // referred to. Get a pointer of the correct type (i.e.
+ // a non-reference pointer) to what the reference pointer
+ // points to.
+
+ EVAL_TYP( ST ) = PTR_UTYPE(ST);
+ }
+ pvT = &evalT;
+ ProtoPtr (pvT, ST, FALSE, Mod);
+
+ if (MatchType (pvT, FALSE) == MTYP_none) {
+ // searching the context of the pointer type for a type
+ // record which is a pointer record and has the current
+ // pointer type as its underlying type has failed, set
+ // the type to pointer to character
+
+ if (EVAL_IS_NPTR (ST)) {
+ type = T_PCHAR;
+ }
+ else if (EVAL_IS_FPTR (ST)) {
+ type = T_PFCHAR;
+ }
+ else if (EVAL_IS_NPTR32 (ST)) {
+ type = T_32PCHAR;
+ }
+ else if (EVAL_IS_FPTR32 (ST)) {
+ type = T_32PFCHAR;
+ }
+ else if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ type = T_32PCHAR;
+ } else {
+ type = T_PHCHAR;
+ }
+ }
+ else {
+ type = EVAL_TYP (pvT);
+ }
+ }
+ else if (CV_IS_PRIMITIVE (EVAL_TYP (ST))) {
+ // if the node is primitive, then a pointer to the primitive type
+ // can be created. We will create the pointer as a pointer
+ // and assume that subsequent code will cast to a pointer if
+ // necessary
+
+ if (ADDR_IS_FLAT (pCxt->addr)) {
+ // since I am creating a pointer, I am guessing the type
+ // based upon the mode of the current context packet
+
+ type = CV_NEWMODE(EVAL_TYP (ST), CV_TM_NPTR32);
+ }
+ else {
+ type = CV_NEWMODE(EVAL_TYP (ST), CV_TM_NPTR);
+ }
+ }
+ else if (EVAL_IS_CLASS (ST)) {
+ pvT = &evalT;
+
+ ProtoPtr (pvT, ST, FALSE, Mod);
+ if (MatchType (pvT, FALSE) == MTYP_none) {
+ // searching the context of the class type for a type
+ // record which is a pointer record and has the current
+ // class type as its underlying type has failed, set
+ // the type to pointer to special CV pointer
+ type = T_FCVPTR;
+ }
+ else {
+ type = EVAL_TYP (pvT);
+ }
+ }
+ else {
+ // we are punting here and calling the address of anything else
+ // a pointer to character
+
+ type = T_PFCHAR;
+ }
+
+ if ((NODE_STYPE (pnodeOfbnode(bn)) = type) == 0) {
+ // unable to find proper pointer type
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+ else {
+ if (EVAL_STATE (ST) != EV_type) {
+ EVAL_STATE (ST) = EV_rvalue;
+ }
+ return (SetNodeType (ST, type));
+ }
+}
+
+
+
+
+
+/** Arith - bind an arithmetic operation
+ *
+ * fSuccess = Arith (op)
+ *
+ * Entry op = operator (OP_...)
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ * DESCRIPTION
+ * Binds the result of an arithmetic operation. The binary operators
+ * dealt with here are:
+ *
+ * && || (both are bound here but evaluation is different)
+ * * / %
+ * + -
+ * == !=
+ * < <= > >=
+ * << >>
+ * & ^ |
+ *
+ * Pointer arithmetic is NOT handled; all operands must be of
+ * arithmetic type.
+ */
+
+
+LOCAL bool_t FASTCALL
+Arith (
+ op_t op
+ )
+{
+ CV_typ_t typRes;
+ bool_t fIsReal;
+ bool_t fIsSigned;
+ bool_t fResInt;
+
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+ if (EVAL_IS_REF (STP)) {
+ RemoveIndir (STP);
+ }
+ // Resolve identifiers and check the node types. If the nodes
+ // pass validation, they should not be pointers (only arithmetic
+ // operands are handled by this routine).
+
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+ if (!ValidateNodes (op, STP, ST)) {
+ return (FALSE);
+ }
+ if (EVAL_IS_BITF (ST)) {
+ SetNodeType (ST, BITF_UTYPE (ST));
+ }
+ if (EVAL_IS_BITF (STP)) {
+ SetNodeType (STP, BITF_UTYPE (STP));
+ }
+
+ // M00KLUDGE - this is commented out because &&, etc. come through
+ // M00KLUDGE - and they allow pointers.
+ //DASSERT (!EVAL_IS_PTR (ST) && !EVAL_IS_PTR (STP));
+
+ // The resultant type is the same as the type of the left-hand
+ // side (assume for now we don't have the special int-result case).
+
+ typRes = PerformUAC(EVAL_TYP (STP), EVAL_TYP(ST));
+
+ fIsReal = CV_TYP_IS_REAL (typRes);
+ fIsSigned = CV_TYP_IS_SIGNED (typRes);
+ fResInt = FALSE;
+
+
+ // Finally, check the actual arithmetic operation.
+
+ switch (op) {
+ case OP_eqeq:
+ case OP_bangeq:
+ case OP_lt:
+ case OP_gt:
+ case OP_lteq:
+ case OP_gteq:
+ case OP_oror:
+ case OP_andand:
+ fResInt = TRUE;
+ break;
+
+ case OP_plus:
+ case OP_minus:
+ case OP_mult:
+ case OP_div:
+ break;
+
+ case OP_mod:
+ case OP_shl:
+ case OP_shr:
+ case OP_and:
+ case OP_or:
+ case OP_xor:
+ // Both operands must have integral type.
+
+ DASSERT(!fIsReal);
+ if (fIsReal) {
+ return (FALSE);
+ }
+ else {
+ break;
+ }
+
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+
+ // Now set up the resultant node and coerce back to the correct
+ // type:
+
+ if (EVAL_STATE (STP) != EV_type) {
+ EVAL_STATE (STP) = EV_rvalue;
+ }
+ if (fResInt) {
+ SetNodeType ((peval_t)STP, (CV_typ_t)(ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? T_LONG : T_SHORT));
+ }
+ else if (fIsReal) {
+ SetNodeType ((peval_t)STP, (CV_typ_t)typRes);
+ }
+ else if (fIsSigned) {
+ SetNodeType ((peval_t)STP, (CV_typ_t)T_LONG);
+ }
+ else {
+ SetNodeType ((peval_t)STP, (CV_typ_t)T_ULONG);
+ }
+ if (!fResInt) {
+ if (CastNode (STP, typRes, typRes) == FALSE) {
+ return (FALSE);
+ }
+ }
+ return (PopStack ());
+}
+
+
+LOCAL bool_t FASTCALL
+CastBinary (
+ op_t op
+ )
+{
+ CV_typ_t typRes;
+ bool_t fIsReal;
+ bool_t fIsSigned;
+ bool_t fResInt;
+
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+
+ if (EVAL_IS_BITF (ST)) {
+ SetNodeType (ST, BITF_UTYPE (ST));
+ }
+
+ //
+ // The resultant type is the same as the type of the left-hand
+ // side.
+ //
+ typRes = EVAL_TYP (STP);
+
+ fIsReal = CV_TYP_IS_REAL (typRes);
+ fIsSigned = CV_TYP_IS_SIGNED (typRes);
+ fResInt = FALSE;
+
+ //
+ // Now set up the resultant node and coerce back to the correct
+ // type:
+ //
+ EVAL_STATE (STP) = EVAL_STATE(ST);
+ if (fIsReal) {
+ SetNodeType (STP, typRes);
+ } else if (fIsSigned) {
+ SetNodeType (STP, T_LONG);
+ } else {
+ SetNodeType (STP, T_ULONG);
+ }
+
+ if (!fResInt) {
+ if (CastNode (STP, typRes, typRes) == FALSE) {
+ return (FALSE);
+ }
+ }
+ return (PopStack ());
+}
+
+
+
+/*** Fetch - complete the fetch (*) operation
+ *
+ * fSuccess = Fetch (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ */
+
+
+LOCAL bool_t FASTCALL
+Fetch (
+ void
+ )
+{
+
+ // validate the node type
+
+ if (!ValidateNodes (OP_fetch, ST, NULL)) {
+ return(FALSE);
+ }
+ if (EVAL_IS_BASED (ST)) {
+ if (!NormalizeBase (ST)) {
+ return(FALSE);
+ }
+ }
+ if (EVAL_STATE (ST) != EV_type) {
+ EVAL_STATE (ST) = EV_lvalue;
+ }
+
+ // Remove a level of indirection from the resultant type.
+
+ RemoveIndir (ST);
+ return (TRUE);
+}
+
+
+
+
+/*** PlusMinus - Perform an addition or subtraction operation
+ *
+ * fSuccess = PlusMinus (op)
+ *
+ * Entry op = operator (OP_plus or OP_Minus)
+ * STP = left operand
+ * ST = right operand
+ *
+ * Returns TRUE if bind successful
+ * FALSE if bind error
+ *
+ * Exit pExState->err_num = error ordinal if bind error
+ *
+ * Notes Special handling is required when one or both operands are
+ * pointers. Otherwise, the arguments are passed on to
+ * Arith ().
+ */
+
+LOCAL bool_t FASTCALL
+PlusMinus (
+ op_t op
+ )
+{
+ if (EVAL_IS_REF (STP)) {
+ RemoveIndir (STP);
+ }
+ if (EVAL_IS_REF (ST)) {
+ RemoveIndir (ST);
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ /*
+ * If we have a code address in one item, cast it to be a
+ * char *
+ */
+
+ if ((EVAL_IS_LABEL(ST) || EVAL_IS_FCN(ST)) && !EVAL_IS_PTR(STP)) {
+ CastNode(ST, T_PFUCHAR, T_PFUCHAR);
+ } else if ((EVAL_IS_LABEL(STP) || EVAL_IS_FCN(STP)) && !EVAL_IS_PTR(ST)) {
+ CastNode(STP, T_PFUCHAR, T_PFUCHAR);
+ }
+
+ // validate node types
+
+ if (!ValidateNodes (op, STP, ST)) {
+ return(FALSE);
+ }
+
+ // Check to see if either operand is a pointer or a reference to
+ // a pointer. If so, the operation is special. Otherwise,
+ // hand it to Arith ().
+
+ if (!EVAL_IS_PTR (STP) && !EVAL_IS_PTR (ST)) {
+ return (Arith (op));
+ }
+
+ // Perform the bind. There are two cases:
+ //
+ // I) ptr + int, int + ptr, ptr - int
+ // II) ptr - ptr
+
+ if ((op == OP_plus) || !(EVAL_IS_PTR (ST))) {
+ // Case (I). ptr + int, int + ptr, ptr - int
+ // The resultant node has the same type as the pointer:
+ if (!EVAL_IS_PTR (STP)) {
+ *STP = *ST;
+ }
+ if ((EVAL_STATE (STP) == EV_type) && (EVAL_STATE (ST) == EV_type)) {
+ EVAL_STATE (STP) = EV_type;
+ }
+ else {
+ EVAL_STATE (STP) = EV_lvalue;
+ }
+ }
+ else {
+ // Case (II): ptr - ptr. The result is of type ptrdiff_t and
+ // is equal to the distance between the two pointers (in the
+ // address space) divided by the size of the items pointed to:
+
+ if (EVAL_TYP (STP) != EVAL_TYP (ST)) {
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+ if ((EVAL_STATE (STP) == EV_type) && (EVAL_STATE (ST) == EV_type)) {
+ EVAL_STATE (STP) = EV_type;
+ }
+ else {
+ EVAL_STATE (STP) = EV_rvalue;
+ }
+ // we know we are working with pointers so we do not have to check
+ // EVAL_IS_PTR (pv)
+
+ if (EVAL_IS_BASED (STP)) {
+ NormalizeBase (STP);
+ }
+ if (EVAL_IS_BASED (ST)) {
+ NormalizeBase (ST);
+ }
+ if (EVAL_IS_NPTR (STP) || EVAL_IS_FPTR (STP)) {
+ SetNodeType (STP, T_SHORT);
+ }
+ if (EVAL_IS_NPTR32 (STP)) {
+ SetNodeType (STP, T_LONG);
+ }
+ else {
+ SetNodeType (STP, T_LONG);
+ }
+ }
+ return (PopStack());
+}
+
+
+
+
+/** PrePost - perform the increment/decrement operation
+ *
+ * fSuccess = PrePost (op);
+ *
+ * Entry op = operation to perform (OP_plus or OP_minus)
+ *
+ * Exit increment/decrement performed and result stored in memory
+ *
+ * Returns TRUE if no error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+PrePost (
+ op_t op
+ )
+{
+ eval_t evalT = {0};
+ peval_t pvT;
+
+ // initialize the increment/decrecment to a constant 1
+
+ pvT = &evalT;
+ CLEAR_EVAL (pvT);
+ SetNodeType (pvT, T_USHORT);
+ EVAL_STATE (pvT) = EV_constant;
+ EVAL_USHORT (pvT) = 1;
+ if (!PushStack (pvT)) {
+ return (FALSE);
+ }
+ if (PlusMinus (op)) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+
+
+/** Unary - bind an unary arithmetic operation
+ *
+ * fSuccess = Unary (op)
+ *
+ * Entry op = operator
+ * ST = operand (must be dereferenced)
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ * DESCRIPTION
+ * Binds the result of an arithmetic operation. The unary operators
+ * dealt with here are:
+ *
+ * ! ~ - +
+ *
+ * Pointer arithmetic is NOT handled; all operands must be of
+ * arithmetic type.
+ */
+
+
+LOCAL bool_t FASTCALL
+Unary (
+ op_t op
+ )
+{
+ CV_typ_t typRes;
+ bool_t fIsReal;
+ bool_t fIsSigned;
+ register ushort fResInt;
+
+ if (EVAL_IS_BITF (ST)) {
+ SetNodeType (ST, BITF_UTYPE (ST));
+ }
+
+ DASSERT (!EVAL_IS_PTR (ST) && !EVAL_IS_CLASS (ST));
+
+ // The resultant type is the same as the type of the left-hand
+ // side (assume for now we don't have the special int-result case).
+
+ typRes = EVAL_TYP (ST);
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ if (TypeSizePrim(typRes) < 4) {
+ typRes = T_LONG;
+ }
+ } else {
+ if (TypeSizePrim(typRes) < 2) {
+ typRes = T_SHORT;
+ }
+ }
+
+ fIsReal = CV_TYP_IS_REAL (typRes);
+ fIsSigned = CV_TYP_IS_SIGNED (typRes);
+ fResInt = FALSE;
+
+
+ // Finally, check the actual arithmetic operation.
+
+ switch (op) {
+ case OP_bang:
+ fResInt = TRUE;
+ break;
+
+ case OP_negate:
+ case OP_uplus:
+ break;
+
+ case OP_tilde:
+ // The operand must have integral type.
+
+ DASSERT (!fIsReal);
+ if (fIsReal) {
+ return (FALSE);
+ }
+ else {
+ break;
+ }
+
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+
+ // Now set up the resultant node and coerce back to the correct
+ // type:
+
+ EVAL_STATE (ST) = EV_rvalue;
+ if (fResInt) {
+ SetNodeType (ST, T_SHORT);
+ }
+ else if (fIsReal) {
+ SetNodeType (ST, typRes);
+ }
+ else if (fIsSigned) {
+ SetNodeType (ST, T_LONG);
+ }
+ else {
+ SetNodeType (ST, T_ULONG);
+ }
+ if (!fResInt) {
+ if (CastNode (ST, typRes, typRes) == FALSE) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+
+
+
+
+/** Function call support routines
+ *
+ */
+
+#ifdef TARGET_i386
+
+LOCAL bool_t FASTCALL
+PushTArgs(
+ peval_t pvF,
+ pnode_t pn,
+ UOFFSET * pSPOff,
+ int argn,
+ peval_t pvScr
+ )
+
+/*++
+
+routine description:
+
+ This function deals with assignment of locations on the stack and registers
+ for the THIS CALL calling convention. This calling convention is used for
+ C++ code 32-bit x86 only.
+
+arguments:
+
+ pvF - Supplies the pointer to the function description
+ pn - Supplies a pointer to the argument node in the tree
+ pSPOff - Supplies a pointer to the current SP address
+ argn - Supplies the count of arguements for the function
+ pvScr - Supplies a scratch arguement descriptor.
+
+return value:
+
+ TRUE if no error and FALSE if error
+
+--*/
+
+{
+ return PushCArgs(pvF, pn, pSPOff, argn, pvScr );
+} /* PushTArgs() */
+
+
+/** PushCArgs - setup argument tree for C style calling
+ *
+ * fSuccess = PushCArgs (pvF, pn, pSPOff, argn);
+ *
+ * Entry pvF = pointer to function description
+ * pn = pointer to argument node
+ * pSPOff = pointer to SP relative offset counter
+ * argn = argument number
+ *
+ * Exit type field of node = type of formal argument
+ * type field of node = 0 if vararg
+ * *pSPOff incremented by size of formal or size of actual if vararg
+ *
+ * Returns TRUE if no error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t FASTCALL
+PushCArgs (
+ peval_t pvF,
+ pnode_t pn,
+ UOFFSET *pSPOff,
+ int argn,
+ peval_t pvScr
+ )
+{
+ CV_typ_t type;
+ pargd_t pa;
+ uint cbVal;
+ short argc;
+ farg_t argtype;
+
+ // If C calling convention, push arguments in reverse
+
+ if (NODE_OP (pn) == OP_endofargs) {
+ // set the number of required parameters
+ argc = FCN_PCOUNT (pvF);
+ switch (argtype = GetArgType (pvF, argc, &type)) {
+ case FARG_error:
+ // there is an error in the OMF or the number of arguments
+ // exceeds the number of formals in an exact match list
+ pExState->err_num = ERR_FCNERROR;
+ return (FALSE);
+
+ case FARG_none:
+ // return TRUE if number of actuals is 0
+ return (argn == 0);
+
+ case FARG_vararg:
+ // if the formals count is zero then this can be
+ // either voidargs or varargs. We cannot tell the
+ // difference so we allow either case. If varargs,
+ // then the number of actuals must be at least one
+ // less than the number of formals
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return (TRUE);
+ }
+ else {
+ return (FALSE);
+ }
+
+ case FARG_exact:
+ // varargs are not allowed. Exact match required
+ return (argc == argn);
+ }
+ }
+
+ // recurse to end of actual argument list
+
+ if (!PushCArgs (pvF, pnodeOfbnode(NODE_RCHILD (pn)), pSPOff, argn + 1, pvScr)) {
+ return (FALSE);
+ }
+ else {
+ switch (argtype = GetArgType (pvF, (short) argn, &type)) {
+ case FARG_error:
+ case FARG_none:
+ pExState->err_num = ERR_FCNERROR;
+ return (FALSE);
+
+ case FARG_vararg:
+ case FARG_exact:
+ pa = (pargd_t)&(pn->v[0]);
+ pa->type = type;
+
+ /*
+ * increment relative SP offset by size of item rounded
+ * up to the next word and set address field of OP_arg
+ * node to relative SP offset.
+ */
+
+ SetNodeType (pvScr, pa->type);
+
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ cbVal = (uint)(TypeSize (pvScr) + 3) & ~3;
+ } else {
+ cbVal = (uint)(TypeSize (pvScr) + 1) & ~1;
+ }
+ *pSPOff += (UOFFSET)cbVal;
+ if (EVAL_IS_REF (pvScr)) {
+ pa->flags.ref = TRUE;
+ pa->utype = PTR_UTYPE (pvScr);
+ SetNodeType (pvScr, pa->utype);
+ if (EVAL_IS_CLASS (pvScr)) {
+ pa->flags.utclass = TRUE;
+ }
+ }
+ pa->flags.isreg = FALSE;
+ pa->vallen = cbVal;
+ pa->SPoff = *pSPOff;
+ return (TRUE);
+ }
+ }
+}
+
+
+
+/** PushFArgs - push arguments for fastcall call
+ *
+ * fSuccess = PushFArgs (pvF, pn, pSPOff);
+ *
+ * Entry pvF = pointer to function description
+ * pn = pointer to argument node
+ * pSPOff = pointer to SP relative offset counter
+ *
+ * Exit type field of node = type of formal argument
+ * *pSPOff incremented by size of formal
+ *
+ * Returns TRUE if parameters pushed without error
+ * FALSE if error during push
+ */
+
+
+LOCAL bool_t FASTCALL
+PushFArgs(
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET * pSPOff,
+ peval_t pvScr
+ )
+{
+ ushort regmask = 0;
+ short argn = 0;
+ CV_typ_t type;
+ pargd_t pa;
+ uint cbVal;
+
+ for (; NODE_OP (pnArg) != OP_endofargs;
+ pnArg = pnodeOfbnode(NODE_RCHILD (pnArg))) {
+ switch (GetArgType (pvF, argn, &type)) {
+ case FARG_error:
+ case FARG_vararg:
+ pExState->err_num = ERR_FCNERROR;
+ return (FALSE);
+
+ case FARG_none:
+ return (TRUE);
+
+ case FARG_exact:
+ pa = (pargd_t)&pnArg->v[0];
+ pa->type = type;
+ SetNodeType (pvScr, type);
+ if (!FastCallReg (pa, pvScr, &regmask)) {
+ /*
+ * increment relative SP offset by size of item rounded up
+ * to the next word and set address field of OP_arg node to
+ * relative SP offset.
+ */
+
+ cbVal = (uint)(TypeSize (pvScr) + 1) & ~1;
+ *pSPOff += (UOFFSET)cbVal;
+ pa->flags.isreg = FALSE;
+ pa->vallen = cbVal;
+ pa->SPoff = *pSPOff;
+ }
+ if (EVAL_IS_REF (pvScr)) {
+ pa->flags.ref = TRUE;
+ pa->utype = PTR_UTYPE (pvScr);
+ SetNodeType (pvScr, pa->utype);
+ if (EVAL_IS_CLASS (pvScr)) {
+ pa->flags.utclass = TRUE;
+ }
+ }
+ argn++;
+ }
+ }
+ return (TRUE);
+} /* PushFArgs() */
+
+/** PushPArgs - push arguments for call
+ *
+ * fSuccess = PushPArgs (pvF, pn, pSPOff);
+ *
+ * Entry pvF = pointer to function description
+ * pn = pointer to argument node
+ * pSPOff = pointer to SP relative offset counter
+ *
+ * Exit type field of node = type of formal argument
+ * *pSPOff incremented by size of formal
+ *
+ * Returns TRUE if parameters pushed without error
+ * FALSE if error during push
+ */
+
+
+LOCAL bool_t FASTCALL
+PushPArgs (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ peval_t pvScr
+ )
+{
+ pargd_t pa;
+ short argn = 0;
+ CV_typ_t type;
+ long cbVal;
+
+ // push arguments onto stack left to right
+
+ for (; NODE_OP (pnArg) != OP_endofargs; pnArg = pnodeOfbnode(NODE_RCHILD (pnArg))) {
+ switch (GetArgType (pvF, argn, &type)) {
+ case FARG_error:
+ case FARG_vararg:
+ pExState->err_num = ERR_FCNERROR;
+ return (FALSE);
+
+ case FARG_none:
+ return (TRUE);
+
+ case FARG_exact:
+ pa = (pargd_t)&pnArg->v[0];
+
+ // increment relative SP offset by size of item rounded up to the
+ // next word and set address field of OP_arg node to relative
+ // SP offset.
+
+ pa->type = type;
+ SetNodeType (pvScr, type);
+
+ // increment relative SP offset by size of item rounded up to the
+ // next word and set address field of OP_arg node to relative
+ // SP offset.
+
+ cbVal = (ushort)(TypeSize (pvScr) + 1) & ~1;
+ *pSPOff += (UOFFSET)cbVal;
+ pa->vallen = (ushort)cbVal;
+ pa->SPoff = *pSPOff;
+ pa->flags.isreg = FALSE;
+ if (EVAL_IS_REF (pvScr)) {
+ pa->flags.ref = TRUE;
+ pa->utype = PTR_UTYPE (pvScr);
+ SetNodeType (pvScr, pa->utype);
+ if (EVAL_IS_CLASS (pvScr)) {
+ pa->flags.utclass = TRUE;
+ }
+ }
+ argn++;
+ }
+ }
+ return (TRUE);
+}
+
+
+
+
+/*** FastCallReg - assign fast call parameter to register
+ *
+ * fSuccess = FastCallReg (pa, pv, pmask)
+ *
+ * Entry pa = pointer to argument data
+ * pv = pointer to value
+ * pmask = pointer to allocation mask. *pmask must be
+ * zero on first call
+ *
+ * Exit EVAL_IS_REG (pv) = TRUE if assigned to register
+ * EVAL_REG (pv) = register ordinal if assigned to register
+ * *pmask updated if assigned to register
+ *
+ * Returns TRUE if parameter is passed in register
+ * FALSE if parameter is not passed in register
+ */
+
+
+LOCAL bool_t FASTCALL
+FastCallReg (
+ pargd_t pa,
+ peval_t pv,
+ ushort * mask
+ )
+{
+#define AX_PARAM 0x1
+#define DX_PARAM 0x2
+#define BX_PARAM 0x4
+#define ES_PARAM 0x8
+#define CX_PARAM 0x10
+
+ /*
+ * Two different calling conventions here. 32-bit and 16-bit
+ */
+
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ /*
+ * First parameter goes into EAX, second paramter goes into EDX
+ */
+ pa->vallen = (ushort) TypeSize( pv );
+ if (pa->vallen <= 4) {
+ if (! (*mask & CX_PARAM) ) {
+ *mask |= CX_PARAM;
+ pa->flags.isreg = TRUE;
+ switch( pa->vallen ) {
+ case 1: pa->reg = CV_REG_CL; break;
+ case 2: pa->reg = CV_REG_CX; break;
+ case 3: pa->reg = CV_REG_ECX; break;
+ case 4: pa->reg = CV_REG_ECX; break;
+ }
+ } else if (! (*mask & DX_PARAM) ) {
+ *mask |= DX_PARAM;
+ pa->flags.isreg = TRUE;
+ switch( pa->vallen ) {
+ case 1: pa->reg = CV_REG_DL; break;
+ case 2: pa->reg = CV_REG_DX; break;
+ case 3: pa->reg = CV_REG_EDX; break;
+ case 4: pa->reg = CV_REG_EDX; break;
+ }
+ } else {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ } else {
+
+ if (!SetNodeType (pv, pa->type)) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ pa->vallen = (ushort)TypeSize (pv);
+
+ switch (pa->type) {
+ case T_UCHAR:
+ case T_CHAR:
+ case T_RCHAR:
+ case T_USHORT:
+ case T_SHORT:
+ case T_INT2:
+ case T_UINT2:
+ /*
+ * assign these types to registers ax, dx,bx
+ * note that the character types will use the full register
+ */
+
+ int_order:
+ /*
+ * Allocation order is hard-wired
+ */
+
+ if (!(*mask & AX_PARAM)) {
+ *mask |= AX_PARAM;
+ pa->flags.isreg = TRUE;
+ pa->reg = pa->vallen == 1 ? CV_REG_AL : CV_REG_AX;
+ }
+ else if (!(*mask & DX_PARAM)) {
+ *mask |= DX_PARAM;
+ pa->flags.isreg = TRUE;
+ pa->reg = pa->vallen == 1 ? CV_REG_DL : CV_REG_DX;
+ }
+ else if (!(*mask & BX_PARAM)) {
+ *mask |= BX_PARAM;
+ pa->flags.isreg = TRUE;
+ pa->reg = pa->vallen == 1 ? CV_REG_BL : CV_REG_BX;
+ }
+ else {
+ return (FALSE);
+ }
+ break;
+
+ case T_ULONG:
+ case T_LONG:
+ case T_INT4:
+ case T_UINT4:
+ /*
+ * assign long values to dx:ax
+ */
+
+ if (!(*mask & AX_PARAM) && !(*mask & DX_PARAM)) {
+ *mask |= AX_PARAM | DX_PARAM;
+ pa->flags.isreg = TRUE;
+ pa->reg = (CV_REG_DX << 8) | CV_REG_AX;
+ }
+ else {
+ return (FALSE);
+ }
+ break;
+
+ default:
+ if (EVAL_IS_PTR (pv) && EVAL_IS_NPTR (pv)) {
+ /*
+ * assign short pointers (including references)
+ * to bx, ax, dx. Allocation order is hard-wired
+ */
+
+ if (!(*mask & BX_PARAM)) {
+ *mask |= BX_PARAM;
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_REG_BX;
+ }
+ else {
+ goto int_order; // nasty tail merging of mine
+ }
+ }
+ else if (EVAL_IS_PTR (pv) && EVAL_IS_NPTR32 (pv)) {
+ DASSERT (FALSE); // M00FLAT32
+ }
+ else {
+ //M00KLUDGE - it is assumed that pointers go on the stack
+ return (FALSE);
+ }
+ break;
+ }
+ }
+ return (TRUE);
+} /* FastCallReg() */
+
+#endif // TARGET_i386
+
+
+#ifdef TARGET_MIPS
+
+LOCAL bool_t FASTCALL
+PushMArgs (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ peval_t pvScr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the offsets for a MIPS calling convention routine.
+
+Arguments:
+
+ pvF - Supplies a pointer to the function description
+ pn - Supplies a pointer to the arugment node
+ pSPOff - Supplies pointer to the Stack Pointer relative offset counter
+ this value is updated to reflect pushed parameters
+
+Return Value:
+
+ TRUE if parameters pushed without error else FALSE
+
+--*/
+
+{
+ uint regmask = 0;
+ eval_t evalRet;
+ peval_t pvRet;
+
+
+ /*
+ * Must deal with return type and this parameters before
+ * dealing with anything else.
+ */
+
+ pvRet = &evalRet;
+ *pvRet = *ST;
+ SetNodeType( pvRet, FCN_RETURN(pvRet));
+
+ if (EVAL_IS_METHOD(pvF)) {
+ SET_PARAM_INT(&regmask, 0);
+ }
+
+ if (!EVAL_IS_REF(pvRet) &&
+ !CV_IS_PRIMITIVE(EVAL_TYP(pvRet)) &&
+ (TypeSize(pvRet) > 4) &&
+ (CV_TYPE ( EVAL_TYP (pvRet)) != CV_REAL)) {
+
+ if (IS_PARAM_EMPTY(&regmask, 0)) {
+ SET_PARAM_INT(&regmask, 0);
+ } else {
+ SET_PARAM_INT(&regmask, 1);
+ }
+ }
+
+
+ /*
+ * Now deal with the actual declared parameter list.
+ */
+
+ return PushMArgs2( pvF, pnArg, pSPOff, 0, regmask, pvScr);
+}
+
+
+LOCAL bool_t FASTCALL
+PushMArgs2 (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ int argn,
+ uint regmask,
+ peval_t pvScr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the offsets for a MIPS calling convention routine.
+
+Arguments:
+
+ pvF - Supplies a pointer to the function description
+ pn - Supplies a pointer to the arugment node
+ pSPOff - Supplies pointer to the Stack Pointer relative offset counter
+ this value is updated to reflect pushed parameters
+ argn - Supplies the count of arguments pushed to date
+
+Return Value:
+
+ TRUE if parameters pushed without error else FALSE
+
+--*/
+
+{
+ int argc;
+ CV_typ_t type;
+ pargd_t pa;
+ uint cbVal;
+ int cbR;
+ farg_t argtype;
+ BOOL fReg;
+
+ /*
+ * Arguments are pushed in reverse (C) order
+ */
+
+ if (NODE_OP(pnArg) == OP_endofargs) {
+ /*
+ * Set number of required parameters
+ */
+
+ argc = FCN_PCOUNT( pvF );
+ switch( argtype = GetArgType( pvF, (short) argc, &type ) ) {
+
+ /*
+ * Error in the OMF or the number of arguments
+ * exceeds the number of formals in an exact match list
+ */
+ case FARG_error:
+ pExState->err_num = ERR_FCNERROR;
+ return FALSE;
+
+ /*
+ * return TRUE if number of actuals is 0
+ */
+
+ case FARG_none:
+ *pSPOff = 16;
+ return (argn == 0);
+
+ /*
+ * if the formals count is zero then this can be
+ * either voidargs or varargs. We cannot tell
+ * the difference so we allow either case. If
+ * varargs, then the number of acutals must
+ * be at least one less than the number of formals
+ */
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return TRUE;
+ }
+ return FALSE;
+
+ case FARG_vararg:
+ // if the formals count is zero then this can be
+ // either voidargs or varargs. We cannot tell the
+ // difference so we allow either case. If varargs,
+ // then the number of actuals must be at least one
+ // less than the number of formals
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return (TRUE);
+ }
+ else {
+ return (FALSE);
+ }
+
+ case FARG_exact:
+ if (*pSPOff < 16) {
+ *pSPOff = 16;
+ } else {
+ *pSPOff = (*pSPOff + 8 - 1) & ~(8 - 1);
+ }
+ return (argc == argn);
+ }
+ }
+
+ /*
+ * Need to get the size of the item to be pushed so that we can
+ * do correct alignment of the stack for this data item.
+ */
+
+ switch ( argtype = GetArgType( pvF, (short) argn, &type )) {
+
+ default:
+ DASSERT(FALSE);
+
+ /*
+ * If no type or error then return error
+ */
+ case FARG_error:
+ case FARG_none:
+ pExState->err_num = ERR_FCNERROR;
+ return FALSE;
+
+ case FARG_vararg:
+ case FARG_exact:
+ pa = (pargd_t)&pnArg->v[0];
+ pa->type = type;
+ pa->flags.isreg = FALSE;
+
+ SetNodeType (pvScr, type);
+
+ fReg = MipsCallReg( pa, pvScr, &regmask);
+
+ /*
+ * We always allocate space on the stack for any argument
+ * even if it is placed in a register.
+ */
+
+ /*
+ * To compute location on stack take the size of the
+ * item and round to DWORDS. The stack is then aligned
+ * to this size.
+ *
+ * NOTENOTE??? - I don't know if this is correct for structures.
+ */
+
+
+ cbVal = (uint)(TypeSize(pvScr) + 3) & ~3;
+ cbR = (cbVal > 8) ? 8 : cbVal;
+ *pSPOff = (*pSPOff + cbR - 1 ) & ~(cbR - 1);
+
+ cbR = *pSPOff;
+
+ *pSPOff += cbVal;
+
+ break;
+
+ }
+
+
+ /*
+ * At an actual arguement. Recurse down the list to the end
+ * and then process this argument
+ */
+
+ if (!PushMArgs2( pvF, pnodeOfbnode(NODE_RCHILD (pnArg)), pSPOff,
+ argn+1, regmask, pvScr)) {
+ return FALSE;
+ } else {
+
+ /*
+ * Allocate space on stack (in increments of 4) and
+ * save the offset of the stack for the item. Offsets
+ * are saved backwards (i.e. from the end of the stack) so
+ * we can push them on the stack easier.
+ */
+
+ pa->SPoff = *pSPOff - cbR;
+
+ if (EVAL_IS_REF( pvScr )) {
+ pa->flags.ref = TRUE;
+ pa->utype = PTR_UTYPE ( pvScr );
+ SetNodeType (pvScr, pa->utype );
+ if (EVAL_IS_CLASS (pvScr)) {
+ pa->flags.utclass = TRUE;
+ }
+ }
+ }
+ return (TRUE);
+} /* PushMArgs() */
+
+
+
+
+
+/*** MipsCallReg - assign mips call parameter to register
+ *
+ * fSuccess = MipsCallReg (pa, pv, pmask)
+ *
+ * Entry pa = pointer to argument data
+ * pv = pointer to value
+ * pmask = pointer to allocation mask. *pmask must be
+ * zero on first call
+ *
+ * Exit EVAL_IS_REG (pv) = TRUE if assigned to register
+ * EVAL_REG (pv) = register ordinal if assigned to register
+ * *pmask updated if assigned to register
+ *
+ * Returns TRUE if parameter is passed in register
+ * FALSE if parameter is not passed in register
+ */
+
+LOCAL bool_t FASTCALL
+MipsCallReg (
+ pargd_t pa,
+ peval_t pv,
+ uint *mask
+ )
+{
+
+ if (!SetNodeType (pv, pa->type)) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+ /*
+ * Are there any slots free?
+ */
+
+ pa->vallen = (ushort)TypeSize (pv);
+
+ if (!IS_PARAM_EMPTY(mask, 3)) {
+ return FALSE;
+ }
+
+ /*
+ * Depending on the type we need to allocate something to the
+ * correct set of registers and to void other registers as
+ * appriopirate
+ */
+
+ switch( pa->type ) {
+ /*
+ * These are all assigned to $4, $5, $6, $7 -- which ever
+ * is first available. When a register is used it
+ * is marked as unavailable.
+ */
+
+ default:
+ if (pa->vallen > 4) {
+ break;
+ }
+
+ case T_UCHAR:
+ case T_CHAR:
+ case T_RCHAR:
+ case T_USHORT:
+ case T_SHORT:
+ case T_INT2:
+ case T_UINT2:
+ case T_ULONG:
+ case T_LONG:
+ case T_INT4:
+ case T_UINT4:
+ case T_32PCHAR:
+ case T_32PUCHAR:
+ case T_32PRCHAR:
+ case T_32PWCHAR:
+ case T_32PINT2:
+ case T_32PUINT2:
+ case T_32PSHORT:
+ case T_32PUSHORT:
+ case T_32PINT4:
+ case T_32PUINT4:
+ case T_32PLONG:
+ case T_32PULONG:
+ case T_32PINT8:
+ case T_32PUINT8:
+ case T_32PREAL32:
+ case T_32PREAL48:
+ case T_32PREAL64:
+
+ if (IS_PARAM_EMPTY(mask, 0)) {
+ SET_PARAM_INT(mask, 0);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_IntA0;
+
+ } else if (IS_PARAM_EMPTY(mask, 1)) {
+ SET_PARAM_INT(mask, 1);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_IntA1;
+
+ } else if (IS_PARAM_EMPTY(mask, 2)) {
+ SET_PARAM_INT(mask, 2);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_IntA2;
+
+ } else if (IS_PARAM_EMPTY(mask, 3)) {
+ SET_PARAM_INT(mask, 3);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_IntA3;
+
+ } else {
+ DASSERT(FALSE);
+ return FALSE;
+
+ }
+ return TRUE;
+
+ /*
+ *
+ */
+
+ case T_REAL32:
+
+ if (IS_PARAM_EMPTY(mask, 0)) {
+ SET_PARAM_FLOAT(mask, 0);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_FltF12;
+
+ } else if (IS_PARAM_EMPTY(mask, 1)) {
+ SET_PARAM_FLOAT(mask, 1);
+ pa->flags.isreg = TRUE;
+ if (IS_PARAM_FLOAT(mask, 0)) {
+ pa->reg = CV_M4_FltF14;
+ } else {
+ pa->reg = CV_M4_IntA1;
+ }
+
+ } else if (IS_PARAM_EMPTY(mask, 2)) {
+ SET_PARAM_FLOAT(mask, 2);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_IntA2;
+
+ } else if (IS_PARAM_EMPTY(mask, 3)) {
+ SET_PARAM_FLOAT(mask, 3);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_M4_IntA3;
+ } else {
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+
+ /*
+ *
+ */
+
+ case T_REAL64:
+
+ if (IS_PARAM_EMPTY(mask, 0)) {
+ SET_PARAM_DOUBLE(mask, 0);
+ SET_PARAM_DOUBLE(mask, 1);
+ pa->flags.isreg = TRUE;
+ pa->reg = ( CV_M4_FltF13 << 8 ) | CV_M4_FltF12;
+
+ } else if (IS_PARAM_EMPTY(mask, 2)) {
+ SET_PARAM_DOUBLE(mask, 2);
+ SET_PARAM_DOUBLE(mask, 3);
+ pa->flags.isreg = TRUE;
+
+ if (IS_PARAM_DOUBLE(mask, 0)) {
+ pa->reg = ( CV_M4_FltF15 << 8 ) | CV_M4_FltF14;
+ } else {
+ pa->reg = ( CV_M4_IntA3 << 8) | CV_M4_IntA2;
+ }
+ } else {
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+
+
+ }
+
+ *mask = 0xffffffff;
+ return FALSE;
+} /* MipsCallReg() */
+
+#endif // TARGET_MIPS
+
+#ifdef TARGET_PPC
+
+LOCAL bool_t FASTCALL
+PushPPCArgs (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ peval_t pvScr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the offsets for a PPC calling convention routine.
+
+Arguments:
+
+ pvF - Supplies a pointer to the function description
+ pn - Supplies a pointer to the arugment node
+ pSPOff - Supplies pointer to the Stack Pointer relative offset counter
+ this value is updated to reflect pushed parameters
+
+Return Value:
+
+ TRUE if parameters pushed without error else FALSE
+
+--*/
+
+{
+ uint regmask[3];
+ eval_t evalRet;
+ peval_t pvRet;
+
+ regmask[0] = regmask[1] = regmask[2] = 0;
+
+ /*
+ * Must deal with return type and this parameters before
+ * dealing with anything else.
+ */
+
+ pvRet = &evalRet;
+ *pvRet = *ST;
+ SetNodeType( pvRet, FCN_RETURN(pvRet));
+
+ if (EVAL_IS_METHOD(pvF)) {
+ SET_PARAM_INT(regmask, 0);
+ }
+
+ if (!EVAL_IS_REF(pvRet) &&
+ !CV_IS_PRIMITIVE(EVAL_TYP(pvRet)) &&
+ (TypeSize(pvRet) > 4) &&
+ (CV_TYPE ( EVAL_TYP (pvRet)) != CV_REAL)) {
+
+ if (IS_PARAM_EMPTY(regmask, 0)) {
+ SET_PARAM_INT(regmask, 0);
+ } else {
+ SET_PARAM_INT(regmask, 1);
+ }
+ }
+
+
+ /*
+ * Now deal with the actual declared parameter list.
+ */
+
+ return PushPPCArgs2( pvF, pnArg, pSPOff, 0, regmask, pvScr);
+}
+
+
+LOCAL bool_t FASTCALL
+PushPPCArgs2 (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ int argn,
+ uint *regmask,
+ peval_t pvScr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the offsets for a PPC calling convention routine.
+
+Arguments:
+
+ pvF - Supplies a pointer to the function description
+ pn - Supplies a pointer to the arugment node
+ pSPOff - Supplies pointer to the Stack Pointer relative offset counter
+ this value is updated to reflect pushed parameters
+ argn - Supplies the count of arguments pushed to date
+
+Return Value:
+
+ TRUE if parameters pushed without error else FALSE
+
+--*/
+
+{
+ int argc;
+ CV_typ_t type;
+ pargd_t pa;
+ uint cbVal;
+ int cbR;
+ farg_t argtype;
+ BOOL fReg;
+
+ /*
+ * Arguments are pushed in reverse (C) order
+ */
+
+ if (NODE_OP(pnArg) == OP_endofargs) {
+ /*
+ * Set number of required parameters
+ */
+
+ argc = FCN_PCOUNT( pvF );
+ switch( argtype = GetArgType( pvF, (short) argc, &type ) ) {
+
+ /*
+ * Error in the OMF or the number of arguments
+ * exceeds the number of formals in an exact match list
+ */
+ case FARG_error:
+ pExState->err_num = ERR_FCNERROR;
+ return FALSE;
+
+ /*
+ * return TRUE if number of actuals is 0
+ */
+
+ case FARG_none:
+ *pSPOff = 24;
+ return (argn == 0);
+
+ /*
+ * if the formals count is zero then this can be
+ * either voidargs or varargs. We cannot tell
+ * the difference so we allow either case. If
+ * varargs, then the number of acutals must
+ * be at least one less than the number of formals
+ */
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return TRUE;
+ }
+ return FALSE;
+
+ case FARG_vararg:
+ // I putG_vararg back in because that's what GetArgType
+ // returns if there are no arguments. v-matth
+
+ // if the formals count is zero then this can be
+ // either voidargs or varargs. We cannot tell the
+ // difference so we allow either case. If varargs,
+ // then the number of actuals must be at least one
+ // less than the number of formals
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return (TRUE);
+ }
+ else {
+ return (FALSE);
+ }
+
+ case FARG_exact:
+ *pSPOff = (*pSPOff + 8 - 1) & ~(8 - 1);
+ return (argc == argn);
+ }
+ }
+
+ /*
+ * Need to get the size of the item to be pushed so that we can
+ * do correct alignment of the stack for this data item.
+ */
+
+ switch ( argtype = GetArgType( pvF, (short) argn, &type )) {
+
+ default:
+ DASSERT(FALSE);
+
+ /*
+ * If no type or error then return error
+ */
+ case FARG_error:
+ case FARG_none:
+ pExState->err_num = ERR_FCNERROR;
+ return FALSE;
+
+ case FARG_vararg:
+ case FARG_exact:
+ pa = (pargd_t)&pnArg->v[0];
+ pa->type = type;
+ pa->flags.isreg = FALSE;
+
+ SetNodeType (pvScr, type);
+
+ fReg = PPCCallReg( pa, pvScr, regmask);
+
+ /*
+ * We always allocate space on the stack for any argument
+ * even if it is placed in a register.
+ */
+
+ /*
+ * To compute location on stack take the size of the
+ * item and round to DWORDS. The stack is DWORD aligned.
+ *
+ * NOTENOTE??? - I don't know if this is correct for structures.
+ */
+
+
+ cbVal = (uint)(TypeSize(pvScr) + 3) & ~3;
+ cbR = (cbVal > 8) ? 8 : cbVal;
+ *pSPOff = (*pSPOff + cbR - 1 ) & ~(cbR - 1);
+
+ cbR = *pSPOff;
+ *pSPOff += cbVal;
+
+ break;
+
+ }
+
+
+ /*
+ * At an actual arguement. Recurse down the list to the end
+ * and then process this argument
+ */
+
+ if (!PushPPCArgs2( pvF, pnodeOfbnode(NODE_RCHILD (pnArg)), pSPOff,
+ argn+1, regmask, pvScr)) {
+ return FALSE;
+ } else {
+ DASSERT( ( argtype == FARG_exact ) || ( argtype == FARG_vararg ) );
+
+ /*
+ * Allocate space on stack (in increments of 4) and
+ * save the offset of the stack for the item. Offsets
+ * are saved backwards (i.e. from the end of the stack) so
+ * we can push them on the stack easier.
+ */
+
+ pa->SPoff = *pSPOff - cbR;
+ // A little adjustment for linkage convention. This function
+ // only allocates enough stack for the arguments. We need 24
+ // bytes more. v-matth
+ if( argn == 0 )
+ {
+ pa->SPoff = pa->SPoff + 24;
+ }
+
+ if (EVAL_IS_REF( pvScr )) {
+ pa->flags.ref = TRUE;
+ pa->utype = PTR_UTYPE ( pvScr );
+ SetNodeType (pvScr, pa->utype );
+ if (EVAL_IS_CLASS (pvScr)) {
+ pa->flags.utclass = TRUE;
+ }
+ }
+ }
+ return (TRUE);
+} /* PushPPCArgs2() */
+
+
+
+
+
+/*** PPCCallReg - assign PPC call parameter to register
+ *
+ * fSuccess = PPCCallReg (pa, pv, pmask)
+ *
+ * Entry pa = pointer to argument data
+ * pv = pointer to value
+ * pmask = pointer to allocation mask. *pmask must be
+ * zero on first call
+ *
+ * Exit EVAL_IS_REG (pv) = TRUE if assigned to register
+ * EVAL_REG (pv) = register ordinal if assigned to register
+ * *pmask updated if assigned to register
+ *
+ * Returns TRUE if parameter is passed in register
+ * FALSE if parameter is not passed in register
+ */
+
+LOCAL bool_t FASTCALL
+PPCCallReg (
+ pargd_t pa,
+ peval_t pv,
+ uint *mask
+ )
+{
+ int i, j;
+
+ if (!SetNodeType (pv, pa->type)) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+ pa->vallen = (ushort)TypeSize (pv);
+
+ /*
+ * Depending on the type we need to allocate something to the
+ * correct set of registers and to void other registers as
+ * appriopirate
+ */
+
+ switch( pa->type ) {
+
+ default:
+ if (pa->vallen > 8) {
+ // Here is where we do the "painting across" registers
+ // trick, if we overflow, we spill into memory. FIXME
+ break;
+ }
+
+ case T_UCHAR:
+ case T_CHAR:
+ case T_RCHAR:
+ case T_USHORT:
+ case T_SHORT:
+ case T_INT2:
+ case T_UINT2:
+ case T_ULONG:
+ case T_LONG:
+ case T_INT4:
+ case T_UINT4:
+ case T_32PCHAR:
+ case T_32PUCHAR:
+ case T_32PRCHAR:
+ case T_32PWCHAR:
+ case T_32PINT2:
+ case T_32PUINT2:
+ case T_32PSHORT:
+ case T_32PUSHORT:
+ case T_32PINT4:
+ case T_32PUINT4:
+ case T_32PLONG:
+ case T_32PULONG:
+ case T_32PINT8:
+ case T_32PUINT8:
+ case T_32PREAL32:
+ case T_32PREAL48:
+ case T_32PREAL64:
+
+ if (!IS_PARAM_EMPTY(mask, 7))
+ return FALSE;
+
+ for (i = 0; i < 8; i++)
+ if (IS_PARAM_EMPTY(mask, i)) {
+ SET_PARAM_INT(mask, i);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_PPC_GPR3 + i;
+ break;
+ }
+
+ return TRUE;
+
+ case T_REAL32:
+
+ if (!IS_PARAM_EMPTY(mask, 8+13-1))
+ return FALSE;
+
+ for (i = 8; i < 8+13; i++) {
+ if (IS_PARAM_EMPTY(mask, i)) {
+ SET_PARAM_FLOAT(mask, i);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_PPC_FPR1 + i - 8;
+
+ if (IS_PARAM_EMPTY(mask, 7)) {
+ for (j = 0; j < 8; j++) {
+ if (IS_PARAM_EMPTY(mask, j)) {
+ SET_PARAM_FLOAT(mask, j);
+ pa->reg |= (CV_PPC_GPR3 + j) << 8;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return TRUE;
+
+ case T_REAL64:
+
+ if (!IS_PARAM_EMPTY(mask, 8+13-1))
+ return FALSE;
+
+ for (i = 8; i < 8+13; i++) {
+ if (IS_PARAM_EMPTY(mask, i)) {
+ SET_PARAM_DOUBLE(mask, i);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_PPC_FPR1 + i - 8;
+
+ if (IS_PARAM_EMPTY(mask, 7)) {
+ for (j = 0; j < 8; j+= 2) {
+ if (IS_PARAM_EMPTY(mask, j)) {
+ SET_PARAM_DOUBLE(mask, j);
+ pa->reg |= (CV_PPC_GPR3 + j) << 12;
+ if (j < 7) {
+ SET_PARAM_DOUBLE(mask, j+1);
+ pa->reg |= (CV_PPC_GPR3 + j + 1) << 8;
+ }
+ if (IS_PARAM_EMPTY(mask, j-1)) {
+ SET_PARAM_SKIPPED(mask, j-1);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ mask[0] = mask[1] = mask[2] = 0xffffffff;
+ return FALSE;
+} /* PPCCallReg() */
+
+#endif // TARGET_PPC
+
+
+
+#ifdef TARGET_ALPHA
+
+LOCAL bool_t FASTCALL
+PushAArgs (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ peval_t pvScr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the offsets for a routine using
+ the Alpha calling convention.
+
+Arguments:
+
+ pvF - Supplies a pointer to the function description
+ pn - Supplies a pointer to the arugment node
+ pSPOff - Supplies pointer to the Stack Pointer relative offset counter
+ this value is updated to reflect pushed parameters
+
+Return Value:
+
+ TRUE if parameters pushed without error else FALSE
+
+--*/
+
+{
+ uint regmask = 0;
+ eval_t evalRet;
+ peval_t pvRet;
+
+
+ /*
+ * Must deal with return type and this parameters before
+ * dealing with anything else.
+ */
+
+ pvRet = &evalRet;
+ *pvRet = *ST;
+ SetNodeType( pvRet, FCN_RETURN(pvRet));
+
+ if (EVAL_IS_METHOD(pvF)) {
+ SET_PARAM_INT(&regmask, 0);
+ }
+
+ if (!EVAL_IS_REF(pvRet) &&
+ !CV_IS_PRIMITIVE(EVAL_TYP(pvRet)) &&
+// MBH - bugbug
+// for us, we should check against a size of 8, not 4,
+// but the other quad support is still missing, so leave it be.
+//
+ (TypeSize(pvRet) > 4) &&
+ (CV_TYPE ( EVAL_TYP (pvRet)) != CV_REAL)) {
+
+ if (IS_PARAM_EMPTY(&regmask, 0)) {
+ SET_PARAM_INT(&regmask, 0);
+ } else {
+ SET_PARAM_INT(&regmask, 1);
+ }
+ }
+
+
+ /*
+ * Now deal with the actual declared parameter list.
+ */
+
+ return PushAArgs2( pvF, pnArg, pSPOff, 0, regmask, pvScr);
+}
+
+
+LOCAL bool_t FASTCALL
+PushAArgs2 (
+ peval_t pvF,
+ pnode_t pnArg,
+ UOFFSET *pSPOff,
+ int argn,
+ uint regmask,
+ peval_t pvScr
+ )
+
+/*++
+
+Routine Description:
+
+ Alpha - see PushAArgs, above
+
+Arguments:
+
+ pvF - Supplies a pointer to the function description
+ pn - Supplies a pointer to the arugment node
+ pSPOff - Supplies pointer to the Stack Pointer relative offset counter
+ this value is updated to reflect pushed parameters
+ argn - Supplies the count of arguments pushed to date
+
+Return Value:
+
+ TRUE if parameters pushed without error else FALSE
+
+--*/
+
+{
+ int argc;
+ CV_typ_t type;
+ pargd_t pa;
+ uint cbVal;
+ int cbR = 0;
+ farg_t argtype;
+ BOOL fReg;
+
+ /*
+ * Arguments are pushed in reverse (C) order
+ */
+
+ if (NODE_OP(pnArg) == OP_endofargs) {
+ /*
+ * Set number of required parameters
+ */
+
+ argc = FCN_PCOUNT( pvF );
+ switch( argtype = GetArgType( pvF, (short) argc, &type ) ) {
+
+ /*
+ * Error in the OMF or the number of arguments
+ * exceeds the number of formals in an exact match list
+ */
+ case FARG_error:
+ pExState->err_num = ERR_FCNERROR;
+ return FALSE;
+
+ /*
+ * return TRUE if number of actuals is 0
+ */
+
+ case FARG_none:
+ *pSPOff = 16;
+ return (argn == 0);
+
+ /*
+ * if the formals count is zero then this can be
+ * either voidargs or varargs. We cannot tell
+ * the difference so we allow either case. If
+ * varargs, then the number of acutals must
+ * be at least one less than the number of formals
+ */
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return TRUE;
+ }
+ return FALSE;
+
+ /*
+ * Varargs are not allowed. Exact match required
+ */
+
+ case FARG_vararg:
+ // if the formals count is zero then this can be
+ // either voidargs or varargs. We cannot tell the
+ // difference so we allow either case. If varargs,
+ // then the number of actuals must be at least one
+ // less than the number of formals
+
+ if ((argc == 0) || (argn >= argc - 1)) {
+ return (TRUE);
+ }
+ else {
+ return (FALSE);
+ }
+
+ case FARG_exact:
+ if (*pSPOff < 16) {
+ *pSPOff = 16;
+ } else {
+ *pSPOff = (*pSPOff + 8 - 1) & ~(8 - 1);
+ }
+ return (argc == argn);
+ }
+ }
+
+ /*
+ * Need to get the size of the item to be pushed so that we can
+ * do correct alignment of the stack for this data item.
+ */
+
+ switch ( argtype = GetArgType( pvF, (short) argn, &type )) {
+
+ default:
+ DASSERT(FALSE);
+
+ /*
+ * If no type or error then return error
+ */
+ case FARG_error:
+ case FARG_none:
+ pExState->err_num = ERR_FCNERROR;
+ return FALSE;
+
+ case FARG_vararg:
+ case FARG_exact:
+ pa = (pargd_t)&pnArg->v[0];
+ pa->type = type;
+ pa->flags.isreg = FALSE;
+
+ SetNodeType (pvScr, type);
+
+ fReg = AlphaCallReg( pa, pvScr, &regmask);
+
+ /*
+ * Space is only allocated on the stack for arguments
+ * that aren't in registers. The argument home area
+ * is in the stack space of the callee, so allocating
+ * it here would be double-allocation.
+ */
+
+ /*
+ * To compute location on stack take the size of the
+ * item and round to QUADWORDS. The stack is then aligned
+ * to this size.
+ *
+ * NOTENOTE??? - I don't know if this is correct for structures.
+ */
+
+ if (fReg == FALSE) {
+ cbVal = (uint)(TypeSize(pvScr) + 7) & ~7;
+ cbR = (cbVal > 16) ? 16 : cbVal;
+ *pSPOff = (*pSPOff + cbR - 1 ) & ~(cbR - 1);
+
+ cbR = *pSPOff;
+
+ *pSPOff += cbVal;
+
+ break;
+
+ }
+ }
+
+ /*
+ * At an actual arguement. Recurse down the list to the end
+ * and then process this argument
+ */
+
+ if (!PushAArgs2( pvF, pnodeOfbnode(NODE_RCHILD (pnArg)), pSPOff,
+ argn+1, regmask, pvScr)) {
+ return FALSE;
+ } else {
+ /*
+ * Indicate where on the stack this goes, if it goes anywhere.
+ * If cbR isn't reasonable (ie 0) for Register variables, the
+ * routine evaluation won't work.
+ * They are saved backwards (i.e. from the end of the stack) so
+ * we can push them on the stack easier.
+ */
+
+ pa->SPoff = *pSPOff - cbR;
+
+ if (EVAL_IS_REF( pvScr )) {
+ pa->flags.ref = TRUE;
+ pa->utype = PTR_UTYPE ( pvScr );
+ SetNodeType (pvScr, pa->utype );
+ if (EVAL_IS_CLASS (pvScr)) {
+ pa->flags.utclass = TRUE;
+ }
+ }
+ }
+ return (TRUE);
+} /* PushAArgs2() */
+
+
+
+
+
+/*** AlphaCallReg - assign Alpha call parameter to register
+ *
+ * fSuccess = AlphaCallReg (pa, pv, pmask)
+ *
+ * Entry pa = pointer to argument data
+ * pv = pointer to value
+ * pmask = pointer to allocation mask. *pmask must be
+ * zero on first call
+ *
+ * Exit EVAL_IS_REG (pv) = TRUE if assigned to register
+ * EVAL_REG (pv) = register ordinal if assigned to register
+ * *pmask updated if assigned to register
+ *
+ * Returns TRUE if parameter is passed in register
+ * FALSE if parameter is not passed in register
+ */
+
+LOCAL bool_t FASTCALL
+AlphaCallReg (
+ pargd_t pa,
+ peval_t pv,
+ uint *mask
+ )
+{
+
+ if (!SetNodeType (pv, pa->type)) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+ /*
+ * Are there any slots free?
+ */
+
+ pa->vallen = (ushort)TypeSize (pv);
+
+ if (!IS_PARAM_EMPTY(mask, 5)) {
+ return FALSE;
+ }
+
+ /*
+ * Depending on the type we need to allocate something to the
+ * correct set of registers and to void other registers as
+ * appropriate
+ */
+
+ switch( pa->type ) {
+ /*
+ * These are all assigned to IntA0 - IntA5 -- which ever
+ * is first available. When a register is used it
+ * is marked as unavailable.
+ */
+
+ default:
+ if (pa->vallen > 8) {
+ break;
+ }
+
+ case T_UCHAR:
+ case T_CHAR:
+ case T_RCHAR:
+ case T_USHORT:
+ case T_SHORT:
+ case T_INT2:
+ case T_UINT2:
+ case T_ULONG:
+ case T_LONG:
+ case T_INT4:
+ case T_UINT4:
+ case T_QUAD:
+ case T_UQUAD:
+ case T_INT8:
+ case T_UINT8:
+ case T_32PCHAR:
+ case T_32PUCHAR:
+ case T_32PRCHAR:
+ case T_32PWCHAR:
+ case T_32PINT2:
+ case T_32PUINT2:
+ case T_32PSHORT:
+ case T_32PUSHORT:
+ case T_32PINT4:
+ case T_32PUINT4:
+ case T_32PLONG:
+ case T_32PULONG:
+ case T_32PINT8:
+ case T_32PUINT8:
+ case T_32PREAL32:
+ case T_32PREAL48:
+ case T_32PREAL64:
+
+ if (IS_PARAM_EMPTY(mask, 0)) {
+ SET_PARAM_INT(mask, 0);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_IntA0;
+
+ } else if (IS_PARAM_EMPTY(mask, 1)) {
+ SET_PARAM_INT(mask, 1);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_IntA1;
+
+ } else if (IS_PARAM_EMPTY(mask, 2)) {
+ SET_PARAM_INT(mask, 2);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_IntA2;
+
+ } else if (IS_PARAM_EMPTY(mask, 3)) {
+ SET_PARAM_INT(mask, 3);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_IntA3;
+
+ } else if (IS_PARAM_EMPTY(mask, 4)) {
+ SET_PARAM_INT(mask, 4);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_IntA4;
+
+ } else if (IS_PARAM_EMPTY(mask, 5)) {
+ SET_PARAM_INT(mask, 5);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_IntA5;
+
+ } else {
+ DASSERT(FALSE);
+ return FALSE;
+
+ }
+ return TRUE;
+
+ /*
+ *
+ */
+
+ case T_REAL32:
+
+ if (IS_PARAM_EMPTY(mask, 0)) {
+ SET_PARAM_FLOAT(mask, 0);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF16;
+
+ } else if (IS_PARAM_EMPTY(mask, 1)) {
+ SET_PARAM_FLOAT(mask, 1);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF17;
+
+ } else if (IS_PARAM_EMPTY(mask, 2)) {
+ SET_PARAM_FLOAT(mask, 2);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF18;
+
+ } else if (IS_PARAM_EMPTY(mask, 3)) {
+ SET_PARAM_FLOAT(mask, 3);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF19;
+
+ } else if (IS_PARAM_EMPTY(mask, 4)) {
+ SET_PARAM_FLOAT(mask, 4);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF20;
+
+ } else if (IS_PARAM_EMPTY(mask, 5)) {
+ SET_PARAM_FLOAT(mask, 5);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF21;
+
+ } else {
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+
+ case T_REAL64:
+
+ if (IS_PARAM_EMPTY(mask, 0)) {
+ SET_PARAM_DOUBLE(mask, 0);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF16;
+
+ } else if (IS_PARAM_EMPTY(mask, 1)) {
+ SET_PARAM_DOUBLE(mask, 1);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF17;
+
+ } else if (IS_PARAM_EMPTY(mask, 2)) {
+ SET_PARAM_DOUBLE(mask, 2);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF18;
+
+ } else if (IS_PARAM_EMPTY(mask, 3)) {
+ SET_PARAM_DOUBLE(mask, 3);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF19;
+
+ } else if (IS_PARAM_EMPTY(mask, 4)) {
+ SET_PARAM_DOUBLE(mask, 4);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF20;
+
+ } else if (IS_PARAM_EMPTY(mask, 5)) {
+ SET_PARAM_DOUBLE(mask, 5);
+ pa->flags.isreg = TRUE;
+ pa->reg = CV_ALPHA_FltF21;
+
+ } else {
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+
+ }
+
+ *mask = 0xffffffff;
+ return FALSE;
+} /* MipsCallReg() */
+
+#endif // TARGET_ALPHA
+
+
+struct _OvlMap {
+ op_t op;
+ op_t ovlfcn;
+};
+
+struct _OvlMap BinaryOvlMap[] = {
+ {OP_preinc ,OP_Oincrement },
+ {OP_predec ,OP_Odecrement },
+ {OP_postinc ,OP_Oincrement },
+ {OP_postdec ,OP_Odecrement },
+ {OP_function ,OP_Ofunction },
+ {OP_lbrack ,OP_Oarray },
+ {OP_pmember ,OP_Opmember },
+ {OP_mult ,OP_Ostar },
+ {OP_div ,OP_Odivide },
+ {OP_mod ,OP_Opercent },
+ {OP_plus ,OP_Oplus },
+ {OP_minus ,OP_Ominus },
+ {OP_shl ,OP_Oshl },
+ {OP_shr ,OP_Oshr },
+ {OP_lt ,OP_Oless },
+ {OP_lteq ,OP_Olessequal },
+ {OP_gt ,OP_Ogreater },
+ {OP_gteq ,OP_Ogreatequal },
+ {OP_eqeq ,OP_Oequalequal },
+ {OP_bangeq ,OP_Obangequal },
+ {OP_and ,OP_Oand },
+ {OP_xor ,OP_Oxor },
+ {OP_or ,OP_Oor },
+ {OP_andand ,OP_Oandand },
+ {OP_oror ,OP_Ooror },
+ {OP_eq ,OP_Oequal },
+ {OP_multeq ,OP_Otimesequal },
+ {OP_diveq ,OP_Odivequal },
+ {OP_modeq ,OP_Opcentequal },
+ {OP_pluseq ,OP_Oplusequal },
+ {OP_minuseq ,OP_Ominusequal },
+ {OP_shleq ,OP_Oleftequal },
+ {OP_shreq ,OP_Orightequal },
+ {OP_andeq ,OP_Oandequal },
+ {OP_xoreq ,OP_Oxorequal },
+ {OP_oreq ,OP_Oorequal },
+ {OP_comma ,OP_Ocomma }
+};
+#define BINARYOVLMAPCNT (sizeof (BinaryOvlMap)/sizeof (struct _OvlMap))
+
+
+
+
+
+/** BinaryOverload - process overloaded binary operator
+ *
+ * fSuccess = BinaryOverload (bn)
+ *
+ * Entry bn = based pointer to operator node
+ * STP = pointer to left operand if not function operator
+ * ST = pointer to right operand if not function operator
+ * STP = pointer to argument list if function operator
+ * ST = pointer to class object if function operator
+ *
+ * Exit tree rewritten to function call and bound
+ *
+ * Returns TRUE if tree rewritten and bound correctly
+ * FALSE if error
+ *
+ * Note: If the node operator is post increment or decrement, then
+ * the code below will supply an implicit second argument of
+ * 0;
+ */
+
+
+LOCAL bool_t
+BinaryOverload (
+ bnode_t bn
+ )
+{
+ ushort lenClass;
+ ushort lenGlobal;
+ HDEP hOld = 0;
+ HDEP hClass = 0;
+ HDEP hGlobal = 0;
+ pstree_t pOld = NULL;
+ pstree_t pClass = NULL;
+ pstree_t pGlobal = NULL;
+ bool_t fClass = FALSE;
+ bool_t fGlobal = FALSE;
+ bnode_t Fcn;
+ bnode_t Left;
+ bnode_t LeftRight;
+ bnode_t Arg1;
+ bnode_t Arg2;
+ bnode_t EndArg;
+ bnode_t Zero;
+ eval_t evalSTP = {0};
+ eval_t evalST = {0};
+ eval_t evalClass = {0};
+ eval_t evalGlobal = {0};
+ op_t OldOper = NODE_OP (pnodeOfbnode(bn));
+ op_t Oper;
+ bool_t PostID = FALSE;
+ bool_t RightOp = TRUE;
+ peval_t pv;
+ ushort i;
+
+
+ // search for the overload operator name
+
+ for (i = 0; i < BINARYOVLMAPCNT; i++) {
+ if (BinaryOvlMap[i].op == OldOper) {
+ break;
+ }
+ }
+ if (i == BINARYOVLMAPCNT) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ Oper = BinaryOvlMap[i].ovlfcn;
+
+ lenClass = 3 * (sizeof (node_t) + sizeof (eval_t)) + sizeof (node_t)
+ + sizeof (node_t) + sizeof (argd_t);
+
+ lenGlobal = 2 * (sizeof (node_t) + sizeof (eval_t)) + sizeof (node_t) +
+ 2 * (sizeof (node_t) + sizeof (argd_t));
+
+ if ((OldOper == OP_postinc) || (OldOper == OP_postdec)) {
+ // if we are processing post increment/decrement, then we have to
+ // supply the implicit zero second argument
+
+ PostID = TRUE;
+ RightOp = FALSE;
+ lenClass += sizeof (node_t) + sizeof (eval_t);
+ lenGlobal += sizeof (node_t) + sizeof (eval_t);
+ }
+
+ if ((hClass = DupETree (lenClass, &pClass)) == 0) {
+ return (FALSE);
+ }
+ if ((hGlobal = DupETree (lenGlobal, &pGlobal)) == 0) {
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ return (FALSE);
+ }
+
+ // save and pop the left and right operands
+
+ evalST = *ST;
+ PopStack ();
+ if (RightOp == TRUE) {
+ // if we have class--, class++ or class->, there is only one operand
+ // on the evaluation stack. Otherwise, we have to pop and save the
+ // right operand.
+ evalSTP = *ST;
+ PopStack ();
+ }
+
+ // generate the expression tree for "a.operator@ (b)"
+ // and link it to the current node which is the made into an OP_noop
+
+ hOld = pExState->hETree;
+ pOld = pTree;
+ pExState->hETree = hClass;
+ pTree = pClass;
+
+ Fcn = (bnode_t)pTree->node_next;
+ Left = (bnode_t)((char *)Fcn + sizeof (node_t) + sizeof (eval_t));
+ LeftRight = (bnode_t)((char *)Left + sizeof (node_t) + sizeof (eval_t));
+ Arg1 = (bnode_t)((char *)LeftRight + sizeof (node_t) + sizeof (eval_t));
+ EndArg = (bnode_t)((char *)Arg1 + sizeof (node_t) + sizeof (argd_t));
+ if (PostID == TRUE) {
+ // if we are processing post increment/decrement, then we have to
+ // supply the implicit zero second argument
+
+ Zero = (bnode_t)((char *)EndArg + sizeof (node_t)); // M00BUG? - removal of based
+ NODE_OP (pnodeOfbnode(Zero)) = OP_const;
+ pv = &pnodeOfbnode(Zero)->v[0];
+ EVAL_STATE (pv) = EV_constant;
+ SetNodeType (pv, T_SHORT);
+ EVAL_SHORT (pv) = 0;
+ }
+ pTree->node_next += lenClass;
+ NODE_OP (pnodeOfbnode(Fcn)) = OP_function;
+ NODE_LCHILD (pnodeOfbnode(Fcn)) = Left;
+ NODE_OP (pnodeOfbnode(Left)) = OP_dot;
+ NODE_LCHILD (pnodeOfbnode(Left)) = NODE_LCHILD (pnodeOfbnode(bn));
+ NODE_RCHILD (pnodeOfbnode(Left)) = LeftRight;
+ NODE_OP (pnodeOfbnode(LeftRight)) = Oper;
+ NODE_RCHILD (pnodeOfbnode(Fcn)) = Arg1;
+ NODE_OP (pnodeOfbnode(Arg1)) = OP_arg;
+ if (PostID == TRUE) {
+ NODE_LCHILD (pnodeOfbnode(Arg1)) = Zero;
+ }
+ else {
+ NODE_LCHILD (pnodeOfbnode(Arg1)) = NODE_RCHILD (pnodeOfbnode(bn));
+ }
+ NODE_RCHILD (pnodeOfbnode(Arg1)) = EndArg;
+ NODE_OP (pnodeOfbnode(EndArg)) = OP_endofargs;
+ NODE_LCHILD (pnodeOfbnode(bn)) = Fcn;
+ NODE_RCHILD (pnodeOfbnode(bn)) = 0;
+ NODE_OP (pnodeOfbnode(bn)) = OP_noop;
+
+ // bind method call
+
+ CkPointStack ();
+ if ((fClass = Function (Fcn)) == TRUE) {
+ evalClass = *ST;
+ PopStack ();
+ }
+ if (ResetStack () == FALSE) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+
+ // the expression tree may have been altered during bind
+
+ pClass = pTree;
+ hClass = pExState->hETree;
+ pExState->err_num = ERR_NONE;
+
+ if ((OldOper != OP_function) && (OldOper != OP_eq) &&
+ (OldOper != OP_lbrack)) {
+
+ // generate the expression tree for "operator@ (a, b)"
+ // and link it to the current node which is the made into an OP_noop
+
+ pExState->hETree = hGlobal;
+ pTree = pGlobal;
+
+ Fcn = (bnode_t)pTree->node_next;
+ Left = (bnode_t)((char *)Fcn + sizeof (node_t) + sizeof (eval_t));
+ Arg1 = (bnode_t)((char *)Left + sizeof (node_t) + sizeof (eval_t));
+ Arg2 = (bnode_t)((char *)Arg1 + sizeof (node_t) + sizeof (argd_t));
+ EndArg = (bnode_t)((char *)Arg2 + sizeof (node_t) + sizeof (argd_t));
+ if (PostID == TRUE) {
+ // if we are processing post increment/decrement, then we have to
+ // supply the implicit zero second argument
+
+ Zero = (bnode_t)((char *)EndArg + sizeof (node_t));
+ NODE_OP (pnodeOfbnode(Zero)) = OP_const;
+ pv = &pnodeOfbnode(Zero)->v[0];
+ EVAL_STATE (pv) = EV_constant;
+ SetNodeType (pv, T_SHORT);
+ EVAL_SHORT (pv) = 0;
+ }
+ pTree->node_next += lenGlobal;
+ NODE_OP (pnodeOfbnode(Fcn)) = OP_function;
+ NODE_LCHILD (pnodeOfbnode(Fcn)) = Left;
+ NODE_OP (pnodeOfbnode(Left)) = Oper;
+ NODE_RCHILD (pnodeOfbnode(Fcn)) = Arg1;
+ NODE_OP (pnodeOfbnode(Arg1)) = OP_arg;
+ NODE_LCHILD (pnodeOfbnode(Arg1)) = NODE_LCHILD (pnodeOfbnode(bn));
+ NODE_RCHILD (pnodeOfbnode(Arg1)) = Arg2;
+ NODE_OP (pnodeOfbnode(Arg2)) = OP_arg;
+ if (PostID == TRUE) {
+ NODE_LCHILD (pnodeOfbnode(Arg2)) = Zero;
+ }
+ else {
+ NODE_LCHILD (pnodeOfbnode(Arg2)) = NODE_RCHILD (pnodeOfbnode(bn));
+ }
+ NODE_RCHILD (pnodeOfbnode(Arg2)) = EndArg;
+ NODE_OP (pnodeOfbnode(EndArg)) = OP_endofargs;
+ NODE_LCHILD (pnodeOfbnode(bn)) = Fcn;
+ NODE_RCHILD (pnodeOfbnode(bn)) = 0;
+ NODE_OP (pnodeOfbnode(bn)) = OP_noop;
+
+ // bind function call
+
+ CkPointStack ();
+ if ((fGlobal = Function (Fcn)) == TRUE) {
+ evalGlobal = *ST;
+ PopStack ();
+ }
+ if (ResetStack () == FALSE) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+
+ // the expression tree may have been altered during bind
+
+ pGlobal = pTree;
+ hGlobal = pExState->hETree;
+ pExState->err_num = ERR_NONE;
+ }
+
+ if ((fClass == FALSE) && (fGlobal == FALSE)) {
+ pExState->err_num = ERR_NOOVERLOAD;
+ pExState->hETree = hOld;
+ pTree = pOld;
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ MHMemUnLock (hGlobal);
+ MHMemFree (hGlobal);
+ PushStack (&evalSTP);
+ if (PostID == FALSE) {
+ PushStack (&evalST);
+ }
+ return (FALSE);
+ }
+ else if ((fClass == TRUE) && (fGlobal == TRUE)) {
+ pExState->err_num = ERR_AMBIGUOUS;
+ pExState->hETree = hOld;
+ pTree = pOld;
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ MHMemUnLock (hGlobal);
+ MHMemFree (hGlobal);
+ return (FALSE);
+ }
+ else if (fClass == TRUE) {
+ pExState->hETree = hClass;
+ pTree = pClass;
+ MHMemUnLock (hGlobal);
+ MHMemFree (hGlobal);
+ MHMemUnLock (hOld);
+ MHMemFree (hOld);
+ return (PushStack (&evalClass));
+ }
+ else {
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ MHMemUnLock (hOld);
+ MHMemFree (hOld);
+ return (PushStack (&evalGlobal));
+ }
+}
+
+
+
+
+struct _OvlMap UnaryOvlMap[] = {
+ {OP_bang ,OP_Obang },
+ {OP_tilde ,OP_Otilde },
+ {OP_negate ,OP_Ominus },
+ {OP_uplus ,OP_Oplus },
+ {OP_fetch ,OP_Ostar },
+ {OP_addrof ,OP_Oand },
+};
+#define UNARYOVLMAPCNT (sizeof (UnaryOvlMap)/sizeof (struct _OvlMap))
+
+
+
+
+/** UnaryOverload - process overloaded unary operator
+ *
+ * fSuccess = UnaryOverload (bn)
+ *
+ * Entry bn = based pointer to operator node
+ * ST = pointer to operand (actual operand if pv is reference)
+ *
+ * Exit tree rewritten to function call and bound
+ *
+ * Returns TRUE if tree rewritten and bound correctly
+ * FALSE if error
+ */
+
+
+LOCAL bool_t
+UnaryOverload (
+ bnode_t bn
+ )
+{
+ ushort lenClass;
+ ushort lenGlobal;
+ HDEP hOld = 0;
+ HDEP hClass = 0;
+ HDEP hGlobal = 0;
+ pstree_t pOld = NULL;
+ pstree_t pClass = NULL;
+ pstree_t pGlobal = NULL;
+ bool_t fClass;
+ bool_t fGlobal;
+ bnode_t Fcn;
+ bnode_t Left;
+ bnode_t LeftRight;
+ bnode_t Right;
+ bnode_t RightRight;
+ eval_t evalST = {0};
+ eval_t evalClass = {0};
+ eval_t evalGlobal = {0};
+ op_t Oper = NODE_OP (pnodeOfbnode(bn));
+ ushort i;
+
+ // search for the overload operator name
+
+
+ for (i = 0; i < UNARYOVLMAPCNT; i++) {
+ if (UnaryOvlMap[i].op == Oper) {
+ break;
+ }
+ }
+ if (i == UNARYOVLMAPCNT) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ Oper = UnaryOvlMap[i].ovlfcn;
+
+ // the amount of space required for an overloaded unary method is
+ // OP_function + OP_dot + OP_ident + OP_endofargs
+ // There is actually another node which is the unary operand but we
+ // reuse that (subtree) node
+
+ lenClass = 3 * (sizeof (node_t) + sizeof (eval_t)) + sizeof (node_t);
+
+ // the amount of space required for an overloaded unary global is
+ // OP_function + OP_ident + OP_arg + OP_ident + OP_endofargs
+
+ lenGlobal = 3 * (sizeof (node_t) + sizeof (eval_t)) + sizeof (node_t) +
+ sizeof (node_t) + sizeof (argd_t);
+
+ if ((hClass = DupETree (lenClass, &pClass)) == 0) {
+ return (FALSE);
+ }
+ if ((hGlobal = DupETree (lenGlobal, &pGlobal)) == 0) {
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ return (FALSE);
+ }
+
+ // save and pop the current stack top
+
+ evalST = *ST;
+ PopStack ();
+
+ // generate the expression tree for "a.operator@ ()"
+ // and link it to the current node which is the made into an OP_noop
+
+ hOld = pExState->hETree;
+ pOld = pTree;
+ pExState->hETree = hClass;
+ pTree = pClass;
+
+ Fcn = (bnode_t)pTree->node_next;
+ Left = (bnode_t)((char *)Fcn + sizeof (node_t) + sizeof (eval_t));
+ LeftRight = (bnode_t)((char *)Left + sizeof (node_t) + sizeof (eval_t));
+ Right = (bnode_t)((char *)LeftRight + sizeof (node_t) + sizeof (eval_t));
+ pTree->node_next += lenClass;
+ NODE_OP (pnodeOfbnode(Fcn)) = OP_function;
+ NODE_LCHILD (pnodeOfbnode(Fcn)) = Left;
+ NODE_OP (pnodeOfbnode(Left)) = OP_dot;
+ NODE_LCHILD (pnodeOfbnode(Left)) = NODE_LCHILD (pnodeOfbnode(bn));
+ NODE_RCHILD (pnodeOfbnode(Left)) = LeftRight;
+ NODE_OP (pnodeOfbnode(LeftRight)) = Oper;
+ NODE_RCHILD (pnodeOfbnode(Fcn)) = Right;
+ NODE_OP (pnodeOfbnode(Right)) = OP_endofargs;
+ NODE_LCHILD (pnodeOfbnode(bn)) = Fcn;
+ NODE_RCHILD (pnodeOfbnode(bn)) = 0;
+ NODE_OP (pnodeOfbnode(bn)) = OP_noop;
+
+ // bind method call
+
+ CkPointStack ();
+ if ((fClass = Function (Fcn)) == TRUE) {
+ evalClass = *ST;
+ PopStack ();
+ }
+ if (ResetStack () == FALSE) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+
+ // the expression tree may have been altered during bind
+
+ pClass = pTree;
+ pExState->err_num = ERR_NONE;
+
+ // generate the expression tree for "operator@ (a)"
+ // and link it to the current node which is the made into an OP_noop
+
+ pExState->hETree = hGlobal;
+ pTree = pGlobal;
+
+ Fcn = (bnode_t)pTree->node_next;
+ Left = (bnode_t)((char *)Fcn + sizeof (node_t) + sizeof (eval_t));
+ Right = (bnode_t)((char *)Left + sizeof (node_t) + sizeof (eval_t));
+ RightRight = (bnode_t)((char *)Right + sizeof (node_t) + sizeof (argd_t));
+ pTree->node_next += lenGlobal;
+ NODE_OP (pnodeOfbnode(Fcn)) = OP_function;
+ NODE_LCHILD (pnodeOfbnode(Fcn)) = Left;
+ NODE_OP (pnodeOfbnode(Left)) = Oper;
+ NODE_RCHILD (pnodeOfbnode(Fcn)) = Right;
+ NODE_OP (pnodeOfbnode(Right)) = OP_arg;
+ NODE_LCHILD (pnodeOfbnode(Right)) = NODE_LCHILD (pnodeOfbnode(bn));
+ NODE_RCHILD (pnodeOfbnode(Right)) = RightRight;
+ NODE_OP (pnodeOfbnode(RightRight)) = OP_endofargs;
+ NODE_LCHILD (pnodeOfbnode(bn)) = Fcn;
+ NODE_RCHILD (pnodeOfbnode(bn)) = 0;
+ NODE_OP (pnodeOfbnode(bn)) = OP_noop;
+
+ // bind function call
+
+ CkPointStack ();
+ if ((fGlobal = Function (Fcn)) == TRUE) {
+ evalGlobal = *ST;
+ PopStack ();
+ }
+ if (ResetStack () == FALSE) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+
+ // the expression tree may have been altered during bind
+
+ pGlobal = pTree;
+ pExState->err_num = ERR_NONE;
+
+ if ((fClass == FALSE) && (fGlobal == FALSE)) {
+ pExState->err_num = ERR_NOOVERLOAD;
+ pExState->hETree = hOld;
+ pTree = pOld;
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ MHMemUnLock (hGlobal);
+ MHMemFree (hGlobal);
+ PushStack (&evalST);
+ return (FALSE);
+ }
+ else if ((fClass == TRUE) && (fGlobal == TRUE)) {
+ pExState->err_num = ERR_AMBIGUOUS;
+ pExState->hETree = hOld;
+ pTree = pOld;
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ MHMemUnLock (hGlobal);
+ MHMemFree (hGlobal);
+ return (FALSE);
+ }
+ else if (fClass == TRUE) {
+ pExState->hETree = hClass;
+ pTree = pClass;
+ MHMemUnLock (hGlobal);
+ MHMemFree (hGlobal);
+ MHMemUnLock (hOld);
+ MHMemFree (hOld);
+ return (PushStack (&evalClass));
+ }
+ else {
+ MHMemUnLock (hClass);
+ MHMemFree (hClass);
+ MHMemUnLock (hOld);
+ MHMemFree (hOld);
+ return (PushStack (&evalGlobal));
+ }
+}
+
+
+
+
+/** PointsToOverload - process overloaded -> operator
+ *
+ * fSuccess = PointsToOverload (bn)
+ *
+ * Entry bn = based pointer to operator node
+ * ST = pointer to operand (actual operand if pv is reference)
+ *
+ * Exit tree rewritten to function call and bound
+ *
+ * Returns TRUE if tree rewritten and bound correctly
+ * FALSE if error
+ */
+
+
+LOCAL bool_t
+PointsToOverload (
+ bnode_t bn
+ )
+{
+ pExState->err_num = ERR_OVLPOINTSTO;
+ return (FALSE);
+}
+
+
+
+
+/** DupETree - Duplicate Expression Tree
+ *
+ * hNew = DupETree (count, ppTree)
+ *
+ * Entry count = number of free bytes required in new expression tree
+ * ppTree = pointer to expression tree address
+ *
+ * Exit Current expression tree duplicated
+ * ppTree = address of locked expression tree
+ * additional memory cleared
+ *
+ * Returns 0 if expression tree not duplicated
+ * memory handle if expression tree duplicated
+ */
+
+LOCAL HDEP
+DupETree (
+ ushort count,
+ pstree_t *ppTree
+ )
+{
+ HDEP hNew;
+
+ // copy syntax tree
+
+ if ((hNew = MHMemAllocate (pTree->node_next + count)) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (hNew);
+ }
+ *ppTree = (pstree_t)MHMemLock (hNew);
+ memcpy (*ppTree, pTree, pTree->node_next);
+ (*ppTree)->size = pTree->node_next + count;
+ memset ((char *)*ppTree + (*ppTree)->node_next, 0, count);
+ return (hNew);
+}
+
+
+
+
+/** Type and context parsing
+ *
+ */
+
+
+
+/** FcnCast - check to see if function call is a functional style cast
+ *
+ * fSuccess = FcnCast (bn)
+ *
+ * Entry bn = based pointer to OP_function node which has exactly
+ * one argument node.
+ *
+ * Exit the OP_function node is changed to an OP_cast node
+ *
+ * Returns TRUE if the "function name" is a primitive type or a UDT
+ * and the tree was rewritten as an OP_cast
+ * FALSE if the function is not a cast node
+ */
+
+
+LOCAL bool_t FASTCALL
+FcnCast (
+ bnode_t bn
+ )
+{
+ peval_t pv;
+ bnode_t bnLeft = NODE_LCHILD (pnodeOfbnode(bn));
+
+ // Check for casting a class to anything, not having a symbol or
+ // the symbol not being a type
+
+ if (EVAL_IS_CLASS (ST)) {
+ pExState->err_num = ERR_CONSTRUCTOR;
+ return (FALSE);
+ }
+ if (EVAL_IS_BITF (STP)) {
+ // change the type of the node to the underlying type
+ EVAL_TYP (STP) = BITF_UTYPE (STP);
+ }
+ NODE_OP (pnodeOfbnode(bn)) = OP_cast;
+ NODE_RCHILD (pnodeOfbnode(bn)) = NODE_LCHILD (pnodeOfbnode(NODE_RCHILD (pnodeOfbnode(bn))));
+
+ // copy the base type node up to the cast node and then try to find a
+ // way to cast the stack to to the base type
+
+ pv = (peval_t)&pnodeOfbnode(bnLeft)->v[0];
+ PopStack ();
+ if (CastPtrToPtr (bn) == TRUE) {
+ // the desired type is a base class so we can just set the node type.
+ // the value portion of bn contains the data to cast right to left
+
+ return (SetNodeType (ST, EVAL_TYP (pv)));
+ }
+ else {
+ return (CastNode (ST, EVAL_TYP (pv), PTR_UTYPE (pv)));
+ }
+}
+
+
+
+
+/** GetID - get identifier length from string
+ *
+ * len = GetID (pb)
+ *
+ * Entry pb = pointer to string
+ *
+ * Exit none
+ *
+ * Returns length of next token
+ * if *pb is a digit, len = 0
+ */
+
+
+LOCAL uchar FASTCALL
+GetID (
+ char *pb
+ )
+{
+ char *start = pb;
+ char c = *pb++;
+
+ if (isdigit (c))
+ return (0);
+ if ((c == '*') || (c == '&'))
+ return (1);
+ while (iscsym(c) || c == '$' || c == '@') {
+ c = *pb++;
+ }
+ /* return length of string */
+ return ((uchar)(pb - start - 1));
+}
+
+
+
+/** ParseType - parse a type string
+ *
+ * fSuccess = ParseType (bn)
+ *
+ * Entry bn = based pointer to node referencing "(typestring)"
+ *
+ * Exit
+ *
+ * Returns TRUE if valid type string
+ * FALSE if error in type string
+ */
+
+
+LOCAL bool_t FASTCALL
+ParseType (
+ bnode_t bn
+ )
+{
+ pnode_t pn = pnodeOfbnode(bn);
+ char *pb;
+ char *pbEnd;
+ peval_t pv;
+ bool_t cmpflag;
+ uchar len;
+ ulong mask = 0;
+ CV_typ_t type = 0;
+ ushort mode = 0;
+ ushort btype = 0;
+ ushort size = 0;
+ struct typrec *p;
+ eval_t evalT = {0};
+ peval_t pvT = &evalT;
+ CV_modifier_t Mod = {0};
+ bool_t searchmask;
+ MTYP_t retval;
+
+ pb = pExStr + EVAL_ITOK (&pn->v[0]);
+ pbEnd = pb + EVAL_CBTOK (&pn->v[0]);
+ if (*pb == '(') {
+ pb++;
+ pbEnd--;
+ }
+ pv = &pn->v[0];
+ EVAL_TYPDEF (pv) = 0;
+ for (;;) {
+ while (isspace (*pb))
+ ++pb;
+ if (pb >= pbEnd) {
+ // end of type string
+ break;
+ }
+ if (*pb == 0) {
+ goto typebad;
+ }
+ len = GetID (pb);
+ if ((cmpflag = len) == 0) {
+ goto typebad;
+ }
+ else {
+ for (p = Predef; p->token[0] != 0; p++) {
+ if ((p->token[0] == len) &&
+ ((cmpflag = strncmp ((char *)&p->token[1], pb, len)) == 0)) {
+ break;
+ }
+ }
+ if (cmpflag == 0) {
+ // a predefined token was encountered
+ mask |= p->flags;
+ }
+ else {
+ if (((mask & TY_UDT) != 0) ||
+ !FindUDT (bn, pvT, pExStr, pb, len)) {
+ // we either already have a UDT or we could not
+ // find this one
+ goto typebad;
+ }
+ else {
+ type = EVAL_TYP (pvT);
+ mask |= TY_UDT;
+ }
+ }
+ // skip to end of token and continue
+ pb += len;
+ }
+ }
+
+ // check error conditions At this point we are checking obvious errors
+ // such as a user defined type without a type index, multiple pointer modes,
+ // no valid type specifiers, mixed arithmetic types
+
+ if (mask == 0) {
+ // no type specifiers found
+ goto typebad;
+ }
+ if (mask & TY_REF) {
+ //M00KLUDGE - what about int&
+ if (mask & TY_PTR) {
+ goto typebad;
+ }
+ }
+ switch (mask & TY_PTR) {
+ case TY_POINTER:
+ // set ambiant model from compile flag symbol
+ switch (SetAmbiant (TRUE)) {
+ default:
+ case CV_PTR_NEAR:
+ mask |= TY_NEAR;
+ mode = CV_TM_NPTR;
+ break;
+
+ case CV_PTR_FAR:
+ mask |= TY_FAR;
+ mode = CV_TM_FPTR;
+ break;
+
+ case CV_PTR_NEAR32:
+ mask |= TY_NEAR;
+ mode = CV_TM_NPTR32;
+ break;
+
+ case CV_PTR_FAR32:
+ mask |= TY_FAR;
+ mode = CV_TM_FPTR32;
+ break;
+
+ case CV_PTR_HUGE:
+ mask |= TY_HUGE;
+ mode = CV_TM_HPTR;
+ break;
+ }
+ break;
+
+ case TY_POINTER | TY_NEAR:
+ mode = CV_TM_NPTR;
+ break;
+
+ case TY_POINTER | TY_FAR:
+ mode = CV_TM_FPTR;
+ break;
+
+ case TY_POINTER | TY_HUGE:
+ mode = CV_TM_HPTR;
+ break;
+
+ case 0:
+ mode = CV_TM_DIRECT;
+ break;
+
+ default:
+ // pointer mode conflict
+ goto typebad;
+ }
+ switch (mask & (TY_AGGR | TY_UDT)) {
+ case TY_UDT:
+ case TY_UDT | TY_CLASS:
+ case TY_UDT | TY_STRUCT:
+ case TY_UDT | TY_UNION:
+ case 0:
+ break;
+
+ default:
+ // conflict in aggregrate type
+ goto typebad;
+ }
+ if (((mask & TY_REAL) != 0) && ((mask & TY_NOTREAL) != 0)) {
+ // real type specified with conflicting modifiers
+ goto typebad;
+ }
+ if (((mask & TY_UDT) != 0) && ((mask & TY_ARITH) != 0)) {
+ // user defined type and arithmetic type specified
+ goto typebad;
+ }
+ if ((mask & TY_SIGN) == TY_SIGN) {
+ // both sign modifers specified
+ goto typebad;
+ }
+
+ if ((mask & TY_UDT) != 0) {
+ // user defined type specified
+
+ *pv = *pvT;
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pvT))) {
+ // if the user defined type is an alias for a primitive type
+ // set the pointer mode bits into the type
+
+ type |= (mode << CV_MSHIFT);
+ }
+ else {
+ if ((mask & (TY_PTR | TY_REF)) == 0) {
+ // the UDT was not modified to a pointer or reference
+ type = EVAL_TYP (pvT);
+ }
+ else {
+ // the UDT was modified to a pointer. try to find the
+ // correct pointer type
+
+ if ((mask & TY_CONST) == TY_CONST) {
+ Mod.MOD_const = TRUE;
+ }
+ else if ((mask & TY_VOLATILE) == TY_VOLATILE) {
+ Mod.MOD_volatile = TRUE;
+ }
+ ProtoPtr (pvT, pv, ((mask & TY_REF) == TY_REF), Mod);
+ switch (mask & TY_PTR) {
+ case TY_POINTER:
+ // set ambiant model from compile flag symbol
+ EVAL_PTRTYPE (pvT) = (uchar)SetAmbiant (TRUE);
+ break;
+
+ case TY_POINTER | TY_NEAR:
+ if (mode == CV_TM_NPTR32) {
+ EVAL_PTRTYPE (pvT) = CV_PTR_NEAR32;
+ } else {
+ EVAL_PTRTYPE (pvT) = CV_PTR_NEAR;
+ }
+ break;
+
+ case TY_POINTER | TY_FAR:
+ EVAL_PTRTYPE (pvT) = CV_PTR_FAR;
+ break;
+
+ case TY_POINTER | TY_HUGE:
+ EVAL_PTRTYPE (pvT) = CV_PTR_HUGE;
+ break;
+ }
+ searchmask = ((mask & TY_CONST) == TRUE) ||
+ ((mask & TY_VOLATILE) == TRUE);
+
+ if (searchmask == FALSE) {
+ retval = MatchType (pvT, FALSE);
+ }
+ else {
+ retval = MatchType (pvT, TRUE);
+ }
+ switch (retval) {
+ case MTYP_exact:
+ case MTYP_inexact:
+ // searching the context of the class type for
+ // a type record which is a pointer record and
+ // has the current type as its underlying type
+ // has succeeded
+
+ type = EVAL_TYP (pvT);
+ break;
+
+ case MTYP_none:
+ // fake out the caster by using a created pointer
+ switch (mask & TY_PTR) {
+ case TY_POINTER:
+ type = T_FCVPTR;
+ break;
+
+ case TY_POINTER | TY_NEAR:
+ type = T_NCVPTR;
+ break;
+
+ case TY_POINTER | TY_FAR:
+ type = T_FCVPTR;
+ break;
+
+ case TY_POINTER | TY_HUGE:
+ type = T_HCVPTR;
+ break;
+
+ default:
+ goto typebad;
+ }
+ break;
+ }
+ }
+ }
+ }
+ else {
+ // type must be primitive or a pointer to a primitive type
+
+ if (!BuildType (&type, &mask, &mode, &btype, &size)) {
+ goto typebad;
+ }
+ if ((mask & (TY_REF | TY_CONST | TY_VOLATILE)) != 0) {
+ // the primitive type was modified to a const, volatile or
+ // reference. We will need to search for a type record that
+ // has the primitive type as the underlying type
+
+ SetNodeType (pv, type);
+ EVAL_MOD (pv) = SHHMODFrompCXT (pCxt);
+ *pvT = *pv;
+ if ((mask & TY_REF) != 0) {
+ ProtoPtr (pvT, pv, ((mask & TY_REF) == TY_REF), Mod);
+ switch (mask & TY_PTR) {
+ case TY_POINTER:
+ // set ambiant model from compile flag symbol
+ EVAL_PTRTYPE (pvT) = (uchar)SetAmbiant (TRUE);
+ break;
+
+ case TY_POINTER | TY_NEAR:
+ EVAL_PTRTYPE (pvT) = CV_PTR_NEAR;
+ break;
+
+ case TY_POINTER | TY_FAR:
+ EVAL_PTRTYPE (pvT) = CV_PTR_FAR;
+ break;
+
+ case TY_POINTER | TY_HUGE:
+ EVAL_PTRTYPE (pvT) = CV_PTR_HUGE;
+ break;
+ }
+ }
+ else if ((mask & TY_CONST) == TY_CONST) {
+ EVAL_IS_CONST (pvT) = TRUE;
+ searchmask = TRUE;
+ }
+ else if ((mask & TY_VOLATILE) == TY_VOLATILE) {
+ EVAL_IS_VOLATILE (pvT) = TRUE;
+ searchmask = TRUE;
+ }
+ if (searchmask == FALSE) {
+ retval = MatchType (pvT, FALSE);
+ }
+ else {
+ retval = MatchType (pvT, TRUE);
+ }
+ switch (retval) {
+ case MTYP_exact:
+ case MTYP_inexact:
+ // searching the context of the class type for
+ // a type record which is a pointer record and
+ // has the current type as its underlying type
+ // has succeeded
+
+ type = EVAL_TYP (pvT);
+ break;
+
+ case MTYP_none:
+ goto typebad;
+ }
+ }
+ }
+ EVAL_STATE (pv) = EV_type;
+ return (SetNodeType (pv, type));
+
+
+typebad:
+ // If not "(type-name)"
+ pExState->err_num = ERR_TYPECAST;
+ return (FALSE);
+
+}
+
+
+
+
+
+LOCAL bool_t FASTCALL
+BuildType (
+ CV_typ_t *type,
+ ulong *mask,
+ ushort *mode,
+ ushort *btype,
+ ushort *size
+ )
+{
+
+ // type must be primitive or a pointer to a primitive type
+
+ if (((*mask & TY_VOID) == 0) &&
+ ((*mask & (TY_REAL | TY_INTEGRAL)) == 0)) {
+ // no type specified so set default to the int of the moment.
+ *mask |= (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? TY_LONG : TY_SHORT);
+ }
+ if ((*mask & TY_REAL) != 0) {
+ *btype = CV_REAL;
+ switch (*mask & (TY_REAL | TY_LONG)) {
+ case TY_FLOAT:
+ *size = CV_RC_REAL32;
+ break;
+
+ case TY_DOUBLE:
+ *size = CV_RC_REAL64;
+ break;
+
+ case TY_DOUBLE | TY_LONG:
+#if defined( LONG_DOUBLE_80 )
+ *size = CV_RC_REAL80;
+#endif
+#if defined( LONG_DOUBLE_64 )
+ *size = CV_RC_REAL64;
+#endif
+ break;
+
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ }
+ else if ((*mask & TY_INTEGRAL) != 0) {
+ if (*mask & TY_INT) {
+ *btype = CV_INT;
+ // user specified int possibly along with sign and size
+ switch (*mask & (TY_SIGN | TY_SHORT | TY_LONG)) {
+ case 0:
+ case TY_SIGNED:
+ //
+ *size = (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) ? CV_RI_INT4 : CV_RI_INT2;
+ break;
+
+ case TY_SHORT:
+ case TY_SHORT | TY_SIGNED:
+ // set default integral types to signed two byte int
+ *size = CV_RI_INT2;
+ break;
+
+ case TY_UNSIGNED:
+ *size = (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) ? CV_RI_UINT4 : CV_RI_UINT2;
+ break;
+
+ case TY_SHORT | TY_UNSIGNED:
+ // set default integral types to signed two byte int
+ *size = CV_RI_UINT2;
+ break;
+
+ case TY_LONG:
+ case TY_LONG | TY_SIGNED:
+ // set default integral types to signed two byte int
+ *size = CV_RI_INT4;
+ break;
+
+ case TY_LONG | TY_UNSIGNED:
+ // set default integral types to signed two byte int
+ *size = CV_RI_UINT4;
+ break;
+
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ }
+ else if ((*mask & TY_CHAR) != 0) {
+ // user specified a character type
+
+ switch (*mask & TY_SIGN) {
+ case 0:
+ // if no sign was specified, we are looking for a
+ // real character
+
+ *btype = CV_INT;
+ *size = CV_RI_CHAR;
+ break;
+
+ case TY_SIGNED:
+ *btype = CV_SIGNED;
+ *size = CV_IN_1BYTE;
+ break;
+
+ case TY_UNSIGNED:
+ *btype = CV_UNSIGNED;
+ *size = CV_IN_1BYTE;
+ break;
+ }
+ }
+ else {
+ switch (*mask & TY_SIGN) {
+ case 0:
+ // set default integral types to signed
+ *mask |= TY_SIGNED;
+ case TY_SIGNED:
+ *btype = CV_SIGNED;
+ break;
+
+ case TY_UNSIGNED:
+ *btype = CV_UNSIGNED;
+ break;
+ }
+ switch (*mask & TY_INTEGRAL) {
+ case TY_CHAR:
+ *size = CV_IN_1BYTE;
+ break;
+
+ case TY_SHORT:
+ *size = CV_IN_2BYTE;
+ break;
+
+ case TY_LONG:
+ *size = CV_IN_4BYTE;
+ break;
+ }
+ }
+
+ }
+ else if ((*mask & TY_VOID) != 0) {
+ if (*mask & (TY_ARITH | TY_REAL | TY_AGGR | TY_SIGN) != 0) {
+ return (FALSE);
+ }
+ *btype = CV_SPECIAL;
+ *size = CV_SP_VOID;
+ }
+ else {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+ *type = (*mode << CV_MSHIFT) | (*btype << CV_TSHIFT) | (*size << CV_SSHIFT);
+ return (TRUE);
+}
+
+
+
+
+/** FindUDT - find user defined type
+ *
+ * fSuccess = FindUDT (bn, pv, pStr, pb, len)
+ *
+ * Entry pv = pointer to evaluation node
+ * pStr = pointer to beginning of input string
+ * pb = pointer to structure name
+ * len = length of name
+ *
+ * Exit EVAL_TYP (pv) = type index
+ *
+ * Returns TRUE if UDT found
+ * FALSE if error
+ *
+ * Looks in the current module only.
+ */
+
+
+LOCAL bool_t
+FindUDT (
+ bnode_t bn,
+ peval_t pv,
+ char *pStr,
+ char *pb,
+ uchar len
+ )
+{
+ search_t Name;
+
+ EVAL_TYP (pv) = 0;
+ EVAL_ITOK (pv) = pb - pStr;
+ EVAL_CBTOK (pv) = len;
+
+ // M00SYMBOL - need to allow for T::U::V::type
+
+ InitSearchSym (bn, pv, &Name, 0, SCP_all, CLS_enumerate | CLS_ntype);
+ // modify search to look only for UDTs
+
+ Name.sstr.searchmask = SSTR_symboltype;
+ Name.sstr.symtype = S_UDT;
+ switch (SearchSym (&Name)) {
+ case HR_notfound:
+ break;
+
+ case HR_found:
+ // if the symbol was found, it was pushed onto the stack
+ PopStack ();
+ if (EVAL_STATE (pv) == EV_type) {
+ return (TRUE);
+ }
+ break;
+
+ case HR_rewrite:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ return (FALSE);
+}
+
+
+
+LOCAL bool_t FASTCALL
+ContextToken(
+ char * * ppStr,
+ char * * ppTok,
+ short * pcTok
+ )
+/*++
+
+Routine Description:
+
+ This function will parse a string looking for the next legal item
+ in a context token. These are defined as strings delimiated by
+ either commas or right brackets in which the number of parentheses
+ is balanced.
+
+Arguments:
+
+ ppStr - Supplies a pointer to the string to be parsed
+ ppTok - Returns a pointer to the start of the context token
+ pcTok - Returns the number of characters in the token
+
+Return Value:
+
+ TRUE if a token was successfully found, and FALSE on error
+
+--*/
+
+{
+ int cParenOpen = 0;
+ short pdepth = 0;
+ char ch;
+ int cchTok;
+ char * pStr = *ppStr;
+
+ /*
+ * Skip leading white space
+ */
+
+ while (iswspace(*pStr)) {
+ pStr++;
+ }
+
+ /*
+ * If at the end of the context specifier then return -1 for the
+ * character count to indicate that the token does not exist
+ */
+
+ if (*pStr == '}') {
+ *pcTok = -1;
+ *ppStr = pStr;
+ return (TRUE);
+ }
+
+ /*
+ * Start scaning over the token string. Balance all parentheses
+ * so that we get the entire expression. Check for a paren
+ * off the front since we don't care to look at it.
+ */
+
+ cchTok = 0;
+ while (*pStr == '(') {
+ cParenOpen += 1;
+ pStr++;
+ pdepth += 1;
+ }
+ *ppTok = pStr;
+#ifdef DBCS
+ while ((ch = *pStr, (pStr = CharNext(pStr)), ch) != 0) {
+ /*
+ * increment count of characters in token
+ */
+ cchTok += pStr - CharPrev(*ppTok,pStr);
+#else
+ while ((ch = *pStr++) != 0) {
+ /*
+ * increment count of characters in token
+ */
+
+ cchTok += 1;
+#endif
+ switch (ch) {
+ /*
+ * increment parentheses depth
+ */
+
+ case '(':
+ pdepth++;
+ break;
+
+ /*
+ * Decrement parentheses depth -- checking for overflow
+ */
+
+ case ')':
+ if (--pdepth < 0) {
+ return (FALSE);
+ } else if (pdepth == 0) {
+ if (cParenOpen) {
+ /*
+ * for a parentheses enclosed string, adjust count and
+ * skip blanks to either , or } that terminates the
+ * token. Any other character is an error
+ */
+
+ cParenOpen -= 1;
+ cchTok -= 1;
+
+ /*
+ * Make sure that all of the openning parens
+ * are accounted for
+ */
+
+ while (cParenOpen) {
+ while (iswspace(*pStr)) {
+ pStr++;
+ }
+ if (*pStr != ')') {
+ *pcTok = cchTok;
+ *ppStr = pStr;
+ return FALSE;
+ }
+ cParenOpen -= 1;
+ }
+
+ /*
+ * Skip over any more white space and the next character
+ * must be either a comma or a close bracket to mark
+ * the end of this token.
+ */
+
+ while (iswspace(*pStr)) {
+ pStr++;
+ }
+
+ switch (*pStr) {
+ case ',':
+ /*
+ * skip over the , terminating the token
+ */
+ pStr++;
+
+ case '}':
+ *pcTok = cchTok;
+ *ppStr = pStr;
+ return (TRUE);
+
+ default:
+ *pcTok = cchTok;
+ *ppStr = pStr;
+ return (FALSE);
+ }
+ }
+ }
+ break;
+
+ default:
+ if (pdepth > 0) {
+ /*
+ * any character inside parentheses is ignored
+ */
+ break;
+ }
+ /*
+ * decrement character count of token and reset pointer to }
+ * so next scan will find it
+ */
+
+ else if (ch == '}') {
+ pStr -= 1;
+ cchTok -= 1;
+ *pcTok = cchTok;
+ *ppStr = pStr;
+ return (TRUE);
+ }
+ /*
+ * decrement character count of token but leave pointer past comma
+ * so next scan will find following token
+ */
+
+ else if (ch == ',') {
+ cchTok -= 1;
+ *pcTok = cchTok;
+ *ppStr = pStr;
+ return (TRUE);
+ }
+ break;
+ }
+ }
+ *pcTok = cchTok;
+ *ppStr = pStr;
+ return (FALSE);
+} /* ContextToken() */
+
+
+
+
+
+/** InitSearchSym - initialize symbol search
+ *
+ * InitSearchSym (bn, pName, iClass, scope, clsmask)
+ *
+ * Entry bn = based pointer to node of symbol
+ * pName = pointer to symbol search structure
+ * iClass = initial class if explicit class reference
+ * scope = mask describing scope of search
+ * clsmask = mask describing permitted class elements
+ *
+ * Exit search structure initialized for SearchSym
+ *
+ * Returns pointer to search symbol structure
+ */
+
+
+void
+InitSearchSym (
+ bnode_t bn,
+ peval_t pv,
+ psearch_t pName,
+ CV_typ_t iClass,
+ ushort scope,
+ ushort clsmask
+ )
+{
+ op_t op = NODE_OP (pnodeOfbnode(bn));
+
+ // set starting context for symbol search to current context
+
+ memset (pName, 0, sizeof (*pName));
+ pName->initializer = INIT_sym;
+ pName->pfnCmp = FNCMP;
+ pName->pv = pv;
+ pName->scope = scope;
+ pName->clsmask = clsmask;
+ pName->CXTT = *pCxt;
+ pName->bn = bn;
+ pName->bnOp = 0;
+
+ // set pointer to symbol name
+
+ if ((op >= OP_this) && (op <= OP_Odelete)) {
+ pName->sstr.lpName = (uchar *)&OpName[op - OP_this].str[1];
+ pName->sstr.cb = OpName[op - OP_this].str[0];
+ }
+ else {
+ pName->sstr.lpName = (uchar *)pExStr + EVAL_ITOK (pv);
+ pName->sstr.cb = EVAL_CBTOK (pv);
+ }
+ pName->state = SYM_init;
+ if ((pName->ExpClass = iClass) != 0) {
+ // restrict searching to class scope
+ pName->scope &= SCP_class;
+ }
+}
+
+
+
+
+/** InitSearchRight - initialize right symbol search
+ *
+ * InitSearchRight (bnOp, bn, pName, clsmask)
+ *
+ * Entry bnOp = based pointer to node of operator
+ * bn = based pointer to node of symbol
+ * pName = pointer to symbol search structure
+ * iClass = initial class if explicit class reference
+ * scope = mask describing scope of search
+ * clsmask = mask describing permitted class elements
+ *
+ * Exit search structure initialized for SearchSym
+ *
+ * Returns pointer to search symbol structure
+ */
+
+
+void
+InitSearchRight (
+ bnode_t bnOp,
+ bnode_t bn,
+ psearch_t pName,
+ ushort clsmask
+ )
+{
+ peval_t pv = &pnodeOfbnode(bn)->v[0];
+ pnode_t pn = pnodeOfbnode(bn);
+ op_t op = NODE_OP (pnodeOfbnode(bn));
+
+ // set starting context for symbol search to current context
+
+ memset (pName, 0, sizeof (*pName));
+ pName->initializer = INIT_right;
+ pName->pfnCmp = FNCMP;
+ pName->pv = pv;
+ pName->scope = SCP_class;
+ pName->clsmask = clsmask;
+ pName->CXTT = pn->pcxf ? pn->pcxf->cxt : *pCxt;
+ pName->bn = bn;
+ pName->bnOp = bnOp;
+
+ // set pointer to symbol name
+ if ((op >= OP_this) && (op <= OP_Odelete)) {
+ pName->sstr.lpName = (uchar *)&OpName[op - OP_this].str[1];
+ pName->sstr.cb = OpName[op - OP_this].str[0];
+ }
+ else {
+ pName->sstr.lpName = (uchar *)pExStr + EVAL_ITOK (pv);
+ pName->sstr.cb = EVAL_CBTOK (pv);
+ }
+ pName->state = SYM_init;
+ // restrict searching to class scope
+ pName->ExpClass = ClassExp;
+ pName->scope = SCP_class;
+}
diff --git a/private/windbg/eecan/debdef.h b/private/windbg/eecan/debdef.h
new file mode 100644
index 000000000..bb8b24152
--- /dev/null
+++ b/private/windbg/eecan/debdef.h
@@ -0,0 +1,115 @@
+#include "types.h"
+#include "cvtypes.hxx"
+
+#ifndef FAR
+#ifdef WIN32
+#define FAR
+#else
+#define FAR _far
+#endif
+#endif
+
+#ifdef WIN32
+typedef unsigned short _segment;
+#define _loadds
+#endif
+
+
+typedef uint bool_t;
+
+
+//NOTENOTE a-kentf endian bias
+#ifndef HIBYTE
+#define HIBYTE(a) (*(((unsigned char FAR *) &(a)) + 1))
+#define LOBYTE(a) (*((unsigned char FAR *) &(a)))
+#endif
+
+
+
+
+// these typedefs define the pointers to the cvinfo.h structures
+
+typedef TYPTYPE FAR *TYPPTR;
+typedef lfEasy FAR *plfEasy;
+typedef lfModifier FAR *plfModifier;
+typedef lfPointer FAR *plfPointer;
+typedef lfArray FAR *plfArray;
+typedef lfClass FAR *plfClass;
+typedef lfStructure FAR *plfStructure;
+typedef lfUnion FAR *plfUnion;
+typedef lfEnum FAR *plfEnum;
+typedef lfProc FAR *plfProc;
+typedef lfMFunc FAR *plfMFunc;
+typedef lfVTShape FAR *plfVTShape;
+typedef lfCobol0 FAR *plfCobol0;
+typedef lfCobol1 FAR *plfCobol1;
+typedef lfBArray FAR *plfBArray;
+typedef lfDimArray FAR *plfDimArray;
+typedef lfVFTPath FAR *plfVFTPath;
+typedef lfLabel FAR *plfLabel;
+typedef lfSkip FAR *plfSkip;
+typedef lfArgList FAR *plfArgList;
+typedef lfDerived FAR *plfDerived;
+typedef lfDefArg FAR *plfDefArg;
+typedef lfList FAR *plfList;
+typedef lfFieldList FAR *plfFieldList;
+typedef mlMethod FAR *pmlMethod;
+typedef lfMethodList FAR *plfMethodList;
+typedef lfBitfield FAR *plfBitfield;
+typedef lfDimCon FAR *plfDimCon;
+typedef lfDimVar FAR *plfDimVar;
+typedef lfRefSym FAR *plfRefSym;
+typedef lfChar FAR *plfChar;
+typedef lfShort FAR *plfShort;
+typedef lfUShort FAR *plfUShort;
+typedef lfLong FAR *plfLong;
+typedef lfULong FAR *plfULong;
+typedef lfReal32 FAR *plfReal32;
+typedef lfReal48 FAR *plfReal48;
+typedef lfReal64 FAR *plfReal64;
+typedef lfReal80 FAR *plfReal80;
+typedef lfReal128 FAR *plfReal128;
+typedef lfIndex FAR *plfIndex;
+typedef lfIndex FAR *nplfIndex;
+typedef lfBClass FAR *plfBClass;
+typedef lfVBClass FAR *plfVBClass;
+typedef lfFriendCls FAR *plfFriendCls;
+typedef lfFriendFcn FAR *plfFriendFcn;
+typedef lfMember FAR *plfMember;
+typedef lfSTMember FAR *plfSTMember;
+typedef lfVFuncTab FAR *plfVFuncTab;
+typedef lfMethod FAR *plfMethod;
+typedef lfEnumerate FAR *plfEnumerate;
+typedef lfNestType FAR *plfNestType;
+
+typedef SYMTYPE FAR *SYMPTR;
+typedef CFLAGSYM FAR *CFLAGPTR;
+typedef CONSTSYM FAR *CONSTPTR;
+typedef REGSYM FAR *REGPTR;
+typedef UDTSYM FAR *UDTPTR;
+typedef SEARCHSYM FAR *SEARCHPTR;
+typedef BLOCKSYM16 FAR *BLOCKPTR16;
+typedef DATASYM16 FAR *DATAPTR16;
+typedef PUBSYM16 FAR *PUBPTR16;
+typedef LABELSYM16 FAR *LABELPTR16;
+typedef BPRELSYM16 FAR *BPRELPTR16;
+typedef PROCSYM16 FAR *PROCPTR16;
+typedef THUNKSYM16 FAR *THUNKPTR16;
+typedef CEXMSYM16 FAR *CEXMPTR16;
+typedef VPATHSYM16 FAR *VPATHPTR16;
+typedef WITHSYM16 FAR *WITHPTR16;
+
+typedef BLOCKSYM32 FAR *BLOCKPTR32;
+typedef DATASYM32 FAR *DATAPTR32;
+typedef PUBSYM32 FAR *PUBPTR32;
+typedef LABELSYM32 FAR *LABELPTR32;
+typedef BPRELSYM32 FAR *BPRELPTR32;
+typedef PROCSYM32 FAR *PROCPTR32;
+typedef THUNKSYM32 FAR *THUNKPTR32;
+typedef WITHSYM32 FAR *WITHPTR32;
+typedef VPATHSYM32 FAR *VPATHPTR32;
+
+typedef BLOCKSYM FAR *BLOCKPTR;
+typedef PROCSYM FAR *PROCPTR;
+typedef THUNKSYM FAR *THUNKPTR;
+typedef WITHSYM FAR *WITHPTR;
diff --git a/private/windbg/eecan/deberr.c b/private/windbg/eecan/deberr.c
new file mode 100644
index 000000000..8271294dc
--- /dev/null
+++ b/private/windbg/eecan/deberr.c
@@ -0,0 +1,83 @@
+#ifdef MIPS_C
+static char * message[] = {
+#define ERRDAT(name, mes) mes,
+};
+#else
+#ifdef WIN32
+#define ERRDAT(name, mes) static char S##name[] = mes;
+#else
+#define ERRDAT(name, mes) static char _based(_segname("_CODE")) S##name[] = mes;
+#endif
+#include "errors.h"
+#undef ERRDAT
+
+#ifdef WIN32
+static char * message[] = {
+#else
+static char _based(_segname("_CODE")) *_based(_segname("_CODE")) message[] = {
+#endif
+#define ERRDAT(name, mes) S##name,
+#include "errors.h"
+#undef ERRDAT
+};
+#endif
+
+ushort PASCAL GetErrorText (PHTM phTM, EESTATUS Status, PEEHSTR phError)
+{
+ UINT len;
+ ushort err_num;
+ ushort buflen;
+ char FAR *pBuf;
+ char Tempbuf[4];
+ int cnt;
+
+ if ((*phTM == 0) || (Status != EEGENERAL)) {
+ *phError = 0;
+ return (EECATASTROPHIC);
+ }
+ if ((*phError = MHMemAllocate (ERRSTRMAX)) == 0) {
+ return (EENOMEMORY);
+ }
+ else {
+ buflen = ERRSTRMAX - 1;
+ pBuf = MHMemLock (*phError);
+ _fmemset (pBuf, 0, buflen);
+ DASSERT( pExState == NULL );
+ pExState = MHMemLock (*phTM);
+ if ((err_num = pExState->err_num) != 0) {
+ if (err_num >= ERR_MAX) {
+ DASSERT (FALSE);
+ }
+ else {
+ //DASSERT (message[err_num].num == err_num);
+ len = _fstrlen (message[err_num]);
+ len = (UINT) min (len, (UINT)buflen);
+ _itoa (err_num, Tempbuf, 10);
+ cnt = 7 - (short)_fstrlen (Tempbuf);
+#if defined(C_ONLY)
+ _fmemcpy (pBuf, "CAN000", cnt);
+#else
+ _fmemcpy (pBuf, "CXX000", cnt);
+#endif
+ pBuf += cnt;
+ _fmemcpy (pBuf, Tempbuf, _fstrlen (Tempbuf));
+ pBuf +=_fstrlen(Tempbuf);
+ _fmemcpy (pBuf, ": Error: ", 10);
+ pBuf += 9;
+ _fstrncpy (pBuf, message[err_num], len);
+ *(pBuf + len) = 0;
+ }
+ } else {
+#if defined(C_ONLY)
+ _fstrcpy (pBuf, "CAN000");
+#else
+ _fstrcpy (pBuf, "CXX000");
+#endif
+ _fstrcat (pBuf, " Error: Unknown error");
+ }
+ MHMemUnLock (*phError);
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ return (EENOERROR);
+ }
+}
diff --git a/private/windbg/eecan/debeval.c b/private/windbg/eecan/debeval.c
new file mode 100644
index 000000000..1293c75eb
--- /dev/null
+++ b/private/windbg/eecan/debeval.c
@@ -0,0 +1,5441 @@
+/*** DEBEVAL.C - Expression evaluator main routines
+ *
+ *
+ */
+
+// Return values from Logical ().
+
+#define DL_DEBERR 1 // Error occurred, DebErr is set
+#define DL_SUCCESS 2 // Evaluation successful
+#define DL_CONTINUE 3 // Inconclusive, continue evaluation
+
+
+// Actions to be taken by EvalUtil().
+
+#define EU_LOAD 0x0001 // Load node values
+#define EU_TYPE 0x0002 // Do implicit type coercion
+
+
+
+
+LOCAL uint NEAR PASCAL Logical (op_t, bool_t);
+
+LOCAL bool_t NEAR FASTCALL CalcThisExpr (CV_typ_t, OFFSET, OFFSET, CV_typ_t);
+LOCAL bool_t NEAR PASCAL DerefVBPtr (CV_typ_t);
+LOCAL bool_t NEAR FASTCALL Eval (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalAddrOf (bnode_t);
+LOCAL bool_t NEAR FASTCALL AddrOf (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalArray (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalAssign (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalBang (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalBasePtr (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalBinary (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalBScope (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalByteOps (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalCast (bnode_t);
+LOCAL bool_t NEAR FASTCALL CastST (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalCastBin (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalContext (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalDMember (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalDot (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalError (register bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalFetch (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalFunction (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalFuncIdent (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalLChild (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalLogical (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalRChild (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalPlusMinus (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalPMember (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalPostIncDec (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalPreIncDec (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalPointsTo (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalPushNode (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalRelat (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalSegOp (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalThisInit (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalThisConst (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalThisExpr (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalUnary (bnode_t);
+LOCAL bool_t NEAR FASTCALL EvalUScope (bnode_t);
+
+LOCAL bool_t NEAR FASTCALL Arith (op_t);
+LOCAL bool_t NEAR FASTCALL Assign (op_t);
+LOCAL bool_t NEAR FASTCALL EvalUtil (op_t, peval_t, peval_t, ushort);
+LOCAL bool_t NEAR FASTCALL FetchOp (peval_t pv);
+LOCAL bool_t NEAR FASTCALL InitConst (long);
+LOCAL bool_t NEAR FASTCALL PlusMinus (op_t);
+LOCAL bool_t NEAR FASTCALL PrePost (op_t);
+LOCAL bool_t NEAR FASTCALL Relational (op_t);
+LOCAL bool_t NEAR FASTCALL SBitField (void);
+LOCAL bool_t NEAR FASTCALL StructEval (bnode_t);
+LOCAL bool_t NEAR FASTCALL StructElem (bnode_t);
+LOCAL bool_t NEAR PASCAL ThisOffset (peval_t);
+LOCAL bool_t NEAR FASTCALL Unary (op_t);
+LOCAL bool_t NEAR PASCAL PushArgs (pnode_t, SHREG FAR *, UOFFSET FAR*);
+LOCAL bool_t NEAR PASCAL PushOffset (UOFFSET, SHREG FAR *, UOFFSET FAR *, uint);
+LOCAL bool_t NEAR PASCAL PushString (peval_t, SHREG FAR *, CV_typ_t);
+LOCAL bool_t NEAR PASCAL PushRef (peval_t, SHREG FAR *, CV_typ_t);
+LOCAL bool_t NEAR PASCAL PushUserValue (peval_t, pargd_t, SHREG FAR *, UOFFSET FAR *);
+LOCAL bool_t NEAR PASCAL StoreC (peval_t);
+LOCAL bool_t NEAR PASCAL StoreP (void);
+LOCAL bool_t NEAR PASCAL StoreF (void);
+LOCAL bool_t NEAR PASCAL StorePPC (peval_t);
+LOCAL bool_t NEAR PASCAL StoreMips (peval_t);
+LOCAL bool_t NEAR PASCAL StoreAlpha (peval_t);
+LOCAL bool_t NEAR PASCAL VFuncAddress (peval_t, ulong);
+
+
+eval_t ThisAddress;
+const peval_t pvThis = &ThisAddress;
+
+
+
+// Bind dispatch table
+
+#ifdef WIN32
+LOCAL bool_t (NEAR FASTCALL *pEval[]) (bnode_t) = {
+#else
+LOCAL bool_t (NEAR FASTCALL *_based(_segname("_CODE"))pEval[]) (bnode_t) = {
+#endif
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk) opeval,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+
+
+LOCAL bool_t NEAR FASTCALL EvalError (register bnode_t bn)
+{
+ Unreferenced(bn);
+
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+}
+
+
+LOCAL bool_t NEAR FASTCALL Eval (bnode_t bn)
+{
+ return ((*pEval[NODE_OP(pnodeOfbnode(bn))])(bn));
+}
+
+LOCAL bool_t NEAR FASTCALL EvalLChild (bnode_t bn)
+{
+ register bnode_t bnL = NODE_LCHILD (pnodeOfbnode(bn));
+
+ return ((*pEval[NODE_OP(pnodeOfbnode(bnL))])(bnL));
+}
+
+LOCAL bool_t NEAR FASTCALL EvalRChild (bnode_t bn)
+{
+ register bnode_t bnR = NODE_RCHILD (pnodeOfbnode(bn));
+
+ return ((*pEval[NODE_OP(pnodeOfbnode(bnR))])(bnR));
+}
+
+
+
+
+
+/*** DoEval - Evaluate parse tree
+ *
+ * SYNOPSIS
+ * error = DoEval ()
+ *
+ * ENTRY
+ * none
+ *
+ * RETURNS
+ * True if tree evaluated without error.
+ *
+ * DESCRIPTION
+ * The parser will call this routine to evaluate the parse tree
+ *
+ * NOTES
+ */
+
+
+EESTATUS PASCAL DoEval (PHTM phTM, PFRAME pFrame, EEDSP style)
+{
+ EESTATUS retval = EEGENERAL;
+ bool_t evalstate;
+
+ // lock the expression state structure, save the formatting style
+ // and frame
+
+ DASSERT (*phTM != 0);
+ if (*phTM == 0) {
+ return (EECATASTROPHIC);
+ }
+ DASSERT(pExState == NULL );
+ pExState = MHMemLock (*phTM);
+ pExState->style = style;
+ pExState->frame = *pFrame;
+ pCxt = &pExState->cxt;
+
+ //DASSERT (pExState->state.parse_ok == TRUE);
+ //DASSERT (pExState->state.bind_ok == TRUE);
+ //DASSERT (pExState->hSTree != 0);
+
+ if ((pExState->state.parse_ok == TRUE)
+ && (pExState->state.bind_ok == TRUE)) {
+ pTree = MHMemLock (pExState->hETree);
+ DASSERT (hEStack != 0);
+ pEStack = MHMemLock (hEStack);
+ StackMax = 0;
+ StackCkPoint = 0;
+ StackOffset = 0;
+ pExState->err_num = 0;
+ ST = NULL;
+ STP = NULL;
+ pExStr = MHMemLock (pExState->hExStr);
+
+ // zero out type of ThisAddress so that users can check to see if
+ // ThisAddress has been correctly initialized
+
+ bnCxt = 0;
+ EVAL_TYP (pvThis) = 0;
+ Evaluating = TRUE;
+ evalstate = Eval ((bnode_t)pTree->start_node);
+ Evaluating = FALSE;
+ bnCxt = 0;
+ MHMemUnLock (pExState->hExStr);
+
+ // If the input consisted of a single identifier (i.e., no
+ // operators involved), then the resulting value may still
+ // be an identifier. Look it up in the symbols.
+
+ if (evalstate == TRUE) {
+ pExState->result = *ST;
+ pExState->state.eval_ok = TRUE;
+ retval = EENOERROR;
+ }
+ else {
+ retval = EEGENERAL;
+ }
+ MHMemUnLock (hEStack);
+ MHMemUnLock (pExState->hETree);
+ } else {
+ if(!pExState->err_num) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ }
+ }
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ return (retval);
+}
+
+
+LOCAL bool_t NEAR FASTCALL EvalPushNode (bnode_t bn)
+{
+ bool_t Ok;
+ Ok = PushStack(&pnodeOfbnode(bn)->v[0]);
+
+ if ( Ok && EVAL_IS_CURPC( ST ) ) {
+
+ //
+ // Get current PC
+ //
+ SYGetAddr( &(EVAL_PTR( ST )), adrPC);
+ EVAL_IS_ADDR( ST ) = TRUE;
+ EVAL_IS_BPREL( ST ) = FALSE;
+ EVAL_IS_REGREL( ST ) = FALSE;
+ EVAL_IS_TLSREL( ST ) = FALSE;
+ }
+
+ return Ok;
+}
+
+
+
+
+
+/** EvalUnary - perform a unary arithmetic operation
+ *
+ * fSuccess = EvalUnary (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ * DESCRIPTION
+ * Evaluates the result of an arithmetic operation. The unary operators
+ * dealt with here are:
+ *
+ * ~ - +
+ *
+ * Pointer arithmetic is NOT handled; all operands must be of
+ * arithmetic type.
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalUnary (bnode_t bn)
+{
+ if (EvalLChild (bn)) {
+ return (Unary (NODE_OP (pnodeOfbnode(bn))));
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalBasePtr - Perform a based pointer access (:>)
+ *
+ * fSuccess = EvalBasePtr (bnRight)
+ *
+ * Entry bnRight = based pointer to right operand node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalBasePtr (bnode_t bn)
+{
+ return (EvalSegOp (bn));
+}
+
+
+
+
+/** EvalBinary - evaluate a binary arithmetic operation
+ *
+ * fSuccess = EvalBinary (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalBinary (bnode_t bn)
+{
+ if (EvalLChild (bn) && EvalRChild (bn)) {
+ return (Arith (NODE_OP (pnodeOfbnode(bn))));
+ }
+ return (FALSE);
+}
+
+
+
+
+LOCAL bool_t NEAR FASTCALL EvalCastBin (bnode_t bn)
+{
+
+ bool_t f = FALSE;
+
+
+ if ( EvalLChild(bn) && EvalRChild (bn)) {
+ switch( (NODE_OP (pnodeOfbnode(bn)) ) ) {
+
+ case OP_caststar:
+ f = (FetchOp(ST));
+ break;
+
+ case OP_castplus:
+ f = Unary(OP_uplus);
+ break;
+
+ case OP_castminus:
+ f = Unary(OP_negate);
+ break;
+
+ case OP_castamp:
+ f = AddrOf( NODE_RCHILD(pnodeOfbnode(bn)) );
+ break;
+ }
+
+ if ( f ) {
+
+ f = CastST( bn );
+
+ *STP = *ST;
+ PopStack ();
+ }
+ }
+
+ return f;
+}
+
+
+
+
+
+
+/*** EvalPlusMinus - Evaluate binary plus or minus
+ *
+ * fSuccess = EvalPlusMinus (bn)
+ *
+ * Entry bn = based pointer to tree node
+ *
+ * Exit ST = STP +- ST
+ *
+ * Returns TRUE if Eval successful
+ * FALSE if Eval error
+ *
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalPlusMinus (bnode_t bn)
+{
+ if (EvalLChild (bn) && EvalRChild (bn)) {
+ return (PlusMinus (NODE_OP (pnodeOfbnode(bn))));
+ }
+ return (FALSE);
+}
+
+
+
+
+
+
+/*** EvalDot - Perform the dot ('.') operation
+ *
+ * fSuccess = EvalDot (bn)
+ *
+ * Entry bn = based pointer to tree node
+ *
+ * Exit NODE_STYPE (bn) = type of stack top
+ *
+ * Returns TRUE if Eval successful
+ * FALSE if Eval error
+ *
+ * Exit pExState->err_num = error ordinal if Eval error
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalDot (bnode_t bn)
+{
+ if (!EvalLChild (bn)) {
+ return (FALSE);
+ }
+ if (EVAL_STATE (ST) == EV_rvalue) {
+ return (StructElem (bn));
+ }
+ else {
+ return (StructEval (bn));
+ }
+}
+
+
+/** EvalLogical - Handle '&&' and '||' operators
+ *
+ * wStatus = EvalLogical (bn)
+ *
+ * Entry op = Operand (OP_andand or OP_oror)
+ * REval = FALSE if right hand not evaluated
+ * ST = left hand value
+ * REval = TRUE if right hand evaluated
+ * STP = left hand value
+ * ST = right hand value
+ *
+ * Returns wStatus = evaluation status
+ * (REval = TRUE)
+ * DL_DEBERR Evaluation failed, DebErr is set
+ * DL_SUCCESS Evaluation succeeded, result in ST
+ *
+ * (REVAL == FALSE)
+ * DL_DEBERR Evaluation failed,
+ * DL_SUCCESS Evaluation succeeded, result in ST
+ * DL_CONTINUE Evaluation inconclusive, must evaluate right node
+ *
+ * DESCRIPTION
+ * If (REval = TRUE), checks that both operands (STP and ST) are of scalar
+ * type and evaluates the result (0 or 1).
+ *
+ * If (REval == FALSE), checks that the left operand (ST) is of scalar
+ * type and determines whether evaluation of the right operand is
+ * necessary.
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalLogical (bnode_t bn)
+{
+ uint wStatus;
+
+ if (!EvalLChild (bn)) {
+ return (FALSE);
+ }
+ wStatus = Logical (NODE_OP (pnodeOfbnode(bn)), FALSE);
+ if (wStatus == DL_DEBERR) {
+ return(FALSE);
+ }
+ else if (wStatus == DL_SUCCESS) {
+ // Do not evaluate rhs
+ return (TRUE);
+ }
+
+ //DASSERT (wStatus == DL_CONTINUE);
+
+ if (!EvalRChild (bn)) {
+ return (FALSE);
+ }
+ return (Logical (NODE_OP (pnodeOfbnode(bn)), TRUE) == DL_SUCCESS);
+}
+
+
+/** Logical - Handle '&&' and '||' operators
+ *
+ * wStatus = Logical (op, REval)
+ *
+ * Entry op = Operand (OP_andand or OP_oror)
+ * REval = FALSE if right hand not evaluated
+ * ST = left hand value
+ * REval = TRUE if right hand evaluated
+ * STP = left hand value
+ * ST = right hand value
+ *
+ * Returns wStatus = evaluation status
+ * (REval = TRUE)
+ * DL_DEBERR Evaluation failed, DebErr is set
+ * DL_SUCCESS Evaluation succeeded, result in ST
+ *
+ * (REVAL == FALSE)
+ * DL_DEBERR Evaluation failed,
+ * DL_SUCCESS Evaluation succeeded, result in ST
+ * DL_CONTINUE Evaluation inconclusive, must evaluate right node
+ *
+ * DESCRIPTION
+ * If (REval = TRUE), checks that both operands (STP and ST) are of scalar
+ * type and evaluates the result (0 or 1).
+ *
+ * If (REval == FALSE), checks that the left operand (ST) is of scalar
+ * type and determines whether evaluation of the right operand is
+ * necessary.
+ *
+ */
+
+
+LOCAL uint NEAR PASCAL Logical (op_t op, bool_t REval)
+{
+ int result;
+ bool_t fIsZeroL;
+ bool_t fIsZeroR;
+
+ // Evaluate the result. We push a constant node with value of
+ // zero so we can compare against it (i.e., expr1 && expr2 is
+ // equivalent to (expr1 != 0) && (expr2 != 0)).
+ // Evaluate whether the left node is zero.
+
+ if (REval == FALSE) {
+ if (!PushStack (ST) || !InitConst (0)) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ if (!Relational (OP_eqeq))
+ return (DL_DEBERR);
+
+ //DASSERT (EVAL_TYP (ST) == T_SHORT);
+
+ fIsZeroL = (EVAL_SHORT (ST) == 1);
+
+ // remove left hand comparison
+
+ PopStack ();
+ result = (op == OP_oror);
+ EVAL_STATE (ST) = EV_rvalue;
+ EVAL_SHORT (ST) = (short) result;
+ SetNodeType (ST, T_SHORT);
+ if (
+ ((op == OP_andand) && (!fIsZeroL))
+ ||
+ ((op == OP_oror) && (fIsZeroL))
+ ) {
+ return(DL_CONTINUE);
+ }
+ else {
+ return (DL_SUCCESS);
+ }
+ }
+ else {
+ if (!PushStack (ST) || !InitConst (0)) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ if (!Relational (OP_eqeq))
+ return (DL_DEBERR);
+
+ //DASSERT (EVAL_TYP(ST) == T_SHORT);
+
+ fIsZeroR = (EVAL_SHORT (ST) == 1);
+ PopStack ();
+ fIsZeroL = (EVAL_SHORT (STP) == 1);
+
+ // Finally, determine whether or not we have a result, and if so,
+ // what the result is:
+
+ if (
+ ((op == OP_andand) && ((!fIsZeroL) && (!fIsZeroR)))
+ ||
+ ((op == OP_oror) && ((!fIsZeroL) || (!fIsZeroR)))
+ )
+ result = 1;
+ else
+ result = 0;
+ }
+ EVAL_STATE (STP) = EV_rvalue;
+ EVAL_SHORT (STP) = (short) result;
+ SetNodeType (STP, T_SHORT);
+ PopStack ();
+ return (DL_SUCCESS);
+}
+
+
+
+
+
+/*** EvalContext - evaluate the context operator
+ *
+ * fSuccess = EvalContext (bn)
+ *
+ *
+ * Exit ST = address node
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * The stack top value (ST) is set to the address of the
+ * stack top operand
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalContext (bnode_t bn)
+{
+ PCXT oldCxt;
+ bool_t error;
+ bnode_t oldbnCxt;
+ FRAME oldFrame;
+
+ // Set the new context for evaluation of the remainder of this
+ // part of the tree
+
+ oldCxt = pCxt;
+ oldbnCxt = bnCxt;
+ pCxt = SHpCXTFrompCXF ((PCXF)&pnodeOfbnode(bn)->v[0]);
+ oldFrame = pExState->frame;
+ pExState->frame = *SHpFrameFrompCXF ((PCXF)&pnodeOfbnode(bn)->v[0]);
+ if ((pExState->frame.BP.seg == 0) && (pExState->frame.BP.off == 0)) {
+ // we did not have a valid frame at bind time
+ pExState->frame = oldFrame;
+ }
+ error = EvalLChild (bn);
+ if (error == TRUE) {
+ // if there was not an error and if the result of the
+ // expression is bp relative, then we must load the value
+ // before returning to the original context
+
+ if ((EVAL_STATE (ST) == EV_lvalue) &&
+ (EVAL_IS_BPREL (ST) || EVAL_IS_REGREL (ST) ||
+ EVAL_IS_TLSREL (ST))) {
+ if (EVAL_IS_REF (ST)) {
+ if (!EvalUtil (OP_fetch, ST, NULL, EU_LOAD)) {
+ // unable to load value
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ pExState->frame = oldFrame;
+ return (FALSE);
+ }
+ EVAL_IS_REF (ST) = FALSE;
+ EVAL_STATE (ST) = EV_lvalue;
+ EVAL_SYM_OFF (ST) = EVAL_PTR_OFF (ST);
+ EVAL_SYM_SEG (ST) = EVAL_PTR_SEG (ST);
+ SetNodeType (ST, PTR_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (!EvalUtil (OP_fetch, ST, NULL, EU_LOAD)) {
+ // unable to load value
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ pExState->frame = oldFrame;
+ return (FALSE);
+ }
+ }
+ }
+ pExState->frame = oldFrame;
+ if ((bnCxt = oldbnCxt) != 0) {
+ // the old context was pointing into the expression tree.
+ // since the expression tree could have been reallocated,
+ // we must recompute the context pointer
+
+ pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
+ }
+ else {
+ // the context pointer is pointing into the expression state structure
+ pCxt = oldCxt;
+ }
+ return (error);
+}
+
+
+
+
+/*** EvalAddrOf - Perform the address-of ('&') operation
+ *
+ * fSuccess = EvalAddrOf (bn)
+ *
+ * Entry
+ *
+ * Exit ST = address node
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * The stack top value (ST) is set to the address of the
+ * stack top operand
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalAddrOf (bnode_t bn)
+{
+ if (!EvalLChild (bn)) {
+ return (FALSE);
+ }
+
+ return AddrOf( bn );
+}
+
+
+LOCAL bool_t NEAR FASTCALL AddrOf (bnode_t bn)
+{
+ CV_typ_t type;
+
+ if (EVAL_STATE (ST) == EV_type) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return (FALSE);
+ }
+
+ // The operand must be an lvalue and cannot be a register variable
+
+ DASSERT (EVAL_STATE (ST) == EV_lvalue);
+ DASSERT (!(EVAL_IS_REG (ST)));
+ DASSERT (NODE_STYPE (pnodeOfbnode(bn)) != 0);
+
+ if ((type = NODE_STYPE (pnodeOfbnode(bn))) == 0) {
+ // unable to find proper pointer type
+ return (FALSE);
+ }
+ else {
+ /*
+ * If the address is a reference -- then all that changes
+ * is the type, the value of the reference is the pointer
+ * value. Otherwise the address of the pointer becomes
+ * the value of the pointer to the pointer.
+ */
+
+ if (!EVAL_IS_REF(ST)) {
+ ResolveAddr(ST);
+ EVAL_STATE(ST) = EV_rvalue;
+
+ EVAL_PTR (ST) = EVAL_SYM (ST);
+ if (ADDR_IS_LI (EVAL_PTR (ST))) {
+ SHFixupAddr (&EVAL_PTR (ST));
+ }
+ }
+ return (SetNodeType (ST, type));
+ }
+}
+
+
+
+
+
+/*** EvalFetch - Perform the fetch ('*') operation
+ *
+ * fSuccess = EvalFetch (bn)
+ *
+ * Entry ST = pointer to address value
+ *
+ * Exit ST = dereferenced value
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * The resultant node is set to the contents of the location
+ * pointed to by the operand node.
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalFetch (bnode_t bn)
+{
+ if (EvalLChild (bn)) {
+ return (FetchOp (ST));
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalThisInit - initialize this calculation
+ *
+ * fSuccess = EvalThisInit (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit TempThis = stack top
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalThisInit (bnode_t bn)
+{
+ Unreferenced(bn);
+
+ *pvThis = *ST;
+ if (EVAL_IS_CLASS (pvThis)) {
+ ResolveAddr(pvThis);
+ return TRUE;
+ }
+ else if (EVAL_IS_PTR (pvThis)) {
+ if (EVAL_STATE (pvThis) == EV_lvalue) {
+ FetchOp (pvThis);
+ }
+ else {
+ EVAL_SYM (pvThis) = EVAL_PTR (pvThis);
+ EVAL_STATE (pvThis) = EV_lvalue;
+
+ // Remove a level of indirection from the resultant type.
+
+ RemoveIndir (pvThis);
+ EVAL_IS_REF (pvThis) = FALSE;
+ return (TRUE);
+ }
+ }
+
+ // we should not initialize the this address unless the stack top
+ // is a class or a pointer to class
+
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+}
+
+
+
+
+/*** EvalThisConst - Adjust this temp by constant
+ *
+ * fSuccess = EvalThisConst (bn)
+ *
+ * Entry bn = based pointer to node containing constant
+ *
+ * Exit EVAL_SYM_OFF (TempThis) adjusted by constant
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalThisConst (bnode_t bn)
+{
+ if (EvalLChild (bn) == TRUE) {
+ EVAL_SYM_OFF (pvThis) += ((padjust_t)(&pnodeOfbnode(bn)->v[0]))->disp;
+ return (SetNodeType (pvThis, ((padjust_t)(&pnodeOfbnode(bn)->v[0]))->btype));
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalThisExpr - Adjust this temp by expression
+ *
+ * fSuccess = EvalThisExpr (bn)
+ *
+ * Entry bn = based pointer to node containing expression
+ *
+ * Exit EVAL_SYM_OFF (TempThis) adjusted by expression
+ * newaddr = oldaddr + *(*(oldaddr + vbptroff) + vbindex)
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * The evaluation of this node will result in
+ *
+ * pvThis = (pvThis + vbpoff) + *(*(pvThis +vbpoff) + vbdisp)
+ * where
+ * pvThis = address of base class
+ * ap = current address point
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalThisExpr (bnode_t bn)
+{
+ padjust_t pa = (padjust_t)(&pnodeOfbnode(bn)->v[0]);
+
+ // we set the node types of the pointer to char FAR * to prevent the
+ // PlusMinus () code from attempting an array indexing operation
+
+
+ if (EvalLChild (bn) == TRUE) {
+ return (CalcThisExpr (pa->vbptr, pa->vbpoff, pa->disp, pa->btype));
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** CalcThisExpr - Adjust this temp by expression
+ *
+ * fSuccess = CalcThisExpr (vbptr, vbpoff, disp, btype)
+ *
+ * Entry vbptr = type index of virtual base pointer
+ * vbpoff = offset of vbptr from this pointer
+ * disp = index of virtual base displacement from *vbptr
+ * btype = type index of base class
+ *
+ * Exit EVAL_SYM_OFF (TempThis) adjusted by expression
+ * newaddr = oldaddr + *(*(oldaddr + vbptroff) + vbindex)
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * The evaluation of this node will result in
+ *
+ * pvThis = (pvThis + vbpoff) + *(*(pvThis + vbpoff) + vbdisp)
+ * where
+ * pvThis = address of base class
+ */
+
+
+LOCAL bool_t NEAR FASTCALL CalcThisExpr (CV_typ_t vbptr, OFFSET vbpoff,
+ OFFSET disp, CV_typ_t btype)
+{
+ // we set the node types of the pointer to char FAR * to prevent the
+ // PlusMinus () code from attempting an array indexing operation
+
+ if (PushStack (pvThis) == TRUE) {
+ EVAL_PTR (ST) = EVAL_SYM (ST);
+ EVAL_STATE (ST) = EV_rvalue;
+ if ((SetNodeType (ST, (CV_typ_t)(ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? T_32PFCHAR : T_PFCHAR)) == TRUE) &&
+ (InitConst (vbpoff) == TRUE) &&
+ (PlusMinus (OP_plus) == TRUE) &&
+ (PushStack (ST) == TRUE) &&
+ (DerefVBPtr (vbptr)) &&
+ (InitConst (disp) == TRUE) &&
+ (PlusMinus (OP_plus) == TRUE) &&
+ (FetchOp (ST) == TRUE) &&
+ (PlusMinus (OP_plus) == TRUE)) {
+ SetNodeType (ST, btype);
+ EVAL_STATE (ST) = EV_lvalue;
+ EVAL_SYM (ST) = EVAL_PTR (ST);
+ *pvThis = *ST;
+ return (PopStack ());
+ }
+ }
+ return (FALSE);
+}
+
+
+
+/** DerefVBPtr - dereference virtual base pointer
+ *
+ * flag = DerefVBPtr (type)
+ *
+ * Entry type = type index of virtual base pointer
+ * ST = address of virtual base pointer as T_PFCHAR
+ *
+ * Exit ST = virtual base pointer
+ *
+ * Returns TRUE if no error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR PASCAL DerefVBPtr (CV_typ_t type)
+{
+
+ // The operand cannot be a register variable
+
+ DASSERT (!(EVAL_IS_REG (ST)));
+ DASSERT (type != 0);
+ DASSERT (EVAL_IS_BPREL (ST) == FALSE);
+ DASSERT (EVAL_IS_REGREL (ST) == FALSE);
+
+ if (type != 0) {
+ if (SetNodeType (ST, type) == TRUE) {
+ EVAL_STATE (ST) = EV_lvalue;
+ EVAL_SYM (ST) = EVAL_PTR (ST);
+ if (!EvalUtil (OP_fetch, ST, NULL, EU_LOAD | EU_TYPE)) {
+ return (FALSE);
+ }
+
+ // The resultant node is basically identical to the child except
+ // that its EVAL_SYM field is equal to the actual contents of
+ // the pointer:
+
+ if (EVAL_IS_BASED (ST)) {
+ if (!NormalizeBase (ST)) {
+ return(FALSE);
+ }
+ }
+
+ // Remove a level of indirection from the resultant type.
+
+ RemoveIndir (ST);
+ EVAL_IS_REF (ST) = FALSE;
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalAssign - Perform an assignment operation
+ *
+ * fSuccess = EvalAssign (bn)
+ *
+ * Entry bn = based pointer to assignment node
+ *
+ * Exit
+ *
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalAssign (bnode_t bn)
+{
+ if (!EvalLChild (bn) || !EvalRChild (bn)) {
+ return (FALSE);
+ }
+ return (Assign (NODE_OP (pnodeOfbnode(bn))));
+}
+
+
+
+
+/*** Assign - Perform an assignment operation
+ *
+ * fSuccess = Assign (op)
+ *
+ * Entry op = assignment operator
+ *
+ * Exit
+ *
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL Assign (op_t op)
+{
+ extern CV_typ_t eqop[];
+ op_t nop;
+
+ // Left operand must have evaluated to an lvalue
+
+ if (EVAL_STATE (STP) != EV_lvalue) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ return (FALSE);
+ }
+ if (EVAL_IS_REF (ST)) {
+ if (FetchOp (ST) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_REF (STP)) {
+ if (FetchOp (STP) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+
+ /*
+ * if the rhs is a bit-field then convert to the underlying type
+ */
+
+ if (EVAL_IS_BITF( ST )) {
+ EVAL_TYP( ST ) = BITF_UTYPE( ST );
+ }
+
+ if (op == OP_eq) {
+
+ // for simple assignment, load both nodes
+
+ if (!EvalUtil (OP_eq, ST, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+ if (EVAL_IS_BASED (ST) && !((EVAL_TYP (STP) == T_SHORT) ||
+ (EVAL_TYP (STP) == T_USHORT) || (EVAL_TYP (STP) == T_INT2) ||
+ (EVAL_TYP (STP) == T_UINT2))) {
+ // if the value to be stored is a based pointer and the type
+ // of the destination is not an int, then normalize the pointer.
+ // A based pointer can be stored into an int without normalization.
+
+ if (!NormalizeBase (ST)) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_BASED (STP)) {
+ // if the location to be stored into is a based pointer and the
+ // value to be stored is a pointer or is a long value not equal
+ // to zero, then the value is denormalized
+
+ if (EVAL_IS_PTR (ST) ||
+ (((EVAL_TYP (ST) == T_LONG) || (EVAL_TYP(ST) == T_ULONG)) &&
+ (EVAL_ULONG (ST) != 0L)) ||
+ (((EVAL_TYP (ST) == T_INT4) || (EVAL_TYP(ST) == T_UINT4)) &&
+ (EVAL_ULONG (ST) != 0L))) {
+ //M00KLUDGE - this should go through CastNode
+ if (!DeNormalizePtr (ST, STP)) {
+ return (FALSE);
+ }
+ }
+ }
+ }
+ else {
+ // map assignment operator to arithmetic operator
+ // push address onto top of stack and load the value and
+ // perform operation
+
+ if (!PushStack (STP) || !PushStack (STP)) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ switch (nop = eqop[op - OP_multeq]) {
+ case OP_plus:
+ case OP_minus:
+ PlusMinus (nop);
+ break;
+
+ default:
+ Arith (nop);
+ }
+ // The top of the stack now contains the value of the memory location
+ // modified by the value. Move the value to the right operand of the
+ // assignment operand.
+
+ // M00KLUDGE - this will not work with variable sized stack entries
+
+ *STP = *ST;
+ PopStack ();
+ }
+
+ // store result
+
+ if (EVAL_IS_BITF (STP)) {
+ // store bitfield
+ return (SBitField ());
+ }
+ else if (EVAL_IS_PTR (STP)) {
+ if (!CastNode (ST, EVAL_TYP (STP), PTR_UTYPE (STP))) {
+ return FALSE;
+ }
+ if (ADDR_IS_LI (EVAL_PTR (ST)) == TRUE) {
+ SHFixupAddr (&EVAL_PTR (ST));
+ }
+ EVAL_VAL (STP) = EVAL_VAL (ST);
+ }
+ else {
+ if (!CastNode (ST, EVAL_TYP (STP), EVAL_TYP (STP))) {
+ return FALSE;
+ }
+ EVAL_VAL (STP) = EVAL_VAL (ST);
+ }
+ PopStack ();
+ EVAL_STATE (ST) = EV_rvalue;
+ return (UpdateMem (ST));
+}
+
+
+
+
+/** FetchOp - fetch pointer value
+ *
+ * fSuccess = FetchOp (pv)
+ *
+ * Entry ST = pointer node
+ *
+ * Exit EVAL_SYM (ST) = pointer value
+ *
+ * Returns TRUE if pointer value fetched without error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL FetchOp (peval_t pv)
+{
+
+ // load the value and perform implicit type conversions.
+
+ if (!EvalUtil (OP_fetch, pv, NULL, EU_LOAD | EU_TYPE)) {
+ return (FALSE);
+ }
+
+ // The resultant node is basically identical to the child except
+ // that its EVAL_SYM field is equal to the actual contents of
+ // the pointer:
+
+ if (EVAL_IS_BASED (pv)) {
+ if (!NormalizeBase (pv)) {
+ return(FALSE);
+ }
+ }
+ EVAL_SYM (pv) = EVAL_PTR (pv);
+ EVAL_STATE (pv) = EV_lvalue;
+
+ // Remove a level of indirection from the resultant type.
+
+ RemoveIndir (pv);
+ EVAL_IS_REF (pv) = FALSE;
+ return (TRUE);
+}
+
+
+
+
+/** InitConst - initialize constand on evaluation stack
+ *
+ * fSuccess = InitConst (const)
+ *
+ * Entry const = constant value
+ *
+ * Exit value field of ST = constant eval node
+ *
+ * Returns TRUE if node added without error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL InitConst (long off)
+{
+ eval_t evalT;
+ peval_t pvT;
+
+ pvT = &evalT;
+ CLEAR_EVAL (pvT);
+ EVAL_STATE (pvT) = EV_constant;
+ if ((SCHAR_MIN <= off) && (off <= SCHAR_MAX)) {
+ SetNodeType(pvT, T_CHAR);
+ EVAL_CHAR(pvT) = (char) off;
+ } else if ((SHRT_MIN <= off) && (off <= SHRT_MAX)) {
+ SetNodeType(pvT, T_SHORT);
+ EVAL_SHORT(pvT) = (short) off;
+ } else {
+ SetNodeType (pvT, T_LONG);
+ EVAL_LONG (pvT) = off;
+ }
+ return (PushStack (pvT));
+}
+
+
+
+
+/** SBitField - store value into bitfield
+ *
+ * fSuccess = SBitField ()
+ *
+ * Entry STP = result bitfield
+ * ST = value
+ *
+ * Exit value field of STP = new field value
+ *
+ * Returns TRUE if field inserted without error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL SBitField ()
+{
+ ushort cBits; // Number of bits in field
+ ushort pos; // Bit position of field
+ ushort mask; // Bit mask
+ ulong mask_l; // 32 bit version
+ uchar mask_c; // 8 bit version
+ LARGE_INTEGER mask_q; // 64-bit version
+ CV_typ_t uType;
+ bool_t retval;
+
+ // get information on the bit field. Shift counts are limited to 5 bits
+ // to emulate the hardware
+
+ pos = (ushort)(BITF_POS (STP) & 0x3f);
+
+ cBits = BITF_LEN (STP);
+ uType = BITF_UTYPE (STP);
+ PushStack (STP);
+ SetNodeType (ST, uType);
+ EVAL_STATE (ST) = EV_lvalue;
+ if (!LoadSymVal (ST)) {
+ return (FALSE);
+ }
+ CastNode (STP, uType, uType);
+ switch (uType) {
+
+ case T_CHAR:
+ case T_RCHAR:
+ case T_UCHAR:
+ mask_c = (uchar) ((1 << cBits) - 1);
+ EVAL_UCHAR (STP) = (uchar) (EVAL_UCHAR (STP) & mask_c);
+ EVAL_UCHAR (ST) = (uchar) ((EVAL_UCHAR (ST) &
+ ~(mask_c << pos)) | (EVAL_UCHAR (STP) << pos));
+ break;
+
+ case T_SHORT:
+ case T_USHORT:
+ case T_INT2:
+ case T_UINT2:
+ mask = (ushort) ((1 << cBits) - 1);
+ EVAL_USHORT (STP) = (ushort) (EVAL_USHORT (STP) & mask);
+ EVAL_USHORT (ST) = (ushort) ((EVAL_USHORT (ST) &
+ ~(mask << pos)) | (EVAL_USHORT (STP) << pos));
+ break;
+
+ case T_LONG:
+ case T_ULONG:
+ case T_INT4:
+ case T_UINT4:
+ mask_l = ((1L << cBits) - 1);
+ EVAL_ULONG (STP) = EVAL_ULONG (STP) & mask_l;
+ EVAL_ULONG (ST) = (EVAL_ULONG (ST) &
+ ~(mask_l << pos)) | (EVAL_ULONG (STP) << pos);
+ break;
+
+ case T_QUAD:
+ case T_UQUAD:
+ case T_INT8:
+ case T_UINT8:
+
+ //
+ // first make sure the bit value is appropriately sized.
+ //
+ if (cBits <= 32) {
+ mask_q.LowPart = ((1L << cBits) -1);
+ mask_q.HighPart = 0;
+ } else {
+ mask_q.LowPart = 0xffffffff;
+ mask_q.HighPart = ((1L << (cBits-32))-1);
+ }
+
+ (EVAL_QUAD(STP)).QuadPart &= mask_q.QuadPart;
+
+ //
+ // now clear out the bit field in the ST
+ //
+ mask_q.QuadPart = mask_q.QuadPart << pos;
+ mask_q.QuadPart = ~mask_q.QuadPart;
+ (EVAL_QUAD(STP)).QuadPart &= mask_q.QuadPart;
+
+ //
+ // finally, put the new bit value in
+ //
+ mask_q.QuadPart = (EVAL_QUAD(STP)).QuadPart << pos;
+ (EVAL_QUAD(STP)).QuadPart |= mask_q.QuadPart;
+
+ break;
+
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ retval = UpdateMem (ST);
+ PopStack ();
+#if 0
+ switch (uType) {
+ case T_CHAR:
+ case T_RCHAR:
+ case T_UCHAR:
+ EVAL_CHAR (ST) <<= (8 - cBits - pos);
+ EVAL_CHAR (ST) >>= (8 - cBits);
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+ case T_UINT2:
+ case T_USHORT:
+ EVAL_SHORT (ST) <<= (16 - cBits - pos);
+ EVAL_SHORT (ST) >>= (16 - cBits);
+ break;
+
+ case T_LONG:
+ case T_ULONG:
+ case T_INT4:
+ case T_UINT4:
+ EVAL_LONG (ST) <<= (32 - cBits - pos);
+ EVAL_LONG (ST) >>= (32 - pos);
+ break;
+ case T_QUAD:
+ case T_UQUAD:
+ case T_INT8:
+ case T_UINT8:
+ // If this is ever re-instantiated, add 64-bit stuff here.
+
+ }
+#endif
+ *STP = *ST;
+ PopStack ();
+ return (retval);
+}
+
+
+
+
+/*** PlusMinus - Perform an addition or subtraction operation
+ *
+ * fSuccess = PlusMinus (op)
+ *
+ * Entry op = OP_plus or OP_minus
+ *
+ * Exit STP = STP op ST and stack popped
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * DESCRIPTION
+ * Special handling is required when one or both operands are
+ * pointers. Otherwise, the arguments are passed on to Arith().
+ */
+
+
+LOCAL bool_t NEAR FASTCALL PlusMinus (op_t op)
+{
+ ulong cbBase;
+ eval_t evalT;
+ peval_t pvT;
+
+ if (EVAL_IS_REF (ST)) {
+ if (FetchOp (ST) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_REF (STP)) {
+ if (FetchOp (STP) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ // Check to see if either operand is a pointer.
+ // If so, the operation is special. Otherwise,
+ // hand it to Arith ().
+
+ if (!EVAL_IS_PTR (STP) && !EVAL_IS_PTR (ST)) {
+ return (Arith (op));
+ }
+
+ // Load values and perform implicit type coercion if required.
+
+ if (!EvalUtil (op, STP, ST, EU_LOAD)) {
+ return (FALSE);
+ }
+
+ // Perform the evaluation. There are two cases:
+ //
+ // I) ptr + int, int + ptr, ptr - int
+ // II) ptr - ptr
+ //
+ // Do some common setup first.
+
+ pvT = &evalT;
+
+ if ((op == OP_plus) || !(EVAL_IS_PTR (ST))) {
+ // Case (I). ptr + int, int + ptr, ptr - int
+
+ if (!EVAL_IS_PTR (STP)) {
+ // Switch so int is on right
+ *pvT = *STP;
+ *STP = *ST;
+ *ST = *pvT;
+ }
+
+ // if pointer node is BP relative, compute actual address
+ *pvT = *STP;
+ RemoveIndir (pvT);
+ cbBase = TypeSize (pvT);
+
+ // The resultant node has the same type as the pointer:
+
+ ResolveAddr(STP);
+ EVAL_STATE(STP) = EV_rvalue;
+
+ // Cast the increment node to an unsigned long.
+
+ CastNode (ST, T_ULONG, T_ULONG);
+
+ // Assign the proper value to the resultant node.
+
+ if (op == OP_plus)
+ EVAL_PTR_OFF (STP) += (UOFFSET)(EVAL_ULONG (ST) * cbBase);
+ else
+ EVAL_PTR_OFF (STP) -= (UOFFSET)(EVAL_ULONG (ST) * cbBase);
+ }
+ else {
+ // Case (II): ptr - ptr. The result is of type ptrdiff_t and
+ // is equal to the distance between the two pointers (in the
+ // address space) divided by the size of the items pointed to:
+
+ if (EVAL_TYP (STP) != EVAL_TYP (ST)) {
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+ *pvT = *STP;
+ RemoveIndir (pvT);
+ cbBase = TypeSize (pvT);
+ EVAL_STATE (STP) = EV_rvalue;
+
+ // we know we are working with pointers so we do not
+ // have to check EVAL_IS_PTR (pv)
+
+ if (EVAL_IS_BASED (STP)) {
+ NormalizeBase (STP);
+ }
+ if (EVAL_IS_BASED (ST)) {
+ NormalizeBase (ST);
+ }
+ if (EVAL_IS_NPTR (STP) || EVAL_IS_FPTR (STP)) {
+ SetNodeType (STP, T_SHORT);
+ EVAL_SHORT (STP) = (short) (EVAL_PTR_OFF (STP) - EVAL_PTR_OFF (ST));
+ EVAL_SHORT (STP) /= (ushort) cbBase;
+ }
+ else if (EVAL_IS_NPTR32 (STP) || EVAL_IS_FPTR32 (STP)) {
+ SetNodeType (STP, T_ULONG);
+ EVAL_ULONG (STP) = EVAL_PTR_OFF (STP) - EVAL_PTR_OFF (ST);
+ EVAL_ULONG (STP) /= cbBase;
+ }
+ else {
+ SetNodeType (STP, T_LONG);
+ // M00KLUDGE This will not work in 32 bit mode
+ EVAL_LONG (STP) =
+ ((((ushort)EVAL_PTR_SEG (STP)) << 16) + EVAL_PTR_OFF (STP))
+ - ((((ushort)EVAL_PTR_SEG (ST)) << 16) + EVAL_PTR_OFF (ST));
+ EVAL_LONG (STP) /= cbBase;
+ }
+ }
+ return(PopStack ());
+}
+
+
+
+
+/** EvalRelat - Perform relational and equality operations
+ *
+ * fSuccess = EvalRelat (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Returns TRUE if no evaluation error
+ * FALSE if evaluation error
+ *
+ * Description
+ * If both operands are arithmetic, passes them on to Arith().
+ * Otherwise (one or both operands pointers), does the evaluation
+ * here.
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalRelat (bnode_t bn)
+{
+ if (!EvalLChild (bn) || !EvalRChild (bn)) {
+ return (FALSE);
+ }
+ return (Relational (NODE_OP (pnodeOfbnode(bn))));
+}
+
+
+
+
+
+/** Relational - Perform relational and equality operations
+ *
+ * fSuccess = Relational (op)
+ *
+ * Entry op = OP_lt, OP_lteq, OP_gt, OP_gteq, OP_eqeq, or OP_bangeq
+ *
+ * Returns TRUE if no evaluation error
+ * FALSE if evaluation error
+ *
+ * Description
+ * If both operands are arithmetic, passes them on to Arith().
+ * Otherwise (one or both operands pointers), does the evaluation
+ * here.
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL Relational (op_t op)
+{
+ int result;
+ ushort segL;
+ ushort segR;
+ UOFFSET offL;
+ UOFFSET offR;
+
+
+ if (EVAL_IS_REF (ST)) {
+ if (FetchOp (ST) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_REF (STP)) {
+ if (FetchOp (STP) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ // Check to see if either operand is a pointer.
+ // If so, the operation is special. Otherwise,
+ // hand it to Arith ().
+
+ if (!EVAL_IS_PTR (STP) && !EVAL_IS_PTR (ST)) {
+ return (Arith (op));
+ }
+
+ if (EvalUtil (op, ST, STP, EU_LOAD | EU_TYPE) == FALSE) {
+ return (FALSE);
+ }
+
+ // Both nodes should now be typed as either near or far
+ // pointers.
+
+ DASSERT (EVAL_IS_PTR (STP) && EVAL_IS_PTR (ST));
+
+ // For the relational operators ('<', '<=', '>', '>='),
+ // only offsets are compared. For the equality operators ('==', '!='),
+ // both segments and offsets are compared.
+
+ if (ADDR_IS_LI (EVAL_PTR (STP))) {
+ SHFixupAddr (&EVAL_PTR (STP));
+ }
+ if (ADDR_IS_LI (EVAL_PTR (ST))) {
+ SHFixupAddr (&EVAL_PTR (ST));
+ }
+
+ segL = EVAL_PTR_SEG (STP);
+ segR = EVAL_PTR_SEG (ST);
+ offL = EVAL_PTR_OFF (STP);
+ offR = EVAL_PTR_OFF (ST);
+
+ switch (op) {
+ case OP_lt:
+ result = (offL < offR);
+ break;
+
+ case OP_lteq:
+ result = (offL <= offR);
+ break;
+
+ case OP_gt:
+ result = (offL > offR);
+ break;
+
+ case OP_gteq:
+ result = (offL >= offR);
+ break;
+
+ case OP_eqeq:
+ if (ADDR_IS_FLAT(EVAL_PTR(STP))) {
+ result = (offL == offR);
+ } else {
+ result = ((segL == segR) && (offL == offR));
+ }
+ break;
+
+ case OP_bangeq:
+ if (ADDR_IS_FLAT(EVAL_PTR(STP))) {
+ result = (offL != offR);
+ } else {
+ result = ((segL != segR) || (offL != offR));
+ }
+ break;
+
+ default:
+ //DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ EVAL_STATE (STP) = EV_rvalue;
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ EVAL_LONG (STP) = result;
+ SetNodeType (STP, T_LONG);
+ } else {
+ EVAL_SHORT (STP) = (short) result;
+ SetNodeType (STP, T_SHORT);
+ }
+ return (PopStack ());
+}
+
+
+
+
+
+/*** EvalUScope - Do unary :: scoping
+ *
+ * fSuccess = EvalUScope (bn);
+ *
+ * Entry pvRes = based pointer to unary scoping node
+ *
+ * Exit pvRes = evaluated left node of pvRes
+ *
+ * Returns TRUE if evaluation successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalUScope (bnode_t bn)
+{
+ register bool_t retval;
+ CXT cxt;
+
+ // save current context packet and set current context to module scope
+
+ cxt = *pCxt;
+ SHGetCxtFromHmod (SHHMODFrompCXT (pCxt), pCxt);
+ retval = EvalLChild (bn);
+ *pCxt = cxt;
+ return (retval);
+}
+
+
+
+
+
+/*** DoBScope - Do binary :: scoping
+ *
+ * fSuccess = DoBScope (pn);
+ *
+ * Entry pvRes = pointer to binary scoping node
+ *
+ * Returns TRUE if evaluation successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalBScope (bnode_t bn)
+{
+ peval_t pv;
+
+ pv = &pnodeOfbnode(NODE_LCHILD (pnodeOfbnode(bn)))->v[0];
+ if (CLASS_GLOBALTYPE (pv) == TRUE) {
+ // the left member of the scope operator was a type not in class
+ // scope. We presumably have an empty stack so we need to fake
+ // up a stack entry
+
+ PushStack (pv);
+ }
+ return (StructEval (bn));
+}
+
+
+
+
+/*** EvalPreIncDec - Do ++expr or --expr
+ *
+ * fSuccess = EvalPreIncDec (bnode_t bn);
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit ST decremented or incremented
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalPreIncDec (bnode_t bn)
+{
+ op_t nop = OP_plus;
+
+ if (!EvalLChild (bn)) {
+ return(FALSE);
+ }
+
+ if (NODE_OP (pnodeOfbnode(bn)) == OP_predec) {
+ nop = OP_minus;
+ }
+
+ // push the entry on the stack and then perform incmrement/decrement
+
+ PushStack (ST);
+
+ // load left node and store as return value
+
+ if (EvalUtil (nop, ST, NULL, EU_LOAD)) {
+ // do the post-increment or post-decrement operation and store
+
+ if (PrePost (nop)) {
+ EVAL_STATE (STP) = EV_lvalue;
+ if (Assign (OP_eq)) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalPostIncDec - Do expr++ or expr--
+ *
+ * fSuccess = EvalPostIncDec (op);
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit ST decremented or incremented
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalPostIncDec (bnode_t bn)
+{
+ eval_t evalT;
+ peval_t pvT = &evalT;
+ op_t nop = OP_plus;
+
+ if (!EvalLChild (bn)) {
+ return(FALSE);
+ }
+ if (NODE_OP (pnodeOfbnode(bn)) == OP_postdec) {
+ nop = OP_minus;
+ }
+
+ // push the entry on the stack and then perform incmrement/decrement
+
+ PushStack (ST);
+
+ // load left node and store as return value
+
+ if (EvalUtil (nop, ST, NULL, EU_LOAD)) {
+ *pvT = *ST;
+
+ // do the post-increment or post-decrement operation and store
+
+ if (PrePost (nop)) {
+ EVAL_STATE (STP) = EV_lvalue;
+ if (Assign (OP_eq)) {
+ *ST = *pvT;
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+}
+
+
+
+
+/** PrePost - perform the increment operation
+ *
+ * fSuccess = PrePost (op);
+ *
+ * Entry op = operation to perform (OP_plus or OP_minus)
+ *
+ * Exit increment/decrement performed and result stored in memory
+ * DebErr set if error
+ *
+ * Returns TRUE if no error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL PrePost (op_t op)
+{
+ if (InitConst (1) == TRUE) {
+ return (PlusMinus (op));
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalBang - Perform logical negation operation
+ *
+ * fSuccess = EvalBang (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit ST = pointer to negated value
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * DESCRIPTION
+ * Checks for a pointer operand; if found, handles it here, otherwise
+ * passes it on to Unary ().
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalBang (bnode_t bn)
+{
+ int result;
+ ushort seg;
+ UOFFSET off;
+
+ if (!EvalLChild (bn)) {
+ return (FALSE);
+ }
+
+ // load the value and perform implicit type conversion.
+
+ if (!EvalUtil (OP_bang, ST, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+ if (EVAL_IS_REF (ST)) {
+ if (FetchOp (ST) == FALSE) {
+ return (FALSE);
+ }
+ }
+
+ // If the operand is not of pointer type, just pass it on to Unary
+
+ if (!(EVAL_IS_PTR (ST)))
+ return (Unary (OP_bang));
+
+ // The result is 1 if the pointer is a null pointer and 0 otherwise
+ // Note that for a near pointer, we compare the offset against
+ // 0, while for a far pointer we compare both segment and offset.
+
+ seg = EVAL_PTR_SEG (ST);
+ off = EVAL_PTR_OFF (ST);
+
+ if (EVAL_IS_NPTR (ST) || EVAL_IS_NPTR32 (ST)) {
+ result = (off == 0);
+ }
+ else {
+ result = ((seg == 0) && (off == 0));
+ }
+
+ CLEAR_EVAL (ST);
+ EVAL_STATE (ST) = EV_rvalue;
+ EVAL_SHORT (ST) = (short) result;
+ return (SetNodeType (ST, T_USHORT));
+}
+
+
+
+
+
+/*** EvalDMember - Perform a dot member access ('.*')
+ *
+ * fSuccess = EvalDMember (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit ST = value of member
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalDMember (bnode_t bn)
+{
+ Unreferenced(bn);
+
+ pExState->err_num = ERR_OPNOTSUPP;
+ return (FALSE); //M00KLUDGE - not implemented
+}
+
+
+
+
+/*** EvalPMember - Perform a pointer to member access ('->*')
+*
+* SYNOPSIS
+* fSuccess = EvalPMember (bn)
+*
+* ENTRY
+* pvRes Pointer to node in which result is to be stored
+* pvLeft Pointer to left operand node
+* pvRight Pointer to right operand node
+*
+* RETURNS
+* TRUE if successful, FALSE if not and sets DebErr
+*
+* DESCRIPTION
+*
+* NOTES
+*/
+
+LOCAL bool_t NEAR FASTCALL EvalPMember (bnode_t bn)
+{
+ Unreferenced(bn);
+
+ // Check to make sure the left operand is a struct/union pointer.
+ // To do this, remove a level of indirection from the node's type
+ // and see if it's a struct or union.
+
+
+ pExState->err_num = ERR_OPNOTSUPP;
+ return (FALSE);
+}
+
+
+
+
+/*** EvalPointsTo - Perform a structure access ('->')
+ *
+ * fSuccess = EvalPointsTo (bn)
+ *
+ * Entry bRight = based pointer to node
+ *
+ * Exit ST = value node for member
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalPointsTo (bnode_t bn)
+{
+
+ if (!EvalLChild (bn)) {
+ return (FALSE);
+ }
+ if (!FetchOp (ST)) {
+ return (FALSE);
+ }
+
+ // The result is simple -- (*ST).pnRight. The call to StructEval ()
+ // will set the error code if it fails.
+
+ if (EVAL_STATE (ST) == EV_rvalue) {
+ return (StructElem (bn));
+ }
+ else {
+ return (StructEval (bn));
+ }
+}
+
+
+
+
+/*** EvalArray - Perform an array access ('[]')
+ *
+ * fSuccess = EvalArray (bn)
+ *
+ * Entry bn = based pointer to array node
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * Obtains the contents of an array member. This is done by
+ * calling PlusMinus() and DoFetch().
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalArray (bnode_t bn)
+{
+ ushort index;
+ eval_t evalT;
+ peval_t pvT;
+
+ if (EvalLChild (bn) && EvalRChild (bn)) {
+ if (EVAL_IS_ARRAY (STP) || EVAL_IS_ARRAY (ST)) {
+ // above check is for array[3] or 3[array]
+ if (EvalUtil (OP_lbrack, STP, ST, EU_LOAD) && PlusMinus (OP_plus)) {
+ return (FetchOp (ST));
+ }
+ }
+ else if (EVAL_IS_PTR (STP)) {
+ // this code is a hack to allow the locals and quick watch windows
+ // display the virtual function table. The GetChildTM generates
+ // an expression of the form a.__vfuncptr[n]. This means that the
+ // evaluation of a.__vfuncptr on the left sets STP to a pointer
+ // node and ThisAddress to the adjusted this pointer. Note that
+ // it turns out that symbol address of STP and ThisAddress are
+ // the same
+
+ pvT = &evalT;
+ *pvT = *STP;
+ SetNodeType (pvT, PTR_UTYPE (pvT));
+ if (EVAL_IS_VTSHAPE (pvT) && (EVAL_STATE (ST) == EV_constant) &&
+ ((index = EVAL_USHORT (ST)) < VTSHAPE_COUNT (pvT))) {
+ index = EVAL_USHORT (ST);
+ PopStack ();
+ DASSERT ((EVAL_SYM_OFF (pvThis) == EVAL_SYM_OFF (ST)) &&
+ (EVAL_SYM_SEG (pvThis) == EVAL_SYM_SEG (ST)));
+ return (VFuncAddress (ST, index));
+ }
+ else {
+ if (EvalUtil (OP_lbrack, STP, ST, EU_LOAD) && PlusMinus (OP_plus)) {
+ return (FetchOp (ST));
+ }
+ }
+ }
+ }
+ return (FALSE);
+}
+
+
+
+
+/*** EvalCast - Perform a type cast operation
+ *
+ * fSuccess = EvalCast (bn)
+ *
+ * Entry bn = based pointer to cast node
+ *
+ * Exit
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+LOCAL bool_t NEAR FASTCALL EvalCast (bnode_t bn)
+{
+
+ if (!EvalRChild (bn) ) {
+ return (FALSE);
+ }
+
+
+ return CastST( bn );
+}
+
+
+
+
+LOCAL bool_t NEAR FASTCALL CastST (bnode_t bn)
+{
+ peval_t pv;
+ peval_t pvL;
+
+ if (!EvalUtil (OP_cast, ST, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+ DASSERT (!EVAL_IS_CLASS (ST));
+
+ // Cast the node to the desired type. if the cast node is a member node,
+ // then the stack top is cast by changing the pointer value by the amount
+ // in the value and then setting the type of the stack top to the type
+ // of the left node
+
+ pv = (peval_t)&pnodeOfbnode(bn)->v[0];
+ pvL = &pnodeOfbnode((NODE_LCHILD (pnodeOfbnode(bn))))->v[0];
+ if (EVAL_MOD (pvL) != 0) {
+ EVAL_MOD (ST) = EVAL_MOD (pvL);
+ }
+ if (EVAL_IS_MEMBER (pv) == TRUE) {
+ // a cast of pointer to derived to pointer to base is not done
+ // for a null value
+ if (EVAL_PTR_OFF (ST) != 0) {
+ if (Eval (MEMBER_THISEXPR (pv)) == FALSE) {
+ return (FALSE);
+ }
+ *ST = *pvThis;
+ EVAL_STATE (ST) = EV_rvalue;
+ EVAL_PTR (ST) = EVAL_SYM (pvThis);
+ }
+ return (SetNodeType (ST, EVAL_TYP (pvL)));
+ }
+ else {
+ if (EVAL_IS_PTR (pvL)) {
+ return (CastNode (ST, EVAL_TYP (pvL), PTR_UTYPE (pvL)));
+ }
+ else {
+ return (CastNode (ST, EVAL_TYP (pvL), EVAL_TYP (pvL)));
+ }
+ }
+}
+
+
+
+
+/*** EvalByteOps - Handle 'by', 'wo' and 'dw' operators
+ *
+ * fSuccess = EvalByteOps (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit ST = pointer to value
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * DESCRIPTION
+ * Evaluates the contents of the address operand as a byte
+ * ('by'), word ('wo') or dword ('dw'):
+ *
+ * Operand Result
+ * ------- ------
+ * <register> *(uchar *)<register>
+ * <address> *(uchar *)<address>
+ * <variable> *(uchar *)&variable
+ *
+ * Where (uchar *) is replaced by (uint *) for the 'wo' operator,
+ * or by (ulong *) for the 'dw' operator.
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalByteOps (bnode_t bn)
+{
+ CV_typ_t type;
+ register op_t op;
+
+ if (!EvalLChild (bn)) {
+ return (FALSE);
+ }
+
+ // If the operand is an lvalue and it is a register,
+ // load the value of the register; otherwise, use the
+ // address of the variable.
+ //
+ // If the operand is not an lvalue, use its value as is.
+
+ if (EVAL_STATE (ST) == EV_lvalue) {
+ if (EVAL_IS_REG (ST)) {
+ if (!LoadVal (ST)) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ else {
+ type = T_USHORT;
+ }
+ }
+ else {
+ if ((type = NODE_STYPE (pnodeOfbnode(bn))) == 0) {
+ // unable to find proper pointer type
+ return (FALSE);
+ }
+
+ ResolveAddr( ST );
+ EVAL_STATE(ST) = EV_rvalue;
+
+ EVAL_PTR (ST) = EVAL_SYM (ST);
+ SetNodeType (ST, type);
+ }
+ }
+
+ // Now cast the node to (char far *), (int far *) or
+ // (long far *). If the type is char, uchar, short
+ // or ushort, we want to first cast to (char *) so
+ // that we properly DS-extend (casting (int)8 to (char
+ // far *) will give the result 0:8).
+
+ type = EVAL_TYP (ST);
+
+ //DASSERT(IS_PRIMITIVE (typ));
+
+ if (CV_TYP_IS_REAL (type)) {
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+ if ((op = NODE_OP (pnodeOfbnode(bn))) == OP_by) {
+ type = T_PFUCHAR;
+ }
+ else if (op == OP_wo) {
+ type = T_PFUSHORT;
+ }
+ else if (op == OP_dw) {
+ type = T_PFULONG;
+ }
+ if (CastNode (ST, type, type) == FALSE) {
+ return (FALSE);
+ }
+ return (FetchOp (ST));
+}
+
+
+
+
+/*** EvalSegOp - Handle ':' segmentation operator
+ *
+ * fSuccess = EvalSegOp (bn)
+ *
+ * Entry bn = based pointer to node
+ *
+ * Exit EVAL_SYM (ST) = seg (STP): offset (ST)
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ * DESCRIPTION
+ * Both operands must have integral values (but cannot
+ * be long or ulong). The result of op1:op2 is a (char
+ * far *) with segment equal to op1 and offset equal to
+ * op2.
+ *
+ * NOTES
+ */
+
+LOCAL bool_t NEAR FASTCALL EvalSegOp (bnode_t bn)
+{
+ if (!EvalLChild (bn) || !EvalRChild (bn)) {
+ return(FALSE);
+ }
+
+#ifndef WIN32
+ // check to make sure that neither operand is of type long or ulong.
+
+ if ((EVAL_TYP (STP) == T_LONG) ||
+ (EVAL_TYP (STP) == T_ULONG) ||
+ (EVAL_TYP (ST) == T_LONG) ||
+ (EVAL_TYP (ST) == T_ULONG) ||
+ (EVAL_TYP (STP) == T_INT4) ||
+ (EVAL_TYP (STP) == T_UINT4) ||
+ (EVAL_TYP (ST) == T_INT4) ||
+ (EVAL_TYP (ST) == T_UINT4)) {
+
+ pExState->err_num = ERR_OPERANDTYPES;
+ return (FALSE);
+ }
+#endif
+
+ /*
+ * Load values and perform implicit type coercion if required.
+ *
+ * OP_segop and OP_segopReal use the same parameters so just choose
+ * one to pass into EvalUtil
+ */
+
+ if (!EvalUtil (OP_segop, STP, ST, EU_LOAD | EU_TYPE)) {
+ return(FALSE);
+ }
+
+ //DASSERT ((EVAL_TYP (STP) == T_SHORT) || (EVAL_TYP (STP) == T_USHORT));
+ //DASSERT ((EVAL_TYP (ST) == T_SHORT) || (EVAL_TYP (ST) == T_USHORT));
+
+ EVAL_STATE (STP) = EV_rvalue;
+ EVAL_PTR_SEG (STP) = EVAL_USHORT (STP);
+ EVAL_PTR_OFF (STP) = EVAL_ULONG (ST);
+
+ if (NODE_OP(pnodeOfbnode(bn)) == OP_segopReal) {
+ ADDR_IS_REAL(EVAL_PTR(STP)) = TRUE;
+ }
+
+ SHUnFixupAddr( &EVAL_PTR(STP) );
+
+ if (ADDR_IS_OFF32(EVAL_PTR(STP))) {
+ SetNodeType (STP, T_32PFCHAR);
+ } else {
+ SetNodeType (STP, T_PFCHAR);
+ }
+ return (PopStack ());
+}
+
+
+
+
+/** Unary - Evaluate the result of a unary arithmetic operation
+ *
+ * fSuccess = Unary (op)
+ *
+ * Entry op = Operator (OP_...)
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ * DESCRIPTION
+ * Evaluates the result of an arithmetic operation. The unary operators
+ * dealt with here are:
+ *
+ * ! ~ - +
+ *
+ * Pointer arithmetic is NOT handled; all operands must be of
+ * arithmetic type.
+ */
+
+
+LOCAL bool_t NEAR FASTCALL Unary (op_t op)
+{
+ bool_t fIsFloat = FALSE;
+ bool_t fIsDouble = FALSE;
+ bool_t fIsLDouble = FALSE;
+ bool_t fIsSigned;
+ bool_t fResInt;
+ int iRes;
+ LARGE_INTEGER liRes, liL;
+ ULARGE_INTEGER uliRes, uliL;
+ FLOAT10 ldRes;
+ FLOAT10 ldL;
+ double dRes, dL;
+ float fRes, fL;
+ CV_typ_t typRes;
+
+ if (EVAL_IS_REF (ST)) {
+ if (FetchOp (ST) == FALSE) {
+ return (FALSE);
+ }
+ }
+
+ // Load the values and perform implicit type conversion.
+
+ if (!EvalUtil (op, ST, NULL, EU_LOAD | EU_TYPE))
+ return (FALSE);
+
+ // The resultant type is an int or larger.
+
+ typRes = EVAL_TYP (ST);
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ if (TypeSizePrim(typRes) < 4) {
+ typRes = T_LONG;
+ }
+ } else {
+ if (TypeSizePrim(typRes) < 2) {
+ typRes = T_SHORT;
+ }
+ }
+
+ if (CV_TYP_IS_REAL (typRes) == TRUE) {
+ fIsFloat = (CV_SUBT (typRes) == CV_RC_REAL32);
+ fIsDouble = (CV_SUBT (typRes) == CV_RC_REAL64);
+ fIsLDouble = (CV_SUBT (typRes) == CV_RC_REAL80);
+ }
+ fIsSigned = CV_TYP_IS_SIGNED (typRes);
+ fResInt = FALSE;
+
+ // Common code. Since we're going to do most of our arithmetic
+ // in either long, ulong or double, we do the casts and get the
+ // value of the operands here rather than repeating this code
+ // in each arm of the switch statement.
+
+ if (fIsFloat) {
+ fL = EVAL_FLOAT (ST);
+ }
+ else if (fIsDouble) {
+ dL = EVAL_DOUBLE (ST);
+ }
+ else if (fIsLDouble) {
+ ldL = EVAL_LDOUBLE (ST);
+ }
+ else if (fIsSigned) {
+ CastNode (ST, T_QUAD, T_QUAD);
+ liL = EVAL_QUAD (ST);
+ }
+ else {
+ // unsigned
+ CastNode (ST, T_UQUAD, T_UQUAD);
+ uliL = EVAL_UQUAD (ST);
+ }
+
+ // Finally, do the actual arithmetic operation.
+
+ switch (op) {
+ case OP_bang:
+ // Operand is of arithmetic type; result is always int.
+
+ fResInt = TRUE;
+ if (fIsFloat) {
+ iRes = !fL;
+ }
+ else if (fIsDouble) {
+ iRes = !dL;
+ }
+ else if (fIsLDouble) {
+ iRes = R10Not(ldL);
+ }
+ else if (fIsSigned) {
+ iRes = liL.QuadPart == 0;
+ }
+ else {
+ iRes = uliL.QuadPart == 0;
+ }
+ break;
+
+ case OP_tilde:
+ // operand must be integral.
+
+ //DASSERT (!fIsReal);
+
+ if (fIsSigned) {
+ liRes.LowPart = ~liL.LowPart;
+ liRes.HighPart = ~liL.HighPart;
+ }
+ else {
+ uliRes.LowPart = ~uliL.LowPart;
+ uliRes.HighPart = ~uliL.HighPart;
+ }
+ break;
+
+ case OP_negate:
+ if (fIsFloat) {
+ fRes = -fL;
+ }
+ else if (fIsDouble) {
+ dRes = -dL;
+ }
+ else if (fIsLDouble) {
+ R10Uminus(&ldRes, ldL);
+ }
+ else if (fIsSigned) {
+ liRes.QuadPart = liL.QuadPart * -1;
+ }
+ else {
+ uliRes.QuadPart = uliL.QuadPart * -1;
+ }
+ break;
+
+ case OP_uplus:
+ if (fIsFloat) {
+ fRes = fL;
+ }
+ else if (fIsDouble) {
+ dRes = dL;
+ }
+ else if (fIsLDouble) {
+ ldRes = ldL;
+ }
+ else if (fIsSigned) {
+ liRes = liL;
+ }
+ else {
+ uliRes = uliL;
+ }
+ break;
+
+ default:
+ DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+
+ }
+
+ // Now set up the resultant node and coerce back to the correct
+ // type:
+
+ EVAL_STATE (ST) = EV_rvalue;
+
+ if (fResInt) {
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ EVAL_LONG (ST) = (long) iRes;
+ SetNodeType (ST, T_LONG);
+ } else {
+ EVAL_SHORT (ST) = (short) iRes;
+ SetNodeType (ST, T_SHORT);
+ }
+ }
+ else {
+ if (fIsFloat) {
+ EVAL_FLOAT (ST) = fRes;
+ SetNodeType (ST, T_REAL32);
+ }
+ else if (fIsDouble) {
+ EVAL_DOUBLE (ST) = dRes;
+ SetNodeType (ST, T_REAL64);
+ }
+ else if (fIsLDouble) {
+ EVAL_LDOUBLE (ST) = ldRes;
+ SetNodeType (ST, T_REAL80);
+ }
+ else if (fIsSigned) {
+ EVAL_QUAD (ST) = liRes;
+ SetNodeType (ST, T_QUAD);
+ }
+ else {
+ EVAL_UQUAD (ST) = uliRes;
+ SetNodeType (ST, T_UQUAD);
+ }
+ CastNode (ST, typRes, typRes);
+ }
+}
+
+
+
+
+/** Arith - Evaluate the result of an arithmetic operation
+ *
+ * fSuccess = Arith (op)
+ *
+ * Entry op = Operator (OP_...)
+ *
+ * Returns TRUE if no error during evaluation
+ * FALSE if error during evaluation
+ *
+ * DESCRIPTION
+ * Evaluates the result of an arithmetic operation. The operators
+ * dealt with here are:
+ *
+ * * / %
+ * + -
+ * == !=
+ * < <= > >=
+ * << >>
+ * & ^ |
+ *
+ * Pointer arithmetic is NOT handled; all operands must be of
+ * arithmetic type.
+ */
+
+
+LOCAL bool_t NEAR FASTCALL Arith (op_t op)
+{
+ bool_t fIsFloat = FALSE;
+ bool_t fIsDouble = FALSE;
+ bool_t fIsLDouble = FALSE;
+ bool_t fIsSigned;
+ bool_t fResInt;
+ int iRes;
+ long lRes, lL, lR;
+ ulong ulRes, ulL, ulR;
+ float fRes, fL, fR;
+ double dRes, dL, dR;
+ FLOAT10 ldRes;
+ FLOAT10 ldL;
+ FLOAT10 ldR;
+ CV_typ_t typRes;
+
+ if (EVAL_IS_REF (STP)) {
+ if (FetchOp (STP) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_REF (ST)) {
+ if (FetchOp (ST) == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (EVAL_IS_ENUM (ST)) {
+ SetNodeType (ST, ENUM_UTYPE (ST));
+ }
+ if (EVAL_IS_ENUM (STP)) {
+ SetNodeType (STP, ENUM_UTYPE (STP));
+ }
+
+ // Resolve identifiers and check the node types. If the nodes
+ // pass validation, they should not be pointers (only arithmetic
+ // operands are handled by this routine).
+
+ // Load the values and perform implicit type conversion.
+
+ if (!EvalUtil (op, STP, ST, EU_LOAD | EU_TYPE))
+ return (FALSE);
+
+ // The resultant type is the same as the type of the left-hand
+ // side (assume for now we don't have the special int-result case).
+
+ typRes = PerformUAC(EVAL_TYP (STP), EVAL_TYP(ST));
+
+ if (CV_TYP_IS_REAL (typRes) == TRUE) {
+ fIsFloat = (CV_SUBT (typRes) == CV_RC_REAL32);
+ fIsDouble = (CV_SUBT (typRes) == CV_RC_REAL64);
+ fIsLDouble = (CV_SUBT (typRes) == CV_RC_REAL80);
+ }
+ fIsSigned = CV_TYP_IS_SIGNED (typRes);
+ fResInt = FALSE;
+
+ // Common code. Since we're going to do most of our arithmetic
+ // in either long, ulong or double, we do the casts and get the
+ // value of the operands here rather than repeating this code
+ // in each arm of the switch statement.
+
+ if (fIsLDouble) {
+ CastNode (STP, T_REAL80, T_REAL80);
+ ldL = EVAL_LDOUBLE (STP);
+ CastNode (ST, T_REAL80, T_REAL80);
+ ldR = EVAL_LDOUBLE (ST);
+ } else
+ if (fIsDouble) {
+ CastNode (STP, T_REAL64, T_REAL64);
+ dL = EVAL_DOUBLE (STP);
+ CastNode (ST, T_REAL64, T_REAL64);
+ dR = EVAL_DOUBLE (ST);
+ }
+ else if (fIsFloat) {
+ CastNode (STP, T_REAL32, T_REAL32);
+ fL = EVAL_FLOAT (STP);
+ CastNode (ST, T_REAL32, T_REAL32);
+ fR = EVAL_FLOAT (ST);
+ }
+ else if (fIsSigned) {
+ CastNode (STP, T_LONG, T_LONG);
+ lL = EVAL_LONG (STP);
+ CastNode (ST, T_LONG, T_LONG);
+ lR = EVAL_LONG (ST);
+ }
+ else {
+ // unsigned
+ CastNode (STP, T_ULONG, T_ULONG);
+ ulL = EVAL_ULONG (STP);
+ CastNode (ST, T_ULONG, T_ULONG);
+ ulR = EVAL_ULONG (ST);
+ }
+
+ // Finally, do the actual arithmetic operation.
+
+ switch (op) {
+ case OP_eqeq:
+ case OP_bangeq:
+ case OP_lt:
+ case OP_gt:
+ case OP_lteq:
+ case OP_gteq:
+ {
+ // This is kind of a strange way to do things, but it should
+ // be pretty obvious what's going on, and it saves code.
+
+ int fEq;
+ int fLt;
+
+ fResInt = TRUE;
+
+ if (fIsLDouble) {
+ fEq = R10Equal(ldL, ldR);
+ fLt = R10Lt(ldL, ldR);
+ } else
+ if (fIsDouble) {
+ fEq = (dL == dR);
+ fLt = (dL < dR);
+ }
+ else if (fIsFloat) {
+ fEq = (fL == fR);
+ fLt = (fL < fR);
+ }
+ else if (fIsSigned) {
+ fEq = (lL == lR);
+ fLt = (lL < lR);
+ }
+ else {
+ fEq = (ulL == ulR);
+ fLt = (ulL < ulR);
+ }
+
+ switch (op) {
+ case OP_eqeq:
+ iRes = fEq;
+ break;
+
+ case OP_bangeq:
+ iRes = !fEq;
+ break;
+
+ case OP_lt:
+ iRes = fLt;
+ break;
+
+ case OP_gt:
+ iRes = !fLt && !fEq;
+ break;
+
+ case OP_lteq:
+ iRes = fLt || fEq;
+ break;
+
+ case OP_gteq:
+ iRes = !fLt || fEq;
+ break;
+ }
+ }
+ break;
+
+ case OP_plus:
+ if (fIsLDouble) {
+ R10Plus(&ldRes, ldL, ldR);
+ } else
+ if (fIsDouble) {
+ dRes = dL + dR;
+ }
+ else if (fIsFloat) {
+ fRes = fL + fR;
+ }
+ else if (fIsSigned) {
+ lRes = lL + lR;
+ }
+ else {
+ ulRes = ulL + ulR;
+ }
+ break;
+
+ case OP_minus:
+ if (fIsLDouble) {
+ R10Minus(&ldRes, ldL, ldR);
+ } else
+ if (fIsDouble) {
+ dRes = dL - dR;
+ }
+ else if (fIsFloat) {
+ fRes = fL - fR;
+ }
+ else if (fIsSigned) {
+ lRes = lL - lR;
+ }
+ else {
+ ulRes = ulL - ulR;
+ }
+ break;
+
+ case OP_mult:
+ if (fIsLDouble) {
+ R10Times(&ldRes, ldL, ldR);
+ } else
+ if (fIsDouble) {
+ dRes = dL * dR;
+ }
+ else if (fIsFloat) {
+ fRes = fL * fR;
+ }
+ else if (fIsSigned) {
+ lRes = lL * lR;
+ }
+ else {
+ ulRes = ulL * ulR;
+ }
+ break;
+
+ case OP_div:
+ // This looks big, but I can't figure out how to do it
+ // with ||'s. Besides, Hans claims it will tail merge
+ // on the error conditions anyway.
+
+ if (fIsLDouble) {
+ if (R10Equal(ldR, Real10_Zero)) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ R10Divide(&ldRes, ldL, ldR);
+ } else
+ if (fIsDouble) {
+ if (dR == (double)0.0) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ dRes = dL / dR;
+ }
+ else if (fIsFloat) {
+ if (fR == (float)0.0) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ fRes = fL / fR;
+ }
+ else if (fIsSigned) {
+ if (lR == (long)0) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ lRes = lL / lR;
+ }
+ else {
+ if (ulR == (unsigned long)0) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ ulRes = ulL / ulR;
+ }
+ break;
+
+ case OP_mod:
+ // Both operands must be integral.
+
+ //DASSERT(!fIsReal);
+
+ if (fIsSigned) {
+ if (lR == (long)0) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ lRes = lL % lR;
+ }
+ else {
+ if (ulR == (unsigned long)0) {
+ pExState->err_num = ERR_DIVIDEBYZERO;
+ return (FALSE);
+ }
+ ulRes = ulL % ulR;
+ }
+ break;
+
+ case OP_shl:
+ // Both operands must be integral.
+
+ //DASSERT(!fIsReal);
+
+ if (fIsSigned) {
+ lRes = lL << lR;
+ }
+ else {
+ ulRes = ulL << ulR;
+ }
+ break;
+
+ case OP_shr:
+ // Both operands must be integral.
+
+ //DASSERT(!fIsReal);
+
+ if (fIsSigned) {
+ lRes = lL >> lR;
+ }
+ else {
+ ulRes = ulL >> ulR;
+ }
+ break;
+
+ case OP_and:
+ // Both operands must have integral type.
+
+ //DASSERT(!fIsReal);
+
+ if (fIsSigned) {
+ lRes = lL & lR;
+ }
+ else {
+ ulRes = ulL & ulR;
+ }
+ break;
+
+ case OP_or:
+ // Both operands must have integral type.
+
+ //DASSERT(!fIsReal);
+
+ if (fIsSigned) {
+ lRes = lL | lR;
+ }
+ else {
+ ulRes = ulL | ulR;
+ }
+ break;
+
+ case OP_xor:
+ // Both operands must have integral type.
+
+ //DASSERT(!fIsReal);
+
+ if (fIsSigned) {
+ lRes = lL ^ lR;
+ }
+ else {
+ ulRes = ulL ^ ulR;
+ }
+ break;
+
+ default:
+ pExState->err_num = ERR_INTERNAL;
+ //DASSERT(FALSE);
+ return (FALSE);
+ }
+
+ // Now set up the resultant node and coerce back to the correct
+ // type:
+
+ EVAL_STATE (STP) = EV_rvalue;
+
+ if (fResInt) {
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ EVAL_LONG (STP) = iRes;
+ SetNodeType (STP, T_LONG);
+ } else {
+ EVAL_SHORT (STP) = (short) iRes;
+ SetNodeType (STP, T_SHORT);
+ }
+ }
+ else {
+ if (fIsLDouble) {
+ EVAL_LDOUBLE (STP) = ldRes;
+ SetNodeType (STP, T_REAL80);
+ } else
+ if (fIsDouble) {
+ EVAL_DOUBLE (STP) = dRes;
+ SetNodeType (STP, T_REAL64);
+ }
+ else if (fIsFloat) {
+ EVAL_FLOAT (STP) = fRes;
+ SetNodeType (STP, T_REAL32);
+ }
+ else {
+ if (fIsSigned) {
+ EVAL_LONG (STP) = lRes;
+ SetNodeType (STP, T_LONG);
+ }
+ else {
+ EVAL_ULONG (STP) = ulRes;
+ SetNodeType (STP, T_ULONG);
+ }
+ CastNode (STP, typRes, typRes);
+ }
+ }
+ return (PopStack ());
+}
+
+
+
+
+/*** EvalUtil - Set up nodes for evaluation
+ *
+ * fSuccess = EvalUtil (op, pvLeft, pvRight, wFlags)
+ *
+ * Entry pvLeft = pointer to left operand node
+ * pvRight = pointer to right operand node, or NULL
+ * wFlags = EU_...
+ *
+ * Exit pvLeft and pvRight loaded and/or typed as requested
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalUtil (op_t op, peval_t pvLeft, peval_t pvRight, ushort wFlags)
+{
+ // Load the value of the node(s).
+
+ if (wFlags & EU_LOAD) {
+ switch (EVAL_STATE (pvLeft)) {
+ case EV_lvalue:
+ if (!LoadVal (pvLeft)) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return (FALSE);
+ }
+ break;
+
+ case EV_rvalue:
+ case EV_constant:
+ break;
+
+ case EV_type:
+ if (EVAL_IS_STMEMBER (pvLeft)) {
+ if (!LoadVal (pvLeft)) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return (FALSE);
+ }
+ else {
+ break;
+ }
+ }
+
+ default:
+ pExState->err_num = ERR_SYNTAX;
+ return (FALSE);
+ }
+ if (pvRight != NULL) {
+ switch (EVAL_STATE (pvRight)) {
+ case EV_lvalue:
+ if (!LoadVal (pvRight)) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return (FALSE);
+ }
+ break;
+
+ case EV_rvalue:
+ case EV_constant:
+ break;
+
+ case EV_type:
+ if (EVAL_IS_STMEMBER (pvRight)) {
+ if (!LoadVal (pvRight)) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return (FALSE);
+ }
+ else {
+ break;
+ }
+ }
+
+ default:
+ pExState->err_num = ERR_SYNTAX;
+ return (FALSE);
+ }
+ }
+ }
+
+ // Perform implicit type coercion.
+
+ if (wFlags & EU_TYPE) {
+ TypeNodes (op, pvLeft, pvRight);
+ }
+
+ return (TRUE);
+}
+
+LOCAL bool_t NEAR FASTCALL
+EvalFuncIdent(
+ bnode_t bn
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ peval_t pvF;
+ eval_t evalF;
+ peval_t pvRet;
+ eval_t evalRet;
+ ushort type;
+ SHREG reg;
+
+ if (!EvalLChild(bn)) {
+
+ return FALSE;
+ }
+
+ if (EVAL_IS_PTR(ST)) {
+ FetchOp(ST);
+ }
+
+ pvF = &evalF;
+ *pvF = *ST;
+
+
+ if (EVAL_IS_METHOD (ST)) {
+ if ((FCN_PROPERTY (pvF) == CV_MTvirtual) ||
+ (FCN_PROPERTY (pvF) == CV_MTintro)) {
+ /*
+ * we have a virtual function. We now need to find the vfuncptr
+ * which is stored at the this pointer and then walk down the
+ * shape table to find the offset of the virtual function pointer
+ * note that we use pvRet to read the vfuncptr
+ */
+
+ pvRet = &evalRet;
+ *pvRet = *pvThis;
+ SetNodeType (pvRet, FCN_VFPTYPE (pvF));
+
+ if (!EvalUtil (OP_fetch, pvRet, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+
+ EVAL_SYM_OFF (pvRet) = EVAL_PTR_OFF (pvRet) + FCN_VTABIND (pvF);
+ EVAL_SYM_SEG (pvRet) = EVAL_PTR_SEG (pvRet);
+ EVAL_STATE (pvRet) = EV_lvalue;
+
+ if (FCN_FARCALL (pvF) == TRUE) {
+ type = T_PFUCHAR;
+ }
+ else {
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ type = T_32PUCHAR;
+ } else {
+ type = T_PUCHAR;
+ }
+ }
+
+ SetNodeType (pvRet, type);
+
+ if (!EvalUtil (OP_fetch, pvRet, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+
+ EVAL_SYM (pvF) = EVAL_PTR (pvRet);
+ reg.hReg = CV_REG_CS;
+ GetReg (&reg, pCxt);
+ EVAL_SYM_SEG (pvF) = reg.Byte2;
+ }
+ }
+
+ *ST = *pvF;
+
+ return TRUE;
+} /* EvalFuncIdent() */
+
+
+
+
+/** EvalFunction - Perform an function call
+ *
+ * fSuccess = EvalFunction (pn)
+ *
+ * Entry bn = based pointer to OP_fcn
+ *
+ * Exit ST = result of function call
+ * pExState->err_num = error number if error
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR FASTCALL EvalFunction (bnode_t bn)
+{
+ bnode_t bnRight = NODE_RCHILD (pnodeOfbnode(bn));
+ bnode_t bnT;
+ eval_t evalRet;
+ peval_t pvRet;
+ eval_t evalF;
+ peval_t pvF;
+ bnode_t bnA;
+ peval_t pvA;
+ SHREG spReg;
+ bool_t retval;
+ UOFFSET maxSP = 0;
+ CV_typ_t typArg;
+ pargd_t pa;
+ ushort type;
+ SHREG reg;
+ ADDR fcnAddr;
+ HDEP hFunc;
+
+#ifdef TARGET_PPC
+ /* We need this for some PPC cases to do an extra
+ * level of dereferencing.
+ */
+ int ppc_extra_deref=FALSE;
+#endif
+
+ /*
+ * the left child must resolve to a function address and BP must not
+ * be zero and the overlay containing the function must be loaded
+ */
+
+ if ((pExState->frame.BP.off == 0) && (pExState->style != EEBPADDRESS)) {
+ pExState->err_num = ERR_FCNCALL;
+ return (FALSE);
+ }
+
+ /*
+ * Save current registers. All returns from this point must restore the
+ * registers or there will be memory loss
+ */
+
+ if (DHSetupExecute(&hFunc) != 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+
+#ifdef TARGET_MIPS
+ spReg.hReg = CV_M4_IntSP;
+#endif
+
+
+#ifdef TARGET_PPC
+ spReg.hReg = CV_PPC_GPR1;
+#endif
+
+#ifdef TARGET_i386
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ spReg.hReg = CV_REG_ESP;
+ } else {
+ spReg.hReg = CV_REG_SP;
+ }
+#endif
+
+#ifdef TARGET_ALPHA
+ spReg.hReg = CV_ALPHA_IntSP;
+#endif
+
+ GetReg (&spReg, pCxt);
+
+ /*
+ * Evaluate argument nodes until end of arguments reached and count
+ * arguments
+ *
+ * if we are evaluating for breakpoint address, we do not need to
+ * evaluate the arguments.
+ */
+
+ if (pExState->style != EEBPADDRESS) {
+ for (bnT = bnRight;
+ NODE_OP (pnodeOfbnode(bnT)) != OP_endofargs;
+ bnT = NODE_RCHILD (pnodeOfbnode(bnT))) {
+
+ /*
+ * Check to make sure the current node is for an argument
+ */
+
+ if (NODE_OP (pnodeOfbnode(bnT)) != OP_arg) {
+ pExState->err_num = ERR_INTERNAL;
+ goto fcnerror;
+ }
+
+ /*
+ * Setup and evaluate the current node
+ */
+
+ bnA = NODE_LCHILD (pnodeOfbnode(bnT));
+ pvA = &pnodeOfbnode(bnA)->v[0];
+ pa = (pargd_t)&pnodeOfbnode(bnT)->v[0];
+ typArg = pa->type;
+ if (Eval (bnA) == FALSE) {
+ goto fcnerror;
+ }
+
+ /*
+ * Base on the type and value of the current argument, push any
+ * additional information needed onto the stack.
+ *
+ * STRINGS: The string will need to be pushed on the stack and
+ * the address of the string is passed as the argument.
+ */
+
+ if ((EVAL_STATE (ST) == EV_constant) && (EVAL_TYP (pvA) == T_PCHAR)) {
+ if (PushString (ST, &spReg, typArg) == FALSE) {
+ return (FALSE);
+ }
+ }
+
+ /*
+ * if the OP_arg node contains a nonzero type (not vararg),
+ * cast the stack top to the specified value
+ */
+
+ else if (pa->flags.ref == TRUE) {
+ /*
+ * for a reference argument, the following happens
+ * if the actual is a constant, cast and push onto
+ * the stack and pass the address. If the actual
+ * is a variable of the correct type, pass the address.
+ * If the actual is a variable of the wrong type, load
+ * and attempt to cast to the correct type, push the
+ * value onto the stack and pass the address. If the
+ * actual is a complex type, pass the address. If the
+ * formal is a base class of the actual, cast the
+ * address and pass that.
+ */
+
+ if (EVAL_STATE (ST) == EV_constant) {
+ // push the casted constant onto the stack
+ if (!CastNode (ST, pa->utype, pa->utype)) {
+ goto fcnerror;
+ }
+ PushRef (ST, &spReg, pa->type);
+ }
+
+ /*
+ * Classes are pushed on the stack
+ * and the address of the pushed area is pushed on
+ * the stack.
+ */
+
+ else if (EVAL_IS_CLASS (ST)) {
+ SetNodeType (ST, T_32FCVPTR);
+ if (!CastNode (ST, pa->type, pa->type)) {
+ goto fcnerror;
+ }
+
+ if (EVAL_IS_BPREL(ST)) {
+ EVAL_IS_BPREL(ST) = FALSE;
+ EVAL_SYM_OFF(ST) += pExState->frame.BP.off;
+ EVAL_SYM_SEG(ST) = pExState->frame.SS;
+ ADDR_IS_LI( EVAL_SYM( ST )) = FALSE;
+ SHUnFixupAddr(&EVAL_SYM(ST));
+ SHFixupAddr(&EVAL_SYM(ST));
+ }
+
+ if (EVAL_IS_REGREL(ST)) {
+ SHREG reg;
+
+ EVAL_IS_REGREL(ST) = FALSE;
+
+ reg.hReg = EVAL_REGREL (ST);
+ if (GetReg(&reg, pCxt) == NULL) {
+ DASSERT(FALSE);
+ return (FALSE);
+ }
+ EVAL_SYM_OFF (ST) += reg.Byte4;
+ EVAL_SYM_SEG (ST) = pExState->frame.SS;
+ ADDR_IS_LI (EVAL_SYM (ST)) = FALSE;
+ SHUnFixupAddr (&EVAL_SYM (ST));
+ }
+
+ EVAL_PTR( ST ) = EVAL_SYM( ST );
+ }
+ else {
+ /*
+ * process a "simple" variable
+ */
+
+ if (!EvalUtil (OP_function, ST, NULL, EU_LOAD)) {
+ goto fcnerror;
+ }
+
+ /*
+ * if the variable is not of the correct type,
+ * load and cast the value to the correct type,
+ * push the value onto the stack and pass that
+ * address to the function
+ */
+
+ if (EVAL_TYP (ST) != pa->type) {
+ if (!CastNode (ST, pa->utype, pa->utype)) {
+ goto fcnerror;
+ }
+ }
+ PushRef (ST, &spReg, pa->type);
+ }
+ }
+ else {
+ /*
+ * an actual that is not a reference cannot be a class.
+ * Load the value and cast it to the proper type.
+ */
+
+ if (EVAL_IS_CLASS (ST)) {
+ pExState->err_num = ERR_CANTCONVERT;
+ goto fcnerror;
+ }
+ if (!EvalUtil (OP_function, ST, NULL, EU_LOAD) ||
+ !CastNode (ST, typArg, typArg)) {
+ goto fcnerror;
+ }
+ }
+ }
+ }
+
+ /*
+ * evaluate left hand side of tree to get function address
+ */
+
+ if (!EvalLChild (bn)){
+ goto fcnerror;
+ }
+
+ if (EVAL_IS_PTR (ST)) {
+ FetchOp (ST);
+ }
+
+ /*
+ * the stack top is the function address node. We save this information
+ * and pop the function node. We then push the argument left to right
+ * using the SP relative offset from the bind that is stored in the
+ * address field of the OP_arg node.
+ */
+
+ /*
+ * The evaluation of the left node also processed the this pointer
+ * adjustment. ThisAddress contains the value of the this pointer
+ */
+
+ pvF = &evalF;
+ *pvF = *ST;
+
+ /*
+ * set type of this pointer if method
+ */
+
+ pvRet = &evalRet;
+
+ if (EVAL_IS_METHOD (ST)) {
+ ResolveAddr( pvThis );
+
+ if ((FCN_PROPERTY (pvF) == CV_MTvirtual) ||
+ (FCN_PROPERTY (pvF) == CV_MTintro)) {
+ /*
+ * we have a virtual function. We now need to find the vfuncptr
+ * which is stored at the this pointer and then walk down the
+ * shape table to find the offset of the virtual function pointer
+ * note that we use pvRet to read the vfuncptr
+ */
+
+ *pvRet = *pvThis;
+ SetNodeType (pvRet, FCN_VFPTYPE (pvF));
+
+ if (!EvalUtil (OP_fetch, pvRet, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+
+ EVAL_SYM_OFF (pvRet) = EVAL_PTR_OFF (pvRet) + FCN_VTABIND (pvF);
+ EVAL_SYM_SEG (pvRet) = EVAL_PTR_SEG (pvRet);
+ EVAL_STATE (pvRet) = EV_lvalue;
+
+ if (FCN_FARCALL (pvF) == TRUE) {
+ type = T_PFUCHAR;
+ }
+ else {
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ type = T_32PUCHAR;
+ } else {
+ type = T_PUCHAR;
+ }
+ }
+
+ SetNodeType (pvRet, type);
+
+ if (!EvalUtil (OP_fetch, pvRet, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+
+#ifdef TARGET_PPC
+ // On the PPC make sure to deref the function-descriptor
+ // (we are left pointing to the FD instead of the actual
+ // function entry point).
+
+ ppc_extra_deref = TRUE;
+#endif
+ EVAL_SYM (pvF) = EVAL_PTR (pvRet);
+ reg.hReg = CV_REG_CS;
+ GetReg (&reg, pCxt);
+ EVAL_SYM_SEG (pvF) = reg.Byte2;
+ }
+ }
+
+#ifdef TARGET_PPC
+ /* If what we have in our hands is a function descriptor, we
+ * must set up the right address to get the entry point.
+ */
+ if (ppc_extra_deref) {
+ eval_t teval = *pvF;
+
+ EVAL_SYM_SEG (&teval) = EVAL_PTR_SEG (&teval);
+ EVAL_STATE (&teval) = EV_lvalue;
+
+ SetNodeType(&teval, T_32PUCHAR);
+ if (!EvalUtil (OP_fetch, &teval, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+ EVAL_SYM (pvF) = EVAL_PTR (&teval);
+ }
+#endif /* TARGET_PPC */
+
+ if (pExState->style == EEBPADDRESS) {
+ *ST = *pvF;
+ return (TRUE);
+ }
+
+ /*
+ * set type of return node
+ */
+
+ *pvRet = *ST;
+ SetNodeType (pvRet, FCN_RETURN (pvRet));
+ EVAL_VALLEN (pvRet) = (ushort)TypeSize (pvRet);
+ EVAL_STATE (pvRet) = EV_rvalue;
+ PopStack ();
+
+ /*
+ * for some return types, pascal and fastcalls requires a hidden
+ * argument pointing to space allocated on the user's stack large
+ * enough to hold the return value.
+ */
+
+ switch (FCN_CALL (pvF)) {
+#ifdef TARGET_i386
+ case FCN_THIS:
+ case FCN_STD:
+ case FCN_C:
+ /*
+ * In the 32-bit world --
+ * if the return value is > 4 bytes AND it is not a
+ * real then allocate space on the stack to hold it.
+ */
+
+ if (ADDR_IS_FLAT(EVAL_SYM(pvF))) {
+ if (!EVAL_IS_REF(pvRet) &&
+ ((!CV_IS_PRIMITIVE(EVAL_TYP(pvRet)) &&
+ ((EVAL_VALLEN (pvRet) > 4) &&
+ (CV_TYPE ( EVAL_TYP (pvRet)) != CV_REAL))))) {
+
+ ADDR_IS_LI (EVAL_SYM (pvRet)) = FALSE;
+ EVAL_STATE (pvRet) = EV_lvalue;
+ spReg.Byte4 -= (EVAL_VALLEN (pvRet) + 3) & ~3;
+ EVAL_ULONG (pvRet) = spReg.Byte4;
+ EVAL_SYM_OFF (pvRet) = spReg.Byte4;
+ EVAL_SYM_SEG (pvRet) = pExState->frame.SS;
+ }
+ }
+ break;
+
+ case FCN_PASCAL:
+ // If the return value is larger than 4 bytes, then allocate
+ // space on the stack and set the return node
+ // to point to this address
+
+ if (!EVAL_IS_REF (pvRet) &&
+ ((!CV_IS_PRIMITIVE (EVAL_TYP (pvRet)) ||
+ (CV_TYPE (EVAL_TYP (pvRet)) == CV_REAL) ||
+ (EVAL_VALLEN (pvRet) > 4)))) {
+ ADDR_IS_LI (EVAL_SYM (pvRet)) = FALSE;
+ EVAL_STATE (pvRet) = EV_lvalue;
+ if (!ADDR_IS_FLAT (EVAL_SYM (pvRet))) {
+ spReg.Byte2 -= (ushort) ((EVAL_VALLEN (pvRet) + 1) & ~1);
+ EVAL_SYM_OFF (pvRet) = spReg.Byte2;
+ EVAL_USHORT (pvRet) = spReg.Byte2;
+ EVAL_SYM_SEG (pvRet) = pExState->frame.SS;
+ }
+ else {
+ spReg.Byte4 -= (EVAL_VALLEN (pvRet) + 1) & ~1;
+ EVAL_SYM_OFF (pvRet) = spReg.Byte4;
+ EVAL_ULONG (pvRet) = spReg.Byte4;
+ EVAL_SYM_SEG (pvRet) = pExState->frame.SS;
+ }
+ }
+ break;
+
+
+ case FCN_FAST:
+ // If the return value is not real and is larger than 4 bytes,
+ // then allocate space on the stack and set the return node
+ // to point to this address. For fastcall, real values are
+ // returned on the numeric coprocessor stack
+
+ if (!EVAL_IS_REF (pvRet) &&
+ ((!CV_IS_PRIMITIVE (EVAL_TYP (pvRet)) &&
+ ((EVAL_VALLEN (pvRet) > 4) &&
+ (CV_TYPE (EVAL_TYP (pvRet)) != CV_REAL))))) {
+ ADDR_IS_LI (EVAL_SYM (pvRet)) = FALSE;
+ EVAL_STATE (pvRet) = EV_lvalue;
+ if (!ADDR_IS_FLAT (EVAL_SYM (pvRet))) {
+ spReg.Byte2 -= (ushort) ((EVAL_VALLEN (pvRet) + 1) & ~1);
+ EVAL_SYM_OFF (pvRet) = spReg.Byte2;
+ EVAL_USHORT (pvRet) = spReg.Byte2;
+ EVAL_SYM_SEG (pvRet) = pExState->frame.SS;
+ }
+ else {
+ spReg.Byte4 -= (EVAL_VALLEN (pvRet) + 1) & ~1;
+ EVAL_SYM_OFF (pvRet) = spReg.Byte4;
+ EVAL_ULONG (pvRet) = spReg.Byte4;
+ EVAL_SYM_SEG (pvRet) = pExState->frame.SS;
+ }
+ }
+ break;
+#endif // TARGET_i386
+
+
+#ifdef TARGET_PPC
+ case FCN_PPC:
+ /*
+ * This was already taken care of in the bind phase
+ */
+
+ break;
+#endif // TARGET_PPC
+
+
+#ifdef TARGET_MIPS
+ case FCN_MIPS:
+ /*
+ * This was already taken care of in the bind phase
+ */
+
+ break;
+#endif // TARGET_MIPS
+
+#ifdef TARGET_ALPHA
+ case FCN_ALPHA:
+ /*
+ * This was already taken care of in the bind phase
+ */
+
+ break;
+#endif // TARGET_ALPHA
+
+ default:
+ DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+
+ /*
+ * push arguments for the function
+ */
+
+ if (PushArgs (pnodeOfbnode(bnRight), &spReg, &maxSP) == FALSE) {
+ goto fcnerror;
+ }
+
+ if (EVAL_STATE (pvRet) == EV_lvalue) {
+ if (!PushOffset (EVAL_SYM_OFF (pvRet), &spReg, &maxSP,
+ /*sizeof (CV_uoff16_t)*/ sizeof(CV_uoff32_t))) {
+ return (FALSE);
+ }
+ }
+
+ /*
+ * This is a C++ function. We therefore need to push in the pointer
+ * to this.
+ */
+
+ if (EVAL_IS_METHOD (pvF)) {
+ SetNodeType (pvThis, FCN_THIS (pvF));
+
+ if (EVAL_TYP(pvThis) == T_NOTYPE) {
+ /*
+ * This is a no-op -- This means that we just referenced
+ * a static element.
+ */
+
+ } else if (EVAL_IS_NPTR32 (pvThis)) {
+
+ SHREG argReg;
+
+ switch(FCN_CALL( pvF ) ) {
+ case FCN_THIS:
+#ifdef TARGET_i386
+ argReg.hReg = CV_REG_ECX;
+ argReg.Byte4 = EVAL_SYM_OFF( pvThis );
+ SetReg(&argReg, pCxt);
+#else
+ DASSERT(FCN_CALL(pvThis) == FCN_THIS);
+ return (FALSE);
+#endif
+ break;
+
+ case FCN_PPC:
+#ifdef TARGET_PPC
+ argReg.hReg = CV_PPC_GPR3;
+ argReg.Byte4 = EVAL_SYM_OFF( pvThis );
+ argReg.Byte4High = 0;
+ SetReg(&argReg, pCxt);
+#else
+ if (!PushOffset (EVAL_SYM_OFF (pvThis), &spReg, &maxSP,
+ sizeof (CV_uoff32_t))) {
+ return (FALSE);
+ }
+#endif
+ break;
+
+ case FCN_MIPS:
+#ifdef TARGET_MIPS
+ argReg.hReg = CV_M4_IntA0;
+ argReg.Byte4 = EVAL_SYM_OFF( pvThis );
+ SetReg(&argReg, pCxt);
+#else
+ if (!PushOffset (EVAL_SYM_OFF (pvThis), &spReg, &maxSP,
+ sizeof (CV_uoff32_t))) {
+ return (FALSE);
+ }
+#endif
+ break;
+
+ case FCN_ALPHA:
+#ifdef TARGET_ALPHA
+ argReg.hReg = CV_ALPHA_IntA0;
+ argReg.Byte4 = EVAL_SYM_OFF( pvThis );
+ argReg.Byte4High = 0;
+ SetReg(&argReg, pCxt);
+#else
+ if (!PushOffset (EVAL_SYM_OFF (pvThis), &spReg, &maxSP,
+ sizeof (CV_uoff32_t))) {
+ return (FALSE);
+ }
+#endif
+ break;
+ }
+ }
+ }
+
+ // Call the user's procedure
+
+#ifdef TARGET_MIPS
+ spReg.Byte4 -= (UOFFSET) maxSP;
+#endif
+
+#ifdef TARGET_PPC
+ spReg.Byte4 -= (UOFFSET) maxSP;
+#endif
+
+#ifdef TARGET_i386
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ spReg.Byte4 -= (UOFFSET) maxSP;
+ } else {
+ spReg.Byte2 -= (ushort) maxSP;
+ }
+#endif
+
+#ifdef TARGET_ALPHA
+ spReg.Byte4 -= (UOFFSET) maxSP;
+#endif
+
+ SetReg (&spReg, pCxt);
+
+ fcnAddr = EVAL_SYM (pvF);
+
+ // make sure that the execution model is Native, if it is not
+ // then return ERR_CALLSEQ.
+ {
+ WORD wModel;
+ SYMPTR pSym;
+ UOFFSET obMax = 0xFFFFFFFF;
+
+ SHModelFromAddr(&fcnAddr, &wModel, (char FAR *)&pSym, (UOFFSET FAR *)&obMax );
+ if ( wModel != CEXM_MDL_native ) {
+
+ // not native calling sequence, return error
+ pExState->err_num = ERR_CALLSEQ;
+ goto fcnerror;
+ }
+ }
+
+ if (ADDR_IS_LI (fcnAddr)) {
+ SHFixupAddr (&fcnAddr);
+ }
+
+ if (DHStartExecute(hFunc, &fcnAddr, TRUE, EVAL_IS_FFCN (pvF)? SHFar:SHNear) != 0) {
+ pExState->err_num = ERR_EXCEPTION;
+ goto fcnerror;
+ }
+
+ // Procedure succeeded, set return information and set flag to force
+ // update
+
+ is_assign = TRUE;
+ PushStack (pvRet);
+ if (EVAL_TYP (ST) == T_VOID) {
+ retval = TRUE;
+ } else {
+ switch (FCN_CALL (pvF)) {
+ case FCN_STD:
+ case FCN_C:
+ case FCN_THIS:
+ retval = StoreC (pvF);
+ break;
+
+ case FCN_PASCAL:
+ retval = StoreP ();
+ break;
+
+ case FCN_PPC:
+ retval = StorePPC(pvF);
+ break;
+
+ case FCN_MIPS:
+ retval = StoreMips(pvF);
+ break;
+
+ case FCN_ALPHA:
+ retval = StoreAlpha(pvF);
+ break;
+
+ case FCN_FAST:
+ retval = StoreF ();
+ break;
+
+ default:
+ goto fcnerror;
+ }
+ }
+ if (retval == TRUE) {
+ if (DHCleanUpExecute(hFunc)) {
+ return (FALSE);
+ } else {
+ EVAL_STATE (ST) = EV_rvalue;
+ return (TRUE);
+ }
+ }
+
+fcnerror:
+ DHCleanUpExecute(hFunc);
+ return (FALSE);
+}
+
+
+
+
+/** PushArgs - push arguments
+ *
+ * fSuccess = PushArgs (pnArg, pspReg, pmaxSP);
+ *
+ * Entry pnArg = pointer to argument nodes
+ * pspReg = pointer to register structure for SP value
+ * pmaxSP = pointer to location to store maximum SP relative offset
+ *
+ * Exit arguments pushed onto stack
+ *
+ * Returns TRUE if parameters pushed without error
+ * FALSE if error during push
+ */
+
+
+LOCAL bool_t NEAR PASCAL PushArgs (pnode_t pnArg, SHREG FAR *pspReg, UOFFSET FAR *pmaxSP)
+{
+ SHREG argReg;
+
+#ifdef TARGET_PPC
+ SHREG tmpReg;
+#endif
+
+ // The arguments have been evaluated left to right which means that the
+ // rightmost argument is at ST. We need to recurse down the right side
+ // of the argument tree to find the OP_arg node that corresponds to the
+ // stack top.
+
+ if (NODE_OP (pnArg) == OP_endofargs) {
+ return (TRUE);
+ }
+
+ if (!PushArgs (pnodeOfbnode(NODE_RCHILD (pnArg)), pspReg, pmaxSP)) {
+ return (FALSE);
+ }
+ else {
+#ifdef TARGET_i386
+ if (((pargd_t)&(pnArg->v[0]))->flags.isreg == TRUE) {
+ argReg.hReg = ((pargd_t)&(pnArg->v[0]))->reg;
+ switch (argReg.hReg & 0xff) {
+ case CV_REG_AL:
+ case CV_REG_CL:
+ case CV_REG_DL:
+ case CV_REG_BL:
+ case CV_REG_AH:
+ case CV_REG_CH:
+ case CV_REG_DH:
+ argReg.Byte1 = EVAL_UCHAR (ST);
+ break;
+
+ case CV_REG_ST0:
+ case CV_REG_ST1:
+ case CV_REG_ST2:
+ case CV_REG_ST3:
+ case CV_REG_ST4:
+ case CV_REG_ST5:
+ case CV_REG_ST6:
+ case CV_REG_ST7:
+ memcpy(&argReg.Byte10, &EVAL_DOUBLE(ST), sizeof(FLOAT10));
+ break;
+
+ default:
+ argReg.Byte2 = EVAL_USHORT (ST);
+ break;
+
+ case CV_REG_EAX:
+ case CV_REG_ECX:
+ case CV_REG_EDX:
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+ case CV_REG_DR0:
+ case CV_REG_DR1:
+ case CV_REG_DR2:
+ case CV_REG_DR3:
+ case CV_REG_DR4:
+ case CV_REG_DR5:
+ case CV_REG_DR6:
+ case CV_REG_DR7:
+ case CV_REG_PSEUDO1:
+ case CV_REG_PSEUDO2:
+ case CV_REG_PSEUDO3:
+ case CV_REG_PSEUDO4:
+ case CV_REG_PSEUDO5:
+ case CV_REG_PSEUDO6:
+ case CV_REG_PSEUDO7:
+ case CV_REG_PSEUDO8:
+ case CV_REG_PSEUDO9:
+ argReg.Byte4 = EVAL_ULONG( ST );
+ break;
+ }
+ if ((argReg.hReg >> 8) != CV_REG_NONE) {
+ switch (argReg.hReg >> 8) {
+ case CV_REG_DX:
+ case CV_REG_ES:
+ argReg.Byte2High = *(((ushort FAR *)&(EVAL_ULONG (ST))) + 1);
+ break;
+ }
+ }
+ SetReg (&argReg, pCxt);
+ }
+#endif
+
+
+#ifdef TARGET_PPC
+ if (((pargd_t)&(pnArg->v[0]))->flags.isreg == TRUE) {
+ ushort reg = ((pargd_t)&(pnArg->v[0]))->reg;
+
+ argReg.hReg = (reg & 0xff);
+
+ switch (argReg.hReg) {
+ case CV_PPC_GPR3:
+ case CV_PPC_GPR4:
+ case CV_PPC_GPR5:
+ case CV_PPC_GPR6:
+ case CV_PPC_GPR7:
+ case CV_PPC_GPR8:
+ case CV_PPC_GPR9:
+ case CV_PPC_GPR10:
+ argReg.Byte4 = EVAL_ULONG(ST);
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+ break;
+
+ case CV_PPC_FPR1:
+ case CV_PPC_FPR2:
+ case CV_PPC_FPR3:
+ case CV_PPC_FPR4:
+ case CV_PPC_FPR5:
+ case CV_PPC_FPR6:
+ case CV_PPC_FPR7:
+ case CV_PPC_FPR8:
+ case CV_PPC_FPR9:
+ case CV_PPC_FPR10:
+ case CV_PPC_FPR11:
+ case CV_PPC_FPR12:
+ case CV_PPC_FPR13:
+
+ if (EVAL_TYP(ST) == T_REAL32) {
+ argReg.Byte8 = (double) (EVAL_FLOAT(ST));
+ } else {
+ argReg.Byte8 = EVAL_DOUBLE(ST);
+ }
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+
+ /*
+ * Floating point values are passed in FPRs as well as GPRs.
+ */
+ switch (reg >>= 8) {
+ case CV_PPC_GPR3:
+ case CV_PPC_GPR4:
+ case CV_PPC_GPR5:
+ case CV_PPC_GPR6:
+ case CV_PPC_GPR7:
+ case CV_PPC_GPR8:
+ case CV_PPC_GPR9:
+ case CV_PPC_GPR10:
+ SetReg (&argReg, pCxt);
+ argReg.hReg = reg;
+ memcpy(&argReg.Byte4, &EVAL_FLOAT(ST), sizeof(float));
+ break;
+
+ case (CV_PPC_GPR3<<4)|CV_PPC_GPR4 :
+ case (CV_PPC_GPR5<<4)|CV_PPC_GPR6 :
+ case (CV_PPC_GPR7<<4)|CV_PPC_GPR8 :
+ case (CV_PPC_GPR9<<4)|CV_PPC_GPR10:
+ SetReg (&argReg, pCxt);
+ tmpReg.hReg = (reg & 0xf);
+ tmpReg.Byte4 = argReg.Byte4High;
+ SetReg (&tmpReg, pCxt);
+ argReg.hReg = ((reg >> 4) & 0xf);
+ break;
+ }
+ break;
+
+ default:
+ DASSERT(FALSE);
+ break;
+ }
+
+ SetReg (&argReg, pCxt);
+ }
+#endif
+
+
+
+
+
+#ifdef TARGET_MIPS
+ if (((pargd_t)&(pnArg->v[0]))->flags.isreg == TRUE) {
+ argReg.hReg = ((pargd_t)&(pnArg->v[0]))->reg;
+
+ switch (argReg.hReg) {
+ case CV_M4_IntA0:
+ case CV_M4_IntA1:
+ case CV_M4_IntA2:
+ case CV_M4_IntA3:
+ argReg.Byte4 = EVAL_ULONG( ST );
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+ break;
+
+ case CV_M4_FltF12:
+ case CV_M4_FltF14:
+ memcpy(&argReg.Byte4, &EVAL_FLOAT( ST ), sizeof(float));
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+ break;
+
+ case (CV_M4_IntA3<<8)|CV_M4_IntA2:
+ case (CV_M4_FltF13<<8)|CV_M4_FltF12:
+ case (CV_M4_FltF15<<8)|CV_M4_FltF14:
+ memcpy(&argReg.Byte1, &EVAL_DOUBLE( ST ), sizeof(double));
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+ break;
+
+
+ default:
+ DASSERT(FALSE);
+ break;
+ }
+
+ SetReg (&argReg, pCxt);
+ }
+#endif
+
+#ifdef TARGET_ALPHA
+ if (((pargd_t)&(pnArg->v[0]))->flags.isreg == TRUE) {
+ argReg.hReg = ((pargd_t)&(pnArg->v[0]))->reg;
+
+ switch (argReg.hReg) {
+ case CV_ALPHA_IntA0:
+ case CV_ALPHA_IntA1:
+ case CV_ALPHA_IntA2:
+ case CV_ALPHA_IntA3:
+ case CV_ALPHA_IntA4:
+ case CV_ALPHA_IntA5:
+ *((PLARGE_INTEGER) & argReg.Byte4) = EVAL_QUAD( ST );
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+ break;
+
+ case CV_ALPHA_FltF16:
+ case CV_ALPHA_FltF17:
+ case CV_ALPHA_FltF18:
+ case CV_ALPHA_FltF19:
+ case CV_ALPHA_FltF20:
+ case CV_ALPHA_FltF21:
+ memcpy(&argReg.Byte1, &EVAL_DOUBLE( ST ), sizeof(double));
+ *pmaxSP = max( *pmaxSP, ((pargd_t)&pnArg->v[0])->SPoff );
+ break;
+
+ default:
+ DASSERT(FALSE);
+ break;
+ }
+
+ SetReg (&argReg, pCxt);
+ }
+#endif // ALPHA
+
+ else if (!PushUserValue (ST, (pargd_t)&pnArg->v[0], pspReg, pmaxSP)) {
+ pExState->err_num = ERR_PTRACE;
+ return (FALSE);
+ }
+ }
+ PopStack ();
+ return (TRUE);
+}
+
+
+
+
+
+
+/** PushRef - push referenced value onto stack
+ *
+ * fSuccess = PushRef (pv, spReg, reftype);
+ *
+ * Entry pv = value
+ * spReg = pointer to sp register structure
+ * reftype = type of the reference
+ *
+ * Exit string pushed onto user stack
+ * SP register structure updated to reflect size of string
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL PushRef (peval_t pv, SHREG FAR *spReg, CV_typ_t reftype)
+{
+ uint cbVal;
+ bool_t retval = TRUE;
+
+ Unreferenced( reftype );
+
+ switch (EVAL_STATE (pv)) {
+ case EV_lvalue:
+ // for an lvalue, change the node to a reference to the lvalue
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ CastNode (pv, T_FCVPTR, T_FCVPTR);
+ break;
+
+ case EV_rvalue:
+ case EV_constant:
+ cbVal = ((uint)TypeSize (pv) + 3) & ~3;
+
+ // decrement stack pointer to allocate room for string
+
+ spReg->Byte4 -= cbVal;
+
+ // get current SS value and set symbol address to SS:SP
+
+ EVAL_SYM_SEG (pv) = pExState->frame.SS;
+ EVAL_SYM_OFF (pv) = spReg->Byte4;
+ ADDR_IS_FLAT(EVAL_SYM(pv)) = TRUE;
+ EVAL_STATE (pv) = EV_lvalue;
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+ retval = (PutDebuggeeBytes (EVAL_SYM (pv), cbVal, EVAL_PVAL (pv), EVAL_TYP(pv)) == cbVal);
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ if (retval == FALSE) {
+ pExState->err_num = ERR_PTRACE;
+ }
+ break;
+
+ default:
+ DASSERT (FALSE);
+ retval = FALSE;
+ break;
+ }
+ return (retval);
+}
+
+
+
+
+
+
+/** PushString - push constant string onto stack
+ *
+ * fSuccess = PushString (pv, spReg, typArg);
+ *
+ * Entry pv = value describing string
+ * spReg = pointer to sp register structure
+ * typArg = type of resultant pointer node
+ *
+ * Exit string pushed onto user stack
+ * SP register structure updated to reflect size of string
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL PushString (peval_t pv, SHREG FAR *spReg, CV_typ_t typArg)
+{
+ char FAR *pb;
+ char FAR *pbEnd;
+ uint cbVal;
+ bool_t errcnt = 0;
+ bool_t fWide;
+ ushort zero = 0;
+ ushort FillCnt;
+ ushort ch;
+ OFFSET spSave;
+
+ // compute location and length of string note that pointer points to
+ // initial " or L" of string and the length includes the initial ' or
+ // L" and the ending ". The byte count must be rounded to even parity
+ // because of restrictions on the stack. If the string is a wide
+ // character string, then the C runtime must be called to translate the
+ // string.
+
+ pb = pExStr + EVAL_ITOK (pv);
+ pbEnd = pb + EVAL_CBTOK (pv) - 1;
+ if ((fWide = (*pb == 'L')) == TRUE) {
+ // skip wide character leader and compute number of bytes for stack
+ // we add two bytes for forcing a zero termination
+ pb++;
+ cbVal = 2 * (EVAL_CBTOK (pv) - 3);
+ FillCnt = 2;
+ }
+ else {
+ cbVal = EVAL_CBTOK (pv) - 2;
+ FillCnt = 1;
+ }
+
+ DASSERT (*pb == '"');
+ pb++;
+
+ // decrement stack pointer to allocate room for string. We know that
+ // the string actually pushed can be no longer than cbVal + FillCnt.
+ // It can be shorter because of escaped characters such as \n and \001
+
+ if (!ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ spReg->Byte4 &= 0xffff;
+ }
+ spReg->Byte4 -= (cbVal + FillCnt);
+ spReg->Byte4 &= ~3; // round down to correct stack size
+ spSave = spReg->Byte4;
+ SetNodeType (pv, typArg);
+
+ // get current SS value and set symbol address to SS:SP
+
+ EVAL_SYM_SEG (pv) = pExState->frame.SS;
+ EVAL_SYM_OFF (pv) = spReg->Byte4;
+ ADDR_IS_FLAT(EVAL_SYM(pv)) = ADDR_IS_FLAT(*SHpADDRFrompCXT(pCxt));
+ ADDR_IS_OFF32(EVAL_SYM(pv)) = ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt));
+ ADDR_IS_REAL(EVAL_SYM(pv)) = ADDR_IS_REAL(*SHpADDRFrompCXT(pCxt));
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+
+ EVAL_STATE (pv) = EV_lvalue;
+ if (fWide == FALSE) {
+ // move characters one at a time onto the user's stack, converting
+ // while moving.
+
+ while (pb < pbEnd) {
+ if ((ch = *pb++) == '\\') {
+ GetEscapedChar (&pb, &ch);
+ }
+ if (PutDebuggeeBytes (EVAL_SYM (pv), sizeof (char), &ch, T_RCHAR) != sizeof (char)) {
+ errcnt++;
+ }
+ EVAL_SYM_OFF (pv) += sizeof (char);
+ }
+ }
+ else {
+ // M00BUG - this is a fake routine until the runtime routines are
+ // M00BUG - available to do the correct translation. We will also
+ // M00BUG - need to get the locale state from the user's space for
+ // M00BUG - for the translation
+
+ while (pb < pbEnd) {
+ ch = *pb++;
+ // move wide characters onto the user's stack
+ if (PutDebuggeeBytes (EVAL_SYM (pv), 2, &ch, T_WCHAR) != 2) {
+ errcnt++;
+ }
+ EVAL_SYM_OFF (pv) += 2 * sizeof (char);
+ }
+ }
+ if (PutDebuggeeBytes (EVAL_SYM (pv), FillCnt, &zero, (fWide ? T_WCHAR : T_RCHAR)) != FillCnt) {
+ errcnt++;
+ }
+ EVAL_SYM_OFF (pv) = spSave;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ if (errcnt != 0) {
+ pExState->err_num = ERR_PTRACE;
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+
+
+/** StoreC - store return value for C call
+ *
+ * fSuccess = StoreC (pvF);
+ *
+ * Entry pvF = pointer to function descriptor
+ *
+ * Exit return value stored in ST
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL StoreC (peval_t pvF)
+{
+ SHREG argReg;
+ ushort len;
+ ADDR addr;
+
+ Unreferenced( pvF );
+
+ if (EVAL_IS_PTR (ST)) {
+ /*
+ ** The result is a 16-bit pointer. Use DX:AX for far pointers
+ ** and DS:AX for near pointers.
+ */
+
+ if (EVAL_IS_NPTR(ST) || EVAL_IS_FPTR(ST)) {
+ if (EVAL_IS_NPTR(ST)) {
+ argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+ } else {
+ argReg.hReg = ((CV_REG_DS << 8) | CV_REG_AX);
+ }
+
+ GetReg (&argReg, pCxt);
+ EVAL_PTR_OFF (ST) = argReg.Byte2;
+ EVAL_USHORT (ST) = argReg.Byte2;
+ EVAL_PTR_SEG (ST) = argReg.Byte2High;
+
+ } else {
+ DASSERT( EVAL_IS_NPTR32(ST) || EVAL_IS_FPTR32(ST) );
+
+ argReg.hReg = CV_REG_EAX;
+
+ GetReg( &argReg, pCxt );
+ EVAL_PTR_OFF (ST) = argReg.Byte4;
+ EVAL_ULONG (ST) = argReg.Byte4;
+
+ if ( EVAL_IS_NPTR32( ST )) {
+ EVAL_PTR_SEG (ST) = pExState->frame.DS;
+ } else {
+ argReg.hReg = CV_REG_DX;
+
+ GetReg( &argReg, pCxt );
+ EVAL_PTR_SEG (ST) = argReg.Byte2;
+ }
+ ADDR_IS_OFF32(EVAL_PTR(ST)) = TRUE;
+ ADDR_IS_FLAT(EVAL_PTR (ST)) = TRUE;
+ }
+ }
+ /*
+ * Floating point value returned; return location system dependent
+ */
+
+ else if ((EVAL_TYP (ST) == T_REAL32) ||
+ (EVAL_TYP (ST) == T_REAL64) ||
+ (EVAL_TYP (ST) == T_REAL80)) {
+ if (ADDR_IS_FLAT(*SHpADDRFrompCXT(pCxt)) || EVAL_TYP(ST) == T_REAL80) {
+ /*
+ * For the flat world (i.e. nt) the return value is on the
+ * top of the floating point stack.
+ */
+
+ argReg.hReg = CV_REG_ST0;
+ GetReg(&argReg, pCxt);
+ memcpy(&EVAL_LDOUBLE(ST), &argReg.Byte10, sizeof(FLOAT10));
+
+ switch( EVAL_TYP ( ST )) {
+ case T_REAL32:
+ EVAL_FLOAT(ST) = R10CastToFloat(EVAL_LDOUBLE(ST));
+ break;
+
+ case T_REAL64:
+ EVAL_DOUBLE(ST) = R10CastToDouble(EVAL_LDOUBLE(ST));
+ break;
+
+ case T_REAL80:
+ break;
+ }
+ } else if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ /*
+ * for the 32-bit non NT world --- HELP!!!!
+ */
+
+ DASSERT(FALSE);
+ return FALSE;
+ } else {
+ /*
+ * for the dos world AX has a pointer to the address containning
+ * the return value. Return value is correctly sized.
+ */
+
+ argReg.hReg = ((CV_REG_DS << 8) | CV_REG_AX);
+ GetReg(&argReg, pCxt);
+
+ AddrInit(&addr, 0, argReg.Byte2High, argReg.Byte2,
+ FALSE, FALSE, FALSE,
+ ADDR_IS_REAL(*SHpADDRFrompCXT(pCxt)));
+ if (GetDebuggeeBytes(addr, EVAL_VALLEN(ST),
+ (char FAR *) &EVAL_DOUBLE(ST), EVAL_TYP(ST)) != (UINT)EVAL_VALLEN(ST)) {
+ return FALSE;
+ }
+ }
+ }
+ else if ((EVAL_TYP (ST) == T_CHAR) || (EVAL_TYP (ST) == T_RCHAR)) {
+ argReg.hReg = CV_REG_AL;
+ GetReg (&argReg, pCxt);
+ EVAL_SHORT (ST) = argReg.Byte1;
+ }
+ else if (EVAL_TYP (ST) == T_UCHAR) {
+ argReg.hReg = CV_REG_AL;
+ GetReg (&argReg, pCxt);
+ EVAL_USHORT (ST) = argReg.Byte1;
+ }
+ else {
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ len = EVAL_VALLEN (ST);
+ argReg.hReg = CV_REG_EAX;
+ GetReg (&argReg, pCxt);
+
+ /*
+ ** Check for prmitive types (i.e. long or short) and for
+ ** classes which are of lenght less that 3
+ */
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len < 4) && (len != 3))) {
+
+ if (len <= 2) {
+ EVAL_USHORT(ST) = argReg.Byte2;
+ } else {
+ DASSERT( len == 4 );
+ EVAL_ULONG (ST) = argReg.Byte4;
+ }
+
+ } else {
+ /*
+ ** DS:EAX points to the return value
+ */
+
+ EVAL_SYM_OFF (ST) = argReg.Byte4;
+ argReg.hReg = CV_REG_DS;
+ GetReg(&argReg, pCxt);
+ EVAL_SYM_SEG (ST) = argReg.Byte2;
+ ADDR_IS_LI ( EVAL_SYM (ST)) = FALSE;
+
+ if (GetDebuggeeBytes(EVAL_SYM(ST), EVAL_VALLEN(ST),
+ (char FAR *)&EVAL_VAL(ST), EVAL_TYP(ST)) != (UINT)EVAL_VALLEN(ST)) {
+
+ pExState->err_num = ERR_PTRACE;
+ return FALSE;
+ }
+ }
+ } else {
+ len = EVAL_VALLEN (ST);
+ argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+ GetReg (&argReg, pCxt);
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len < 4) && (len != 3))) {
+ EVAL_USHORT (ST) = argReg.Byte2;
+ if (len > 2) {
+ *(((ushort FAR *)&(EVAL_ULONG (ST))) + 1) = argReg.Byte2High;
+ }
+ }
+ else {
+ // treat (DS)DX:AX as the pointer to the return value
+ EVAL_SYM_OFF (ST) = argReg.Byte2;
+ argReg.hReg = CV_REG_DS;
+ GetReg (&argReg, pCxt);
+ EVAL_SYM_SEG (ST) = argReg.Byte2;
+ ADDR_IS_LI (EVAL_SYM (ST)) = FALSE;
+ if (GetDebuggeeBytes (EVAL_SYM (ST), EVAL_VALLEN (ST),
+ (char FAR *)&EVAL_VAL (ST), EVAL_TYP(ST)) != (UINT)EVAL_VALLEN (ST)) {
+ pExState->err_num = ERR_PTRACE;
+ return (FALSE);
+ }
+ }
+ }
+ }
+ return (TRUE);
+}
+
+
+
+
+/** StoreF - store return value for fast call
+ *
+ * fSuccess = StoreF ();
+ *
+ * Entry ST pointer to eval describing return value
+ *
+ * Exit return value stored
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL StoreF (void)
+{
+ SHREG argReg;
+ int len;
+
+ if (EVAL_IS_PTR (ST)) {
+ /*
+ * The results is a 16 bit pointer. Use DX:AX for far pointers and
+ * DS:AX for near pointers.
+ */
+
+ if (EVAL_IS_NPTR(ST) || EVAL_IS_FPTR(ST)) {
+ if (EVAL_IS_NPTR( ST)) {
+ argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+ } else {
+ argReg.hReg = ((CV_REG_DS << 8) | CV_REG_AX);
+ }
+
+ GetReg( &argReg, pCxt );
+ EVAL_PTR_OFF( ST ) = EVAL_USHORT( ST ) = argReg.Byte2;
+ EVAL_PTR_SEG( ST ) = argReg.Byte2High;
+ } else {
+ /*
+ * assume no 32-bit far pointers
+ */
+
+ DASSERT( EVAL_IS_NPTR32( ST ) );
+
+ argReg.hReg = CV_REG_EAX;
+ GetReg( &argReg, pCxt );
+ EVAL_PTR_OFF( ST ) = EVAL_ULONG( ST ) = argReg.Byte4;
+ EVAL_PTR_SEG( ST ) = pExState->frame.DS;
+
+ /*
+ * For far pointers use DX not DS
+ */
+
+ ADDR_IS_FLAT( EVAL_PTR( ST )) = TRUE;
+ }
+ }
+ else if (CV_IS_PRIMITIVE (EVAL_TYP(ST)) &&
+ (CV_TYPE (EVAL_TYP (ST)) == CV_REAL)) {
+ /*
+ * return value is real, read value from the coprocessor
+ * stack and cast to proper size
+ */
+
+ argReg.hReg = CV_REG_ST0;
+ GetReg (&argReg, pCxt);
+ memcpy(&EVAL_DOUBLE(ST), &argReg.Byte10, sizeof(FLOAT10));
+
+ switch( EVAL_TYP ( ST )) {
+ case T_REAL32:
+ EVAL_FLOAT(ST) = R10CastToFloat(EVAL_LDOUBLE(ST));
+ break;
+
+ case T_REAL64:
+ EVAL_DOUBLE(ST) = R10CastToDouble(EVAL_LDOUBLE(ST));
+ break;
+
+ case T_REAL80:
+ break;
+ }
+ }
+ else if ((EVAL_TYP (ST) == T_CHAR) || (EVAL_TYP (ST) == T_RCHAR)) {
+ argReg.hReg = CV_REG_AL;
+ GetReg (&argReg, pCxt);
+ EVAL_SHORT (ST) = argReg.Byte1;
+ }
+ else if (EVAL_TYP (ST) == T_UCHAR) {
+ argReg.hReg = CV_REG_AL;
+ GetReg (&argReg, pCxt);
+ EVAL_USHORT (ST) = argReg.Byte1;
+ }
+ else {
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ len = EVAL_VALLEN (ST);
+ argReg.hReg = CV_REG_EAX;
+ GetReg (&argReg, pCxt);
+
+ /*
+ ** Check for prmitive types (i.e. long or short) and for
+ ** classes which are of lenght less that 3
+ */
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len < 4) && (len != 3))) {
+
+ if (len <= 2) {
+ EVAL_USHORT(ST) = argReg.Byte2;
+ } else {
+ DASSERT( len == 4 );
+ EVAL_ULONG (ST) = argReg.Byte4;
+ }
+
+ } else {
+ /*
+ ** DS:EAX points to the return value
+ */
+
+ EVAL_SYM_OFF (ST) = argReg.Byte4;
+ argReg.hReg = CV_REG_DS;
+ GetReg(&argReg, pCxt);
+ EVAL_SYM_SEG (ST) = argReg.Byte2;
+ ADDR_IS_LI ( EVAL_SYM (ST)) = FALSE;
+
+ if (GetDebuggeeBytes(EVAL_SYM(ST), EVAL_VALLEN(ST),
+ (char FAR *)&EVAL_VAL(ST), EVAL_TYP(ST)) != (UINT)EVAL_VALLEN(ST)) {
+
+ pExState->err_num = ERR_PTRACE;
+ return FALSE;
+ }
+ }
+ } else {
+ len = EVAL_VALLEN (ST);
+ argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+ GetReg (&argReg, pCxt);
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len < 4) && (len != 3))) {
+ EVAL_USHORT (ST) = argReg.Byte2;
+ if (len > 2) {
+ *(((ushort FAR *)&(EVAL_ULONG (ST))) + 1) = argReg.Byte2High;
+ }
+ }
+ else {
+ // treat (DS)DX:AX as the pointer to the return value
+ EVAL_SYM_OFF (ST) = argReg.Byte2;
+ argReg.hReg = CV_REG_DS;
+ GetReg (&argReg, pCxt);
+ EVAL_SYM_SEG (ST) = argReg.Byte2;
+ ADDR_IS_LI (EVAL_SYM (ST)) = FALSE;
+ if (GetDebuggeeBytes (EVAL_SYM (ST), EVAL_VALLEN (ST),
+ (char FAR *)&EVAL_VAL (ST), EVAL_TYP(ST)) != (UINT)EVAL_VALLEN (ST)) {
+ pExState->err_num = ERR_PTRACE;
+ return (FALSE);
+ }
+ }
+ }
+ }
+ return (TRUE);
+}
+
+
+
+
+
+/** StoreMips - store return value for Mips call
+ *
+ * fSuccess = StoreMips (pvF);
+ *
+ * Entry pvF = pointer to function descriptor
+ *
+ * Exit return value stored in ST
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL StoreMips (peval_t pvF)
+{
+ SHREG argReg;
+ ushort len;
+
+ Unreferenced( pvF );
+
+ DASSERT( EVAL_TYP(ST) != T_REAL80 );
+
+ /*
+ * Floating point values are returned in f0 (Real) or f0:f1 (float)
+ */
+
+ if ((EVAL_TYP (ST) == T_REAL32) ||
+ (EVAL_TYP (ST) == T_REAL64) ) {
+ argReg.hReg = (CV_M4_FltF1 << 8) | CV_M4_FltF0;
+ GetReg ( &argReg, pCxt );
+
+ if (EVAL_TYP (ST) == T_REAL32) {
+ EVAL_FLOAT(ST) = *((float *) &argReg.Byte4);
+ } else {
+ EVAL_DOUBLE(ST) = *((double *) &argReg.Byte4);
+ }
+ }
+ else if ((EVAL_TYP (ST) == T_CHAR) || (EVAL_TYP (ST) == T_RCHAR)) {
+ argReg.hReg = CV_M4_IntV0;
+ GetReg( &argReg, pCxt );
+ EVAL_SHORT( ST ) = argReg.Byte1;
+ }
+ else if (EVAL_TYP (ST) == T_UCHAR) {
+ argReg.hReg = CV_M4_IntV0;
+ GetReg( &argReg, pCxt );
+ EVAL_USHORT( ST ) = argReg.Byte1;
+ }
+
+ else if (EVAL_IS_PTR (ST)) {
+ DASSERT( EVAL_IS_NPTR32(ST) );
+ argReg.hReg = CV_M4_IntV0;
+ GetReg( &argReg, pCxt );
+
+ EVAL_PTR_OFF (ST) = argReg.Byte4;
+ EVAL_ULONG (ST) = argReg.Byte4;
+
+ EVAL_PTR_SEG (ST) = 0;
+ ADDR_IS_FLAT( EVAL_PTR (ST)) = TRUE;
+ ADDR_IS_OFF32( EVAL_PTR (ST)) = TRUE;
+ ADDR_IS_REAL( EVAL_PTR( ST)) = FALSE;
+ ADDR_IS_LI( EVAL_PTR (ST)) = FALSE;
+ }
+
+ else {
+
+ len = EVAL_VALLEN(ST);
+ argReg.hReg = CV_M4_IntV0;
+ GetReg( &argReg, pCxt );
+
+ /*
+ * Check for primitive lengths
+ */
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len < 4) && (len != 3))) {
+
+ if (len <= 2) {
+ EVAL_USHORT(ST) = argReg.Byte2;
+ } else {
+ EVAL_ULONG (ST) = argReg.Byte4;
+ }
+ } else {
+ EVAL_SYM_OFF (ST) = argReg.Byte4;
+ EVAL_SYM_SEG (ST) = 0;
+ ADDR_IS_FLAT( EVAL_SYM (ST)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM (ST)) = TRUE;
+ ADDR_IS_LI( EVAL_SYM (ST)) = FALSE;
+
+ if (GetDebuggeeBytes(EVAL_SYM(ST), EVAL_VALLEN(ST),
+ (char *)&EVAL_VAL(ST), EVAL_TYP(ST))
+ != (UINT)EVAL_VALLEN(ST)) {
+ pExState->err_num = ERR_PTRACE;
+ return FALSE;
+ }
+ }
+ }
+ return (TRUE);
+} /* StoreMips() */
+
+
+/** StorePPC - store return value for PPC call
+ *
+ * fSuccess = StorePPC (pvF);
+ *
+ * Entry pvF = pointer to function descriptor
+ *
+ * Exit return value stored in ST
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL StorePPC (peval_t pvF)
+{
+ SHREG argReg;
+ ushort len;
+
+ Unreferenced( pvF );
+
+ DASSERT( EVAL_TYP(ST) != T_REAL80 );
+
+ /*
+ * Floating point values are returned in FPR1
+ */
+
+ if ((EVAL_TYP (ST) == T_REAL32) ||
+ (EVAL_TYP (ST) == T_REAL64) ) {
+ argReg.hReg = (CV_PPC_FPR1);
+ GetReg ( &argReg, pCxt );
+
+ if (EVAL_TYP (ST) == T_REAL32) {
+ EVAL_FLOAT(ST) = (float) argReg.Byte8;
+ } else {
+ EVAL_DOUBLE(ST) = *((double *) &argReg.Byte4);
+ }
+ }
+ else if ((EVAL_TYP (ST) == T_CHAR) || (EVAL_TYP (ST) == T_RCHAR)) {
+ argReg.hReg = CV_PPC_GPR3;
+ GetReg( &argReg, pCxt );
+ EVAL_SHORT( ST ) = argReg.Byte1;
+ }
+ else if (EVAL_TYP (ST) == T_UCHAR) {
+ argReg.hReg = CV_PPC_GPR3;
+ GetReg( &argReg, pCxt );
+ EVAL_USHORT( ST ) = argReg.Byte1;
+ }
+ else if (EVAL_IS_PTR (ST)) {
+ DASSERT( EVAL_IS_NPTR32(ST) );
+ argReg.hReg = CV_PPC_GPR3;
+ GetReg( &argReg, pCxt );
+
+ EVAL_PTR_OFF (ST) = argReg.Byte4;
+ EVAL_ULONG (ST) = argReg.Byte4;
+
+ EVAL_PTR_SEG (ST) = 0;
+ ADDR_IS_FLAT( EVAL_PTR (ST)) = TRUE;
+ ADDR_IS_OFF32( EVAL_PTR (ST)) = TRUE;
+ ADDR_IS_REAL( EVAL_PTR( ST)) = FALSE;
+ ADDR_IS_LI( EVAL_PTR (ST)) = FALSE;
+ }
+
+ else {
+
+ len = EVAL_VALLEN(ST);
+ argReg.hReg = CV_PPC_GPR3;
+ GetReg( &argReg, pCxt );
+
+ /*
+ * Check for primitive lengths
+ */
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len < 4) && (len != 3))) {
+
+ if (len <= 2) {
+ EVAL_USHORT(ST) = argReg.Byte2;
+ } else {
+ EVAL_ULONG (ST) = argReg.Byte4;
+ }
+ } else {
+ EVAL_SYM_OFF (ST) = argReg.Byte4;
+ EVAL_SYM_SEG (ST) = 0;
+ ADDR_IS_FLAT( EVAL_SYM (ST)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM (ST)) = TRUE;
+ ADDR_IS_LI( EVAL_SYM (ST)) = FALSE;
+
+ if (GetDebuggeeBytes(EVAL_SYM(ST), EVAL_VALLEN(ST),
+ (char *)&EVAL_VAL(ST), EVAL_TYP(ST))
+ != (UINT)EVAL_VALLEN(ST)) {
+ pExState->err_num = ERR_PTRACE;
+ return FALSE;
+ }
+ }
+ }
+ return (TRUE);
+} /* StorePPC() */
+
+
+
+
+/** StoreAlpha - store return value for Alpha call
+ *
+ * fSuccess = StoreAlpha (pvF);
+ *
+ * Entry pvF = pointer to function descriptor
+ *
+ * Exit return value stored in ST
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ *
+ */
+
+LOCAL bool_t NEAR PASCAL StoreAlpha (peval_t pvF)
+{
+ SHREG argReg;
+ ushort len;
+
+ Unreferenced( pvF );
+
+ DASSERT( EVAL_TYP(ST) != T_REAL80 );
+
+ if (CV_TYP_IS_REAL ( EVAL_TYP (ST) ) ) {
+
+ union {
+ float f;
+ double d;
+ unsigned long l[2];
+ } u;
+
+ /*
+ * Floating point values are returned in f0
+ */
+ argReg.hReg = CV_ALPHA_FltF0;
+ GetReg ( &argReg, pCxt );
+
+ //
+ // The SHREG is unaligned; this compiler can only do aligned
+ // loads and stores of floating points.
+ //
+
+ u.l[0] = argReg.Byte4;
+ u.l[1] = argReg.Byte4High;
+
+ if (EVAL_TYP (ST) == T_REAL64) {
+
+ EVAL_DOUBLE(ST) = u.d;
+ return (TRUE);
+ }
+
+ if (EVAL_TYP (ST) == T_REAL32) {
+
+ //
+ // This does the conversion from double to single
+ //
+
+ u.f = (float)u.d;
+ EVAL_FLOAT (ST) = u.f;
+ return (TRUE);
+ }
+ }
+
+ /*
+ * All other values are returned in IntV0 (r0)
+ */
+
+ argReg.hReg = CV_ALPHA_IntV0;
+ GetReg( &argReg, pCxt);
+
+ switch( EVAL_TYP(ST) ) {
+ case T_CHAR:
+ case T_RCHAR:
+ EVAL_SHORT( ST ) = argReg.Byte1;
+ return (TRUE);
+ break;
+
+ case T_UCHAR:
+ EVAL_USHORT( ST ) = argReg.Byte1;
+ return (TRUE);
+ break;
+
+ }
+
+ if (EVAL_IS_PTR (ST)) {
+ DASSERT( EVAL_IS_NPTR32(ST) );
+
+ EVAL_PTR_OFF (ST) = argReg.Byte4;
+ EVAL_ULONG (ST) = argReg.Byte4;
+
+ EVAL_PTR_SEG (ST) = 0;
+ ADDR_IS_OFF32 ( EVAL_PTR (ST)) = TRUE;
+ ADDR_IS_FLAT ( EVAL_PTR (ST)) = TRUE;
+ ADDR_IS_LI( EVAL_PTR (ST)) = FALSE;
+ }
+
+ else {
+
+ len = EVAL_VALLEN(ST);
+
+ /*
+ * Check for primitive lengths
+ */
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (ST)) ||
+ (EVAL_IS_CLASS (ST) && (len <= 4) && (len != 3))) {
+
+ if (len <= 2) {
+ EVAL_USHORT(ST) = argReg.Byte2;
+ } else {
+ EVAL_ULONG (ST) = argReg.Byte4;
+ }
+ } else {
+ EVAL_SYM_OFF (ST) = argReg.Byte4;
+ EVAL_SYM_SEG (ST) = 0;
+ ADDR_IS_LI (EVAL_SYM (ST)) = FALSE;
+
+ if (GetDebuggeeBytes(EVAL_SYM(ST), EVAL_VALLEN(ST),
+ (char *)&EVAL_VAL(ST), EVAL_TYP(ST))
+ != (UINT)EVAL_VALLEN(ST)) {
+ pExState->err_num = ERR_PTRACE;
+ return FALSE;
+ }
+ }
+ }
+ return (TRUE);
+} /* StoreAlpha() */
+
+/** StoreP - store return value for pascal call
+ *
+ * fSuccess = StoreP ();
+ *
+ * Entry ST = pointer to node describing return value
+ *
+ * Exit return value stored
+ *
+ * Returns TRUE if return value stored without error
+ * FALSE if error during store
+ */
+
+
+LOCAL bool_t NEAR PASCAL StoreP ()
+{
+ SHREG argReg;
+
+#pragma message ("Pascal call needs to have 32-bit work done")
+
+ if (EVAL_IS_PTR (ST)) {
+ argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+ GetReg (&argReg, pCxt);
+ EVAL_PTR_OFF (ST) = argReg.Byte2;
+ if (EVAL_VALLEN (ST) > 2) {
+ EVAL_PTR_SEG (ST) = argReg.Byte2High;
+ }
+ if (EVAL_IS_NPTR (ST) || EVAL_IS_NPTR32 (ST)) {
+ // for near pointer, pointer DS:AX
+ EVAL_PTR_SEG (ST) = pExState->frame.DS;
+ }
+ }
+ else if (CV_TYPE (EVAL_TYP (ST)) == CV_REAL) {
+ // read real return value from the value pointed to by either
+ // DS:AX (near) or DX:AX (far)
+// if (EVAL_IS_NFCN (ST)) {
+ // for near return, pointer to return variable is DS:AX
+ argReg.hReg = (CV_REG_DS << 8) | CV_REG_AX;
+// }
+// else {
+ // for far return, pointer to return variable is DX:AX
+// argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+// }
+ GetReg (&argReg, pCxt); // M00FLAT32
+ EVAL_SYM_SEG (ST) = argReg.Byte2High;
+ EVAL_SYM_OFF (ST) = argReg.Byte2;
+ ADDR_IS_LI (EVAL_SYM (ST)) = FALSE;
+ if (GetDebuggeeBytes (EVAL_SYM (ST), EVAL_VALLEN (ST),
+ (char FAR *)&EVAL_DOUBLE (ST), EVAL_TYP(ST)) != (UINT)EVAL_VALLEN (ST)) {
+ return (FALSE);
+ }
+#if 0
+ if (EVAL_TYP (ST) == T_REAL32) {
+ CastNode (ST, T_REAL64, T_REAL64);
+ }
+#endif
+ }
+ else if ((EVAL_TYP (ST) == T_CHAR) || (EVAL_TYP (ST) == T_RCHAR)) {
+ argReg.hReg = CV_REG_AL;
+ GetReg (&argReg, pCxt);
+ EVAL_SHORT (ST) = argReg.Byte1;
+ }
+ else if (EVAL_TYP (ST) == T_UCHAR) {
+ argReg.hReg = CV_REG_AL;
+ GetReg (&argReg, pCxt);
+ EVAL_USHORT (ST) = argReg.Byte1;
+ }
+ else {
+ argReg.hReg = ((CV_REG_DX << 8) | CV_REG_AX);
+ GetReg (&argReg, pCxt);
+ EVAL_USHORT (ST) = argReg.Byte2;
+ if (EVAL_VALLEN (ST) > 2) {
+ *(((ushort FAR *)&(EVAL_ULONG (ST))) + 1) = argReg.Byte2High;
+ }
+ if (EVAL_IS_PTR (ST) && (EVAL_IS_NPTR (ST) || EVAL_IS_NPTR32(ST))) {
+ // for near pointer, pointer DS:AX
+ EVAL_PTR_SEG (ST) = pExState->frame.DS;
+ }
+ }
+ return (TRUE);
+}
+
+
+
+
+
+/** PushUserValue - push value onto user stack
+ *
+ * fSuccess = PushUserValue (pv, pa, pspReg, pmaxSP)
+ *
+ * Entry pv = pointer to value
+ * pa = pointer to argument data describing stack offset
+ * spReg = pointer to register packet for stack pointer
+ * pmaxSP = pointer to location to store maximum SP relative offset
+ *
+ * Exit value pushed onto user stack
+ *
+ * Returns TRUE if value pushed
+ * FALSE if error in push
+ */
+
+
+LOCAL bool_t NEAR PASCAL PushUserValue (peval_t pv, pargd_t pa, SHREG FAR *pspReg, UOFFSET FAR *pmaxSP)
+{
+ ADDR addrStk;
+ uint offsize;
+
+ *pmaxSP = max (*pmaxSP, pa->SPoff);
+ addrStk = EVAL_SYM (pv);
+ addrStk.addr.seg = pExState->frame.SS; //M00FLAT32
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ addrStk.addr.off = pspReg->Byte4 - pa->SPoff;
+ ADDR_IS_FLAT(addrStk) = TRUE;
+ } else {
+ addrStk.addr.off = pspReg->Byte2 - pa->SPoff;
+ ADDR_IS_FLAT(addrStk) = FALSE;
+ }
+ ADDR_IS_LI (addrStk) = FALSE;
+ if (EVAL_IS_PTR (pv)) {
+ // since pointers are stored strangely, we have to put them
+ // in two pieces. First we store the offset (16 or 32 bits)
+
+ if (ADDR_IS_LI (EVAL_PTR (pv))) {
+ SHFixupAddr (&EVAL_PTR (pv));
+ }
+ offsize = ADDR_IS_FLAT(addrStk) ? sizeof (CV_uoff32_t): sizeof (CV_uoff16_t);
+ if (PutDebuggeeBytes (addrStk, offsize, &EVAL_PTR_OFF (pv),
+ (ADDR_IS_FLAT(addrStk). ? T_USHORT: T_ULONG)) == offsize) {
+ if (EVAL_IS_NPTR (pv) || EVAL_IS_NPTR32 (pv)) {
+ return (TRUE);
+ }
+ else {
+ addrStk.addr.off += offsize;
+ if (PutDebuggeeBytes (addrStk, sizeof (_segment),
+ (char FAR *)&EVAL_PTR_SEG (pv), T_SEGMENT) == sizeof (_segment)) {
+ return (TRUE);
+ }
+ }
+ }
+ }
+ else {
+ if (PutDebuggeeBytes (addrStk, pa->vallen,
+ (char FAR *)&EVAL_VAL (pv), EVAL_TYP(pv)) == (UINT)pa->vallen) {
+ return (TRUE);
+ }
+ }
+ pExState->err_num = ERR_PTRACE;
+ return (FALSE);
+}
+
+
+
+/** PushOffset - push address value for pascal and fastcall
+ *
+ * fSuccess = PushOffset (offset, pspReg, pmaxSP, size);
+ *
+ * Entry offset = offset from user's SP of return value
+ * pspReg = pointer to register structure for SP
+ * pmaxSP = pointer to location to store maximum SP relative offset
+ * size = size in bytes of value to be pushed
+ *
+ * Exit
+ *
+ * Returns TRUE if offset pushed
+ * FALSE if error
+ *
+ * Note Can be used to push segment also
+ */
+
+
+LOCAL bool_t NEAR PASCAL PushOffset (UOFFSET offset, SHREG FAR *pspReg,
+ UOFFSET FAR *pmaxSP, uint size)
+{
+ ADDR addrStk = {0};
+
+ *pmaxSP += size;
+ addrStk.addr.seg = pExState->frame.SS;
+ if (size == 2) {
+ addrStk.addr.off = pspReg->Byte2 - *pmaxSP;
+ } else {
+ addrStk.addr.off = pspReg->Byte4 - *pmaxSP;
+ }
+ if (PutDebuggeeBytes (addrStk, size, (char FAR *)&offset,
+ T_USHORT) == size) {
+ return (TRUE);
+ }
+ else {
+ pExState->err_num = ERR_PTRACE;
+ return (FALSE);
+ }
+}
+
+
+
+
+/*** StructElem - Extract a structure element from stack
+ *
+ * fSuccess = StructElem (bn)
+ *
+ * Entry bn = based pointer to operator node
+ * ST = address of struct (initial this address)
+ *
+ * Exit ST = value node for member
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL StructElem (bnode_t bnOp)
+{
+ peval_t pvOp;
+ peval_t pvR;
+ bnode_t bnR;
+ char FAR *pS;
+
+ pvOp = &pnodeOfbnode(bnOp)->v[0];
+ bnR = NODE_RCHILD (pnodeOfbnode(bnOp));
+ pvR = &pnodeOfbnode(bnR)->v[0];
+ if (EVAL_IS_MEMBER (pvOp) == FALSE) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ return (FALSE);
+ }
+ SetNodeType (ST, EVAL_TYP (pvR));
+ EVAL_VALLEN (ST) = (ushort)TypeSize (ST);
+ pS = (char FAR *)&EVAL_VAL (ST);
+ pS += MEMBER_OFFSET (pvOp);
+ _fmemmove (&EVAL_VAL (ST), pS, EVAL_VALLEN (ST));
+ return (TRUE);
+}
+
+
+
+
+
+/*** StructEval - Perform a structure access (., ->, ::, .*, ->*)
+ *
+ * fSuccess = StructEval (bn)
+ *
+ * Entry bn = based pointer to operator node
+ * ST = address of struct (initial this address)
+ *
+ * Exit ST = value node for member
+ *
+ * Returns TRUE if successful
+ * FALSE if error
+ *
+ */
+
+
+LOCAL bool_t NEAR FASTCALL StructEval (bnode_t bn)
+{
+ peval_t pv;
+ peval_t pvR;
+ bnode_t bnR;
+ CV_typ_t typ;
+ bool_t retval;
+ eval_t evalT;
+ peval_t pvT;
+
+ if (EVAL_IS_REF (ST)) {
+ if (!FetchOp (ST)) {
+ return (FALSE);
+ }
+ EVAL_IS_REF (ST) = FALSE;
+ }
+
+ // point to the eval_t field of the operator node. This field will
+ // contain the data needed to adjust the this pointer (*ST). For
+ // any structure reference (., ->, ::, .*, ->*), the stack top is
+ // the initial value of the this pointer
+
+ pv = &pnodeOfbnode(bn)->v[0];
+ DASSERT (EVAL_IS_MEMBER (pv));
+ if (MEMBER_THISEXPR (pv) == 0) {
+ *pvThis = *ST;
+ }
+ else if (Eval ((bnode_t)MEMBER_THISEXPR (pv)) == FALSE) {
+ return (FALSE);
+ }
+ if ((MEMBER_VBASE (pv) == TRUE) || (MEMBER_IVBASE (pv) == TRUE)) {
+ if (CalcThisExpr (MEMBER_VBPTR (pv), MEMBER_VBPOFF (pv),
+ MEMBER_VBIND (pv), MEMBER_TYPE (pv)) == FALSE) {
+ return (FALSE);
+ }
+ }
+ *ST = *pvThis;
+ if (!OP_IS_IDENT (NODE_OP (pnodeOfbnode(NODE_RCHILD (pnodeOfbnode(bn)))))) {
+ if ((retval = EvalRChild (bn)) == FALSE) {
+ return (FALSE);
+ }
+ }
+ else {
+ bnR = NODE_RCHILD (pnodeOfbnode(bn));
+ pvR = &pnodeOfbnode(bnR)->v[0];
+ if (EVAL_IS_STMEMBER (pvR)) {
+ *ST = *pvR;
+ return (TRUE);
+ }
+ else if (EVAL_IS_METHOD (pvR)) {
+ if ((FCN_PROPERTY (pvR) == CV_MTvirtual) ||
+ (FCN_PROPERTY (pvR) == CV_MTintro)) {
+ pvT = &evalT;
+ *pvT = *pvThis;
+ SetNodeType (pvT, FCN_VFPTYPE (pvR));
+ if (VFuncAddress (pvT, (FCN_VTABIND (pvR))) == FALSE) {
+ return (FALSE);
+ }
+ else {
+ *ST = *pvR;
+ EVAL_SYM (ST) = EVAL_PTR (pvT);
+ }
+ }
+ else {
+ *ST = *pvR;
+ }
+ return (TRUE);
+ }
+ else {
+ EVAL_SYM_OFF (ST) += MEMBER_OFFSET (pv);
+ typ = EVAL_TYP (pvR);
+ return (SetNodeType (ST, typ));
+ }
+ }
+}
+
+
+
+/** VFuncAddress - compute virtual function address
+ *
+ * fSuccess = VFuncAddress (pv, index)
+ *
+ * Entry pv = pointer to pointer node to adjust
+ * index = vtshape table index
+ * pvThis = initial this pointer
+ *
+ * Exit pv = adjusted pointer
+ *
+ * Returns TRUE if adjustment made
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR PASCAL VFuncAddress (peval_t pv, ulong index)
+{
+ eval_t evalT;
+ peval_t pvT;
+ plfVTShape pShape;
+ uint desc;
+ ulong i;
+ ushort shape;
+ ulong ob;
+
+ pvT = &evalT;
+ *pvT = *pv;
+ SetNodeType (pvT, PTR_UTYPE (pvT));
+ EVAL_STATE (pvT) = EV_lvalue;
+ if (!EVAL_IS_VTSHAPE (pvT)) {
+ // the only way we should get array referencing on a pointer
+ // is if the pointer is a vfuncptr.
+
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ if (!EvalUtil (OP_fetch, pv, NULL, EU_LOAD)) {
+ return (FALSE);
+ }
+ CLEAR_EVAL_FLAGS (pv);
+ EVAL_SYM_OFF (pv) = EVAL_PTR_OFF (pv);
+ EVAL_SYM_SEG (pv) = EVAL_PTR_SEG (pv);
+ EVAL_STATE (pv) = EV_lvalue;
+ EVAL_IS_ADDR (pv) = TRUE;
+ EVAL_IS_PTR (pv) = TRUE;
+
+ // now walk down the descriptor list, incrementing the pointer
+ // address by the size of the entry described by the shape table
+
+ pShape = (plfVTShape)(&((TYPPTR)MHOmfLock ((HDEP)EVAL_TYPDEF (pvT)))->leaf);
+ for (i = 0, ob = 0; ob < index; i++) {
+ shape = pShape->desc[i >> 1];
+ desc = (shape >> ((~i & 1) * 4)) & 0x0f;
+ switch (desc) {
+ case CV_VTS_near:
+ EVAL_SYM_OFF (pv) += sizeof (CV_uoff16_t);
+ ob += sizeof(CV_uoff16_t);
+ break;
+
+ case CV_VTS_far:
+ EVAL_SYM_OFF (pv) += sizeof (CV_uoff16_t) + sizeof (_segment);
+ ob += sizeof (CV_uoff16_t) + sizeof (_segment);
+ break;
+
+ case CV_VTS_near32:
+ EVAL_SYM_OFF (pv) += sizeof (CV_uoff32_t);
+ ob += sizeof (CV_uoff32_t);
+ break;
+
+ case CV_VTS_far32:
+ EVAL_SYM_OFF (pv) += sizeof (CV_uoff32_t) + sizeof(_segment);
+ ob += sizeof (CV_uoff32_t) + sizeof(_segment);
+ break;
+
+ default:
+ DASSERT (FALSE);
+ MHOmfUnLock ((HDEP)EVAL_TYPDEF (pvT));
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ }
+ shape = pShape->desc[i >> 1];
+ desc = (shape >> ((~i & 1) * 4)) & 0x0f;
+ MHOmfUnLock ((HDEP)EVAL_TYPDEF (pvT));
+ switch (desc) {
+ case CV_VTS_near:
+ EVAL_PTRTYPE (pv) = CV_PTR_NEAR;
+ break;
+
+ case CV_VTS_far:
+ EVAL_PTRTYPE (pv) = CV_PTR_FAR;
+ break;
+
+ case CV_VTS_near32:
+ EVAL_PTRTYPE (pv) = CV_PTR_NEAR32;
+ break;
+
+ case CV_VTS_far32:
+ EVAL_PTRTYPE (pv) = CV_PTR_FAR32;
+ break;
+
+ default:
+ return (FALSE);
+ }
+ if (EvalUtil (OP_fetch, pv, NULL, EU_LOAD)) {
+ CLEAR_EVAL_FLAGS (pv);
+ EVAL_IS_ADDR (pv) = TRUE;
+ EVAL_IS_FCN (pv) = TRUE;
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/private/windbg/eecan/debexpr.h b/private/windbg/eecan/debexpr.h
new file mode 100644
index 000000000..238316356
--- /dev/null
+++ b/private/windbg/eecan/debexpr.h
@@ -0,0 +1,1247 @@
+/*** debexpr.h - include file for expression evaluator
+ *
+ * Constants, structures and function prototypes required by
+ * expression evaluator.
+ *
+ */
+
+
+// define DASSERT macro
+#if DBG
+#include "cxassert.h"
+#define DASSERT(ex) assert(ex)
+#define NOTTESTED(ex) assert(ex)
+#else
+#define DASSERT(ex)
+#define NOTTESTED(ex)
+#endif
+
+// define the default string buffers for the API formatting routines
+
+#define TYPESTRMAX 256 // EEGetTypeFromTM maximum string length
+#define FMTSTRMAX 256 // EEGetValueFromTM maximum string length
+#define ERRSTRMAX 256 // EEGetError maximum string length
+#define FCNSTRMAX 256 // maximum formatted function prototype
+
+#define MAXRETURN 1000 // maximum structure return from fcn call
+#define ESTACK_DEFAULT 10 // default evaluation stack size
+#define HSYML_SIZE 0xFFFF // size of HSYM list buffer
+
+#define BIND_fForceBind 0x01 // TRUE if bind is forced
+#define BIND_fEnableProlog 0x02 // TRUE if prolog search enabled
+#define BIND_fSupOvlOps 0x04 // TRUE if overloaded operators suppressed
+#define BIND_fSupBase 0x08 // TRUE if base class searching suppressed
+
+#define HSYM_MARKER 0x01 // in expr, indicates that an HSYM follows
+#define HSYM_CODE_LEN 0x08 // length of encoded HSYM
+
+// Number of operators supported
+
+enum {
+#define OPCNT(name, val) name = val
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk)
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+
+
+// Error message ordinals
+
+typedef enum {
+#define ERRDAT(name, mes) name,
+#include "errors.h"
+#undef ERRDAT
+ ERR_MAX // MUST BE LAST NUMBER
+} ERRNUM;
+
+// Operator type.
+
+typedef enum {
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk) op,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+
+ OP_badtok = 255
+} op_t;
+
+
+// Operator class.
+
+
+typedef enum
+{
+#define OPCNT(name, val)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk)
+#define OPCDAT(opc) opc,
+#include "debops.h"
+#undef OPCDAT
+#undef OPDAT
+#undef OPCNT
+ OPC_LAST
+} opc_t;
+
+
+
+// return enumeration from MatchType
+
+typedef enum MTYP_t {
+ MTYP_none,
+ MTYP_exact,
+ MTYP_inexact
+} MTYP_t;
+
+// Macros for determination of operator types. Relies on
+// implicit ordering of ops (see debops.h).
+
+
+#define OP_IS_IDENT(op) ((op) < OP_lparen)
+#define OP_IS_GROUP(op) (((op) == OP_lparen) || ((op) == OP_rparen))
+#define OP_IS_UNARY(op) (((op) >= OP_bang) && ((op) <= OP_context))
+#define OP_IS_BINARY(op) ((op) >= OP_function)
+
+
+// Token Structure Definition
+// This structure is built by the lexer and is used to hold information in
+// the shift/reduce stack until the data can be transerred to the parse
+// tree in debtree.c
+
+// M00WARN: This structure MUST be kept in sync with that in DEBLEXER.ASM
+// value structure for constant nodes in parse tree or for all elements
+// in evaluation stack at evaluation time.
+
+
+typedef union val_t {
+ char vchar;
+ uchar vuchar;
+ short vshort;
+ ushort vushort;
+ long vlong;
+ ulong vulong;
+ LARGE_INTEGER vquad;
+ ULARGE_INTEGER vuquad;
+ float vfloat;
+ double vdouble;
+ FLOAT10 vldouble;
+ ADDR vptr;
+} val_t;
+typedef val_t *pval_t;
+
+typedef struct token_t {
+ op_t opTok; // Token type: OP_ident, OP_dot, etc.
+ char *pbTok; // Pointer to start of actual token
+ char *pbEnd; // pointer to last character + 1 of token
+ ushort iTokStart; // index of token start calculated from pbTok
+ uchar cbTok; // Size of token (in bytes)
+ CV_typ_t typ; // Type of constant token
+ val_t val; // Value of constant token
+} token_t;
+typedef token_t *ptoken_t;
+
+// Macros to access values of a parse token
+
+#define VAL_VAL(pv) ((pv)->val)
+#define VAL_CHAR(pv) ((pv)->val.vchar)
+#define VAL_UCHAR(pv) ((pv)->val.vuchar)
+#define VAL_SHORT(pv) ((pv)->val.vshort)
+#define VAL_USHORT(pv) ((pv)->val.vushort)
+#define VAL_LONG(pv) ((pv)->val.vlong)
+#define VAL_ULONG(pv) ((pv)->val.vulong)
+#define VAL_QUAD(pv) ((pv)->val.vquad)
+#define VAL_UQUAD(pv) ((pv)->val.vuquad)
+#define VAL_FLOAT(pv) ((pv)->val.vfloat)
+#define VAL_DOUBLE(pv) ((pv)->val.vdouble)
+#define VAL_LDOUBLE(pv) ((pv)->val.vldouble)
+
+
+
+//------------------- Node Structure Definition -------------------
+
+enum fcn_call {
+ FCN_C = 1,
+ FCN_PASCAL,
+ FCN_FAST,
+ FCN_PCODE,
+ FCN_STD,
+ FCN_MIPS,
+ FCN_THIS,
+ FCN_ALPHA,
+ FCN_PPC
+};
+
+
+enum eval_op {
+ EV_type = 1, // node represents a type - no address or value
+ EV_hsym, // node represents a handle to symbol
+ EV_constant, // node represents a constant - no address
+ EV_lvalue, // node represents a value - has value
+ EV_rvalue // node represents an address
+};
+
+
+
+
+// The following bit field describes the contents of an evaluation node.
+// This information is contained in a parse tree node after the bind phase
+// or in elements on the evaluation stack during bind or evaluation
+// If a bitfield is set, the the corresponding vdata_t union element will
+// contain the additional information describing the data in the node. For
+// example, if isptr is set, then vbits.ptr.pIndex contains the type index of
+// the object pointed to.
+
+typedef union vbits_t {
+ struct {
+ uchar ptrtype :5; // type of pointer
+ uchar isptr :1; // true if node is a pointer
+ uchar ispmember :1; // true if node is a pointer to member
+ uchar ispmethod :1; // true if node is a pointer to method
+ uchar isref :1; // true if node contains a reference
+ uchar isdptr :1; // true if node is a data pointer
+ uchar isaddr :1; // true if node is an address
+ uchar isdata :1; // true if node references data
+ uchar isreg :1; // true if node references a register
+ uchar isclass :1; // true if node is a class
+ uchar isenum :1; // true if node is an enumeration
+ uchar isbitf :1; // true if node is a bitfield
+ uchar isfcn :1; // true if node is a function
+ uchar isambiguous :1; // true if function is ambiguous
+ uchar isarray :1; // true if node is an arrary
+ uchar isbprel :1; // true if node is bp relative symbol
+ uchar isregrel :1; // true if node is register relative symbol
+ uchar istlsrel :1; // true if node is thread local storage symbol
+ uchar ismember :1; // true if node is member
+ uchar isstmember :1; // true if node is static member
+ uchar isvptr :1; // true if node is a vtable pointer
+ uchar ismethod :1; // true if node is a method
+ uchar isstmethod :1; // true if node is a static method
+ uchar isvtshape :1; // true if node is a virtual fcn shape table
+ uchar isconst :1; // true if constant
+ uchar isvolatile :1; // true if volatile
+ uchar islabel :1; // true if code label
+ uchar iscurpc :1; // true if current program counter
+ uchar access :2; // access control if class member
+ } bits;
+} vbits_t;
+
+// value type flags in identifier node in parse tree or all elements
+// in the evaluation stack at evaluation time
+
+typedef union vdata_t {
+ struct {
+ ushort utype; // underlying type of pointer
+ ushort bseg; // base segment
+ ushort symtype; // symbol type of base
+ ADDR addr; // address of base
+ ushort btype; // type index of base on type
+ ushort stype; // type index of based symbol
+ CV_typ_t pmclass; // containing class for pointer to member
+ ushort pmenum; // enumeration specifying pm format
+ long arraylen; // length of array in bytes
+ long thisadjust; // adjustor for this pointer
+ struct {
+ ushort ireg; // System register values
+ bool_t hibyte; // TRUE if register is high byte
+ } reg;
+ } ptr;
+
+ struct {
+ struct {
+ ushort fGlobType :1; // TRUE if bscope left member is global type
+ } flags;
+ ushort cblen; // number of bytes in class
+ short count; // number of elements in class
+ CV_typ_t fList; // type index of field list
+ CV_typ_t dList; // type index of derivation list
+ CV_typ_t utype; // underlying type if enum
+ CV_typ_t vshape; // type index of vshape table for this class
+ CV_prop_t property; // class property mask
+ } classd;
+
+ struct {
+ struct {
+ uchar fGlobType :1; // TRUE if bscope left member is global type
+ } flags;
+ short count; // number of elements in class
+ CV_typ_t fList; // type index of field list
+ CV_typ_t utype; // underlying type if enum
+ CV_prop_t property; // class property mask
+ } enumd;
+
+ struct {
+ ushort len; // length of bitfield
+ ushort pos; // position of bitfield
+ ushort type; // type of bitfield
+ } bit;
+
+ struct {
+ enum fcn_call call; // calling sequence indices
+ struct { // calling sequence flags
+ uchar farcall :1; // far call if true
+ uchar callerpop :1; // caller pop if true
+ uchar varargs :1; // variable arguments if true
+ uchar defargs :1; // default arguments if true
+ uchar notpresent :1; // not present if true
+ } flags;
+ CV_fldattr_t attr; // attribute if method
+ CV_off32_t thisadjust; // logical this adjustor
+ CV_typ_t rvtype; // type index of function return value
+ short cparam; // number of parameters
+ CV_typ_t parmtype; // type index of parameter list
+ CV_typ_t classtype; // class type index if member function
+ CV_typ_t thistype; // this type index if member function
+ UOFFSET vtabind; // vtable index if virtual method
+ CV_typ_t vfptype; // type index of vfuncptr if virtual method
+ } fcn;
+
+ struct {
+ ushort ireg; // System register values
+ bool_t hibyte; // TRUE if register is high byte
+ } reg;
+
+ struct {
+ struct {
+ ushort fbase :1; // true if direct base
+ ushort fvbase :1; // true if virtual base
+ ushort fivbase :1; // true if indirect virtual base
+ } flags;
+ CV_typ_t type; // type index of member
+ CV_fldattr_t access; // field attribute
+ OFFSET offset; // offset from containing class address point
+ CV_typ_t vbptr; // virtual base pointer type
+ OFFSET vbpoff; // offset from this pointer to virtual base pointer
+ ushort vbind; // virtual base index in vb pointer table
+ CV_typ_t thistype; // type index of this pointer
+ uint thisexpr; // node to start this calculation if non-zero
+ } member;
+
+ struct {
+ UOFFSET offset; // offset of member in class
+ } vptr;
+
+ struct {
+ ushort count; // number of entries in shape table
+ } vtshape;
+
+ struct {
+ char count; // number of overloads for function name
+ CV_typ_t type; // type index of method list
+ } method;
+} vdata_t;
+
+
+
+// Evaluation element
+// This contains all of the information known about a constant or identifier
+// in the bound parse tree or all elements in the evaluation stack at bind or
+// evaluation time
+
+
+typedef struct eval_t {
+ ushort state; // evaluation state EV_lvalue, EV_rvalue, EV_constant
+ CV_typ_t type; // type index
+ ushort iTokStart; // offset of token in command string
+ uchar cbTok; // length of token
+ ADDR addr; // address of symbol
+ HMOD mod; // handle to module
+ HSYM hSym; // handle to symbol structure
+ HTYPE typdef; // handle to typdef structure
+ vbits_t flags; //
+ vdata_t data; //
+ ushort regrel; // REGREL index off of register
+ ushort vallen; // length of value in bytes
+ val_t val; // value of node
+} eval_t;
+typedef eval_t *peval_t; // pointer to evaluation element
+typedef eval_t *neval_t; // pointer to evaluation element
+
+// The following macros are used to test and set values in an evaluation
+// element. pv is a far pointer to an evaluation element either in the
+// syntax tree or on the evaluation stack.
+
+#define CLEAR_EVAL(pv) _fmemset(pv, 0, sizeof (eval_t))
+
+#define EVAL_STATE(pv) ((pv)->state)
+#define EVAL_ITOK(pv) ((pv)->iTokStart)
+#define EVAL_CBTOK(pv) ((pv)->cbTok)
+#define EVAL_TYPDEF(pv) ((pv)->typdef)
+#define EVAL_SYM(pv) ((pv)->addr)
+#define EVAL_SYM_ADDR(pv) ((pv)->addr.addr)
+#define EVAL_SYM_SEG(pv) ((pv)->addr.addr.seg)
+#define EVAL_SYM_OFF(pv) ((pv)->addr.addr.off)
+#define EVAL_SYM_EMI(pv) ((pv)->addr.emi)
+#define EVAL_SYM_MODE(pv) ((pv)->addr.mode)
+
+#define EVAL_SYM_IS32(pv) (ADDR_IS_OFF32(EVAL_SYM(pv)))
+#define EVAL_SYM_ISFLAT(pv) (ADDR_IS_FLAT(EVAL_SYM(pv)))
+#define EVAL_HSYM(pv) ((pv)->hSym)
+#define EVAL_MOD(pv) ((pv)->mod)
+#define EVAL_VALLEN(pv) ((pv)->vallen)
+
+
+#define EVAL_TYP(pv) ((pv)->type)
+#define EVAL_FLAGS(pv) ((pv)->flags)
+#define EVAL_DATA(pv) ((pv)->data)
+#define EVAL_VAL(pv) ((pv)->val)
+#define EVAL_PVAL(pv) (&(EVAL_VAL(pv)))
+#define EVAL_CHAR(pv) ((pv)->val.vchar)
+#define EVAL_UCHAR(pv) ((pv)->val.vuchar)
+#define EVAL_SHORT(pv) ((pv)->val.vshort)
+#define EVAL_USHORT(pv) ((pv)->val.vushort)
+#define EVAL_LONG(pv) ((pv)->val.vlong)
+#define EVAL_QUAD(pv) (* ((PLARGE_INTEGER)&( (pv)->val.vdouble)))
+#define EVAL_UQUAD(pv) (* ((PULARGE_INTEGER)&( (pv)->val.vdouble)))
+#define EVAL_ULONG(pv) ((pv)->val.vulong)
+#define EVAL_FLOAT(pv) ((pv)->val.vfloat)
+#define EVAL_DOUBLE(pv) ((pv)->val.vdouble)
+#define EVAL_LDOUBLE(pv) ((pv)->val.vldouble)
+#define EVAL_PTR(pv) ((pv)->val.vptr)
+#define EVAL_PTR_ADDR(pv) ((pv)->val.vptr.addr)
+#define EVAL_PTR_OFF(pv) ((pv)->val.vptr.addr.off)
+#define EVAL_PTR_SEG(pv) ((pv)->val.vptr.addr.seg)
+#define EVAL_PTR_EMI(pv) ((pv)->val.vptr.emi)
+#define EVAL_PTR_MODE(pv) ((pv)->val.vptr.mode)
+
+// Macros for accessing flag bits in node structure
+// This data is almost always from the type and typedef record of the node
+
+#define CLEAR_EVAL_FLAGS(pv) _fmemset(&(pv)->flags, 0, sizeof((pv)->flags))
+#define EVAL_IS_REG(pv) ((pv)->flags.bits.isreg)
+#define EVAL_IS_DATA(pv) ((pv)->flags.bits.isdata)
+#define EVAL_IS_CLASS(pv) ((pv)->flags.bits.isclass)
+#define EVAL_IS_ENUM(pv) ((pv)->flags.bits.isenum)
+#define EVAL_IS_ARRAY(pv) ((pv)->flags.bits.isarray)
+#define EVAL_IS_REF(pv) ((pv)->flags.bits.isref)
+#define EVAL_IS_BITF(pv) ((pv)->flags.bits.isbitf)
+#define EVAL_IS_ADDR(pv) ((pv)->flags.bits.isaddr)
+#define EVAL_IS_FCN(pv) ((pv)->flags.bits.isfcn)
+#define EVAL_IS_BPREL(pv) ((pv)->flags.bits.isbprel)
+#define EVAL_IS_REGREL(pv) ((pv)->flags.bits.isregrel)
+#define EVAL_IS_TLSREL(pv) ((pv)->flags.bits.istlsrel)
+#define EVAL_IS_STMEMBER(pv) ((pv)->flags.bits.isstmember)
+#define EVAL_IS_MEMBER(pv) ((pv)->flags.bits.ismember)
+#define EVAL_IS_METHOD(pv) ((pv)->flags.bits.ismethod)
+#define EVAL_IS_STMETHOD(pv) ((pv)->flags.bits.isstmethod)
+#define EVAL_IS_VPTR(pv) ((pv)->flags.bits.isvptr)
+#define EVAL_IS_AMBIGUOUS(pv) ((pv)->flags.bits.isambiguous)
+#define EVAL_IS_CONST(pv) ((pv)->flags.bits.isconst)
+#define EVAL_IS_VOLATILE(pv) ((pv)->flags.bits.isvolatile)
+#define EVAL_IS_LABEL(pv) ((pv)->flags.bits.islabel)
+#define EVAL_IS_VTSHAPE(pv) ((pv)->flags.bits.isvtshape)
+
+#define EVAL_IS_PTR(pv) ((pv)->flags.bits.isptr)
+#define EVAL_IS_PMEMBER(pv) ((pv)->flags.bits.ispmember)
+#define EVAL_IS_PMETHOD(pv) ((pv)->flags.bits.ispmethod)
+#define EVAL_IS_DPTR(pv) ((pv)->flags.bits.isdptr)
+#define EVAL_IS_BASED(pv) (((pv)->flags.bits.ptrtype >= CV_PTR_BASE_SEG) && ((pv)->flags.bits.ptrtype <= CV_PTR_BASE_SELF))
+#define EVAL_PTRTYPE(pv) ((pv)->flags.bits.ptrtype)
+#define EVAL_ACCESS(pv) ((pv)->flags.bits.access)
+#define EVAL_IS_NPTR(pv) (((pv)->flags.bits.ptrtype==CV_PTR_NEAR)\
+ &&((pv)->flags.bits.isarray==FALSE)&&((pv)->flags.bits.isfcn==FALSE))
+#define EVAL_IS_FPTR(pv) (((pv)->flags.bits.ptrtype==CV_PTR_FAR) \
+ &&((pv)->flags.bits.isarray==FALSE)&&((pv)->flags.bits.isfcn==FALSE))
+#define EVAL_IS_NPTR32(pv) (((pv)->flags.bits.ptrtype==CV_PTR_NEAR32)\
+ &&((pv)->flags.bits.isarray==FALSE)&&((pv)->flags.bits.isfcn==FALSE))
+#define EVAL_IS_FPTR32(pv) (((pv)->flags.bits.ptrtype==CV_PTR_FAR32) \
+ &&((pv)->flags.bits.isarray==FALSE)&&((pv)->flags.bits.isfcn==FALSE))
+#define EVAL_IS_HPTR(pv) (((pv)->flags.bits.ptrtype==CV_PTR_HUGE)&&((pv)->flags.bits.isarray==FALSE)&&((pv)->flags.bits.isfcn==FALSE))
+#define EVAL_IS_BSEG(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_SEG)
+#define EVAL_IS_BVAL(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_VAL)
+#define EVAL_IS_BSEGVAL(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_SEGVAL)
+#define EVAL_IS_BADDR(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_ADDR)
+#define EVAL_IS_BSEGADDR(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_SEGADDR)
+#define EVAL_IS_BTYPE(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_TYPE)
+#define EVAL_IS_BSELF(pv) ((pv)->flags.bits.ptrtype==CV_PTR_BASE_SELF)
+#define EVAL_IS_CURPC(pv) ((pv)->flags.bits.iscurpc)
+
+
+// Macros for accessing flag specified data in node structure
+// This data is almost always from the type and typedef record of the node
+
+#define EVAL_REG(pv) ((pv)->data.reg.ireg)
+#define EVAL_IS_HIBYTE(pv) ((pv)->data.reg.hibyte)
+
+#define EVAL_REGREL(pv) ((pv)->regrel)
+
+#define EVAL_IS_NFCN(pv) (!((pv)->data.fcn.flags.farcall))
+#define EVAL_IS_FFCN(pv) (((pv)->data.fcn.flags.farcall))
+
+
+#define PTR_UTYPE(pv) (((pv)->data.ptr.utype))
+#define PTR_BSEG(pv) (((pv)->data.ptr.bseg))
+#define PTR_BSYM(pv) (((pv)->data.ptr.bSym))
+#define PTR_BTYPE(pv) (((pv)->data.ptr.btype))
+#define PTR_STYPE(pv) (((pv)->data.ptr.stype))
+#define PTR_BSYMTYPE(pv) (((pv)->data.ptr.symtype))
+#define PTR_ADDR(pv) (((pv)->data.ptr.addr))
+#define PTR_THISADJUST(pv) (((pv)->data.ptr.thisadjust))
+#define PTR_PMCLASS(pv) (((pv)->data.ptr.pmclass))
+#define PTR_PMENUM(pv) (((pv)->data.ptr.pmenum))
+#define PTR_ARRAYLEN(pv) (((pv)->data.ptr.arraylen))
+#define PTR_REG_IREG(pv) (((pv)->data.ptr.reg.ireg))
+
+#define CLASS_LEN(pv) (((pv)->data.classd.cblen))
+#define CLASS_COUNT(pv) (((pv)->data.classd.count))
+#define CLASS_FIELD(pv) (((pv)->data.classd.fList))
+#define CLASS_DERIVE(pv) (((pv)->data.classd.dList))
+#define CLASS_PROP(pv) (((pv)->data.classd.property))
+#define CLASS_UTYPE(pv) (((pv)->data.classd.utype))
+#define CLASS_VTSHAPE(pv) (((pv)->data.classd.vshape))
+#define CLASS_GLOBALTYPE(pv) (((pv)->data.classd.flags.fGlobType))
+
+#define ENUM_COUNT(pv) (((pv)->data.enumd.count))
+#define ENUM_FIELD(pv) (((pv)->data.enumd.fList))
+#define ENUM_PROP(pv) (((pv)->data.enumd.property))
+#define ENUM_UTYPE(pv) (((pv)->data.enumd.utype))
+#define ENUM_GLOBALTYPE(pv) (((pv)->data.enumd.flags.fGlobType))
+
+#define BITF_LEN(pv) (((pv)->data.bit.len))
+#define BITF_POS(pv) (((pv)->data.bit.pos))
+#define BITF_UTYPE(pv) (((pv)->data.bit.type))
+
+#define FCN_CALL(pv) (((pv)->data.fcn.call))
+#define FCN_FARCALL(pv) (((pv)->data.fcn.flags.farcall))
+#define FCN_CALLERPOP(pv) (((pv)->data.fcn.flags.callerpop))
+#define FCN_VARARGS(pv) (((pv)->data.fcn.flags.varargs))
+#define FCN_DEFARGS(pv) (((pv)->data.fcn.flags.defargs))
+#define FCN_NOTPRESENT(pv) (((pv)->data.fcn.flags.notpresent))
+#define FCN_RETURN(pv) (((pv)->data.fcn.rvtype))
+#define FCN_PCOUNT(pv) (((pv)->data.fcn.cparam))
+#define FCN_PINDEX(pv) (((pv)->data.fcn.parmtype))
+#define FCN_CLASS(pv) (((pv)->data.fcn.classtype))
+#define FCN_THIS(pv) (((pv)->data.fcn.thistype))
+#define FCN_ATTR(pv) (((pv)->data.fcn.attr))
+#define FCN_ACCESS(pv) (((pv)->data.fcn.attr.access))
+#define FCN_PROPERTY(pv) (((pv)->data.fcn.attr.mprop))
+#define FCN_VTABIND(pv) (((pv)->data.fcn.vtabind))
+#define FCN_VFPTYPE(pv) (((pv)->data.fcn.vfptype))
+#define FCN_THISADJUST(pv) (((pv)->data.fcn.thisadjust))
+
+#define MEMBER_OFFSET(pv) (((pv)->data.member.offset))
+#define MEMBER_THISTYPE(pv) (((pv)->data.member.thistype))
+#define MEMBER_THISEXPR(pv) (((pv)->data.member.thisexpr))
+#define MEMBER_TYPE(pv) (((pv)->data.member.type))
+#define MEMBER_ACCESS(pv) (((pv)->data.member.access))
+#define MEMBER_BASE(pv) (((pv)->data.member.flags.fbase))
+#define MEMBER_VBASE(pv) (((pv)->data.member.flags.fvbase))
+#define MEMBER_IVBASE(pv) (((pv)->data.member.flags.fivbase))
+#define MEMBER_VBPTR(pv) (((pv)->data.member.vbptr))
+#define MEMBER_VBPOFF(pv) (((pv)->data.member.vbpoff))
+#define MEMBER_VBIND(pv) (((pv)->data.member.vbind))
+
+#define VTSHAPE_COUNT(pv) (((pv)->data.vtshape.count))
+
+// Near versions of the above macros. These macros can be used when it is
+// known that the evaluation node is in DS
+
+#define N_CLEAR_EVAL(nv) _nmemset(nv, 0, sizeof (eval_t))
+
+#define N_EVAL_STATE(nv) ((nv)->state)
+#define N_EVAL_ITOK(nv) ((nv)->iTokStart)
+#define N_EVAL_CBTOK(nv) ((nv)->cbTok)
+#define N_EVAL_TYPDEF(nv) ((nv)->typdef)
+#define N_EVAL_SYM(nv) ((nv)->addr)
+#define N_EVAL_SYM_ADDR(nv) ((nv)->addr.addr)
+#define N_EVAL_SYM_SEG(nv) ((nv)->addr.addr.seg)
+#define N_EVAL_SYM_OFF(nv) ((nv)->addr.addr.off)
+#define N_EVAL_SYM_EMI(nv) ((nv)->addr.emi)
+#define N_EVAL_SYM_MODE(nv) ((nv)->addr.mode)
+#define N_EVAL_HSYM(nv) ((nv)->hSym)
+#define N_EVAL_MOD(nv) ((nv)->mod)
+#define N_EVAL_VALLEN(nv) ((nv)->vallen)
+
+
+#define N_EVAL_TYP(nv) ((nv)->type)
+#define N_EVAL_FLAGS(nv) ((nv)->flags)
+#define N_EVAL_DATA(nv) ((nv)->data)
+#define N_EVAL_VAL(nv) ((nv)->val)
+#define N_EVAL_PVAL(nv) (&(N_EVAL_VAL(nv)))
+#define N_EVAL_CHAR(nv) ((nv)->val.vchar)
+#define N_EVAL_UCHAR(nv) ((nv)->val.vuchar)
+#define N_EVAL_SHORT(nv) ((nv)->val.vshort)
+#define N_EVAL_USHORT(nv) ((nv)->val.vushort)
+#define N_EVAL_LONG(nv) ((nv)->val.vlong)
+#define N_EVAL_ULONG(nv) ((nv)->val.vulong)
+#define N_EVAL_FLOAT(nv) ((nv)->val.vfloat)
+#define N_EVAL_DOUBLE(nv) ((nv)->val.vdouble)
+#define N_EVAL_LDOUBLE(nv) ((nv)->val.vldouble)
+#define N_EVAL_PTR(nv) ((nv)->val.vptr)
+#define N_EVAL_PTR_ADDR(nv) ((nv)->val.vptr.addr)
+#define N_EVAL_PTR_OFF(nv) ((nv)->val.vptr.addr.off)
+#define N_EVAL_PTR_SEG(nv) ((nv)->val.vptr.addr.seg)
+#define N_EVAL_PTR_EMI(nv) ((nv)->val.vptr.emi)
+#define N_EVAL_PTR_MODE(nv) ((nv)->val.vptr.mode)
+
+// Macros for accessing flag bits in node structure
+// This data is almost always from the type and typedef record of the node
+
+#define N_CLEAR_EVAL_FLAGS(nv) _fmemset(&(nv)->flags, 0, sizeof((nv)->flags))
+#define N_EVAL_IS_REG(nv) ((nv)->flags.bits.isreg)
+#define N_EVAL_IS_DATA(nv) ((nv)->flags.bits.isdata)
+#define N_EVAL_IS_ENUM(nv) ((nv)->flags.bits.isenum)
+#define N_EVAL_IS_CLASS(nv) ((nv)->flags.bits.isclass)
+#define N_EVAL_IS_ARRAY(nv) ((nv)->flags.bits.isarray)
+#define N_EVAL_IS_REF(nv) ((nv)->flags.bits.isref)
+#define N_EVAL_IS_BITF(nv) ((nv)->flags.bits.isbitf)
+#define N_EVAL_IS_ADDR(nv) ((nv)->flags.bits.isaddr)
+#define N_EVAL_IS_FCN(nv) ((nv)->flags.bits.isfcn)
+#define N_EVAL_IS_BPREL(nv) ((nv)->flags.bits.isbprel)
+#define N_EVAL_IS_REGREL(nv) ((nv)->flags.bits.isregrel)
+#define N_EVAL_IS_TLSREL(nv) ((nv)->flags.bits.istlsrel)
+#define N_EVAL_IS_STMEMBER(nv) ((nv)->flags.bits.isstmember)
+#define N_EVAL_IS_MEMBER(nv) ((nv)->flags.bits.ismember)
+#define N_EVAL_IS_METHOD(nv) ((nv)->flags.bits.ismethod)
+#define N_EVAL_IS_STMETHOD(nv) ((nv)->flags.bits.isstmethod)
+#define N_EVAL_IS_VPTR(nv) ((nv)->flags.bits.isvptr)
+#define N_EVAL_IS_AMBIGUOUS(nv) ((nv)->flags.bits.isambiguous)
+#define N_EVAL_IS_CONST(nv) ((nv)->flags.bits.isconst)
+#define N_EVAL_IS_VOLATILE(nv) ((nv)->flags.bits.isvolatile)
+#define N_EVAL_IS_LABEL(nv) ((nv)->flags.bits.islabel)
+#define N_EVAL_IS_VTSHAPE(nv) ((nv)->flags.bits.isvtshape)
+
+#define N_EVAL_IS_PTR(nv) ((nv)->flags.bits.isptr)
+#define N_EVAL_IS_PMEMBER(nv) ((nv)->flags.bits.ispmember)
+#define N_EVAL_IS_PMETHOD(nv) ((nv)->flags.bits.ispmethod)
+#define N_EVAL_IS_DPTR(nv) ((nv)->flags.bits.isdptr)
+#define N_EVAL_IS_BASED(nv) (((nv)->flags.bits.ptrtype >= CV_PTR_BASE_SEG) && ((nv)->flags.bits.ptrtype <= CV_PTR_BASE_SELF))
+#define N_EVAL_PTRTYPE(nv) ((nv)->flags.bits.ptrtype)
+#define N_EVAL_ACCESS(nv) ((nv)->flags.bits.access)
+#define N_EVAL_IS_NPTR(nv) (((nv)->flags.bits.ptrtype==CV_PTR_NEAR)\
+ &&((nv)->flags.bits.isarray==FALSE)&&((nv)->flags.bits.isfcn==FALSE))
+#define N_EVAL_IS_FPTR(nv) (((nv)->flags.bits.ptrtype==CV_PTR_FAR) \
+ &&((nv)->flags.bits.isarray==FALSE)&&((nv)->flags.bits.isfcn==FALSE))
+#define N_EVAL_IS_NPTR32(nv) (((nv)->flags.bits.ptrtype==CV_PTR_NEAR32)\
+ &&((nv)->flags.bits.isarray==FALSE)&&((nv)->flags.bits.isfcn==FALSE))
+#define N_EVAL_IS_FPTR32(nv) (((nv)->flags.bits.ptrtype==CV_PTR_FAR32) \
+ &&((nv)->flags.bits.isarray==FALSE)&&((nv)->flags.bits.isfcn==FALSE))
+#define N_EVAL_IS_HPTR(nv) (((nv)->flags.bits.ptrtype==CV_PTR_HUGE)&&((nv)->flags.bits.isarray==FALSE)&&((nv)->flags.bits.isfcn==FALSE))
+#define N_EVAL_IS_BSEG(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_SEG)
+#define N_EVAL_IS_BVAL(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_VAL)
+#define N_EVAL_IS_BSEGVAL(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_SEGVAL)
+#define N_EVAL_IS_BADDR(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_ADDR)
+#define N_EVAL_IS_BSEGADDR(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_SEGADDR)
+#define N_EVAL_IS_BTYPE(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_TYPE)
+#define N_EVAL_IS_BSELF(nv) ((nv)->flags.bits.ptrtype==CV_PTR_BASE_SELF)
+
+// Macros for accessing flag specified data in node structure
+// This data is almost always from the type and typedef record of the node
+
+#define N_EVAL_REG(nv) ((nv)->data.reg.ireg)
+#define N_EVAL_IS_HIBYTE(nv) ((nv)->data.reg.hibyte)
+
+#define N_EVAL_IS_NFCN(nv) (!((nv)->data.fcn.flags.farcall))
+#define N_EVAL_IS_FFCN(nv) (((nv)->data.fcn.flags.farcall))
+
+
+#define N_PTR_UTYPE(nv) (((nv)->data.ptr.utype))
+#define N_PTR_BSEG(nv) (((nv)->data.ptr.bseg))
+#define N_PTR_BSYM(nv) (((nv)->data.ptr.bSym))
+#define N_PTR_BTYPE(nv) (((nv)->data.ptr.btype))
+#define N_PTR_STYPE(nv) (((nv)->data.ptr.stype))
+#define N_PTR_BSYMTYPE(nv) (((nv)->data.ptr.symtype))
+#define N_PTR_ADDR(nv) (((nv)->data.ptr.addr))
+#define N_PTR_PMCLASS(nv) (((nv)->data.ptr.pmclass))
+#define N_PTR_PMENUM(nv) (((nv)->data.ptr.pmenum))
+#define N_PTR_ARRAYLEN(nv) (((nv)->data.ptr.arraylen))
+#define N_PTR_REG_IREG(nv) (((nv)->data.ptr.reg.ireg))
+#define N_PTR_REG_HIBYTE(nv) (((nv)->data.ptr.reg.hibyte))
+
+#define N_CLASS_LEN(nv) (((nv)->data.classd.cblen))
+#define N_CLASS_COUNT(nv) (((nv)->data.classd.count))
+#define N_CLASS_FIELD(nv) (((nv)->data.classd.fList))
+#define N_CLASS_DERIVE(nv) (((nv)->data.classd.dList))
+#define N_CLASS_PROP(nv) (((nv)->data.classd.property))
+#define N_CLASS_UTYPE(nv) (((nv)->data.classd.utype))
+#define N_CLASS_VTSHAPE(nv) (((nv)->data.classd.vshape))
+#define N_CLASS_GLOBALTYPE(nv) (((nv)->data.classd.flags.fGlobType))
+
+#define N_ENUM_COUNT(nv) (((nv)->data.enumd.count))
+#define N_ENUM_FIELD(nv) (((nv)->data.enumd.fList))
+#define N_ENUM_PROP(nv) (((nv)->data.enumd.property))
+#define N_ENUM_UTYPE(nv) (((nv)->data.enumd.utype))
+#define N_ENUM_GLOBALTYPE(nv) (((nv)->data.enumd.flags.fGlobType))
+
+
+#define N_BITF_LEN(nv) (((nv)->data.bit.len))
+#define N_BITF_POS(nv) (((nv)->data.bit.pos))
+#define N_BITF_UTYPE(nv) (((nv)->data.bit.type))
+
+#define N_FCN_CALL(nv) (((nv)->data.fcn.call))
+#define N_FCN_FARCALL(nv) (((nv)->data.fcn.flags.farcall))
+#define N_FCN_CALLERPOP(nv) (((nv)->data.fcn.flags.callerpop))
+#define N_FCN_VARARGS(nv) (((nv)->data.fcn.flags.varargs))
+#define N_FCN_DEFARGS(nv) (((nv)->data.fcn.flags.defargs))
+#define N_FCN_NOTPRESENT(nv) (((nv)->data.fcn.flags.notpresent))
+#define N_FCN_RETURN(nv) (((nv)->data.fcn.rvtype))
+#define N_FCN_PCOUNT(nv) (((nv)->data.fcn.cparam))
+#define N_FCN_PINDEX(nv) (((nv)->data.fcn.parmtype))
+#define N_FCN_CLASS(nv) (((nv)->data.fcn.classtype))
+#define N_FCN_THIS(nv) (((nv)->data.fcn.thistype))
+#define N_FCN_ATTR(nv) (((nv)->data.fcn.attr))
+#define N_FCN_ACCESS(nv) (((nv)->data.fcn.attr.access))
+#define N_FCN_PROPERTY(nv) (((nv)->data.fcn.attr.mprop))
+#define N_FCN_VTABIND(nv) (((nv)->data.fcn.attr.vtabind))
+#define N_FCN_VFPTYPE(nv) (((nv)->data.fcn.vfptype))
+#define N_FCN_THISADJUST(nv) (((nv)->data.fcn.thisadjust))
+
+#define N_MEMBER_OFFSET(nv) (((nv)->data.member.offset))
+#define N_MEMBER_THISTYPE(nv) (((nv)->data.member.thistype))
+#define N_MEMBER_THISEXPR(nv) (((nv)->data.member.thisexpr))
+#define N_MEMBER_TYPE(nv) (((nv)->data.member.type))
+#define N_MEMBER_ACCESS(nv) (((nv)->data.member.access))
+#define N_MEMBER_BASE(nv) (((nv)->data.member.flags.fbase))
+#define N_MEMBER_VBASE(nv) (((nv)->data.member.flags.fvbase))
+#define N_MEMBER_IVBASE(nv) (((nv)->data.member.flags.fivbase))
+#define N_MEMBER_VBPTR(nv) (((nv)->data.member.vbptr))
+#define N_MEMBER_VBPOFF(nv) (((nv)->data.member.vbpoff))
+#define N_MEMBER_VBIND(nv) (((nv)->data.member.vbind))
+
+#define N_VTSHAPE_COUNT(pv) (((nv)->data.vtshape.count))
+
+
+// pointers to evaluation stack
+
+extern HDEP hEStack; // handle of evaluation stack if not zero
+extern struct elem_t *pEStack; // pointer to evaluation stack
+#ifndef USE_BASED
+typedef int belem_t;
+#define pelemOfbelem(a) ((pelem_t)(((char *) pEStack) + (a)))
+#define belemOfpelem(a) ((belem_t)(((char *) a) - (char *) (pEStack)))
+#else
+typedef struct elem_t _based(pEStack) *belem_t; // based pointer to stack element
+#define pelemOfbelem(a) ((pelem_t) a)
+#define belemOfpelem(a) ((belem_t) a)
+#endif
+typedef struct elem_t *pelem_t; // far pointer to evaluation stack element
+
+extern belem_t StackLen; // length is evaluation stack buffer
+extern belem_t StackMax; // maximum length reached by evaluation stack
+extern belem_t StackOffset; // offset into evaluation stack for next element
+extern belem_t StackCkPoint; // checkpointed evaluation stack offset
+extern uchar Evaluating; // TRUE if evaluating rather than binding
+extern char *pExStr; // pointer to current expression string
+extern uchar BindingBP; // true if binding breakpoint expression
+extern CV_typ_t ClassExp; // current explicit class
+extern CV_typ_t ClassImp; // implicit class (set if current context is method)
+extern long ClassThisAdjust;// implicit class this adjustor
+extern char *vfuncptr;
+extern char *vbaseptr;
+extern HTM *pTMList; // breakpoint return list
+extern PTML pTMLbp; // global pointer to TML for breakpoint
+extern HDEP hBPatch; // handle to back patch data during BP bind
+extern ushort iBPatch; // index into pTMLbp for backpatch data
+extern bool_t GettingChild; // true if in EEGetChildTM
+extern BOOL fAutoClassCast; // true if auto class cast is enabled
+
+typedef struct elem_t {
+ belem_t pe; // based pointer to previous evalation element
+ eval_t se; // evaluation element
+} elem_t;
+
+
+extern peval_t ST; // pointer to evaluation stack top
+extern peval_t STP; // pointer to evaluation stack previous
+extern PCXT pCxt; // pointer to current cxt for bind
+extern PCXT pBindBPCxt; // pointer to Bp Binding context
+
+
+// stree_t - abstract syntax tree
+// The abstract syntax tree is a variable sized buffer allocated as
+// struct stree_t
+// variable space for tree nodes (initially NODE_DEFAULT bytes)
+// NSTACK_MAX indices to open terms in the parse tree
+// unused node space and the NSTACK_MAX indices are deallocated at the
+// end of the parse to maintain minimum memory usage.
+
+
+#define NODE_DEFAULT (10 *sizeof (node_t) + 5 * sizeof (eval_t))
+#define NSTACK_MAX 30
+
+typedef struct stree_t {
+ uint size; // allocated size of syntax tree
+ uint stack_base; // offset into buffer for parse stack
+ uint stack_next; // index of next parse stack entry
+ uint node_next; // offset of space for next node
+ uint start_node; // offset of node to start evaluation
+ size_t StackSize; // size required for evaluation stack
+ char nodebase[];
+} stree_t;
+
+typedef stree_t *pstree_t;
+extern pstree_t pTree; // locked address of abstract or evaluation tree
+
+#ifndef USE_BASED
+typedef int bnode_t;
+#define pnodeOfbnode(a) ((pnode_t)(((char *) pTree) + (a)))
+#define bnodeOfpnode(a) ((bnode_t)(((char *) a) - (char *) (pTree)))
+#else
+typedef struct node_t _based (pTree) *bnode_t;
+#define pnodeOfbnode(a) (a)
+#endif
+extern bnode_t bArgList; // based pointer to argument list
+extern bnode_t bnCxt; // based pointer to node containing {...} context
+
+typedef struct node_t {
+ op_t op; // Operator, OP_...
+ CV_typ_t stype; // type to set stack eval to (OP_addrof, ...)
+ bnode_t pnLeft; // offset of left child
+ bnode_t pnRight; // offset of right child or 0 if unary op
+ PCXF pcxf; // pointer to a context for binding class/structs
+ eval_t v[]; // extra data if ident or constant
+} node_t;
+typedef struct node_t *pnode_t;
+
+
+typedef struct adjust_t {
+ CV_typ_t btype; // type index of base
+ CV_typ_t vbptr; // type index of virtual base table pointer
+ OFFSET vbpoff; // displacement from address point to vbptr
+ OFFSET disp; // displacement from *vbptr to base displacement
+} adjust_t;
+typedef struct adjust_t *padjust_t;
+
+typedef enum {
+ OM_none, // initialization state
+ OM_exact, // exact match - no conversion required
+ OM_implicit, // implicit conversion required
+ OM_vararg // matches on vararg
+} ometric;
+
+
+// Structure for argument data including overload calculations
+// There is one of these structures allocated for each OP_arg node
+
+typedef struct argd_t {
+ CV_typ_t type;
+ CV_typ_t actual; // actual type at argument bind time
+ UOFFSET SPoff;
+ struct {
+ uchar isreg :1; // true if register parameter
+ uchar ref :1; // true if reference parameter
+ uchar utclass :1; // true if referenced type is a class
+ uchar istype :1; // true if arg node is EV_type
+ uchar isconst :1; // true if arg type is const
+ uchar isvolatile :1; // true if arg type is volatile
+ } flags;
+ ushort reg; // register handles
+ CV_typ_t utype; // underlying type of reference
+ ushort vallen;
+ ometric best; // best overload metric for this argument
+ ometric current; // current overload metric for this argument
+} argd_t;
+typedef struct argd_t *pargd_t;
+
+
+
+// Macros for accessing Node structure.
+
+#define CLEAR_NODE(pn) _fmemset(pn, 0, sizeof (node_t))
+
+#define NODE_OP(pn) ((pn)->op)
+#define NODE_STYPE(pn) ((pn)->stype)
+#define NODE_LCHILD(pn) ((pn)->pnLeft)
+#define NODE_RCHILD(pn) ((pn)->pnRight)
+
+
+
+// expression evaluator state structure definition
+// This is the structure that totally describes an expression and is the
+// TM referred to in the API documentation.
+
+typedef struct exstate_t {
+ struct {
+ ushort childtm :1; // TM represents a child
+ ushort noname :1; // TM does not have a name
+ ushort parse_ok :1; // true if expression parsed without error
+ ushort bind_ok :1; // true if expression is bound without error
+ ushort eval_ok :1; // true if expression evaluated without error
+ ushort bprel :1; // true if expression contains BP relative terms
+ ushort regrel :1; // true if expression contains register relative term
+ // bprel implies regrel
+ ushort nullcontext :1; // true if expression contains {} context
+ ushort fCase :1; // true if case insensitive search
+ ushort fEProlog :1; // true if function symbols during prolog
+ ushort fFunction :1; // true if bind tree contains function call
+ ushort fLData :1; // true if bind tree references local data
+ ushort fGData :1; // true if bind tree references global data
+ ushort fSupOvlOps :1; // true if overloaded operator search suppressed
+ ushort fSupBase :1; // true if base class searches suppressed
+ ushort tlsrel :1; // true if expression is TLS relative
+ ushort fNotPresent :1; // true if expr contains a missing data item
+ } state;
+ uint ExLen; // expression length
+ uint style; // display formatting style
+ ERRNUM err_num; // error number
+ ushort strIndex; // index into string at end of parse
+ uint radix; // radix for expression
+ HDEP hCName; // handle to child name if derived TM
+ HDEP hExStr; // handle to zero terminated expression string
+ HDEP hSTree; // handle of abstract syntax tree
+ HDEP hETree; // handle of tree in evaluation
+ bnode_t ambiguous; // based pointer to breakpoint ambiguous node
+ CXT cxt; // bind context
+ FRAME frame; // evaluation frame
+ eval_t result; // evaluation result
+} exstate_t;
+
+typedef exstate_t *pexstate_t;
+extern pexstate_t pExState; // global pointer to current evaluation state structure
+
+
+// global handle to the CXT list buffer
+
+extern HCXTL hCxtl; // handle for context list buffer during GetCXTL
+extern PCXTL pCxtl; // pointer to context list buffer during GetCXTL
+extern ushort mCxtl; // maximum number of elements in context list
+
+// Structure describing the current state of a function match
+
+typedef struct {
+ CV_typ_t match; // type index of a matching function
+ CV_fldattr_t attr; // attributes of matched method
+ UOFFSET vtabind; // vftable index if virtual method
+ ushort exact; // number of exact matches on argument type
+ ushort implicit; // number of implicit matches on argument type
+ ushort varargs; // ordinal of the first argument matching as vararg
+ HSYM hSym; // handle of best matching function
+} argcounters;
+
+
+// structure describing base classes traversed in feature search
+
+typedef struct symbase_t {
+ eval_t Base; // value node for base
+ CV_fldattr_t attrBC; // attribute of base class
+ CV_typ_t tTypeDef; // typedef type if found (member/method overrides)
+ bool_t virtual; // true of virtual base
+ OFFSET thisadjust; // this pointer adjustment from address point
+ // or offset of displacement from vbase table
+ ushort clsmask; // used to flag introvirtual search
+ CV_typ_t vbptr; // type of virtual base pointer
+ OFFSET vbpoff; // offset of virtual base pointer from address point
+ ushort vbind; // index into virtal base table
+} symbase_t;
+
+typedef symbase_t *psymbase_t;
+
+// structure for accumulating dominated and searched virtual bases
+
+#define DOMBASE_DEFAULT 30
+
+typedef struct dombase_t {
+ ushort CurIndex;
+ ushort MaxIndex;
+ CV_typ_t dom[];
+} dombase_t;
+
+typedef struct dombase_t *pdombase_t;
+
+
+// symclass_t - structure to describe symbol searching in a class
+// The symclass_t is a variable sized buffer allocated as
+// struct symclass_t
+// variable array of symbase_t (initially SYMBASE_DEFAULT entries)
+
+
+#define SYMBASE_DEFAULT 10
+
+typedef struct symclass_t {
+ HDEP hNext; // handle of next found class element
+ short CurIndex; // index of current symbase_t element
+ short MaxIndex; // maximum symbase_t element
+ CXT CXTT; // context of found symbol
+ struct {
+ bool_t viable; // path is viable (set false if dominated)
+ bool_t isbase; // found feature is base if true
+ bool_t isvbase; // found feature is virtual base if true
+ bool_t isivbase; // found feature is indirect virtual base if true
+ bool_t isdupvbase; // found feature is duplicate virtual base if true
+ } s;
+ eval_t evalP; // value node for feature found on this path
+ OFFSET offset; // offset of member from final base
+ CV_fldattr_t access; // access flags of member
+ address_t addr;
+ CV_typ_t vfpType; // type index of vfuncptr if method
+ ushort possibles; // count of possible features
+ CV_typ_t mlist; // type index of method list if method
+ CV_typ_t vbptr; // type of virtual base pointer
+ OFFSET vbpoff; // offset of virtual base pointer from address point
+ ushort vbind; // index into virtal base table
+ symbase_t symbase[];
+} symclass_t;
+
+typedef symclass_t *psymclass_t;
+
+
+
+// Internal state of SearchSym
+
+typedef enum {
+ SYM_init,
+ SYM_bclass,
+ SYM_lexical,
+ SYM_function,
+ SYM_class,
+ SYM_module,
+ SYM_global,
+ SYM_exe,
+ SYM_public
+} symstate_t;
+
+
+
+// Structure to describe search name to fnCmp
+
+typedef struct search_t {
+
+ // input to search routine
+ SSTR sstr;
+ uchar initializer; // enum of routine that initialized search
+ ushort lastsym; // type of symbol last checked by pfnCmp
+ int flags; // compare flags
+ symstate_t state; // internal state of symbol search
+ ushort scope; // mask describing scopes to be searched
+ ushort clsmask; // mask describing grouping to search in class
+ CV_typ_t typeIn; // input type if type search (i.e. casting)
+ CXT CXTT; // initial context (modified during search)
+ bnode_t bnOp; // based pointer to operator node if right search
+ bnode_t bn; // based pointer to node (used for tree rewrite)
+ peval_t pv; // pointer to value to receive symbol info
+ PFNCMP pfnCmp; // pointer to symbol compare routine
+ HSYM hSym; // handle to symbol if found in symbol table
+ ushort cFound; // count of handles to found features
+ HDEP hFound; // handle of path to first found feature
+ HDEP hAmbCl; // handle of ambiguous found feature list
+ HEXE hExe; // handle to exe of starting context
+ HMOD hMod; // handle to module of starting context
+ HMOD hModCur; // handle to module of current context
+ CV_typ_t ExpClass; // initial class if explicit class reference
+ CV_typ_t CurClass; // class currently being searched
+ ushort possibles; // number of possible matches
+ CV_typ_t FcnBP; // function index of another function with
+ // same name but different index if searching
+ // for a procedure
+
+ // output from search routine
+
+ CV_typ_t typeOut; // type index of found element
+ OFFSET offset; // symbol address point offset if member
+ OFFSET thisoff; // this pointer offset from original address point
+#ifdef NEVER
+ address_t address; // address of symbol
+#endif
+ ADDR addr; // address of symbol
+ argcounters best;
+ ushort overloadCount; // overload counter used by arg matching functions --gdp 9/20/92
+ CV_fldattr_t access; // access flags if class member
+} search_t;
+
+typedef search_t * psearch_t;
+
+
+
+// search flags describing implicit and explicit class searching
+
+#define CLS_vfunc 0x0001 // search for vfunc pointer
+#define CLS_vbase 0x0002 // search for vbase pointer
+#define CLS_member 0x0004 // search for members
+#define CLS_method 0x0008 // search for methods
+#define CLS_frmethod 0x0010 // search for friend method
+#define CLS_bclass 0x0020 // search for base classes
+#define CLS_fclass 0x0040 // search for friend classes
+#define CLS_enumerate 0x0080 // search for enumerates
+#define CLS_ntype 0x0100 // search for nested types
+#define CLS_virtintro 0x0200 // search for introducing virtual
+
+#define CLS_data (CLS_member | CLS_vfunc | CLS_vbase | CLS_bclass)
+#define CLS_defn (CLS_member | CLS_vfunc | CLS_vbase | CLS_bclass | CLS_method | CLS_enumerate | CLS_ntype)
+
+
+
+
+// Enumeration of return values from GetArgType. This value specifies what
+// type of argument matching is permitted for a function
+
+typedef enum {
+ FARG_error, // error in argument
+ FARG_none, // no arguments allowed
+ FARG_vararg, // variable argument list
+ FARG_exact // exact argument list is required
+} farg_t;
+
+
+// Bit values describing the permitted scope for symbol searching
+
+#define SCP_lexical 0x0001 // lexical scope (formals, automatics & local statics)
+#define SCP_class 0x0002 // class scope if member function
+#define SCP_module 0x0004 // module scope
+#define SCP_global 0x0008 // global scope
+#define SCP_nomatchfn 0x0010 // don't call matchfunction (avoid recursion)
+
+#define SCP_all (SCP_lexical | SCP_module | SCP_class | SCP_global)
+
+
+// Enumeration of return values from SearchSym
+
+
+typedef enum {
+ HR_error, // error in search - do not continue
+ HR_notfound, // symbol not found
+ HR_found, // symbol found
+ HR_rewrite, // symbol found but tree rewrite required
+ HR_ambiguous, // symbol found but ambiguous
+ HR_end // end of search
+} HR_t;
+
+
+
+
+// Global functions
+
+// deblex.c
+
+ushort GetDBToken (uchar *, ptoken_t, uint, op_t);
+ushort GetEscapedChar (char * *, ushort*);
+ushort ParseConst (uchar *, ptoken_t, uint);
+
+// debparse.c
+
+EESTATUS DoParse (PHTM, uint, bool_t, uint *);
+EESTATUS Parse (char *, uint, SHFLAG, PHTM, uint *);
+
+// debbind.c
+
+EESTATUS DoBind (PHTM, PCXT, uint);
+void InitSearchRight (bnode_t, bnode_t, psearch_t, ushort);
+void InitSearchSym (bnode_t, peval_t, psearch_t, CV_typ_t, ushort, ushort);
+
+// debeval.c
+
+EESTATUS DoEval (PHTM, PFRAME, EEDSP);
+
+
+// debsup.c
+
+bool_t AreTypesEqual (HTM, HTM);
+HTYPE GetHtypeFromTM(HTM);
+EESTATUS cChildrenTM (PHTM, long *, PSHFLAG);
+ushort cParamTM (HTM, ushort *, PSHFLAG);
+EESTATUS DereferenceTM (HTM, PEEHSTR);
+ushort DupTM (PHTM, PHTM);
+EESTATUS GetChildTM (HTM, ulong, PEEHSTR, PEEHSTR, uint);
+EESTATUS GetSymName (PHTM, PEEHSTR);
+ushort InfoFromTM (PHTM, PRI, PHTI);
+ushort IsExpandablePtr (peval_t);
+bool_t LoadVal (peval_t);
+bool_t ResolveAddr (peval_t);
+
+// debsym.c
+
+void InitSearchBase (bnode_t, CV_typ_t, CV_typ_t, psearch_t, peval_t);
+void InitSearchtDef (psearch_t, peval_t, ushort);
+farg_t GetArgType (peval_t, short, CV_typ_t *);
+bool_t getDefnFromDecl(CV_typ_t, peval_t, CV_typ_t*);
+CV_ptrmode_e SetAmbiant (bool_t);
+EESTATUS GetHSYMList (HDEP *, PCXT, ushort, uchar *, SHFLAG);
+HSYM SearchCFlag (void);
+HR_t SearchBasePtrBase (psearch_t);
+HR_t SearchSym (psearch_t);
+bool_t pvThisFromST (bnode_t);
+
+// debtree.c
+
+ushort PushToken (ptoken_t);
+bool_t FASTCALL GrowTree (uint);
+bool_t FASTCALL GrowETree (uint);
+
+// debsrch.c
+
+bool_t FindPtrToPtr (peval_t, CV_typ_t *);
+bool_t LoadSymVal (peval_t pn);
+bool_t LoadLValue (peval_t);
+MTYP_t MatchType (peval_t, bool_t);
+void ProtoPtr (peval_t, peval_t, bool_t, CV_modifier_t);
+
+// debtyper.c
+
+bool_t CastNode (peval_t, CV_typ_t, CV_typ_t);
+bool_t DeNormalizePtr (peval_t, peval_t);
+bool_t NormalizeBase (peval_t);
+void TypeNodes (op_t, peval_t, peval_t);
+bool_t ValidateNodes (op_t, peval_t, peval_t);
+CV_typ_t PerformUAC (CV_typ_t, CV_typ_t);
+
+// debfmt.c
+
+ushort FormatCXT (PCXT, PEEHSTR, BOOL);
+void FormatFormal (HSYM, CXF *, ushort, char **, short *);
+EESTATUS FormatNode (PHTM phTM, uint Radix, PEEFORMAT pFormat, PEEHSTR phszValue);
+void FormatType (peval_t, char **, uint *, char * *, ulong, PHDR_TYPE);
+void FormatProc (peval_t, char * *, uint *,
+ char * *, CV_typ_t, CV_typ_t,
+ CV_call_e, ushort, CV_typ_t, ulong,
+ PHDR_TYPE);
+
+
+
+// deberr.c
+
+ushort GetErrorText (PHTM, EESTATUS, PEEHSTR);
+
+
+// debutil.c
+
+SHFLAG csCmp (LPSSTR, LPV, LSZ, SHFLAG);
+SHFLAG fnCmp (LPSSTR, LPV, LSZ, SHFLAG);
+SHFLAG tdCmp (LPSSTR, LPV, LSZ, SHFLAG);
+bool_t PopStack (void);
+bool_t PushStack (peval_t);
+void CkPointStack (void);
+bool_t fCanSubtractPtrs (peval_t, peval_t);
+char * GetHSYMCodeFromHSYM(HSYM);
+HSYM GetHSYMFromHSYMCode(char *);
+bool_t ResetStack (void);
+void RemoveIndir (peval_t);
+ulong RNumLeaf (void *, uint *);
+bool_t SetNodeType (peval_t, CV_typ_t);
+long TypeDefSize (peval_t);
+long TypeSize (peval_t);
+int TypeSizePrim (CV_typ_t);
+bool_t UpdateMem (peval_t);
+CV_typ_t GetUdtDefnTindex (CV_typ_t TypeIn, neval_t nv, char *lpStr);
+
+// debwalk.c
+
+ushort DoGetCXTL (PHTM, PHCXTL);
+EESTATUS GetExpr (PHTM, EERADIX, PEEHSTR, ushort *);
+
+
+/*
+ * Define the size of "long double"
+ */
+
+#ifdef TARGET_i386
+#define LONG_DOUBLE_80
+#endif
+
+#ifdef TARGET_MIPS
+#define LONG_DOUBLE_64
+#endif
+
+#ifdef TARGET_PPC
+#define LONG_DOUBLE_64
+#endif
+
+#ifdef TARGET_ALPHA
+#define LONG_DOUBLE_64
+#endif
+
+
+#if !defined(LONG_DOUBLE_80) && !defined(LONG_DOUBLE_64)
+#pragma message("Must Define the size of a Long Double")
+#endif
diff --git a/private/windbg/eecan/debfmt.c b/private/windbg/eecan/debfmt.c
new file mode 100644
index 000000000..6f1629bf2
--- /dev/null
+++ b/private/windbg/eecan/debfmt.c
@@ -0,0 +1,1890 @@
+/*** debfmt.c - expression evaluator formatting routines
+ *
+ * GLOBAL
+ *
+ *
+ * LOCAL
+ *
+ *
+ *
+ * DESCRIPTION
+ * Expression evaluator formatting routines
+ *
+ */
+
+
+
+
+extern char Suffix;
+
+
+typedef enum FMT_ret {
+ FMT_error,
+ FMT_none,
+ FMT_ok
+} FMT_ret;
+
+
+LOCAL void NEAR PASCAL Format (peval_t, uint, char FAR * FAR *, uint FAR *);
+LOCAL void PASCAL EvalString (peval_t, char FAR * FAR *, uint FAR *);
+LOCAL void NEAR PASCAL FormatExpand (peval_t, char FAR * FAR *, uint FAR *, char FAR * FAR *, ulong, PHDR_TYPE);
+LOCAL void NEAR PASCAL FormatClass (peval_t, uint, char FAR * FAR * , uint FAR *);
+LOCAL bool_t NEAR PASCAL FormatUDT (peval_t, char FAR * FAR *, uint FAR *);
+LOCAL char FAR *NEAR PASCAL FormatVirtual (char FAR *, CV_typ_t, peval_t, PEEHSTR);
+LOCAL FMT_ret NEAR PASCAL VerifyFormat (peval_t, PEEFORMAT, char FAR * FAR *, uint FAR *);
+
+BOOL UseUnicode( peval_t pv );
+BOOL BaseIs16Bit( CV_typ_t utype );
+
+
+
+
+
+static char accessstr[4][4] = {" ", "PV ", "PR ", "PB "};
+
+struct typestr {
+ CV_typ_t typ;
+ uchar len;
+#ifdef WIN32
+ char *name;
+#else
+ char _based (_segname("_CODE")) *name;
+#endif
+};
+
+#ifdef WIN32
+//#define FMTSTR(name, type, mode, len, str) static char S##name[] = str;
+#define FMTSTR(name, type, mode, len, str) static char name[] = str;
+#else
+#define FMTSTR(name, type, mode, len, str) static char _based(_segname("_CODE")) S##name[] = str;
+#endif
+#define PTRNAME(name, str)
+#include "fmtstr.h"
+#undef FMTSTR
+#undef PTRNAME
+
+#ifdef WIN32
+static struct typestr nametype[] = {
+#else
+static struct typestr _based(_segname("_CODE")) nametype[] = {
+#endif
+//#define FMTSTR(name, type, mode, len, str) {(type | (mode << CV_MSHIFT)), len, S##name},
+#define FMTSTR(name, type, mode, len, str) {(type | (mode << CV_MSHIFT)), len, name},
+#define PTRNAME(name, str)
+#include "fmtstr.h"
+#undef FMTSTR
+#undef PTRNAME
+};
+
+
+#define FMTSTR(name, type, mode, len, str)
+#ifdef WIN32
+//#define PTRNAME(name, str) static char S##name[] = str;
+#define PTRNAME(name, str) static char name[] = str;
+#else
+#define PTRNAME(name, str) static char _based(_segname("_CODE")) S##name[] = str;
+#endif
+#include "fmtstr.h"
+#undef FMTSTR
+#undef PTRNAME
+
+#ifdef WIN32
+static char * ptrname[] = {
+#else
+static char _based(_segname("_CODE")) *_based(_segname("_CODE")) ptrname[] = {
+#endif
+#define FMTSTR(name, type, mode, len, str)
+//#define PTRNAME(name, str) S##name,
+#define PTRNAME(name, str) name,
+#include "fmtstr.h"
+#undef FMTSTR
+#undef PTRNAME
+};
+
+
+
+#define typecount (sizeof (nametype) / sizeof (nametype[0]))
+bool_t fPtrAndString; // true if pointer AND string to be displayed
+
+
+
+char *fmt_char[] = {
+ "0o%03.03o",
+ "%d",
+ "0x%02.02x"
+};
+
+char *fmt_uchar[] = {
+ "0o%03.03o",
+ "%u",
+ "0x%02.02x"
+};
+
+
+char *fmt_short[] = {
+ "0o%06.06ho",
+ "%hd",
+ "0x%04.04hx"
+};
+
+
+char *fmt_ushort[] = {
+ "0o%06.06ho",
+ "%hu",
+ "0x%04.04hx"
+};
+
+
+char *fmt_long[] = {
+ "0o%011.011lo",
+ "%ld",
+ "0x%08.08lx"
+};
+
+
+char *fmt_ulong[] = {
+ "0o%011.011lo",
+ "%lu",
+ "0x%08.08lx"
+};
+
+char *bailout = "\x006""??? * ";
+
+
+/** FormatCXT - format context packet
+ *
+ * status = FormatCXT (pCXT, ppbuf, pbuflen);
+ *
+ * Entry pCXT = pointer to context
+ * ppbuf = pointer pointer to buffer
+ * pbuflen = pointer to buffer length
+ *
+ * Exit context formatted into buffer as a context operator
+ * *pcount = space remaining in buffer
+ *
+ * Returns EENONE if no error
+ * EEGENERAL if error
+ */
+
+ushort PASCAL FormatCXT (PCXT pCXT, PEEHSTR phStr, BOOL fAbbreviated)
+{
+ HMOD hMod;
+ HPROC hProc;
+ HSF hsf;
+ HEXE hExe;
+ SYMPTR pProc;
+ char FAR *pFile;
+ char FAR *pExe;
+ char FAR *pStr;
+ uint len = 6;
+
+ hMod = SHHMODFrompCXT (pCXT);
+ hProc = SHHPROCFrompCXT (pCXT);
+ if ((hMod == 0) && (hProc == 0)) {
+ if ((*phStr = MHMemAllocate (10)) != 0) {
+ pStr = MHMemLock (*phStr);
+ *pStr = 0;
+ MHMemUnLock (*phStr);
+ return (EENOERROR);
+ }
+
+ }
+
+ hsf = SLHsfFromPcxt (pCXT);
+ hExe = SHHexeFromHmod (hMod);
+
+ if (fAbbreviated) {
+ pExe = SHGetModNameFromHexe( hExe );
+ } else {
+ pExe = SHGetExeName( hExe );
+ }
+
+ if (!pExe) {
+ //
+ // we can't generate a CXT if we can't get the exe name
+ //
+ return EECATASTROPHIC;
+ }
+
+ pFile = SLNameFromHsf (hsf) ;
+ // it is possible to get the exe name, but not source
+ // file/line information (ex. a public) In this case we will use
+ // pExe instead of pFile (ie. {,,foob.exe} )
+
+ if (hProc != 0) {
+ switch ((pProc = (SYMPTR)MHOmfLock ((HDEP)hProc))->rectyp) {
+#if defined (ADDR_16) || defined (ADDR_MIXED)
+ case S_LPROC16:
+ case S_GPROC16:
+ len += ((PROCPTR16)pProc)->name[0];
+ break;
+#endif
+
+#if defined (ADDR_32) || defined (ADDR_MIXED)
+ case S_LPROC32:
+ case S_GPROC32:
+ len += ((PROCPTR32)pProc)->name[0];
+ break;
+#endif
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ len += ((PROCPTRMIPS)pProc)->name[0];
+ break;
+
+ default:
+ DASSERT (FALSE);
+ MHOmfUnLock ((HDEP)hProc);
+ return (EECATASTROPHIC);
+ }
+ }
+
+ if ( pFile ) {
+ len += *pFile + (int)_fstrlen (pExe) ;
+ }
+ else {
+ len += (int)_fstrlen (pExe) ;
+ }
+
+
+ if (fAbbreviated) {
+ len = max( 16, len );
+ }
+
+ if ((*phStr = MHMemAllocate (len)) != 0) {
+ pStr = MHMemLock (*phStr);
+
+ if (fAbbreviated) {
+ strcpy(pStr,pExe);
+#ifdef DBCS
+ CharUpper(pStr);
+#else
+ _strupr(pStr);
+#endif
+ strcat (pStr,"!");
+ MHMemUnLock (*phStr);
+ } else {
+ _fstrcpy (pStr, "{");
+ if (hProc != 0) {
+ switch (pProc->rectyp) {
+#if defined (ADDR_16) || defined (ADDR_MIXED)
+ case S_LPROC16:
+ case S_GPROC16:
+ _fstrncat (pStr, &((PROCPTR16)pProc)->name[1],
+ ((PROCPTR16)pProc)->name[0]);
+ break;
+#endif
+
+ case S_LPROC32:
+ case S_GPROC32:
+ _fstrncat (pStr, &((PROCPTR32)pProc)->name[1],
+ ((PROCPTR32)pProc)->name[0]);
+ break;
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ _fstrncat (pStr, &((PROCPTRMIPS)pProc)->name[1],
+ ((PROCPTRMIPS)pProc)->name[0]);
+ break;
+ }
+ }
+ _fstrcat (pStr, ",");
+
+ if ( pFile ) {
+ _fstrncat (pStr, pFile + 1, *pFile);
+ }
+
+ _fstrcat (pStr, ",");
+ _fstrcat (pStr, pExe);
+ _fstrcat (pStr, "}");
+ MHMemUnLock (*phStr);
+ }
+ }
+ else {
+ MHOmfUnLock ((HDEP)hProc);
+ return (EECATASTROPHIC);
+ }
+ MHOmfUnLock ((HDEP)hProc);
+ return (EENOERROR);
+}
+
+
+
+/** FormatType - format type string
+ *
+ * FormatType (pv, ppbuf, pcount, ppName, select, pHdr);
+ *
+ * Entry pv = pointer to value node
+ * ppbuf = pointer pointer to buffer
+ * pcount = pointer to buffer length
+ * ppName = pointer to name if not null
+ * select = selection mask
+ * pHdr = pointer to structure describing formatting
+ *
+ * Exit type formatted into buffer
+ * *pcount = space remaining in buffer
+ * *pHdr updated
+ *
+ * Returns none
+ */
+
+void PASCAL FormatType (peval_t pv, char FAR * FAR *buf, uint FAR *buflen,
+ char FAR * FAR *ppName, ulong select, PHDR_TYPE pHdr)
+{
+ eval_t evalT;
+ peval_t pvT = &evalT;
+ uint skip = 1;
+ int len;
+ int i;
+ char FAR *tname;
+ CV_typ_t type;
+
+#if defined (NEVR)
+#if !defined (C_ONLY)
+ if (EVAL_ACCESS (pv) != 0) {
+ len = min (*buflen, ( uint ) 3);
+ _fstrncpy (*buf, accessstr[EVAL_ACCESS (pv)], len);
+ *buf += len;
+ *buflen -= len;
+ }
+#endif
+#endif
+ if (EVAL_IS_CONST (pv)) {
+ len = min (*buflen, 6);
+ _fstrncpy (*buf, "const ", len);
+ *buf += len;
+ *buflen -= len;
+ }
+ else if (EVAL_IS_VOLATILE (pv)) {
+ len = min (*buflen, 9);
+ _fstrncpy (*buf, "volatile ", len);
+ *buf += len;
+ *buflen -= len;
+ }
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
+ switch (EVAL_TYP (pv)) {
+ default:
+ for (i = 0; i < typecount - 1; i++) {
+ if (nametype[i].typ == EVAL_TYP (pv))
+ break;
+ }
+
+ // copy type string and add blank afterwards
+
+ len = min (*buflen, (uint)(nametype[i].len));
+ _fstrncpy (*buf, nametype[i].name, len);
+ *buf += len;
+ *buflen -= len;
+ break;
+
+ case T_NCVPTR:
+ tname = "\x007""near * ";
+ goto formatmode;
+
+ case T_HCVPTR:
+ tname = "\x007""huge * ";
+ goto formatmode;
+
+ case T_FCVPTR:
+ tname = "\x006""far * ";
+
+formatmode:
+ *pvT = *pv;
+ SetNodeType (pvT, PTR_UTYPE (pv));
+ type = EVAL_TYP (pvT);
+ if ((type == T_NCVPTR) || (type == T_FCVPTR) ||
+ (type == T_HCVPTR)) {
+ // we are in a bind here. The type generator messed
+ // up and generated a created type pointing to a created
+ // type. we are going to bail out here.
+
+ len = min (*buflen, (uint) *bailout);
+ _fstrncpy (*buf, bailout + 1, len);
+ *buflen -= len;
+ *buf += len;
+
+ }
+ else {
+ FormatType (pvT, buf, buflen, 0, select, pHdr);
+ }
+ len = min (*buflen, (uint) *tname);
+ _fstrncpy (*buf, tname + 1, len);
+ *buflen -= len;
+ *buf += len;
+ break;
+ }
+ }
+ else {
+ if (FormatUDT (pv, buf, buflen) == FALSE) {
+ FormatExpand (pv, buf, buflen, ppName, select, pHdr);
+ }
+ }
+ if (ppName != NULL && *ppName != NULL) {
+ len = (int)_fstrlen (*ppName);
+ len = min (len, (int) *buflen);
+ pHdr->offname = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
+ pHdr->lenname = len;
+ _fstrncpy (*buf, *ppName, len);
+ *buflen -= len;
+ *buf += len;
+ *ppName = NULL;
+ }
+}
+
+
+
+/** FormatExpand - format expanded type definition
+ *
+ * FormatExpand (pv, ppbuf, pbuflen, ppName, select)
+ *
+ * Entry pv = pointer to value node
+ * ppbuf = pointer to pointer to buffer
+ * pbuflen = pointer to space remaining in buffer
+ * ppName = pointer to name to insert after type if not null
+ * select = selection mask
+ * pHdr = pointer to type formatting header
+ *
+ * Exit buffer contains formatted type
+ * ppbuf = end of formatted string
+ * pbuflen = space remaining in buffer
+ *
+ * Returns none
+ */
+
+
+LOCAL void NEAR PASCAL FormatExpand (peval_t pv, char FAR * FAR *buf,
+ uint FAR *buflen, char FAR * FAR *ppName, ulong select, PHDR_TYPE pHdr)
+{
+ eval_t evalT;
+ peval_t pvT = &evalT;
+ uint skip = 1;
+ int len;
+ HTYPE hType;
+ plfEasy pType;
+ ushort model;
+ ulong count;
+ char tempbuf[33];
+ CV_typ_t rvtype;
+ CV_typ_t mclass;
+ CV_call_e call;
+ ushort cparam;
+ CV_typ_t parmtype;
+ CV_typ_t thistype;
+ char FAR *movestart;
+ int movelen;
+ int movedist;
+
+ if ((hType = THGetTypeFromIndex (EVAL_MOD (pv), EVAL_TYP (pv))) == 0) {
+ return;
+ }
+ pType = (plfEasy)(&((TYPPTR)(MHOmfLock ((HDEP)hType)))->leaf);
+ switch (pType->leaf) {
+ case LF_STRUCTURE:
+ case LF_CLASS:
+ skip = offsetof (lfClass, data[0]);
+ RNumLeaf (((char FAR *)(&pType->leaf)) + skip, &skip);
+ len = *(((char FAR *)&(pType->leaf)) + skip);
+ len = min (len, (int) *buflen);
+ _fstrncpy (*buf, ((char FAR *)pType) + skip + 1, len);
+ *buflen -= len;
+ *buf += len;
+ if (*buflen > 1) {
+ **buf = ' ';
+ (*buf)++;
+ (*buflen)--;
+ }
+ MHOmfUnLock ((HDEP)hType);
+ break;
+
+ case LF_UNION:
+ skip = offsetof (lfUnion, data[0]);
+ RNumLeaf (((char FAR *)(&pType->leaf)) + skip, &skip);
+ len = *(((char FAR *)&(pType->leaf)) + skip);
+ len = min (len, (int) *buflen);
+ _fstrncpy (*buf, ((char FAR *)pType) + skip + 1, len);
+ *buflen -= len;
+ *buf += len;
+ if (*buflen > 1) {
+ **buf = ' ';
+ (*buf)++;
+ (*buflen)--;
+ }
+ MHOmfUnLock ((HDEP)hType);
+ break;
+
+ case LF_ENUM:
+ skip = offsetof (lfEnum, Name[0]);
+ len = ((plfEnum)pType)->Name[0];
+ len = min (len, (int) *buflen);
+ _fstrncpy (*buf, &((plfEnum)pType)->Name[1], len);
+ *buflen -= len;
+ *buf += len;
+ if (*buflen > 1) {
+ **buf = ' ';
+ (*buf)++;
+ (*buflen)--;
+ }
+ MHOmfUnLock ((HDEP)hType);
+ break;
+
+ case LF_POINTER:
+
+ // set up a node to evaluate this field
+
+ model = ((plfPointer)pType)->attr.ptrtype;
+ if (((plfPointer)pType)->attr.ptrmode == (uchar)CV_PTR_MODE_REF) {
+ model = CV_PTR_UNUSEDPTR;
+ }
+ // format the underlying type
+ *pvT = *pv;
+ EVAL_TYP (pvT) = ((plfPointer)pType)->utype;
+ MHOmfUnLock ((HDEP)hType);
+ SetNodeType (pvT, EVAL_TYP (pvT));
+ FormatType (pvT, buf, buflen, 0, select, pHdr);
+ len = min (*buflen, (uint) *ptrname[model]);
+ _fstrncpy (*buf, ptrname[model] + 1, len);
+ *buflen -= len;
+ *buf += len;
+ break;
+
+ case LF_ARRAY:
+ *pvT = *pv;
+ EVAL_TYP (pvT) = ((plfArray)(&pType->leaf))->elemtype;
+ skip = offsetof (lfArray, data[0]);
+ count = RNumLeaf (((char FAR *)(&pType->leaf)) + skip, &skip);
+ MHOmfUnLock ((HDEP)hType);
+ SetNodeType (pvT, EVAL_TYP (pvT));
+ // continue down until the underlying type is reached
+
+ FormatType (pvT, buf, buflen, ppName, select, pHdr);
+ if ((ppName != NULL) && (*ppName != NULL)) {
+ len = (int)_fstrlen (*ppName);
+ len = min (len, (int) *buflen);
+ _fstrncpy (*buf, *ppName, len);
+ pHdr->offname = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
+ pHdr->lenname = len;
+ *buflen -= len;
+ *buf += len;
+ *ppName = NULL;
+ }
+
+ // display size of array or * if size unknown. We have to
+ // move the trailing part of the string down if it already
+ // set so that the array dimensions come out in the proper
+ // order
+
+ if (count != 0) {
+ _ultoa (count / TypeSize (pvT), tempbuf, 10);
+ len = _fstrlen (tempbuf);
+ }
+ else {
+ *tempbuf = '?';
+ *(tempbuf + 1) = 0;
+ len = 1;
+ }
+ if (*buflen >= 2) {
+ if (pHdr->offtrail == 0) {
+ pHdr->offtrail = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
+ movestart = (char FAR *)pHdr + sizeof (HDR_TYPE) +
+ pHdr->offtrail;
+ movelen = 0;
+ movedist = 0;
+ }
+ else {
+ movestart = (char FAR *)pHdr + sizeof (HDR_TYPE) +
+ pHdr->offtrail;
+ movelen = _fstrlen (movestart);
+ movedist = _fstrlen (tempbuf) + 2;
+ movelen = min ((int) *buflen, movelen);
+ _fmemmove (movestart + movedist, movestart, movelen);
+ }
+ *movestart++ = '[';
+ _fmemmove (movestart, tempbuf, len);
+ movestart += len;
+ *movestart++ = ']';
+ *buf += len + 2;
+ *buflen -= len + 2;
+ }
+ break;
+
+ case LF_PROCEDURE:
+ mclass = 0;
+ rvtype = ((plfProc)pType)->rvtype;
+ call = ((plfProc)pType)->calltype;
+ cparam = ((plfProc)pType)->parmcount;
+ parmtype = ((plfProc)pType)->arglist;
+ MHOmfUnLock ((HDEP)hType);
+ FormatProc (pv, buf, buflen, ppName, rvtype, mclass, call,
+ cparam, parmtype, select, pHdr);
+ break;
+
+#if !defined (C_ONLY)
+ case LF_MFUNCTION:
+ rvtype = ((plfMFunc)pType)->rvtype;
+ mclass = ((plfMFunc)pType)->classtype;
+ call = ((plfMFunc)pType)->calltype;
+ thistype = ((plfMFunc)pType)->thistype;
+ cparam = ((plfMFunc)pType)->parmcount;
+ parmtype = ((plfMFunc)pType)->arglist;
+ MHOmfUnLock ((HDEP)hType);
+ FormatProc (pv, buf, buflen, ppName, rvtype, mclass, call,
+ cparam, parmtype, select, pHdr);
+ break;
+#else
+ Unreferenced(thistype);
+#endif
+
+ case LF_MODIFIER:
+ if (*buflen >= 6) {
+ if (((plfModifier)pType)->attr.MOD_const == TRUE) {
+ _fstrncpy (*buf, "const ", 6);
+ *buf += 6;
+ *buflen -= 6;
+ }
+ }
+ if (*buflen >= 9) {
+ if (((plfModifier)pType)->attr.MOD_volatile == TRUE) {
+ _fstrncpy (*buf, "volatile ", 9);
+ *buf += 9;
+ *buflen -= 9;
+ }
+ }
+ EVAL_TYP (pv) = ((plfModifier)pType)->type;
+ MHOmfUnLock ((HDEP)hType);
+ FormatType (pv, buf, buflen, ppName, select, pHdr);
+ break;
+
+ case LF_LABEL:
+ break;
+
+ default:
+ MHOmfUnLock ((HDEP)hType);
+ break;
+ }
+}
+
+
+LOCAL bool_t NEAR PASCAL FormatUDT (peval_t pv, char FAR * FAR *buf,
+ uint FAR *buflen)
+{
+ search_t Name;
+ UDTPTR pUDT;
+ uint len;
+
+// Slow ineffective search disabled jsg 2/1/92
+//
+// This code would search all symbols for typedefs to the current type index.
+// This was making the local window repaint too sluggish, since 'FormatUDT'
+// can be called many times per line.
+//
+ Unreferenced( Name );
+ Unreferenced( len );
+ Unreferenced( pUDT );
+ Unreferenced( pv );
+ Unreferenced( buf );
+ Unreferenced( buflen );
+
+ pExState->err_num = ERR_NONE;
+ return (FALSE);
+}
+
+
+
+
+
+/** FormatProc - format proc or member function
+ *
+ * FormatProc (pv. buf, buflen, ppName, rvtype, mclass, call,
+ * cparam, paramtype, select)
+ */
+
+void NEAR PASCAL
+FormatProc (
+ peval_t pv,
+ char FAR * FAR * buf,
+ uint FAR * buflen,
+ char FAR * FAR * ppName,
+ CV_typ_t rvtype,
+ CV_typ_t mclass,
+ CV_call_e call,
+ ushort cparam,
+ CV_typ_t paramtype,
+ ulong select,
+ PHDR_TYPE pHdr
+ )
+{
+ eval_t evalT;
+ peval_t pvT;
+ HTYPE hArg;
+ plfArgList pArg;
+ ushort noffset = 1;
+ short len;
+ bool_t farcall;
+ ushort argCnt;
+
+ Unreferenced( mclass );
+
+ pvT = &evalT;
+ *pvT = *pv;
+
+ if (GettingChild == FALSE && (select & 1) == 0 ) {
+ // output function return type if we are not getting a child TM.
+ // If we are getting a child tm and the function type is included,
+ // the subsequent parse of the generated expression will fail
+ // because the parse cannot handle
+ // type fcn (..........
+
+ // OR...
+ // if select == 0x1 then this is a request to format procs
+ // without the return type (for BPs etc)
+
+ EVAL_TYP (pvT) = (rvtype == 0)? T_VOID: rvtype;
+ FormatType (pvT, buf, buflen, NULL, select, pHdr);
+ //M00KLUDGE - need to output call and model here
+ switch (call) {
+ case CV_CALL_NEAR_C:
+ //near C call - caller pops stack
+ call = FCN_C;
+ farcall = FALSE;
+ break;
+
+ case CV_CALL_FAR_C:
+ // far C call - caller pops stack
+ call = FCN_C;
+ farcall = TRUE;
+ break;
+
+ case CV_CALL_NEAR_PASCAL:
+ // near pascal call - callee pops stack
+ call = FCN_PASCAL;
+ farcall = FALSE;
+ break;
+
+ case CV_CALL_FAR_PASCAL:
+ // far pascal call - callee pops stack
+ call = FCN_PASCAL;
+ farcall = TRUE;
+ break;
+
+ case CV_CALL_NEAR_FAST:
+ // near fast call - callee pops stack
+ call = FCN_FAST;
+ farcall = FALSE;
+ break;
+
+ case CV_CALL_FAR_FAST:
+ // far fast call - callee pops stack
+ call = FCN_FAST;
+ farcall = TRUE;
+ break;
+
+ case CV_CALL_NEAR_STD:
+ // near fast call - callee pops stack
+ call = FCN_STD;
+ farcall = FALSE;
+ break;
+
+ case CV_CALL_FAR_STD:
+ // far fast call - callee pops stack
+ call = FCN_STD;
+ farcall = TRUE;
+ break;
+
+ default:
+ DASSERT (FALSE);
+ call = 0;
+ farcall = FALSE;
+ break;
+
+ }
+ }
+
+ // output function name
+
+ if ((ppName != NULL) && (*ppName != NULL)) {
+ len = (int)_fstrlen (*ppName);
+ len = min (( uint ) len, *buflen);
+ pHdr->offname = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
+ pHdr->lenname = len;
+ _fstrncpy (*buf, *ppName, len);
+ *buflen -= len;
+ *buf += len;
+ *ppName = NULL;
+ }
+ if (*buflen > 1) {
+ pHdr->offtrail = (*buf - (char FAR *) pHdr) - sizeof (HDR_TYPE);
+ **buf = '(';
+ (*buf)++;
+ (*buflen)--;
+ }
+ if (cparam == 0) {
+ EVAL_TYP (pvT) = T_VOID;
+ FormatType (pvT, buf, buflen, NULL, select, pHdr);
+ }
+ else {
+ if ((hArg = THGetTypeFromIndex (EVAL_MOD (pv), paramtype)) == 0) {
+ return;
+ }
+ argCnt = 0;
+ while (argCnt < cparam) {
+ pArg = (plfArgList)((&((TYPPTR)MHOmfLock ((HDEP)hArg))->leaf));
+ EVAL_TYP (pvT) = pArg->arg[argCnt];
+ MHOmfUnLock ((HDEP)hArg);
+ FormatType (pvT, buf, buflen, NULL, select, pHdr);
+ (*buf)--; (*buflen)--;
+ argCnt++;
+ if ((argCnt < cparam) && (*buflen > 2)) {
+ // insert a comma if there are further arguments
+ **buf = ',';
+ (*buf)++;
+ (*buflen)--;
+ **buf = ' ';
+ (*buf)++;
+ (*buflen)--;
+ }
+ }
+ }
+ if (*buflen > 1) {
+ **buf = ')';
+ (*buf)++;
+ (*buflen)--;
+ }
+}
+
+
+
+
+/** FormatNode - format node according to format string
+ *
+ * retval = FormatNode (phTM, radix, pFormat, phValue);
+ *
+ * Entry phTM = pointer to handle to TM
+ * radix = default radix for formatting
+ * pFormat = pointer to format string
+ * phValue = pointer to handle for display string
+ *
+ * Exit evaluation result formatted
+ *
+ * Returns EENOERROR if no error in formatting
+ * error number if error
+ */
+
+
+EESTATUS PASCAL FormatNode (PHTM phTM, uint Radix, PEEFORMAT pFormat,
+ PEEHSTR phszValue)
+{
+ char islong = FALSE;
+ char fc = 0;
+ char FAR *buf;
+ uint buflen = FMTSTRMAX - 1;
+ eval_t evalT;
+ peval_t pv = &evalT;
+ char FAR *pExStr;
+ ushort retval = EECATASTROPHIC;
+
+ DASSERT (*phTM != 0);
+ if (*phTM == 0) {
+ return (retval);
+ }
+ if ((*phszValue = MHMemAllocate (FMTSTRMAX)) == 0) {
+ // unable to allocate memory for formatting
+ return (retval);
+ }
+ buf = (char FAR *)MHMemLock (*phszValue);
+ _fmemset (buf, 0, FMTSTRMAX);
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+
+ // Get expression string
+ pExStr = (char FAR *)MHMemLock (pExState->hExStr);
+
+ if (pExState->state.eval_ok == TRUE) {
+ *pv = pExState->result;
+ if ((EVAL_STATE (pv) == EV_lvalue) ||
+ (EVAL_STATE (pv) == EV_type) ||
+ (EVAL_STATE (pv) == EV_rvalue && EVAL_IS_PTR (pv))) {
+ // do nothing
+ }
+ else {
+ // this handles the case were the return result is a large
+ // structure.
+
+ pv = &pExState->result;
+ }
+ if (EVAL_IS_REF (pv)) {
+ if (!LoadSymVal (pv)) {
+ // unable to load value
+ goto formatexit;
+ }
+ EVAL_IS_REF (pv) = FALSE;
+ EVAL_STATE (pv) = EV_lvalue;
+ EVAL_SYM_OFF (pv) = EVAL_PTR_OFF (pv);
+ EVAL_SYM_SEG (pv) = EVAL_PTR_SEG (pv);
+ SetNodeType (pv, PTR_UTYPE (pv));
+ }
+ if (EVAL_IS_CLASS (pv)) {
+ // For structures and classes ignore format string and format
+ // according to element data types
+
+ EVAL_STATE (pv) = EV_rvalue;
+ goto format;
+ }
+ else if (EVAL_IS_ENUM (pv)) {
+ SetNodeType (pv, CLASS_UTYPE (pv));
+ }
+
+ // load value and format according to format string
+
+
+ if ((EVAL_STATE (pv) == EV_type) || !LoadSymVal (pv)) {
+ // unable to load value
+ retval = EEGENERAL;
+ if (pExState->err_num == ERR_NONE) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ }
+ goto formatexit;
+ }
+ else {
+ switch (VerifyFormat (pv, pFormat, &buf, &buflen)) {
+ case FMT_error:
+ retval = EEGENERAL;
+ pExState->err_num = ERR_FORMAT;
+ goto formatexit;
+
+ case FMT_none:
+ goto format;
+
+ case FMT_ok:
+ retval = EENOERROR;
+ goto formatexit;
+ }
+ }
+ }
+ else {
+ // not evaluated, fail
+ retval = EEGENERAL;
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ goto formatexit;
+ }
+
+format:
+ retval = EENOERROR;
+ Format (pv, Radix, &buf, &buflen);
+formatexit:
+ MHMemUnLock (pExState->hExStr);
+ pExState = NULL;
+ MHMemUnLock (*phszValue);
+ MHMemUnLock (*phTM);
+ return (retval);
+}
+
+
+
+/** VerifyFormat -
+ *
+ *
+ */
+
+
+LOCAL FMT_ret NEAR PASCAL VerifyFormat (peval_t pv, PEEFORMAT pFmtIn,
+ char FAR * FAR *buf, uint FAR *buflen)
+{
+ char tempbuf[41];
+ char prefix = 0;
+ char fmtchar = 0;
+ char fmtcnt = 0;
+ char fmtcnt2 = 0;
+ ushort size = 0;
+ char FAR *pf;
+ char fmtstr[10];
+ ADDR addr;
+ ushort cnt;
+
+ DASSERT (*buflen > 40);
+ if (EVAL_TYP (pv) == T_VOID) {
+ // if the value is void, ignore all formatting
+ _fstrcpy (*buf, "<void>");
+ *buflen -= 6;
+ *buf += 6;
+ return (FMT_ok);
+ }
+
+ if (pFmtIn == NULL) {
+ pf = &pExStr[pExState->strIndex];
+ } else {
+ /*
+ * p is a special format character. It turns off string following
+ * pointers and is generally used for call stack code.
+ */
+
+ if (*pFmtIn == 'p') {
+ fPtrAndString = FALSE;
+ return (FMT_none);
+ }
+
+ pf = pFmtIn;
+ }
+
+ if (*pf == ',') {
+ pf++;
+ }
+ while ((*pf != 0) && ((*pf == ' ') || (*pf == '\t'))) {
+ pf++;
+ }
+
+ if (*pf == 0) {
+ // add string to pointer display
+ fPtrAndString = TRUE;
+ return (FMT_none);
+ }
+
+ fPtrAndString = FALSE;
+
+ size = (ushort)TypeSize (pv);
+ if (*pf != 0) {
+ // extract the prefix character if it exists
+
+ switch (*pf) {
+ case 'h':
+ case 'l':
+ case 'L':
+ prefix = *pf++;
+ break;
+ }
+
+ // extract the format character
+
+ switch (*pf) {
+ case 'd':
+ if ((prefix != 'h') && (size > 2)) {
+ prefix = 'l';
+ }
+ fmtchar = *pf++;
+ break;
+
+ case 'i':
+ if ((prefix != 'h') && (size > 2)) {
+ prefix = 'l';
+ }
+ fmtchar = *pf++;
+ break;
+
+ case 'u':
+ if ((prefix != 'h') && (size > 2)) {
+ prefix = 'l';
+ }
+ fmtchar = *pf++;
+ break;
+
+ case 'o':
+ if ((prefix != 'h') && (size > 2)) {
+ fmtcnt = '1';
+ fmtcnt2 = '1';
+ prefix = 'l';
+ } else {
+ fmtcnt = '6';
+ }
+ fmtchar = *pf++;
+ break;
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ /*
+ * Ensure that the value is of type float
+ */
+
+ if (!CV_TYP_IS_REAL( EVAL_TYP( pv ))) {
+ return FMT_error;
+ }
+
+ /*
+ * Validate for legal prefix character
+ */
+
+ if (prefix == 0) {
+ ;
+ } else if (prefix == 'h') {
+ return (FMT_error);
+ } else if (prefix == 'l') {
+ fmtcnt = '#';
+ } else if (prefix == 'L') {
+#ifdef LONG_DOUBLE_64
+ prefix = 'l';
+ fmtcnt = '#';
+#endif
+#ifdef LONG_DOUBLE_80
+ /*
+ * Hack since we don't have code for 'Lf' convert
+ * to lf
+ */
+ if ((fmtchar == 'f') || (fmtchar == 'F')) {
+ EVAL_DOUBLE(pv) = R10CastToDouble(EVAL_LDOUBLE(pv));
+ prefix = 'l';
+ fmtcnt = '#';
+ }
+#endif
+ } else {
+ return FMT_error;
+ }
+
+ fmtchar = *pf++;
+ break;
+
+ case 'c':
+ case 's':
+ switch ( prefix ) {
+ case 0:
+ if ( ((size == 2) && (*pf == 'c')) ||
+ UseUnicode(pv) ) {
+ prefix = 'l';
+ } else {
+ prefix = 'h';
+ }
+ break;
+
+ case 'l':
+ case 'h':
+ break;
+
+ default:
+ return (FMT_error);
+ }
+
+ fmtchar = *pf++;
+ break;
+
+ case 'x':
+ case 'X':
+ if ((prefix != 'h') && (size > 2)) {
+ // note that only the first 8 bytes of a long double
+ // will be displayed
+ fmtcnt = '8';
+ prefix = 'l';
+ }
+ else {
+ fmtcnt = '4';
+ }
+ fmtchar = *pf++;
+ break;
+
+ default:
+ return (FMT_error);
+ }
+ if ((*pf != 0) && !isspace (*pf)) {
+ return (FMT_error);
+ }
+
+ pf = fmtstr;
+ *pf++ = '%';
+ if (fmtcnt != 0) {
+ *pf++ = fmtcnt;
+ if (fmtcnt2 != 0) {
+ *pf++ = fmtcnt2;
+ }
+ }
+
+ if (prefix != 0) {
+ *pf++ = prefix;
+ }
+ *pf++ = fmtchar;
+ *pf = 0;
+ switch (fmtchar) {
+ case 'd':
+ case 'i':
+ case 'u':
+ cnt = sprintf (tempbuf, fmtstr, EVAL_LONG (pv));
+ break;
+
+ case 'o':
+ pf = fmtstr;
+ *pf++ = '0';
+ *pf++ = 'o';
+ *pf++ = '%';
+ *pf++ = '0';
+ if (fmtcnt != 0) {
+ *pf++ = fmtcnt;
+ if (fmtcnt2 != 0) {
+ *pf++ = fmtcnt2;
+ }
+ }
+ if (prefix != 0) {
+ *pf++ = prefix;
+ }
+ *pf++ = fmtchar;
+ *pf = 0;
+ cnt = sprintf (tempbuf, fmtstr, EVAL_LONG (pv));
+ break;
+
+
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ if (prefix == 'l') {
+ cnt = _snprintf (tempbuf, sizeof(tempbuf), fmtstr, EVAL_DOUBLE (pv));
+ } else if (prefix == 'L') {
+#ifdef LONG_DOUBLE_80
+ _uldtoa((_ULDOUBLE *) &EVAL_LDOUBLE( pv ), 25, tempbuf);
+ cnt = strlen(tempbuf);
+ if ((fmtchar == 'E') || (fmtchar == 'G')) {
+ _strupr(tempbuf);
+ }
+#endif
+#ifdef LONG_DOUBLE_64
+ DASSERT(FALSE);
+#endif
+ } else {
+ cnt = _snprintf (tempbuf, sizeof(tempbuf), fmtstr, EVAL_FLOAT (pv));
+ }
+ break;
+
+ case 'c':
+ {
+ unsigned short s;
+
+ pf = fmtstr;
+ *pf++ = '\'';
+
+ if ( prefix == 'l' ) {
+ s = EVAL_USHORT(pv);
+ } else {
+ s = (unsigned short)EVAL_CHAR(pv);
+ }
+
+ if (s != 0) {
+ // if the value is not zero, then display it.
+ // otherwise, display ''
+ *pf++ = '%';
+ *pf++ = fmtchar;
+ }
+ *pf++ = '\'';
+ *pf = 0;
+
+ //
+ // NOTENOTE ramonsa - Convert unicode if necessary.
+ //
+
+ cnt = sprintf (tempbuf, fmtstr, s);
+ }
+ break;
+
+ case 's':
+ if (EVAL_IS_ADDR (pv)) {
+ // Need to set Evaluating to 1 to force Normalization
+ // of based ptrs in CastNode (and reset to 0 immediately
+ // afterwards
+
+ Evaluating = TRUE;
+ if ( prefix == 'l' ) {
+ CastNode (pv, T_PFWCHAR, T_PFWCHAR);
+
+ } else {
+ CastNode (pv, T_PFCHAR, T_PFCHAR);
+ }
+ EvalString (pv, buf, buflen);
+ Evaluating = FALSE;
+ return (FMT_ok);
+ }
+ else {
+ return (FMT_error);
+ }
+ break;
+
+ case 'x':
+ case 'X':
+ if (EVAL_IS_PTR (pv)) {
+ addr = EVAL_PTR (pv);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+
+ /*
+ * Treat near pointers the same as far pointers
+ * for formatting purposes. Thus if you would
+ * display a segment for the far pointer then
+ * also display it for the near pointer.
+ */
+
+ if ((EVAL_IS_NPTR32(pv)) || (EVAL_IS_FPTR32(pv))) {
+ DASSERT( ADDR_IS_FLAT( addr ) );
+ }
+
+ EEFormatAddr(&addr, tempbuf, sizeof(tempbuf),
+ (fmtchar == 'x') ? EEFMT_LOWER : 0);
+ cnt = strlen(tempbuf);
+ }
+ else {
+ pf = fmtstr;
+ *pf++ = '0';
+ *pf++ = fmtchar;
+ *pf++ = '%';
+ *pf++ = '.';
+ if (fmtcnt != 0) {
+ *pf++ = fmtcnt;
+ }
+ if (prefix != 0) {
+ *pf++ = prefix;
+ }
+ *pf++ = fmtchar;
+ *pf = 0;
+ cnt = sprintf (tempbuf, fmtstr, EVAL_ULONG (pv));
+
+ }
+ break;
+ }
+
+ if ((cnt == -1) || (cnt > (ushort)*buflen)) {
+ strcpy(tempbuf, "******");
+ cnt = 6;
+ }
+ _fstrncpy (*buf, tempbuf, cnt + 1);
+ *buf += cnt;
+ *buflen -= cnt;
+ return (FMT_ok);
+ }
+}
+
+
+
+
+
+
+
+/* Format - format data
+ *
+ */
+
+
+LOCAL void NEAR PASCAL Format (peval_t pv, uint radix, char FAR * FAR *buf,
+ uint FAR *plen)
+{
+ char tempbuf[FMTSTRMAX];
+ char FAR *pTempBuf = tempbuf;
+ int cnt;
+ ushort isfloat = FALSE;
+ HSYM hProc = 0;
+ // M00FLAT32
+ SYMPTR pProc;
+ char FAR *pc = NULL;
+ uint cbTempBuf;
+ uint FAR *pcbTempBuf = &cbTempBuf;
+ ushort iRadix;
+ ADDR addr;
+ CV_typ_t type;
+ EEHSTR hStr = 0;
+
+ if (*plen < 5 ) {
+ return;
+ }
+
+ if (EVAL_IS_BITF (pv)) {
+ // for a bitfield, change the type to the underlying type
+ SetNodeType (pv, BITF_UTYPE (pv));
+ }
+ if (EVAL_IS_CLASS (pv)) {
+ FormatClass (pv, radix, buf, plen);
+ return;
+ }
+ else if (EVAL_IS_ENUM (pv)) {
+ SetNodeType (pv, CLASS_UTYPE (pv));
+ }
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pv)) && !EVAL_IS_PTR (pv)) {
+ if (EVAL_TYP (pv) == T_VOID) {
+ _fstrcpy (tempbuf, "<void>");
+ }
+ else {
+ // establish format string index
+ switch (radix) {
+ case 8:
+ iRadix = 0;
+ break;
+
+ case 10:
+ iRadix = 1;
+ break;
+
+ default:
+ DASSERT (FALSE);
+ // note fall through
+ case 16:
+ iRadix = 2;
+ break;
+ }
+
+ switch (EVAL_TYP (pv)) {
+ case T_CHAR:
+ case T_RCHAR:
+ case T_UCHAR:
+ if (EVAL_TYP (pv) == T_UCHAR) {
+ sprintf (tempbuf, fmt_uchar[iRadix], EVAL_CHAR (pv));
+ } else {
+ sprintf (tempbuf, fmt_char[iRadix], EVAL_CHAR (pv));
+ }
+ if (strlen(tempbuf) > 4) {
+ strcpy(&tempbuf[2],&tempbuf[strlen(tempbuf)-2]);
+ }
+ if (fPtrAndString) {
+ if (EVAL_CHAR (pv) == 0) {
+ sprintf( &tempbuf[strlen(tempbuf)], " ''" );
+ } else {
+ sprintf( &tempbuf[strlen(tempbuf)], " '%c'", EVAL_CHAR(pv) );
+ }
+ }
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+
+ sprintf (tempbuf, fmt_short[iRadix], EVAL_SHORT (pv));
+ break;
+
+ case T_SEGMENT:
+ case T_USHORT:
+ case T_UINT2:
+ default:
+ sprintf (tempbuf, fmt_ushort[iRadix], EVAL_USHORT (pv));
+ break;
+
+ case T_LONG:
+ case T_INT4:
+ sprintf (tempbuf, fmt_long[iRadix], EVAL_LONG (pv));
+ break;
+
+ case T_ULONG:
+ case T_UINT4:
+ sprintf (tempbuf, fmt_ulong[iRadix], EVAL_ULONG (pv));
+ break;
+
+ case T_QUAD:
+ case T_INT8:
+
+ EEFormatMemory(tempbuf,
+ 17,
+ (LPBYTE) &EVAL_QUAD(pv),
+ 64,
+ fmtInt | fmtZeroPad,
+ radix);
+ break;
+
+ case T_UQUAD:
+ case T_UINT8:
+
+ EEFormatMemory(tempbuf,
+ 17,
+ (LPBYTE) &EVAL_QUAD(pv),
+ 64,
+ fmtUInt | fmtZeroPad,
+ radix);
+ break;
+
+ case T_REAL32:
+ sprintf (tempbuf, "%#g", EVAL_FLOAT (pv));
+ isfloat = TRUE;
+ break;
+
+ case T_REAL64:
+ sprintf (tempbuf, "%#.15lg", EVAL_DOUBLE (pv));
+ isfloat = TRUE;
+ break;
+
+#ifdef LONG_DOUBLE_80
+ case T_REAL80:
+ _uldtoa((_ULDOUBLE *) &EVAL_LDOUBLE( pv ), 25, tempbuf);
+ isfloat = TRUE;
+ break;
+#endif
+ }
+ }
+ }
+ else if (EVAL_IS_ADDR (pv)) {
+ addr = EVAL_PTR (pv);
+ if (EVAL_IS_BASED (pv)) {
+ cbTempBuf = sprintf (tempbuf, "0x%04lX", (ulong)EVAL_PTR_OFF (pv));
+ }
+ else if (EVAL_IS_PTR (pv) && EVAL_IS_REG (pv)) {
+ if (EVAL_IS_NPTR (pv)) {
+ EEFormatAddress(pExState->frame.DS, EVAL_PTR_OFF (pv),
+ tempbuf, sizeof(tempbuf), 0);
+ cbTempBuf = strlen(tempbuf);
+ }
+ else if (EVAL_IS_NPTR32 (pv)) {
+ EEFormatAddress(pExState->frame.DS, EVAL_PTR_OFF (pv),
+ tempbuf, sizeof(tempbuf), EEFMT_32);
+ cbTempBuf = strlen(tempbuf);
+ }
+ else {
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+
+ if (EVAL_IS_FPTR32(pv)) {
+ DASSERT( ADDR_IS_FLAT( addr ) );
+ }
+
+ EEFormatAddr(&addr, tempbuf, sizeof(tempbuf), 0);
+ cbTempBuf = strlen(tempbuf);
+
+ }
+ }
+ else if (EVAL_IS_PTR (pv) && EVAL_IS_NPTR (pv)) {
+ // if it is a near ptr we will treat is as a far ptr
+ // since we always carry around the seg & offset
+ // even if it is near.
+ // DASSERT( EVAL_PTR_SEG (pv) != 0);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+ EEFormatAddr( &addr, tempbuf, sizeof(tempbuf), 0);
+ cbTempBuf = strlen(tempbuf);
+ }
+ else if (EVAL_IS_PTR (pv) && EVAL_IS_NPTR32 (pv)) {
+ // if it is a near ptr we will treat is as a far ptr
+ // since we always carry around the seg & offset
+ // even if it is near.
+ // DASSERT( EVAL_PTR_SEG (pv) != 0);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+
+ DASSERT (ADDR_IS_FLAT( addr ));
+ EEFormatAddr( &addr, tempbuf, sizeof(tempbuf), 0);
+ cbTempBuf = strlen(tempbuf);
+
+ }
+ else {
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+ EEFormatAddr( &addr, tempbuf, sizeof(tempbuf), 0);
+ cbTempBuf = strlen(tempbuf);
+ }
+ if (!EVAL_IS_DPTR (pv)) {
+ addr = EVAL_PTR (pv);
+ if (!ADDR_IS_LI (addr)) {
+ SHUnFixupAddr (&addr);
+ }
+ if (SHGetNearestHsym (&addr, EVAL_MOD (pv), EECODE, &hProc) == 0) {
+ // the address exactly matches a symbol
+ pProc = (SYMPTR)MHOmfLock( (HDEP)hProc );
+ switch ( pProc->rectyp ) {
+
+ char FAR *TempName;
+ CV_typ_t TempType;
+
+#if defined (ADDR_16) || defined (ADDR_MIXED)
+ case S_LPROC16:
+ case S_GPROC16:
+
+ TempName = ((PROCPTR16)pProc)->name;
+ TempType = ((PROCPTR16)pProc)->typind;
+ MHOmfUnLock ((HDEP)hProc);
+
+ pc = FormatVirtual ( TempName, TempType, pv, &hStr);
+ break;
+
+ case S_THUNK16:
+ pc = ((THUNKPTR16)pProc)->name;
+ MHOmfUnLock ((HDEP)hProc);
+ break;
+#endif
+
+#if defined (ADDR_32) || defined (ADDR_MIXED)
+
+ case S_LPROC32:
+ case S_GPROC32:
+
+ TempName = ((PROCPTR32)pProc)->name;
+ TempType = ((PROCPTR32)pProc)->typind;
+ MHOmfUnLock ((HDEP)hProc);
+
+ pc = FormatVirtual ( TempName, TempType, pv, &hStr);
+ break;
+
+ case S_THUNK32:
+ pc = ((THUNKPTR32)pProc)->name;
+ MHOmfUnLock ((HDEP)hProc);
+ break;
+#endif
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ TempName = ((PROCPTRMIPS)pProc)->name;
+ TempType = ((PROCPTRMIPS)pProc)->typind;
+ MHOmfUnLock ((HDEP)hProc);
+
+ pc = FormatVirtual ( TempName, TempType, pv, &hStr);
+ break;
+ }
+ }
+ }
+
+ // M00KLUDGE - display strings of chars
+ if ((fPtrAndString == TRUE) && (EVAL_IS_PTR (pv))) {
+ type = EVAL_TYP (pv);
+ if (EVAL_IS_BASED (pv)) {
+ type = PTR_UTYPE (pv);
+ }
+ if (((type & (CV_TMASK | CV_SMASK)) == T_CHAR) ||
+ ((type & (CV_TMASK | CV_SMASK)) == T_UCHAR) ||
+ ((type & (CV_TMASK | CV_SMASK)) == T_RCHAR)) {
+
+ // Need to set Evaluating to 1 to force Normalization
+ // of based ptrs in CastNode (and reset to 0 immediately
+ // afterwards)
+ tempbuf[cbTempBuf] = ' ';
+ Evaluating = TRUE;
+ CastNode (pv, T_PFCHAR, T_PFCHAR);
+ Evaluating = FALSE;
+ pTempBuf += cbTempBuf + 1;
+ *pcbTempBuf = FMTSTRMAX - cbTempBuf - 1;
+ EvalString (pv, &pTempBuf, pcbTempBuf);
+
+ } else if ( ((type & (CV_TMASK | CV_SMASK)) == T_WCHAR) ||
+ ((Suffix == 'W') && ((type & (CV_TMASK | CV_SMASK)) == T_USHORT)) ) {
+
+ tempbuf[cbTempBuf] = ' ';
+ Evaluating = TRUE;
+ CastNode (pv, T_PFWCHAR, T_PFWCHAR);
+ Evaluating = FALSE;
+ pTempBuf += cbTempBuf + 1;
+ *pcbTempBuf = FMTSTRMAX - cbTempBuf - 1;
+ EvalString (pv, &pTempBuf, pcbTempBuf);
+ }
+ }
+ }
+ else {
+ _fstrcpy (tempbuf,"?CANNOT DISPLAY");
+ }
+ cnt = (int)_fstrlen (tempbuf);
+ cnt = min (*plen, ( uint ) cnt);
+ _fstrncpy (*buf, tempbuf, cnt);
+ *plen -= cnt;
+ *buf += cnt;
+ if (pc != NULL) {
+ cnt = min (*plen, ( uint ) ( *pc + 1 ));
+ **buf = ' ';
+ (*buf)++;
+ _fstrncpy (*buf, pc + 1, cnt - 1);
+ *plen -= cnt;
+ *buf += cnt;
+ }
+ if (hStr != 0) {
+ MHMemUnLock (hStr);
+ MHMemFree (hStr);
+ }
+ return;
+}
+
+
+LOCAL void NEAR PASCAL FormatClass(
+ peval_t pv,
+ uint radix,
+ char **buf,
+ uint *buflen
+ )
+{
+ int len;
+ ADDR addr;
+ SHREG reg;
+
+
+ addr = pv->addr;
+ if (EVAL_IS_BPREL(pv)) {
+ GetAddrOff( addr ) += pExState->frame.BP.off;
+ GetAddrSeg( addr ) = pExState->frame.SS;
+ ADDR_IS_LI( addr ) = FALSE;
+ } else if (EVAL_IS_REGREL(pv)) {
+ reg.hReg = EVAL_REGREL(pv);
+ GetReg( &reg, pCxt );
+ GetAddrOff( addr ) += reg.Byte4;
+ GetAddrSeg( addr ) = pExState->frame.SS;
+ ADDR_IS_LI( addr ) = FALSE;
+ }
+
+ SHUnFixupAddr( &addr );
+ SHFixupAddr( &addr );
+
+ **buf = 0;
+ EEFormatAddr( &addr, *buf, *buflen, EEFMT_32 );
+ len = strlen( *buf );
+ *buflen -= len;
+ *buf += len;
+
+ len = min (*buflen, 6);
+ _fstrncpy (*buf, " {...}", len);
+ *buflen -= len;
+ *buf += len;
+
+ return;
+}
+
+
+
+
+/*
+ * EvalString
+ *
+ * Evaluate an expression whose format string contains an 's'.
+ */
+
+LOCAL void PASCAL EvalString (peval_t pv, char FAR *FAR *buf,
+ uint FAR *buflen)
+{
+ ADDR addr;
+ short count;
+ BOOL fUnicode;
+ ushort *p, *q;
+ int len;
+
+ fUnicode = (EVAL_TYP(pv) == T_PFWCHAR);
+
+ if(*buflen < 3) return;
+
+ **buf = '\"';
+ (*buf)++;
+ (*buflen)--;
+ addr = EVAL_PTR (pv);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+ if (EVAL_IS_PTR (pv) && (EVAL_IS_NPTR (pv) || EVAL_IS_NPTR32 (pv))) {
+ addr.addr.seg = pExState->frame.DS;
+ }
+
+ if ( fUnicode ) {
+
+ p = q = (ushort *)malloc( *buflen * sizeof(ushort) );
+
+ if ( !p ) {
+ **buf = 0;
+ return;
+ }
+
+ count = GetDebuggeeBytes (addr, *buflen * sizeof(ushort), p, T_WCHAR );
+
+ for (; *q != 0 && count > 0 && *buflen > 0; ) {
+
+ len = wctomb( *buf, *q++ );
+
+ if ( len == -1 ) {
+ break;
+ }
+
+ *buf += len;
+ *buflen -= len;
+ count -= sizeof( ushort );
+ }
+
+ free(p);
+
+ } else {
+ count = GetDebuggeeBytes (addr, *buflen - 2, *buf, T_RCHAR);
+
+ for (; (**buf != 0) && (count > 0); (*buf)++, count--) {
+ (*buflen)--;
+ }
+ }
+ **buf = '\"';
+ (*buf)++;
+ (*buflen)--;
+ **buf = 0;
+ (*buf)++;
+ (*buflen)--;
+}
+
+LOCAL char FAR *NEAR PASCAL FormatVirtual (char FAR *pc, CV_typ_t type, peval_t pv,
+ PEEHSTR phStr)
+{
+ char save;
+ char FAR *pEnd;
+ char FAR *bufsave;
+ char FAR *buf;
+ uint buflen;
+ PHDR_TYPE pHdr;
+ char FAR *pName;
+
+ if ((*phStr = MHMemAllocate (TYPESTRMAX + sizeof (HDR_TYPE))) == 0) {
+ // unable to allocate memory for type string. at least print name
+ return (pc);
+ }
+ bufsave = (char FAR *)MHMemLock (*phStr);
+ _fmemset (bufsave, 0, TYPESTRMAX + sizeof (HDR_TYPE));
+ buflen = TYPESTRMAX - 1;
+ pHdr = (PHDR_TYPE)bufsave;
+ buf = bufsave + sizeof (HDR_TYPE);
+ pCxt = &pExState->cxt;
+ bnCxt = 0;
+ pEnd = pc + *pc + 1;
+ save = *pEnd;
+ *pEnd = 0;
+ pName = pc + 1;
+ SetNodeType (pv, type);
+ FormatType (pv, &buf, &buflen, &pName, 1L, pHdr);
+ *pEnd = save;
+ *(bufsave + sizeof (HDR_TYPE) - 1) = TYPESTRMAX - 1 - buflen;
+ return (bufsave + sizeof (HDR_TYPE) - 1);
+}
+
+
+BOOL UseUnicode (
+ peval_t pv
+ )
+{
+ BOOL Ok = FALSE;
+ TYPPTR TypPtr;
+ lfBArray *LeafArray;
+
+ if (CV_IS_PRIMITIVE(EVAL_TYP(pv))) {
+
+ Ok = BaseIs16Bit( EVAL_TYP(pv) );
+
+ } else {
+
+ TypPtr = MHOmfLock( (HDEP)EVAL_TYPDEF(pv) );
+ LeafArray = (lfBArray *)&(TypPtr->leaf);
+
+ if ( LeafArray->leaf == LF_ARRAY ||
+ LeafArray->leaf == LF_BARRAY) {
+
+ Ok = BaseIs16Bit( LeafArray->utype );
+ }
+
+ MHOmfUnLock( (HDEP)EVAL_TYPDEF(pv) );
+ }
+
+ return Ok;
+}
+
+BOOL BaseIs16Bit (
+ CV_typ_t utype
+ )
+{
+ switch( utype ) {
+ case T_WCHAR:
+ case T_PWCHAR:
+ case T_PFWCHAR:
+ case T_PHWCHAR:
+ case T_32PWCHAR:
+ case T_32PFWCHAR:
+ case T_SHORT:
+ case T_USHORT:
+ case T_PSHORT:
+ case T_PUSHORT:
+ case T_PFSHORT:
+ case T_PFUSHORT:
+ case T_PHSHORT:
+ case T_PHUSHORT:
+ case T_32PSHORT:
+ case T_32PUSHORT:
+ case T_32PFSHORT:
+ case T_32PFUSHORT:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
diff --git a/private/windbg/eecan/deblex.c b/private/windbg/eecan/deblex.c
new file mode 100644
index 000000000..1b4ebfb64
--- /dev/null
+++ b/private/windbg/eecan/deblex.c
@@ -0,0 +1,963 @@
+/*** deblex.c - lexer module for expression evaluator
+ *
+ * Lexer routines for expression evaluator.
+ */
+
+
+
+
+ ushort PASCAL ParseOp (char FAR *, token_t FAR *);
+LOCAL ushort NEAR PASCAL CanonOp (uchar FAR *, ptoken_t);
+LOCAL ushort NEAR PASCAL ParseIntConst (uchar FAR *, ptoken_t, uint, PLARGE_INTEGER);
+LOCAL ushort NEAR PASCAL ParseFloatConst (uchar FAR *, ptoken_t);
+LOCAL ushort NEAR PASCAL ParseIdent (uchar FAR *, ptoken_t, bool_t);
+LOCAL ushort NEAR PASCAL ParseChar (uchar FAR *, ptoken_t);
+LOCAL ushort NEAR PASCAL ParseString (uchar FAR *, ptoken_t);
+LOCAL ushort NEAR PASCAL FakeIdent (uchar FAR *pb, ptoken_t pTok);
+LOCAL bool_t NEAR PASCAL FInRadix (uchar, uint);
+
+struct Op {
+ char str[5];
+#ifdef WIN32
+} OpStr[] = {
+#else
+} _based (_segname("_CODE")) OpStr[] = {
+#endif
+ {"\003->*"},
+ {"\003>>="},
+ {"\003<<="},
+ {"\002+="},
+ {"\002-="},
+ {"\002*="},
+ {"\002/="},
+ {"\002%="},
+ {"\002^="},
+ {"\002&="},
+ {"\002|="},
+ {"\002<<"},
+ {"\002>>"},
+ {"\002=="},
+ {"\002!="},
+ {"\002<="},
+ {"\002>="},
+ {"\002&&"},
+ {"\002||"},
+ {"\002++"},
+ {"\002--"},
+ {"\002->"},
+ {"\001+"},
+ {"\001-"},
+ {"\001*"},
+ {"\001/"},
+ {"\001%"},
+ {"\001^"},
+ {"\001&"},
+ {"\001|"},
+ {"\001~"},
+ {"\001!"},
+ {"\001="},
+ {"\001<"},
+ {"\001>"},
+ {"\001,"},
+};
+
+#define OPCNT (sizeof (OpStr)/sizeof (struct Op))
+
+
+/*** GetDBToken - Fetch next token from expression string
+ *
+ * status = GetDBToken (pbExpr, ptoken, radix, oper)
+ *
+ * Entry pbExpr = far pointer to expression string
+ * ptoken = pointer to token return location
+ * radix = default radix for numeric conversion
+ * oper = previous operator
+ *
+ * Exit *ptoken = token as lexed from input string. If an
+ * error occurred, the token will be of type OP_badtok.
+ * If the token is a constant, its value will be determined and
+ * placed in the token's 'val' field, and its type
+ * (e.g., T_USHORT) will be placed in the token's 'typ' field.
+ * If the previous operator is ., ->, ::, then ~ as the next
+ * character is taken to be part of an identifier
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error encountered in parse
+ *
+ * Calls the appropriate routine to lex the input string. Handles:
+ *
+ * foo Identifiers OP_ident
+ * +, -, etc. Operators OP_...
+ * 345 Decimal constants OP_const
+ * 0123 Octal constants OP_const
+ * 0xABCD Hexadecimal constants OP_const
+ * 'a', '\n' Character constants OP_const
+ * "foo" String constants OP_const
+ * L"foo" Wide string constants OP_const
+ * 3.45 Floating point constants OP_const
+ * 0xff handle to symbol follows OP_ident
+ *
+ * The handle to symbol is a hack to make sure that an expression
+ * can be generated from and locked to the handle to symbol that is
+ * passed to EEGetTMFromHSYM by the kernel
+ */
+
+
+ushort PASCAL GetDBToken (uchar FAR *pbExpr, ptoken_t pTok, uint radix, op_t oper)
+{
+ uchar c;
+ uchar FAR *pbSave = pbExpr;
+ ushort error;
+
+ memset (pTok, 0, sizeof (token_t));
+ pTok->opTok = OP_badtok;
+ pTok->pbTok = (char FAR *)pbExpr;
+ c = *pbExpr;
+ if (c == '~') {
+ switch (oper) {
+ case OP_dot:
+ case OP_pointsto:
+ case OP_uscope:
+ case OP_bscope:
+ case OP_pmember:
+ case OP_dotmember:
+ error = ParseIdent (pbExpr, pTok, TRUE);
+ pTok->cbTok = (uchar)(pTok->pbEnd - pTok->pbTok);
+ return (error);
+ }
+ }
+
+ if (isdigit (c)) {
+ error = ParseConst (pbExpr, pTok, radix);
+ }
+ else if (((c == 'L') && (pbExpr[1] == '"')) || (c == '"')) {
+ error = ParseString (pbExpr, pTok);
+ }
+ else if ((iscsymf(c)) || (c == '?') || (c == '$') || (c == '@')) {
+ error = ParseIdent (pbExpr, pTok, FALSE);
+ }
+ else if (c == '\'') {
+ error = ParseChar (pbExpr, pTok);
+ }
+ else if (c == '.') {
+
+ c = *(pbExpr+1);
+
+ if ( (c == 0) || (c == '+') || (c=='-') || (c==')')) {
+ error = ParseIdent (pbExpr, pTok, FALSE);
+ } else if ( isdigit(c) ) {
+ error = ParseConst (pbExpr, pTok, radix);
+ } else {
+ error = ParseOp (pbExpr, pTok);
+ }
+ }
+ else if (c == 0xff) {
+ error = FakeIdent (pbExpr, pTok);
+ }
+ else {
+ error = ParseOp (pbExpr, pTok);
+ }
+ pTok->cbTok = (uchar)(pTok->pbEnd - pTok->pbTok);
+
+ // note that caller must compute index of token
+
+ return (error);
+}
+
+
+
+
+/** ParseConst - Parse an integer or floating point constant string
+ *
+ * error = ParseConst (pb, pTok, radix);
+ *
+ * Entry pb = far pointer to string
+ * pTok = pointer to return token
+ * radix = default radix for numeric conversion
+ *
+ * Exit *pTok initialized for constant
+ * pTok->pbEnd = end of token
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error encountered
+ */
+
+
+ushort PASCAL ParseConst (uchar FAR *pb, ptoken_t pTok, uint radixin)
+{
+ char FAR *pbSave = pb;
+ uint radix = radixin;
+ bool_t fUSuffix = FALSE;
+ bool_t fLSuffix = FALSE;
+ bool_t fFitsInt = FALSE;
+ bool_t fFitsUint = FALSE;
+ bool_t fFitsLong = FALSE;
+ bool_t fFitsQuad = FALSE;
+ LARGE_INTEGER value;
+ CV_typ_t typ;
+ ushort error;
+
+ // check beginning of constant for radix specifiers
+
+ if ((*pb == '0') && (*(pb + 1) != '.')) {
+ pb++;
+ if (toupper (*pb) == 'X') {
+ // Hex constant 0x.......
+ radix = 16;
+ ++pb;
+ }
+ else if (toupper(*pb) == 'T') {
+ // Decimal constant 0t......
+ radix = 10;
+ ++pb;
+ }
+ else if (toupper(*pb) == 'O') {
+ // Octal constant 0........
+ radix = 8;
+ ++pb;
+ } else {
+ // No radix override (012 is in current radix)
+ --pb;
+ }
+ }
+
+ if ((*pb != '.') && FInRadix (*pb, radix)) {
+ // save pointer to string and parse as integer constant
+ if ((error = ParseIntConst (pb, pTok, radix, &value)) != ERR_NONE) {
+ // error parsing as integer constant
+ return (error);
+ }
+ if ((*pTok->pbEnd == '.') || (toupper (*pTok->pbEnd) == 'E') ||
+ (toupper (*pTok->pbEnd) == 'F')) {
+ // Back up and reparse string as floating point
+ return (ParseFloatConst (pbSave, pTok));
+ }
+ }
+ else if (*pb == '.') {
+ return (ParseFloatConst (pbSave, pTok));
+ }
+ else {
+ return (ERR_SYNTAX);
+ }
+
+ // Check for the 'u' and 'l' modifiers.
+
+ pb = pTok->pbEnd;
+ if (toupper(*pb) == 'U') {
+ ++pb;
+ fUSuffix = TRUE;
+ if (toupper(*pb) == 'L') {
+ ++pb;
+ fLSuffix = TRUE;
+ }
+ }
+ else if (toupper(*pb) == 'L') {
+ ++pb;
+ fLSuffix = TRUE;
+ if (toupper(*pb) == 'U') {
+ ++pb;
+ fUSuffix = TRUE;
+ }
+ }
+
+ // ANSI spec, section 3.1.3.2:
+ //
+ // The type of an integer constant is the first of the corresponding
+ // list in which its value can be represented:
+ // unsuffixed decimal : int, long int, unsigned long int
+ // unsuffixed octal or hex : int, unsigned int, long int, unsigned long int;
+ // suffixed by the letter u or U : unsigned int, unsigned long int
+ // suffixed by the letter l or L : long int, unsigned long int
+ // suffixed by both the letters u or U and l or L: unsigned long int.
+ //
+ // To extend for quad values:
+ // unsuffixed decimal: postpend __int64
+ // octal or hex: postpend __int64, unsigned __int64
+ // suffix with u or U: postpend unsigned __int64
+ // suffix with l or L: postpend __int64, unsigned __int64
+ // suffix with both: postpend unsigned __int64
+ // Technically, ANSI doesn't know anything about quads. It's being assumed here
+ // to be either the same or larger than long (where ANSI sees long as the longest).
+ //
+
+
+ if ( (value.HighPart == 0) || (value.HighPart == -1L) ) {
+
+ if (value.LowPart < 0x8000L) {
+ fFitsInt = TRUE;
+ }
+ if (value.LowPart < 0x10000L && value.HighPart == 0 ) {
+ fFitsUint = TRUE;
+ }
+ if (value.LowPart < 0x80000000L) {
+ fFitsLong = TRUE;
+ }
+ if (value.HighPart == 0) {
+ typ = T_UINT4;
+ } else {
+ typ = T_INT4;
+ }
+ } else {
+ if ( (LONG)value.HighPart < 0x80000000L ) {
+ fFitsQuad = TRUE;
+ }
+ typ = T_UINT8;
+ }
+
+ if ((fUSuffix) && (fLSuffix)) {
+ // it's already the smaller of T_UINT8 or T_UINT4
+ ;
+ }
+ else if (fUSuffix) {
+ if (fFitsUint) {
+ typ = T_UINT2;
+ }
+ }
+ else if (fLSuffix) {
+ //
+ // might be long int, unsigned long int,
+ // __int64, unsigned __int64
+ //
+
+ if (fFitsLong) {
+ typ = T_INT4;
+ }
+ if (fFitsQuad) {
+ typ = T_INT8;
+ }
+ }
+ else {
+ if (fFitsInt) {
+ typ = T_INT2;
+ }
+ else if ((fFitsUint) && (radix != 10)) {
+ typ = T_UINT2;
+ }
+ else if (fFitsLong) {
+ typ = T_INT4;
+ }
+ else if (fFitsQuad) {
+ typ = T_INT8;
+ }
+ }
+
+ pTok->typ = typ;
+ pTok->opTok = OP_const;
+ pTok->pbEnd = pb;
+ VAL_QUAD (pTok) = value;
+ return (ERR_NONE);
+}
+
+
+
+
+/*** ParseIntConst - Parse an integer constant
+ *
+ * error = ParseIntConst (pb, pTok, radix, pval)
+ *
+ * Entry pb = pointer to pointer to input string
+ * pTok = pointer to token return
+ * radix = radix (8, 10, 16)
+ * pval = pointer to ulong for value of constant
+ *
+ * Exit pTok updated to reflect token
+ *
+ * Returns ERR_NONE if the input string was successfully parsed as an integer
+ * constant with the given radix
+ * ERR_... if error.
+ *
+ * Note This routine runs on any processor with LARGE_INTEGER support.
+ */
+
+
+LOCAL ushort NEAR PASCAL ParseIntConst (uchar FAR *pb, ptoken_t pTok, uint radix, PLARGE_INTEGER pval)
+{
+ char c;
+ LARGE_INTEGER li;
+ LARGE_INTEGER maxvalue;
+ ULONG junk;
+
+
+ maxvalue.QuadPart = (ULONGLONG)-1 / (ULONGLONG)radix;
+ li.QuadPart = 0;
+
+ DASSERT(radix == 10 || radix == 8 || radix == 16);
+
+ for (;;) {
+ c = *pb;
+
+ if (((radix > 10) && !isxdigit (c)) ||
+ ((radix <= 10) && !isdigit (c))) {
+ // Must have reached the end
+ break;
+ }
+
+ if (!FInRadix(c, radix)) {
+ return (ERR_SYNTAX);
+ }
+
+ if (li.QuadPart < 0 || li.QuadPart > maxvalue.QuadPart) {
+ //
+ // This is the overflow case
+ //
+ return ERR_CONSTANT;
+ }
+
+ li.QuadPart = li.QuadPart * radix;
+
+ if (isdigit (c = *pb)) {
+ li.QuadPart += (c - '0');
+
+ } else {
+ li.QuadPart += (toupper(c) - 'A' + 10);
+ }
+ pb++;
+ }
+ *(PLARGE_INTEGER)pval = li;
+ pTok->pbEnd = pb;
+ return (ERR_NONE);
+}
+
+/** ParseFloatConst - Parse a floating-point constant
+ *
+ * fSuccess = ParseFloatConst (pb, pTok);
+ *
+ * Entry pb = pointer to input string
+ * pTok = pointer to parse token structure
+ *
+ * Exit pTok updated to reflect floating point number if one
+ * is found.
+ *
+ * Returns ERR_NONE if no error encountered
+ * ERR_... error
+ */
+
+
+LOCAL ushort NEAR PASCAL ParseFloatConst (uchar FAR *pb, ptoken_t pTok)
+{
+ char *pEnd;
+ CV_typ_t typ;
+ _ULDBL12 val;
+ char *pVal = (char *)&val;
+
+
+ // check for a single '.' - strtold returns 0 in such a case
+
+ if (((*pb == '.') && (!isdigit (*(pb + 1)))) ||
+ (strlen (pb)) >= 100) {
+ return (ERR_SYNTAX);
+ }
+
+ // Call library routine to figure out the value. This will also
+ // return a pointer to the first character which is not
+ // part of the value -- this allows us to check for an
+ // 'f' or 'l' suffix character:
+ //
+ // ANSI, Section 3.1.3.1:
+ //
+ // "An unsuffixed floating constant has type double.
+ // If suffixed by the letter f or F, it has type float.
+ // If suffixed by the letter l or L, it has type long double."
+
+ if ( __strgtold12(&val,&pEnd,pb,1) != 0 ) {
+ return(ERR_SYNTAX);
+ }
+
+ if (toupper (*pEnd) == 'F') {
+ pEnd++;
+ typ = T_REAL32;
+ _ld12tof(&val,(FLOAT *)&VAL_FLOAT(pTok));
+ }
+
+// MBH - bugbug (FP)
+// Is the correct handling for us?
+//
+#if defined (TARGET_MIPS) || defined( TARGET_i386) || defined(ALPHA) || defined(PPC)
+ else if (toupper(*pEnd) == 'L') {
+ pEnd++;
+
+#if defined( TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
+
+ //
+ // NOTENOTE: v_willhe, MIPS doesn't support long double, but treats
+ // it as a double, so we have to emulate.
+
+ typ = T_REAL64;
+ _ld12tod(&val,(UDOUBLE *)&VAL_DOUBLE(pTok));
+#endif
+
+#ifdef TARGET_i386
+ typ = T_REAL80;
+ _ld12told(&val,(_ULDOUBLE *)&VAL_LDOUBLE(pTok));
+#endif
+
+
+ }
+#endif /* defined (TARGET_MIPS) || defined(TARGET_i386) */
+
+ else {
+ typ = T_REAL64;
+ _ld12tod(&val,(UDOUBLE *)&VAL_DOUBLE(pTok));
+ }
+
+ pTok->opTok = OP_const;
+ pTok->typ = typ;
+ pTok->pbEnd = pEnd;
+ return (ERR_NONE);
+
+}
+
+
+
+
+/*** FakeIdent - Fake an identifier from handle to symbol
+ *
+ * error = FakeIdent (pb, pTok);
+ *
+ * Entry pb = far pointer to string
+ * pTok = pointer to return token
+ *
+ * Exit *pTok initialized for identifier fro handle to symbol
+ * pTok->pbEnd = end of token (first non-identifier character)
+ *
+ * Returns ERR_NONE
+ *
+ */
+
+
+LOCAL ushort NEAR PASCAL FakeIdent (uchar FAR *pb, ptoken_t pTok)
+{
+ pTok->opTok = OP_hsym;
+ pTok->pbEnd = pb + sizeof (char) + sizeof (HSYM);
+ return (ERR_NONE);
+}
+
+
+
+
+
+/*** ParseIdent - Parse an identifier
+ *
+ * error = ParseIdent (pb, pTok, fTilde);
+ *
+ * Entry pb = far pointer to string
+ * pTok = pointer to return token
+ * fTilde = TRUE if ~ acceptable as first character
+ *
+ * Exit *pTok initialized for identifier
+ * pTok->pbEnd = end of token (first non-identifier character)
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error encountered
+ * Also handles the 'sizeof', 'by', 'wo' and 'dw' operators, since these
+ * look like identifiers.
+ *
+ */
+
+
+LOCAL ushort NEAR PASCAL ParseIdent (uchar FAR *pb, ptoken_t pTok, bool_t fTilde)
+{
+ int len;
+
+ if ( *pb == '.' ) {
+ ++pb;
+ pTok->opTok = OP_ident;
+ pTok->pbEnd = pb;
+ } else if ((iscsymf(*pb)) || (*pb == '?') || (*pb == '$') || (*pb == '@') ||
+ ((*pb == '~') && (fTilde == TRUE))) {
+ ++pb;
+ while ((iscsym(*pb)) || (*pb == '?') || (*pb == '$') ||
+ (*pb == '@')) {
+ ++pb;
+ }
+ pTok->opTok = OP_ident;
+ pTok->pbEnd = pb;
+ }
+
+ // Check for the 'operator', 'sizeof', 'by', 'wo' and 'dw' operators.
+
+ if ((len = pTok->pbEnd - pTok->pbTok) == 6) {
+ if (strncmp (pTok->pbTok, "sizeof", 6) == 0) {
+ pTok->opTok = OP_sizeof;
+ }
+ }
+#if !defined (C_ONLY)
+ else if (len == 8) {
+ if (strncmp (pTok->pbTok, "operator", 8) == 0) {
+ // allow for operator op
+ return (CanonOp (pb, pTok));
+ }
+ }
+#endif
+ else if (len == 2) {
+ // Could be 'by', 'wo' or 'dw'...
+ if (_strnicmp (pTok->pbTok, "BY", 2) == 0) {
+ pTok->opTok = OP_by;
+ }
+ else if (_strnicmp (pTok->pbTok, "WO", 2) == 0) {
+ pTok->opTok = OP_wo;
+ }
+ else if (_strnicmp (pTok->pbTok, "DW", 2) == 0) {
+ pTok->opTok = OP_dw;
+ }
+ }
+ return (ERR_NONE);
+}
+
+
+
+
+/** CanonOp - canonicalize operator string
+ *
+ * error = CanonOp (pb, pTok)
+ *
+ * Entry pb = pointer to first character after "operator"
+ *
+ * Exit string rewritten to ripple excess white space to the right
+ * pTok updated to reflect total function name
+ * pb points to '(' of function call
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error
+ */
+
+
+#if !defined (C_ONLY)
+LOCAL ushort NEAR PASCAL CanonOp (uchar FAR *pb, ptoken_t pTok)
+{
+ char FAR *pOp = pb;
+ char FAR *pTemp;
+ int i;
+
+ while (isspace (*pb)) {
+ pb++;
+ }
+ if (*pb == 0) {
+ return (ERR_SYNTAX);
+ }
+ if (isalpha (*pb)) {
+ // process new, delete
+ // process
+ // {[const &| volatile] id [const &| volatile]}
+ // [{\*[const &| volatile]}*[{\&[const &| volatile]}]]
+ //
+ // Note that the current code only processes a single id
+ // new (), delete () and type () will pass. All others will
+ // cause a syntax error later.
+
+ pTemp = pb;
+ while (isalpha (*pTemp)) {
+ // skip to end of alpha string
+ pTemp++;
+ }
+ *pOp++ = ' ';
+ memmove (pOp, pb, pTemp - pb);
+ pOp += pTemp - pb;
+ pb = pTemp;
+ }
+ else if (*pb == '(') {
+ // process "( )"
+ pb++;
+ while (*pb++ != ')') {
+ if (!isspace (*pb)) {
+ return (ERR_SYNTAX);
+ }
+ }
+ *pOp++ = '(';
+ *pOp++ = ')';
+ }
+ else if (*pb == '[') {
+ // process "[ ]"
+ pb++;
+ while (*pb++ != ']') {
+ if (!isspace (*pb)) {
+ return (ERR_SYNTAX);
+ }
+ }
+ *pOp++ = '[';
+ *pOp++ = ']';
+ }
+ else {
+ // process operator strings
+ for ( i = 0; i < OPCNT; i++) {
+ if (strncmp (OpStr[i].str + 1, pb, OpStr[i].str[0]) == 0) {
+ break;
+ }
+ }
+ if (i == OPCNT) {
+ return (ERR_SYNTAX);
+ }
+ memmove (pOp, OpStr[i].str + 1, OpStr[i].str[0]);
+ pOp += OpStr[i].str[0];
+ pb += OpStr[i].str[0];
+ }
+
+ // blank out moved characters
+
+ pTok->pbEnd = pOp;
+ while (pOp < pb) {
+ *pOp++ = ' ';
+ }
+
+ // skip to the next token and check to make sure it is a (
+ // the zero and ) checks are to allow "bp operator +" and
+ // bp (operator +)
+
+ while (isspace (*pb)) {
+ pb++;
+ }
+ if ((*pb == '(') || (*pb == 0) || (*pb == ')')) {
+ return (ERR_NONE);
+ }
+ else {
+ return (ERR_SYNTAX);
+ }
+}
+#endif
+
+
+/** GetEscapedChar - Parse an escaped character
+ *
+ * error = GetEscapedChar (ppb, pVal);
+ *
+ * Entry pb = far pointer to far pointer to string. pb points to
+ * character after the \
+ *
+ * Exit ppb updated to end of escaped character constant
+ * *pVal = value of escaped character constant
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error encountered
+ */
+
+
+
+ushort PASCAL GetEscapedChar (char FAR * FAR *pb, ushort FAR *pVal)
+{
+ char c;
+ uint nval = 0;
+
+ c = **pb;
+ (*pb)++;
+ switch (c) {
+ case 'n':
+ *pVal = '\n';
+ break;
+
+ case 't':
+ *pVal = '\t';
+ break;
+
+ case 'b':
+ *pVal = '\b';
+ break;
+
+ case 'r':
+ *pVal = '\r';
+ break;
+
+ case 'f':
+ *pVal = '\f';
+ break;
+
+ case 'v':
+ *pVal = '\v';
+ break;
+
+ case 'a':
+ *pVal = '\a';
+ break;
+
+ case 'x':
+ if (!FInRadix (**pb, 16)) {
+ return (ERR_SYNTAX);
+ }
+ for (;;) {
+ c = **pb;
+ if (!FInRadix (c, 16)) {
+ break;
+ }
+ nval *= 16;
+ if (isdigit (c)) {
+ nval += c - '0';
+ }
+ else {
+ nval += toupper(c) - 'A' + 10;
+ }
+ if (nval > 255) {
+ return (ERR_CONSTANT);
+ }
+ (*pb)++;
+ }
+ *pVal = (uchar)nval;
+ break;
+
+ default:
+ if (FInRadix (c, 8)) {
+ // Octal character constant
+ nval = (c - '0');
+ for (;;) {
+ c = **pb;
+ if (!isdigit (c)) {
+ break;
+ }
+ if (!FInRadix (c, 8)) {
+ return (ERR_SYNTAX);
+ }
+ nval = nval * 8 + (c - '0');
+ if (nval > 255) {
+ return (ERR_CONSTANT);
+ }
+ (*pb)++;
+ }
+ *pVal = (uchar)nval;
+ }
+ else {
+ *pVal = c;
+ }
+ break;
+ }
+ return (ERR_NONE);
+}
+
+
+
+
+/** ParseChar - Parse an character constant
+ *
+ * error = ParseChar (pb, pTok);
+ *
+ * Entry pb = far pointer to string
+ * pTok = pointer to return token
+ *
+ * Exit *pTok initialized for character constant
+ * pTok->pbEnd = end of token
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error encountered
+ */
+
+
+
+LOCAL ushort NEAR PASCAL ParseChar (uchar FAR *pb, ptoken_t pTok)
+{
+ char c;
+ ushort value;
+ ushort retval;
+
+ DASSERT(*pb == '\'');
+ ++pb;
+ if ((*pb == '\'') || (*pb == 0)) {
+ return (ERR_SYNTAX);
+ }
+ while ((*pb != '\'') && (*pb != 0)) {
+ if ((c = *pb++) == '\\') {
+ // Escaped character constant
+ if ((retval = GetEscapedChar (&pb, &value)) != ERR_NONE) {
+ return (retval);
+ }
+ }
+ else {
+ value = c;
+ }
+ }
+ if (*pb++ != '\'') {
+ return (ERR_MISSINGSQ);
+ }
+ pTok->opTok = OP_const;
+ VAL_CHAR(pTok) = (char) value;
+ pTok->typ = T_RCHAR;
+ pTok->pbEnd = pb;
+ return (ERR_NONE);
+}
+
+
+
+
+/** ParseString - Parse a string constant "..." or L"..."
+ *
+ * error = ParseString (pb, pTok, fWide);
+ *
+ * Entry pb = far pointer to string
+ * pTok = pointer to return token
+ *
+ * Exit *pTok initialized for string constant
+ * pTok->pbEnd = end of token
+ *
+ * Returns ERR_NONE if no error
+ * ERR_... if error encountered
+ *
+ * Note The string pointer will point to the initial " or L"
+ * and the byte count will include beginning " or L" and the
+ * ending ". The evaluator will have to adjust for the extra
+ * characters and store the proper data.
+ */
+
+
+LOCAL ushort NEAR PASCAL ParseString (uchar FAR *pb, ptoken_t pTok)
+{
+ if (*pb =='L') {
+ // skip initial L if L"
+ pb++;
+ }
+
+ // skip initial "
+
+ pb++;
+
+ // search for ending double quote
+
+ while ((*pb != 0) && (*pb != '"')) {
+ if (*pb == '\\' && *(pb + 1) == '"') {
+ pb++;
+ }
+ pb++;
+ }
+ if (!*pb) {
+ // reached end of string
+ return (ERR_MISSINGDQ);
+ }
+ pTok->opTok = OP_const;
+ pTok->typ = T_PCHAR;
+ pTok->pbEnd = pb + 1;
+ return (ERR_NONE);
+}
+
+
+
+
+/*** FInRadix - Is character appropriate for radix?
+ *
+ * fOK = FInRadix (ch, radix)
+ *
+ * Entry ch = character to check
+ * radix = 8, 10, 16
+ *
+ * Exit none
+ *
+ * Returns TRUE if character is in radix
+ * FALSE if not.
+ *
+ */
+
+
+LOCAL bool_t NEAR PASCAL FInRadix (uchar ch, uint radix)
+{
+ switch (radix) {
+ case 8:
+ if (ch >= '8') {
+ return (FALSE);
+ }
+ // Fall through
+
+ case 10:
+ return (isdigit(ch));
+
+ case 16:
+ return (isxdigit(ch));
+
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+}
diff --git a/private/windbg/eecan/deblexer.c b/private/windbg/eecan/deblexer.c
new file mode 100644
index 000000000..63b44000c
--- /dev/null
+++ b/private/windbg/eecan/deblexer.c
@@ -0,0 +1,330 @@
+/*-----------------------------------------------------------
+; DEBLEXER.ASM
+;
+; This module implements a very basic transition diagram lexer for
+; use in the QC debugging expression evaluator. It is flexible enough
+; to facilitate future expansion to include more operators.
+;
+; The state tables are fairly simple to operate. Consider, for example,
+; the '>' symbol in C. This can be followed by '>', '=' or something
+; else. If it is followed by '>', it can thereafter be followed by
+; '=' or something else. In all, we have four possibilities:
+;
+; >, >=, >>, >>=
+;
+; The transition diagram would be something like:
+;
+; '>' '>' '='
+; start ----- state1 ----- state2 ----- token('>>=')
+; | |
+; | |other
+; | +----- token('>>')
+; | '='
+; +----- token('>=')
+; |
+; |other
+; +----- token('>')
+;
+; Each entry in LexTable is a single character (thus, a transition to
+; another state based on "char is digit 0..9" CANNOT be handled by this
+; code -- that's why it's simple) followed by either the identifier
+; INTERMEDIATE or ENDSTATE, indicating whether following that edge leads you
+; to a new state or to an actual value (token). If it is followed by
+; INTERMEDIATE, the next word must contain the offset of the new state
+; table. If followed by ENDSTATE, the next word contains the token value.
+;
+; Thus, the above example would look like this (using the macro defined
+; below):
+;
+; LexTable label byte
+;
+; LexEntry '>', INTERMEDIATE, <dataOFFSET LTstate1>
+; ...
+; (other entries)
+; ...
+; LexEntry TABLE_END, 0, 0
+;
+; LTstate1 label byte
+;
+; LexEntry '>', INTERMEDIATE, <dataOFFSET LTstate2>
+; LexEntry '=', ENDSTATE, TOK_GTEQ
+; LexEntry OTHER, ENDSTATE, TOK_GT
+;
+; LTstate2 label byte
+;
+; LexEntry '=', ENDSTATE, TOK_GTGTEQ
+; LexEntry OTHER, ENDSTATE, TOK_GTGT
+;
+; Note that for the intermediate state tables, a TABLE_END entry is
+; unnecessary since the OTHER route is automatically taken.
+;
+; These routines do NOT handle identifiers or constants; only those
+; symbol strings explicitly defined in the state tables will be
+; recognized (i.e., only operators).
+;------------------------------------------------------------
+
+;------------------------------------------------------------
+; History:
+; 14.Apr.87 [mattg] Created
+; 30.Nov.87 [mattg] Upgrade for QC2.0, many ops added,
+; ident, constant parsing removed
+; 22.Mar.88 [mattg] Installed into QC2.0
+; 12.Jan.89 [mattg] Added many ops for QASM1.0
+;------------------------------------------------------------
+*/
+
+
+
+/*
+;------------------------------------------------------------
+; Macro for clean lexer tables
+;------------------------------------------------------------
+
+LexEntry macro Character, StateType, NextTableOrTok
+
+ db Character, StateType
+ifdef MODEL
+ dd NextTableOrTok
+else
+ dw NextTableOrTok
+endif
+
+ endm
+*/
+
+/*
+**
+** Identifiers used for tables
+**
+*/
+
+#define INTERMEDIATE 1
+#define ENDSTATE 2
+
+/*
+** The use of the following constants assumes that the character string
+** being lexed contains only ASCII values 00h <= val <= 7Fh.
+*/
+
+#define OTHER ((unsigned char) 0xFE)
+#define TABLE_END ((unsigned char) 0xFF)
+
+typedef struct ltbl FAR * LPLTBL;
+
+typedef struct ltbl {
+ unsigned char character;
+ unsigned char state;
+ LPLTBL next;
+} LTBL;
+
+/*
+**; Second state intermediate state tables
+*/
+
+LTBL LTltlt[] = {
+ '=', ENDSTATE, (LPLTBL) OP_shleq,
+ OTHER, ENDSTATE, (LPLTBL) OP_shl
+};
+
+LTBL LTgtgt[] = {
+ '=', ENDSTATE, (LPLTBL) OP_shreq,
+ OTHER, ENDSTATE, (LPLTBL) OP_shr
+};
+
+LTBL LTdashgt[] = {
+ '*', ENDSTATE, (LPLTBL) OP_pmember,
+ OTHER, ENDSTATE, (LPLTBL) OP_pointsto
+};
+
+/*
+** First state intermediate state tables
+*/
+
+LTBL LTdash[] = {
+ '>', INTERMEDIATE, (LPLTBL) LTdashgt,
+ '=', ENDSTATE, (LPLTBL) OP_minuseq,
+ '-', ENDSTATE, (LPLTBL) OP_decr,
+ OTHER, ENDSTATE, (LPLTBL) OP_negate
+};
+
+LTBL LTbang[] = {
+ '=', ENDSTATE, (LPLTBL) OP_bangeq,
+ OTHER, ENDSTATE, (LPLTBL) OP_bang
+};
+
+LTBL LTstar[] = {
+ '=', ENDSTATE, (LPLTBL) OP_multeq,
+ OTHER, ENDSTATE, (LPLTBL) OP_fetch
+};
+
+LTBL LTampersand[] = {
+ '&', ENDSTATE, (LPLTBL) OP_andand,
+ '=', ENDSTATE, (LPLTBL) OP_andeq,
+ OTHER, ENDSTATE, (LPLTBL) OP_addrof
+};
+
+LTBL LTslash[] = {
+ '=', ENDSTATE, (LPLTBL) OP_diveq,
+ OTHER, ENDSTATE, (LPLTBL) OP_div
+};
+
+LTBL LTpct[] = {
+ '=', ENDSTATE, (LPLTBL) OP_modeq,
+ OTHER, ENDSTATE, (LPLTBL) OP_mod
+};
+
+LTBL LTplus[] = {
+ '=', ENDSTATE, (LPLTBL) OP_pluseq,
+ '+', ENDSTATE, (LPLTBL) OP_incr,
+ OTHER, ENDSTATE, (LPLTBL) OP_uplus
+};
+
+LTBL LTlessthan[] = {
+ '<', INTERMEDIATE, (LPLTBL) LTltlt,
+ '=', ENDSTATE, (LPLTBL) OP_lteq,
+ OTHER, ENDSTATE, (LPLTBL) OP_lt
+};
+
+LTBL LTgreaterthan[] = {
+ '>', INTERMEDIATE, (LPLTBL) LTgtgt,
+ '=', ENDSTATE, (LPLTBL) OP_gteq,
+ OTHER, ENDSTATE, (LPLTBL) OP_gt
+};
+
+LTBL LTequals[] = {
+ '=', ENDSTATE, (LPLTBL) OP_eqeq,
+ OTHER, ENDSTATE, (LPLTBL) OP_eq,
+};
+
+LTBL LTcaret[] = {
+ '=', ENDSTATE, (LPLTBL) OP_xoreq,
+
+ OTHER, ENDSTATE, (LPLTBL) OP_xor
+};
+
+LTBL LTpipe[] = {
+ '|', ENDSTATE, (LPLTBL) OP_oror,
+ '=', ENDSTATE, (LPLTBL) OP_oreq,
+ OTHER, ENDSTATE, (LPLTBL) OP_or
+};
+
+LTBL LTdot[] = {
+ '*', ENDSTATE, (LPLTBL) OP_dotmember,
+ OTHER, ENDSTATE, (LPLTBL) OP_dot
+};
+
+LTBL LTcolon[] = {
+ ':', ENDSTATE, (LPLTBL) OP_uscope,
+ '>', ENDSTATE, (LPLTBL) OP_baseptr,
+ OTHER, ENDSTATE, (LPLTBL) OP_segop
+};
+
+
+/*
+** main Lexer table
+*/
+
+LTBL LexTable [] = {
+ '+', INTERMEDIATE, (LPLTBL) LTplus,
+ '-', INTERMEDIATE, (LPLTBL) LTdash,
+ '*', INTERMEDIATE, (LPLTBL) LTstar,
+ '&', INTERMEDIATE, (LPLTBL) LTampersand,
+ '/', INTERMEDIATE, (LPLTBL) LTslash,
+ '.', INTERMEDIATE, (LPLTBL) LTdot,
+ '!', INTERMEDIATE, (LPLTBL) LTbang,
+ '~', ENDSTATE, (LPLTBL) OP_tilde,
+ '%', INTERMEDIATE, (LPLTBL) LTpct,
+ '<', INTERMEDIATE, (LPLTBL) LTlessthan,
+ '>', INTERMEDIATE, (LPLTBL) LTgreaterthan,
+ '=', INTERMEDIATE, (LPLTBL) LTequals,
+ '^', INTERMEDIATE, (LPLTBL) LTcaret,
+ '|', INTERMEDIATE, (LPLTBL) LTpipe,
+ ':', INTERMEDIATE, (LPLTBL) LTcolon,
+ ';', ENDSTATE, (LPLTBL) OP_lowprec,
+ ',', ENDSTATE, (LPLTBL) OP_comma,
+ '(', ENDSTATE, (LPLTBL) OP_lparen,
+ ')', ENDSTATE, (LPLTBL) OP_rparen,
+ '[', ENDSTATE, (LPLTBL) OP_lbrack,
+ ']', ENDSTATE, (LPLTBL) OP_rbrack,
+ '{', ENDSTATE, (LPLTBL) OP_lcurly,
+ '}', ENDSTATE, (LPLTBL) OP_rcurly,
+ '#', ENDSTATE, (LPLTBL) OP_segopReal,
+
+ TABLE_END, 0, 0
+};
+
+/*------------------------------------------------------------
+; ptoken_t ParseOp (pb, pTok)
+; char *pb;
+;
+; Scans the input string (pb) for the next token and returns
+; the token type. Also returns the number of characters in
+; the token so that the caller can advance the input stream
+; before calling again. The string need not be NULL-terminated:
+; it will only scan as deep as the lexer tables indicate.
+;------------------------------------------------------------
+*/
+
+EESTATUS PASCAL ParseOp(char FAR * lpb, token_t FAR * lpTok)
+{
+ LTBL * lpLexTable = &LexTable[0];
+
+ /*
+ ** Skip over any leading white space in the string
+ ** as this is not part of the next token
+ */
+
+ while (*lpb == ' ') lpb++;
+
+ while (TRUE) {
+ /*
+ ** Check for the end of this lexer table. If we
+ ** run off the table then we can not recognized this
+ ** token and return an error.
+ */
+
+ if (lpLexTable->character == TABLE_END) {
+ lpTok->opTok = OP_badtok;
+ return /*EESYNTAX*/ 10;
+ }
+
+ /*
+ ** Check for the wild card marker. This means that
+ ** we have found a complete token prior to this character.
+ ** An example of this is '<a'.
+ */
+
+ if (lpLexTable->character == OTHER) {
+// Assert(lpLexTable->state == ENDSTATE);
+ lpTok->pbEnd = lpb;
+ lpTok->opTok = (op_t) lpLexTable->next;
+ return EENOERROR;
+ }
+
+ /*
+ ** Check for a match of this character againist
+ ** the parser table
+ */
+
+ if (lpLexTable->character == *lpb) {
+ /*
+ ** It matches -- see if we have found a complete token
+ */
+
+ lpb++;
+ if (lpLexTable->state == ENDSTATE) {
+ lpTok->pbEnd = lpb;
+ lpTok->opTok = (op_t) lpLexTable->next;
+ return EENOERROR;
+ } else {
+ lpLexTable = lpLexTable->next;
+ }
+ } else {
+ /*
+ ** Move to the next entry in the lexer table
+ */
+
+ lpLexTable ++;
+ }
+ }
+} /* ParseOp() */
diff --git a/private/windbg/eecan/debops.h b/private/windbg/eecan/debops.h
new file mode 100644
index 000000000..f3c78c91b
--- /dev/null
+++ b/private/windbg/eecan/debops.h
@@ -0,0 +1,138 @@
+OPCDAT (OPC_null)
+OPCDAT (OPC_integral)
+OPCDAT (OPC_scalar)
+OPCDAT (OPC_arith)
+OPCDAT (OPC_ptr)
+OPCDAT (OPC_ptrint)
+OPCDAT (OPC_relat)
+OPCDAT (OPC_equiv)
+OPCDAT (OPC_plus)
+OPCDAT (OPC_minus)
+OPCDAT (OPC_cast)
+
+OPCNT (COPS_EXPR, 124 )
+
+OPDAT (OP_endofargs , 31, 32, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_ident , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_grouped , 31, 32, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_hsym , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_this , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Opmember , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Orightequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oleftequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ofunction , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oarray , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oplusequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ominusequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Otimesequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Odivequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Opcentequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oandequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oxorequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oorequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oshl , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oshr , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oequalequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Obangequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Olessequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ogreatequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oandand , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ooror , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oincrement , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Odecrement , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Opointsto , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oplus , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ominus , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ostar , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Odivide , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Opercent , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oxor , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oand , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oor , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Otilde , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Obang , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oequal , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Oless , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ogreater , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Ocomma , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Onew , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_Odelete , 31, 32, OPC_null ,BindSymbol ,EvalPushNode ,WalkSymbol)
+OPDAT (OP_typestr , 31, 32, OPC_null ,BindTRUE ,EvalError ,WalkTypestr)
+OPDAT (OP_const , 31, 32, OPC_null ,BindConst ,EvalPushNode ,WalkConst)
+OPDAT (OP_thisinit , 31, 32, OPC_null ,BindError ,EvalThisInit ,WalkEmpty)
+OPDAT (OP_thisconst , 31, 32, OPC_null ,BindError ,EvalThisConst ,WalkEmpty)
+OPDAT (OP_thisexpr , 31, 32, OPC_null ,BindError ,EvalThisExpr ,WalkEmpty)
+OPDAT (OP_noop , 31, 32, OPC_null ,BindError ,EvalLChild ,WalkLChild)
+OPDAT (OP_lparen , 0, 30, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_rparen , 29, 0, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_lcurly , 0, 30, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_rcurly , 29, 0, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_bang , 27, 28, OPC_scalar ,BindBang ,EvalBang ,WalkBang)
+OPDAT (OP_tilde , 27, 28, OPC_integral ,BindUnary ,EvalUnary ,WalkUnary)
+OPDAT (OP_negate , 27, 28, OPC_arith ,BindUnary ,EvalUnary ,WalkUnary)
+OPDAT (OP_uplus , 27, 28, OPC_arith ,BindUnary ,EvalUnary ,WalkUnary)
+OPDAT (OP_fetch , 27, 28, OPC_ptr ,BindFetch ,EvalFetch ,WalkFetch)
+OPDAT (OP_addrof , 27, 28, OPC_null ,BindAddrOf ,EvalAddrOf ,WalkAddrOf)
+OPDAT (OP_sizeof , 27, 28, OPC_null ,BindSizeOf ,EvalPushNode ,WalkSizeOf)
+OPDAT (OP_incr , 27, 28, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_decr , 27, 28, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_preinc , 27, 28, OPC_null ,BindPreIncDec ,EvalPreIncDec ,WalkPreIncDec)
+OPDAT (OP_predec , 27, 28, OPC_null ,BindPreIncDec ,EvalPreIncDec ,WalkPreIncDec)
+OPDAT (OP_postinc , 27, 28, OPC_null ,BindPostIncDec ,EvalPostIncDec ,WalkPostIncDec)
+OPDAT (OP_postdec , 27, 28, OPC_null ,BindPostIncDec ,EvalPostIncDec ,WalkPostIncDec)
+OPDAT (OP_uscope , 31, 30, OPC_null ,BindUScope ,EvalUScope ,WalkUScope)
+OPDAT (OP_by , 3, 4, OPC_null ,BindByteOps ,EvalByteOps ,WalkByteOps)
+OPDAT (OP_wo , 3, 4, OPC_null ,BindByteOps ,EvalByteOps ,WalkByteOps)
+OPDAT (OP_dw , 3, 4, OPC_null ,BindByteOps ,EvalByteOps ,WalkByteOps)
+OPDAT (OP_context , 27, 28, OPC_null ,BindContext ,EvalContext ,WalkContext)
+OPDAT (OP_execontext , 27, 28, OPC_null ,BindExeContext ,EvalContext ,WalkContext)
+OPDAT (OP_function , 0, 28, OPC_null ,BindFunction ,EvalFunction ,WalkFunction)
+OPDAT (OP_cast , 27, 28, OPC_null ,BindCast ,EvalCast ,WalkCast)
+OPDAT (OP_arg , 1, 2, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_bscope , 31, 30, OPC_null ,BindBScope ,EvalBScope ,WalkBScope)
+OPDAT (OP_fcnend , 29, 0, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_lbrack , 0, 28, OPC_ptrint ,BindArray ,EvalArray ,WalkArray)
+OPDAT (OP_rbrack , 29, 0, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_pointsto , 29, 28, OPC_null ,BindPointsTo ,EvalPointsTo ,WalkPointsTo)
+OPDAT (OP_dot , 29, 28, OPC_null ,BindDot ,EvalDot ,WalkDot)
+OPDAT (OP_segop , 29, 28, OPC_integral ,BindSegOp ,EvalSegOp ,WalkSegOp)
+OPDAT (OP_segopReal , 29, 28, OPC_integral ,BindSegOp ,EvalSegOp ,WalkSegOp)
+OPDAT (OP_baseptr , 29, 28, OPC_null ,BindBasePtr ,EvalBasePtr ,WalkBasePtr)
+OPDAT (OP_pmember , 25, 26, OPC_null ,BindPMember ,EvalPMember ,WalkPMember)
+OPDAT (OP_dotmember , 25, 26, OPC_null ,BindDMember ,EvalDMember ,WalkDMember)
+OPDAT (OP_mult , 25, 24, OPC_arith ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_div , 25, 24, OPC_arith ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_mod , 25, 24, OPC_integral ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_plus , 23, 22, OPC_plus ,BindPlusMinus ,EvalPlusMinus ,WalkPlusMinus)
+OPDAT (OP_minus , 23, 22, OPC_minus ,BindPlusMinus ,EvalPlusMinus ,WalkPlusMinus)
+OPDAT (OP_shl , 21, 20, OPC_integral ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_shr , 21, 20, OPC_integral ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_lt , 19, 18, OPC_relat ,BindRelat ,EvalRelat ,WalkRelat)
+OPDAT (OP_lteq , 19, 18, OPC_relat ,BindRelat ,EvalRelat ,WalkRelat)
+OPDAT (OP_gt , 19, 18, OPC_relat ,BindRelat ,EvalRelat ,WalkRelat)
+OPDAT (OP_gteq , 19, 18, OPC_relat ,BindRelat ,EvalRelat ,WalkRelat)
+OPDAT (OP_eqeq , 17, 16, OPC_equiv ,BindRelat ,EvalRelat ,WalkRelat)
+OPDAT (OP_bangeq , 17, 16, OPC_equiv ,BindRelat ,EvalRelat ,WalkRelat)
+OPDAT (OP_and , 15, 14, OPC_integral ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_xor , 13, 12, OPC_integral ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_or , 11, 10, OPC_integral ,BindBinary ,EvalBinary ,WalkBinary)
+OPDAT (OP_andand , 9, 8, OPC_scalar ,BindBinary ,EvalLogical ,WalkBinary)
+OPDAT (OP_oror , 7, 6, OPC_scalar ,BindBinary ,EvalLogical ,WalkBinary)
+OPDAT (OP_eq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_multeq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_diveq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_modeq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_pluseq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_minuseq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_shleq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_shreq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_andeq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_xoreq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_oreq , 5, 6, OPC_null ,BindAssign ,EvalAssign ,WalkAssign)
+OPDAT (OP_lowprec , 0, 0, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_comma , 0, 0, OPC_null ,BindError ,EvalError ,WalkError)
+OPDAT (OP_caststar , 25, 24, OPC_null ,BindBinary ,EvalCastBin ,WalkBinary)
+OPDAT (OP_castplus , 25, 24, OPC_null ,BindBinary ,EvalCastBin ,WalkBinary)
+OPDAT (OP_castminus , 25, 24, OPC_null ,BindBinary ,EvalCastBin ,WalkBinary)
+OPDAT (OP_castamp , 25, 24, OPC_null ,BindBinary ,EvalCastBin ,WalkBinary)
+OPDAT (OP_identFunc , 0, 0, OPC_null ,BindFunction ,EvalFuncIdent ,WalkFunction)
diff --git a/private/windbg/eecan/debparse.c b/private/windbg/eecan/debparse.c
new file mode 100644
index 000000000..8c47d64d5
--- /dev/null
+++ b/private/windbg/eecan/debparse.c
@@ -0,0 +1,1187 @@
+/*** DEBPARSE.C - Main parser module for C expression evaluator
+ *
+ * Operator precedence parser for parsing arbitrary (almost)
+ * C expressions.
+ */
+
+
+/* The parser deals with nearly all C operators, with the exception of ?:
+ * operator.
+ *
+ * The parser is an operator precedence parser; because of the large
+ * number of operators, an operator precedence function has been designed,
+ * and is used instead of the precedence matrix. See "Compilers, principles,
+ * techniques, and tools" (the 'Dragon' book) by Aho, Sethi and Ullman,
+ * section 4.6.
+ *
+ * Five operators (::, +, -, & and *) are ambiguous; they can be used in
+ * either the unary or binary sense. Again, the main parsing loop cannot
+ * tell the difference; therefore, we keep track of the previous token: if it
+ * is id, const, ) or ], an ambiguous token is interpreted as being binary;
+ * otherwise, it is unary. Note that the lexer will always claim to have
+ * found the unary version of these three ops: '*' will always be returned
+ * as OP_fetch, and the parser will convert to OP_mult if necessary.
+ */
+
+
+// Size of shift-reduce stack, below.
+
+#define SRSTACKSIZE 30
+#define SRSTACKGROW 10
+#define FCNDEPTH 5
+
+
+// Macros for pushes and pops from the shift-reduce stack.
+
+#define SRPUSH(tok) (pSRStack[--SRsp] = (tok))
+#define SRPOP() (pSRStack[SRsp++])
+#define SRCUR() (pSRStack[SRsp])
+#define SRPREV() (pSRStack[SRsp+1])
+
+
+
+// Precedence function arrays.
+
+#ifdef WIN32
+uchar F_level[COPS_EXPR] =
+#else
+uchar _based(_segname("_CODE")) F_level[COPS_EXPR] =
+#endif
+{
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk) opfprec,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+
+#ifdef WIN32
+uchar G_level[COPS_EXPR] =
+#else
+uchar _based(_segname("_CODE")) G_level[COPS_EXPR] =
+#endif
+{
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk) opgprec,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+
+typedef enum PTN_flag {
+ PTN_error, // error encountered
+ PTN_nottype, // not a type
+ PTN_typestr, // type string (type...)
+ PTN_typefcn, // (type)(....
+ PTN_formal // ...type, or ...type)
+} PTN_flag;
+
+HDEP hSRStack = 0;
+ushort maxSRsp = SRSTACKSIZE;
+token_t *pSRStack;
+ushort SRsp;
+ushort argcnt[FCNDEPTH];
+short fdepth;
+
+LOCAL ushort CvtOp (ptoken_t, ptoken_t, ushort);
+LOCAL ushort CheckErr (op_t, op_t, ushort);
+LOCAL bool_t GrowSR (void);
+LOCAL EESTATUS FParseExpr (uint radix);
+LOCAL PTN_flag ParseTypeName (ptoken_t, char *, uint, EESTATUS *);
+LOCAL void ParseContext (ptoken_t, EESTATUS *);
+
+
+
+
+/** Parse - parse expression string to abstract syntax tree
+ *
+ * ushort Parse (szExpr, radix, fCase, phTM);
+ *
+ * Entry szExpr = pointer to expression string
+ * radix = default number radix for conversions
+ * fCase = case sensitive search if TRUE
+ * phTM = pointer to handle of expression state structure
+ * pEnd = pointer to ushort for index of char that ended parse
+ *
+ * Exit *phTM = handle of expression state structure if allocated
+ * *phTM = 0 if expression state structure could not be allocated
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if no error in parse
+ * EECATASTROPHIC if unable to initialize
+ * error number if error
+ */
+
+
+EESTATUS
+Parse (
+ char *szExpr,
+ uint radix,
+ SHFLAG fCase,
+ PHTM phTM,
+ uint *pEnd
+ )
+{
+ ushort len = 0;
+ uchar *p = (uchar *)szExpr;
+
+ if ((*phTM = MHMemAllocate (sizeof (struct exstate_t))) == 0) {
+ return (EECATASTROPHIC);
+ }
+
+ // lock expression state structure, clear and allocate components
+
+ DASSERT(pExState == NULL);
+ pExState = (pexstate_t)MHMemLock (*phTM);
+ memset (pExState, 0, sizeof (exstate_t));
+
+ // allocate buffer for input string and copy
+
+ for (; *p != 0; p++) {
+ if (*p == 0xff) {
+ p += sizeof (HSYM);
+ }
+ }
+ pExState->ExLen = (ushort)(p - szExpr);
+ if ((pExState->hExStr = MHMemAllocate (pExState->ExLen + 1)) == 0) {
+ // clean up after error in allocation of input string buffer
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ EEFreeTM (phTM);
+ return (EECATASTROPHIC);
+ }
+ memcpy (MHMemLock (pExState->hExStr), szExpr, pExState->ExLen + 1);
+ MHMemUnLock (pExState->hExStr);
+ pExState = NULL;
+ MHMemUnLock (*phTM);
+ return (DoParse (phTM, radix, fCase, pEnd));
+}
+
+
+/*** DoParse - parse expression
+ *
+ * error = DoParse (phTM, radix, fCase, pEnd)
+ *
+ * Entry phTM = pointer to handle to TM
+ * radix = numberic radix for conversions
+ * fCase = case sensitive search if TRUE
+ * pEnd = pointer to ushort for index of char that ended parse
+ *
+ * Exit expression parsed
+ * pExState->hExStr = handle of expression string
+ * pExState->ExLen = length of expression string
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if expression parsed without error
+ * EECATASTROPHIC if parser was unable to initialize
+ * EEGENERAL if syntax error in expression
+ */
+
+
+EESTATUS
+DoParse (
+ PHTM phTM,
+ uint radix,
+ bool_t fCase,
+ uint *pEnd
+ )
+{
+ EESTATUS error;
+ uint len;
+
+ DASSERT(pExState == NULL);
+
+ pExState = (pexstate_t)MHMemLock (*phTM);
+ pExState->radix = radix;
+ pExState->state.fCase = fCase;
+ len = sizeof (stree_t) + NODE_DEFAULT + NSTACK_MAX * sizeof (bnode_t);
+ if ((pExState->hSTree = MHMemAllocate (len)) == 0) {
+ // clean up if error in allocation of syntax tree buffer
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ EEFreeTM (phTM);
+ return (EECATASTROPHIC);
+ }
+ else {
+ memset ((pTree = MHMemLock (pExState->hSTree)), 0, len);
+ pTree->size = len;
+ pTree->stack_base = sizeof (stree_t) + NODE_DEFAULT;
+ // note that stack_next is zero from memset above
+ pTree->node_next = pTree->start_node = offsetof (stree_t, nodebase[0]);
+ }
+
+ // call the parser
+ // note that the expression state structure and the abstract syntax tree
+ // buffers are locked.
+
+ if ((error = FParseExpr (radix)) == EECATASTROPHIC) {
+ // clean up if parser unable to initialize
+ MHMemUnLock (pExState->hSTree);
+ pExState = NULL;
+ MHMemUnLock (*phTM);
+ EEFreeTM (phTM);
+ }
+
+ // compute the correct size of the abstract syntax tree buffer and
+ // reallocate the buffer to that size
+
+ len = pTree->node_next;
+ pTree->size = len;
+ MHMemUnLock (pExState->hSTree);
+ pExState->hSTree = MHMemReAlloc (pExState->hSTree, len);
+ *pEnd = pExState->strIndex;
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ return (error);
+}
+
+
+
+
+/*** FParseExpr - Parse a C expression
+ *
+ * fSuccess = FParseExpr (radix);
+ *
+ * Entry radix = default numeric radix
+ *
+ * Exit expression state structure updated
+ *
+ * Returns EENOERROR if expression was successfully parsed
+ * EENOMEMORY if out of memory
+ * EEGENERAL if parse error
+ *
+ * Description
+ * Lexes and parses the expression string into an abstract
+ * syntax tree.
+ *
+ */
+
+LOCAL EESTATUS FParseExpr (uint radix)
+{
+ EESTATUS error = EENOERROR;
+ ERRNUM lexerr = ERR_NONE;
+ token_t tokOld;
+ token_t tokNext;
+ token_t tokT;
+ short pdepth = 0;
+ char *szStart;
+ char *szExpr;
+
+ // allocate memory for shift-reduce stack if not already allocated
+
+ if (hSRStack == 0) {
+ if ((hSRStack = MHMemAllocate (maxSRsp * sizeof (token_t))) == 0) {
+ // unable to allocate space for shift reduce stack
+ return (EECATASTROPHIC);
+ }
+ }
+ pSRStack = (token_t *)MHMemLock (hSRStack);
+ SRsp = maxSRsp;
+
+ // lock the expression buffer. Note that all exits from this
+ // routine must unlock the expression buffer and unlock
+ // the shift-reduce stack
+
+ szStart = MHMemLock (pExState->hExStr);
+ szExpr = szStart;
+ fdepth = 0;
+ pExState->strIndex = 0;
+
+ // push the lowest-precedence terminal token on the shift-reduce stack
+
+ tokOld.opTok = OP_lowprec;
+ SRPUSH (tokOld);
+
+ // Fetch first token
+
+ while ((*szExpr == ' ') || (*szExpr == '\t')) {
+ szExpr++;
+ }
+ if (*szExpr == 0) {
+ lexerr = ERR_SYNTAX;
+ tokNext.opTok = OP_badtok;
+ }
+ else if ((lexerr = GetDBToken ((uchar *)szExpr, &tokNext, radix,
+ SRCUR().opTok)) == ERR_NONE) {
+ // compute the index of the start of the first token from
+ // the beginning of the input
+ tokNext.iTokStart = (ushort)(tokNext.pbTok - szStart);
+ }
+
+ // process tokens from the input string until either a bad token is
+ // encountered, an illegal combination of operators and operators occurrs
+ // or the end of string is found.
+
+ for (;;) {
+kludge:
+ if (tokNext.opTok == OP_badtok) {
+ if (lexerr != ERR_NONE) {
+ pExState->err_num = lexerr;
+ }
+ else {
+ pExState->err_num = ERR_SYNTAX;
+ }
+ error = EEGENERAL;
+ break;
+ }
+ if (error != EENOERROR) {
+ if (pExState->err_num == ERR_NONE) {
+ pExState->err_num = ERR_SYNTAX;
+ }
+ break;
+ }
+ if (SRsp == 0) {
+ // shift/reduce stack overflow
+ if (!GrowSR ()) {
+ pExState->err_num = ERR_TOOCOMPLEX;
+ error = EEGENERAL;
+ break;
+ }
+ }
+
+ // Change increment and decrement operators to pre or post form.
+ // process opening parenthesis that is beginning of a function,
+ // cast expression or sizeof expression
+
+ if (tokNext.opTok == OP_incr) {
+ if (F_level[SRCUR().opTok] <= G_level[OP_incr]) {
+ tokNext.opTok = OP_preinc;
+ }
+ else {
+ tokNext.opTok = OP_postinc;
+ }
+ }
+ else if (tokNext.opTok == OP_decr) {
+ if (F_level[SRCUR().opTok] <= G_level[OP_decr]) {
+ tokNext.opTok = OP_predec;
+ }
+ else {
+ tokNext.opTok = OP_postdec;
+ }
+ }
+ else if (tokNext.opTok == OP_lcurly) {
+ ParseContext (&tokNext, &error);
+ }
+ else if ((tokNext.opTok == OP_lparen) &&
+ ((SRCUR().opTok == OP_ident) ||
+ (tokOld.opTok == OP_rparen))) {
+
+ // If the next token is a left parenthesis and the
+ // shift/reduce top is an identifier or the previous
+ // token was a right paren "(*pfcn)(...)
+
+ tokNext.opTok = OP_function;
+ }
+ else if ((tokNext.opTok == OP_lparen) ||
+ ((tokNext.opTok == OP_ident) &&
+ (SRCUR().opTok == OP_arg) && (fdepth > 0))) {
+ // we possibly have either a type string of the form (type) or an
+ // identifier which is the first token of an argument
+
+ switch (ParseTypeName (&tokNext, szExpr, radix, &error)) {
+ case PTN_nottype:
+ case PTN_error:
+ break;
+
+ case PTN_typestr:
+ if (SRCUR().opTok == OP_sizeof) {
+ // sizeof (type string)
+ tokNext.opTok = OP_typestr;
+ }
+ else {
+ // OP_cast is a unary op. However, we will treat it as
+ // a binary op and put the type string onto the tree
+ // and change the current token to an OP_cast
+
+ tokT = tokNext;
+ tokT.opTok = OP_typestr;
+ if ((error = PushToken (&tokT)) != 0) {
+ break;
+ }
+ tokNext.opTok = OP_cast;
+ }
+ break;
+
+ case PTN_typefcn:
+ if (SRCUR().opTok == OP_sizeof) {
+ // sizeof (type string)(.... is an error
+ pExState->err_num = ERR_NOOPERAND;
+ error = EEGENERAL;
+ }
+ else {
+ // we have something of the form (type string)(....
+ // which is a cast. We will treat this as in the
+ // case above.
+
+ tokT = tokNext;
+ tokT.opTok = OP_typestr;
+ if ((error = PushToken (&tokT)) != 0)
+ break;
+ tokNext.opTok = OP_cast;
+ }
+ break;
+
+ case PTN_formal:
+ // let parser push as an argument
+ break;
+
+ default:
+ DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ error = EEGENERAL;
+ break;
+ }
+ }
+ if (error != 0) {
+ break;
+ }
+ if ((tokOld.opTok == OP_function) || (tokOld.opTok == OP_lparen)) {
+ // increment paren depth to detect proper nesting
+ pdepth++;
+ }
+ if (tokOld.opTok == OP_function) {
+ // increment function depth to allow comma terminated typestring
+ // arguments. Also initialize function argument counter
+ argcnt[fdepth++] = 0;
+ if (fdepth == FCNDEPTH) {
+ error = EEGENERAL;
+ lexerr = ERR_FCNTOODEEP;
+ }
+ if (tokNext.opTok != OP_rparen) {
+ // insert token for first argument onto stack
+ tokOld.opTok = OP_arg;
+ SRPUSH(tokOld);
+ argcnt[fdepth - 1]++;
+ // this allows foo(const class &... and similar forms
+ goto kludge;
+ }
+ }
+
+ // Convert unary op to binary if necessary
+
+ if ((pExState->err_num =
+ CvtOp (&tokOld, &tokNext, pdepth)) != ERR_NONE) {
+ error = EEGENERAL;
+ break;
+ }
+
+ if (tokNext.opTok == OP_execontext) {
+ // there is an identifier on top of the stack
+ // discard the indentifier and keep the string in this token.
+ DASSERT(SRCUR().opTok == OP_ident);
+
+ tokNext.pbTok = SRCUR().pbTok;
+ tokNext.iTokStart = SRCUR().iTokStart;
+ tokNext.cbTok = tokNext.pbEnd - tokNext.pbTok;
+ szExpr = szStart + tokNext.iTokStart;
+
+ (void)SRPOP();
+ }
+
+ // check for scan termination
+
+ if (((SRCUR().opTok == OP_lowprec) && (tokNext.opTok == OP_lowprec))) {
+ if ((pTree->stack_next != 1) || (SRsp != (ushort)(maxSRsp - 1)) ||
+ (pdepth != 0) || (fdepth != 0)) {
+ // statement did not reduce to a single node
+ pExState->err_num = ERR_SYNTAX;
+ error = EEGENERAL;
+ }
+ else {
+ pExState->strIndex = (ushort)(szExpr - szStart);
+ pExState->state.parse_ok = TRUE;
+ }
+ break;
+ }
+
+ // process ) as either end of function or end of grouping
+
+ if (tokNext.opTok == OP_rparen) {
+ if ((SRCUR().opTok == OP_function) &&
+ (argcnt[fdepth - 1] == 0)) {
+ // For a function with no arguments, shift the end of
+ // arguments token onto the stack and convert the right
+ // parenthesis into the end of function token
+
+ tokOld.opTok = OP_endofargs;
+ SRPUSH(tokOld);
+ tokNext.opTok = OP_fcnend;
+ fdepth--;
+ }
+ else if (((SRCUR().opTok != OP_lparen) && (SRCUR().opTok != OP_arg))
+ && (SRPREV().opTok == OP_arg)) {
+
+ // For a function with one or more arguments, pop the last
+ // argument, shift the end of arguments token onto the stack
+ // and then convert the right parenthesis into the end of function
+
+ tokT = SRPOP();
+ if (tokT.opTok != OP_grouped) {
+ if ((error = PushToken (&tokT)) != 0) {
+ break;
+ }
+ }
+ tokOld.opTok = OP_endofargs;
+ SRPUSH(tokOld);
+ tokNext.opTok = OP_fcnend;
+ fdepth--;
+ }
+ else if ((SRPREV().opTok == OP_function) &&
+ (SRCUR().opTok == OP_arg)) {
+ tokOld.opTok = OP_endofargs;
+ SRPUSH(tokOld);
+ tokNext.opTok = OP_fcnend;
+ fdepth--;
+ }
+ }
+ if ((pExState->err_num =
+ CheckErr (SRCUR().opTok, tokNext.opTok, pdepth)) != ERR_NONE) {
+ error = EEGENERAL;
+ break;
+ }
+
+ if (F_level[SRCUR().opTok] <= G_level[tokNext.opTok]) {
+ // Shift next token onto stack since it has higher precedence
+ // than token on top of the stack. Note that f values larger
+ // than g values mean higher precedence
+
+ if((SRCUR().opTok == OP_lparen) && (tokNext.opTok == OP_rparen)) {
+ // change the left paren on the stack to a grouping operator
+ // which will be discarded later. This is to solve the problem
+ // of (id)++ becoming a preincrement
+ SRCUR().opTok = OP_grouped;
+ }
+ else {
+ SRPUSH(tokNext);
+ }
+ if ((tokNext.opTok == OP_rparen) || (tokNext.opTok == OP_fcnend)) {
+ if (pdepth-- < 0) {
+ pExState->err_num = ERR_MISSINGLP;
+ error = EEGENERAL;
+ break;
+ }
+ }
+ // Skip token and trailing spaces in string
+ szExpr += tokNext.cbTok;
+ while ((*szExpr == ' ') || (*szExpr == '\t')) {
+ ++szExpr;
+ }
+
+ // save contents of next token in old token for later
+
+ tokOld = tokNext;
+ if (*szExpr) {
+ // If not at end of input
+ if ((lexerr = GetDBToken ((uchar *)szExpr, &tokNext, radix, SRCUR().opTok)) == ERR_NONE) {
+ tokNext.iTokStart = (ushort) (tokNext.pbTok - szStart);
+ }
+ }
+ else {
+ tokNext.opTok = OP_lowprec;
+ tokNext.cbTok = 0;
+ }
+ }
+ else {
+ // Reduce ...
+ // This loop pops tokens off the stack while the token removed has
+ // lower precedence than the token remaining on the top of the stack.
+ // This has the effect of throwing away the right parenthesis of
+ // () and the right bracket of [] and pushing only the left paren or
+ // left bracket;
+
+ do {
+ // Pop off stack (struct copy)
+ tokT = SRPOP();
+ }
+ while (F_level[SRCUR().opTok] >= G_level[tokT.opTok]);
+
+ // Push onto RPN stack or whatever
+ if (tokT.opTok != OP_grouped) {
+ if ((error = PushToken (&tokT)) != 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ // unlock and free the shift-reduce stack and unlock the
+ // input string
+
+ MHMemUnLock (hSRStack);
+ MHMemUnLock (pExState->hExStr);
+ return (error);
+}
+
+
+
+
+LOCAL bool_t GrowSR ()
+{
+ ushort oldSRsp = maxSRsp;
+
+ MHMemUnLock (hSRStack);
+ if ((hSRStack = MHMemReAlloc (hSRStack, (maxSRsp + SRSTACKGROW) * sizeof (token_t))) == 0) {
+ pSRStack = MHMemLock (hSRStack);
+ return (FALSE);
+ }
+ maxSRsp += SRSTACKGROW;
+ pSRStack = MHMemLock (hSRStack);
+ memmove (((char *)pSRStack) + SRSTACKGROW * sizeof (token_t),
+ pSRStack, oldSRsp * sizeof (token_t));
+ SRsp += SRSTACKGROW;
+ return (TRUE);
+}
+
+
+
+
+/*** CvtOp - Convert a token from unary to binary if necessary
+ *
+ * error = CvtOp (ptokPrev, ptokNext, pdepth)
+ *
+ *
+ * Entry ptokPrev = pointer to previously fetched token
+ * ptokNext = pointer to token just fetched
+ * pdepth = parenthesis depth
+ *
+ * Exit ptokNext->opTok = binary form of operator if necessary
+ *
+ * Returns 0 if no error
+ * error index if error
+ *
+ * Because operator precedence parsing can't deal with ambiguous
+ * operators (such as '-': is it unary or binary?), this routine
+ * looks at the previous token to determine whether the operator
+ * is unary or binary.
+ *
+ * Note that ALL tokens come through here; this routine ignores
+ * tokens that have no ambiguity. The lexer will always return
+ * the unary form of the operator; thus, OP_fetch instead of
+ * OP_mult for '*'.
+ */
+
+
+LOCAL ushort
+CvtOp (
+ ptoken_t ptokOld,
+ ptoken_t ptokNext,
+ ushort pdepth
+ )
+{
+ if (ptokNext->opTok == OP_comma) {
+ if (pdepth == 0) {
+ ptokNext->opTok = OP_lowprec;
+ } else if (ptokOld->opTok == OP_arg) {
+ // error if OP_arg followed immediately by a comma
+ pExState->err_num = ERR_SYNTAX;
+ return (EEGENERAL);
+ } else {
+ ptokNext->opTok = OP_arg;
+ argcnt[pdepth - 1]++;
+ }
+ }
+
+ switch (ptokOld->opTok) {
+ case OP_ident:
+ case OP_hsym:
+ case OP_const:
+ case OP_rparen:
+ case OP_fcnend:
+ case OP_rbrack:
+ case OP_postinc:
+ case OP_postdec:
+ case OP_typestr:
+
+ // If the previous token was an identifier, a constant, or
+ // a right parenthesis or bracket, and the token is ambiguous,
+ // it is taken to be of the binary form.
+
+ switch (ptokNext->opTok) {
+ case OP_fetch:
+ ptokNext->opTok = OP_mult;
+ break;
+
+ case OP_uplus:
+ ptokNext->opTok = OP_plus;
+ break;
+
+ case OP_negate:
+ ptokNext->opTok = OP_minus;
+ break;
+
+ case OP_addrof:
+ ptokNext->opTok = OP_and;
+ break;
+
+ case OP_uscope:
+ ptokNext->opTok = OP_bscope;
+ break;
+
+ case OP_bang:
+ if (ptokOld->opTok == OP_ident) {
+ ptokNext->opTok = OP_execontext;
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (ERR_NONE);
+}
+
+
+
+
+/*** CheckErr - Check for syntax errors which parser won't find
+ *
+ * err = CheckErr (op1, op2, pdepth)
+ *
+ * Entry op1 = (OP_...) token at top of shift-reduce stack
+ * op2 = (OP_...) token at head of input string
+ * pdepth = parenthesis nesting depth
+ *
+ * Returns error index
+ *
+ * DESCRIPTION
+ * Checks for errors which the parser is incapable of finding
+ * (since we use precedence functions rather than a matrix).
+ * Simple code, could probably be optimized.
+ */
+
+
+LOCAL ushort CheckErr (op_t op1, op_t op2, ushort pdepth)
+{
+ switch (op1) {
+ // Top token on shift-reduce stack
+ case OP_ident:
+ case OP_const:
+ if ((op2 == OP_ident) || (op2 == OP_const)) {
+ return (ERR_NOOPERATOR);
+ }
+ if ((op2 == OP_bang) || (op2 == OP_tilde)) {
+ return (ERR_SYNTAX);
+ }
+ break;
+
+ case OP_lparen:
+ if (op2 == OP_rbrack) {
+ return (ERR_SYNTAX);
+ }
+ else if (op2 == OP_lowprec) {
+ return (ERR_MISSINGRP);
+ }
+ break;
+
+ case OP_rparen:
+ if ((op2 == OP_bang) || (op2 == OP_tilde)) {
+ return (ERR_SYNTAX);
+ }
+ break;
+
+ case OP_lbrack:
+ if (op2 == OP_rparen) {
+ return (ERR_SYNTAX);
+ }
+ else if (op2 == OP_lowprec) {
+ return (ERR_MISSINGRB);
+ }
+ break;
+
+ case OP_rbrack:
+ if ((op2 == OP_ident) || (op2 == OP_lparen)) {
+ return (ERR_NOOPERATOR);
+ }
+ if ((op2 == OP_bang) || (op2 == OP_tilde)) {
+ return (ERR_SYNTAX);
+ }
+ break;
+
+ case OP_lowprec:
+ if (op2 == OP_rparen) {
+ return (ERR_MISSINGLP);
+ }
+ else if (op2 == OP_rbrack) {
+ return (ERR_MISSINGLB);
+ }
+ else if (op2 == OP_rcurly) {
+ return (ERR_MISSINGLC);
+ }
+ else if ((op2 == OP_lowprec) && (pdepth != 0)) {
+ return (ERR_SYNTAX);
+ }
+ break;
+ }
+ return (ERR_NONE);
+}
+
+
+
+/** ParseTypeName - Parse a type name (e.g., "(int)")
+ *
+ * value = ParseTypeName (pn, szExpr, radix, perror)
+ *
+ * Entry pn = pointer to initial token
+ * szExpr = pointer to expression
+ * radix = radix for numeric constants
+ * perror = pointer to error return
+ *
+ * Exit pExState->err-num = ERR_MISSINGRP if end of string encountered
+ * *perror = EEGENERAL if end of string encountered
+ * token pointers in pn updated if valid type name
+ *
+ * Returns PTN_error if error
+ * PTN_nottype if not a type string
+ * PTN_typefcn if (type string)(......
+ * PTN_typestr if (type string){ident | constant | op}
+ * PTN_formal if ...typestring, or ...typestring)
+ *
+ * DESCRIPTION
+ * Examines string for possible type strings
+ * Note that the actual type flags are not set in the node.
+ * This is left to the bind phase.
+ */
+
+
+LOCAL PTN_flag ParseTypeName (ptoken_t ptokEntry, char *szExpr,
+ uint radix, EESTATUS *perror)
+{
+ enum {
+ PT_S0,
+ PT_S1,
+ PT_S2,
+ PT_S3,
+ PT_S4,
+ PT_S5
+ };
+ token_t tokNext;
+ char *pParen;
+ bool_t ParenReq;
+ ushort state = PT_S0;
+ op_t tokTerm;
+
+ // Save entry token for later update if this is a type string
+
+
+ tokNext = *ptokEntry;
+
+ // if the initial character is a ( then the termination must be a )
+
+ ParenReq = (*szExpr == '(')? TRUE: FALSE;
+
+ // check tokens up to next right parenthesis or comma. There are the
+ // following cases:
+ //
+ // 1. (token)
+ // token can be either an identifier or a type name.
+ // If opprev is OP_sizeof, call it an identifier and let the
+ // binder detect that is a type string. If the token after the
+ // ')' is a constant, identifier or '(' then '(token)' must be a
+ // cast.
+ //
+ // 2. (token op token)
+ // This can only be an expression
+ //
+ // 3. (token token...)
+ // This can only be a type. Let the binder evaluate it to a type
+ //
+ // 4. (token op)
+ // if op is * or & then it is a type. Otherwise, it is an expression
+ //
+ // 5. (op token)
+ // This can only be an expression
+
+ for (;;) {
+ // Skip token and trailing spaces in string
+
+ if ((state != PT_S0) || (ParenReq == TRUE)) {
+ // skip the previous token or skip the initial paren if
+ // this is the first time through the loop
+ szExpr += tokNext.cbTok;
+ while ((*szExpr == ' ') || (*szExpr == '\t')) {
+ szExpr++;
+ }
+ if (*szExpr != 0) {
+ if ((GetDBToken ((uchar *)szExpr, &tokNext, radix, OP_lowprec) != ERR_NONE) ||
+ (tokNext.opTok == OP_badtok)) {
+ pExState->err_num = ERR_SYNTAX;
+ *perror = EEGENERAL;
+ return (PTN_error);
+ }
+ }
+ else {
+ // flag end of statement
+ tokNext.opTok = OP_lowprec;
+ }
+ }
+ switch (state) {
+ case PT_S0:
+ // state 0 looks at the first token and and if it is an
+ // identifier, continues the scan
+
+ switch (tokNext.opTok) {
+ case OP_ident:
+ case OP_hsym:
+ // 'token' can be either type or expression
+ state = PT_S1;
+ break;
+
+ default:
+ // let parser handle everything else
+ return (PTN_nottype);
+ }
+ break;
+
+ case PT_S1:
+ // state 1 looks at the token after the initial identifier
+ switch (tokNext.opTok) {
+ case OP_rparen:
+ if (ParenReq) {
+ // go to state that will examine token after ')'
+ // to see if (token) is a cast or expression.
+ // save location of ')'
+
+ pParen = szExpr;
+ state = PT_S3;
+ }
+ else {
+ // we have ...token) which must be an argument
+ return (PTN_nottype);
+ }
+ break;
+
+ case OP_comma:
+ if (ParenReq) {
+ // if the opening character was a '(', then
+ // a ',' is an error
+ return (PTN_error);
+ }
+ else {
+ // if we have "...token," then it must be an expression
+ return (PTN_nottype);
+ }
+ break;
+
+ case OP_ident:
+ case OP_hsym:
+ // '(token token...' must be a type string
+ // enter the state that is looking for the terminating
+ // ')' or ','
+
+ state = PT_S4;
+ break;
+
+ case OP_fetch:
+ case OP_addrof:
+ // '(token *' or '(token &' can be expression or type
+ // go to state where we are looking for ident, ')'
+ // or ','
+
+ state = PT_S2;
+ break;
+
+ default:
+ // '(token op' must be an expression
+ return (PTN_nottype);
+ }
+ break;
+
+ case PT_S2:
+ // state 2 looks at the token after an ambiguous operator
+ // if the token is '*' or '&', then the string is a type string
+
+ switch (tokNext.opTok) {
+ case OP_rparen:
+
+ // '...token *)' or '...token &)' is a type string
+
+ pParen = tokNext.pbTok;
+ tokTerm = tokNext.opTok;
+ state = PT_S5;
+ break;
+
+ case OP_comma:
+ if (ParenReq) {
+ // an string of the form '(token *,' is an error
+ // because the function processing has already
+ // processed the opening paren
+ return (PTN_error);
+ }
+
+ // 'token *,' or 'token &,' is a type string
+
+ ptokEntry->pbEnd = szExpr;
+ ptokEntry->cbTok = (uchar)(ptokEntry->pbEnd - ptokEntry->pbTok);
+ return (PTN_formal);
+
+ default:
+ // '(token * ...' or '(token & ...' must be an expr
+ return (PTN_nottype);
+ }
+ break;
+
+ case PT_S3:
+ // we have found '(token)...' We now look at the next
+ // token to determine if we have type string or the parenthesized
+ // name of a function call or pointer to function
+ switch (tokNext.opTok) {
+ case OP_const:
+ case OP_ident:
+ case OP_hsym:
+ case OP_lparen:
+ case OP_sizeof:
+ case OP_bang:
+ case OP_tilde:
+ case OP_uscope:
+ case OP_context:
+ // reset parse to ')' at end of type string
+ ptokEntry->pbEnd = ++pParen;
+ ptokEntry->cbTok = (uchar)(ptokEntry->pbEnd - ptokEntry->pbTok);
+ if (tokNext.opTok == OP_lparen) {
+ return (PTN_typefcn);
+ }
+ else {
+ return (PTN_typestr);
+ }
+
+ default:
+ // '(token) op ...' is an expression not a type
+ // note that we for the operators + - * &
+ // we assume the binary forms. If the user wants
+ // to cast these then the operand must be in (...)
+ // for example (type)(+var)
+
+ return (PTN_nottype);
+ }
+ break;
+
+
+ case PT_S4:
+ // state 4 looks for the terminating ')' or ',' at the end
+ // of a type string
+
+ switch (tokNext.opTok) {
+ case OP_lowprec:
+ // end of statement without ')' or ','
+ pExState->err_num = ERR_MISSINGRP;
+ *perror = EEGENERAL;
+ return (PTN_error);
+
+ case OP_rparen:
+ // save location of ')' and set state to look
+ // the next token
+ pParen = szExpr;
+ tokTerm = tokNext.opTok;
+ state = PT_S5;
+ break;
+
+ case OP_comma:
+ ptokEntry->pbEnd = szExpr;
+ ptokEntry->cbTok = (uchar)(ptokEntry->pbEnd - ptokEntry->pbTok);
+ return (PTN_formal);
+
+
+ default:
+ // loop to closing )
+ break;
+ }
+ break;
+
+ case PT_S5:
+ // we know we have a type string. Set the end of string
+ // to the closing ). If the next token is ( then the type
+ // string is functional style, i.e. (type)(....). Otherwise,
+ // it is a normal typestring '(type)token.....' or '(token)\0'
+
+ if (ParenReq) {
+ ptokEntry->pbEnd = ++pParen;
+ }
+ else {
+ ptokEntry->pbEnd = pParen;
+ }
+ ptokEntry->cbTok = (uchar)(ptokEntry->pbEnd - ptokEntry->pbTok);
+
+ switch (tokNext.opTok) {
+ case OP_lparen:
+ // (typestr)(...
+ return (PTN_typefcn);
+
+ default:
+ if (ParenReq) {
+ return (PTN_typestr);
+ }
+ else {
+ return (PTN_formal);
+ }
+ }
+ break;
+ }
+ }
+}
+
+
+
+
+/** ParseContext - Parse a context description {...}
+ *
+ * flag = ParseContext (pn, perror)
+ *
+ * Entry pn = Pointer to token containing {
+ *
+ * Exit perror = ERR_BADCONTEXT if end of string encountered
+ * token pointers in pn updated if valid context
+ *
+ * Returns none
+ *
+ * DESCRIPTION
+ * Examines type string for primitive types such as "int", "long",
+ * etc. Also checks for "struct" keyword. Note that the actual type
+ * flags are not set in the node. This is left to the evaluation phase.
+ *
+ * NOTES
+ */
+
+
+LOCAL void ParseContext (ptoken_t ptokNext, EESTATUS *perror)
+{
+ char *pb;
+ char *pbSave;
+ char *pbCurly;
+
+ // Initialization.
+
+ pb = pbSave = ptokNext->pbTok + 1 - ptokNext->cbTok;
+
+ while (isspace(*pb))
+ ++pb;
+
+ DASSERT (*pb == '{');
+
+ // Save position and skip '{'
+
+ pbCurly = pb++;
+
+ // skip to closing }
+
+ while ((*pb != 0) && (*pb != '}')) {
+ // M00KLUDGE need to check for } in quoted long file name
+#ifdef DBCS
+ pb = CharNext(pb);
+#else
+ pb++;
+#endif
+ }
+
+ ptokNext->cbTok = (uchar)(pb - pbCurly + 1);
+ ptokNext->opTok = OP_context;
+
+ if (*pb != '}') {
+ pExState->err_num = ERR_BADCONTEXT;
+ *perror = EEGENERAL;
+ }
+}
diff --git a/private/windbg/eecan/debsrch.c b/private/windbg/eecan/debsrch.c
new file mode 100644
index 000000000..50d61220f
--- /dev/null
+++ b/private/windbg/eecan/debsrch.c
@@ -0,0 +1,1143 @@
+// debsrch.c - symbol search routines
+// R. A. Garmoe 89/04/24
+
+#define CheckType CheckType_H
+
+LOCAL bool_t LoadAddress (peval_t);
+LOCAL bool_t EBitfield (peval_t);
+LOCAL MTYP_t CheckType (peval_t, CV_typ_t, HTYPE, bool_t);
+void InsertCache (CV_typ_t type, HEXE hExe);
+LOCAL void ReorderCache (int);
+
+typedef unsigned char FAR* LNST; // length preceded string
+
+LOCAL BOOL FSameLnst(LNST lnst1, LNST lnst2);
+LOCAL BOOL FSameTypePrep(peval_t pv, CV_typ_t ti, HTYPE* phtype, BOOL* pfForward, LNST* plnst);
+LOCAL BOOL FSameTypeByIndex(peval_t pv, CV_typ_t ti1, CV_typ_t ti2);
+LOCAL MTYP_t SearchCheckType (peval_t, CV_typ_t, HTYPE, bool_t);
+
+#define CACHE_MAX 100
+
+CV_typ_t Cache[CACHE_MAX] = {T_NOTYPE};
+HEXE exeCache[CACHE_MAX] = {0};
+int cCache = 0;
+
+/** MatchType - match type described by node
+ *
+ * MatchType does an exhaustive scan of the types table looking for
+ * a type record that matches the type described by the value node
+ *
+ * status = MatchType (pv, fExact)
+ *
+ * Entry pv = pointer to value node
+ * fExact = TRUE if exact match on const/volatile and mode
+ * preferred
+ *
+ * Exit EVAL_TYP (pv) = matching type
+ *
+ * Returns MTYP_none if type not matched
+ * MTYP_exact if exact match found
+ * MTYP_inexact if inexact match found
+ */
+
+
+MTYP_t
+MatchType (
+ peval_t pv,
+ bool_t fExact
+ )
+{
+ CV_typ_t index;
+ HTYPE hType;
+ int iCache;
+ CV_typ_t possible = T_NOTYPE;
+ HEXE hExe;
+
+ hExe = SHHexeFromHmod (EVAL_MOD (pv));
+ for (iCache = 0; iCache < cCache; iCache++) {
+ if (exeCache[iCache] != hExe) {
+ continue;
+ }
+ index = Cache[iCache];
+ if ((hType = THGetTypeFromIndex (EVAL_MOD (pv), index)) == 0) {
+ DASSERT (FALSE);
+ continue;
+ }
+ switch (SearchCheckType (pv, Cache[iCache], hType, fExact)) {
+ case MTYP_none:
+ break;
+
+ case MTYP_exact:
+ ReorderCache (iCache);
+ EVAL_TYP (pv) = index;
+ return (MTYP_exact);
+
+ case MTYP_inexact:
+ if (fExact == FALSE) {
+ ReorderCache (iCache);
+ EVAL_TYP (pv) = index;
+ return (MTYP_inexact);
+ }
+ break;
+ }
+ }
+ index = CV_FIRST_NONPRIM - 1;
+ while ((hType = THGetTypeFromIndex (EVAL_MOD (pv), ++index)) != 0) {
+ switch (SearchCheckType (pv, index, hType, fExact)) {
+ case MTYP_none:
+ break;
+
+ case MTYP_exact:
+ InsertCache (index, hExe);
+ EVAL_TYP (pv) = index;
+ return (MTYP_exact);
+
+ case MTYP_inexact:
+ if (fExact == FALSE) {
+ InsertCache (index, hExe);
+ EVAL_TYP (pv) = index;
+ return (MTYP_inexact);
+ }
+ else if (possible == T_NOTYPE) {
+ possible = index;
+ }
+ break;
+ }
+ }
+ if (possible == T_NOTYPE) {
+ return (MTYP_none);
+ }
+ InsertCache (possible, hExe);
+ EVAL_TYP (pv) = possible;
+ return (MTYP_inexact);
+}
+
+
+void
+InsertCache (
+ CV_typ_t type,
+ HEXE hExe)
+{
+ int i;
+
+ DASSERT (!CV_IS_PRIMITIVE (type));
+ if (cCache == CACHE_MAX) {
+ cCache--;
+ }
+ for (i = cCache; i > 0; i--) {
+ exeCache[i] = exeCache[i - 1];
+ Cache[i] = Cache[i - 1];
+ }
+ Cache[0] = type;
+ exeCache[0] = hExe;
+ cCache++;
+}
+
+
+
+
+LOCAL void
+ReorderCache (
+ int iCache
+ )
+{
+ CV_typ_t temp;
+ HEXE exeTemp;
+ int i;
+
+ if (iCache == 0) {
+ return;
+ }
+ temp = Cache[iCache];
+ exeTemp = exeCache[iCache];
+ for (i = iCache; i > 0; i--) {
+ exeCache[i] = exeCache[i - 1];
+ Cache[i] = Cache[i - 1];
+ }
+ Cache[0] = temp;
+ exeCache[0] = exeTemp;
+}
+
+
+LOCAL MTYP_t
+SearchCheckType (
+ peval_t pv,
+ CV_typ_t index,
+ HTYPE hType,
+ bool_t fExact
+ )
+{
+ char FAR *pType;
+ CV_modifier_t Mod;
+ CV_typ_t uType;
+ MTYP_t retval = MTYP_none;
+ plfPointer plfP;
+
+ if (hType == (HTYPE) NULL) {
+ return retval;
+ }
+
+ pType = (char FAR *)(&((TYPPTR)MHOmfLock (hType))->leaf);
+ switch (((plfEasy)pType)->leaf) {
+ case LF_POINTER:
+ plfP = (plfPointer)pType;
+ uType = plfP->utype;
+ if (EVAL_IS_PTR (pv)) {
+ // we have a pointer record and we are looking
+ // for a pointer. We now check the underlying types
+
+ if (FSameTypeByIndex(pv, PTR_UTYPE (pv), uType)) {
+ // the underlying types are the same. we now need
+ // to check the pointer modes
+
+ if ((plfP->attr.ptrmode == CV_PTR_MODE_REF) !=
+ EVAL_IS_REF (pv)) {
+ // if the reference modes are different, we do not
+ // have any type of a match
+ break;
+ }
+ if (plfP->attr.ptrtype == EVAL_PTRTYPE (pv)) {
+ // we have exact match on pointer mode
+
+ retval = MTYP_exact;
+ }
+ else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
+ (plfP->attr.ptrtype != CV_PTR_FAR)) {
+ // we we do not have a far pointer that could
+ // be cast to a near pointer
+ break;
+
+ }
+ else {
+ retval = MTYP_inexact;
+ }
+ if (fExact == TRUE) {
+ if ((plfP->attr.isconst != EVAL_IS_CONST (pv)) ||
+ (plfP->attr.isvolatile != EVAL_IS_VOLATILE (pv))) {
+ retval = MTYP_inexact;
+ }
+ }
+ }
+ else {
+ // the underlying types are not the same but we
+ // have to check for a modifier with the proper
+ // underlying type, i.e. pointer to const class
+
+ if (CV_IS_PRIMITIVE (uType)) {
+ // the underlying type of the pointer cannot be
+ // a modifier
+
+ break;
+ }
+ if ((plfP->attr.ptrmode == CV_PTR_MODE_REF) !=
+ EVAL_IS_REF (pv)) {
+ // if the reference modes are different, we cannot
+ // have any type of a match
+ break;
+ }
+ if (plfP->attr.ptrtype != EVAL_PTRTYPE (pv)) {
+ // we do not have an exact match on pointer type
+
+ if (fExact == TRUE) {
+ // this cannot be an exact match
+ break;
+ }
+ else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
+ (plfP->attr.ptrtype != CV_PTR_FAR)) {
+ // we we do not have a far pointer that could
+ // be cast to a near pointer
+ break;
+ }
+ }
+ MHOmfUnLock (hType);
+ hType = THGetTypeFromIndex (EVAL_MOD (pv), uType);
+ DASSERT(hType != (HTYPE) NULL);
+ pType = (char FAR *)(&((TYPPTR)MHOmfLock (hType))->leaf);
+ if (((plfEasy)pType)->leaf != LF_MODIFIER) {
+ break;
+ }
+ if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
+ Mod = ((plfModifier)pType)->attr;
+ if (FSameTypeByIndex(pv, uType, PTR_UTYPE(pv))) {
+ if (((Mod.MOD_const == TRUE) == EVAL_IS_CONST (pv)) &&
+ ((Mod.MOD_volatile == TRUE) == (EVAL_IS_VOLATILE (pv)))) {
+ retval = MTYP_exact;
+ }
+ else {
+ retval = MTYP_inexact;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case LF_MODIFIER:
+ if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
+ Mod = ((plfModifier)pType)->attr;
+ if (FSameTypeByIndex(pv, uType, EVAL_TYP(pv))) {
+ if (((Mod.MOD_const == TRUE) == EVAL_IS_CONST (pv)) ||
+ ((Mod.MOD_volatile == TRUE) == (EVAL_IS_VOLATILE (pv)))) {
+ retval = MTYP_exact;
+ }
+ else {
+ retval = MTYP_inexact;
+ }
+ }
+ }
+ break;
+
+ default:
+ // type not interesting so skip
+ break;
+ }
+ if (hType != 0) {
+ MHOmfUnLock (hType);
+ }
+ return (retval);
+}
+
+
+// Return TRUE if ti1 and ti2 are equivalent, that is, if they are the same,
+// or if one (but not the other) is a struct T definition and the other is a
+// struct T forward reference.
+
+LOCAL BOOL
+FSameTypeByIndex(
+ peval_t pv,
+ CV_typ_t ti1,
+ CV_typ_t ti2
+ )
+{
+ HTYPE htype1 = 0, htype2 = 0;
+ BOOL fForward1, fForward2;
+ LNST lnstName1, lnstName2;
+ BOOL fRet = FALSE;
+
+ if (ti1 == ti2)
+ return TRUE;
+ if (CV_IS_PRIMITIVE(ti1) || CV_IS_PRIMITIVE(ti2))
+ return FALSE;
+
+ // Try to fetch both type records, which must be class/struct/union records.
+ if (!FSameTypePrep(pv, ti1, &htype1, &fForward1, &lnstName1) ||
+ !FSameTypePrep(pv, ti2, &htype2, &fForward2, &lnstName2))
+ goto ret;
+
+ // One or the other must be a forward reference, otherwise we are comparing
+ // different structs with the same name!
+ if (fForward1 == fForward2)
+ goto ret;
+
+ // Match if length preceded names match
+ fRet = FSameLnst(lnstName1, lnstName2);
+
+ret:
+ if (htype2)
+ MHOmfUnLock(htype2);
+ if (htype1)
+ MHOmfUnLock(htype1);
+
+ return fRet;
+}
+
+// Set up for FSameTypeByIndex. Lookup ti in pv and set *phtype, *pfForward, and *plnst
+// in the process.
+
+LOCAL BOOL
+FSameTypePrep(
+ peval_t pv,
+ CV_typ_t ti,
+ HTYPE* phtype,
+ BOOL* pfForward,
+ LNST* plnst
+ )
+{
+ TYPPTR ptype;
+
+ if (!(*phtype = THGetTypeFromIndex(EVAL_MOD(pv), ti)))
+ return FALSE;
+ ptype = (TYPPTR)MHOmfLock(*phtype);
+
+ switch (ptype->leaf) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ {
+ plfClass pclass = (plfClass)&ptype->leaf;
+ uint skip = 0;
+ RNumLeaf(pclass->data, &skip);
+
+ *pfForward = pclass->property.fwdref;
+ *plnst = pclass->data + skip;
+ return TRUE;
+ }
+
+ case LF_UNION:
+ {
+ plfUnion punion = (plfUnion)&ptype->leaf;
+ uint skip = 0;
+ RNumLeaf(punion->data, &skip);
+
+ *pfForward = punion->property.fwdref;
+ *plnst = punion->data + skip;
+ return TRUE;
+ }
+
+ case LF_ENUM:
+ {
+ plfEnum penum = (plfEnum)&ptype->leaf;
+
+ *pfForward = penum->property.fwdref;
+ *plnst = penum->Name;
+ return TRUE;
+ }
+
+ default:
+ return FALSE;
+ }
+}
+
+// Return TRUE if the LNSTs are identical.
+//
+LOCAL BOOL
+FSameLnst(
+ LNST lnst1,
+ LNST lnst2)
+{
+ return *lnst1 == *lnst2 && memcmp(lnst1 + 1, lnst2 + 1, *lnst1) == 0;
+}
+
+
+
+/** ProtoPtr - set up a prototype of a pointer or reference node
+ *
+ * ProtoPtr (pvOut, pvIn, IsRef, Mod)
+ *
+ * Entry pvOut = pointer to protype node
+ * pvIn = pointer to node to prototype
+ * IsRef = TRUE if prototype is for a reference
+ * Mod = modifier type (CV_MOD_none, CV_MOD_const, CV_MOD_volatile)
+ *
+ * Exit pvOut = prototype pointer node
+ *
+ * Returns none
+ */
+
+
+void
+ProtoPtr (
+ peval_t pvOut,
+ peval_t pvIn,
+ bool_t IsRef,
+ CV_modifier_t Mod
+ )
+{
+ _fmemset (pvOut, 0, sizeof (*pvOut));
+ EVAL_MOD (pvOut) = EVAL_MOD (pvIn);
+ EVAL_IS_ADDR (pvOut) = TRUE;
+ EVAL_IS_DPTR (pvOut) = TRUE;
+ if (IsRef == TRUE) {
+ EVAL_IS_REF (pvOut) = TRUE;
+ }
+ EVAL_IS_PTR (pvOut) = TRUE;
+ if (Mod.MOD_const == TRUE) {
+ EVAL_IS_CONST (pvOut) = TRUE;
+ }
+ else if (Mod.MOD_volatile == TRUE) {
+ EVAL_IS_VOLATILE (pvOut) = TRUE;
+ }
+ EVAL_PTRTYPE (pvOut) = (uchar)SetAmbiant (TRUE);
+ PTR_UTYPE (pvOut) = EVAL_TYP (pvIn);
+}
+
+#if 0
+
+MTYP_t PASCAL MatchType (peval_t pv, bool_t fExact)
+{
+ CV_typ_t index;
+ HTYPE hType;
+ int iCache;
+ CV_typ_t possible = T_NOTYPE;
+
+ for (iCache = 0; iCache < cCache; iCache++) {
+ index = Cache[iCache];
+ hType = THGetTypeFromIndex (EVAL_MOD (pv), index);
+ switch (CheckType (pv, Cache[iCache], hType, fExact)) {
+ case MTYP_none:
+ break;
+
+ case MTYP_exact:
+ ReorderCache (iCache);
+ EVAL_TYP (pv) = index;
+ return (MTYP_exact);
+
+ case MTYP_inexact:
+ if (fExact == FALSE) {
+ ReorderCache (iCache);
+ EVAL_TYP (pv) = index;
+ return (MTYP_inexact);
+ }
+ break;
+ }
+ }
+ index = CV_FIRST_NONPRIM - 1;
+ while ((hType = THGetTypeFromIndex (EVAL_MOD (pv), ++index)) != 0) {
+ switch (CheckType (pv, Cache[iCache], hType, fExact)) {
+ case MTYP_none:
+ break;
+
+ case MTYP_exact:
+ InsertCache (index);
+ EVAL_TYP (pv) = index;
+ return (MTYP_exact);
+
+ case MTYP_inexact:
+ if (fExact == FALSE) {
+ InsertCache (index);
+ EVAL_TYP (pv) = index;
+ return (MTYP_inexact);
+ }
+ else if (possible == T_NOTYPE) {
+ possible = index;
+ }
+ break;
+ }
+ }
+ if (possible == T_NOTYPE) {
+ return (MTYP_none);
+ }
+ InsertCache (possible);
+ EVAL_TYP (pv) = possible;
+ return (MTYP_inexact);
+}
+
+
+
+
+LOCAL void NEAR PASCAL InsertCache (CV_typ_t type)
+{
+ int i;
+
+ if (cCache == CACHE_MAX) {
+ cCache--;
+ }
+ for (i = cCache; i > 0; i--) {
+ Cache[i] = Cache[i - 1];
+ }
+ Cache[0] = type;
+ cCache++;
+}
+
+
+
+
+LOCAL void NEAR PASCAL ReorderCache (int iCache)
+{
+ CV_typ_t temp;
+ int i;
+
+ if (iCache == 0) {
+ return;
+ }
+ temp = Cache[iCache];
+ for (i = iCache; i > 0; i--) {
+ Cache[i] = Cache[i - 1];
+ }
+ Cache[0] = temp;
+}
+
+
+
+LOCAL MTYP_t NEAR PASCAL CheckType (peval_t pv, CV_typ_t index,
+ HTYPE hType, bool_t fExact)
+{
+ char FAR *pType;
+ CV_modifier_t Mod;
+ CV_typ_t uType;
+ MTYP_t retval = MTYP_none;
+ plfPointer plfP;
+
+ if (hType == (HTYPE) NULL) {
+ return retval;
+ }
+
+ pType = (char FAR *)(&((TYPPTR)MHOmfLock (hType))->leaf);
+ switch (((plfEasy)pType)->leaf) {
+ case LF_POINTER:
+ plfP = (plfPointer)pType;
+ uType = plfP->u.utype;
+ if (EVAL_IS_PTR (pv)) {
+ // we have a pointer record and we are looking
+ // for a pointer. We now check the underlying types
+
+ if (PTR_UTYPE (pv) == uType) {
+ // the underlying types are the same. we now need
+ // to check the pointer modes
+
+ if ((UINT) (plfP->u.attr.ptrmode == CV_PTR_MODE_REF) !=
+ (UINT)EVAL_IS_REF (pv)) {
+ // if the reference modes are different, we do not
+ // have any type of a match
+ break;
+ }
+ if (plfP->u.attr.ptrtype == EVAL_PTRTYPE (pv)) {
+ // we have exact match on pointer mode
+
+ retval = MTYP_exact;
+ }
+ else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
+ (plfP->u.attr.ptrtype != CV_PTR_FAR)) {
+ // we we do not have a far pointer that could
+ // be cast to a near pointer
+ break;
+
+ }
+ else {
+ retval = MTYP_inexact;
+ }
+ if (fExact == TRUE) {
+ if ((plfP->u.attr.isconst != EVAL_IS_CONST (pv)) ||
+ (plfP->u.attr.isvolatile != EVAL_IS_VOLATILE (pv))) {
+ retval = MTYP_inexact;
+ }
+ }
+ }
+ else {
+ // the underlying types are not the same but we
+ // have to check for a modifier with the proper
+ // underlying type, i.e. pointer to const class
+
+ if (CV_IS_PRIMITIVE (uType)) {
+ // the underlying type of the pointer cannot be
+ // a modifier
+
+ break;
+ }
+ if ((UINT) (plfP->u.attr.ptrmode == CV_PTR_MODE_REF) !=
+ (UINT)EVAL_IS_REF (pv)) {
+ // if the reference modes are different, we cannot
+ // have any type of a match
+ break;
+ }
+ if (plfP->u.attr.ptrtype != EVAL_PTRTYPE (pv)) {
+ // we do not have an exact match on pointer type
+
+ if (fExact == TRUE) {
+ // this cannot be an exact match
+ break;
+ }
+ else if ((EVAL_PTRTYPE (pv) != CV_PTR_NEAR) ||
+ (plfP->u.attr.ptrtype != CV_PTR_FAR)) {
+ // we we do not have a far pointer that could
+ // be cast to a near pointer
+ break;
+ }
+ }
+ MHOmfUnLock ((HDEP)hType);
+ hType = THGetTypeFromIndex (EVAL_MOD (pv), uType);
+ DASSERT(hType != (HTYPE) NULL);
+ pType = (char FAR *)(&((TYPPTR)MHOmfLock ((HDEP)hType))->leaf);
+ if (((plfEasy)pType)->leaf != LF_MODIFIER) {
+ break;
+ }
+ if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
+ Mod = ((plfModifier)pType)->attr;
+ if (uType == PTR_UTYPE (pv)) {
+ if (((UINT) (Mod.MOD_const == TRUE) == (UINT)EVAL_IS_CONST (pv)) ||
+ ((UINT) (Mod.MOD_volatile == TRUE) == (UINT)(EVAL_IS_VOLATILE (pv)))) {
+ retval = MTYP_exact;
+ }
+ else {
+ retval = MTYP_inexact;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case LF_MODIFIER:
+ if ((uType = ((plfModifier)pType)->type) != T_NOTYPE) {
+ Mod = ((plfModifier)pType)->attr;
+ if (uType == EVAL_TYP (pv)) {
+ if (((UINT) (Mod.MOD_const == TRUE) == (UINT)EVAL_IS_CONST (pv)) ||
+ ((UINT) (Mod.MOD_volatile == TRUE) == (UINT)(EVAL_IS_VOLATILE (pv)))) {
+ retval = MTYP_exact;
+ }
+ else {
+ retval = MTYP_inexact;
+ }
+ }
+ }
+ break;
+
+ default:
+ // type not interesting so skip
+ break;
+ }
+ if (hType != 0) {
+ MHOmfUnLock ((HDEP)hType);
+ }
+ return (retval);
+}
+
+
+
+/** ProtoPtr - set up a prototype of a pointer or reference node
+ *
+ * ProtoPtr (pvOut, pvIn, IsRef, Mod)
+ *
+ * Entry pvOut = pointer to protype node
+ * pvIn = pointer to node to prototype
+ * IsRef = TRUE if prototype is for a reference
+ * Mod = modifier type (CV_MOD_none, CV_MOD_const, CV_MOD_volatile)
+ *
+ * Exit pvOut = prototype pointer node
+ *
+ * Returns none
+ */
+
+
+void PASCAL ProtoPtr (peval_t pvOut, peval_t pvIn, bool_t IsRef, CV_modifier_t Mod)
+{
+ _fmemset (pvOut, 0, sizeof (*pvOut));
+ EVAL_MOD (pvOut) = EVAL_MOD (pvIn);
+ EVAL_IS_ADDR (pvOut) = TRUE;
+ EVAL_IS_DPTR (pvOut) = TRUE;
+ if (IsRef == TRUE) {
+ EVAL_IS_REF (pvOut) = TRUE;
+ }
+ EVAL_IS_PTR (pvOut) = TRUE;
+ if (Mod.MOD_const == TRUE) {
+ EVAL_IS_CONST (pvOut) = TRUE;
+ }
+ else if (Mod.MOD_volatile == TRUE) {
+ EVAL_IS_VOLATILE (pvOut) = TRUE;
+ }
+ EVAL_PTRTYPE (pvOut) = (uchar)SetAmbiant (TRUE);
+ PTR_UTYPE (pvOut) = EVAL_TYP (pvIn);
+}
+
+
+#endif
+
+bool_t PASCAL LoadSymVal (peval_t pv)
+{
+ long cbVal;
+ SHREG reg;
+ ADDR addr;
+
+ if (EVAL_IS_CLASS (pv)) {
+ return (FALSE);
+ }
+ if (EVAL_STATE (pv) != EV_lvalue) {
+ // If not an lvalue, value has already been loaded
+ return (TRUE);
+ }
+ _fmemset (&EVAL_VAL (pv), 0, sizeof (EVAL_VAL (pv)));
+
+ ResolveAddr( pv );
+
+ if (EVAL_IS_ADDR (pv) && !EVAL_IS_REG (pv)) {
+
+ // we only Load the Address of PTRs that are not enregistered
+ return (LoadAddress (pv));
+ }
+
+ if (EVAL_IS_REG (pv)) {
+ if (EVAL_IS_PTR(pv)) {
+ // enregistered PTR, PTR_REG instead
+
+ reg.hReg = PTR_REG_IREG (pv);
+ PTR_REG_IREG (pv) = CV_REG_NONE;
+ }
+ else {
+ reg.hReg = EVAL_REG (pv);
+ }
+ if (GetReg (&reg, pCxt) == NULL) {
+ pExState->err_num = ERR_REGNOTAVAIL;
+ return (FALSE);
+ }
+
+#if defined (TARGET_ALPHA) || defined (TARGET_PPC)
+ if (CV_IS_PRIMITIVE ( EVAL_TYP (pv) ) &&
+ CV_TYP_IS_REAL ( EVAL_TYP (pv) ) ) {
+ //
+ // ALPHA & PPC floating point registers have only one format:
+ // In the context structure, fp's are doubles. If we
+ // want a float (32bits), convert here.
+ //
+
+ union {
+ float f;
+ double d;
+ unsigned long l[2];
+ } u;
+
+ //
+ // The shreg is unaligned, so move to a local aligned struct
+ //
+
+ u.l[0] = reg.Byte4;
+ u.l[1] = reg.Byte4High;
+
+ switch (EVAL_TYP (pv )) {
+ case T_REAL32:
+
+ //
+ // We transfer the double to a floating point value
+ //
+
+ u.f = (float)u.d;
+ EVAL_FLOAT (pv) = u.f;
+ break;
+
+ case T_REAL64:
+
+ EVAL_DOUBLE (pv) = u.d;
+ break;
+
+ case T_REAL48:
+ case T_REAL80:
+ default:
+
+ //
+ // no other FP types supported on Alpha
+ //
+
+ DASSERT(FALSE);
+ }
+ } else
+#endif // ALPHA || PPC
+
+ if (CV_IS_PRIMITIVE ( EVAL_TYP (pv) ) ) {
+
+ //
+ // notenote: this is dependent on byte ordering.
+ // Won't work on a big-endian machine.
+ //
+
+ cbVal = TypeSizePrim(EVAL_TYP (pv));
+ memcpy(&EVAL_CHAR (pv), &reg.Byte1, cbVal);
+
+ } else if (EVAL_IS_PTR (pv) ) {
+
+ //
+ // Handle pointers to UserDefinedTypes.
+ // notenote - this isn't right for WOW,
+ // where pointers can be different lengths.
+ //
+
+ memcpy(&EVAL_CHAR (pv), &reg.Byte1, sizeof (long));
+
+ } else {
+
+ //
+ // Non-primitive types in registers not
+ // supported in first release
+ //
+
+ EVAL_LONG (pv) = 0;
+ DASSERT(FALSE);
+ }
+
+ EVAL_IS_REG (pv) = FALSE;
+ if (EVAL_IS_PTR (pv)) {
+ EVAL_PTR_EMI (pv) = EVAL_SYM_EMI (pv);
+ if (EVAL_IS_BASED (pv)) {
+ EVAL_PTR_SEG (pv) = 0;
+ }
+ else {
+ if (EVAL_IS_DPTR (pv)) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS; //M00FLAT32
+ }
+ else {
+#ifdef TARGET_I386
+ reg.hReg = CV_REG_CS;
+ GetReg (&reg, pCxt);
+ EVAL_PTR_SEG (pv) = reg.Byte2;
+#else
+ EVAL_PTR_SEG (pv) = 0;
+#endif
+ }
+ }
+ ADDR_IS_OFF32 ( EVAL_PTR (pv) ) = TRUE;
+ ADDR_IS_FLAT ( EVAL_PTR (pv) ) = TRUE;
+ ADDR_IS_LI ( EVAL_PTR (pv) ) = FALSE;
+ }
+ }
+
+ else {
+ addr = EVAL_SYM (pv);
+ if (ADDR_IS_LI (addr)) {
+ //M00KLUDGE - should be moved to OSDEBUG
+ SHFixupAddr (&addr);
+ }
+ // Try to fetch contents of address
+ if (EVAL_IS_CLASS (pv)) {
+ pExState->err_num = ERR_STRUCT;
+ return (FALSE);
+ }
+
+ if (EVAL_IS_BITF (pv)) {
+ cbVal = (BITF_LEN (pv) + (BITF_POS(pv) & 0x3f) + 7 ) /8;
+ }
+ else if ((cbVal = TypeSize (pv)) > sizeof (EVAL_VAL (pv)) || cbVal < 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (FALSE);
+ }
+ if ((cbVal != 0) &&
+ (GetDebuggeeBytes (addr, (ushort)cbVal, (char FAR *)&EVAL_VAL (pv), EVAL_TYP(pv)) != (UINT)cbVal)) {
+ return (FALSE);
+ }
+ }
+
+ /* Mark node as loaded */
+
+ EVAL_STATE (pv) = EV_rvalue;
+ if (EVAL_IS_BITF (pv)) {
+ return (EBitfield (pv));
+ }
+ else {
+ return (TRUE);
+ }
+}
+
+
+
+LOCAL bool_t NEAR PASCAL
+LoadAddress (
+ peval_t pv
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes an address and loads the memory pointed to.
+
+Arguments:
+
+ pv - Suppiles value to load contents of
+
+Return Value:
+
+ TRUE if pointer loaded and FALSE if error occured
+
+--*/
+
+{
+ SHREG reg;
+ ushort dummy[2];
+ ADDR addr;
+
+ if (EVAL_IS_FCN (pv) || EVAL_IS_ARRAY (pv)) {
+ /*
+ * the reference of function or array names implies addresses
+ * not values. Therefore, we return the address of the symbol
+ * as a pointer
+ */
+
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ if (ADDR_IS_LI (EVAL_PTR(pv))) {
+ SHFixupAddr (&EVAL_PTR(pv));
+ }
+
+ } else {
+ if (EVAL_IS_NPTR (pv) || EVAL_IS_BASED (pv) || EVAL_IS_NPTR32 (pv)) {
+ /*
+ * If near/based pointer, load the offset from either the
+ * register or memory. Then set the segment portion to zero
+ * if a based pointer. If the pointer is a pointer to data, set
+ * the segment to DS. Otherwise, set the segment to CS
+ * NOTENOTE jimsch - what does this do with data in the code segment
+ */
+
+ if (EVAL_IS_REG (pv)) {
+ reg.hReg = EVAL_REG (pv);
+ GetReg (&reg, pCxt);
+ EVAL_PTR_OFF (pv) = reg.Byte2;
+ } else {
+ addr = EVAL_SYM (pv);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+
+ if (EVAL_IS_NPTR32(pv)) {
+ if (GetDebuggeeBytes (addr, sizeof (CV_off32_t),
+ (char FAR *)&EVAL_PTR_OFF (pv),
+ T_ULONG) != sizeof (CV_off32_t)) {
+ return(FALSE);
+ }
+ } else {
+ if (GetDebuggeeBytes (addr, sizeof (CV_off16_t),
+ (char FAR *)&EVAL_PTR_OFF (pv),
+ T_USHORT) != sizeof (CV_off16_t)) {
+ return(FALSE);
+ }
+ }
+ }
+ EVAL_PTR_EMI (pv) = 0;
+ ADDR_IS_FLAT( EVAL_PTR ( pv ) ) = ADDR_IS_FLAT(addr);
+
+ if (EVAL_IS_NPTR32( pv )) {
+ ADDR_IS_OFF32(EVAL_PTR(pv)) = TRUE;
+ } else {
+ ADDR_IS_OFF32( EVAL_PTR( pv)) = FALSE;
+ }
+
+ if (EVAL_IS_BASED (pv)) {
+ EVAL_PTR_SEG (pv) = 0;
+ } else {
+ if (EVAL_IS_DPTR (pv)) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ } else {
+ reg.hReg = CV_REG_CS;
+ GetReg (&reg, pCxt);
+ EVAL_PTR_SEG (pv) = reg.Byte2;
+ }
+ }
+ } else {
+ /*
+ * Must be a FAR_16 pointer -- FAR_32 pointers don't exists.
+ */
+
+ addr = EVAL_SYM (pv);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+ DASSERT(!EVAL_IS_FPTR32(pv));
+ if (GetDebuggeeBytes (addr, 4, (char FAR *)dummy, EVAL_TYP(pv)) != 4) {
+ /*
+ * load the value of a far pointer from memory
+ */
+ return (FALSE);
+ }
+ else {
+ /*
+ * shuffle the bits around
+ */
+
+ EVAL_PTR_OFF (pv) = (UOFFSET)dummy[0];
+ EVAL_PTR_SEG (pv) = (_segment)dummy[1];
+ EVAL_PTR_EMI (pv) = EVAL_SYM_EMI (pv);
+ ADDR_IS_LI (EVAL_PTR (pv)) = FALSE;
+ ADDR_IS_FLAT (EVAL_PTR (pv)) = FALSE;
+ ADDR_IS_OFF32( EVAL_PTR( pv)) = FALSE;
+ }
+ }
+ }
+ EVAL_STATE (pv) = EV_rvalue;
+ return (TRUE);
+}
+
+
+
+
+
+/*
+ * Do final evaluation of a bitfield stack element.
+ */
+
+
+LOCAL bool_t NEAR PASCAL EBitfield (peval_t pv)
+{
+ unsigned short cBits; /* Number of bits in field */
+ unsigned int pos; /* Bit position of field */
+
+ // Shift right by bit position, then mask off extraneous bits.
+ // for signed bitfields, shift field left so high bit of field is
+ // in sign bit. Then shift right (signed) to get sign extended
+ // The shift count is limited to 5 bits to emulate the hardware
+
+ pos = BITF_POS (pv) & 0x1f;
+ cBits = BITF_LEN (pv);
+
+ // set the type of the node to the type of the underlying bit field
+ // note that this will cause subsequent reloads of the node value
+ // to load the containing word and not extract the bitfield. This is
+ // how the assign op manage to not destroy the other bitfields in the
+ // location
+
+ SetNodeType (pv, BITF_UTYPE (pv));
+ switch (EVAL_TYP (pv)) {
+ case T_CHAR:
+ case T_RCHAR:
+ DASSERT (cBits <= 8);
+ EVAL_CHAR (pv) <<= (8 - cBits - pos);
+ EVAL_CHAR (pv) >>= (8 - cBits);
+ break;
+
+ case T_UCHAR:
+ DASSERT (cBits <= 8);
+ EVAL_UCHAR (pv) >>= pos;
+ EVAL_UCHAR (pv) &= (1 << cBits) - 1;
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+ DASSERT (cBits <= 16);
+ EVAL_SHORT (pv) <<= (16 - cBits - pos);
+ EVAL_SHORT (pv) >>= (16 - cBits);
+ break;
+
+ case T_USHORT:
+ case T_UINT2:
+ DASSERT (cBits <= 16);
+ EVAL_USHORT (pv) >>= pos;
+ EVAL_USHORT (pv) &= (1 << cBits) - 1;
+ break;
+
+ case T_LONG:
+ case T_INT4:
+ DASSERT (cBits <= 32);
+ EVAL_LONG (pv) <<= (32 - cBits - pos);
+ EVAL_LONG (pv) >>= (32 - cBits);
+ break;
+
+ case T_ULONG:
+ case T_UINT4:
+ DASSERT (cBits <= 32);
+ EVAL_ULONG (pv) >>= pos;
+ EVAL_ULONG (pv) &= (1L << cBits) - 1;
+ break;
+
+ case T_QUAD:
+ case T_INT8:
+ DASSERT (cBits <= 64);
+ //
+ // reset pos because it is truncated to five bits above
+ //
+ pos = BITF_POS(pv) & 0x3f;
+ (EVAL_QUAD(pv)).QuadPart = (EVAL_QUAD(pv)).QuadPart << (64 - cBits - pos);
+ (EVAL_QUAD(pv)).QuadPart = (EVAL_QUAD(pv)).QuadPart >> (64 - cBits);
+ break;
+
+ case T_UQUAD:
+ case T_UINT8:
+ {
+ //
+ // set up a mask of the wanted bits, right shifted
+ // (reset pos because it is truncated to five bits above)
+ //
+
+ LARGE_INTEGER mask_q;
+
+ DASSERT (cBits <= 64);
+
+ pos = BITF_POS (pv) & 0x3f;
+ mask_q.QuadPart = (1 << cBits) - 1;
+
+ //
+ // extract the bits
+ //
+ (EVAL_QUAD(pv)).QuadPart = (EVAL_QUAD(pv)).QuadPart >> pos;
+ (EVAL_QUAD(pv)).QuadPart &= mask_q.QuadPart;
+ break;
+ }
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ return(TRUE);
+}
diff --git a/private/windbg/eecan/debsup.c b/private/windbg/eecan/debsup.c
new file mode 100644
index 000000000..5fa831d91
--- /dev/null
+++ b/private/windbg/eecan/debsup.c
@@ -0,0 +1,2049 @@
+/*** debsup.c - debapi support routines.
+ *
+ * The routines in this module can only be called from debapi.c.
+ */
+
+
+
+
+LOCAL EESTATUS CountClassElem (peval_t, long *, uint);
+LOCAL ushort SetClassiName (peval_t, long, PEEHSTR, PEEHSTR, uint, ushort, uint);
+LOCAL ushort SetFcniParm (peval_t, long, PEEHSTR);
+
+static char *pExStrP;
+
+
+
+
+/** AreTypesEqual - are TM types equal
+ *
+ * flag = AreTypesEqual (hTMLeft, hTMRight);
+ *
+ * Entry hTMLeft = handle of left TM
+ * hTMRight = handle of right TM
+ *
+ * Exit none
+ *
+ * Returns TRUE if TMs have identical types
+ */
+
+
+bool_t AreTypesEqual (HTM hTMLeft, HTM hTMRight)
+{
+ bool_t retval = FALSE;
+ pexstate_t pExLeft;
+ pexstate_t pExRight;
+
+ if ((hTMLeft != 0) && (hTMRight != 0)) {
+ pExLeft = MHMemLock (hTMLeft);
+ pExRight = MHMemLock (hTMRight);
+ if (EVAL_TYP(&pExLeft->result) == EVAL_TYP (&pExRight->result)) {
+ retval = TRUE;
+ }
+ MHMemUnLock (hTMLeft);
+ MHMemUnLock (hTMRight);
+ }
+ return (retval);
+}
+
+
+/** GetHtypeFromTM - Get the HTYPE of a TM result
+ *
+ * hType = GetHtypeFromTM(hTM);
+ *
+ * Entry hTM = handle of TM
+ *
+ * Exit none
+ *
+ * Returns the HTYPE of the result or 0
+ */
+
+HTYPE
+GetHtypeFromTM(
+ HTM hTM
+ )
+{
+ HTYPE retval = 0;
+ pexstate_t pEx;
+
+ if ( hTM != 0 ) {
+ pEx = MHMemLock (hTM);
+ retval = THGetTypeFromIndex (EVAL_MOD (&pEx->result),
+ EVAL_TYP (&pEx->result));
+ MHMemUnLock (hTM);
+ }
+ return (retval);
+}
+
+
+
+/** cChildrenTM - return number of children for the TM
+ *
+ * flag = cChildrenTM (phTM, pcChildren, pVar)
+ *
+ * Entry phTM = pointer to handle of TM
+ * pcChildren = pointer to location to store count
+ *
+ * Exit *pcChildren = number of children for TM
+ *
+ * Returns EENOERROR if no error
+ * non-zero if error
+ */
+
+
+EESTATUS cChildrenTM (PHTM phTM, long *pcChildren, PSHFLAG pVar)
+{
+ EESTATUS retval = EENOERROR;
+ eval_t eval;
+ peval_t pv = &eval;
+ long len;
+
+ Unreferenced( pVar );
+
+
+ DASSERT (*phTM != 0);
+ *pcChildren = 0;
+ if (*phTM == 0) {
+ return (EECATASTROPHIC);
+ }
+ DASSERT(pExState == NULL );
+ pExState = MHMemLock (*phTM);
+ if (pExState->state.bind_ok == TRUE) {
+ eval = pExState->result;
+#if !defined (C_ONLY)
+ if (EVAL_IS_REF (pv)) {
+ RemoveIndir (pv);
+ }
+#endif
+ pExState->err_num = 0;
+ if (!CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
+ if (EVAL_IS_CLASS (pv)) {
+ retval = CountClassElem (pv, pcChildren,
+ (EVAL_STATE (pv) == EV_type)? CLS_defn: CLS_data);
+ }
+ else if (EVAL_IS_ARRAY (pv) && (PTR_ARRAYLEN (pv) != 0)) {
+ // if an array is undimensioned in the source then we
+ // do not guess how many elements it really has.
+ // Otherwise, the number of elements is the sizeof the
+ // array divided by the size of the underlying type
+
+ len = PTR_ARRAYLEN (pv);
+ SetNodeType (pv, PTR_UTYPE (pv));
+ *pcChildren = len / TypeSize (pv);
+ }
+ else if (EVAL_IS_PTR (pv)) {
+ SetNodeType (pv, PTR_UTYPE (pv));
+ if (EVAL_IS_VTSHAPE (pv)) {
+ *pcChildren = VTSHAPE_COUNT (pv);
+ }
+ else {
+ *pcChildren = 1;
+ }
+ }
+ else {
+ pExState->err_num = ERR_INTERNAL;
+ retval = EEGENERAL;
+ }
+ }
+ }
+ else {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ retval = EEGENERAL;
+ }
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ return (retval);
+}
+
+
+
+
+
+/** cParamTM - return count of parameters for TM
+ *
+ * ushort cParamTM (phTM, pcParam, pVarArg)
+ *
+ * Entry hTM = handle to TM
+ * pcParam = pointer return count
+ * pVarArg = pointer to vararg flags
+ *
+ * Exit *pcParam = count of number of parameters
+ * *pVarArgs = TRUE if function has varargs
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * EENOERROR if no error
+ */
+
+
+
+ushort cParamTM (HTM hTM, ushort *pcParam, PSHFLAG pVarArg)
+{
+ peval_t pv;
+ ushort retval = EECATASTROPHIC;
+
+ DASSERT (hTM != 0);
+ if (hTM != 0) {
+ DASSERT (pExState == NULL);
+ pExState = MHMemLock (hTM);
+ if (pExState->state.bind_ok == TRUE) {
+ pv = &pExState->result;
+ if (EVAL_IS_FCN (pv)) {
+ if ((*pVarArg = FCN_VARARGS (pv)) == TRUE) {
+ if ((*pcParam = FCN_PCOUNT (pv)) > 0) {
+ (*pcParam)--;
+ }
+ } else {
+ *pcParam = FCN_PCOUNT (pv);
+ }
+ retval = EENOERROR;
+ }
+ else if (EVAL_IS_LABEL (pv)) {
+ *pcParam = 0;
+ retval = EENOERROR;
+ }
+ else {
+ pExState->err_num = ERR_NOTFCN;
+ retval = EEGENERAL;
+ }
+ } else {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ retval = EEGENERAL;
+ }
+ MHMemUnLock (hTM);
+ pExState = NULL;
+ }
+ return (retval);
+}
+
+
+
+
+/** DupTM - duplicate TM
+ *
+ * flag = DupTM (phTMIn, phTMOut)
+ *
+ * Entry phTMIn = pointer to handle for input TM
+ * phTMOut = pointer to handle for output TM
+ *
+ * Exit TM and buffers duplicated
+ *
+ * Returns EENOERROR if TM duplicated
+ * EENOMEMORY if unable to allocate memory
+ */
+
+
+ushort DupTM (PHTM phTMIn, PHTM phTMOut)
+{
+ ushort retval = EENOMEMORY;
+ pexstate_t pExOut;
+ char *pStr;
+ char *pcName;
+ uint len;
+
+ DASSERT (pExState == NULL);
+ pExState = MHMemLock (*phTMIn);
+ pExStr = MHMemLock (pExState->hExStr);
+ pTree = MHMemLock (pExState->hSTree);
+ if ((*phTMOut = MHMemAllocate (sizeof (exstate_t))) != 0) {
+ pExOut = MHMemLock (*phTMOut);
+ memset (pExOut, 0, sizeof (exstate_t));
+ pExOut->ambiguous = pExState->ambiguous;
+ pExOut->state.parse_ok = TRUE;
+
+ // copy expression string
+
+ if ((pExOut->hExStr = MHMemAllocate (pExOut->ExLen = pExState->ExLen)) == 0) {
+ goto failure;
+ }
+ pStr = MHMemLock (pExOut->hExStr);
+ memcpy (pStr, pExStr, pExOut->ExLen);
+ MHMemUnLock (pExOut->hExStr);
+
+ // copy syntax tree
+
+ if ((pExOut->hSTree = MHMemAllocate (pTree->size)) == 0) {
+ goto failure;
+ }
+ pStr = MHMemLock (pExOut->hSTree);
+ memcpy (pStr, pTree, pTree->size);
+ MHMemUnLock (pExOut->hSTree);
+
+ // copy name string
+
+ if (pExState->hCName != 0) {
+ pcName = MHMemLock (pExState->hCName);
+ len = strlen (pcName) + 1;
+ if ((pExOut->hCName = MHMemAllocate (len)) == 0) {
+ MHMemUnLock (pExState->hCName);
+ goto failure;
+ }
+ pStr = MHMemLock (pExOut->hCName);
+ memcpy (pStr, pcName, len);
+ MHMemUnLock (pExOut->hCName);
+ MHMemUnLock (pExState->hCName);
+ }
+ MHMemUnLock (*phTMOut);
+ retval = EENOERROR;
+ }
+succeed:
+ MHMemUnLock (pExState->hExStr);
+ MHMemUnLock (pExState->hSTree);
+ MHMemUnLock (*phTMIn);
+ pExState = NULL;
+ return (retval);
+
+failure:
+ if (pExOut->hExStr != 0) {
+ MHMemFree (pExOut->hExStr);
+ }
+ if (pExOut->hSTree != 0) {
+ MHMemFree (pExOut->hSTree);
+ }
+ if (pExOut->hCName != 0) {
+ MHMemFree (pExOut->hCName);
+ }
+ MHMemUnLock (*phTMOut);
+ MHMemFree (*phTMOut);
+ *phTMOut = 0;
+ goto succeed;
+}
+
+
+
+/** GetChildTM - get TM representing ith child of a TM
+ *
+ * flag = GetChildTM (iChild)
+ *
+ * Entry iChild = child to get TM for
+ * pExStateP = address of locked parent expression state
+ * pExState = address of locked expression state
+ *
+ * Exit pExState initialized for child
+ *
+ * Returns TRUE if no error
+ * FALSE if error
+ */
+
+
+EESTATUS GetChildTM (HTM hTM, ulong iChild, PEEHSTR phDStr, PEEHSTR phName, uint radix)
+{
+ eval_t evalP;
+ peval_t pvP;
+ EESTATUS retval = EENOERROR;
+ char tempbuf[16];
+ ushort len;
+ ushort plen;
+ uint excess;
+ char *pDStr;
+ char *pName;
+ char *fmtstr;
+
+
+ DASSERT (hTM != 0);
+ if (hTM == 0) {
+ return (EECATASTROPHIC);
+ }
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (hTM);
+ if (pExState->state.bind_ok != TRUE) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ MHMemUnLock (hTM);
+ pExState = NULL;
+ return (EEGENERAL);
+ }
+ pExStrP = MHMemLock (pExState->hExStr);
+ pCxt = &pExState->cxt;
+ DASSERT (pExState->strIndex <= pExState->ExLen);
+ plen = pExState->strIndex;
+ excess = pExState->ExLen - plen;
+ pvP = &evalP;
+ *pvP = pExState->result;
+#if !defined (C_ONLY)
+ if (EVAL_IS_REF (pvP)) {
+ RemoveIndir (pvP);
+ }
+#endif
+ GettingChild = TRUE;
+ if (EVAL_IS_ARRAY (pvP)) {
+ // fake up name as [i] ultoa not used here because 0 converts
+ // as null string
+
+ switch (radix) {
+ case 8:
+ fmtstr = "[%o]";
+ break;
+
+ case 16:
+ fmtstr = "[%x]";
+ break;
+
+ default:
+ case 10:
+ fmtstr = "[%ld]";
+ break;
+ }
+
+ len = sprintf (tempbuf, fmtstr, iChild);
+
+ if (((*phName = MHMemAllocate (len + 1)) == 0) ||
+ ((*phDStr = MHMemAllocate (plen + excess + len + 1)) == 0)) {
+ goto nomemory;
+ }
+ pName = MHMemLock (*phName);
+ pDStr = MHMemLock (*phDStr);
+ strcpy (pName, tempbuf);
+ memcpy (pDStr, pExStrP, plen);
+ memcpy (pDStr + plen, pName, len);
+ *(pDStr + plen + len) = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ }
+ else if (EVAL_IS_PTR (pvP)) {
+ SetNodeType (pvP, PTR_UTYPE (pvP));
+ if (!EVAL_IS_VTSHAPE (pvP)) {
+ // set name to null
+
+ if (((*phName = MHMemAllocate (1)) == 0) ||
+ ((*phDStr = MHMemAllocate (plen + 3)) == 0)) {
+ goto nomemory;
+ }
+ pName = MHMemLock (*phName);
+ pDStr = MHMemLock (*phDStr);
+ *pName = 0;
+ *pDStr++ = '(';
+ memcpy (pDStr, pExStrP, plen);
+ pDStr += plen;
+ *pDStr++ = ')';
+ memcpy (pDStr, pExStrP + plen, excess);
+ pDStr += excess;
+ *pDStr = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ }
+ else {
+ // fake up name as [i] ultoa not used here because 0 converts
+ // as null string
+
+ switch (radix) {
+ case 8:
+ fmtstr = "[%o]";
+ break;
+
+ case 16:
+ fmtstr = "[%x]";
+ break;
+
+ default:
+ case 10:
+ fmtstr = "[%ld]";
+ break;
+ }
+
+ len = sprintf (tempbuf, fmtstr, iChild);
+
+ if (((*phName = MHMemAllocate (len + 1)) == 0) ||
+ ((*phDStr = MHMemAllocate (plen + len + 1)) == 0)) {
+ goto nomemory;
+ }
+ pName = MHMemLock (*phName);
+ pDStr = MHMemLock (*phDStr);
+ strcpy (pName, tempbuf);
+ memcpy (pDStr, pExStrP, plen);
+ memcpy (pDStr + plen, pName, len);
+ memcpy (pDStr + plen + len, pExStrP + plen, excess);
+ *(pDStr + plen + len + excess) = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ }
+ }
+ else if (EVAL_IS_CLASS (pvP)) {
+ // the type of the parent node is a class. We need to search for
+ // the data members if an object is pointed to or the entire definition
+ // if the class type is pointed to
+
+ if ((pExState->err_num = SetClassiName (pvP, iChild, phDStr, phName,
+ ((EVAL_STATE (pvP) == EV_type)? CLS_defn: CLS_data), plen, excess)) != ERR_NONE) {
+ goto general;
+ }
+ }
+ else if (EVAL_IS_FCN (pvP)) {
+ // the type of the parent node is a function. We walk down the
+ // formal argument list and return a TM that references the ith
+ // actual argument. We return an error if the ith actual is a vararg.
+
+ if ((retval = SetFcniParm (pvP, iChild, phName)) == EENOERROR) {
+ pName = MHMemLock (*phName);
+ if ((*phDStr = MHMemAllocate ((len = strlen (pName)) + 1)) == 0) {
+ MHMemUnLock (*phName);
+ goto nomemory;
+ }
+ pDStr = MHMemLock (*phDStr);
+ memcpy (pDStr, pName, len);
+ *(pDStr + len) = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ }
+ }
+ else if (EVAL_IS_LABEL (pvP)) {
+ // CV should never ask for the children of a label
+ DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ goto general;
+ }
+ MHMemUnLock (pExState->hExStr);
+ pExState = NULL;
+ MHMemUnLock (hTM);
+ GettingChild = FALSE;
+ return (retval);
+
+nomemory:
+ pExState->err_num = ERR_NOMEMORY;
+general:
+ MHMemUnLock (pExState->hExStr);
+ pExState = NULL;
+ MHMemUnLock (hTM);
+ GettingChild = FALSE;
+ return (EEGENERAL);
+}
+
+
+
+
+/** GetSymName - get name of symbol from node
+ *
+ * fSuccess = GetSymName (buf, buflen)
+ *
+ * Entry buf = pointer to buffer for name
+ * buflen = length of buffer
+ *
+ * Exit *buf = symbol name
+ *
+ * Returns TRUE if no error retreiving name
+ * FALSE if error
+ *
+ * Note if pExState->hChildName is not zero, then the name in in
+ * the buffer pointed to by hChildName
+ */
+
+
+EESTATUS GetSymName (PHTM phTM, PEEHSTR phszName)
+{
+ SYMPTR pSym;
+ short len = 0;
+ UOFFSET offset = 0;
+ char *pExStr;
+ peval_t pv;
+ short retval = EECATASTROPHIC;
+ short buflen = TYPESTRMAX - 1;
+ char *buf;
+ HSYM hProc = 0;
+ ADDR addr;
+
+
+ // M00SYMBOL - we now need to allow for a symbol name to be imbedded
+ // M00SYMBOL - in a type. Particularly for scoped types and enums.
+
+ DASSERT (*phTM != 0);
+ if ((*phTM != 0) && ((*phszName = MHMemAllocate (TYPESTRMAX)) != 0)) {
+ retval = EEGENERAL;
+ buf = MHMemLock (*phszName);
+ memset (buf, 0, TYPESTRMAX);
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ if (pExState->state.bind_ok == TRUE) {
+ pv = &pExState->result;
+ if ((pExState->state.childtm == TRUE) && (pExState->state.noname == TRUE)) {
+ // if there is no name
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ MHMemUnLock (*phszName);
+ return (EENOERROR);
+ }
+ else if (pExState->hCName != 0) {
+
+ // M00SYMBOL - for scoped types and symbols, we may be able to
+ // M00SYMBOL - hCName to hold the imbedded symbol name
+
+ pExStr = MHMemLock (pExState->hCName);
+ len = (int)strlen (pExStr);
+ len = min (len, buflen);
+ strncpy (buf, pExStr, len);
+ MHMemUnLock (pExState->hCName);
+ retval = EENOERROR;
+ }
+ else if (EVAL_HSYM (pv) == 0) {
+ if ((EVAL_IS_PTR (pv) == TRUE) && (EVAL_STATE (pv) == EV_rvalue)) {
+ addr = EVAL_PTR (pv);
+ }
+ else {
+ addr = EVAL_SYM (pv);
+ }
+ if (!ADDR_IS_LI (addr)) {
+ SHUnFixupAddr (&addr);
+ }
+ if (SHGetNearestHsym (&addr, EVAL_MOD (pv), EECODE, &hProc) == 0) {
+ EVAL_HSYM (pv) = hProc;
+ }
+ }
+ else {
+
+ // if (EVAL_HSYM (pv) != 0)
+
+ switch ((pSym = MHOmfLock (EVAL_HSYM (pv)))->rectyp) {
+ case S_REGISTER:
+ len = ((REGPTR)pSym)->name[0];
+ offset = offsetof (REGSYM, name[1]);
+ break;
+
+ case S_CONSTANT:
+ len = ((CONSTPTR)pSym)->name[0];
+ offset = offsetof (CONSTSYM, name[1]);
+ break;
+
+ case S_UDT:
+ // for a UDT, we do not return a name so that a
+ // display of the type will display the type name
+ // only once
+
+ len = 0;
+ offset = offsetof (UDTSYM, name[1]);
+ break;
+
+ case S_BLOCK16:
+ len = ((BLOCKPTR16)pSym)->name[0];
+ offset = offsetof (BLOCKSYM16, name[1]);
+ break;
+
+ case S_LPROC16:
+ case S_GPROC16:
+ len = ((PROCPTR16)pSym)->name[0];
+ offset = offsetof (PROCSYM16, name[1]);
+ break;
+
+ case S_LABEL16:
+ len = ((LABELPTR16)pSym)->name[0];
+ offset = offsetof (LABELSYM16, name[1]);
+ break;
+
+ case S_BPREL16:
+ len = ((BPRELPTR16)pSym)->name[0];
+ offset = offsetof (BPRELSYM16, name[1]);
+ break;
+
+ case S_LDATA16:
+ case S_GDATA16:
+ case S_PUB16:
+ len = ((DATAPTR16)pSym)->name[0];
+ offset = offsetof (DATASYM16, name[1]);
+ break;
+
+ case S_BLOCK32:
+ len = ((BLOCKPTR32)pSym)->name[0];
+ offset = offsetof (BLOCKSYM32, name[1]);
+ break;
+
+ case S_LPROC32:
+ case S_GPROC32:
+ len = ((PROCPTR32)pSym)->name[0];
+ offset = offsetof (PROCSYM32, name[1]);
+ break;
+
+ case S_LABEL32:
+ len = ((LABELPTR32)pSym)->name[0];
+ offset = offsetof (LABELSYM32, name[1]);
+ break;
+
+ case S_BPREL32:
+ len = ((BPRELPTR32)pSym)->name[0];
+ offset = offsetof (BPRELSYM32, name[1]);
+ break;
+
+ case S_LDATA32:
+ case S_GDATA32:
+ case S_PUB32:
+ case S_LTHREAD32:
+ case S_GTHREAD32:
+ len = ((DATAPTR32)pSym)->name[0];
+ offset = offsetof (DATASYM32, name[1]);
+ break;
+
+ case S_REGREL32:
+ len = ((LPREGREL32)pSym)->name[0];
+ offset = offsetof (REGREL32, name[1]);
+ break;
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ len = ((PROCPTRMIPS)pSym)->name[0];
+ offset = offsetof (PROCSYMMIPS, name[1]);
+ break;
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ /// BUGBUG -- Messed up return
+ return (EEGENERAL);
+ }
+ len = min (len, buflen);
+ strncpy (buf, ((char *)pSym) + offset, len);
+ MHOmfUnLock (EVAL_HSYM (pv));
+ *(buf + len) = 0;
+ retval = EENOERROR;
+ }
+ }
+ else {
+ /*
+ * if the expression did not bind, return the expression and
+ * the error message if one is available
+ *
+ * Lets treat this a bit more funny. Since the only known
+ * occurance of this is currently in locals and watch windows,
+ * check to see if there is a direct symbol refrence and
+ * correct for this case, additionally don't return an
+ * error if we can get any type of name
+ */
+
+ pExStr = MHMemLock (pExState->hExStr);
+
+ for (len = 0; pExStr[len] != 0; len++) {
+ if (pExStr[len] == (char)-1) {
+ pExStr += len+5;
+ len = -1;
+ } else if ((len == 0) &&
+ ((pExStr[len] == ')') || (pExStr[len] == '.'))) {
+ pExStr++;
+ len = -1;
+ }
+ }
+
+ if (*pExStr != 0) {
+ len = min (buflen, len);
+ strncpy (buf, pExStr, len);
+ buf += len;
+ buflen -= len;
+ retval = EENOERROR;
+ }
+ MHMemUnLock (pExState->hExStr);
+ }
+ MHMemUnLock (*phszName);
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ }
+ return (retval);
+}
+
+
+
+
+/** InfoFromTM - return information about TM
+ *
+ * EESTATUS InfoFromTM (phTM, pReqInfo, phTMInfo);
+ *
+ * Entry phTM = pointer to the handle for the expression state structure
+ * reqInfo = info request structure
+ * phTMInfo = pointer to handle for request info data structure
+ *
+ * Exit *phTMInfo = handle of info structure
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * 0 if no error
+ *
+ * The return information is based on the input request structure:
+ *
+ * fSegType - Requests the segment type the TM resides in.
+ * returned in TI.fCode
+ * fAddr - Return result as an address
+ * fValue - Return value of TM
+ * fLvalue - Return address of TM if lValue. This and
+ * fValue are mutually exclusive
+ * fSzBits - Return size of value in bits
+ * fSzBytes - Return size of value in bytes. This and
+ * fSzBits are mutually exclusive.
+ * Type - If not T_NOTYPE then cast value to this type.
+ * fValue must be set.
+ */
+
+
+EESTATUS
+InfoFromTM (
+ PHTM phTM,
+ PRI pReqInfo,
+ PHTI phTMInfo
+ )
+{
+ EESTATUS eestatus = EEGENERAL;
+ TI * pTMInfo;
+ eval_t evalT;
+ peval_t pvT;
+#ifdef TARGET_i386
+ SHREG reg;
+#endif
+ char *p;
+
+ *phTMInfo = 0;
+
+ /*
+ * Verify that there is a TM to play with
+ */
+
+ DASSERT( *phTM != 0 );
+ if (*phTM == 0) {
+ return EECATASTROPHIC;
+ }
+
+ /*
+ * Check for consistancy on the requested information
+ */
+
+ if (((pReqInfo->fValue) && (pReqInfo->fLvalue)) ||
+ ((pReqInfo->fSzBits) && (pReqInfo->fSzBytes)) ||
+ ((pReqInfo->Type != T_NOTYPE) && (!pReqInfo->fValue))) {
+ return EEGENERAL;
+ }
+
+ /*
+ * Allocate and lock down the TI which is used to return the answers
+ */
+
+ if (( *phTMInfo = MHMemAllocate( sizeof(TI) + sizeof(val_t) )) == 0) {
+ return EENOMEMORY;
+ }
+ pTMInfo = MHMemLock( *phTMInfo );
+ DASSERT( pTMInfo != NULL );
+ memset( pTMInfo, 0, sizeof(TI) + sizeof(val_t) );
+
+ /*
+ * Lock down the TM passed in
+ */
+
+ DASSERT(pExState == NULL);
+ pExState = (pexstate_t) MHMemLock( *phTM );
+ if ( pExState->state.bind_ok != TRUE ) {
+ /*
+ * If the expression has not been bound, then we can't actually
+ * answer any of the questions being asked.
+ */
+
+ MHMemUnLock( *phTMInfo );
+ MHMemUnLock( *phTM );
+ pExState = NULL;
+ return EEGENERAL;
+ }
+
+ pvT = &evalT;
+ *pvT = pExState->result;
+
+ eestatus = EENOERROR;
+
+ /*
+ * If the user asked about the segment type for the expression,
+ * get it.
+ */
+
+ if (pReqInfo->fSegType || pReqInfo->fAddr) {
+
+ if (EVAL_STATE( pvT ) == EV_lvalue) {
+ pTMInfo->fResponse.fSegType = TRUE;
+
+ /*
+ * Check for type of 0. If so then this must be a public
+ * as all compiler symbols have some type information
+ */
+
+ if (EVAL_TYP( pvT ) == 0) {
+ pTMInfo->u.SegType = EEDATA | EECODE;
+ }
+
+ /*
+ * If item is of type pointer to data then must be in
+ * data segment
+ */
+
+ else if (EVAL_IS_DPTR( pvT ) == TRUE) {
+ pTMInfo->u.SegType = EEDATA;
+ }
+
+ /*
+ * in all other cases it must have been a code segment
+ */
+
+ else {
+ pTMInfo->u.SegType = EECODE;
+ }
+
+ } else if ((EVAL_STATE( pvT ) == EV_rvalue) &&
+ (EVAL_IS_FCN( pvT ) ||
+ EVAL_IS_LABEL( pvT ))) {
+
+ pTMInfo->fResponse.fSegType = TRUE;
+ pTMInfo->u.SegType = EECODE;
+
+ } else if ((EVAL_STATE( pvT ) == EV_rvalue) &&
+ (EVAL_IS_ADDR( pvT ))) {
+
+ pTMInfo->fResponse.fSegType = TRUE;
+ pTMInfo->u.SegType = EECODE | EEDATA;
+
+ } else if ((EVAL_STATE( pvT ) == EV_rvalue) ||
+ (EVAL_STATE( pvT ) == EV_constant)) {
+ ;
+ }
+ }
+
+ /*
+ * If the user asked for the value then get it
+ */
+
+ if (pReqInfo->fValue) {
+ if ((pExState->state.eval_ok == TRUE) && LoadSymVal(pvT)) {
+ EVAL_STATE (pvT) = EV_rvalue;
+ }
+
+
+ if ((EVAL_STATE(pvT) == EV_rvalue) &&
+ (EVAL_IS_FCN(pvT) ||
+ EVAL_IS_LABEL(pvT))) {
+
+ if ( pReqInfo->Type == T_NOTYPE ) {
+ pTMInfo->fResponse.fValue = TRUE;
+ pTMInfo->fResponse.fAddr = TRUE;
+ pTMInfo->fResponse.fLvalue = FALSE;
+ pTMInfo->u2.AI = EVAL_SYM( pvT );
+ pTMInfo->fResponse.Type = EVAL_TYP( pvT );
+ if (!ADDR_IS_LI(pTMInfo->u2.AI)) {
+ SHUnFixupAddr(&pTMInfo->u2.AI);
+ }
+ } else {
+ Evaluating = TRUE;
+ if (CastNode( pvT, pReqInfo->Type, pReqInfo->Type )) {
+ memcpy( pTMInfo->Value, &pvT->val, sizeof( pvT->val ));
+ pTMInfo->fResponse.fValue = TRUE;
+ pTMInfo->fResponse.Type = EVAL_TYP( pvT );
+ }
+ Evaluating = FALSE;
+ }
+
+ } else if ((EVAL_STATE( pvT ) == EV_rvalue) &&
+ (EVAL_IS_ADDR( pvT ))) {
+
+ if (EVAL_IS_BASED( pvT )) {
+ Evaluating = TRUE;
+ NormalizeBase( pvT );
+ Evaluating = FALSE;
+ }
+
+ if ( pReqInfo->Type == T_NOTYPE ) {
+
+ pTMInfo->fResponse.fValue = TRUE;
+ pTMInfo->fResponse.fAddr = TRUE;
+ pTMInfo->fResponse.fLvalue = FALSE;
+ pTMInfo->u2.AI = EVAL_PTR( pvT );
+ pTMInfo->fResponse.Type = EVAL_TYP(pvT);
+ if (!ADDR_IS_LI( pTMInfo->u2.AI )) {
+ SHUnFixupAddr( &pTMInfo->u2.AI );
+ }
+ } else {
+ Evaluating = TRUE;
+ if (CastNode( pvT, pReqInfo->Type, pReqInfo->Type )) {
+ memcpy( pTMInfo->Value, &pvT->val, sizeof( pvT->val ));
+ pTMInfo->fResponse.fValue = TRUE;
+ pTMInfo->fResponse.Type = EVAL_TYP( pvT );
+ }
+ Evaluating = FALSE;
+ }
+ } else if ((EVAL_STATE( pvT ) == EV_rvalue) ||
+ (EVAL_STATE( pvT ) == EV_constant)) {
+
+ if ((EVAL_STATE( pvT ) == EV_constant ) ||
+ (pExState->state.eval_ok == TRUE)) {
+
+ if (CV_IS_PRIMITIVE( pReqInfo->Type )) {
+ if (pReqInfo->Type == 0) {
+ pReqInfo->Type = EVAL_TYP( pvT );
+ }
+
+ Evaluating = TRUE;
+ if (CastNode( pvT, pReqInfo->Type, pReqInfo->Type )) {
+ memcpy( pTMInfo->Value, &pvT->val, sizeof( pvT->val ));
+ pTMInfo->fResponse.fValue = TRUE;
+ pTMInfo->fResponse.Type = EVAL_TYP( pvT );
+ }
+ Evaluating = FALSE;
+ }
+ }
+ }
+
+ }
+
+
+ /*
+ * If the user asked for the lvalue as an address
+ */
+
+ if (pReqInfo->fAddr && pReqInfo->fLvalue) {
+ pTMInfo->u2.AI = pvT->addr;
+ //eestatus = EEGENERAL;
+ }
+
+ /*
+ * If the user asked for the value as an address
+ */
+
+ if (pReqInfo->fAddr && !pReqInfo->fLvalue) {
+ if ((EVAL_STATE(pvT) == EV_lvalue) &&
+ (pExState->state.eval_ok == TRUE) &&
+ LoadSymVal(pvT)) {
+ EVAL_STATE (pvT) = EV_rvalue;
+ }
+
+
+ if ((EVAL_STATE(pvT) == EV_rvalue) &&
+ (EVAL_IS_FCN(pvT) ||
+ EVAL_IS_LABEL(pvT))) {
+
+ pTMInfo->u2.AI = EVAL_SYM( pvT );
+ pTMInfo->fResponse.fAddr = TRUE;
+ pTMInfo->fResponse.Type = EVAL_TYP( pvT );
+
+ if (!ADDR_IS_LI(pTMInfo->u2.AI)) {
+ SHUnFixupAddr(&pTMInfo->u2.AI);
+ }
+
+ eestatus = EENOERROR;
+ } else if ((EVAL_STATE(pvT) == EV_rvalue) &&
+ (EVAL_IS_ADDR( pvT ))) {
+ if (EVAL_IS_BASED( pvT )) {
+ Evaluating = TRUE;
+ NormalizeBase( pvT );
+ Evaluating = FALSE;
+ }
+
+ pTMInfo->fResponse.fAddr = TRUE;
+ pTMInfo->u2.AI = EVAL_PTR( pvT );
+ pTMInfo->fResponse.Type = EVAL_TYP( pvT );
+
+ if (!ADDR_IS_LI( pTMInfo->u2.AI )) {
+ SHUnFixupAddr( &pTMInfo->u2.AI );
+ }
+
+ } else if ((EVAL_STATE( pvT ) == EV_rvalue) ||
+ (EVAL_STATE( pvT ) == EV_constant)) {
+
+ if ((EVAL_STATE( pvT ) == EV_constant) ||
+ (pExState->state.eval_ok == TRUE)) {
+
+ pReqInfo->Type = T_ULONG;
+ Evaluating = TRUE;
+ if (CastNode(pvT, pReqInfo->Type, pReqInfo->Type)) {
+ switch( TypeSize( pvT ) ) {
+ case 1:
+ pTMInfo->u2.AI.addr.off = VAL_UCHAR( pvT );
+ break;
+
+ case 2:
+ pTMInfo->u2.AI.addr.off = VAL_USHORT( pvT );
+ break;
+
+ case 4:
+ pTMInfo->u2.AI.addr.off = VAL_ULONG( pvT );
+ break;
+
+ default:
+ eestatus = EEGENERAL;
+ break;
+ }
+
+ pTMInfo->fResponse.fAddr = TRUE;
+ pTMInfo->fResponse.Type = pReqInfo->Type;
+
+#ifdef TARGET_i386
+ if (pTMInfo->u.SegType & EECODE) {
+ reg.hReg = CV_REG_CS;
+ } else {
+ reg.hReg = CV_REG_DS;
+ }
+
+ GetReg(&reg, pCxt);
+ pTMInfo->u2.AI.addr.seg = reg.Byte2;
+#else
+ pTMInfo->u2.AI.addr.seg = 0;
+#endif
+
+ SHUnFixupAddr( &pTMInfo->u2.AI);
+ } else {
+ eestatus = EEGENERAL;
+ }
+ Evaluating = FALSE;
+ } else {
+ eestatus = EEGENERAL;
+ }
+ } else {
+ eestatus = EEGENERAL;
+ }
+ }
+
+
+ /*
+ * Set the size fields if requested
+ */
+
+ if (pReqInfo->fSzBits) {
+ if (EVAL_IS_BITF( pvT )) {
+ pTMInfo->cbValue = BITF_LEN( pvT );
+ pTMInfo->fResponse.fSzBits = TRUE;
+ } else {
+ if (EVAL_TYP( pvT ) != 0) {
+ pTMInfo->cbValue = 8 * TypeSize( pvT );
+ pTMInfo->fResponse.fSzBits = TRUE;
+ }
+ }
+ }
+
+ if (pReqInfo->fSzBytes) {
+ if (EVAL_IS_BITF( pvT )) {
+ EVAL_TYP( pvT ) = BITF_UTYPE( pvT );
+ }
+
+ if (EVAL_TYP( pvT ) != 0) {
+ pTMInfo->cbValue = TypeSize( pvT );
+ pTMInfo->fResponse.fSzBytes = TRUE;
+ }
+ }
+
+ /*
+ * Set random flags
+ */
+
+ pTMInfo->u.fFunction = pExState->state.fFunction;
+
+ pExStr = MHMemLock(pExState->hExStr);
+ p = &pExStr[pExState->strIndex];
+ if (*p == ',') {
+ *p++;
+ }
+ if (tolower(*p) == 's') {
+ pTMInfo->u.fFmtStr = TRUE;
+ }
+ else {
+ pTMInfo->u.fFmtStr = FALSE;
+ }
+ MHMemUnLock( pExState->hExStr );
+
+ MHMemUnLock( *phTMInfo );
+ MHMemUnLock( *phTM );
+ pExState = NULL;
+
+ return eestatus;
+}
+
+
+
+
+/** IsExpandablePtr - check for pointer to displayable data
+ *
+ * fSuccess = IsExpandablePtr (pn)
+ *
+ * Entry pn = pointer to node for variable
+ *
+ * Exit none
+ *
+ * Returns EEPOINTER if node is a pointer to primitive data or,
+ * class/struct/union
+ * EEAGGREGATE if node is an array with a non-zero size or is
+ * a pointer to a virtual function shape table
+ * EENOTEXP otherwise
+ */
+
+
+ushort IsExpandablePtr (peval_t pv)
+{
+ eval_t evalT;
+ peval_t pvT;
+ ushort retval = EENOTEXP;
+
+ if (EVAL_IS_PTR (pv)) {
+ // this will also handle the reference cases
+ if (EVAL_TYP(pv) == T_VOID ||
+ EVAL_TYP(pv) == T_PVOID ||
+ EVAL_TYP(pv) == T_PFVOID ||
+ EVAL_TYP(pv) == T_PHVOID ||
+ EVAL_TYP(pv) == T_32PVOID ||
+ EVAL_TYP(pv) == T_32PFVOID) {
+ return retval;
+ }
+ if (CV_IS_PRIMITIVE (PTR_UTYPE (pv))) {
+ retval = EEPOINTER;
+ } else {
+ pvT = &evalT;
+ CLEAR_EVAL (pvT);
+ EVAL_MOD (pvT) = EVAL_MOD (pv);
+ SetNodeType (pvT, PTR_UTYPE (pv));
+ if (EVAL_IS_CLASS (pvT) || EVAL_IS_PTR (pvT)) {
+ retval = EEPOINTER;
+ }
+ else if (EVAL_IS_VTSHAPE (pvT) ||
+ (EVAL_IS_ARRAY (pvT) && (PTR_ARRAYLEN (pv) != 0))) {
+ retval = EEAGGREGATE;
+ }
+ }
+ }
+ return (retval);
+}
+
+
+
+
+/*** CountClassElem - count number of class elements according to mask
+ *
+ * count = CountClassElem (pv, search)
+ *
+ * Entry pv = pointer to node to be initialized
+ * search = mask specifying which element types to count
+ *
+ * Exit none
+ *
+ * Returns count of number of class elements meeting search requirments
+ */
+
+
+LOCAL EESTATUS CountClassElem (peval_t pv, long *pcChildren,
+ uint search)
+{
+ ushort cnt; // total number of elements in class
+ HTYPE hField; // type record handle for class field list
+ char *pField; // current position within field list
+ uint fSkip = 0; // current offset in the field list
+ uint anchor;
+ ushort retval = EENOERROR;
+ CV_typ_t newindex;
+ uchar pad;
+
+ // set the handle of the field list
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), CLASS_FIELD (pv))) == 0) {
+ DASSERT (FALSE);
+ return (0);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+
+ // walk field list to the end counting elements
+
+ for (cnt = CLASS_COUNT (pv); cnt > 0; cnt--) {
+ if ((pad = *(((char *)pField) + fSkip)) >= LF_PAD0) {
+ // there is a pad field
+ fSkip += pad & 0x0f;
+ }
+ anchor = fSkip;
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // move to next list in chain
+
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) == 0) {
+ DASSERT (FALSE);
+ return (0);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ fSkip = 0;
+ // the LF_INDEX is not part of the field count
+ cnt++;
+ break;
+
+ case LF_MEMBER:
+ // skip offset of member and name of member
+ fSkip += offsetof (lfMember, offset[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_member) {
+ (*pcChildren)++;
+ }
+ break;
+
+
+#if !defined(C_ONLY)
+ case LF_ENUMERATE:
+ // skip value name of enumerate
+ fSkip += offsetof (lfEnumerate, value[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_enumerate) {
+ (*pcChildren)++;
+ }
+ break;
+
+ case LF_STMEMBER:
+ fSkip += offsetof (lfSTMember, Name[0]);
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_member) {
+ (*pcChildren)++;
+ }
+ break;
+
+ case LF_BCLASS:
+ fSkip += offsetof (lfBClass, offset[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ if (search & CLS_bclass) {
+ (*pcChildren)++;
+ }
+ break;
+
+ case LF_VBCLASS:
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ if (search & CLS_bclass) {
+ (*pcChildren)++;
+ }
+ break;
+
+ case LF_IVBCLASS:
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ break;
+
+ case LF_FRIENDCLS:
+ fSkip += sizeof (lfFriendCls);
+ if (search & CLS_fclass) {
+ (*pcChildren)++;
+ }
+ break;
+
+ case LF_FRIENDFCN:
+ fSkip += sizeof (struct lfFriendFcn) +
+ ((plfFriendFcn)(pField + fSkip))->Name[0];
+ if (search & CLS_frmethod) {
+ (*pcChildren)++;
+ }
+ break;
+
+ case LF_VFUNCTAB:
+ fSkip += sizeof (lfVFuncTab);
+ if (search & CLS_vfunc) {
+ (*pcChildren)++;
+ }
+ break;
+
+
+ case LF_METHOD:
+ fSkip += sizeof (struct lfMethod) +
+ ((plfMethod)(pField + fSkip))->Name[0];
+ cnt -= ((plfMethod)(pField + anchor))->count - 1;
+ if (search & CLS_method) {
+ *pcChildren += ((plfMethod)(pField + anchor))->count;
+ }
+ break;
+
+ case LF_NESTTYPE:
+ fSkip += sizeof (struct lfNestType) +
+ ((plfNestType)(pField + fSkip))->Name[0];
+ if (search & CLS_ntype) {
+ (*pcChildren)++;
+ }
+ break;
+#endif
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ MHOmfUnLock (hField);
+ *pcChildren = 0;
+ return (EEGENERAL);
+ }
+ }
+ if (hField != 0) {
+ MHOmfUnLock (hField);
+ }
+ return (retval);
+}
+
+
+
+
+
+/** DereferenceTM - generate expression string from pointer to data TM
+ *
+ * flag = DereferenceTM (hTMIn, phEStr)
+ *
+ * Entry phTMIn = handle to TM to dereference
+ * phEStr = pointer to handle to dereferencing expression
+ *
+ * Exit *phEStr = expression referencing pointer data
+ *
+ * Returns EECATASTROPHIC if fatal error
+ * EEGENERAL if TM not dereferencable
+ * EENOERROR if expression generated
+ */
+
+
+EESTATUS DereferenceTM (HTM hTM, PEEHSTR phDStr)
+{
+ peval_t pvTM;
+ EESTATUS retval = EECATASTROPHIC;
+ pexstate_t pTM;
+ ushort plen;
+ uint excess;
+
+ DASSERT (hTM != 0);
+ if (hTM != 0) {
+ // lock TM and set pointer to result field of TM
+
+ pTM = MHMemLock (hTM);
+ pvTM = &pTM->result;
+ if (EVAL_IS_ARRAY (pvTM) || (IsExpandablePtr (pvTM) != EEPOINTER)) {
+ pTM->err_num = ERR_NOTEXPANDABLE;
+ retval = EEGENERAL;
+ }
+ else {
+ // allocate buffer for *(input string) and copy
+
+ if ((*phDStr = MHMemAllocate (pTM->ExLen + 4)) != 0) {
+ // if not reference generate, expression = *(old expr)
+ // if reference, expression = (old expr)
+
+ pExStr = MHMemLock (*phDStr);
+ *pExStr++ = '(';
+#if !defined (C_ONLY)
+ if (!EVAL_IS_REF (pvTM)) {
+ *pExStr++ = '*';
+ }
+#else
+ *pExStr++ = '*';
+#endif
+ plen = pTM->strIndex;
+ excess = pTM->ExLen - plen;
+ pExStrP = MHMemLock (pTM->hExStr);
+ memcpy (pExStr, pExStrP, plen);
+ pExStr += plen;
+ *pExStr++ = ')';
+ memcpy (pExStr, pExStrP + plen, excess);
+ pExStr += excess;
+ *pExStr = 0;
+ MHMemUnLock (pTM->hExStr);
+ MHMemUnLock (*phDStr);
+ retval = EENOERROR;
+ }
+ }
+ MHMemUnLock (hTM);
+ }
+ return (retval);
+}
+
+
+
+
+/*** SetClassiName - Set a node to a specified element of a class
+ *
+ * fFound = SetClassiName (pv, ordinal, phDStr, phName, search, plen)
+ *
+ * Entry ordinal = number of class element to initialize for
+ * (zero based)
+ * search = mask specifying which element types to count
+ * pExStrP = address of locked pExParent->hExStr
+ * plen = length of parent string to end of parse
+ * excess = length of parent string after end of parse
+ *
+ * Exit pExState->hCName = handle of buffer containing name
+ *
+ * Returns ERR_NONE if element found within structure
+ * error number if element not found within structure
+ */
+
+
+LOCAL ushort SetClassiName (peval_t pv, long ordinal,
+ PEEHSTR phDStr, PEEHSTR phName, uint search, ushort plen, uint excess)
+{
+ HTYPE hField; // handle to type record for struct field list
+ char *pField; // current position withing field list
+ char *pMethod;
+ uint fSkip = 0; // current offset in the field list
+ uint anchor;
+ uint len;
+ bool_t retval = ERR_NONE;
+ CV_typ_t newindex;
+ char *pName;
+ char *pc;
+ char *pDStr;
+ char FName[255];
+ char *pFName = &FName[0];
+ eval_t evalT;
+ peval_t pvT;
+ uchar pad;
+ PHDR_TYPE pHdr;
+
+ // set fField to the handle of the field list
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), CLASS_FIELD (pv))) == 0) {
+ DASSERT (FALSE);
+ return (ERR_BADOMF);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+
+ // walk field list to iElement-th field
+
+ while (ordinal >= 0) {
+ if ((pad = *(((char *)pField) + fSkip)) >= LF_PAD0) {
+ // there is a pad field
+ fSkip += pad & 0x0f;
+ }
+ anchor = fSkip;
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // move to next list in chain
+
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) == 0) {
+ return (ERR_BADOMF);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ fSkip = 0;
+ break;
+
+ case LF_MEMBER:
+ // skip offset of member and name of member
+ fSkip += offsetof (lfMember, offset[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_member) {
+ ordinal--;
+ }
+ break;
+
+ case LF_ENUMERATE:
+ // skip value name of enumerate
+ fSkip += offsetof (lfEnumerate, value[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_enumerate) {
+ ordinal--;
+ }
+ break;
+
+
+#if !defined(C_ONLY)
+ case LF_STMEMBER:
+ fSkip += offsetof (lfSTMember, Name[0]);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_member) {
+ ordinal--;
+ }
+ break;
+
+ case LF_BCLASS:
+ fSkip += offsetof (lfBClass, offset[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ if (search & CLS_bclass) {
+ ordinal--;
+ }
+ break;
+
+ case LF_VBCLASS:
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ if (search & CLS_bclass) {
+ ordinal--;
+ }
+ break;
+
+ case LF_IVBCLASS:
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ break;
+
+ case LF_FRIENDCLS:
+ fSkip += sizeof (struct lfFriendCls);
+ if (search & CLS_fclass) {
+ ordinal--;
+ }
+ break;
+
+ case LF_FRIENDFCN:
+ fSkip += sizeof (struct lfFriendFcn) +
+ ((plfFriendFcn)(pField + fSkip))->Name[0];
+ if (search & CLS_frmethod) {
+ ordinal--;
+ }
+ break;
+
+ case LF_VFUNCTAB:
+ fSkip += sizeof (struct lfVFuncTab);
+ pc = vfuncptr;
+ if (search & CLS_vfunc) {
+ ordinal--;
+ }
+ break;
+
+ case LF_METHOD:
+ pc = pField + anchor + offsetof (lfMethod, Name[0]);
+ fSkip += sizeof (struct lfMethod) + *pc;
+ if (search & CLS_method) {
+ ordinal -= ((plfMethod)(pField + anchor))->count;
+ }
+ break;
+
+ case LF_NESTTYPE:
+ fSkip += offsetof (lfNestType, Name[0]);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (search & CLS_ntype) {
+ ordinal--;
+ }
+ break;
+#endif
+
+ default:
+ MHOmfUnLock (hField);
+ return (ERR_BADOMF);
+ }
+ if (ordinal < 0) {
+ break;
+ }
+ }
+
+ // we have found the ith element of the class. Now create the
+ // name and the expression to reference the name
+
+ switch (((plfEasy)(pField + anchor))->leaf) {
+ case LF_MEMBER:
+ case LF_STMEMBER:
+ case LF_VFUNCTAB:
+ len = *pc;
+ if (((*phName = MHMemAllocate (len + 1)) == 0) ||
+ ((*phDStr = MHMemAllocate (plen + excess + len + 4)) == 0)) {
+ goto nomemory;
+ }
+ pName = MHMemLock (*phName);
+ strncpy (pName, pc + 1, len);
+ *(pName + len) = 0;
+ pDStr = MHMemLock (*phDStr);
+ *pDStr++ = '(';
+ memcpy (pDStr, pExStrP, plen);
+ pDStr += plen;
+ *pDStr++ = ')';
+ *pDStr++ = '.';
+ memcpy (pDStr, pName, len);
+ pDStr += len;
+ memcpy (pDStr, pExStrP + plen, excess);
+ pDStr += excess;
+ *pDStr = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ break;
+#if !defined (C_ONLY)
+
+ case LF_BCLASS:
+ newindex = ((plfBClass)(pField + anchor))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
+ // find the name of the base class from the referenced class
+
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->leaf);
+ fSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ len = *(pField + fSkip);
+
+ // generate (*(base *)(&expr))
+
+ if (((*phName = MHMemAllocate (len + 1)) == 0) ||
+ ((*phDStr = MHMemAllocate (plen + len + excess + 10)) == 0)) {
+ goto nomemory;
+ }
+ pName = MHMemLock (*phName);
+ strncpy (pName, pField + fSkip + sizeof (char), len);
+ *(pName + len) = 0;
+ pDStr = MHMemLock (*phDStr);
+ memcpy (pDStr, "(*(", 3);
+ memcpy (pDStr + 3, pField + fSkip + sizeof (char), len);
+ memcpy (pDStr + 3 + len, "*)(&", 4);
+ memcpy (pDStr + 7 + len, pExStrP, plen);
+ memcpy (pDStr + 7 + len + plen, "))", 2);
+ memcpy (pDStr + 7 + len + plen + 2, pExStrP + plen, excess);
+ *(pDStr + 9 + len + plen + excess) = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ }
+ break;
+
+ case LF_VBCLASS:
+ newindex = ((plfVBClass)(pField + anchor))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
+ // find the name of the base class from the referenced class
+
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->leaf);
+ fSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ len = *(pField + fSkip);
+
+ // generate (*(base *)(&expr))
+
+ if (((*phName = MHMemAllocate (len + 1)) == 0) ||
+ ((*phDStr = MHMemAllocate (plen + len + 10)) == 0)) {
+ goto nomemory;
+ }
+ pName = MHMemLock (*phName);
+ //*pName = 0;
+ strncpy (pName, pField + fSkip + sizeof (char), len);
+ *(pName + len) = 0;
+ pDStr = MHMemLock (*phDStr);
+ memcpy (pDStr, "(*(", 3);
+ memcpy (pDStr + 3, pField + fSkip + sizeof (char), len);
+ memcpy (pDStr + 3 + len, "*)(&", 4);
+ memcpy (pDStr + 7 + len, pExStrP, plen);
+ memcpy (pDStr + 7 + len + plen, "))", 2);
+ memcpy (pDStr + 7 + len + plen + 2, pExStrP + plen, excess);
+ *(pDStr + 9 + len + plen + excess) = 0;
+ MHMemUnLock (*phDStr);
+ MHMemUnLock (*phName);
+ }
+ break;
+
+ case LF_FRIENDCLS:
+ // look at referenced type record to get name of class
+ // M00KLUDGE - figure out what to do here - not bindable
+
+ newindex = ((plfFriendCls)(pField + anchor))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->leaf);
+ fSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ len = *(pField + fSkip);
+ }
+ break;
+
+ case LF_FRIENDFCN:
+ // look at referenced type record to get name of function
+ // M00KLUDGE - figure out what to do here - not bindable
+
+ newindex = ((plfFriendFcn)(pField + anchor))->index;
+ pc = (char *)(((plfFriendFcn)(pField + anchor))->Name[0]);
+ break;
+
+ case LF_METHOD:
+ // copy function name to temporary buffer
+
+ len = *pc;
+ memcpy (FName, pc + 1, len);
+ FName[len] = 0;
+ newindex = ((plfMethod)(pField + anchor))->mList;
+ MHOmfUnLock (hField);
+
+ // index down method list to find correct method
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pv), newindex)) != 0) {
+ pMethod = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ fSkip = 0;
+ while (++ordinal < 0) {
+ if (((pmlMethod)(pMethod + fSkip))->attr.mprop == CV_MTvirtual) {
+ fSkip += sizeof (mlMethod);
+ RNumLeaf (pMethod + fSkip, &fSkip);
+ }
+ else {
+ fSkip += sizeof (mlMethod);
+ }
+ }
+ pvT = &evalT;
+ CLEAR_EVAL (pvT);
+ EVAL_MOD (pvT) = SHHMODFrompCXT (pCxt);
+ newindex = ((pmlMethod)(pMethod + fSkip))->index;
+ MHOmfUnLock (hField);
+ hField = 0;
+ SetNodeType (pvT, newindex);
+ if ((*phName = MHMemAllocate (FCNSTRMAX + sizeof (HDR_TYPE))) == 0) {
+ goto nomemory;
+ }
+
+ // FormatType places a structure at the beginning of the buffer
+ // containing offsets into the type string. We need to skip this
+ // structure
+
+ pName = MHMemLock (*phName);
+ pHdr = (PHDR_TYPE)pName;
+ memset (pName, 0, FCNSTRMAX + sizeof (HDR_TYPE));
+ pName = pName + sizeof (HDR_TYPE);
+ pc = pName;
+ len = FCNSTRMAX - 1;
+ FormatType (pvT, &pName, &len, &pFName, 0L, pHdr);
+ len = FCNSTRMAX - len;
+
+ // ignore buffer header from FormatType
+
+ memmove ((char *)pHdr, pc, len);
+ pc = (char *)pHdr;
+ if ((*phDStr = MHMemAllocate (plen + FCNSTRMAX + 2)) == 0) {
+ MHMemUnLock (*phName);
+ goto nomemory;
+ }
+
+ pDStr = MHMemLock (*phDStr);
+ memcpy (pDStr, pExStrP, plen);
+ memcpy (pDStr + plen, ".", 1);
+ memcpy (pDStr + 1 + plen, pc, len);
+ memcpy (pDStr + 1 + plen + len, pExStrP + plen, excess);
+ *(pDStr + len + plen + 1 + excess) = 0;
+ MHMemUnLock (*phDStr);
+ // truncate name to first (
+ for (len = 0; (*pc != '(') && (*pc != 0); pc++) {
+ len++;
+ }
+ *pc = 0;
+ MHMemUnLock (*phName);
+ if ((*phName = MHMemReAlloc (*phName, len + 1)) == 0) {
+ goto nomemory;
+ }
+ }
+ break;
+#else
+ Unreferenced( evalT );
+ Unreferenced( pHdr );
+ Unreferenced( pvT );
+ Unreferenced( pMethod );
+#endif
+
+ default:
+ retval = ERR_BADOMF;
+ break;
+ }
+ if (hField != 0) {
+ MHOmfUnLock (hField);
+ }
+ return (retval);
+
+nomemory:
+ if (hField != 0) {
+ MHOmfUnLock (hField);
+ }
+ if (*phName != 0) {
+ MHMemFree (*phName);
+ }
+ return (ERR_NOMEMORY);
+}
+
+
+
+
+/*** SetFcniParm - Set a node to a specified parameter of a function
+ *
+ * fFound = SetFcniParm (pv, ordinal, pHStr)
+ *
+ * Entry pv = pointer to node to be initialized
+ * ordinal = number of struct element to initialize for
+ * (zero based)
+ * pHStr = pointer to handle for parameter name
+ *
+ * Exit pv initialized if no error
+ * *pHStr = handle for name
+ *
+ * Returns EENOERROR if parameter found
+ * EEGENERAL if parameter not found
+ *
+ * This routine is essentially a kludge. We are depending upon the
+ * the compiler to output the formals in order of declaration before
+ * any of the hidden parameters or local variables. We also are
+ * depending upon the presence of an S_END record to break us out of
+ * the search loop.
+ */
+
+
+LOCAL ushort SetFcniParm (peval_t pv, long ordinal, PEEHSTR pHStr)
+{
+ char *pStr;
+ HSYM hSym;
+ SYMPTR pSym;
+ ushort offset;
+ ushort len;
+ bool_t retval;
+
+ if ((ordinal > FCN_PCOUNT (pv)) ||
+ ((ordinal == (FCN_PCOUNT (pv) - 1)) && (FCN_VARARGS (pv) == TRUE))) {
+ // attempting to reference a vararg or too many parameters
+
+ pExState->err_num = ERR_FCNERROR;
+ return (EEGENERAL);
+ }
+ hSym = EVAL_HSYM (pv);
+ for (;;) {
+ if ((hSym = SHNextHsym (EVAL_MOD (pv), hSym)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (EEGENERAL);
+ }
+
+ // lock the symbol and check the type
+ pSym = MHOmfLock (hSym);
+ switch (pSym->rectyp) {
+#if defined (ADDR_16) || defined (ADDR_MIXED)
+ case S_BPREL16:
+ if (((BPRELPTR16)pSym)->off >= 0) {
+ // This is a formal argument
+ ordinal--;
+ len = ((BPRELPTR16)pSym)->name[0];
+ offset = offsetof (BPRELSYM16, name[0]) + sizeof (char);
+ }
+ break;
+#endif
+
+ case S_BPREL32:
+ if (((BPRELPTR32)pSym)->off >= 0) {
+ // This is a formal argument
+ ordinal--;
+ len = ((BPRELPTR32)pSym)->name[0];
+ offset = offsetof (BPRELSYM32, name[0]) + sizeof (char);
+ }
+ break;
+
+ case S_REGREL32:
+ if (((LPREGREL32)pSym)->off >= 0) {
+ // Formal parameter
+ ordinal--;
+ len = ((LPREGREL32)pSym)->name[0];
+ offset = offsetof (REGREL32, name[1]);
+ }
+ break;
+
+ case S_REGISTER:
+ ordinal--;
+ len = ((REGPTR)pSym)->name[0];
+ offset = offsetof (REGSYM, name[1]);
+ break;
+
+ case S_GTHREAD32:
+ case S_LTHREAD32:
+ DASSERT(FALSE);
+ return( EEGENERAL );
+
+ case S_END:
+ case S_BLOCK16:
+ case S_BLOCK32:
+ case S_ENDARG:
+ // we should never get here
+ pExState->err_num = ERR_BADOMF;
+ MHOmfUnLock (hSym);
+ return (EEGENERAL);
+
+ default:
+ break;
+ }
+ if (ordinal < 0) {
+ break;
+ }
+ MHOmfUnLock (hSym);
+ }
+
+ // if we get here, pSym points to the symbol record for the parameter
+
+ if ((*pHStr = MHMemAllocate (len + 1)) != 0) {
+ pStr = MHMemLock (*pHStr);
+ strncpy (pStr, ((char *)pSym) + offset, len);
+ *(pStr + len) = 0;
+ MHMemUnLock (*pHStr);
+ retval = EENOERROR;
+ }
+ else {
+ MHOmfUnLock (hSym);
+ retval = EEGENERAL;
+ }
+ MHOmfUnLock (hSym);
+ return (retval);
+}
+
+
+bool_t
+ResolveAddr(
+ peval_t pv
+ )
+{
+ ulong ul;
+ ADDR addr;
+ SHREG reg;
+
+ /*
+ * Fixup BP Relative addresses. The BP register always comes in
+ * as part of the frame.
+ *
+ * This form is currently only used by x86 systems.
+ */
+
+ if (EVAL_IS_BPREL (pv)) {
+ EVAL_SYM_OFF (pv) += pExState->frame.BP.off;
+ EVAL_SYM_SEG (pv) = pExState->frame.SS;
+ EVAL_IS_BPREL (pv) = FALSE;
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+ SHUnFixupAddr (&EVAL_SYM (pv));
+ }
+
+ /*
+ * Fixup register relative addresses. This form is currently used
+ * by all non-x86 systems.
+ *
+ * We need to see if we are relative to the "Frame register" for the
+ * machine. If so then we need to pick the address up from the
+ * frame packet rather than going out and getting the register
+ * directly. This has implications for getting variables up a stack.
+ */
+
+ else if (EVAL_IS_REGREL (pv)) {
+ reg.hReg = EVAL_REGREL (pv);
+#ifdef TARGET_PPC
+ if (reg.hReg == CV_PPC_GPR1) {
+ ul = pExState->frame.BP.off;
+ } else
+#endif
+#ifdef TARGET_MIPS
+ if (reg.hReg == CV_M4_IntSP) {
+ ul = pExState->frame.BP.off;
+ } else
+#endif
+#ifdef TARGET_ALPHA
+ if (reg.hReg == CV_ALPHA_IntSP) {
+ ul = pExState->frame.BP.off;
+ } else
+#endif
+ if (GetReg (&reg, pCxt) == NULL) {
+ DASSERT (FALSE);
+ } else {
+ ul = reg.Byte4;
+ if (!ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ ul &= 0xffff;
+ }
+ }
+
+ EVAL_SYM_OFF (pv) += ul;
+ EVAL_SYM_SEG (pv) = pExState->frame.SS;
+ EVAL_IS_REGREL (pv) = FALSE;
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+ emiAddr (EVAL_SYM (pv)) = 0;
+ SHUnFixupAddr (&EVAL_SYM (pv));
+ }
+ /*
+ * Fixup Thread local storage relative addresses. This form is
+ * currently used by all platforms.
+ */
+
+ else if (EVAL_IS_TLSREL (pv)) {
+ EVAL_IS_TLSREL( pv ) = FALSE;
+
+ /*
+ * Query the EM for the TLS base on this (current) thread
+ */
+
+ memset(&addr, 0, sizeof(ADDR));
+ emiAddr( addr ) = emiAddr( EVAL_SYM( pv ));
+ SYGetAddr(&addr, adrTlsBase);
+
+ EVAL_SYM_OFF( pv ) += GetAddrOff(addr);
+ EVAL_SYM_SEG( pv ) = GetAddrSeg(addr);
+ ADDR_IS_LI(EVAL_SYM( pv )) = ADDR_IS_LI(addr);
+ emiAddr(EVAL_SYM( pv )) = 0;
+ SHUnFixupAddr( &EVAL_SYM( pv ));
+ }
+
+ return TRUE;
+} /* ResolveAddr() */
diff --git a/private/windbg/eecan/debsym.c b/private/windbg/eecan/debsym.c
new file mode 100644
index 000000000..49857eb16
--- /dev/null
+++ b/private/windbg/eecan/debsym.c
@@ -0,0 +1,6674 @@
+/*** DEBSYM.C - symbol lookup routines for expression evaluator
+ *
+ *
+ */
+
+
+extern bool_t FNtsdEvalType;
+
+// enum specifying return from IsDominated
+
+typedef enum {
+ DOM_ambiguous,
+ DOM_keep,
+ DOM_replace
+} DOM_t;
+
+// Return values from SearchClassName
+
+typedef enum {
+ SCN_error, // error, abort search
+ SCN_notfound, // not found
+ SCN_found, // found
+ SCN_rewrite // found and this pointer inserted
+} SCN_t;
+
+
+// Return values from MatchMethod
+
+typedef enum {
+ MTH_error, // error - abort search
+ MTH_found // found without error
+} MTH_t;
+
+
+typedef struct HSL_restart_t {
+ search_t Name;
+ HSYM hSym;
+ HSYML_t state;
+ ushort mask;
+} HSL_restart_t;
+
+
+static char *vtabptr = "#vptr#";
+static HDEP hSymClass = 0;
+static psymclass_t pSymClass = NULL;
+
+static HDEP hVBDom = 0;
+static pdombase_t pVBDom = NULL;
+
+static HDEP hVBSearch = 0;
+static pdombase_t pVBSearch = NULL;
+static psearch_t pNameFirst = NULL;
+
+LOCAL pnode_t AddETConst (pnode_t, OFFSET, CV_typ_t);
+LOCAL pnode_t AddETExpr (pnode_t, CV_typ_t, OFFSET, OFFSET, CV_typ_t);
+LOCAL pnode_t AddETInit (pnode_t, CV_typ_t);
+LOCAL bool_t AddHSYM (psearch_t, HSYM, PHSL_HEAD, uint);
+LOCAL SCN_t AddVBList (psymclass_t, pdombase_t *, HDEP *);
+LOCAL SCN_t AddVBType (pdombase_t *, HDEP *, CV_typ_t);
+LOCAL ushort AmbFromList (psearch_t);
+LOCAL bool_t AmbToList (psearch_t);
+LOCAL HR_t ClAmbToList (psearch_t);
+LOCAL bool_t DebLoadConst (peval_t, CONSTPTR, HSYM);
+LOCAL SCN_t DupSymCl (psearch_t);
+LOCAL SCN_t FindIntro (psearch_t);
+LOCAL SCN_t GenQualExpr (psearch_t);
+LOCAL HDEP GenQualName (psearch_t, psymclass_t);
+LOCAL bool_t GrowTMList (void);
+LOCAL SCN_t IncrSymBase (void);
+LOCAL bool_t InitMod (psearch_t);
+LOCAL DOM_t IsDominated (psymclass_t, psymclass_t);
+LOCAL bool_t IsIntroVirt (ushort, CV_typ_t, ushort *);
+LOCAL bool_t LineNumber (psearch_t);
+LOCAL void MatchArgs (peval_t, psearch_t, CV_fldattr_t, UOFFSET, bool_t);
+LOCAL HR_t __fastcall MatchFunction (psearch_t);
+LOCAL void MoveSymCl (HDEP hSymCl);
+LOCAL SCN_t OverloadToAmbList (psearch_t, psymclass_t);
+LOCAL SCN_t MethodsToAmbList (psearch_t, psymclass_t);
+LOCAL bool_t ParseRegister (psearch_t);
+LOCAL void PurgeAmbCl (psearch_t);
+LOCAL SCN_t RecurseBase (psearch_t, CV_typ_t, CV_typ_t, OFFSET, OFFSET, CV_fldattr_t, bool_t);
+LOCAL SCN_t RemoveAmb (psearch_t);
+LOCAL SCN_t SearchBases (psearch_t);
+LOCAL SCN_t SearchBType (psearch_t);
+LOCAL SCN_t SearchClassName (psearch_t);
+LOCAL bool_t SearchQualName (psearch_t, psymclass_t, HDEP, bool_t);
+LOCAL SCN_t SearchRoot (psearch_t);
+LOCAL SCN_t SetBase (psearch_t, CV_typ_t, CV_typ_t, OFFSET, OFFSET, CV_fldattr_t, bool_t);
+LOCAL SCN_t SetBPValue (psearch_t);
+LOCAL SCN_t SetValue (psearch_t);
+LOCAL HR_t SymAmbToList (psearch_t);
+LOCAL bool_t SymToNode (psearch_t);
+LOCAL bool_t VBSearched (CV_typ_t);
+LOCAL bool_t VBaseFound (psearch_t);
+
+LOCAL CV_typ_t SkipModifiers(HMOD, CV_typ_t);
+LOCAL bool_t CheckDupAmb ( psearch_t );
+
+LOCAL bool_t __fastcall InsertThis (psearch_t);
+LOCAL MTH_t MatchMethod (psearch_t, psymclass_t);
+
+__inline BOOL
+getBaseDefnFromDecl(
+ CV_typ_t typeIn,
+ peval_t pv,
+ CV_typ_t* ptypeOut)
+{
+ peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
+ Unreferenced (pv);
+ return getDefnFromDecl (typeIn, pvBase, ptypeOut);
+}
+
+__inline unsigned char
+SkipPad(
+ unsigned char *pb)
+{
+
+ if (*pb >= LF_PAD0) {
+ // there is a pad field
+ return(*pb & 0x0f);
+ }
+
+ return(0);
+}
+
+OPNAME OpName[] = {
+ {"\x004""this"}, // OP_this
+ {"\x00b""operator->*"}, // OP_Opmember
+ {"\x00b""operator>>="}, // OP_Orightequal
+ {"\x00b""operator<<="}, // OP_Oleftequal
+ {"\x00a""operator()"}, // OP_Ofunction
+ {"\x00a""operator[]"}, // OP_Oarray
+ {"\x00a""operator+="}, // OP_Oplusequal
+ {"\x00a""operator-="}, // OP_Ominusequal
+ {"\x00a""operator*="}, // OP_Otimesequal
+ {"\x00a""operator/="}, // OP_Odivequal
+ {"\x00a""operator%="}, // OP_Opcentequal
+ {"\x00a""operator&="}, // OP_Oandequal
+ {"\x00a""operator^="}, // OP_Oxorequal
+ {"\x00a""operator|="}, // OP_Oorequal
+ {"\x00a""operator<<"}, // OP_Oshl
+ {"\x00a""operator>>"}, // OP_Oshr
+ {"\x00a""operator=="}, // OP_Oequalequal
+ {"\x00a""operator!="}, // OP_Obangequal
+ {"\x00a""operator<="}, // OP_Olessequal
+ {"\x00a""operator>="}, // OP_Ogreatequal
+ {"\x00a""operator&&"}, // OP_Oandand
+ {"\x00a""operator||"}, // OP_Ooror
+ {"\x00a""operator++"}, // OP_Oincrement
+ {"\x00a""operator--"}, // OP_Odecrement
+ {"\x00a""operator->"}, // OP_Opointsto
+ {"\x009""operator+"}, // OP_Oplus
+ {"\x009""operator-"}, // OP_Ominus
+ {"\x009""operator*"}, // OP_Ostar
+ {"\x009""operator/"}, // OP_Odivide
+ {"\x009""operator%"}, // OP_Opercent
+ {"\x009""operator^"}, // OP_Oxor
+ {"\x009""operator&"}, // OP_Oand
+ {"\x009""operator|"}, // OP_Oor
+ {"\x009""operator~"}, // OP_Otilde
+ {"\x009""operator!"}, // OP_Obang
+ {"\x009""operator="}, // OP_Oequal
+ {"\x009""operator<"}, // OP_Oless
+ {"\x009""operator>"}, // OP_Ogreater
+ {"\x009""operator,"}, // OP_Ocomma
+ {"\x012""operator new"}, // OP_Onew
+ {"\x015""operator delete"} // OP_Odelete
+};
+
+extern char Suffix;
+
+// Symbol searching and search initialization routines
+
+/** InitSearchBase - initialize search for base class
+ *
+ * InitSearchBase (bnOp, typD, typ, pName, pv)
+ *
+ * Entry bnOp = based pointer to OP_cast node
+ * bn = based pointer to cast string
+ * typD = type of derived class
+ * typB = type of desired base class
+ * pName = pointer to symbol search structure
+ * pv = pointer to value node
+ *
+ * Exit search structure initialized for SearchSym
+ *
+ * Returns pointer to search symbol structure
+ */
+
+
+void
+InitSearchBase (
+ bnode_t bnOp,
+ CV_typ_t typD,
+ CV_typ_t typB,
+ psearch_t pName,
+ peval_t pv
+ )
+{
+ // set starting context for symbol search to current context
+
+ _fmemset (pName, 0, sizeof (*pName));
+ pName->initializer = INIT_base;
+ pName->pv = pv;
+ pName->typeIn = typD;
+ pName->typeOut = typB;
+ pName->scope = SCP_class;
+ pName->CXTT = *pCxt;
+ pName->bn = 0;
+ pName->bnOp = bnOp;
+ pName->state = SYM_bclass;
+ pName->CurClass = typD;
+}
+
+
+
+
+/** InitSearchtDef - initialize typedef symbol search
+ *
+ * InitSearctDef (pName, iClass, tDef, scope, clsmask)
+ *
+ * Entry iClass = initial class if explicit class reference
+ * tDef = index of typedef
+ * scope = mask describing scope of search
+ * clsmask = mask describing permitted class elements
+ *
+ * Exit search structure initialized for SearchSym
+ *
+ * Returns pointer to search symbol structure
+ */
+
+
+void
+InitSearchtDef (
+ psearch_t pName,
+ peval_t pv,
+ ushort scope
+ )
+{
+ char NullString = 0;
+
+ // set starting context for symbol search to current context
+
+ _fmemset (pName, 0, sizeof (*pName));
+ pName->initializer = INIT_tdef;
+ pName->sstr.lpName = &NullString;
+ pName->sstr.cb = 0;
+ pName->pfnCmp = TDCMP;
+ pName->scope = scope;
+ pName->CXTT = *pCxt;
+ pName->pv = pv;
+ pName->typeIn = EVAL_TYP (pv);
+ pName->sstr.searchmask |= SSTR_symboltype | SSTR_NoHash;
+ pName->sstr.symtype = S_UDT;
+ pName->state = SYM_init;
+}
+
+
+
+
+/** SearchCFlag - initialize compile flags symbol search
+ *
+ * SearchCFlag (pName, iClass, scope, clsmask)
+ *
+ * Entry pName = pointer to symbol search structure
+ *
+ * Exit search structure initialized for SearchSym
+ *
+ * Returns pointer to search symbol structure
+ */
+
+
+HSYM
+SearchCFlag (
+ void
+ )
+{
+ search_t Name;
+ CXT CXTTOut;
+
+ // set starting context for symbol search to current context
+
+ _fmemset (&Name, 0, sizeof (Name));
+ Name.pfnCmp = CSCMP;
+ Name.CXTT = *pCxt;
+ Name.sstr.searchmask |= SSTR_symboltype;
+ Name.sstr.symtype = S_COMPILE;
+ if (InitMod (&Name) == TRUE) {
+ SHGetCxtFromHmod (Name.hMod, &Name.CXTT);
+ if ((Name.hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
+ (LPSSTR)&Name, pExState->state.fCase,
+ Name.pfnCmp,
+ &CXTTOut)) != 0) {
+ return (Name.hSym);
+ }
+ }
+ // error in context initialization or compile flag symbol not found
+ return (0);
+}
+
+
+
+
+/** SetAmbiant - set ambiant code or data model
+ *
+ * mode = SetAmbiant (flag)
+ *
+ * Entry flag = TRUE if ambiant data model
+ * flag = FALSE if ambiant code model
+ *
+ * Exit none
+ *
+ * Returns ambiant model C7_... from the compile flags symbol
+ * if the compile flags symbol is not found, C7_NEAR is returned
+ */
+
+
+CV_ptrmode_e
+SetAmbiant (
+ bool_t isdata
+ )
+{
+ HSYM hCFlag;
+ CFLAGPTR pCFlag;
+ CV_ptrmode_e mode;
+
+ Unreferenced( isdata );
+
+ if ((hCFlag = SearchCFlag ()) == 0) {
+ // compile flag symbol not found, set model to near
+ mode = (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) ? CV_PTR_NEAR32 : CV_PTR_NEAR;
+ }
+ else {
+ pCFlag = MHOmfLock ((HDEP)hCFlag);
+ switch (pCFlag->flags.ambdata) {
+ default:
+ DASSERT (FALSE);
+ case CV_CFL_DNEAR:
+ // NOTENOTE Compiler is always sending us this one...
+ // convert it to something appropriate sounding.
+ mode = (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) ? CV_PTR_NEAR32 : CV_PTR_NEAR;
+ break;
+
+ case CV_CFL_DFAR:
+ mode = CV_PTR_FAR;
+ break;
+
+ case CV_CFL_DHUGE:
+ mode = CV_PTR_HUGE;
+ break;
+ }
+ MHOmfUnLock ((HDEP)hCFlag);
+ }
+ return (mode);
+}
+
+
+
+
+/** GetHSYMList - get HSYM list for context
+ *
+ * status = EEGetHSYMList (phSYMl, pCXT, mask, pRE, fEnableProlog)
+ *
+ * Entry phSYML = pointer to handle to symbol list
+ * pCXT = pointer to context
+ * mask = selection mask
+ * pRE = pointer to regular expression
+ * fEnableProlog = FALSE if function scoped symbols only after prolog
+ * fEnableProlog = TRUE if function scoped symbols during prolog
+ *
+ * Exit *phMem = handle for HSYM list buffer
+ *
+ * Returns EENOERROR if no error
+ * status code if error
+ */
+
+
+EESTATUS
+GetHSYMList (
+ HDEP *phSYML,
+ PCXT pCxt,
+ ushort mask,
+ uchar *pRE,
+ SHFLAG fEnableProlog
+ )
+{
+ search_t Name = {0};
+ CXT CXTTOut;
+ HSYM hSym = 0;
+ PHSL_HEAD pHSLHead;
+ HSYML_t state;
+ HSL_restart_t *pRestart;
+ bool_t fRestart;
+ bool_t isprolog;
+ bool_t fCaseSensitive = TRUE;
+
+ if (mask & HSYMR_nocase) {
+ mask &= ~HSYMR_nocase;
+ fCaseSensitive = FALSE;
+ }
+
+ if (*phSYML == 0) {
+ // allocate and initialize buffer
+
+ if ((*phSYML = MHMemAllocate (HSYML_SIZE)) == 0) {
+ return (EECATASTROPHIC);
+ }
+ pHSLHead = MHMemLock (*phSYML);
+ _fmemset (pHSLHead, 0, HSYML_SIZE);
+ pHSLHead->size = HSYML_SIZE;
+ pHSLHead->blockcnt = 1;
+ pHSLHead->remaining = HSYML_SIZE - sizeof ( HSL_HEAD );
+ pHSLHead->pHSLList = (PHSL_LIST)(((uchar *)pHSLHead) + sizeof (HSL_HEAD));
+ state = HSYML_lexical;
+ Name.initializer = INIT_RE;
+ Name.pfnCmp = FNCMP;
+ Name.sstr.searchmask |= SSTR_RE;
+ Name.CXTT = *pCxt;
+ Name.hMod = pCxt->hMod;
+ if ( pCxt->hMod ) {
+ Name.hExe = SHHexeFromHmod ( pCxt->hMod );
+ }
+ else {
+
+ // not valid to call SHHexeFromHmod with an Hmod of 0,
+ // so set Hexe explicitly
+ Name.hExe = 0;
+ }
+ if ( pRE && *pRE ) {
+ Name.sstr.pRE = pRE;
+ }
+ fRestart = FALSE;
+ }
+ else {
+ pHSLHead = MHMemLock (*phSYML);
+ pRestart = MHMemLock (pHSLHead->restart);
+ Name = pRestart->Name;
+ mask = pRestart->mask;
+ state = pRestart->state;
+ hSym = pRestart->hSym;
+ pHSLHead->blockcnt = 1;
+ pHSLHead->symbolcnt = 0;
+ pHSLHead->remaining = HSYML_SIZE - sizeof ( HSL_HEAD );
+ pHSLHead->pHSLList = (PHSL_LIST)(((uchar *)pHSLHead) + sizeof (HSL_HEAD));
+ MHMemUnLock (pHSLHead->restart);
+ _fmemset ((uchar *)pHSLHead + sizeof (HSL_HEAD), 0,
+ HSYML_SIZE - sizeof (HSL_HEAD));
+ AddHSYM (&Name, hSym, pHSLHead, state);
+ fRestart = TRUE;
+ Name.hSym = hSym;
+ }
+ switch (state) {
+ case HSYML_lexical:
+ if (mask & HSYMR_lexical) {
+ // search up the lexical scope to but not including the
+ // function level
+
+ while (SHIsCXTBlk (&Name.CXTT)) {
+ while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
+ (LPSSTR)&Name, fCaseSensitive, FNCMP, &CXTTOut)) != 0) {
+ if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_lexical) == FALSE) {
+ goto hsyml_exit;
+ }
+ Name.hSym = hSym;
+ }
+
+ // go to the parent scope
+
+ SHGoToParent (&Name.CXTT, &CXTTOut);
+ // reset current symbol
+ Name.CXTT = CXTTOut;
+ Name.hSym = 0;
+ }
+ mask &= ~HSYMR_lexical;
+ }
+
+ case HSYML_function:
+ if (mask & HSYMR_function) {
+ if (fRestart == FALSE) {
+ Name.hSym = 0;
+ Name.CXTT.hBlk = 0;
+ }
+ fRestart = FALSE;
+ state = HSYML_function;
+
+ if ( Name.CXTT.hMod != 0 ) {
+ isprolog = SHIsInProlog (&Name.CXTT);
+ }
+ while (!SHIsCXTMod (&Name.CXTT) && Name.CXTT.hMod != 0) {
+ while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
+ (LPSSTR)&Name, fCaseSensitive, FNCMP, &CXTTOut)) != 0) {
+ if ((isprolog == TRUE) && (fEnableProlog == FALSE)) {
+ // we want to reject bp_relative and register
+ // stuff if we are in the prolog or epilog of
+ // a function
+
+ if ((Name.lastsym != S_BPREL16) &&
+ (Name.lastsym != S_BPREL32) &&
+ (Name.lastsym != S_REGISTER)) {
+ if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_function) == FALSE) {
+ goto hsyml_exit;
+ }
+ }
+ }
+ else {
+ if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_function) == FALSE) {
+ goto hsyml_exit;
+ }
+ }
+ Name.hSym = hSym;
+ }
+
+ // go to the parent scope
+
+ SHGoToParent (&Name.CXTT, &CXTTOut);
+ // reset current symbol
+ Name.CXTT = CXTTOut;
+ Name.hSym = 0;
+ }
+ mask &= ~HSYMR_function;
+ }
+
+
+ case HSYML_class:
+ if (mask & HSYMR_class) {
+ if (fRestart == FALSE) {
+ Name.hSym = 0;
+ if (ClassImp != 0) {
+ Name.CurClass = ClassImp;
+ }
+ }
+ fRestart = FALSE;
+
+ if ((Name.CurClass != 0)) {
+ DASSERT (FALSE);
+ // need to do equivalent of EEGetChild on this
+ }
+ mask &= ~HSYMR_class;
+ }
+
+ case HSYML_module:
+ if (mask & HSYMR_module) {
+ if (fRestart == FALSE) {
+ SHGetCxtFromHmod (Name.hMod, &Name.CXTT);
+ Name.hSym = 0;
+ }
+ fRestart = FALSE;
+ Name.state = HSYML_module;
+ while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
+ (LPSSTR)&Name, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) {
+ if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_module) == FALSE) {
+ goto hsyml_exit;
+ }
+ Name.hSym = hSym;
+ }
+ mask &= ~HSYMR_module;
+ }
+
+ case HSYML_global:
+ // search global symbol table
+ if (mask & HSYMR_global) {
+ if (fRestart == FALSE) {
+ Name.hSym = 0;
+ }
+ fRestart = FALSE;
+ Name.state = HSYML_global;
+ Name.sstr.searchmask |= SSTR_NoHash;
+ while ((hSym = SHFindNameInGlobal (Name.hSym, &Name.CXTT,
+ (LPSSTR)&Name, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) {
+ if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_global) == FALSE) {
+ goto hsyml_exit;
+ }
+ Name.hSym = hSym;
+ }
+ mask &= ~HSYMR_global;
+ }
+
+ case HSYML_exe:
+ if (mask & HSYMR_exe) {
+ Name.state = HSYML_exe;
+ if (fRestart == FALSE) {
+ Name.hModCur = SHGetNextMod (Name.hExe, Name.hMod);
+ Name.hSym = 0;
+ }
+ fRestart = FALSE;
+ Name.sstr.searchmask |= SSTR_NoHash;
+ do {
+ if (SHGetCxtFromHmod (Name.hModCur, &Name.CXTT)) {
+ while ((hSym = SHFindNameInContext (Name.hSym,
+ &Name.CXTT,
+ (LPSSTR)&Name,
+ fCaseSensitive,
+ Name.pfnCmp,
+ &CXTTOut)
+ ) != 0)
+ {
+ if (AddHSYM (&Name,
+ hSym,
+ pHSLHead,
+ HSYMR_exe)
+ == FALSE)
+ {
+ goto hsyml_exit;
+ }
+ Name.hSym = hSym;
+ }
+ }
+ } while (Name.hSym = 0,
+ (Name.hModCur = SHGetNextMod (Name.hExe, Name.hModCur)) != Name.hMod);
+ mask &= ~HSYMR_exe;
+ }
+
+ case HSYML_public:
+ if (mask & HSYMR_public && Name.hExe) {
+ if (fRestart == FALSE) {
+ hSym = 0;
+ }
+ fRestart = FALSE;
+ Name.state = HSYML_public;
+ Name.sstr.searchmask |= SSTR_NoHash;
+ while ((hSym = PHFindNameInPublics (hSym, Name.hExe,
+ (LPSSTR)&Name, fCaseSensitive, Name.pfnCmp)) != 0) {
+ if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_public) == FALSE) {
+ goto hsyml_exit;
+ }
+ Name.hSym = hSym;
+ }
+ mask &= ~HSYMR_public;
+ }
+ }
+ pHSLHead->status.endsearch = TRUE;
+ MHMemUnLock (*phSYML);
+ return (EENOERROR);
+
+hsyml_exit:
+ if (pHSLHead->restart == 0) {
+ // allocate restart buffer
+
+ if ((pHSLHead->restart = MHMemAllocate (sizeof (HSL_restart_t))) == 0) {
+ pHSLHead->status.fatal = TRUE;
+ MHMemUnLock (*phSYML);
+ return (EENOMEMORY);
+ }
+ }
+ pRestart = MHMemLock (pHSLHead->restart);
+ pRestart->Name = Name;
+ pRestart->mask = mask;
+ pRestart->state = state;
+ pRestart->hSym = hSym;
+ MHMemUnLock (pHSLHead->restart);
+ MHMemUnLock (*phSYML);
+ return (EENOERROR);
+}
+
+
+
+
+LOCAL bool_t
+AddHSYM (
+ psearch_t pName,
+ HSYM hSym,
+ PHSL_HEAD pHSLHead,
+ uint request
+ )
+{
+ PHSL_LIST pHSLList;
+
+ pHSLList = pHSLHead->pHSLList;
+
+ // check usability of current block
+
+ if (pHSLList->status.isused == TRUE) {
+ // block has been used, check for same context
+
+ if (_fmemcmp (&pHSLList->Cxt, &pName->CXTT, sizeof (CXT)) != 0) {
+ // context has changed
+
+ pHSLList->status.complete = TRUE;
+ pHSLHead->pHSLList = (PHSL_LIST)((uchar *)pHSLList +
+ sizeof ( HSL_LIST ) +
+ pHSLList->symbolcnt * sizeof ( HSYM ) );
+ pHSLList = pHSLHead->pHSLList;
+ pHSLHead->blockcnt++;
+ }
+ }
+ if (pHSLList->status.hascxt == FALSE) {
+ if (pHSLHead->remaining < (sizeof (HSL_LIST) + sizeof (HSYM))) {
+ return (FALSE);
+ }
+ pHSLHead->remaining -= sizeof (HSL_LIST);
+ pHSLList->status.hascxt = TRUE;
+ pHSLList->Cxt = pName->CXTT;
+ pHSLList->request = (ushort) request;
+ }
+ if (pHSLHead->remaining < sizeof (HSYM)) {
+ return (FALSE);
+ }
+ pHSLList->status.isused = TRUE;
+ pHSLList->hSym[pHSLList->symbolcnt++] = hSym;
+ pHSLHead->remaining -= sizeof (HSYM);
+ return (TRUE);
+}
+
+
+
+// search for the base sym of the base pointer
+//
+// Entry pName = structure describing the base pointer name
+//
+// Exit pName.eval reflects the bound base info
+//
+// Returns HR_ if base sym found
+
+HR_t
+SearchBasePtrBase (
+ psearch_t pName
+ )
+{
+ search_t lName = *pName;
+ plfPointer pType;
+ SYMPTR pSym;
+ unsigned short lrectyp;
+ eval_t eval;
+ peval_t lpv = &eval;
+ ushort savefEProlog = pExState->state.fEProlog;
+ HR_t retval = HR_notfound;
+
+ pExState->state.fEProlog = TRUE; // KLUDGE to get around CXT complications
+ eval = *pName->pv;
+ CLEAR_EVAL_FLAGS (lpv);
+ // an enregistered primitive
+ EVAL_IS_REG (lpv) = EVAL_IS_REG(pName->pv);
+ EVAL_IS_BPREL (lpv) = EVAL_IS_BPREL(pName->pv);
+ lName.hSym = 0; // start search at beginning of CXT
+ lName.pv = lpv;
+ DASSERT(!CV_IS_PRIMITIVE (EVAL_TYP(lpv)));
+ DASSERT (EVAL_MOD (lpv) != 0);
+
+ EVAL_TYPDEF (lpv) = THGetTypeFromIndex (EVAL_MOD (lpv), EVAL_TYP(lpv));
+ DASSERT (EVAL_TYPDEF (lpv) != 0);
+
+ _fmemset (&lpv->data, 0, sizeof (lpv->data));
+ pType = (plfPointer)(&((TYPPTR)(MHOmfLock (EVAL_TYPDEF(lpv))))->leaf);
+ DASSERT(pType->leaf == LF_POINTER);
+ DASSERT((pType->attr.ptrtype >= CV_PTR_BASE_VAL) &&
+ (pType->attr.ptrtype <= CV_PTR_BASE_SEGADDR));
+
+ pSym = (SYMPTR)(&((plfPointer)pType)->pbase.Sym);
+ PTR_BSYMTYPE (pName->pv) = pSym->rectyp;
+ emiAddr (PTR_ADDR (pName->pv)) = pCxt->addr.emi;
+
+ switch (pSym->rectyp) {
+ case S_BPREL16:
+ lName.sstr.lpName = &((BPRELPTR16)pSym)->name[1];
+ lName.sstr.cb = ((BPRELPTR16)pSym)->name[0];
+ if (SearchSym(&lName) != HR_found) {
+ goto ReturnNotFound;;
+ }
+ PopStack();
+ SetAddrSeg (&PTR_ADDR (pName->pv), 0);
+ pSym = (SYMPTR)MHOmfLock(lName.hSym);
+ if (((BPRELPTR16)pSym)->rectyp == S_BPREL16) {
+ SetAddrOff (&PTR_ADDR (pName->pv), ((BPRELPTR16)pSym)->off);
+ ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = FALSE;
+ ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = FALSE;
+ ADDR_IS_LI (PTR_ADDR (pName->pv)) = FALSE;
+ PTR_STYPE (pName->pv) = ((BPRELPTR16)pSym)->typind;
+ }
+ else {
+ goto ReturnNotFound;;
+ }
+ pExState->state.bprel = TRUE;
+ break;
+
+ case S_LDATA16:
+ case S_GDATA16:
+ lName.sstr.lpName = &((DATAPTR16)pSym)->name[1];
+ lName.sstr.cb = ((DATAPTR16)pSym)->name[0];
+ lrectyp = pSym->rectyp;
+ do {
+ if (SearchSym(&lName) != HR_found) {
+ goto ReturnNotFound;;
+ }
+ PopStack();
+ pSym = (SYMPTR)MHOmfLock(lName.hSym);
+ } while (pSym->rectyp != lrectyp);
+ pExState->state.fLData = TRUE;
+ SetAddrSeg (&PTR_ADDR (pName->pv), ((DATAPTR16)pSym)->seg);
+ SetAddrOff (&PTR_ADDR (pName->pv), ((DATAPTR16)pSym)->off);
+ ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = FALSE;
+ ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = FALSE;
+ ADDR_IS_LI (PTR_ADDR (pName->pv)) = TRUE;
+ PTR_STYPE (pName->pv) = ((DATAPTR16)pSym)->typind;
+ break;
+
+ case S_BPREL32:
+ lName.sstr.lpName = &((BPRELPTR32)pSym)->name[1];
+ lName.sstr.cb = ((BPRELPTR32)pSym)->name[0];
+ if (SearchSym(&lName) != HR_found) {
+ goto ReturnNotFound;;
+ }
+ PopStack();
+ SetAddrSeg (&PTR_ADDR (pName->pv), 0);
+ if (((BPRELPTR32)pSym)->off != 0) {
+ SetAddrOff (&PTR_ADDR (pName->pv), ((BPRELPTR32)pSym)->off);
+ ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = TRUE;
+ ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = TRUE;
+ ADDR_IS_LI (PTR_ADDR (pName->pv)) = FALSE;
+ PTR_STYPE (pName->pv) = ((BPRELPTR32)pSym)->typind;
+ }
+ else {
+ goto ReturnNotFound;;
+ }
+ pExState->state.bprel = TRUE;
+ break;
+
+ case S_LDATA32:
+ case S_GDATA32:
+ case S_LTHREAD32:
+ case S_GTHREAD32:
+ lName.sstr.lpName = &((DATAPTR32)pSym)->name[1];
+ lName.sstr.cb = ((DATAPTR32)pSym)->name[0];
+ lrectyp = pSym->rectyp;
+ do {
+ if (SearchSym(&lName) != HR_found) {
+ goto ReturnNotFound;;
+ }
+ PopStack();
+ pSym = (SYMPTR)MHOmfLock(lName.hSym);
+ } while (pSym->rectyp != lrectyp);
+ pExState->state.fLData = TRUE;
+ SetAddrSeg (&PTR_ADDR (pName->pv), ((DATAPTR32)pSym)->seg);
+ SetAddrOff (&PTR_ADDR (pName->pv), ((DATAPTR32)pSym)->off);
+ ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = TRUE;
+ ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = TRUE;
+ ADDR_IS_LI (PTR_ADDR (pName->pv)) = TRUE;
+ PTR_STYPE (pName->pv) = ((DATAPTR32)pSym)->typind;
+ break;
+
+ case S_REGISTER:
+ break;
+
+ default:
+ DASSERT(FALSE);
+ break;
+ }
+ retval = HR_found;
+
+ReturnNotFound:
+ pExState->state.fEProlog = savefEProlog;
+ return(retval);
+}
+
+
+/** SearchSym - search for symbol
+ *
+ * status = SearchSym (pName)
+ *
+ * Entry pName = structure describing state of search
+ *
+ * Exit pName updated to reflect search results
+ * pName->hSym = handle of symbol
+ * pName->CXTT = context of symbol
+ *
+ * Returns HR_... enum specifying search result
+ */
+
+
+HR_t
+SearchSym (
+ psearch_t pName
+ )
+{
+ CXT CXTTOut;
+ HSYM hSym = 0;
+ bool_t isprolog;
+ SCN_t retval;
+
+ char NameNew[ 256 ];
+ LPB NameOld = ((LPSSTR) pName)->lpName;
+ unsigned char cbNew;
+ unsigned char cbOld = ((LPSSTR) pName)->cb;
+ BOOL SearchWithSuffix;
+
+ // NOTE: this routine may be called recursively through MatchFunction
+
+ if ((hBPatch != 0) && (pExState->ambiguous != 0) &&
+ (pExState->ambiguous == pName->bn)) {
+ // this is a request for a symbol that was previously found to
+ // be ambiguous. Pop the next ambiguous symbol off the list and
+ // return it to the caller.
+
+ return (AmbFromList (pName));
+ }
+
+ // If we encounter a lone '.', handle as the CUR PC operator (for any platform).
+
+ if ((pName->sstr.cb == 1 ) &&
+ *(pName->sstr.lpName) == '.') {
+
+
+ EVAL_STATE( pName->pv ) = EV_rvalue;
+ EVAL_TYP( pName->pv ) = T_PCHAR;
+ EVAL_IS_PTR( pName->pv ) = TRUE;
+ EVAL_IS_CURPC( pName->pv ) = TRUE;
+
+ PushStack (pName->pv);
+ return (HR_found);
+ }
+
+ SearchWithSuffix = ( Suffix && !(((LPSSTR)pName)->searchmask & SSTR_RE) );
+
+ if ( SearchWithSuffix ) {
+ cbNew = cbOld+1;
+ memcpy( NameNew, NameOld, cbOld );
+ NameNew[ cbOld ] = Suffix;
+ NameNew[ cbNew ] = '\0';
+ }
+
+
+
+ // this routine will terminate on the following conditions:
+ // 1. A symbol is found that is not a function address
+ // 2. A symbol is found that is a function and is not a method
+ // and the end of the symbol table is reached
+ // 3. A symbol is found that is a method and the end of the
+ // inheritance tree for the class is reached.
+ // If BindingBP is set, all function/method addresses that match
+ // the expression are entered into the TMList pointed to by pTMList
+
+ for (;;) {
+ switch (pName->state) {
+ case SYM_bclass:
+ // this state is a special entry for searching for the base
+ // class of a class when only the type of the base is known
+
+ if (InitMod (pName) == FALSE) {
+ // error in context
+ return (HR_notfound);
+ }
+ pName->state = SYM_class;
+ continue;
+
+ case SYM_init:
+ if (InitMod (pName) == FALSE) {
+
+ /*
+ * For line numbers (@linenumber) to be error
+ */
+
+ if ((pName->scope & ~SCP_class) &&
+ (*pName->sstr.lpName == '@') &&
+ (isdigit (*(pName->sstr.lpName + 1)))
+ ) {
+ return HR_notfound;
+ }
+
+ // error in context so we will allow check for registers
+ return (ParseRegister (pName));
+ }
+ if ((pName->scope & ~SCP_class) && *pName->sstr.lpName == '@') {
+ //search for @register, @linenumber, fastcall routine
+
+ if (isdigit (*(pName->sstr.lpName + 1))) {
+ return (LineNumber (pName));
+ }
+ else if ((hSym = PHFindNameInPublics ((HSYM) NULL,
+ pName->hExe, (LPSSTR)pName, pExState->state.fCase,
+ pName->pfnCmp)) != 0) {
+ goto found;
+ }
+ else if (ParseRegister (pName) == HR_found) {
+ return (HR_found);
+ }
+ else {
+ return (HR_notfound);
+ }
+ }
+ else if (*pName->sstr.lpName == 0xff) {
+ // search for handle to symbol. The handle to
+ // symbol comes from CV when a specific symbol
+ // is to be searched. The most common case is
+ // when a specific variable is to be displayed
+ // in the locals window
+
+ pName->sstr.lpName++;
+ hSym = *((HSYM UNALIGNED *)(pName->sstr.lpName));
+ goto found;
+ }
+ // start normal symbol search
+
+ pName->state = SYM_lexical;
+
+ case SYM_lexical:
+ if (pName->scope & SCP_lexical) {
+ // search up the lexical scope to the function level
+ // but do not search the module level because of the
+ // class search required for method functions
+
+ isprolog = SHIsInProlog (&pName->CXTT);
+ while (!SHIsCXTMod (&pName->CXTT) ) {
+
+ hSym = SHFindNameInContext (pName->hSym,
+ &pName->CXTT,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ FNCMP,
+ &CXTTOut);
+
+
+ if ( hSym ) {
+
+ if (isprolog && (pExState->state.fEProlog == FALSE)) {
+ // we want to reject bp_relative and register
+ // stuff if we are in the prolog or epilog of
+ // a function
+
+ // M00FLAT32 - need another check here
+ if ((pName->lastsym != S_BPREL16) &&
+ (pName->lastsym != S_BPREL32) &&
+ (pName->lastsym != S_REGISTER)) {
+ goto foundsave;
+ }
+ else {
+ // stop the search here: we have
+ // already found a symbol, but cannot
+ // evaluate it. --caviar #5898
+ pExState->err_num = ERR_NOSTACKFRAME;
+ return HR_error;
+ }
+ }
+ else {
+ goto foundsave;
+ }
+ }
+
+ // go to the parent scope
+
+ SHGoToParent (&pName->CXTT, &CXTTOut);
+ // reset current symbol
+ pName->hSym = 0;
+ pName->CXTT = CXTTOut;
+ }
+ }
+ pName->state = SYM_class;
+ if (pName->scope & SCP_class) {
+ if (pName->ExpClass != 0) {
+ // search an explicit class
+ pName->CurClass = pName->ExpClass;
+ }
+ else if (ClassImp != 0) {
+ pName->CurClass = ClassImp;
+ }
+ }
+
+ case SYM_class:
+ if ((pName->CurClass != 0) && (pName->scope & SCP_class)) {
+ retval = SearchClassName (pName);
+ switch (retval) {
+ case SCN_found:
+ // the symbol is a member of the class. If
+ // an explict class was not specified and
+ // the current context is implicitly a class,
+ // then we rewrote the tree to change the
+ // symbol reference to this->symbol
+
+ DASSERT (pName->hFound == 0);
+ DASSERT (pName->hAmbCl == 0);
+ if (EVAL_TYP (pName->pv) != T_NOTYPE) {
+ if (PushStack (pName->pv) == FALSE)
+ return (HR_error);
+ goto nopush;
+ }
+ else {
+ if (EVAL_IS_STMEMBER(pName->pv)) {
+ pExState->err_num = ERR_STATICNOOMF;
+ } else {
+ pExState->err_num = ERR_BADOMF;
+ }
+ return (HR_error);
+ }
+
+ case SCN_rewrite:
+ return (HR_rewrite);
+
+ case SCN_error:
+ return (HR_error);
+
+ default:
+ DASSERT (pName->hFound == 0);
+ DASSERT (pName->hAmbCl == 0);
+ if (pName->initializer == INIT_base) {
+ // we were searching for the base class of
+ // a class which was not found.
+
+ return (HR_notfound);
+ }
+ break;
+ }
+ }
+ SHGetCxtFromHmod (pName->hMod, &pName->CXTT);
+ pName->hSym = 0;
+ pName->state = SYM_module;
+
+ case SYM_module:
+ if (pName->scope & SCP_module) {
+ if ((hSym = SHFindNameInContext (pName->hSym, &pName->CXTT,
+ (LPSSTR)pName, pExState->state.fCase, pName->pfnCmp,
+ &CXTTOut)) != 0) {
+ goto foundsave;
+ }
+ }
+ pName->state = SYM_global;
+ pName->hSym = 0;
+
+ case SYM_global:
+ // users specified a context on a break point command
+ // we have already searched the module specified so end the search
+ // here
+ // sps - 7/24/92
+ if (pBindBPCxt && pBindBPCxt->hMod &&(pBindBPCxt->hMod != pName->hModCur) &&
+ (pExState->ambiguous != 0) && (pExState->ambiguous == pName->bn)) {
+
+ return(HR_end);
+ }
+
+ // search global symbol table
+ if (pName->scope & SCP_global) {
+ hSym = SHFindNameInGlobal( pName->hSym,
+ &pName->CXTT,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ pName->pfnCmp,
+ &CXTTOut);
+
+ if ( !hSym && SearchWithSuffix ) {
+
+ ((LPSSTR)pName)->lpName = NameNew;
+ ((LPSSTR)pName)->cb = cbNew;
+
+ hSym = SHFindNameInGlobal( pName->hSym,
+ &pName->CXTT,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ pName->pfnCmp,
+ &CXTTOut );
+
+ ((LPSSTR)pName)->lpName = NameOld;
+ ((LPSSTR)pName)->cb = cbOld;
+
+ }
+
+ if ( hSym ) {
+ goto foundsave;
+ }
+ }
+ pName->hModCur = SHGetNextMod (pName->hExe, pName->hMod);
+ pName->hSym = 0;
+ pName->state = SYM_exe;
+
+ case SYM_exe:
+ if (pName->scope & SCP_global) {
+
+ if (pName->hModCur == 0) {
+ pName->hModCur = SHGetNextMod(pName->hExe,
+ pName->hModCur);
+ }
+
+ while (pName->hModCur != pName->hMod) {
+ if (SHGetCxtFromHmod (pName->hModCur, &pName->CXTT)) {
+ hSym = SHFindNameInContext (pName->hSym,
+ &pName->CXTT,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ pName->pfnCmp,
+ &CXTTOut);
+
+ if ( !hSym && SearchWithSuffix ) {
+
+ ((LPSSTR)pName)->lpName = NameNew;
+ ((LPSSTR)pName)->cb = cbNew;
+
+ hSym = SHFindNameInContext (pName->hSym,
+ &pName->CXTT,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ pName->pfnCmp,
+ &CXTTOut);
+
+ ((LPSSTR)pName)->lpName = NameOld;
+ ((LPSSTR)pName)->cb = cbOld;
+ }
+
+ if ( hSym ) {
+ goto foundsave;
+ }
+ }
+
+ pName->hSym = 0;
+ pName->hModCur = SHGetNextMod (pName->hExe,
+ pName->hModCur);
+ if (pName->hModCur == 0) {
+ pName->hModCur = SHGetNextMod(pName->hExe,
+ pName->hModCur);
+ }
+ }
+ }
+ // we are at the end of the normal symbol search. If the
+ // symbol has not been found, we will search the public
+ // symbol table.
+
+ if (!BindingBP) {
+ // if we are not binding breakpoints and we have
+ // found a symbol in previous calls, return. Otherwise,
+ // we will look in the publics table. Note that
+ // finding a symbol in the publics table has a
+ // large probability of finding one with a type of
+ // zero which will limit it's usefulness
+
+ if (pName->hSym != 0) {
+ if (pName->possibles > 1) {
+ pExState->err_num = ERR_AMBIGUOUS;
+ return (HR_ambiguous);
+ }
+ return (HR_notfound);
+ }
+ }
+ else {
+ // we are binding breakpoints. We need to see if
+ // one or more symbols have matched. If so, we
+ // are done with the symbol search. If we have
+ // not found the symbol, we search the publics table.
+ // For breakpoints, we do not need type information,
+ // only the address, so symbols found in the publics
+ // table are much more useful.
+
+ if ((pExState->ambiguous != 0) &&
+ (pExState->ambiguous == pName->bn)) {
+ // we have found at least one symbol to this
+ // point. this is indicated by SymAmbToList
+ // setting the node of the function's symbol
+ // into the expression state structure. By
+ // this point all ambiguous symbols have been
+ // added to the back patch list. If we have
+ // not found any symbol yet, we search the
+ // publics table. Note also that there cannot
+ // be any ambiguity in the publics table because
+ // the function names have to be unique in the
+ // publics table.
+
+ return HR_end;
+
+ }
+ }
+
+ // search public symbol table
+ pName->state = SYM_public;
+
+ case SYM_public:
+ //
+ // some searches such as finding a UDT by type
+ // do not require a symbol
+ //
+ if (pName->scope & SCP_global) {
+ hSym = PHFindNameInPublics ( (HSYM)NULL,
+ pName->hExe,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ pName->pfnCmp);
+
+ if ( !hSym && SearchWithSuffix ) {
+
+ ((LPSSTR)pName)->lpName = NameNew;
+ ((LPSSTR)pName)->cb = cbNew;
+
+ hSym = PHFindNameInPublics ( (HSYM)NULL,
+ pName->hExe,
+ (LPSSTR)pName,
+ pExState->state.fCase,
+ pName->pfnCmp );
+
+ ((LPSSTR)pName)->lpName = NameOld;
+ ((LPSSTR)pName)->cb = cbOld;
+ }
+ if (!hSym) {
+ char rgch[256];
+
+ *rgch = '_';
+ strcpy(&rgch[1], NameOld);
+ ((LPSSTR)pName)->lpName = rgch;
+ ((LPSSTR)pName)->cb = cbOld + 1;
+
+ hSym = PHFindNameInPublics ( (HSYM)NULL,
+ pName->hExe,
+ (LPSSTR) pName,
+ pExState->state.fCase,
+ pName->pfnCmp );
+
+ if ( !hSym && SearchWithSuffix ) {
+
+ *rgch = '_';
+ strcpy(&rgch[1], NameNew);
+ ((LPSSTR)pName)->lpName = rgch;
+ ((LPSSTR)pName)->cb = cbNew + 1;
+
+ hSym = PHFindNameInPublics ( (HSYM)NULL,
+ pName->hExe,
+ (LPSSTR) pName,
+ pExState->state.fCase,
+ pName->pfnCmp );
+ }
+
+ //
+ // now look for fastcall names
+ //
+
+ if (!hSym) {
+ *rgch = '@';
+ strcpy(&rgch[1], NameOld);
+ ((LPSSTR)pName)->lpName = rgch;
+ ((LPSSTR)pName)->cb = cbOld + 1;
+
+ hSym = PHFindNameInPublics ( (HSYM)NULL,
+ pName->hExe,
+ (LPSSTR) pName,
+ pExState->state.fCase,
+ pName->pfnCmp );
+ }
+
+ ((LPSSTR)pName)->lpName = NameOld;
+ ((LPSSTR)pName)->cb = cbOld;
+ }
+ if ( hSym ) {
+
+ if (hSym == pName->hSym) {
+ // We found this symbol last call! There
+ // are no more to be found (or worth finding).
+ return HR_notfound;
+ }
+
+ goto foundsave;
+ }
+
+ }
+ if (EVAL_IS_REG (pName->pv)) {
+ return (HR_notfound); // found it last time - quite looking
+ }
+ else if ((pName->scope & ~SCP_class) && ParseRegister (pName) == HR_found) {
+ return (HR_found);
+ }
+
+ pExState->err_num = ERR_UNKNOWNSYMBOL;
+ return (HR_notfound);
+ }
+ }
+
+foundsave:
+ pName->CXTT = CXTTOut;
+found:
+ pName->hSym = hSym;
+ EVAL_HSYM (pName->pv) = pName->hSym;
+ if (pName->initializer == INIT_tdef) {
+ // the routines that search for UDTs only need the
+ // hsym and the stack pointer may not be valid at this
+ // point (FormatUDT for example), so return now
+
+ return (HR_found);
+ }
+ if (SymToNode (pName) == FALSE) {
+ return (HR_notfound);
+ }
+ if (PushStack (pName->pv) == FALSE)
+ return (HR_error);
+nopush:
+ if (!EVAL_IS_FCN (ST)) {
+ // if this symbol is not a function and we have not processed
+ // a function previously, then the search is done
+
+ if (pExState->ambiguous == 0) {
+ return (HR_found);
+ }
+ else if (pExState->ambiguous == pName->bn) {
+ pExState->err_num = ERR_SYMCONFLICT;
+ return (HR_error);
+ }
+ else {
+ return (HR_found);
+ }
+ }
+ else if (EVAL_IS_METHOD (ST)) {
+ // ambiguous methods were entered into the ambiguous breakpoint
+ // list by SetBPValue which was called in SearchClassName
+
+ return (HR_found);
+ }
+ else if (pName->state == SYM_public) {
+ // we will take the first function symbol found in the
+ // publics table since the names have to be unique in the
+ // publics table
+
+ return (HR_found);
+ }
+ else if ((BindingBP == TRUE) && (bArgList == 0)) {
+ // if we are binding breakpoints and there is not an
+ // argument list, we will enter all functions found with
+ // this name into the breakpoint ambiguity list.
+
+ return (SymAmbToList (pName));
+ }
+ else {
+ // the found symbol is non-member function. continue
+ // search to end of symbols to find the best function.
+ // in the case of a breakpoint with argument list, there
+ // must be an exact match on the argument types
+
+ EVAL_MOD (pName->pv) = SHHMODFrompCXT (&pName->CXTT);
+ if (pName->scope & SCP_nomatchfn)
+ return (HR_found);
+
+ return (MatchFunction (pName));
+ }
+}
+
+
+
+
+LOCAL bool_t
+InitMod (
+ psearch_t pName
+ )
+{
+ if (((pName->hMod = SHHMODFrompCXT (&pName->CXTT)) == 0) ||
+ ((pName->hExe = SHHexeFromHmod (pName->hMod)) == 0)) {
+ // error in context
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+// Class searching and main support routines
+
+
+
+
+/*** SearchClassName - Search a class and bases for element by name
+ *
+ * flag = SearchClassName (pName)
+ *
+ * Entry pName = pointer to struct describing search
+ *
+ * Exit pName updated to reflect type
+ *
+ * Returns SCN_... enum describing result
+ */
+
+
+LOCAL SCN_t
+SearchClassName (
+ psearch_t pName
+ )
+{
+ SCN_t retval;
+ ushort max;
+ CV_fldattr_t attr = {0};
+
+ // allocate and initialize list of dominated virtual bases
+
+ if (hVBDom == 0) {
+ if ((hVBDom = MHMemAllocate (sizeof (dombase_t) +
+ DOMBASE_DEFAULT * sizeof (CV_typ_t))) == 0) {
+ pExState->err_num == ERR_NOMEMORY;
+ return (SCN_error);
+ }
+ pVBDom = MHMemLock (hVBDom);
+ pVBDom->MaxIndex = DOMBASE_DEFAULT;
+ }
+ else {
+ pVBDom = MHMemLock (hVBDom);
+ }
+ pVBDom->CurIndex = 0;
+
+ // allocate and initialize list of searched virtual bases
+
+ if (hVBSearch == 0) {
+ if ((hVBSearch = MHMemAllocate (sizeof (dombase_t) +
+ DOMBASE_DEFAULT * sizeof (CV_typ_t))) == 0) {
+ pExState->err_num == ERR_NOMEMORY;
+ MHMemUnLock (hVBDom);
+ return (SCN_error);
+ }
+ pVBSearch = MHMemLock (hVBSearch);
+ pVBSearch->MaxIndex = DOMBASE_DEFAULT;
+ }
+ else {
+ pVBSearch = MHMemLock (hVBSearch);
+ }
+ pVBSearch->CurIndex = 0;
+
+ // allocate and initialize structure for recursive base searches
+
+ if (hSymClass == 0) {
+ if ((hSymClass = MHMemAllocate (sizeof (symclass_t) +
+ SYMBASE_DEFAULT * sizeof (symbase_t))) == 0) {
+ pExState->err_num == ERR_NOMEMORY;
+ MHMemUnLock (hVBDom);
+ MHMemUnLock (hVBSearch);
+ return (SCN_error);
+ }
+ pSymClass = MHMemLock (hSymClass);
+ pSymClass->MaxIndex = SYMBASE_DEFAULT;
+ }
+ else {
+ pSymClass = MHMemLock (hSymClass);
+ }
+ pSymClass->CurIndex = 0;
+ pSymClass->hNext = 0;
+ max = pSymClass->MaxIndex;
+ _fmemset (pSymClass, 0, max * sizeof (symbase_t) + sizeof (symclass_t));
+ pSymClass->MaxIndex = max;
+
+ // recurse through the inheritance tree searching for the feature
+
+ if ((retval = RecurseBase (pName, pName->CurClass, 0, 0, 0,
+ attr, FALSE)) != SCN_error) {
+ // at this point we need to check for dominance and then clean
+ // up the allocated memory and return the search results
+
+ if (pName->possibles == 0) {
+ // if the count was zero, the handle of found list must be zero
+ DASSERT (pName->hFound == 0);
+ retval = SCN_notfound;
+ }
+ else if (pName->cFound == 0) {
+ if (pName->hFound == 0) {
+ DASSERT (pSymClass->s.viable == TRUE);
+ // the found value is in the permanent stack. This means
+ // the feature was found in the most derived class
+ retval = SetValue (pName);
+ }
+ }
+ else if (pName->cFound == 1) {
+ // the feature was not found in the most derived class
+ // but no other matching feature was found. Move the feature
+ // descriptor pointed to by pName->hFound into the permanent
+ // feature descriptor pSymClass. An important thing to remember
+ // here is that there can only be one feature descriptor pSymClass
+ // when calling SetValue unless we are binding breakpoints.
+ // If we are binding breakpoints we can have multiple feature
+ // descriptors in pSymClass and the list pointed to by
+ // pName->hAmbCl. If we have an argument list, these must
+ // resolve to one feature. If we do not have an argument
+ // list, all of the features are valid and must be added
+ // to the breakpoint list.
+
+ MoveSymCl (pName->hFound);
+ pName->hFound = 0;
+ pName->cFound--;
+ DASSERT (pSymClass->s.viable == TRUE);
+ retval = SetValue (pName);
+ }
+ else {
+ // since two or more features were found, we need to cull the
+ // feature list to remove dominated features and features which
+ // are the same static item. Ambiguity is removed strictly on
+ // the name of the feature. Overloaded methods are resolved later.
+
+ if ((retval = RemoveAmb (pName)) == SCN_found) {
+ retval = SetValue (pName);
+ }
+ }
+ }
+ MHMemUnLock (hVBDom);
+ MHMemUnLock (hVBSearch);
+ MHMemUnLock (hSymClass);
+ DASSERT (pName->hAmbCl == 0);
+ return (retval);
+}
+
+
+
+
+/*** RecurseBase - Search a class and its bases for element by name
+ *
+ * status = RecurseBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual)
+ *
+ * Entry pName = pointer to struct describing search
+ * type = type index of class
+ * vbptr = type index of virtual base pointer
+ * vbpoff = offset of virtual base pointer from address point
+ * thisadjust = offset of base from previous class
+ * thisadjust = virtual base index if virtual base
+ * attr = attribute of base class
+ * virtual = TRUE if this is a virtual base
+ *
+ * Exit pName updated to reflect type
+ *
+ * Returns SCN_... enum describing result
+ */
+
+LOCAL SCN_t
+RecurseBase (
+ psearch_t pName,
+ CV_typ_t type,
+ CV_typ_t vbptr,
+ OFFSET vbpoff,
+ OFFSET thisadjust,
+ CV_fldattr_t attr,
+ bool_t virtual
+ )
+{
+ SCN_t retval;
+
+ // save offset of base from address point for this pointer adjustment
+
+ if (SetBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual) != SCN_found) {
+ return (SCN_error);
+ }
+ if (pName->initializer == INIT_base) {
+ retval = SearchBType (pName);
+ }
+ else {
+ retval = SearchRoot (pName);
+ }
+ switch (retval) {
+ case SCN_found:
+ if ((pName->clsmask & CLS_virtintro) == FALSE) {
+ // add virtual bases to searched and dominated base lists
+ // if we were searching for the introducing virtual function,
+ // the fact that we found one is sufficient.
+
+ if ((pSymClass->s.isvbase == TRUE) &&
+ (VBaseFound (pName) == TRUE)) {
+ // the found feature is a previously found
+ // virtual base class.
+
+ pSymClass->s.isdupvbase = TRUE;
+ }
+ if ((retval = AddVBList
+ (pSymClass, &pVBSearch, &hVBSearch)) != SCN_error) {
+ retval = AddVBList (pSymClass, &pVBDom, &hVBDom);
+ }
+ }
+
+ case SCN_error:
+ return (retval);
+
+ case SCN_notfound:
+ // we did not find the element in the root of this class
+ // so we search the inheritance tree.
+
+ if (pExState->state.fSupBase == FALSE) {
+ return (SearchBases (pName));
+ }
+ else {
+ return (SCN_notfound);
+ }
+
+ default:
+ return (SCN_error);
+ }
+}
+
+
+
+
+/** VBaseFound - search to see if virtual base already found
+ *
+ * status = VBaseFound (pName)
+ *
+ * Entry pName = structure describing search
+ * pSymClass = structure describing most recent class search
+ *
+ * Exit pName updated to reflect search
+ * pSymClass updated to unambiguous feature
+ *
+ * Returns TRUE if duplicate virtual base found
+ * FALSE if not duplicate virtual base
+ */
+
+
+LOCAL bool_t
+VBaseFound (
+ psearch_t pName
+ )
+{
+ psymclass_t pSymCl;
+ HDEP hSymCl;
+ CV_typ_t type = EVAL_TYP (&pSymClass->evalP);
+
+ hSymCl = pName->hFound;
+ while (hSymCl != 0) {
+ pSymCl = MHMemLock (hSymCl);
+ if (pSymCl == pSymClass) {
+ return (FALSE);
+ }
+ if ((pSymCl->s.isvbase == TRUE) && (type == EVAL_TYP (&pSymCl->evalP))) {
+ // the virtual base is already in the list
+ MHMemUnLock( hSymCl );
+ return (TRUE);
+ }
+ DASSERT( FALSE );
+ MHMemUnLock( hSymCl );
+ hSymCl = 0; // NOTENOTE -- jimsch -- was no linking to next
+ }
+ return (FALSE);
+}
+
+
+
+/** RemoveAmb - remove ambiguity
+ *
+ * status = RemoveAmb (pName)
+ *
+ * Entry pName = structure describing search
+ * pSymClass = structure describing most recent class search
+ *
+ * Exit pName updated to reflect search
+ * pSymClass updated to unambiguous feature
+ *
+ * Returns SCN_found if unambiguous feature found
+ * SCN_error otherwise
+ */
+
+
+LOCAL SCN_t
+RemoveAmb (
+ psearch_t pName
+ )
+{
+ psymclass_t pSymCl;
+
+ // we know that at this point two or more features were found
+ // the list of features are pointed to by pName->hFound.
+ // The permanent stack cannot contain a viable feature
+
+ DASSERT (pSymClass->s.viable == FALSE);
+ MoveSymCl (pName->hFound);
+ pName->hFound = pSymClass->hNext;
+ while (pName->hFound != 0) {
+ // lock and check next list element
+
+ pSymCl = MHMemLock (pName->hFound);
+ switch (IsDominated (pSymClass, pSymCl)) {
+ case DOM_ambiguous:
+ // the new feature does not dominate the current best
+ MHMemUnLock (pName->hFound);
+ if (BindingBP == FALSE) {
+ pExState->err_num = ERR_AMBIGUOUS;
+ return (SCN_error);
+ }
+ // feature is ambiguous and we are setting breakpoints
+ // save the feature in the ambiguous list and advance to
+ // the next feature
+
+ pSymClass->hNext = pSymCl->hNext;
+ pSymCl->hNext = pName->hAmbCl;
+ pName->hAmbCl = pName->hFound;
+ MHMemUnLock (pName->hAmbCl);
+ pName->hFound = pSymClass->hNext;
+ break;
+
+ case DOM_replace:
+ // decrement the number of possible matches by the
+ // count in the current best structure
+
+ pName->possibles -= pSymClass->possibles;
+ pName->cFound--;
+ MHMemUnLock (pName->hFound);
+ MoveSymCl (pName->hFound);
+ pName->hFound = pSymClass->hNext;
+ PurgeAmbCl (pName);
+ break;
+
+ case DOM_keep:
+ // decrement the number of possible matches by the
+ // count in the structure being discarded
+
+ pName->possibles -= pSymCl->possibles;
+ pName->cFound--;
+ pSymClass->hNext = pSymCl->hNext;
+ MHMemUnLock (pName->hFound);
+ pName->hFound = pSymClass->hNext;
+ break;
+ }
+ }
+ // decrement the count of found features to account for the one we kept
+ pName->cFound--;
+ return (SCN_found);
+}
+
+
+/*** SearchBases - Search for an element in the bases of a class
+ *
+ * flag = SearchBases (pName, pvClass)
+ *
+ * Entry pName = pointer to struct describing search
+ *
+ * Exit pName updated to reflect type
+ *
+ * Returns enum describing search state
+ *
+ */
+
+LOCAL SCN_t
+SearchBases (
+ psearch_t pName
+ )
+{
+ ushort cnt; // count of number of elements in struct
+ HTYPE hField; // handle to type record for struct field list
+ char *pField; // pointer to field list
+ uint fSkip = 0; // offset in the field list
+ SCN_t retval = SCN_notfound;
+ CV_typ_t newindex;
+ CV_typ_t vbptr;
+ OFFSET offset;
+ OFFSET vbpoff;
+ CV_fldattr_t attr;
+ CV_fldattr_t vattr;
+ peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
+ bool_t virtual;
+
+ // Set to head of type record and search the base classes in order
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) {
+ // set error and stop search
+ DASSERT (FALSE);
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+
+ for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
+ fSkip += SkipPad(((uchar *)pField) + fSkip);
+ newindex = 0;
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // switch to next part of type record
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ fSkip = 0;
+ // the LF_INDEX is not part of the field count
+ cnt++;
+ break;
+
+ case LF_BCLASS:
+ // read type index of base class offset of base pointer
+ // from address point
+
+ attr = ((plfBClass)(pField + fSkip))->attr;
+ newindex = ((plfBClass)(pField + fSkip))->index;
+ fSkip += sizeof (struct lfBClass);
+ offset = (OFFSET)RNumLeaf (pField + fSkip, &fSkip);
+ vbptr = 0;
+ vbpoff = 0;
+ virtual = FALSE;
+ goto foo;
+
+ case LF_VBCLASS:
+ // read type index of base class, type index of virtual
+ // base pointer, offset of virtual base pointer from
+ // address point and offset of virtual base displacement
+ // from virtual base table
+
+ vattr = ((plfVBClass)(pField + fSkip))->attr;
+ newindex = ((plfVBClass)(pField + fSkip))->index;
+ vbptr = ((plfVBClass)(pField + fSkip))->vbptr;
+ virtual = TRUE;
+ fSkip += sizeof (struct lfVBClass);
+ vbpoff = (OFFSET)RNumLeaf (pField + fSkip, &fSkip);
+ offset = (OFFSET)RNumLeaf (pField + fSkip, &fSkip);
+ if ((pName->clsmask & CLS_virtintro) == FALSE) {
+ // if we are searching for the introducing virtual method
+ // then we want to search all bases
+ if (VBSearched (newindex) == TRUE) {
+ break;
+ }
+ retval = AddVBType (&pVBSearch, &hVBSearch, newindex);
+ }
+
+foo:
+ // check base class
+
+ MHOmfUnLock (hField);
+
+ // Advance to next base class structure
+
+ if (IncrSymBase () != SCN_found) {
+ return (SCN_error);
+ }
+ retval = RecurseBase (pName, newindex, vbptr, vbpoff,
+ offset, attr, virtual);
+ switch (retval) {
+ case SCN_error:
+ // if we got an error, abort the search
+ newindex = 0;
+ break;
+
+ case SCN_found:
+ // we have found the feature in a base class.
+ // Dup the class search structure and continue the
+ // search to the end of the inheritance tree
+
+ if ((pName->clsmask & CLS_virtintro) == FALSE) {
+ if ((retval = DupSymCl (pName)) != SCN_found) {
+ // if we got an error duping, abort the search
+ newindex = 0;
+ }
+ // set not found, so the unwinding of the call stack
+ // does not reduplicate the class search structure
+ retval = SCN_notfound;
+ }
+ else {
+ // we were searching for the introducing virtual
+ // method. Since there can be only one in the
+ // tree above the virtual method, we can terminate
+ // the search immediately
+ return (retval);
+ }
+ break;
+
+ default:
+ break;
+ }
+ pSymClass->CurIndex--;
+ MHOmfLock (hField);
+ break;
+
+ default:
+ // we have reached the end of the base classes.
+ // exit loop and check search results.
+ break;
+
+ }
+ if (newindex == 0) {
+ // all base classes must appear first in the field list.
+ break;
+ }
+ }
+ MHOmfUnLock (hField);
+ return (retval);
+}
+
+
+
+bool_t
+getDefnFromDecl(
+ CV_typ_t typeIn,
+ peval_t pv,
+ CV_typ_t* ptypeOut)
+{
+ HTYPE hType;
+ uint skip;
+ TYPPTR pType;
+ eval_t localEval;
+ neval_t nv = &localEval;
+
+ *nv = *pv;
+
+ DASSERT (!CV_IS_PRIMITIVE (typeIn));
+ if ((hType = THGetTypeFromIndex (EVAL_MOD (nv), typeIn)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return FALSE;
+ }
+ pType = (TYPPTR)MHOmfLock(hType);
+
+ switch (pType->leaf) {
+ case LF_STRUCTURE:
+ case LF_CLASS:
+ {
+ plfClass pClass = (plfClass)(&pType->leaf);
+ if (pClass->property.fwdref) {
+ skip = offsetof (lfClass, data);
+ RNumLeaf (((char *)(&pClass->leaf)) + skip, &skip);
+ // forward ref - look for the definition of the UDT
+ if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, ((char *)&(pClass->leaf)) + skip)) == T_NOTYPE) {
+ goto failed;
+ }
+ }
+ else
+ *ptypeOut = typeIn;
+
+ break;
+ }
+
+ case LF_UNION:
+ {
+ plfUnion pUnion = (plfUnion)(&pType->leaf);
+ if (pUnion->property.fwdref) {
+ skip = offsetof (lfUnion, data);
+ RNumLeaf (((char *)(&pUnion->leaf)) + skip, &skip);
+ // forward ref - look for the definition of the UDT
+ if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, ((char *)&(pUnion->leaf)) + skip)) == T_NOTYPE) {
+ goto failed;
+ }
+ }
+ else
+ *ptypeOut = typeIn;
+
+ break;
+ }
+
+ case LF_ENUM:
+ {
+ plfEnum pEnum = (plfEnum)(&pType->leaf);
+ if (pEnum->property.fwdref) {
+ // forward ref - look for the definition of the UDT
+ if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, (char *) pEnum->Name)) == T_NOTYPE) {
+ goto failed;
+ }
+ }
+ else
+ *ptypeOut = typeIn;
+
+ break;
+ }
+
+ default:
+ *ptypeOut = typeIn;
+ }
+
+ MHOmfUnLock (hType);
+ return TRUE;
+
+failed:
+ MHOmfUnLock (hType);
+ pExState->err_num = ERR_BADOMF;
+ return FALSE;
+}
+
+
+/*** SearchBType - Search for an base by type
+ *
+ * flag = SearchBType (pName)
+ *
+ * Entry pName = pointer to struct describing search
+ * pSymClass = pointer to base class path list structure
+ *
+ * Exit pName updated to reflect search
+ *
+ * Return enum describing search
+ *
+ * If the base class is found, the base class value is stored in the
+ * the symbase[], not in pSymClass->evalP. This is to simplify the
+ * GenQualExpr code.
+ */
+
+
+LOCAL SCN_t
+SearchBType (
+ psearch_t pName
+ )
+{
+ ushort cnt; // count of number of elements in struct
+ HTYPE hField; // handle to type record for struct field list
+ char *pField; // pointer to field list
+ uint fSkip = 0; // offset in the field list
+ ushort anchor = 0; // offset in the field list to start of type
+ CV_typ_t newindex;
+ CV_typ_t vbptr;
+ ushort retval = SCN_notfound;
+ OFFSET offset;
+ OFFSET vbpoff;
+ bool_t termflag = FALSE;
+ CV_fldattr_t attr;
+ CV_fldattr_t vattr;
+ peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
+
+ // set hField to the handle of the field list for the class
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+
+ // walk field list for the class
+
+ for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
+ fSkip += SkipPad(((uchar *)pField) + fSkip);
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // switch to new type record because compiler split it up
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_INTERNAL;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ fSkip = 0;
+ // the LF_INDEX is not part of the field count
+ cnt++;
+ break;
+
+ case LF_BCLASS:
+ attr = ((plfBClass)(pField + fSkip))->attr;
+ if (!getBaseDefnFromDecl(((plfBClass)(pField + fSkip))->index, pName->pv, &newindex))
+ return SCN_error;
+// newindex = ((plfBClass)(pField + fSkip))->index;
+ fSkip += offsetof (lfBClass, offset[0]);
+ offset = (ushort)RNumLeaf (pField + fSkip, &fSkip);
+ if (pName->typeOut == newindex) {
+ // base has been found, set result values
+
+ MHOmfUnLock (hField);
+ if (IncrSymBase () != SCN_found) {
+ return (SCN_error);
+ }
+
+ // save offset of base from address point for this
+ // pointer adjustment
+
+ if (SetBase (pName, newindex, 0, 0, offset, attr, FALSE) != SCN_found) {
+ return (SCN_error);
+ }
+ pSymClass->s.viable = TRUE;
+ pName->possibles++;
+ return (SCN_found);
+ }
+ break;
+
+ case LF_VBCLASS:
+ vattr = ((plfVBClass)(pField + fSkip))->attr;
+ if (!getBaseDefnFromDecl(((plfVBClass)(pField + fSkip))->index, pName->pv, &newindex))
+ return SCN_error;
+// newindex = ((plfVBClass)(pField + fSkip))->index;
+ vbptr = ((plfVBClass)(pField + fSkip))->vbptr;
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ vbpoff = (ushort)RNumLeaf (pField + fSkip, &fSkip);
+ offset = (ushort)RNumLeaf (pField + fSkip, &fSkip);
+ if (pName->typeOut == newindex) {
+ // base has been found, set result values
+
+ MHOmfUnLock (hField);
+ if (IncrSymBase () != SCN_found) {
+ return (SCN_error);
+ }
+
+ // save offset of base from address point for this
+ // pointer adjustment
+
+ if (SetBase (pName, newindex, vbptr, vbpoff, offset, attr, TRUE) != SCN_found) {
+ return (SCN_error);
+ }
+ pSymClass->s.viable = TRUE;
+ pName->possibles++;
+ return (SCN_found);
+ }
+ break;
+
+ default:
+ termflag = TRUE;
+ break;
+ }
+ if (termflag == TRUE) {
+ break;
+ }
+ }
+ MHOmfUnLock (hField);
+ return (retval);
+}
+
+
+/*** SearchRoot - Search for an element of a class
+ *
+ * flag = SearchRoot (pName)
+ *
+ * Entry pName = pointer to struct describing search
+ * pvBase = pointer to value describing base to be searched
+ *
+ * Exit pName updated to reflect search
+ *
+ * Return enum describing search
+ */
+
+
+LOCAL SCN_t
+SearchRoot (
+ psearch_t pName
+ )
+{
+ ushort cnt; // count of number of elements in struct
+ HTYPE hField; // handle to type record for struct field list
+ char *pField; // pointer to field list
+ HTYPE hBase; // handle to type record for base class
+ uint fSkip = 0; // offset in the field list
+ uint anchor; // offset in the field list to start of type
+ uint tSkip; // temporary offset in the field list
+ bool_t cmpflag = 1;
+ CV_typ_t newindex;
+ CV_typ_t vbptr;
+ ushort retval = SCN_notfound;
+ char *pc;
+ ulong value;
+ OFFSET offset;
+ OFFSET vbpoff;
+ CV_fldattr_t access;
+ short count;
+ CV_typ_t vfpType = T_NOTYPE;
+ peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
+ CV_typ_t type;
+ peval_t pvF = &pSymClass->evalP;
+ ushort vtabind;
+ ushort vbind;
+
+ // set hField to the handle of the field list for the class
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase),
+ CLASS_FIELD (pvBase))) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock ((HDEP)hField))->data[0]);
+
+ // walk field list for the class
+
+#if 0
+
+ for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
+ fSkip += SkipPad(((uchar *)pField) + fSkip);
+ anchor = fSkip;
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // switch to new type record because compiler split it up
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock ((HDEP)hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock ((HDEP)hField))->data[0]);
+ fSkip = 0;
+ // the LF_INDEX is not part of the field count
+ cnt++;
+ break;
+
+ case LF_MEMBER:
+ fSkip += offsetof (lfMember, offset[0]);
+ offset = (short)RNumLeaf (pField + fSkip, &fSkip);
+ access = ((plfMember)(pField + anchor))->attr;
+ pc = pField + fSkip;
+ fSkip += (*(pField + fSkip) + sizeof (char));
+ if (pName->clsmask & CLS_member) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc,
+ pExState->state.fCase)) == 0) {
+ type = ((plfMember)(pField + anchor))->index;
+ MHOmfUnLock ((HDEP)hField);
+ hField = 0;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_lvalue;
+
+ // save the casting data for the this pointer
+
+ pSymClass->offset = offset;
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ break;
+
+ case LF_ENUMERATE:
+ access = ((plfEnumerate)(pField + fSkip))->attr;
+ fSkip += offsetof (lfEnumerate, value[0]);
+ value = RNumLeaf (pField + fSkip, &fSkip);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (pName->clsmask & CLS_enumerate) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc,
+ pExState->state.fCase)) == 0) {
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ break;
+
+#if !defined(C_ONLY)
+ case LF_STMEMBER:
+ type = ((plfSTMember)(pField + anchor))->index;
+ fSkip += offsetof (lfSTMember, Name[0]);
+ if (pName->clsmask & CLS_member) {
+ if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pField + fSkip,
+ pExState->state.fCase)) == 0) {
+ pSymClass->access =
+ ((plfSTMember)(pField + anchor))->attr;
+ MHOmfUnLock (hField);
+ hField = 0;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_lvalue;
+ EVAL_IS_STMEMBER (pvF) = TRUE;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ fSkip += *(pField + fSkip) + sizeof (char);
+ break;
+
+ case LF_BCLASS:
+ type = ((plfBClass)(pField + anchor))->index;
+ access = ((plfBClass)(pField + anchor))->attr;
+ fSkip += offsetof (lfBClass, offset[0]);
+ newindex = ((plfBClass)(pField + anchor))->index;
+ offset = (short)RNumLeaf (pField + fSkip, &fSkip);
+ if ((pName->clsmask & CLS_bclass) != 0) {
+
+ // switch to the base class type record to check the name
+
+ MHOmfUnLock (hField);
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
+ tSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = pField + tSkip;
+ cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc, pExState->state.fCase);
+ MHOmfUnLock (hBase);
+
+ // reset to original field list
+
+ if (cmpflag == 0) {
+
+ // element has been found, set result values
+
+ pSymClass->s.isbase = TRUE;
+ pSymClass->s.isvbase = FALSE;
+ pSymClass->offset += offset;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_type;
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ }
+ break;
+
+ case LF_VBCLASS:
+ type = ((plfBClass)(pField + anchor))->index;
+ access = ((plfVBClass)(pField + anchor))->attr;
+ newindex = ((plfVBClass)(pField + anchor))->index;
+ vbptr = ((plfVBClass)(pField + anchor))->vbptr;
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ vbpoff = (short)RNumLeaf (pField + fSkip, &fSkip);
+ vbind = (short)RNumLeaf (pField + fSkip, &fSkip);
+ if ((pName->clsmask & CLS_bclass) != 0) {
+
+ // switch to the base class type record to check the name
+
+ MHOmfUnLock (hField);
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
+ tSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = pField + tSkip;
+ cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc, pExState->state.fCase);
+ MHOmfUnLock (hBase);
+
+ // reset to original field list
+
+ if (cmpflag == 0) {
+
+ // element has been found, set result values
+
+ pSymClass->s.isbase = FALSE;
+ pSymClass->s.isvbase = TRUE;
+ pSymClass->vbind = vbind;
+ pSymClass->vbpoff = vbpoff;
+ pSymClass->vbptr = vbptr;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_type;
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ }
+ break;
+
+ case LF_IVBCLASS:
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ break;
+
+ case LF_FRIENDCLS:
+ newindex = ((plfFriendCls)(pField + fSkip))->index;
+ fSkip += sizeof (struct lfFriendCls);
+ if ((pName->clsmask & CLS_fclass) != 0) {
+
+ DASSERT (FALSE);
+
+ // switch to the base class type record to check the name
+
+ MHOmfUnLock (hField);
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_INTERNAL;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->data[0]);
+ tSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = pField + tSkip;
+ cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc, pExState->state.fCase);
+ MHOmfUnLock (hBase);
+
+ // reset to original field list
+
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ if (cmpflag == 0) {
+
+ // element has been found, set result values
+
+ pName->typeOut = newindex;
+ }
+ }
+ break;
+
+ case LF_FRIENDFCN:
+ newindex = ((plfFriendFcn)(pField + fSkip))->index;
+ fSkip += sizeof (struct lfFriendFcn) +
+ ((plfFriendFcn)(pField + fSkip))->Name[0];
+ if ((pName->clsmask & CLS_frmethod) != 0) {
+ DASSERT (FALSE);
+ }
+ break;
+
+ case LF_VFUNCTAB:
+ fSkip += sizeof (struct lfVFuncTab);
+ // save the type of the virtual function pointer
+ vfpType = ((plfVFuncTab)(pField + anchor))->type;
+ pc = vfuncptr;
+ if (pName->clsmask & CLS_vfunc) {
+ if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc,
+ pExState->state.fCase)) == 0) {
+ MHOmfUnLock (hField);
+ hField = 0;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, vfpType);
+ EVAL_STATE (pvF) = EV_lvalue;
+
+ // save the casting data for the this pointer
+
+ if (pName->bnOp != 0) {
+ pSymClass->offset = 0;
+ pSymClass->access.access = CV_public;
+ }
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ break;
+
+ case LF_METHOD:
+ count = ((plfMethod)(pField + fSkip))->count;
+ cnt -= count - 1;
+ newindex = ((plfMethod)(pField + fSkip))->mList;
+ pc = pField + anchor + offsetof (lfMethod, Name[0]);
+ fSkip += sizeof (struct lfMethod) + *pc;
+ if (pName->clsmask & CLS_method) {
+ if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc,
+ pExState->state.fCase)) == 0) {
+ // note that the OMF specifies that the vfuncptr will
+ // be emitted as the first field after the bases
+
+ if (pName->clsmask & CLS_virtintro) {
+ // we are looking for the introducing virtual
+ // method. We need to find a method with the
+ // correct name of the correct type index that
+ // is introducing.
+
+ MHOmfUnLock (hField);
+ if (IsIntroVirt (count, newindex, &vtabind) == FALSE) {
+ cmpflag = 1;
+ }
+ else {
+ if (FCN_VFPTYPE (pvF) == T_NOTYPE) {
+ FCN_VFPTYPE (pvF) = vfpType;
+ FCN_VFPTYPE (pName->pv) = vfpType;
+ FCN_VTABIND (pvF) = vtabind;
+ FCN_VTABIND (pName->pv) = vtabind;
+ }
+ cmpflag = 0;
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ }
+ else {
+ // save the type index of the method list, the
+ // count of methods overloaded on this name,
+ // the type index of the vfuncptr. Also,
+ // increment the number of possible features by
+ // the overload count
+
+ pSymClass->possibles = count;
+ pName->possibles += count;
+ pSymClass->mlist = newindex;
+ pSymClass->vfpType = vfpType;
+ }
+ }
+ }
+ break;
+
+ case LF_NESTTYPE:
+ newindex = ((plfNestType)(pField + fSkip))->index;
+ fSkip += offsetof (lfNestType, Name[0]);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (pName->clsmask & CLS_ntype) {
+ if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc,
+ pExState->state.fCase)) == 0) {
+ // set type of typedef symbol
+ EVAL_STATE (pvF) = EV_type;
+ }
+ }
+ break;
+#else
+ Unreferenced( vbpoff );
+ Unreferenced( hBase );
+ Unreferenced( vbptr );
+ Unreferenced( tSkip );
+ Unreferenced( count );
+ Unreferenced( vtabind );
+ Unreferenced( vbind );
+#endif
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ retval = SCN_notfound;
+
+ }
+
+ if (cmpflag == 0) {
+ pSymClass->s.viable = TRUE;
+ retval = SCN_found;
+ break;
+ }
+ }
+
+#endif
+
+#if 1
+ for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
+ fSkip += SkipPad(((uchar *)pField) + fSkip);
+ anchor = fSkip;
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // switch to new type record because compiler split it up
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
+ fSkip = 0;
+ // the LF_INDEX is not part of the field count
+ cnt++;
+ break;
+
+ case LF_MEMBER:
+ fSkip += offsetof (lfMember, offset);
+ offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip);
+ access = ((plfMember)(pField + anchor))->attr;
+ pc = pField + fSkip;
+ fSkip += (*(pField + fSkip) + sizeof (char));
+ if (pName->clsmask & CLS_member) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
+ type = ((plfMember)(pField + anchor))->index;
+ MHOmfUnLock (hField);
+ hField = 0;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_lvalue;
+
+ // save the casting data for the this pointer
+
+ pSymClass->offset = offset;
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ break;
+
+ case LF_ENUMERATE:
+ access = ((plfEnumerate)(pField + fSkip))->attr;
+ fSkip += offsetof (lfEnumerate, value);
+ value = (ulong) RNumLeaf (pField + fSkip, &fSkip);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (pName->clsmask & CLS_enumerate) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ break;
+
+ case LF_STMEMBER:
+ type = ((plfSTMember)(pField + anchor))->index;
+ fSkip += offsetof (lfSTMember, Name);
+ if (pName->clsmask & CLS_member) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pField + fSkip, pExState->state.fCase)) == 0) {
+ pSymClass->access =
+ ((plfSTMember)(pField + anchor))->attr;
+ MHOmfUnLock (hField);
+ hField = 0;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_lvalue;
+ EVAL_IS_STMEMBER (pvF) = TRUE;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ fSkip += *(pField + fSkip) + sizeof (char);
+ break;
+
+ case LF_BCLASS:
+ type = ((plfBClass)(pField + anchor))->index;
+ access = ((plfBClass)(pField + anchor))->attr;
+ fSkip += offsetof (lfBClass, offset);
+ newindex = ((plfBClass)(pField + anchor))->index;
+ offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip);
+ if ((pName->clsmask & CLS_bclass) != 0) {
+
+ // switch to the base class type record to check the name
+
+ MHOmfUnLock (hField);
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
+ tSkip = offsetof (lfClass, data);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = pField + tSkip;
+ cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase);
+ MHOmfUnLock (hBase);
+
+ // reset to original field list
+
+ if (cmpflag == 0) {
+
+ // element has been found, set result values
+
+ pSymClass->s.isbase = TRUE;
+ pSymClass->s.isvbase = FALSE;
+ pSymClass->offset += offset;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_type;
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
+ }
+ break;
+
+ case LF_VBCLASS:
+ type = ((plfBClass)(pField + anchor))->index;
+ access = ((plfVBClass)(pField + anchor))->attr;
+ newindex = ((plfVBClass)(pField + anchor))->index;
+ vbptr = ((plfVBClass)(pField + anchor))->vbptr;
+ fSkip += offsetof (lfVBClass, vbpoff);
+ vbpoff = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip);
+ vbind = (short)RNumLeaf (pField + fSkip, &fSkip);
+ if ((pName->clsmask & CLS_bclass) != 0) {
+
+ // switch to the base class type record to check the name
+
+ MHOmfUnLock (hField);
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
+ tSkip = offsetof (lfClass, data);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = pField + tSkip;
+ cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase);
+ MHOmfUnLock (hBase);
+
+ // reset to original field list
+
+ if (cmpflag == 0) {
+
+ // element has been found, set result values
+
+ pSymClass->s.isbase = FALSE;
+ pSymClass->s.isvbase = TRUE;
+ pSymClass->vbind = vbind;
+ pSymClass->vbpoff = vbpoff;
+ pSymClass->vbptr = vbptr;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, type);
+ EVAL_STATE (pvF) = EV_type;
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
+ }
+ break;
+
+ case LF_IVBCLASS:
+ fSkip += offsetof (lfVBClass, vbpoff);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ break;
+
+ case LF_FRIENDCLS:
+ newindex = ((plfFriendCls)(pField + fSkip))->index;
+ fSkip += sizeof (struct lfFriendCls);
+ if ((pName->clsmask & CLS_fclass) != 0) {
+
+ DASSERT (FALSE);
+
+ // switch to the base class type record to check the name
+
+ MHOmfUnLock (hField);
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_INTERNAL;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->data);
+ tSkip = offsetof (lfClass, data);
+ RNumLeaf (pField + tSkip, &tSkip);
+ pc = pField + tSkip;
+ cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase);
+ MHOmfUnLock (hBase);
+
+ // reset to original field list
+
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
+ if (cmpflag == 0) {
+
+ // element has been found, set result values
+
+ pName->typeOut = newindex;
+ }
+ }
+ break;
+
+ case LF_FRIENDFCN:
+ newindex = ((plfFriendFcn)(pField + fSkip))->index;
+ fSkip += sizeof (struct lfFriendFcn) +
+ ((plfFriendFcn)(pField + fSkip))->Name[0];
+ if ((pName->clsmask & CLS_frmethod) != 0) {
+ DASSERT (FALSE);
+ }
+ break;
+
+ case LF_VFUNCTAB:
+ fSkip += sizeof (struct lfVFuncTab);
+ // save the type of the virtual function pointer
+ vfpType = ((plfVFuncTab)(pField + anchor))->type;
+ pc = vfuncptr;
+ if (pName->clsmask & CLS_vfunc) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
+ MHOmfUnLock (hField);
+ hField = 0;
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, vfpType);
+ EVAL_STATE (pvF) = EV_lvalue;
+
+ // save the casting data for the this pointer
+
+ if (pName->bnOp != 0) {
+ pSymClass->offset = 0;
+ pSymClass->access.access = CV_public;
+ }
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ }
+ }
+ break;
+
+ case LF_METHOD:
+ count = ((plfMethod)(pField + fSkip))->count;
+ cnt -= count - 1;
+ newindex = ((plfMethod)(pField + fSkip))->mList;
+ pc = pField + anchor + offsetof (lfMethod, Name);
+ fSkip += sizeof (struct lfMethod) + *pc;
+ if (pName->clsmask & CLS_method) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
+ // note that the OMF specifies that the vfuncptr will
+ // be emitted as the first field after the bases
+
+ if (pName->clsmask & CLS_virtintro) {
+ // we are looking for the introducing virtual
+ // method. We need to find a method with the
+ // correct name of the correct type index that
+ // is introducing.
+
+ MHOmfUnLock (hField);
+ if (IsIntroVirt (count, newindex, &vtabind) == FALSE) {
+ cmpflag = 1;
+ }
+ else {
+ if (FCN_VFPTYPE (pvF) == T_NOTYPE) {
+ FCN_VFPTYPE (pvF) = vfpType;
+ FCN_VFPTYPE (pName->pv) = vfpType;
+ FCN_VTABIND (pvF) = vtabind;
+ FCN_VTABIND (pName->pv) = vtabind;
+ }
+ cmpflag = 0;
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
+ }
+ else {
+ // save the type index of the method list, the
+ // count of methods overloaded on this name,
+ // the type index of the vfuncptr. Also,
+ // increment the number of possible features by
+ // the overload count
+
+ pSymClass->possibles = count;
+ pName->possibles += count;
+ pSymClass->mlist = newindex;
+ pSymClass->vfpType = vfpType;
+ }
+ }
+ }
+ break;
+
+ case LF_NESTTYPE:
+ newindex = ((plfNestType)(pField + fSkip))->index;
+ fSkip += offsetof (lfNestType, Name);
+ pc = pField + fSkip;
+ fSkip += *(pField + fSkip) + sizeof (char);
+ if (pName->clsmask & CLS_ntype) {
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
+ // set type of typedef symbol
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ EVAL_STATE (pvF) = EV_type;
+ EVAL_TYP(pvF) = newindex;
+ }
+ else if (pName->clsmask & CLS_enumerate) {
+ // check if the nested type is an enum. if it is
+ // we gotta search thru its field list for a matching
+ // enumerate
+ // sps - 9/14/92
+ HTYPE hEnum, hEnumField; // nested handle
+ plfEnum pEnum;
+ char *pEnumField; // field list of the enum record
+ ushort enumCount;
+ uint fSkip = 0; // offset in the field list
+ uint anchor; // offset in the field list to start of type
+
+ if (CV_IS_PRIMITIVE(newindex)) {
+ break;
+ }
+
+ if ((hEnum = THGetTypeFromIndex (EVAL_MOD (pvBase),
+ newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pEnum = (plfEnum) (&((TYPPTR)MHOmfLock (hEnum))->leaf);
+ if (pEnum->leaf == LF_ENUM) {
+ if (pEnum->property.fwdref) {
+ eval_t localeval = *pvBase;
+ neval_t nv = &localeval;
+
+ // forward ref - look for the definition of the UDT
+ if ((newindex = GetUdtDefnTindex (newindex, pvBase, (char *)&(pEnum->Name[0]))) != T_NOTYPE) {
+ if ((hEnum = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pEnum = (plfEnum) (&((TYPPTR)MHOmfLock (hEnum))->leaf);
+ }
+ else
+ break; // No Fwd ref found... no CVInfo for nested type... proceed with search [rm]
+ }
+ if ((hEnumField = THGetTypeFromIndex (EVAL_MOD (pvBase),
+ pEnum->field)) == 0) {
+ if ( BindingBP ) {
+ break;
+ }
+ else {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ }
+ pEnumField = (char *)(&((TYPPTR)MHOmfLock (hEnumField))->data);
+ for (enumCount = pEnum->count; enumCount > 0; enumCount--) {
+ fSkip += SkipPad(((uchar *)pEnumField) + fSkip);
+ anchor = fSkip;
+ DASSERT ((((plfEasy)(pEnumField + fSkip))->leaf) == LF_ENUMERATE);
+
+ access = ((plfEnumerate)(pEnumField + fSkip))->attr;
+ fSkip += offsetof (lfEnumerate, value);
+ value = (ulong) RNumLeaf (pEnumField + fSkip, &fSkip);
+ pc = pEnumField + fSkip;
+ fSkip += *(pEnumField + fSkip) + sizeof (char);
+ if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
+ EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
+ SetNodeType (pvF, pEnum->utype);
+ EVAL_STATE (pvF) = EV_constant;
+ EVAL_LONG (pvF) = value;
+
+ // save the casting data for the this pointer
+
+ pSymClass->access = access;
+ pSymClass->possibles = 1;
+ pName->possibles++;
+ break;
+ }
+ }
+ MHOmfUnLock (hEnumField);
+ }
+ MHOmfUnLock (hEnum);
+ }
+ }
+ break;
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ retval = SCN_notfound;
+
+ }
+#ifdef NEVER
+ // if ((cnt == 0) && ************ (pName->tTypeDef != 0)) {
+ if ((cnt == 0) && (pName->tTypeDef != 0)) {
+ // we found a typedef name that was not hidden by
+ // a member or method name
+ }
+#endif
+
+ if (cmpflag == 0) {
+ pSymClass->s.viable = TRUE;
+ retval = SCN_found;
+ break;
+ }
+ }
+
+#endif
+
+ if (hField != 0) {
+ MHOmfUnLock ((HDEP)hField);
+ }
+ return (retval);
+}
+
+
+
+
+/** SetBPValue - set the breakpoint list from a class search
+ *
+ * status = SetBPValue (pName)
+ *
+ * Entry pName = pointer to structure describing search
+ * pSymCl = pointer to class element
+ *
+ * Exit pName updated to reflect found feature
+ * this pointer inserted in bind tree if feature is part of
+ * the class pointed to by this pointer of method
+ *
+ * Returns SCN_rewrite if this pointer inserted (rebind required)
+ * SCN_found if no error
+ * SCN_error otherwise
+ */
+
+
+LOCAL SCN_t
+SetBPValue (
+ psearch_t pName
+ )
+{
+ peval_t pv;
+
+ DASSERT ((pName->cFound == 0) && (pName->hFound == 0));
+ if (pSymClass->mlist != T_NOTYPE) {
+ if ((pName->possibles == 1) || (bArgList != 0)) {
+ switch (MatchMethod (pName, pSymClass)) {
+ default:
+ DASSERT (FALSE);
+ case MTH_error:
+ return (SCN_error);
+
+ case MTH_found:
+ break;
+ }
+ }
+ else {
+ // we have a list of functions and no argument list.
+ // This means that we have an ambiguous breakpoint
+ // and need to add the functions to the breakpoint
+ // list for user disambiguation. Basically what
+ // we are going to do is force all of the methods
+ // into the breakpoint list and let later
+ // binding resolve any errors.
+
+ return (OverloadToAmbList (pName, pSymClass));
+ }
+ }
+
+ // at this point, the following values are set
+ // pName->addr = address of method if not virtual method
+ // pName->typeOut = type index of method
+ // pName->hSym = handle of symbol for function
+
+ pv = &pSymClass->evalP;
+ if ((FCN_ATTR (pv).mprop == CV_MTvirtual) ||
+ (FCN_ATTR (pv).mprop == CV_MTintro)) {
+ pExState->err_num = ERR_NOVIRTUALBP;
+ return (SCN_error);
+ }
+ pv = pName->pv;
+ *pv = pSymClass->evalP;
+ EVAL_ACCESS (pv) = (uchar)(pSymClass->access.access);
+ pName->typeOut = EVAL_TYP (pv);
+
+ // save the offset of a class member
+ // (caviar #1756) --gdp 9-10-92
+
+ if (pName->bnOp) {
+ peval_t pvOp = &(pnodeOfbnode(pName->bnOp))->v[0];
+ EVAL_IS_MEMBER(pvOp) = TRUE;
+ MEMBER_OFFSET(pvOp) = pName->initializer == INIT_right ?
+ pSymClass->offset : 0;
+ }
+
+ return (SCN_found);
+}
+
+
+LOCAL SCN_t
+OverloadToAmbList (
+ psearch_t pName,
+ psymclass_t pSymCl
+ )
+{
+ SCN_t retval;
+
+ // add the first list of methods
+
+ if ((retval = MethodsToAmbList (pName, pSymCl)) != SCN_found) {
+ return (retval);
+ }
+
+ // loop through the remaining class descriptors adding them to the list
+
+ while (pName->hAmbCl != 0) {
+ MoveSymCl (pName->hAmbCl);
+ if ((retval = MethodsToAmbList (pName,pSymCl)) != SCN_found) {
+ return (retval);
+ }
+ }
+
+ if (pExState->ambiguous == 0) {
+ // no instantiated function has been found
+ return (SCN_notfound);
+ }
+
+ SymToNode (pName);
+ DASSERT (EVAL_TYP (pName->pv) != T_NOTYPE);
+ return (SCN_found);
+}
+
+
+
+
+/** MethodsToAmbList - add a list of methods to ambiguous breakpoints
+ *
+ * flag = MethodsToAmbList (pName, pSymCl)
+ *
+ * Entry pName = pointer to search descriptor
+ * pSymCl = pointer to symbol class structure
+ *
+ * Exit methods added to list of ambiguous breakpoints
+ *
+ * Returns SCN_found if methods added
+ * SCN_error if error during addition
+ *
+ */
+
+
+LOCAL SCN_t
+MethodsToAmbList (
+ psearch_t pName,
+ psymclass_t pSymCl
+ )
+{
+ HTYPE hMethod;
+ pmlMethod pMethod;
+ uint skip;
+ CV_fldattr_t attr;
+ CV_typ_t type;
+ ushort vtabind;
+ HDEP hQual;
+ peval_t pvF;
+ ushort count = pSymCl->possibles;
+ peval_t pvB;
+ HMOD hMod;
+ HDEP hTemp;
+ psearch_t pTemp;
+ bool_t retval;
+
+ pvB = &pSymCl->symbase[pSymCl->CurIndex].Base;
+ hMod = EVAL_MOD (pvB);
+
+ // we now walk the list of methods adding each method to the list of
+ // ambiguous breakpoints
+
+ if ((hMethod = THGetTypeFromIndex (hMod, pSymCl->mlist)) == (HTYPE) NULL) {
+ DASSERT (FALSE);
+ return (MTH_error);
+ }
+
+ // set the number of methods overloaded on this name and the index into
+ // the method list
+
+ skip = 0;
+ while (count-- > 0) {
+ // lock the omf record, extract information for the current entry in
+ // the method list and increment to field for next method
+
+ pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1);
+ pMethod = (pmlMethod)((uchar *)pMethod + skip);
+ attr = pMethod->attr;
+ type = pMethod->index;
+ skip += sizeof (mlMethod);
+ if (pMethod->attr.mprop == CV_MTintro) {
+ vtabind = (short)RNumLeaf (((char *)pMethod) + skip, &skip);
+ }
+ else {
+ vtabind = 0;
+ }
+ MHOmfUnLock (hMethod);
+
+ // now add the method to the list
+
+ pvF = &pSymCl->evalP;
+ EVAL_MOD (pvF) = hMod;
+ DASSERT (type != T_NOTYPE);
+ if (SetNodeType (pvF, type) == FALSE) {
+ return (MTH_error);
+ }
+ else {
+ FCN_ATTR (pvF) = attr;
+ FCN_VTABIND (pvF) = vtabind;
+ FCN_VFPTYPE (pvF) = pSymCl->vfpType;
+ pName->best.match = type;
+ if (((hQual = GenQualName (pName, pSymCl)) == 0) ||
+ (SearchQualName (pName, pSymCl, hQual, TRUE) == FALSE)) {
+ if (hQual != 0) {
+ MHMemFree (hQual);
+ }
+ return (SCN_error);
+ }
+ MHMemFree (hQual);
+ }
+
+ /*
+ * Function must be present in the exe and the one we found must
+ * be of the correct type (it will find others for some reason)
+ * or else it should be ignored. We will conver all possible
+ * function types so throwing this one away should make no
+ * difference
+ */
+
+ if ((FCN_NOTPRESENT (pvF) == FALSE) && (EVAL_TYP( pvF ) == type)) {
+ if (pExState->ambiguous == 0) {
+ // we have found the first function. We need to set all of
+ // the return values in the pointer to the search entry
+
+ pExState->ambiguous = pName->bn;
+
+ // at this point, the following values are set
+ // pName->addr = address of method if not virtual method
+ // pName->typeOut = type index of method
+ // pName->hSym = handle of symbol for function
+
+ *pName->pv = pSymClass->evalP;
+ EVAL_ACCESS (pName->pv) = (uchar)(pSymClass->access.access);
+ pName->typeOut = EVAL_TYP (pName->pv);
+ pName->hSym = EVAL_HSYM (pvF);
+ }
+ else {
+ if ((hTemp = MHMemAllocate (sizeof (search_t))) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (SCN_error);
+ }
+ pTemp = MHMemLock (hTemp);
+ *pTemp = *pName;
+ pTemp->hSym = pvF->hSym;
+ retval = AmbToList (pTemp);
+ MHMemUnLock (hTemp);
+ MHMemFree (hTemp);
+ if (retval == FALSE) {
+ return (SCN_error);
+ }
+ }
+ }
+ }
+ if (pExState->ambiguous == 0) {
+ return SCN_notfound;
+ }
+ return (SCN_found);
+}
+
+
+/** SetValue - set the result of the class search
+ *
+ * status = SetValue (pName)
+ *
+ * Entry pName = pointer to structure describing search
+ * pSymClass = pointer to class element
+ *
+ * Exit pName updated to reflect found feature
+ * this pointer inserted in bind tree if feature is part of
+ * the class pointed to by this pointer of method
+ *
+ * Returns SCN_rewrite if this pointer inserted (rebind required)
+ * SCN_found if no error
+ * SCN_error otherwise
+ */
+
+
+LOCAL SCN_t
+SetValue (
+ psearch_t pName
+ )
+{
+ peval_t pv;
+ peval_t pvOp;
+ SCN_t retval;
+ HDEP hQual;
+
+ // When we get here, the situation is a bit complex.
+ // If we are not binding breakpoints, the following conditions
+ // must be true:
+ // pName->hAmbCl = 0 (only one feature can remain after dominance)
+ // pName->cFound = 0
+ // pName->hFound = 0
+ // pSymClass->s.viable = TRUE
+ // If the feature is a data item (pSymClass->mlist == T_NOTYPE), then
+ // pName->possibles = 1
+ // If the feature is a method, then
+ // pName->possibles = number of overloads on name
+ // pSymClass->mlist = type index of member list
+ // bArgList = based pointer to argument list tree (cannot be 0)
+ // Argument matching must result in a best match to a single method
+ //
+ // If we are binding breakpoints, the following conditions must be true
+ // pName->cFound = 0
+ // pName->hFound = 0
+ // pName->possibles = total number of methods in pSymClass and
+ // pName->hAmbCl
+ // pName->hAmbCl > 0 if two or more features survived dominance
+ // Each of the features in pSymClass and the pName->hAmbCl list
+ // must be a method list (pSymClass->mlist != T_NOTYPE)
+ //
+ // If we do not have an argument list, then we accept all methods in
+ // pSymClass->mlist and pName->hAmbCl.mlist. The number of methods is
+ // pName->possibles.
+ //
+ // If we do have an argument list, then we accept all methods in
+ // pSymClass->mlist and pName->hAmbCl.mlist that are exact matches
+ // for the argument list. Implicit conversions are not considered.
+ // The number of methods must less than 1 + number of elements in the
+ // list pName->hAmbCl and must be less than or equal to pName->possibles.
+
+ if (BindingBP == TRUE) {
+ // call the set of routines that will process breakpoints on methods
+ // of a class, the inheritance tree of the class and the derivation
+ // tree of the class. If the routine returns without error, pName
+ // describes the first function breakpoint and hTMList describes the
+ // remainder of the list of methods that match the function and
+ // signature if one is specified.
+
+ return (SetBPValue (pName));
+ }
+ // At this point, there must be only one class after dominance resolution,
+ // the count of the found items must be zero, and the handle of the found
+ // item list must be null. Otherwise there was a failure in dominance
+ // resolution.
+
+ DASSERT ((pName->hAmbCl == 0) &&
+ (pName->cFound == 0) &&
+ (pName->hFound == 0) &&
+ (pSymClass->s.viable == TRUE));
+ if (pSymClass->mlist == T_NOTYPE) {
+ DASSERT (pName->possibles == 1);
+ }
+ else if (bArgList == 0) {
+ pExState->err_num = ERR_NOARGLIST;
+ return (SCN_error);
+ }
+ // if we are processing C++, then we can allow for overloaded methods
+ // which is specified by the type index of the method list not being
+ // zero. If this is true, then we select the best of the overloaded
+ // methods.
+
+ if (pSymClass->mlist != T_NOTYPE) {
+ switch (MatchMethod (pName, pSymClass)) {
+ default:
+ DASSERT (FALSE);
+ case MTH_error:
+ return (SCN_error);
+
+ case MTH_found:
+ // at this point, the following values are set
+ // pName->addr = address of method if not virtual method
+ // pName->typeOut = type index of method
+ // pName->hSym = handle of symbol for function
+
+ pv = &pSymClass->evalP;
+ if (FCN_ATTR (pv).mprop == CV_MTvirtual) {
+ // search to introducing virtual method
+ if ((retval = FindIntro (pName)) != SCN_found) {
+ return (retval);
+ }
+ }
+ break;
+ }
+ }
+ // the symbol is a data member of the class (C or C++). If an
+ // explict class was not specified and the current context is
+ // implicitly a class (we are in the scope of the method of the class),
+ // then we rewrite the tree to change the symbol reference to this->symbol
+
+ if ((pName->initializer != INIT_base) &&
+ (pName->initializer != INIT_sym) &&
+ (pName->ExpClass == 0)) {
+ //DASSERT (FALSE);
+ pExState->err_num = ERR_INTERNAL;
+ return (SCN_error);
+ }
+
+ else if ((pName->ExpClass == 0) && (ClassImp != 0) &&
+ (pName->initializer != INIT_base)) {
+ // if the feature is a member of *this class of a method, then
+ // we need to rewrite
+ // feature
+ // to
+ // this->feature
+ // The calling routine will need to rebind the expression
+
+ InsertThis (pName);
+ return (SCN_rewrite);
+ }
+ // the initializer for the search must be INIT_right or INIT_base.
+ // by the time we get to here we know that bnOp is the based pointer to
+ // the node that will receive the casting expression and pv points
+ // to the feature node.
+
+ pv = pName->pv;
+ pvOp = &(pnodeOfbnode(pName->bnOp)->v[0]);
+ switch (pName->initializer) {
+ case INIT_right:
+ EVAL_CBTOK(&pSymClass->evalP) = EVAL_CBTOK(pv);
+ EVAL_ITOK(&pSymClass->evalP) = EVAL_ITOK(pv);
+ *pv = pSymClass->evalP;
+ EVAL_ACCESS (pv) = (uchar)(pSymClass->access.access);
+ pName->typeOut = EVAL_TYP (pv);
+ EVAL_IS_MEMBER (pvOp) = TRUE;
+ MEMBER_TYPE (pvOp) = EVAL_TYP (pv);
+ MEMBER_OFFSET (pvOp) = pSymClass->offset;
+ MEMBER_ACCESS (pvOp) = pSymClass->access;
+ if ((pSymClass->s.isvbase == TRUE) || (pSymClass->s.isivbase == TRUE)) {
+ MEMBER_VBASE (pvOp) = pSymClass->s.isvbase;
+ MEMBER_IVBASE (pvOp) = pSymClass->s.isivbase;
+ MEMBER_VBPTR (pvOp) = pSymClass->vbptr;
+ MEMBER_VBPOFF (pvOp) = pSymClass->vbpoff;
+ MEMBER_VBIND (pvOp) = pSymClass->vbind;
+ }
+ break;
+
+ case INIT_base:
+ *pv = pSymClass->symbase[pSymClass->CurIndex].Base;
+ EVAL_ACCESS (pv) = (uchar)(pSymClass->symbase[pSymClass->
+ CurIndex].attrBC.access);
+ pName->typeOut = EVAL_TYP (pv);
+ EVAL_IS_MEMBER (pvOp) = TRUE;
+ EVAL_ACCESS (pvOp) = (uchar)(pSymClass->symbase[pSymClass->
+ CurIndex].attrBC.access);
+ MEMBER_OFFSET (pvOp) = 0;
+ break;
+
+ default:
+ DASSERT (FALSE);
+ return (SCN_error);
+ }
+ if (EVAL_IS_STMEMBER (pv) == FALSE) {
+ // the feature is not a static data member of the class
+ return (GenQualExpr (pName));
+ }
+ else {
+ // the feature is a static member so we need to generate the
+ // qualified path and search for a symbol of the correct type
+ // so we can set the address
+
+ if (((hQual = GenQualName (pName, pSymClass)) == 0) ||
+ (SearchQualName (pName, pSymClass, hQual, FALSE) == FALSE)) {
+ if (hQual != 0) {
+ MHMemFree (hQual);
+ }
+ return (SCN_error);
+ }
+ *pv = pSymClass->evalP;
+ EVAL_STATE (pv) = EV_lvalue;
+ MHMemFree (hQual);
+ return (SCN_found);
+ }
+}
+
+
+
+// Support routines
+
+
+
+
+/** AddETConst - add evalthisconst node
+ *
+ * pn = AddETConst (pnP, off, btype)
+ *
+ * Entry pnP = pointer to previous node
+ *
+ * Exit OP_evalthisconst node added to bind tree
+ * current node linked to pnP as left child if pnP != NULL
+ * pTree->node_next advanced
+ * btype = type of the base class
+ *
+ * Returns pointer to node just allocated
+ */
+
+
+LOCAL pnode_t
+AddETConst (
+ pnode_t pnP,
+ OFFSET off,
+ CV_typ_t btype
+ )
+{
+ pnode_t pn;
+ padjust_t pa;
+
+ pn = (pnode_t)(((char *)pTree) + pTree->node_next);
+ pa = (padjust_t)(&pn->v[0]);
+ _fmemset (pn, 0, sizeof (node_t) + sizeof (adjust_t));
+ NODE_OP (pn) = OP_thisconst;
+ pa->btype = btype;
+ pa->disp = off;
+ if (pnP != NULL) {
+ NODE_LCHILD (pnP) = bnodeOfpnode(pn);
+ }
+ pTree->node_next += sizeof (node_t) + sizeof (adjust_t);
+ return (pn);
+}
+
+
+
+
+/** AddETInit - add evalthisinit node
+ *
+ * pn = AddETInit (pnP, btype)
+ *
+ * Entry pnP = pointer to previous node
+ *
+ * Exit OP_evalthisinit node added to bind tree
+ * current node linked to pnP as left child if pnP != NULL
+ * pTree->node_next advanced
+ * btype = type of the base class
+ *
+ * Returns pointer to node just allocated
+ */
+
+
+LOCAL pnode_t
+AddETInit (
+ pnode_t pnP,
+ CV_typ_t btype
+ )
+{
+ pnode_t pn;
+ padjust_t pa;
+
+ pn = (pnode_t)(((char *)pTree) + pTree->node_next);
+ pa = (padjust_t)(&pn->v[0]);
+ _fmemset (pn, 0, sizeof (node_t) + sizeof (adjust_t));
+ NODE_OP (pn) = OP_thisinit;
+ pa->btype = btype;
+ if (pnP != NULL) {
+ NODE_LCHILD (pnP) = bnodeOfpnode(pn);
+ }
+ pTree->node_next += sizeof (node_t) + sizeof (adjust_t);
+ return (pn);
+}
+
+
+
+
+/** AddETExpr - add evalthisexpr node
+ *
+ * pn = AddETExpr (pnP, vbptr, vbpoff, vbind, btype)
+ *
+ * Entry pnP = pointer to previous node
+ * vbptr = type index of virtual base pointer
+ * vboff = offset of vbptr from address point
+ * vbdisp = offset of displacement in virtual base table
+ * btype = type of the base class
+ *
+ * Exit OP_evalthisconst node added to bind tree
+ * current node linked to pnP as left child if pnP != NULL
+ * pTree->node_next advanced
+ *
+ * Returns pointer to node just allocated
+ *
+ * The evaluation of this node will result in
+ *
+ * ab = (ap * vbpoff) + *(*(ap +vbpoff) + vbdisp)
+ * where
+ * ab = address of base class
+ * ap = current address point
+ */
+
+
+LOCAL pnode_t
+AddETExpr (
+ pnode_t pnP,
+ CV_typ_t vbptr,
+ OFFSET vbpoff,
+ OFFSET vbdisp,
+ CV_typ_t btype
+ )
+{
+ pnode_t pn;
+ padjust_t pa;
+
+ pn = (pnode_t)(((char *)pTree) + pTree->node_next);
+ pa = (padjust_t)(&pn->v[0]);
+ _fmemset (pn, 0, sizeof (node_t) + sizeof (adjust_t));
+ NODE_OP (pn) = OP_thisexpr;
+ pa->btype = btype;
+ pa->disp = vbdisp;
+ pa->vbpoff = vbpoff;
+ pa->vbptr = vbptr;
+ if (pnP != NULL) {
+ NODE_LCHILD (pnP) = bnodeOfpnode(pn);
+ }
+ pTree->node_next += sizeof (node_t) + sizeof (adjust_t);
+ return (pn);
+}
+
+
+
+
+/*** AddVBList - Add virtual bases to searched or dominated list
+ *
+ * status = AddVBList (pSymClass, ppList, phMem)
+ *
+ * Entry pSymClass = pointer to base class path list structure
+ * ppList = pointer to dominated or searched list
+ * phMem = pointer to handle for ppList
+ *
+ * Exit virtual bases added to list
+ *
+ * Return SCN_found if all bases added to list
+ * SCN_error if bases could not be added
+ */
+
+
+LOCAL SCN_t
+AddVBList (
+ psymclass_t pSymClass,
+ pdombase_t *ppList,
+ HDEP * phList
+ )
+{
+ ushort cnt; // count of number of elements in struct
+ HTYPE hField; // handle to type record for struct field list
+ char *pField; // pointer to field list
+ uint fSkip = 0; // offset in the field list
+ uint anchor; // offset in the field list to start of type
+ CV_typ_t newindex;
+ ushort retval = SCN_found;
+ bool_t termflag = FALSE;
+ peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
+ ushort pad;
+
+ // set hField to the handle of the field list for the class
+
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+
+ // walk field list for the class
+
+ for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
+ if ((pad = *(((char *)pField) + fSkip)) >= LF_PAD0) {
+ // there is a pad field
+ fSkip += pad & 0x0f;
+ }
+ anchor = fSkip;
+ switch (((plfEasy)(pField + fSkip))->leaf) {
+ case LF_INDEX:
+ // switch to new type record because compiler split it up
+ newindex = ((plfIndex)(pField + fSkip))->index;
+ MHOmfUnLock (hField);
+ if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
+ pExState->err_num = ERR_INTERNAL;
+ return (SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
+ fSkip = 0;
+ // the LF_INDEX is not part of the field count
+ cnt++;
+ break;
+
+ case LF_BCLASS:
+ // skip direct base class
+ fSkip += offsetof (lfBClass, offset[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ break;
+
+ case LF_VBCLASS:
+ case LF_IVBCLASS:
+ newindex = ((plfVBClass)(pField + fSkip))->index;
+ if ((retval = AddVBType (ppList, phList, newindex)) == SCN_error) {
+ termflag = TRUE;
+ break;
+ }
+ fSkip += offsetof (lfVBClass, vbpoff[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ RNumLeaf (pField + fSkip, &fSkip);
+ break;
+
+ default:
+ termflag = TRUE;
+ break;
+ }
+ if (termflag == TRUE) {
+ break;
+ }
+ }
+ MHOmfUnLock (hField);
+ return (retval);
+}
+
+
+
+/*** AddVBType - Add virtual base to list
+ *
+ * status = AddVBType (ppList, phList, type)
+ *
+ * Entry ppList = pointer to dominated or searched list
+ * phList = pointer to handle for ppList
+ * type = type index
+ *
+ * Exit type added to list
+ *
+ * Return SCN_found if all bases added to list
+ * SCN_error if bases could not be added
+ */
+
+
+LOCAL SCN_t
+AddVBType (
+ pdombase_t *ppList,
+ HDEP *phList,
+ CV_typ_t type
+ )
+{
+ ushort i;
+ bool_t add = TRUE;
+ ushort len;
+ pdombase_t pList = *ppList;
+
+ for (i = 0; i < pList->CurIndex; i++) {
+ if (type == pList->dom[i]) {
+ add = FALSE;
+ break;
+ }
+ }
+ if (add == TRUE) {
+ if (pList->CurIndex >= pList->MaxIndex) {
+ len = sizeof (dombase_t) + (pList->MaxIndex + 10) * sizeof (CV_typ_t);
+ MHMemUnLock (*phList);
+ if ((*phList = MHMemReAlloc (*phList, len)) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ pList = MHMemLock (*phList);
+ return (SCN_error);
+ }
+ else {
+ pList = MHMemLock (*phList);
+ pVBDom->MaxIndex += 10;
+ }
+ }
+ pList->dom[pList->CurIndex++] = type;
+ }
+ return (SCN_found);
+}
+
+
+/** AmbFromList - add get next ambiguous symbol from list
+ *
+ * status = AmbFromList (pName)
+ *
+ * Entry pName = pointer to list describing search
+ *
+ * Exit breakpoint added to list of breakpoints
+ * pName reset to continue breakpoint search
+ *
+ * Returns HR_found if breakpoint added
+ * HR_error if breakpoint could not be added to list
+ */
+
+
+LOCAL ushort
+AmbFromList (
+ psearch_t pName
+ )
+{
+ psearch_t pBPatch;
+
+ pBPatch = MHMemLock (hBPatch);
+ *pName = *pBPatch;
+ MHMemUnLock (hBPatch);
+ pName->pv = &(pnodeOfbnode(pName->bn)->v[0]);
+ EVAL_HSYM (pName->pv) = pName->hSym;
+ if ((SymToNode (pName) == TRUE) && (PushStack (pName->pv) == TRUE)) {
+ return (HR_found);
+ }
+ else {
+ return (HR_error);
+ }
+}
+
+
+
+
+/** AmbToList - add ambiguous symbol to list
+ *
+ * fSuccess = AmbToList (pName)
+ *
+ * Entry pName = pointer to list describing search
+ *
+ * Exit ambiguous symbol added to list pointed to by pTMList
+ * pTMLbp
+ *
+ * Returns TRUE if symbol added
+ * FALSE if error
+ */
+
+
+LOCAL bool_t
+AmbToList (
+ psearch_t pName
+ )
+{
+ HDEP hBPatch;
+ psearch_t pBPatch;
+
+ if (iBPatch >= (USHORT)pTMLbp->cTMListMax) {
+ // the back patch list has filled the TM list
+ if (!GrowTMList ()) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ }
+ if ((hBPatch = MHMemAllocate (sizeof (search_t))) != 0) {
+ pTMList[iBPatch++] = hBPatch;
+ pBPatch = MHMemLock (hBPatch);
+ *pBPatch = *pName;
+ MHMemUnLock (hBPatch);
+ return (TRUE);
+ }
+ else {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+}
+
+
+
+
+/** ClAmbToList - add class ambiguous symbol to list
+ *
+ * status = ClAmbToList (pName)
+ *
+ * Entry pName = pointer to list describing search
+ *
+ * Exit ambiguous symbol added to list pointed to by pTMList
+ * pTMLbp
+ * pName reset to continue breakpoint search
+ *
+ * Returns HR_... describing state
+ */
+
+
+LOCAL HR_t
+ClAmbToList (
+ psearch_t pName
+ )
+{
+ HDEP hSearch;
+ psearch_t pSearch;
+ HR_t retval;
+ HDEP hevalT;
+
+ PopStack ();
+ if (pExState->ambiguous == 0) {
+ // this is the first breakpoint symbol found.
+ // indicate the only node in the tree that is
+ // allowed ambiguity and initialize list of
+ // symbols for later back patching into duplicated
+ // expression trees. We save the initial search packet
+ // so that the first symbol will be set into the breakpoint
+ // list.
+
+ pExState->ambiguous = pName->bn;
+ if ((hSearch = MHMemAllocate (sizeof (search_t))) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (HR_error);
+ }
+ if ((hSearch = MHMemAllocate (sizeof (eval_t))) == 0) {
+ MHMemFree (hSearch);
+ pExState->err_num = ERR_NOMEMORY;
+ return (HR_error);
+ }
+ pSearch = MHMemLock (hSearch);
+ *pSearch = *pName;
+ pSearch->pv = (peval_t)MHMemLock (hevalT);
+ retval = SearchSym (pSearch);
+ PushStack (pName->pv);
+ MHMemUnLock (hSearch);
+ MHMemFree (hSearch);
+ MHMemUnLock (hevalT);
+ MHMemFree (hevalT);
+ return (retval);
+ }
+ else if (pExState->ambiguous != pName->bn) {
+ // there has already been a ambiguous symbol that is
+ // not at this node in the tree
+
+ pExState->err_num = ERR_BPAMBIGUOUS;
+ return (HR_error);
+ }
+ else {
+ if (AmbToList (pName) == FALSE) {
+ return (HR_error);
+ }
+ // reset search to allow more symbols
+ pName->possibles = 0;
+ return (SearchSym (pName));
+ }
+}
+
+
+
+
+/** DupSymCl - duplicate symbol class structure and link to list
+ *
+ * DupSymCl (pName);
+ *
+ * Entry pName = handle of structure describing search
+ * *pSymClass = symbol class structure
+ *
+ * Exit *pSymClass = duplicated and linked to list pName->hFound
+ * pSymClass->s.viable = FALSE
+ *
+ * Returns SCN_found if pSymClass duplicated
+ * SCN_error if unable to allocate memory for duplication
+ */
+
+
+LOCAL SCN_t
+DupSymCl (
+ psearch_t pName
+ )
+{
+ HDEP hSymCl;
+ psymclass_t pSymCl;
+ ushort size;
+
+ size = (ushort) (sizeof (symclass_t) + (pSymClass->CurIndex + 1) * sizeof (symbase_t));
+ if ((hSymCl = MHMemAllocate (size)) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (SCN_error);
+ }
+ pSymCl = MHMemLock (hSymCl);
+ _fmemmove (pSymCl, pSymClass, size);
+ pSymCl->MaxIndex = (ushort)(pSymCl->CurIndex + 1);
+ pSymCl->hNext = pName->hFound;
+ pName->hFound = hSymCl;
+ pName->cFound++;
+ pSymClass->s.viable = FALSE;
+ MHMemUnLock (hSymCl);
+ return (SCN_found);
+}
+
+
+
+
+/** FindIntro - find introducing virtual method
+ *
+ * status = FindIntro (pName)
+ *
+ * Entry pName = structure describing search
+ * pSymClass = structure describing class search
+ *
+ * Exit pSymClass updated to reflect introducing virtual method
+ *
+ * Returns SCN_found if introducing virtual method found
+ * SCN_error if introducing virtual method not found
+ */
+
+
+LOCAL SCN_t
+FindIntro (
+ psearch_t pName
+ )
+{
+ ushort oldmask;
+ SCN_t retval;
+
+ oldmask = pName->clsmask;
+
+ // limit searches to introducing virtual methods
+ // the CLS_vfunc is set so that we pick up the vfuncptr information
+
+ pName->clsmask = CLS_virtintro | CLS_vfunc | CLS_method;
+ retval = SearchBases (pName);
+ pName->clsmask = oldmask;
+ return (retval);
+}
+
+
+
+
+/*** GenQualName - generate qualified method name
+ *
+ * handle = GenQualName (pName, pSymClass)
+ *
+ * Entry pSymCLass = pointer to struct describing search
+ *
+ * Exit qualified function name generated
+ *
+ * Returns 0 if name string not generated
+ * handle if name string generated
+ */
+
+
+LOCAL HDEP
+GenQualName (
+ psearch_t pName,
+ psymclass_t pSymCl
+ )
+{
+ HDEP hQual;
+ char *pQual;
+ uint buflen = 255;
+ uint len;
+ uint fSkip;
+ char *pField; // pointer to field list
+ HTYPE hBase; // handle to type record for base class
+ char *pc;
+ short i;
+ peval_t pL;
+
+ if ((hQual = MHMemAllocate (buflen + 1)) == 0) {
+ // unable to allocate memory
+ pExState->err_num = ERR_NOMEMORY;
+ return (0);
+ }
+ pQual = MHMemLock (hQual);
+ _fmemset (pQual, 0, 256);
+
+ // walk up list of search structures adding qualifiers
+
+ for (i = 0; i <= pSymCl->CurIndex; i++) {
+ if (CLASS_PROP (&pSymCl->symbase[i].Base).cnested == TRUE) {
+ NOTTESTED (FALSE);
+ }
+ if ((pSymCl->symbase[i].clsmask & CLS_virtintro) != 0) {
+ // if the search turned into a search for the introducing virtual
+ // function, break out of this loop so that the method name is
+ // correct
+
+ break;
+ }
+ pL = &pSymCl->symbase[i].Base;
+ }
+
+ // copy name of last class encountered
+
+ if ((hBase = THGetTypeFromIndex (EVAL_MOD (pL), EVAL_TYP (pL))) == 0) {
+ pExState->err_num = ERR_INTERNAL;
+ return (HDEP)(SCN_error);
+ }
+ pField = (char *)(&((TYPPTR)MHOmfLock ((HDEP)hBase))->leaf);
+ switch (((plfClass)pField)->leaf) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ fSkip = offsetof (lfClass, data[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ pc = pField + fSkip;
+ break;
+
+ case LF_UNION:
+ fSkip = offsetof (lfUnion, data[0]);
+ RNumLeaf (pField + fSkip, &fSkip);
+ pc = pField + fSkip;
+ break;
+
+ default:
+ DASSERT (FALSE);
+ MHOmfUnLock ((HDEP)hBase);
+ MHMemUnLock (hQual);
+ return (hQual);
+ }
+ len = *pc++;
+ if ((len + 2) <= buflen) {
+ _fmemcpy (pQual, pc, len);
+ pQual += len;
+ *pQual++ = ':';
+ *pQual++ = ':';
+ buflen -= len + 2;
+ }
+ _fmemcpy (pQual, pName->sstr.lpName, pName->sstr.cb);
+ MHOmfUnLock ((HDEP)hBase);
+ MHMemUnLock (hQual);
+ return (hQual);
+}
+
+
+
+
+/*** pvThisFromST - generate expression for null path to qualified name
+ *
+ * status = pvThisFromST (bnOp)
+ *
+ * Entry bnOp = node to add init expression to
+ *
+ * Exit qualified path expression generated
+ *
+ * Returns TRUE if expression generated
+ * FALSE if no memory
+ */
+
+
+bool_t
+pvThisFromST (
+ bnode_t bnOp
+ )
+{
+ uint len;
+ pnode_t Parent;
+ peval_t pvOp;
+ int diff;
+
+ if (ST == NULL) {
+ return (FALSE);
+ }
+
+ // we need to generate an expression tree attached to the operator node
+ // which will compute the null this pointer adjustment from ST. This
+ // routine is used for pClass->Class::member
+
+ len = sizeof (node_t) + sizeof (adjust_t);
+ if ((diff = pTree->size - pTree->node_next - len) < 0) {
+ if (!GrowETree ((uint) (-diff))) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ if (bnCxt != 0) {
+ // the context was pointing into the expression tree.
+ // since the expression tree could have been reallocated,
+ // we must recompute the context pointer
+
+ pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
+ }
+ }
+ pvOp = &pnodeOfbnode(bnOp)->v[0];
+ EVAL_IS_MEMBER (pvOp) = TRUE;
+ MEMBER_THISEXPR (pvOp) = pTree->node_next;
+ Parent = NULL;
+
+ // now add the node that causes pvThis to be initialized with the
+ // value of ST.
+
+ AddETInit (Parent, EVAL_TYP (ST));
+ return (TRUE);
+}
+
+
+
+
+/*** GenQualExpr - generate expression for path to qualified name
+ *
+ * status = GenQualExpr (pName)
+ *
+ * Entry pName = pointer to struct describing search
+ * pSymClass = pointer to class path structure
+ *
+ * Exit qualified path expression generated
+ *
+ * Returns SCN_found is expression generated
+ * SCN_error if no memory
+ */
+
+
+LOCAL SCN_t
+GenQualExpr (
+ psearch_t pName
+ )
+{
+ short i;
+ peval_t pvOp;
+ uint len;
+ pnode_t Parent;
+ int diff;
+ peval_t pvB;
+ CV_typ_t btype;
+ OFFSET off;
+ uint pvOff = 0;
+
+ // we need to generate an expression tree attached to the operator node
+ // which will compute the this pointer adjustment. The number
+ // of nodes is potentially the number of base classes + an
+ // initializer.
+
+ // M00OPTIMIZE - if the final base is a direct or indirect virtual base
+ // M00OPTIMIZE - of the inital class, then the entire expression can be
+ // M00OPTIMIZE - reduced to one node + the initializer
+
+ len = (pSymClass->CurIndex + 2) * (sizeof (node_t) + sizeof (adjust_t));
+ pvOp = &(pnodeOfbnode(pName->bnOp)->v[0]);
+ if ((diff = pTree->size - pTree->node_next - len) < 0) {
+ if (((char *)(pName->pv) >= (char *)pTree) &&
+ ((char *)(pName->pv) < ((char *)pTree) + pTree->size)) {
+ pvOff = ((char *)pName->pv) - ((char *)pTree);
+ }
+ if (!GrowETree ((uint) (-diff))) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (SCN_error);
+ }
+ if (bnCxt != 0) {
+ // the context was pointing into the expression tree.
+ // since the expression tree could have been reallocated,
+ // we must recompute the context pointer
+
+ pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
+ }
+ if (pvOff != 0) {
+ pName->pv = (peval_t)(((char *)pTree) + pvOff);
+ }
+ pvOp = &(pnodeOfbnode(pName->bnOp)->v[0]);
+ }
+
+ // walk the path backwards generating the expression required to do
+ // the adjustment. The backwards walk is because evaluation is depth
+ // first.
+
+ MEMBER_THISEXPR (pvOp) = pTree->node_next;
+ Parent = NULL;
+ for (i = pSymClass->CurIndex; i > 0; i--) {
+ pvB = &pSymClass->symbase[i].Base;
+ btype = EVAL_TYP (pvB);
+ off = pSymClass->symbase[i].thisadjust;
+ if (pSymClass->symbase[i].virtual == TRUE) {
+ Parent = AddETExpr (Parent, pSymClass->symbase[i].vbptr,
+ pSymClass->symbase[i].vbpoff, off, btype);
+ }
+ else {
+ Parent = AddETConst (Parent, off, btype);
+ }
+ }
+
+ // add the first real adjustment if necessary. What is really happening
+ // here is that the the expression was of the form x.CLASS::member and
+ // we need an adjustment from the object to the start of the base class
+
+ pvB = &pSymClass->evalP;
+ btype = EVAL_TYP (pvB);
+ if ((EVAL_STATE (pvB) == EV_type) && EVAL_IS_CLASS (pvB)) {
+ Parent = AddETConst (Parent, pSymClass->offset, btype);
+ }
+
+ // now add the node that causes pvThis to be initialized with the
+ // value of ST.
+
+ pvB = &pSymClass->symbase[i].Base;
+ btype = EVAL_TYP (pvB);
+ Parent = AddETInit (Parent, btype);
+ return (SCN_found);
+}
+
+
+
+
+/** GetArgType - get type of argument to function
+ *
+ * fSuccess = GetArgType (pvF, argn, ptype);
+ *
+ * Entry pvF = pointer to function description
+ * argn = argument index (0-based)
+ * ptype = pointer to location to store type
+ *
+ * Exit *ptype = type of argument
+ * *ptype = 0 if vararg
+ *
+ * Returns FARG_error if error
+ * FARG_none if no arguments
+ * FARG_vararg if varargs allowed
+ * FARG_exact if exact list
+ */
+
+
+farg_t
+GetArgType (
+ peval_t pvF,
+ short argn,
+ CV_typ_t *type
+ )
+{
+ HTYPE hList; // handle of the type list
+ plfArgList pList = NULL;
+ register farg_t retval;
+
+ if (FCN_PCOUNT (pvF) == 0) {
+ // there are no formals. We need to check for varargs
+
+ *type = 0;
+ if (FCN_VARARGS (pvF) == TRUE) {
+ return (FARG_vararg);
+ }
+ else {
+ return (FARG_none);
+ }
+ }
+
+ // set hList to the handle of the type list
+
+ if ((hList = THGetTypeFromIndex (EVAL_MOD (pvF), FCN_PINDEX (pvF))) == HNULL) {
+ DASSERT (FALSE);
+ return (FARG_error);
+ }
+ if (argn >= FCN_PCOUNT (pvF) - 1) {
+ // this argument can possibly be a vararg.
+
+ if (FCN_VARARGS (pvF) == TRUE) {
+ *type = 0;
+ retval = FARG_vararg;
+ }
+ else if (argn > FCN_PCOUNT (pvF)) {
+ // varargs are not allowed and the maximum arg count is exceeded
+ retval = FARG_error;
+ }
+ else {
+ // varargs are not allowed and this is the last argument
+ pList = (plfArgList)(&((TYPPTR)MHOmfLock ((HDEP)hList))->leaf);
+ *type = pList->arg[argn];
+ retval = FARG_exact;
+ }
+ }
+ else {
+ // this is before the last argument so it cannot be a vararg
+ // load type list and store type of argument
+
+ pList = (plfArgList)(&((TYPPTR)MHOmfLock ((HDEP)hList))->leaf);
+ *type = pList->arg[argn];
+ retval = FARG_exact;
+ }
+ if (pList != NULL) {
+ MHOmfUnLock ((HDEP)hList);
+ }
+ return (retval);
+}
+
+
+
+
+/** VBSearched - check to see if virtual base hase already been searched
+ *
+ * flag = VBSearched (type)
+ *
+ * Entry type = type index of virtual base
+ *
+ * Exit none
+ *
+ * Returns TRUE if virtual base has already been searched
+ * FALSE if virtual base has not been searched
+ */
+
+
+LOCAL bool_t
+VBSearched (
+ CV_typ_t type
+ )
+{
+ ushort i;
+
+ for (i = 0; i < pVBSearch->CurIndex; i++) {
+ if (pVBSearch->dom[i] == type) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+
+
+
+
+/** GrowTMList - grow TML
+ *
+ * fSuccess = GrowTMList (void)
+ *
+ * Entry pTMLbp = pointer to TML
+ * pTMList = pointer to TM list
+ *
+ * Exit TML grown
+ * pTMList = pointer to locked table
+ *
+ * Returns TRUE if table grown
+ * FALSE if out of memory
+ */
+
+
+LOCAL bool_t
+GrowTMList(
+ void
+ )
+{
+ register bool_t retval = FALSE;
+
+ MHMemUnLock (pTMLbp->hTMList);
+ if ((pTMLbp->hTMList = MHMemReAlloc (pTMLbp->hTMList,
+ (pTMLbp->cTMListMax + TMLISTCNT) * sizeof (HTM))) != 0) {
+ pTMLbp->cTMListMax += TMLISTCNT;
+ retval = TRUE;
+ }
+ // lock list to maintain lock/unlock synchronization
+
+ pTMList = MHMemLock (pTMLbp->hTMList);
+ return (retval);
+}
+
+
+
+
+/** IncrSymBase - increment symbase_t index and grow if necessary
+ *
+ * status = IncrSymbase ();
+ *
+ * Entry none
+ *
+ * Exit *pSymClass->CurIndex incremented
+ * pSymBase grown if necessary
+ *
+ * Returns SCN_found if pSymClass->CurIndex incremented
+ * SCN_error if unable to allocate memory for duplication
+ */
+
+
+LOCAL SCN_t
+IncrSymBase (
+ void
+ )
+{
+ uint size;
+
+ if (++pSymClass->CurIndex >= pSymClass->MaxIndex) {
+ size = sizeof (psymclass_t) + (pSymClass->CurIndex + 5) * sizeof (symbase_t);
+ MHMemUnLock (hSymClass);
+ if ((hSymClass = MHMemReAlloc (hSymClass, size)) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ pSymClass = MHMemLock (hSymClass);
+ pSymClass->CurIndex--;
+ return (SCN_error);
+ }
+ pSymClass = MHMemLock (hSymClass);
+ pSymClass->MaxIndex += 5;
+ }
+ return (SCN_found);
+}
+
+
+
+/** IsDominated - check to see of feature is dominated
+ *
+ * fStatus = IsDominated (pSymBest, pSymTest)
+ *
+ * Entry pName = structure describing search
+ * pSymClass = structure describing most recent class search
+ *
+ * Exit pName updated to reflect search
+ * pSymClass updated to unambiguous feature
+ *
+ * Returns DOM_replace if pSymBest is dominated by pSymTest
+ * DOM_keep if pSymBest is exactly equivalent to pSymTest
+ * DOM_ambiguous if pSymBest is equal to pSymTest
+ * DOM_keep if pSymTest is duplicate virtual base
+ */
+
+
+LOCAL DOM_t
+IsDominated (
+ psymclass_t pSymBest,
+ psymclass_t pSymTest
+ )
+{
+ short i;
+ short j;
+
+ if (pSymBest->s.isdupvbase == TRUE) {
+ return (DOM_replace);
+ }
+ if (pSymTest->s.isdupvbase == TRUE) {
+ return (DOM_keep);
+ }
+
+ // check all of the base classes for a dominated virtual base
+
+ for (i = 0; i <= pSymBest->CurIndex; i++) {
+ if (pSymBest->symbase[i].virtual == TRUE) {
+ for (j = pVBDom->CurIndex; j >= 0; j--) {
+ if (pVBDom->dom[j] == EVAL_TYP (&pSymBest->symbase[i].Base)) {
+ return (DOM_replace);
+ }
+ }
+ }
+ }
+ for (i = 0; i <= pSymTest->CurIndex; i++) {
+ if (pSymTest->symbase[i].virtual == TRUE) {
+ for (j = pVBDom->CurIndex; j >= 0; j--) {
+ if (pVBDom->dom[j] == EVAL_TYP (&pSymTest->symbase[i].Base)) {
+ return (DOM_keep);
+ }
+ }
+ }
+ }
+
+ // we have two paths to potentially two different features. We now check
+ // to see if the features are identical. This is done by checking for
+ // static data members that have identical addresses and types
+
+ if (!EVAL_IS_STMEMBER (&pSymBest->evalP) ||
+ !EVAL_IS_STMEMBER (&pSymTest->evalP) ||
+ (EVAL_TYP (&pSymBest->evalP) != EVAL_TYP (&pSymTest->evalP)) ||
+ (EVAL_SYM_SEG (&pSymBest->evalP) != EVAL_SYM_SEG (&pSymTest->evalP)) ||
+ (EVAL_SYM_OFF (&pSymBest->evalP) != EVAL_SYM_OFF (&pSymTest->evalP))) {
+ return (DOM_ambiguous);
+ }
+ return (DOM_keep);
+}
+
+
+
+/** IsIntroVirt - is this the introducing virtual method
+ *
+ * fSuccess = IsIntroVirt (count, mlist, pvtabindex)
+ *
+ * Entry count = number of methods in list
+ * mlist = type index of method list
+ * pvtabind = pointer to virtual function table index
+ *
+ * Exit *pvtabind = virtual fuction table index
+ *
+ * Returns TRUE if the introducing virtual method is found
+ * FALSE otherwise
+ */
+
+
+LOCAL bool_t
+IsIntroVirt (
+ ushort count,
+ CV_typ_t mlist,
+ ushort *vtabind)
+{
+ HTYPE hMethod;
+ pmlMethod pMethod;
+ plfMFunc pMFunc;
+ uint skip;
+ CV_fldattr_t attr;
+ CV_typ_t type;
+ bool_t Mmatch = 0;
+ peval_t pvF;
+ HMOD hMod;
+ bool_t retval;
+
+ pvF = &pSymClass->evalP;
+ hMod = EVAL_MOD (pvF);
+
+ // we now walk the list of methods looking for a method with the same
+ // return type and argument list type
+
+ if ((hMethod = THGetTypeFromIndex (hMod, mlist)) == (HTYPE) NULL) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+
+ // set the number of methods overloaded on this name and the index into
+ // the method list
+
+ skip = 0;
+
+ while (count-- > 0) {
+ // lock the omf record, extract information for the current entry in
+ // the method list and increment to field for next method
+
+ pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1 + skip);
+ attr = pMethod->attr;
+ type = pMethod->index;
+ skip += sizeof (mlMethod);
+ if (pMethod->attr.mprop == CV_MTintro) {
+ *vtabind = (short)RNumLeaf (((char *)pMethod) + skip, &skip);
+ }
+ else {
+ *vtabind = 0;
+ }
+ MHOmfUnLock (hMethod);
+ if (attr.mprop == CV_MTintro) {
+ if ((hMethod = THGetTypeFromIndex (hMod, type)) == (HTYPE) NULL) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ pMFunc = (plfMFunc)((&((TYPPTR)MHOmfLock (hMethod))->leaf));
+ retval = (pMFunc->rvtype == FCN_RETURN (pvF)) &&
+ (pMFunc->arglist == FCN_PINDEX (pvF));
+ MHOmfUnLock (hMethod);
+ if (retval == TRUE) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+}
+
+
+
+LOCAL CV_typ_t
+SkipModifiers(
+ HMOD mod,
+ CV_typ_t type
+ )
+{
+ HTYPE hType;
+ plfModifier pType;
+
+ if (!CV_IS_PRIMITIVE (type)) {
+ hType = THGetTypeFromIndex (mod, type);
+ pType = (plfModifier)((&((TYPPTR)MHOmfLock (hType))->leaf));
+ while (pType->leaf == LF_MODIFIER) {
+ type = pType->type;
+ if (CV_IS_PRIMITIVE (type)) {
+ break;
+ }
+ MHOmfUnLock (hType);
+ hType = THGetTypeFromIndex (mod, type);
+ pType = (plfModifier)((&((TYPPTR)MHOmfLock (hType))->leaf));
+ }
+ }
+
+ MHOmfUnLock (hType);
+ return type;
+}
+
+
+/** MatchArgs - match a method against argument list
+ *
+ * flag = MatchArgs (pv, pName, fattr, vtabind, fForce)
+ *
+ * Entry pv = pointer to function descriptor
+ * pName = pointer to search structure
+ * attr = attribute if method
+ * vtabind = offset into vtable if virtual method
+ * fForce = TRUE if match on first (only) method is forced
+ * This is the case if bp method, no args and single
+ * method.
+ * BindingBP = TRUE if call is via ParseBP API entry
+ * if BindingBP is true, then only exact matches are allowed
+ * bArgList = based pointer to argument list
+ *
+ * Exit ST = resolved address of method
+ *
+ * Returns TRUE if a match was found or ambiguous references are allowed
+ * FALSE if no match or ambiguity not allowed
+ */
+
+
+LOCAL void
+MatchArgs (
+ peval_t pvM,
+ psearch_t pName,
+ CV_fldattr_t attr,
+ UOFFSET vtabind,
+ bool_t fForce
+ )
+{
+ pnode_t pnT;
+ pargd_t pa;
+ bool_t update;
+ argcounters current;
+ short argc;
+ CV_typ_t Ftype;
+ bool_t argmatch;
+ eval_t evalArg;
+ peval_t pvArg = &evalArg;
+ HTYPE hType;
+ plfModifier pType;
+
+ // walk down the formal list specified by pvM and the actual list
+ // specified by bArgList. Initialize the conversion counters to
+ // zero and set the index to varargs parameter to zero
+
+ argc = 0;
+ current.exact = 0;
+ current.implicit = 0;
+ current.varargs = 0;
+ argmatch = FALSE;
+ update = FALSE;
+ pnT = pnodeOfbnode(bArgList);
+
+ (pName->overloadCount)++;
+ if (fForce == TRUE) {
+ argmatch = TRUE;
+ update = TRUE;
+ }
+ else if (!N_EVAL_IS_FCN(pvM)) {
+ argmatch = TRUE;
+ current.exact = 0;
+ }
+ else while (TRUE) {
+ if (NODE_OP (pnT) == OP_endofargs) {
+ if ((argc == FCN_PCOUNT (pvM)) ||
+ ((argc >= (FCN_PCOUNT (pvM) - 1)) && (FCN_VARARGS (pvM) == TRUE))) {
+ argmatch = TRUE;
+ }
+ break;
+ }
+ if ((argc > FCN_PCOUNT (pvM)) && (FCN_VARARGS (pvM) == FALSE)) {
+ // this function cannot possibly be a match because the
+ // number of actuals is greater than the number of formals
+ // and the method does not allow varargs.
+
+ break;
+ }
+ switch (GetArgType (pvM, argc, &Ftype)) {
+ case FARG_error:
+ DASSERT (FALSE);
+ return;
+
+ case FARG_none:
+ // special case foo(void)
+ // sps 2/20/92
+ if ((argc == 0) && (pa->actual == T_VOID)) {
+ argmatch = TRUE;
+ goto argmatchloop;
+ }
+ return;
+
+ case FARG_vararg:
+ // varargs are allowed unless we are binding breakpoints
+ if (BindingBP == TRUE) {
+ return;
+ }
+ break;
+
+ case FARG_exact:
+ if ((argc + 1) > FCN_PCOUNT (pvM)) {
+ // we must exactly match the argument count and we
+ // have more arguments
+ return;
+ }
+ break;
+
+ }
+ argc++;
+
+ // pa points to the argument descriptor array in the OP_arg node
+
+ pa = (pargd_t)&(pnT->v[0]);
+ if (Ftype == 0) {
+ // all arguments from this point on are vararg
+ current.varargs = argc;
+ pa->current = OM_vararg;
+ }
+#if 1
+ else {
+ CV_typ_t Atype = pa->actual;
+ eval_t vA, vF;
+ peval_t pvA = &vA;
+ peval_t pvF = &vF;
+
+ if (pa->flags.istype) {
+ // If we have a type want identical type indices
+ // (This helps with class dumps)
+ if (Atype == Ftype) {
+ current.exact++;
+ pa->current = OM_exact;
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ continue;
+ }
+ else {
+ pExState->err_num = ERR_NONE;
+ break;
+ }
+ }
+
+ Ftype = SkipModifiers(EVAL_MOD(pvM), Ftype);
+ Atype = SkipModifiers(EVAL_MOD(pvM), Atype);
+
+ *pvF = *pvM;
+ if (!SetNodeType(pvF, Ftype)) {
+ // error (not valid type)
+ break;
+ }
+
+ // Update Ftype (SetNodeType must have resolved potential fwd refs)
+ Ftype = EVAL_TYP (pvF);
+
+ // if we are calling a 32 bit func we must promote all const
+ // int2's to int4's
+
+ if (EVAL_SYM_IS32(pvM) &&
+ (EVAL_STATE((peval_t)(&(pnodeOfbnode(NODE_LCHILD (pnT)))->v[0])) == EV_constant) &&
+ ((Atype == T_INT2) || (Atype == T_UINT2))
+ ) {
+ Atype++;
+ }
+
+ *pvA = *pvM;
+ if (!SetNodeType(pvA, Atype)) {
+ // error (not valid type)
+ break;
+ }
+
+
+ if (EVAL_IS_PTR(pvA) && EVAL_IS_REF(pvA)) {
+ Atype = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvA));
+ }
+
+ if (Atype == Ftype) {
+ current.exact++;
+ pa->current = OM_exact;
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ continue;
+ }
+
+ if (EVAL_IS_PTR(pvF)) {
+ *pvA = *pvM;
+ if (!SetNodeType(pvA, Atype)) {
+ // error (not valid type)
+ break;
+ }
+ if (!EVAL_IS_REF(pvF)) {
+ if (!EVAL_IS_PTR(pvA)) {
+ // do not cast a non-pointer to pointer
+ break;
+ }
+
+ PTR_UTYPE(pvA) = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvA));
+ PTR_UTYPE(pvF) = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvF));
+
+ if (EVAL_PTRTYPE(pvA) == EVAL_PTRTYPE(pvF) &&
+ PTR_UTYPE(pvA) == PTR_UTYPE(pvF) &&
+ !EVAL_IS_BASED(pvA) &&
+ !EVAL_IS_BASED(pvF)) {
+
+ // we don't match based pointers. if we want to
+ // do this we must examine additional information
+ // we allow mathcing a pointer with an array
+ // however all arrays are considered far
+ // since codeview information does not distinguish
+ // between far or near arrays. --gdp 10/16/92
+
+ current.exact++;
+ pa->current = OM_exact;
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ continue;
+ }
+ }
+ else {
+
+ //
+ // special handling of a reference
+ //
+
+ CV_typ_t Utype;
+
+ Utype = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE (pvF));
+ if (Utype == Atype) {
+ current.exact++;
+ pa->current = OM_exact;
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+
+ // see if we can cast the type of the actual to the type of
+ // the formal if we are not binding breakpoints. If we are
+ // binding breakpoints, only exact matches are allowed
+
+ *pvArg = *pvM;
+ SetNodeType (pvArg, pa->actual);
+ if (EVAL_IS_BITF (pvArg)) {
+ SetNodeType (pvArg, BITF_UTYPE (pvArg));
+ }
+ if (CastNode (pvArg, Ftype, Ftype)) {
+ pa->current = OM_implicit;
+ current.implicit++;
+ }
+ else {
+ pExState->err_num = ERR_NONE;
+ break;
+ }
+ }
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ }
+argmatchloop:
+
+#endif
+
+#if 0
+ else if (pa->actual == Ftype) {
+ current.exact++;
+ pa->current = OM_exact;
+ }
+ else {
+ /*
+ * we need to check to see if we have a modifier to the
+ * actual type
+ *
+ * Modifies we look for are:
+ *
+ * const foo
+ * volatile foo
+ *
+ * pointer to foo by reference (C++ call by reference)
+ */
+
+
+ if (!CV_IS_PRIMITIVE (Ftype)) {
+ hType = THGetTypeFromIndex (EVAL_MOD (pvM), Ftype);
+ DASSERT(hType != (HTYPE) NULL);
+ pType = (plfModifier)((&((TYPPTR)MHOmfLock ((HDEP)hType))->leaf));
+ if (pType->leaf == LF_MODIFIER) {
+ if (((pType->attr.MOD_const == TRUE) == (int) pa->flags.isconst) ||
+ ((pType->attr.MOD_volatile == TRUE) == (int) pa->flags.isvolatile) &&
+ (pType->type == Ftype)) {
+ current.exact++;
+ pa->current = OM_exact;
+ MHOmfUnLock((HDEP)hType);
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ continue;
+ }
+ } else {
+ if (pType->leaf == LF_POINTER) {
+ lfPointer * pType2 = (lfPointer *) pType;
+
+ if ((pType2->attr.ptrmode == CV_PTR_MODE_REF) &&
+ (pType2->utype == pa->actual)) {
+
+ current.exact++;
+ pa->current = OM_exact;
+ MHOmfUnLock((HDEP)hType);
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ continue;
+ }
+ }
+ }
+ MHOmfUnLock( (HDEP)hType );
+ }
+ if (pa->flags.istype == TRUE) {
+ // the formal argument is a type and exact match is required
+ break;
+ }
+ else {
+ // see if we can cast the type of the actual to the type of
+ // the formal if we are not binding breakpoints. If we are
+ // binding breakpoints, only exact matches are allowed
+
+ *pvArg = *pvM;
+ SetNodeType (pvArg, pa->actual);
+ if (EVAL_IS_BITF (pvArg)) {
+ SetNodeType (pvArg, BITF_UTYPE (pvArg));
+ }
+ if (CastNode (pvArg, Ftype, Ftype)) {
+ pa->current = OM_implicit;
+ current.implicit++;
+ }
+ else {
+ pExState->err_num = ERR_NONE;
+ break;
+ }
+ }
+ }
+ pnT = pnodeOfbnode(NODE_RCHILD (pnT));
+ }
+
+#endif
+
+ if (argmatch == TRUE) {
+ // check current against best match
+
+ if (pName->best.match == 0) {
+ // we have a first time match
+ update = TRUE;
+ pName->possibles++;
+ }
+ else if (fForce == FALSE) {
+ // we have already matched on some function so we now
+ // check to see if the current is better than the best
+ if (current.varargs == 0) {
+ // there are no varargs in this method therefor it is
+ // better than any previous match with varargs
+ if (pName->best.varargs != 0) {
+ update = TRUE;
+ pName->best = current;
+ pName->possibles = 1;
+ }
+ else if (current.exact > pName->best.exact) {
+ // this function has more exact matches than the
+ // best one so far
+ update = TRUE;
+ pName->possibles = 1;
+ }
+ else if (EVAL_TYP (pvM) != pName->best.match &&
+ current.exact == pName->best.exact) {
+ // this function is a good as the best one.
+ // this means the call is ambiguous
+ pName->possibles++;
+ }
+ }
+ else {
+ if (pName->best.varargs != 0) {
+ // both the current and the best functions have
+ // varargs
+
+ if (current.varargs < pName->best.varargs) {
+ // this function uses fewer varargs which
+ // makes it a better one
+ update = TRUE;
+ pName->possibles = 1;
+ }
+ else if (current.varargs == pName->best.varargs) {
+ // this function uses the same number of varargs
+ // pick the one with more exact matches
+ if (current.exact > pName->best.exact) {
+ update = TRUE;
+ pName->possibles = 1;
+ }
+ else if (EVAL_TYP (pvM) != pName->best.match &&
+ current.exact == pName->best.exact) {
+ pName->possibles++;
+ }
+ }
+ }
+ }
+ }
+ if (update == TRUE) {
+ if (fForce == FALSE) {
+ // the current match is better
+ for (pnT = pnodeOfbnode(bArgList); NODE_OP (pnT) != OP_endofargs; pnT = pnodeOfbnode(NODE_RCHILD (pnT))) {
+ pa = (pargd_t)&(pnT->v[0]);
+ pa->best = pa->current;
+ }
+ { //M00KLUDGE - hack for compiler DS != SS bug
+ argcounters *pcurrent = &current;
+ pName->best = *pcurrent;
+ }
+ }
+ pName->best.match = EVAL_TYP (pvM);
+ pName->best.attr = attr;
+ pName->best.vtabind = vtabind;
+ pName->best.hSym = pName->hSym;
+ }
+ }
+}
+
+
+
+
+/** MatchFunction - match a function against argument list
+ *
+ * flag = MatchFunction (pName)
+ *
+ * Entry pName = pointer to search status
+ * BindingBP = TRUE if call is via ParseBP API entry
+ * bArgList = based pointer to argument list
+ *
+ * Exit pv = resolved address of method
+ *
+ * Returns HR_... describing match result
+ */
+
+
+LOCAL HR_t __fastcall
+MatchFunction (
+ psearch_t pName
+ )
+{
+ HR_t retval;
+ CV_fldattr_t attr = {0};
+ CV_typ_t type;
+ ADDR addr;
+ bool_t dupfcn;
+
+ if (bArgList == 0) {
+ // if there is no argument list, assume we are assigning to a
+ // function pointer and take the first function found. Let the
+ // user beware.
+
+ return (HR_found);
+ }
+
+ // NOTENOTE -- jimsch -- don't search publics if something was found
+ // it is making all sorts of problems for me on MIPS
+
+ pName->scope &= ~SCP_global;
+
+ // save the function address and type. Then if a subsequent match has
+ // the same address and type (i.e., comdat code), we can ignore it.
+
+ addr = EVAL_SYM (ST);
+ type = EVAL_TYP (ST);
+
+ // pop the entry that SearchSym has added to the evaluation stack
+ // the best match will be pushed back on later
+
+ pName->scope |= SCP_nomatchfn;
+
+ PopStack ();
+ MatchArgs (pName->pv, pName, attr, 0, FALSE);
+ while ((retval = SearchSym (pName)) != HR_notfound) {
+ DASSERT (retval != HR_end);
+ dupfcn = FALSE;
+ if (retval == HR_found) {
+ if ((EVAL_TYP (ST) == type) &&
+ (_fmemcmp (&addr, &EVAL_SYM (ST), sizeof (addr)) == 0)) {
+ dupfcn = TRUE;
+ }
+ PopStack ();
+ if (dupfcn == FALSE) {
+ MatchArgs (pName->pv, pName, attr, 0, FALSE);
+ }
+ }
+ else {
+ return (retval);
+ }
+ }
+
+ pName->scope &= ~SCP_nomatchfn;
+
+ // clear the symbol not found error from the recursive symbol search
+
+ pExState->err_num = ERR_NONE;
+ if (pName->best.match == 0) {
+ pExState->err_num = ERR_ARGLIST;
+ return (HR_error);
+ }
+ else if (pName->possibles > 1) {
+ PushStack (pName->pv);
+ pExState->err_num = ERR_AMBIGUOUS;
+ EVAL_IS_AMBIGUOUS (ST) = TRUE;
+ return (HR_ambiguous);
+ }
+ else if (pName->overloadCount > 1 && pName->best.implicit > 0) {
+ //
+ // overloaded function that involves implicit casts
+ //
+ pExState->err_num = ERR_AMBIGUOUS;
+ return (HR_ambiguous);
+ }
+ else {
+ pName->hSym = pName->best.hSym;
+ if ((SymToNode (pName) == FALSE) || (PushStack (pName->pv) == FALSE)) {
+ return (HR_notfound);
+ }
+ else {
+ return (HR_found);
+ }
+ }
+}
+
+
+
+
+/** MatchMethod - match a method against argument list
+ *
+ * flag = MatchMethod (pName, pSymCl)
+ *
+ * Entry pName = pointer to search descriptor
+ * pSymCl = pointer tp symbol class structure
+ * select = selection masj
+ * BindingBP = TRUE if call is via ParseBP API entry
+ * if BindingBP is true, then only exact matches allowed
+ * bArgList = based pointer to argument list
+ *
+ * Exit pName->pv = resolved address of method
+ *
+ * Returns MTH_found if a match was found or ambiguous references are allowed
+ * MTH_error if error or ambiguity not allowed
+ *
+ */
+
+
+LOCAL MTH_t
+MatchMethod (
+ psearch_t pName,
+ psymclass_t pSymCl
+ )
+{
+ HTYPE hMethod;
+ pmlMethod pMethod;
+ uint skip;
+ eval_t evalM;
+ peval_t pvM = &evalM;
+ CV_fldattr_t attr;
+ CV_typ_t type;
+ ushort vtabind;
+ bool_t Mmatch = 0;
+ HDEP hQual;
+ peval_t pvF;
+ ushort count = pSymCl->possibles;
+ peval_t pvB;
+ HMOD hMod;
+ bool_t fForce = FALSE;
+
+ pvB = &pSymClass->symbase[pSymClass->CurIndex].Base;
+ hMod = EVAL_MOD (pvB);
+ pName->possibles = 0;
+
+ // we now walk the list of methods looking for an argument match
+ // For now, we require an exact match except that we assume any
+ // primitive type can be cast to any other primitive type. A cast from
+ // pointer to derived to pointer to base is an implicit conversion
+
+ if ((hMethod = THGetTypeFromIndex (hMod, pSymCl->mlist)) == (HTYPE)NULL) {
+ DASSERT (FALSE);
+ return (MTH_error);
+ }
+
+ // set the number of methods overloaded on this name and the index into
+ // the method list
+
+ skip = 0;
+// if ((BindingBP == TRUE) && (bArgList == 0))
+ if (bArgList == 0)
+ {
+ if (count == 1) {
+ fForce = TRUE;
+ }
+ else {
+ // there is not an argument list. We allow breakpoints if a single
+ // method by that name exists. Otherwise, we require an argument
+ // list
+
+ pExState->err_num = ERR_NOARGLIST;
+ return (MTH_error);
+ }
+ }
+ while (count-- > 0) {
+ // lock the omf record, extract information for the current entry in
+ // the method list and increment to field for next method
+
+ pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1);
+ pMethod = (pmlMethod)((uchar *)pMethod + skip);
+ attr = pMethod->attr;
+ type = pMethod->index;
+ skip += sizeof (mlMethod);
+ if (pMethod->attr.mprop == CV_MTintro) {
+ vtabind = (short)RNumLeaf (((char *)pMethod) + skip, &skip);
+ }
+ else {
+ vtabind = 0;
+ }
+ MHOmfUnLock (hMethod);
+
+ // now compare the actual and formal argument lists for the function
+ // pvM will be initialized to be a function node whose type index is
+ // type.
+
+ CLEAR_EVAL (pvM);
+ EVAL_MOD (pvM) = hMod;
+ if (SetNodeType (pvM, type) == FALSE) {
+ // the type record for the method was not found
+ DASSERT (FALSE);
+ return (MTH_error);
+ }
+ MatchArgs (pvM, pName, attr, vtabind, fForce);
+ }
+
+ // since the name was found at this level, it hides all other methods
+ // by the same name above it in the inheritance tree. Therefore we must
+ // either have a match or an error because there is no match or two or
+ // methods match after conversions are considered
+
+ if (pName->best.match == 0) {
+ pExState->err_num = ERR_ARGLIST;
+ return (MTH_error);
+ }
+ else if (pName->possibles > 1) {
+ pExState->err_num = ERR_AMBIGUOUS;
+ EVAL_IS_AMBIGUOUS (pName->pv) = TRUE;
+ return (MTH_error);
+ }
+ else if (pName->overloadCount > 1 && pName->best.implicit > 0) {
+ // we have an overloaded method
+ // in this case the EE requires exact matches only
+ pExState->err_num = ERR_AMBIGUOUS;
+ EVAL_IS_AMBIGUOUS (pName->pv) = TRUE;
+ return (MTH_error);
+ }
+ else {
+ // we have found a non-ambiguous match
+
+ pvF = &pSymCl->evalP;
+ EVAL_MOD (pvF) = hMod;
+ if (SetNodeType (pvF, pName->best.match) == FALSE) {
+ return (MTH_error);
+ }
+ else {
+ pSymCl->access.access = pName->best.attr.access;
+ FCN_ATTR (pvF) = pName->best.attr;
+ FCN_VTABIND (pvF) = pName->best.vtabind;
+ FCN_VFPTYPE (pvF) = pSymCl->vfpType;
+ if (NODE_OP (pnodeOfbnode(pName->bnOp)) == OP_bscope) {
+ // binary scoping switches off virtual function evaluation
+ FCN_PROPERTY (pvF) = CV_MTvanilla;
+ }
+ if ((FCN_PROPERTY (pvF) == CV_MTvirtual) ||
+ (FCN_PROPERTY (pvF) == CV_MTintro)) {
+ // do nothing. address will have to be found at evaluation
+ }
+ else {
+ if (((hQual = GenQualName (pName, pSymClass)) == 0) ||
+ (SearchQualName (pName, pSymCl, hQual, TRUE) == FALSE)) {
+ if (hQual != 0) {
+ MHMemFree (hQual);
+ }
+ return (MTH_error);
+ }
+ MHMemFree (hQual);
+ }
+ return (MTH_found);
+ }
+ }
+}
+
+
+
+
+/** MoveSymCl - move symbol class structure
+ *
+ * MoveSymCl (hSymCl);
+ *
+ * Entry hSymCl = handle of symbol class structure
+ *
+ * Exit *pSymClass = symbol class structure
+ *
+ * Returns none
+ */
+
+
+LOCAL void
+MoveSymCl (
+ HDEP hSymCl
+ )
+{
+ psymclass_t pSymCl;
+ ushort max;
+
+ pSymCl = MHMemLock (hSymCl);
+ DASSERT (pSymClass->MaxIndex >= pSymCl->CurIndex);
+ max = pSymClass->MaxIndex;
+ _fmemmove (pSymClass, pSymCl,
+ sizeof (symclass_t) + (pSymCl->CurIndex + 1) * sizeof (symbase_t));
+ pSymClass->MaxIndex = max;
+ MHMemUnLock (hSymCl);
+ MHMemFree (hSymCl);
+}
+
+
+
+
+/** PurgeAmbCl - purge ambiguous class structure list
+ *
+ * PurgeAmbCl (pName)
+ *
+ * Entry pName = pointer to symbol search structure
+ *
+ * Exit pname->hAmb list freed
+ *
+ * Returns none
+ */
+
+
+LOCAL void
+PurgeAmbCl (
+ psearch_t pName
+ )
+{
+ psymclass_t pAmbCl;
+ HDEP hNext;
+
+ while (pName->hAmbCl != 0) {
+ pAmbCl = MHMemLock (pName->hAmbCl);
+ hNext = pAmbCl->hNext;
+ MHMemUnLock (pName->hAmbCl);
+ pName->hAmbCl = hNext;
+ }
+}
+
+
+
+
+/*** SetBase - set base value in pSymClass->symbase array
+ *
+ * status = SetBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual)
+ *
+ * Entry pName = pointer to struct describing search
+ * type = type index of class
+ * vbptr = type index of virtual base pointer
+ * vbpoff = offset of virtual base pointer from address point
+ * thisadjust = offset of base from previous class
+ * thisadjust = virtual base index if virtual base
+ * attr = field attribute mask
+ * virtual = TRUE if virtual base
+ *
+ * Exit new base class added to pSymClass
+ *
+ * Returns enum describing search state
+ */
+
+
+LOCAL SCN_t
+SetBase (
+ psearch_t pName,
+ CV_typ_t type,
+ CV_typ_t vbptr,
+ OFFSET vbpoff,
+ OFFSET thisadjust,
+ CV_fldattr_t attr,
+ bool_t virtual
+ )
+{
+ peval_t pvB;
+
+ // save offset of base from address point for this pointer adjustment
+
+ pSymClass->symbase[pSymClass->CurIndex].thisadjust = thisadjust;
+ pSymClass->symbase[pSymClass->CurIndex].vbptr = vbptr;
+ pSymClass->symbase[pSymClass->CurIndex].vbpoff = vbpoff;
+ pSymClass->symbase[pSymClass->CurIndex].attrBC = attr;
+ pSymClass->symbase[pSymClass->CurIndex].virtual = virtual;
+ pSymClass->symbase[pSymClass->CurIndex].clsmask = pName->clsmask;
+ pvB = &pSymClass->symbase[pSymClass->CurIndex].Base;
+ EVAL_MOD (pvB) = pName->hMod;
+ if (SetNodeType (pvB, type) == FALSE) {
+ pExState->err_num = ERR_BADOMF;
+ return (SCN_error);
+ }
+ return (SCN_found);
+}
+
+
+
+
+/*** SearchQualName - Search for a qualified method name
+ *
+ * flag = SearchQualName (pName, pSymCl, hQual, fProc)
+ *
+ * Entry pName = pointer to struct describing search
+ * pSymCl = pointer to structure describing path to symbol
+ * hQual = handle to symbol name
+ * fProc = TRUE if proc symbol to be searched for
+ * fProc = FALSE if data to be searched for
+ *
+ * Exit pName updated to reflect search
+ *
+ * Return enum describing search
+ */
+
+
+LOCAL bool_t
+SearchQualName (
+ psearch_t pName,
+ psymclass_t pSymCl,
+ HDEP hQual,
+ bool_t fProc
+ )
+{
+ HDEP hTemp;
+ psearch_t pTemp;
+ uchar *pQual;
+ ushort retval;
+
+ if ((hTemp = MHMemAllocate (sizeof (search_t))) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ pTemp = MHMemLock (hTemp);
+ *pTemp = *pName;
+ pTemp->CXTT = *pCxt;
+
+ // set pointer to symbol name
+
+ pQual = (uchar *)MHMemLock (hQual);
+ pTemp->sstr.lpName = pQual;
+ pTemp->sstr.cb = (uchar)_fstrlen ((char *)pQual);
+ pTemp->state = SYM_init;
+ if (fProc == TRUE) {
+ pTemp->scope = SCP_module | SCP_global;
+ pTemp->sstr.searchmask |= SSTR_proc;
+ }
+ else {
+ pTemp->scope = SCP_module | SCP_global | SCP_lexical;
+ // data members may not be overloaded, hence there is
+ // no need for the type to qualify the name. Furthermore
+ // there are cases where the symbol type doesn't match
+ // the member type exactly (e.g. variable length arrays,
+ // symbol has actual length and member has zero length)
+ // hence this matching is suppressed for data items [rm]
+
+ // pTemp->sstr.searchmask |= SSTR_data;
+ }
+ pTemp->initializer = INIT_qual;
+ pTemp->typeOut = EVAL_TYP (&pSymCl->evalP);
+ retval = SearchSym (pTemp);
+ MHMemUnLock (hQual);
+ if (retval != HR_found) {
+#ifdef NEVER /* CAVIAR #1081 */
+ if ((retval != HR_end) && (pTemp->FcnBP != 0)) {
+// if (pTemp->FcnBP != 0) {
+ // there is another symbol with the same name but a different
+ // type. Since this is set only when we are binding breakpoints,
+ // let's go ahead and try it
+
+ pTemp->state = SYM_init;
+ pTemp->scope = SCP_module | SCP_global;
+ pTemp->sstr.searchmask |= SSTR_proc;
+ pTemp->typeOut = pTemp->FcnBP;
+ retval = SearchSym (pTemp);
+ }
+#endif
+ if (retval != HR_found) {
+ // the only way we can get here is if the method or data
+ // is declared in the class but is not defined or
+ // is a noninstianted inline method.
+ // therefore, we return a special error code
+
+ if (ST == NULL) {
+ // this is a hack to get around the case where the expression
+ // bp {,foo.c, foo.exe}X::f
+ // and the first function in the module foo is a method.
+ // SearchSym ended up calling the class search routines
+ // because the context is implicitly a class so class is
+ // searched even though it shouldn't be. Any fix for this
+ // causes problems and we are too close to release to find
+ // a valid fix. The major result of this fix is that
+ // some breakpoints will not get reset on entry.
+
+ return (FALSE);
+ }
+
+ PushStack (ST);
+ // if this is a missing static DATA member function then
+ // best.match won't have anything in it at all... we'll need
+ // to pick up what we want from typeOut which will have been
+ // set by a previous non-qualified name search... [rm]
+
+ if (pName->best.match == T_NOTYPE) {
+ SetNodeType (ST, pName->typeOut);
+ }
+ else {
+ SetNodeType (ST, pName->best.match);
+ }
+ if (EVAL_IS_FCN(ST)) {
+ FCN_NOTPRESENT (ST) = TRUE;
+ }
+ else {
+ // indicate missing static data member
+ EVAL_HSYM (ST) = 0;
+ pExState->state.fNotPresent = TRUE;
+ }
+// if (fProc) {
+// SetNodeType (ST, pName->best.match);
+// FCN_NOTPRESENT (ST) = TRUE;
+// }
+ }
+ }
+ // pop off the stack entry that a successful search found. Move the
+ // static data member flag first so that it will not be lost.
+
+ EVAL_IS_STMEMBER (ST) = EVAL_IS_STMEMBER (&pSymCl->evalP);
+ EVAL_ACCESS (ST) = (uchar)(pSymCl->access.access);
+ pSymCl->evalP = *ST;
+ MHMemUnLock (hTemp);
+ MHMemFree (hTemp);
+ return (PopStack ());
+}
+
+
+
+
+
+/** SymAmbToList - add ambiguous symbol to list
+ *
+ * status = SymAmbToList (pName)
+ *
+ * Entry pName = pointer to list describing search
+ *
+ * Exit ambiguous symbol added to list pointed to by pTMList
+ * pTMLbp
+ * pName reset to continue breakpoint search
+ *
+ * Returns HR_... describing state
+ */
+
+
+LOCAL HR_t
+SymAmbToList (
+ psearch_t pName
+ )
+{
+ HDEP hSearch;
+ psearch_t pSearch;
+ HR_t retval;
+ HDEP hevalT;
+
+ PopStack ();
+ if (pExState->ambiguous == 0) {
+ // this is the first breakpoint symbol found.
+ // indicate the only node in the tree that is
+ // allowed ambiguity and initialize list of
+ // symbols for later back patching into duplicated
+ // expression trees. We save the initial search packet
+ // so that the first symbol will be set into the breakpoint
+ // list.
+
+ pNameFirst = pName;
+ pExState->ambiguous = pName->bn;
+ if ((hSearch = MHMemAllocate (sizeof (search_t))) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (HR_error);
+ }
+ if ((hevalT = MHMemAllocate (sizeof (eval_t))) == 0) {
+ MHMemFree (hSearch);
+ pExState->err_num = ERR_NOMEMORY;
+ return (HR_error);
+ }
+ pSearch = MHMemLock (hSearch);
+ *pSearch = *pName;
+ pSearch->pv = (peval_t)MHMemLock (hevalT);
+ SHGoToParent (&pName->CXTT, &pSearch->CXTT);
+
+ // clear the newly allocated pv
+
+ _fmemset ( pSearch->pv, 0, sizeof (eval_t) );
+ retval = SearchSym (pSearch);
+ PushStack (pName->pv);
+ MHMemUnLock (hSearch);
+ MHMemFree (hSearch);
+ MHMemUnLock (hevalT);
+ MHMemFree (hevalT);
+ if (retval == HR_end) {
+ retval = HR_found;
+ }
+ return (retval);
+ }
+ else if (pExState->ambiguous != pName->bn) {
+ // there has already been a ambiguous symbol that is
+ // not at this node in the tree
+
+ pExState->err_num = ERR_BPAMBIGUOUS;
+ return (HR_error);
+ }
+ else {
+ if (CheckDupAmb (pName) == FALSE) {
+ // the function is not already in the ambiguity list
+
+ if (AmbToList (pName) == FALSE) {
+ return (HR_error);
+ }
+ }
+
+ // reset search to allow more symbols
+ pName->possibles = 0;
+ return (SearchSym (pName));
+ }
+}
+
+
+
+
+/** CheckDupAmb - check for duplicate ambiguity entry
+ *
+ * fSuccess = CheckDupAmb (pName)
+ *
+ * Entry pName = pointer to list describing search
+ *
+ * Exit none
+ *
+ * Returns TRUE if duplicate symbol found
+ * FALSE if duplicate symbol not found
+ */
+
+
+LOCAL bool_t
+CheckDupAmb (
+ psearch_t pName
+ )
+{
+ psearch_t pN;
+ ushort i;
+ bool_t fdup = FALSE;
+
+ if ((EVAL_TYP (pNameFirst->pv) == EVAL_TYP (pName->pv)) &&
+ (_fmemcmp ((void *)&EVAL_SYM (pNameFirst->pv), (void *)&EVAL_SYM (pName->pv),
+ sizeof (ADDR)) == 0)) {
+ return (TRUE);
+ }
+ for (i = 1; i < iBPatch; i++) {
+ pN = (psearch_t) MHMemLock (pTMList[i]);
+ if (pN->typeOut == EVAL_TYP (pName->pv) &&
+ (_fmemcmp ((void *)&pN->addr, (void *)&EVAL_SYM (pName->pv), sizeof (ADDR)) == 0)) {
+ fdup = TRUE;
+ }
+ MHMemUnLock (pTMList[i]);
+ if (fdup == TRUE) {
+ break;
+ }
+ }
+ return (fdup);
+}
+
+
+
+/** SymToNode - store symbol information in evaluation node
+ *
+ * fSuccess = SymToNode (hName)
+ *
+ * Entry pName = pointer to search state
+ *
+ * Exit type information and address data stored in value
+ * if the symbol is a typedef record, then the evaluation
+ * state will be set to EV_type. Otherwise, it will be set
+ * to EV_lvalue.
+ *
+ * Returns TRUE if variable was accessible
+ * FALSE if error
+ */
+
+
+LOCAL bool_t
+SymToNode (
+ psearch_t pName
+ )
+{
+ CV_typ_t typ;
+ ushort evalstate;
+ HSYM hSym;
+ peval_t pv = pName->pv;
+ PCXT pCXT = &pName->CXTT;
+ SYMPTR pSym;
+ ushort cmpThis = 1;
+ MEMINFO mi;
+
+ if ((hSym = pName->hSym) == NULL) {
+ // this symbol is found as a class member which means it does
+ // not have a symbol.
+
+ DASSERT (pName->typeOut != T_NOTYPE);
+ return (SetNodeType (pv, pName->typeOut));
+ }
+ EVAL_STATE (pv) = EV_lvalue;
+ EVAL_MOD (pv) = SHHMODFrompCXT (pCXT);
+ CLEAR_EVAL_FLAGS (pv);
+ EVAL_SYM_EMI (pv) = pCXT->addr.emi;
+ switch((pSym = MHOmfLock ((HDEP)hSym))->rectyp) {
+ case S_REGISTER:
+ EVAL_IS_REG (pv) = TRUE;
+ EVAL_REG (pv) = ((REGPTR)pSym)->reg;
+ typ = ((REGPTR)pSym)->typind;
+ cmpThis = strncmp ( (char *) &((REGPTR)pSym)->name[0],
+ (char *) &OpName[0], ((REGPTR)pSym)->name[0] + 1);
+ break;
+
+ case S_CONSTANT:
+ if (!DebLoadConst (pv, (CONSTPTR)pSym, hSym)) {
+ MHOmfUnLock ((HDEP)hSym);
+ return (FALSE);
+ }
+ EVAL_STATE (pv) = EV_constant;
+ typ = EVAL_TYP (pv);
+ break;
+
+
+ case S_UDT:
+ typ = ((UDTPTR)pSym)->typind;
+ EVAL_STATE (pv) = EV_type;
+ break;
+
+ case S_BLOCK16:
+ EVAL_SYM_SEG (pv) = ((BLOCKPTR16)pSym)->seg;
+ EVAL_SYM_OFF (pv) = ((BLOCKPTR16)pSym)->off;
+ typ = T_NOTYPE;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ NOTTESTED (FALSE); // not tested
+ break;
+
+ case S_LPROC16:
+ case S_GPROC16:
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ if ((typ = ((PROCPTR16)pSym)->typind) == T_NOTYPE) {
+ // this is a hack to allow breakpoints on untyped symbols
+ typ = T_PFUCHAR;
+ EVAL_SYM_OFF (pv) = ((PROCPTR16)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((PROCPTR16)pSym)->seg;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ EVAL_STATE (pv) = EV_rvalue;
+ }
+ else {
+ EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT);
+ EVAL_SYM_SEG (pv) = ((PROCPTR16)pSym)->seg;
+ EVAL_SYM_OFF (pv) = ((PROCPTR16)pSym)->off;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ }
+ break;
+
+ case S_LABEL16:
+ EVAL_IS_LABEL (pv) = TRUE;
+ EVAL_SYM_OFF (pv) = ((LABELPTR16)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((LABELPTR16)pSym)->seg;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ EVAL_STATE (pv) = EV_rvalue;
+ typ = T_PFUCHAR;
+ break;
+
+ case S_BPREL16:
+ EVAL_IS_BPREL (pv) = TRUE;
+ EVAL_SYM_OFF (pv) = ((BPRELPTR16)pSym)->off;
+ EVAL_SYM_SEG (pv) = 0;
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+ typ = ((BPRELPTR16)pSym)->typind;
+ pExState->state.bprel = TRUE;
+ cmpThis = strncmp ( (char *) &((BPRELPTR16)pSym)->name[0],
+ (char *) &OpName[0], ((BPRELPTR16)pSym)->name[0] + 1);
+ break;
+
+ case S_LDATA16:
+ pExState->state.fLData = TRUE;
+ EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg;
+ typ = ((DATAPTR16)pSym)->typind;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ break;
+
+ case S_GDATA16:
+ pExState->state.fGData = TRUE;
+ EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg;
+ typ = ((DATAPTR16)pSym)->typind;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ break;
+
+ case S_PUB16:
+ EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg;
+ EVAL_STATE (pv) = EV_lvalue;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ if ((typ = ((DATAPTR16)pSym)->typind) == T_NOTYPE) {
+ // this is a hack to allow breakpoints on untyped symbols
+ MEMINFO mi;
+ mi.addr = EVAL_SYM(pv);
+ SYGetMemInfo(&mi);
+ if ((mi.dwState & MEM_COMMIT)
+ && (mi.dwProtect & (PAGE_EXECUTE |
+ PAGE_EXECUTE_READ |
+ PAGE_EXECUTE_READWRITE |
+ PAGE_EXECUTE_WRITECOPY))
+ ) {
+ typ = T_PFUCHAR;
+ EVAL_STATE (pv) = EV_rvalue;
+ } else {
+ typ = T_UINT2;
+ EVAL_STATE (pv) = EV_lvalue;
+ }
+ }
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ break;
+
+ case S_BLOCK32:
+ EVAL_SYM_SEG (pv) = ((BLOCKPTR32)pSym)->seg;
+ EVAL_SYM_OFF (pv) = ((BLOCKPTR32)pSym)->off;
+ typ = T_NOTYPE;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ break;
+
+ case S_LPROC32:
+ case S_GPROC32:
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ if ((typ = ((PROCPTR32)pSym)->typind) == T_NOTYPE) {
+ // this is a hack to allow breakpoints on untyped symbols
+ typ = T_32PUCHAR;
+ EVAL_SYM_OFF (pv) = ((PROCPTR32)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((PROCPTR32)pSym)->seg;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ EVAL_STATE (pv) = EV_rvalue;
+ }
+ else {
+ EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT);
+ EVAL_SYM_SEG (pv) = ((PROCPTR32)pSym)->seg;
+ EVAL_SYM_OFF (pv) = ((PROCPTR32)pSym)->off;
+ }
+ break;
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ if ((typ = ((PROCPTRMIPS)pSym)->typind) == T_NOTYPE) {
+ // this is a hack to allow breakpoints on untyped symbols
+ typ = T_32PUCHAR;
+ EVAL_SYM_OFF (pv) = ((PROCPTRMIPS)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((PROCPTRMIPS)pSym)->seg;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ EVAL_STATE (pv) = EV_rvalue;
+ } else {
+ EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT);
+ EVAL_SYM_SEG (pv) = ((PROCPTRMIPS)pSym)->seg;
+ EVAL_SYM_OFF (pv) = ((PROCPTRMIPS)pSym)->off;
+ }
+ break;
+
+ case S_REGREL32:
+ EVAL_IS_REGREL (pv) = TRUE;
+ EVAL_SYM_OFF (pv) = ((LPREGREL32)pSym)->off;
+ EVAL_SYM_SEG (pv) = 0;
+ EVAL_REGREL (pv) = ((LPREGREL32)pSym)->reg;
+ typ = ((LPREGREL32)pSym)->typind;
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ pExState->state.regrel = TRUE;
+ cmpThis = strncmp ( (char *) &((LPREGREL32)pSym)->name[0],
+ (char *) &OpName[0], ((LPREGREL32)pSym)->name[0] + 1);
+ break;
+
+ case S_LABEL32:
+ EVAL_IS_LABEL (pv) = TRUE;
+ EVAL_SYM_OFF (pv) = ((LABELPTR32)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((LABELPTR32)pSym)->seg;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ EVAL_STATE (pv) = EV_rvalue;
+ typ = T_32PUCHAR;
+ break;
+
+ case S_BPREL32:
+ EVAL_IS_BPREL (pv) = TRUE;
+ EVAL_SYM_OFF (pv) = ((BPRELPTR32)pSym)->off;
+ EVAL_SYM_SEG (pv) = 0;
+ typ = ((BPRELPTR32)pSym)->typind;
+ ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ pExState->state.bprel = TRUE;
+ pExState->state.regrel = TRUE;
+ cmpThis = strncmp ( (char *) &((BPRELPTR32)pSym)->name[0],
+ (char *) &OpName[0], ((BPRELPTR32)pSym)->name[0] + 1);
+ break;
+
+ case S_LTHREAD32:
+ // NOTENOTE - jimsch -- TLS -- global vs local difference?
+ case S_GTHREAD32:
+ EVAL_IS_TLSREL( pv ) = TRUE;
+ EVAL_SYM_OFF( pv ) = ((DATAPTR32) pSym)->off;
+ EVAL_SYM_SEG( pv ) = ((DATAPTR32) pSym)->seg;
+ typ = ((DATAPTR32) pSym)->typind;
+ ADDR_IS_LI( EVAL_SYM( pv )) = TRUE;
+ ADDR_IS_FLAT( EVAL_SYM( pv )) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ pExState->state.tlsrel = TRUE;
+ break;
+
+ case S_LDATA32:
+ pExState->state.fLData = TRUE;
+ EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg;
+ typ = ((DATAPTR32)pSym)->typind;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ break;
+
+ case S_GDATA32:
+ pExState->state.fGData = TRUE;
+ EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg;
+ typ = ((DATAPTR32)pSym)->typind;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ if (FNtsdEvalType) {
+ FNtsdEvalType = FALSE;
+ EVAL_STATE (pv) = EV_rvalue;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ typ = T_32PULONG;
+ }
+ break;
+
+ case S_PUB32:
+ EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off;
+ EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg;
+ ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
+ ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
+ EVAL_PTR (pv) = EVAL_SYM (pv);
+ EVAL_STATE (pv) = EV_lvalue;
+ if (((typ = ((DATAPTR32)pSym)->typind) == T_NOTYPE) || FNtsdEvalType) {
+ if (FNtsdEvalType) {
+ FNtsdEvalType = FALSE;
+ evalstate = EV_rvalue;
+ typ = T_32PULONG;
+ } else {
+ typ = T_UINT4;
+ evalstate = EV_lvalue;
+ }
+ //
+ // this is a hack to allow breakpoints on untyped symbols
+ //
+ mi.addr = EVAL_SYM(pv);
+ SYGetMemInfo(&mi);
+ if ((mi.dwState & MEM_COMMIT)
+ && (mi.dwProtect & (PAGE_EXECUTE |
+ PAGE_EXECUTE_READ |
+ PAGE_EXECUTE_READWRITE |
+ PAGE_EXECUTE_WRITECOPY))
+ ) {
+ typ = T_32PUCHAR;
+ EVAL_STATE (pv) = EV_rvalue;
+ } else {
+ //
+ // this gives windbg the "look & feel" of ntsd/kd
+ // if the user does a "dd foo" and there are only
+ // coff publics then the answer will be the same
+ // as ntsd/kd
+ //
+ EVAL_STATE (pv) = evalstate;
+ }
+ }
+ break;
+
+ default:
+ // these OMF records are no longer supported
+ MHOmfUnLock ((HDEP)hSym);
+ pExState->err_num = ERR_BADOMF;
+ return (FALSE);
+ }
+ MHOmfUnLock ((HDEP)hSym);
+ if (SetNodeType (pv, typ) == FALSE) {
+ return (FALSE);
+ }
+ else if (ClassImp != T_NOTYPE) {
+ if (EVAL_IS_PTR (pv) &&
+ memcmp (pName->sstr.lpName, &OpName[0] + 1, pName->sstr.cb) == 0) {
+ PTR_THISADJUST (pv) = ClassThisAdjust;
+ }
+ else if (cmpThis == 0) {
+ PTR_THISADJUST (pv) = ClassThisAdjust;
+ }
+ }
+ return (TRUE);
+}
+
+#if defined (M68K)
+
+#define VALID68851 0x40
+#define VALID68882 0x80
+
+#define VALID68000 0x01
+#define VALID68010 0x02 | VALID68000
+#define VALID68020 0x04 | VALID68010
+#define VALID68030 0x08 | VALID68020 | VALID68851
+#define VALID68040 0x10 | VALID68030
+
+struct hreg {
+ char name[7];
+ ushort index;
+ char valid;
+ ushort type;
+} _based (_segname("_CODE")) hreg_list[] = {
+ {"\x002""D0", CV_R68_D0, VALID68000, T_ULONG},
+ {"\x002""D1", CV_R68_D1, VALID68000, T_ULONG},
+ {"\x002""D2", CV_R68_D2, VALID68000, T_ULONG},
+ {"\x002""D3", CV_R68_D3, VALID68000, T_ULONG},
+ {"\x002""D4", CV_R68_D4, VALID68000, T_ULONG},
+ {"\x002""D5", CV_R68_D5, VALID68000, T_ULONG},
+ {"\x002""D6", CV_R68_D6, VALID68000, T_ULONG},
+ {"\x002""D7", CV_R68_D7, VALID68000, T_ULONG},
+ {"\x002""A0", CV_R68_A0, VALID68000, T_ULONG},
+ {"\x002""A1", CV_R68_A1, VALID68000, T_ULONG},
+ {"\x002""A2", CV_R68_A2, VALID68000, T_ULONG},
+ {"\x002""A3", CV_R68_A3, VALID68000, T_ULONG},
+ {"\x002""A4", CV_R68_A4, VALID68000, T_ULONG},
+ {"\x002""A5", CV_R68_A5, VALID68000, T_ULONG},
+ {"\x002""A6", CV_R68_A6, VALID68000, T_ULONG},
+ {"\x002""A7", CV_R68_A7, VALID68000, T_ULONG},
+ {"\x003""CCR", CV_R68_CCR, VALID68000, T_USHORT},
+ {"\x002""SR", CV_R68_SR, VALID68000, T_USHORT},
+ {"\x003""USP", CV_R68_USP, VALID68000, T_ULONG},
+ {"\x003""MSP", CV_R68_MSP, VALID68000, T_ULONG},
+ {"\x002""PC", CV_R68_PC, VALID68000, T_ULONG},
+
+ {"\x003""SFC", CV_R68_SFC, VALID68010, T_USHORT},
+ {"\x003""DFC", CV_R68_DFC, VALID68010, T_USHORT},
+ {"\x003""VBR", CV_R68_VBR, VALID68010, T_USHORT},
+
+ {"\x004""CACR", CV_R68_CACR, VALID68020, T_ULONG},
+ {"\x004""CAAR", CV_R68_CAAR, VALID68020, T_ULONG},
+ {"\x003""ISP", CV_R68_ISP, VALID68020, T_ULONG},
+
+ {"\x003""PSR", CV_R68_PSR, VALID68851, T_USHORT},
+ {"\x004""PCSR", CV_R68_PCSR, VALID68851, T_USHORT},
+ {"\x003""VAL", CV_R68_VAL, VALID68851, T_USHORT},
+ {"\x003""CRP", CV_R68_CRP, VALID68851, T_UQUAD},
+ {"\x003""SRP", CV_R68_SRP, VALID68851, T_UQUAD},
+ {"\x003""DRP", CV_R68_DRP, VALID68851, T_UQUAD},
+ {"\x002""TC", CV_R68_TC, VALID68851, T_ULONG},
+ {"\x002""AC", CV_R68_AC, VALID68851, T_USHORT},
+ {"\x003""SCC", CV_R68_SCC, VALID68851, T_USHORT},
+ {"\x003""CAL", CV_R68_CAL, VALID68851, T_USHORT},
+ {"\x004""BAD0", CV_R68_BAD0, VALID68851, T_USHORT},
+ {"\x004""BAD1", CV_R68_BAD1, VALID68851, T_USHORT},
+ {"\x004""BAD2", CV_R68_BAD2, VALID68851, T_USHORT},
+ {"\x004""BAD3", CV_R68_BAD3, VALID68851, T_USHORT},
+ {"\x004""BAD4", CV_R68_BAD4, VALID68851, T_USHORT},
+ {"\x004""BAD5", CV_R68_BAD5, VALID68851, T_USHORT},
+ {"\x004""BAD6", CV_R68_BAD6, VALID68851, T_USHORT},
+ {"\x004""BAD7", CV_R68_BAD7, VALID68851, T_USHORT},
+ {"\x004""BAC0", CV_R68_BAC0, VALID68851, T_USHORT},
+ {"\x004""BAC1", CV_R68_BAC1, VALID68851, T_USHORT},
+ {"\x004""BAC2", CV_R68_BAC2, VALID68851, T_USHORT},
+ {"\x004""BAC3", CV_R68_BAC3, VALID68851, T_USHORT},
+ {"\x004""BAC4", CV_R68_BAC4, VALID68851, T_USHORT},
+ {"\x004""BAC5", CV_R68_BAC5, VALID68851, T_USHORT},
+ {"\x004""BAC6", CV_R68_BAC6, VALID68851, T_USHORT},
+ {"\x004""BAC7", CV_R68_BAC7, VALID68851, T_USHORT},
+
+ {"\x003""TT0", CV_R68_TT0, VALID68030, T_ULONG},
+ {"\x003""TT1", CV_R68_TT1, VALID68030, T_ULONG},
+
+ {"\x004""FPCR", CV_R68_FPCR, VALID68882, T_ULONG},
+ {"\x004""FPSR", CV_R68_FPSR, VALID68882, T_ULONG},
+ {"\x005""FPIAR", CV_R68_FPIAR, VALID68882, T_ULONG},
+ {"\x003""FP0", CV_R68_FP0, VALID68882, T_REAL80},
+ {"\x003""FP1", CV_R68_FP1, VALID68882, T_REAL80},
+ {"\x003""FP2", CV_R68_FP2, VALID68882, T_REAL80},
+ {"\x003""FP3", CV_R68_FP3, VALID68882, T_REAL80},
+ {"\x003""FP4", CV_R68_FP4, VALID68882, T_REAL80},
+ {"\x003""FP5", CV_R68_FP5, VALID68882, T_REAL80},
+ {"\x003""FP6", CV_R68_FP6, VALID68882, T_REAL80},
+ {"\x003""FP7", CV_R68_FP7, VALID68882, T_REAL80},
+};
+
+#endif // M68K
+
+struct hreg {
+ char name[9];
+ int index;
+ ushort type;
+#ifdef WIN32
+} hreg_list[] = {
+#else
+} _based (_segname("_CODE")) hreg_list[] = {
+#endif
+ {"\x002""$p", CV_REG_PSEUDO1, T_ULONG},
+ {"\x003""$p1", CV_REG_PSEUDO1, T_ULONG},
+ {"\x003""$p2", CV_REG_PSEUDO2, T_ULONG},
+ {"\x003""$p3", CV_REG_PSEUDO3, T_ULONG},
+ {"\x003""$p4", CV_REG_PSEUDO4, T_ULONG},
+ {"\x002""$u", CV_REG_PSEUDO5, T_ULONG},
+ {"\x003""$u1", CV_REG_PSEUDO5, T_ULONG},
+ {"\x003""$u2", CV_REG_PSEUDO6, T_ULONG},
+ {"\x003""$u3", CV_REG_PSEUDO7, T_ULONG},
+ {"\x003""$u4", CV_REG_PSEUDO8, T_ULONG},
+ {"\x004""$exp", CV_REG_PSEUDO9, T_ULONG},
+#ifdef TARGET_i386
+ {"\x002""AX", CV_REG_AX, T_USHORT},
+ {"\x002""BX", CV_REG_BX, T_USHORT},
+ {"\x002""CX", CV_REG_CX, T_USHORT},
+ {"\x002""DX", CV_REG_DX, T_USHORT},
+ {"\x002""SP", CV_REG_SP, T_USHORT},
+ {"\x002""BP", CV_REG_BP, T_USHORT},
+ {"\x002""SI", CV_REG_SI, T_USHORT},
+ {"\x002""DI", CV_REG_DI, T_USHORT},
+ {"\x002""DS", CV_REG_DS, T_USHORT},
+ {"\x002""ES", CV_REG_ES, T_USHORT},
+ {"\x002""SS", CV_REG_SS, T_USHORT},
+ {"\x002""CS", CV_REG_CS, T_USHORT},
+ {"\x002""IP", CV_REG_IP, T_USHORT},
+ {"\x002""FL", CV_REG_FLAGS, T_USHORT},
+ {"\x003""EFL", CV_REG_EFLAGS, T_ULONG},
+ {"\x003""EAX", CV_REG_EAX, T_ULONG},
+ {"\x003""EBX", CV_REG_EBX, T_ULONG},
+ {"\x003""ECX", CV_REG_ECX, T_ULONG},
+ {"\x003""EDX", CV_REG_EDX, T_ULONG},
+ {"\x003""ESP", CV_REG_ESP, T_ULONG},
+ {"\x003""EBP", CV_REG_EBP, T_ULONG},
+ {"\x003""ESI", CV_REG_ESI, T_ULONG},
+ {"\x003""EDI", CV_REG_EDI, T_ULONG},
+ {"\x003""EIP", CV_REG_EIP, T_ULONG},
+ {"\x002""FS", CV_REG_FS, T_USHORT},
+ {"\x002""GS", CV_REG_GS, T_USHORT},
+ {"\x002""AH", CV_REG_AH, T_UCHAR},
+ {"\x002""BH", CV_REG_BH, T_UCHAR},
+ {"\x002""CH", CV_REG_CH, T_UCHAR},
+ {"\x002""DH", CV_REG_DH, T_UCHAR},
+ {"\x002""AL", CV_REG_AL, T_UCHAR},
+ {"\x002""BL", CV_REG_BL, T_UCHAR},
+ {"\x002""CL", CV_REG_CL, T_UCHAR},
+ {"\x002""DL", CV_REG_DL, T_UCHAR},
+ {"\x002""st", CV_REG_ST0, T_REAL80},
+ {"\x003""st0", CV_REG_ST0, T_REAL80},
+ {"\x003""st1", CV_REG_ST1, T_REAL80},
+ {"\x003""st2", CV_REG_ST2, T_REAL80},
+ {"\x003""st3", CV_REG_ST3, T_REAL80},
+ {"\x003""st4", CV_REG_ST4, T_REAL80},
+ {"\x003""st5", CV_REG_ST5, T_REAL80},
+ {"\x003""st6", CV_REG_ST6, T_REAL80},
+ {"\x003""st7", CV_REG_ST7, T_REAL80},
+ {"\x003""cr0", CV_REG_CR0, T_ULONG},
+ {"\x003""cr1", CV_REG_CR1, T_ULONG},
+ {"\x003""cr2", CV_REG_CR2, T_ULONG},
+ {"\x003""cr3", CV_REG_CR3, T_ULONG},
+ {"\x003""cr4", CV_REG_CR4, T_ULONG},
+ {"\x003""dr0", CV_REG_DR0, T_ULONG},
+ {"\x003""dr1", CV_REG_DR1, T_ULONG},
+ {"\x003""dr2", CV_REG_DR2, T_ULONG},
+ {"\x003""dr3", CV_REG_DR3, T_ULONG},
+ {"\x003""dr4", CV_REG_DR4, T_ULONG},
+ {"\x003""dr5", CV_REG_DR5, T_ULONG},
+ {"\x003""dr6", CV_REG_DR6, T_ULONG},
+ {"\x003""dr7", CV_REG_DR7, T_ULONG},
+#endif // TARGET_i386
+
+#ifdef TARGET_PPC
+ {"\004""GPR0", CV_PPC_GPR0,T_ULONG},
+ {"\004""GPR1", CV_PPC_GPR1, T_ULONG},
+ {"\004""GPR2", CV_PPC_GPR2, T_ULONG},
+ {"\004""GPR3", CV_PPC_GPR3, T_ULONG},
+ {"\004""GPR4", CV_PPC_GPR4, T_ULONG},
+ {"\004""GPR5", CV_PPC_GPR5, T_ULONG},
+ {"\004""GPR6", CV_PPC_GPR6, T_ULONG},
+ {"\004""GPR7", CV_PPC_GPR7, T_ULONG},
+ {"\004""GPR8", CV_PPC_GPR8, T_ULONG},
+ {"\004""GPR9", CV_PPC_GPR9, T_ULONG},
+ {"\005""GPR10", CV_PPC_GPR10, T_ULONG},
+ {"\005""GPR11", CV_PPC_GPR11, T_ULONG},
+ {"\005""GPR12", CV_PPC_GPR12, T_ULONG},
+ {"\005""GPR13", CV_PPC_GPR13, T_ULONG},
+ {"\005""GPR14", CV_PPC_GPR14, T_ULONG},
+ {"\005""GPR15", CV_PPC_GPR15, T_ULONG},
+ {"\005""GPR16", CV_PPC_GPR16, T_ULONG},
+ {"\005""GPR17", CV_PPC_GPR17, T_ULONG},
+ {"\005""GPR18", CV_PPC_GPR18, T_ULONG},
+ {"\005""GPR19", CV_PPC_GPR19, T_ULONG},
+ {"\005""GPR20", CV_PPC_GPR20, T_ULONG},
+ {"\005""GPR21", CV_PPC_GPR21, T_ULONG},
+ {"\005""GPR22", CV_PPC_GPR22, T_ULONG},
+ {"\005""GPR23", CV_PPC_GPR23, T_ULONG},
+ {"\005""GPR24", CV_PPC_GPR24, T_ULONG},
+ {"\005""GPR25", CV_PPC_GPR25, T_ULONG},
+ {"\005""GPR30", CV_PPC_GPR30, T_ULONG},
+ {"\005""GPR26", CV_PPC_GPR26, T_ULONG},
+ {"\005""GPR27", CV_PPC_GPR27, T_ULONG},
+ {"\005""GPR28", CV_PPC_GPR28, T_ULONG},
+ {"\005""GPR29", CV_PPC_GPR29, T_ULONG},
+ {"\005""GPR31", CV_PPC_GPR31, T_ULONG},
+
+// floating point registers follow
+
+ {"\004""FPR0", CV_PPC_FPR0, T_REAL64 },
+ {"\004""FPR1", CV_PPC_FPR1, T_REAL64 },
+ {"\004""FPR2", CV_PPC_FPR2, T_REAL64 },
+ {"\004""FPR3", CV_PPC_FPR3, T_REAL64 },
+ {"\004""FPR4", CV_PPC_FPR4, T_REAL64 },
+ {"\004""FPR5", CV_PPC_FPR5, T_REAL64 },
+ {"\004""FPR6", CV_PPC_FPR6, T_REAL64 },
+ {"\004""FPR7", CV_PPC_FPR7, T_REAL64 },
+ {"\004""FPR8", CV_PPC_FPR8, T_REAL64 },
+ {"\004""FPR9", CV_PPC_FPR9, T_REAL64 },
+ {"\005""FPR10", CV_PPC_FPR10, T_REAL64 },
+ {"\005""FPR11", CV_PPC_FPR11, T_REAL64 },
+ {"\005""FPR12", CV_PPC_FPR12, T_REAL64 },
+ {"\005""FPR13", CV_PPC_FPR13, T_REAL64 },
+ {"\005""FPR14", CV_PPC_FPR14, T_REAL64 },
+ {"\005""FPR15", CV_PPC_FPR15, T_REAL64 },
+ {"\005""FPR16", CV_PPC_FPR16, T_REAL64 },
+ {"\005""FPR17", CV_PPC_FPR17, T_REAL64 },
+ {"\005""FPR18", CV_PPC_FPR18, T_REAL64 },
+ {"\005""FPR19", CV_PPC_FPR19, T_REAL64 },
+ {"\005""FPR20", CV_PPC_FPR20, T_REAL64 },
+ {"\005""FPR21", CV_PPC_FPR21, T_REAL64 },
+ {"\005""FPR22", CV_PPC_FPR22, T_REAL64 },
+ {"\005""FPR23", CV_PPC_FPR23, T_REAL64 },
+ {"\005""FPR24", CV_PPC_FPR24, T_REAL64 },
+ {"\005""FPR25", CV_PPC_FPR25, T_REAL64 },
+ {"\005""FPR26", CV_PPC_FPR26, T_REAL64 },
+ {"\005""FPR27", CV_PPC_FPR27, T_REAL64 },
+ {"\005""FPR28", CV_PPC_FPR28, T_REAL64 },
+ {"\005""FPR29", CV_PPC_FPR29, T_REAL64 },
+ {"\005""FPR30", CV_PPC_FPR30, T_REAL64 },
+ {"\005""FPR31", CV_PPC_FPR31, T_REAL64 },
+
+ {"\005""FPSCR", CV_PPC_FPSCR, T_ULONG },
+ {"\002""LR", CV_PPC_LR, T_ULONG },
+ {"\002""CR", CV_PPC_CR, T_ULONG },
+ {"\003""CTR", CV_PPC_CTR, T_ULONG },
+ {"\003""CIA", CV_PPC_PC, T_ULONG },
+ {"\003""XER", CV_PPC_XER, T_ULONG },
+ {"\003""MSR", CV_PPC_MSR, T_ULONG }
+
+#endif //TARGET_PPC
+
+
+#ifdef TARGET_MIPS
+ {"\004""ZERO", CV_M4_IntZERO, T_ULONG},
+ {"\002""AT", CV_M4_IntAT, T_ULONG},
+ {"\002""V0", CV_M4_IntV0, T_ULONG},
+ {"\002""V1", CV_M4_IntV1, T_ULONG},
+ {"\002""A0", CV_M4_IntA0, T_ULONG},
+ {"\002""A1", CV_M4_IntA1, T_ULONG},
+ {"\002""A2", CV_M4_IntA2, T_ULONG},
+ {"\002""A3", CV_M4_IntA3, T_ULONG},
+ {"\002""T0", CV_M4_IntT0, T_ULONG},
+ {"\002""T1", CV_M4_IntT1, T_ULONG},
+ {"\002""T2", CV_M4_IntT2, T_ULONG},
+ {"\002""T3", CV_M4_IntT3, T_ULONG},
+ {"\002""T4", CV_M4_IntT4, T_ULONG},
+ {"\002""T5", CV_M4_IntT5, T_ULONG},
+ {"\002""T6", CV_M4_IntT6, T_ULONG},
+ {"\002""T7", CV_M4_IntT7, T_ULONG},
+ {"\002""T8", CV_M4_IntT8, T_ULONG},
+ {"\002""T9", CV_M4_IntT9, T_ULONG},
+ {"\002""S0", CV_M4_IntS0, T_ULONG},
+ {"\002""S1", CV_M4_IntS1, T_ULONG},
+ {"\002""S2", CV_M4_IntS2, T_ULONG},
+ {"\002""S3", CV_M4_IntS3, T_ULONG},
+ {"\002""S4", CV_M4_IntS4, T_ULONG},
+ {"\002""S5", CV_M4_IntS5, T_ULONG},
+ {"\002""S6", CV_M4_IntS6, T_ULONG},
+ {"\002""S7", CV_M4_IntS7, T_ULONG},
+ {"\002""S8", CV_M4_IntS8, T_ULONG},
+ {"\002""K0", CV_M4_IntKT0, T_ULONG},
+ {"\002""K1", CV_M4_IntKT1, T_ULONG},
+ {"\002""GP", CV_M4_IntGP, T_ULONG},
+ {"\002""SP", CV_M4_IntSP, T_ULONG},
+ {"\002""RA", CV_M4_IntRA, T_ULONG},
+ {"\003""FIR", CV_M4_Fir, T_ULONG},
+ {"\003""PSR", CV_M4_Psr, T_ULONG},
+ {"\003""FSR", CV_M4_FltFsr, T_ULONG},
+ {"\002""HI", CV_M4_IntHI, T_ULONG},
+ {"\002""LO", CV_M4_IntLO, T_ULONG},
+ {"\003""FR0", CV_M4_FltF0, T_REAL32},
+ {"\003""FR1", CV_M4_FltF1, T_REAL32},
+ {"\003""FR2", CV_M4_FltF2, T_REAL32},
+ {"\003""FR3", CV_M4_FltF3, T_REAL32},
+ {"\003""FR4", CV_M4_FltF4, T_REAL32},
+ {"\003""FR5", CV_M4_FltF5, T_REAL32},
+ {"\003""FR6", CV_M4_FltF6, T_REAL32},
+ {"\003""FR7", CV_M4_FltF7, T_REAL32},
+ {"\003""FR8", CV_M4_FltF8, T_REAL32},
+ {"\003""FR9", CV_M4_FltF9, T_REAL32},
+ {"\004""FR10", CV_M4_FltF10, T_REAL32},
+ {"\004""FR11", CV_M4_FltF11, T_REAL32},
+ {"\004""FR12", CV_M4_FltF12, T_REAL32},
+ {"\004""FR13", CV_M4_FltF13, T_REAL32},
+ {"\004""FR14", CV_M4_FltF14, T_REAL32},
+ {"\004""FR15", CV_M4_FltF15, T_REAL32},
+ {"\004""FR16", CV_M4_FltF16, T_REAL32},
+ {"\004""FR17", CV_M4_FltF17, T_REAL32},
+ {"\004""FR18", CV_M4_FltF18, T_REAL32},
+ {"\004""FR19", CV_M4_FltF19, T_REAL32},
+ {"\004""FR20", CV_M4_FltF20, T_REAL32},
+ {"\004""FR21", CV_M4_FltF21, T_REAL32},
+ {"\004""FR22", CV_M4_FltF22, T_REAL32},
+ {"\004""FR23", CV_M4_FltF23, T_REAL32},
+ {"\004""FR24", CV_M4_FltF24, T_REAL32},
+ {"\004""FR25", CV_M4_FltF25, T_REAL32},
+ {"\004""FR26", CV_M4_FltF26, T_REAL32},
+ {"\004""FR27", CV_M4_FltF27, T_REAL32},
+ {"\004""FR28", CV_M4_FltF28, T_REAL32},
+ {"\004""FR29", CV_M4_FltF29, T_REAL32},
+ {"\004""FR30", CV_M4_FltF30, T_REAL32},
+ {"\004""FR31", CV_M4_FltF31, T_REAL32},
+ {"\003""FP0", CV_M4_FltF0 << 8 | CV_M4_FltF1, T_REAL64},
+ {"\003""FP2", CV_M4_FltF2 << 8 | CV_M4_FltF3, T_REAL64},
+ {"\003""FP4", CV_M4_FltF4 << 8 | CV_M4_FltF5, T_REAL64},
+ {"\003""FP6", CV_M4_FltF6 << 8 | CV_M4_FltF7, T_REAL64},
+ {"\003""FP8", CV_M4_FltF8 << 8 | CV_M4_FltF9, T_REAL64},
+ {"\004""FP10", CV_M4_FltF10 << 8 | CV_M4_FltF11, T_REAL64},
+ {"\004""FP12", CV_M4_FltF12 << 8 | CV_M4_FltF13, T_REAL64},
+ {"\004""FP14", CV_M4_FltF14 << 8 | CV_M4_FltF15, T_REAL64},
+ {"\004""FP16", CV_M4_FltF16 << 8 | CV_M4_FltF17, T_REAL64},
+ {"\004""FP18", CV_M4_FltF18 << 8 | CV_M4_FltF19, T_REAL64},
+ {"\004""FP20", CV_M4_FltF20 << 8 | CV_M4_FltF21, T_REAL64},
+ {"\004""FP22", CV_M4_FltF22 << 8 | CV_M4_FltF23, T_REAL64},
+ {"\004""FP24", CV_M4_FltF24 << 8 | CV_M4_FltF25, T_REAL64},
+ {"\004""FP26", CV_M4_FltF26 << 8 | CV_M4_FltF27, T_REAL64},
+ {"\004""FP28", CV_M4_FltF28 << 8 | CV_M4_FltF29, T_REAL64},
+ {"\004""FP30", CV_M4_FltF30 << 8 | CV_M4_FltF31, T_REAL64},
+#endif // TARGET_MIPS
+
+#ifdef TARGET_ALPHA
+ {"\002""V0", CV_ALPHA_IntV0, T_UQUAD },
+ {"\002""T0", CV_ALPHA_IntT0, T_UQUAD },
+ {"\002""T1", CV_ALPHA_IntT1, T_UQUAD },
+ {"\002""T2", CV_ALPHA_IntT2, T_UQUAD },
+ {"\002""T3", CV_ALPHA_IntT3, T_UQUAD },
+ {"\002""T4", CV_ALPHA_IntT4, T_UQUAD },
+ {"\002""T5", CV_ALPHA_IntT5, T_UQUAD },
+ {"\002""T6", CV_ALPHA_IntT6, T_UQUAD },
+ {"\002""T7", CV_ALPHA_IntT7, T_UQUAD },
+ {"\002""S0", CV_ALPHA_IntS0, T_UQUAD },
+ {"\002""S1", CV_ALPHA_IntS1, T_UQUAD },
+ {"\002""S2", CV_ALPHA_IntS2, T_UQUAD },
+ {"\002""S3", CV_ALPHA_IntS3, T_UQUAD },
+ {"\002""S4", CV_ALPHA_IntS4, T_UQUAD },
+ {"\002""S5", CV_ALPHA_IntS5, T_UQUAD },
+ {"\002""FP", CV_ALPHA_IntFP, T_UQUAD },
+ {"\002""A0", CV_ALPHA_IntA0, T_UQUAD },
+ {"\002""A1", CV_ALPHA_IntA1, T_UQUAD },
+ {"\002""A2", CV_ALPHA_IntA2, T_UQUAD },
+ {"\002""A3", CV_ALPHA_IntA3, T_UQUAD },
+ {"\002""A4", CV_ALPHA_IntA4, T_UQUAD },
+ {"\002""A5", CV_ALPHA_IntA5, T_UQUAD },
+ {"\002""T8", CV_ALPHA_IntT8, T_UQUAD },
+ {"\002""T9", CV_ALPHA_IntT9, T_UQUAD },
+ {"\003""T10", CV_ALPHA_IntT10, T_UQUAD },
+ {"\003""T11", CV_ALPHA_IntT11, T_UQUAD },
+ {"\002""RA", CV_ALPHA_IntRA, T_UQUAD },
+ {"\003""T12", CV_ALPHA_IntT12, T_UQUAD },
+ {"\002""AT", CV_ALPHA_IntAT, T_UQUAD },
+ {"\002""GP", CV_ALPHA_IntGP, T_UQUAD },
+ {"\002""SP", CV_ALPHA_IntSP, T_UQUAD },
+ {"\004""ZERO", CV_ALPHA_IntZERO, T_UQUAD },
+ {"\002""F0", CV_ALPHA_FltF0, T_REAL64 },
+ {"\002""F1", CV_ALPHA_FltF1, T_REAL64 },
+ {"\002""F2", CV_ALPHA_FltF2, T_REAL64 },
+ {"\002""F3", CV_ALPHA_FltF3, T_REAL64 },
+ {"\002""F4", CV_ALPHA_FltF4, T_REAL64 },
+ {"\002""F5", CV_ALPHA_FltF5, T_REAL64 },
+ {"\002""F6", CV_ALPHA_FltF6, T_REAL64 },
+ {"\002""F7", CV_ALPHA_FltF7, T_REAL64 },
+ {"\002""F8", CV_ALPHA_FltF8, T_REAL64 },
+ {"\002""F9", CV_ALPHA_FltF9, T_REAL64 },
+ {"\003""F10", CV_ALPHA_FltF10, T_REAL64 },
+ {"\003""F11", CV_ALPHA_FltF11, T_REAL64 },
+ {"\003""F12", CV_ALPHA_FltF12, T_REAL64 },
+ {"\003""F13", CV_ALPHA_FltF13, T_REAL64 },
+ {"\003""F14", CV_ALPHA_FltF14, T_REAL64 },
+ {"\003""F15", CV_ALPHA_FltF15, T_REAL64 },
+ {"\003""F16", CV_ALPHA_FltF16, T_REAL64 },
+ {"\003""F17", CV_ALPHA_FltF17, T_REAL64 },
+ {"\003""F18", CV_ALPHA_FltF18, T_REAL64 },
+ {"\003""F19", CV_ALPHA_FltF19, T_REAL64 },
+ {"\003""F20", CV_ALPHA_FltF20, T_REAL64 },
+ {"\003""F21", CV_ALPHA_FltF21, T_REAL64 },
+ {"\003""F22", CV_ALPHA_FltF22, T_REAL64 },
+ {"\003""F23", CV_ALPHA_FltF23, T_REAL64 },
+ {"\003""F24", CV_ALPHA_FltF24, T_REAL64 },
+ {"\003""F25", CV_ALPHA_FltF25, T_REAL64 },
+ {"\003""F26", CV_ALPHA_FltF26, T_REAL64 },
+ {"\003""F27", CV_ALPHA_FltF27, T_REAL64 },
+ {"\003""F28", CV_ALPHA_FltF28, T_REAL64 },
+ {"\003""F29", CV_ALPHA_FltF29, T_REAL64 },
+ {"\003""F30", CV_ALPHA_FltF30, T_REAL64 },
+ {"\003""F31", CV_ALPHA_FltF31, T_REAL64 },
+ {"\003""FIR", CV_ALPHA_Fir, T_UQUAD },
+ {"\004""FPCR", CV_ALPHA_Fpcr, T_UQUAD },
+ {"\003""PSR", CV_ALPHA_Psr, T_ULONG }
+#endif // TARGET_ALPHA
+};
+
+#define REGCNT (sizeof (hreg_list)/sizeof (struct hreg))
+
+LOCAL bool_t
+ParseRegister (
+ psearch_t pName
+ )
+{
+ int i;
+ peval_t pv;
+
+ if (*pName->sstr.lpName == '@') {
+ pName->sstr.lpName++;
+ pName->sstr.cb--;
+ }
+ for (i = 0; i < REGCNT; i++) {
+ if (fnCmp ((LPSSTR) pName, NULL, hreg_list[i].name, FALSE) == 0)
+ break;
+ }
+ if (i >= REGCNT) {
+ return (HR_notfound);
+ }
+ pv = pName->pv;
+ EVAL_REG (pv) = hreg_list[i].index;
+ SetNodeType (pv, hreg_list[i].type);
+ EVAL_IS_REG (pv) = TRUE;
+ EVAL_STATE (pv) = EV_lvalue;
+ PushStack (pv);
+ return (HR_found);
+}
+
+#if defined (M68K)
+/** TypeFromHreg - get the CV type of a register
+ *
+ * type = TypeFromHreg (hReg)
+ *
+ * Entry hReg = register index
+ *
+ * Returns the CV type of the register
+ * (T_NOTYPE if register not found)
+ */
+ushort
+TypeFromHreg (
+ ushort hreg
+ )
+{
+ int i;
+
+ for (i = 0; i < REGCNT; i++) {
+ if (hreg == hreg_list[i].index) {
+ return(hreg_list[i].type);
+ }
+ }
+
+ return(T_NOTYPE);
+}
+#endif
+
+
+
+LOCAL bool_t
+LineNumber (
+ psearch_t pName
+ )
+{
+ uchar *pb = pName->sstr.lpName + 1;
+ uint i;
+ char c;
+ ulong val = 0;
+ //FLS fls;
+ HSF hsf;
+ ADDR addr;
+ SHOFF cbLine;
+
+ peval_t pv;
+
+ // convert line number
+
+ for (i = pName->sstr.cb - 1; i > 0; i--) {
+ c = *pb;
+ if (!isdigit (c)) {
+ // Must have reached the end
+ pExState->err_num = ERR_LINENUMBER;
+ return (HR_error);
+ }
+ val *= 10;
+ val += (c - '0');
+ if (val > 0xffff) {
+ // Must have overflowed
+ pExState->err_num = ERR_LINENUMBER;
+ return (HR_error);
+ }
+ pb++;
+ }
+
+ // Make sure we have the right address.
+
+ if (!ADDR_IS_LI( *SHpADDRFrompCXT( pCxt ) )) {
+ SHUnFixupAddr( SHpADDRFrompCXT( pCxt ) );
+ }
+
+ if ( (hsf = SLHsfFromPcxt ( pCxt ) ) &&
+ SLFLineToAddr ( hsf, (ushort) val, &addr, &cbLine, NULL ) ) {
+
+ pv = pName->pv;
+
+ if (ADDR_IS_FLAT( *SHpADDRFrompCXT( pCxt )) ) {
+ SetNodeType (pv, T_32PUCHAR);
+ } else if (ADDR_IS_OFF32( *SHpADDRFrompCXT( pCxt )) ) {
+ SetNodeType (pv, T_32PFUCHAR);
+ } else {
+ SetNodeType (pv, T_PFUCHAR);
+ }
+
+ EVAL_IS_LABEL (pv) = TRUE;
+ EVAL_STATE (pv) = EV_rvalue;
+ EVAL_SYM (pv) = addr;
+ EVAL_PTR (pv) = addr;
+ PushStack (pv);
+ return (HR_found);
+ }
+ else {
+ pExState->err_num = ERR_NOCODE;
+ return (HR_error);
+ }
+
+ pExState->err_num = ERR_BADCONTEXT;
+ return (HR_error);
+}
+
+
+
+
+/** InsertThis - rewrite bind tree to add this->
+ *
+ * fSuccess = InsertThis (pName);
+ *
+ * Entry pName = pointer to search structure
+ *
+ * Exit tree rewritten such that the node pn becomes OP_pointsto
+ * with the left node being OP_this and the right node being
+ * the original symbol
+ *
+ * Returns TRUE if tree rewritten
+ * FALSE if error
+ */
+
+
+LOCAL bool_t __fastcall
+InsertThis (
+ psearch_t pName
+ )
+{
+ ushort len = 2 * (sizeof (node_t) + sizeof (eval_t));
+ ushort Left;
+ ushort Right;
+ pnode_t pn;
+ bnode_t bn = pName->bn;
+
+ Left = pTree->node_next;
+ Right = Left + sizeof (node_t) + sizeof (eval_t);
+ if ((ushort)(pTree->size - Left) < len) {
+ if (!GrowETree (len)) {
+ NOTTESTED (FALSE);
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ if (bnCxt != 0) {
+ // the context was pointing into the expression tree.
+ // since the expression tree could have been reallocated,
+ // we must recompute the context pointer
+
+ pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
+ }
+ }
+
+ // copy symbol to right node
+
+ _fmemcpy (pnodeOfbnode((bnode_t)Right), pnodeOfbnode(bn), sizeof (node_t) + sizeof (eval_t));
+
+ // insert OP_this node as left node
+
+ pn = pnodeOfbnode((bnode_t)Left);
+ _fmemset (pn, 0, sizeof (node_t) + sizeof (eval_t));
+ NODE_OP (pn) = OP_this;
+
+ // change original node to OP_pointsto
+
+ pn = pnodeOfbnode(bn);
+ _fmemset (pn, 0, sizeof (node_t) + sizeof (eval_t));
+ NODE_OP (pn) = OP_pointsto;
+ NODE_LCHILD (pn) = (bnode_t)Left;
+ NODE_RCHILD (pn) = (bnode_t)Right;
+ pTree->node_next += len;
+ return (TRUE);
+}
+
+
+/*
+ * load a constant symbol into a node.
+ */
+
+LOCAL bool_t
+DebLoadConst (
+ peval_t pv,
+ CONSTPTR pSym,
+ HSYM hSym
+ )
+{
+ uint skip = 0;
+ CV_typ_t type;
+ HTYPE hType;
+ plfEnum pEnum;
+
+ type = pSym->typind;
+ if (!CV_IS_PRIMITIVE (type)) {
+ // we also allow constants that are enumeration values, so check
+ // that the non-primitive type is an enumeration and set the type
+ // to the underlying type of the enum
+
+ MHOmfUnLock ((HDEP)hSym);
+ hType = THGetTypeFromIndex (EVAL_MOD (pv), type);
+ if (hType == 0) {
+ DASSERT (FALSE);
+ pSym = MHOmfLock ((HDEP)hSym);
+ pExState->err_num = ERR_BADOMF;
+ return (FALSE);
+ }
+ pEnum = (plfEnum)(&((TYPPTR)(MHOmfLock ((HDEP)hType)))->leaf);
+ if ((pEnum->leaf != LF_ENUM) || !CV_IS_PRIMITIVE (pEnum->utype)) {
+ DASSERT (FALSE);
+ MHOmfUnLock ((HDEP)hType);
+ pSym = MHOmfLock ((HDEP)hSym);
+ pExState->err_num = ERR_BADOMF;
+ return (FALSE);
+ }
+ MHOmfUnLock ((HDEP)hType);
+ pSym = MHOmfLock ((HDEP)hSym);
+ SetNodeType (pv, type);
+ // SetNodeType will resolve forward ref Enums - but we need to get the
+ // utype from the pv when this happens - sps
+ type = ENUM_UTYPE (pv);
+ }
+ else {
+ SetNodeType (pv, type);
+ }
+
+ EVAL_STATE (pv) = EV_rvalue;
+ if ((CV_MODE (type) != CV_TM_DIRECT) || ((CV_TYPE (type) != CV_SIGNED) &&
+ (CV_TYPE (type) != CV_UNSIGNED) && (CV_TYPE (type) != CV_INT))) {
+ DASSERT (FALSE);
+ pExState->err_num = ERR_BADOMF;
+ return (FALSE);
+ }
+ EVAL_ULONG (pv) = RNumLeaf (&pSym->value, &skip);
+ return (TRUE);
+}
diff --git a/private/windbg/eecan/debsym.h b/private/windbg/eecan/debsym.h
new file mode 100644
index 000000000..a934c9611
--- /dev/null
+++ b/private/windbg/eecan/debsym.h
@@ -0,0 +1,44 @@
+// enum specifying routine that initialized search
+
+typedef enum {
+ INIT_base,
+ INIT_tdef,
+ INIT_sym,
+ INIT_qual,
+ INIT_right,
+ INIT_RE
+} INIT_t;
+
+
+typedef enum HSYML_t {
+ HSYML_lexical,
+ HSYML_function,
+ HSYML_class,
+ HSYML_module,
+ HSYML_global,
+ HSYML_exe,
+ HSYML_public
+} HSYML_t;
+
+
+#if defined(DOS) && !defined(WINDOWS3)
+// these ordinals for the compare routines are additional above the ordinals
+// for entry points defined in the API. If entry points are added to the
+// API, then these ordinals need to be changed.
+
+#define FNCMP (pCVF->pCVfnCmp)
+#define TDCMP (pCVF->pCVtdCmp)
+#define CSCMP (pCVF->pCVcsCmp)
+#else
+#define FNCMP fnCmp
+#define TDCMP tdCmp
+#define CSCMP csCmp
+#endif
+
+
+typedef struct {
+ char str[26];
+} OPNAME;
+
+
+extern OPNAME OpName[];
diff --git a/private/windbg/eecan/debtree.c b/private/windbg/eecan/debtree.c
new file mode 100644
index 000000000..2daa67902
--- /dev/null
+++ b/private/windbg/eecan/debtree.c
@@ -0,0 +1,335 @@
+/*** DEBTREE.C - Routines for building expression tree
+ *
+ * Routines to take tokens lexed from expression string
+ * and add to expression tree (tree building routines).
+ */
+
+
+
+
+LOCAL ushort NEAR PASCAL AddLeaf (ptoken_t);
+LOCAL ushort NEAR PASCAL AddNode (ptoken_t);
+
+
+
+
+
+/*** PushToken - Push a token onto expression stack
+ *
+ *
+ * fSuccess = PushToken (ptok)
+ *
+ * Entry ptok = pointer to token_t structure to add
+ *
+ *
+ * Returns TRUE if token pushed ont expression stack
+ * FALSE if error
+ */
+
+
+ushort PASCAL PushToken (ptoken_t ptok)
+{
+ ushort retVal;
+
+ if (OP_IS_IDENT (ptok->opTok)) {
+ // if the node is an identifier, constant or end of function arguments
+ // just add it to the tree
+ retVal = AddLeaf (ptok);
+ }
+ else {
+ retVal = AddNode (ptok);
+ }
+ return (retVal);
+}
+
+
+
+
+/*** AddLeaf - Add a leaf node to the expression tree
+ *
+ * fSuccess = AddLeaf (ptok)
+ *
+ * Entry ptok = pointer to token to add to tree
+ * pExState->hStree = handle of syntax tree buffer
+ *
+ * Returns TRUE if successful
+ * FALSE if not and sets DebErr
+ *
+ * Notes The start_node index in the stree_t structure is not changed
+ * by AddLeaf. If there is only a single node, (OP_ident or
+ * OP_const), then start_node points to the correct node that
+ * was set by the routine that initialized the tree buffer.
+ * AddNode will set the correct node if there is a
+ * more complex parse tree.
+ */
+
+
+LOCAL ushort NEAR PASCAL AddLeaf (ptoken_t ptok)
+{
+ pnode_t pn;
+ peval_t pv;
+ bnode_t FAR *ia;
+ uint len;
+
+ // check for space
+
+ len = sizeof (node_t) + sizeof (eval_t);
+ if ((uint)(pTree->stack_base - pTree->node_next) < len) {
+ // syntax tree is full, grow it
+ if (!GrowTree (NODE_DEFAULT)) {
+ // grow failed, clean up and return error
+ pExState->err_num = ERR_TOOCOMPLEX;
+ return (EEGENERAL);
+ }
+ }
+ if (pTree->stack_next == NSTACK_MAX) {
+ pExState->err_num = ERR_TOOCOMPLEX;
+ return EEGENERAL;
+ }
+
+ pn = pnodeOfbnode((bnode_t)(pTree->node_next));
+
+ // Initialize the Node.
+
+ _fmemset ((char FAR *)pn, 0, len);
+ NODE_OP (pn) = ptok->opTok;
+ pv = &pn->v[0];
+ EVAL_ITOK (pv) = ptok->iTokStart;
+ EVAL_CBTOK (pv) = ptok->cbTok;
+
+ // If the node is a constant, retrieve its value from the token.
+
+ if (NODE_OP (pn) == OP_const) {
+ EVAL_TYP (pv) = ptok->typ;
+ EVAL_VAL (pv) = VAL_VAL (ptok);
+ }
+ ia = (bnode_t FAR *)((char FAR *)pTree + pTree->stack_base);
+ ia[pTree->stack_next++] = (bnode_t)(pTree->node_next);
+ pTree->node_next += len;
+ return (0);
+}
+
+
+
+
+/** AddNode - Add an operator node to the expression tree
+ *
+ * fSuccess = AddNode (ptok)
+ *
+ * Entry ptok = pointer to token to add
+ *
+ * Returns TRUE if node was added to tree
+ * FALSE if error
+ *
+ * Notes AddNode will set the start_node index in the stree_t structure
+ * to point to the node just added. If the statement is
+ * correctly parsed, start_node will contain the index of the
+ * last operator and there will be only one node on the stack
+ *
+ */
+
+
+LOCAL ushort NEAR PASCAL AddNode (ptoken_t ptok)
+{
+ pnode_t pn;
+ ushort retval = 0;
+ uint iStack;
+ bnode_t FAR *ia;
+ uint len;
+
+ // check for space
+
+ switch (ptok->opTok) {
+ case OP_cast:
+ case OP_function:
+ case OP_sizeof:
+ case OP_dot:
+ case OP_pointsto:
+ case OP_bscope:
+ case OP_pmember:
+ case OP_dotmember:
+ case OP_mult:
+ case OP_and:
+ // these operators use the eval_t portion of the node to store
+ // casting information. In the case of the OP_dot, etc., the
+ // casting information is the implicit cast of the left member
+ // to a base class if one is required.
+
+ len = sizeof (node_t) + sizeof (eval_t);
+ break;
+
+ case OP_arg:
+ len = sizeof (node_t) + sizeof (argd_t);
+ break;
+
+ case OP_context:
+ case OP_execontext:
+ len = sizeof (node_t) + sizeof (CXF);
+ break;
+
+ default:
+ len = sizeof (node_t);
+ break;
+ }
+ len = (len + 1) & ~1;
+ if ((uint)(pTree->stack_base - pTree->node_next) < len) {
+ // syntax tree is full, grow it
+ if (!GrowTree (NODE_DEFAULT)) {
+ // grow failed, clean up and return error
+ pExState->err_num = ERR_TOOCOMPLEX;
+ return (EEGENERAL);
+ }
+ }
+ pn = pnodeOfbnode((bnode_t)(pTree->node_next));
+
+ // Initialize the Node.
+
+ _fmemset (pn, 0, len);
+ NODE_OP (pn) = ptok->opTok;
+ if (ptok->opTok == OP_context || ptok->opTok == OP_execontext) {
+ EVAL_ITOK (&pn->v[0]) = ptok->iTokStart;
+ EVAL_CBTOK (&pn->v[0]) = ptok->cbTok;
+ }
+
+ // Set up the left and right children (left only if unary).
+
+ ia = (bnode_t FAR *)((char FAR *)pTree + pTree->stack_base);
+ iStack = pTree->stack_next;
+ if (OP_IS_BINARY (ptok->opTok)) {
+ if (iStack < 2) {
+ pExState->err_num = ERR_NOOPERAND;
+ retval = EEGENERAL;
+ }
+ else {
+ pn->pnRight = ia[--iStack];
+ pn->pnLeft = ia[--iStack];
+ }
+ }
+ else {
+ if (iStack < 1) {
+ pExState->err_num = ERR_NOOPERAND;
+ retval = EEGENERAL;
+ }
+ else {
+ pn->pnLeft = ia[--iStack];
+ pn->pnRight = 0;
+ }
+ }
+
+ // set this node into the start_node
+
+ if (retval == 0) {
+ ia[iStack++] = (bnode_t)(pTree->node_next);
+ pTree->start_node = pTree->node_next;
+ pTree->node_next += len;
+ pTree->stack_next = iStack;
+ }
+ return (retval);
+}
+
+
+
+
+
+/*** GrowTree - Grow space for the expression tree
+ *
+ * error = GrowTree (incr)
+ *
+ * Entry incr = amount to increase tree size
+ * pExState = address of expression state structure
+ * pExState->hSTree locked
+ *
+ * Exit pExState->hSTree locked
+ * pTree = address of locked syntax tree
+ *
+ * Returns TRUE if successful
+ * FALSE if unsuccessful
+ *
+ */
+
+
+bool_t FASTCALL GrowTree (uint incr)
+{
+ register HDEP NewTree;
+ register uint len;
+
+ len = pTree->size + incr;
+ MHMemUnLock (pExState->hSTree);
+ if ((NewTree = MHMemReAlloc (pExState->hSTree, len)) == 0) {
+ pTree = MHMemLock (pExState->hSTree);
+ return (FALSE);
+ }
+ else {
+ // reallocation succeeded, move data within buffer and update header
+
+ pExState->hSTree = NewTree;
+ pTree = MHMemLock (pExState->hSTree);
+ pTree->size = len;
+
+ // move parse stack down by allocated amount if the stack is in use
+ // by the parser. Stack in use is indicated by non-zero stack_base.
+ // If we are in the bind phase, stack_base is zero,
+
+ if (pTree->stack_base != 0) {
+ _fmemcpy ((char FAR *)pTree + pTree->stack_base + NODE_DEFAULT,
+ (char FAR *)pTree + pTree->stack_base,
+ NSTACK_MAX * sizeof (bnode_t));
+ pTree->stack_base += NODE_DEFAULT;
+ }
+ return (TRUE);
+ }
+}
+
+
+
+
+
+
+/*** GrowETree - Grow space for the expression tree
+ *
+ * error = GrowETree (incr)
+ *
+ * Entry incr = amount to increase tree size
+ * pExState = address of expression state structure
+ * pExState->hETree locked
+ *
+ * Exit pExState->hETree locked
+ * pTree = address of locked syntax tree
+ *
+ * Returns TRUE if successful
+ * FALSE if unsuccessful
+ *
+ */
+
+
+bool_t FASTCALL GrowETree (uint incr)
+{
+ register HDEP NewTree;
+ register uint len;
+
+ len = pTree->size + incr;
+ MHMemUnLock (pExState->hETree);
+ if ((NewTree = MHMemReAlloc (pExState->hETree, len)) == 0) {
+ pTree = MHMemLock (pExState->hETree);
+ return (FALSE);
+ }
+ else {
+ // reallocation succeeded, move data within buffer and update header
+
+ pExState->hETree = NewTree;
+ pTree = MHMemLock (pExState->hETree);
+ pTree->size = len;
+
+ // move parse stack down by allocated amount if the stack is in use
+ // by the parser. Stack in use is indicated by non-zero stack_base.
+ // If we are in the bind phase, stack_base is zero,
+
+ if (pTree->stack_base != 0) {
+ _fmemcpy ((char FAR *)pTree + pTree->stack_base + NODE_DEFAULT,
+ (char FAR *)pTree + pTree->stack_base,
+ NSTACK_MAX * sizeof (bnode_t));
+ pTree->stack_base += NODE_DEFAULT;
+ }
+ return (TRUE);
+ }
+}
diff --git a/private/windbg/eecan/debtyper.c b/private/windbg/eecan/debtyper.c
new file mode 100644
index 000000000..26dd5b8e0
--- /dev/null
+++ b/private/windbg/eecan/debtyper.c
@@ -0,0 +1,1696 @@
+/*** debtyper.c - typer module for expression evaluator
+ *
+ * Routines to validate, add, and change typing information in
+ * an expression tree.
+ */
+
+
+
+
+
+// Basic type groups.
+
+#define BTYP_INT 0x01 // signed/unsigned char, short, int, long
+#define BTYP_FLOAT 0x02 // float, double, long double
+#define BTYP_ENUM 0x04 // enums
+#define BTYP_VOID 0x08 // void
+#define BTYP_PTR 0x10 // pointers
+
+// ANSI-defined type groups.
+
+#define ANSI_BASIC (BTYP_INT | BTYP_FLOAT)
+#define ANSI_ENUM (BTYP_ENUM | BTYP_VOID)
+#define ANSI_INTEGRAL (BTYP_INT | BTYP_ENUM)
+#define ANSI_FLOAT (BTYP_FLOAT)
+#define ANSI_ARITH (ANSI_INTEGRAL | ANSI_FLOAT)
+#define ANSI_SCALAR (ANSI_ARITH | BTYP_PTR)
+
+
+
+// Operator class mapping.
+
+
+#ifdef WIN32
+LOCAL uchar mpopopc[COPS_EXPR] = {
+#else
+LOCAL uchar _based (_segname("_CODE")) mpopopc[COPS_EXPR] = {
+#endif
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalko) opclass,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+
+// Data structure for determining legality of operator/operand
+// combinations.
+//
+// opc = operator class from debops.h. (OPC_null is not checked)
+// atLeft = flags for types that can left hand operand
+// atRight = flags for types that can be right hand operand
+
+
+LOCAL struct {
+ char opc; // Operator class
+ uchar atLeft; // Aggregate Type'
+ uchar atRight;
+}
+optypLegal[] = {
+ { OPC_integral, ANSI_INTEGRAL, ANSI_INTEGRAL },
+ { OPC_scalar, ANSI_SCALAR, ANSI_SCALAR },
+ { OPC_arith, ANSI_ARITH, ANSI_ARITH },
+ { OPC_ptr, BTYP_PTR, BTYP_PTR },
+ { OPC_ptrint, BTYP_PTR, ANSI_INTEGRAL },
+ { OPC_ptrint, ANSI_INTEGRAL, BTYP_PTR },
+ { OPC_relat, ANSI_ARITH, ANSI_ARITH },
+ { OPC_relat, BTYP_PTR, BTYP_PTR },
+ { OPC_relat, BTYP_PTR, ANSI_INTEGRAL }, // M00ANSI
+ { OPC_relat, ANSI_INTEGRAL, BTYP_PTR }, // M00ANSI
+ { OPC_equiv, ANSI_ARITH, ANSI_ARITH },
+ { OPC_equiv, BTYP_PTR, BTYP_PTR },
+ { OPC_equiv, BTYP_PTR, ANSI_INTEGRAL },
+ { OPC_equiv, ANSI_INTEGRAL, BTYP_PTR },
+ { OPC_plus, ANSI_ARITH, ANSI_ARITH },
+ { OPC_plus, BTYP_PTR, ANSI_INTEGRAL },
+ { OPC_plus, ANSI_INTEGRAL, BTYP_PTR },
+ { OPC_minus, ANSI_ARITH, ANSI_ARITH },
+ { OPC_minus, BTYP_PTR, ANSI_INTEGRAL },
+ { OPC_minus, BTYP_PTR, BTYP_PTR }
+};
+
+
+#define C_OPTYP_LEGAL (sizeof (optypLegal) / sizeof (optypLegal[0]))
+
+
+LOCAL void NEAR PASCAL CastRelational (peval_t, peval_t);
+LOCAL bool_t NEAR PASCAL CastToBase (peval_t, peval_t);
+LOCAL ushort NEAR PASCAL CheckType (peval_t, ushort);
+LOCAL void NEAR PASCAL CvtPtr (peval_t, CV_typ_t);
+LOCAL void NEAR PASCAL CvtSizeUp (peval_t);
+LOCAL void NEAR PASCAL CvtSizeDown (peval_t);
+LOCAL CV_typ_t NEAR FASTCALL IntegralPromote (CV_typ_t);
+LOCAL ushort NEAR PASCAL LegalTypes (opc_t, peval_t, peval_t);
+
+
+
+
+
+/** CastNode - Cast a node to a specified type
+ *
+ * CastNode (pv, dType, uType)
+ *
+ * Entry pv = pointer to value to cast
+ * dType = desired resultant type
+ * dType = T_NOTYPE if cast of based pointer to far pointer
+ * uType = type of underlying type if pointer. Used only if
+ * dType is T_xCVPTR
+ *
+ * Exit
+ *
+ * Returns
+ *
+ * Note The actual casting of the value is performed only if the
+ * Evaluating flag is set true by the top level routines
+ */
+
+
+bool_t PASCAL CastNode (peval_t pv, CV_typ_t dType, CV_typ_t uType)
+{
+ ushort size;
+
+ /*
+ * Check to see if the current type is already equal to the desired
+ * pointer type.
+ */
+
+ if (EVAL_TYP (pv) == dType) {
+ /*
+ * If the desired type is one of the internal only primitive pointer
+ * types, check to see if the underlying types are the same,
+ * if so then finished.
+ *
+ * If the desired type is not one of our special internals then
+ * we are also done
+ */
+
+ if ((dType == T_NCVPTR) || (dType == T_FCVPTR) ||
+ (dType == T_HCVPTR)) {
+
+ if (PTR_UTYPE (pv) == uType) {
+ return (TRUE);
+ }
+ } else {
+ return (TRUE);
+ }
+ }
+
+ /*
+ * If the desired type is VOID then all casts succeed.
+ */
+
+ if (dType == T_VOID) {
+ return (SetNodeType (pv, T_VOID));
+ }
+
+ /*
+ * If the current type is VOID then complain since nothing can be
+ * cast from VOID by us.
+ */
+
+ if (EVAL_TYP (pv) == T_VOID) {
+ // cannot cast from void to any other type
+ goto badcast;
+ }
+
+ /*
+ * If the current type is based then attempt to change the type
+ * from based to far and then do normal processing
+ */
+
+ if (EVAL_IS_BASED (pv)) {
+ // this can be one of the following:
+ // cast from based pointer to far pointer
+ //
+ // M00KLUDGE - this code does not work because the CV information
+ // M00KLUDGE - does not not necessarily contain the type record
+ // M00KLUDGE - for the far pointer to type. What we could do is
+ // M00KLUDGE - search the type records for a pointer for which the
+ // M00KLUDGE - underlying type is the same as for the based pointer
+
+ // if we have a based pointer, then we normalize it
+ // to a far pointer to the underlying type
+
+ if (!NormalizeBase (pv)) {
+ goto badcast;
+ }
+ return (TRUE);
+ }
+
+ /*
+ * If the current type is a pointer ---
+ */
+
+ if (EVAL_IS_PTR (pv)) {
+ /*
+ * ---- And the desired type is also a pointer
+ */
+
+ if (!CV_IS_PRIMITIVE (dType)) {
+ // this may be one of the following:
+ // cast from a pointer to a based pointer M00KLUDGE - does not work
+ // cast from pointer to derived to pointer to base
+ // cast from reference to derived to reference to base
+
+ if (!SetNodeType (pv, dType)) {
+ // the destination type does not exist
+ goto badcast;
+ }
+ if (EVAL_IS_BASED (pv)) {
+ // cast pointer to based pointer M00KLUDGE - this does not work
+ DASSERT (FALSE);
+ //return (DeNormalizePtr (pv, pvT));
+ }
+ return (TRUE);
+ }
+
+ /*
+ * ---- And the desired type is one of our special internal
+ * pointer types
+ */
+
+ else if ((dType == T_NCVPTR) || (dType == T_FCVPTR) ||
+ (dType == T_HCVPTR)) {
+ // this may be one of the following:
+ // one of above with dType being a constructed pointer to class
+ EVAL_TYP (pv) = uType;
+ if (!SetNodeType (pv, dType)) {
+ // the destination type does not exist
+ goto badcast;
+ }
+ return (TRUE);
+ }
+ }
+
+ /*
+ * If the desired type is a primiative pointer or the desired
+ * and underlying types are not the same.
+ *
+ * The second case should be that the desired type is a pointer
+ * to the underlying type. If not then we have a problem.
+ */
+
+ if ((CV_IS_PRIMITIVE (dType) && CV_TYP_IS_PTR (dType)) ||
+ (dType != uType)) {
+ /*
+ * Can't convert real numbers to pointers.
+ */
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pv)) &&
+ CV_TYP_IS_REAL (EVAL_TYP (pv))) {
+ goto badcast;
+ }
+
+ /*
+ * If we are currently in the evalutation phase, then we need
+ * to do some acutally manipulation of the value.
+ */
+
+ if (Evaluating) {
+ /*
+ * If the value starts as a pointer -- no work to change
+ * it to a pointer
+ */
+
+ if (EVAL_IS_PTR (pv) || EVAL_IS_FCN (pv)) {
+ ;
+ }
+ /*
+ * If casting a non-pointer to a primitive pointer, the
+ * work depends on what the current type is.
+ */
+
+ else if (CV_IS_PRIMITIVE (dType)) {
+
+ ADDR_IS_LI (EVAL_PTR (pv)) = FALSE;
+ switch ( CV_MODE(dType)) {
+ /*
+ * Desired type is a near 16 bit pointer -- use
+ * the low 16-bits of the value and the DS register
+ * to make an address
+ */
+
+ case CV_TM_NPTR:
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ EVAL_PTR_OFF (pv) = EVAL_USHORT (pv);
+ break;
+
+ /*
+ * Desired type is a far or huge 16-bit pointer --
+ * If a short then construct a pointer using DS
+ * otherwise use the 32-bit value to build a pointer
+ */
+
+ case CV_TM_FPTR:
+ case CV_TM_HPTR:
+ if ( TypeSize(pv) < 4) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ EVAL_PTR_OFF (pv) = EVAL_USHORT (pv);
+ } else {
+ EVAL_PTR_SEG (pv) = (WORD) (EVAL_ULONG (pv) >> 16);
+ EVAL_PTR_OFF (pv) = EVAL_ULONG (pv) & 0xffff;
+ }
+ break;
+
+ /*
+ * Desired type is a 32-bit near pointer. Construct
+ * the value from DS and the value. Result will
+ * be a FLAT address.
+ *
+ * NOTENOTE -- jimsch -- result may not be flat only
+ * off32 if we get a 32-bit dos extender.
+ */
+
+ case CV_TM_NPTR32:
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ if (TypeSize(pv) < 4) {
+ EVAL_PTR_OFF(pv) = EVAL_USHORT(pv);
+ } else {
+ EVAL_PTR_OFF (pv) = EVAL_ULONG(pv);
+ }
+ ADDR_IS_FLAT(EVAL_PTR(pv)) = TRUE;
+ ADDR_IS_OFF32(EVAL_PTR(pv)) = TRUE;
+ break;
+
+ /*
+ * Desired address is a large unsupported pointer or
+ * not a pointer at all. In either case we should never
+ * get here. If we do then panic
+ */
+
+ case CV_TM_FPTR32:
+ case CV_TM_NPTR64:
+ case CV_TM_DIRECT:
+ default:
+ DASSERT(FALSE);
+ }
+
+ /*
+ * Set the type to the underlying type and then reset
+ * to the desired pointer type.
+ */
+
+ EVAL_TYP (pv) = uType;
+ return (SetNodeType (pv, dType));
+ }
+ /*
+ * The desired pointer type is not a primitive type. In
+ * this case we may have trouble since the desired types
+ * not not really exist. Or may not be legal to be pointers.
+ */
+
+ else {
+ plfPointer pType;
+ HTYPE hType;
+
+ /*
+ * First just try and do the type assignments without
+ * worrying about what values to pound on.
+ */
+
+ size = (ushort) TypeSize (pv);
+ EVAL_TYP (pv) = uType;
+ if (!SetNodeType (pv, dType)) {
+ return (FALSE);
+ }
+
+ /*
+ * Ensure that the resulting type is indeed a pointer,
+ * since otherwise we can not do the cast.
+ */
+
+ hType = THGetTypeFromIndex( EVAL_MOD(pv) , dType );
+ DASSERT( hType != (HTYPE) NULL );
+ pType = (plfPointer) (&((TYPPTR) MHOmfLock( (HDEP)hType ))->leaf);
+ if (pType->leaf != LF_POINTER) {
+ pExState->err_num = ERR_NEEDLVALUE;
+ MHOmfUnLock((HDEP)hType);
+ return FALSE;
+ }
+
+ ADDR_IS_LI (EVAL_PTR (pv)) = FALSE;
+
+ /*
+ * Depending on the type of the desired pointer
+ * result then manipulate the address appropriately
+ */
+
+ switch ( pType->attr.ptrtype ) {
+ /*
+ * To make a near pointer use the low 16-bits
+ * and DS to make an address.
+ */
+
+ case CV_PTR_NEAR:
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ EVAL_PTR_OFF (pv) = EVAL_USHORT (pv);
+ break;
+
+ /*
+ * To make a far or huge 16-bit pointer use
+ * all of the bits available. If not enough
+ * then toss in DS to make things happy.
+ */
+
+ case CV_PTR_FAR: /* mode is a far pointer */
+ case CV_PTR_HUGE: /* mode is a huge pointer */
+ if ( TypeSize(pv) < 4) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ EVAL_PTR_OFF (pv) = EVAL_USHORT (pv);
+ }
+ else {
+ EVAL_PTR_SEG (pv) = (WORD) (EVAL_ULONG (pv) >> 16);
+ EVAL_PTR_OFF (pv) = EVAL_ULONG (pv) & 0xffff;
+ }
+ break;
+
+ /*
+ * To make a near-32 bit pointer -- toss in DS
+ * and use all available bits of data.
+ *
+ * NOTENOTE -- jimsch -- result may not be flat only
+ * off32 if we get a 32-bit dos extender.
+ */
+
+ case CV_PTR_NEAR32: /* mode is 32 bit near pointer */
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ if (TypeSize(pv) < 4) {
+ EVAL_PTR_OFF(pv) = EVAL_USHORT(pv);
+ } else {
+ EVAL_PTR_OFF (pv) = EVAL_ULONG(pv);
+ }
+ ADDR_IS_FLAT(EVAL_PTR(pv)) = TRUE;
+ ADDR_IS_OFF32(EVAL_PTR(pv)) = TRUE;
+ break;
+
+ /*
+ * We don't support these types of pointers or
+ * direct at this point. panic if we get here.
+ */
+
+ case CV_PTR_FAR32: /* mode is 32 bit far pointer */
+ default:
+ DASSERT(FALSE);
+ break;
+ }
+ MHOmfUnLock((HDEP)hType);
+ }
+ }
+ /*
+ * Now just preform the type overrides and set up any
+ * new bit patters to match the new types.
+ */
+
+ EVAL_TYP (pv) = uType;
+ return (SetNodeType (pv, dType));
+ }
+
+ if (dType == T_SEGMENT) {
+ // If the requested type is T_SEGMENT and the type of the node is
+ // pointer, then the value of the resulting node is either DS or
+ // the segment portion of the node value.
+
+ if (!EVAL_IS_PTR (pv)) {
+ goto badcast;
+ }
+ if (Evaluating) {
+ if (EVAL_IS_NPTR (pv) == CV_TM_NPTR) {
+ // M00KLUDGE - if this test never hits, the the ptr is far form
+ DASSERT (EVAL_PTR_OFF (pv) == pExState->frame.DS); //M00FLAT32
+ EVAL_USHORT (pv) = pExState->frame.DS; //M00FLAT32
+ }
+ else {
+ EVAL_USHORT (pv) = EVAL_PTR_SEG (pv);
+ }
+ }
+ return (SetNodeType (pv, dType));
+ }
+
+ // If the node is not a primitive type but is an address, then convert
+ // the type of the node to a near or far pointer to character.
+
+ if (!CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
+ if (!EVAL_IS_ADDR (pv)) {
+ goto badcast;
+ }
+ if (ADDR_IS_LI (EVAL_PTR (pv))) {
+ SHFixupAddr (&EVAL_PTR (pv));
+ }
+ SetNodeType (pv, (CV_typ_t) (EVAL_IS_NPTR (pv)? T_PCHAR: T_PFCHAR));
+ }
+
+ // The code above has already taken care of casting a value to a pointer.
+ // Therefore, if the input node is a pointer, then this must be a cast
+ // from a pointer to another type
+
+ if (EVAL_IS_PTR (pv)) {
+ if (ADDR_IS_LI( EVAL_PTR( pv ))) {
+ SHFixupAddr( &EVAL_PTR( pv ));
+ }
+
+ // If converting from pointer. The T_ULONG works because we carry
+ // all pointers as seg:offset
+ /*
+ * NOTENOTE -- JIMSCH -- this code needs adding to if we get
+ * a 32-bit dos-extender
+ */
+
+ if (ADDR_IS_FLAT(EVAL_PTR(pv))) {
+ EVAL_ULONG(pv) = EVAL_PTR_OFF(pv);
+ } else {
+ EVAL_LONG (pv) = ((ulong)EVAL_PTR_SEG (pv) << 16) |
+ EVAL_PTR_OFF (pv);
+ }
+ SetNodeType (pv, T_ULONG);
+ }
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pv)) && !CV_IS_PRIMITIVE (dType)) {
+ goto badcast;
+ }
+
+ // We are casting pointers to integral/real types and among the integral
+ // types.
+
+ DASSERT (!EVAL_IS_PTR (pv));
+ DASSERT (CV_IS_PRIMITIVE (dType));
+ DASSERT (CV_IS_PRIMITIVE (EVAL_TYP (pv)));
+
+ // If we're converting from a real to a non-real, first convert
+ // to a double, then to a long. Then the node is a long and the
+ // desired type is an integer of some sort; let the code below
+ // do its work.
+
+ if ((CV_TYP_IS_REAL (EVAL_TYP (pv))) && (!CV_TYP_IS_REAL (dType))) {
+ if (Evaluating) {
+ switch (EVAL_TYP (pv)) {
+ case T_REAL32:
+ EVAL_LONG (pv) = (long)EVAL_FLOAT (pv);
+ break;
+
+ case T_REAL64:
+ EVAL_LONG (pv) = (long)EVAL_DOUBLE (pv);
+ break;
+
+ case T_REAL80:
+ EVAL_LONG (pv) = R10CastToLong(EVAL_LDOUBLE (pv));
+ break;
+ }
+ }
+ SetNodeType (pv, T_LONG);
+ }
+
+ // Otherwise, if we're converting a non-real to a real, first
+ // convert to a long, then to a double. Then the node is a
+ // double and the desired type is a real of some sort and the
+ // code below works normally.
+
+ else if ((!CV_TYP_IS_REAL (EVAL_TYP (pv))) && (CV_TYP_IS_REAL (dType))) {
+ if (EVAL_TYP (pv) != T_ULONG) {
+ CastNode (pv, T_LONG, T_LONG);
+ if (Evaluating) {
+ EVAL_DOUBLE (pv) = (double)EVAL_LONG (pv);
+ }
+ }
+ else {
+ if (Evaluating)
+ EVAL_DOUBLE (pv) = (double)EVAL_ULONG (pv);
+ }
+ SetNodeType (pv, T_REAL64);
+ }
+ if (EVAL_TYP (pv) == T_SEGMENT) {
+ SetNodeType (pv, T_USHORT);
+ }
+
+ // Increment or decrement the size of the node's type until it
+ // matches the size of the desired type.
+
+ size = (ushort) TypeSizePrim (dType);
+ if ((ushort)TypeSizePrim (EVAL_TYP (pv)) < size) {
+ while ((ushort)TypeSizePrim (EVAL_TYP (pv)) < size) {
+ CvtSizeUp (pv);
+ }
+ }
+ else if ((ushort)TypeSizePrim (EVAL_TYP (pv)) > size) {
+ while ((ushort)TypeSizePrim (EVAL_TYP (pv)) > size) {
+ CvtSizeDown (pv);
+ }
+ }
+ return (SetNodeType (pv, dType));
+
+badcast:
+ pExState->err_num = ERR_TYPECAST;
+ return (FALSE);
+}
+
+
+
+
+/*** TypeNodes - Add type information to child nodes
+ *
+ * TypeNodes (op, pvL, pvR)
+ *
+ * Entry op = operator (OP_...)
+ * pvL = pointer to left-child value
+ * pvR = pointer to right-child valuee (or NULL if unary operator)
+ *
+ * Exit
+ *
+ * Returns none
+ *
+ * Adds type information to child nodes for the specified operator.
+ *
+ */
+
+
+void PASCAL TypeNodes (op_t op, peval_t pvL, peval_t pvR)
+{
+ register CV_typ_t typT;
+
+
+ //DASSERT ((op != OP_lparen) && (op != OP_rparen));
+ //DASSERT (pvL != NULL);
+ //DASSERT (EVAL_STATE (pvL) != EV_ident);
+ //DASSERT ((pvR == NULL) || (EVAL_STATE (pvR) != EV_ident));
+
+ // Type the children according to the operator.
+
+ switch (op) {
+ case OP_plus:
+ case OP_minus:
+
+ // ANSI 3.3.6
+ // If pointers are involved (pointer arithmetic), no
+ // conversion of the operands is necessary. Otherwise,
+ // the 'usual arithmetic conversions' are performed.
+
+ if ((!EVAL_IS_PTR (pvL)) && (!EVAL_IS_PTR (pvR))) {
+ // perform usual arithmetic conversions
+ goto L_uac;
+ }
+ break;
+
+ case OP_shl:
+ case OP_shr:
+ case OP_segop: // Special
+ case OP_segopReal:
+
+ // ANSI 3.3.7
+ // An integral promotion is performed on each operand.
+
+ typT = IntegralPromote (EVAL_TYP (pvL));
+ CastNode (pvL, typT, typT);
+ typT = IntegralPromote (EVAL_TYP (pvR));
+ CastNode (pvR, typT, typT);
+ break;
+
+ case OP_lt: // ANSI 3.3.8
+ case OP_lteq:
+ case OP_gt:
+ case OP_gteq:
+ case OP_eqeq: // ANSI 3.3.9
+ case OP_bangeq:
+
+ // Either both operands are arithmetic, both are
+ // pointers, or one is a pointer and the other is
+ // integral (M00ANSI: ANSI only allows equality
+ // comparisons with the 'null pointer constant' and
+ // does not allow relational comparisons of pointers
+ // with integers at all). If both are arithmetic,
+ // the usual arithmetic conversions are performed.
+ // If either is a pointer, we call a special routine.
+
+ if ((EVAL_IS_PTR (pvL)) || (EVAL_IS_PTR (pvR))) {
+ CastRelational (pvL, pvR);
+ }
+ else {
+ // perfor usual arithmetic conversions
+ goto L_uac;
+ }
+ break;
+
+ case OP_bang: // ANSI 3.3.3.3
+ case OP_andand: // ANSI 3.3.13
+ case OP_oror: // ANSI 3.3.14
+ case OP_fetch: // ANSI 3.3.3.2
+ case OP_addrof:
+ case OP_lbrack: // ANSI 3.3.2.1
+ case OP_pointsto: // ANSI 3.3.2.3
+ case OP_dot:
+ case OP_by: // Special
+ case OP_wo:
+ case OP_dw:
+
+ // No conversion necessary.
+
+ break;
+
+ case OP_eq: // ANSI 3.3.16
+ case OP_multeq:
+ case OP_diveq:
+ case OP_modeq:
+ case OP_pluseq:
+ case OP_minuseq:
+ case OP_shleq:
+ case OP_shreq:
+ case OP_andeq:
+ case OP_xoreq:
+ case OP_oreq:
+
+ // These operators not yet supported (i.e., we
+ // shouldn't get here).
+
+ DASSERT(FALSE);
+ break;
+
+ case OP_negate: // ANSI 3.3.3.3
+ case OP_uplus:
+ case OP_tilde:
+
+ // An integral promotion is performed on the operand.
+
+ typT = IntegralPromote (EVAL_TYP (pvL));
+ CastNode (pvL, typT, typT);
+ break;
+
+ case OP_mult: // ANSI 3.3.5
+ case OP_div:
+ case OP_mod:
+ case OP_and: // ANSI 3.3.10
+ case OP_xor: // ANSI 3.3.11
+ case OP_or: // ANSI 3.3.12
+
+ // The usual arithmetic conversions are performed on each
+ // operand.
+
+L_uac:
+ typT = PerformUAC (EVAL_TYP (pvL), EVAL_TYP (pvR));
+ CastNode (pvL, typT, typT);
+ CastNode (pvR, typT, typT);
+ break;
+
+ default:
+ DASSERT(FALSE);
+ ;
+ }
+}
+
+
+
+
+/*** ValidateNodes - Ensure that operator node has valid operands
+ *
+ * fValid = ValidateNodes (op, pvL, pvR)
+ *
+ * Entry op = operator (OP_...)
+ * pvL = pointer to left-child value
+ * pvR = pointer to right-child value (or NULL if unary operator)
+ *
+ * Exit pExState->err_num = ERR_TYPEINCOMPAT if incorrect operands
+ *
+ * Returns TRUE if operands are valid for operator
+ * FALSE if operands are not valid
+ */
+
+
+bool_t PASCAL ValidateNodes (op_t op, peval_t pvL, peval_t pvR)
+{
+ register int i;
+ register opc_t opc;
+
+ if ((opc = mpopopc[op]) == OPC_null) {
+ return (TRUE);
+ }
+ // if the operand type in the mapping table is not OPC_null, then
+ // the operands must be checked
+
+ for (i = 0; i < C_OPTYP_LEGAL; i++) {
+ // search table looking for operator class
+ if ((op_t)optypLegal[i].opc == opc) {
+ if ((CheckType (pvL, optypLegal[i].atLeft)) &&
+ ((pvR == NULL) || (CheckType (pvR, optypLegal[i].atRight)))) {
+ return (TRUE);
+ }
+ }
+ }
+ pExState->err_num = ERR_TYPEINCOMPAT;
+ return (FALSE);
+}
+
+
+
+
+/** CastRelational - Cast child nodes for relational operators
+ *
+ * CastRelational (pvL, pvR)
+ *
+ * Entry pvL = pointer to left value
+ * pvR = pointer to right child value
+ *
+ * Exit both values cast to the proper types
+ *
+ * Returns none
+ *
+ * DESCRIPTION
+ * Casts two child nodes when one or both are pointers and the
+ * operator is a relational or equality operator ('<', '<=', '>',
+ * '>=', '==', '!=').
+ *
+ * ANSI does not discuss this; the rules used are described below.
+ */
+
+
+LOCAL void NEAR PASCAL CastRelational (peval_t pvL, peval_t pvR)
+{
+ CV_typ_t typL, typR;
+ register CV_typ_t typRes;
+
+ // Since we're going to be doing comparisons on the pointers, we
+ // don't really care what sort of thing they point TO (M00ANSI:
+ // ANSI says we have to make sure they both point to the same
+ // type of object). Therefore, make sure the pointers are primitive
+ // (T_PCHAR or T_PFCHAR).
+
+ if (EVAL_IS_PTR (pvL))
+ CvtPtr (pvL, EVAL_TYP (pvL));
+
+ if (EVAL_IS_PTR (pvR))
+ CvtPtr (pvR, EVAL_TYP (pvR));
+
+ // Fetch the types of the nodes.
+
+ typL = EVAL_TYP (pvL);
+ typR = EVAL_TYP (pvR);
+
+ /*
+ * The cases are:
+ *
+ * (1) near ptr cmp near ptr
+ * (2) near ptr cmp far ptr
+ * (3) far ptr cmp far ptr
+ * (4) near ptr cmp char, uchar, short, ushort, int, uint
+ * (5) near ptr cmp long, ulong
+ * (6) far ptr cmp char, uchar, short, ushort, int, uint
+ * (7) far ptr cmp long, ulong
+ *
+ *
+ * Cases (1) and (3) require no casting; case (2) requires the
+ * near pointer to be cast to a far pointer (DS-extended). Case
+ * (4) requires the integral operand to be cast to a near pointer.
+ * Case (5) requires both operands to be cast to far pointers.
+ * Cases (6) and (7) require the integral operand to be cast to
+ * a far pointer.
+ *
+ * Note that all this can be reduced to: if either operand has
+ * size CV_IN_4BYTE (long, ulong) or is a far pointer, cast both
+ * operands to far pointers; otherwise cast both operands to
+ * near pointers.
+ */
+
+ //DASSERT ((CV_IS_PRIMITIVE(typL)) && (CV_IS_PRIMITIVE(typR)));
+
+ typRes = T_PCHAR; // Assume //
+
+ if ((CV_TYP_IS_NPTR32(typL)) ||
+ (CV_TYP_IS_NPTR32(typR))) {
+ typRes = T_32PCHAR;
+ } else if ((CV_TYP_IS_FPTR(typL)) ||
+ (CV_TYP_IS_FPTR(typR)) ||
+ ((CV_TYP_IS_DIRECT(typL)) && (CV_SUBT(typL) == CV_IN_4BYTE)) ||
+ ((CV_TYP_IS_DIRECT(typL)) && (CV_SUBT(typR) == CV_IN_4BYTE))) {
+ typRes = T_PFCHAR;
+ } else if (CV_TYP_IS_FPTR32(typL) || (CV_TYP_IS_FPTR32(typR))) {
+ DASSERT(FALSE);
+ }
+
+ // Now cast both nodes to the resultant type and we're done.
+ //
+
+ CastNode (pvL, typRes, typRes);
+ CastNode (pvR, typRes, typRes);
+}
+
+
+
+
+/** CheckType - Is a value's type one of a specified aggregate type?
+ *
+ * fTypeOK = CheckType (pv, at)
+ *
+ * Entry pv = pointer to node whose type is to be checked
+ * at = aggregate type flags (ANSI_...)
+ *
+ * Exit none
+ *
+ * Returns TRUE if node's type is acceptable for the aggregate type
+ * FALSE if the type is not acceptable
+ */
+
+
+LOCAL ushort NEAR PASCAL CheckType (peval_t pv, ushort at)
+{
+ register CV_typ_t typ;
+
+ if (EVAL_IS_REF (pv)) {
+ // if the node is a reference, then the type is really that of the
+ // underlying type
+
+ typ = PTR_UTYPE (pv);
+ }
+ else if (EVAL_IS_BITF (pv)) {
+ // if the node is a bitfield, then the type is really that of the
+ // underlying type
+
+ typ = BITF_UTYPE (pv);
+ }
+ else {
+ typ = EVAL_TYP (pv);
+ }
+
+ // If the type is a pointer, it is compatible if the aggregate
+ // type permits pointers.
+
+ if (EVAL_IS_PTR (pv)) {
+ return ((ushort) (at & BTYP_PTR));
+ }
+ if (!CV_IS_PRIMITIVE (typ)) {
+ // If the (underlying) type is not primitive, it cannot match
+ return (FALSE);
+ }
+
+ // The type is not a pointer (mode is CV_TM_DIRECT). If the basic
+ // type is CV_TM_SIGNED or CV_TM_UNSIGNED, it is compatible iff the
+ // aggregate type allows ints (any flavor).
+
+ if ((CV_TYP_IS_SIGNED (typ)) || (CV_TYP_IS_UNSIGNED (typ)))
+ return ((ushort)(at & BTYP_INT));
+
+ // If the type is a real of some sort, it is compatible iff the
+ // aggregate type contains BTYP_FLOAT.
+
+ if (CV_TYP_IS_REAL (typ))
+ return ((ushort)(at & BTYP_FLOAT));
+
+ // M00UNDONE: void, enums.
+
+ return (FALSE);
+}
+
+
+
+
+/** CvtPtr - Convert pointer to primitive pointer
+ *
+ * CvtPtr (pv, target)
+ *
+ * Entry pv = pointer to value to be converted
+ * typTrgt = target type
+ *
+ * Exit value converted to T_PCHAR, T_PFCHAR or T_PHCHAR
+ *
+ * Returns None
+ *
+ */
+
+
+LOCAL void NEAR PASCAL CvtPtr (peval_t pv, CV_typ_t typTrgt)
+{
+ register CV_typ_t typ;
+
+ switch (EVAL_PTRTYPE (pv)) {
+ case CV_PTR_NEAR:
+ typ = T_PCHAR;
+ break;
+
+ case CV_PTR_FAR:
+ typ = T_PFCHAR;
+ break;
+
+ case CV_PTR_HUGE:
+ typ = T_PHCHAR;
+ break;
+
+ case CV_PTR_NEAR32:
+ typ = T_32PCHAR;
+ break;
+
+ case CV_PTR_FAR32:
+ typ = T_32PFCHAR;
+ break;
+
+ default:
+ if (CV_IS_PRIMITIVE (typTrgt) &&
+ (CV_SUBT (typTrgt) < CV_IN_4BYTE ) &&
+ CV_TYP_IS_DIRECT (typTrgt) &&
+ (CV_TYPE (typTrgt) < CV_REAL)) {
+ typ = T_PCHAR;
+ }
+ else {
+ if (EVAL_STATE (pv) != EV_lvalue) {
+ if (!NormalizeBase (pv)) {
+ if ((pExState->err_num != 0) ||
+ !(CV_TYP_IS_NPTR (typTrgt))) {
+ break;
+ }
+ }
+ }
+ typ = T_PFCHAR;
+ }
+ break;
+ }
+ SetNodeType (pv, typ);
+}
+
+
+
+
+/** CvtSizeDown - Convert size of value's type down one step
+ *
+ * CvtSizeDown (pv)
+ *
+ * Entry pv = pointer to value
+ *
+ * Exit value is cast to next smaller size
+ *
+ * Returns none
+ *
+ * Converts the size of the node's type down one step:
+ *
+ * type far * -> type *
+ * ldouble -> double
+ * double -> float
+ * (u)quad -> (u)long
+ * (u)long -> (u)short
+ * (u)short -> (u)char
+ */
+
+
+LOCAL void NEAR PASCAL CvtSizeDown (peval_t pv)
+{
+ register CV_typ_t typ;
+
+ if (CV_TYP_IS_FPTR (EVAL_TYP (pv))) {
+
+ // Far ptr -> near ptr.
+
+ if (Evaluating) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS; //M00FLAT32
+ }
+ typ = CV_NEWMODE (EVAL_TYP (pv), CV_TM_NPTR);
+ }
+ else {
+ switch (EVAL_TYP (pv)) {
+ case T_REAL80:
+ typ = T_REAL64;
+ break;
+
+ case T_REAL64:
+ typ = T_REAL32;
+ break;
+
+ case T_QUAD:
+ case T_INT8:
+ typ = T_LONG;
+ break;
+
+ case T_UQUAD:
+ case T_UINT8:
+ typ = T_ULONG;
+ break;
+
+ case T_LONG:
+ case T_INT4:
+ typ = T_SHORT;
+ break;
+
+ case T_ULONG:
+ case T_UINT4:
+ typ = T_USHORT;
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+ typ = T_CHAR;
+ break;
+
+ case T_USHORT:
+ case T_UINT2:
+ typ = T_UCHAR;
+ break;
+
+ default:
+ DASSERT(FALSE);
+ return;
+ }
+ if (Evaluating) {
+ switch (EVAL_TYP (pv)) {
+ case T_REAL80:
+ EVAL_DOUBLE (pv) = R10CastToDouble(EVAL_LDOUBLE (pv));
+ break;
+
+ case T_REAL64:
+ EVAL_FLOAT (pv) = (float)EVAL_DOUBLE (pv);
+ break;
+
+ case T_QUAD:
+ case T_INT8:
+ EVAL_LONG (pv) = (long)EVAL_QUAD (pv).LowPart;
+ break;
+
+ case T_UQUAD:
+ case T_UINT8:
+ EVAL_ULONG (pv) = (ulong)EVAL_UQUAD (pv).LowPart;
+ break;
+
+ case T_LONG:
+ case T_INT4:
+ EVAL_LONG(pv) &= 0xffff;
+// EVAL_SHORT (pv) = (short)EVAL_LONG (pv);
+ break;
+
+ case T_ULONG:
+ case T_UINT4:
+ EVAL_LONG(pv) &= 0xffff;
+// EVAL_USHORT (pv) = (ushort)EVAL_ULONG (pv);
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+ EVAL_SHORT(pv) &= 0xff;
+// EVAL_CHAR (pv) = (char)EVAL_SHORT (pv);
+ break;
+
+ case T_USHORT:
+ case T_UINT2:
+ EVAL_USHORT(pv) &= 0xff;
+// EVAL_UCHAR (pv) = (uchar)EVAL_USHORT (pv);
+ break;
+ }
+ }
+ }
+ SetNodeType (pv, typ);
+}
+
+
+
+
+/** CvtSizeUp - Convert size of node's type up one step
+ *
+ * CvtSizeUp (pv)
+ *
+ * Entry pv = pointer to value
+ *
+ * Exit value is cast to next larger size
+ *
+ * Returns none
+ *
+ * Converts the size of the node's type up one step:
+ *
+ * (u)char -> (u)short
+ * (u)short -> (u)long
+ * float -> double
+ * double -> ldouble
+ * type * -> type far *
+ */
+
+
+
+// MBH - added the QUAD cases for this routine.
+//
+
+LOCAL void NEAR PASCAL CvtSizeUp (peval_t pv)
+{
+ register CV_typ_t typ;
+
+ if (CV_TYP_IS_NPTR (EVAL_TYP (pv))) {
+
+ // Near ptr -> far ptr.
+ //
+ // If the node is a constant and its offset is zero, we want
+ // to make the segment zero. Otherwise, we DS-extend (which
+ // effectively does nothing since we're already carrying DS
+ // around anyway).
+
+ if (Evaluating &&
+ (EVAL_STATE (pv) == EV_constant) &&
+ (EVAL_PTR_OFF (pv) == 0)) {
+ EVAL_PTR_SEG (pv) = 0;
+ }
+ typ = CV_NEWMODE (EVAL_TYP (pv), CV_TM_FPTR);
+ }
+ else {
+ switch (EVAL_TYP (pv)) {
+ case T_CHAR:
+ case T_RCHAR:
+ typ = T_SHORT;
+ break;
+
+ case T_UCHAR:
+ typ = T_USHORT;
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+ typ = T_LONG;
+ break;
+
+ case T_USHORT:
+ case T_UINT2:
+ typ = T_ULONG;
+ break;
+
+ case T_LONG:
+ case T_INT4:
+ typ = T_QUAD;
+ break;
+
+ case T_ULONG:
+ case T_UINT4:
+ typ = T_UQUAD;
+ break;
+
+ case T_REAL32:
+ typ = T_REAL64;
+ break;
+
+#ifdef TARGET_i386
+ case T_REAL64:
+ typ = T_REAL80;
+ break;
+#endif
+
+ default:
+ DASSERT(FALSE);
+ return;
+ }
+ if (Evaluating) {
+ switch (EVAL_TYP (pv)) {
+ case T_CHAR:
+ case T_RCHAR:
+ EVAL_SHORT (pv) = EVAL_CHAR (pv);
+ break;
+
+ case T_UCHAR:
+ EVAL_USHORT (pv) = EVAL_UCHAR (pv);
+ break;
+
+ case T_SHORT:
+ case T_INT2:
+ EVAL_LONG (pv) = EVAL_SHORT (pv);
+ break;
+
+ case T_USHORT:
+ case T_UINT2:
+ EVAL_ULONG (pv) = EVAL_USHORT (pv);
+ break;
+
+ case T_LONG:
+ case T_INT4:
+ EVAL_QUAD(pv).QuadPart = EVAL_LONG(pv);
+ break;
+
+ case T_ULONG:
+ case T_UINT4:
+
+ //
+ // MBH - bugbug - really want to use Convert routine
+ //
+
+ EVAL_UQUAD (pv).LowPart = EVAL_ULONG (pv);
+ EVAL_UQUAD (pv).HighPart = 0;
+ break;
+
+ case T_REAL32:
+ EVAL_DOUBLE (pv) = EVAL_FLOAT (pv);
+ break;
+
+ case T_REAL64:
+ R10AssignDouble(&EVAL_LDOUBLE (pv), EVAL_DOUBLE (pv));
+ }
+ }
+
+ }
+ SetNodeType (pv, typ);
+}
+
+
+
+
+/** IntegralPromote - Perform an integral promotion
+ *
+ * typPromoted = IntegralPromote (typ)
+ *
+ * Entry typ = type index
+ *
+ * Exit none
+ *
+ * Returns type index of promoted type
+ *
+ * DESCRIPTION
+ * Promotes type as per ANSI spec, section 3.2.1.1:
+ *
+ * "If an int can represent all values of the original type,
+ * the value is converted to an int; otherwise it is converted
+ * to an unsigned int."
+ *
+ * For us this means:
+ *
+ * char -> int
+ * uchar -> int
+ * short -> int
+ * ushort -> uint
+ * int -> int (no conversion)
+ * uint -> uint (no conversion)
+ * long -> long (no conversion)
+ * ulong -> ulong (no conversion)
+ * The other conversions are the same as per ANSI.
+ */
+
+
+LOCAL CV_typ_t NEAR FASTCALL IntegralPromote (CV_typ_t typ)
+{
+ //DASSERT (CV_IS_PRIMITIVE (typ));
+ //DASSERT (CV_TYP_IS_DIRECT (typ));
+
+ if (!CV_TYP_IS_REAL (typ) && ((CV_SUBT (typ) < CV_IN_2BYTE) ||
+ (typ == T_RCHAR))) {
+ // T_CHAR or T_UCHAR
+ return (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? T_LONG : T_SHORT);
+ }
+ else {
+ return (typ);
+ }
+}
+
+
+
+
+/** PerformUAC - Perform 'usual arithmetic conversions'
+ *
+ * typRes = PerformUAC (typ1, typ2)
+ *
+ * Entry typ1 = type index of first node
+ * typ2 = type index of second node
+ *
+ * Exit none
+ *
+ * Returns typRes = type index to which both operands should be
+ * converted
+ *
+ * See ANSI spec, section 3.2.1.5.
+ */
+
+
+CV_typ_t PASCAL PerformUAC (CV_typ_t typ1, CV_typ_t typ2)
+{
+ register CV_typ_t typr;
+
+ // Only permissible types for entry are 'arithmetic' types, i.e.,
+ // chars, integers and floats.
+
+ //DASSERT (!CV_TYP_IS_PTR (typ1));
+ //DASSERT (!CV_TYP_IS_PTR( typ2));
+
+ if ((typ1 == T_REAL80) || (typ2 == T_REAL80)) {
+ // if either operand has type long double, the other
+ // operand is converted to long double."
+
+ typr = T_REAL80;
+ }
+ else if ((typ1 == T_REAL64) || (typ2 == T_REAL64)) {
+ // if either operand has type double, the other
+ // operand is converted to double."
+
+ typr = T_REAL64;
+ }
+ else if ((typ1 == T_REAL32) || (typ2 == T_REAL32)) {
+ // if either operand has type float, the other
+ // operand is converted to float."
+
+ typr = T_REAL32;
+ }
+ else {
+ // the integral promotions are performed on both operands
+
+ typ1 = IntegralPromote (typ1);
+ typ2 = IntegralPromote (typ2);
+ if ((typ1 == T_UINT4) || (typ2 == T_UINT4)) {
+ // If either operand has type unsigned int4, the other
+ // operand is converted to unsigned int4.
+
+ typr = T_UINT4;
+ }
+ else if ((typ1 == T_ULONG) || (typ2 == T_ULONG)) {
+ // If either operand has type unsigned long int, the other
+ // operand is converted to unsigned long int.
+
+ typr = T_ULONG;
+ }
+ else if ((typ1 == T_INT4) || (typ2 == T_INT4)) {
+ // if either operand has type int4, the other
+ // operand is converted to int4."
+
+ typr = T_INT4;
+ }
+ else if ((typ1 == T_LONG) || (typ2 == T_LONG)) {
+ // if either operand has type long int, the other
+ // operand is converted to long as well
+
+ typr = T_LONG;
+ }
+ else if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ /*
+ * Use int as default
+ */
+
+ typr = T_LONG;
+ }
+ else if ((typ1 == T_UINT2) || (typ2 == T_UINT2)) {
+ // "Otherwise, if either operand has type unsigned short, the
+ // other operand is converted to unsigned short."
+
+ typr = T_UINT2;
+ }
+ else if ((typ1 == T_USHORT) || (typ2 == T_USHORT)) {
+ // "Otherwise, if either operand has type unsigned short, the
+ // other operand is converted to unsigned short."
+
+ typr = T_USHORT;
+ }
+ else if ((typ1 == T_INT2) || (typ2 == T_INT2)) {
+ // "Otherwise, if either operand has type short, the
+ // other operand is converted to unsigned short."
+
+ typr = T_INT2;
+ }
+ else {
+ // both operands have type short."
+
+ DASSERT (typ1 == T_SHORT);
+ DASSERT (typ2 == T_SHORT);
+ typr = T_SHORT;
+ }
+ }
+ return (typr);
+}
+
+
+
+/** NormalizeBase - convert based pointer to far pointer
+ *
+ * fSuccess = NormalizeBase (paddr, pv)
+ *
+ * Entry paddr = pointer to address to place result in
+ * pv = pointer to value node for based value
+ *
+ * Exit *paddr = far pointer
+ *
+ * Returns TRUE if far pointer generated
+ * FALSE if error
+ *
+ * This routine is used whenever a based pointer is dereferenced
+ * for load or store.
+ */
+
+
+bool_t PASCAL NormalizeBase (peval_t pv)
+{
+ eval_t vBase;
+ peval_t pvBase;
+ register ushort bptrtyp;
+ register bool_t retval = TRUE;
+
+
+ // check for _based (void) and short circuit with an error code
+
+ switch (bptrtyp = EVAL_PTRTYPE (pv)) {
+ case CV_PTR_BASE_TYPE:
+ // do not normalize based on type
+
+ //pExState->err_num = ERR_NEEDSBIRD;
+ //return (FALSE);
+ return (TRUE);
+
+ case CV_PTR_BASE_SELF:
+ // check for _based((_segment) _self) and build the address now.
+ // There is not a symbol to get information for.
+ //
+ if (Evaluating) {
+ EVAL_PTR_SEG (pv) = EVAL_SYM_SEG (pv);
+ ADDR_IS_LI (EVAL_PTR (pv)) = ADDR_IS_LI (EVAL_SYM (pv));
+ }
+ break;
+
+ case CV_PTR_BASE_SEG:
+ if (Evaluating) {
+ EVAL_PTR_SEG (pv) = PTR_BSEG (pv);
+ ADDR_IS_LI (EVAL_PTR (pv)) = TRUE;
+ }
+ break;
+
+ default:
+ pvBase = &vBase;
+ *pvBase = *pv;
+ CLEAR_EVAL_FLAGS (pvBase);
+ EVAL_STATE (pvBase) = EV_lvalue;
+ SetNodeType (pvBase, PTR_STYPE (pv));
+ EVAL_SYM (pvBase) = PTR_ADDR (pv);
+ switch (PTR_BSYMTYPE (pv)) {
+ case S_BPREL16:
+ case S_BPREL32:
+ EVAL_IS_BPREL (pvBase) = TRUE;
+ break;
+ }
+
+ if (Evaluating && !LoadSymVal (pvBase)) {
+ retval = FALSE;
+ break;
+ }
+
+ switch (bptrtyp) {
+ case CV_PTR_BASE_VAL:
+ // FOO _based (fp)* or FOO _based (segvar)*
+ // The only types of variables which we may base
+ // on are near pointers, far pointers or _segment.
+ //
+ // Result addr =
+ // type == _segment :: VAL (segvar) :> bp
+ // type == far ptr :: SEG (VAL (fp)) :> bp+OFF (VAL (fp))
+ // type == near ptr :: DS :> bp+OFF (VAL (np))
+
+ if (EVAL_TYP (pvBase) != T_SEGMENT) {
+ if (EVAL_PTRTYPE (pvBase) > CV_PTR_FAR) {
+ DASSERT (FALSE);
+ retval = FALSE;
+ break;
+ }
+ }
+ if (Evaluating) {
+ if (EVAL_TYP (pvBase) == T_SEGMENT) {
+ EVAL_PTR_SEG (pv) = EVAL_SHORT (pvBase);
+ }
+ else if (EVAL_PTRTYPE (pvBase) == CV_PTR_NEAR) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS; //M00FLAT32
+ EVAL_PTR_OFF (pv) =
+ (CV_uoff16_t)(EVAL_PTR_OFF (pv) + EVAL_PTR_OFF (pvBase));
+ }
+ else if (EVAL_PTRTYPE (pvBase) == CV_PTR_FAR) {
+ EVAL_PTR_SEG (pv) = EVAL_PTR_SEG (pvBase);
+ EVAL_PTR_OFF (pv) =
+ (CV_uoff16_t)(EVAL_PTR_OFF (pv) + EVAL_PTR_OFF (pvBase));
+ }
+ else {
+ retval = FALSE;
+ }
+ }
+ break;
+
+ case CV_PTR_BASE_SEGVAL:
+ // FOO _based (_segment (fp))//
+
+ DASSERT (EVAL_PTRTYPE (pvBase) <= CV_PTR_FAR);
+ if (EVAL_PTRTYPE (pvBase) > CV_PTR_FAR) {
+ retval = FALSE;
+ }
+ if (Evaluating) {
+ if (EVAL_PTRTYPE (pvBase) == CV_PTR_NEAR) {
+ EVAL_PTR_SEG (pv) = pExState->frame.DS;
+ ADDR_IS_LI (EVAL_PTR (pv)) = FALSE;
+ }
+ else if (EVAL_PTRTYPE (pvBase) == CV_PTR_FAR) {
+ EVAL_PTR_SEG (pv) = EVAL_PTR_SEG (pvBase);
+ ADDR_IS_LI (EVAL_PTR (pv)) = ADDR_IS_LI (EVAL_PTR (pvBase));
+ }
+ }
+ break;
+
+ case CV_PTR_BASE_SEGADDR:
+ // FOO _based (_segment (&fp)) *
+ // result == SEG (ADDR (fp)) :> bp
+
+ if (Evaluating) {
+ if (EVAL_IS_REG (pvBase)) {
+ EVAL_PTR_SEG (pv) = EVAL_USHORT (pvBase);
+ ADDR_IS_LI (EVAL_PTR (pv)) = FALSE;
+ }
+ else {
+ EVAL_PTR_SEG (pv) = EVAL_SYM_SEG (pvBase);
+ ADDR_IS_LI (EVAL_PTR (pv)) = ADDR_IS_LI (EVAL_SYM (pvBase));
+ }
+ }
+ break;
+
+ case CV_PTR_BASE_SEG:
+ case CV_PTR_BASE_SELF:
+ case CV_PTR_BASE_TYPE:
+ case CV_PTR_BASE_ADDR:
+ default:
+ DASSERT (FALSE);
+ retval = FALSE;
+ break;
+
+ }
+ }
+ EVAL_PTRTYPE (pv) = CV_PTR_FAR;
+ return (retval);
+}
+
+
+
+
+/*** DeNormalizePtr - convert far pointer to based pointer
+ *
+ * fSuccess = DeNormalizePtr (pv, pvB)
+ *
+ * Entry pv = pointer to value to denormalize
+ * pvB = pointer to value containing normalize data
+ *
+ * Exit EVAL_PTR (pv) = based pointer
+ *
+ * Returns TRUE if based pointer generated
+ * FALSE if error
+ *
+ * This routine is used whenever a value is stored into a based pointer
+ */
+
+
+bool_t PASCAL DeNormalizePtr (peval_t pv, peval_t pvB)
+{
+ eval_t vBase;
+ peval_t pvBase = &vBase;
+ CV_typ_t typLHS = EVAL_TYP (pvB);
+ bool_t retval = TRUE;
+
+ // If we are assigning in a char or a ushort then copy the
+ // value straight over without change
+
+ if (CV_IS_PRIMITIVE (typLHS) && (CV_SUBT (typLHS) < CV_IN_4BYTE) &&
+ CV_TYP_IS_DIRECT (typLHS) && CV_TYPE (typLHS) < CV_REAL) {
+ if (Evaluating) {
+ EVAL_PTR_OFF (ST) = EVAL_USHORT (ST);
+ }
+ return (TRUE);
+ }
+
+ // Now deal with the complicated items which we can have.
+ // If we get to this point the LHS must be either a near or far
+ // pointer, a long or a floating point. If it is a floating
+ // point then we will really screw it up.
+ //
+ // For all of these cases we will denormalize the expression unless
+ // it is the constant zero -- Which at present we can not detect M00BUG
+
+ switch (EVAL_PTRTYPE (pvB)) {
+ case CV_PTR_BASE_TYPE: // _based (void)
+ case CV_PTR_BASE_SELF: // _based ( (_segment) _self)
+ case CV_PTR_BASE_SEG: // _based (_segment ())
+ case CV_PTR_BASE_SEGVAL: // _based ( (_segment) fp)
+ case CV_PTR_BASE_SEGADDR: // _based ( (_segment) &fp)
+ // All of these cases denormalize by ignoring the
+ // segment and leaving the offset unchanged.
+
+ break;
+
+ case CV_PTR_BASE_VAL: // _based (fp)
+ // This case will denormalize by ignoring the segment and
+ // subtracting the offset of the pointer (unless we start with
+ // the constant zero).
+
+ *pvBase = *pv;
+ CLEAR_EVAL_FLAGS (pvBase);
+ EVAL_STATE (pvBase) = EV_lvalue;
+ SetNodeType (pvBase, PTR_STYPE (pv));
+ EVAL_SYM (pvBase) = PTR_ADDR (pv);
+ DASSERT (EVAL_TYP (pvBase) == T_SEGMENT || (EVAL_PTRTYPE (pv) <= CV_PTR_FAR));
+ if (Evaluating) {
+ if (!LoadSymVal (pvBase)) {
+ return (FALSE);
+ }
+ ResolveAddr( pvBase );
+ EVAL_STATE (pvB) = EV_lvalue;
+ }
+ if (Evaluating && (EVAL_TYP (pvBase) != T_SEGMENT)) {
+ if (!EVAL_IS_CONST (pv) || (EVAL_ULONG (pv) != 0)) {
+ EVAL_PTR_OFF (pv) -= EVAL_PTR_OFF (pvBase);
+ }
+ }
+
+ break;
+
+ case CV_PTR_BASE_ADDR:
+ default:
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/private/windbg/eecan/debutil.c b/private/windbg/eecan/debutil.c
new file mode 100644
index 000000000..9e8b6f977
--- /dev/null
+++ b/private/windbg/eecan/debutil.c
@@ -0,0 +1,2142 @@
+/*** debutil.c - Expression evaluator utility routines
+ *
+ */
+
+
+LOCAL void CheckFcnArgs (neval_t, HTYPE *, CV_call_e);
+ bool_t GrowStack (uint);
+LOCAL void SetDPtr (neval_t, HTYPE *);
+
+char size_special[8] = { 0, 2, 2, 0, 8, 0, 0, 0};
+char size_special2[8] = { 0, 0, 0, 0, 0, 0, 0, 0};
+char size_integral[8] = { 1, 2, 4, 8, 0, 0, 0, 0};
+char size_real[8] = { 4, 8, 10, 16, 3, 0, 0, 0};
+char size_ptr[8] = { 0, 2, 4, 4, 4, 6, 0, 0};
+char size_int[8] = { 1, 2, 2, 2, 4, 4, 8, 8};
+
+
+/** PushStack - push bind data onto stack
+ *
+ * fSuccess = PushStack (pv);
+ *
+ * Entry pv = pointer to evaluation entry
+ *
+ * Exit pv->vflags pushed onto evaluation stack
+ *
+ * Returns TRUE if entry pushed
+ * FALSE if error in push
+ */
+
+bool_t PushStack (peval_t pv)
+{
+ uint len;
+ pelem_t pEL;
+ pelem_t pELP;
+
+ DASSERT ((ST == NULL) || (((char *) ST > (char *) pEStack) &&
+ ((char *)ST < (char *)pEStack + (uint)StackOffset)));
+ DASSERT ((STP == NULL) ||
+ (((char *) STP > (char *) pEStack) && (STP < ST)));
+ len = sizeof (elem_t) +
+ max (EVAL_VALLEN (pv), sizeof (val_t)) - sizeof (val_t);
+
+ if (((uint)StackLen - (uint)StackOffset) < len) {
+ if (!GrowStack (len)) {
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ }
+ if (ST == NULL) {
+ // first element onto stack and set based pointer to previous element
+ // to 0xffff which indicates null
+
+ pEL = (pelem_t)pEStack;
+ pELP = NULL;
+ pEL->pe = UINT_MAX;
+ }
+ else {
+ pEL = (pelem_t)((uchar *)pEStack + (uint)StackOffset);
+ pELP = (pelem_t)((char *)ST - (offsetof (elem_t, se) -
+ offsetof (elem_t, pe)));
+ pEL->pe = belemOfpelem(pELP);
+ }
+ StackOffset = (uint)StackOffset + len;
+ StackMax = max ((uint)StackMax, (uint)StackOffset);
+ if (pELP == NULL) {
+ STP = NULL;
+ }
+ else {
+ STP = (peval_t)&pELP->se;
+ }
+ ST = (peval_t)&pEL->se;
+ *ST = *pv;
+ DASSERT ((ST == NULL) || ((ST > (peval_t) pEStack) &&
+ ((char *)ST < (char *)pEStack + (uint)StackOffset)));
+ DASSERT ((STP == NULL) ||
+ (((char *) STP > (char *)pEStack) && (STP < ST)));
+ return (TRUE);
+}
+
+
+
+
+/** PopStack - pop bind data from stack
+ *
+ * fSuccess = PopStack (void);
+ *
+ * Entry none
+ *
+ * Exit stack popped by one
+ *
+ * Returns TRUE if stack popped
+ * FALSE if error in pop
+ */
+
+
+bool_t PopStack ()
+{
+ pelem_t pEL;
+ uint bELP;
+
+ DASSERT (ST != NULL);
+ DASSERT ((ST == NULL) || ((ST > (peval_t) pEStack) &&
+ ((char *)ST < (char *)pEStack + (uint)StackOffset)));
+ DASSERT ((STP == NULL) ||
+ (((char *) STP > (char *) pEStack) && (STP < ST)));
+ if (ST == NULL) {
+ pExState->err_num = ERR_INTERNAL;
+ return (FALSE);
+ }
+ else {
+ // determine the beginning of the current stack element and
+ // reset the stack offset to the beginning of the top stack element
+
+ if (STP != NULL) {
+ DASSERT (((char *) STP > (char *) pEStack) && (STP < ST));
+ }
+ pEL = (pelem_t)((char *)ST - offsetof (elem_t, se));
+
+ // set the based pointer to the previous stack element
+
+ bELP = (uint)pEL->pe;
+ if (bELP == UINT_MAX) {
+ // we are popping off the only stack element
+
+ StackOffset = 0;
+ STP = NULL;
+ ST = NULL;
+ }
+ else if (bELP == 0) {
+ // we are popping to the last stack element
+
+ StackOffset = (char *)pEL - (char *)pEStack;
+ STP = NULL;
+ ST = (peval_t)&((pelem_t)pEStack)->se;
+ }
+ else {
+ StackOffset = (char *)pEL - (char *)pEStack;
+ ST = STP;
+ pEL = (pelem_t)((char *)ST - offsetof (elem_t, se));
+ bELP = (uint)pEL->pe;
+ STP = (peval_t)&((pelemOfbelem(bELP))->se);
+ }
+ DASSERT ((ST == NULL) || ((ST > (peval_t) pEStack) &&
+ ((char *)ST < (char *)pEStack + (uint)StackOffset)));
+ DASSERT ((STP == NULL) || ((STP > (peval_t) pEStack) && (STP < ST)));
+ return (TRUE);
+ }
+}
+
+
+
+
+/** CkPointStack - checkpoint stack position
+ *
+ * CkPointStack (void);
+ *
+ * Entry none
+ *
+ * Exit stack position saved in StackCkPoint
+ *
+ * Returns nothing
+ */
+
+
+void CkPointStack (void)
+{
+ StackCkPoint = StackOffset;
+}
+
+
+
+
+/** ResetStack - reset stack to checkpoint position
+ *
+ * fSuccess = CkPointStack (void);
+ *
+ * Entry StackCkPoint = checkpointed position
+ *
+ * Exit stack position reset
+ *
+ * Returns TRUE if successfully reset
+ * FALSE if error
+ */
+
+
+bool_t ResetStack (void)
+{
+ while (StackOffset > StackCkPoint) {
+ if (PopStack () == FALSE) {
+ return (FALSE);
+ }
+ }
+ if (StackOffset != StackCkPoint) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+/** GrowStack - grow evaluation stack and reset pointers
+ *
+ * fSuccess = GrowStack (len);
+ *
+ * Entry len = minimum increase size
+ *
+ * Exit stack grown
+ *
+ * Returns TRUE if stack grown
+ * FALSE if error
+ */
+
+
+bool_t GrowStack (uint len)
+{
+ uint bST = UINT_MAX;
+ uint bSTP = UINT_MAX;
+ HDEP hNS; // handle of new evaluation stack
+ pelem_t pNS; // address of new evaluation stack
+ uint size;
+
+ // convert current stack pointers to based form
+
+ if (ST != NULL) {
+ bST = (uchar *)ST - (uchar *)pEStack - offsetof (elem_t, se);
+ }
+ if (STP != NULL) {
+ bSTP = (uchar *)STP - (uchar *)pEStack - offsetof (elem_t, se);
+ }
+
+ // allocate new evaluation stack and copy old to new
+
+ size = max ((uint)StackLen + 5 * sizeof (elem_t), (uint)StackLen + len);
+ if ((hNS = MHMemAllocate (size)) == 0) {
+ // if no memory
+ pExState->err_num = ERR_NOMEMORY;
+ return (FALSE);
+ }
+ else {
+ pNS = MHMemLock (hNS);
+ memcpy (pNS, pEStack, (char *)pelemOfbelem(StackOffset) -
+ (char *)pEStack);
+
+ // if old stack was not the standard fixed buffer, release it
+
+ MHMemUnLock (hEStack);
+ MHMemFree (hEStack);
+ hEStack = hNS;
+ pEStack = pNS;
+ if (bST != UINT_MAX) {
+ ST = (peval_t)&((pelem_t)(((char *)pEStack) + bST))->se;
+ }
+ if (bSTP != UINT_MAX) {
+ STP = (peval_t)&((pelem_t)(((char *)pEStack) + bSTP))->se;
+ }
+ StackLen = size;
+ return (TRUE);
+ }
+}
+
+
+
+
+
+/* RNumLeaf - read numeric leaf
+ *
+ * value = RNumLeaf (
+ * Read numeric leaf and return value and size of leaf
+ */
+
+
+ulong RNumLeaf (void *pleaf, uint *skip)
+{
+ ushort val;
+
+ if ((val = ((plfEasy)pleaf)->leaf) < LF_NUMERIC) {
+ // No leaf can have an index less than LF_NUMERIC (0x8000) so word is value
+ *skip += 2;
+ return (val);
+ }
+
+ switch (val) {
+ case LF_CHAR:
+ *skip += 3;
+ return (((plfChar)pleaf)->val);
+
+ case LF_USHORT:
+ *skip += 4;
+ return (((plfUShort)pleaf)->val);
+
+ case LF_SHORT:
+ *skip += 4;
+ return (((plfShort)pleaf)->val);
+
+ case LF_LONG:
+ case LF_ULONG:
+ *skip += 6;
+ return (((plfULong)pleaf)->val);
+
+ default:
+ DASSERT (FALSE);
+ return (0L);
+ }
+}
+
+
+
+SHFLAG
+fnCmp (
+ LPSSTR lpsstr,
+ LPV lpv,
+ LPSTR stName,
+ SHFLAG fCase
+ )
+/*++
+
+Routine Description:
+
+ Compares the name described by the hInfo packet with a length
+ prefixed name
+
+Arguments:
+
+ lpsstr - sstr packet with match string or pattern (from user)
+ lpv - pointer to acutal symbol record
+ stName - length prefixed string (from symbol record)
+ fCase - case sensitivity flag
+
+Return Value:
+
+ 0 if matched, non-0 if not
+
+--*/
+{
+ psearch_t pName = (psearch_t) lpsstr;
+ SYMPTR pSym = (SYMPTR) lpv;
+
+ DASSERT (pName != NULL);
+
+ if ((stName == NULL) || (stName[0] == 0)) {
+ return (1);
+ }
+
+ if (pName->sstr.searchmask & SSTR_RE) {
+
+ pName->lastsym = pSym->rectyp;
+
+ if (pName->sstr.pRE == NULL) {
+ // return match if no regular expression specified
+ return (0);
+ } else {
+
+ // this is regular expression search
+ char buffer [256];
+ char * lpBuffer = buffer;
+
+ // stName is a length prefixed string. convert to a
+ // null terminated string
+ strncpy ( lpBuffer, stName+1, (unsigned char)stName[0] );
+ lpBuffer [ (unsigned char)stName[0] ] = '\0';
+
+ // do the compare using lpBuffer
+ return SHCompareRE ( lpBuffer, (char *)pName->sstr.pRE, fCase);
+ }
+ }
+
+ // strings do not compare if lengths are different
+
+ if (pName->sstr.cb == (uchar)(*stName++)) {
+ // Lengths are the same
+ if (pSym != NULL) {
+ // save type of last symbol checked
+ pName->lastsym = pSym->rectyp;
+ }
+ if (pName->sstr.searchmask & SSTR_proc) {
+ int cmpflag;
+ CV_typ_t type;
+
+ if (fCase == TRUE) {
+ cmpflag = strncmp ((char *)pName->sstr.lpName, stName, pName->sstr.cb);
+ } else {
+ cmpflag = _strnicmp ((char *)pName->sstr.lpName, stName, pName->sstr.cb);
+ }
+ if (cmpflag != 0) {
+ // we did not have a name match
+ return (cmpflag);
+ }
+
+ // we are checking only procs with the correct type
+ // If this flag is set, then the initializer set the desired
+ // proc index into pName->typeOut
+
+ switch (pSym->rectyp) {
+ case S_LPROC16:
+ case S_GPROC16:
+ type = ((PROCPTR16)pSym)->typind;
+ break;
+
+ case S_LPROC32:
+ case S_GPROC32:
+ type = ((PROCPTR32)pSym)->typind;
+ break;
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ type = ((PROCPTRMIPS)pSym)->typind;
+ break;
+ }
+ if (BindingBP == TRUE) {
+ if (type == pName->typeOut) {
+ // we have an exact match on name and type
+ return (0);
+ }
+ if (pName->FcnBP == 0) {
+ // save alternate type so we can search again
+ pName->FcnBP = type;
+ }
+ } else if (type == pName->typeOut) {
+ // we have an exact match on name and type
+ return (0);
+ }
+ return (1);
+
+ } else if (pName->sstr.searchmask & SSTR_data) {
+ // we are checking only global data with the correct type
+ // If this flag is set, then the initializer set the desired
+ // proc index into pName->typeOut
+
+ switch (pSym->rectyp) {
+
+ case S_GDATA16:
+ if (((DATAPTR16)pSym)->typind != pName->typeOut) {
+ return (1);
+ }
+ break;
+
+ case S_GDATA32:
+ if (((DATAPTR32)pSym)->typind != pName->typeOut) {
+ return (1);
+ }
+ break;
+ }
+ }
+ if (fCase == TRUE) {
+ return (strncmp ((char *)pName->sstr.lpName, stName, pName->sstr.cb));
+ } else {
+ return (_strnicmp ((char *)pName->sstr.lpName, stName, pName->sstr.cb));
+ }
+ }
+
+#ifdef TARGET_i386
+ //
+ // Due to the strange naming conventions and strange assumptions about
+ // the lack of intellegence on the part of some people. It has been
+ // deemed desirable that we do special matching for standard call
+ // functions. Specifically that we ignore the @## on the end of the
+ // public label when doing compares. Potentially stupid but maybe
+ // necessary
+ //
+ // DEFINITLY NECESSARY!
+ //
+
+ //
+ // To do this the following conditions must be met:
+ //
+ // 1. Must be checking againist either a 16-bit public or a
+ // 32-bit public.
+ //
+ // 2. Must be no '@' character in the users string
+ //
+ // 3. Must be an '@' character in the symbol handlers string
+ //
+ // -------------------------------------------------------------
+ // Wesley Witt (wesw) 2-June-1994
+ // -------------------------------------------------------------
+ //
+ // The rules also accomodate fastcall names. A fastcall name
+ // has an @ as the first character. If the user's string has
+ // an @ as the first character and the symbol handler's string
+ // has an @ as the first character then the pointers are
+ // advanced and the above rule set applies as it has.
+ //
+ if (pSym != NULL &&
+ ((pSym->rectyp == S_PUB16) || (pSym->rectyp == S_PUB32))) {
+ int idx = 0;
+ char *pch;
+ if (stName[0] == '@' && pName->sstr.lpName[0] == '@') {
+ idx = 1;
+ }
+ pch = strchr(&stName[idx], '@');
+ if ((pch != NULL) && (strchr(&pName->sstr.lpName[idx], '@') == NULL)) {
+ if ((pch-stName-idx) == pName->sstr.cb-idx) {
+ if (fCase == TRUE) {
+ return strncmp(&pName->sstr.lpName[idx], &stName[idx], pch-stName-idx);
+ } else {
+ return _strnicmp(&pName->sstr.lpName[idx], &stName[idx], pch-stName-idx);
+ }
+ }
+ }
+ }
+
+#endif /* TARGET_i386 */
+ return (1);
+} /* fnCmp() */
+
+
+
+
+/** tdCmp - typedef compare routine.
+ *
+ * Compares the type described by the hInfo packet with a typedef symbol
+ *
+ * fFlag = tdCmp (psearch_t pName, SYMPTR pSym, char *stName, int fCase);
+ *
+ * Entry pName = pointer to psearch_t packet describing name
+ * pSym = pointer to symbol structure (NULL if internal call)
+ * stName = pointer to a length preceeded name
+ * fCase = ignored
+ *
+ * Exit none
+ *
+ * Returns 0 if typedef symbol of proper type found
+ */
+
+
+SHFLAG
+tdCmp (
+ LPSSTR lpsstr,
+ LPV lpv,
+ char *stName,
+ SHFLAG fCase
+ )
+{
+ psearch_t pName = (psearch_t) lpsstr;
+ SYMPTR pSym = (SYMPTR) lpv;
+
+ Unreferenced( stName );
+ Unreferenced( fCase );
+
+ DASSERT (pName != NULL);
+ DASSERT (pSym != NULL);
+
+ // strings do not compare if lengths are different
+
+ if ((pSym->rectyp == S_UDT) && (((UDTPTR)pSym)->typind == pName->typeIn)) {
+ pName->lastsym = pSym->rectyp;
+ return (0);
+ }
+ return (1);
+}
+
+
+
+
+/** csCmp - compile symbol compare routine.
+ *
+ * Compares the type described by the hInfo packet with a compile symbol
+ *
+ * fFlag = csCmp (psearch_t pName, SYMPTR pSym, char *stName, int fCase);
+ *
+ * Entry pName = pointer to psearch_t packet describing name
+ * pSym = pointer to symbol structure (NULL if internal call)
+ * stName = pointer to a length preceeded name
+ * fCase = ignored
+ *
+ * Exit none
+ *
+ * Returns 0 if compile symbol found
+ */
+
+
+SHFLAG
+csCmp (
+ LPSSTR lpsstr,
+ LPV lpv,
+ char *stName,
+ SHFLAG fCase
+ )
+{
+ psearch_t pName = (psearch_t) lpsstr;
+ SYMPTR pSym = (SYMPTR) lpv;
+
+ Unreferenced( stName );
+ Unreferenced( fCase );
+
+ DASSERT (pName != NULL);
+ DASSERT (pSym != NULL);
+
+ // strings do not compare if lengths are different
+
+ if (pSym->rectyp == S_COMPILE) {
+ pName->lastsym = pSym->rectyp;
+ return (0);
+ }
+ return (1);
+}
+
+
+
+
+
+/*** InsertNode - Insert node in parse tree
+ *
+ * error = InsertNode (ptok)
+ *
+ * Entry pExState = address of expression state structure
+ * pExState->hSTree locked
+ *
+ * Exit pExState->hSTree locked
+ * pTree = address of locked syntax tree
+ *
+ * Returns TRUE if successful
+ * FALSE if unsuccessful
+ *
+ */
+
+
+bool_t InsertNode ()
+{
+ return (FALSE);
+}
+
+
+
+
+
+/** RemoveIndir - Remove a level of indirection from a node
+ *
+ * RemoveIndir (pv)
+ *
+ * Entry pv = pointer to value
+ *
+ * Exit
+ *
+ * Returns none
+ *
+ * DESCRIPTION
+ * Strips a level of indirection from a node's type; thus (char **)
+ * becomes (char *), and (char *) becomes (char).
+ */
+
+
+void RemoveIndir (peval_t pv)
+{
+ CV_typ_t typ;
+
+ // Initialization, error checking. Find the base type of the
+ // pointer type.
+
+ DASSERT (EVAL_IS_PTR (pv));
+
+ // Since we are removing a level of indirection on the pointer, the
+ // value can no longer be in a register so we clear the flag indicating
+ // the value is in a register
+
+ EVAL_IS_REG (pv) = FALSE;
+
+ // Set the type of the node to the underlying type
+
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
+ switch (EVAL_TYP (pv)) {
+ case T_NCVPTR:
+ typ = PTR_UTYPE (pv);
+ break;
+
+ case T_FCVPTR:
+ case T_HCVPTR:
+ EVAL_SYM_SEG (pv) = EVAL_PTR_SEG (pv);
+ typ = PTR_UTYPE (pv);
+ break;
+
+ default:
+ typ = CV_NEWMODE (EVAL_TYP (pv), CV_TM_DIRECT);
+ break;
+ }
+ }
+ else if (EVAL_IS_ARRAY (pv)) {
+ typ = PTR_UTYPE (pv);
+ }
+ else if (EVAL_IS_PTR (pv)) {
+ typ = PTR_UTYPE (pv);
+ if (EVAL_PTRTYPE (pv) != CV_PTR_NEAR) {
+ EVAL_SYM_SEG (pv) = EVAL_PTR_SEG (pv);
+ }
+ }
+ else {
+ DASSERT (FALSE);
+ return;
+ }
+ SetNodeType (pv, typ);
+}
+
+
+__inline HTYPE
+GetHTypeFromTindex (
+ neval_t nv,
+ CV_typ_t type
+ )
+{
+ N_EVAL_TYPDEF (nv) = THGetTypeFromIndex (N_EVAL_MOD (nv), type);
+// DASSERT (N_EVAL_TYPDEF (nv) != 0);
+ return (N_EVAL_TYPDEF (nv));
+}
+
+
+
+/*** SetNodeType - set node flags for a type index
+ *
+ * fSuccess = SetNodeType (pv, type)
+ *
+ * Entry pv = pointer to value
+ * type = type index
+ *
+ * Exit EVAL_TYPDEF (pv) = handle to typedef record if not primitive
+ * pv->flags set for type
+ * pv->data set for type
+ *
+ * Returns TRUE if type flags set
+ * FALSE if not (invalid type)
+ */
+
+eval_t evalN;
+neval_t nv = &evalN;
+
+bool_t SetNodeType (peval_t pv, CV_typ_t type)
+{
+ plfEasy pType;
+ uint skip;
+ bool_t retflag = TRUE;
+ HTYPE hType;
+ CV_typ_t oldType;
+ CV_call_e call;
+ CV_modifier_t cvol;
+ CV_ptrmode_e mode;
+ SYMPTR pSym;
+ static uchar cvptr[5] = {CV_PTR_NEAR, CV_PTR_FAR, CV_PTR_HUGE, CV_PTR_NEAR32, CV_PTR_FAR32};
+ search_t Name;
+ psearch_t pName = &Name;
+ eval_t eval, savedeval;
+ peval_t lpv = &eval;
+ peval_t lpsaved = &savedeval;
+ ushort iregSav;
+ bool_t hibyteSav;
+
+ // save static data on stack because of possible
+ // recursion while calling SearchSym
+
+ *lpsaved = *nv;
+
+ // copy the node to near memory to save code space
+
+ *nv = *pv;
+ N_CLEAR_EVAL_FLAGS (nv);
+ if (EVAL_IS_REG (pv)) {
+ // an enregistered primitive
+ N_EVAL_IS_REG (nv) = TRUE;
+ // save register information before clearing data
+ iregSav = EVAL_REG(pv);
+ hibyteSav = EVAL_IS_HIBYTE (pv);
+ }
+ else if (EVAL_IS_BPREL (pv)) {
+ N_EVAL_IS_BPREL (nv) = TRUE;
+ }
+ else if (EVAL_IS_LABEL (pv)) { // CUDA #4067: must preserve islabel bit
+ N_EVAL_IS_LABEL (nv) = TRUE;
+ }
+ else if (EVAL_IS_REGREL (pv)) {
+ N_EVAL_IS_REGREL (nv) = TRUE;
+ }
+ else if (EVAL_IS_TLSREL( pv )) {
+ N_EVAL_IS_TLSREL (nv) = TRUE;
+ }
+
+modifier:
+
+ oldType = N_EVAL_TYP (nv);
+ N_EVAL_TYP (nv) = type;
+ if (!CV_IS_PRIMITIVE (type)) {
+ DASSERT (N_EVAL_MOD (nv) != 0);
+ if ((hType = GetHTypeFromTindex (nv, type)) == 0) {
+ return FALSE;
+ }
+ }
+
+ // from this point, it is assumed that a value of FALSE is zero and
+ // the memset of the node set all bit values to FALSE
+
+ if (CV_IS_INTERNAL_PTR (type)) {
+ // we are creating a special pointer to class type
+
+ if (oldType == T_NOTYPE) {
+ DASSERT (FALSE);
+ return (FALSE);
+ }
+ N_EVAL_IS_ADDR (nv) = TRUE;
+ N_EVAL_IS_PTR (nv) = TRUE;
+ N_EVAL_IS_DPTR (nv) = TRUE;
+ // N_EVAL_IS_CONST (nv) = FALSE;
+ // N_EVAL_IS_VOLATILE (nv) = FALSE;
+ // N_EVAL_IS_REF (nv) = FALSE;
+ N_PTR_UTYPE (nv) = oldType;
+
+ // The following code assumes that the ordering of the
+ // pointer modes is the same as the ordering of the CV created
+ // pointer types
+
+ N_EVAL_PTRTYPE (nv) = cvptr[CV_MODE (type) - CV_TM_NPTR];
+ }
+ else if (CV_IS_PRIMITIVE (type)) {
+
+ // If the type is primitive then it must reference data
+
+ N_EVAL_IS_DATA (nv) = TRUE;
+ N_EVAL_IS_DPTR (nv) = TRUE;
+
+ if (CV_TYP_IS_PTR (type)) {
+
+ // can't cast from 32 bit ptr to a 16 or vice versa
+
+ if ( EVAL_IS_PTR (pv) ) {
+ if (EVAL_PTRTYPE(pv) == CV_PTR_NEAR32 ||
+ EVAL_PTRTYPE(pv) == CV_PTR_FAR32) {
+ if (CV_MODE (type) < CV_TM_NPTR32) {
+ return (FALSE);
+ }
+ }
+ else {
+ if (CV_MODE (type) >= CV_TM_NPTR32) {
+ return (FALSE);
+ }
+ }
+ }
+ else if (EVAL_IS_REG (nv) ) {
+
+ // At this point, the data union believes that this is a REG
+ // This code converts it to be a pointer
+
+ eval_t nvCopy;
+ nvCopy = *nv;
+
+ //
+ // Clear out the register fields
+ //
+ N_EVAL_REG (nv) = 0;
+
+ //
+ // Set up the pointer fields
+ //
+
+ N_PTR_REG_IREG (nv) = N_EVAL_REG (&nvCopy);
+ N_PTR_REG_HIBYTE (nv) = EVAL_IS_HIBYTE (&nvCopy);
+ }
+ N_EVAL_IS_PTR (nv) = TRUE;
+ N_EVAL_IS_ADDR (nv) = TRUE;
+
+ // The following code assumes that the ordering of the
+ // pointer modes is the same as the ordering of the CV created
+ // pointer types
+
+ N_EVAL_PTRTYPE (nv) = cvptr[CV_MODE (type) - CV_TM_NPTR];
+ N_PTR_UTYPE (nv) = CV_NEWMODE(type, CV_TM_DIRECT);
+ }
+ }
+ else {
+ memset (&nv->data, 0, sizeof (nv->data));
+ pType = (plfEasy)(&((TYPPTR)(MHOmfLock (hType)))->leaf);
+ switch (pType->leaf) {
+ case LF_NULL:
+ break;
+
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ if (((plfClass)pType)->property.fwdref) {
+ skip = offsetof (lfClass, data);
+ RNumLeaf (((char *)(&pType->leaf)) + skip, &skip);
+ // forward ref - look for the definition of the UDT
+ if ((type = GetUdtDefnTindex (type, nv, ((char *)&(pType->leaf)) + skip)) == T_NOTYPE) {
+ retflag = FALSE;
+ break;
+ }
+ MHOmfUnLock (hType);
+ if ((hType = GetHTypeFromTindex (nv, type)) == 0) {
+ retflag = FALSE;
+ break;
+ }
+ pType = (plfEasy)(&((TYPPTR)(MHOmfLock (hType)))->leaf);
+ N_EVAL_TYP (nv) = type;
+ }
+ if (((plfClass)pType)->property.fwdref) {
+ retflag = FALSE;
+ break;
+ }
+ N_EVAL_IS_DATA (nv) = TRUE;
+ N_EVAL_IS_CLASS (nv) = TRUE;
+ N_CLASS_COUNT (nv) = ((plfClass)pType)->count;
+ N_CLASS_FIELD (nv) = ((plfClass)pType)->field;
+ N_CLASS_DERIVE (nv) = ((plfClass)pType)->derived;
+ N_CLASS_VTSHAPE (nv) = ((plfClass)pType)->vshape;
+ N_CLASS_PROP (nv) = ((plfClass)pType)->property;
+ skip = offsetof (lfClass, data[0]);
+ N_CLASS_LEN (nv) = (ushort)RNumLeaf (((char *)(&pType->leaf)) + skip, &skip);
+ break;
+
+ case LF_UNION:
+ if (((plfUnion)pType)->property.fwdref) {
+ skip = offsetof (lfUnion, data);
+ RNumLeaf (((char *)(&pType->leaf)) + skip, &skip);
+ // forward ref - look for the definition of the UDT
+ if ((type = GetUdtDefnTindex (type, nv, ((char *)&(pType->leaf)) + skip)) == T_NOTYPE) {
+ retflag = FALSE;
+ break;
+ }
+ MHOmfUnLock (hType);
+ if ((hType = GetHTypeFromTindex (nv, type)) == 0) {
+ retflag = FALSE;
+ break;
+ }
+ pType = (plfEasy)(&((TYPPTR)(MHOmfLock (hType)))->leaf);
+ N_EVAL_TYP (nv) = type;
+ }
+ if (((plfUnion)pType)->property.fwdref) {
+ retflag = FALSE;
+ break;
+ }
+ N_EVAL_IS_DATA (nv) = TRUE;
+ N_EVAL_IS_CLASS (nv) = TRUE;
+ N_CLASS_COUNT (nv) = ((plfUnion)pType)->count;
+ N_CLASS_FIELD (nv) = ((plfUnion)pType)->field;
+ N_CLASS_PROP (nv) = ((plfClass)pType)->property;
+ skip = offsetof (lfUnion, data[0]);
+ N_CLASS_LEN (nv) = (ushort)RNumLeaf (((char *)(&pType->leaf)) + skip, &skip);
+ break;
+
+ case LF_ENUM:
+ if (((plfEnum)pType)->property.fwdref) {
+ // forward ref - look for the definition of the UDT
+ if ((type = GetUdtDefnTindex (type, nv, (char *)&(((plfEnum)pType)->Name[0]))) == T_NOTYPE) {
+ retflag = FALSE;
+ break;
+ }
+ MHOmfUnLock (hType);
+ if ((hType = GetHTypeFromTindex (nv, type)) == 0) {
+ retflag = FALSE;
+ break;
+ }
+ pType = (plfEasy)(&((TYPPTR)(MHOmfLock (hType)))->leaf);
+ N_EVAL_TYP (nv) = type;
+ }
+ if (((plfEnum)pType)->property.fwdref) {
+ retflag = FALSE;
+ break;
+ }
+ N_EVAL_IS_ENUM (nv) = TRUE;
+ N_ENUM_COUNT (nv) = ((plfEnum)pType)->count;
+ N_ENUM_FIELD (nv) = ((plfEnum)pType)->field;
+ N_ENUM_UTYPE (nv) = ((plfEnum)pType)->utype;
+ N_ENUM_PROP (nv) = ((plfClass)pType)->property;
+ break;
+
+
+ case LF_BITFIELD:
+ N_EVAL_IS_DATA (nv) = TRUE;
+ N_EVAL_IS_BITF (nv) = TRUE;
+ skip = 1;
+
+ // read number of bits in field
+
+ N_BITF_LEN (nv) = ((plfBitfield)pType)->length;
+ N_BITF_POS (nv) = ((plfBitfield)pType)->position;
+ N_BITF_UTYPE (nv) = ((plfBitfield)pType)->type;
+ skip = sizeof (lfBitfield);
+ break;
+
+
+ case LF_POINTER:
+ if (EVAL_IS_REG (pv)) {
+ // an en-registered pointer
+ N_PTR_REG_IREG (nv) = EVAL_REG (pv);
+ N_PTR_REG_HIBYTE (nv) = EVAL_IS_HIBYTE (pv);
+ }
+ N_EVAL_IS_ADDR (nv) = TRUE;
+ N_EVAL_IS_PTR (nv) = TRUE;
+ N_EVAL_IS_CONST (nv) = ((plfPointer)pType)->attr.isconst;
+ N_EVAL_IS_VOLATILE (nv) = ((plfPointer)pType)->attr.isvolatile;
+ mode = ((plfPointer)pType)->attr.ptrmode;
+ N_PTR_UTYPE (nv) = ((plfPointer)&(pType->leaf))->utype;
+ if (!CV_IS_PRIMITIVE (N_PTR_UTYPE (nv))) {
+ // Avoid leaving unresolved forward references in the
+ // evaluation node, in order to work around context-related
+ // problems. Resolving a fwd ref requires a symbol search
+ // and the appropriate context may be unavailable at a later
+ // time.
+ CV_typ_t newindex;
+ if (getDefnFromDecl(N_PTR_UTYPE (nv), nv, &newindex)) {
+ N_PTR_UTYPE (nv) = newindex;
+ }
+ }
+ switch (N_EVAL_PTRTYPE (nv) = ((plfPointer)pType)->attr.ptrmode) {
+ case CV_PTR_MODE_PTR:
+ break;
+
+ case CV_PTR_MODE_REF:
+ N_EVAL_IS_REF (nv) = TRUE;
+ break;
+
+ case CV_PTR_MODE_PMEM:
+ N_EVAL_IS_PMEMBER (nv) = TRUE;
+ N_PTR_PMCLASS (nv) = ((plfPointer)pType)->pbase.pm.pmclass;
+ N_PTR_PMENUM (nv) = ((plfPointer)pType)->pbase.pm.pmenum;
+ break;
+
+ case CV_PTR_MODE_PMFUNC:
+ N_EVAL_IS_PMETHOD (nv) = TRUE;
+ N_PTR_PMCLASS (nv) = ((plfPointer)pType)->pbase.pm.pmclass;
+ N_PTR_PMENUM (nv) = ((plfPointer)pType)->pbase.pm.pmenum;
+ break;
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ retflag = FALSE;
+ break;
+ }
+ switch (N_EVAL_PTRTYPE (nv) = ((plfPointer)pType)->attr.ptrtype) {
+ case CV_PTR_NEAR32:
+ case CV_PTR_FAR32:
+ // can't cast from 32 bit ptr to a 16 or vice versa
+ if (EVAL_IS_PTR (pv) &&
+ (EVAL_PTRTYPE(pv) != CV_PTR_NEAR32) &&
+ (EVAL_PTRTYPE(pv) != CV_PTR_FAR32)
+ ) {
+ retflag = FALSE;
+ }
+ break;
+
+ default:
+ if (EVAL_IS_PTR (pv) &&
+ ((EVAL_PTRTYPE(pv) == CV_PTR_NEAR32) ||
+ (EVAL_PTRTYPE(pv) == CV_PTR_FAR32))
+ ) {
+ retflag = FALSE;
+ break;
+ }
+
+ switch (N_EVAL_PTRTYPE (nv)) {
+ case CV_PTR_BASE_SEG:
+ // based on a segment. Use the segment value from the leaf
+ N_PTR_BSEG (nv) = ((plfPointer)pType)->pbase.bseg;
+ break;
+
+ case CV_PTR_BASE_VAL:
+ case CV_PTR_BASE_SEGVAL:
+ case CV_PTR_BASE_ADDR:
+ case CV_PTR_BASE_SEGADDR:
+ // We need to do an extra symbol search to find
+ // the symbol on which the pointer is based.
+ // The copy of the symbol record in the type
+ // section is not good. We need to do the
+ // extra search even if the base is bp-relative
+ // The compiler no longer sets the correct offset
+ // in copy of the symbol record found in the type
+ // section.
+
+ memset (pName, 0, sizeof (*pName));
+
+ // initialize search_t struct
+ // M00KLUDGE: We use the context stored
+ // in the TM during the bind phase. This
+ // does not work properly If the actual
+ // base is shadowed by a local variable
+
+ pName->pfnCmp = (PFNCMP) FNCMP;
+ pName->pv = (peval_t) nv;
+ pName->scope = SCP_lexical | SCP_module | SCP_global;
+ pName->clsmask = 0;
+ pName->CXTT = *pCxt;
+ pName->bn = 0;
+ pName->bnOp = 0;
+ pName->state = SYM_init;
+
+ pSym = (SYMPTR)(&((plfPointer)pType)->pbase.Sym);
+ N_PTR_BSYMTYPE (nv) = pSym->rectyp;
+ emiAddr (N_PTR_ADDR (nv)) = pCxt->addr.emi;
+
+ if (SearchBasePtrBase(pName) != HR_found) {
+ pExState->err_num = ERR_NOTEVALUATABLE;
+ return FALSE;
+ }
+
+ case CV_PTR_BASE_TYPE:
+ N_PTR_BTYPE (nv) = ((plfPointer)pType)->pbase.btype.index;
+ break;
+
+ default:
+ break;
+ }
+ }
+ SetDPtr (nv, &hType);
+ break;
+
+ case LF_ARRAY:
+ // The CodeView information doesn't tell us whether arrays
+ // are near or far, so we always make them far.
+
+ if (EVAL_IS_REG (pv)) {
+ // an en-registered pointer
+ N_PTR_REG_IREG (nv) = EVAL_REG (pv);
+ N_PTR_REG_HIBYTE (nv) = EVAL_IS_HIBYTE (pv);
+ }
+ N_EVAL_IS_DATA (nv) = TRUE;
+ N_EVAL_IS_ADDR (nv) = TRUE;
+ N_EVAL_IS_PTR (nv) = TRUE;
+ N_EVAL_IS_ARRAY (nv) = TRUE;
+ N_EVAL_PTRTYPE (nv) = ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt)) ? CV_PTR_NEAR32 : CV_PTR_FAR;
+ N_PTR_UTYPE (nv) = ((plfArray)pType)->elemtype;
+ if (!CV_IS_PRIMITIVE (N_PTR_UTYPE (nv))) {
+ // Avoid leaving unresolved forward references in the
+ // evaluation node, in order to work around context-related
+ // problems. Resolving a fwd ref requires a symbol search
+ // and the appropriate context may be unavailable at a later
+ // time.
+ CV_typ_t newindex;
+ if (getDefnFromDecl(N_PTR_UTYPE (nv), nv, &newindex)) {
+ N_PTR_UTYPE (nv) = newindex;
+ }
+ }
+ skip = offsetof (lfArray, data[0]);
+ N_PTR_ARRAYLEN (nv) = RNumLeaf (((char *)(&pType->leaf)) + skip, &skip);
+ break;
+
+ case LF_PROCEDURE:
+ N_EVAL_IS_ADDR (nv) = TRUE;
+ N_EVAL_IS_FCN (nv) = TRUE;
+ N_FCN_RETURN (nv) = ((plfProc)pType)->rvtype;
+ if (N_FCN_RETURN (nv) == 0) {
+ N_FCN_RETURN (nv) = T_VOID;
+ }
+ call = ((plfProc)pType)->calltype;
+ N_FCN_PCOUNT (nv) = ((plfProc)pType)->parmcount;
+ N_FCN_PINDEX (nv) = ((plfProc)pType)->arglist;
+ skip = sizeof (lfProc);
+ CheckFcnArgs (nv, &hType, call);
+ break;
+
+ case LF_MFUNCTION:
+ N_EVAL_IS_ADDR (nv) = TRUE;
+ N_EVAL_IS_FCN (nv) = TRUE;
+ N_EVAL_IS_METHOD (nv) = TRUE;
+ N_FCN_CLASS (nv) = ((plfMFunc)pType)->classtype;
+ N_FCN_THIS (nv) = ((plfMFunc)pType)->thistype;
+ N_FCN_RETURN (nv) = ((plfMFunc)pType)->rvtype;
+ if (N_FCN_RETURN (nv) == 0) {
+ N_FCN_RETURN (nv) = T_VOID;
+ }
+ call = ((plfMFunc)pType)->calltype;
+ N_FCN_PCOUNT (nv) = ((plfMFunc)pType)->parmcount;
+ N_FCN_PINDEX (nv) = ((plfMFunc)pType)->arglist;
+ N_FCN_THISADJUST (nv) = ((plfMFunc)pType)->thisadjust;
+ skip = sizeof (lfMFunc);
+ CheckFcnArgs (nv, &hType, call);
+ break;
+
+ case LF_MODIFIER:
+ cvol = ((plfModifier)pType)->attr;
+ type = ((plfModifier)pType)->type;
+ MHOmfUnLock (hType);
+ hType = 0;
+ if (cvol.MOD_const == TRUE) {
+ N_EVAL_IS_CONST (nv) = TRUE;
+ }
+ else if (cvol.MOD_volatile == TRUE){
+ N_EVAL_IS_VOLATILE (nv) = TRUE;
+ }
+ goto modifier;
+
+ case LF_VTSHAPE:
+ N_EVAL_IS_VTSHAPE (nv) = TRUE;
+ N_VTSHAPE_COUNT (nv) = ((plfVTShape)pType)->count;
+ break;
+
+ case LF_LABEL:
+ N_EVAL_IS_LABEL (nv) = TRUE;
+ break;
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ retflag = FALSE;
+ break;
+ }
+ if (hType != 0) {
+ MHOmfUnLock (hType);
+ }
+ }
+
+ if (EVAL_IS_REG (nv) && EVAL_IS_PTR (nv)) {
+ // an enregistered pointer
+ // restore register information
+ N_PTR_REG_IREG (nv) = iregSav;
+ N_PTR_REG_HIBYTE (nv) = hibyteSav;
+ }
+
+ *pv = *nv;
+ *nv = *lpsaved;
+ return (retflag);
+}
+
+
+
+
+/** CheckFcnArgs - check for function arguments
+ *
+ * CheckVarArgs (nv, phType, call, pcParam);
+ *
+ * Entry nv = near pointer to value node
+ * phType = pointer to type handle
+ * call = calling convention
+ * pcParam = pointer to paramater count
+ *
+ * Exit N_FCN_VARARGS (nv) = TRUE if varargs
+ *
+ * Returns none
+ */
+
+
+LOCAL void
+CheckFcnArgs (
+ neval_t nv,
+ HTYPE *phType,
+ CV_call_e call
+ )
+{
+ plfArgList pType;
+ ushort skip = 0;
+
+ switch(call) {
+
+ case CV_CALL_NEAR_C:
+
+ //near C call - caller pops stack
+ N_FCN_CALL (nv) = FCN_C;
+ // N_FCN_FARCALL (nv) = FALSE;
+ N_FCN_CALLERPOP (nv) = TRUE;
+ break;
+
+ case CV_CALL_FAR_C:
+ // far C call - caller pops stack
+ N_FCN_CALL (nv) = FCN_C;
+ N_FCN_FARCALL (nv) = TRUE;
+ N_FCN_CALLERPOP (nv) = TRUE;
+ break;
+
+ case CV_CALL_NEAR_PASCAL:
+ // near pascal call - callee pops stack
+ N_FCN_CALL (nv) = FCN_PASCAL;
+ // N_FCN_FARCALL (nv) = FALSE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ case CV_CALL_FAR_PASCAL:
+ // far pascal call - callee pops stack
+ N_FCN_CALL (nv) = FCN_PASCAL;
+ N_FCN_FARCALL (nv) = TRUE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ case CV_CALL_NEAR_FAST:
+ // near fast call - callee pops stack
+ N_FCN_CALL (nv) = FCN_FAST;
+ // N_FCN_FARCALL (nv) = FALSE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ case CV_CALL_FAR_FAST:
+ // far fast call - callee pops stack
+ N_FCN_CALL (nv) = FCN_FAST;
+ N_FCN_FARCALL (nv) = TRUE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ case CV_CALL_NEAR_STD:
+ // near standard call - callee pops stack
+ N_FCN_CALL (nv) = FCN_STD;
+ // N_FCN_FARCALL (nv) = FALSE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ case CV_CALL_FAR_STD:
+ // far fast call - callee pops stack
+ N_FCN_CALL (nv) = FCN_STD;
+ N_FCN_FARCALL (nv) = TRUE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ case CV_CALL_PPCCALL:
+ N_FCN_CALL (nv) = FCN_PPC;
+ break;
+
+ case CV_CALL_MIPSCALL:
+ N_FCN_CALL (nv) = FCN_MIPS;
+ break;
+
+ case CV_CALL_ALPHACALL:
+ N_FCN_CALL (nv) = FCN_ALPHA;
+ break;
+
+ case CV_CALL_THISCALL:
+ N_FCN_CALL (nv) = FCN_THIS;
+ break;
+
+ case CV_CALL_GENERIC:
+#ifdef ALPHA
+//
+// MBH -bugbug
+// This is here because CV_CALL_ALPHACALL has changed values in
+// cvinfo.h, but no in the front end yet.
+//
+ CheckFcnArgs (nv, phType, CV_CALL_ALPHACALL);
+ return;
+#endif
+ //
+ // otherwise, deliberately fall through
+ //
+
+ default:
+ // unknown function
+ DASSERT (FALSE);
+ N_FCN_CALL (nv) = 0;
+ // N_FCN_FARCALL (nv) = FALSE;
+ // N_FCN_CALLERPOP (nv) = FALSE;
+ break;
+
+ }
+
+ //M00KLUDGE - this check is to avoid a cvpack problem to be fixed
+ if (N_FCN_PINDEX (nv) == 0) {
+ return;
+ }
+
+ if ((N_FCN_CALL (nv) != FCN_C) &&
+ (N_FCN_CALL (nv) != FCN_PPC) &&
+ (N_FCN_CALL (nv) != FCN_MIPS) &&
+ (N_FCN_CALL (nv) != FCN_ALPHA) &&
+ (FCN_PINDEX (nv) == T_VOID)) {
+ return;
+ }
+
+ MHOmfUnLock (*phType);
+ *phType = THGetTypeFromIndex (EVAL_MOD (nv), N_FCN_PINDEX (nv));
+ DASSERT (*phType != 0);
+ if (*phType == 0) {
+ return;
+ }
+ pType = (plfArgList)(&((TYPPTR)(MHOmfLock (*phType)))->leaf);
+
+ if (FCN_PCOUNT (nv) == 0) {
+ // there are no arguments. We need to check for old C
+ // style varargs and voidarg function calls. These are
+ // indicated by an argument count of zero and an
+ // argument type list which is a LF_EASY list.
+
+ if ((pType->count == 0) || (pType->arg[0] == T_NOTYPE)) {
+ // This is either void or no args. We cannot
+ // tell the difference so we set the varargs flag
+ N_FCN_VARARGS (nv) = TRUE;
+ }
+ }
+ else {
+ // There are formal parameters. Skip down the list to the last
+ // parameter and check for varargs
+
+ if (pType->arg[pType->count - 1] == T_NOTYPE) {
+ // the last argument has a type of zero which is the specification
+ // of varargs. Set the type to 0 to indicate vararg
+ N_FCN_VARARGS (nv) = TRUE;
+ }
+ else if (pType->arg[pType->count - 1] == LF_DEFARG) {
+ N_FCN_DEFARGS (nv) = TRUE;
+ }
+ }
+}
+
+
+
+
+/** SetDPtr - set data pointer flag
+ *
+ * SetDPtr (nv, phType)
+ *
+ * Entry nv = near pointer to value node
+ * phType = pointer to type handle
+ *
+ * Exit EVAL_IS_DPTR (nv) = TRUE if pointer to data
+ *
+ * Returns none
+ */
+
+
+LOCAL void SetDPtr (neval_t nv, HTYPE *phType)
+{
+ if (!CV_IS_PRIMITIVE (N_PTR_UTYPE (nv))) {
+ MHOmfUnLock (*phType);
+ *phType = THGetTypeFromIndex (EVAL_MOD (nv), N_PTR_UTYPE (nv));
+ DASSERT(*phType != (HTYPE) NULL);
+ if (((plfEasy)(&((TYPPTR)(MHOmfLock (*phType)))->leaf))->leaf != LF_PROCEDURE) {
+ N_EVAL_IS_DPTR (nv) = TRUE;
+ }
+ }
+ else {
+ N_EVAL_IS_DPTR (nv) = TRUE;
+ }
+}
+
+
+
+
+/*** LoadVal - Load the value of a node
+ *
+ * fSuccess = LoadVal (pv)
+ *
+ * Entry pv = pointer to value
+ *
+ * Exit EVAL_VAL (pv) = value
+ * EVAL_STATE (pv) = EV_rvalue
+ *
+ * Returns TRUE if value loaded
+ * FALSE if not (complex symbol type such as structure).
+ *
+ */
+
+
+bool_t LoadVal (peval_t pv)
+{
+ DASSERT (EVAL_STATE (pv) == EV_lvalue);
+
+ if (LoadSymVal (pv)) {
+ EVAL_STATE (pv) = EV_rvalue;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+
+
+/*
+ * TypeSize
+ *
+ * Returns size in bytes of value on expression stack
+ */
+
+
+long TypeSize (peval_t pv)
+{
+ if (CV_IS_PRIMITIVE (EVAL_TYP (pv))) {
+ // primitive type
+ return (TypeSizePrim (EVAL_TYP (pv)));
+ }
+ else {
+ // complex type
+ return (TypeDefSize (pv));
+ }
+}
+
+
+/*
+ * TypeDefSize
+ *
+ * Returns size in bytes of a non-primitive type.
+ */
+
+long TypeDefSize (peval_t pv)
+{
+ long retval;
+
+ if (EVAL_IS_ARRAY (pv)) {
+ retval = PTR_ARRAYLEN (pv);
+ }
+ else if (EVAL_IS_PTR (pv)) {
+ switch (EVAL_PTRTYPE (pv)) {
+ case CV_PTR_FAR:
+ case CV_PTR_HUGE:
+ retval = 4;
+ break;
+
+ case CV_PTR_NEAR32:
+ retval = 4;
+ break;
+
+ case CV_PTR_FAR32:
+ retval = 6;
+ break;
+
+ default:
+ retval = 2;
+ }
+ }
+ else if (EVAL_IS_CLASS (pv)) {
+ retval = CLASS_LEN (pv);
+ }
+ else if (EVAL_IS_FCN (pv)) {
+ if (pv->data.fcn.flags.farcall == TRUE) {
+ retval = 4;
+ }
+ else {
+ retval = sizeof (UOFFSET);
+ }
+ }
+ else if (EVAL_IS_BITF (pv)) {
+ switch (BITF_UTYPE (pv)) {
+ case T_SHORT:
+ case T_USHORT:
+ retval = 2;
+ break;
+
+ case T_LONG:
+ case T_ULONG:
+ retval = 4;
+ break;
+
+ default:
+ pExState->err_num = ERR_BADOMF;
+ retval = 0;
+ break;
+ }
+ }
+ else {
+ retval = 0;
+ }
+ return (retval);
+}
+
+
+
+
+
+
+/** TypeSizePrim - return size of primitive type
+ *
+ * len = TypeSizePrim (type)
+ *
+ * Entry type = primitive type index
+ *
+ * Exit none
+ *
+ * Returns size in byte of primitive type
+ */
+
+
+int TypeSizePrim (CV_typ_t itype)
+{
+ if (itype == T_NOTYPE) {
+ /*
+ * we need to have a assert here but we cannot because a
+ * pointer to function can (will) have a null argumtent list
+ * which makes it look like a varargs which means all bets are off
+ */
+ if (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) {
+ return (sizeof (ULONG));
+ } else {
+ return sizeof(USHORT);
+ }
+ }
+ else if (CV_MODE (itype) != CV_TM_DIRECT) {
+ return (size_ptr [CV_MODE (itype)]);
+ }
+ else switch (CV_TYPE (itype)) {
+ case CV_SPECIAL:
+ return (size_special [CV_SUBT (itype)]);
+
+ case CV_SPECIAL2:
+ return (size_special2 [CV_SUBT (itype)]);
+
+ case CV_INT:
+ return (size_int [CV_SUBT (itype)]);
+
+ case CV_SIGNED:
+ case CV_UNSIGNED:
+ case CV_BOOLEAN:
+ return (size_integral [CV_SUBT (itype)]);
+
+ case CV_REAL:
+ return (size_real [CV_SUBT (itype)]);
+
+ case CV_COMPLEX:
+ default:
+ DASSERT (FALSE);
+ return (0);
+ }
+}
+
+
+
+
+
+
+
+/** UpdateMem - update memory or register for assignment operation
+ *
+ * fSuccess = UpdateMem (pv);
+ *
+ * Entry pv = pointer to node containg update data
+ *
+ * Exit is_assign = TRUE to indicate memory changed
+ *
+ * Returns TRUE if memory updated without error
+ * FALSE if error during memory update
+ */
+
+
+bool_t UpdateMem (peval_t pv)
+{
+ SHREG reg;
+ ushort cbVal;
+ ushort dummy[2];
+ ADDR addr;
+
+ is_assign = TRUE; /* Indicate assignment operation */
+ if (!EVAL_IS_REG (pv)) {
+ // destination is not a register
+ ResolveAddr( pv );
+
+ cbVal = (ushort)TypeSize (pv);
+ addr = EVAL_SYM (pv);
+ if (ADDR_IS_LI (addr)) {
+ SHFixupAddr (&addr);
+ }
+ if (EVAL_IS_PTR (pv) && (EVAL_IS_FPTR (pv) || EVAL_IS_HPTR (pv))) {
+ dummy[0] = (OFF16) EVAL_PTR_OFF (pv);
+ dummy[1] = EVAL_PTR_SEG (pv);
+ return (PutDebuggeeBytes (addr, cbVal, (char *)dummy, EVAL_TYP(pv)) == (UINT)cbVal);
+ }
+ else {
+ return (PutDebuggeeBytes (addr, cbVal, (char *)&EVAL_VAL (pv), EVAL_TYP(pv)) == (UINT)cbVal);
+ }
+ }
+
+ //
+ // It is in a register
+ //
+
+ reg.hReg = EVAL_REG (pv);
+ if (EVAL_IS_PTR(pv)) {
+ reg.hReg = PTR_REG_IREG(pv);
+ }
+
+ //
+ // Get the old register value; we copy in the number of bits
+ // for the current data type; allows multiple vars in one
+ // register should a compiler ever so desire.
+ //
+
+ if (GetReg (&reg, pCxt) == NULL) {
+ pExState->err_num = ERR_REGNOTAVAIL;
+ return FALSE;
+ }
+
+ //
+ // Transfer the bytes from the eval_t to the register
+ //
+
+
+ if (CV_IS_PRIMITIVE ( EVAL_TYP (pv) ) ) {
+
+ //
+ // notenote: this is dependent on byte ordering.
+ // Won't work on a big-endian machine.
+ //
+
+#if defined(TARGET_ALPHA) || defined(TARGET_PPC)
+ if ( EVAL_TYP(pv) == T_REAL32 ) {
+ //
+ // Can't do a memory copy here because the
+ // register subsystem assumes that the reg value
+ // is a double (the type of Byte8).
+ //
+
+ float f1;
+ double d1;
+
+ f1 = EVAL_FLOAT(pv);
+ d1 = f1;
+ *((ULONGLONG UNALIGNED *)&reg.Byte8) = *((PULONGLONG)&d1);
+ } else
+#endif
+ {
+ cbVal = TypeSizePrim(EVAL_TYP (pv));
+
+ memcpy(&reg.Byte1, &EVAL_CHAR (pv), cbVal);
+ }
+
+ } else if (EVAL_IS_PTR (pv) ) {
+
+ //
+ // Handle pointers to UserDefinedTypes
+ // notenote - this isn't right for WOW,
+ // where pointers can be different lengths.
+ //
+
+ memcpy(&reg.Byte1, &EVAL_CHAR (pv), sizeof (long));
+
+ } else {
+
+ //
+ // Non-primitive types in registers not
+ // supported in first release
+ //
+
+ EVAL_LONG (pv) = 0;
+ DASSERT(FALSE);
+ }
+
+ if (SetReg (&reg, NULL) == NULL) {
+ pExState->err_num = ERR_REGNOTAVAIL;
+ return (FALSE);
+ }
+
+ if ((reg.hReg == CV_REG_CS) || (reg.hReg == CV_REG_IP)) {
+ // M00KLUDGE what do I do here?????
+ //fEnvirGbl.fAll &= mdUserPc; /* clear the user pc mask */
+ //UpdateUserEnvir (mUserPc); /* restore the user pc */
+ }
+ return (TRUE);
+}
+
+
+
+#if defined (M68K)
+/** FlipBytes - reverse byte order (toggle big/little endian)
+ *
+ * FlipBytes (pval, type)
+ *
+ * Entry pval = pointer to byte stream to be reversed
+ * type = CV type index (Must be primitive, presently)
+ *
+ * Exit byte stream reversed
+ *
+ * Returns nothing
+ */
+void FlipBytes (uchar *pval, CV_typ_t type)
+{
+ int cbSize;
+ uchar *pb, bT;
+
+ DASSERT(CV_IS_PRIMITIVE(type));
+
+ if (!CV_TYP_IS_REAL(type)) {
+ cbSize = TypeSizePrim(type);
+ pb = pval;
+
+ while (cbSize > 1) {
+ cbSize--;
+
+ bT = *pb;
+ *pb = *(pb+cbSize);
+ *(pb+cbSize) = bT;
+
+ pb++;
+ cbSize--;
+ }
+
+ }
+
+}
+
+/** GetDebuggeeBytes
+ ** PutDebuggeeBytes
+ ** GetReg
+ ** SetReg
+ *
+ * These routines are a layer for the DH...
+ * routines. For big-endian targets, (i.e. if
+ * M68K is defined,) they call the byte-flipping
+ * routine as neccesary. Parameters and returns
+ * are the same as the DH... routines, except
+ * DH___DebuggeeBytes, which take one extra parameter,
+ * the CV type of the data.
+ *
+ * This layer only exists for big-endian-target builds.
+ * (Presently, if M68K is defined.)
+ */
+UINT GetDebuggeeBytes (ADDR addr, UINT cb, void *pv, CV_typ_t type)
+{
+ UINT retval;
+
+ retval = (*pCVF->pDHGetDebuggeeBytes)(addr, cb, pv);
+ FlipBytes((uchar *)pv, type);
+
+ return(retval);
+}
+
+UINT PutDebuggeeBytes (ADDR addr, UINT cb, void *pv, CV_typ_t type)
+{
+ UINT retval;
+
+ FlipBytes((uchar *)pv, type);
+ retval = (*pCVF->pDHPutDebuggeeBytes)(addr, cb, pv);
+ FlipBytes((uchar *)pv, type);
+
+ return(retval);
+}
+
+PSHREG GetReg (PSHREG pshreg, PCXT pcxt)
+{
+ PSHREG retval;
+
+ retval = (*pCVF->pDHGetReg)(pshreg, pcxt);
+ FlipBytes(&retval->Byte1, TypeFromHreg(retval->hReg));
+
+ return(retval);
+}
+
+PSHREG SetReg (PSHREG pshreg, PCXT pcxt)
+{
+ PSHREG retval;
+
+ FlipBytes(&pshreg->Byte1, TypeFromHreg(pshreg->hReg));
+ retval = (*pCVF->pDHSetReg)(pshreg, pcxt);
+ FlipBytes(&retval->Byte1, TypeFromHreg(retval->hReg));
+
+ return(retval);
+}
+
+#endif
+
+
+LOCAL __inline CV_prop_t
+GetProperty(
+ CV_typ_t type,
+ neval_t nv)
+{
+ HTYPE hType;
+ plfEasy pType;
+ CV_prop_t retval = {0};
+
+ if ((hType = GetHTypeFromTindex (nv, type)) == 0) {
+ DASSERT(FALSE);
+ return retval;
+ }
+ pType = (plfEasy)(&((TYPPTR)(MHOmfLock (hType)))->leaf);
+
+ switch (pType->leaf) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ retval = ((plfClass)pType)->property;
+ break;
+
+ case LF_UNION:
+ retval = ((plfUnion)pType)->property;
+ break;
+
+ case LF_ENUM:
+ retval = ((plfEnum)pType)->property;
+ break;
+
+ default:
+ DASSERT(FALSE);
+ }
+
+ MHOmfUnLock(hType);
+ return retval;
+}
+
+CV_typ_t
+GetUdtDefnTindex (
+ CV_typ_t TypeIn,
+ neval_t nv,
+ char *lpStr)
+{
+ static BOOL fIn = FALSE;
+ search_t Name;
+ eval_t localEval = *nv;
+ CV_typ_t tiResult = T_NOTYPE;
+ CV_prop_t propIn, propSeek;
+
+ // recursion check
+ if (fIn)
+ return FALSE;
+ fIn = TRUE; // set recursion guard
+
+ EVAL_TYP (&localEval) = 0;
+ EVAL_ITOK (&localEval) = 0;
+ EVAL_CBTOK (&localEval) = 0;
+
+ memset (&Name, 0, sizeof (search_t));
+ Name.initializer = INIT_sym;
+ Name.pfnCmp = (PFNCMP) FNCMP;
+ Name.pv = &localEval;
+ // Look in all scopes except class scope: if we are in a member
+ // fn of the current class, this will lead to infinite recursion
+ // as we look for class X in the scope of class X in the ...
+ Name.scope = SCP_all & ~SCP_class;
+ Name.clsmask = CLS_enumerate | CLS_ntype;
+ Name.CXTT = *pCxt;
+ Name.bn = 0;
+ Name.bnOp = 0;
+ Name.sstr.lpName = (uchar *) lpStr + 1;
+ Name.sstr.cb = *lpStr;
+ Name.state = SYM_init;
+
+ // modify search to look only for UDTs
+
+ Name.sstr.searchmask = SSTR_symboltype;
+ Name.sstr.symtype = S_UDT;
+
+ propIn = GetProperty(TypeIn, nv);
+
+ while (SearchSym (&Name) == HR_found) {
+ PopStack ();
+ if (EVAL_STATE (&localEval) == EV_type) {
+ propSeek = GetProperty(EVAL_TYP(&localEval), &localEval);
+ if ((propIn.isnested == propSeek.isnested) &&
+ (propIn.scoped == propSeek.scoped)) {
+ tiResult = EVAL_TYP (&localEval);
+ break;
+ }
+ }
+ }
+
+ fIn = FALSE; // clear recursion guard
+ return tiResult;
+}
+
+/** GetHSYMCodeFromHSYM - Get HSYM encoded form from HSYM value
+ *
+ * lsz = GetHSYMFromHSYMCode (hSym)
+ *
+ * Entry hSm = hSym to be encoded
+ *
+ * Exit none
+ *
+ * Returns pointer to static buffer containing a string
+ * representation of hSym. The encoding is merely
+ * a conversion to a string that expresses the
+ * hSym value in hex notation.
+ *
+ */
+
+char *
+GetHSYMCodeFromHSYM(
+ HSYM hSym)
+{
+ static char buf[HSYM_CODE_LEN + 1];
+ sprintf(buf, "%08.08lx\0", (ulong)hSym);
+ return (char *)buf;
+}
+
+/** GetHSYMFromHSYMCode - Get HSYM from encoded HSYM string
+ *
+ * hSym = GetHSYMFromHSYMCode (lsz)
+ *
+ * Entry lsz = pointer to encoded HSYM string
+ *
+ * Exit none
+ *
+ * Returns hSym value
+ */
+
+HSYM
+GetHSYMFromHSYMCode(
+ char *lsz)
+{
+ unsigned long ul = 0;
+ char ch;
+ int digit;
+ int i;
+ for (i=0; i < HSYM_CODE_LEN; i++) {
+ DASSERT (isdigit (*lsz));
+ ch = *lsz++;
+ if (isdigit (ch))
+ digit = ch - '0';
+ else
+ digit = toupper(ch) - 'A' + 10;
+ ul <<= 4;
+ ul += digit;
+ }
+ return (HSYM) ul;
+}
+
+/** fCanSubtractPtrs - Check if ptrs can be subtracted
+ *
+ * flag = fCanSubtractPtrs (pvleft, pvright)
+ *
+ * Entry pvleft, pvRight = pointers to corresponding
+ * evaluation nodes.
+ *
+ * Exit none
+ *
+ * Returns TRUE if ptr subtraction is allowed for the
+ * corresponding pointer types.
+ */
+
+bool_t
+fCanSubtractPtrs (
+ peval_t pvleft,
+ peval_t pvright)
+{
+ bool_t retval = FALSE;
+ eval_t evalL;
+ eval_t evalR;
+ peval_t pvL = &evalL;
+ peval_t pvR = &evalR;
+
+ DASSERT (EVAL_IS_PTR (pvleft) && EVAL_IS_PTR (pvright));
+ DASSERT (!EVAL_IS_REF (pvleft) && !EVAL_IS_REF (pvright));
+
+ if (EVAL_TYP (pvleft) == EVAL_TYP (pvright)) {
+ retval = TRUE;
+ }
+ else if ( EVAL_PTRTYPE (pvleft) == EVAL_PTRTYPE (pvright) ) {
+ *pvL = *pvleft;
+ *pvR = *pvright;
+
+ // check the underlying types
+ // RemoveIndir will resolve fwd. references and
+ // skip modifier nodes.
+ RemoveIndir (pvL);
+ RemoveIndir (pvR);
+
+ retval = ( EVAL_TYP (pvL) == EVAL_TYP (pvR) );
+ }
+
+ return retval;
+}
+
+#if MEMDBG
+
+#define MAX_MEM_ENTRIES 20000
+
+typedef struct MEMORYINFO {
+ UINT addr;
+ UINT addr2;
+ UINT size;
+ UINT line;
+ CHAR tag[16];
+ CHAR file[16];
+} MEMORYINFO, *LPMEMORYINFO;
+
+LPMEMORYINFO mi;
+UINT cmi;
+
+
+VOID
+LogMemoryInfo(
+ char *tag,
+ UINT addr,
+ UINT addr2,
+ UINT size,
+ char *file,
+ UINT line
+ )
+{
+ CHAR buf[128];
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+
+
+ if (mi == NULL) {
+ mi = (LPMEMORYINFO)VirtualAlloc(
+ NULL,
+ sizeof(MEMORYINFO) * MAX_MEM_ENTRIES,
+ MEM_COMMIT,
+ PAGE_READWRITE );
+ if (mi == NULL) {
+ ExitProcess( 1 );
+ }
+ }
+ buf[0] = 0;
+ _splitpath( file, NULL, NULL, fname, ext );
+ sprintf( mi[cmi].file, "%s%s", fname, ext );
+ strcpy( mi[cmi].tag, tag );
+ mi[cmi].addr = addr;
+ mi[cmi].addr2 = addr2;
+ mi[cmi].size = size;
+ mi[cmi].line = line;
+ cmi++;
+ if (cmi == MAX_MEM_ENTRIES) {
+ cmi = 0;
+ }
+}
+
+
+HDEP
+DbgMemAlloc(
+ UINT size,
+ char *file,
+ UINT line
+ )
+{
+ HDEP hdep = (HDEP)(*pCVF->pMHMemAllocate)( size );
+ LogMemoryInfo( "alloc", (UINT)hdep, 0, size, file, line );
+ return hdep;
+}
+
+
+HDEP
+DbgMemReAlloc(
+ HDEP hmem,
+ UINT size,
+ char *file,
+ UINT line
+ )
+{
+ HDEP hdep = (HDEP)(*pCVF->pMHMemReAlloc)( hmem, size );
+ LogMemoryInfo( "realloc", (UINT)hmem, (UINT)hdep, size, file, line );
+ return hdep;
+}
+
+
+VOID
+DbgMemFree(
+ HDEP hmem,
+ char *file,
+ UINT line
+ )
+{
+ LogMemoryInfo( "free", (UINT)hmem, 0, 0, file, line );
+ (*pCVF->pMHMemFree)( hmem );
+}
+
+LPVOID
+DbgMemLock(
+ HDEP hmem,
+ char *file,
+ UINT line
+ )
+{
+ LPVOID lpv = (*pCVF->pMHMemLock)( hmem );
+// LogMemoryInfo( "lock", (UINT)hmem, (UINT)lpv, 0, file, line );
+ return lpv;
+}
+
+VOID
+DbgMemUnLock(
+ HDEP hmem,
+ char *file,
+ UINT line
+ )
+{
+// LogMemoryInfo( "unlock", (UINT)hmem, 0, 0, file, line );
+ (*pCVF->pMHMemUnLock)( hmem );
+}
+#endif
diff --git a/private/windbg/eecan/debwalk.c b/private/windbg/eecan/debwalk.c
new file mode 100644
index 000000000..a3c3b52c3
--- /dev/null
+++ b/private/windbg/eecan/debwalk.c
@@ -0,0 +1,1010 @@
+/*** debwalk.c - walk bound expression tree and perform operations
+ *
+ */
+
+
+
+
+
+/*
+*
+*/
+LOCAL bool_t NEAR FASTCALL Walk (bnode_t);
+
+LOCAL bool_t NEAR FASTCALL WalkAddrOf (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkArray (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkAssign (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkBang (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkBasePtr (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkBinary (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkBScope (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkByteOps (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkCast (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkCastBin (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkConst (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkContext (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkDMember (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkDot (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkError (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkEmpty (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkFetch (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkFunction (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkLChild (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkRChild (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkPlusMinus (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkPMember (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkPostIncDec (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkPreIncDec (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkPointsTo (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkRelat (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkSegOp (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkSizeOf (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkSymbol (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkTypestr (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkUnary (bnode_t);
+LOCAL bool_t NEAR FASTCALL WalkUScope (bnode_t);
+
+/*
+*
+*/
+LOCAL bool_t NEAR PASCAL PushCXT (peval_t);
+LOCAL bool_t NEAR PASCAL GetCXTL (pnode_t);
+LOCAL bool_t NEAR PASCAL GetCXTFunction (pnode_t, pnode_t);
+
+// Walk Dispatch table
+
+LOCAL bool_t (NEAR FASTCALL *pWalk[]) (bnode_t) = {
+#define OPCNT(name, val)
+#define OPCDAT(opc)
+#define OPDAT(op, opfprec, opgprec, opclass, opbind, opeval, opwalk) opwalk,
+#include "debops.h"
+#undef OPDAT
+#undef OPCDAT
+#undef OPCNT
+};
+#ifdef WIN32
+extern uchar F_level[COPS_EXPR];
+#else
+extern uchar _based(_segname("_CODE")) F_level[COPS_EXPR];
+#endif
+#ifdef WIN32
+extern uchar G_level[COPS_EXPR];
+#else
+extern uchar _based(_segname("_CODE")) G_level[COPS_EXPR];
+#endif
+
+LOCAL char * PchString;
+LOCAL int CchString;
+LOCAL int CchStringMax;
+LOCAL bool_t FPrototype = TRUE;
+LOCAL bool_t FInScope = FALSE;
+
+typedef struct {
+ HDR_TYPE Hdr;
+ char Buf[256];
+} FORMATBUF;
+
+
+/** DoGetCXTL - Gets a list of symbols and contexts for expression
+ *
+ * status = DoGetCXTL (phTM, phCXTL)
+ *
+ * Entry phTM = pointer to handle to expression state structure
+ * phCXTL = pointer to handle for CXT list buffer
+ *
+ * Exit *phCXTL = handle for CXT list buffer
+ *
+ * Returns EENOERROR if no error
+ * status code if error
+ */
+
+
+ushort PASCAL DoGetCXTL (PHTM phTM, PHCXTL phCXTL)
+{
+ ushort retval = EECATASTROPHIC;
+
+ // lock the expression state structure and copy the context package
+
+ DASSERT (*phTM != 0);
+ if (*phTM != 0) {
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ if ((pExState->state.parse_ok == TRUE) &&
+ (pExState->state.bind_ok == TRUE)) {
+ if ((hCxtl = MHMemAllocate (sizeof (CXTL) + 5 * sizeof (HCS))) == 0) {
+ pExState->err_num = ERR_NOMEMORY;
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ *phCXTL = hCxtl;
+ return (EEGENERAL);
+ }
+ else {
+ pCxtl = MHMemLock (hCxtl);
+ mCxtl = 5;
+ pCxtl->CXT = pExState->cxt;
+ pCxtl->cHCS = 0;
+
+ }
+ pTree = MHMemLock (pExState->hETree);
+ if (GetCXTL (pnodeOfbnode(pTree->start_node))) {
+ retval = EENOERROR;
+ }
+ else {
+ retval = EEGENERAL;
+ }
+ *phCXTL = hCxtl;
+ MHMemUnLock (hCxtl);
+ MHMemUnLock (pExState->hETree);
+ }
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ }
+ return (retval);
+}
+
+
+
+
+
+/** GetCXTL - get CXT list from bound expression tree
+ *
+ * fSuccess = GetCXTL (pn)
+ *
+ * Entry pn = pointer to node
+ * hCxtl = handle of CXT list
+ * pCxtl = pointer to CXT list
+ * mCxtl = maximum number of context list entries
+ *
+ * Exit *phCXTL = handle for CXT list
+ *
+ * Returns TRUE if no error
+ * FALSEif error
+ */
+
+
+LOCAL bool_t NEAR PASCAL GetCXTL (pnode_t pn)
+{
+ PCXT oldCxt;
+ bool_t retval;
+ peval_t pv;
+
+ // Recurse down the tree.
+
+ pv = &pn->v[0];
+ switch (NODE_OP (pn)) {
+ case OP_typestr:
+ return (TRUE);
+
+ case OP_const:
+ case OP_ident:
+ case OP_this:
+ case OP_hsym:
+ return (PushCXT (pv));
+
+ case OP_cast:
+ return (GetCXTL (pnodeOfbnode(NODE_RCHILD (pn))));
+
+ case OP_function:
+ return (GetCXTFunction (
+ pnodeOfbnode(NODE_LCHILD (pn)),
+ pnodeOfbnode(NODE_RCHILD (pn))));
+
+ case OP_context:
+ // Set the new context for evaluation of the remainder of this
+ // part of the tree
+
+ oldCxt = pCxt;
+ pCxt = SHpCXTFrompCXF ((PCXF)&pn->v[0]);
+ retval = GetCXTL (pnodeOfbnode(NODE_LCHILD (pn)));
+ pCxt = oldCxt;
+ return (retval);
+
+ // All other operators come through here. Recurse down the tree
+
+ default:
+ if (!GetCXTL (pnodeOfbnode(NODE_LCHILD (pn))))
+ return (FALSE);
+
+ if ((pn->pnRight != 0) && (!GetCXTL (pnodeOfbnode(NODE_RCHILD (pn)))))
+ return (FALSE);
+
+ return (TRUE);
+ }
+}
+
+
+
+
+
+
+/** GetExpr - get expression from bound expression tree
+ *
+ * status = GetExpr (radix, phStr, pEnd);
+ *
+ * Entry radix = numeric radix for formatting
+ * phStr = pointer to handle for formatted string
+ * pEnd = pointer to int to receive index of char that ended parse
+ *
+ * Exit *phStr = handle for allocated expression
+ * *pEnd = index of character that terminated parse
+ *
+ * Returns EENOERROR if no error
+ * error number if
+ */
+
+
+EESTATUS PASCAL
+GetExpr (
+ PHTM phTM,
+ EERADIX radix,
+ PEEHSTR phStr,
+ ushort FAR * pEnd
+ )
+{
+ EESTATUS retval = EECATASTROPHIC;
+ char FAR *pStr;
+
+ DASSERT (*phTM != 0);
+ if (*phTM == 0) {
+ return retval;
+ }
+
+ DASSERT(pExState == NULL);
+ pExState = MHMemLock (*phTM);
+ if (pExState->state.bind_ok == TRUE) {
+ pTree = MHMemLock(pExState->hETree);
+ pExStr = MHMemLock(pExState->hExStr);
+
+ PchString = NULL;
+ CchStringMax = CchString = 0;
+
+ retval = Walk((bnode_t)pTree->start_node);
+
+ MHMemUnLock(pExState->hETree);
+ MHMemUnLock(pExState->hExStr);
+ if (retval == TRUE) {
+ retval = EENOERROR;
+ if ((*phStr = MHMemAllocate( CchString+1 )) != 0) {
+ pStr = MHMemLock( *phStr );
+ _fmemcpy(pStr, PchString, CchString);
+ *pEnd = CchString;
+ MHMemUnLock( *phStr);
+ } else {
+ retval = EEGENERAL;
+ *phStr = 0;
+ }
+ } else {
+ retval = EEGENERAL;
+ *phStr = 0;
+ }
+
+ if (PchString != NULL) {
+ free(PchString);
+ }
+ PchString = NULL;
+ }
+ MHMemUnLock (*phTM);
+ pExState = NULL;
+ return (retval);
+}
+
+
+
+
+/** PushCXT - Push CXT list entry
+ *
+ * fSuccess = PushCXT (pv)
+ *
+ * Entry pv = pointer to evaluation
+ * hCxtl = handle of CXT list
+ * pCxtl = pointer to CXT list
+ * mCxtl = maximum number of context list entries
+ *
+ * Exit CXT entry pushed
+ *
+ * Returns TRUE if no error
+ * FALSE if error
+ */
+
+
+LOCAL bool_t NEAR PASCAL PushCXT (peval_t pv)
+{
+ HCXTL nhCxtl;
+ PCXTL npCxtl;
+ uint lenIn;
+ uint lenOut;
+
+ DASSERT (pCxtl->cHCS <= mCxtl);
+ if (mCxtl < pCxtl->cHCS) {
+ // this is a catatrosphic error
+ return (FALSE);
+ }
+ if (mCxtl == pCxtl->cHCS) {
+ // grow CXT list
+
+ lenIn = sizeof (CXTL) + mCxtl * sizeof (HCS);
+ lenOut = sizeof (CXTL) + (mCxtl + 5) * sizeof (HCS);
+ if ((nhCxtl = MHMemAllocate (lenOut)) == 0) {
+ return (FALSE);
+ }
+ npCxtl = MHMemLock (nhCxtl);
+ _fmemcpy (npCxtl, pCxtl, lenIn);
+ mCxtl += 5;
+ MHMemUnLock (hCxtl);
+ MHMemFree (hCxtl);
+ hCxtl = nhCxtl;
+ pCxtl = npCxtl;
+ }
+
+ // in case of a constant we will return only the context information.
+ // anything more than that doesn't make sense and since we
+ // need to get context only information in the case of bp {..}.line
+ // we needed to make this change.
+
+ pCxtl->rgHCS[pCxtl->cHCS].hSym = pv->hSym;
+ pCxtl->rgHCS[pCxtl->cHCS].CXT = *pCxt;
+ pCxtl->cHCS++;
+ return (TRUE);
+}
+
+
+
+LOCAL bool_t NEAR PASCAL GetCXTFunction (pnode_t pnLeft, pnode_t pnRight)
+{
+ Unreferenced( pnLeft );
+ Unreferenced( pnRight );
+
+ return (FALSE);
+}
+
+LOCAL BOOLEAN
+WalkAppendString(
+ char * pch,
+ int cch
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+
+--*/
+{
+ if (cch > CchStringMax - CchString) {
+ PchString = (LPSTR)MHMemReAlloc((HDEP)PchString, CchStringMax + 256);
+ if (PchString == NULL) {
+ return FALSE;
+ }
+ CchStringMax += 256;
+ }
+
+ _fstrncpy(&PchString[CchString], pch, cch);
+ CchString += cch;
+ return TRUE;
+} /* WalkAppendString() */
+
+/*
+ * Functions to build a string from a TM Tree
+ */
+
+LOCAL bool_t NEAR FASTCALL
+Walk(
+ bnode_t bn
+ )
+{
+ return (*pWalk[NODE_OP(pnodeOfbnode(bn))])(bn);
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkLChild (bnode_t bn)
+{
+ register bnode_t bnL = NODE_LCHILD (pnodeOfbnode(bn));
+ BOOL f = FALSE;
+
+ if (F_level[NODE_OP(pnodeOfbnode(bn))] > F_level[NODE_OP(pnodeOfbnode(bnL))]) {
+ if (!WalkAppendString("(", 1)) {
+ return FALSE;
+ }
+ f = TRUE;
+ }
+
+ if (!((*pWalk[NODE_OP(pnodeOfbnode(bnL))])(bnL))) {
+ return FALSE;
+ }
+
+ if (f) {
+ return WalkAppendString(")", 1);
+ }
+
+ return TRUE;
+} /* WalkLChild() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkRChild (bnode_t bn)
+{
+ register bnode_t bnR = NODE_RCHILD (pnodeOfbnode(bn));
+ BOOL f = FALSE;
+
+ if (F_level[NODE_OP(pnodeOfbnode(bn))] > F_level[NODE_OP(pnodeOfbnode(bnR))]) {
+ if (!WalkAppendString("(", 1)) {
+ return FALSE;
+ }
+ f = TRUE;
+ }
+
+ if (!((*pWalk[NODE_OP(pnodeOfbnode(bnR))])(bnR))) {
+ return FALSE;
+ }
+
+ if (f) {
+ return WalkAppendString(")", 1);
+ }
+
+ return TRUE;
+} /* WalkRChild() */
+
+/*
+*
+*/
+
+LOCAL bool_t NEAR FASTCALL
+WalkAddrOf (bnode_t bn)
+{
+ return WalkAppendString("&", 1) && WalkLChild(bn);
+} /* WalkAddrOf() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkArray (bnode_t bn)
+{
+ return WalkLChild(bn) && WalkAppendString("[", 1) &&
+ WalkRChild(bn) && WalkAppendString("]", 1);
+} /* WalkArray() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkAssign (bnode_t bn)
+{
+ char * pch;
+ int cch = 2;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_eq: pch = "="; cch = 1; break;
+ case OP_multeq: pch = "*="; break;
+ case OP_diveq: pch = "/="; break;
+ case OP_modeq: pch = "%="; break;
+ case OP_pluseq: pch = "+="; break;
+ case OP_minuseq: pch = "-="; break;
+ case OP_shleq: pch = "<<="; cch = 3; break;
+ case OP_shreq: pch = ">>="; cch = 3; break;
+ case OP_andeq: pch = "&="; break;
+ case OP_xoreq: pch = "^="; break;
+ case OP_oreq: pch = "|="; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkLChild(bn) && WalkAppendString(pch, cch) && WalkRChild(bn);
+} /* WalkAssign() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkBang (bnode_t bn)
+{
+ return WalkAppendString("!", 1) && WalkLChild(bn);
+} /* WalkBang() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkBasePtr (bnode_t bn)
+{
+ DASSERT(FALSE);
+ return TRUE;
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkBinary (bnode_t bn)
+{
+ char * pch;
+ int cch = 1;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_mult: pch = "*"; break;
+ case OP_div: pch = "/"; break;
+ case OP_mod: pch = "%"; break;
+ case OP_shl: pch = "<<"; cch = 2; break;
+ case OP_shr: pch = ">>"; cch = 2; break;
+ case OP_and: pch = "&"; break;
+ case OP_xor: pch = "^"; break;
+ case OP_or: pch = "|"; break;
+ case OP_andand: pch = "&&"; cch = 2; break;
+ case OP_oror: pch = "||"; cch = 2; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkLChild(bn) && WalkAppendString(pch, cch) && WalkRChild(bn);
+} /* WalkBinary() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkBScope (bnode_t bn)
+{
+ bool_t fInScope = FInScope;
+ bool_t fResult;
+
+ FInScope = TRUE;
+ fResult = WalkLChild(bn) && WalkAppendString("::", 2) && WalkRChild(bn);
+ FInScope = fInScope;
+ return fResult;
+} /* WalkBScope() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkByteOps (bnode_t bn)
+{
+ char * pch;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_by: pch = "BY "; break;
+ case OP_wo: pch = "WO "; break;
+ case OP_dw: pch = "DW "; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkAppendString(pch, 2) && WalkLChild(bn);
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkCast (bnode_t bn)
+{
+ peval_t pv = &pnodeOfbnode(NODE_LCHILD(pnodeOfbnode(bn)))->v[0];
+ FORMATBUF fb;
+ char * pch;
+ unsigned int cch;
+
+ pch = fb.Buf;
+ cch = sizeof(fb.Buf);
+ FormatType(pv, &pch, &cch, NULL, FPrototype, &fb.Hdr);
+
+ do {
+ pch--;
+ } while (*pch == ' ');
+
+ return WalkAppendString("(", 1) &&
+ WalkAppendString(fb.Buf, pch-fb.Buf+1) &&
+ WalkAppendString(")", 1) &&
+ WalkRChild(bn);
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkCastBin (bnode_t bn)
+{
+ peval_t pv = &pnodeOfbnode(NODE_LCHILD(pnodeOfbnode(bn)))->v[0];
+ FORMATBUF fb;
+ char * pch;
+ unsigned int cch;
+ bool_t f;
+
+ pch = fb.Buf;
+ cch = sizeof(fb.Buf);
+ FormatType(pv, &pch, &cch, NULL, FPrototype, &fb.Hdr);
+
+ do {
+ pch--;
+ } while (*pch == ' ');
+
+ f = WalkAppendString("(", 1) &&
+ WalkAppendString(fb.Buf, pch-fb.Buf+1) &&
+ WalkAppendString(")", 1);
+
+ if (!f) {
+ return f;
+ }
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_caststar: pch = "*"; break;
+ case OP_castplus: pch = "+"; break;
+ case OP_castminus: pch = "-"; break;
+ case OP_castamp: pch = "&"; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkAppendString(pch, 1) && WalkRChild(bn);
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkConst (bnode_t bn)
+{
+ peval_t pv = &pnodeOfbnode(bn)->v[0];
+
+ return WalkAppendString(pExStr + EVAL_ITOK(pv), EVAL_CBTOK(pv));
+} /* WalkConst() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkContext (bnode_t bn)
+{
+ peval_t pv = &pnodeOfbnode(bn)->v[0];
+
+ return WalkAppendString(pExStr + EVAL_ITOK(pv), EVAL_CBTOK(pv)) &&
+ WalkLChild(bn);
+} /* WalkContext() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkDMember (bnode_t bn)
+{
+ DASSERT(FALSE);
+ return TRUE;
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkDot (bnode_t bn)
+{
+ return WalkLChild(bn) && WalkAppendString(".", 1) && WalkRChild(bn);
+} /* WalkDot() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkEmpty (register bnode_t bn)
+{
+ return TRUE;
+} /* WalkEmpty */
+
+LOCAL bool_t NEAR FASTCALL
+WalkError (register bnode_t bn)
+{
+ DASSERT(FALSE);
+ return TRUE;
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkFetch (bnode_t bn)
+{
+ return WalkAppendString("*", 1) && WalkLChild(bn);
+} /* WalkFetch() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkFunction (bnode_t bn)
+{
+ bnode_t bnT;
+ BOOLEAN f = FALSE;
+ bool_t fPrototype = FPrototype;
+
+ FPrototype = FALSE;
+
+ if (!WalkLChild(bn) || !WalkAppendString("(", 1)) {
+ FPrototype = fPrototype;
+ return FALSE;
+ }
+
+ FPrototype = fPrototype;
+ for (bnT = NODE_RCHILD( pnodeOfbnode(bn) );
+ NODE_OP(pnodeOfbnode(bnT)) != OP_endofargs;
+ bnT = NODE_RCHILD( pnodeOfbnode(bnT) )) {
+ if (f) {
+ if (!WalkAppendString(", ", 2)) {
+ return FALSE;
+ }
+ } else {
+ f = TRUE;
+ }
+ if (!WalkLChild(bnT)) {
+ return FALSE;
+ }
+ }
+
+ return WalkAppendString(")", 1);
+} /* WalkFunction() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkPlusMinus (bnode_t bn)
+{
+ char * pch;
+
+ switch( NODE_OP(pnodeOfbnode(bn)) ) {
+ case OP_plus:
+ pch = "+";
+ break;
+
+ case OP_minus:
+ pch = "-";
+ break;
+
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ if (WalkLChild(bn) && WalkAppendString(pch, 1) && WalkRChild(bn)) {
+ return TRUE;
+ }
+ return FALSE;
+} /* WalkPlusMinus() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkPMember (bnode_t bn)
+{
+ DASSERT(FALSE);
+ return TRUE;
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkPostIncDec (bnode_t bn)
+{
+ char * pch;
+ int cch = 2;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_postinc: pch = "++"; break;
+ case OP_postdec: pch = "--"; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkLChild(bn) && WalkAppendString(pch, cch);
+} /* WalkPostIncDec() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkPreIncDec (bnode_t bn)
+{
+ char * pch;
+ int cch = 2;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_preinc: pch = "++"; break;
+ case OP_predec: pch = "--"; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkAppendString(pch, cch) && WalkLChild(bn);
+} /* WalkPreIncDec() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkPointsTo (bnode_t bn)
+{
+ return WalkLChild(bn) && WalkAppendString("->", 2) && WalkRChild(bn);
+} /* WalkPointsTo() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkRelat (bnode_t bn)
+{
+ char * pch;
+ int cch = 2;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_lt: pch = "<"; cch = 1; break;
+ case OP_lteq: pch = "<="; break;
+ case OP_gt: pch = ">"; cch = 1; break;
+ case OP_gteq: pch = ">="; break;
+ case OP_eqeq: pch = "=="; break;
+ case OP_bangeq: pch = "!="; break;
+
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkLChild(bn) && WalkAppendString(pch, cch) && WalkRChild(bn);
+} /* WalkRelat() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkSegOp (bnode_t bn)
+{
+ return WalkLChild(bn) && WalkAppendString(":", 1) && WalkRChild(bn);
+}
+
+LOCAL bool_t NEAR FASTCALL
+WalkSizeOf (bnode_t bn)
+{
+ return WalkAppendString("sizeof(", 7) && WalkLChild(bn) &&
+ WalkAppendString(")", 1);
+} /* WalkSizeOf() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkSymbol (bnode_t bn)
+{
+ peval_t pv = &pnodeOfbnode(bn)->v[0];
+ SYMPTR pSym;
+ int len;
+ EEHSTR hStr = 0;
+ FORMATBUF fb;
+ CV_typ_t rvtype;
+ CV_typ_t mclass;
+ CV_typ_t call;
+ ushort cparam;
+ CV_typ_t paramtype;
+ HTYPE hType;
+ plfEasy pType;
+ char * pch;
+ int cch;
+ char * pch2;
+ char * pch3;
+ char ch;
+
+ if (EVAL_HSYM(pv) == 0) {
+ return WalkAppendString(pExStr + EVAL_ITOK(pv), EVAL_CBTOK(pv));
+ }
+
+ switch((pSym = MHOmfLock( (HDEP)EVAL_HSYM (pv) ))->rectyp) {
+ case S_BPREL16:
+ len = ((BPRELPTR16) pSym)->name[0];
+ pch = &((BPRELPTR16) pSym)->name[1];
+ break;
+
+ case S_BPREL32:
+ len = ((BPRELPTR32) pSym)->name[0];
+ pch = &((BPRELPTR32) pSym)->name[1];
+ break;
+
+ case S_LDATA16:
+ case S_GDATA16:
+ case S_PUB16:
+ len = ((DATAPTR16) pSym)->name[0];
+ pch = &((DATAPTR16) pSym)->name[1];
+ break;
+
+ case S_LDATA32:
+ case S_GDATA32:
+ case S_PUB32:
+ len = ((DATAPTR32) pSym)->name[0];
+ pch = &((DATAPTR32) pSym)->name[1];
+ break;
+
+ case S_REGISTER:
+ len = ((REGPTR) pSym)->name[0];
+ pch = &((REGPTR) pSym)->name[1];
+ break;
+
+ case S_REGREL16:
+ len = ((REGREL16 *) pSym)->name[0];
+ pch = &((REGREL16 *) pSym)->name[1];
+ break;
+
+ case S_REGREL32:
+ len = ((LPREGREL32) pSym)->name[0];
+ pch = &((LPREGREL32) pSym)->name[1];
+ break;
+
+ case S_LPROC16:
+ case S_GPROC16:
+ len = ((PROCPTR16) pSym)->name[0];
+ pch = &((PROCPTR16) pSym)->name[1];
+ break;
+
+ case S_LPROC32:
+ case S_GPROC32:
+ len = ((PROCPTR32) pSym)->name[0];
+ pch = &((PROCPTR32) pSym)->name[1];
+ break;
+
+ case S_LPROCMIPS:
+ case S_GPROCMIPS:
+ len = ((PROCPTRMIPS) pSym)->name[0];
+ pch = &((PROCPTRMIPS) pSym)->name[1];
+ break;
+
+ case S_UDT:
+ len = ((UDTSYM *) pSym)->name[0];
+ pch = &((UDTSYM *) pSym)->name[1];
+ break;
+
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ if ((FPrototype) &&
+ (hType = THGetTypeFromIndex( EVAL_MOD(pv), EVAL_TYP(pv) )) != 0) {
+ pType = (plfEasy) (&((TYPPTR)(MHOmfLock ((HDEP)hType)))->leaf);
+ switch( pType->leaf ) {
+ case LF_PROCEDURE:
+ mclass = 0;
+ rvtype = ((plfProc)pType)->rvtype;
+ call = ((plfProc)pType)->calltype;
+ cparam = ((plfProc)pType)->parmcount;
+ paramtype = ((plfProc)pType)->arglist;
+ MHOmfUnLock((HDEP)hType);
+ pch2 = fb.Buf;
+ pch3 = pch + len;
+ ch = *pch3;
+ *pch3 = 0;
+ cch = sizeof(fb.Buf);
+ FormatProc(pv, &pch2, &cch, &pch, rvtype, mclass, call,
+ cparam, paramtype, 1, &fb.Hdr);
+ len = pch2 - fb.Buf;
+ pch = fb.Buf;
+ *pch3 = ch;
+ break;
+
+#if !defined (C_ONLY)
+ case LF_MFUNCTION:
+ rvtype = ((plfMFunc)pType)->rvtype;
+ mclass = ((plfMFunc)pType)->classtype;
+ call = ((plfMFunc)pType)->calltype;
+ cparam = ((plfMFunc)pType)->parmcount;
+ paramtype = ((plfMFunc)pType)->arglist;
+ MHOmfUnLock ((HDEP)hType);
+ pch3 = pch + len;
+ ch = *pch3;
+ *pch3 = 0;
+ if (FInScope) {
+ pch2 = strrchr(pch, ':');
+ if (pch2 == NULL) {
+ pch2 = pch;
+ } else {
+ pch2++;
+ }
+ } else {
+ pch2 = pch;
+ }
+ pch = fb.Buf;
+ cch = sizeof(fb.Buf);
+ FormatProc (pv, &pch, &cch, &pch2, rvtype, mclass, call,
+ cparam, paramtype, 1, &fb.Hdr);
+ len = pch - fb.Buf;
+ pch = fb.Buf;
+ *pch3 = ch;
+ break;
+#endif
+
+
+ default:
+ MHOmfUnLock((HDEP)hType);
+ }
+ }
+
+ return WalkAppendString(pch, len);
+} /* WalkSymbol() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkTypestr (bnode_t bn)
+{
+ peval_t pv = &pnodeOfbnode(NODE_LCHILD(pnodeOfbnode(bn)))->v[0];
+ FORMATBUF fb;
+ char * pch;
+ unsigned int cch;
+
+ pch = fb.Buf;
+ cch = sizeof(fb.Buf);
+ FormatType(pv, &pch, &cch, NULL, FPrototype, &fb.Hdr);
+
+ return WalkAppendString(fb.Buf, pch-fb.Buf);
+} /* WalkTypestr() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkUnary (bnode_t bn)
+{
+ char * pch;
+ int cch = 1;
+
+ switch( NODE_OP (pnodeOfbnode(bn)) ) {
+ case OP_negate: pch = "-"; break;
+ case OP_tilde: pch = "~"; break;
+ case OP_uplus: pch = "+"; break;
+ default:
+ DASSERT(FALSE);
+ return FALSE;
+ }
+
+ return WalkAppendString(pch, cch) && WalkLChild(bn);
+} /* WalkUnary() */
+
+LOCAL bool_t NEAR FASTCALL
+WalkUScope (bnode_t bn)
+{
+ bool_t fInScope = FInScope;
+ bool_t fResult;
+
+ FInScope = TRUE;
+ fResult = WalkAppendString("::", 2) && WalkLChild(bn);
+ FInScope = fInScope;
+ return fResult;
+} /* WalkUScope() */
diff --git a/private/windbg/eecan/dirs b/private/windbg/eecan/dirs
new file mode 100644
index 000000000..d388bd338
--- /dev/null
+++ b/private/windbg/eecan/dirs
@@ -0,0 +1,19 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= p_alpha \
+ p_i386 \
+ p_mips \
+ p_ppc
diff --git a/private/windbg/eecan/eeformat.c b/private/windbg/eecan/eeformat.c
new file mode 100644
index 000000000..1db2f3fb1
--- /dev/null
+++ b/private/windbg/eecan/eeformat.c
@@ -0,0 +1,642 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ EEFormat.c
+
+Abstract:
+
+ This module contains system wide formatting routines for all
+ windows that need to format and unformat supported types.
+
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-1992
+ Griffith Wm. Kadnier (v-griffk) 27-Apr-1992
+ Miche Baker-Harvey (miche) 05-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+
+typedef UINT FAR * LPUINT;
+
+struct format {
+ uint cBits;
+ uint fmtType;
+ uint radix;
+ uint fTwoFields;
+ uint cchMax;
+ LPSTR lpszDescription;
+} RgFormats[] = {
+ {8, fmtAscii, 0, FALSE, 1, "ASCII"},
+ {8, fmtInt, 16, TRUE, 2, "Byte"},
+ {16, fmtInt, 10, FALSE, 6, "Short"},
+ {16, fmtUInt, 16, FALSE, 4, "Short Hex"},
+ {16, fmtUInt, 10, FALSE, 5, "Short Unsigned"},
+ {32, fmtInt, 10, FALSE, 11, "Long"},
+ {32, fmtUInt, 16, FALSE, 8, "Long Hex"},
+ {32, fmtUInt, 10, FALSE, 10, "Long Unsigned"},
+ {64, fmtInt, 10, FALSE, 21, "Quad"},
+ {64, fmtUInt, 16, FALSE, 16, "Quad Hex"},
+ {64, fmtUInt, 10, FALSE, 20, "Quad Unsigned"},
+ {32, fmtFloat, 10, FALSE, 14, "Real (32-bit)"},
+ {64, fmtFloat, 10, FALSE, 23, "Real (64-bit)"},
+ {80, fmtFloat, 10, FALSE, 25, "Real (10-byte)"}
+// {128,fmtFloat, 10, FALSE, 42, "Real (16-byte)"}
+};
+
+//
+// range[i] is smallest value larger than that
+// expressible in 'i' bits.
+//
+
+ULONG range[] = {
+ 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
+ 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
+ 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
+ 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
+ 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
+ 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
+ 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
+
+ };
+
+
+char FAR *
+SkipWhitespace(char FAR * lpszIn)
+{
+ while (*lpszIn == ' ' || *lpszIn == '\t') {
+ lpszIn++;
+ }
+ return( lpszIn );
+} /* CPSkipWhiteSpace() */
+
+
+/*++
+
+Routine Description:
+
+ LargeIntegerFormat.
+
+ This routine formats a large integer, signed or unsigned,
+ in radix 8, 10 or 16, into a string.
+ This works on any machine with a LARGE_INTEGER type; it
+ does not require LARGE_INTEGER support from sprintf.
+
+Arguments:
+
+ li - the large integer value to be formatted
+ radix - the radix to use in formatting (8, 10, 16)
+ signed - whether the li is signed
+ buf - where to store the result
+ max - the buffer size.
+
+Returns:
+
+ pointer into buf where string begins
+
+--*/
+
+char *
+LargeIntegerFormat(LARGE_INTEGER li,
+ uint radix,
+ BOOLEAN signe,
+ char * buf,
+ unsigned long max
+ )
+{
+
+ LARGE_INTEGER radixli, remain;
+ int digit;
+ BOOLEAN needsign = FALSE;
+
+
+ //
+ // make sure the radix is ok, and put in LARGE_INTEGER
+ //
+
+ DASSERT (radix == 8 || radix == 10 || radix == 16 );
+
+ radixli.LowPart = radix;
+ radixli.HighPart = 0;
+
+ remain.LowPart = remain.HighPart = 0;
+
+ //
+ // null-terminate the string
+ //
+
+ max--;
+ buf[max] = '\0';
+ digit = 1;
+
+ //
+ // If we are to do a signed operation, and the value is negative
+ // operate on its inverse, and prepend a '-' sign when complete.
+ //
+
+ if (signe && li.QuadPart < 0) {
+ li.QuadPart = li.QuadPart * -1;
+ needsign = TRUE;
+ }
+
+ if (li.HighPart)
+ sprintf(buf, "-%x%08x", li.HighPart, li.LowPart);
+ else
+ sprintf(buf, "-%x", li.LowPart);
+
+ if (needsign)
+ return buf;
+ else
+ return buf+1; // skip minus skip if not needed
+
+#if 0
+ //
+ // Starting with LSD, pull the digits out
+ // and put them in the string at the right end.
+ //
+ do {
+ remain.QuadPart = li.QuadPart - (li.QuadPart / radixli.QuadPart);
+ li.QuadPart = li.QuadPart / radixli.QuadPart;
+
+ //
+ // If remainder is > 9, then radix was 16, and
+ // we need to print A-E, else print 0-9.
+ //
+
+ if (remain.LowPart > 9) {
+ buf[max - digit++] = (char)('A' + remain.LowPart - 10);
+ } else {
+ buf[max - digit++] = (char)('0' + remain.LowPart);
+ }
+
+ } while ( li.LowPart || li.HighPart );
+
+ if (needsign) {
+ buf[max-digit++] = '-';
+ }
+
+ return(&buf[max-digit+1]);
+#endif
+}
+
+
+EESTATUS
+EEFormatMemory(
+ LPCH lpchTarget,
+ uint cchTarget,
+ LPBYTE lpbSource,
+ uint cBits,
+ FMTTYPE fmtType,
+ uint radix
+ )
+/*++
+
+Routine Description:
+
+ EEFormatMemory.
+
+ formats a value by template
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ long l;
+ long cb;
+ ULONG ul;
+ char rgch[512];
+
+
+ DASSERT (radix == 8 || radix == 10 || radix == 16 ||
+ (fmtType & fmtBasis) == fmtAscii ||
+ (fmtType & fmtBasis) == fmtUnicode);
+ DASSERT (cBits != 0);
+ DASSERT (cchTarget <= sizeof(rgch));
+
+ switch (fmtType & fmtBasis)
+ {
+ /*
+ ** Format from memory bytes into an integer format number
+ */
+ case fmtInt:
+
+ if (radix == 10) {
+
+ switch( (cBits + 7)/8 ) {
+ case 1:
+ l = *(signed char *)lpbSource;
+ if (fmtType & fmtZeroPad) {
+ sprintf(rgch, "%0*d", cchTarget-1, l);
+ } else {
+ sprintf(rgch, "% d", l);
+ }
+ break;
+
+ case 2:
+ l = *(short *)lpbSource;
+ if (fmtType & fmtZeroPad) {
+ sprintf(rgch, "%0*d", cchTarget-1, l);
+ } else {
+ sprintf(rgch, "% d", l);
+ }
+ break;
+
+ case 4:
+ l = *(long *)lpbSource;
+ if (fmtType & fmtZeroPad) {
+ sprintf(rgch, "%0*d", cchTarget-1, l);
+ } else {
+ sprintf(rgch, "% d", l);
+ }
+ break;
+
+ case 8:
+ {
+
+ char tbuf[100], *tbufp;
+
+ tbufp = LargeIntegerFormat(*(PLARGE_INTEGER)lpbSource,
+ radix,
+ TRUE,
+ tbuf,
+ 100);
+
+ if (!(fmtType & fmtZeroPad)) {
+ sprintf(rgch, "%s", tbufp);
+ } else if (*tbufp == '-') {
+ sprintf(rgch, "%-0*s", cchTarget - 2, tbufp+1);
+ } else {
+ sprintf(rgch, "%0*s", cchTarget - 1, tbufp);
+ }
+
+ break;
+
+ }
+
+ default:
+ return EEBADFORMAT;
+ }
+
+
+ if (strlen(rgch) >= cchTarget) {
+ return EEOVERRUN;
+ }
+
+ _fstrcpy(lpchTarget, rgch);
+
+ break;
+ }
+ /*
+ else
+ handle as UInt
+ */
+
+ case fmtUInt:
+
+ cb = (cBits + 7)/8;
+ switch( cb ) {
+ case 1:
+ ul = *(BYTE FAR *) lpbSource;
+ break;
+
+ case 2:
+ ul = *(USHORT FAR *) lpbSource;
+ break;
+
+ case 4:
+ ul = *(ULONG FAR *) lpbSource;
+ break;
+
+//
+// MBH - bugbug - CENTAUR bug;
+// putting contents of instead of address of structure
+// for return value in a0.
+//
+
+ case 8:
+ {
+ //
+ // Handle 64-bits out of band, since sprintf
+ // cannot handle it.
+ //
+
+ char tbuf[100], *tbufp;
+
+ tbufp = LargeIntegerFormat(*(PLARGE_INTEGER)lpbSource,
+ radix,
+ FALSE,
+ tbuf,
+ 100);
+
+ if (fmtType & fmtZeroPad) {
+ sprintf(rgch, "%0*s", cchTarget - 1, tbufp);
+ } else {
+ sprintf(rgch, "%s", tbufp);
+ }
+ _strlwr(rgch);
+
+ break;
+ }
+
+
+ default:
+ if (radix != 16 || (fmtType & fmtZeroPad) == 0) {
+ return EEBADFORMAT;
+ }
+ }
+
+ if (cb != 8) {
+
+
+ if (fmtType & fmtZeroPad) {
+ switch (radix) {
+ case 8:
+ sprintf(rgch, "%0*.*o", cchTarget-1, cchTarget-1, ul);
+ break;
+ case 10:
+ sprintf(rgch, "%0*.*u", cchTarget-1, cchTarget-1, ul);
+ break;
+ case 16:
+ // handle any size:
+ // NOTENOTE a-kentf this is dependent on byte order
+ for (l = 0; l < cb; l++) {
+ sprintf(rgch+l+l, "%02.2x", lpbSource[cb - l - 1]);
+ }
+ //sprintf(rgch, "%0*.*x", cchTarget-1, cchTarget-1, ul);
+ break;
+ }
+ } else {
+ switch (radix) {
+ case 8:
+ sprintf(rgch, "%o", ul);
+ break;
+ case 10:
+ sprintf(rgch, "%u", ul);
+ break;
+ case 16:
+ sprintf(rgch, "%x", ul);
+ break;
+ }
+ }
+
+
+ }
+
+ if (strlen(rgch) >= cchTarget) {
+ return EEOVERRUN;
+ }
+
+ _fstrcpy(lpchTarget, rgch);
+
+ break;
+
+
+ case fmtAscii:
+ if ( cBits != 8 ) {
+ return EEBADFORMAT;
+ }
+ lpchTarget[0] = *(BYTE FAR *) lpbSource;
+ if ((lpchTarget[0] < ' ') || (lpchTarget[0] > 0x7e)) {
+ lpchTarget[0] = '.';
+ }
+ lpchTarget[1] = 0;
+ return EENOERROR;
+
+ case fmtUnicode:
+ if (cBits != 16) {
+ return EEBADFORMAT;
+ }
+ DASSERT((uint)MB_CUR_MAX <= cchTarget);
+// DASSERT(cchTarget >= 2);
+ if ((wctomb(lpchTarget, *(LPWCH)lpbSource) == -1) ||
+ (lpchTarget[0] < ' ') ||
+ (lpchTarget[0] > 0x7e)) {
+ lpchTarget[0] = '.';
+ }
+ lpchTarget[1] = 0;
+ return EENOERROR;
+
+ case fmtFloat:
+ // NOTENOTE a-kentf doesn't currently handle fmtZeroPad
+ switch ( cBits ) {
+ case 4*8:
+ sprintf(rgch, "% 12.6e",*((float FAR *) lpbSource));
+ break;
+
+ case 8*8:
+// sprintf(rgch, "% 17.11le", *((double FAR *) lpbSource));
+ sprintf(rgch, "% 21.14le", *((double FAR *) lpbSource));
+ break;
+
+ case 10*8:
+ if (_uldtoa((_ULDOUBLE *)lpbSource, 25, rgch) == NULL) {
+ return EEBADFORMAT;
+ }
+ break;
+
+ case 16*8:
+ //NOTENOTE mips long doubles revert to ????....for now
+ _fstrcpy (rgch,"??????????????????????????????????????????");
+ break;
+
+ default:
+ return EEBADFORMAT;
+
+ }
+
+ if (strlen(rgch) >= cchTarget) {
+ return EEOVERRUN;
+ }
+
+ _fstrncpy(lpchTarget, rgch, cchTarget-1);
+ lpchTarget[cchTarget-1] = 0;
+ return EENOERROR;
+
+ case fmtAddress:
+ return EEBADFORMAT;
+
+ case fmtZeroPad:
+ return EEBADFORMAT;
+
+ }
+
+ return EENOERROR;
+} /* EEFormatMemory() */
+
+
+EESTATUS
+EEUnformatMemory(
+ LPBYTE lpbTarget,
+ LPSTR lpszSource,
+ uint cBits,
+ FMTTYPE fmtType,
+ uint radix
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+ ULARGE_INTEGER largeint;
+ ULONG l;
+ char *ptr = lpszSource;
+
+ switch ( fmtType & fmtBasis ) {
+ case fmtInt:
+ case fmtUInt:
+
+ DASSERT (radix == 8 || radix == 10 || radix == 16);
+
+ l = 0;
+
+ ptr = SkipWhitespace(ptr);
+
+ if ((fmtType & fmtOverRide) == 0)
+ {
+ if (*ptr == '0') {
+ // force radix - is it hex or octal?
+ ++ptr;
+ if (*ptr == 'x' || *ptr == 'X') {
+ ++ptr;
+ radix = 16;
+ } else if ((*ptr == 'o') || (*ptr == 'O')) {
+ radix = 8;
+ }
+ }
+ }
+
+ errno = 0;
+ largeint = (strtouli(ptr, &ptr, (int)radix));
+ l = largeint.LowPart;
+
+ if ((l == 0 || l == ULONG_MAX) && errno == ERANGE) {
+ return EEBADFORMAT;
+ }
+
+ if (cBits < 32 && l > range[cBits-1] ) {
+ return EEBADFORMAT;
+ }
+
+ if (*SkipWhitespace(ptr)) {
+ return EEBADFORMAT;
+ }
+
+ switch( (cBits + 7)/8 ) {
+ case 1:
+ *(BYTE FAR *) lpbTarget = (BYTE) l;
+ break;
+
+ case 2:
+ *(USHORT FAR *) lpbTarget = (USHORT) l;
+ break;
+
+ case 4:
+ *(ULONG FAR *) lpbTarget = l;
+ break;
+
+ case 8:
+ *(PULARGE_INTEGER)lpbTarget = largeint;
+ break;
+
+
+ default:
+ return EEBADFORMAT;
+ }
+ break;
+
+ case fmtFloat:
+ // radix is ALWAYS 10 in the world of floats
+ switch ( (cBits + 7)/8 ) {
+
+ case 4:
+ if (sscanf(lpszSource, "%f", (float *)lpbTarget) != 1) {
+ return EEBADFORMAT;
+ }
+ break;
+
+ case 8:
+ if (sscanf(lpszSource, "%lf", (double *)lpbTarget) != 1) {
+ return EEBADFORMAT;
+ }
+ break;
+
+ case 10:
+ // i = sscanf(lpszSource, "%Lf", (long double *)lpbTarget);
+ _atoldbl( (_ULDOUBLE *)lpbTarget, lpszSource );
+ break;
+
+ default:
+ return EEBADFORMAT;
+ }
+
+ break;
+
+ case fmtAscii:
+ case fmtUnicode:
+ case fmtAddress:
+ // these aren't handled here.
+ return EEBADFORMAT;
+ }
+ return EENOERROR;
+} /* EEUnformatMemory() */
+
+
+/*** EEFormatEnumerate
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+EESTATUS
+EEFormatEnumerate(
+ UINT iFmt,
+ LPUINT lpcBits,
+ LPUINT lpFmtType,
+ LPUINT lpRadix,
+ LPUINT lpFTwoFields,
+ LPUINT lpcchMax,
+ LPCH FAR * lplpszDesc
+)
+{
+ if (iFmt >= sizeof(RgFormats)/sizeof(struct format)) {
+ return (1); // M00BUG -- get an error code for here
+ }
+
+ *lpcBits = RgFormats[iFmt].cBits;
+ *lpFmtType = RgFormats[iFmt].fmtType;
+ *lpRadix = RgFormats[iFmt].radix;
+ *lpFTwoFields = RgFormats[iFmt].fTwoFields;
+ *lpcchMax = RgFormats[iFmt].cchMax;
+ if (lplpszDesc != NULL)
+ *lplpszDesc = &RgFormats[iFmt].lpszDescription[0];
+
+ return (EENOERROR);
+} /* EEFormatEnumerate() */
diff --git a/private/windbg/eecan/errors.h b/private/windbg/eecan/errors.h
new file mode 100644
index 000000000..8a6009315
--- /dev/null
+++ b/private/windbg/eecan/errors.h
@@ -0,0 +1,76 @@
+ERRDAT (ERR_NONE, "no error condition")
+// Note the ERR_EXCEPTION must be the first error message
+ERRDAT (ERR_EXCEPTION, "exception error executing user function")
+ERRDAT (ERR_PTRACE, "error accessing user memory")
+ERRDAT (ERR_INTERNAL, "internal error in expression evaluator")
+ERRDAT (ERR_SYNTAX, "syntax error")
+ERRDAT (ERR_OPNOTSUPP, "operator not supported")
+ERRDAT (ERR_MISSINGLP, "missing left parenthesis")
+ERRDAT (ERR_MISSINGRP, "missing right parenthesis")
+ERRDAT (ERR_MISSINGDQ, "missing double quotation mark (\") at end of string")
+ERRDAT (ERR_MISSINGSQ, "missing single quotation mark (') after character constant")
+ERRDAT (ERR_MISSINGLB, "missing left bracket")
+ERRDAT (ERR_MISSINGRB, "missing right bracket")
+ERRDAT (ERR_MISSINGLC, "missing left curly brace")
+ERRDAT (ERR_NOOPERATOR, "missing operator")
+ERRDAT (ERR_NOOPERAND, "missing operand")
+ERRDAT (ERR_TOOCOMPLEX, "expression too complex (stack overflow)")
+ERRDAT (ERR_CONSTANT, "constant too big")
+ERRDAT (ERR_UNKNOWNSYMBOL, "symbol not found")
+ERRDAT (ERR_BADREGISTER, "bad register name")
+ERRDAT (ERR_TYPECAST, "bad type cast")
+ERRDAT (ERR_OPERANDTYPES, "operand types bad for this operation")
+ERRDAT (ERR_STRUCT, "struct or union used as scalar")
+ERRDAT (ERR_FCNCALL, "function call before _main")
+ERRDAT (ERR_RADIX, "bad radix")
+ERRDAT (ERR_NEEDLVALUE, "operation needs l-value")
+ERRDAT (ERR_NEEDSTRUCT, "operator needs class/struct/union")
+ERRDAT (ERR_FORMAT, "bad format string")
+ERRDAT (ERR_NOTLVALUE, "tp addr not lvalue")
+ERRDAT (ERR_NOTELEMENT, "not struct/union element")
+ERRDAT (ERR_NOTSTRUCTPTR, "not struct pointer")
+ERRDAT (ERR_NOTEVALUATABLE, "expression cannot be evaluated")
+ERRDAT (ERR_NOTEXPANDABLE, "expression cannot be evaluated")
+ERRDAT (ERR_DIVIDEBYZERO, "divide by 0")
+ERRDAT (ERR_BADOMF, "error in OMF type information")
+ERRDAT (ERR_TYPEINCOMPAT, "types incompatable with operator")
+ERRDAT (ERR_NOTRESIDENT, "overlay not resident")
+ERRDAT (ERR_BADCONTEXT, "bad context {...} specification")
+ERRDAT (ERR_NOMEMORY, "out of memory")
+ERRDAT (ERR_FCNERROR, "function argument count and/or type mismatch")
+ERRDAT (ERR_AMBIGUOUS, "symbol is ambiguous")
+ERRDAT (ERR_CANTCONVERT, "function requires implicit conversion")
+ERRDAT (ERR_NOTSTATIC, "class element must be static member or member function")
+ERRDAT (ERR_BADLINE, "bad line number")
+ERRDAT (ERR_BADTHIS, "this pointer used outside of member function")
+ERRDAT (ERR_NEEDSBIRD, "use of _based(void) pointer requires :> operator")
+ERRDAT (ERR_NOTFCN, "not a function")
+ERRDAT (ERR_NOARGLIST, "argument list required for member function")
+ERRDAT (ERR_ARGLIST, "argument list does not match a function")
+ERRDAT (ERR_CALLSEQ, "calling sequence not supported")
+ERRDAT (ERR_OLDOMF, "obsolete OMF - please relink program")
+ERRDAT (ERR_BSCOPE, "left side of :: must be class/struct/union type")
+ERRDAT (ERR_BPAMBIGUOUS, "more than one overloaded symbol specified in breakpoint")
+ERRDAT (ERR_METHODNP, "member function not present")
+ERRDAT (ERR_SYMCONFLICT, "nonfunction symbol match while binding breakpoints")
+ERRDAT (ERR_REGINBP, "register in breakpoint expression illegal")
+ERRDAT (ERR_AMBCONTEXT, "ambiguous symbol in context operator")
+ERRDAT (ERR_LINENUMBER, "error in line number")
+ERRDAT (ERR_NOCODE, "no code at line number")
+ERRDAT (ERR_NOOVERLOAD, "overloaded operator not found")
+ERRDAT (ERR_CLASSNOTFCN, "left operand is class not a function name")
+ERRDAT (ERR_REGNOTAVAIL, "register is not available")
+ERRDAT (ERR_FCNTOODEEP, "function nesting depth exceeded")
+ERRDAT (ERR_CONSTRUCTOR, "constructor calls not supported")
+ERRDAT (ERR_OVLPOINTSTO, "overloaded operator -> not supported")
+ERRDAT (ERR_NOVIRTUALBP, "can't set breakpoint on bound virtual member function")
+ERRDAT (ERR_NOCLASSASSIGN, "class assignment not supported")
+ERRDAT (ERR_NOFLOATPARSE, "floating point constants NYI")
+ERRDAT (ERR_MIXTYPEANDVALUE, "cannot match types and arguments in a function call")
+ERRDAT (ERR_ADDROFREG, "cannot take the address of a register")
+ERRDAT (ERR_STATICNOOMF, "static member has no debug information")
+ERRDAT (ERR_NOMODIFIABLELV, "l-value is not modifiable")
+ERRDAT (ERR_INVENUMVAL, "Illegal Enum Value")
+ERRDAT (ERR_TYPESUPPORT, "type not supported")
+ERRDAT (ERR_NOSTACKFRAME, "variable needs stack frame")
+ERRDAT (ERR_STMEMBERNP, "static member not present")
diff --git a/private/windbg/eecan/expr2.z b/private/windbg/eecan/expr2.z
new file mode 100644
index 000000000..6813a784d
--- /dev/null
+++ b/private/windbg/eecan/expr2.z
@@ -0,0 +1,274 @@
+# This table represents a directed graph (in matrix form) used
+# to calculate operator precedence functions. For more information,
+# see Compilers: Principles, Techniques and Tools, by Aho, Sethi
+# and Ullman [Addison-Wesley], Section 4.6. A value of 1 in the
+# matrix indicates an edge from the row operator to the column operator.
+# A 1 in an F row and G column indicates that the row operator followed
+# by the column operator causes a reduce operation. A 0 indicates
+# a shift operation. A 1 in a G row and an F column indicates that a
+# row operator preceeded by the column operator causes a shift operation.
+# A 0 indicates a reduce operation.
+#
+# Note that the entries fx -> fy and gx -> gy are only present as
+# placeholders (to make the matrix easier to read in); these values
+# should always be zero.
+#
+# To use this table, first run it through the opprec program:
+#
+# opprec c expr2.z > debops.h for C version
+# opprec a expr2.z > debops.inc for asm version
+#
+# The output file then contains the precedence function
+# values in the form index:value, where index is the index of the
+# node in the order below and value is the precedence function value.
+#
+# The elements in the table below represent the following
+#
+# Element Group
+# Fi identifier, constant
+# F! !, ~, , ++, --, unary -, unary +, *(contents), &(address), ()(cast)
+# F-> ->, ., :(asm only)
+# F* *, /, %
+# F+ +, -,
+# F<< <<, >>
+# F< <, <=, >, >=
+# F== ==, !=
+# F& &
+# F^ ^
+# F| |
+# F&& &&
+# F|| ||
+# F= =, *=, /=, %=, +=, -=, <=, >=, &=, |=, ^=
+# Fby byte, word, double word (asm only)
+# F$ beginning of statement, end of statement
+#
+# F) f for end of grouping
+# F] f for end of subscript
+# G( g for beginning of grouping
+# G[ g for beginning of subscript
+# F(G) f for beginning of grouping OR g for end of subscript
+# F[G] f for beginning of subscript OR g for end of subscript
+#
+# The precedence functions are generated by matching the f value for an
+# element with the g value for the element. For example
+# f( * ) = F* and g( * ) = G*
+# The complications to this simple rule are:
+# f( ( ) = F(G) and g( ( ) = G(
+# f( ) ) = F) and g( ) ) = F(G)
+# f( [ ) = F[G] and g( [ ) = G[
+# f( ] ) = F] and g( ] ) = F[G]
+#
+
+OPC_null
+OPC_integral
+OPC_scalar
+OPC_arith
+OPC_ptr
+OPC_ptrint
+OPC_relat
+OPC_equiv
+OPC_plus
+OPC_minus
+END
+
+
+# Beginning of identifiers and constants
+# OP_hsym is a hack to allow a handle to symbol to be equivalent to an ident
+# OP_this through OP_Odelete are special symbols indicating to SearchSym
+# that the string pointers in the name structure do not point to the
+# expression string but that special strings must be pointed to.
+# OP_Odelete must be that last entry in this group. These nodes are
+# created on the fly during tree rewriting during binding and symbol
+# searching
+# OP_thisinit, OP_thisconst and OP_thisexpr are used to calculate
+# this pointer adjustments for virtual bases
+# The OP_noop is used to replace an overloaded operator by a pointer to
+# the function node. This way we can guarantee that replacement of
+# an existing node will not overwrite surrounding nodes
+
+Fi OP_endofargs OPC_null BindError EvalError
+Fi OP_ident OPC_null BindSymbol EvalPushNode
+Fi OP_grouped OPC_null BindError EvalError
+Fi OP_hsym OPC_null BindSymbol EvalPushNode
+Fi OP_this OPC_null BindSymbol EvalPushNode
+Fi OP_Opmember OPC_null BindSymbol EvalPushNode
+Fi OP_Orightequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oleftequal OPC_null BindSymbol EvalPushNode
+Fi OP_Ofunction OPC_null BindSymbol EvalPushNode
+Fi OP_Oarray OPC_null BindSymbol EvalPushNode
+Fi OP_Oplusequal OPC_null BindSymbol EvalPushNode
+Fi OP_Ominusequal OPC_null BindSymbol EvalPushNode
+Fi OP_Otimesequal OPC_null BindSymbol EvalPushNode
+Fi OP_Odivequal OPC_null BindSymbol EvalPushNode
+Fi OP_Opcentequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oandequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oxorequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oorequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oshl OPC_null BindSymbol EvalPushNode
+Fi OP_Oshr OPC_null BindSymbol EvalPushNode
+Fi OP_Oequalequal OPC_null BindSymbol EvalPushNode
+Fi OP_Obangequal OPC_null BindSymbol EvalPushNode
+Fi OP_Olessequal OPC_null BindSymbol EvalPushNode
+Fi OP_Ogreatequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oandand OPC_null BindSymbol EvalPushNode
+Fi OP_Ooror OPC_null BindSymbol EvalPushNode
+Fi OP_Oincrement OPC_null BindSymbol EvalPushNode
+Fi OP_Odecrement OPC_null BindSymbol EvalPushNode
+Fi OP_Opointsto OPC_null BindSymbol EvalPushNode
+Fi OP_Oplus OPC_null BindSymbol EvalPushNode
+Fi OP_Ominus OPC_null BindSymbol EvalPushNode
+Fi OP_Ostar OPC_null BindSymbol EvalPushNode
+Fi OP_Odivide OPC_null BindSymbol EvalPushNode
+Fi OP_Opercent OPC_null BindSymbol EvalPushNode
+Fi OP_Oxor OPC_null BindSymbol EvalPushNode
+Fi OP_Oand OPC_null BindSymbol EvalPushNode
+Fi OP_Oor OPC_null BindSymbol EvalPushNode
+Fi OP_Otilde OPC_null BindSymbol EvalPushNode
+Fi OP_Obang OPC_null BindSymbol EvalPushNode
+Fi OP_Oequal OPC_null BindSymbol EvalPushNode
+Fi OP_Oless OPC_null BindSymbol EvalPushNode
+Fi OP_Ogreater OPC_null BindSymbol EvalPushNode
+Fi OP_Ocomma OPC_null BindSymbol EvalPushNode
+Fi OP_Onew OPC_null BindSymbol EvalPushNode
+Fi OP_Odelete OPC_null BindSymbol EvalPushNode
+Fi OP_typestr OPC_null BindTRUE EvalError
+Fi OP_const OPC_null BindConst EvalPushNode
+Fi OP_thisinit OPC_null BindError EvalThisInit
+Fi OP_thisconst OPC_null BindError EvalThisConst
+Fi OP_thisexpr OPC_null BindError EvalThisExpr
+Fi OP_noop OPC_null BindError EvalLChild
+
+# End of identifiers and constants
+# Beginning of grouping operators
+
+F( OP_lparen OPC_null BindError EvalError
+F) OP_rparen OPC_null BindError EvalError
+F( OP_lcurly OPC_null BindError EvalError
+F) OP_rcurly OPC_null BindError EvalError
+
+# End of grouping operators
+# Beginning of unary operators (OP_bang must be first)
+# Note: the OP_incr and OP_decr will be changed into pre or post operators
+# the first time they are seen
+
+F! OP_bang OPC_scalar BindBang EvalBang
+F! OP_tilde OPC_integral BindUnary EvalUnary
+F! OP_negate OPC_arith BindUnary EvalUnary
+F! OP_uplus OPC_arith BindUnary EvalUnary
+F! OP_fetch OPC_ptr BindFetch EvalFetch
+F! OP_addrof OPC_null BindAddrOf EvalAddrOf
+F! OP_sizeof OPC_null BindSizeOf EvalPushNode
+F! OP_incr OPC_null BindError EvalError
+F! OP_decr OPC_null BindError EvalError
+F! OP_preinc OPC_null BindPreIncDec EvalPreIncDec
+F! OP_predec OPC_null BindPreIncDec EvalPreIncDec
+F! OP_postinc OPC_null BindPostIncDec EvalPostIncDec
+F! OP_postdec OPC_null BindPostIncDec EvalPostIncDec
+F:: OP_uscope OPC_null BindUScope EvalUScope
+Fby OP_by OPC_null BindByteOps EvalByteOps
+Fby OP_wo OPC_null BindByteOps EvalByteOps
+Fby OP_dw OPC_null BindByteOps EvalByteOps
+F! OP_context OPC_null BindContext EvalContext
+
+# End of unary operators (OP_context must be last)
+
+# OP_cast is really unary but is faked to look like a function call
+# in debparse.c and debtree.c
+
+F[ OP_function OPC_null BindFunction EvalFunction
+F! OP_cast OPC_null BindCast EvalCast
+Fa OP_arg OPC_null BindError EvalError
+F:: OP_bscope OPC_null BindBScope EvalBScope
+F] OP_fcnend OPC_null BindError EvalError
+F[ OP_lbrack OPC_ptrint BindArray EvalArray
+F] OP_rbrack OPC_null BindError EvalError
+F-> OP_pointsto OPC_null BindPointsTo EvalPointsTo
+F-> OP_dot OPC_null BindDot EvalDot
+F-> OP_segop OPC_integral BindSegOp EvalSegOp
+F-> OP_baseptr OPC_null BindBasePtr EvalBasePtr
+F.* OP_pmember OPC_null BindPMember EvalPMember
+F.* OP_dotmember OPC_null BindDMember EvalDMember
+F* OP_mult OPC_arith BindBinary EvalBinary
+F* OP_div OPC_arith BindBinary EvalBinary
+F* OP_mod OPC_integral BindBinary EvalBinary
+F+ OP_plus OPC_plus BindPlusMinus EvalPlusMinus
+F+ OP_minus OPC_minus BindPlusMinus EvalPlusMinus
+F<< OP_shl OPC_integral BindBinary EvalBinary
+F<< OP_shr OPC_integral BindBinary EvalBinary
+F< OP_lt OPC_relat BindRelat EvalRelat
+F< OP_lteq OPC_relat BindRelat EvalRelat
+F< OP_gt OPC_relat BindRelat EvalRelat
+F< OP_gteq OPC_relat BindRelat EvalRelat
+F== OP_eqeq OPC_equiv BindRelat EvalRelat
+F== OP_bangeq OPC_equiv BindRelat EvalRelat
+F& OP_and OPC_integral BindBinary EvalBinary
+F^ OP_xor OPC_integral BindBinary EvalBinary
+F| OP_or OPC_integral BindBinary EvalBinary
+F&& OP_andand OPC_scalar BindBinary EvalLogical
+F|| OP_oror OPC_scalar BindBinary EvalLogical
+F= OP_eq OPC_null BindAssign EvalAssign
+F= OP_multeq OPC_null BindAssign EvalAssign
+F= OP_diveq OPC_null BindAssign EvalAssign
+F= OP_modeq OPC_null BindAssign EvalAssign
+F= OP_pluseq OPC_null BindAssign EvalAssign
+F= OP_minuseq OPC_null BindAssign EvalAssign
+F= OP_shleq OPC_null BindAssign EvalAssign
+F= OP_shreq OPC_null BindAssign EvalAssign
+F= OP_andeq OPC_null BindAssign EvalAssign
+F= OP_xoreq OPC_null BindAssign EvalAssign
+F= OP_oreq OPC_null BindAssign EvalAssign
+F$ OP_lowprec OPC_null BindError EvalError
+F$ OP_comma OPC_null BindError EvalError
+
+END
+
+# Dimension of matrix
+
+44
+
+# F F F F F F F F F F F F F F F F F F F F F G G G G G G G G G G G G G G G G G G G G FG FG G
+# i :: ) ] -> ! .* * + << < == & ^ | && || = by $ a i :: ( [ -> ! .* * + << < == & ^ | && || = by $ () [] a
+Fi 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F:: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F-> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F! 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F.* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F<< 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+F< 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
+F== 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1
+F& 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
+F^ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
+F| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1
+F&& 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
+F|| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
+F= 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
+Fby 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
+F$ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+Fa 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
+Gi 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+G:: 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+G( 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G[ 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G-> 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G! 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G.* 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G* 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G+ 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G<< 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G< 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G== 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G& 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G^ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G&& 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G|| 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G= 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+Gby 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+G$ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+F(G) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+F[G] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+Ga 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
diff --git a/private/windbg/eecan/fmtstr.h b/private/windbg/eecan/fmtstr.h
new file mode 100644
index 000000000..151a42a68
--- /dev/null
+++ b/private/windbg/eecan/fmtstr.h
@@ -0,0 +1,141 @@
+FMTSTR (str001, T_ABS, 0, 9, "absolute ")
+FMTSTR (str002, T_NOTYPE, 0, 10, "<no type> ")
+FMTSTR (str003, T_SEGMENT, 0, 9, "_segment ")
+
+FMTSTR (str010, T_CHAR, CV_TM_DIRECT, 5, "char ")
+FMTSTR (str011, T_SHORT, CV_TM_DIRECT, 6, "short ")
+FMTSTR (str012, T_LONG, CV_TM_DIRECT, 5, "long ")
+FMTSTR (str013, T_QUAD, CV_TM_DIRECT, 5, "quad ")
+FMTSTR (str014, T_UCHAR, CV_TM_DIRECT, 14, "unsigned char ")
+FMTSTR (str015, T_USHORT, CV_TM_DIRECT, 15, "unsigned short ")
+FMTSTR (str016, T_ULONG, CV_TM_DIRECT, 14, "unsigned long ")
+FMTSTR (str017, T_UQUAD, CV_TM_DIRECT, 14, "unsigned quad ")
+FMTSTR (str018, T_REAL32, CV_TM_DIRECT, 6, "float ")
+FMTSTR (str019, T_REAL64, CV_TM_DIRECT, 7, "double ")
+FMTSTR (str020, T_REAL80, CV_TM_DIRECT, 12, "long double ")
+FMTSTR (str021, T_VOID, CV_TM_DIRECT, 5, "void ")
+FMTSTR (str022, T_INT2, CV_TM_DIRECT, 4, "int ")
+FMTSTR (str023, T_UINT2, CV_TM_DIRECT, 13, "unsigned int ")
+FMTSTR (str024, T_INT4, CV_TM_DIRECT, 4, "int ")
+FMTSTR (str025, T_UINT4, CV_TM_DIRECT, 13, "unsigned int ")
+FMTSTR (str026, T_INT8, CV_TM_DIRECT, 4, "int ")
+FMTSTR (str027, T_UINT8, CV_TM_DIRECT, 13, "unsigned int ")
+FMTSTR (str028, T_RCHAR, CV_TM_DIRECT, 5, "char ")
+
+FMTSTR (str030, T_CHAR, CV_TM_NPTR, 7, "char * ")
+FMTSTR (str031, T_SHORT, CV_TM_NPTR, 8, "short * ")
+FMTSTR (str032, T_LONG, CV_TM_NPTR, 7, "long * ")
+FMTSTR (str033, T_QUAD, CV_TM_NPTR, 7, "quad * ")
+FMTSTR (str034, T_UCHAR, CV_TM_NPTR, 16, "unsigned char * ")
+FMTSTR (str035, T_USHORT, CV_TM_NPTR, 17, "unsigned short * ")
+FMTSTR (str036, T_ULONG, CV_TM_NPTR, 16, "unsigned long * ")
+FMTSTR (str037, T_UQUAD, CV_TM_NPTR, 16, "unsigned quad * ")
+FMTSTR (str038, T_REAL32, CV_TM_NPTR, 8, "float * ")
+FMTSTR (str039, T_REAL64, CV_TM_NPTR, 9, "double * ")
+FMTSTR (str040, T_REAL80, CV_TM_NPTR, 14, "long double * ")
+FMTSTR (str041, T_VOID, CV_TM_NPTR, 7, "void * ")
+FMTSTR (str042, T_INT2, CV_TM_NPTR, 6, "int * ")
+FMTSTR (str043, T_UINT2, CV_TM_NPTR, 15, "unsigned int * ")
+FMTSTR (str044, T_INT4, CV_TM_NPTR, 6, "int * ")
+FMTSTR (str045, T_UINT4, CV_TM_NPTR, 15, "unsigned int * ")
+FMTSTR (str046, T_INT8, CV_TM_NPTR, 6, "int * ")
+FMTSTR (str047, T_UINT8, CV_TM_NPTR, 15, "unsigned int * ")
+FMTSTR (str048, T_RCHAR, CV_TM_NPTR, 7, "char * ")
+
+FMTSTR (str050, T_CHAR, CV_TM_FPTR, 11, "char far * ")
+FMTSTR (str051, T_SHORT, CV_TM_FPTR, 12, "short far * ")
+FMTSTR (str052, T_LONG, CV_TM_FPTR, 11, "long far * ")
+FMTSTR (str053, T_QUAD, CV_TM_FPTR, 11, "quad far * ")
+FMTSTR (str054, T_UCHAR, CV_TM_FPTR, 20, "unsigned char far * ")
+FMTSTR (str055, T_USHORT, CV_TM_FPTR, 21, "unsigned short far * ")
+FMTSTR (str056, T_ULONG, CV_TM_FPTR, 20, "unsigned long far * ")
+FMTSTR (str057, T_UQUAD, CV_TM_FPTR, 20, "unsigned quad far * ")
+FMTSTR (str058, T_REAL32, CV_TM_FPTR, 12, "float far * ")
+FMTSTR (str059, T_REAL64, CV_TM_FPTR, 13, "double far * ")
+FMTSTR (str060, T_REAL80, CV_TM_FPTR, 18, "long double far * ")
+FMTSTR (str061, T_VOID, CV_TM_FPTR, 11, "void far * ")
+FMTSTR (str062, T_INT2, CV_TM_FPTR, 10, "int far * ")
+FMTSTR (str063, T_UINT2, CV_TM_FPTR, 19, "unsigned int far * ")
+FMTSTR (str064, T_INT4, CV_TM_FPTR, 10, "int far * ")
+FMTSTR (str065, T_UINT4, CV_TM_FPTR, 19, "unsigned int far * ")
+FMTSTR (str066, T_INT8, CV_TM_FPTR, 10, "int far * ")
+FMTSTR (str067, T_UINT8, CV_TM_FPTR, 19, "unsigned int far * ")
+FMTSTR (str068, T_RCHAR, CV_TM_FPTR, 11, "char far * ")
+
+FMTSTR (str070, T_CHAR, CV_TM_HPTR, 11, "char huge * ")
+FMTSTR (str071, T_SHORT, CV_TM_HPTR, 13, "short huge * ")
+FMTSTR (str072, T_LONG, CV_TM_HPTR, 12, "long huge * ")
+FMTSTR (str073, T_QUAD, CV_TM_HPTR, 12, "quad huge * ")
+FMTSTR (str074, T_UCHAR, CV_TM_HPTR, 21, "unsigned char huge * ")
+FMTSTR (str075, T_USHORT, CV_TM_HPTR, 22, "unsigned short huge * ")
+FMTSTR (str076, T_ULONG, CV_TM_HPTR, 21, "unsigned long huge * ")
+FMTSTR (str077, T_UQUAD, CV_TM_HPTR, 21, "unsigned quad huge * ")
+FMTSTR (str078, T_REAL32, CV_TM_HPTR, 13, "float huge * ")
+FMTSTR (str079, T_REAL64, CV_TM_HPTR, 14, "double huge * ")
+FMTSTR (str080, T_REAL80, CV_TM_HPTR, 19, "long double huge * ")
+FMTSTR (str081, T_VOID, CV_TM_HPTR, 12, "void huge * ")
+FMTSTR (str082, T_INT2, CV_TM_HPTR, 11, "int huge * ")
+FMTSTR (str083, T_UINT2, CV_TM_HPTR, 20, "unsigned int huge * ")
+FMTSTR (str084, T_INT4, CV_TM_HPTR, 11, "int huge * ")
+FMTSTR (str085, T_UINT4, CV_TM_HPTR, 20, "unsigned int huge * ")
+FMTSTR (str086, T_INT8, CV_TM_HPTR, 11, "int huge * ")
+FMTSTR (str087, T_UINT8, CV_TM_HPTR, 20, "unsigned int huge * ")
+FMTSTR (str088, T_RCHAR, CV_TM_HPTR, 12, "char huge * ")
+
+FMTSTR (str090, T_CHAR, CV_TM_NPTR32, 7, "char * ")
+FMTSTR (str091, T_SHORT, CV_TM_NPTR32, 8, "short * ")
+FMTSTR (str092, T_LONG, CV_TM_NPTR32, 7, "long * ")
+FMTSTR (str093, T_QUAD, CV_TM_NPTR32, 7, "quad * ")
+FMTSTR (str094, T_UCHAR, CV_TM_NPTR32, 16, "unsigned char * ")
+FMTSTR (str095, T_USHORT, CV_TM_NPTR32, 17, "unsigned short * ")
+FMTSTR (str096, T_ULONG, CV_TM_NPTR32, 16, "unsigned long * ")
+FMTSTR (str097, T_UQUAD, CV_TM_NPTR32, 16, "unsigned quad * ")
+FMTSTR (str098, T_REAL32, CV_TM_NPTR32, 8, "float * ")
+FMTSTR (str099, T_REAL64, CV_TM_NPTR32, 9, "double * ")
+FMTSTR (str100, T_REAL80, CV_TM_NPTR32, 14, "long double * ")
+FMTSTR (str101, T_VOID, CV_TM_NPTR32, 7, "void * ")
+FMTSTR (str102, T_INT2, CV_TM_NPTR32, 6, "int * ")
+FMTSTR (str103, T_UINT2, CV_TM_NPTR32, 15, "unsigned int * ")
+FMTSTR (str104, T_INT4, CV_TM_NPTR32, 6, "int * ")
+FMTSTR (str105, T_UINT4, CV_TM_NPTR32, 15, "unsigned int * ")
+FMTSTR (str106, T_INT8, CV_TM_NPTR32, 6, "int * ")
+FMTSTR (str107, T_UINT8, CV_TM_NPTR32, 15, "unsigned int * ")
+FMTSTR (str108, T_RCHAR, CV_TM_NPTR32, 7, "char * ")
+
+FMTSTR (str110, T_CHAR, CV_TM_FPTR32, 13, "char far32 * ")
+FMTSTR (str111, T_SHORT, CV_TM_FPTR32, 14, "short far32 * ")
+FMTSTR (str112, T_LONG, CV_TM_FPTR32, 13, "long far32 * ")
+FMTSTR (str113, T_QUAD, CV_TM_FPTR32, 13, "quad far32 * ")
+FMTSTR (str114, T_UCHAR, CV_TM_FPTR32, 22, "unsigned char far32 * ")
+FMTSTR (str115, T_USHORT, CV_TM_FPTR32, 23, "unsigned short far32 * ")
+FMTSTR (str116, T_ULONG, CV_TM_FPTR32, 22, "unsigned long far32 * ")
+FMTSTR (str117, T_UQUAD, CV_TM_FPTR32, 22, "unsigned quad far32 * ")
+FMTSTR (str118, T_REAL32, CV_TM_FPTR32, 14, "float far32 * ")
+FMTSTR (str119, T_REAL64, CV_TM_FPTR32, 15, "double far32 * ")
+FMTSTR (str120, T_REAL80, CV_TM_FPTR32, 20, "long double far32 * ")
+FMTSTR (str121, T_VOID, CV_TM_FPTR32, 13, "void far32 * ")
+FMTSTR (str122, T_INT2, CV_TM_FPTR32, 12, "int far32 * ")
+FMTSTR (str123, T_UINT2, CV_TM_FPTR32, 21, "unsigned int far32 * ")
+FMTSTR (str124, T_INT4, CV_TM_FPTR32, 12, "int far32 * ")
+FMTSTR (str125, T_UINT4, CV_TM_FPTR32, 21, "unsigned int far32 * ")
+FMTSTR (str126, T_INT8, CV_TM_FPTR32, 12, "int far32 * ")
+FMTSTR (str127, T_UINT8, CV_TM_FPTR32, 21, "unsigned int far32 * ")
+FMTSTR (str128, T_RCHAR, CV_TM_FPTR32, 13, "char far32 * ")
+
+FMTSTR (str150, 0xffff, 0, 3, "???")
+
+
+PTRNAME (str200, "\x007""near * ")
+PTRNAME (str201, "\x006""far * ")
+PTRNAME (str202, "\x007""huge * ")
+PTRNAME (str203, "\x00c""based seg * ")
+PTRNAME (str204, "\x00c""based val * ")
+PTRNAME (str205, "\x00f""based segval * ")
+PTRNAME (str206, "\x00d""based addr * ")
+PTRNAME (str207, "\x010""based segaddr * ")
+PTRNAME (str208, "\x00d""based type * ")
+PTRNAME (str209, "\x00d""based self * ")
+PTRNAME (str210, "\x002""* ")
+PTRNAME (str211, "\x008""far32 * ")
+PTRNAME (str212, "\x002""& ")
+
diff --git a/private/windbg/eecan/p_alpha/debapi.c b/private/windbg/eecan/p_alpha/debapi.c
new file mode 100644
index 000000000..20a8aa47f
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debapi.c"
diff --git a/private/windbg/eecan/p_alpha/debbind.c b/private/windbg/eecan/p_alpha/debbind.c
new file mode 100644
index 000000000..de18178de
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debbind.c"
diff --git a/private/windbg/eecan/p_alpha/deberr.c b/private/windbg/eecan/p_alpha/deberr.c
new file mode 100644
index 000000000..9117022b2
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deberr.c"
diff --git a/private/windbg/eecan/p_alpha/debeval.c b/private/windbg/eecan/p_alpha/debeval.c
new file mode 100644
index 000000000..f9d03e64f
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debeval.c"
diff --git a/private/windbg/eecan/p_alpha/debfmt.c b/private/windbg/eecan/p_alpha/debfmt.c
new file mode 100644
index 000000000..b6be2d176
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debfmt.c"
diff --git a/private/windbg/eecan/p_alpha/deblex.c b/private/windbg/eecan/p_alpha/deblex.c
new file mode 100644
index 000000000..192353c67
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblex.c"
diff --git a/private/windbg/eecan/p_alpha/deblexer.c b/private/windbg/eecan/p_alpha/deblexer.c
new file mode 100644
index 000000000..758b7e259
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblexer.c"
diff --git a/private/windbg/eecan/p_alpha/debparse.c b/private/windbg/eecan/p_alpha/debparse.c
new file mode 100644
index 000000000..94ae0d2a0
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debparse.c"
diff --git a/private/windbg/eecan/p_alpha/debsrch.c b/private/windbg/eecan/p_alpha/debsrch.c
new file mode 100644
index 000000000..b8c920b5e
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsrch.c"
diff --git a/private/windbg/eecan/p_alpha/debsup.c b/private/windbg/eecan/p_alpha/debsup.c
new file mode 100644
index 000000000..76c44b83a
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsup.c"
diff --git a/private/windbg/eecan/p_alpha/debsym.c b/private/windbg/eecan/p_alpha/debsym.c
new file mode 100644
index 000000000..b4994c7fd
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsym.c"
diff --git a/private/windbg/eecan/p_alpha/debtree.c b/private/windbg/eecan/p_alpha/debtree.c
new file mode 100644
index 000000000..9d9393139
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtree.c"
diff --git a/private/windbg/eecan/p_alpha/debtyper.c b/private/windbg/eecan/p_alpha/debtyper.c
new file mode 100644
index 000000000..3eacb04d0
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtyper.c"
diff --git a/private/windbg/eecan/p_alpha/debutil.c b/private/windbg/eecan/p_alpha/debutil.c
new file mode 100644
index 000000000..ec1b146d9
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debutil.c"
diff --git a/private/windbg/eecan/p_alpha/debwalk.c b/private/windbg/eecan/p_alpha/debwalk.c
new file mode 100644
index 000000000..5223d15f1
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debwalk.c"
diff --git a/private/windbg/eecan/p_alpha/eecan.rc b/private/windbg/eecan/p_alpha/eecan.rc
new file mode 100644
index 000000000..a50f7f4b5
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/eecan.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (ANSI C) for WinDbg"
+#define VER_INTERNALNAME_STR "eecan.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecan.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecan/p_alpha/eecanalp.def b/private/windbg/eecan/p_alpha/eecanalp.def
new file mode 100644
index 000000000..becebbbce
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/eecanalp.def
@@ -0,0 +1,4 @@
+LIBRARY eecanalp initinstance
+EXPORTS
+ EEInitializeExpr
+ WINDBGVersionCheck
diff --git a/private/windbg/eecan/p_alpha/eeformat.c b/private/windbg/eecan/p_alpha/eeformat.c
new file mode 100644
index 000000000..f95f10b27
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\eeformat.c"
diff --git a/private/windbg/eecan/p_alpha/makefile b/private/windbg/eecan/p_alpha/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecan/p_alpha/makefile.inc b/private/windbg/eecan/p_alpha/makefile.inc
new file mode 100644
index 000000000..7b84e5e01
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+# SRCDIR=..\..\eecan
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecan/p_alpha/precomp.h b/private/windbg/eecan/p_alpha/precomp.h
new file mode 100644
index 000000000..2d67ed312
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/precomp.h
@@ -0,0 +1,57 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.h"
+#include "cvinfo.h"
+#include "shapi.h"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "dbgver.h"
+#include "debsym.h"
+#include <limits.h>
+#include "cv.h"
+#include <errno.h>
+#include "cp.h"
+
diff --git a/private/windbg/eecan/p_alpha/r10math.c b/private/windbg/eecan/p_alpha/r10math.c
new file mode 100644
index 000000000..3c6c7cb26
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\r10math.c"
diff --git a/private/windbg/eecan/p_alpha/sources b/private/windbg/eecan/p_alpha/sources
new file mode 100644
index 000000000..a1ea86c1a
--- /dev/null
+++ b/private/windbg/eecan/p_alpha/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecanalp
+
+TARGETNAME=eecanalp
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecan.rc
+
+UMTYPE=windows
+
+TARGETLIBS=..\..\real10\obj\*\real10.lib ..\..\lib\obj\*\lilib.lib
+
+MIPS_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_MIPS -DTARGET_ALPHA
+386_FLAGS=-DNO_STRICT -DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_i386 -DTARGET_ALPHA
+ALPHA_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_ALPHA -DTARGET_ALPHA
+PPC_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_PPC -DTARGET_ALPHA
+
+MS_MIPS=1
+386_WARNING_LEVEL=/WX /W3
+
+LINKER_FLAGS=-ignore:505
+386_WARNING_LEVEL=/WX
+USE_CRTDLL=1
+INCLUDES=..\..\osdebug\include;..;..\..\lib;..\..\real10
+LIBRARIES=obj\*\eecan.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecan/p_i386/debapi.c b/private/windbg/eecan/p_i386/debapi.c
new file mode 100644
index 000000000..20a8aa47f
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debapi.c"
diff --git a/private/windbg/eecan/p_i386/debbind.c b/private/windbg/eecan/p_i386/debbind.c
new file mode 100644
index 000000000..de18178de
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debbind.c"
diff --git a/private/windbg/eecan/p_i386/deberr.c b/private/windbg/eecan/p_i386/deberr.c
new file mode 100644
index 000000000..9117022b2
--- /dev/null
+++ b/private/windbg/eecan/p_i386/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deberr.c"
diff --git a/private/windbg/eecan/p_i386/debeval.c b/private/windbg/eecan/p_i386/debeval.c
new file mode 100644
index 000000000..f9d03e64f
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debeval.c"
diff --git a/private/windbg/eecan/p_i386/debfmt.c b/private/windbg/eecan/p_i386/debfmt.c
new file mode 100644
index 000000000..b6be2d176
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debfmt.c"
diff --git a/private/windbg/eecan/p_i386/deblex.c b/private/windbg/eecan/p_i386/deblex.c
new file mode 100644
index 000000000..192353c67
--- /dev/null
+++ b/private/windbg/eecan/p_i386/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblex.c"
diff --git a/private/windbg/eecan/p_i386/deblexer.c b/private/windbg/eecan/p_i386/deblexer.c
new file mode 100644
index 000000000..758b7e259
--- /dev/null
+++ b/private/windbg/eecan/p_i386/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblexer.c"
diff --git a/private/windbg/eecan/p_i386/debparse.c b/private/windbg/eecan/p_i386/debparse.c
new file mode 100644
index 000000000..94ae0d2a0
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debparse.c"
diff --git a/private/windbg/eecan/p_i386/debsrch.c b/private/windbg/eecan/p_i386/debsrch.c
new file mode 100644
index 000000000..b8c920b5e
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsrch.c"
diff --git a/private/windbg/eecan/p_i386/debsup.c b/private/windbg/eecan/p_i386/debsup.c
new file mode 100644
index 000000000..76c44b83a
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsup.c"
diff --git a/private/windbg/eecan/p_i386/debsym.c b/private/windbg/eecan/p_i386/debsym.c
new file mode 100644
index 000000000..b4994c7fd
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsym.c"
diff --git a/private/windbg/eecan/p_i386/debtree.c b/private/windbg/eecan/p_i386/debtree.c
new file mode 100644
index 000000000..9d9393139
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtree.c"
diff --git a/private/windbg/eecan/p_i386/debtyper.c b/private/windbg/eecan/p_i386/debtyper.c
new file mode 100644
index 000000000..3eacb04d0
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtyper.c"
diff --git a/private/windbg/eecan/p_i386/debutil.c b/private/windbg/eecan/p_i386/debutil.c
new file mode 100644
index 000000000..ec1b146d9
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debutil.c"
diff --git a/private/windbg/eecan/p_i386/debwalk.c b/private/windbg/eecan/p_i386/debwalk.c
new file mode 100644
index 000000000..5223d15f1
--- /dev/null
+++ b/private/windbg/eecan/p_i386/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debwalk.c"
diff --git a/private/windbg/eecan/p_i386/eecan.rc b/private/windbg/eecan/p_i386/eecan.rc
new file mode 100644
index 000000000..a50f7f4b5
--- /dev/null
+++ b/private/windbg/eecan/p_i386/eecan.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (ANSI C) for WinDbg"
+#define VER_INTERNALNAME_STR "eecan.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecan.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecan/p_i386/eecanx86.def b/private/windbg/eecan/p_i386/eecanx86.def
new file mode 100644
index 000000000..178c7208e
--- /dev/null
+++ b/private/windbg/eecan/p_i386/eecanx86.def
@@ -0,0 +1,4 @@
+LIBRARY eecanx86 initinstance
+EXPORTS
+ EEInitializeExpr
+ WINDBGVersionCheck
diff --git a/private/windbg/eecan/p_i386/eeformat.c b/private/windbg/eecan/p_i386/eeformat.c
new file mode 100644
index 000000000..f95f10b27
--- /dev/null
+++ b/private/windbg/eecan/p_i386/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\eeformat.c"
diff --git a/private/windbg/eecan/p_i386/makefile b/private/windbg/eecan/p_i386/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecan/p_i386/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecan/p_i386/makefile.inc b/private/windbg/eecan/p_i386/makefile.inc
new file mode 100644
index 000000000..7b84e5e01
--- /dev/null
+++ b/private/windbg/eecan/p_i386/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+# SRCDIR=..\..\eecan
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecan/p_i386/precomp.h b/private/windbg/eecan/p_i386/precomp.h
new file mode 100644
index 000000000..2d67ed312
--- /dev/null
+++ b/private/windbg/eecan/p_i386/precomp.h
@@ -0,0 +1,57 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.h"
+#include "cvinfo.h"
+#include "shapi.h"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "dbgver.h"
+#include "debsym.h"
+#include <limits.h>
+#include "cv.h"
+#include <errno.h>
+#include "cp.h"
+
diff --git a/private/windbg/eecan/p_i386/r10math.c b/private/windbg/eecan/p_i386/r10math.c
new file mode 100644
index 000000000..3c6c7cb26
--- /dev/null
+++ b/private/windbg/eecan/p_i386/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\r10math.c"
diff --git a/private/windbg/eecan/p_i386/sources b/private/windbg/eecan/p_i386/sources
new file mode 100644
index 000000000..e4bd6d1ce
--- /dev/null
+++ b/private/windbg/eecan/p_i386/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecanx86
+
+TARGETNAME=eecanx86
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecan.rc
+
+UMTYPE=windows
+
+TARGETLIBS=..\..\real10\obj\*\real10.lib ..\..\lib\obj\*\lilib.lib
+
+MIPS_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_MIPS -DTARGET_i386
+386_FLAGS=-DNO_STRICT -DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_i386 -DTARGET_i386
+ALPHA_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_ALPHA -DTARGET_i386
+PPC_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_PPC -DTARGET_i386
+
+MS_MIPS=1
+
+LINKER_FLAGS=-ignore:505
+386_WARNING_LEVEL=/WX /W3
+
+USE_CRTDLL=1
+INCLUDES=..\..\osdebug\include;..;..\..\lib;..\..\real10
+LIBRARIES=obj\*\eecan.lib;
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecan/p_mips/debapi.c b/private/windbg/eecan/p_mips/debapi.c
new file mode 100644
index 000000000..20a8aa47f
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debapi.c"
diff --git a/private/windbg/eecan/p_mips/debbind.c b/private/windbg/eecan/p_mips/debbind.c
new file mode 100644
index 000000000..de18178de
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debbind.c"
diff --git a/private/windbg/eecan/p_mips/deberr.c b/private/windbg/eecan/p_mips/deberr.c
new file mode 100644
index 000000000..9117022b2
--- /dev/null
+++ b/private/windbg/eecan/p_mips/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deberr.c"
diff --git a/private/windbg/eecan/p_mips/debeval.c b/private/windbg/eecan/p_mips/debeval.c
new file mode 100644
index 000000000..f9d03e64f
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debeval.c"
diff --git a/private/windbg/eecan/p_mips/debfmt.c b/private/windbg/eecan/p_mips/debfmt.c
new file mode 100644
index 000000000..b6be2d176
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debfmt.c"
diff --git a/private/windbg/eecan/p_mips/deblex.c b/private/windbg/eecan/p_mips/deblex.c
new file mode 100644
index 000000000..192353c67
--- /dev/null
+++ b/private/windbg/eecan/p_mips/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblex.c"
diff --git a/private/windbg/eecan/p_mips/deblexer.c b/private/windbg/eecan/p_mips/deblexer.c
new file mode 100644
index 000000000..758b7e259
--- /dev/null
+++ b/private/windbg/eecan/p_mips/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblexer.c"
diff --git a/private/windbg/eecan/p_mips/debparse.c b/private/windbg/eecan/p_mips/debparse.c
new file mode 100644
index 000000000..94ae0d2a0
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debparse.c"
diff --git a/private/windbg/eecan/p_mips/debsrch.c b/private/windbg/eecan/p_mips/debsrch.c
new file mode 100644
index 000000000..b8c920b5e
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsrch.c"
diff --git a/private/windbg/eecan/p_mips/debsup.c b/private/windbg/eecan/p_mips/debsup.c
new file mode 100644
index 000000000..76c44b83a
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsup.c"
diff --git a/private/windbg/eecan/p_mips/debsym.c b/private/windbg/eecan/p_mips/debsym.c
new file mode 100644
index 000000000..b4994c7fd
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsym.c"
diff --git a/private/windbg/eecan/p_mips/debtree.c b/private/windbg/eecan/p_mips/debtree.c
new file mode 100644
index 000000000..9d9393139
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtree.c"
diff --git a/private/windbg/eecan/p_mips/debtyper.c b/private/windbg/eecan/p_mips/debtyper.c
new file mode 100644
index 000000000..3eacb04d0
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtyper.c"
diff --git a/private/windbg/eecan/p_mips/debutil.c b/private/windbg/eecan/p_mips/debutil.c
new file mode 100644
index 000000000..ec1b146d9
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debutil.c"
diff --git a/private/windbg/eecan/p_mips/debwalk.c b/private/windbg/eecan/p_mips/debwalk.c
new file mode 100644
index 000000000..5223d15f1
--- /dev/null
+++ b/private/windbg/eecan/p_mips/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debwalk.c"
diff --git a/private/windbg/eecan/p_mips/eecan.rc b/private/windbg/eecan/p_mips/eecan.rc
new file mode 100644
index 000000000..a50f7f4b5
--- /dev/null
+++ b/private/windbg/eecan/p_mips/eecan.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (ANSI C) for WinDbg"
+#define VER_INTERNALNAME_STR "eecan.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecan.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecan/p_mips/eecanmip.def b/private/windbg/eecan/p_mips/eecanmip.def
new file mode 100644
index 000000000..324cfd530
--- /dev/null
+++ b/private/windbg/eecan/p_mips/eecanmip.def
@@ -0,0 +1,4 @@
+LIBRARY eecan initinstance
+EXPORTS
+ EEInitializeExpr
+ WINDBGVersionCheck
diff --git a/private/windbg/eecan/p_mips/eeformat.c b/private/windbg/eecan/p_mips/eeformat.c
new file mode 100644
index 000000000..f95f10b27
--- /dev/null
+++ b/private/windbg/eecan/p_mips/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\eeformat.c"
diff --git a/private/windbg/eecan/p_mips/makefile b/private/windbg/eecan/p_mips/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecan/p_mips/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecan/p_mips/makefile.inc b/private/windbg/eecan/p_mips/makefile.inc
new file mode 100644
index 000000000..7b84e5e01
--- /dev/null
+++ b/private/windbg/eecan/p_mips/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+# SRCDIR=..\..\eecan
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecan/p_mips/precomp.h b/private/windbg/eecan/p_mips/precomp.h
new file mode 100644
index 000000000..2d67ed312
--- /dev/null
+++ b/private/windbg/eecan/p_mips/precomp.h
@@ -0,0 +1,57 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.h"
+#include "cvinfo.h"
+#include "shapi.h"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "dbgver.h"
+#include "debsym.h"
+#include <limits.h>
+#include "cv.h"
+#include <errno.h>
+#include "cp.h"
+
diff --git a/private/windbg/eecan/p_mips/r10math.c b/private/windbg/eecan/p_mips/r10math.c
new file mode 100644
index 000000000..3c6c7cb26
--- /dev/null
+++ b/private/windbg/eecan/p_mips/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\r10math.c"
diff --git a/private/windbg/eecan/p_mips/sources b/private/windbg/eecan/p_mips/sources
new file mode 100644
index 000000000..c82b385d2
--- /dev/null
+++ b/private/windbg/eecan/p_mips/sources
@@ -0,0 +1,75 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecanmip
+
+TARGETNAME=eecanmip
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecan.rc
+
+UMTYPE=windows
+
+TARGETLIBS=..\..\real10\obj\*\real10.lib ..\..\lib\obj\*\lilib.lib
+
+MIPS_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_MIPS -DTARGET_MIPS
+386_FLAGS=-DNO_STRICT -DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_i386 -DTARGET_MIPS
+ALPHA_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_ALPHA -DTARGET_MIPS
+PPC_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_PPC -DTARGET_MIPS
+
+MS_MIPS=1
+
+LINKER_FLAGS=-ignore:505
+386_WARNING_LEVEL=/WX /W3
+USE_CRTDLL=1
+INCLUDES=..\..\osdebug\include;..;..\..\lib;..\..\real10
+LIBRARIES=obj\*\eecan.lib;
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecan/p_ppc/debapi.c b/private/windbg/eecan/p_ppc/debapi.c
new file mode 100644
index 000000000..20a8aa47f
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debapi.c"
diff --git a/private/windbg/eecan/p_ppc/debbind.c b/private/windbg/eecan/p_ppc/debbind.c
new file mode 100644
index 000000000..de18178de
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debbind.c"
diff --git a/private/windbg/eecan/p_ppc/deberr.c b/private/windbg/eecan/p_ppc/deberr.c
new file mode 100644
index 000000000..9117022b2
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deberr.c"
diff --git a/private/windbg/eecan/p_ppc/debeval.c b/private/windbg/eecan/p_ppc/debeval.c
new file mode 100644
index 000000000..f9d03e64f
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debeval.c"
diff --git a/private/windbg/eecan/p_ppc/debfmt.c b/private/windbg/eecan/p_ppc/debfmt.c
new file mode 100644
index 000000000..b6be2d176
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debfmt.c"
diff --git a/private/windbg/eecan/p_ppc/deblex.c b/private/windbg/eecan/p_ppc/deblex.c
new file mode 100644
index 000000000..192353c67
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblex.c"
diff --git a/private/windbg/eecan/p_ppc/deblexer.c b/private/windbg/eecan/p_ppc/deblexer.c
new file mode 100644
index 000000000..758b7e259
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\deblexer.c"
diff --git a/private/windbg/eecan/p_ppc/debparse.c b/private/windbg/eecan/p_ppc/debparse.c
new file mode 100644
index 000000000..94ae0d2a0
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debparse.c"
diff --git a/private/windbg/eecan/p_ppc/debsrch.c b/private/windbg/eecan/p_ppc/debsrch.c
new file mode 100644
index 000000000..b8c920b5e
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsrch.c"
diff --git a/private/windbg/eecan/p_ppc/debsup.c b/private/windbg/eecan/p_ppc/debsup.c
new file mode 100644
index 000000000..76c44b83a
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsup.c"
diff --git a/private/windbg/eecan/p_ppc/debsym.c b/private/windbg/eecan/p_ppc/debsym.c
new file mode 100644
index 000000000..b4994c7fd
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debsym.c"
diff --git a/private/windbg/eecan/p_ppc/debtree.c b/private/windbg/eecan/p_ppc/debtree.c
new file mode 100644
index 000000000..9d9393139
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtree.c"
diff --git a/private/windbg/eecan/p_ppc/debtyper.c b/private/windbg/eecan/p_ppc/debtyper.c
new file mode 100644
index 000000000..3eacb04d0
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debtyper.c"
diff --git a/private/windbg/eecan/p_ppc/debutil.c b/private/windbg/eecan/p_ppc/debutil.c
new file mode 100644
index 000000000..ec1b146d9
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debutil.c"
diff --git a/private/windbg/eecan/p_ppc/debwalk.c b/private/windbg/eecan/p_ppc/debwalk.c
new file mode 100644
index 000000000..5223d15f1
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\debwalk.c"
diff --git a/private/windbg/eecan/p_ppc/eecan.rc b/private/windbg/eecan/p_ppc/eecan.rc
new file mode 100644
index 000000000..a50f7f4b5
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/eecan.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (ANSI C) for WinDbg"
+#define VER_INTERNALNAME_STR "eecan.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecan.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecan/p_ppc/eecanppc.def b/private/windbg/eecan/p_ppc/eecanppc.def
new file mode 100644
index 000000000..8a084fd4f
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/eecanppc.def
@@ -0,0 +1,4 @@
+LIBRARY eecanppc initinstance
+EXPORTS
+ EEInitializeExpr
+ WINDBGVersionCheck
diff --git a/private/windbg/eecan/p_ppc/eeformat.c b/private/windbg/eecan/p_ppc/eeformat.c
new file mode 100644
index 000000000..f95f10b27
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\eeformat.c"
diff --git a/private/windbg/eecan/p_ppc/makefile b/private/windbg/eecan/p_ppc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecan/p_ppc/makefile.inc b/private/windbg/eecan/p_ppc/makefile.inc
new file mode 100644
index 000000000..7b84e5e01
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+# SRCDIR=..\..\eecan
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecan/p_ppc/precomp.h b/private/windbg/eecan/p_ppc/precomp.h
new file mode 100644
index 000000000..c144c53de
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.h"
+#include "cvinfo.h"
+#include "shapi.h"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include <debexpr.h>
+#include <dbgver.h>
+#include <debsym.h>
+#include <limits.h>
+#include <cv.h>
+#include <errno.h>
+#include <cp.h>
diff --git a/private/windbg/eecan/p_ppc/r10math.c b/private/windbg/eecan/p_ppc/r10math.c
new file mode 100644
index 000000000..3c6c7cb26
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\r10math.c"
diff --git a/private/windbg/eecan/p_ppc/sources b/private/windbg/eecan/p_ppc/sources
new file mode 100644
index 000000000..1eb8ddb1e
--- /dev/null
+++ b/private/windbg/eecan/p_ppc/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecanppc
+
+TARGETNAME=eecanppc
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecan.rc
+
+UMTYPE=windows
+
+TARGETLIBS=..\..\real10\obj\*\real10.lib ..\..\lib\obj\*\lilib.lib
+
+MIPS_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_MIPS -DTARGET_PPC
+386_FLAGS=-DNO_STRICT -DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_i386 -DTARGET_PPC
+ALPHA_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_ALPHA -DTARGET_PPC
+PPC_FLAGS=-DWIN32 -DHOST32 -DADDR_MIXED -DC_ONLY -DHOST_PPC -DTARGET_PPC
+
+MS_MIPS=1
+
+LINKER_FLAGS=-ignore:505
+#386_WARNING_LEVEL=/WX /W3
+386_WARNING_LEVEL=/W3
+USE_CRTDLL=1
+INCLUDES=..\..\osdebug\include;..;..\..\lib;..\..\real10
+LIBRARIES=obj\*\eecan.lib;
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecan/r10math.c b/private/windbg/eecan/r10math.c
new file mode 100644
index 000000000..18304e296
--- /dev/null
+++ b/private/windbg/eecan/r10math.c
@@ -0,0 +1,575 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ r10math.c
+
+Abstract:
+
+ This file contains a set of routines which will do arithmetic on
+ the 80-bit floating point format supported by the 80x87 family of
+ processors.
+
+Author:
+
+ Jim Schaad (jimsch) 06-27-92
+
+Environment:
+
+ Win32 - user mode
+
+
+--*/
+
+
+
+
+/*
+ * This is the constant 0 in the 80-bit format.
+ */
+
+FLOAT10 Real10_Zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 4};
+
+
+
+int
+R10Not(
+ FLOAT10 ld
+ )
+
+/*++
+
+Routine Description:
+
+ This function will compute the NOT of an 80-bit value.
+
+Arguments:
+
+ ld - Supplies the long double to be NOT-ed
+
+Return Value:
+
+ 1 if ld is 0.0 and 0 otherwise
+
+--*/
+
+{
+ return 0; /* NOTENOTE jimsch return !ld */
+
+} /* R10Not() */
+
+
+
+
+void
+R10Uminus(
+ FLOAT10 * pldDest,
+ FLOAT10 ldLeft
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the uninary minus of a 80-bit real number.
+
+Arguments:
+
+ pldDest - Supplies a pointer to the destination FLOAT10 buffer
+ ldLeft - Supplies the value to be negated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef i386
+ // NOTENOTE jimsch - need to try/except this code
+ _asm {
+ lea eax, ldLeft
+ fld tbyte ptr [eax] ; Load ldLeft on the float point chip;
+ fchs ;
+ mov eax, pldDest ;
+ fstp tbyte ptr [eax] ;
+ }
+#else
+#endif
+
+ return;
+
+} /* R10Uminus() */
+
+
+
+bool_t
+R10Equal(
+ FLOAT10 ldLeft,
+ FLOAT10 ldRight
+ )
+/*++
+
+Routine Description:
+
+ This function will compare two 80-bit reals and return TRUE if
+ ldLeft == ldRight. This routine using an unorder compare on NANs.
+
+Arguments:
+
+ ldLeft - Supplies long double to compare
+ ldRight - Supplies long double to compare
+
+Return Value:
+
+ TRUE if the items are equal else FALSE
+
+--*/
+
+{
+#ifdef i386
+ short sw;
+
+ _asm {
+ lea eax, ldLeft ;
+ fld tbyte ptr [eax] ;
+
+ lea eax, ldRight ;
+ fld tbyte ptr [eax] ;
+
+ fucompp ;
+ fstsw sw ;
+ }
+
+ if ((sw & 0x4700) == 0x04000) {
+ return TRUE;
+ }
+ return FALSE;
+#else
+ return FALSE;
+#endif
+} /* R10Equal() */
+
+
+
+bool_t
+R10Lt(
+ FLOAT10 ldLeft,
+ FLOAT10 ldRight
+ )
+
+/*++
+
+Routine Description:
+
+ This function will compare two 80-bit reals and return TRUE if
+ ldLeft < ldRight. This routine uses an unordered compare on NANs
+
+Arguments:
+
+ ldLeft - Supplies long double to compare
+ ldRight - Supplies long double to compare
+
+Return Value:
+
+ TRUE if the items are equal else FALSE
+
+--*/
+
+{
+#ifdef i386
+ short sw;
+
+ _asm {
+ lea eax, ldLeft ;
+ fld tbyte ptr [eax] ;
+
+ lea eax, ldRight ;
+ fld tbyte ptr [eax] ;
+
+ fucompp ;
+ fstsw sw ;
+ }
+
+ if ((sw & 0x4700) == 0x00000) {
+ return TRUE;
+ }
+ return FALSE;
+#else
+ return FALSE;
+#endif
+} /* R10Lt() */
+
+
+
+void
+R10Plus(
+ FLOAT10 * pldResult,
+ FLOAT10 ldLeft,
+ FLOAT10 ldRight
+ )
+
+/*++
+
+Routine Description:
+
+ This function adds ldLeft and ldRight together and stores the result in
+ pldResult
+
+Arguments:
+
+ pldResult - Supplies pointer to destination
+ ldLeft - Supplies parameter 1
+ ldRight - Supplies parameter 2
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef i386
+ _asm {
+ lea eax, ldLeft ;
+ fld tbyte ptr [eax] ;
+
+ lea eax, ldRight ;
+ fld tbyte ptr [eax] ;
+
+ faddp st(1),st
+
+ mov eax, pldResult ;
+ fstp tbyte ptr [eax] ;
+ }
+
+#else
+ memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
+#endif
+ return;
+} /* R10Plus() */
+
+
+
+void
+R10Minus(
+ FLOAT10 * pldResult,
+ FLOAT10 ldLeft,
+ FLOAT10 ldRight
+ )
+
+/*++
+
+Routine Description:
+
+ This function subtraces ldRight from ldLeft together and stores
+ the result in pldResult
+
+Arguments:
+
+ pldResult - Supplies pointer to destination
+ ldLeft - Supplies parameter 1
+ ldRight - Supplies parameter 2
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef i386
+ _asm {
+ lea eax, ldLeft ;
+ fld tbyte ptr [eax] ;
+
+ lea eax, ldRight ;
+ fld tbyte ptr [eax] ;
+
+ fsubp st(1),st
+
+ mov eax, pldResult ;
+ fstp tbyte ptr [eax] ;
+ }
+
+#else // i386
+ memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
+#endif // i386
+ return;
+} /* R10Minus() */
+
+
+
+void
+R10Times(
+ FLOAT10 * pldResult,
+ FLOAT10 ldLeft,
+ FLOAT10 ldRight
+ )
+
+/*++
+
+Routine Description:
+
+ This function multiplies ldRight and ldLeft together and stores
+ the result in pldResult
+
+Arguments:
+
+ pldResult - Supplies pointer to destination
+ ldLeft - Supplies parameter 1
+ ldRight - Supplies parameter 2
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef i386
+ _asm {
+ lea eax, ldLeft ;
+ fld tbyte ptr [eax] ;
+
+ lea eax, ldRight ;
+ fld tbyte ptr [eax] ;
+
+ fmulp st(1),st ;
+
+ mov eax, pldResult ;
+ fstp tbyte ptr [eax] ;
+ }
+#else // i386
+ memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
+#endif // i386
+ return;
+} /* R10Times() */
+
+
+void
+R10Divide(
+ FLOAT10 * pldResult,
+ FLOAT10 ldLeft,
+ FLOAT10 ldRight
+ )
+
+/*++
+
+Routine Description:
+
+ This function multiplies ldRight and ldLeft together and stores
+ the result in pldResult
+
+Arguments:
+
+ pldResult - Supplies pointer to destination
+ ldLeft - Supplies parameter 1
+ ldRight - Supplies parameter 2
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef i386
+ _asm {
+ lea eax, ldLeft ;
+ fld tbyte ptr [eax] ;
+
+ lea eax, ldRight ;
+ fld tbyte ptr [eax] ;
+
+ fdivp st(1),st ;
+
+ mov eax, pldResult ;
+ fstp tbyte ptr [eax] ;
+ }
+#else // i386
+ memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
+#endif // i386
+ return;
+} /* R10Divide() */
+
+
+double
+R10CastToDouble(
+ FLOAT10 ld
+ )
+
+/*++
+
+Routine Description:
+
+ Convert the 80-bit real to a 64-bit real and return it
+
+Arguments:
+
+ ld - Supplies the 80-bit real to convert
+
+Return Value:
+
+ Returns the value ld in 64-bit format
+
+--*/
+
+{
+#ifdef i386
+ double d;
+ _asm {
+ lea eax, ld
+ fld tbyte ptr [eax]
+ lea eax, d
+ fstp qword ptr [eax]
+ }
+ return d;
+#else
+ return 0.0;
+#endif
+} /* R10CastToDouble() */
+
+
+float
+R10CastToFloat(
+ FLOAT10 ld
+ )
+
+/*++
+
+Routine Description:
+
+ Converts a 80-bit real number to a 32-bit real number
+
+Arguments:
+
+ ld - Supplies 80-bit number to be converted
+
+Return Value:
+
+ Returns the 32-bit equivalent value
+
+--*/
+
+{
+#ifdef i386
+ float d;
+ _asm {
+ lea eax, ld
+ fld tbyte ptr [eax]
+ lea eax, d
+ fstp dword ptr [eax]
+ }
+ return d;
+#else
+ return (float) 0.0;
+#endif
+} /* R10CastToFloat() */
+
+
+
+long
+R10CastToLong(
+ FLOAT10 ld
+ )
+
+/*++
+
+Routine Description:
+
+ Converts a 80-bit real number to a 32-bit long
+
+Arguments:
+
+ ld - Supplies 80-bit number to be converted
+
+Return Value:
+
+ returns 32-bit equvalent to ld
+
+--*/
+
+{
+#ifdef i386
+ long d;
+ _asm {
+ lea eax, ld
+ fld tbyte ptr [eax]
+ lea eax, d
+ fistp dword ptr [eax]
+ }
+ return d;
+#else
+ return 0;
+#endif
+} /* R10CastToLong() */
+
+
+
+void
+R10AssignDouble(
+ FLOAT10 * pld,
+ double d
+ )
+/*++
+
+Routine Description:
+
+ This function will assign a double to a 80-bit real
+
+Arguments:
+
+ pld - Supplies pointer to destiniation buffer
+ d - Supplies the double to be assigned
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef i386
+ _asm {
+ lea eax, d
+ fld qword ptr [eax]
+ mov eax, pld
+ fstp tbyte ptr [eax]
+ }
+#else
+ return;
+#endif
+} /* R10AssignDouble() */
+
+
+
+void
+R10AssignFloat(
+ FLOAT10 * pld,
+ float f
+ )
+/*++
+
+Routine Description:
+
+ This function will assign a float to a 80-bit real
+
+Arguments:
+
+ pld - Supplies pointer to destiniation buffer
+ f - Supplies the float to be assigned
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+} /* R10AssignFloat() */
+
+
diff --git a/private/windbg/eecan/r10math.h b/private/windbg/eecan/r10math.h
new file mode 100644
index 000000000..3ee9fda09
--- /dev/null
+++ b/private/windbg/eecan/r10math.h
@@ -0,0 +1,15 @@
+extern FLOAT10 Real10_Zero;
+
+int R10Not(FLOAT10);
+void R10Uminus(FLOAT10 *, FLOAT10);
+bool_t R10Equal(FLOAT10, FLOAT10);
+bool_t R10Lt(FLOAT10, FLOAT10);
+void R10Plus(FLOAT10 *, FLOAT10, FLOAT10);
+void R10Minus(FLOAT10 *, FLOAT10, FLOAT10);
+void R10Times(FLOAT10 *, FLOAT10, FLOAT10);
+void R10Divide(FLOAT10 *, FLOAT10, FLOAT10);
+double R10CastToDouble(FLOAT10);
+float R10CastToFloat(FLOAT10);
+long R10CastToLong(FLOAT10);
+void R10AssignDouble(FLOAT10 *, double);
+void R10AssignFloat(FLOAT10 *, float);
diff --git a/private/windbg/eecan/shfunc.h b/private/windbg/eecan/shfunc.h
new file mode 100644
index 000000000..4f3d4b870
--- /dev/null
+++ b/private/windbg/eecan/shfunc.h
@@ -0,0 +1,186 @@
+extern PCVF pCVF;
+extern PCRF pCRF;
+
+#define MHlpvAlloc (*pCVF->pMHlpvAlloc)
+#define MHFreeLpv (*pCVF->pMHFreeLpv)
+#define SHGetNextExe (*pCVF->pSHGetNextExe)
+#define SHHexeFromHmod (*pCVF->pSHHexeFromHmod)
+#define SHGetNextMod (*pCVF->pSHGetNextMod)
+#define SHGetCxtFromHmod (*pCVF->pSHGetCxtFromHmod)
+#define SHGetCxtFromHexe (*pCVF->pSHGetCxtFromHexe)
+#define SHSetCxt (*pCVF->pSHSetCxt)
+#define SHSetCxtMod (*pCVF->pSHSetCxtMod)
+#define SHFindNameInGlobal (*pCVF->pSHFindNameInGlobal)
+#define SHFindNameInContext (*pCVF->pSHFindNameInContext)
+#define SHGoToParent (*pCVF->pSHGoToParent)
+#define SHHsymFromPcxt (*pCVF->pSHHsymFromPcxt)
+#define SHNextHsym (*pCVF->pSHNextHsym)
+#define SHGetFuncCxf (*pCVF->pSHGetFuncCxf)
+#define SHGetModName (*pCVF->pSHGetModName)
+//#define SHGetFileName (*pCVF->pSHGetFileName)
+#define SHGetExeName (*pCVF->pSHGetExeName)
+#define SHGetModNameFromHexe (*pCVF->pSHGetModNameFromHexe)
+#define SHGetSymFName (*pCVF->pSHGetSymFName)
+//#define SHGethFileFromhMod (*pCVF->pSHGethFileFromhMod)
+//#define SHGethModFromName (*pCVF->pSHGethModFromName)
+#define SHGethExeFromName (*pCVF->pSHGethExeFromName)
+#define SHGethExeFromModuleName (*pCVF->pSHGethExeFromModuleName)
+#define SHGetNearestHsym (*pCVF->pSHGetNearestHsym)
+#define SHIsInProlog (*pCVF->pSHIsInProlog)
+#define SHIsAddrInCxt (*pCVF->pSHIsAddrInCxt)
+//#define SHLineFromADDR (*pCVF->pSHLineFromADDR)
+//#define SHADDRFromLine (*pCVF->pSHADDRFromLine)
+#define SHModelFromAddr (*pCVF->pSHModelFromAddr)
+#define SHCompareRE (*pCVF->pSHCompareRE)
+#define SHFixupAddr (*pCVF->pSHFixupAddr)
+#define SHUnFixupAddr (*pCVF->pSHUnFixupAddr)
+#define SHWantSymbols (*pCVF->pSHWantSymbols)
+#define PHGetNearestHsym (*pCVF->pPHGetNearestHsym)
+#define PHFindNameInPublics (*pCVF->pPHFindNameInPublics)
+#define THGetTypeFromIndex (*pCVF->pTHGetTypeFromIndex)
+#define THGetNextType (*pCVF->pTHGetNextType)
+#define MHIsMemLocked (*pCVF->pMHIsMemLocked)
+#define SYGetAddr (*pCVF->pSYGetAddr)
+#define SYGetMemInfo (*pCVF->pSYGetMemInfo)
+
+// MAGIC NUMBERS
+
+#define adrTlsBase 7
+#define adrPC 2
+
+__inline LPV MHOmfLock(HDEP hdep) { return((LPV) hdep); }
+
+__inline void MHOmfUnLock(HDEP hdep) {}
+
+#define DHSetupExecute (*pCVF->pDHSetupExecute)
+#define DHStartExecute (*pCVF->pDHStartExecute)
+#define DHCleanUpExecute (*pCVF->pDHCleanUpExecute)
+
+#if !defined (M68K)
+#define GetDebuggeeBytes(addr, cb, pv, type) \
+ (*pCVF->pDHGetDebuggeeBytes)((addr), (cb), (pv))
+#define PutDebuggeeBytes(addr, cb, pv, type) \
+ (*pCVF->pDHPutDebuggeeBytes)((addr), (cb), (pv))
+#define GetReg (*pCVF->pDHGetReg)
+#define SetReg (*pCVF->pDHSetReg)
+#endif
+
+#define in386mode (*pCVF->pin386mode)
+#define is_assign (*pCVF->pis_assign)
+#define ArrayDefault (*pCVF->pArrayDefault)
+#define quit (*pCVF->pquit)
+#define assert_out (*pCVF->passert)
+
+//
+// Source Line Handler
+//
+
+#define SLLineFromAddr (*pCVF->pSLLineFromAddr)
+#define SLFLineToAddr (*pCVF->pSLFLineToAddr)
+#define SLNameFromHsf (*pCVF->pSLNameFromHsf)
+#define SLHmodFromHsf (*pCVF->pSLHmodFromHsf)
+#define SLHsfFromPcxt (*pCVF->pSLHsfFromPcxt)
+#define SLHsfFromFile (*pCVF->pSLHsfFromFile)
+
+
+//
+// Shell callbacks
+//
+#define GetCurrentPC (*pCVF->pGetCurrentPC)
+
+
+
+// **********************************************************************
+// * *
+// * RUN TIME CALLBACKS *
+// * *
+// **********************************************************************
+
+#ifndef WIN32
+#define ultoa(a,b,c) ((pCRF->pultoa)(a, b, c))
+#define itoa(a,b,c) ((pCRF->pitoa)(a, b, c))
+#define ltoa(a,b,c) ((pCRF->pltoa)(a, b, c))
+#endif
+#define _strtold(a, b) ((pCRF->p_strtold)(a, b))
+
+#define eprintf (*pCRF->peprintf)
+//#define sprintf (*pCRF->psprintf)
+
+// **********************************************************************
+// * *
+// * Expr Evaluator Declarations *
+// * *
+// **********************************************************************
+void LOADDS PASCAL EEInitializeExpr (PCI, PEI);
+void LOADDS PASCAL EEFreeStr (EEHSTR);
+EESTATUS LOADDS PASCAL EEGetError (PHTM, EESTATUS, PEEHSTR);
+
+EESTATUS LOADDS PASCAL EEParse (char FAR *, EERADIX, SHFLAG, PHTM, uint FAR *);
+EESTATUS LOADDS PASCAL EEBindTM (PHTM, PCXT, SHFLAG, SHFLAG, BOOL);
+EESTATUS LOADDS PASCAL EEvaluateTM (PHTM, PFRAME, EEDSP);
+
+EESTATUS LOADDS PASCAL EEGetExprFromTM (PHTM, PEERADIX, PEEHSTR, ushort FAR *);
+EESTATUS LOADDS PASCAL EEGetValueFromTM (PHTM, EERADIX, PEEFORMAT, PEEHSTR);
+EESTATUS LOADDS PASCAL EEGetNameFromTM (PHTM, PEEHSTR);
+EESTATUS LOADDS PASCAL EEGetTypeFromTM (PHTM, EEHSTR, PEEHSTR, ulong);
+EESTATUS LOADDS PASCAL EEFormatCXTFromPCXT (PCXT, PEEHSTR, BOOL);
+void LOADDS PASCAL EEFreeTM (PHTM);
+
+EESTATUS LOADDS PASCAL EEParseBP (char FAR *, EERADIX, SHFLAG, PCXF, PTML, ulong, uint FAR *, SHFLAG);
+void LOADDS PASCAL EEFreeTML (PTML);
+
+EESTATUS LOADDS PASCAL EEInfoFromTM (PHTM, PRI, PHTI);
+void LOADDS PASCAL EEFreeTI (PHTI);
+
+EESTATUS LOADDS PASCAL EEGetCXTLFromTM(PHTM, PHCXTL);
+void LOADDS PASCAL EEFreeCXTL(PHCXTL);
+
+EESTATUS LOADDS PASCAL EEAssignTMToTM (PHTM, PHTM);
+
+EEPDTYP LOADDS PASCAL EEIsExpandable (PHTM);
+SHFLAG LOADDS PASCAL EEAreTypesEqual (PHTM, PHTM);
+HTYPE LOADDS PASCAL EEGetHtypeFromTM(PHTM );
+EESTATUS LOADDS PASCAL EEcChildrenTM (PHTM, long FAR *, PSHFLAG);
+EESTATUS LOADDS PASCAL EEGetChildTM (PHTM, long, PHTM, uint FAR *, SHFLAG, uint);
+EESTATUS LOADDS PASCAL EEDereferenceTM (PHTM, PHTM, uint FAR *, SHFLAG);
+
+EESTATUS LOADDS PASCAL EEcParamTM (PHTM, ushort FAR *, PSHFLAG);
+EESTATUS LOADDS PASCAL EEGetParmTM (PHTM, uint, PHTM, uint FAR *, SHFLAG, uint);
+EESTATUS LOADDS PASCAL EEGetTMFromHSYM (HSYM, PCXT, PHTM, uint FAR *, SHFLAG);
+
+EESTATUS LOADDS PASCAL EEFormatAddress( SHSEG, SHOFF, char FAR *, uint, uint );
+EESTATUS LOADDS PASCAL EEFormatAddr(LPADDR, char FAR *, uint, uint);
+EESTATUS LOADDS PASCAL EEUnFormatAddr(LPADDR, char FAR *);
+EESTATUS LOADDS PASCAL EEFormatMemory(LPCH, uint, LPBYTE, uint, FMTTYPE, uint);
+EESTATUS LOADDS PASCAL EEUnformatMemory(uchar FAR *, char FAR *, uint,
+ FMTTYPE, uint);
+EESTATUS LOADDS PASCAL EEFormatEnumerate(uint, uint FAR *, uint FAR *,
+ uint FAR *, uint FAR *, uint FAR *,
+ LPCH FAR *);
+
+
+EESTATUS LOADDS PASCAL EEGetHSYMList (HDEP FAR *, PCXT, ushort, uchar FAR *, SHFLAG);
+void LOADDS PASCAL EEFreeHSYMList (HDEP FAR *);
+
+void LOADDS PASCAL EESetSuffix( char );
+
+#if MEMDBG
+HDEP DbgMemAlloc(UINT,char*,UINT);
+HDEP DbgMemReAlloc(HDEP,UINT,char*,UINT);
+VOID DbgMemFree(HDEP,char*,UINT);
+LPVOID DbgMemLock(HDEP,char*,UINT);
+VOID DbgMemUnLock(HDEP,char*,UINT);
+
+#define MHMemAllocate(x) DbgMemAlloc(x,__FILE__,__LINE__)
+#define MHMemReAlloc(x,y) DbgMemReAlloc(x,y,__FILE__,__LINE__)
+#define MHMemFree(x) DbgMemFree(x,__FILE__,__LINE__)
+#define MHMemLock(x) DbgMemLock(x,__FILE__,__LINE__)
+#define MHMemUnLock(x) DbgMemUnLock(x,__FILE__,__LINE__)
+#else
+#define MHMemAllocate (*pCVF->pMHMemAllocate)
+#define MHMemReAlloc (*pCVF->pMHMemReAlloc)
+#define MHMemFree (*pCVF->pMHMemFree)
+#define MHMemLock (*pCVF->pMHMemLock)
+#define MHMemUnLock (*pCVF->pMHMemUnLock)
+#endif
+
diff --git a/private/windbg/eecxx/dirs b/private/windbg/eecxx/dirs
new file mode 100644
index 000000000..b0a36666c
--- /dev/null
+++ b/private/windbg/eecxx/dirs
@@ -0,0 +1,19 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= p_alpha \
+ p_i386 \
+ p_mips \
+ p_ppc
diff --git a/private/windbg/eecxx/p_alpha/debapi.c b/private/windbg/eecxx/p_alpha/debapi.c
new file mode 100644
index 000000000..5c6d6725e
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debapi.c"
diff --git a/private/windbg/eecxx/p_alpha/debbind.c b/private/windbg/eecxx/p_alpha/debbind.c
new file mode 100644
index 000000000..12a41aaeb
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debbind.c"
diff --git a/private/windbg/eecxx/p_alpha/deberr.c b/private/windbg/eecxx/p_alpha/deberr.c
new file mode 100644
index 000000000..21eca1722
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deberr.c"
diff --git a/private/windbg/eecxx/p_alpha/debeval.c b/private/windbg/eecxx/p_alpha/debeval.c
new file mode 100644
index 000000000..6c158f9a8
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debeval.c"
diff --git a/private/windbg/eecxx/p_alpha/debfmt.c b/private/windbg/eecxx/p_alpha/debfmt.c
new file mode 100644
index 000000000..0925d21b1
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debfmt.c"
diff --git a/private/windbg/eecxx/p_alpha/deblex.c b/private/windbg/eecxx/p_alpha/deblex.c
new file mode 100644
index 000000000..deef2e982
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblex.c"
diff --git a/private/windbg/eecxx/p_alpha/deblexer.c b/private/windbg/eecxx/p_alpha/deblexer.c
new file mode 100644
index 000000000..ff7c6172e
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblexer.c"
diff --git a/private/windbg/eecxx/p_alpha/debparse.c b/private/windbg/eecxx/p_alpha/debparse.c
new file mode 100644
index 000000000..51a2946b8
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debparse.c"
diff --git a/private/windbg/eecxx/p_alpha/debsrch.c b/private/windbg/eecxx/p_alpha/debsrch.c
new file mode 100644
index 000000000..5d2c07357
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsrch.c"
diff --git a/private/windbg/eecxx/p_alpha/debsup.c b/private/windbg/eecxx/p_alpha/debsup.c
new file mode 100644
index 000000000..8cd0505e4
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsup.c"
diff --git a/private/windbg/eecxx/p_alpha/debsym.c b/private/windbg/eecxx/p_alpha/debsym.c
new file mode 100644
index 000000000..f3c3a1795
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsym.c"
diff --git a/private/windbg/eecxx/p_alpha/debtree.c b/private/windbg/eecxx/p_alpha/debtree.c
new file mode 100644
index 000000000..9682617d8
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtree.c"
diff --git a/private/windbg/eecxx/p_alpha/debtyper.c b/private/windbg/eecxx/p_alpha/debtyper.c
new file mode 100644
index 000000000..b8665d7b0
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtyper.c"
diff --git a/private/windbg/eecxx/p_alpha/debutil.c b/private/windbg/eecxx/p_alpha/debutil.c
new file mode 100644
index 000000000..e20298030
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debutil.c"
diff --git a/private/windbg/eecxx/p_alpha/debwalk.c b/private/windbg/eecxx/p_alpha/debwalk.c
new file mode 100644
index 000000000..3e6f59867
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debwalk.c"
diff --git a/private/windbg/eecxx/p_alpha/eecxx.rc b/private/windbg/eecxx/p_alpha/eecxx.rc
new file mode 100644
index 000000000..170fc3f94
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/eecxx.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (C++) for WinDbg"
+#define VER_INTERNALNAME_STR "eecxx.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecxx.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecxx/p_alpha/eecxxalp.def b/private/windbg/eecxx/p_alpha/eecxxalp.def
new file mode 100644
index 000000000..ada1d9d3c
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/eecxxalp.def
@@ -0,0 +1,4 @@
+LIBRARY eecxxalp initinstance
+EXPORTS
+ EEInitializeExpr PRIVATE
+ DBGVersionCheck PRIVATE
diff --git a/private/windbg/eecxx/p_alpha/eeformat.c b/private/windbg/eecxx/p_alpha/eeformat.c
new file mode 100644
index 000000000..49e09b217
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\eeformat.c"
diff --git a/private/windbg/eecxx/p_alpha/makefile b/private/windbg/eecxx/p_alpha/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecxx/p_alpha/makefile.inc b/private/windbg/eecxx/p_alpha/makefile.inc
new file mode 100644
index 000000000..62f1832fd
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..\..\eecan
+# SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecxx/p_alpha/precomp.h b/private/windbg/eecxx/p_alpha/precomp.h
new file mode 100644
index 000000000..cb701f206
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.hxx"
+#include "cvinfo.h"
+#include "shapi.hxx"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "debsym.h"
+#include "cv.h"
+
+#include "dbgver.h"
diff --git a/private/windbg/eecxx/p_alpha/r10math.c b/private/windbg/eecxx/p_alpha/r10math.c
new file mode 100644
index 000000000..b53243c34
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\r10math.c"
diff --git a/private/windbg/eecxx/p_alpha/sources b/private/windbg/eecxx/p_alpha/sources
new file mode 100644
index 000000000..bfcb153c0
--- /dev/null
+++ b/private/windbg/eecxx/p_alpha/sources
@@ -0,0 +1,75 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecxxalp
+
+TARGETNAME=eecxxalp
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= \
+ debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecxx.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include;\
+ ..\..\eecan; \
+ ..\..\lib; \
+ ..\..\real10
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_ALPHA
+
+TARGETLIBS= \
+ ..\..\lib\obj\*\mathlib.lib \
+ $(MORE_LIBS)
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecxx/p_i386/debapi.c b/private/windbg/eecxx/p_i386/debapi.c
new file mode 100644
index 000000000..5c6d6725e
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debapi.c"
diff --git a/private/windbg/eecxx/p_i386/debbind.c b/private/windbg/eecxx/p_i386/debbind.c
new file mode 100644
index 000000000..12a41aaeb
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debbind.c"
diff --git a/private/windbg/eecxx/p_i386/deberr.c b/private/windbg/eecxx/p_i386/deberr.c
new file mode 100644
index 000000000..21eca1722
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deberr.c"
diff --git a/private/windbg/eecxx/p_i386/debeval.c b/private/windbg/eecxx/p_i386/debeval.c
new file mode 100644
index 000000000..6c158f9a8
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debeval.c"
diff --git a/private/windbg/eecxx/p_i386/debfmt.c b/private/windbg/eecxx/p_i386/debfmt.c
new file mode 100644
index 000000000..0925d21b1
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debfmt.c"
diff --git a/private/windbg/eecxx/p_i386/deblex.c b/private/windbg/eecxx/p_i386/deblex.c
new file mode 100644
index 000000000..deef2e982
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblex.c"
diff --git a/private/windbg/eecxx/p_i386/deblexer.c b/private/windbg/eecxx/p_i386/deblexer.c
new file mode 100644
index 000000000..ff7c6172e
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblexer.c"
diff --git a/private/windbg/eecxx/p_i386/debparse.c b/private/windbg/eecxx/p_i386/debparse.c
new file mode 100644
index 000000000..51a2946b8
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debparse.c"
diff --git a/private/windbg/eecxx/p_i386/debsrch.c b/private/windbg/eecxx/p_i386/debsrch.c
new file mode 100644
index 000000000..5d2c07357
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsrch.c"
diff --git a/private/windbg/eecxx/p_i386/debsup.c b/private/windbg/eecxx/p_i386/debsup.c
new file mode 100644
index 000000000..8cd0505e4
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsup.c"
diff --git a/private/windbg/eecxx/p_i386/debsym.c b/private/windbg/eecxx/p_i386/debsym.c
new file mode 100644
index 000000000..f3c3a1795
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsym.c"
diff --git a/private/windbg/eecxx/p_i386/debtree.c b/private/windbg/eecxx/p_i386/debtree.c
new file mode 100644
index 000000000..9682617d8
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtree.c"
diff --git a/private/windbg/eecxx/p_i386/debtyper.c b/private/windbg/eecxx/p_i386/debtyper.c
new file mode 100644
index 000000000..b8665d7b0
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtyper.c"
diff --git a/private/windbg/eecxx/p_i386/debutil.c b/private/windbg/eecxx/p_i386/debutil.c
new file mode 100644
index 000000000..e20298030
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debutil.c"
diff --git a/private/windbg/eecxx/p_i386/debwalk.c b/private/windbg/eecxx/p_i386/debwalk.c
new file mode 100644
index 000000000..3e6f59867
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debwalk.c"
diff --git a/private/windbg/eecxx/p_i386/eecxx.rc b/private/windbg/eecxx/p_i386/eecxx.rc
new file mode 100644
index 000000000..170fc3f94
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/eecxx.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (C++) for WinDbg"
+#define VER_INTERNALNAME_STR "eecxx.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecxx.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecxx/p_i386/eecxxx86.def b/private/windbg/eecxx/p_i386/eecxxx86.def
new file mode 100644
index 000000000..9d3af0ec9
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/eecxxx86.def
@@ -0,0 +1,4 @@
+LIBRARY eecxxx86 initinstance
+EXPORTS
+ EEInitializeExpr PRIVATE
+ DBGVersionCheck PRIVATE
diff --git a/private/windbg/eecxx/p_i386/eeformat.c b/private/windbg/eecxx/p_i386/eeformat.c
new file mode 100644
index 000000000..49e09b217
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\eeformat.c"
diff --git a/private/windbg/eecxx/p_i386/makefile b/private/windbg/eecxx/p_i386/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecxx/p_i386/makefile.inc b/private/windbg/eecxx/p_i386/makefile.inc
new file mode 100644
index 000000000..62f1832fd
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..\..\eecan
+# SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecxx/p_i386/precomp.h b/private/windbg/eecxx/p_i386/precomp.h
new file mode 100644
index 000000000..cb701f206
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.hxx"
+#include "cvinfo.h"
+#include "shapi.hxx"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "debsym.h"
+#include "cv.h"
+
+#include "dbgver.h"
diff --git a/private/windbg/eecxx/p_i386/r10math.c b/private/windbg/eecxx/p_i386/r10math.c
new file mode 100644
index 000000000..b53243c34
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\r10math.c"
diff --git a/private/windbg/eecxx/p_i386/sources b/private/windbg/eecxx/p_i386/sources
new file mode 100644
index 000000000..eef867ca0
--- /dev/null
+++ b/private/windbg/eecxx/p_i386/sources
@@ -0,0 +1,74 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecxxx86
+
+TARGETNAME=eecxxx86
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecxx.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include;\
+ ..\..\eecan; \
+ ..\..\lib; \
+ ..\..\real10
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_i386
+
+TARGETLIBS= \
+ ..\..\lib\obj\*\mathlib.lib \
+ $(MORE_LIBS)
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecxx/p_mips/debapi.c b/private/windbg/eecxx/p_mips/debapi.c
new file mode 100644
index 000000000..5c6d6725e
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debapi.c"
diff --git a/private/windbg/eecxx/p_mips/debbind.c b/private/windbg/eecxx/p_mips/debbind.c
new file mode 100644
index 000000000..12a41aaeb
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debbind.c"
diff --git a/private/windbg/eecxx/p_mips/deberr.c b/private/windbg/eecxx/p_mips/deberr.c
new file mode 100644
index 000000000..21eca1722
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deberr.c"
diff --git a/private/windbg/eecxx/p_mips/debeval.c b/private/windbg/eecxx/p_mips/debeval.c
new file mode 100644
index 000000000..6c158f9a8
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debeval.c"
diff --git a/private/windbg/eecxx/p_mips/debfmt.c b/private/windbg/eecxx/p_mips/debfmt.c
new file mode 100644
index 000000000..0925d21b1
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debfmt.c"
diff --git a/private/windbg/eecxx/p_mips/deblex.c b/private/windbg/eecxx/p_mips/deblex.c
new file mode 100644
index 000000000..deef2e982
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblex.c"
diff --git a/private/windbg/eecxx/p_mips/deblexer.c b/private/windbg/eecxx/p_mips/deblexer.c
new file mode 100644
index 000000000..ff7c6172e
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblexer.c"
diff --git a/private/windbg/eecxx/p_mips/debparse.c b/private/windbg/eecxx/p_mips/debparse.c
new file mode 100644
index 000000000..51a2946b8
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debparse.c"
diff --git a/private/windbg/eecxx/p_mips/debsrch.c b/private/windbg/eecxx/p_mips/debsrch.c
new file mode 100644
index 000000000..5d2c07357
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsrch.c"
diff --git a/private/windbg/eecxx/p_mips/debsup.c b/private/windbg/eecxx/p_mips/debsup.c
new file mode 100644
index 000000000..8cd0505e4
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsup.c"
diff --git a/private/windbg/eecxx/p_mips/debsym.c b/private/windbg/eecxx/p_mips/debsym.c
new file mode 100644
index 000000000..f3c3a1795
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsym.c"
diff --git a/private/windbg/eecxx/p_mips/debtree.c b/private/windbg/eecxx/p_mips/debtree.c
new file mode 100644
index 000000000..9682617d8
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtree.c"
diff --git a/private/windbg/eecxx/p_mips/debtyper.c b/private/windbg/eecxx/p_mips/debtyper.c
new file mode 100644
index 000000000..b8665d7b0
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtyper.c"
diff --git a/private/windbg/eecxx/p_mips/debutil.c b/private/windbg/eecxx/p_mips/debutil.c
new file mode 100644
index 000000000..e20298030
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debutil.c"
diff --git a/private/windbg/eecxx/p_mips/debwalk.c b/private/windbg/eecxx/p_mips/debwalk.c
new file mode 100644
index 000000000..3e6f59867
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debwalk.c"
diff --git a/private/windbg/eecxx/p_mips/eecxx.rc b/private/windbg/eecxx/p_mips/eecxx.rc
new file mode 100644
index 000000000..170fc3f94
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/eecxx.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (C++) for WinDbg"
+#define VER_INTERNALNAME_STR "eecxx.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecxx.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecxx/p_mips/eecxxmip.def b/private/windbg/eecxx/p_mips/eecxxmip.def
new file mode 100644
index 000000000..fdecab464
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/eecxxmip.def
@@ -0,0 +1,4 @@
+LIBRARY eecxxmip initinstance
+EXPORTS
+ EEInitializeExpr PRIVATE
+ DBGVersionCheck PRIVATE
diff --git a/private/windbg/eecxx/p_mips/eeformat.c b/private/windbg/eecxx/p_mips/eeformat.c
new file mode 100644
index 000000000..49e09b217
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\eeformat.c"
diff --git a/private/windbg/eecxx/p_mips/makefile b/private/windbg/eecxx/p_mips/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecxx/p_mips/makefile.inc b/private/windbg/eecxx/p_mips/makefile.inc
new file mode 100644
index 000000000..62f1832fd
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..\..\eecan
+# SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecxx/p_mips/precomp.h b/private/windbg/eecxx/p_mips/precomp.h
new file mode 100644
index 000000000..cb701f206
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.hxx"
+#include "cvinfo.h"
+#include "shapi.hxx"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "debsym.h"
+#include "cv.h"
+
+#include "dbgver.h"
diff --git a/private/windbg/eecxx/p_mips/r10math.c b/private/windbg/eecxx/p_mips/r10math.c
new file mode 100644
index 000000000..b53243c34
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\r10math.c"
diff --git a/private/windbg/eecxx/p_mips/sources b/private/windbg/eecxx/p_mips/sources
new file mode 100644
index 000000000..a02aafb35
--- /dev/null
+++ b/private/windbg/eecxx/p_mips/sources
@@ -0,0 +1,74 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecxxmip
+
+TARGETNAME=eecxxmip
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecxx.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include;\
+ ..\..\eecan; \
+ ..\..\lib; \
+ ..\..\real10
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_MIPS
+
+TARGETLIBS= \
+ ..\..\lib\obj\*\mathlib.lib \
+ $(MORE_LIBS)
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/eecxx/p_ppc/debapi.c b/private/windbg/eecxx/p_ppc/debapi.c
new file mode 100644
index 000000000..5c6d6725e
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debapi.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debapi.c"
diff --git a/private/windbg/eecxx/p_ppc/debbind.c b/private/windbg/eecxx/p_ppc/debbind.c
new file mode 100644
index 000000000..12a41aaeb
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debbind.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debbind.c"
diff --git a/private/windbg/eecxx/p_ppc/deberr.c b/private/windbg/eecxx/p_ppc/deberr.c
new file mode 100644
index 000000000..21eca1722
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/deberr.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deberr.c"
diff --git a/private/windbg/eecxx/p_ppc/debeval.c b/private/windbg/eecxx/p_ppc/debeval.c
new file mode 100644
index 000000000..6c158f9a8
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debeval.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debeval.c"
diff --git a/private/windbg/eecxx/p_ppc/debfmt.c b/private/windbg/eecxx/p_ppc/debfmt.c
new file mode 100644
index 000000000..0925d21b1
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debfmt.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debfmt.c"
diff --git a/private/windbg/eecxx/p_ppc/deblex.c b/private/windbg/eecxx/p_ppc/deblex.c
new file mode 100644
index 000000000..deef2e982
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/deblex.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblex.c"
diff --git a/private/windbg/eecxx/p_ppc/deblexer.c b/private/windbg/eecxx/p_ppc/deblexer.c
new file mode 100644
index 000000000..ff7c6172e
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/deblexer.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\deblexer.c"
diff --git a/private/windbg/eecxx/p_ppc/debparse.c b/private/windbg/eecxx/p_ppc/debparse.c
new file mode 100644
index 000000000..51a2946b8
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debparse.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debparse.c"
diff --git a/private/windbg/eecxx/p_ppc/debsrch.c b/private/windbg/eecxx/p_ppc/debsrch.c
new file mode 100644
index 000000000..5d2c07357
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debsrch.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsrch.c"
diff --git a/private/windbg/eecxx/p_ppc/debsup.c b/private/windbg/eecxx/p_ppc/debsup.c
new file mode 100644
index 000000000..8cd0505e4
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debsup.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsup.c"
diff --git a/private/windbg/eecxx/p_ppc/debsym.c b/private/windbg/eecxx/p_ppc/debsym.c
new file mode 100644
index 000000000..f3c3a1795
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debsym.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debsym.c"
diff --git a/private/windbg/eecxx/p_ppc/debtree.c b/private/windbg/eecxx/p_ppc/debtree.c
new file mode 100644
index 000000000..9682617d8
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debtree.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtree.c"
diff --git a/private/windbg/eecxx/p_ppc/debtyper.c b/private/windbg/eecxx/p_ppc/debtyper.c
new file mode 100644
index 000000000..b8665d7b0
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debtyper.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debtyper.c"
diff --git a/private/windbg/eecxx/p_ppc/debutil.c b/private/windbg/eecxx/p_ppc/debutil.c
new file mode 100644
index 000000000..e20298030
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debutil.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debutil.c"
diff --git a/private/windbg/eecxx/p_ppc/debwalk.c b/private/windbg/eecxx/p_ppc/debwalk.c
new file mode 100644
index 000000000..3e6f59867
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/debwalk.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\debwalk.c"
diff --git a/private/windbg/eecxx/p_ppc/eecxx.rc b/private/windbg/eecxx/p_ppc/eecxx.rc
new file mode 100644
index 000000000..170fc3f94
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/eecxx.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Expression Evaluator (C++) for WinDbg"
+#define VER_INTERNALNAME_STR "eecxx.dll\0"
+#define VER_ORIGINALFILENAME_STR "eecxx.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/eecxx/p_ppc/eecxxppc.def b/private/windbg/eecxx/p_ppc/eecxxppc.def
new file mode 100644
index 000000000..a884cf357
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/eecxxppc.def
@@ -0,0 +1,4 @@
+LIBRARY eecxxppc initinstance
+EXPORTS
+ EEInitializeExpr PRIVATE
+ DBGVersionCheck PRIVATE
diff --git a/private/windbg/eecxx/p_ppc/eeformat.c b/private/windbg/eecxx/p_ppc/eeformat.c
new file mode 100644
index 000000000..49e09b217
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/eeformat.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\eeformat.c"
diff --git a/private/windbg/eecxx/p_ppc/makefile b/private/windbg/eecxx/p_ppc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/eecxx/p_ppc/makefile.inc b/private/windbg/eecxx/p_ppc/makefile.inc
new file mode 100644
index 000000000..62f1832fd
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/makefile.inc
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..\..\eecan
+# SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/eecxx/p_ppc/precomp.h b/private/windbg/eecxx/p_ppc/precomp.h
new file mode 100644
index 000000000..429e40172
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef USE_BASED
+#define _based(a) ERROR
+#endif
+
+#include "types.h"
+#include "cvtypes.hxx"
+#include "cvinfo.h"
+#include "shapi.hxx"
+#include "eeapi.h"
+#include "debdef.h"
+#include "shfunc.h"
+#include "r10math.h"
+
+#include "rtlproto.h"
+
+#include "debexpr.h"
+#include "dbgver.h"
+#include "debsym.h"
+#include <limits.h>
+#include "cv.h"
+#include <errno.h>
+
diff --git a/private/windbg/eecxx/p_ppc/r10math.c b/private/windbg/eecxx/p_ppc/r10math.c
new file mode 100644
index 000000000..b53243c34
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/r10math.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\..\eecan\r10math.c"
diff --git a/private/windbg/eecxx/p_ppc/sources b/private/windbg/eecxx/p_ppc/sources
new file mode 100644
index 000000000..9f40014bf
--- /dev/null
+++ b/private/windbg/eecxx/p_ppc/sources
@@ -0,0 +1,74 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=eecxxppc
+
+TARGETNAME=eecxxppc
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+##
+## If you add a common source file to eecan, BE SURE to
+## add a line in eecan\common.inc at the same time as you
+## add one here!!
+##
+SOURCES= debapi.c \
+ debbind.c \
+ deberr.c \
+ debeval.c \
+ debfmt.c \
+ deblex.c \
+ deblexer.c \
+ debparse.c \
+ debsrch.c \
+ debsup.c \
+ debsym.c \
+ debtree.c \
+ debtyper.c \
+ debutil.c \
+ debwalk.c \
+ eeformat.c \
+ r10math.c \
+ eecxx.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include;\
+ ..\..\eecan; \
+ ..\..\lib; \
+ ..\..\real10
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_PPC
+
+TARGETLIBS= \
+ ..\..\lib\obj\*\mathlib.lib \
+ $(MORE_LIBS)
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/em/biavst.h b/private/windbg/em/biavst.h
new file mode 100644
index 000000000..633edd283
--- /dev/null
+++ b/private/windbg/em/biavst.h
@@ -0,0 +1,158 @@
+#include "stdarg.h"
+#include "heap.h"
+
+#undef i386
+#undef _X86_
+#undef MIPS
+#undef _MIPS_
+#undef ALPHA
+#undef _ALPHA_
+#undef PPC
+#undef _PPC_
+
+
+//
+// _X86_ causes:
+// nt.h include "nti386.h"
+// nti386.h an x86 typedef for _DBGKD_CONTROL_REPORT et al
+// nti386.h the 386 CONTEXT record and friends
+//
+// _ALPHA_ causes:
+// ntdef.h UNALIGNED to be defined as __unaligned
+// nt.h include "ntalpha.h"
+// ntalpha.h an alpha typedef for _DBGKD_CONTROL_REPORT et al
+// ntalpha.h the alpha CONTEXT record and friends
+//
+// _MIPS_ causes:
+// nt.h include "ntmips.h"
+// ntdef.h UNALIGNED to be defined as __unaligned
+// ntmips.h _cdecl to be defined as ""
+// ntmips.h ifdef MIPS:
+// a MIPS typedef for _DBGKD_CONTROL_REPORT et al
+// the MIPS CONTEXT record and friends
+//
+// _PPC_ causes:
+// ntdef.h UNALIGNED to be defined as __unaligned
+// nt.h include "ntppc.h"
+// ntppc.h a ppc typedef for _DBGKD_CONTROL_REPORT et al
+// ntppc.h the ppc CONTEXT record and friends
+//
+//
+
+
+
+#if defined(TARGET_MIPS)
+
+#define _MIPS_ 1
+
+#if defined(HOST_MIPS)
+#define MIPS 1
+#endif
+
+#if defined(HOST_i386)
+#define __unaligned
+#endif
+
+
+#include <windows.h>
+#include <windbgkd.h>
+#include <imagehlp.h>
+
+#if !defined(HOST_MIPS)
+#undef MIPS
+#undef _MIPS_
+#endif
+
+#if defined(HOST_i386)
+#undef _cdecl
+#undef UNALIGNED
+#define UNALIGNED
+#endif
+
+#elif defined(TARGET_PPC)
+
+#define _PPC_ 1
+
+#if defined(HOST_MIPS)
+#define MIPS 1
+#endif
+
+#if defined(HOST_i386)
+#define __unaligned
+#endif
+
+
+#include <windows.h>
+#include <windbgkd.h>
+#include <imagehlp.h>
+
+#if !defined(HOST_MIPS)
+#undef MIPS
+#undef _MIPS_
+#endif
+
+#if defined(HOST_i386)
+#undef _cdecl
+#undef UNALIGNED
+#define UNALIGNED
+#endif
+
+#elif defined(TARGET_i386)
+
+#define _X86_ 1
+
+#if defined(HOST_MIPS)
+#define MIPS 1
+#endif
+
+#include <windows.h>
+#include <windbgkd.h>
+#include <imagehlp.h>
+
+#if defined(HOST_MIPS)
+#undef _cdecl
+#define _cdecl
+#endif
+
+#if defined(HOST_ALPHA)
+#undef _cdecl
+#define _cdecl
+#endif
+
+
+#elif defined(TARGET_ALPHA)
+
+#define _ALPHA_ 1
+
+#if defined(HOST_i386)
+#define __unaligned
+#endif
+
+#if defined(HOST_MIPS)
+#define MIPS 1
+#endif
+
+#include <windows.h>
+#include <windbgkd.h>
+#include <imagehlp.h>
+
+#if defined(HOST_MIPS)
+#undef _cdecl
+#define _cdecl
+#endif
+
+#if defined(HOST_i386)
+#undef UNALIGNED
+#define UNALIGNED
+#endif
+
+#if !defined(HOST_ALPHA)
+#undef _ALPHA_
+#endif
+
+
+#else
+
+#error "Unsupported target CPU"
+
+#endif
diff --git a/private/windbg/em/common.inc b/private/windbg/em/common.inc
new file mode 100644
index 000000000..af7e191a9
--- /dev/null
+++ b/private/windbg/em/common.inc
@@ -0,0 +1,39 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ common.inc
+
+Abstract:
+
+ This is an include file for makefile.inc in each of the
+ directories which has c files that are wrappers for the
+ files in this directory. The WRAPPEDCOBJECTS macro contains
+ a list of the objects which are dependent on the files
+ in this directory.
+
+ SRCDIR must be defined in each makefile.inc, and will
+ always point to the directory that this file is in.
+
+
+Author:
+
+ Kent Forschmiedt
+
+!ENDIF
+
+
+WRAPPEDCOBJECTS = \
+ obj\*\emdp.obj \
+ obj\*\emdp2.obj \
+ obj\*\strings.obj \
+ obj\*\wintrans.obj
+
+$(WRAPPEDCOBJECTS:*=i386): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=mips): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=alpha): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=ppc): $(SRCDIR)\$$(@B).c
+
+obj\$(TARET_DIRECTORY)\emdp.obj: regs.h flags.h strings.h
diff --git a/private/windbg/em/dirs b/private/windbg/em/dirs
new file mode 100644
index 000000000..8600acb15
--- /dev/null
+++ b/private/windbg/em/dirs
@@ -0,0 +1,20 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= p_i386 \
+ p_mips \
+ p_alpha \
+ p_ppc
+
diff --git a/private/windbg/em/em.rc b/private/windbg/em/em.rc
new file mode 100644
index 000000000..7a167135a
--- /dev/null
+++ b/private/windbg/em/em.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Execution Model for WinDbg"
+#define VER_INTERNALNAME_STR "em.dll\0"
+#define VER_ORIGINALFILENAME_STR "em.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/em/emdata.h b/private/windbg/em/emdata.h
new file mode 100644
index 000000000..990ded56d
--- /dev/null
+++ b/private/windbg/em/emdata.h
@@ -0,0 +1,286 @@
+#ifndef _EMDATA
+#define _EMDATA
+
+/*
+** These are handles to structures. The structures are different in
+** the EM and the DM
+*/
+
+typedef HLLE HPRC;
+typedef HLLE HTHD;
+typedef HLLE HEXD;
+
+
+
+#ifdef HOSTDOS32
+#define EMENTRY far pascal
+#else
+#define EMENTRY PASCAL LOADDS
+#endif
+
+#define IsSegEqual(seg1,seg2) ( (seg1) == (seg2) )
+#define FP_SEG(fp) (*((unsigned _far *)&(fp)+1))
+#define FP_OFF(fp) (*((unsigned _far *)&(fp)))
+
+typedef enum {
+ statStarted,
+ statRunning,
+ statStopped,
+ statDead
+} STAT; // process STATus
+
+typedef enum {
+ efpNone,
+ efpEmulator,
+ efpChip
+} EFP; // Existence of Floating Point chip or emulator
+
+
+// Global Segment Info table
+typedef struct _sgf {
+ union {
+ struct {
+ unsigned short fRead :1;
+ unsigned short fWrite :1;
+ unsigned short fExecute:1;
+ unsigned short f32Bit :1;
+ unsigned short res1 :4;
+ unsigned short fSel :1;
+ unsigned short fAbs :1;
+ unsigned short res2 :2;
+ unsigned short fGroup :1;
+ unsigned short res3 :3;
+ } u1;
+ struct {
+ unsigned short segAttr :8;
+ unsigned short saAttr :4;
+ unsigned short misc :4;
+ } u2;
+ } u;
+} SGF;
+
+typedef struct _sgi {
+ SGF sgf; // Segment flags
+ unsigned short iovl; // Overlay number
+ unsigned short igr; // Group index
+ unsigned short isgPhy; // Physical segment index
+ unsigned short isegName; // Index to segment name
+ unsigned short iclassName; // Index to segment class name
+ unsigned long doffseg; // Starting offset inside physical segment
+ unsigned long cbSeg; // Logical segment size
+} SGI;
+
+typedef SGI FAR * LPSGI;
+
+typedef struct _GSI {
+ unsigned short csgMax;
+ unsigned short csgLogical;
+ SGI rgsgi[];
+} GSI;
+
+typedef GSI FAR * LPGSI;
+
+
+/*
+ * This structure is used by the EM to describe all of the relevant
+ * information for an executable object.
+ *
+ */
+
+typedef struct _MDI {
+ WORD mte; /* Unique handle identifing the DLL */
+ unsigned short pad0; /* PAD */
+ DWORD lpBaseOfDll;/* Base offset of the DLL */
+ DWORD dwSizeOfDll;
+ SEGMENT StartingSegment; // Starting segment for real mode
+
+ SEGMENT CSSel; /* FLAT CS selector */
+ SEGMENT DSSel; /* FLAT DS selector */
+
+ DWORD cobj; /* Count of objects (sections) in the DLL */
+ OBJD * rgobjd; /* Array of object (section) descriptors */
+
+ LPGSI lpgsi; /* Symbol handler description of sections */
+ LPDEBUGDATA lpDebug; /* fpo/pdata/omap info */
+ HEMI hemi; /* Handle to the symbol handle description */
+ LSZ lszName; /* Name of DLL */
+
+ BOOL fFlatMode; /* Is this dll 0:32 or 16:32 addressing */
+ BOOL fRealMode; /* Is this dll real mode? */
+ BOOL fOffset32; /* Is this dll offset 32? */
+} MDI; // Module Info
+typedef MDI FAR *LPMDI;
+typedef HIND HMDI;
+
+#define hmdiNull ((HMDI) 0)
+
+typedef struct _PRC {
+ HPID hpid;
+ PID pid;
+ BOOL fRunning;
+ ADDR addrTaskData;
+ ADDR addrFPArray;
+#ifndef OSDEBUG4
+ ADDR addrCurrent; // used with set/get adrCurrent for htid == htidNull
+#endif
+ BOOL fDmiCache;
+ DMINFO dmi; // debug metric info
+ HLLI llthd;
+ HLLI llmdi;
+ HLLI llexc;
+ STAT stat;
+ WORD cFPThread;
+ SEGMENT selFlatCs; /* The one and only FLAT code selector */
+ SEGMENT selFlatDs; /* The one and only FLAT data selector */
+} PRC;
+typedef PRC FAR *LPPRC; // Process information
+typedef HPRC FAR *LPHPRC;
+
+#define hprcNull 0
+#define hprcInvalid (HPRC)(-1)
+
+/*
+ * The THD structure contains the information which describes the
+ * internal state of a debuggee thread.
+ */
+
+//
+// For specifying the frame number
+// If the frame number is 0, use "regs", not "frameRegs"
+//
+
+#ifndef OSDEBUG4
+#define CURRENT_FRAME 0
+#define INVALID_FRAME -1
+#endif
+
+typedef enum {
+ drtNonePresent = 0, /* No registers present */
+ drtCntrlPresent = 1, /* Control registers are present */
+ drtAllPresent = 2, /* All registers are present */
+ drtSpecialPresent = 4, /* Kernel specials are present */
+ drtCntrlDirty = 0x10, /* Control registers are dirty */
+ drtAllDirty = 0x20, /* Non-control register dirty */
+ drtSpecialDirty = 0x40, /* Kernel special regs dirty */
+} DRT; // DiRTy registers
+
+typedef struct _THD {
+ HTID htid; // WinDbg thread identifier
+ TID tid; // System thread identifier
+ HPRC hprc; // System process identifier
+ BOOL fVirtual:1; // Thread has been terminated and does
+ // not really exist anymore
+ BOOL fFlat:1; // Current context is in 0:32 bit mode
+ BOOL fOff32:1; // Current context is 32-bit offset
+ BOOL fReal:1; // Current context is in real mode
+ BOOL fRunning:1; // Thread is thought to be executing
+#ifndef OSDEBUG4
+ ADDR addrCurrent; // adrCurrent Address maintained on a
+ // per thread basis
+#endif
+ DRT drt; // Thread dirty status flags
+ ADDR addrTls; // Address of TLS data
+ CONTEXT regs; // Last known context of thread
+#ifndef OSDEBUG4
+ DWORD frameNumber; // frame number
+ CONTEXT frameRegs; // Regs for frameNumber
+ KNONVOLATILE_CONTEXT_POINTERS
+ frameRegPtrs; // Pointers to last place register saved.
+#endif
+ PVOID pvSpecial; // kernel mode data
+ DWORD dwcbSpecial; // size of special data
+} THD;
+typedef THD FAR *LPTHD; // Thread information
+typedef HTHD FAR *LPHTHD;
+
+#define hthdNull ((HTHD) 0)
+#define hthdInvalid ((HTHD)(-1))
+
+/*
+ *
+ */
+
+#pragma pack ( 1 )
+
+typedef struct _EMC {
+ WORD wControl; // Control word.
+ WORD wStatus; // Status word.
+ WORD BASstk; // base of emulator stack
+ WORD CURstk; // current stack element
+ WORD LIMstk; // limit of stack
+} EMC; // Emulator control
+
+
+typedef struct _EME {
+ WORD rgwMantissa [ 4 ];
+ union {
+ WORD wExponent;
+ struct {
+ WORD wExpPad : 15;
+ WORD bitExpSign : 1;
+ } u;
+ } u;
+ BYTE fSingle : 1;
+ BYTE flagpad : 6;
+ BYTE fSign : 1;
+ BYTE tag : 2;
+ BYTE tagpad : 6;
+} EME; // Emulator element
+
+#pragma pack ( )
+
+
+typedef enum {
+ emdiName,
+ emdiEMI,
+ emdiMTE,
+ emdiBaseAddr
+} EMDI;
+
+
+
+/*
+ * The following structure is used for doing function evaluation
+ */
+
+typedef struct _EXECUTE_OBJECT_EM {
+ CONTEXT regs; /* save register area */
+ HTHD hthd; /* thread execution is on */
+ HIND heoDm; /* execute object from DM */
+} EXECUTE_OBJECT_EM;
+
+typedef EXECUTE_OBJECT_EM FAR * LP_EXECUTE_OBJECT_EM;
+
+//
+// flag description structure. contains a register description
+// and the shift count to the rightmost bit in the flag.
+//
+struct RGFD {
+ FD fd;
+ USHORT iShift;
+};
+
+extern LPDBF lpdbf;
+extern LPFNSVC lpfnsvcTL;
+
+extern HLLI llpid;
+
+extern HLLI llprc;
+
+extern HPRC hprcCurr;
+extern HPID hpidCurr;
+extern PID pidCurr;
+
+extern HTHD hthdCurr;
+extern HTID htidCurr;
+extern TID tidCurr;
+
+#define cbBufferDef 525
+extern DWORD cbBuffer;
+extern LPDM_MSG LpDmMsg;
+
+extern XOSD (PASCAL LOADDS *CallTL) ( TLF, HPID, DWORD, LPV );
+extern XOSD (PASCAL LOADDS *CallDB) ( DBC, HPID, HTID, DWORD, DWORD, LPV );
+extern XOSD (PASCAL LOADDS *CallNT) ( EMF, HPID, HTID, DWORD, LPV );
+
+#endif // _EMDATA
diff --git a/private/windbg/em/emdp.c b/private/windbg/em/emdp.c
new file mode 100644
index 000000000..1a9564ed2
--- /dev/null
+++ b/private/windbg/em/emdp.c
@@ -0,0 +1,3971 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ emdp.c
+
+Abstract:
+
+ This file contains the main driver for the native execution models
+ supported by us. This file additionally contains the machine
+ independent portions of the execution model. The machine dependent
+ portions are in other files.
+
+Author:
+
+ Jim Schaad (jimsch) 05-23-92
+
+Environment:
+
+ Win32 -- User
+
+Notes:
+
+ The orginal source for this came from the CodeView group.
+
+--*/
+
+#include "strings.h"
+
+#ifdef FE_IME
+#include <ime.h>
+#endif
+
+/*************************** DEFINES *****************************/
+
+#define CBBUFFERDEF 1024
+#define CEXM_MDL_native 0x20
+#define cchErrMax 50
+
+/******************* TYPEDEFS and STRUCTURE ***********************/
+
+/*********************** LOCAL DATA *******************************/
+
+CRITICAL_SECTION csCache;
+
+LPBYTE LpSendBuf = NULL;
+DWORD CbSendBuf = 0;
+
+DWORD CbDmMsg = 0;
+LPDM_MSG LpDmMsg = NULL;
+
+LPDBF lpdbf = (LPDBF)NULL;
+
+LPFNSVC lpfnsvcTL = (LPFNSVC)NULL;
+XOSD (PASCAL LOADDS *CallTL) ( TLF, HPID, DWORD, LPV );
+XOSD (PASCAL LOADDS *CallDB) ( DBC, HPID, HTID, DWORD, DWORD, LPV );
+XOSD (PASCAL LOADDS *CallNT) ( EMF, HPID, HTID, DWORD, LPV );
+
+HLLI llprc = (HLLI)NULL;
+
+HPRC hprcCurr = 0;
+HPID hpidCurr = 0;
+PID pidCurr = 0;
+
+HTHD hthdCurr = 0;
+HTID htidCurr = 0;
+TID tidCurr = 0;
+
+HLLI HllEo = (HLLI) NULL;
+
+API_VERSION ApiVersionForImagehlp = { 3, 5, API_VERSION_NUMBER, 0 };
+
+#ifdef OSDEBUG4
+
+LOADDMSTRUCT LoadDmStruct = {
+ "dm.dll"
+};
+
+#endif
+
+
+#ifdef OSDEBUG4
+
+#define DECL_MASK(n,v,s) n = v,
+#define DECL_MSG(n,s,m)
+
+enum {
+#include "win32msg.h"
+};
+
+#undef DECL_MASK
+#define DECL_MASK(n,v,s) { n, s },
+
+MASKINFO MaskInfo[] = {
+#include "win32msg.h"
+};
+
+#define MASKMAPSIZE (sizeof(MaskInfo)/sizeof(MASKINFO))
+MASKMAP MaskMap = {MASKMAPSIZE, MaskInfo};
+
+#undef DECL_MASK
+#undef DECL_MSG
+
+
+#define DECL_MASK(n,v,s)
+#define DECL_MSG(n,s,m) { n, s, m },
+
+MESSAGEINFO MessageInfo[] = {
+#include "win32msg.h"
+};
+
+#define MESSAGEMAPSIZE (sizeof(MessageInfo)/sizeof(MESSAGEINFO))
+MESSAGEMAP MessageMap = {MESSAGEMAPSIZE,MessageInfo};
+
+#undef DECL_MASK
+#undef DECL_MSG
+
+
+#else // OSDEBUG4
+
+MSGINFO MsgInfo[] = {
+ WM_NULL , "WM_NULL" , MSG_TYPE_OTHER ,
+ WM_CREATE , "WM_CREATE" , MSG_TYPE_WINDOW ,
+ WM_DESTROY , "WM_DESTROY" , MSG_TYPE_WINDOW ,
+ WM_MOVE , "WM_MOVE" , MSG_TYPE_WINDOW ,
+ WM_SIZE , "WM_SIZE" , MSG_TYPE_WINDOW ,
+ WM_ACTIVATE , "WM_ACTIVATE" , MSG_TYPE_WINDOW ,
+ WM_SETFOCUS , "WM_SETFOCUS" , MSG_TYPE_WINDOW ,
+ WM_KILLFOCUS , "WM_KILLFOCUS" , MSG_TYPE_WINDOW ,
+ WM_ENABLE , "WM_ENABLE" , MSG_TYPE_WINDOW ,
+ WM_SETREDRAW , "WM_SETREDRAW" , MSG_TYPE_WINDOW ,
+ WM_SETTEXT , "WM_SETTEXT" , MSG_TYPE_WINDOW ,
+ WM_GETTEXT , "WM_GETTEXT" , MSG_TYPE_WINDOW ,
+ WM_GETTEXTLENGTH , "WM_GETTEXTLENGTH" , MSG_TYPE_WINDOW ,
+ WM_PAINT , "WM_PAINT" , MSG_TYPE_WINDOW ,
+ WM_CLOSE , "WM_CLOSE" , MSG_TYPE_WINDOW ,
+ WM_QUERYENDSESSION , "WM_QUERYENDSESSION" , MSG_TYPE_WINDOW ,
+ WM_QUIT , "WM_QUIT" , MSG_TYPE_WINDOW ,
+ WM_QUERYOPEN , "WM_QUERYOPEN" , MSG_TYPE_WINDOW ,
+ WM_ERASEBKGND , "WM_ERASEBKGND" , MSG_TYPE_WINDOW ,
+ WM_SYSCOLORCHANGE , "WM_SYSCOLORCHANGE" , MSG_TYPE_SYSTEM ,
+ WM_ENDSESSION , "WM_ENDSESSION" , MSG_TYPE_SYSTEM ,
+ WM_SHOWWINDOW , "WM_SHOWWINDOW" , MSG_TYPE_WINDOW ,
+ WM_WININICHANGE , "WM_WININICHANGE" , MSG_TYPE_SYSTEM ,
+
+ WM_DEVMODECHANGE , "WM_DEVMODECHANGE" , MSG_TYPE_SYSTEM ,
+ WM_ACTIVATEAPP , "WM_ACTIVATEAPP" , MSG_TYPE_WINDOW ,
+ WM_FONTCHANGE , "WM_FONTCHANGE" , MSG_TYPE_SYSTEM ,
+ WM_TIMECHANGE , "WM_TIMECHANGE" , MSG_TYPE_SYSTEM ,
+ WM_CANCELMODE , "WM_CANCELMODE" , MSG_TYPE_WINDOW ,
+ WM_SETCURSOR , "WM_SETCURSOR" , MSG_TYPE_MOUSE ,
+ WM_MOUSEACTIVATE , "WM_MOUSEACTIVATE" , MSG_TYPE_MOUSE ,
+ WM_CHILDACTIVATE , "WM_CHILDACTIVATE" , MSG_TYPE_WINDOW ,
+ WM_QUEUESYNC , "WM_QUEUESYNC" , MSG_TYPE_SYSTEM ,
+ WM_GETMINMAXINFO , "WM_GETMINMAXINFO" , MSG_TYPE_WINDOW ,
+ WM_PAINTICON , "WM_PAINTICON" , MSG_TYPE_WINDOW ,
+ WM_ICONERASEBKGND , "WM_ICONERASEBKGND" , MSG_TYPE_WINDOW ,
+ WM_NEXTDLGCTL , "WM_NEXTDLGCTL" , MSG_TYPE_WINDOW ,
+ WM_SPOOLERSTATUS , "WM_SPOOLERSTATUS" , MSG_TYPE_OTHER ,
+ WM_DRAWITEM , "WM_DRAWITEM" , MSG_TYPE_WINDOW ,
+ WM_MEASUREITEM , "WM_MEASUREITEM" , MSG_TYPE_WINDOW ,
+ WM_DELETEITEM , "WM_DELETEITEM" , MSG_TYPE_WINDOW ,
+ WM_VKEYTOITEM , "WM_VKEYTOITEM" , MSG_TYPE_WINDOW ,
+ WM_CHARTOITEM , "WM_CHARTOITEM" , MSG_TYPE_WINDOW ,
+ WM_SETFONT , "WM_SETFONT" , MSG_TYPE_WINDOW ,
+ WM_GETFONT , "WM_GETFONT" , MSG_TYPE_WINDOW ,
+ WM_SETHOTKEY , "WM_SETHOTKEY" , MSG_TYPE_INPUT ,
+ WM_GETHOTKEY , "WM_GETHOTKEY" , MSG_TYPE_INPUT ,
+ WM_QUERYDRAGICON , "WM_QUERYDRAGICON" , MSG_TYPE_WINDOW ,
+ WM_COMPAREITEM , "WM_COMPAREITEM" , MSG_TYPE_WINDOW ,
+ WM_COMPACTING , "WM_COMPACTING" , MSG_TYPE_SYSTEM ,
+ // WM_OTHERWINDOWCREATED , "WM_OTHERWINDOWCREATED" , MSG_TYPE_SYSTEM ,
+ // WM_OTHERWINDOWDESTROYED , "WM_OTHERWINDOWDESTROYED" , MSG_TYPE_SYSTEM ,
+ // WM_COMMNOTIFY , "WM_COMMNOTIFY" , MSG_TYPE_SYSTEM ,
+ // WM_HOTKEYEVENT , "WM_HOTKEYEVENT" , MSG_TYPE_SYSTEM ,
+ WM_WINDOWPOSCHANGING , "WM_WINDOWPOSCHANGING" , MSG_TYPE_WINDOW ,
+ WM_WINDOWPOSCHANGED , "WM_WINDOWPOSCHANGED" , MSG_TYPE_WINDOW ,
+ WM_POWER , "WM_POWER" , MSG_TYPE_SYSTEM ,
+ WM_COPYDATA , "WM_COPYDATA" , MSG_TYPE_SYSTEM ,
+ WM_CANCELJOURNAL , "WM_CANCELJOURNAL" , MSG_TYPE_SYSTEM ,
+ WM_NCCREATE , "WM_NCCREATE" , MSG_TYPE_NONCLIENT ,
+ WM_NCDESTROY , "WM_NCDESTROY" , MSG_TYPE_NONCLIENT ,
+ WM_NCCALCSIZE , "WM_NCCALCSIZE" , MSG_TYPE_NONCLIENT ,
+ WM_NCHITTEST , "WM_NCHITTEST" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCPAINT , "WM_NCPAINT" , MSG_TYPE_NONCLIENT ,
+ WM_NCACTIVATE , "WM_NCACTIVATE" , MSG_TYPE_NONCLIENT ,
+ WM_GETDLGCODE , "WM_GETDLGCODE" , MSG_TYPE_WINDOW ,
+ WM_NCMOUSEMOVE , "WM_NCMOUSEMOVE" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCLBUTTONDOWN , "WM_NCLBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCLBUTTONUP , "WM_NCLBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCLBUTTONDBLCLK , "WM_NCLBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCRBUTTONDOWN , "WM_NCRBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCRBUTTONUP , "WM_NCRBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCRBUTTONDBLCLK , "WM_NCRBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCMBUTTONDOWN , "WM_NCMBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCMBUTTONUP , "WM_NCMBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_NCMBUTTONDBLCLK , "WM_NCMBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE ,
+ WM_KEYDOWN , "WM_KEYDOWN" , MSG_TYPE_INPUT ,
+ WM_KEYUP , "WM_KEYUP" , MSG_TYPE_INPUT ,
+ WM_CHAR , "WM_CHAR" , MSG_TYPE_INPUT ,
+ WM_DEADCHAR , "WM_DEADCHAR" , MSG_TYPE_INPUT ,
+ WM_SYSKEYDOWN , "WM_SYSKEYDOWN" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
+ WM_SYSKEYUP , "WM_SYSKEYUP" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
+ WM_SYSCHAR , "WM_SYSCHAR" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
+ WM_SYSDEADCHAR , "WM_SYSDEADCHAR" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT ,
+ WM_INITDIALOG , "WM_INITDIALOG" , MSG_TYPE_INIT ,
+ WM_COMMAND , "WM_COMMAND" , MSG_TYPE_INPUT ,
+ WM_SYSCOMMAND , "WM_SYSCOMMAND" , MSG_TYPE_SYSTEM ,
+ WM_TIMER , "WM_TIMER" , MSG_TYPE_INPUT ,
+ WM_HSCROLL , "WM_HSCROLL" , MSG_TYPE_INPUT ,
+ WM_VSCROLL , "WM_VSCROLL" , MSG_TYPE_INPUT ,
+ WM_INITMENU , "WM_INITMENU" , MSG_TYPE_INIT ,
+ WM_INITMENUPOPUP , "WM_INITMENUPOPUP" , MSG_TYPE_INIT ,
+ WM_MENUSELECT , "WM_MENUSELECT" , MSG_TYPE_INPUT ,
+ WM_MENUCHAR , "WM_MENUCHAR" , MSG_TYPE_INPUT ,
+ WM_ENTERIDLE , "WM_ENTERIDLE" , MSG_TYPE_SYSTEM ,
+ WM_CTLCOLORMSGBOX , "WM_CTLCOLORMSGBOX" , MSG_TYPE_WINDOW ,
+ WM_CTLCOLOREDIT , "WM_CTLCOLOREDIT" , MSG_TYPE_WINDOW ,
+ WM_CTLCOLORLISTBOX , "WM_CTLCOLORLISTBOX" , MSG_TYPE_WINDOW ,
+ WM_CTLCOLORBTN , "WM_CTLCOLORBTN" , MSG_TYPE_WINDOW ,
+ WM_CTLCOLORDLG , "WM_CTLCOLORDLG" , MSG_TYPE_WINDOW ,
+ WM_CTLCOLORSCROLLBAR , "WM_CTLCOLORSCROLLBAR" , MSG_TYPE_WINDOW ,
+ WM_CTLCOLORSTATIC , "WM_CTLCOLORSTATIC" , MSG_TYPE_WINDOW ,
+ WM_MOUSEMOVE , "WM_MOUSEMOVE" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_LBUTTONDOWN , "WM_LBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_LBUTTONUP , "WM_LBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_LBUTTONDBLCLK , "WM_LBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_RBUTTONDOWN , "WM_RBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_RBUTTONUP , "WM_RBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_RBUTTONDBLCLK , "WM_RBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_MBUTTONDOWN , "WM_MBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_MBUTTONUP , "WM_MBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_MBUTTONDBLCLK , "WM_MBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ WM_PARENTNOTIFY , "WM_PARENTNOTIFY" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE ,
+ //WM_ENTERMENULOOP , "WM_ENTERMENULOOP" , MSG_TYPE_SYSTEM ,
+ //WM_EXITMENULOOP , "WM_EXITMENULOOP" , MSG_TYPE_SYSTEM ,
+ WM_MDICREATE , "WM_MDICREATE" , MSG_TYPE_WINDOW ,
+ WM_MDIDESTROY , "WM_MDIDESTROY" , MSG_TYPE_WINDOW ,
+ WM_MDIACTIVATE , "WM_MDIACTIVATE" , MSG_TYPE_WINDOW ,
+ WM_MDIRESTORE , "WM_MDIRESTORE" , MSG_TYPE_WINDOW ,
+ WM_MDINEXT , "WM_MDINEXT" , MSG_TYPE_WINDOW ,
+ WM_MDIMAXIMIZE , "WM_MDIMAXIMIZE" , MSG_TYPE_WINDOW ,
+ WM_MDITILE , "WM_MDITILE" , MSG_TYPE_WINDOW ,
+ WM_MDICASCADE , "WM_MDICASCADE" , MSG_TYPE_WINDOW ,
+ WM_MDIICONARRANGE , "WM_MDIICONARRANGE" , MSG_TYPE_WINDOW ,
+ WM_MDIGETACTIVE , "WM_MDIGETACTIVE" , MSG_TYPE_WINDOW ,
+ WM_MDISETMENU , "WM_MDISETMENU" , MSG_TYPE_WINDOW ,
+ WM_DROPFILES , "WM_DROPFILES" , MSG_TYPE_WINDOW ,
+ WM_MDIREFRESHMENU , "WM_MDIREFRESHMENU" , MSG_TYPE_WINDOW ,
+ WM_CUT , "WM_CUT" , MSG_TYPE_CLIPBOARD ,
+ WM_COPY , "WM_COPY" , MSG_TYPE_CLIPBOARD ,
+ WM_PASTE , "WM_PASTE" , MSG_TYPE_CLIPBOARD ,
+ WM_CLEAR , "WM_CLEAR" , MSG_TYPE_CLIPBOARD ,
+ WM_UNDO , "WM_UNDO" , MSG_TYPE_CLIPBOARD ,
+ WM_RENDERFORMAT , "WM_RENDERFORMAT" , MSG_TYPE_CLIPBOARD ,
+ WM_RENDERALLFORMATS , "WM_RENDERALLFORMATS" , MSG_TYPE_CLIPBOARD ,
+ WM_DESTROYCLIPBOARD , "WM_DESTROYCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
+ WM_DRAWCLIPBOARD , "WM_DRAWCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
+ WM_PAINTCLIPBOARD , "WM_PAINTCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
+ WM_VSCROLLCLIPBOARD , "WM_VSCROLLCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
+ WM_SIZECLIPBOARD , "WM_SIZECLIPBOARD" , MSG_TYPE_CLIPBOARD ,
+ WM_ASKCBFORMATNAME , "WM_ASKCBFORMATNAME" , MSG_TYPE_CLIPBOARD ,
+ WM_CHANGECBCHAIN , "WM_CHANGECBCHAIN" , MSG_TYPE_CLIPBOARD ,
+ WM_HSCROLLCLIPBOARD , "WM_HSCROLLCLIPBOARD" , MSG_TYPE_CLIPBOARD ,
+ WM_QUERYNEWPALETTE , "WM_QUERYNEWPALETTE" , MSG_TYPE_WINDOW ,
+ WM_PALETTEISCHANGING , "WM_PALETTEISCHANGING" , MSG_TYPE_WINDOW ,
+ WM_PALETTECHANGED , "WM_PALETTECHANGED" , MSG_TYPE_WINDOW ,
+ WM_HOTKEY , "WM_HOTKEY" , MSG_TYPE_WINDOW ,
+ WM_DDE_INITIATE , "WM_DDE_INITIATE" , MSG_TYPE_DDE ,
+ WM_DDE_TERMINATE , "WM_DDE_TERMINATE" , MSG_TYPE_DDE ,
+ WM_DDE_ADVISE , "WM_DDE_ADVISE" , MSG_TYPE_DDE ,
+ WM_DDE_UNADVISE , "WM_DDE_UNADVISE" , MSG_TYPE_DDE ,
+ WM_DDE_ACK , "WM_DDE_ACK" , MSG_TYPE_DDE ,
+ WM_DDE_DATA , "WM_DDE_DATA" , MSG_TYPE_DDE ,
+ WM_DDE_REQUEST , "WM_DDE_REQUEST" , MSG_TYPE_DDE ,
+ WM_DDE_POKE , "WM_DDE_POKE" , MSG_TYPE_DDE ,
+ WM_DDE_EXECUTE , "WM_DDE_EXECUTE" , MSG_TYPE_DDE ,
+#ifdef FE_IME
+// we had better create IME class(e.g. MSG_TYPE_IME)
+// for the following messages.
+ WM_CONVERTREQUEST , "WM_CONVERTREQUEST" , MSG_TYPE_INPUT ,
+// WM_CONVERTREQUESTEX , "WM_CONVERTREQUESTEX" , MSG_TYPE_INPUT ,
+ WM_CONVERTRESULT , "WM_CONVERTRESULT" , MSG_TYPE_INPUT ,
+ WM_IME_REPORT , "WM_IME_REPORT" , MSG_TYPE_INPUT ,
+ WM_IMEKEYDOWN , "WM_IMEKEYDOWN" , MSG_TYPE_INPUT ,
+ WM_IMEKEYUP , "WM_IMEKEYUP" , MSG_TYPE_INPUT ,
+ WM_INTERIM , "WM_INTERIM" , MSG_TYPE_INPUT ,
+ WM_IME_CHAR , "WM_IME_CHAR" , MSG_TYPE_INPUT ,
+ WM_IME_COMPOSITION , "WM_IME_COMPOSITION" , MSG_TYPE_INPUT ,
+ WM_IME_COMPOSITIONFULL , "WM_IME_COMPOSITIONFULL" , MSG_TYPE_INPUT ,
+ WM_IME_CONTROL , "WM_IME_CONTROL" , MSG_TYPE_INPUT ,
+ WM_IME_ENDCOMPOSITION , "WM_IME_ENDCOMPOSITION" , MSG_TYPE_INPUT ,
+ WM_IME_KEYDOWN , "WM_IME_KEYDOWN" , MSG_TYPE_INPUT ,
+ WM_IME_KEYLAST , "WM_IME_KEYLAST" , MSG_TYPE_INPUT ,
+ WM_IME_KEYUP , "WM_IME_KEYUP" , MSG_TYPE_INPUT ,
+ WM_IME_NOTIFY , "WM_IME_NOTIFY" , MSG_TYPE_INPUT ,
+ WM_IME_SELECT , "WM_IME_SELECT" , MSG_TYPE_INPUT ,
+ WM_IME_SETCONTEXT , "WM_IME_SETCONTEXT" , MSG_TYPE_INPUT ,
+ WM_IME_STARTCOMPOSITION , "WM_IME_STARTCOMPOSITION" , MSG_TYPE_INPUT ,
+#endif
+
+ 0 , NULL , 0
+};
+
+MSGMAP MsgMap = {0,MsgInfo};
+
+#endif // OSDEBUG4
+
+
+/********************* EXTERNAL DATA ******************************/
+
+
+/*********************** PROTOTYPES *******************************/
+
+XOSD DoCustomCommand(HPID hpid, HTID htid, DWORD wValue, LPIOL lpiol);
+
+
+/************************** &&&&&& ********************************/
+
+/*
+ * This is the description of all registers and flags for the
+ * machine being debugged. These files are machine dependent.
+ */
+
+RD Rgrd[] = {
+#include "regs.h"
+};
+const unsigned CRgrd = (sizeof(Rgrd)/sizeof(Rgrd[0]));
+
+struct RGFD Rgfd[] = {
+#include "flags.h"
+};
+const unsigned CRgfd = (sizeof(Rgfd)/sizeof(Rgfd[0]));
+
+
+
+
+/*************************** CODE *****************************************/
+
+/**** DBGVersionCheck ****
+ * *
+ * PURPOSE: *
+ * *
+ * To export out version information to the debugger. *
+ * *
+ * INPUTS: *
+ * *
+ * NONE. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Returns - A pointer to the standard version information. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Just returns a pointer to a static structure. *
+ * *
+ ***************************************************************************/
+
+#ifdef DEBUGVER
+DEBUG_VERSION('E','M',"Execution Model")
+#else
+RELEASE_VERSION('E','M',"Execution Model")
+#endif
+
+DBGVERSIONCHECK()
+
+
+/**** SENDREQUEST - Send a request to the DM ****
+ * *
+ * PURPOSE: *
+ * Send a DMF request to the DM. *
+ * *
+ * INPUTS: *
+ * dmf - the request to send *
+ * hpid - the process *
+ * htid - the thread *
+ * *
+ * OUTPUTS: *
+ * xosd - error code indicating if request was sent successfully *
+ * LpDmMsg - global buffer filled in with returned data *
+ * *
+ * IMPLEMENTATION: *
+ * Unlike SendCommand, this function will wait for data to be *
+ * returned from the DM before returning to the caller. *
+ * *
+ ***************************************************************************/
+XOSD
+SendRequest (
+ DMF dmf,
+ HPID hpid,
+ HTID htid
+ )
+{
+ DBB dbb;
+ XOSD xosd;
+
+ dbb.dmf = dmf;
+ dbb.hpid = hpid;
+ dbb.htid = htid;
+
+ xosd = CallTL ( tlfRequest, hpid, sizeof ( DBB ), &dbb );
+
+ if (xosd != xosdNone)
+ return xosd;
+
+ xosd = (XOSD) LpDmMsg->xosdRet;
+
+ return xosd;
+}
+
+
+/**** SENDREQUESTX - Send a request with parameters to the DM ****
+ * *
+ * PURPOSE: *
+ * Send a DMF request and its parameter info to the DM. *
+ * *
+ * INPUTS: *
+ * dmf - the request to send *
+ * hpid - the process *
+ * htid - the thread *
+ * wLen - number of bytes in lpv *
+ * lpv - pointer to additional info needed by the DM; contents are *
+ * dependent on the DMF *
+ * *
+ * OUTPUTS: *
+ * xosd - error code indicating if request was sent successfully *
+ * *
+ * IMPLEMENTATION: *
+ * Unlike SendCommand, this function will wait for data to be *
+ * returned from the DM before returning to the caller. *
+ * *
+ ***************************************************************************/
+XOSD
+SendRequestX (
+ DMF dmf,
+ HPID hpid,
+ HTID htid,
+ DWORD wLen,
+ LPV lpv
+ )
+{
+ LPDBB lpdbb;
+ XOSD xosd;
+
+ if (wLen + sizeof(DBB) > CbSendBuf) {
+ if (LpSendBuf) {
+ MHFree(LpSendBuf);
+ }
+ CbSendBuf = sizeof(DBB) + wLen;
+ LpSendBuf = MHAlloc(CbSendBuf);
+ }
+
+ if (!LpSendBuf) {
+ return xosdOutOfMemory;
+ }
+
+ lpdbb = (LPDBB)LpSendBuf;
+
+ lpdbb->dmf = dmf;
+ lpdbb->hpid = hpid;
+ lpdbb->htid = htid;
+ _fmemcpy ( lpdbb->rgbVar, lpv, wLen );
+
+ xosd = CallTL ( tlfRequest, hpid, sizeof ( DBB ) + wLen, (LPV)lpdbb );
+
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ xosd = (XOSD) LpDmMsg->xosdRet;
+
+ return xosd;
+}
+
+
+XOSD
+ProgramLoad (
+ HPID hpid,
+ DWORD cb,
+ LPPRL lpprl
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to cause a program to be loaded by the
+ debug monitor.
+
+Arguments:
+
+ hpid - Supplies the OSDEBUG handle to the process to be loaded
+ cb - Length of the command line
+ lpprl - Pointer to structure containning the command line
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ XOSD xosd = xosdNone;
+ LPPRC lpprc;
+ HPRC hprc = HprcFromHpid(hpid);
+
+ lpprc = LLLock ( hprc );
+
+ LLDestroy ( lpprc->llmdi );
+ lpprc->llmdi = LLInit ( sizeof ( MDI ), llfNull, NULL, MDIComp );
+
+ LLUnlock ( hprc );
+
+ PurgeCache ();
+
+ xosd = SendRequestX (
+ dmfProgLoad,
+ hpid,
+ NULL,
+ cb,
+ lpprl
+ );
+
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ lpprc = LLLock ( hprc );
+ lpprc->stat = statStarted;
+ LLUnlock ( hprc );
+ }
+
+ return xosd;
+} /* ProgramLoad() */
+
+
+/**** PROGRAMFREE - Terminate the program and free the pid ****
+ * *
+ * PURPOSE: *
+ * *
+ * INPUTS: *
+ * *
+ * OUTPUTS: *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD
+ProgramFree (
+ HPID hpid,
+ HTID htid
+ )
+{
+ return SendRequest( dmfProgFree, hpid, NULL);
+}
+
+
+
+#ifdef OSDEBUG4
+XOSD
+CompareAddrs(
+ HPID hpid,
+ HTID htid,
+ LPCAS lpcas
+ )
+{
+ ADDR a1 = *lpcas->lpaddr1;
+ ADDR a2 = *lpcas->lpaddr2;
+ XOSD xosd = xosdNone;
+ LONG l;
+
+ // if both are LI, see if they are comparable:
+ if (ADDR_IS_LI(a1) && ADDR_IS_LI(a2)
+ && emiAddr(a1) == emiAddr(a2)
+ && GetAddrSeg(a1) == GetAddrSeg(a2))
+ {
+ l = GetAddrOff(a1) - GetAddrOff(a2);
+ *lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
+ }
+
+ else {
+
+ // if neccessary, fixup addresses:
+ if (ADDR_IS_LI(a1)) {
+ FixupAddr(hpid, &a1);
+ }
+
+ if (ADDR_IS_LI(a2)) {
+ FixupAddr(hpid, &a2);
+ }
+
+
+ // if real mode address, we can really compare
+ if (ADDR_IS_REAL(a1) && ADDR_IS_REAL(a2)) {
+ l = ((GetAddrSeg(a1) << 4) + (GetAddrOff(a1) & 0xffff))
+ - ((GetAddrSeg(a2) << 4) + (GetAddrOff(a2) & 0xffff));
+ *lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
+ }
+
+ else if (ADDR_IS_FLAT(a1) != ADDR_IS_FLAT(a2)) {
+ xosd = xosdInvalidParameter;
+ }
+
+ // if flat, ignore selectors
+ else if (ADDR_IS_FLAT(a1)) {
+ l = GetAddrOff(a1) - GetAddrOff(a2);
+ *lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
+ }
+
+ else if (GetAddrSeg(a1) == GetAddrSeg(a2)) {
+ l = GetAddrOff(a1) - GetAddrOff(a2);
+ *lpcas->lpResult = (l < 0) ? -1 : ((l == 0) ? 0 : 1);
+ }
+
+ // not flat, different selectors
+ else {
+ xosd = xosdInvalidParameter;
+ }
+
+ }
+ return xosd;
+}
+#endif // OSDEBUG4
+
+
+static BOOL fCacheDisabled = FALSE;
+
+#define cbMaxCache CACHESIZE
+typedef struct _MCI {
+ WORD cb;
+ HPID hpid;
+ ADDR addr;
+ BYTE rgb [ cbMaxCache ];
+} MCI; // Memory Cache Item
+
+#define imciMax MAXCACHE
+MCI FAR rgmci [ imciMax ] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
+
+// Most recent used == 0, 2nd to last == 1, etc
+
+int rgiUsage [ imciMax ] = {0};
+
+void InitUsage ( void ) {
+ int iUsage;
+
+ for ( iUsage = 0; iUsage < imciMax; iUsage++ ) {
+ rgiUsage [ iUsage ] = imciMax - ( iUsage + 1 );
+ }
+}
+
+VOID
+SetMostRecent (
+ int imci
+ )
+{
+ int i;
+
+ if ( rgiUsage [ imci ] != 0 ) {
+ for ( i = 0; i < imciMax; i++ ) {
+ if ( rgiUsage [ i ] < rgiUsage [ imci ] ) {
+ rgiUsage [ i ] ++;
+ }
+ }
+ rgiUsage [ imci ] = 0;
+ }
+}
+
+int
+GetLeastRecent (
+ VOID
+ )
+{
+ int i;
+
+ for ( i = 0; i < imciMax; i++ ) {
+ assert ( rgiUsage [ i ] >= 0 && rgiUsage [ i ] < imciMax );
+ if ( rgiUsage [ i ] == imciMax - 1 ) {
+ return i;
+ }
+ }
+
+ assert ( FALSE );
+
+ return i;
+}
+
+VOID
+SetLeastRecent (
+ int imci
+ )
+{
+ int i;
+
+ if ( rgiUsage [ imci ] != imciMax - 1 ) {
+ for ( i = 0; i < imciMax; i++ ) {
+ if ( rgiUsage [ i ] > rgiUsage [ imci ] ) {
+ rgiUsage [ i ] --;
+ }
+ }
+ rgiUsage [ imci ] = imciMax-1;
+ }
+}
+
+
+XOSD
+ReadPhysical (
+ HPID hpid,
+ DWORD cb,
+ LPBYTE lpbDest,
+ LPADDR lpaddr,
+ DWORD iCache,
+ LPDWORD lpcbr
+ )
+{
+ BYTE rgb [ sizeof ( DBB ) + sizeof ( RWP ) ];
+ LPDBB lpdbb = (LPDBB) rgb;
+ PRWP prwp = (PRWP) lpdbb->rgbVar;
+ WORD wRet = 0;
+ XOSD xosd = xosdNone;
+
+ if (!ValidHprcFromHpid(hpid)) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ lpdbb->dmf = dmfReadMem;
+ lpdbb->hpid = hpid;
+ lpdbb->htid = NULL;
+
+ if ( cb + sizeof(DWORD) + FIELD_OFFSET(DM_MSG, rgb) > CbDmMsg ) {
+ MHFree ( LpDmMsg );
+ CbDmMsg = cb + sizeof ( DWORD ) + FIELD_OFFSET(DM_MSG, rgb);
+ LpDmMsg = MHAlloc ( CbDmMsg );
+ CallTL ( tlfSetBuffer, lpdbb->hpid, CbDmMsg, LpDmMsg );
+ }
+
+ prwp->cb = cb;
+ prwp->addr = *lpaddr;
+
+ xosd = CallTL(tlfRequest, lpdbb->hpid, sizeof (DBB) + sizeof(RWP), rgb);
+
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ xosd = LpDmMsg->xosdRet;
+ if (xosd == xosdNone) {
+ *lpcbr = *( (LPDWORD) (LpDmMsg->rgb) );
+ assert( *lpcbr <= cb );
+ _fmemcpy ( lpbDest, LpDmMsg->rgb + sizeof ( DWORD ), *lpcbr );
+ }
+
+ return xosd;
+}
+
+XOSD
+EnableCache (
+ HPID hpid,
+ HTID htid,
+ BOOL state
+ )
+{
+ fCacheDisabled = state;
+
+ if (fCacheDisabled) {
+ PurgeCache();
+ }
+
+ return xosdNone;
+}
+
+
+void
+PurgeCache (
+ VOID
+ )
+{
+ int imci;
+
+ for ( imci = 0; imci < imciMax; imci++ ) {
+ rgmci [ imci ].cb = 0;
+ }
+}
+
+void
+PurgeCacheHpid (
+ HPID hpid
+ )
+{
+ int imci;
+
+ for ( imci = 0; imci < imciMax; imci++ ) {
+
+ if ( rgmci [ imci ].hpid == hpid ) {
+ rgmci [ imci ].cb = 0;
+ SetLeastRecent ( imci );
+ }
+ }
+}
+
+
+XOSD
+ReadForCache(
+ HPID hpid,
+ DWORD cbP,
+ LPBYTE lpbDest,
+ LPADDR lpaddr,
+ LPDWORD lpcb
+ )
+
+/*++
+
+Routine Description:
+
+ This function will fill in a cache entry with the bytes requested
+ to be read. The function puts the bytes in both the cache and the
+ memory buffer.
+
+Arguments:
+
+ hpid - Supplies the process to do the read in
+
+ cbP - Supplies the number of bytes to be read
+
+ lpbDest - Supplies the buffer to place the bytes in
+
+ lpaddr - Supplies the address to read the bytes from
+
+ lpcb - Returns the number of bytes read
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ int cb = cbP;
+ DWORD cbT = cb < cbMaxCache ? cbMaxCache : cb;
+ DWORD imci;
+ DWORD cbr;
+ int dbOverlap = 0;
+ XOSD xosd;
+ ADDR addrSave = *lpaddr;
+ MCI * pmci;
+
+ /*
+ * Determine if the starting address is contained in a
+ * voided cache entry
+ */
+
+ for ( imci = 0, pmci = rgmci ; imci < imciMax; imci++, pmci++ ) {
+
+ if ( (pmci->cb == 0) &&
+ (pmci->hpid == hpid) &&
+ (ADDR_IS_REAL( pmci->addr) == ADDR_IS_REAL( *lpaddr )) &&
+ (GetAddrSeg ( pmci->addr ) == GetAddrSeg ( *lpaddr )) &&
+ (GetAddrOff ( *lpaddr ) >= GetAddrOff ( pmci->addr )) &&
+ (GetAddrOff ( *lpaddr ) + cbP < GetAddrOff ( pmci->addr ) + cbMaxCache)
+ ) {
+ dbOverlap = (int) (GetAddrOff ( pmci->addr ) - GetAddrOff ( *lpaddr ) );
+ GetAddrOff ( *lpaddr ) = GetAddrOff ( pmci->addr );
+ break;
+ }
+ }
+
+
+ /*
+ * if we have not found a cache entry then just get one based on
+ * an LRU algorithm.
+ */
+
+ if ( imci == imciMax ) {
+ imci = GetLeastRecent ( );
+ }
+
+ /*
+ * Do an actual read of memory from the debuggee
+ */
+
+ xosd = ReadPhysical ( hpid, cbT, rgmci [ imci ].rgb, lpaddr, imci, &cbr );
+
+ if ( xosd != xosdNone ) {
+ return xosd;
+ }
+
+ /*
+ * If only a partial cache entry was read in then reset our read
+ * size variable.
+ */
+
+ if ( cbr < cbT ) {
+ cbT = cbr;
+ }
+
+ /*
+ * if we did not anything (or enough), then don't adjust
+ */
+
+ if ( (int)cbr + dbOverlap > 0 ) {
+ cbT += dbOverlap;
+ }
+
+ /*
+ * touch the LRU table
+ */
+
+ SetMostRecent ( imci );
+
+ /*
+ * set up the cache entry
+ */
+
+ rgmci [ imci ].cb = (WORD) cbT;
+ rgmci [ imci ].addr = *lpaddr;
+ rgmci [ imci ].hpid = hpid;
+ GetAddrOff ( *lpaddr ) += cbT;
+ *lpaddr = addrSave;
+
+ /*
+ * compute the number of bytes read
+ */
+
+ cbT = (int)min( cbP, (DWORD)rgmci[ imci ].cb );
+
+ /*
+ * copy from the cache entry to the users space
+ */
+
+ if ( dbOverlap >= 0 ) {
+ dbOverlap = 0;
+ }
+ _fmemcpy ( lpbDest, rgmci [ imci ].rgb - dbOverlap, cbT );
+
+ /*
+ * return the number of bytes read
+ */
+
+ *lpcb = cbT;
+
+ return xosdNone;
+} /* ReadForCache() */
+
+
+int
+GetCacheIndex(
+ HPID hpid,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is given a process and an address and will locate
+ which cache entry (if any) the address is in.
+
+Arguments:
+
+ hpid - Supplies the handle to the process
+ lpaddr - Supplies the address to look for
+
+Return Value:
+
+ The index of the cache entry containing the address or imciMax if
+ no cache entry contains the address
+
+--*/
+
+{
+ int imci;
+
+ for ( imci = 0; imci < imciMax; imci++ ) {
+ LPADDR lpaddrT = &rgmci [ imci ].addr;
+
+ /*
+ * To be in the cache entry check:
+ *
+ * 1. The cache entry contains bytes
+ * 2. The cache entry is for the correct process
+ * 3. The cache entry if for the correct segment
+ * 4. The requested offset is between the starting and
+ * ending points of the cache
+ */
+
+ if ( (rgmci [ imci ].cb != 0) &&
+ (rgmci [ imci ].hpid == hpid) &&
+ (ADDR_IS_REAL( *lpaddrT ) == ADDR_IS_REAL( *lpaddr )) &&
+ (GetAddrSeg ( *lpaddrT ) == GetAddrSeg ( *lpaddr )) &&
+ (GetAddrOff ( *lpaddrT ) <= GetAddrOff ( *lpaddr )) &&
+ (GetAddrOff ( *lpaddrT ) + rgmci[ imci ].cb > GetAddrOff ( *lpaddr ))) {
+
+ break;
+ }
+ }
+
+ return imci;
+} /* GetCacheIndex() */
+
+
+int
+ReadFromCache (
+ HPID hpid,
+ DWORD cb,
+ LPBYTE lpbDest,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ hpid - Supplies a handle to the process
+ cb - Supplies the count of bytes to read from the cache
+ lpbDest - Suppiies the pointer to store bytes at
+ lpaddr - Supplies pointer to address to read at
+
+Return Value:
+
+ > 0 - The number of bytes read from the cache
+ == 0 - No cache entry for the address was found
+
+--*/
+
+{
+ int imci;
+
+ /*
+ * See if the address for the start of the read is current contained
+ * in one of the cached buffers.
+ */
+
+ imci = GetCacheIndex ( hpid, lpaddr );
+
+ /*
+ * If the starting address is in a cache entry then read as many
+ * bytes as is possible from that cache entry.
+ */
+
+ if ( imci != imciMax ) {
+ DWORD ibStart;
+ DWORD cbT;
+
+ /*
+ * Compute the difference between the address for the cache start
+ * and the address for the read request start and then
+ * the number of bytes which can be read in
+ */
+
+ ibStart = (DWORD)( GetAddrOff ( *lpaddr ) - GetAddrOff ( rgmci[imci].addr ) );
+ cbT = min ( cb, rgmci [ imci ].cb - ibStart );
+
+ /*
+ * Preform the copy
+ */
+
+ _fmemcpy ( lpbDest, rgmci [ imci ].rgb + ibStart, cbT );
+
+ /*
+ * Return the number of bytes copied. If it is less than
+ * zero then for some reason the current cache was not
+ * filled to capacity.
+ */
+
+ return cbT;
+ }
+
+ return 0;
+} /* ReadFromCache() */
+
+
+XOSD
+ReadBuffer (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ DWORD cb,
+ LPBYTE lpbDest,
+ LPDWORD lpcbRead
+ )
+/*++
+
+Routine Description:
+
+ This function is called in response to an emfReadBuf message. The
+ address to start the read at was set earlier and is stored in the
+ adrCurrent Address Buffer.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to read memory for
+
+ htid - Supplies the handle to the thread to read memory for
+ (may be NULL)
+ lpaddr -
+
+ cb - Supplies count of bytes to read
+
+ lpbDest - Supplies pointer to buffer to place bytes read
+
+ lpcbRead - Returns number of bytes read
+
+Return Value:
+
+ if >= 0 then it is the number of bytes actually read otherwise it
+ is an xosdError code.
+
+--*/
+
+{
+ XOSD xosd = xosdNone;
+ ADDR addr;
+ int cbT = 0;
+ int cbRead = 0;
+ HPRC hprc = HprcFromHpid(hpid);
+ LPPRC lpprc;
+
+
+ /*
+ * Retrieve the address to start the read at from the address buffer
+ * location
+ */
+ if (cb == 0) {
+ if (lpcbRead) {
+ *lpcbRead = 0;
+ }
+ return xosdNone;
+ }
+
+#ifdef OSDEBUG4
+ addr = *lpaddr;
+#else
+ if (lpaddr) {
+ addr = *lpaddr;
+ } else {
+ xosd = GetAddr ( hpid, htid, adrCurrent, &addr );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+ }
+#endif
+
+ assert( !ADDR_IS_LI(addr) );
+
+ /*
+ * Are we trying to read more bytes than is possible to store in
+ * a single cache? If so then skip trying to hit the cache and
+ * go directly to asking the DM for the memory.
+ *
+ * This generally is due to large memory dumps.
+ */
+
+ lpprc = (LPPRC) LLLock(hprc);
+ if ( (cb > cbMaxCache) || (lpprc->fRunning ) || (fCacheDisabled) ) {
+ LLUnlock(hprc);
+ return ReadPhysical ( hpid, cb, lpbDest, &addr, MAXCACHE, lpcbRead );
+ }
+ LLUnlock(hprc);
+
+ /*
+ * Read as much as possible from the set of cached memory reads.
+ * If cbT > 0 then bytes were read from a cache entry
+ * if cbT == 0 then no bytes were read in
+ */
+
+ while ((cb != 0) &&
+ ( cbT = ReadFromCache ( hpid, cb, lpbDest, &addr ) ) > 0 ) {
+ cbRead += cbT;
+ lpbDest += cbT;
+ GetAddrOff ( addr ) += cbT;
+ cb -= cbT;
+ }
+
+ /*
+ * If there are still bytes left to be read then get the cache
+ * routines to read them in and copy both to a cache and to the
+ * buffer.
+ */
+
+ if ( cb > 0 ) {
+ xosd = ReadForCache ( hpid, cb, lpbDest, &addr, &cbT );
+ if (xosd == xosdNone) {
+ cbRead += cbT;
+ }
+ }
+
+ if (lpcbRead) {
+ *lpcbRead = cbRead;
+ }
+
+ return xosd;
+} /* ReadBuffer() */
+
+
+#ifdef OSDEBUG4
+
+XOSD
+WriteBufferCache (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ DWORD cb,
+ LPBYTE lpb,
+ LPDWORD lpdwBytesWritten
+ )
+{
+ PurgeCacheHpid ( hpid );
+ return WriteBuffer ( hpid, htid, lpaddr, cb, lpb, lpdwBytesWritten );
+}
+
+
+
+XOSD
+WriteBuffer (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ DWORD cb,
+ LPBYTE lpb,
+ LPDWORD lpdwBytesWritten
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to send a request to the Debug Monitor to
+ do a write to the debuggees memory.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to write memory in
+
+ htid - Supplies a thead handle
+
+ lpaddr - Supplies debuggee address to write at
+
+ cb - Supplies the number of bytes to be written
+
+ lpb - Supplies a pointer to the buffer to write
+
+ lpdwBytesWritten - Returns number of bytes actually written
+
+Return Value:
+
+ an XOSD error code
+
+--*/
+{
+ LPRWP lprwp = MHAlloc( sizeof( RWP ) + cb );
+ XOSD xosd;
+
+ lprwp->cb = cb;
+ lprwp->addr = *lpaddr;
+
+ _fmemcpy ( lprwp->rgb, lpb, cb );
+
+ xosd = SendRequestX (dmfWriteMem,
+ hpid,
+ htid,
+ sizeof ( RWP ) + cb,
+ lprwp
+ );
+
+ MHFree ( lprwp );
+
+ if (xosd == xosdNone) {
+ *lpdwBytesWritten = *((LPDWORD)(LpDmMsg->rgb));
+ }
+
+ //
+ // Notify the shell that we changed memory. An error here is not
+ // tragic, so we ignore the return code. The shell uses this
+ // notification to update all its memory breakpoints.
+ //
+ CallDB (
+ dbcMemoryChanged,
+ hpid,
+ NULL,
+ CEXM_MDL_native,
+ cb,
+ (LPV)lpaddr
+ );
+
+ return xosd;
+} /* WriteBuffer() */
+
+#else // OSDEBUG4
+
+XOSD
+WriteBufferCache (
+ HPID hpid,
+ HTID htid,
+ DWORD cb,
+ LPBYTE lpb
+ )
+{
+
+ PurgeCacheHpid ( hpid );
+ return WriteBuffer ( hpid, htid, cb, lpb );
+}
+
+
+
+XOSD
+WriteBuffer (
+ HPID hpid,
+ HTID htid,
+ DWORD cb,
+ LPBYTE lpb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to send a request to the Debug Monitor to
+ do a write to the debuggees memory.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to write memory in
+ htid - Supplies a thead handle
+ cb - Supplies the number of bytes to be written
+ lpb - Supplies a pointer to the buffer to write
+
+Return Value:
+
+ an XOSD error code
+
+--*/
+{
+ LPRWP lprwp = MHAlloc ( sizeof ( RWP ) + cb );
+ ADDR addr;
+ XOSD xosd;
+
+ GetAddr ( hpid, htid, adrCurrent, &addr );
+
+ lprwp->cb = (WORD) cb;
+ lprwp->addr = addr;
+
+ _fmemcpy ( lprwp->rgb, lpb, cb );
+
+ xosd = SendRequestX (
+ dmfWriteMem,
+ hpid,
+ htid,
+ sizeof ( RWP ) + cb,
+ lprwp
+ );
+
+ MHFree ( lprwp );
+
+ //
+ // Notify the shell that we changed memory. An error here is not
+ // tragic, so we ignore the return code. The shell uses this
+ // notification to update all its memory breakpoints.
+ //
+ CallDB (
+ dbcChangedMemory,
+ hpid,
+ NULL,
+ CEXM_MDL_native,
+ 0,
+ (LPV)cb
+ );
+
+ return xosd;
+} /* WriteBuffer() */
+#endif
+
+
+XOSD
+UpdateChild (
+ HPID hpid,
+ HTID htid,
+ DMF dmfCommand
+ )
+/*++
+
+Routine Description:
+
+ This function is used to cause registers to be written back to
+ the child as necessary before the child is executed.
+
+Arguments:
+
+ hprc - Supplies a process handle
+
+ hthdExec - Supplies the handle of the thread to update
+
+ dmfCommand - Supplies the command about to be executed.
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ HPRC hprc;
+ HTHD hthd;
+ HTHD hthdExec;
+ XOSD xosd = xosdNone;
+ HLLI llthd;
+ LPPRC lpprc;
+ PST pst;
+
+ hprc = HprcFromHpid(hpid);
+ hthdExec = HthdFromHtid(hprc, htid);
+
+ llthd = LlthdFromHprc ( hprc );
+
+ xosd = ProcessStatus(hpid, &pst);
+
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ if (pst.dwProcessState == pstDead || pst.dwProcessState == pstExited) {
+ return xosdInvalidProc;
+ } else if (pst.dwProcessState != pstRunning) {
+ for ( hthd = LLNext ( llthd, hthdNull );
+ hthd != hthdNull;
+ hthd = LLNext ( llthd, hthd ) ) {
+
+ LPTHD lpthd = LLLock ( hthd );
+
+ if ( lpthd->drt & (drtCntrlDirty | drtAllDirty) ) {
+ assert(lpthd->drt & drtAllPresent);
+ SendRequestX (dmfWriteReg,
+ hpid,
+ lpthd->htid,
+ sizeof ( CONTEXT ),
+ &lpthd->regs
+ );
+
+ lpthd->drt &= ~(drtCntrlDirty | drtAllDirty);
+ }
+ if ( lpthd->drt & drtSpecialDirty ) {
+ assert(lpthd->drt & drtSpecialPresent);
+ if (lpthd->dwcbSpecial) {
+#ifdef TARGET_i386
+ ((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr0 =
+ lpthd->regs.Dr0;
+ ((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr1 =
+ lpthd->regs.Dr1;
+ ((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr2 =
+ lpthd->regs.Dr2;
+ ((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr3 =
+ lpthd->regs.Dr3;
+ ((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr6 =
+ lpthd->regs.Dr6;
+ ((PKSPECIAL_REGISTERS)(lpthd->pvSpecial))->KernelDr7 =
+ lpthd->regs.Dr7;
+#endif
+ SendRequestX(dmfWriteRegEx,
+ hpid,
+ lpthd->htid,
+ lpthd->dwcbSpecial,
+ lpthd->pvSpecial
+ );
+ } else {
+#ifdef TARGET_i386
+ DWORD DR[6];
+ DR[0] = lpthd->regs.Dr0;
+ DR[1] = lpthd->regs.Dr1;
+ DR[2] = lpthd->regs.Dr2;
+ DR[3] = lpthd->regs.Dr3;
+ DR[4] = lpthd->regs.Dr6;
+ DR[5] = lpthd->regs.Dr7;
+ SendRequestX (dmfWriteRegEx,
+ hpid,
+ lpthd->htid,
+ sizeof ( DR ),
+ DR
+ );
+#endif
+ }
+ lpthd->drt &= ~drtSpecialDirty;
+ }
+
+ lpthd->fRunning = TRUE;
+
+ LLUnlock ( hthd );
+
+ if ( xosd != xosdNone ) {
+ break;
+ }
+ }
+ lpprc = (LPPRC) LLLock(hprc);
+ lpprc->fRunning = TRUE;
+ LLUnlock(hprc);
+ }
+
+ return xosd;
+}
+
+#ifndef OSDEBUG4
+
+XOSD
+Freeze (
+ HPID hpid,
+ HTID htid
+ )
+{
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == hthdNull ) {
+ return xosdInvalidTID;
+ }
+
+ SendRequest ( dmfFreeze, hpid, htid);
+
+ return LpDmMsg->xosdRet;
+}
+
+
+XOSD
+Thaw (
+ HPID hpid,
+ HTID htid
+ )
+{
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == hthdNull ) {
+ return xosdInvalidTID;
+ }
+
+ SendRequest ( dmfResume, hpid, htid);
+
+ return LpDmMsg->xosdRet;
+}
+
+#endif // !OSDEBUG4
+
+
+typedef struct _EMIC {
+ HEMI hemi;
+ WORD sel;
+ HPID hpid;
+} EMIC; // EMI cache item
+
+#define cemicMax 4
+
+EMIC rgemic [ cemicMax ] = {0};
+
+XOSD
+FindEmi (
+ HPID hpid,
+ LPADDR lpaddr
+ )
+{
+ XOSD xosd = xosdNone;
+ WORD sel = GetAddrSeg ( *lpaddr );
+ HPRC hprc = HprcFromHpid(hpid);
+ HLLI llmdi = LlmdiFromHprc ( hprc );
+ BOOL fFound = FALSE;
+ ULONG iobj = 0;
+ HMDI hmdi;
+ LPPRC lpprc = LLLock( hprc );
+
+ if ((lpprc->dmi.fAlwaysFlat) || (sel == lpprc->selFlatCs) || (sel == lpprc->selFlatDs)) {
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ }
+ LLUnlock( hprc );
+
+ for ( hmdi = LLNext ( llmdi, hmdiNull );
+ hmdi != hmdiNull;
+ hmdi = LLNext ( llmdi, hmdi ) ) {
+
+ LPMDI lpmdi = LLLock ( hmdi );
+ LPOBJD rgobjd;
+
+ if (ADDR_IS_FLAT(*lpaddr) && (!ADDR_IS_LI(*lpaddr))) {
+ if (GetAddrOff(*lpaddr) < lpmdi->lpBaseOfDll ||
+ GetAddrOff(*lpaddr) >= lpmdi->lpBaseOfDll+lpmdi->dwSizeOfDll) {
+ //
+ // can't be in this dll so look at the next one
+ //
+ LLUnlock ( hmdi );
+ continue;
+ }
+ }
+
+ if (lpmdi && lpmdi->cobj == -1) {
+ if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
+ // can't do it now; punt with hpid.
+ break;
+ }
+ }
+
+ rgobjd = &lpmdi->rgobjd[0];
+
+ for ( iobj = 0; iobj < lpmdi->cobj; iobj++ ) {
+ if (((lpmdi->fFlatMode && ADDR_IS_FLAT(*lpaddr)) ||
+ (rgobjd[iobj].wSel == sel) && !ADDR_IS_FLAT(*lpaddr)) &&
+ (rgobjd[iobj].offset <= GetAddrOff(*lpaddr)) &&
+ (GetAddrOff(*lpaddr) < rgobjd[iobj].offset + rgobjd[iobj].cb)) {
+
+ fFound = TRUE;
+ break;
+ }
+ }
+
+ LLUnlock ( hmdi );
+
+ // This break is here instead of in the "for" condition so
+ // that hmdi does not get advanced before we break
+
+ if ( fFound ) {
+ break;
+ }
+ }
+
+
+ if ( !fFound ) {
+ emiAddr ( *lpaddr ) = (HEMI) hpid;
+ } else {
+ emiAddr ( *lpaddr ) = (HEMI) HemiFromHmdi ( hmdi );
+
+ if ( LLNext ( llmdi, hmdiNull ) != hmdi ) {
+
+ // put the most recent hit at the head
+ // this is an optimization to speed up the fixup/unfixup process
+ LLRemove ( llmdi, hmdi );
+ LLAddHead ( llmdi, hmdi );
+ }
+ }
+
+ assert ( emiAddr ( *lpaddr ) != 0 );
+
+ return xosd;
+}
+
+#pragma optimize ("", off)
+XOSD
+SetEmiFromCache (
+ HPID hpid,
+ LPADDR lpaddr
+ )
+{
+ XOSD xosd = xosdContinue;
+#ifndef TARGET32
+ int iemic;
+
+ for ( iemic = 0; iemic < cemicMax; iemic++ ) {
+
+ if ( rgemic [ iemic ].hpid == hpid &&
+ rgemic [ iemic ].sel == GetAddrSeg ( *lpaddr ) ) {
+
+ if ( iemic != 0 ) {
+ EMIC emic = rgemic [ iemic ];
+ int iemicT;
+
+ for ( iemicT = iemic - 1; iemicT >= 0; iemicT-- ) {
+ rgemic [ iemicT + 1 ] = rgemic [ iemicT ];
+ }
+ rgemic [ 0 ] = emic;
+ }
+
+ xosd = xosdNone;
+ emiAddr ( *lpaddr ) = rgemic [ 0 ].hemi;
+ assert ( emiAddr ( *lpaddr ) != 0 );
+ break;
+ }
+ }
+#else
+ Unreferenced( hpid );
+ Unreferenced( lpaddr );
+#endif // !TARGET32
+ return xosd;
+}
+#pragma optimize ("", on)
+
+XOSD
+SetCacheFromEmi (
+ HPID hpid,
+ LPADDR lpaddr
+ )
+{
+ int iemic;
+
+ assert ( emiAddr ( *lpaddr ) != 0 );
+
+ for ( iemic = cemicMax - 2; iemic >= 0; iemic-- ) {
+
+ rgemic [ iemic + 1 ] = rgemic [ iemic ];
+ }
+
+ rgemic [ 0 ].hpid = hpid;
+ rgemic [ 0 ].hemi = emiAddr ( *lpaddr );
+ rgemic [ 0 ].sel = GetAddrSeg ( *lpaddr );
+
+ return xosdNone;
+}
+
+
+/*** CleanCacheOfEmi
+ *
+ * Purpose:
+ * To purge the emi cache
+ *
+ * Notes:
+ * The emi cache must be purged whenever a RegisterEmi
+ * is done. Unpredicable results can occur otherwise.
+ *
+ */
+XOSD
+CleanCacheOfEmi (
+ void
+ )
+{
+ int iemic;
+
+ for ( iemic = 0; iemic < cemicMax; iemic++ ) {
+
+ rgemic [ iemic ].hpid = NULL;
+ rgemic [ iemic ].sel = 0;
+ }
+
+ return xosdNone;
+}
+
+
+
+XOSD
+SetEmi (
+ HPID hpid,
+ LPADDR lpaddr
+ )
+{
+ XOSD xosd = xosdNone;
+
+ if ( emiAddr ( *lpaddr ) == 0 ) {
+
+ //if (ADDR_IS_REAL(*lpaddr)) {
+ // emiAddr( *lpaddr ) = (HEMI) hpid;
+ // return xosd;
+ //}
+
+ if ( ( xosd = SetEmiFromCache ( hpid, lpaddr ) ) == xosdContinue ) {
+
+ xosd = FindEmi ( hpid, lpaddr );
+ if ( xosd == xosdNone ) {
+ SetCacheFromEmi ( hpid, lpaddr );
+ }
+ }
+
+ assert ( emiAddr ( *lpaddr ) != 0 );
+ }
+
+ return xosd;
+}
+
+
+
+
+
+XOSD
+GetRegValue (
+ HPID hpid,
+ HTID htid,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPPRC lpprc;
+ LPCONTEXT lpregs;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ assert ( hthd != hthdNull );
+
+ lpthd = LLLock ( hthd );
+ lpprc = (LPPRC) LLLock( hprc );
+
+ lpregs = &lpthd->regs;
+
+ if (lpthd->fRunning) {
+ UpdateRegisters( lpthd->hprc, hthd );
+ UpdateSpecialRegisters( lpthd->hprc, hthd );
+ } else {
+ if ( !(lpthd->drt & drtAllPresent) ) {
+
+ switch ( ireg ) {
+
+#ifdef TARGET_i386
+ case CV_REG_CS:
+ case CV_REG_IP:
+ case CV_REG_SS:
+ case CV_REG_BP:
+
+ case CV_REG_EIP:
+ case CV_REG_EBP:
+#endif
+#ifdef TARGET_MIPS
+ case CV_M4_Fir:
+ case CV_M4_IntSP:
+#endif
+
+#ifdef TARGET_ALPHA
+ case CV_ALPHA_Fir:
+ case CV_ALPHA_IntSP:
+#endif
+
+#ifdef TARGET_PPC
+ case CV_PPC_PC:
+ case CV_PPC_GPR1:
+#endif
+ if (!(lpthd->drt & drtCntrlPresent)) {
+ UpdateRegisters( lpthd->hprc, hthd );
+ }
+ break;
+
+ default:
+
+ UpdateRegisters ( lpthd->hprc, hthd );
+ break;
+ }
+ }
+
+
+ if ( !(lpthd->drt & drtSpecialPresent) ) {
+
+ switch ( ireg ) {
+
+#ifdef TARGET_i386
+ case CV_REG_GDTR:
+ case CV_REG_GDTL:
+ case CV_REG_IDTR:
+ case CV_REG_IDTL:
+ case CV_REG_LDTR:
+ case CV_REG_TR:
+
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+
+ case CV_REG_DR0:
+ case CV_REG_DR1:
+ case CV_REG_DR2:
+ case CV_REG_DR3:
+ case CV_REG_DR4:
+ case CV_REG_DR5:
+ case CV_REG_DR6:
+ case CV_REG_DR7:
+
+ UpdateSpecialRegisters( lpthd->hprc, hthd );
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+ }
+
+#ifdef TARGET_i386
+ if (lpprc->dmi.fAlwaysFlat || lpthd->regs.SegCs == lpprc->selFlatCs) {
+ lpthd->fFlat = lpthd->fOff32 = TRUE;
+ lpthd->fReal = FALSE;
+ } else {
+ /*
+ * BUGBUG -- jimsch -- some one might eventually catch on
+ * that this is incorrect. We are not checking to see if the
+ * current address is really a 16-bit WOW address but assuming
+ * that it is. This will be a problem for people who are doing
+ * real 16:32 programming (on WOW) and people who are doing
+ * real mode program -- but so what
+ */
+ lpthd->fFlat = lpthd->fOff32 = lpthd->fReal = FALSE;
+ }
+#else
+ lpthd->fFlat = lpthd->fOff32 = TRUE;
+ lpthd->fReal = FALSE;
+#endif
+
+ switch ( ireg ) {
+
+#ifdef TARGET_i386
+ case CV_REG_GDTR:
+ case CV_REG_GDTL:
+ case CV_REG_IDTR:
+ case CV_REG_IDTL:
+ case CV_REG_LDTR:
+ case CV_REG_TR:
+
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+
+ lpregs = lpthd->pvSpecial;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+
+ LLUnlock( hprc );
+ LLUnlock( hthd );
+
+ if (lpregs) {
+ lpvRegValue = DoGetReg ( lpregs, ireg & 0xff, lpvRegValue );
+ } else {
+ lpvRegValue = NULL;
+ }
+
+ if ( lpvRegValue != NULL ) {
+ ireg = ireg >> 8;
+
+ if ( ireg != CV_REG_NONE ) {
+ lpvRegValue = DoGetReg ( lpregs, ireg, lpvRegValue );
+ }
+ }
+
+ if ( lpvRegValue == NULL ) {
+#ifdef OSDEBUG4
+ return xosdInvalidParameter;
+#else
+ return xosdInvalidRegister;
+#endif
+ }
+
+ return xosdNone;
+
+} /* GetRegValue */
+
+
+
+XOSD
+SetRegValue (
+ HPID hpid,
+ HTID htid,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+{
+ XOSD xosd = xosdNone;
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPVOID lpregs = NULL;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ assert ( hthd != hthdNull );
+
+ lpthd = LLLock ( hthd );
+
+ switch ( ireg ) {
+#ifdef TARGET_i386
+ case CV_REG_GDTR:
+ case CV_REG_GDTL:
+ case CV_REG_IDTR:
+ case CV_REG_IDTL:
+ case CV_REG_LDTR:
+ case CV_REG_TR:
+
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+
+ lpregs = &lpthd->pvSpecial;
+ // fall thru
+
+ case CV_REG_DR0:
+ case CV_REG_DR1:
+ case CV_REG_DR2:
+ case CV_REG_DR3:
+ case CV_REG_DR4:
+ case CV_REG_DR5:
+ case CV_REG_DR6:
+ case CV_REG_DR7:
+
+ if (!(lpthd->drt & drtSpecialPresent)) {
+ UpdateSpecialRegisters( lpthd->hprc, hthd );
+ }
+ break;
+#endif
+
+ default:
+
+ lpregs = &lpthd->regs;
+
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( lpthd->hprc, hthd );
+ }
+ break;
+ }
+
+ lpvRegValue = DoSetReg ( lpregs, ireg & 0xff, lpvRegValue );
+
+ if ( lpvRegValue == NULL ) {
+ LLUnlock ( hthd );
+#ifdef OSDEBUG4
+ return xosdInvalidParameter;
+#else
+ return xosdInvalidRegister;
+#endif
+ }
+
+ ireg = ireg >> 8;
+ if ( ireg != 0 ) {
+ lpvRegValue = DoSetReg ( lpregs, ireg, lpvRegValue );
+ }
+ if ( lpvRegValue == NULL ) {
+ LLUnlock ( hthd );
+#ifdef OSDEBUG4
+ return xosdInvalidParameter;
+#else
+ return xosdInvalidRegister;
+#endif
+ }
+
+
+ switch ( ireg ) {
+#ifdef TARGET_i386
+ case CV_REG_GDTR:
+ case CV_REG_GDTL:
+ case CV_REG_IDTR:
+ case CV_REG_IDTL:
+ case CV_REG_LDTR:
+ case CV_REG_TR:
+
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+
+ case CV_REG_DR0:
+ case CV_REG_DR1:
+ case CV_REG_DR2:
+ case CV_REG_DR3:
+ case CV_REG_DR4:
+ case CV_REG_DR5:
+ case CV_REG_DR6:
+ case CV_REG_DR7:
+
+ lpthd->drt |= drtSpecialDirty;
+ break;
+#endif
+
+ default:
+
+ lpthd->drt |= drtAllDirty;
+ break;
+ }
+
+
+
+ LLUnlock ( hthd );
+
+ return xosd;
+
+}
+
+#ifndef OSDEBUG4
+
+/*++
+
+Routine Description:
+
+ This routine sets the frame context.
+
+Arguments:
+
+ hpid - handle for the process
+ htid - handle for the thread
+ frame - the frame number. The current frame is 0; caller is 1.
+
+Return value:
+
+ xosd.
+
+--*/
+
+XOSD
+SetFrameContext(
+ HPID hpid,
+ HTID htid,
+ DWORD frame
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ assert ( hthd != hthdNull );
+ assert ( (INT)frame > INVALID_FRAME );
+
+ lpthd = LLLock ( hthd );
+
+ lpthd->frameNumber = frame;
+
+ //
+ // If the frame to use is not the current frame,
+ // retrieve its registers into frameRegs
+ //
+
+ if ( frame != CURRENT_FRAME ) {
+
+ SendRequestX ( dmfReadFrameReg,
+ HpidFromHprc ( hprc ),
+ HtidFromHthd ( hthd ),
+ sizeof (frame),
+ &frame );
+
+ _fmemcpy ( &lpthd->frameRegs,
+ &((PFRAME_INFO)LpDmMsg->rgb)->frameRegs,
+ sizeof ( lpthd->frameRegs) );
+
+ _fmemcpy ( &lpthd->frameRegPtrs,
+ &((PFRAME_INFO)LpDmMsg->rgb)->frameRegPtrs,
+ sizeof (lpthd->frameRegPtrs) );
+ }
+
+
+ LLUnlock( hprc );
+ LLUnlock( hthd );
+
+}
+
+
+XOSD
+SetFrameRegValue(
+ HPID hpid,
+ HTID htid,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ assert ( hthd != hthdNull );
+
+ lpthd = LLLock ( hthd );
+
+ if (lpthd->frameNumber == CURRENT_FRAME) {
+
+ LLUnlock ( hthd );
+ return SetRegValue(hpid, htid, ireg, lpvRegValue);
+
+ }
+
+ //
+ // use the frame registers
+ //
+
+ lpvRegValue = DoSetFrameReg ( hpid,
+ htid,
+ lpthd,
+ &lpthd->frameRegPtrs,
+ ireg & 0xff,
+ lpvRegValue );
+
+ if ( lpvRegValue != NULL ) {
+
+ ireg = ireg >> 8;
+
+ if ( ireg != CV_REG_NONE ) {
+ lpvRegValue = DoSetFrameReg ( hpid,
+ htid,
+ lpthd,
+ &lpthd->frameRegPtrs,
+ ireg,
+ lpvRegValue );
+ }
+ }
+
+ LLUnlock ( hthd );
+
+ if ( lpvRegValue == NULL ) {
+ return xosdInvalidRegister;
+ }
+
+ return xosdNone;
+}
+
+XOSD
+GetFrameRegValue (
+ HPID hpid,
+ HTID htid,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ assert ( hthd != hthdNull );
+
+ lpthd = LLLock ( hthd );
+
+ if ( lpthd->frameNumber == CURRENT_FRAME ) {
+ LLUnlock ( hthd );
+ return GetRegValue(hpid, htid, ireg, lpvRegValue);
+ }
+
+ lpvRegValue = DoGetReg ( &lpthd->frameRegs, ireg & 0xff, lpvRegValue );
+
+ if ( lpvRegValue != NULL ) {
+
+ ireg = ireg >> 8;
+
+ if ( ireg != CV_REG_NONE ) {
+ lpvRegValue = DoGetReg ( &lpthd->frameRegs, ireg, lpvRegValue );
+ }
+ }
+
+ LLUnlock ( hthd );
+
+ if ( lpvRegValue == NULL ) {
+ return xosdInvalidRegister;
+ }
+
+ return xosdNone;
+
+} /* GetFrameRegValue */
+
+#endif // !OSDEBUG4
+
+
+XOSD
+SetFlagValue (
+ HPID hpid,
+ HTID htid,
+ DWORD iFlag,
+ LPV lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPCONTEXT lpregs;
+ LONG mask;
+ LONG l;
+ LONGLONG ll;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ assert ( hthd != hthdNull );
+
+ lpthd = LLLock( hthd );
+
+ lpregs = &lpthd->regs;
+
+ if ( !( lpthd->drt & drtAllPresent )) {
+ UpdateRegisters ( lpthd->hprc, hthd );
+ }
+
+#ifdef OSDEBUG4
+
+ if (Rgrd[Rgfd[iFlag].fd.dwId].dwcbits > 32) {
+
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.dwId, &ll ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidParameter;
+ }
+
+ mask = (1 << Rgfd[iFlag].fd.dwcbits) - 1;
+ mask <<= Rgfd[iFlag].iShift;
+ ll &= ~mask;
+ ll |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
+ DoSetReg(lpregs, Rgfd[iFlag].fd.dwId, &ll );
+
+ } else {
+
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.dwId, &l ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidParameter;
+ }
+
+ mask = (1 << Rgfd[iFlag].fd.dwcbits) - 1;
+ mask <<= Rgfd[iFlag].iShift;
+ l &= ~mask;
+ l |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
+ DoSetReg(lpregs, Rgfd[iFlag].fd.dwId, &l );
+ }
+#else
+ if (Rgrd[Rgfd[iFlag].fd.hReg].cbits > 32) {
+
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &ll ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidRegister;
+ }
+
+ mask = (1 << Rgfd[iFlag].fd.cbits) - 1;
+ mask <<= Rgfd[iFlag].iShift;
+ ll &= ~mask;
+ ll |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
+ DoSetReg(lpregs, Rgfd[iFlag].fd.hReg, &ll );
+
+ } else {
+
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &l ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidRegister;
+ }
+
+ mask = (1 << Rgfd[iFlag].fd.cbits) - 1;
+ mask <<= Rgfd[iFlag].iShift;
+ l &= ~mask;
+ l |= ((*((ULONG FAR *) lpvRegValue)) << Rgfd[iFlag].iShift) & mask;
+ DoSetReg(lpregs, Rgfd[iFlag].fd.hReg, &l );
+ }
+#endif
+
+ lpthd->drt |= drtAllDirty;
+ LLUnlock ( hthd );
+ return xosdNone;
+} /* SetFlagValue */
+
+
+
+#ifdef OSDEBUG4
+/*
+ Note: We are not guaranteed that the incoming address is actually
+ on an instruction boundary. When this happens, we derive the
+ boundary and send back the difference in the return value and
+ the address of the instruction previous to the DERIVED instruction
+ in the address.
+
+ Thus there are three classes of returns -
+
+ ==0 - The incoming address was in fact on an instruction boundary
+ > 0 - The case noted above
+ < 0 - Error value - the most common "error" is that there is
+ no previous instruction.
+
+ When the return value >= 0, *lpaddr contains the address of the
+ previous instruction.
+*/
+
+
+#define doffMax 60
+
+static HPID hpidGPI = NULL;
+static BYTE rgbGPI [ doffMax ];
+static ADDR addrGPI;
+
+XOSD
+GPIBuildCache (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr
+ )
+{
+ XOSD xosd = xosdBadAddress;
+ int fFound = FALSE;
+ ADDR addr = *lpaddr;
+ ADDR addrT;
+ int ib = 0;
+
+ _fmemset ( rgbGPI, 0, doffMax );
+
+ addrGPI = *lpaddr;
+ hpidGPI = hpid;
+
+ GetAddrOff ( addr ) -= (int) min ( (UOFFSET) doffMax, GetAddrOff ( *lpaddr ) );
+
+ while ( !fFound && GetAddrOff ( addr ) < GetAddrOff ( *lpaddr ) ) {
+ SDI sdi;
+
+ sdi.dop = dopNone;
+ sdi.addr = addr;
+
+ addrT = addr;
+
+ disasm ( hpid, htid, &sdi );
+
+ addr = sdi.addr;
+
+ rgbGPI [ ib ] = (BYTE) ( GetAddrOff ( addrGPI ) - GetAddrOff ( addr ) );
+
+ if ( GetAddrOff ( addr ) == GetAddrOff ( *lpaddr ) ) {
+ xosd = xosdNone;
+ *lpaddr= addrT;
+ fFound = TRUE;
+ }
+
+ ib += 1;
+ }
+
+ // We haven't synced yet, so *lpaddr is probably pointing
+ // to something that isn't really syncronous
+
+ if ( !fFound ) {
+ xosd = (XOSD) ( GetAddrOff ( *lpaddr ) - GetAddrOff ( addrT ) );
+ GetAddrOff ( *lpaddr ) -= xosd;
+ if ( GetAddrOff ( *lpaddr ) != 0 ) {
+ (void) GetPrevInst ( hpid, htid, lpaddr );
+ }
+ }
+
+ return xosd;
+}
+
+
+VOID
+GPIShiftCache (
+ LPADDR lpaddr,
+ int *pib
+ )
+{
+ int doff = (int) ( GetAddrOff ( addrGPI ) - GetAddrOff ( *lpaddr ) );
+ int ib = 0;
+
+ *pib = 0;
+ while ( ib < doffMax && rgbGPI [ ib ] != 0 ) {
+ rgbGPI [ ib ] = (BYTE) max ( (int) rgbGPI [ ib ] - doff, 0 );
+
+ if ( rgbGPI [ ib ] == 0 && *pib == 0 ) {
+ *pib = ib;
+ }
+
+ ib += 1;
+ }
+
+ addrGPI = *lpaddr;
+}
+
+XOSD
+GPIUseCache (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr
+ )
+{
+ XOSD xosd = xosdBadAddress;
+ int fFound = FALSE;
+ ADDR addr = *lpaddr;
+ int ib = 0;
+ int ibCache= 0;
+ int ibMax = 0;
+ BYTE rgb [ doffMax ];
+
+
+ GPIShiftCache ( lpaddr, &ibMax );
+
+ _fmemset ( rgb, 0, doffMax );
+
+ GetAddrOff ( addr ) -= (int) min ( (UOFFSET) doffMax, GetAddrOff ( *lpaddr ) );
+
+ while ( !fFound && GetAddrOff ( addr ) < GetAddrOff ( *lpaddr ) ) {
+ ADDR addrT;
+ BYTE doff = (BYTE) ( GetAddrOff ( *lpaddr ) - GetAddrOff ( addr ) );
+
+ // Attempt to align with the cache
+
+ while ( doff < rgbGPI [ ibCache ] ) {
+ ibCache += 1;
+ }
+
+ if ( doff == rgbGPI [ ibCache ] ) {
+
+ // We have alignment with the cache
+
+ addr = *lpaddr;
+ addrT = addr;
+ GetAddrOff ( addrT ) -= rgbGPI [ ibMax - 1 ];
+ }
+ else {
+ SDI sdi;
+
+ sdi.dop = dopNone;
+ sdi.addr = addr;
+ addrT = addr;
+
+ disasm ( hpid, htid, &sdi );
+
+ addr = sdi.addr;
+
+ rgb [ ib ] = (BYTE) ( GetAddrOff ( addrGPI ) - GetAddrOff ( addr ) );
+
+ ib += 1;
+ }
+
+ if ( GetAddrOff ( addr ) == GetAddrOff ( *lpaddr ) ) {
+ xosd = xosdNone;
+ *lpaddr= addrT;
+ fFound = TRUE;
+ }
+
+ }
+
+ // Rebuild the cache
+
+ _fmemmove ( &rgbGPI [ ib - 1 ], &rgbGPI [ ibCache ], ibMax - ibCache );
+ _fmemcpy ( rgbGPI, rgb, ib - 1 );
+
+ return xosd;
+}
+
+XOSD
+GetPrevInst (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr
+ )
+{
+
+ if ( GetAddrOff ( *lpaddr ) == 0 ) {
+
+ return xosdBadAddress;
+ }
+ else if (
+ hpid == hpidGPI &&
+ GetAddrSeg ( *lpaddr ) == GetAddrSeg ( addrGPI ) &&
+ GetAddrOff ( *lpaddr ) < GetAddrOff ( addrGPI ) &&
+ GetAddrOff ( *lpaddr ) > GetAddrOff ( addrGPI ) - doffMax / 2
+ ) {
+
+ return GPIUseCache ( hpid, htid, lpaddr );
+ }
+ else {
+
+ return GPIBuildCache ( hpid, htid, lpaddr );
+ }
+}
+#endif // OSDEBUG4
+
+
+//
+// Return xosdContinue if overlay is loaded
+// Else return xosdNone
+//
+XOSD
+FLoadedOverlay(
+ HPID hpid,
+ LPADDR lpaddr
+ )
+{
+ XOSD xosd = xosdContinue;
+#ifdef DOS16
+ HMDI hmdi;
+ LPMDI lpmdi;
+ LPGSI lpgsi;
+ WORD seg = (WORD)GetAddrSeg( *lpaddr );
+
+ assert( ADDR_IS_LI(*lpaddr) );
+
+ if ( emiAddr ( *lpaddr ) != HpidFromHprc ( hprc ) ) {
+ if ( hmdi = LLFind (LlmdiFromHprc ( hprc ),
+ wNull,
+ &emiAddr ( *lpaddr ),
+ (LONG) emdiEMI ) ) {
+
+ lpmdi = LLLock( hmdi );
+
+ // Segment is 1 based, make zero based like GSN table
+ --seg;
+
+ // If we've got a GSN table, make sure that the seg is in
+ // range. See if the GSN is an overlay. If so, andthe
+ // frame number if the lpsel table is zero,
+ // then the overlay is not loaded
+ if ( ( lpgsi = lpmdi->lpgsi ) && seg < lpgsi->csgMax &&
+ !lpgsi->rgsgi[ seg ].sgf.saAttr &&
+ !lpmdi->lpsel[ lpgsi->rgsgi[ seg ].iovl ] ) {
+
+ xosd = xosdNone;
+ LLUnlock( hmdi );
+ }
+ }
+
+ } else {
+ xosd = xosdNone;
+ }
+#else
+ Unreferenced( hpid );
+ Unreferenced( lpaddr );
+#endif // DOS16
+ return xosd;
+}
+
+
+XOSD
+SetupExecute(
+ HPID hpid,
+ HTID htid,
+ LPHIND lphind
+ )
+/*++
+
+Routine Description:
+
+ This function is used to set up a thread for doing function evaluation.
+ The first thing it will do is to
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ HIND hind;
+ HTHD hthd;
+ HPRC hprc;
+ LPTHD lpthd;
+ LP_EXECUTE_OBJECT_EM lpeo;
+ XOSD xosd;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ if (!hthd || hthd == hthdInvalid) {
+#ifdef OSDEBUG4
+ return xosdBadThread;
+#else
+ return xosdInvalidThread;
+#endif
+ }
+
+ /*
+ * If the list of execute objects has not yet been setup then it
+ * needs to be setup now.
+ */
+
+ if (HllEo == 0) {
+ HllEo = LLInit(sizeof(EXECUTE_OBJECT_EM), llfNull, NULL, NULL);
+ }
+
+ /*
+ * Allocate an execute object for this working item.
+ */
+
+ if ((hind = LLCreate( HllEo )) == 0) {
+ return xosdOutOfMemory;
+ }
+ lpeo = LLLock( hind );
+
+ /*
+ * Ask the DM to allocate a handle on its end for its low level
+ * execute object.
+ */
+
+ xosd = SendRequest(dmfSetupExecute, hpid, htid );
+
+ if (xosd != xosdNone) {
+ LLUnlock( hind );
+ LLDelete( HllEo, hind );
+ return xosd;
+ }
+
+ lpeo->heoDm = *(HIND *) LpDmMsg->rgb;
+
+ /*
+ * Get the current register set for the thread on which we are going
+ * to do the exeucte.
+ */
+
+ lpthd = LLLock( hthd );
+
+ lpeo->hthd = hthd;
+
+ if (!( lpthd->drt & drtAllPresent )) {
+ UpdateRegisters( hprc, hthd );
+ }
+
+ _fmemcpy( &lpeo->regs, &lpthd->regs, sizeof( CONTEXT ));
+
+ LLUnlock( hthd );
+
+ /*
+ * Unlock the execute object and return its handle
+ */
+
+ LLUnlock( hind );
+
+ *lphind = hind;
+
+ return xosdNone;
+} /* SetupExecute() */
+
+
+
+XOSD
+StartExecute(
+ HPID hpid,
+ HIND hind,
+ LPEXECUTE_STRUCT lpes
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+ LP_EXECUTE_OBJECT_EM lpeo;
+ HTHD hthd;
+ HTID htid;
+ HPRC hprc;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ lpeo = LLLock( hind );
+ hthd= lpeo->hthd;
+ htid = HtidFromHthd(hthd),
+ lpes->hindDm = lpeo->heoDm;
+ FixupAddr(hpid, &lpes->addr);
+ LLUnlock( hind );
+
+ /*
+ * Cause any changes to registers to be written back
+ */
+
+ UpdateChild(hpid, htid, dmfGo);
+
+ /*
+ * Issue the command to the DM
+ */
+
+ xosd = SendRequestX(dmfStartExecute, hpid, htid,
+ sizeof(EXECUTE_STRUCT), lpes);
+
+
+ return xosd;
+} /* StartExecute() */
+
+
+
+XOSD
+CleanUpExecute(
+ HPID hpid,
+ HIND hind
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ LPTHD lpthd;
+ LP_EXECUTE_OBJECT_EM lpeo;
+
+ lpeo = LLLock( hind );
+
+ lpthd = LLLock( lpeo->hthd );
+
+ _fmemcpy( &lpthd->regs, &lpeo->regs, sizeof( CONTEXT ));
+
+ lpthd->drt = drtAllPresent | drtCntrlPresent | drtAllDirty | drtCntrlDirty;
+
+ SendRequestX(dmfCleanUpExecute, hpid, HtidFromHthd(lpeo->hthd),
+ sizeof(HIND), &lpeo->heoDm);
+
+ LLUnlock( (lpeo->hthd) );
+ LLUnlock( hind );
+
+ LLDelete( HllEo, hind );
+
+ return xosdNone;
+
+} /* CleanUpExecute() */
+
+#ifndef OSDEBUG4
+
+XOSD
+DoCustomCommand(
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LPIOL lpiol
+ )
+{
+ LPSTR lpsz = lpiol->rgbVar;
+ LPSTR p;
+ XOSD xosd;
+ char cmd[256];
+
+ //
+ // parse the command from the command line
+ //
+ p = cmd;
+ while (*lpsz && !isspace(*lpsz)) {
+ *p++ = *lpsz++;
+ }
+ *p = '\0';
+
+ //
+ // this is where you would _stricmp() for your custom em command
+ // otherwise it is passed to the dm
+ //
+
+ return SendRequestX( dmfIOCTL, hpid, htid, wValue, (LPV) lpiol );
+
+ //
+ // this is what would be executed if you have a custom em command
+ // instead of the above sendrequest()
+ //
+
+ strcpy( lpiol->rgbVar, lpsz );
+ xosd = IoctlCmd(hpid, htid, wValue, lpiol);
+
+ return xosd;
+} /* DoCustomCommand */
+
+
+
+
+XOSD
+IoctlCmd(
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LPIOL lpiol
+ )
+
+/*++
+
+Routine Description:
+
+ This function examines IOCTL requests (escapes) and deal with
+ those which the EM knows about. All others are pass on to the
+ DM for later processing.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+ HANDLE * ph;
+
+ switch( lpiol-> wFunction ) {
+ case ioctlGetProcessHandle:
+ case ioctlGetThreadHandle:
+ ph = *((HANDLE **) lpiol->rgbVar);
+ xosd = SendRequestX( dmfIOCTL, hpid, htid, wValue, lpiol );
+ *ph = *((HANDLE *) LpDmMsg->rgb);
+ return xosd;
+
+ case ioctlGetThreadContext:
+ return DoGetContext(hpid, htid, lpiol->rgbVar);
+
+ case ioctlSetThreadContext:
+ return DoSetContext(hpid, htid, lpiol->rgbVar);
+
+ case ioctlCustomCommand:
+ return DoCustomCommand(hpid, htid, wValue, lpiol);
+
+ case ioctlGeneric:
+ xosd = SendRequestX( dmfIOCTL, hpid, htid, wValue, (LPV) lpiol );
+ memcpy ( (LPVOID)lpiol->rgbVar, LpDmMsg->rgb, wValue-sizeof(IOL) );
+ return xosd;
+
+ default:
+ return SendRequestX( dmfIOCTL, hpid, htid, wValue, (LPV) lpiol );
+ }
+
+}
+
+
+XOSD
+DebugActive(
+ HPID hpid,
+ HTID htid,
+ LPDBG_ACTIVE_STRUCT lpdba
+ )
+{
+ XOSD xosd = SendRequestX(dmfDebugActive, hpid, htid, sizeof(*lpdba), lpdba);
+ if (xosd != xosdNone) {
+ lpdba->dwStatus = 0;
+ } else {
+ lpdba->dwStatus = *((DWORD *) LpDmMsg->rgb );
+ }
+ return xosd;
+}
+
+
+
+XOSD
+GetModuleList(
+ HPID hpid,
+ HTID htid,
+ LPMODULE_LIST_REQUEST Request
+ )
+{
+ XOSD xosd;
+ HLLI llmdi;
+ HMDI hmdi;
+ LPMDI lpmdi;
+ DWORD Count;
+ LPMODULE_LIST ModList;
+ LPMODULE_LIST TmpList;
+ LPMODULE_ENTRY Entry;
+ LDT_ENTRY Ldt;
+ DWORD MaxSize;
+ DWORD Size;
+ DWORD Delta;
+ DWORD i;
+ SEGMENT Selector;
+ DWORD Base;
+ DWORD Limit;
+ OBJD *ObjD;
+
+
+ if ( !Request || !(Request->List) ) {
+ return xosdInvalidParameter;
+ }
+
+ *(Request->List) = NULL;
+
+ llmdi = LlmdiFromHprc( HprcFromHpid ( hpid ));
+
+ if ( !llmdi ) {
+ return xosdInvalidProc;
+ }
+
+ //
+ // Estimate the list size, to minimize the calls to realloc.
+ //
+
+ hmdi = hmdiNull;
+ Count = 0;
+
+ while ( (hmdi = LLNext( llmdi, hmdi )) != hmdiNull ) {
+
+ lpmdi = LLLock( hmdi );
+
+ // No boolean xor operator in C...
+ if ( !(lpmdi->fFlatMode) == !(Request->Flat) ) {
+ Count += lpmdi->fFlatMode ? 1 : lpmdi->cobj;
+ }
+
+ LLUnlock( hmdi );
+ }
+
+ //
+ // Allocate the list
+ //
+ MaxSize = sizeof(MODULE_LIST) + Count * sizeof(MODULE_ENTRY);
+
+ ModList = malloc( MaxSize );
+
+ if ( !ModList ) {
+ return xosdOutOfMemory;
+ }
+
+ //
+ // Build the list
+ //
+ hmdi = hmdiNull;
+ Count = 0;
+
+ Size = sizeof(MODULE_LIST);
+
+ while ( (hmdi = LLNext( llmdi, hmdi )) != hmdiNull ) {
+
+ lpmdi = LLLock( hmdi );
+
+ if (lpmdi && lpmdi->cobj == -1) {
+ if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
+ continue;
+ }
+ }
+
+ // No boolean xor operator in C...
+ if ( !(lpmdi->fFlatMode) == !(Request->Flat) ) {
+
+ Delta = lpmdi->fFlatMode ? 1 : lpmdi->cobj;
+
+ //
+ // Reallocate buffer if necessary
+ //
+ if ( Size + Delta * sizeof(MODULE_ENTRY) > MaxSize ) {
+ Size += Delta * sizeof(MODULE_ENTRY);
+
+ TmpList = realloc( ModList, Size );
+
+ if ( !TmpList ) {
+ FreeModuleList(ModList);
+ return xosdOutOfMemory;
+ }
+
+ ModList = TmpList;
+ }
+
+ //
+ // have buffer, fill it up
+ //
+ if ( lpmdi->fFlatMode ) {
+
+ Entry = NthModuleEntry(ModList,Count);
+
+ ModuleEntryFlat(Entry) = TRUE;
+ ModuleEntrySegment(Entry) = 0;
+ ModuleEntrySelector(Entry) = 0;
+ ModuleEntryBase(Entry) = lpmdi->lpBaseOfDll;
+ ModuleEntryLimit(Entry) = lpmdi->dwSizeOfDll;
+ if (lpmdi->lpDebug) {
+ ModuleEntryType(Entry) = (DWORD) lpmdi->lpDebug->she;
+ } else {
+ ModuleEntryType(Entry) = 0;
+ }
+ ModuleEntrySectionCount(Entry) = lpmdi->cobj;
+ ModuleEntryHexe(Entry) = (HEXE)lpmdi->hemi;
+
+ Count++;
+
+ } else {
+
+ for ( i=0, ObjD = lpmdi->rgobjd;
+ i < Delta;
+ i++, ObjD++ ) {
+
+ if ( ObjD->wSel ) {
+
+ Selector = ObjD->wSel;
+
+ Entry = NthModuleEntry(ModList,Count);
+
+ ModuleEntrySegment(Entry) = i+1;
+ ModuleEntrySelector(Entry) = Selector;
+ ModuleEntryType(Entry) = 0;
+ ModuleEntrySectionCount(Entry) = 0;
+ ModuleEntryHexe(Entry) = (HEXE)lpmdi->hemi;
+
+ if ( lpmdi->fRealMode ) {
+
+ ModuleEntryFlat(Entry) = FALSE;
+ ModuleEntryReal(Entry) = TRUE;
+ ModuleEntryBase(Entry) = 0xBAD00BAD;
+ ModuleEntryLimit(Entry) = 0xBAD00BAD;
+
+ Count++;
+
+ } else {
+
+ xosd = SendRequestX( dmfQuerySelector,
+ hpid,
+ htidNull,
+ sizeof(SEGMENT),
+ &Selector );
+
+ if (xosd == xosdNone) {
+
+
+ _fmemcpy( &Ldt, LpDmMsg->rgb, sizeof(Ldt));
+
+ Base = (Ldt.HighWord.Bits.BaseHi << 0x18) |
+ (Ldt.HighWord.Bits.BaseMid << 0x10) |
+ Ldt.BaseLow;
+
+ Limit = (Ldt.HighWord.Bits.LimitHi << 0x10) |
+ Ldt.LimitLow;
+
+ ModuleEntryFlat(Entry) = FALSE;
+ ModuleEntryReal(Entry) = FALSE;
+ ModuleEntryBase(Entry) = Base;
+ ModuleEntryLimit(Entry) = Limit;
+
+ Count++;
+
+ } else {
+
+ ModuleEntryFlat(Entry) = FALSE;
+ ModuleEntryReal(Entry) = FALSE;
+ ModuleEntryBase(Entry) = 0xBAD00BAD;
+ ModuleEntryLimit(Entry) = 0xBAD00BAD;
+ Count++;
+ }
+ }
+ }
+ }
+ }
+ }
+ LLUnlock( hmdi );
+ }
+
+ ModuleListCount(ModList) = Count;
+ *(Request->List) = ModList;
+
+ return xosdNone;
+}
+
+
+XOSD
+GetMemInfo(
+ HPID hpid,
+ DWORD cbSize,
+ LPMEMINFO lpmi
+ )
+{
+ PMEMORY_BASIC_INFORMATION lpmbi;
+ ADDR addr;
+ XOSD xosd = xosdNone;
+
+ assert(cbSize == sizeof(MEMINFO));
+
+ addr = lpmi->addr;
+
+ if (ADDR_IS_LI(addr)) {
+ xosd = FixupAddr(hpid, &addr);
+ }
+
+ if (xosd == xosdNone) {
+ xosd = SendRequestX( dmfVirtualQuery, hpid, 0, sizeof(ADDR), (LPV)&addr );
+ }
+
+ if (xosd == xosdNone) {
+ lpmbi = (PMEMORY_BASIC_INFORMATION) LpDmMsg->rgb;
+ lpmi->addrAllocBase = addr;
+ lpmi->addrAllocBase.addr.off = (UOFF32)lpmbi->AllocationBase;
+ lpmi->uRegionSize = (UOFF32)lpmbi->RegionSize;
+ lpmi->dwProtect = lpmbi->Protect;
+ lpmi->dwState = lpmbi->State;
+ lpmi->dwType = lpmbi->Type;
+ }
+
+ return xosd;
+}
+#endif // !OSDEBUG4
+
+
+XOSD FAR PASCAL
+EMFunc (
+ EMF emf,
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LONG lValue
+ )
+
+/*++
+
+Routine Description:
+
+ This is the main dispatch routine for processing of commands to the
+ execution model.
+
+Arguments:
+
+ emf - Supplies the function to be performed. (Execution Model Function )
+ hpid - Supplies The process to be used.
+ htid - Supplies The thread to be used.
+ wValue - Supplies Info about the command
+ lValue - Supplies Info about the command
+
+Return Value:
+
+ returns an XOSD error code
+
+Other:
+
+ Hpid and htid can never be invalid. In some cases, they can be
+ null. The entries under P and T marked with an 0 indicate that
+ the null value is valid for this function, an X indicates that
+ it is invalid.
+
+ Brief descriptions of the wValue and lValue
+
+
+ EMF P T WVALUE LVALUE
+
+ emfGo X X ---- ----
+ emfShowDebuggee X 0 ---- ----
+ emfStop X 0 ---- ----
+ emfWriteBuf X 0 #of bytes pointer to buffer
+ emfReadBuf X 0 #of bytes pointer to buffer
+ emfSingleStep X X ---- -----
+ emfStepOver X X ---- ----
+ emfSetBreakPoint X X ---- ----
+ emfRemoveBreakPoint X X ---- ----
+ emfSetWatchPoint X X ---- ----
+ emfRemoveWatchPoint X X ---- ----
+ emfRangeStep,
+ emfRangeOver,
+ emfThreadStatus X X ---- pointer to status buf.
+ emfProcStatus X X ---- pointer to status buf.
+ emfFreeze X X ---- ----
+ emfThaw X X ---- ----
+ emfRegisterDBF 0 0 ---- pointer to dbf
+ emfInit 0 0 ---- pointer to em serv.
+ emfUnInit 0 0 ---- ----
+ emfCreatePid X 0 ---- ----
+ emfDestroyPid X 0 ---- ----
+ emfDestroyTid X X ---- ----
+ emfDestroy 0 0 hem ----
+ emfIsValid X X hem ----
+ emfSetAddr X X ---- pointer to addr
+ emfGetAddr X X ---- pointer to addr
+ emfRegValue X X register index pointer to buffer
+ emfSetReg X X register index pointer to buffer
+ emfSetFrameContext X X frame
+ emfFrameRegValue X X register index pointer to buffer
+ emfFrameSetReg X X register index pointer to buffer
+ emfProgramLoad X 0 length pntr to cmd line
+ emfProgramFree X 0 ---- ----
+ emfDebugPacket X X ---- pointer to buffer
+ emfMetric X 0 ---- pointer to metric
+ emfUnassemble X X ---- pointer to buffer
+ emfAssemble X X ---- pointer to buffer
+ emfGetObjLength X X ---- pointer to addr
+ emfIOCTL X X IOCTL type pointer to data
+ emfGetRegStruct 0 0 register index pointer to buffer
+ emfGetFlagStruct 0 0 flag index pointer to buffer
+ emfGetFlag X X flag index pointer to buffer
+ emfSetFlag X X flag index pointer to data
+ emfIsStackSetup X X ---- pointer to addr
+ emfCompareAddr ? ? ---- pointerr to rglpaddr[2]
+ emfSetupExecute X X ---- pointer to handle
+ emfStartExecute X - Handle pointer to execute_struct
+ emfCleanUpExecute X 0 Handle -----
+ emfLoadDllAck X 0 ---- -----
+ emfUnLoadDllAck X 0 ---- pointer to MDI
+ emfAttach X 0 ----
+ emfStackWalkSetup X X PC In Prolog pointer to stack walk data
+ emfStackWalkNext X X ---- pointer to stack walk data
+ emfStackWalkCleanup X X ---- pointer to stack walk data
+ emfDebugActive X 0 ---- LPDBG_ACTIVE_STRUCT
+ emfConnect X 0 ---- ----
+ emfDisconnect X 0 ---- ----
+ emfEnableCache X 0 ---- ----
+ emfGetMemInfo X 0 sizeof MEMINFO LPMEMINFO
+ emfGetFunctionInfo X 0 PADDR PFUNCTION_INFO
+
+--*/
+
+{
+ XOSD xosd = xosdNone;
+
+
+ ValidateHeap();
+
+ switch ( emf ) {
+
+ case emfShowDebuggee :
+
+ xosd = SendRequestX ( dmfSelect, hpid, htid, sizeof ( BOOL ), &wValue );
+ break;
+
+ case emfStop:
+
+ xosd = SendRequestX ( dmfStop, hpid, htid, sizeof( BOOL ), &wValue );
+ break;
+
+ case emfRegisterDBF:
+
+ InitUsage ( );
+ lpdbf = (LPDBF) lValue;
+ break;
+
+ case emfInit:
+
+ llprc = LLInit ( sizeof ( PRC ), llfNull, PiDKill, PDComp );
+
+ CallDB = ( (LPEMCB) lValue)->lpfnCallBackDB;
+ CallTL = ( (LPEMCB) lValue)->lpfnCallBackTL;
+ CallNT = ( (LPEMCB) lValue)->lpfnCallBackNT;
+
+ LpDmMsg = MHAlloc ( CBBUFFERDEF );
+ CbDmMsg = CBBUFFERDEF;
+ CallTL ( tlfSetBuffer, hpid, CBBUFFERDEF, LpDmMsg );
+
+ ImagehlpApiVersionEx(&ApiVersionForImagehlp);
+
+ break;
+
+ case emfUnInit:
+
+ /*
+ * do any uninitialization for the EM itself
+ */
+
+ MHFree(LpDmMsg);
+ LpDmMsg = NULL;
+ CbDmMsg = 0;
+
+ break;
+
+ case emfSetAddr:
+
+ xosd = SetAddr ( hpid, htid, (ADR) wValue, (LPADDR) lValue );
+ break;
+
+ case emfGetAddr:
+
+ xosd = GetAddr ( hpid, htid, (ADR) wValue, (LPADDR) lValue );
+ break;
+
+ case emfProgramLoad:
+
+ xosd = ProgramLoad ( hpid, wValue, (LPPRL) lValue );
+ break;
+
+ case emfProgramFree:
+
+ xosd = ProgramFree ( hpid, htid );
+ break;
+
+ case emfFixupAddr:
+
+ xosd = FixupAddr ( hpid, (LPADDR) lValue );
+ break;
+
+ case emfUnFixupAddr:
+
+ xosd = UnFixupAddr ( hpid, (LPADDR) lValue );
+ break;
+
+ case emfSetEmi:
+
+ xosd = SetEmi ( hpid, (LPADDR) lValue );
+ break;
+
+ case emfMetric:
+
+ xosd = DebugMetric ( hpid, htid, wValue, (LPLONG) lValue );
+ break;
+
+ case emfDebugPacket: {
+ LPRTP lprtp = (LPRTP) lValue;
+
+ xosd = DebugPacket (
+ lprtp->dbc,
+ lprtp->hpid,
+ lprtp->htid,
+ lprtp->cb,
+ (lprtp->cb == 0 ) ? NULL : (LPBYTE) lprtp->rgbVar
+ );
+ }
+ break;
+
+ case emfSetMulti:
+
+ xosd = SendRequest ( (DMF) (wValue ? dmfSetMulti : dmfClearMulti),
+ hpid, htid );
+ break;
+
+ case emfDebugger:
+
+ xosd = SendRequestX ( dmfDebugger, hpid, htid, wValue, (LPV) lValue );
+ break;
+
+ case emfRegisterEmi:
+
+ RegisterEmi ( hpid, (LPREMI) lValue );
+ break;
+
+ case emfGetModel:
+ *(WORD FAR *)lValue = CEXM_MDL_native;
+ break;
+
+ case emfGetRegStruct:
+ *((RD FAR *) lValue) = Rgrd[wValue];
+ break;
+
+ case emfGetFlagStruct:
+ *((FD FAR *) lValue) = Rgfd[wValue].fd;
+ break;
+
+ case emfGetFlag:
+ xosd = GetFlagValue ( hpid, htid, wValue, (LPV) lValue );
+ break;
+
+ case emfSetFlag:
+ xosd = SetFlagValue ( hpid, htid, wValue, (LPV) lValue );
+ break;
+
+ case emfSetupExecute:
+ xosd = SetupExecute(hpid, htid, (LPHIND) lValue);
+ break;
+
+ case emfStartExecute:
+ xosd = StartExecute(hpid, (HIND) wValue, (LPEXECUTE_STRUCT) lValue);
+ break;
+
+ case emfCleanUpExecute:
+ xosd = CleanUpExecute(hpid, (HIND) wValue);
+ break;
+
+
+
+
+
+
+
+
+
+ case emfBreakPoint:
+
+ xosd = HandleBreakpoints( hpid, wValue, lValue );
+ break;
+
+ case emfGo:
+
+ xosd = Go(hpid, htid, (LPEXOP)lValue);
+ break;
+
+ case emfSingleStep:
+ xosd = SingleStep ( hpid, htid, (LPEXOP)lValue );
+ break;
+
+ case emfRangeStep:
+ xosd = RangeStep(hpid, htid, (LPRSS)lValue);
+ break;
+
+#if 0
+ case emfReturnStep:
+ xosd = ReturnStep(hpid, htid, (LPEXOP)lValue);
+ break;
+#endif
+
+ case emfGetReg:
+ xosd = GetRegValue ( hpid, htid, wValue, (LPV) lValue );
+ break;
+
+ case emfSetReg:
+ xosd = SetRegValue ( hpid, htid, wValue, (LPV) lValue );
+ break;
+
+
+#ifdef OSDEBUG4
+
+ case emfWriteMemory:
+ {
+ LPRWMS lprwms = (LPRWMS)lValue;
+ xosd = WriteBufferCache ( hpid, htid, lprwms->lpaddr, lprwms->cbBuffer,
+ lprwms->lpbBuffer, lprwms->lpcb);
+ break;
+ }
+
+ case emfReadMemory:
+ {
+ LPRWMS lprwms = (LPRWMS)lValue;
+ xosd = ReadBuffer ( hpid, htid, lprwms->lpaddr, lprwms->cbBuffer,
+ lprwms->lpbBuffer, lprwms->lpcb);
+ break;
+ }
+
+ case emfGetMemoryInfo:
+
+ xosd = GetMemoryInfo(hpid, htid, (LPMEMINFO)lValue);
+ break;
+#endif
+
+ case emfProcessStatus:
+
+ xosd = ProcessStatus(hpid, (LPPST)lValue);
+ break;
+
+ case emfThreadStatus:
+
+ xosd = ThreadStatus(hpid, htid, (LPTST)lValue);
+ break;
+
+ case emfGetExceptionState:
+
+ xosd = GetExceptionState(hpid, htid, (EXCEPTION_CONTROL) wValue,
+ (LPEXCEPTION_DESCRIPTION) lValue);
+ break;
+
+ case emfSetExceptionState:
+
+ xosd = SetExceptionState(hpid, htid, (LPEXCEPTION_DESCRIPTION)lValue);
+ break;
+
+#ifdef OSDEBUG4
+
+ case emfFreezeThread:
+
+ xosd = FreezeThread(hpid, htid, wValue);
+ break;
+
+ case emfCreateHpid:
+
+ xosd = CreateHprc ( hpid );
+
+ if ( xosd == xosdNone ) {
+ xosd = SendRequest ( dmfCreatePid, hpid, NULL );
+ }
+
+ SyncHprcWithDM( hpid );
+
+ break;
+
+ case emfDestroyHpid:
+ {
+ HPRC hprc = HprcFromHpid(hpid);
+ xosd = SendRequest ( dmfDestroyPid, hpid, NULL );
+ if ( xosd == xosdLineNotConnected ) {
+ //
+ // Communication line broke, we'll ignore this error.
+ //
+ xosd = xosdNone;
+ }
+ DestroyHprc ( hprc );
+ }
+ break;
+
+ case emfDestroyHtid:
+ {
+ HPRC hprc = HprcFromHpid(hpid);
+ DestroyHthd( HthdFromHtid( hprc, htid ));
+ }
+ break;
+
+ case emfUnassemble:
+
+ xosd = disasm ( hpid, htid, (LPSDI) lValue );
+ break;
+
+ case emfGetPrevInst:
+
+ xosd = GetPrevInst ( hpid, htid, (LPADDR) lValue );
+ break;
+
+ case emfAssemble:
+
+ xosd = Assemble ( hpid, htid, (LPADDR) wValue, (LPSTR) lValue );
+ break;
+
+ case emfDebugActive:
+ xosd = SendRequestX(dmfDebugActive, hpid, htid, wValue, (LPVOID)lValue);
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ }
+ break;
+
+ case emfGetMessageMap:
+ *((LPMESSAGEMAP *)lValue) = &MessageMap;
+ break;
+
+ case emfGetMessageMaskMap:
+ *((LPMASKMAP *)lValue) = &MaskMap;
+ break;
+
+ case emfGetModuleList:
+ xosd = GetModuleList( hpid, htid, (LPSTR)wValue,
+ (LPMODULE_LIST FAR *)lValue );
+ break;
+
+ case emfCompareAddrs:
+ xosd = CompareAddrs( hpid, htid, (LPCAS) lValue );
+ break;
+
+
+
+#endif // OSDEBUG4
+
+
+
+
+#ifndef OSDEBUG4
+
+
+
+
+
+ case emfWriteBuf:
+
+ xosd = WriteBufferCache ( hpid, htid, wValue, (LPBYTE) lValue );
+ break;
+
+ case emfReadBuf:
+
+ {
+ DWORD cbr;
+ xosd = ReadBuffer ( hpid, htid, 0, wValue, (LPBYTE) lValue, &cbr );
+ if (xosd != xosdNone) {
+ cbr = 0;
+ }
+ xosd = cbr;
+ }
+ break;
+
+ case emfSetFrameContext:
+
+ xosd = SetFrameContext ( hpid, htid, wValue );
+ break;
+
+ case emfFrameRegValue:
+
+ xosd = GetFrameRegValue ( hpid, htid, wValue, (LPV) lValue );
+ break;
+
+ case emfFrameSetReg:
+
+ xosd = SetFrameRegValue ( hpid, htid, wValue, (LPV) lValue );
+ break;
+
+ case emfIsStackSetup:
+ {
+ ADDR addrStart = *(LPADDR)lValue;
+ xosd = IsStackSetup( hpid, htid, &addrStart );
+ }
+ break;
+
+ case emfStackWalkSetup:
+ xosd = StackWalkSetup( hpid, htid, (LPSTACKFRAME) lValue );
+ break;
+
+ case emfStackWalkNext:
+ xosd = StackWalkNext( hpid, htid, (LPSTACKFRAME) lValue );
+ break;
+
+ case emfStackWalkCleanup:
+ break;
+
+ case emfSetFrame:
+ xosd = SetFrame(hpid, htid, (PFRAME) lValue);
+ break;
+
+ case emfIOCTL:
+
+ xosd = IoctlCmd( hpid, htid, wValue, (LPIOL) lValue );
+ break;
+
+ case emfFreeze:
+
+ xosd = Freeze ( hpid, htid );
+ break;
+
+ case emfThaw:
+
+ xosd = Thaw ( hpid, htid );
+ break;
+
+ case emfCreatePid:
+
+ xosd = CreateHprc ( hpid );
+
+ if ( xosd == xosdNone ) {
+ xosd = SendRequest ( dmfCreatePid, hpid, NULL );
+ }
+
+ SyncHprcWithDM( hpid );
+
+ break;
+
+ case emfDestroyPid:
+ {
+ HPRC hprc = HprcFromHpid(hpid);
+ xosd = SendRequest ( dmfDestroyPid, hpid, NULL );
+ if ( xosd == xosdLineNotConnected ) {
+ //
+ // Communication line broke, we'll ignore this error.
+ //
+ xosd = xosdNone;
+ }
+ DestroyHprc ( hprc );
+ }
+ break;
+
+ case emfDestroyTid: {
+ HPRC hprc = HprcFromHpid(hpid);
+ DestroyHthd( HthdFromHtid( hprc, htid ));
+ }
+ break;
+
+ case emfUnassemble:
+
+ xosd = disasm ( hpid, htid, (LPSDI) lValue );
+ break;
+
+ case emfAssemble:
+ {
+ ADDR addr = {0};
+
+ GetAddr ( hpid, htid, adrCurrent, &addr );
+ xosd = Assemble ( hpid, htid, &addr, (LSZ) lValue );
+ SetAddr ( hpid, htid, adrCurrent, &addr );
+ }
+ break;
+
+ case emfGetMemInfo:
+ xosd = GetMemInfo(hpid, wValue, (LPMEMINFO)lValue);
+ break;
+
+ case emfIsOverlayLoaded:
+
+ xosd = FLoadedOverlay( hpid, (LPADDR) lValue );
+ break;
+
+ case emfDebugActive:
+ xosd = DebugActive(hpid, htid, (LPDBG_ACTIVE_STRUCT)lValue);
+ break;
+
+ case emfGetMsgMap:
+ MsgMap.Count = (sizeof( MsgInfo ) / sizeof( MsgInfo[0] ))-1;
+ *((LPMSGMAP *)lValue) = &MsgMap;
+ break;
+
+#if defined ( WIN )
+ xosd = ( WMSGTranslate ( ((LPGTM)lValue)->lpwMsg,
+ ((LPGTM)lValue)->lpwType,
+ ((LPGTM)lValue)->lszMsg,
+ ((LPGTM)lValue)->lpwMask ) ? xosdNone : xosdSyntax );
+#else
+ xosd = xosdSyntax;
+#endif
+ break;
+
+#if defined ( WIN )
+ case emfSendChar:
+
+ xosd = SendRequestX ( dmfSendChar, hpid, htid, wValue, (LPV) lValue );
+ break;
+#endif
+
+ case emfGetPrompt:
+ xosd = GetPrompt(hpid, htid, (LPPROMPTMSG)lValue);
+ break;
+
+ case emfGetModuleList:
+ xosd = GetModuleList( hpid, htid, (LPMODULE_LIST_REQUEST)lValue );
+ break;
+
+
+
+#endif // !OSDEBUG4
+
+
+
+
+
+
+
+
+
+
+ /*
+ * This will tell the DM that we have finished processing the
+ * Module Load message.
+ */
+
+ case emfLoadDllAck:
+ {
+ BYTE b = 1;
+ HPRC hprc = HprcFromHpid(hpid);
+ HTHD hthd = HthdFromHtid(hprc,htid);
+ LPPRC lpprc;
+ LPTHD lpthd;
+
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = TRUE;
+ LLUnlock(hprc);
+ if (hthd) {
+ lpthd = LLLock(hthd);
+ lpthd->fRunning = TRUE;
+ LLUnlock(hthd);
+ }
+
+ CallTL ( tlfReply, hpid, 1, &b );
+ }
+ xosd = xosdNone;
+ break;
+
+ case emfUnLoadDllAck:
+
+ if ( UnLoadFixups (hpid, (HEMI)lValue, wValue ) ) {
+ xosd = xosdNone;
+ } else {
+ xosd = xosdUnknown;
+ }
+ break;
+
+ case emfSetPath:
+ xosd = SetPath(hpid, htid, wValue, (LSZ)lValue);
+ break;
+
+ case emfConnect:
+#ifdef OSDEBUG4
+ xosd = CallTL( tlfLoadDM, hpid, sizeof(LOADDMSTRUCT), &LoadDmStruct);
+ if (xosd == xosdNone) {
+ xosd = SendRequest( dmfInit, hpid, htid );
+ }
+#else
+ xosd = SendRequest( dmfInit, hpid, htid );
+#endif
+ break;
+
+ case emfDisconnect:
+ xosd = SendRequest( dmfUnInit, hpid, htid );
+ break;
+
+#ifdef OSDEBUG4
+ case emfInfoReply:
+#else
+ case emfMiscReply:
+#endif
+ CallTL ( tlfReply, hpid, wValue, (LPV)lValue );
+ xosd = xosdNone;
+ break;
+
+ case emfGetFunctionInfo:
+ xosd = GetFunctionInfo( hpid, (PADDR)wValue, (PFUNCTION_INFO)lValue );
+ break;
+
+ default:
+ assert ( FALSE );
+ xosd = xosdUnknown;
+ break;
+ }
+
+ ValidateHeap();
+ return xosd;
+} /* EMFunc() */
+
+
+/*
+**
+*/
+
+DllInit(
+ HANDLE hModule,
+ DWORD dwReason,
+ DWORD dwReserved
+ )
+{
+ Unreferenced(hModule);
+ Unreferenced(dwReserved);
+
+ switch (dwReason) {
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ if (LpSendBuf) {
+ MHFree(LpSendBuf);
+ CbSendBuf = 0;
+ }
+ if (LpDmMsg) {
+ MHFree(LpDmMsg);
+ CbDmMsg = 0;
+ }
+ DeleteCriticalSection(&csCache);
+ break;
+
+ case DLL_PROCESS_ATTACH:
+
+ InitializeCriticalSection(&csCache);
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/private/windbg/em/emdp2.c b/private/windbg/em/emdp2.c
new file mode 100644
index 000000000..9f40c8bb0
--- /dev/null
+++ b/private/windbg/em/emdp2.c
@@ -0,0 +1,2528 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ emdp2.c
+
+Abstract:
+
+ This file contains the some of the machine independent portions of the
+ execution model. The machine dependent portions are in other files.
+
+Author:
+
+ Kent Forschmiedt (kentf) 10-23-92
+
+Environment:
+
+ Win32 -- User
+
+Notes:
+
+ The orginal source for this came from the CodeView group.
+
+--*/
+
+extern CRITICAL_SECTION csCache;
+
+#ifdef OSDEBUG4
+
+#define DECL_XOSD(n,s) {s,n},
+static struct _EMERROR {
+ LPSTR lpsz;
+ XOSD xosd;
+} EmErrors[] = {
+#include "xosd.h"
+};
+const int nErrors = (sizeof(EmErrors)/sizeof(*EmErrors));
+#undef DECL_XOSD
+
+#else
+
+#define DECL_STR(s,v) {s,v},
+static struct _EMERROR {
+ LPSTR lpsz;
+ XOSD xosd;
+} EmErrors[] = {
+#include "emerror.h"
+};
+const int nErrors = (sizeof(EmErrors)/sizeof(*EmErrors));
+#undef DECL_STR
+
+#endif
+
+
+LPSTR
+EmError(
+ XOSD xosd
+ )
+{
+ int i;
+ for (i = 0; i < nErrors; i++) {
+ if (EmErrors[i].xosd == xosd) {
+ return EmErrors[i].lpsz;
+ }
+ }
+ return EmErrors[0].lpsz;
+}
+
+
+
+XOSD
+LoadFixups (
+ HPID hpid,
+ MODULELOAD UNALIGNED *lpmdl
+ )
+/*++
+
+Routine Description:
+
+ This function is called in response to a module load message. It
+ will cause information to be internally setup for doing fixups/
+ unfixups ...
+
+Arguments:
+
+ hpid - Supplies a handle for the process
+
+ lpmdl - Supplies a pointer to a module load message from the DM
+
+Return Value:
+
+ xosd Error code
+
+--*/
+
+{
+ XOSD xosd = xosdNone;
+ HMDI hmdi;
+ MDI UNALIGNED * lpmdi;
+ LPCH lpchName;
+ HPRC hprc = HprcFromHpid( hpid );
+ HLLI llmdi = LlmdiFromHprc ( hprc );
+ LPPRC lpprc;
+ int cobj;
+ //DWORD fIsRemote;
+ //LPSTR p1;
+
+
+ hmdi = LLCreate ( llmdi );
+ if ( hmdi == 0 ) {
+ assert( "load dll cannot create llmdi" && FALSE );
+ return xosdOutOfMemory;
+ }
+
+ lpmdi = (MDI UNALIGNED *)LLLock ( hmdi );
+
+ lpmdi->mte = lpmdl->mte;
+ lpmdi->lpBaseOfDll = (DWORD)lpmdl->lpBaseOfDll;
+ lpmdi->dwSizeOfDll = lpmdl->dwSizeOfDll;
+ lpmdi->StartingSegment = lpmdl->StartingSegment;
+
+ lpmdi->CSSel = lpmdl->CSSel;
+ lpmdi->DSSel = lpmdl->DSSel;
+
+ lpmdi->fRealMode = lpmdl->fRealMode;
+ lpmdi->fOffset32 = lpmdl->fOffset32;
+ lpmdi->fFlatMode = lpmdl->fFlatMode;
+
+ if (lpmdi->fFlatMode) {
+ lpprc = LLLock( hprc );
+ lpprc->selFlatCs = lpmdi->CSSel;
+ lpprc->selFlatDs = lpmdi->DSSel;
+ LLUnlock( hprc );
+ }
+
+
+ //
+ // cobj might be -1 or 0. If it is -1, the objdir load is
+ // deferred until we need it. If it is 0, later segloads
+ // will add sections one at a time.
+ //
+
+ cobj = lpmdi->cobj = lpmdl->cobj;
+ if (cobj == -1) {
+ cobj = 0;
+ }
+
+ lpmdi->rgobjd = NULL;
+ lpchName = ( (LPCH) &( lpmdl->rgobjd[cobj] ) );
+
+ lpmdi->lszName = MHAlloc ( strlen ( lpchName ) + 1 );
+ if ( lpmdi->lszName == NULL ) {
+ LLUnlock( hmdi );
+ assert( "load dll cannot dup mod name" && FALSE );
+ return xosdOutOfMemory;
+ }
+ strcpy ( lpmdi->lszName, lpchName );
+
+ if (cobj) {
+ lpmdi->rgobjd = (LPOBJD) MHAlloc ( sizeof(OBJD) * cobj);
+ if ( lpmdi->rgobjd == NULL ) {
+ LLUnlock( hmdi );
+ assert( "load cannot create rgobjd" && FALSE );
+ return xosdOutOfMemory;
+ }
+ memcpy( lpmdi->rgobjd, lpmdl->rgobjd, sizeof(OBJD) * cobj );
+ }
+
+ LLAdd ( llmdi, hmdi );
+
+ xosd = CallDB (
+ dbcModLoad,
+ hpid,
+ NULL,
+ CEXM_MDL_native,
+ (UINT) hmdi,
+ lpmdi->lszName
+ );
+
+ LLUnlock ( hmdi );
+
+ return xosd;
+}
+
+
+
+BOOL
+UnLoadFixups (
+ HPID hpid,
+ HEMI hemi,
+ BOOL fSendAck
+ )
+/*++
+
+Routine Description:
+
+ This function is called in response to a module unload message.
+
+ It returns the emi of the module being unloaded
+
+Arguments:
+
+ hprc - Supplies a handle for the process
+ hemi - Supplies hemi (if Unload)
+
+Return Value:
+
+ TRUE if deleted
+
+--*/
+
+{
+ HLLI hlli;
+ HMDI hmdi;
+ BYTE b = 1;
+
+
+ hlli = LlmdiFromHprc( HprcFromHpid ( hpid ));
+ hmdi = LLFind( hlli, 0, (LPVOID)&hemi, (LONG) emdiEMI);
+
+ if (hmdi != hmdiNull) {
+ LLDelete( hlli, hmdi );
+ }
+
+ /*
+ * Ack back to to DM
+ */
+
+ if (fSendAck) {
+ CallTL ( tlfReply, hpid, 1, &b );
+ }
+
+ return hmdi != hmdiNull;
+} /* UnLoadFixups() */
+
+
+
+
+
+
+/**** ****
+ * *
+ * PURPOSE: *
+ * *
+ * INPUTS: *
+ * *
+ * OUTPUTS: *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+
+XOSD
+CreateThreadStruct (
+ HPID hpid,
+ TID tid,
+ HTID *lphtid
+ )
+{
+ HPRC hprc = HprcFromHpid ( hpid );
+ LPPRC lpprc = LLLock ( hprc );
+ HTHD hthd = hthdNull;
+ LPTHD lpthd = NULL;
+
+ hthd = HthdFromTid ( hprc, tid );
+ assert(hthd == NULL);
+ if ( hthd == hthdNull ) {
+
+ hthd = LLCreate ( lpprc->llthd );
+ lpthd = LLLock ( hthd );
+
+ CallDB (
+ dbcoCreateThread,
+ hpid,
+ NULL,
+ CEXM_MDL_native,
+ sizeof ( HTID ),
+ (LPVOID)lphtid
+ );
+
+ lpthd->htid = *lphtid;
+ lpthd->hprc = hprc;
+ lpthd->tid = tid;
+ lpthd->drt = drtNonePresent;
+ lpthd->dwcbSpecial = lpprc->dmi.cbSpecialRegs;
+ if (lpthd->dwcbSpecial) {
+ lpthd->pvSpecial = malloc(lpthd->dwcbSpecial);
+ }
+
+ LLAdd ( lpprc->llthd, hthd );
+ }
+ else {
+ lpthd = LLLock ( hthd );
+ assert ( lpthd->fVirtual == TRUE );
+ *lphtid = lpthd->htid;
+ lpthd->fVirtual = FALSE;
+ lpthd->drt = drtNonePresent;
+ }
+
+ LLUnlock ( hthd );
+ LLUnlock ( hprc );
+
+ return xosdNone;
+} /* CreateThreadStruct() */
+
+
+VOID
+SyncHprcWithDM(
+ HPID hpid
+ )
+{
+ BYTE rgb[sizeof(DBB) + sizeof(EXCMD)];
+ LPDBB pdbb = (LPDBB) rgb;
+ LPEXCEPTION_CONTROL lpexc = &((LPEXCMD)(pdbb + 1))->exc;
+ LPEXCEPTION_DESCRIPTION lpexd = &((LPEXCMD)(pdbb + 1))->exd;
+ LPEXCEPTION_DESCRIPTION lpexdr;
+ HEXD hexd;
+ HPRC hprc;
+ HLLI llexc;
+ LONG lT;
+
+ hprc = HprcFromHpid(hpid);
+ if (!hprc) {
+ return;
+ }
+ llexc = ((LPPRC)LLLock(hprc))->llexc;
+ LLUnlock(hprc);
+
+ // force the DMINFO struct to get loaded
+
+ DebugMetric ( hpid, NULL, mtrcProcessorType, &lT );
+
+
+ // get exception info
+
+ pdbb->dmf = dmfGetExceptionState;
+ pdbb->hpid = hpid;
+ pdbb->htid = NULL;
+ *lpexc = exfFirst;
+
+ do {
+
+ CallTL(tlfRequest, hpid, sizeof(rgb), rgb);
+ if (LpDmMsg->xosdRet != xosdNone) {
+ break;
+ }
+
+ //
+ // add to local exception list
+ //
+ hexd = LLCreate( llexc );
+ LLAdd( llexc, hexd );
+ lpexdr = LLLock( hexd );
+ *lpexdr = *((LPEXCEPTION_DESCRIPTION)(LpDmMsg->rgb));
+ LLUnlock( hexd );
+
+ //
+ // ask for the next one
+ //
+ *lpexd = *((LPEXCEPTION_DESCRIPTION)(LpDmMsg->rgb));
+ *lpexc = exfNext;
+
+ } while (lpexd->dwExceptionCode != 0);
+}
+
+
+XOSD
+CreateHprc (
+ HPID hpid
+ )
+{
+ XOSD xosd = xosdNone;
+ HPRC hprc;
+ LPPRC lpprc;
+
+ hprc = LLCreate ( llprc );
+
+ if ( hprc == 0 ) {
+ return xosdOutOfMemory;
+ }
+
+ LLAdd ( llprc, hprc );
+
+ lpprc = (LPPRC) LLLock ( hprc );
+
+ lpprc->stat = statDead;
+ lpprc->hpid = hpid;
+ lpprc->pid = (PID) 0;
+ lpprc->fDmiCache = 0;
+
+ GetAddrSeg ( lpprc->addrTaskData ) = 0;
+ GetAddrOff ( lpprc->addrTaskData ) = 0;
+
+ lpprc->cFPThread = 1;
+
+ lpprc->llthd = LLInit (
+ sizeof ( THD ),
+ llfNull,
+ TiDKill,
+ TDComp
+ );
+
+ if ( lpprc->llthd == 0 ) {
+ xosd = xosdOutOfMemory;
+ }
+
+ lpprc->llmdi = LLInit ( sizeof ( MDI ), llfNull, MDIKill, MDIComp );
+
+ if ( lpprc->llmdi == 0 ) {
+ xosd = xosdOutOfMemory;
+ }
+
+ lpprc->llexc = LLInit ( sizeof(EXCEPTION_DESCRIPTION),
+ llfNull,
+ NULL,
+ EXCComp );
+ if ( lpprc->llexc == 0 ) {
+ xosd = xosdOutOfMemory;
+ }
+
+ LLUnlock ( hprc );
+
+ return xosd;
+}
+
+VOID
+DestroyHprc (
+ HPRC hprc
+ )
+{
+ EnterCriticalSection(&csCache);
+
+ LLDelete ( llprc, hprc );
+ FlushPTCache();
+
+ LeaveCriticalSection(&csCache);
+}
+
+VOID
+DestroyHthd(
+ HTHD hthd
+ )
+{
+ LPTHD lpthd;
+ HPRC hprc;
+
+ EnterCriticalSection(&csCache);
+
+ lpthd = LLLock ( hthd );
+ hprc = lpthd->hprc;
+ LLUnlock ( hthd );
+ LLDelete ( LlthdFromHprc ( hprc ), hthd );
+ FlushPTCache();
+
+ LeaveCriticalSection(&csCache);
+}
+
+void EMENTRY
+PiDKill (
+ LPVOID lpv
+ )
+{
+ LPPRC lpprc = (LPPRC) lpv;
+ LLDestroy ( lpprc->llthd );
+ LLDestroy ( lpprc->llmdi );
+ LLDestroy ( lpprc->llexc );
+}
+
+void EMENTRY
+TiDKill (
+ LPVOID lpv
+ )
+{
+ LPTHD lpthd = (LPTHD) lpv;
+ if (lpthd->pvSpecial) {
+ free(lpthd->pvSpecial);
+ }
+}
+
+void EMENTRY
+MDIKill(
+ LPVOID lpv
+ )
+{
+ LPMDI lpmdi = (LPMDI)lpv;
+ if (lpmdi->lszName) {
+ MHFree(lpmdi->lszName);
+ lpmdi->lszName = NULL;
+ }
+ if (lpmdi->rgobjd) {
+ MHFree(lpmdi->rgobjd);
+ lpmdi->rgobjd = NULL;
+ }
+}
+
+
+int EMENTRY
+PDComp (
+ LPVOID lpv1,
+ LPVOID lpv2,
+ LONG lParam
+ )
+{
+
+ Unreferenced(lParam);
+
+ if ( ( (LPPRC) lpv1)->hpid == *( (LPHPID) lpv2 ) ) {
+ return fCmpEQ;
+ }
+ else {
+ return fCmpLT;
+ }
+}
+
+int EMENTRY
+TDComp (
+ LPVOID lpv1,
+ LPVOID lpv2,
+ LONG lParam
+ )
+{
+
+ Unreferenced(lParam);
+
+ if ( ( (LPTHD) lpv1)->htid == *( (LPHTID) lpv2 ) ) {
+ return fCmpEQ;
+ }
+ else {
+ return fCmpLT;
+ }
+}
+
+
+int EMENTRY
+MDIComp (
+ LPVOID lpv1,
+ LPVOID lpv,
+ LONG lParam
+ )
+{
+ LPMDI lpmdi = (LPMDI) lpv1;
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ CHAR fn1[MAX_PATH];
+ CHAR fn2[MAX_PATH];
+
+
+ switch ( lParam ) {
+
+ case emdiName:
+ if ( !strchr(lpv,'|') ) {
+ char *p1,*p2;
+ p1 = lpmdi->lszName;
+ if ( *p1 == '|' ) {
+ p1++;
+ }
+ p2 = strchr(p1,'|');
+ if ( !p2 ) {
+ p2 = p1 + strlen(p1);
+ }
+ memcpy(fn2, p1, p2-p1);
+ fn2[p2-p1]='\0';
+
+ _splitpath( (LPSTR)lpv, NULL, NULL, fname, ext );
+ _makepath( fn1, NULL, NULL, fname, ext );
+
+ _splitpath( (LPSTR)fn2, NULL, NULL, fname, ext );
+ _makepath( fn2, NULL, NULL, fname, ext );
+
+ return _stricmp ( fn1, fn2 );
+
+ } else {
+
+ return _stricmp ( lpv, lpmdi->lszName );
+
+ }
+
+ case emdiEMI:
+ return !(lpmdi->hemi == *(( HEMI * ) lpv ) );
+
+ case emdiMTE:
+ return !(lpmdi->mte == *((LPWORD) lpv ));
+
+ case emdiBaseAddr:
+ return !(lpmdi->lpBaseOfDll == *((OFFSET *) lpv));
+
+ default:
+ break;
+ }
+}
+
+
+int
+EXCComp(
+ LPVOID lpRec,
+ LPVOID lpVal,
+ LONG lParam
+ )
+{
+ Unreferenced(lParam);
+ if ( ((LPEXCEPTION_DESCRIPTION)lpRec)->dwExceptionCode ==
+ *((LPDWORD)lpVal)) {
+ return fCmpEQ;
+ } else {
+ return fCmpLT;
+ }
+}
+
+
+DWORD
+ConvertOmapFromSrc(
+ LPMDI lpmdi,
+ DWORD addr
+ )
+{
+ DWORD rva;
+ DWORD comap;
+ LPOMAP pomapLow;
+ LPOMAP pomapHigh;
+ DWORD comapHalf;
+ LPOMAP pomapMid;
+
+
+ if (!lpmdi) {
+ return addr;
+ }
+
+ if ( lpmdi->lpgsi == NULL ) {
+ SHWantSymbols( (HEXE)lpmdi->hemi );
+ lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)lpmdi->hemi );
+ }
+
+ if ((!lpmdi->lpDebug) || (!lpmdi->lpDebug->lpOmapFrom)) {
+ return addr;
+ }
+
+ rva = addr - lpmdi->lpBaseOfDll;
+
+ comap = lpmdi->lpDebug->cOmapFrom;
+ pomapLow = lpmdi->lpDebug->lpOmapFrom;
+ pomapHigh = pomapLow + comap;
+
+ while (pomapLow < pomapHigh) {
+
+ comapHalf = comap / 2;
+
+ pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
+
+ if (rva == pomapMid->rva) {
+ return lpmdi->lpBaseOfDll + pomapMid->rvaTo;
+ }
+
+ if (rva < pomapMid->rva) {
+ pomapHigh = pomapMid;
+ comap = (comap & 1) ? comapHalf : (comapHalf - 1);
+ } else {
+ pomapLow = pomapMid + 1;
+ comap = comapHalf;
+ }
+ }
+
+ assert(pomapLow == pomapHigh);
+
+ //
+ // If no exact match, pomapLow points to the next higher address
+ //
+ if (pomapLow == lpmdi->lpDebug->lpOmapFrom) {
+ //
+ // This address was not found
+ //
+ return 0;
+ }
+
+ if (pomapLow[-1].rvaTo == 0) {
+ //
+ // This address is not translated so just return the original
+ //
+ return addr;
+ }
+
+ //
+ // Return the closest address plus the bias
+ //
+ return lpmdi->lpBaseOfDll + pomapLow[-1].rvaTo + (rva - pomapLow[-1].rva);
+}
+
+
+DWORD
+ConvertOmapToSrc(
+ LPMDI lpmdi,
+ DWORD addr
+ )
+{
+ DWORD rva;
+ DWORD comap;
+ LPOMAP pomapLow;
+ LPOMAP pomapHigh;
+ DWORD comapHalf;
+ LPOMAP pomapMid;
+ INT i;
+
+
+ if (!lpmdi) {
+ return addr;
+ }
+
+ if ( lpmdi->lpgsi == NULL ) {
+ SHWantSymbols( (HEXE)lpmdi->hemi );
+ lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)lpmdi->hemi );
+ }
+
+ if ((!lpmdi->lpDebug) || (!lpmdi->lpDebug->lpOmapTo)) {
+ return addr;
+ }
+
+ rva = addr - lpmdi->lpBaseOfDll;
+
+ comap = lpmdi->lpDebug->cOmapTo;
+ pomapLow = lpmdi->lpDebug->lpOmapTo;
+ pomapHigh = pomapLow + comap;
+
+ while (pomapLow < pomapHigh) {
+
+ comapHalf = comap / 2;
+
+ pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
+
+ if (rva == pomapMid->rva) {
+ if (pomapMid->rvaTo == 0) {
+ //
+ // We are probably in the middle of a routine
+ //
+ i = -1;
+ while ((&pomapMid[i] != lpmdi->lpDebug->lpOmapTo) && pomapMid[i].rvaTo == 0) {
+ //
+ // Keep on looping back until the beginning
+ //
+ i--;
+ }
+ return lpmdi->lpBaseOfDll + pomapMid[i].rvaTo;
+ } else {
+ return lpmdi->lpBaseOfDll + pomapMid->rvaTo;
+ }
+ }
+
+ if (rva < pomapMid->rva) {
+ pomapHigh = pomapMid;
+ comap = (comap & 1) ? comapHalf : (comapHalf - 1);
+ } else {
+ pomapLow = pomapMid + 1;
+ comap = comapHalf;
+ }
+ }
+
+ assert(pomapLow == pomapHigh);
+
+ //
+ // If no exact match, pomapLow points to the next higher address
+ //
+ if (pomapLow == lpmdi->lpDebug->lpOmapTo) {
+ //
+ // This address was not found
+ //
+ return 0;
+ }
+
+ if (pomapLow[-1].rvaTo == 0) {
+ return 0;
+ }
+
+ //
+ // Return the new address plus the bias
+ //
+ return lpmdi->lpBaseOfDll + pomapLow[-1].rvaTo + (rva - pomapLow[-1].rva);
+}
+
+
+XOSD
+FixupAddr (
+ HPID hpid,
+ LPADDR lpaddr
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to convert addresses between linker index (section
+ or segment relative) addresses and real addresses (segment:offset).
+
+Arguments:
+
+ hpid - Supplies the handle to the process for context to convert
+ the address.
+ lpaddr - Pointer to address packet to be converted.
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ HMDI hmdi;
+
+ // Check to see if the address is already a segment:offset pair and return if it is.
+
+ if ( !ADDR_IS_LI(*lpaddr) ) {
+ return xosdNone;
+ }
+
+ // Now based on the emi field of the address (which uniquely defines the
+ // executable module in the symbol handler), get the conversion information.
+
+ assert( emiAddr( *lpaddr ) != 0 );
+
+ if ( (HPID)emiAddr ( *lpaddr ) == hpid ) {
+
+ ADDR_IS_LI(*lpaddr) = FALSE;
+
+#if defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
+
+ // The opposite of the code in UnFixupAddr -- Remove the 1 which was
+ // stuck in to make sure we did not think it was an absolute.
+
+ lpaddr->addr.seg = 0;
+
+#endif // TARGET_MIPS || TARGET_ALPHA || TARGET_PPC
+
+ } else {
+
+ // Based on the symbol handler handle find our internal data structure
+ // for the dll.
+
+ hmdi = LLFind ( LlmdiFromHprc ( HprcFromHpid(hpid) ), 0,
+ (LPVOID)&emiAddr ( *lpaddr ), (LONG) emdiEMI );
+
+ if ( hmdi == 0 ) {
+
+ ADDR_IS_LI(*lpaddr) = FALSE;
+
+ } else {
+
+ LPMDI lpmdi = LLLock ( hmdi );
+ WORD wsel;
+ LPSGI lpsgi;
+ unsigned short seg;
+
+ // If we could not find an internal structure for the DLL
+ // then it must be some type of error.
+
+ if ( lpmdi == NULL ) {
+ return xosdUnknown;
+ }
+
+ if (lpmdi->cobj == -1) {
+ if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
+ return xosdUnknown;
+ }
+ }
+
+ // If the segment/selector is 0 then it must be an absolute symbol
+ // and we therefore don't need to do any conversion.
+ //
+ // If we could get no information describing the symbol information
+ // then we can't do any conversion.
+
+ if ( lpmdi->lpgsi == NULL ) {
+ LLUnlock( hmdi );
+ SHWantSymbols( (HEXE)(emiAddr( *lpaddr )) );
+ lpmdi = LLLock ( hmdi );
+ lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)(emiAddr( *lpaddr )) );
+ }
+
+ seg = GetAddrSeg( *lpaddr );
+
+ if ( seg > 0 ) {
+ if (lpmdi->lpgsi) {
+
+ // Get the linker index number for the segment number
+ // and assure that it is valid.
+
+ wsel = (WORD) (GetAddrSeg( *lpaddr ) - 1);
+ if ( wsel >= lpmdi->lpgsi->csgMax ) {
+
+ // Linker index is either not valid or not yet loaded
+
+ return xosdUnknown;
+ } else {
+
+ // We know which section it comes from. To compute the
+ // real offset we need to add the following items
+ // together.
+ //
+ // original offset GetAddrOff( *lpaddr )
+ // offset of index in section lpsgi->doffseg
+ // (this is the group offset)
+ // offset of section from base of rgobjd[physSeg-1].offset
+ // image
+ //
+ // The segment can just be loaded from the MAP. Notice
+ // that we will infact "lose" information in this
+ // conversion sometimes. Specifically a cs:data address
+ // after unfixup and fixup will come out ds:data. This
+ // is "expected" behavior.
+
+ lpsgi = &lpmdi->lpgsi->rgsgi[ wsel ];
+
+ if (lpmdi->rgobjd[(lpsgi->isgPhy-1)].wPad == 0) {
+ return xosdUnknown;
+ }
+
+ GetAddrOff ( *lpaddr ) += lpsgi->doffseg;
+
+ GetAddrOff( *lpaddr ) +=
+ (UOFFSET) (lpmdi->rgobjd[ (lpsgi->isgPhy - 1) ]. offset);
+
+ // Make sure we adjust to the original start (just in case the
+ // image was modified since the CV info was written).
+ //
+ // rgobjd contains the VA for each section start.
+ // lpSecStart contains the calculated RVA for the section start.
+
+ if (lpmdi->lpDebug->lpSecStart) {
+ GetAddrOff ( *lpaddr ) +=
+ lpmdi->lpDebug->lpSecStart[(lpsgi->isgPhy - 1)].Offset -
+ (lpmdi->rgobjd[(lpsgi->isgPhy - 1)].offset -
+ lpmdi->lpBaseOfDll);
+ }
+ seg = lpmdi->rgobjd[(lpsgi->isgPhy - 1)].wSel;
+ }
+
+ GetAddrSeg ( *lpaddr ) = seg;
+ }
+ }
+
+ // Set the bits describing the address
+
+ ADDR_IS_REAL(*lpaddr) = lpmdi->fRealMode;
+ ADDR_IS_OFF32(*lpaddr) = lpmdi->fOffset32;
+ ADDR_IS_FLAT(*lpaddr) = lpmdi->fFlatMode;
+ ADDR_IS_LI(*lpaddr) = FALSE;
+
+ if (lpmdi->lpDebug->lpOmapFrom) {
+ DWORD off = ConvertOmapFromSrc( lpmdi, lpaddr->addr.off );
+ if (off) {
+ lpaddr->addr.off = off;
+ }
+ }
+
+ // Now release the module description
+
+ LLUnlock ( hmdi );
+ }
+ }
+
+ return xosdNone;
+} /* FixupAddr() */
+
+
+XOSD
+UnFixupAddr(
+ HPID hpid,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to convert addresses from Real Physical addresses
+ to linker index addresses. Linker index addresses have an advantage
+ to the symbol handler in that we know which DLL the address is in.
+
+ The result of calling UnFixupAddr should be one of the following:
+
+ 1. A true Linker Index address. In this case
+ emi == the HEXE (assigned by SH) for the DLL containning the address
+ seg == the Section number of the address
+ off == the offset in the Section
+
+ 2. Address not in a dll. In this case
+ emi == the HPID of the current process
+ seg == the physical selector of the address
+ off == the offset in the physical selector
+
+ 3. An error
+
+Arguments:
+
+ hpid - Supplies the handle to the process the address is in
+ lpaddr - Supplies a pointer to the address to be converted. The
+ address is converted in place
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ HPRC hprc;
+ LPPRC lpprc;
+ LDT_ENTRY ldt;
+ XOSD xosd;
+
+ // If the address already has the Linker Index bit set then there
+ // is no work for use to do.
+
+ if ( ADDR_IS_LI(*lpaddr) ) {
+ return xosdNone;
+ }
+
+ // If the EMI field in the address is not already filled in, then
+ // we will now fill it in.
+
+ if ( emiAddr ( *lpaddr ) == 0 ) {
+ SetEmi ( hpid, lpaddr );
+ }
+
+ // Get the internal Process Descriptor structure
+
+ hprc = HprcFromHpid(hpid);
+
+ // Is the EMI we got from the address equal to the process handle? if so then
+ // we cannot unfix the address and should just set the bits in the mode field.
+
+ if ( (HPID)emiAddr ( *lpaddr ) != hpid ) {
+ LPMDI lpmdi;
+ HMDI hmdi = LLFind (LlmdiFromHprc ( hprc ), 0,
+ (LPVOID)&emiAddr ( *lpaddr ), (LONG) emdiEMI);
+ WORD igsn;
+ LPSGI lpsgi;
+ unsigned long ulo;
+ USHORT seg;
+ ULONG iSeg;
+
+ if (hmdi == 0) {
+
+ // If we get here we are really messed up. We have a valid (?)
+ // emi field set in the ADDR packeet, it is not the process
+ // handle, but it does not correspond to a known emi in the
+ // current process. Therefore bail out as an error
+
+ return xosdUnknown;
+ }
+
+ lpmdi = LLLock ( hmdi );
+ if ( lpmdi == NULL ) {
+ return xosdUnknown;
+ }
+
+ if (lpmdi->cobj == -1) {
+ if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
+ return xosdUnknown;
+ }
+ }
+
+ // Start out by using the "default" set of fields. These are based
+ // on what our best guess is for the executable module. This is based
+ // on what the DM told use when it loaded the exe.
+
+ ADDR_IS_REAL(*lpaddr) = lpmdi->fRealMode;
+ ADDR_IS_OFF32(*lpaddr) = lpmdi->fOffset32;
+ ADDR_IS_FLAT(*lpaddr) = lpmdi->fFlatMode;
+
+ // If there is not table describing the layout of segments in the exe, there
+ // is no debug information and there fore no need to continue process.
+
+ if ( lpmdi->lpgsi == NULL ) {
+ LLUnlock( hmdi );
+ SHWantSymbols( (HEXE)(emiAddr( *lpaddr )) );
+ lpmdi = LLLock ( hmdi );
+ lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)(emiAddr( *lpaddr )) );
+ }
+
+ if (lpmdi->lpDebug->lpOmapTo) {
+ DWORD off = ConvertOmapToSrc( lpmdi, lpaddr->addr.off );
+ if (off) {
+ lpaddr->addr.off = off;
+ }
+ }
+
+ if ( lpmdi->lpgsi == NULL ) {
+ LLUnlock( hmdi );
+ goto itsBogus;
+ }
+
+ lpsgi = lpmdi->lpgsi->rgsgi;
+ ulo = (unsigned long)GetAddrOff( *lpaddr );
+ seg = (unsigned short)GetAddrSeg( *lpaddr );
+
+ // First correct out the "segment" portion of the offset.
+ //
+ // For flat addresses this means that we locate which section
+ // number the address fell in and adjust back to that section
+ //
+ // For non-flat address this mains locate which segment number
+ // the selector matches
+
+ assert(lpmdi->cobj >= 0);
+
+ if (ADDR_IS_FLAT( *lpaddr )) {
+
+ // If there's a SecStart table use it (it should contain the section
+ // values the symbolic was built with).
+ if (lpmdi->lpDebug->lpSecStart) {
+ DWORD NewOff = ulo - lpmdi->lpBaseOfDll;
+ LPSECSTART SecStart = lpmdi->lpDebug->lpSecStart;
+
+ for ( iSeg=0; iSeg < lpmdi->cobj; iSeg++) {
+ if ((SecStart[iSeg].Offset <= NewOff) &&
+ NewOff < (SecStart[iSeg].Offset + SecStart[iSeg].Size)
+ ) {
+ ulo = NewOff - SecStart[iSeg].Offset;
+// ulo -=
+// SecStart[iSeg].Offset -
+// (lpmdi->rgobjd[iSeg].offset - lpmdi->lpBaseOfDll);
+ break;
+ }
+ }
+ } else {
+
+ // Then convert to a true rva so we can find it in the symbol tree.
+
+ for ( iSeg=0; iSeg < lpmdi->cobj; iSeg++) {
+ if ((lpmdi->rgobjd[ iSeg ].offset <= ulo) &&
+ (ulo < (OFFSET) (lpmdi->rgobjd[ iSeg ].offset +
+ lpmdi->rgobjd[ iSeg].cb))
+ ) {
+ ulo -= lpmdi->rgobjd[ iSeg ].offset;
+ break;
+ }
+ }
+ }
+ } else {
+ for (iSeg=0; iSeg < lpmdi->cobj; iSeg++) {
+ if (lpmdi->rgobjd[iSeg].wSel == seg) {
+ break;
+ }
+ }
+ }
+
+ if (iSeg == lpmdi->cobj) {
+ emiAddr( *lpaddr ) = (HEMI) hpid;
+ goto itsBogus;
+ }
+
+ iSeg += 1;
+
+ for( igsn=0; igsn < lpmdi->lpgsi->csgMax; igsn++, lpsgi++ ) {
+
+ if ( (ULONG)lpsgi->isgPhy == iSeg &&
+ lpsgi->doffseg <= ulo &&
+ ulo < lpsgi->doffseg + lpsgi->cbSeg ) {
+
+ GetAddrSeg( *lpaddr ) = (USHORT) (igsn + 1);
+ GetAddrOff( *lpaddr ) = ulo - lpsgi->doffseg;
+
+ break;
+ }
+ }
+
+ if (igsn == lpmdi->lpgsi->csgMax) {
+ LLUnlock ( hmdi );
+ emiAddr( *lpaddr ) = (HEMI) hpid;
+ goto itsBogus;
+ }
+ LLUnlock ( hmdi );
+
+ } else {
+
+itsBogus:
+ if (ADDR_IS_REAL( *lpaddr )) {
+ ADDR_IS_FLAT( *lpaddr ) = FALSE;
+ ADDR_IS_OFF32( *lpaddr ) = FALSE;
+ } else {
+
+ // See if the segment matches the flat segment. If it does not
+ // then we must be in a non-flat segment.
+
+ lpprc = LLLock( hprc );
+
+ if ((lpaddr->addr.seg == 0) ||
+ (lpprc->dmi.fAlwaysFlat) ||
+ (lpaddr->addr.seg == lpprc->selFlatCs) ||
+ (lpaddr->addr.seg == lpprc->selFlatDs)) {
+
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ ADDR_IS_OFF32(*lpaddr) = TRUE;
+ ADDR_IS_REAL(*lpaddr) = FALSE;
+
+ } else {
+
+ xosd = SendRequestX(dmfQuerySelector, hpid, NULL,
+ sizeof(SEGMENT), &GetAddrSeg(*lpaddr) );
+
+ if (xosd != xosdNone) {
+ LLUnlock(hprc);
+ return xosd;
+ }
+
+ memcpy( &ldt, LpDmMsg->rgb, sizeof(ldt));
+
+ ADDR_IS_FLAT(*lpaddr) = FALSE;
+ ADDR_IS_OFF32(*lpaddr) = (BYTE) ldt.HighWord.Bits.Default_Big;
+ ADDR_IS_REAL(*lpaddr) = FALSE;
+ }
+ LLUnlock( hprc );
+ }
+
+#if !defined (TARGET_i386)
+
+ // This line is funny. We assume that all addresses
+ // which have a segment of 0 to be absolute symbols.
+ // We therefore set the segment to 1 just to make sure
+ // that it is not zero.
+
+ lpaddr->addr.seg = 1;
+#endif // ! TARGET_i386
+ }
+
+ ADDR_IS_LI(*lpaddr) = TRUE;
+ return xosdNone;
+}
+
+
+
+void
+UpdateRegisters (
+ HPRC hprc,
+ HTHD hthd
+ )
+{
+ LPTHD lpthd = LLLock ( hthd );
+
+ SendRequest ( dmfReadReg, HpidFromHprc ( hprc ), HtidFromHthd ( hthd ) );
+ memcpy ( &lpthd->regs, LpDmMsg->rgb, sizeof ( lpthd->regs ) );
+
+
+ lpthd->drt = drtCntrlPresent | drtAllPresent;
+
+ LLUnlock ( hthd );
+}
+
+void
+UpdateSpecialRegisters (
+ HPRC hprc,
+ HTHD hthd
+ )
+{
+#ifdef TARGET_i386
+
+ LPTHD lpthd = LLLock ( hthd );
+
+ SendRequest ( dmfReadRegEx, HpidFromHprc ( hprc ), HtidFromHthd ( hthd ) );
+
+ if (lpthd->dwcbSpecial) {
+ //
+ // in kernel mode...
+ //
+ memcpy ( lpthd->pvSpecial, LpDmMsg->rgb, lpthd->dwcbSpecial );
+ lpthd->regs.Dr0 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr0;
+ lpthd->regs.Dr1 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr1;
+ lpthd->regs.Dr2 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr2;
+ lpthd->regs.Dr3 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr3;
+ lpthd->regs.Dr6 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr6;
+ lpthd->regs.Dr7 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr7;
+ } else {
+ //
+ // User mode
+ //
+ lpthd->regs.Dr0 = ((LPDWORD)(LpDmMsg->rgb))[0];
+ lpthd->regs.Dr1 = ((LPDWORD)(LpDmMsg->rgb))[1];
+ lpthd->regs.Dr2 = ((LPDWORD)(LpDmMsg->rgb))[2];
+ lpthd->regs.Dr3 = ((LPDWORD)(LpDmMsg->rgb))[3];
+ lpthd->regs.Dr6 = ((LPDWORD)(LpDmMsg->rgb))[4];
+ lpthd->regs.Dr7 = ((LPDWORD)(LpDmMsg->rgb))[5];
+ }
+
+ lpthd->drt &= ~drtSpecialDirty;
+ lpthd->drt |= drtSpecialPresent;
+
+ LLUnlock ( hthd );
+
+#endif
+}
+
+
+XOSD
+DoGetContext(
+ HPID hpid,
+ HTID htid,
+ LPVOID lpv
+ )
+{
+ XOSD xosd = SendRequest ( dmfReadReg, hpid, htid );
+ if (xosd == xosdNone) {
+ memcpy ( *(LPVOID *)lpv, LpDmMsg->rgb, sizeof (CONTEXT) );
+ }
+ return xosd;
+}
+
+
+XOSD
+DoSetContext(
+ HPID hpid,
+ HTID htid,
+ LPVOID lpv
+ )
+{
+ return SendRequestX( dmfWriteReg, hpid, htid, sizeof(CONTEXT), lpv );
+}
+
+
+void
+RegisterEmi (
+ HPID hpid,
+ LPREMI lpremi
+ )
+{
+ HLLI llmdi;
+ HMDI hmdi;
+ LPMDI lpmdi;
+ LPSGI lpsgi;
+ LPSGI lpsgiMax;
+ USHORT usOvlMax = 0;
+
+
+ llmdi = LlmdiFromHprc( HprcFromHpid ( hpid ) );
+ assert( llmdi != 0 );
+
+ hmdi = LLFind( llmdi, 0, lpremi->lsz, (LONG)emdiName );
+
+ if (hmdi == 0) {
+ hmdi = LLFind( llmdi, 0, &lpremi->hemi, (LONG)emdiEMI );
+ }
+
+ assert( hmdi != 0 );
+
+ lpmdi = LLLock ( hmdi );
+ assert( lpmdi != NULL );
+
+ assert( lpremi->hemi != 0 );
+
+ lpmdi->hemi = lpremi->hemi;
+
+#ifdef OSDEBUG4
+ lpmdi->lpDebug = (LPDEBUGDATA)SHGetDebugData( (HIND)(lpremi->hemi) );
+
+ // Get the GSN info table from the symbol handler
+ if ( lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HIND)(lpremi->hemi) ) )
+#else
+ lpmdi->lpDebug = (LPDEBUGDATA)SHGetDebugData( (HEXE)(lpremi->hemi) );
+
+ // Get the GSN info table from the symbol handler
+ if ( lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)(lpremi->hemi) ) )
+#endif
+ {
+
+ //
+ // If real mode, do some patch magic.
+ //
+ if ( lpmdi->fRealMode ) {
+
+ int i;
+
+ assert( lpmdi->cobj );
+ assert( lpmdi->rgobjd );
+
+ lpmdi->cobj = lpmdi->lpgsi->csgMax+1;
+ lpmdi->rgobjd = MHRealloc(lpmdi->rgobjd,
+ sizeof(OBJD)*lpmdi->cobj);
+ memset(lpmdi->rgobjd, 0, sizeof(OBJD)*(lpmdi->cobj));
+
+ lpsgi = lpmdi->lpgsi->rgsgi;
+ lpsgiMax = lpsgi + lpmdi->lpgsi->csgMax;
+
+ for( i=0; lpsgi < lpsgiMax; lpsgi++, i++ ) {
+
+ lpmdi->rgobjd[ i ].wSel = (WORD)(lpsgi->doffseg + lpmdi->StartingSegment);
+ lpmdi->rgobjd[ i ].wPad = 1;
+ lpmdi->rgobjd[ i ].cb = (DWORD) -1;
+
+ lpsgi->doffseg = 0;
+
+ }
+ }
+
+ // Determine if child is overlaid and, if so, how many overlays
+ lpsgi = lpmdi->lpgsi->rgsgi;
+ lpsgiMax = lpsgi + lpmdi->lpgsi->csgMax;
+ for( ; lpsgi < lpsgiMax; lpsgi++ ) {
+
+ // iovl == 0xFF is reserved, it means no overlay specified.
+ // we should ignore 0xFF in iovl. Linker uses it
+ // to (insert lots of hand-waving here) support COMDATS
+ if ( lpsgi->iovl < 0xFF ) { // [02]
+ usOvlMax = max( usOvlMax, lpsgi->iovl );
+ }
+ }
+#ifndef TARGET32
+ // Setup the overlay table
+ if ( usOvlMax ) {
+ lpmdi->lpsel = MHRealloc( lpmdi->lpsel, sizeof( WORD ) * usOvlMax + 1 );
+ memset( &lpmdi->lpsel [ 1 ], 0, sizeof( WORD ) * usOvlMax );
+ }
+#endif // !TARGET32
+ }
+ LLUnlock ( hmdi );
+
+ // purge the emi cache (get rid of old, now invalid hpid/emi pairs)
+ CleanCacheOfEmi();
+}
+
+
+void
+UpdateProcess (
+ HPRC hprc
+ )
+{
+ assert ( hprc != NULL );
+ EnterCriticalSection(&csCache);
+
+ {
+ LPPRC lpprc = LLLock ( hprc );
+
+ FlushPTCache();
+
+ hprcCurr = hprc;
+ hpidCurr = lpprc->hpid;
+ pidCurr = lpprc->pid;
+
+ LLUnlock ( hprc );
+ }
+ LeaveCriticalSection(&csCache);
+}
+
+
+HEMI
+HemiFromHmdi (
+ HMDI hmdi
+ )
+{
+ LPMDI lpmdi = LLLock ( hmdi );
+ HEMI hemi = lpmdi->hemi;
+
+ LLUnlock ( hmdi );
+ return hemi;
+}
+
+
+void
+FlushPTCache (
+ void
+ )
+{
+ EnterCriticalSection(&csCache);
+
+ hprcCurr = NULL;
+ hpidCurr = NULL;
+ pidCurr = 0;
+
+ hthdCurr = NULL;
+ htidCurr = NULL;
+ tidCurr = 0;
+
+ LeaveCriticalSection(&csCache);
+}
+
+
+HPRC
+ValidHprcFromHpid(
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+ only return an hprc if there is a real process for it.
+ the other version will return an hprc whose process has
+ not been created or has been destroyed.
+
+Arguments:
+
+ hpid - Supplies hpid to look for in HPRC list.
+
+Return Value:
+
+ An HPRC or NULL.
+
+--*/
+{
+ HPRC hprcT;
+ HPRC hprc = NULL;
+ LPPRC lpprc;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hpid == hpidCurr ) {
+
+ hprc = hprcCurr;
+
+ } else {
+
+ if ( hpid != NULL ) {
+ hprc = LLFind ( llprc, NULL, (LPVOID)&hpid, 0 );
+ }
+
+ if ( hprc != NULL ) {
+ lpprc = LLLock( hprcT = hprc );
+ if (lpprc->stat == statDead) {
+ hprc = NULL;
+ }
+ LLUnlock( hprcT );
+ }
+ if ( hprc != NULL ) {
+ UpdateProcess ( hprc );
+ }
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return hprc;
+}
+
+
+HPRC
+HprcFromHpid (
+ HPID hpid
+ )
+{
+ HPRC hprc = NULL;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hpid == hpidCurr ) {
+
+ hprc = hprcCurr;
+
+ } else {
+
+ if ( hpid != NULL ) {
+ hprc = LLFind ( llprc, NULL, (LPVOID)&hpid, 0 );
+ }
+
+ if ( hprc != NULL ) {
+ UpdateProcess ( hprc );
+ }
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return hprc;
+}
+
+
+HPRC
+HprcFromPid (
+ PID pid
+ )
+{
+ HPRC hprc;
+ BOOL fFound = FALSE;
+
+ EnterCriticalSection(&csCache);
+
+ if ( pid == pidCurr ) {
+
+ hprc = hprcCurr;
+
+ } else {
+
+ for ( hprc = LLNext ( llprc, 0 );
+ !fFound && hprc != 0;
+ hprc = LLNext ( llprc, hprc ) ) {
+
+ LPPRC lpprc = LLLock ( hprc );
+ fFound = lpprc->pid == pid;
+ LLUnlock ( hprc );
+ }
+
+ if ( !fFound ) {
+ hprc = NULL;
+ } else {
+ UpdateProcess ( hprc );
+ }
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return hprc;
+}
+
+
+HPID
+HpidFromHprc (
+ HPRC hprc
+ )
+{
+ HPID hpid = NULL;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hprc == hprcCurr ) {
+ hpid = hpidCurr;
+ } else if ( hprc != NULL ) {
+ UpdateProcess ( hprc );
+ hpid = hpidCurr;
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return hpid;
+}
+
+
+PID
+PidFromHprc (
+ HPRC hprc
+ )
+{
+ PID pid = 0;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hprc == hprcCurr ) {
+ pid = pidCurr;
+ } else if ( hprc != NULL ) {
+ UpdateProcess ( hprc );
+ pid = pidCurr;
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return pid;
+}
+
+
+void
+UpdateThread (
+ HTHD hthd
+ )
+{
+ EnterCriticalSection(&csCache);
+
+ if ( hthd == NULL ) {
+ FlushPTCache();
+ } else {
+ LPTHD lpthd = LLLock ( hthd );
+
+ UpdateProcess ( lpthd->hprc );
+
+ hthdCurr = hthd;
+ htidCurr = lpthd->htid;
+ tidCurr = lpthd->tid;
+
+ LLUnlock ( hthd );
+ }
+ LeaveCriticalSection(&csCache);
+}
+
+
+HTHD
+HthdFromTid (
+ HPRC hprc,
+ TID tid
+ )
+{
+ LPPRC lpprc;
+ HTHD hthd = NULL;
+ BOOL fFound = FALSE;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hprc == hprcCurr && tid == tidCurr ) {
+ hthd = hthdCurr;
+ } else {
+ lpprc = LLLock ( hprc );
+
+ for ( hthd = LLNext ( lpprc->llthd, 0 );
+ !fFound && hthd != 0;
+ hthd = LLNext ( lpprc->llthd, hthd ) ) {
+
+ LPTHD lpthd = LLLock ( hthd );
+ fFound = lpthd->tid == tid;
+
+ LLUnlock ( hthd );
+ }
+
+ LLUnlock ( hprc );
+
+ if ( fFound ) {
+ UpdateThread ( hthd );
+ } else {
+ hthd = NULL;
+ }
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return hthd;
+}
+
+
+HTHD
+HthdFromHtid (
+ HPRC hprc,
+ HTID htid
+ )
+{
+ HTHD hthd = NULL;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hprc == hprcCurr && htid == htidCurr ) {
+ hthd = hthdCurr;
+ } else if ( hprc != NULL ) {
+ LPPRC lpprc = LLLock ( hprc );
+ hthd = LLFind ( lpprc->llthd, NULL, (LPVOID)&htid, 0 );
+ LLUnlock ( hprc );
+ }
+ UpdateThread ( hthd );
+
+ LeaveCriticalSection(&csCache);
+
+ return hthd;
+}
+
+
+HTID
+HtidFromHthd (
+ HTHD hthd
+ )
+{
+ HTID htid = NULL;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hthd == hthdCurr ) {
+ htid = htidCurr;
+ } else if ( hthd != NULL ) {
+ UpdateThread ( hthd );
+ htid = htidCurr;
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return htid;
+}
+
+
+TID
+TidFromHthd (
+ HTHD hthd
+ )
+{
+ TID tid = 0;
+
+ EnterCriticalSection(&csCache);
+
+ if ( hthd == hthdCurr ) {
+ tid = tidCurr;
+ } else if ( hthd != NULL ) {
+ UpdateThread ( hthd );
+ tid = tidCurr;
+ }
+
+ LeaveCriticalSection(&csCache);
+
+ return tid;
+}
+
+
+
+HLLI LlthdFromHprc ( HPRC hprc ) {
+ HLLI llthd = 0;
+
+ if ( hprc != NULL ) {
+ LPPRC lpprc = LLLock ( hprc );
+ llthd = lpprc->llthd;
+ LLUnlock ( hprc );
+ }
+
+ return llthd;
+}
+
+HLLI LlmdiFromHprc ( HPRC hprc ) {
+ HLLI llmdi = 0;
+
+ if ( hprc != NULL ) {
+ LPPRC lpprc = LLLock ( hprc );
+ llmdi = lpprc->llmdi;
+ LLUnlock ( hprc );
+ }
+
+ return llmdi;
+}
+
+STAT StatFromHprc ( HPRC hprc ) {
+ LPPRC lpprc = LLLock ( hprc );
+ STAT stat = lpprc->stat;
+ LLUnlock ( hprc );
+ return stat;
+}
+
+#ifndef OSDEBUG4
+
+XOSD
+GetPrompt(
+ HPID hpid,
+ HTID htid,
+ LPPROMPTMSG lppm
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path in the DM
+
+Arguments:
+
+ hpid - process
+ htid - thread
+ Len - length of prompt buffer
+ Prompt - Path to search, PATH if null
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ XOSD xosd;
+
+ xosd = SendRequestX( dmfGetPrompt, hpid, htid,
+ lppm->len+sizeof(PROMPTMSG), lppm );
+ if (xosd == xosdNone) {
+ memcpy( lppm, LpDmMsg->rgb, lppm->len+sizeof(PROMPTMSG) );
+ }
+ return xosd;
+}
+#endif
+
+//**************************************************************************
+//
+// global stack walking api support functions
+//
+// these are the callbacks used by imagehlp.dll
+//
+// there are custom callbacks in each of the emdpdev.c files
+//
+//**************************************************************************
+
+HMDI
+SwGetMdi(
+ HPID hpid,
+ DWORD Address
+ )
+{
+ HLLI hlli = 0;
+ HMDI hmdi = 0;
+ LPMDI lpmdi = NULL;
+
+
+ hlli = LlmdiFromHprc( HprcFromHpid ( hpid ));
+
+ do {
+
+ hmdi = LLNext( hlli, hmdi );
+ if (hmdi) {
+ lpmdi = LLLock( hmdi );
+ if (lpmdi) {
+ //
+ // we have a pointer to a module so lets see if its the one...
+ //
+ if (Address >= lpmdi->lpBaseOfDll &&
+ Address < lpmdi->lpBaseOfDll+lpmdi->dwSizeOfDll ) {
+
+ LLUnlock( hmdi );
+ return hmdi;
+
+ }
+ LLUnlock( hmdi );
+ }
+ }
+
+ } while (hmdi);
+
+ return 0;
+}
+
+
+DWORD
+SwGetModuleBase(
+ HPID hpid,
+ DWORD ReturnAddress
+ )
+{
+ HLLI hlli = 0;
+ HMDI hmdi = 0;
+ LPMDI lpmdi = NULL;
+
+
+ hmdi = SwGetMdi( hpid, ReturnAddress );
+ if (!hmdi) {
+ return 0;
+ }
+
+ lpmdi = LLLock( hmdi );
+ if (lpmdi) {
+ LLUnlock( hmdi );
+ return lpmdi->lpBaseOfDll;
+ }
+
+ return 0;
+}
+
+
+XOSD
+DebugPacket (
+ DBC dbc,
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LPBYTE lpb
+ )
+{
+ XOSD xosd = xosdContinue;
+ HPRC hprc = HprcFromHpid ( hpid );
+ HTHD hthd = HthdFromHtid ( hprc, htid );
+ LONG emdi;
+ LPTHD lpthd;
+ LPPRC lpprc;
+
+ if (hthd) {
+ lpthd = LLLock(hthd);
+ lpthd->drt = drtNonePresent;
+ LLUnlock(hthd);
+ }
+
+
+ /* Do any preprocessing on the packet before sending the notification
+ * on to the debugger. For example, the wValue and lValue might need
+ * some munging. Also, if the notification shouldn't be passed on to
+ * the debugger, then set xosd = xosdNone or some other value other
+ * than xosdContinue.
+ */
+
+ switch ( dbc ) {
+ case dbceAssignPID:
+ {
+ LPPRC lpprc = LLLock ( hprc );
+
+ assert ( wValue == sizeof ( PID ) );
+ lpprc->pid = *( (PID *) lpb );
+ lpprc->stat = statStarted;
+ LLUnlock ( hprc );
+ }
+ xosd = xosdNone;
+ break;
+
+ case dbcCreateThread:
+
+ if (!hprc) {
+ //
+ // happens during forced termination.
+ //
+ htid = 0;
+ CallTL ( tlfReply, hpid, sizeof ( HTID ), (LPVOID)&htid );
+ xosd = xosdUnknown;
+
+ } else {
+
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+
+ assert ( wValue == sizeof ( TID ) );
+ xosd = CreateThreadStruct ( hpid, *( (TID *) lpb ), &htid );
+
+ CallTL ( tlfReply, hpid, sizeof ( HTID ), (LPVOID)&htid );
+ if ( xosd == xosdNone ) {
+ xosd = xosdContinue;
+ }
+ }
+ break;
+
+ case dbcNewProc:
+ {
+ HPRC hprcT;
+ HPID hpidT;
+ LPPRC lpprc;
+ LPNPP lpnpp;
+
+ /*
+ * lpb points to an NPP (New Process Packet). The PID is
+ * the PID of the debuggee; fReallyNew indicates if this is
+ * really a new process or if it already existed but hasn't
+ * been seen before by OSDebug.
+ */
+
+ assert ( wValue == sizeof(NPP) );
+ lpnpp = (LPNPP) lpb;
+
+ // See EMCallBackDB in od.c
+
+ CallDB ( dbcoNewProc, hpid, htid, CEXM_MDL_native,
+ sizeof ( HPID ), (LPVOID)&hpidT );
+
+ (void) CreateHprc ( hpidT );
+
+ hprcT = HprcFromHpid ( hpidT );
+ lpprc = LLLock ( hprcT );
+ lpprc->pid = lpnpp->pid;
+ lpprc->stat = statStarted;
+ LLUnlock ( hprcT );
+
+ CallTL ( tlfReply, hpid, sizeof ( HPID ), (LPVOID)&hpidT );
+
+ SyncHprcWithDM( hpidT );
+
+ wValue = (UINT)hpidT;
+ lpb = (LPBYTE) (LONG) lpnpp->fReallyNew;
+ if ( xosd == xosdNone ) {
+ xosd = xosdContinue;
+ }
+ }
+ break;
+
+
+ case dbcThreadTerm:
+
+ if (!hprc) {
+ //
+ // happens during forced termination.
+ //
+ return xosdUnknown;
+ }
+
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+ lpthd = LLLock(hthd);
+ lpthd->fRunning = FALSE;
+ LLUnlock(hthd);
+
+ case dbcProcTerm:
+
+ /*
+ * For both of these notifications, the incoming wValue is
+ * sizeof(ULONG), and lpb contains a ULONG which is the exit
+ * code of the process or thread. For the debugger, set
+ * wValue = 0 and lValue = exit code.
+ */
+
+ assert ( wValue == sizeof(ULONG) );
+ wValue = 0;
+ lpb = (LPBYTE) (*(ULONG*)lpb);
+ break;
+
+#ifdef OSDEBUG4
+ case dbcDeleteThread:
+#else
+ case dbcThreadDestroy:
+#endif
+
+ lpthd = LLLock(hthd);
+ lpthd->tid = (TID)-1;
+ LLUnlock(hthd);
+
+ assert ( wValue == sizeof(ULONG) );
+ wValue = 0;
+ lpb = (LPBYTE) (*(ULONG*)lpb);
+ break;
+
+ case dbcModLoad:
+
+ if (!hprc) {
+ //
+ // happens during forced termination.
+ //
+ return xosdUnknown;
+ }
+
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+ if (hthd) {
+ lpthd = LLLock(hthd);
+ lpthd->fRunning = FALSE;
+ LLUnlock(hthd);
+ }
+ xosd = LoadFixups ( hpid, (LPMODULELOAD) lpb );
+ break;
+
+ case dbcModFree: /* Should use dbceModFree* */
+ assert(FALSE);
+ break;
+
+ case dbceModFree32:
+ emdi = emdiBaseAddr;
+ modFree:
+ {
+ HMDI hmdi;
+ LPMDI lpmdi;
+ HLLI llmdi;
+
+ llmdi = LlmdiFromHprc ( hprc );
+ assert( llmdi );
+
+ hmdi = LLFind( llmdi, 0, lpb, emdi);
+ assert( hmdi );
+
+ lpmdi = LLLock( hmdi );
+ lpb = (LPBYTE) lpmdi->hemi;
+ LLUnlock( hmdi );
+
+ dbc = dbcModFree;
+ }
+ break;
+
+ case dbceModFree16:
+ emdi = emdiMTE;
+ goto modFree;
+ break;
+
+ case dbcExecuteDone:
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+ lpthd = LLLock(hthd);
+ lpthd->fRunning = FALSE;
+ LLUnlock(hthd);
+ break;
+
+ case dbcStep:
+ case dbcThreadBlocked:
+ case dbcSignal:
+
+ case dbcAsyncStop:
+ case dbcBpt:
+ case dbcCheckBpt:
+ case dbcEntryPoint:
+ case dbcLoadComplete:
+ {
+ LPBPR lpbpr = (LPBPR) lpb;
+ LPTHD lpthd = LLLock ( hthd );
+
+ /*
+ * This assert should be re-enabled when all the DMs are
+ * fixed to send the proper packet back!!
+ */
+
+ assert ( wValue == sizeof ( BPR ) );
+
+ PurgeCache ( );
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+ lpthd->fRunning = FALSE;
+
+
+#if defined(TARGET_i386)
+ lpthd->regs.SegCs = lpbpr->segCS;
+ lpthd->regs.SegSs = lpbpr->segSS;
+ lpthd->regs.Eip = lpbpr->offEIP;
+ lpthd->regs.Ebp = lpbpr->offEBP;
+#elif defined(TARGET_MIPS)
+ lpthd->regs.XFir = lpbpr->offEIP;
+ lpthd->regs.XIntSp = lpbpr->offEBP;
+#elif defined(TARGET_ALPHA)
+ lpthd->regs.Fir = lpbpr->offEIP;
+ lpthd->regs.IntSp = lpbpr->offEBP;
+#elif defined(TARGET_PPC)
+ lpthd->regs.Iar = lpbpr->offEIP;
+ lpthd->regs.Gpr1 = lpbpr->offEBP;
+#else
+
+#error "unrecognized target CPU"
+
+#endif
+
+ lpthd->fFlat = lpbpr->fFlat;
+ lpthd->fOff32 = lpbpr->fOff32;
+ lpthd->fReal = lpbpr->fReal;
+
+ lpthd->drt = drtCntrlPresent;
+
+ LLUnlock( hthd );
+ }
+
+ break;
+
+ case dbcException:
+ {
+ LPEPR lpepr = (LPEPR) lpb;
+ LPTHD lpthd = LLLock ( hthd );
+ ADDR addr = {0};
+
+ PurgeCache ( );
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+ lpthd->fRunning = FALSE;
+
+
+#if defined(TARGET_i386)
+ lpthd->regs.SegCs = lpepr->bpr.segCS;
+ lpthd->regs.SegSs = lpepr->bpr.segSS;
+ lpthd->regs.Eip = lpepr->bpr.offEIP;
+ lpthd->regs.Ebp = lpepr->bpr.offEBP;
+#elif defined(TARGET_MIPS)
+ lpthd->regs.XFir = lpepr->bpr.offEIP;
+ lpthd->regs.XIntSp = lpepr->bpr.offEBP;
+#elif defined(TARGET_ALPHA)
+ lpthd->regs.Fir = lpepr->bpr.offEIP;
+ lpthd->regs.IntSp = lpepr->bpr.offEBP;
+#elif defined(TARGET_PPC)
+ lpthd->regs.Iar = lpepr->bpr.offEIP;
+ lpthd->regs.Gpr1 = lpepr->bpr.offEBP;
+#else
+
+#error "unrecognized target CPU"
+
+#endif
+
+ lpthd->fFlat = lpepr->bpr.fFlat;
+ lpthd->fOff32 = lpepr->bpr.fOff32;
+ lpthd->fReal = lpepr->bpr.fReal;
+
+ lpthd->drt = drtCntrlPresent;
+
+ LLUnlock( hthd );
+ }
+ break;
+
+#if 0
+
+ // BUGBUG kentf review this... do we need to support it?
+ // if so, it should turn into a dbcInfoAvail and
+ // a breakpoint or something.
+ case dbcNtRip:
+ {
+ LPNT_RIP lprip = (LPNT_RIP) lpb;
+ LPTHD lpthd = LLLock ( hthd );
+ ADDR addr = {0};
+
+ assert ( wValue == sizeof ( NT_RIP ) );
+
+ PurgeCache ( );
+ lpprc = LLLock(hprc);
+ lpprc->fRunning = FALSE;
+ LLUnlock(hprc);
+ lpthd->fRunning = FALSE;
+
+
+#if defined(TARGET_i386)
+ lpthd->regs.SegCs = lprip->bpr.segCS;
+ lpthd->regs.SegSs = lprip->bpr.segSS;
+ lpthd->regs.Eip = lprip->bpr.offEIP;
+ lpthd->regs.Ebp = lprip->bpr.offEBP;
+#elif defined(TARGET_MIPS)
+ lpthd->regs.XFir = lprip->bpr.offEIP;
+ lpthd->regs.XIntSp = lprip->bpr.offEBP;
+#elif defined(TARGET_ALPHA)
+ lpthd->regs.Fir = lprip->bpr.offEIP;
+ lpthd->regs.IntSp = lprip->bpr.offEBP;
+#elif defined(TARGET_PPC)
+ lpthd->regs.Iar = lprip->bpr.offEIP;
+ lpthd->regs.Gpr1 = lprip->bpr.offEBP;
+#else
+
+#error "unrecognized target CPU"
+
+#endif
+
+ lpthd->fFlat = lprip->bpr.fFlat;
+ lpthd->fOff32 = lprip->bpr.fOff32;
+ lpthd->fReal = lprip->bpr.fReal;
+
+ lpthd->drt = drtCntrlPresent;
+
+ LLUnlock (hthd );
+ }
+ break;
+#endif
+
+ case dbceCheckBpt:
+ assert(FALSE);
+ xosd = xosdNone;
+ break;
+
+#if 0
+
+ // BUGBUG kentf yuck. what is this supposed to do?
+
+ case dbcError:
+ {
+ static char sz[500];
+ XOSD xosdErr = *( (XOSD *)lpb );
+
+ sprintf(sz,
+ "DMX32%04d: %s",
+ -(int)xosdErr,
+ EmError(xosdErr));
+
+ wValue = xosdErr;
+ lpb = sz;
+ }
+ break;
+#endif
+
+ case dbceSegLoad:
+ {
+ SLI sli;
+ HMDI hmdi;
+ LPMDI lpmdi;
+ UINT i;
+
+ sli = *( (LPSLI) lpb );
+
+ hmdi = LLFind( LlmdiFromHprc( hprc ), 0, &sli.mte,
+ (LONG) emdiMTE);
+
+ assert( hmdi );
+
+ lpmdi = LLLock(hmdi );
+
+ if (sli.wSegNo >= lpmdi->cobj) {
+ i = lpmdi->cobj;
+ lpmdi->cobj = sli.wSegNo+1;
+ lpmdi->rgobjd = MHRealloc(lpmdi->rgobjd,
+ sizeof(OBJD)*lpmdi->cobj);
+ memset(&lpmdi->rgobjd[i], 0, sizeof(OBJD)*(lpmdi->cobj - i));
+ }
+ lpmdi->rgobjd[ sli.wSegNo ].wSel = sli.wSelector;
+ lpmdi->rgobjd[ sli.wSegNo ].wPad = 1;
+ lpmdi->rgobjd[ sli.wSegNo ].cb = (DWORD) -1;
+
+ LLUnlock( hmdi );
+
+ //
+ // Let the shell know that a new segment was loaded, so it
+ // can try to instantiate virtual BPs.
+ //
+ xosd=CallDB( dbcSegLoad, hpid, htid, CEXM_MDL_native, 0,
+ (LPVOID)sli.wSelector );
+ xosd=xosdNone;
+
+ }
+ break;
+
+ case dbceSegMove:
+ {
+ SLI sli;
+ HMDI hmdi;
+ LPMDI lpmdi;
+
+ sli = *( (LPSLI) lpb );
+
+ hmdi = LLFind( LlmdiFromHprc( hprc ), 0, &sli.mte,
+ (LONG) emdiMTE);
+
+ assert( hmdi );
+
+ lpmdi = LLLock(hmdi );
+
+ assert(sli.wSegNo > 0 );
+ if (sli.wSegNo < lpmdi->cobj) {
+ lpmdi->rgobjd[ sli.wSegNo - 1 ].wSel = sli.wSelector;
+ }
+
+ LLUnlock( hmdi );
+ }
+ break;
+
+ case dbcCanStep:
+ {
+ CANSTEP CanStep;
+
+ assert ( wValue == sizeof ( ADDR ) );
+
+ UnFixupAddr( hpid, (LPADDR) lpb);
+
+ xosd=CallDB(dbc,hpid,htid,CEXM_MDL_native,0,(LPVOID)lpb);
+
+ if ( xosd == xosdNone ) {
+ CanStep = *((CANSTEP*)lpb);
+ } else {
+ CanStep.Flags = CANSTEP_NO;
+ }
+
+ CallTL ( tlfReply, hpid, sizeof( CanStep ), &CanStep );
+
+ xosd = xosdNone;
+ }
+ break;
+
+ case dbceGetOffsetFromSymbol:
+ {
+ ADDR addr = {0};
+ if (SHGetPublicAddr(&addr, lpb)) {
+ FixupAddr(hpid, &addr);
+ }
+ CallTL( tlfReply, hpid, sizeof(addr.addr.off), (LPVOID)&addr.addr.off );
+ xosd = xosdNone;
+ }
+ break;
+
+ case dbceGetSymbolFromOffset:
+ {
+ LPSTR p;
+ ADDR addr;
+ LPDMSYM lpds;
+ STACKFRAME stk = {0};
+ LPSTR fname = SHAddrToPublicName( (LPADDR)lpb, &addr );
+ StackWalkSetup( hpid, htid, &stk );
+ if (fname) {
+ lpds = (LPDMSYM)malloc( sizeof(DMSYM) + strlen(fname) + 1);
+ strcpy(lpds->fname,fname);
+ free(fname);
+ } else {
+ lpds = (LPDMSYM)malloc( sizeof(DMSYM) + 32 );
+ sprintf( lpds->fname, "<unknown>0x%08x", GetAddrOff(*(LPADDR)lpb) );
+ }
+ lpds->AddrSym = addr;
+ lpds->Ra = stk.AddrReturn.Offset;
+ CallTL( tlfReply, hpid, sizeof(DMSYM) + strlen(lpds->fname) + 1 , (LPVOID)lpds );
+ free( lpds );
+ xosd = xosdNone;
+ }
+ break;
+
+ case dbceEnableCache:
+ EnableCache( hpid, htid, *(LPDWORD)lpb );
+ CallTL( tlfReply, hpid, 0, NULL );
+ xosd = xosdNone;
+ break;
+
+ case dbcLastAddr:
+ assert( wValue == sizeof( ADDR ) );
+
+ UnFixupAddr( hpid, (LPADDR) lpb );
+
+ xosd = CallDB(dbc, hpid, htid, CEXM_MDL_native, 0, (LPVOID) lpb);
+
+ if ( xosd == xosdNone ) {
+ FixupAddr( hpid, (LPADDR) lpb );
+ }
+
+ CallTL( tlfReply, hpid, sizeof(ADDR), lpb);
+ break;
+
+ default:
+ break;
+ }
+
+ if ((xosd == xosdContinue) && (dbc < dbcMax) && (dbc != dbcModLoad)) {
+ xosd = CallDB ( dbc, hpid, htid, CEXM_MDL_native, wValue, (LPVOID)lpb );
+ }
+
+ switch ( dbc ) {
+
+ case dbcProcTerm:
+ {
+ LPPRC lpprc = LLLock ( hprc );
+ lpprc->stat = statDead;
+ LLUnlock ( hprc );
+ }
+ break;
+
+ case dbcThreadTerm:
+ {
+ LPTHD lpthd = LLLock ( hthd );
+ lpthd->fVirtual = TRUE;
+ LLUnlock ( hthd );
+ }
+ break;
+
+ case dbcDeleteProc:
+ break;
+
+#ifdef OSDEBUG4
+ case dbcDeleteThread:
+#else
+ case dbcThreadDestroy:
+#endif
+ break;
+ }
+
+ return xosd;
+} /* DebugPacket() */
+
+XOSD
+GetSectionObjectsFromDM(
+ HPID hpid,
+ LPMDI lpmdi
+ )
+{
+ XOSD xosd;
+ xosd = SendRequestX( dmfGetSections,
+ hpid,
+ 0,
+ sizeof(DWORD),
+ &lpmdi->lpBaseOfDll );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ lpmdi->cobj = *(LPDWORD)LpDmMsg->rgb;
+ lpmdi->rgobjd = (LPOBJD) MHAlloc ( sizeof(OBJD) * lpmdi->cobj);
+ if ( lpmdi->rgobjd == NULL ) {
+ assert( "load cannot create rgobjd" && FALSE );
+ return xosdOutOfMemory;
+ }
+
+ memcpy( lpmdi->rgobjd,
+ LpDmMsg->rgb+sizeof(DWORD),
+ sizeof(OBJD) * lpmdi->cobj );
+
+ return xosdNone;
+}
diff --git a/private/windbg/em/emdp3.c b/private/windbg/em/emdp3.c
new file mode 100644
index 000000000..92dabaf8d
--- /dev/null
+++ b/private/windbg/em/emdp3.c
@@ -0,0 +1,1233 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ emdp3.c
+
+Abstract:
+
+ This file contains the some of the machine independent portions of the
+ execution model. The machine dependent portions are in other files.
+
+Author:
+
+ Kent Forschmiedt (kentf) 11-8-93
+
+Environment:
+
+ Win32 -- User
+
+Notes:
+
+ The orginal source for this came from the CodeView group.
+
+--*/
+
+extern RD Rgrd[];
+extern const unsigned CRgrd;
+extern struct RGFD Rgfd[];
+extern const unsigned CRgfd;
+
+//
+// This list is only used when there is no DM present. Whenever an
+// hpid is created, the real list is obtained from the DM and stored
+// in a list bound to the hprc.
+//
+static EXCEPTION_DESCRIPTION DefaultExceptionList[] = {
+ {EXCEPTION_ACCESS_VIOLATION, efdStop, "Access Violation"},
+ {EXCEPTION_DATATYPE_MISALIGNMENT, efdStop, "Data Misalignment"},
+ {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, efdStop, "Array Bounds Exceeded"},
+ {EXCEPTION_FLT_DENORMAL_OPERAND, efdStop, "FP Denormal Operand"},
+ {EXCEPTION_FLT_DIVIDE_BY_ZERO, efdStop, "FP Divide by Zero"},
+ {EXCEPTION_FLT_INEXACT_RESULT, efdStop, "FP Inexact Result"},
+ {EXCEPTION_FLT_INVALID_OPERATION, efdStop, "FP Invalid Operation"},
+ {EXCEPTION_FLT_OVERFLOW, efdStop, "FP Overflow"},
+ {EXCEPTION_FLT_STACK_CHECK, efdStop, "FP Stack Check"},
+ {EXCEPTION_FLT_UNDERFLOW, efdStop, "FP Underflow"},
+ {EXCEPTION_INT_DIVIDE_BY_ZERO, efdStop, "Int Divide by zero"},
+ {EXCEPTION_INT_OVERFLOW, efdStop, "Int Overflow"},
+ {EXCEPTION_PRIV_INSTRUCTION, efdStop, "Insufficient Privilege"},
+ {EXCEPTION_IN_PAGE_ERROR, efdStop, "I/O Error in Paging"},
+ {EXCEPTION_ILLEGAL_INSTRUCTION, efdStop, "Illegal Instruction"},
+ {EXCEPTION_NONCONTINUABLE_EXCEPTION,efdStop, "Noncontinuable Exception"},
+ {EXCEPTION_STACK_OVERFLOW, efdStop, "Stack Overflow"},
+ {EXCEPTION_INVALID_DISPOSITION, efdStop, "Invalid Disposition"},
+ {RPC_S_OUT_OF_RESOURCES, efdNotify, "RPC Out Of Resources"},
+ {RPC_S_SERVER_UNAVAILABLE, efdNotify, "RPC Server Unavailable"},
+ {RPC_S_SERVER_TOO_BUSY, efdNotify, "RPC Server Too Busy"},
+ {DBG_CONTROL_C, efdStop, "Control-C break"},
+ {0xE06d7363, efdNotify, "Microsoft C++ EH Exception"},
+ {(DWORD)STATUS_NO_MEMORY, efdStop, "No Memory"},
+ {(DWORD)NULL, efdStop, "Unknown"},
+};
+
+
+XOSD
+HandleBreakpoints(
+ HPID hpid,
+ DWORD wValue,
+ LONG lValue
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ LPBPS lpbps = (LPBPS) lValue;
+ LPDBB lpdbb = malloc(sizeof(DBB) + wValue);
+
+ // let the DM handle everything?
+ lpdbb->hpid = hpid;
+ lpdbb->htid = NULL;
+ lpdbb->dmf = dmfBreakpoint;
+ memcpy(lpdbb->rgbVar, lpbps, wValue);
+ CallTL ( tlfRequest, hpid, sizeof ( DBB ) + wValue, (LPVOID)lpdbb );
+ if (LpDmMsg->xosdRet == xosdNone) {
+ memcpy(DwNotification(lpbps),
+ DwNotification( (LPBPS)(LpDmMsg->rgb) ),
+ lpbps->cbpis * sizeof(DWORD));
+ }
+ return LpDmMsg->xosdRet;
+}
+
+
+XOSD
+Go (
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpexop
+ )
+{
+ UpdateChild ( hpid, htid, dmfGo );
+ return SendRequestX(dmfGo, hpid, htid, sizeof(EXOP), lpexop);
+}
+
+#if 0
+
+XOSD
+ReturnStep (
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpexop
+ )
+{
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ RTRNSTP rtrnstp;
+ XOSD xosd = xosdNone;
+ HTID vhtid = htid;
+
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
+ return xosdInvalidThread;
+ }
+ rtrnstp.exop = *lpexop;
+ if ((((DWORD)htid) & 1) == 0) {
+ xosd = DoGetFrame( hpid, vhtid, 1, (DWORD)&vhtid );
+ }
+ if ( xosd == xosdNone ) {
+ xosd = DoGetFrame( hpid, vhtid, 1, (DWORD)&vhtid );
+ if ( xosd == xosdNone ) {
+ xosd = GetAddr( hpid, vhtid, adrPC, &(rtrnstp.addrRA) );
+ }
+ }
+ if ( xosd != xosdNone ) {
+ return( xosd );
+ }
+ return SendRequestX ( dmfReturnStep, hpid, htid, sizeof(rtrnstp), &rtrnstp);
+
+}
+#endif
+
+
+XOSD
+ThreadStatus (
+ HPID hpid,
+ HTID htid,
+ LPTST lptst
+ )
+{
+ XOSD xosd = SendRequest ( dmfThreadStatus, hpid, htid );
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ }
+ if (xosd == xosdNone) {
+ memcpy(lptst, LpDmMsg->rgb, sizeof(TST));
+ }
+ return xosd;
+}
+
+
+XOSD
+ProcessStatus(
+ HPID hpid,
+ LPPST lppst
+ )
+{
+ XOSD xosd;
+ xosd = SendRequest(dmfProcessStatus, hpid, NULL );
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ }
+ if (xosd == xosdNone) {
+ memcpy(lppst, LpDmMsg->rgb, sizeof(PST));
+ }
+ return xosd;
+}
+
+#ifdef OSDEBUG4
+
+
+XOSD
+Freeze (
+ HPID hpid,
+ HTID htid
+ )
+{
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdBadProcess;
+ }
+ if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
+ return xosdBadThread;
+ }
+
+ SendRequest ( dmfFreeze, hpid, htid);
+
+ return LpDmMsg->xosdRet;
+}
+
+
+XOSD
+Thaw (
+ HPID hpid,
+ HTID htid
+ )
+{
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdBadProcess;
+ }
+ if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
+ return xosdBadThread;
+ }
+
+ SendRequest ( dmfResume, hpid, htid);
+
+ return LpDmMsg->xosdRet;
+}
+
+#endif
+
+XOSD
+DebugMetric (
+ HPID hpid,
+ HTID htid,
+ MTRC mtrc,
+ LPLONG lpl
+ )
+/*++
+
+Routine Description:
+
+ The debugger queries this function to find out the size of OS and machine
+ dependent values, e.g. the size of a process ID.
+
+Arguments:
+
+ hpid
+
+ htid
+
+ mtrc - metric identifier
+
+ lpl - answer buffer
+
+Return Value:
+
+ xosdNone if the request succeeded, xosd error code otherwise.
+
+--*/
+{
+ HPRC hprc;
+ LPPRC lpprc = NULL;
+ XOSD xosd = xosdNone;
+
+ hprc = HprcFromHpid(hpid);
+
+ if (hprc) {
+
+ lpprc = LLLock( hprc );
+ assert( lpprc );
+
+ switch ( mtrc ) {
+
+ default:
+ break;
+
+ //
+ // Invalidate cache for some items:
+ //
+ case mtrcProcessorType:
+ case mtrcProcessorLevel:
+ case mtrcOSVersion:
+ lpprc->fDmiCache = FALSE;
+
+ case mtrcEndian:
+ case mtrcThreads:
+ case mtrcAsync:
+ case mtrcAsyncStop:
+ case mtrcBreakPoints:
+ case mtrcReturnStep:
+ case mtrcRemote:
+ if (!lpprc->fDmiCache) {
+ xosd = SendRequest ( dmfGetDmInfo, hpid, htid );
+ if (xosd == xosdNone) {
+ memcpy(&lpprc->dmi, LpDmMsg->rgb, sizeof(DMINFO));
+ lpprc->fDmiCache = TRUE;
+ }
+ }
+ break;
+
+ }
+
+ if (xosd != xosdNone) {
+ LLUnlock( hprc );
+ return xosd;
+ }
+
+
+ }
+
+ switch ( mtrc ) {
+
+ default:
+ assert(FALSE);
+ xosd = xosdInvalidParameter;
+ break;
+
+ case mtrcProcessorType:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.Processor.Type;
+ break;
+
+ case mtrcProcessorLevel:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.Processor.Level;
+ break;
+
+ case mtrcEndian:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.Processor.Endian;
+ break;
+
+ case mtrcThreads:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.fHasThreads;
+ break;
+
+ case mtrcCRegs:
+
+ *lpl = CRgrd;
+ break;
+
+ case mtrcCFlags:
+
+ *lpl = CRgfd;
+ break;
+
+ case mtrcExtRegs:
+
+ assert(0 && "do something with this");
+ break;
+
+ case mtrcExtFP:
+
+ assert(0 && "do something with this");
+ break;
+
+ case mtrcExtMMU:
+
+ assert(0 && "do something with this");
+ break;
+
+ case mtrcExceptionHandling:
+
+ *( (LPDWORD) lpl) = TRUE;
+ break;
+
+ case mtrcAssembler:
+
+#if defined(TARGET_i386)
+ *( (LPDWORD) lpl) = TRUE;
+#elif defined(TARGET_PPC)
+ *( (LPDWORD) lpl) = FALSE;
+#elif defined(TARGET_MIPS)
+ *( (LPDWORD) lpl) = FALSE;
+#elif defined(TARGET_ALPHA)
+ *( (LPDWORD) lpl) = TRUE;
+#else
+#error "Unknown CPU type"
+#endif
+ break;
+
+ case mtrcAsync:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.fAsync;
+ break;
+
+ case mtrcAsyncStop:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.fAsyncStop;
+ break;
+
+ case mtrcBreakPoints:
+
+ assert(lpprc);
+ //
+ // Message BPs are implemented in the EM
+ // on top of the exec BP implemented by the DM.
+ //
+ *lpl = lpprc->dmi.Breakpoints |
+ bptsMessage |
+ bptsMClass;
+ break;
+
+ case mtrcReturnStep:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.fReturnStep;
+ break;
+
+ case mtrcShowDebuggee:
+
+ *lpl = FALSE;
+ break;
+
+ case mtrcHardSoftMode:
+
+ *lpl = FALSE;
+ break;
+
+ case mtrcRemote:
+
+ assert(lpprc);
+ *lpl = lpprc->dmi.fRemote;
+ break;
+
+ case mtrcOleRpc:
+
+ *lpl = FALSE;
+ break;
+
+ case mtrcNativeDebugger:
+
+ *lpl = FALSE;
+ break;
+
+ case mtrcOSVersion:
+
+ *lpl = MAKELONG( lpprc->dmi.MinorVersion, lpprc->dmi.MajorVersion );
+ break;
+
+ case mtrcMultInstances:
+
+ *(BOOL*) lpl = TRUE;
+ break;
+ }
+
+ LLUnlock( hprc );
+
+ return xosdNone;
+}
+
+
+
+XOSD
+FakeGetExceptionState(
+ EXCEPTION_CONTROL exc,
+ LPEXCEPTION_DESCRIPTION lpexd
+ )
+/*++
+
+Routine Description:
+
+ Handle the GetExceptionState call when there is no DM connected.
+
+Arguments:
+
+ exc - Supplies exfFirst, exfSpecified or exfNext
+
+ lpexd - Returns EXCEPTION_DESCRIPTION record
+
+Return Value:
+
+ xosdNone except when exc is exfNext and lpexd->dwExceptionCode
+ was not in the list.
+
+--*/
+{
+ DWORD dwT;
+ int i;
+
+ if (exc == exfFirst) {
+ *lpexd = DefaultExceptionList[0];
+ return xosdNone;
+ }
+
+ for (i = 0; DefaultExceptionList[i].dwExceptionCode != 0; i++) {
+ if (DefaultExceptionList[i].dwExceptionCode == lpexd->dwExceptionCode) {
+ break;
+ }
+ }
+
+ if (exc == exfSpecified) {
+ dwT = lpexd->dwExceptionCode;
+ *lpexd = DefaultExceptionList[i];
+ lpexd->dwExceptionCode = dwT;
+ return xosdNone;
+ }
+
+ if (DefaultExceptionList[i].dwExceptionCode != 0) {
+ *lpexd = DefaultExceptionList[++i];
+ return xosdNone;
+ }
+
+ return xosdInvalidParameter;
+}
+
+
+XOSD
+GetExceptionState(
+ HPID hpid,
+ HTID htid,
+ EXCEPTION_CONTROL exc,
+ LPEXCEPTION_DESCRIPTION lpexd
+ )
+{
+ HPRC hprc;
+ LPPRC lpprc;
+ XOSD xosd = xosdNone;
+ HEXD hexd;
+
+ if (!hpid) {
+ return FakeGetExceptionState(exc, lpexd);
+ }
+
+ hprc = HprcFromHpid( hpid );
+ assert(hprc);
+ lpprc = LLLock(hprc);
+
+ switch (exc) {
+
+ default:
+ assert( 0 && "Invalid arg to em!GetExceptionState" );
+ xosd = xosdInvalidParameter;
+ break;
+
+ case exfFirst:
+
+ hexd = LLNext( lpprc->llexc, NULL );
+ if (!hexd) {
+ // get the default exception record
+ DWORD dwT = 0;
+ hexd = LLFind( lpprc->llexc, NULL, &dwT, 0 );
+ }
+ if (!hexd) {
+ memset(lpexd, 0, sizeof(EXCEPTION_DESCRIPTION));
+ }
+ else {
+ *lpexd = *(LPEXCEPTION_DESCRIPTION)LLLock(hexd);
+ LLUnlock(hexd);
+ }
+ break;
+
+
+ case exfSpecified:
+
+ hexd = LLFind( lpprc->llexc, NULL, &lpexd->dwExceptionCode, 0 );
+ if (!hexd) {
+ // get the default exception record
+ DWORD dwT = 0;
+ hexd = LLFind( lpprc->llexc, NULL, &dwT, 0 );
+ }
+ if (!hexd) {
+ memset(lpexd, 0, sizeof(EXCEPTION_DESCRIPTION));
+ xosd = xosdInvalidParameter;
+ }
+ else {
+ *lpexd = *(LPEXCEPTION_DESCRIPTION)LLLock(hexd);
+ LLUnlock(hexd);
+ }
+ break;
+
+
+ case exfNext:
+
+ hexd = LLFind( lpprc->llexc, NULL, &lpexd->dwExceptionCode, 0 );
+ if (!hexd) {
+ //
+ // origin must exist
+ //
+ xosd = xosdInvalidParameter;
+ } else {
+ //
+ // but the next one need not
+ //
+ hexd = LLNext( lpprc->llexc, hexd );
+ if (!hexd) {
+ memset(lpexd, 0, sizeof(EXCEPTION_DESCRIPTION));
+ xosd = xosdEndOfStack;
+ } else {
+ *lpexd = *(LPEXCEPTION_DESCRIPTION)LLLock(hexd);
+ LLUnlock(hexd);
+ }
+ }
+ break;
+
+ }
+
+ LLUnlock(hprc);
+ return xosd;
+}
+
+
+XOSD
+SetExceptionState(
+ HPID hpid,
+ HTID htid,
+ LPEXCEPTION_DESCRIPTION lpexd
+ )
+{
+ HPRC hprc = HprcFromHpid( hpid );
+ HLLI llexc;
+ HEXD hexd;
+
+ assert(lpexd->efd == efdIgnore ||
+ lpexd->efd == efdNotify ||
+ lpexd->efd == efdCommand ||
+ lpexd->efd == efdStop);
+
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ llexc = ((LPPRC)LLLock(hprc))->llexc;
+ LLUnlock(hprc);
+
+ hexd = LLFind( llexc, NULL, &lpexd->dwExceptionCode, 0 );
+
+ if (!hexd) {
+ hexd = LLCreate( llexc );
+ if (!hexd) {
+ return xosdOutOfMemory;
+ }
+ LLAdd( llexc, hexd );
+ }
+
+ *(LPEXCEPTION_DESCRIPTION)LLLock(hexd) = *lpexd;
+ LLUnlock(hexd);
+
+ return SendRequestX( dmfSetExceptionState, hpid, htid,
+ sizeof(EXCEPTION_DESCRIPTION), lpexd);
+}
+
+#ifdef OSDEBUG4
+
+XOSD
+GetMemoryInfo(
+ HPID hpid,
+ HTID htid,
+ LPMEMINFO lpmi
+ )
+{
+ PMEMORY_BASIC_INFORMATION lpmbi;
+ ADDR addr;
+ XOSD xosd = xosdNone;
+
+ Unreferenced(htid);
+
+ addr = lpmi->addr;
+
+ if (ADDR_IS_LI(addr)) {
+ xosd = FixupAddr(hpid, &addr);
+ }
+
+ if (xosd == xosdNone) {
+ xosd = SendRequestX( dmfVirtualQuery, hpid, 0, sizeof(ADDR),
+ (LPVOID)&addr );
+ }
+
+ if (xosd == xosdNone) {
+ lpmbi = (PMEMORY_BASIC_INFORMATION) LpDmMsg->rgb;
+ lpmi->addrAllocBase = addr;
+ lpmi->addrAllocBase.addr.off = (UOFF32)lpmbi->AllocationBase;
+ lpmi->uRegionSize = (UOFF32)lpmbi->RegionSize;
+ lpmi->dwProtect = lpmbi->Protect;
+ lpmi->dwState = lpmbi->State;
+ lpmi->dwType = lpmbi->Type;
+ }
+
+ return xosd;
+}
+
+
+XOSD
+FreezeThread(
+ HPID hpid,
+ HTID htid,
+ BOOL fFreeze
+ )
+{
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdBadProcess;
+ }
+ if ( (hthd = HthdFromHtid(hprc, htid)) == hthdInvalid || hthd == NULL ) {
+ return xosdBadThread;
+ }
+
+ if (fFreeze) {
+ SendRequest ( dmfFreeze, hpid, htid);
+ } else {
+ SendRequest ( dmfResume, hpid, htid);
+ }
+
+ return LpDmMsg->xosdRet;
+}
+
+
+
+#define FreeModuleList(m) free(m)
+#define ModuleListCount(m) ((m)->Count)
+#define FirstModuleEntry(m) ((LPMODULE_ENTRY)((m)+1))
+#define NextModuleEntry(e) ((e)+1)
+#define NthModuleEntry(m,n) (FirstModuleEntry(m)+(n))
+
+#define ModuleEntryFlat(e) ((e)->Flat)
+#define ModuleEntryReal(e) ((e)->Real)
+#define ModuleEntrySegment(e) ((e)->Segment)
+#define ModuleEntrySelector(e) ((e)->Selector)
+#define ModuleEntryBase(e) ((e)->Base)
+#define ModuleEntryLimit(e) ((e)->Limit)
+#define ModuleEntryType(e) ((e)->Type)
+#define ModuleEntrySectionCount(e) ((e)->SectionCount)
+#define ModuleEntryName(e) ((e)->Name)
+
+
+XOSD
+GetModuleList(
+ HPID hpid,
+ HTID htid,
+ LPSTR lpModuleName,
+ LPMODULE_LIST FAR * lplpModuleList
+ )
+{
+ XOSD xosd = xosdNone;
+ HLLI llmdi;
+ HMDI hmdi;
+ LPMDI lpmdi;
+ DWORD Count;
+ LPMODULE_LIST ModList;
+ LPMODULE_LIST TmpList;
+ LPMODULE_ENTRY Entry;
+ LDT_ENTRY Ldt;
+ DWORD MaxSize;
+ DWORD Delta;
+ DWORD i;
+ SEGMENT Selector;
+ DWORD Base;
+ DWORD Limit;
+ OBJD *ObjD;
+ char *p;
+ char WantedName[ MAX_PATH ];
+ char WantedExt[ MAX_PATH ];
+ char ModName[ MAX_PATH ];
+ char ModExt[ MAX_PATH ];
+ char Name[ MAX_PATH ];
+
+ *WantedName = '\0';
+ *WantedExt = '\0';
+
+ if ( !lplpModuleList ) {
+ xosd = xosdInvalidParameter;
+ goto Done;
+ }
+
+ *lplpModuleList = NULL;
+
+ llmdi = LlmdiFromHprc( HprcFromHpid ( hpid ));
+
+ if ( !llmdi ) {
+ xosd = xosdBadProcess;
+ goto Done;
+ }
+
+
+ //
+ // Estimate the list size, to minimize the calls to realloc.
+ //
+ if ( lpModuleName ) {
+
+ Count = 20;
+ _splitpath( lpModuleName, NULL, NULL, WantedName, WantedExt );
+
+ } else {
+
+ hmdi = hmdiNull;
+ Count = 0;
+
+ while ( (hmdi = LLNext( llmdi, hmdi )) != hmdiNull ) {
+ lpmdi = LLLock( hmdi );
+ Count += lpmdi->fFlatMode ? 1 : lpmdi->cobj;
+ LLUnlock( hmdi );
+ }
+ }
+
+ //
+ // Allocate the list
+ //
+ MaxSize = sizeof(MODULE_LIST) + Count * sizeof(MODULE_ENTRY);
+
+ ModList = MHAlloc( MaxSize );
+
+ if ( !ModList ) {
+ xosd = xosdOutOfMemory;
+ goto Done;
+ }
+
+ //
+ // Build the list
+ //
+ Count = 0;
+
+ for ( hmdi = NULL; (hmdi = LLNext( llmdi, hmdi )); LLUnlock( hmdi ) ) {
+
+ lpmdi = LLLock( hmdi );
+
+ //
+ // Get the module name
+ //
+ p = (*(lpmdi->lszName) == '|') ? lpmdi->lszName+1 : lpmdi->lszName;
+ strcpy( Name, p );
+ p = strchr( Name, '|' );
+ if ( p ) {
+ *p = '\0';
+ }
+
+ if ( lpModuleName ) {
+
+ //
+ // Add if base name matches
+ //
+ _splitpath( Name, NULL, NULL, ModName, ModExt );
+
+ if (_stricmp(WantedName, ModName) || _stricmp(WantedExt, ModExt) ) {
+ continue;
+ }
+ }
+
+ Delta = lpmdi->fFlatMode ? 1 : lpmdi->cobj;
+
+ //
+ // Reallocate buffer if necessary
+ //
+ if ( (Count + Delta) * sizeof(MODULE_ENTRY) > MaxSize ) {
+
+ MaxSize += Delta * sizeof(MODULE_ENTRY);
+ TmpList = realloc( ModList, MaxSize );
+ if ( !TmpList ) {
+ FreeModuleList(ModList);
+ xosd = xosdOutOfMemory;
+ break;
+ }
+
+ ModList = TmpList;
+ }
+
+ //
+ // have buffer, fill it up
+ //
+ if ( lpmdi->fFlatMode ) {
+
+ Entry = NthModuleEntry(ModList,Count);
+
+ ModuleEntryFlat(Entry) = TRUE;
+ ModuleEntrySegment(Entry) = 0;
+ ModuleEntrySelector(Entry) = 0;
+ ModuleEntryBase(Entry) = lpmdi->lpBaseOfDll;
+ ModuleEntryLimit(Entry) = 0;
+ ModuleEntryType(Entry) = 0;
+ ModuleEntrySectionCount(Entry) = lpmdi->cobj;
+ strcpy(ModuleEntryName(Entry), Name);
+
+ Count++;
+
+ } else {
+
+ for ( i=0, ObjD = lpmdi->rgobjd; i < Delta; i++, ObjD++ ) {
+
+ if ( ObjD->wSel ) {
+
+ Selector = ObjD->wSel;
+
+ Entry = NthModuleEntry(ModList,Count);
+
+ ModuleEntrySegment(Entry) = i+1;
+ ModuleEntrySelector(Entry) = Selector;
+ ModuleEntryType(Entry) = 0;
+ ModuleEntrySectionCount(Entry) = 0;
+
+ strcpy(ModuleEntryName(Entry), Name);
+
+ if ( lpmdi->fRealMode ) {
+
+ xosd = xosdNone;
+
+ ModuleEntryFlat(Entry) = FALSE;
+ ModuleEntryReal(Entry) = TRUE;
+ ModuleEntryBase(Entry) = 0xBAD00BAD;
+ ModuleEntryLimit(Entry) = 0xBAD00BAD;
+
+ Count++;
+
+ } else {
+
+ xosd = SendRequestX( dmfQuerySelector,
+ hpid,
+ NULL,
+ sizeof(SEGMENT),
+ &Selector );
+
+ if (xosd == xosdNone) {
+
+
+ _fmemcpy( &Ldt, LpDmMsg->rgb, sizeof(Ldt));
+
+ Base = (Ldt.HighWord.Bits.BaseHi << 0x18) |
+ (Ldt.HighWord.Bits.BaseMid << 0x10) |
+ Ldt.BaseLow;
+
+ Limit = (Ldt.HighWord.Bits.LimitHi << 0x10) |
+ Ldt.LimitLow;
+
+ ModuleEntryFlat(Entry) = FALSE;
+ ModuleEntryReal(Entry) = FALSE;
+ ModuleEntryBase(Entry) = Base;
+ ModuleEntryLimit(Entry) = Limit;
+
+ Count++;
+
+ } else {
+
+ xosd = xosdNone;
+
+ ModuleEntryFlat(Entry) = FALSE;
+ ModuleEntryReal(Entry) = FALSE;
+ ModuleEntryBase(Entry) = 0xBAD00BAD;
+ ModuleEntryLimit(Entry) = 0xBAD00BAD;
+ Count++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (hmdi) {
+ LLUnlock(hmdi);
+ }
+
+ ModuleListCount(ModList) = Count;
+ *lplpModuleList = ModList;
+
+Done:
+ return xosd;
+}
+
+
+XOSD
+DoContinue(
+ HPID hpid
+ )
+{
+ LPPRC lpprc;
+ HPRC hprc = HprcFromHpid(hpid);
+ XOSD xosd = xosdUnknown;
+ BYTE b = 1;
+
+ assert(hprc);
+
+ lpprc = LLLock(hprc);
+
+ if (lpprc->fLoadingModule) {
+
+ lpprc->fRunning = TRUE;
+ lpprc->fLoadingModule = FALSE;
+ CallTL ( tlfReply, hpid, 1, &b );
+ xosd = xosdNone;
+
+ } else if (lpprc->fUnloadingModule) {
+
+ lpprc->fRunning = TRUE;
+ lpprc->fUnloadingModule = FALSE;
+ CallTL ( tlfReply, hpid, 1, &b );
+ xosd = xosdNone;
+ }
+
+ LLUnlock(hprc);
+
+ return xosd;
+}
+
+
+XOSD
+DoCustomCommand(
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LPSSS lpsss
+ )
+{
+ LPSTR lpsz = lpsss->rgbData;
+ LPSTR p;
+ XOSD xosd;
+ char cmd[256];
+
+ //
+ // parse the command from the command line
+ //
+ p = cmd;
+ while (*lpsz && !isspace(*lpsz)) {
+ *p++ = *lpsz++;
+ }
+ *p = '\0';
+
+ //
+ // this is where you would _stricmp() for your custom em command
+ // otherwise it is passed to the dm
+ //
+
+ return SendRequestX( dmfSystemService, hpid, htid, wValue, (LPVOID) lpsss );
+
+ //
+ // this is what would be executed if you have a custom em command
+ // instead of the above sendrequest()
+ //
+
+#if 0
+ strcpy( lpiol->rgbVar, lpsz );
+ xosd = IoctlCmd(hpid, htid, wValue, lpiol);
+
+ return xosd;
+#endif
+} /* DoCustomCommand */
+
+
+
+
+XOSD
+SystemService(
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LPSSS lpsss
+ )
+
+/*++
+
+Routine Description:
+
+ This function examines SystemService requests (escapes) and deals
+ with those which the EM knows about. All others are passed on to
+ the DM for later processing.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+ DWORD dw;
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+
+ switch( lpsss-> ssvc ) {
+
+ case ssvcGetStackFrame:
+ hprc = HprcFromHpid( hpid );
+ hthd = HthdFromHtid ( hprc, htid );
+ assert(hthd);
+ lpthd = LLLock(hthd);
+ _fmemcpy(lpsss->rgbData, &lpthd->StackFrame, sizeof(STACKFRAME));
+ lpsss->cbReturned = sizeof(STACKFRAME);
+ xosd = xosdNone;
+ break;
+
+ case ssvcGetThreadContext:
+ xosd = SendRequest ( dmfReadReg, hpid, htid );
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ dw = min(lpsss->cbSend, sizeof(CONTEXT));
+ _fmemcpy (lpsss->rgbData, LpDmMsg->rgb, dw);
+ lpsss->cbReturned = dw;
+ }
+ break;
+
+ case ssvcSetThreadContext:
+ xosd = SendRequestX( dmfWriteReg, hpid, htid, lpsss->cbSend,
+ lpsss->rgbData );
+ break;
+
+ case ssvcGetProcessHandle:
+ case ssvcGetThreadHandle:
+ xosd = SendRequestX(dmfSystemService,hpid, htid, wValue, (LPVOID)lpsss);
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ dw = min(lpsss->cbSend, sizeof(HANDLE));
+ _fmemcpy (lpsss->rgbData, LpDmMsg->rgb, dw);
+ lpsss->cbReturned = dw;
+ }
+ break;
+
+
+ case ssvcCustomCommand:
+ xosd = DoCustomCommand(hpid, htid, wValue, lpsss);
+ break;
+
+ case ssvcGetPrompt:
+ xosd = SendRequestX(dmfSystemService, hpid, htid, wValue, (LPVOID)lpsss);
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ lpsss->cbReturned = ((LPPROMPTMSG)((LPSSS)LpDmMsg->rgb))->len + sizeof(PROMPTMSG);
+ if (lpsss->cbReturned) {
+ _fmemcpy((LPVOID)lpsss->rgbData,
+ LpDmMsg->rgb,
+ lpsss->cbReturned);
+ }
+ }
+ break;
+
+ case ssvcGeneric:
+ xosd = SendRequestX(dmfSystemService,hpid,htid,wValue,(LPVOID)lpsss);
+ if (xosd == xosdNone) {
+ xosd = LpDmMsg->xosdRet;
+ lpsss->cbReturned = *((LPDWORD)LpDmMsg->rgb);
+ if (lpsss->cbReturned) {
+ _fmemcpy ( (LPVOID)lpsss->rgbData,
+ LpDmMsg->rgb + sizeof(DWORD),
+ lpsss->cbReturned);
+ }
+ }
+ break;
+
+ default:
+ xosd = SendRequestX(dmfSystemService,hpid,htid,wValue,(LPVOID)lpsss);
+ break;
+ }
+
+ return xosd;
+
+}
+#endif // OSDEBUG4
+
+XOSD
+RangeStep (
+ HPID hpid,
+ HTID htid,
+ LPRSS lprss
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to implement range steps in the EM. A range
+ step is defined as step all instructions as long as the program counter
+ remains within the starting and ending addresses.
+
+Arguments:
+
+ hpid - Supplies the handle of the process to be stepped
+ htid - Supplies the handle of thread to be stepped
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ XOSD xosd = xosdNone;
+ RST rst = {0};
+
+ UpdateChild ( hpid, htid, dmfRangeStep );
+
+ rst.fStepOver = lprss->lpExop->fStepOver;
+ rst.fAllThreads = !lprss->lpExop->fSingleThread;
+ rst.fInitialBP = lprss->lpExop->fInitialBP;
+ rst.offStart = lprss->lpaddrMin->addr.off;
+ rst.offEnd = lprss->lpaddrMax->addr.off;
+
+ return SendRequestX (
+ dmfRangeStep,
+ hpid,
+ htid,
+ sizeof ( RST ),
+ &rst
+ );
+
+} /* RangeStep() */
+
+XOSD
+SingleStep (
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpexop
+ )
+{
+ assert ( hpid != NULL );
+ assert ( htid != NULL );
+
+ UpdateChild ( hpid, htid, dmfSingleStep );
+
+ return SendRequestX (
+ dmfSingleStep,
+ hpid,
+ htid,
+ sizeof(EXOP),
+ lpexop
+ );
+}
+
diff --git a/private/windbg/em/emerror.h b/private/windbg/em/emerror.h
new file mode 100644
index 000000000..c0ac5e7f9
--- /dev/null
+++ b/private/windbg/em/emerror.h
@@ -0,0 +1,61 @@
+DECL_STR("No error", xosdNone)
+DECL_STR("Bogus error", xosdQueueEmpty)
+DECL_STR("Bogus error", xosdModLoad)
+DECL_STR("Bogus error", xosdFindProc)
+DECL_STR("Bogus error", xosdOSStruct)
+DECL_STR("Syntax Error", xosdSyntax)
+DECL_STR("Invalid Process", xosdInvalidProc)
+DECL_STR("Invalid Thread", xosdInvalidThread)
+DECL_STR("Invalid Transport Layer", xosdInvalidTL)
+DECL_STR("Invalid Execution Model", xosdInvalidEM)
+DECL_STR("No Processes", xosdNoProc)
+DECL_STR("Process already running", xosdProcRunning)
+DECL_STR("Could not create debugger thread", xosdCreateDBGThread)
+DECL_STR("Out of memory", xosdOutOfMemory)
+DECL_STR("Invalid Breakpoint", xosdInvalidBreakPoint)
+DECL_STR("Invalid address", xosdBadAddress)
+DECL_STR("No available watchpoints", xosdNoWatchPoints)
+DECL_STR("Invalid Process", xosdInvalidPID)
+DECL_STR("Invalid Thread", xosdInvalidTID)
+DECL_STR("No available threads", xosdOutOfThreads)
+DECL_STR("No available processes", xosdOutOfProcs)
+DECL_STR("Ptrace", xosdPtrace)
+DECL_STR("Load loading debuggee", xosdLoadChild)
+DECL_STR("Could not read", xosdRead)
+DECL_STR("Could not write", xosdWrite)
+DECL_STR("Invalid Queue", xosdBadQueue)
+DECL_STR("Execution model in use", xosdEMInUse)
+DECL_STR("Transport layer in use", xosdTLInUse)
+DECL_STR("Fatal", xosdFatal)
+DECL_STR("Bogus error", xosdUnknown)
+DECL_STR("Invalid Dll or Exe", xosdInvalidMTE)
+DECL_STR("Invalid selector", xosdInvalidSelector)
+DECL_STR("Invalid Register", xosdInvalidRegister)
+DECL_STR("Invalid Parameter", xosdInvalidParameter)
+DECL_STR("Out of structures", xosdOutOfStructures)
+DECL_STR("Path not found", xosdPathNotFound)
+DECL_STR("Line busy", xosdLineBusy)
+DECL_STR("Invalid Line", xosdBadLine)
+DECL_STR("Broken Line", xosdBrokenLine)
+DECL_STR("Interrupt", xosdInterrupt)
+DECL_STR("Invalid Function", xosdInvalidFunction)
+DECL_STR("Line not connected", xosdLineNotConnected)
+DECL_STR("Access Denied", xosdAccessDenied)
+DECL_STR("Cannot make pipe", xosdCannotMake)
+DECL_STR("File not found", xosdFileNotFound)
+DECL_STR("Invalid Access", xosdInvalidAccess)
+DECL_STR("Open Failed", xosdOpenFailed)
+DECL_STR("Share Buffer Exceeded", xosdSharingBufferExeeded)
+DECL_STR("Sharing violation", xosdSharingViolation)
+DECL_STR("Line", xosdLine)
+DECL_STR("End of Stack", xosdEndOfStack)
+DECL_STR("Floating Point not Loaded", xosdFPNotLoaded)
+DECL_STR("Bogus error", xosdQuit)
+DECL_STR("Too Many Objects", xosdTooManyObjects)
+DECL_STR("Module name invalid", xosdGetModNameFail)
+DECL_STR("Cannot connect", xosdCannotConnect)
+DECL_STR("Bogus error", xosdPunt)
+DECL_STR("Not found", xosdNotFound)
+DECL_STR("Identifier Error", xosdIDError)
+DECL_STR("Overrun", xosdOverrun)
+DECL_STR("Debuggee is deadlocked", xosdAttachDeadlock)
diff --git a/private/windbg/em/emproto.h b/private/windbg/em/emproto.h
new file mode 100644
index 000000000..4c2ad5d88
--- /dev/null
+++ b/private/windbg/em/emproto.h
@@ -0,0 +1,214 @@
+
+
+
+XOSD EMFunc ( EMF, HPID, HTID, DWORD, LONG );
+
+
+void FlushPTCache ( void );
+void PurgeCache ( void );
+HPRC HprcFromHpid ( HPID );
+HPRC ValidHprcFromHpid ( HPID );
+HPID HpidFromHprc ( HPRC );
+PID PidFromHprc ( HPRC );
+HPRC HprcFromPid ( PID );
+HTHD HthdFromHtid ( HPRC, HTID );
+HTID HtidFromHthd ( HTHD );
+TID TidFromHthd ( HTHD );
+HTHD HthdFromTid ( HPRC, TID );
+
+VOID SyncHprcWithDM( HPID hpid );
+
+XOSD DebugPacket ( DBC, HPID, HTID, DWORD, LPBYTE );
+HMDI SwGetMdi( HPID hpid, DWORD Address );
+
+XOSD HandleBreakpoints( HPID hpid, DWORD wValue, LONG lValue );
+
+XOSD ProcessStatus( HPID, LPPST );
+XOSD ThreadStatus ( HPID hpid, HTID htid, LPTST lptst );
+XOSD GetExceptionState(HPID, HTID, EXCEPTION_CONTROL, LPEXCEPTION_DESCRIPTION);
+XOSD SetExceptionState( HPID, HTID, LPEXCEPTION_DESCRIPTION );
+XOSD Go ( HPID, HTID, LPEXOP );
+XOSD SingleStep ( HPID, HTID, LPEXOP );
+XOSD RangeStep ( HPID, HTID, LPRSS );
+XOSD ReturnStep ( HPID hpid, HTID htid, LPEXOP lpexop );
+
+int EMENTRY EXCComp(LPVOID, LPVOID, LONG);
+
+#ifdef OSDEBUG4
+
+XOSD WriteBufferCache ( HPID, HTID, LPADDR, DWORD, LPBYTE, LPDWORD );
+XOSD WriteBuffer ( HPID, HTID, LPADDR, DWORD, LPBYTE, LPDWORD );
+XOSD CompareAddrs( HPID, HTID, LPCAS );
+XOSD UpdateChild ( HPID, HTID, DMF );
+XOSD FreezeThread( HPID hpid, HTID htid, BOOL fFreeze );
+XOSD GetMemoryInfo( HPID hpid, HTID htid, LPMEMINFO lpmi );
+XOSD GetModuleList( HPID, HTID, LPSTR, LPMODULE_LIST FAR * );
+
+
+#else // OSDEBUG4
+
+XOSD GetCaller ( HPID, HTID, FCT, LPADDR );
+XOSD CallPtrace ( WORD, WORD, LPBYTE, HPRC, HTHD );
+
+//XOSD SetBreakPoint ( HPID, HTID, WORD, LPBPARGS );
+//XOSD RemoveBreakPoint ( HPID, HTID, WORD, LPBPARGS );
+//XOSD EnableBP ( HPID, HTID, LPADDR );
+//XOSD DisableBP ( HPID, HTID, LPADDR );
+
+XOSD GetFrameRegValue ( HPID, HTID, DWORD, LPVOID );
+XOSD SetFrameRegValue ( HPID, HTID, DWORD, LPVOID );
+XOSD SetFrameContext ( HPID, HTID, DWORD );
+BOOL NEAR PASCAL IsStackSetup( HPID, HTID, LPADDR );
+XOSD SetFrame ( HPID, HTID, PFRAME );
+CMP CmpAddr ( LPADDR lpaddr1, LPADDR lpaddr2 );
+//XOSD Go ( HPID, HTID, BOOL );
+//XOSD SingleStep ( HPID, HTID, BOOL, STO );
+//XOSD RangeStep ( HPID, HTID, LPADDR, BOOL, STO );
+//XOSD ThreadStatus ( HPID, HTID, LPTST );
+//XOSD ProcStatus ( HPID, LPDWORD );
+//XOSD ProcStatusXX ( HPID, LPDWORD );
+XOSD GetPrompt(HPID hpid, HTID htid, LPPROMPTMSG lppm);
+XOSD WriteBufferCache ( HPID, HTID, DWORD, LPBYTE );
+XOSD WriteBuffer ( HPID, HTID, DWORD, LPBYTE );
+XOSD CompareAddrs( LPADDR, LPADDR );
+XOSD UpdateChild ( HPID, HTID, DMF );
+XOSD Freeze ( HPID, HTID );
+XOSD Thaw ( HPID, HTID );
+XOSD IoctlCmd(HPID hpid, HTID htid, DWORD wValue, LPIOL lpiol);
+
+#endif // !OSDEBUG
+
+
+
+
+
+
+XOSD ProgramLoad ( HPID, DWORD, LPPRL );
+XOSD ProgramFree ( HPID, HTID );
+XOSD GetAddr ( HPID, HTID, ADR, LPADDR );
+XOSD SetAddr ( HPID, HTID, ADR, LPADDR );
+XOSD SetAddrFromCSIP ( HTHD hthd );
+XOSD GetFrame ( HPID, HTID, LPADDR );
+XOSD SetWatchPoint ( HPID, HTID, DWORD );
+XOSD RemoveWatchPoint ( HPID, HTID, DWORD );
+void InitUsage ( void );
+XOSD ReadBuffer ( HPID, HTID, LPADDR, DWORD, LPBYTE, LPDWORD );
+void UpdateRegisters ( HPRC, HTHD );
+void UpdateSpecialRegisters ( HPRC hprc, HTHD hthd );
+XOSD DoGetContext( HPID hpid, HTID htid, LPVOID lpv );
+XOSD DoSetContext( HPID hpid, HTID htid, LPVOID lpv );
+XOSD LoadFixups ( HPID, MODULELOAD UNALIGNED *);
+BOOL UnLoadFixups ( HPID, HEMI, BOOL );
+void RegisterEmi ( HPID, LPREMI );
+XOSD CreateThreadStruct ( HPID, TID, HTID FAR * );
+XOSD CreateHprc ( HPID );
+VOID DestroyHprc ( HPRC );
+VOID DestroyHthd ( HTHD );
+
+void EMENTRY PiDKill ( LPVOID );
+void EMENTRY TiDKill ( LPVOID );
+void EMENTRY MDIKill(LPVOID lpv);
+int EMENTRY PDComp ( LPVOID, LPVOID, LONG );
+int EMENTRY TDComp ( LPVOID, LPVOID, LONG );
+int EMENTRY BPComp ( LPVOID, LPVOID, LONG );
+int EMENTRY TBComp ( LPVOID, LPVOID, LONG );
+int EMENTRY MDIComp ( LPVOID, LPVOID, LONG );
+
+XOSD DebugMetric ( HPID, HTID, MTRC, LPLONG );
+XOSD FixupAddr ( HPID, LPADDR );
+XOSD UnFixupAddr ( HPID, LPADDR );
+XOSD SetEmi ( HPID, LPADDR );
+XOSD GetRegValue ( HPID, HTID , DWORD , LPVOID );
+XOSD SetRegValue ( HPID, HTID , DWORD , LPVOID );
+XOSD GetFlagValue ( HPID, HTID , DWORD , LPVOID );
+XOSD SetFlagValue ( HPID, HTID , DWORD , LPVOID );
+XOSD GetObjLength ( HPID, LPGOL );
+XOSD SaveRegs ( HTHD, LPHIND );
+XOSD RestoreRegs ( HTHD, HIND );
+HLLI LlthdFromHprc ( HPRC );
+HLLI LlmdiFromHprc ( HPRC );
+STAT StatFromHprc ( HPRC );
+
+XOSD WMSGTranslate( LPWORD, LPWORD, LPSTR, LPWORD );
+
+HEMI HemiFromHmdi ( HMDI );
+XOSD GetPrevInst ( HPID, HTID, LPADDR );
+
+XOSD GetPrevInst ( HPID, HTID, LPADDR );
+XOSD disasm ( HPID, HTID, LPSDI );
+XOSD IsCall ( HPID, HTID, LPADDR, LPDWORD );
+
+XOSD Assemble ( HPID, HTID, LPADDR, LPSTR ); // [00]
+
+XOSD SendRequest ( DMF, HPID, HTID );
+XOSD SendRequestX ( DMF dmf, HPID hpid, HTID htid, DWORD wLen, LPVOID lpv );
+BOOL UpdateFPRegisters ( HPRC, HTHD );
+XOSD CleanCacheOfEmi ( void );
+
+BOOL UpdateEmulator ( HPID, HTID );
+LPVOID DoGetReg ( LPCONTEXT, DWORD, LPVOID );
+LPVOID DoSetReg ( LPCONTEXT, DWORD, LPVOID );
+LPVOID DoSetFrameReg ( HPID, HTID, LPTHD, PKNONVOLATILE_CONTEXT_POINTERS,
+ DWORD, LPVOID );
+
+XOSD SetPath ( HPID, HTID, BOOL, LPSTR );
+LPSTR EmError(XOSD xosd);
+XOSD EnableCache( HPID hpid, HTID htid, BOOL state );
+
+XOSD GetFunctionInfo( HPID, PADDR, PFUNCTION_INFO );
+XOSD GetSectionObjectsFromDM(HPID hpid, LPMDI lpmdi);
+
+
+//*************************************************************************
+//
+// stack walking apis
+//
+//*************************************************************************
+XOSD
+StackWalkSetup(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkstr
+ );
+
+XOSD
+StackWalkNext(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkstr
+ );
+
+XOSD
+StackWalkCleanup(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkstr
+ );
+
+BOOL
+SwReadMemory(
+ HPID hpid,
+ LPCVOID lpBaseAddress,
+ LPVOID lpBuffer,
+ DWORD nSize,
+ LPDWORD lpNumberOfBytesRead
+ );
+
+LPVOID
+SwFunctionTableAccess(
+ HPID hpid,
+ DWORD AddrBase
+ );
+
+DWORD
+SwGetModuleBase(
+ HPID hpid,
+ DWORD ReturnAddress
+ );
+
+DWORD
+SwTranslateAddress(
+ HPID hpid,
+ HTID htid,
+ LPADDRESS lpaddr
+ );
diff --git a/private/windbg/em/p_alpha/asm.c b/private/windbg/em/p_alpha/asm.c
new file mode 100644
index 000000000..1409e7cc8
--- /dev/null
+++ b/private/windbg/em/p_alpha/asm.c
@@ -0,0 +1,780 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ assem.c
+
+Abstract:
+
+ This file contains the set of routines which assemble an
+ instruction on Alpha.
+
+Author:
+
+ Miche Baker-Harvey
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+/******************** INCLUDE FILES *******************************/
+#include "precomp.h"
+#pragma hdrstop
+
+#include <alphaops.h>
+
+#include "optable.h"
+#include "ntasm.h"
+#include "ntdis.h"
+
+#include "strings.h"
+
+
+#define OPSIZE 16
+
+int assem(PULONG, PUCHAR, PULONG);
+BOOLEAN TestCharacter (PUCHAR, PUCHAR *, UCHAR ch);
+ULONG GetIntReg(PUCHAR, PUCHAR *);
+ULONG GetFltReg(PUCHAR, PUCHAR *);
+ULONG GetValue(PUCHAR, PUCHAR *, BOOLEAN, ULONG, PULONG, CHAR);
+PUCHAR SkipWhite(PUCHAR *);
+ULONG GetToken(PUCHAR, PUCHAR *, PUCHAR, ULONG);
+
+
+
+/*** assem - assemble instruction
+*
+* Purpose:
+* To assemble the instruction pointed by *poffset.
+*
+* Input:
+* instruction - where to put the assembled instruction
+* pchInput - pointer to string to assemble
+* poffset -
+*
+* Output:
+* status - see ntasm.h for codes
+*
+* Exceptions:
+* error exit: xosd
+*
+* Notes:
+* errors are handled by the calling program by outputting
+* the error string and reprompting the user for the same
+* instruction.
+*
+**************************************************************/
+
+int
+assem (PULONG instruction, PUCHAR pchInput, PULONG poffset)
+{
+ UCHAR szOpcode[OPSIZE];
+ ULONG status;
+
+ POPTBLENTRY pEntry;
+
+ //
+ // Using the mnemonic token, find the entry in the assembler's
+ // table for the associated instruction.
+ //
+
+ if (GetToken(pchInput, &pchInput, szOpcode, OPSIZE) == 0) {
+ return(BADOPCODE);
+ }
+
+ if ((pEntry = findStringEntry(szOpcode)) == (POPTBLENTRY) -1) {
+ return(BADOPCODE);
+ }
+
+ if (pEntry->eType == INVALID_ETYPE) {
+ return(BADOPCODE);
+ }
+
+ //
+ // Use the instruction format specific parser to encode the
+ // instruction plus its operands.
+ //
+
+ status = (*pEntry->parsFunc)
+ (pchInput, pEntry, poffset, instruction);
+
+ return (status);
+}
+
+
+BOOLEAN
+TestCharacter (PUCHAR inString, PUCHAR *outString, UCHAR ch)
+{
+
+ inString = SkipWhite(&inString);
+ if (ch == *inString) {
+ *outString = inString+1;
+ return TRUE;
+ }
+ else {
+ *outString = inString;
+ return FALSE;
+ }
+}
+
+
+/*** GetIntReg - get integer register number
+ *** GetFltReg - get floating register number
+*
+* Purpose:
+* From reading the input stream, return the register number.
+*
+* Input:
+* inString - pointer to input string
+*
+* Output:
+* *outString - pointer to character after register token in input stream
+*
+* Returns:
+* register number
+*
+* Exceptions:
+* error(BADREG) - bad register name
+*
+*************************************************************************/
+
+PUCHAR regNums[] = {
+ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+ "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
+ };
+
+PUCHAR intRegNames[] = {
+ szR0, szR1, szR2, szR3, szR4, szR5, szR6, szR7,
+ szR8, szR9, szR10, szR11, szR12, szR13, szR14, szR15,
+ szR16, szR17, szR18, szR19, szR20, szR21, szR22, szR23,
+ szR24, szR25, szR26, szR27, szR28, szR29, szR30, szR31
+
+ };
+
+PUCHAR fltRegNames[] = {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+ };
+
+ULONG
+GetIntReg (PUCHAR inString, PUCHAR *outString)
+{
+ UCHAR szRegOp[5];
+ ULONG index;
+
+ if (!GetToken(inString, outString, szRegOp, sizeof(szRegOp)))
+ return(BADREG);
+
+ if (szRegOp[0] == '$') {
+ //
+ // use numbers
+ //
+ for (index = 0; index < 32; index++) {
+ if (!strcmp(szRegOp, regNums[index]))
+ return index;
+ }
+ } else {
+ //
+ // use names
+ //
+ for (index = 0; index < 32; index++) {
+ if (!strcmp(szRegOp, intRegNames[index]))
+ return index;
+ }
+ }
+ return(BADREG);
+}
+
+ULONG
+GetFltReg (PUCHAR inString, PUCHAR *outString)
+{
+ UCHAR szRegOp[5];
+ ULONG index;
+
+ if (!GetToken(inString, outString, szRegOp, sizeof(szRegOp)))
+ return(BADREG);
+
+ if (szRegOp[0] == '$') {
+ //
+ // use numbers
+ //
+ for (index = 0; index < 32; index++) {
+ if (!strcmp(szRegOp, regNums[index]))
+ return index;
+ }
+ } else {
+ //
+ // use names
+ //
+ for (index = 0; index < 32; index++) {
+ if (!strcmp(szRegOp, fltRegNames[index]))
+ return index;
+ }
+ }
+
+ return(BADREG);
+}
+
+
+/*** GetValue - get value from command line
+*
+* Purpose:
+* Use GetExpression to evaluate the next expression in the input
+* stream.
+*
+* Input:
+* inString - pointer to input stream
+* fSigned - TRUE if signed value
+* FALSE if unsigned value
+* bitsize - size of value allowed
+*
+* Output:
+* outString - character after the last character of the expression
+* outValue - where to return the value
+*
+* Returns:
+* GOODINSTRUCTION, or error from ntasm.h
+*
+* Exceptions:
+* return exit: OVERFLOW - value too large for bitsize
+*
+*************************************************************************/
+
+ULONG
+GetValue (PUCHAR inString,
+ PUCHAR *outString,
+ BOOLEAN fSigned,
+ ULONG bitsize,
+ PULONG valuep,
+ CHAR ch)
+{
+ ULONG value, index, err;
+
+ inString = SkipWhite(&inString);
+
+ //
+ // find the character that marks the end of the string,
+ // and replace it with a null;
+ // otherwise, the expression evaluator fails
+ //
+
+ for ( index = 0; /**/ ; index++ ) {
+
+ if (inString[index] == ch) {
+ inString[index] = '\0';
+ break;
+ }
+
+ if (inString[index] == '\0') {
+ return OPERAND;
+ }
+ }
+
+ //
+ // This is a callback to the shell which does the work.
+ //
+
+ err = DHGetNumber(inString, &value);
+
+ //
+ // first replace any overwritten character
+ //
+ inString[index] = ch;
+
+ //
+ // DHGetNumber returns 0 if it succeeds.
+ //
+ if ( err != GOODINSTRUCTION ) {
+ return err;
+ }
+
+ if ((value > (ULONG)(1L << bitsize) - 1) &&
+ (!fSigned || (value < (ULONG)(-1L << (bitsize - 1)))))
+ return OVERFLOW;
+
+ *outString = inString + index;
+ *valuep = value;
+ return GOODINSTRUCTION;
+}
+
+
+/*** SkipWhite - skip white-space
+*
+* Purpose:
+* To advance pchCommand over any spaces or tabs.
+*
+* Input:
+* *pchCommand - present command line position
+*
+*************************************************************************/
+
+PUCHAR
+SkipWhite (PUCHAR * string)
+{
+ while (**string == ' ' || **string == '\t')
+ (*string)++;
+
+ return(*string);
+}
+
+
+/*** GetToken - get token from command line
+*
+* Purpose:
+* Build a lower-case mapped token of maximum size maxcnt
+* at the string pointed by *psz. Token consist of the
+* set of characters a-z, A-Z, 0-9, $, and underscore.
+*
+* Input:
+* *inString - present command line position
+* maxcnt - maximum size of token allowed
+*
+* Output:
+* *outToken - token in lower case
+* *outString - pointer to first character beyond token in input
+*
+* Returns:
+* size of token if under maximum else 0
+*
+* Notes:
+* if string exceeds maximum size, the extra characters
+* are still processed, but ignored.
+*
+*************************************************************************/
+
+ULONG
+GetToken (PUCHAR inString, PUCHAR *outString, PUCHAR outToken, ULONG maxcnt)
+{
+ UCHAR ch;
+ ULONG count = 0;
+
+ inString = SkipWhite(&inString);
+
+ while (count < maxcnt) {
+ ch = (UCHAR)tolower(*inString);
+
+ if (!((ch >= '0' && ch <= '9') ||
+ (ch >= 'a' && ch <= 'z') ||
+ (ch == '$') ||
+ (ch == '_') ||
+ (ch == '#')))
+ break;
+
+ count++;
+ *outToken++ = ch;
+ inString++;
+ }
+
+ *outToken = '\0';
+ *outString = inString;
+
+ return (count >= maxcnt ? 0 : count);
+}
+
+
+/*** ParseIntMemory - parse integer memory instruction
+*
+* Purpose:
+* Given the users input, create the instruction.
+*
+* Input:
+* inString - present input position
+* pEntry - pointer into the opTable for this opcode
+* poffset - pointer to offset where assembled instr will go
+* pinstruction - pointer to where to put the instruction
+*
+* Output:
+* &pinstruction - the assembled instruction
+*
+* Returns:
+* the error code, or GOODINSTRUCTINO
+*
+* Format:
+* op Ra, disp(Rb)
+*
+*************************************************************************/
+
+ULONG
+ParseIntMemory(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ ULONG Ra;
+ ULONG Rb;
+ ULONG disp;
+ ULONG err;
+
+ Ra = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ err = GetValue(inString, &inString, TRUE, WIDTH_MEM_DISP, &disp, '(');
+ if (err != GOODINSTRUCTION)
+ return err;
+
+ if (!TestCharacter(inString, &inString, '('))
+ return(OPERAND);
+
+ Rb = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ')'))
+ return(OPERAND);
+
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = OPCODE(pEntry->opCode) +
+ REG_A(Ra) +
+ REG_B(Rb) +
+ MEM_DISP(disp);
+
+ return(GOODINSTRUCTION);
+}
+
+/*** ParseFltMemory - parse floating point memory instruction
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op Fa, disp(Rb)
+*
+*************************************************************************/
+
+ULONG
+ParseFltMemory(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ ULONG Fa;
+ ULONG Rb;
+ ULONG disp;
+ ULONG err;
+
+ Fa = GetFltReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ err = GetValue(inString, &inString, TRUE, WIDTH_MEM_DISP, &disp, '(');
+ if (err != GOODINSTRUCTION)
+ return err;
+
+ if (!TestCharacter(inString, &inString, '('))
+ return(OPERAND);
+
+ Rb = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ')'))
+ return(OPERAND);
+
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = OPCODE(pEntry->opCode) +
+ REG_A(Fa) +
+ REG_B(Rb) +
+ MEM_DISP(disp);
+
+ return(GOODINSTRUCTION);
+}
+
+/*** ParseMemSpec - parse special memory instruction
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op
+*
+*************************************************************************/
+ULONG ParseMemSpec(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ *instruction = (OPCODE(pEntry->opCode) +
+ MEM_FUNC(pEntry->funcCode));
+ return (GOODINSTRUCTION);
+}
+
+/*** ParseJump - parse jump instruction
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op Ra,(Rb),hint
+* op Ra,(Rb) - not really - we just support it here
+*
+*************************************************************************/
+
+ULONG ParseJump(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ ULONG Ra;
+ ULONG Rb;
+ ULONG hint;
+ ULONG err;
+
+ Ra = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ if (!TestCharacter(inString, &inString, '('))
+ return(OPERAND);
+
+ Rb = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ')'))
+ return(OPERAND);
+
+ if (TestCharacter(inString, &inString, ',')) {
+ //
+ // User is giving us a hint
+ //
+ err = GetValue(inString, &inString, TRUE, WIDTH_HINT, &hint, '\0');
+ if (err != GOODINSTRUCTION)
+ return err;
+ } else {
+ hint = 0;
+ }
+
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = OPCODE(pEntry->opCode) +
+ JMP_FNC(pEntry->funcCode) +
+ REG_A(Ra) +
+ REG_B(Rb) +
+ HINT(hint);
+
+ return(GOODINSTRUCTION);
+}
+
+/*** ParseIntBranch - parse integer branch instruction
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op Ra,disp
+*
+*************************************************************************/
+
+ULONG ParseIntBranch(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ ULONG Ra;
+ LONG disp;
+ ULONG err;
+
+ Ra = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ //
+ // the user gives an absolute address; we convert
+ // that to a displacement, which is computed as a
+ // difference off of (pc+1)
+ // GetValue handles both numerics and symbolics
+ //
+ err = GetValue(inString, &inString, TRUE, 32, &disp, '\0');
+ if (err != GOODINSTRUCTION)
+ return err;
+
+ // get the relative displacement from the updated pc
+ disp = disp - (LONG)((*poffset)+4);
+
+ // divide by four
+ disp = disp >> 2;
+
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = OPCODE(pEntry->opCode) +
+ REG_A(Ra) +
+ BR_DISP(disp);
+
+ return(GOODINSTRUCTION);
+}
+
+
+/*** ParseFltBranch - parse floating point branch instruction
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op Fa,disp
+*
+*************************************************************************/
+ULONG ParseFltBranch(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ ULONG Ra;
+ LONG disp;
+ ULONG err;
+
+ Ra = GetFltReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ //
+ // the user gives an absolute address; we convert
+ // that to a displacement, which is computed as a
+ // difference off of (pc+1)
+ // GetValue handles both numerics and symbolics
+ //
+ err = GetValue(inString, &inString, TRUE, 32, &disp, '\0');
+ if (err != GOODINSTRUCTION)
+ return err;
+
+ // get the relative displacement from the updated pc
+ disp = disp - (LONG)((*poffset)+4);
+
+ // divide by four
+ disp = disp >> 2;
+
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = OPCODE(pEntry->opCode) +
+ REG_A(Ra) +
+ BR_DISP(disp);
+
+ return(GOODINSTRUCTION);
+}
+
+
+/*** ParseIntOp - parse integer operation
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op Ra, Rb, Rc
+* op Ra, #lit, Rc
+*
+*************************************************************************/
+
+ULONG ParseIntOp(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ ULONG Ra, Rb, Rc;
+ ULONG lit;
+ ULONG Format; // Whether there is a literal or 3rd reg
+ ULONG err;
+
+ *instruction = OPCODE(pEntry->opCode) +
+ OP_FNC(pEntry->funcCode);
+
+ Ra = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ if (TestCharacter(inString, &inString, '#')) {
+
+ //
+ // User is giving us a literal value
+
+ err = GetValue(inString, &inString, TRUE, WIDTH_LIT, &lit, ',');
+ if (err != GOODINSTRUCTION)
+ return err;
+ Format = RBV_LITERAL_FORMAT;
+
+ } else {
+
+ //
+ // using a third register value
+
+ Rb = GetIntReg(inString, &inString);
+ Format = RBV_REGISTER_FORMAT;
+ }
+
+ if (!TestCharacter(inString, &inString, ','))
+ return(OPERAND);
+
+ Rc = GetIntReg(inString, &inString);
+
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = *instruction +
+ REG_A(Ra) +
+ RBV_TYPE(Format) +
+ REG_C(Rc);
+
+ if (Format == RBV_REGISTER_FORMAT) {
+ *instruction = *instruction + REG_B(Rb);
+ } else {
+ *instruction = *instruction + LIT(lit);
+ }
+
+ return(GOODINSTRUCTION);
+}
+
+
+/*** ParsePal - parse PAL code instruction
+*
+* Purpose:
+* Given the users input, create the memory instruction.
+*
+* Format:
+* op
+*
+*************************************************************************/
+ULONG ParsePal(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ if (!TestCharacter(inString, &inString, '\0'))
+ return(EXTRACHARS);
+
+ *instruction = (OPCODE(pEntry->opCode) +
+ PAL_FNC(pEntry->funcCode));
+ return (GOODINSTRUCTION);
+}
+
+
+/*** ParseUnknown - return an error message for an unknown opcode
+*
+* Purpose:
+* return an error message for an unknown opcode
+*
+* Format:
+* ???
+*
+*************************************************************************/
+ULONG ParseUnknown(PUCHAR inString,
+ POPTBLENTRY pEntry,
+ PULONG poffset,
+ PULONG instruction)
+{
+ return(BADOPCODE);
+}
+
diff --git a/private/windbg/em/p_alpha/asmfront.c b/private/windbg/em/p_alpha/asmfront.c
new file mode 100644
index 000000000..06b364e15
--- /dev/null
+++ b/private/windbg/em/p_alpha/asmfront.c
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ asmfront.c
+
+Abstract:
+
+ This file contains interfaces between the rest of windbg,
+ and the assem.c file
+
+Author:
+
+ Miche Baker-Harvey
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include <alphaops.h>
+
+#include "optable.h"
+#include "ntasm.h"
+
+int assem(PULONG, PUCHAR, PULONG);
+
+
+/*** Assemble - assemble instruction front end
+*
+* Purpose:
+* To call the assembler stolen from ntsd
+*
+* Input:
+* hpid - handle to the pid
+* htid - handle to the tid
+* lpaddr - address of where to put the assembly output
+* lszInput - the assembly input
+*
+* Output: xosd
+*
+* Side Effect:
+* lpaddr - updates the output to reflect the assembly
+*
+**********************************************/
+
+XOSD
+Assemble ( HPID hpid, HTID htid, LPADDR lpaddr, LSZ lszInput )
+{
+ XOSD xosd;
+ ULONG instruction, retValue;
+ ULONG addr;
+
+ if (MODE_IS_FLAT(lpaddr->mode)) {
+ addr = lpaddr->addr.off;
+ } else {
+ assert(MODE_IS_FLAT(lpaddr->mode));
+ }
+
+ retValue = assem ( &instruction, lszInput, &lpaddr->addr.off);
+
+ if ( retValue == GOODINSTRUCTION ) {
+
+ (void) EMFunc ( emfSetAddr,
+ hpid,
+ htid,
+ adrCurrent,
+ (LONG) lpaddr );
+
+ xosd = EMFunc ( emfWriteBuf,
+ hpid,
+ htid,
+ sizeof (instruction),
+ (LONG) &instruction );
+
+ if ( xosd == xosdNone ) {
+ offAddr ( *lpaddr ) += sizeof (instruction);
+ }
+ return (xosd);
+ }
+
+ switch(retValue) {
+ case GOODINSTRUCTION: xosd = xosdNone; break;
+ case BADOPCODE: xosd = xosdAsmBadOpcode; break;
+ case BADREG: xosd = xosdAsmBadReg; break;
+ case OVERFLOW: xosd = xosdAsmOverFlow; break;
+ case OPERAND: xosd = xosdAsmOperand; break;
+ case EXTRACHARS: xosd = xosdAsmExtraChars; break;
+ case BADSIZE: xosd = xosdAsmSize; break;
+ default: xosd = retValue; break;
+ }
+
+ return xosd;
+}
+
diff --git a/private/windbg/em/p_alpha/d3.c b/private/windbg/em/p_alpha/d3.c
new file mode 100644
index 000000000..dcef829b8
--- /dev/null
+++ b/private/windbg/em/p_alpha/d3.c
@@ -0,0 +1,890 @@
+/*++
+
+Copyright (c) 1992,3 Digital Equipment Corporation
+
+Module Name:
+
+ d3.c
+
+Abstract:
+
+
+Author:
+
+ Miche Baker-Harvey (mbh) Nov 1992
+
+Environment:
+
+ Win32 -- User
+
+Notes:
+
+ Largely taken from NTSD code.
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+#include "alphaops.h"
+#include "optable.h"
+#include "ntdis.h"
+#include "ntasm.h"
+
+typedef LPCH FAR *LPLPCH;
+#define MAXL 20
+
+char lhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+char uhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+char *hexdigit = &uhexdigit[0];
+static int fUpper = TRUE;
+
+static int EAsize [2] = {0}; // size of effective address item
+static long EAaddr [2] = {0}; // offset of effective address
+
+int DumpAddress ( LPADDR, LPCH, int );
+int DumpGeneric ( LSZ, LPCH, int );
+int DumpComment ( LSZ, LPCH, int );
+int DumpEA ( HPID, HTID, LPADDR, LPCH, int );
+
+void OutputEffectiveAddress(ULONG);
+void OutputAddr(LPLPCH , LPADDR, int );
+void OutputHexString(LPLPCH , LPCH, int);
+void OutputHexCode(LPLPCH , LPCH, int);
+ULONG GetIntRegNumber (ULONG);
+
+
+extern BOOLEAN GetMemDword(PULONG, PULONG);
+
+static char *PBuf;
+static int CchBuf;
+extern RD Rgrd[];
+
+ALPHA_INSTRUCTION disinstr;
+
+#define OPRNDCOL 27 // Column for first operand
+#define EACOL 40 // column for effective address
+#define FPTYPECOL 40 // .. for the type of FP instruction
+
+/////////////// from ntdis.c above
+
+void CalcMain (HPID, HTID, DOP, LPADDR, LPB, int, int*, LPCH, int, LPCH, int,
+ LPCH, int, LPCH, int);
+
+/****disasm - disassemble an ALPHA instruction
+*
+* Input:
+* pOffset = pointer to offset to start disassembly
+* fEAout = if set, include EA (effective address)
+*
+* Output:
+* pOffset = pointer to offset of next instruction
+* pchDst = pointer to result string
+*
+***************************************************************************/
+
+#define CCHMAX 256
+static char rgchDisasm [ CCHMAX ];
+
+//
+// MBH - this code is the same for MIPS and i386 and doesn't
+// seem to have any (but one) machine dependencies in it.
+//
+
+XOSD
+disasm ( HPID hpid, HTID htid, LPSDI lpsdi )
+{
+ XOSD xosd = xosdNone;
+ int cchMax = CCHMAX;
+ DOP dop = lpsdi->dop;
+ LPCH lpchOut = rgchDisasm;
+ int ichCur = 0;
+ ADDR addrStart = lpsdi->addr;
+ int cch = 0;
+ int cb;
+ int cbUsed=0;
+ BYTE rgb [ MAXL ];
+
+ char rgchRaw [ MAXL * 2 + 1 ];
+ char rgchOpcode [ 80 ];
+ char rgchOperands [ 80 ];
+ char rgchEA [ 44 ];
+ char rgchComment [ 80 ];
+
+ _fmemset ( rgchRaw, 0, sizeof ( rgchRaw ) );
+ _fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
+ _fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
+ _fmemset ( rgchEA, 0, sizeof ( rgchEA ) );
+ _fmemset ( rgchComment, 0, sizeof ( rgchComment ) );
+
+ lpsdi->ichAddr = -1;
+ lpsdi->ichBytes = -1;
+ lpsdi->ichOpcode = -1;
+ lpsdi->ichOperands = -1;
+ lpsdi->ichComment = -1;
+ lpsdi->ichEA0 = -1;
+ lpsdi->ichEA1 = -1;
+ lpsdi->ichEA2 = -1;
+
+ lpsdi->cbEA0 = 0;
+ lpsdi->cbEA1 = 0;
+ lpsdi->cbEA2 = 0;
+
+ lpsdi->fAssocNext = 0;
+
+ lpsdi->lpch = rgchDisasm;
+
+ // Set up for upper or lower case
+
+ fUpper = ( dop & dopUpper ) == dopUpper;
+ if ( fUpper ) {
+ hexdigit = uhexdigit;
+ }
+ else {
+ hexdigit = lhexdigit;
+ }
+
+ SETADDRMODE ( addrStart );
+
+
+ // Output the address if it is requested
+
+ if ( ( dop & dopAddr ) == dopAddr ) {
+ cch = DumpAddress ( &addrStart, lpchOut, cchMax );
+
+ lpsdi->ichAddr = 0;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) &addrStart );
+ cb = EMFunc ( emfReadBuf, hpid, htid, MAXL, (LONG) (LPV) rgb );
+
+ if ( cb <= 0 ) {
+
+ _fmemcpy ( rgchRaw, " ??", 4 );
+ _fmemcpy ( rgchOpcode, "???", 4 );
+ offAddr ( lpsdi->addr )++;
+ }
+ else {
+
+ CalcMain (
+ hpid,
+ htid,
+ lpsdi->dop,
+ &lpsdi->addr,
+ rgb,
+ cb,
+ &cbUsed,
+ rgchOpcode, sizeof(rgchOpcode),
+ rgchOperands, sizeof(rgchOperands),
+ rgchComment, sizeof(rgchComment),
+ rgchEA, sizeof(rgchEA)
+ );
+
+// MBH - for debugging
+// DbgPrint("CalcMain returns: Opcode %s Operands %s\n",
+// rgchOpcode, rgchOperands);
+// DbgPrint(" Comment %s EA %s\n",
+// rgchComment, rgchEA);
+
+ // NOTENOTE jimsch - cbUsed must be 4
+ cbUsed = 4;
+
+ if ( offAddr(lpsdi->addr) > 0xFFFFFFFF - cbUsed ) {
+ return xosdBadAddress;
+ }
+
+ if ( dop & dopRaw ) {
+ LPCH lpchT = rgchRaw;
+
+ OutputHexCode ( &lpchT, rgb, cbUsed );
+
+ *lpchT = '\0';
+ }
+ }
+
+ if ( ( dop & dopRaw ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchRaw, lpchOut, cchMax );
+
+ lpsdi->ichBytes = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+
+ if ( ( dop & dopOpcode ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchOpcode, lpchOut, cchMax );
+
+ lpsdi->ichOpcode = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchOperands [ 0 ] != '\0' ) ) {
+ cch = DumpGeneric ( rgchOperands, lpchOut, cchMax );
+
+ lpsdi->ichOperands = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchComment [ 0 ] != '\0' ) ) {
+ cch = DumpComment ( rgchComment, lpchOut, cchMax );
+
+ lpsdi->ichComment = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( (dop & dopEA) && (cchMax > 0) ) {
+
+ cch = DumpGeneric ( rgchEA, lpchOut, cchMax );
+//
+/// cch = DumpEA ( hpid, htid, &lpsdi->addrEA0, lpchOut, cchMax );
+//
+ if ( cch > 0 ) {
+ lpsdi->ichEA0 = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+ }
+
+ offAddr ( lpsdi->addr ) += cbUsed;
+
+ return xosd;
+}
+
+void OutputString (PUCHAR pStr)
+{
+ int cb;
+
+ cb = strlen(pStr);
+ if (CchBuf < cb) {
+ cb = CchBuf - 1;
+ }
+
+ strncpy(PBuf, pStr, cb);
+ PBuf[cb] = 0;
+
+ if (fUpper) {
+ _strupr(PBuf);
+ } else {
+ _strlwr(PBuf);
+ }
+ PBuf += cb;
+ CchBuf -= cb;
+ return;
+}
+
+void OutputReg (ULONG regnum)
+{
+ assert(regnum < 32);
+
+ OutputString(Rgrd[regnum].lpsz);
+}
+
+void OutputFReg (ULONG regnum)
+{
+ assert(regnum < 32);
+ OutputString(Rgrd[regnum+36].lpsz);
+}
+
+void OutputHex (ULONG outvalue, ULONG length, BOOLEAN fSigned)
+{
+ UCHAR digit[8];
+ LONG index = 0;
+
+ if (fSigned && (long)outvalue < 0) {
+ if (CchBuf > 1) {
+ *PBuf++ = '-';
+ CchBuf -= 1;
+ }
+ outvalue = (ULONG) (- (LONG) outvalue);
+ }
+
+ if (CchBuf > 2) {
+ *PBuf++ = '0';
+ *PBuf++ = (fUpper) ? 'X' : 'x';
+ CchBuf -= 2;
+ }
+
+ do {
+ digit[index++] = hexdigit[outvalue & 0xf];
+ outvalue >>= 4;
+ }
+ while (outvalue || (!fSigned && index < (LONG)length));
+
+ if (CchBuf > index) {
+ CchBuf -= index;
+ while (--index >= 0) {
+ *PBuf++ = digit[index];
+ }
+ }
+ return;
+}
+
+
+//
+// This is stolen and modified from ntsd\alpha\ntdis.c (disasm())
+// version ntsd.c@v16 (11-14-92)
+//
+void
+CalcMain (
+ HPID hpid,
+ HTID htid,
+ DOP dop,
+ LPADDR lpaddr,
+ LPB rgb,
+ int cbMax,
+ int FAR *lpcbUsed,
+ LPCH rgchOpcode,
+ int cchOpcode,
+ LPCH rgchOperands,
+ int cchOperands,
+ LPCH rgchComment,
+ int cchComment,
+ LPCH rgchEA,
+ int cchEA
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ hpid - Supplies the process handle
+ hthd - Supplies a thread handle
+ dop - Supplies the set of disassembly options
+ lpaddr - Supplies the address to be disassembled
+ rgb - Supplies the buffer to dissassemble into
+ cbMax - Supplies the size of rgb
+ lpcbUsed - Returns the acutal size used
+ rgchOpcode - Supplies location to place opcode
+ rgchOperands - Supplies location to place operands
+ rgchComment - Supplies location to place comment
+ rgchEA - Supplies location to place effective address
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG opcode;
+ POPTBLENTRY pEntry;
+ PULONG poffset = &lpaddr->addr.off;
+
+ *rgchComment = *rgchOperands = 0;
+ //
+ // Never use second EAsize value, nor does MIPS
+ //
+ EAsize[0] = EAsize[1] = 0;
+
+ PBuf = rgchOpcode; // Initialize pointers to buffer that
+ // will receive the disassembly text
+ CchBuf = cchOpcode;
+
+ disinstr = *((PALPHA_INSTRUCTION)rgb);
+
+
+ opcode = disinstr.Memory.Opcode; // Select disassembly procedure from
+
+ pEntry = findOpCodeEntry(opcode); // Get non-func entry for this code
+
+ switch (pEntry->iType) {
+ case ALPHA_UNKNOWN:
+ OutputString(pEntry->pszAlphaName);
+ break;
+
+ case ALPHA_MEMORY:
+ OutputString(pEntry->pszAlphaName);
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputReg(disinstr.Memory.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputHex(disinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
+ *PBuf++ = '(';
+ CchBuf -= 1;
+ OutputReg(disinstr.Memory.Rb);
+ *PBuf++ = ')';
+ CchBuf -= 1;
+ break;
+
+ case ALPHA_FP_MEMORY:
+ OutputString(pEntry->pszAlphaName);
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputFReg(disinstr.Memory.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputHex(disinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
+ *PBuf++ = '(';
+ CchBuf -= 1;
+ OutputReg(disinstr.Memory.Rb);
+ *PBuf++ = ')';
+ CchBuf -= 1;
+ break;
+
+ case ALPHA_MEMSPC:
+ OutputString(findFuncName(pEntry,
+ disinstr.Memory.MemDisp & BITS_MEM_DISP));
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ switch (pEntry->funcCode)
+ {
+ default:
+ break;
+
+ case (MB_FUNC): // MB
+ case (WMB_FUNC): // ???
+ case (MB2_FUNC): // ???
+ case (MB3_FUNC): // ???
+ case (TRAPB_FUNC): // TRAPB
+ case (EXCB_FUNC): // EXCB
+ break;
+
+ case (FETCH_FUNC): // FETCH 0(Rb)
+ case (FETCH_M_FUNC): // FETCH_M 0(Rb)
+ OutputHex(0, 1, FALSE);
+ *PBuf++ = '(';
+ CchBuf -= 1;
+ OutputReg(disinstr.Memory.Rb);
+ *PBuf++ = ')';
+ CchBuf -= 1;
+ break;
+
+ case (RC_FUNC): // RS Ra
+ case (RS_FUNC): // RC Ra
+ case (RPCC_FUNC): // RPCC Ra
+ OutputReg(disinstr.Memory.Ra);
+ break;
+ }
+ break;
+
+ case ALPHA_JUMP:
+ OutputString(findFuncName(pEntry, disinstr.Jump.Function));
+ PBuf = rgchOperands;
+ CchBuf -= 1;
+ OutputReg(disinstr.Jump.Ra);
+ *PBuf++ = ',';
+ *PBuf++ = '(';
+ CchBuf -= 2;
+ OutputReg(disinstr.Jump.Rb);
+ *PBuf++ = ')';
+ *PBuf++ = ',';
+ CchBuf -= 2;
+ OutputHex(disinstr.Jump.Hint, (WIDTH_HINT + 3)/4, TRUE);
+
+ EMFunc (
+ emfGetReg, hpid, htid,
+ disinstr.Jump.Rb + 32,
+ (LONG)(LPV)&EAaddr[0]
+ );
+ EAaddr[0] = EAaddr[0] & (~3);
+ EAsize[0] = 4;
+
+ PBuf = rgchEA;
+ CchBuf = cchEA;
+ OutputEffectiveAddress(EAaddr[0]);
+ break;
+
+ case ALPHA_BRANCH:
+ OutputString(pEntry->pszAlphaName);
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputReg(disinstr.Branch.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ EAaddr[0] = (*poffset + 4) + (disinstr.Branch.BranchDisp * 4);
+
+ OutputEffectiveAddress(EAaddr[0]);
+ PBuf = rgchComment;
+ CchBuf = cchComment;
+ OutputHex(EAaddr[0], 8, FALSE);
+ break;
+
+
+ case ALPHA_FP_BRANCH:
+ OutputString(pEntry->pszAlphaName);
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputFReg(disinstr.Branch.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ EAaddr[0] = (*poffset + 4) + (disinstr.Branch.BranchDisp * 4);
+
+ OutputEffectiveAddress(EAaddr[0]);
+ PBuf = rgchComment;
+ CchBuf = cchComment;
+ OutputHex(EAaddr[0], 8, FALSE);
+
+ break;
+
+ case ALPHA_OPERATE:
+ OutputString(findFuncName(pEntry, disinstr.OpReg.Function));
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputReg(disinstr.OpReg.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ if (disinstr.OpReg.RbvType) {
+ *PBuf++ = '#';
+ CchBuf -= 1;
+ OutputHex(disinstr.OpLit.Literal, (WIDTH_LIT + 3)/4, TRUE);
+ } else
+ OutputReg(disinstr.OpReg.Rb);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputReg(disinstr.OpReg.Rc);
+ break;
+
+ case ALPHA_FP_OPERATE:
+ {
+ ULONG Function;
+ ULONG Flags;
+
+ Flags = disinstr.FpOp.Function & MSK_FP_FLAGS;
+ Function = disinstr.FpOp.Function & MSK_FP_OP;
+
+ OutputString(findFuncName(pEntry, Function));
+
+ if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP) ) {
+
+ OutputString(findFlagName(Flags, Function));
+ }
+
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputFReg(disinstr.FpOp.Fa);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputFReg(disinstr.FpOp.Fb);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputFReg(disinstr.FpOp.Fc);
+
+ break;
+ }
+
+ case ALPHA_FP_CONVERT:
+//
+// This is a clone of the ALPHA_FP_OPERATE branch, except that
+// we don't display Ra (which is always F31 and is implicit).
+ {
+ ULONG Function;
+ ULONG Flags;
+
+ Flags = disinstr.FpOp.Function & MSK_FP_FLAGS;
+ Function = disinstr.FpOp.Function & MSK_FP_OP;
+
+ OutputString(findFuncName(pEntry, Function));
+
+ if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP) )
+ {
+ OutputString(findFlagName(Flags, Function));
+ }
+
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputFReg(disinstr.FpOp.Fb);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputFReg(disinstr.FpOp.Fc);
+ break;
+ }
+
+ case ALPHA_CALLPAL:
+ {
+ char* callPalCode = findFuncName(pEntry, disinstr.Pal.Function);
+ if (!strcmp (callPalCode, "???"))
+ {
+ OutputHex ((ULONG)disinstr.Pal.Function, 8, FALSE);
+ }
+ else
+ {
+ OutputString (callPalCode);
+ }
+ }
+ break;
+
+ case ALPHA_EV4_PR:
+ if ((disinstr.Long & MSK_EV4_PR) == 0)
+ OutputString("NOP");
+ else {
+ OutputString(pEntry->pszAlphaName);
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputReg(disinstr.EV4_PR.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ if(disinstr.EV4_PR.Ra != disinstr.EV4_PR.Rb) {
+ OutputReg(disinstr.EV4_PR.Rb);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ };
+ OutputString(findFuncName(pEntry, (disinstr.Long & MSK_EV4_PR)));
+ };
+ break;
+ case ALPHA_EV4_MEM:
+ OutputString(pEntry->pszAlphaName);
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+ OutputReg(disinstr.EV4_MEM.Ra);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ OutputReg(disinstr.EV4_MEM.Rb);
+ break;
+
+ case ALPHA_EV4_REI:
+ OutputString(pEntry->pszAlphaName);
+ break;
+
+ default:
+ OutputString("Invalid type");
+ break;
+ };
+
+ return;
+}
+
+
+/*** OutputEffectiveAddress - Print EA symbolically
+*
+* Purpose:
+* Given the effective address (for a branch, jump or
+* memory instruction, print it symbolically, if
+* symbols are available.
+*
+* Input:
+* offset - computed by the caller as
+* for jumps, the value in Rb
+* for branches, func(PC, displacement)
+* for memory, func(PC, displacement)
+*
+* Returns:
+* None
+*
+*************************************************************************/
+void OutputEffectiveAddress(ULONG offset)
+{
+ UCHAR chAddrBuffer[60];
+ LPCH lpchSymbol;
+ ADDR addrT={0}, addr={0};
+ int cb;
+ ODR odr;
+
+ odr.lszName = chAddrBuffer;
+
+ addr.addr.off = addrT.addr.off = offset;
+ MODE_IS_FLAT(addr.mode) = TRUE;
+ MODE_IS_FLAT(addrT.mode) = TRUE;
+
+ lpchSymbol = SHGetSymbol (&addrT, &addr, sopNone, &odr);
+
+ if (chAddrBuffer[0]) {
+ cb = strlen(chAddrBuffer);
+ if (cb > CchBuf) {
+ cb = CchBuf - 1;
+ }
+ strncpy(PBuf, chAddrBuffer, cb);
+ PBuf += cb;
+ if (odr.dwDeltaOff) {
+ if (CchBuf > 1) {
+ *PBuf++ = '+';
+ CchBuf -= 1;
+ }
+ OutputHex(odr.dwDeltaOff, 8, TRUE);
+ }
+ } else {
+ OutputHex(offset, 8, FALSE);
+ }
+}
+
+
+int DumpAddress ( LPADDR lpaddr, LPCH lpch, int cchMax ) {
+ LPCH lpchT = lpch;
+
+ Unreferenced(cchMax);
+
+ OutputAddr ( &lpch, lpaddr, (ADDR_IS_FLAT(*lpaddr) + 1) * 2 );
+ *lpch = '\0';
+ return lpch - lpchT + 1;
+}
+
+int DumpGeneric ( LSZ lsz, LPCH lpch, int cchMax )
+{
+ int cb;
+
+ cb = strlen(lsz);
+ if (cb > cchMax-1) {
+ cb = cchMax -1;
+ }
+ strncpy(lpch, lsz, cb);
+ lpch[cb] = 0;
+ return cb + 1;
+}
+
+int DumpComment ( LSZ lsz, LPCH lpch, int cchMax ) {
+ *(lpch) = ';';
+ return DumpGeneric ( lsz, lpch + 1, cchMax - 1 ) + 1;
+}
+
+/*
+** MBH bugbug - should we eliminate this routine?
+** or do we want to print out something like this?
+** We don't use this routine.
+** Being used in MIPS to print *EA, where EA value is set up in CalcMain.
+** We call OutputEffectiveAddress, instead, which prints out the symbol
+** associated with an effective address
+*/
+
+int DumpEA ( HPID hpid, HTID htid, LPADDR lpaddr, LPCH lpch, int cchMax ) {
+ LPCH lpchT = lpch;
+ BYTE rgb [ MAXL ];
+ int indx;
+ int cb;
+
+ Unreferenced(cchMax);
+
+ for ( indx = 0; indx < 2; indx++ ) {
+
+ if ( EAsize [ indx ] ) {
+ ADDR addr = {0};
+
+ OutputHexString ( &lpchT, (LPB) &EAaddr [ indx ], 4 );
+
+ *lpchT++ = '=';
+
+ offAddr ( addr ) = (UOFFSET) EAaddr [ indx ];
+ segAddr ( addr ) = (SEGMENT) 0;
+
+ *lpaddr = addr;
+
+ EMFunc (
+ emfSetAddr,
+ hpid,
+ htid,
+ adrCurrent,
+ (LONG) (LPADDR) &addr
+ );
+
+ cb = EMFunc (
+ emfReadBuf,
+ hpid,
+ htid,
+ EAsize [ indx ],
+ (LONG) (LPV) rgb
+ );
+
+ if ( cb == EAsize [ indx ] ) {
+ OutputHexString ( &lpchT, rgb, EAsize [ indx ] );
+ }
+ else {
+ while ( EAsize [ indx ]-- ) {
+ *lpchT++ = '?';
+ *lpchT++ = '?';
+ }
+ }
+ *lpchT++ = '\0';
+ }
+ }
+
+ return lpchT - lpch;
+}
+
+
+/*** OutputHexString - output hex string
+*
+* Purpose:
+* Output the value pointed by *lplpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* *pchValue - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+* *lplpchMemBuf - pointer update to next memory byte
+*
+*************************************************************************/
+
+void OutputHexString (LPLPCH lplpchBuf, PCH pchValue, int length)
+{
+ unsigned char chMem;
+
+ pchValue += length;
+ while ( length-- ) {
+ chMem = *--pchValue;
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
+
+
+/*** OutputAddr - output address package
+*
+* Purpose:
+* Output the address pointed to by lpaddr.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpaddr - Standard address package.
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void OutputAddr ( LPLPCH lplpchBuf, LPADDR lpaddr, int alen )
+{
+ ADDR addr = *lpaddr;
+
+ *(*lplpchBuf)++ = '0';
+ *(*lplpchBuf)++ = (fUpper) ? 'X' : 'x';
+ OutputHexString ( lplpchBuf, (LPCH) &offAddr ( addr ), alen );
+}
+
+
+/*** OutputHexCode - output hex code
+*
+* Purpose:
+* Output the code pointed by lpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed. This differs from OutputHexString
+* in that bytes are printed from low to high addresses.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpchMemBuf - - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void OutputHexCode (LPLPCH lplpchBuf, LPCH lpchMemBuf, int length)
+{
+ unsigned char chMem;
+
+ while (length--) {
+ chMem = lpchMemBuf[length];
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
diff --git a/private/windbg/em/p_alpha/em.rc b/private/windbg/em/p_alpha/em.rc
new file mode 100644
index 000000000..1153a525a
--- /dev/null
+++ b/private/windbg/em/p_alpha/em.rc
@@ -0,0 +1 @@
+#include "..\em.rc"
diff --git a/private/windbg/em/p_alpha/emalp.def b/private/windbg/em/p_alpha/emalp.def
new file mode 100644
index 000000000..5372c8973
--- /dev/null
+++ b/private/windbg/em/p_alpha/emalp.def
@@ -0,0 +1,5 @@
+LIBRARY emalp initinstance
+EXPORTS
+ DBGVersionCheck PRIVATE
+ EMFunc PRIVATE
+ findTypeFromOpcode
diff --git a/private/windbg/em/p_alpha/emdp.c b/private/windbg/em/p_alpha/emdp.c
new file mode 100644
index 000000000..96568b2ed
--- /dev/null
+++ b/private/windbg/em/p_alpha/emdp.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp.c"
diff --git a/private/windbg/em/p_alpha/emdp2.c b/private/windbg/em/p_alpha/emdp2.c
new file mode 100644
index 000000000..5e0024775
--- /dev/null
+++ b/private/windbg/em/p_alpha/emdp2.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp2.c"
diff --git a/private/windbg/em/p_alpha/emdp3.c b/private/windbg/em/p_alpha/emdp3.c
new file mode 100644
index 000000000..57d71318d
--- /dev/null
+++ b/private/windbg/em/p_alpha/emdp3.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp3.c"
diff --git a/private/windbg/em/p_alpha/emdpdev.c b/private/windbg/em/p_alpha/emdpdev.c
new file mode 100644
index 000000000..2236fdd37
--- /dev/null
+++ b/private/windbg/em/p_alpha/emdpdev.c
@@ -0,0 +1,1254 @@
+/**** EMDPDEV.C - Debugger end Execution Model (ALPHA dependent code) **
+ * *
+ * *
+ * Copyright <C> 1993, Digital Equipment Corporation *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: January 1, 1993, Miche Baker-Harvey (mbh)
+ * *
+ * Revision History: *
+ * MBH - this file is a copy of the mips version, with DoSetReg, *
+ * DoGetReg replaced with the ALPHA equivalents, and the *
+ * #ifdef 0 code has been removed. *
+ * Taken from MIPS version dated 08-DEC-92. *
+ * ReTaken from MIPS version in nt353, *
+ * which contained no #ifdef 0 code *
+ * *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#include "strings.h"
+
+#include "llhpt.h"
+#include "mhhpt.h"
+#include "lbhpt.h"
+
+#include "osdem.h"
+#include "emdm.h"
+#include "emdata.h"
+#include "emproto.h"
+
+#include "osassert.h"
+#include "strings.h"
+
+#ifndef SMARTALIAS
+void PurgeCache ( void );
+#endif
+
+#define CEXM_MDL_native 0x20
+
+CONTEXT ContextSave;
+
+/*
+** This is the description of all registers and flags containned on the
+** alpha machine
+*/
+
+extern RD Rgrd[];
+
+extern struct {
+ FD fd;
+ USHORT iShift;
+} Rgfd[];
+
+#define SIZEOF_STACK_OFFSET sizeof(LONG)
+
+BOOL NEAR PASCAL IsStackSetup(
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddrProc
+) {
+ Unreferenced(hpid);
+ Unreferenced(htid);
+ Unreferenced(lpaddrProc);
+ return TRUE;
+}
+
+
+XOSD
+GetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ This function will get return a specific type of address.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to retrive the address from
+ htid - Supplies the handle to the thread to retrieve the address from
+ adr - Supplies the type of address to be retrieved
+ lpaddr - Returns the requested address
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+ XOSD xosd = xosdNone;
+ HEMI hemi = emiAddr(*lpaddr);
+ HMDI hmdi;
+ LPMDI lpmdi;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != hpidNull );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != hthdNull ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ _fmemset ( lpaddr, 0, sizeof ( ADDR ) );
+
+ switch ( adr ) {
+
+ case adrPC:
+ if ( lpthd && !(lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrData:
+ if ( lpthd && !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+
+ case adrCurrent:
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ *lpaddr = lpthd->addrCurrent;
+ } else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ *lpaddr = lpprc->addrCurrent;
+
+ LLUnlock ( hprc );
+ }
+ break;
+
+ case adrPC:
+ AddrInit(lpaddr, 0, 0,
+ (UOFFSET) lpthd->regs.Fir, lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrData:
+ AddrInit(lpaddr, 0, 0, 0,
+ lpthd->fFlat, lpthd->fOff32, FALSE, lpthd->fReal);
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrTlsBase:
+ /*
+ * If -1 then we have not gotten a value from the DM yet.
+ */
+
+ assert(hemi != 0);
+
+ if (hemi == 0) {
+ return xosdBadAddress;
+ }
+
+ if (hemi != emiAddr(lpthd->addrTls)) {
+ hmdi = LLFind( LlmdiFromHprc( hprc ), wNull, (LPB) &hemi, emdiEMI);
+ assert(hmdi != 0);
+
+ if (hmdi == 0) {
+ return xosdBadAddress;
+ }
+
+ lpmdi = LLLock( hmdi );
+
+ SendRequestX( dmfQueryTlsBase, hpid, htid, sizeof(OFFSET),
+ &lpmdi->lpBaseOfDll);
+
+ lpthd->addrTls = *((LPADDR) LpDmMsg->rgb);
+ emiAddr(lpthd->addrTls) = hemi;
+ LLUnlock( hmdi );
+
+ }
+
+ *lpaddr = lpthd->addrTls;
+ emiAddr(*lpaddr) = 0;
+ break;
+
+ default:
+
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != hthdNull ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosd;
+} /* GetAddr() */
+
+
+XOSD
+SetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != hpidNull );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != hthdNull ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ switch ( adr ) {
+ case adrPC:
+ if ( lpthd && !(lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrData:
+ if ( lpthd && !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+
+ case adrCurrent:
+
+ if ( lpaddr->emi == hmemNull ) {
+ SetEmi ( hpid, lpaddr );
+ }
+
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ lpthd->addrCurrent = *lpaddr;
+ }
+ else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ lpprc->addrCurrent = *lpaddr;
+
+ LLUnlock ( hprc );
+ }
+ break;
+
+ case adrPC:
+ lpthd->regs.Fir = (LONG)offAddr ( *lpaddr );
+ lpthd->drt |= drtCntrlDirty;
+ break;
+
+ case adrData:
+ case adrTlsBase:
+ default:
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != hthdNull ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosdNone;
+} /* SetAddr() */
+
+
+XOSD SetAddrFromCSIP ( HTHD hthd ) {
+
+ ADDR addr = {0};
+ LPTHD lpthd;
+
+ assert ( hthd != hthdNull && hthd != hthdInvalid );
+
+ lpthd = LLLock ( hthd );
+
+ segAddr ( addr ) = 0;
+ offAddr ( addr ) = (UOFFSET) lpthd->regs.Fir;
+ emiAddr ( addr ) = 0;
+ SETADDRMODE ( addr );
+
+ lpthd->addrCurrent = addr;
+
+ LLUnlock ( hthd );
+
+ return xosdNone;
+}
+
+
+CMP CmpAddr ( LPADDR lpaddr1, LPADDR lpaddr2 ) {
+// NOTENOTE -- segmented addresses
+ if ( offAddr ( *lpaddr1 ) < offAddr ( *lpaddr2 ) )
+ return ( fCmpLT );
+ else if ( offAddr ( *lpaddr1 ) > offAddr ( *lpaddr2 ) )
+ return ( fCmpGT );
+ else
+ return ( fCmpEQ );
+}
+
+
+//
+// For DoGetReg, we push the full 64-bit value.
+// The correct value is still picked up in the longword
+// by the caller.
+// This is written to be executable on ALPHA, MIPS and i386
+//
+
+LPV
+DoGetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to extract the value of a single register from
+ the debuggee.
+
+Arguments:
+
+ lpregs - Supplies pointer to the register set for the debuggee
+
+ ireg - Supplies the index of the register to be read
+
+ lpvRegValue - Supplies the buffer to place the register value in
+
+Return Value:
+
+ return-value - lpvRegValue + size of register on success and NULL on
+ failure
+--*/
+
+{
+
+ PDWORDLONG RegArray;
+ PDWORDLONG pdwl = (PDWORDLONG)lpvRegValue;
+ PDWORD pdw = (PDWORD)lpvRegValue;
+
+ switch ( ireg ) {
+
+ case CV_ALPHA_IntV0 :
+ case CV_ALPHA_IntT0 :
+ case CV_ALPHA_IntT1 :
+ case CV_ALPHA_IntT2 :
+ case CV_ALPHA_IntT3 :
+ case CV_ALPHA_IntT4 :
+ case CV_ALPHA_IntT5 :
+ case CV_ALPHA_IntT6 :
+ case CV_ALPHA_IntT7 :
+ case CV_ALPHA_IntS0 :
+ case CV_ALPHA_IntS1 :
+ case CV_ALPHA_IntS2 :
+ case CV_ALPHA_IntS3 :
+ case CV_ALPHA_IntS4 :
+ case CV_ALPHA_IntS5 :
+ case CV_ALPHA_IntFP :
+ case CV_ALPHA_IntA0 :
+ case CV_ALPHA_IntA1 :
+ case CV_ALPHA_IntA2 :
+ case CV_ALPHA_IntA3 :
+ case CV_ALPHA_IntA4 :
+ case CV_ALPHA_IntA5 :
+ case CV_ALPHA_IntT8 :
+ case CV_ALPHA_IntT9 :
+ case CV_ALPHA_IntT10 :
+ case CV_ALPHA_IntT11 :
+ case CV_ALPHA_IntRA :
+ case CV_ALPHA_IntT12 :
+ case CV_ALPHA_IntAT :
+ case CV_ALPHA_IntGP :
+ case CV_ALPHA_IntSP :
+ case CV_ALPHA_IntZERO :
+
+ RegArray = &lpregs->IntV0;
+ *pdwl = RegArray[ireg - CV_ALPHA_IntV0];
+ lpvRegValue = (LPVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_Fir:
+
+ *pdwl = lpregs->Fir;
+ lpvRegValue = (LPVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_Psr:
+
+ *pdw = lpregs->Psr;
+ lpvRegValue = (LPVOID)(pdw + 1);
+ break;
+
+ case CV_ALPHA_Fpcr:
+ *pdwl = lpregs->Fpcr;
+ lpvRegValue = (LPVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_SoftFpcr:
+ *pdwl = lpregs->SoftFpcr;
+ lpvRegValue = (LPVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_FltF0 :
+ case CV_ALPHA_FltF1 :
+ case CV_ALPHA_FltF2 :
+ case CV_ALPHA_FltF3 :
+ case CV_ALPHA_FltF4 :
+ case CV_ALPHA_FltF5 :
+ case CV_ALPHA_FltF6 :
+ case CV_ALPHA_FltF7 :
+ case CV_ALPHA_FltF8 :
+ case CV_ALPHA_FltF9 :
+ case CV_ALPHA_FltF10 :
+ case CV_ALPHA_FltF11 :
+ case CV_ALPHA_FltF12 :
+ case CV_ALPHA_FltF13 :
+ case CV_ALPHA_FltF14 :
+ case CV_ALPHA_FltF15 :
+ case CV_ALPHA_FltF16 :
+ case CV_ALPHA_FltF17 :
+ case CV_ALPHA_FltF18 :
+ case CV_ALPHA_FltF19 :
+ case CV_ALPHA_FltF20 :
+ case CV_ALPHA_FltF21 :
+ case CV_ALPHA_FltF22 :
+ case CV_ALPHA_FltF23 :
+ case CV_ALPHA_FltF24 :
+ case CV_ALPHA_FltF25 :
+ case CV_ALPHA_FltF26 :
+ case CV_ALPHA_FltF27 :
+ case CV_ALPHA_FltF28 :
+ case CV_ALPHA_FltF29 :
+ case CV_ALPHA_FltF30 :
+ case CV_ALPHA_FltF31 :
+
+ RegArray = &lpregs->FltF0;
+ *pdwl = RegArray [ireg - CV_ALPHA_FltF0];
+ lpvRegValue = (LPVOID)(pdwl + 1);
+ break;
+
+ default:
+ assert(FALSE);
+ return 0;
+ }
+
+ return lpvRegValue;
+
+}
+
+
+LPV
+DoSetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to set a specific register in a threads
+ context
+
+Arguments:
+
+ lpregs - Supplies pointer to register context for thread
+ ireg - Supplies the index of the register to be modified
+ lpvRegValue - Supplies the buffer containning the new data
+
+Return Value:
+
+ return-value - the pointer the the next location where a register
+ value could be.
+
+--*/
+
+{
+
+ PDWORDLONG RegArray;
+ PDWORDLONG pdwl = (PDWORDLONG)lpvRegValue;
+ PDWORD pdw = (PDWORD)lpvRegValue;
+
+ switch ( ireg ) {
+ case CV_ALPHA_IntZERO :
+ return NULL;
+
+ case CV_ALPHA_IntV0 :
+ case CV_ALPHA_IntT0 :
+ case CV_ALPHA_IntT1 :
+ case CV_ALPHA_IntT2 :
+ case CV_ALPHA_IntT3 :
+ case CV_ALPHA_IntT4 :
+ case CV_ALPHA_IntT5 :
+ case CV_ALPHA_IntT6 :
+ case CV_ALPHA_IntT7 :
+ case CV_ALPHA_IntS0 :
+ case CV_ALPHA_IntS1 :
+ case CV_ALPHA_IntS2 :
+ case CV_ALPHA_IntS3 :
+ case CV_ALPHA_IntS4 :
+ case CV_ALPHA_IntS5 :
+ case CV_ALPHA_IntFP :
+ case CV_ALPHA_IntA0 :
+ case CV_ALPHA_IntA1 :
+ case CV_ALPHA_IntA2 :
+ case CV_ALPHA_IntA3 :
+ case CV_ALPHA_IntA4 :
+ case CV_ALPHA_IntA5 :
+ case CV_ALPHA_IntT8 :
+ case CV_ALPHA_IntT9 :
+ case CV_ALPHA_IntT10 :
+ case CV_ALPHA_IntT11 :
+ case CV_ALPHA_IntRA :
+ case CV_ALPHA_IntT12 :
+ case CV_ALPHA_IntAT :
+ case CV_ALPHA_IntGP :
+ case CV_ALPHA_IntSP :
+
+ RegArray = &lpregs->IntV0;
+ RegArray[ireg - CV_ALPHA_IntV0] = *pdwl;
+ lpvRegValue = (PVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_Fir:
+ lpregs->Fir = *pdwl;
+ lpvRegValue = (PVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_Psr:
+ lpregs->Psr = *pdw;
+ lpvRegValue = (PVOID)(pdw + 1);
+ break;
+
+ case CV_ALPHA_Fpcr:
+ lpregs->Fpcr = *pdwl;
+ lpvRegValue = (PVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_SoftFpcr:
+ lpregs->SoftFpcr = *pdwl;
+ lpvRegValue = (PVOID)(pdwl + 1);
+ break;
+
+ case CV_ALPHA_FltF0 :
+ case CV_ALPHA_FltF1 :
+ case CV_ALPHA_FltF2 :
+ case CV_ALPHA_FltF3 :
+ case CV_ALPHA_FltF4 :
+ case CV_ALPHA_FltF5 :
+ case CV_ALPHA_FltF6 :
+ case CV_ALPHA_FltF7 :
+ case CV_ALPHA_FltF8 :
+ case CV_ALPHA_FltF9 :
+ case CV_ALPHA_FltF10 :
+ case CV_ALPHA_FltF11 :
+ case CV_ALPHA_FltF12 :
+ case CV_ALPHA_FltF13 :
+ case CV_ALPHA_FltF14 :
+ case CV_ALPHA_FltF15 :
+ case CV_ALPHA_FltF16 :
+ case CV_ALPHA_FltF17 :
+ case CV_ALPHA_FltF18 :
+ case CV_ALPHA_FltF19 :
+ case CV_ALPHA_FltF20 :
+ case CV_ALPHA_FltF21 :
+ case CV_ALPHA_FltF22 :
+ case CV_ALPHA_FltF23 :
+ case CV_ALPHA_FltF24 :
+ case CV_ALPHA_FltF25 :
+ case CV_ALPHA_FltF26 :
+ case CV_ALPHA_FltF27 :
+ case CV_ALPHA_FltF28 :
+ case CV_ALPHA_FltF29 :
+ case CV_ALPHA_FltF30 :
+ case CV_ALPHA_FltF31 :
+
+
+ //
+ // Transfer the data from the caller.
+ // We can do this to DOUBLES because we are doing
+ // memory-memory copies.
+ //
+
+ RegArray = &lpregs->FltF0;
+ RegArray [ireg - CV_ALPHA_FltF0] = *pdwl;
+ lpvRegValue = (PVOID)(pdwl + 1);
+ break;
+
+ default:
+ assert(FALSE);
+ return NULL;
+ }
+
+ return lpvRegValue;
+
+}
+
+
+LPV
+DoSetFrameReg(
+ HPID hpid,
+ HTID htid,
+ LPTHD lpthd,
+ PKNONVOLATILE_CONTEXT_POINTERS contextPtrs,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+/*++
+
+Routine Description:
+
+ Sets a register in an old frame; uses context pointers to do it,
+ which is why we can't use DoSetReg:
+ there's another layer of indirection
+
+Arguments:
+
+ lpregs - Supplies pointer to pointers to the frame context
+ ireg - Supplies the index of the register to be modified
+ lpvRegValue - Supplies the buffer containning the new data
+
+Return Value:
+
+ return-value - the pointer the the next location where a register
+ value could be.
+
+--*/
+
+{
+
+ ADDR address;
+ LPADDR lpaddr = &address;
+ XOSD xosdreturn;
+
+ switch ( ireg ) {
+
+ case CV_ALPHA_IntV0 :
+ case CV_ALPHA_IntT0 :
+ case CV_ALPHA_IntT1 :
+ case CV_ALPHA_IntT2 :
+ case CV_ALPHA_IntT3 :
+ case CV_ALPHA_IntT4 :
+ case CV_ALPHA_IntT5 :
+ case CV_ALPHA_IntT6 :
+ case CV_ALPHA_IntT7 :
+ case CV_ALPHA_IntS0 :
+ case CV_ALPHA_IntS1 :
+ case CV_ALPHA_IntS2 :
+ case CV_ALPHA_IntS3 :
+ case CV_ALPHA_IntS4 :
+ case CV_ALPHA_IntS5 :
+ case CV_ALPHA_IntFP :
+ case CV_ALPHA_IntA0 :
+ case CV_ALPHA_IntA1 :
+ case CV_ALPHA_IntA2 :
+ case CV_ALPHA_IntA3 :
+ case CV_ALPHA_IntA4 :
+ case CV_ALPHA_IntA5 :
+ case CV_ALPHA_IntT8 :
+ case CV_ALPHA_IntT9 :
+ case CV_ALPHA_IntT10 :
+ case CV_ALPHA_IntT11 :
+ case CV_ALPHA_IntRA :
+ case CV_ALPHA_IntT12 :
+ case CV_ALPHA_IntAT :
+ case CV_ALPHA_IntGP :
+ case CV_ALPHA_IntSP :
+ case CV_ALPHA_IntZERO :
+
+ //
+ // Setup the ADDR structure for where this register was saved
+ // on the stack for this frame.
+ //
+
+ AddrInit(lpaddr, 0, 0,
+ (UOFFSET) contextPtrs->IntegerContext[ireg - CV_ALPHA_IntV0],
+ lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+
+ xosdreturn = SetAddr(hpid, htid, adrCurrent, &address);
+ if ( xosdreturn == xosdNone ) {
+ xosdreturn = WriteBuffer(hpid, htid, 8, lpvRegValue);
+ }
+
+ break;
+
+
+ case CV_ALPHA_FltF0 :
+ case CV_ALPHA_FltF1 :
+ case CV_ALPHA_FltF2 :
+ case CV_ALPHA_FltF3 :
+ case CV_ALPHA_FltF4 :
+ case CV_ALPHA_FltF5 :
+ case CV_ALPHA_FltF6 :
+ case CV_ALPHA_FltF7 :
+ case CV_ALPHA_FltF8 :
+ case CV_ALPHA_FltF9 :
+ case CV_ALPHA_FltF10 :
+ case CV_ALPHA_FltF11 :
+ case CV_ALPHA_FltF12 :
+ case CV_ALPHA_FltF13 :
+ case CV_ALPHA_FltF14 :
+ case CV_ALPHA_FltF15 :
+ case CV_ALPHA_FltF16 :
+ case CV_ALPHA_FltF17 :
+ case CV_ALPHA_FltF18 :
+ case CV_ALPHA_FltF19 :
+ case CV_ALPHA_FltF20 :
+ case CV_ALPHA_FltF21 :
+ case CV_ALPHA_FltF22 :
+ case CV_ALPHA_FltF23 :
+ case CV_ALPHA_FltF24 :
+ case CV_ALPHA_FltF25 :
+ case CV_ALPHA_FltF26 :
+ case CV_ALPHA_FltF27 :
+ case CV_ALPHA_FltF28 :
+ case CV_ALPHA_FltF29 :
+ case CV_ALPHA_FltF30 :
+ case CV_ALPHA_FltF31 :
+
+ //
+ // Setup the ADDR structure for where this register was saved
+ // on the stack for this frame.
+ //
+
+ AddrInit(lpaddr, 0, 0,
+ (UOFFSET) contextPtrs->FloatingContext[ireg - CV_ALPHA_FltF0],
+ lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+
+ xosdreturn = SetAddr(hpid, htid, adrCurrent, &address);
+ if ( xosdreturn == xosdNone ) {
+ xosdreturn = WriteBuffer(hpid, htid, 8, lpvRegValue);
+ }
+
+ break;
+
+
+ default:
+
+ return NULL;
+ }
+
+ if ( xosdreturn == xosdNone) {
+ return lpvRegValue;
+ } else {
+ return NULL;
+ }
+}
+
+XOSD
+GetFlagValue (
+ HPID hpid,
+ HTID htid,
+ DWORD iFlag,
+ LPV lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPCONTEXT lpregs;
+ DWORDLONG value;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ hthd = HthdFromHtid(hprc, htid);
+
+ assert ( hthd != hthdNull );
+ lpthd = LLLock ( hthd );
+
+ lpregs = &lpthd->regs;
+
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &value ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidRegister;
+ }
+
+ value = (value >> Rgfd[iFlag].iShift) & ((1 << Rgfd[iFlag].fd.cbits) - 1);
+ *( (LPL) lpvRegValue) = (DWORD)value;
+ LLUnlock(hthd);
+ return xosdNone;
+}
+
+
+
+XOSD
+StackWalkSetup(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to setup the StackWalk Structure.
+ This routine will defer the processing to the dm
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk
+ hthd - Supplies handle to thread to stack walk
+ lpstkframe - Supplies pointer the stack walk structure
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == hthdNull) {
+ return xosdInvalidThread;
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (lpthd->drt & (drtCntrlDirty|drtAllDirty)) {
+ SendRequestX(dmfWriteReg, hpid, htid, sizeof(CONTEXT), &lpthd->regs);
+ lpthd->drt &= ~(drtCntrlDirty|drtAllDirty);
+ }
+
+ UpdateRegisters( hprc, hthd );
+
+ ContextSave = lpthd->regs;
+
+ if (StackWalk( IMAGE_FILE_MACHINE_ALPHA,
+ hpid,
+ htid,
+ lpstkframe,
+ &ContextSave,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ NULL,
+ NULL
+ )) {
+
+ LLUnlock( hthd );
+ return xosdNone;
+
+ }
+
+ LLUnlock( hthd );
+
+ return xosdEndOfStack;
+} /* StackWalkSetup() */
+
+
+XOSD
+StackWalkNext(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to move up a level in the call stack.
+ We defer down to the DM to do this.
+
+Arguments:
+
+ hpid - Supplies process handle to stack walk
+ htid - Supplies thread handle to stack walk
+ lpstkframe - Supplies pointer to stack walk data
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+
+
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == hthdNull) {
+ return xosdInvalidThread;
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (StackWalk( IMAGE_FILE_MACHINE_ALPHA,
+ hpid,
+ htid,
+ lpstkframe,
+ &ContextSave,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ NULL,
+ NULL
+ )) {
+
+ LLUnlock( hthd );
+ return xosdNone;
+
+ }
+
+ LLUnlock( hthd );
+
+ return xosdEndOfStack;
+} /* StackWalkNext() */
+
+
+PIMAGE_RUNTIME_FUNCTION_ENTRY
+LookupFunctionEntry (
+ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable,
+ DWORD NumberOfFunctions,
+ DWORD ControlPc
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the currently active function tables for an entry
+ that corresponds to the specified PC value.
+
+Arguments:
+
+ ControlPc - Supplies the address of an instruction within the specified
+ function.
+
+Return Value:
+
+ If there is no entry in the function table for the specified PC, then
+ NULL is returned. Otherwise, the address of the function table entry
+ that corresponds to the specified PC is returned.
+
+--*/
+
+{
+
+ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
+ LONG High;
+ LONG Low;
+ LONG Middle;
+
+ //
+ // Initialize search indicies.
+ //
+
+ Low = 0;
+ High = NumberOfFunctions - 1;
+
+ //
+ // Perform binary search on the function table for a function table
+ // entry that subsumes the specified PC.
+ //
+
+ while (High >= Low) {
+
+ //
+ // Compute next probe index and test entry. If the specified PC
+ // is greater than of equal to the beginning address and less
+ // than the ending address of the function table entry, then
+ // return the address of the function table entry. Otherwise,
+ // continue the search.
+ //
+
+ Middle = (Low + High) >> 1;
+ FunctionEntry = &FunctionTable[Middle];
+ if (ControlPc < FunctionEntry->BeginAddress) {
+ High = Middle - 1;
+
+ } else if (ControlPc >= FunctionEntry->EndAddress) {
+ Low = Middle + 1;
+
+ } else {
+ return FunctionEntry;
+ }
+ }
+
+ //
+ // A function table entry for the specified PC was not found.
+ //
+
+ return NULL;
+}
+
+
+LPVOID
+SwFunctionTableAccess(
+ HPID hpid,
+ DWORD AddrBase
+ )
+{
+ HLLI hlli = 0;
+ HMDI hmdi = 0;
+ LPMDI lpmdi = 0;
+ PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
+
+
+ hmdi = SwGetMdi( hpid, AddrBase );
+ if (!hmdi) {
+ return NULL;
+ }
+
+ lpmdi = LLLock( hmdi );
+ if (lpmdi) {
+
+ rf = LookupFunctionEntry( lpmdi->lpDebug->lpRtf,
+ lpmdi->lpDebug->cRtf,
+ AddrBase
+ );
+
+ LLUnlock( hmdi );
+ return (LPVOID)rf;
+ }
+ return NULL;
+}
+
+BOOL
+SwReadMemory(
+ HPID hpid,
+ LPCVOID lpBaseAddress,
+ LPVOID lpBuffer,
+ DWORD nSize,
+ LPDWORD lpNumberOfBytesRead
+ )
+{
+ ADDR addr;
+ DWORD cb;
+ XOSD xosd;
+
+ addr.addr.off = (OFFSET)lpBaseAddress;
+ addr.addr.seg = 0;
+ addr.emi = 0;
+ addr.mode.fFlat = TRUE;
+ addr.mode.fOff32 = FALSE;
+ addr.mode.fIsLI = FALSE;
+ addr.mode.fReal = FALSE;
+
+ xosd = ReadBuffer( hpid, NULL, &addr, nSize, lpBuffer, &cb );
+ if (xosd != xosdNone) {
+ return FALSE;
+ }
+
+ if (lpNumberOfBytesRead) {
+ *lpNumberOfBytesRead = cb;
+ }
+
+ return TRUE;
+}
+
+
+XOSD
+SetFrame(
+ HPID hpid,
+ HTID htid,
+ PFRAME pframe
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to fill in the FRAME structure.
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk in
+ hthd - Supplies handle to thread to stack walk in
+ pframe - Supplies pointer to the frame structure to fill in
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ LARGE_INTEGER ul;
+
+ GetRegValue( hpid, htid, CV_ALPHA_IntSP, &ul);
+
+ FrameFlat ( *pframe ) = TRUE;
+ FrameOff32 ( *pframe ) = TRUE;
+ FrameReal (*pframe ) = FALSE;
+
+ SetFrameBPOff( *pframe, ul.LowPart );
+ SetFrameBPSeg( *pframe, 0);
+
+ pframe->SS = 0;
+ pframe->DS = 0;
+ pframe->PID = hpid;
+ pframe->TID = htid;
+
+ return xosdNone;
+} /* SetFrame() */
+
+
+XOSD
+SetPath(
+ HPID hpid,
+ HTID htid,
+ BOOL Set,
+ LSZ Path
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path in the DM
+
+Arguments:
+
+ hpid - process
+ htid - thread
+ Set - set flag
+ Path - Path to search, PATH if null
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ char Buffer[ MAX_PATH ];
+ SETPTH *SetPth = (SETPTH *)&Buffer;
+
+ if ( Set ) {
+
+ SetPth->Set = TRUE;
+ if ( Path ) {
+ strcpy(SetPth->Path, Path );
+ } else {
+ SetPth->Path[0] = '\0';
+ }
+ } else {
+ SetPth->Set = FALSE;
+ SetPth->Path[0] = '\0';
+ }
+
+ return SendRequestX( dmfSetPath, hpid, htid, sizeof(SETPTH) + strlen(SetPth->Path), SetPth );
+}
+
+
+XOSD
+GetFunctionInfo(
+ HPID hpid,
+ PADDR Addr,
+ PFUNCTION_INFO FunctionInfo
+ )
+/*++
+
+Routine Description:
+
+ Gets function information for a particular address.
+
+Arguments:
+
+ hpid - process
+ Addr - Address
+ FunctionInfo - Function information
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ PIMAGE_RUNTIME_FUNCTION_ENTRY pfe;
+
+
+ pfe = SwFunctionTableAccess( hpid, GetAddrOff( *Addr ) );
+
+ if ( pfe ) {
+
+ AddrInit( &FunctionInfo->AddrStart, 0,0, pfe->BeginAddress,
+ TRUE, TRUE, FALSE, FALSE );
+ AddrInit( &FunctionInfo->AddrEnd, 0,0, pfe->EndAddress,
+ TRUE, TRUE, FALSE, FALSE );
+ AddrInit( &FunctionInfo->AddrPrologEnd, 0,0, (pfe->PrologEndAddress & ~0x3),
+ TRUE, TRUE, FALSE, FALSE );
+
+ } else {
+
+ xosd = xosdUnknown;
+ }
+
+ return xosd;
+}
diff --git a/private/windbg/em/p_alpha/flags.h b/private/windbg/em/p_alpha/flags.h
new file mode 100644
index 000000000..0af579174
--- /dev/null
+++ b/private/windbg/em/p_alpha/flags.h
@@ -0,0 +1,10 @@
+
+ { szFlagMode, ftRegular|ftRegularExt, 1, CV_ALPHA_Psr, 0 },
+ { szFlagIe, ftRegular|ftRegularExt, 1, CV_ALPHA_Psr, 1 },
+ { szFlagIrql, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2},
+ { szFlagInt5, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2 },
+ { szFlagInt4, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2 },
+ { szFlagInt3, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2 },
+ { szFlagInt2, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2 },
+ { szFlagInt1, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2 },
+ { szFlagInt0, ftRegular|ftRegularExt, 3, CV_ALPHA_Psr, 2 },
diff --git a/private/windbg/em/p_alpha/kdalpha.h b/private/windbg/em/p_alpha/kdalpha.h
new file mode 100644
index 000000000..3cf311f4c
--- /dev/null
+++ b/private/windbg/em/p_alpha/kdalpha.h
@@ -0,0 +1,5 @@
+#ifndef _KDALPHA
+#define _KDALPHA
+
+#include <alphaops.h>
+#endif // _KDALPHA
diff --git a/private/windbg/em/p_alpha/makefile b/private/windbg/em/p_alpha/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/em/p_alpha/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/em/p_alpha/makefile.inc b/private/windbg/em/p_alpha/makefile.inc
new file mode 100644
index 000000000..8b520faa0
--- /dev/null
+++ b/private/windbg/em/p_alpha/makefile.inc
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/em/p_alpha/ntasm.h b/private/windbg/em/p_alpha/ntasm.h
new file mode 100644
index 000000000..f0de4c9ac
--- /dev/null
+++ b/private/windbg/em/p_alpha/ntasm.h
@@ -0,0 +1,25 @@
+
+// MBH - bugbug, of course this should be an enum
+
+#define GOODINSTRUCTION 0
+#define BADOPCODE 2
+#define BADREG 3
+#define OVERFLOW 4
+#define OPERAND 5
+#define EXTRACHARS 6
+#define BADSIZE 7
+
+
+
+
+
+ULONG ParseIntMemory(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseFltMemory(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseMemSpec(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseJump(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseIntBranch(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseFltBranch(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseIntOp(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParsePal(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+ULONG ParseUnknown(PUCHAR, POPTBLENTRY, PULONG, PULONG);
+
diff --git a/private/windbg/em/p_alpha/ntdis.h b/private/windbg/em/p_alpha/ntdis.h
new file mode 100644
index 000000000..d84aa064f
--- /dev/null
+++ b/private/windbg/em/p_alpha/ntdis.h
@@ -0,0 +1,191 @@
+#ifndef _NTDIS_
+#define _NTDIS_
+
+
+// this stuff is all "#if 0"'ed in alphaops.h
+//
+// Bit manipulations for Alpha instructions
+//
+
+#define SHFT_OPCODE 26
+#define SHFT_RA 21
+#define SHFT_RB 16
+#define SHFT_JMP_FNC 14
+#define SHFT_OP_FNC 5
+#define SHFT_RBV_TYPE 12
+#define SHFT_LIT 13
+#define SHFT_FP_FNC 5
+
+#define WIDTH_OPCODE 6
+#define WIDTH_REG 5
+#define WIDTH_MEM_DISP 16
+#define WIDTH_HINT 14
+#define WIDTH_JMP_FNC 2
+#define WIDTH_BR_DISP 21
+#define WIDTH_OP_FNC 7
+#define WIDTH_LIT 8
+#define WIDTH_FP_FNC 11
+#define WIDTH_PAL_FNC 26
+
+#define BITS_OPCODE ~(-1 << WIDTH_OPCODE)
+#define BITS_REG ~(-1 << WIDTH_REG)
+#define BITS_MEM_DISP ~(-1 << WIDTH_MEM_DISP)
+#define BITS_HINT ~(-1 << WIDTH_HINT)
+#define BITS_JMP_FNC ~(-1 << WIDTH_JMP_FNC)
+#define BITS_BR_DISP ~(-1 << WIDTH_BR_DISP)
+#define BITS_OP_FNC ~(-1 << WIDTH_OP_FNC)
+#define BITS_LIT ~(-1 << WIDTH_LIT)
+#define BITS_FP_FNC ~(-1 << WIDTH_FP_FNC)
+#define BITS_PAL_FNC ~(-1 << WIDTH_PAL_FNC)
+
+#define OPCODE(a) ((BITS_OPCODE & (a)) << SHFT_OPCODE)
+#define REG_A(a) ((BITS_REG & (a)) << SHFT_RA)
+#define REG_B(a) ((BITS_REG & (a)) << SHFT_RB)
+#define REG_C(a) (BITS_REG & (a))
+#define MEM_DISP(a) (BITS_MEM_DISP & (a))
+#define MEM_FUNC(a) MEM_DISP(a)
+#define HINT(a) (BITS_HINT & (a))
+#define JMP_FNC(a) ((BITS_JMP_FNC & (a)) << SHFT_JMP_FNC)
+#define BR_DISP(a) (BITS_BR_DISP & (a))
+#define OP_FNC(a) ((BITS_OP_FNC & (a)) << SHFT_OP_FNC)
+#define RBV_TYPE(a) ((1 & (a)) << SHFT_RBV_TYPE)
+#define LIT(a) ((BITS_LIT & (a)) << SHFT_LIT)
+#define FP_FNC(a) ((BITS_FP_FNC & (a)) << SHFT_FP_FNC)
+#define PAL_FNC(a) (BITS_PAL_FNC & (a))
+
+#define MSK_OPCODE OPCODE(BITS_OPCODE)
+#define MSK_RA GET_RA(BITS_REG)
+#define MSK_RB REG_B(BITS_REG)
+#define MSK_RC REG_C(BITS_REG)
+#define MSK_MEM_DISP DISP(BITS_MEM_DISP)
+#define MSK_HINT HINT(BITS_HINT)
+#define MSK_JMP_FNC JMP_FNC(BITS_JMP_FNC)
+#define MSK_BR_DISP BR_DISP(BITS_BR_DISP)
+#define MSK_RBV_TYPE RBV_TYPE(1)
+#define MSK_LIT LIT(BITS_LIT)
+#define MSK_FP_FNC FP_FNC(BITS_FP_FNC)
+#define MSK_PAL_FNC PAL_FNC(BITS_PAL_FNC)
+
+#define EXTR_OPCODE(a) (((a) & MSK_OPCODE) >> SHFT_OPCODE)
+#define EXTR_RA(a) (((a) & MSK_RA) >> SHFT_RA)
+#define EXTR_RB(a) (((a) & MSK_RB) >> SHFT_RA)
+#define EXTR_RC(a) ((a) & MSK_RC)
+#define EXTR_MEM_DISP(a) ((a) & MSK_MEM_DISP)
+#define EXTR_HINT(a) ((a) & MSK_HINT)
+#define EXTR_JMP_FNC(a) (((a) & MSK_JMP_FNC) >> SHFT_JMP_FNC)
+#define EXTR_BR_DISP(a) ((a) & MSK_BR_DISP)
+#define EXTR_RBV_TYPE(a) (((a) & MSK_RBV_TYPE) >> SHFT_RBV_TYPE)
+#define EXTR_LIT(a) (((a) & MSK_LIT) >> SHFT_LIT)
+#define EXTR_FP_FNC(a) (((a) & MSK_FP_FNC) >> SHFT_FP_FNC)
+#define EXTR_PAL_FNC(a) ((a) & MSK_PAL_FNC)
+
+
+
+//
+// Bit manipulations for EV4 PAL mode instructions
+//
+
+#define SHFT_EV4_IBOX 5
+#define SHFT_EV4_ABOX 6
+#define SHFT_EV4_PALTEMP 7
+#define SHFT_EV4_QWORD 12
+#define SHFT_EV4_RWCHECK 13
+#define SHFT_EV4_ALT 14
+#define SHFT_EV4_PHYSICAL 15
+
+#define WIDTH_EV4_INDEX 5
+#define WIDTH_EV4_IBOX 1
+#define WIDTH_EV4_ABOX 1
+#define WIDTH_EV4_PALTEMP 1
+#define WIDTH_EV4_DISP 12
+#define WIDTH_EV4_QWORD 1
+#define WIDTH_EV4_RWCHECK 1
+#define WIDTH_EV4_ALT 1
+#define WIDTH_EV4_PHYSICAL 1
+
+#define BITS_EV4_INDEX ~(-1 << WIDTH_EV4_INDEX)
+#define BITS_EV4_IBOX ~(-1 << WIDTH_EV4_IBOX)
+#define BITS_EV4_ABOX ~(-1 << WIDTH_EV4_ABOX)
+#define BITS_EV4_PALTEMP ~(-1 << WIDTH_EV4_PALTEMP)
+#define BITS_EV4_DISP ~(-1 << WIDTH_EV4_DISP)
+#define BITS_EV4_QWORD ~(-1 << WIDTH_EV4_QWORD)
+#define BITS_EV4_RWCHECK ~(-1 << WIDTH_EV4_RWCHECK)
+#define BITS_EV4_ALT ~(-1 << WIDTH_EV4_ALT)
+#define BITS_EV4_PHYSICAL ~(-1 << WIDTH_EV4_PHYSICAL)
+
+#define EV4_INDEX(a) (BITS_EV4_INDEX & (a))
+#define EV4_IBOX(a) ((BITS_EV4_IBOX & (a)) << SHFT_EV4_IBOX)
+#define EV4_ABOX(a) ((BITS_EV4_ABOX & (a)) << SHFT_EV4_ABOX)
+#define EV4_PALTEMP(a) ((BITS_EV4_PALTEMP & (a)) << SHFT_EV4_PALTEMP)
+#define EV4_DISP(a) (BITS_EV4_DISP & (a))
+#define EV4_QWORD(a) ((BITS_EV4_QWORD & (a)) << SHFT_EV4_QWORD)
+#define EV4_RWCHECK(a) ((BITS_EV4_RWCHECK & (a)) << SHFT_EV4_RWCHECK)
+#define EV4_ALT(a) ((BITS_EV4_ALT & (a)) << SHFT_EV4_ALT)
+#define EV4_PHYSICAL(a) ((BITS_EV4_PHYSICAL & (a)) << SHFT_EV4_PHYSICAL)
+
+#define MSK_EV4_INDEX EV4_INDEX(BITS_EV4_INDEX)
+#define MSK_EV4_IBOX EV4_IBOX(BITS_EV4_IBOX)
+#define MSK_EV4_ABOX EV4_ABOX(BITS_EV4_ABOX)
+#define MSK_EV4_PALTEMP EV4_PALTEMP(BITS_EV4_PALTEMP)
+#define MSK_EV4_PR (MSK_EV4_INDEX | MSK_EV4_IBOX | MSK_EV4_ABOX | MSK_EV4_PALTEMP)
+#define MSK_EV4_DISP EV4_DISP(BITS_EV4_DISP)
+#define MSK_EV4_QWORD EV4_QWORD(BITS_EV4_QWORD)
+#define MSK_EV4_RWCHECK EV4_RWCHECK(BITS_EV4_RWCHECK)
+#define MSK_EV4_ALT EV4_ALT(BITS_EV4_ALT)
+#define MSK_EV4_PHYSICAL EV4_PHYSICAL(BITS_EV4_PHYSICAL)
+
+#define EXTR_EV4_INDEX(a) (MSK_EV4_INDEX & (a))
+#define EXTR_EV4_IBOX(a) ((MSK_EV4_IBOX & (a)) >> SHFT_EV4_IBOX)
+#define EXTR_EV4_ABOX(a) ((MSK_EV4_ABOX & (a)) >> SHFT_EV4_ABOX)
+#define EXTR_EV4_PALTEMP(a) ((MSK_EV4_PALTEMP & (a)) >> SHFT_EV4_PALTEMP)
+#define EXTR_EV4_DISP(a) (MSK_EV4_DISP & (a))
+#define EXTR_EV4_QWORD(a) ((MSK_EV4_QWORD & (a)) >> SHFT_EV4_QWORD)
+#define EXTR_EV4_RWCHECK(a) ((MSK_EV4_RWCHECK & (a)) >> SHFT_EV4_RWCHECK)
+#define EXTR_EV4_ALT(a) ((MSK_EV4_ALT & (a)) >> SHFT_EV4_ALT)
+#define EXTR_EV4_PHYSICAL(a) ((MSK_EV4_PHYSICAL & (a)) >> SHFT_EV4_PHYSICAL)
+
+#define EV4_TB_TAG (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(0))
+#define EV4_ITB_PTE (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(1))
+#define EV4_ICCSR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(2))
+#define EV4_ITM_PTE_TEMP (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(3))
+#define EV4_EXC_ADDR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(4))
+#define EV4_SL_RCV (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(5))
+#define EV4_ITBZAP (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(6))
+#define EV4_ITBASM (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(7))
+#define EV4_ITBIS (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(8))
+#define EV4_PS (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(9))
+#define EV4_EXC_SUM (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(10))
+#define EV4_PAL_BASE (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(11))
+#define EV4_HIRR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(12))
+#define EV4_SIRR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(13))
+#define EV4_ASTRR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(14))
+#define EV4_HIER (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(16))
+#define EV4_SIER (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(17))
+#define EV4_ASTER (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(18))
+#define EV4_SL_CLR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(19))
+#define EV4_SL_XMIT (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(22))
+#define EV4_DTB_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(0))
+#define EV4_DTB_PTE (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(2))
+#define EV4_DTB_PTE_TEMP (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(3))
+#define EV4_MMCSR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(4))
+#define EV4_VA (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(5))
+#define EV4_DTBZAP (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(6))
+#define EV4_DTASM (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(7))
+#define EV4_DTBIS (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(8))
+#define EV4_BIU_ADDR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(9))
+#define EV4_BIU_STAT (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(10))
+#define EV4_DC_ADDR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(11))
+#define EV4_DC_STAT (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(12))
+#define EV4_FILL_ADDR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(13))
+#define EV4_ABOX_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(14))
+#define EV4_ALT_MODE (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(15))
+#define EV4_CC (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(16))
+#define EV4_CC_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(17))
+#define EV4_BIU_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(18))
+#define EV4_FILL_SYNDROME (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(19))
+#define EV4_BC_TAG (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(20))
+#define EV4_FLUSH_IC (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(21))
+#define EV4_FLUSH_IC_ASM (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(23))
+#define EV4_PAL_TEMP(x) (EV4_PALTEMP(1) | EV4_ABOX(0) | EV4_IBOX(0) | EV4_INDEX(x))
+
+#endif
diff --git a/private/windbg/em/p_alpha/optable.c b/private/windbg/em/p_alpha/optable.c
new file mode 100644
index 000000000..0730983d3
--- /dev/null
+++ b/private/windbg/em/p_alpha/optable.c
@@ -0,0 +1,1289 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ optable.c
+
+Abstract:
+
+ Declaration for -
+ Table of operations, their names and charactersitics
+ Used by ntsd, windbg and acc's dissassembler
+
+Author:
+
+ Miche Baker-Harvey (mbh) 10-Jan-1993
+
+Revision History:
+
+ Nigel Haslock (haslock) 5-Sept-1995
+ Added EV56 instructions for Byte and Word aligned memory access
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+#include "alphaops.h"
+#include "optable.h"
+#include "ntasm.h"
+
+#define DEFINE_STRINGS
+#include "strings.h"
+
+// for strcmp
+#include <string.h>
+
+// for fVerboseOutput
+BOOLEAN fVerboseOutput = FALSE;
+
+#define NOFNCTBL (PVOID) 0
+#define NOSIZE (ULONG)0
+
+
+//
+// These fields are used to find the beginning of the sections
+// containing different "ENTRY_TYPE"s
+//
+
+POPTBLENTRY InvalidTab;
+POPTBLENTRY NonTerminalTab;
+POPTBLENTRY TerminalTab;
+POPTBLENTRY FunctionTab;
+
+ULONG InvalidTabSize;
+ULONG NonTerminalTabSize;
+ULONG TerminalTabSize;
+ULONG FunctionTabSize;
+
+
+
+//
+// THE OPCODE TABLE ITSELF
+//
+// The opcode table "opTable" describes each opcode and function.
+// There is an entry for each opcode, and for each function.
+//
+// The table is organized as follows:
+// invalid-ops,
+// non-terminal-ops,
+// terminal-ops,
+// functions,
+//
+// This organization is NOT required:
+// no assumptions are made on it.
+//
+// Searches based on opcode must search
+// INVALID, TERMINAL and NON_TERMINAL
+//
+// Searches based on instruction name must search
+// TERMINAL and FUNCTION
+//
+//
+
+OPTBLENTRY opTable[] = {
+
+
+ //
+ // First, the INVALID_ETYPE section.
+ // (opcode searches begin here)
+ //
+
+
+{ "?Opc01", ParseUnknown, _01_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc02", ParseUnknown, _02_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc03", ParseUnknown, _03_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc04", ParseUnknown, _04_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc05", ParseUnknown, _05_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc06", ParseUnknown, _06_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc07", ParseUnknown, _07_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+//{ "?Opc0A", ParseUnknown, _0A_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+//{ "?Opc0C", ParseUnknown, _0C_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+//{ "?Opc0D", ParseUnknown, _0D_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+//{ "?Opc0E", ParseUnknown, _0E_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+{ "?Opc14", ParseUnknown, _14_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+//{ "?Opc1C", ParseUnknown, _1C_OP, NO_FUNC, ALPHA_UNKNOWN, INVALID_ETYPE},
+
+
+//
+// This is what hasn't been done yet -
+// the EV4 stuff - there are no names for it
+// in the alphaops.h header file. Should we
+// put them there? Should they be elsewhere?
+// Do we want to assemble them?
+//
+// For the moment, just pretend they are invalid. They never
+// come up for all practical purposes, anyway.
+//
+
+
+{ "MFPR", ParseUnknown, MFPR_OP, NO_FUNC,
+ ALPHA_EV4_PR, INVALID_ETYPE },
+{ "MTPR", ParseUnknown, MTPR_OP, NO_FUNC,
+ ALPHA_EV4_PR, INVALID_ETYPE },
+
+
+
+ //
+ // Secondly, the NON_TERMINAL_ETYPE section
+ //
+
+
+
+{ NOFNCTBL, NOSIZE, CALLPAL_OP, NO_FUNC,
+ ALPHA_CALLPAL, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, ARITH_OP, NO_FUNC,
+ ALPHA_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, BIT_OP, NO_FUNC,
+ ALPHA_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, BYTE_OP, NO_FUNC,
+ ALPHA_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, SEXT_OP, NO_FUNC,
+ ALPHA_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, MUL_OP, NO_FUNC,
+ ALPHA_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, MEMSPC_OP, NO_FUNC,
+ ALPHA_MEMSPC, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, JMP_OP, NO_FUNC,
+ ALPHA_JUMP, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, VAXFP_OP, NO_FUNC,
+ ALPHA_FP_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, IEEEFP_OP, NO_FUNC,
+ ALPHA_FP_OPERATE, NON_TERMINAL_ETYPE },
+{ NOFNCTBL, NOSIZE, FPOP_OP, NO_FUNC,
+ ALPHA_FP_OPERATE, NON_TERMINAL_ETYPE },
+
+
+
+ //
+ // Thirdly, the TERMINAL_ETYPE section
+ // (everything from here on has an instruction name)
+ //
+
+
+
+{ szLda, ParseIntMemory, LDA_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdah, ParseIntMemory, LDAH_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdl, ParseIntMemory, LDL_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdq, ParseIntMemory, LDQ_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdf, ParseFltMemory, LDF_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szLdg, ParseFltMemory, LDG_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szLds, ParseFltMemory, LDS_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szLdt, ParseFltMemory, LDT_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szLdq_u, ParseIntMemory, LDQ_U_OP,NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdl_l, ParseIntMemory, LDL_L_OP,NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdq_l, ParseIntMemory, LDQ_L_OP,NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdbu, ParseIntMemory, LDBU_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szLdbu, ParseIntMemory, LDWU_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+
+{ szStl, ParseIntMemory, STL_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szStq, ParseIntMemory, STQ_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szStf, ParseFltMemory, STF_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szStg, ParseFltMemory, STG_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szSts, ParseFltMemory, STS_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szStt, ParseFltMemory, STT_OP, NO_FUNC, ALPHA_FP_MEMORY, TERMINAL_ETYPE },
+{ szStq_u, ParseIntMemory, STQ_U_OP,NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szStl_c, ParseIntMemory, STL_C_OP,NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szStq_c, ParseIntMemory, STQ_C_OP,NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szStb, ParseIntMemory, STB_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+{ szStw, ParseIntMemory, STW_OP, NO_FUNC, ALPHA_MEMORY, TERMINAL_ETYPE },
+
+{ szBeq, ParseIntBranch, BEQ_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBne, ParseIntBranch, BNE_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBlt, ParseIntBranch, BLT_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBle, ParseIntBranch, BLE_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBgt, ParseIntBranch, BGT_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBge, ParseIntBranch, BGE_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBlbc, ParseIntBranch, BLBC_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBlbs, ParseIntBranch, BLBS_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBr, ParseIntBranch, BR_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+{ szBsr, ParseIntBranch, BSR_OP, NO_FUNC, ALPHA_BRANCH, TERMINAL_ETYPE },
+
+{ szFbeq, ParseFltBranch, FBEQ_OP, NO_FUNC, ALPHA_FP_BRANCH, TERMINAL_ETYPE },
+{ szFbne, ParseFltBranch, FBNE_OP, NO_FUNC, ALPHA_FP_BRANCH, TERMINAL_ETYPE },
+{ szFblt, ParseFltBranch, FBLT_OP, NO_FUNC, ALPHA_FP_BRANCH, TERMINAL_ETYPE },
+{ szFble, ParseFltBranch, FBLE_OP, NO_FUNC, ALPHA_FP_BRANCH, TERMINAL_ETYPE },
+{ szFbgt, ParseFltBranch, FBGT_OP, NO_FUNC, ALPHA_FP_BRANCH, TERMINAL_ETYPE },
+{ szFbge, ParseFltBranch, FBGE_OP, NO_FUNC, ALPHA_FP_BRANCH, TERMINAL_ETYPE },
+
+
+{ "REI", ParseUnknown, PAL1B_OP, NO_FUNC, ALPHA_EV4_REI, TERMINAL_ETYPE},
+{ "HW_LD", ParseUnknown, PAL1E_OP, NO_FUNC, ALPHA_EV4_MEM, TERMINAL_ETYPE},
+{ "HW_ST", ParseUnknown, PAL1F_OP, NO_FUNC, ALPHA_EV4_MEM, TERMINAL_ETYPE},
+
+
+ //
+ // Fourthly, (and finally) the FUNCTION_ETYPE section
+ // (opcode searches needn't include this section)
+ //
+
+ //
+ // The memory-special functions
+ //
+
+{ szMb, ParseMemSpec, MEMSPC_OP, MB_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szWmb, ParseMemSpec, MEMSPC_OP, WMB_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szMb2, ParseMemSpec, MEMSPC_OP, MB2_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szMb3, ParseMemSpec, MEMSPC_OP, MB3_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szFetch,ParseMemSpec, MEMSPC_OP, FETCH_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szFetch_m,ParseMemSpec,MEMSPC_OP,FETCH_M_FUNC,ALPHA_MEMSPC,FUNCTION_ETYPE },
+{ szRs, ParseMemSpec, MEMSPC_OP, RS_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szTrapb,ParseMemSpec, MEMSPC_OP, TRAPB_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szExcb, ParseMemSpec, MEMSPC_OP, EXCB_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szRpcc, ParseMemSpec, MEMSPC_OP, RPCC_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+{ szRc, ParseMemSpec, MEMSPC_OP, RC_FUNC, ALPHA_MEMSPC, FUNCTION_ETYPE },
+
+ //
+ // The jump functions
+ //
+
+{ szJmp, ParseJump, JMP_OP, JMP_FUNC, ALPHA_JUMP, FUNCTION_ETYPE },
+{ szJsr, ParseJump, JMP_OP, JSR_FUNC, ALPHA_JUMP, FUNCTION_ETYPE },
+{ szRet, ParseJump, JMP_OP, RET_FUNC, ALPHA_JUMP, FUNCTION_ETYPE },
+{ szJsr_co, ParseJump, JMP_OP, JSR_CO_FUNC, ALPHA_JUMP, FUNCTION_ETYPE },
+
+ //
+ // The arithmetic ops, which are ALPHA_OPERATE
+ //
+
+{ szAddl, ParseIntOp, ARITH_OP, ADDL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szAddlv, ParseIntOp, ARITH_OP, ADDLV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szAddq, ParseIntOp, ARITH_OP, ADDQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szAddqv, ParseIntOp, ARITH_OP, ADDQV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSubl, ParseIntOp, ARITH_OP, SUBL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSublv, ParseIntOp, ARITH_OP, SUBLV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSubq, ParseIntOp, ARITH_OP, SUBQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSubqv, ParseIntOp, ARITH_OP, SUBQV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+
+{ szCmpeq, ParseIntOp, ARITH_OP, CMPEQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmplt, ParseIntOp, ARITH_OP, CMPLT_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmple, ParseIntOp, ARITH_OP, CMPLE_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmpult, ParseIntOp, ARITH_OP, CMPULT_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmpule, ParseIntOp, ARITH_OP, CMPULE_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmpbge, ParseIntOp, ARITH_OP, CMPBGE_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+
+{ szS4addl, ParseIntOp, ARITH_OP, S4ADDL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS4addq, ParseIntOp, ARITH_OP, S4ADDQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS4subl, ParseIntOp, ARITH_OP, S4SUBL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS4subq, ParseIntOp, ARITH_OP, S4SUBQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS8addl, ParseIntOp, ARITH_OP, S8ADDL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS8addq, ParseIntOp, ARITH_OP, S8ADDQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS8subl, ParseIntOp, ARITH_OP, S8SUBL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szS8subq, ParseIntOp, ARITH_OP, S8SUBQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+ //
+ // The bit ops, which are ALPHA_OPERATE
+ //
+
+{ szAnd, ParseIntOp, BIT_OP, AND_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szBic, ParseIntOp, BIT_OP, BIC_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szBis, ParseIntOp, BIT_OP, BIS_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szOrnot, ParseIntOp, BIT_OP, ORNOT_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szXor, ParseIntOp, BIT_OP, XOR_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szEqv, ParseIntOp, BIT_OP, EQV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+{ szCmoveq, ParseIntOp, BIT_OP, CMOVEQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovne, ParseIntOp, BIT_OP, CMOVNE_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovlbs, ParseIntOp, BIT_OP, CMOVLBS_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovlt, ParseIntOp, BIT_OP, CMOVLT_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovge, ParseIntOp, BIT_OP, CMOVGE_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovlbc, ParseIntOp, BIT_OP, CMOVLBC_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovle, ParseIntOp, BIT_OP, CMOVLE_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szCmovgt, ParseIntOp, BIT_OP, CMOVGT_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+ //
+ // The byte ops, which are ALPHA_OPERATE
+ //
+
+{ szSll, ParseIntOp, BYTE_OP, SLL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSra, ParseIntOp, BYTE_OP, SRA_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSrl, ParseIntOp, BYTE_OP, SRL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtbl, ParseIntOp, BYTE_OP, EXTBL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtwl, ParseIntOp, BYTE_OP, EXTWL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtll, ParseIntOp, BYTE_OP, EXTLL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtql, ParseIntOp, BYTE_OP, EXTQL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtwh, ParseIntOp, BYTE_OP, EXTWH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtlh, ParseIntOp, BYTE_OP, EXTLH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szExtqh, ParseIntOp, BYTE_OP, EXTQH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInsbl, ParseIntOp, BYTE_OP, INSBL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInswl, ParseIntOp, BYTE_OP, INSWL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInsll, ParseIntOp, BYTE_OP, INSLL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInsql, ParseIntOp, BYTE_OP, INSQL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInswh, ParseIntOp, BYTE_OP, INSWH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInslh, ParseIntOp, BYTE_OP, INSLH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szInsqh, ParseIntOp, BYTE_OP, INSQH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMskbl, ParseIntOp, BYTE_OP, MSKBL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMskwl, ParseIntOp, BYTE_OP, MSKWL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMskll, ParseIntOp, BYTE_OP, MSKLL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMskql, ParseIntOp, BYTE_OP, MSKQL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMskwh, ParseIntOp, BYTE_OP, MSKWH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMsklh, ParseIntOp, BYTE_OP, MSKLH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMskqh, ParseIntOp, BYTE_OP, MSKQH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szZap, ParseIntOp, BYTE_OP, ZAP_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szZapnot, ParseIntOp, BYTE_OP, ZAPNOT_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+ //
+ // The multiply ops, which are ALPHA_OPERATE
+ //
+
+{ szMull, ParseIntOp, MUL_OP, MULL_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMulqv, ParseIntOp, MUL_OP, MULQV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMullv, ParseIntOp, MUL_OP, MULLV_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szUmulh, ParseIntOp, MUL_OP, UMULH_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szMulq, ParseIntOp, MUL_OP, MULQ_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+ //
+ // The SEXT ops, which are ALPHA_OPERATE
+ //
+
+{ szSextb, ParseIntOp, SEXT_OP, SEXTB_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+{ szSextw, ParseIntOp, SEXT_OP, SEXTW_FUNC, ALPHA_OPERATE, FUNCTION_ETYPE },
+
+ //
+ // The call pal functions
+ //
+
+
+{ szBpt, ParsePal, CALLPAL_OP, BPT_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szCallsys, ParsePal, CALLPAL_OP, CALLSYS_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szImb, ParsePal, CALLPAL_OP, IMB_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdteb, ParsePal, CALLPAL_OP, RDTEB_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szGentrap, ParsePal, CALLPAL_OP, GENTRAP_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szKbpt, ParsePal, CALLPAL_OP, KBPT_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szCallKD, ParsePal, CALLPAL_OP, CALLKD_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szHalt, ParsePal, CALLPAL_OP, HALT_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRestart, ParsePal, CALLPAL_OP, RESTART_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szDraina, ParsePal, CALLPAL_OP, DRAINA_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szInitpal, ParsePal, CALLPAL_OP, INITPAL_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szWrentry, ParsePal, CALLPAL_OP, WRENTRY_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szSwpirql, ParsePal, CALLPAL_OP, SWPIRQL_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdirql, ParsePal, CALLPAL_OP, RDIRQL_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szDi, ParsePal, CALLPAL_OP, DI_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szEi, ParsePal, CALLPAL_OP, EI_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szSwppal, ParsePal, CALLPAL_OP, SWPPAL_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szSsir, ParsePal, CALLPAL_OP, SSIR_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szCsir, ParsePal, CALLPAL_OP, CSIR_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRfe, ParsePal, CALLPAL_OP, RFE_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRetsys, ParsePal, CALLPAL_OP, RETSYS_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szSwpctx, ParsePal, CALLPAL_OP, SWPCTX_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szSwpprocess, ParsePal, CALLPAL_OP, SWPPROCESS_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdmces, ParsePal, CALLPAL_OP, RDMCES_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szWrmces, ParsePal, CALLPAL_OP, WRMCES_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szTbia, ParsePal, CALLPAL_OP, TBIA_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szTbis, ParsePal, CALLPAL_OP, TBIS_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szDtbis, ParsePal, CALLPAL_OP, DTBIS_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdksp, ParsePal, CALLPAL_OP, RDKSP_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szSwpksp, ParsePal, CALLPAL_OP, SWPKSP_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdpsr, ParsePal, CALLPAL_OP, RDPSR_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdpcr, ParsePal, CALLPAL_OP, RDPCR_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdthread, ParsePal, CALLPAL_OP, RDTHREAD_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdcounters, ParsePal, CALLPAL_OP, RDCOUNTERS_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRdstate, ParsePal, CALLPAL_OP, RDSTATE_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szInitpcr, ParsePal, CALLPAL_OP, INITPCR_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szWrperfmon, ParsePal, CALLPAL_OP, WRPERFMON_FUNC,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szMt, ParsePal, CALLPAL_OP, MTPR_OP,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szMf, ParsePal, CALLPAL_OP, MFPR_OP,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szHwld, ParsePal, CALLPAL_OP, HWLD_OP,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szHwst, ParsePal, CALLPAL_OP, HWST_OP,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+{ szRei, ParsePal, CALLPAL_OP, REI_OP,
+ ALPHA_CALLPAL, FUNCTION_ETYPE },
+
+
+ //
+ // The VAX Floating point functions
+ //
+
+
+{ szAddf, ParseUnknown, VAXFP_OP, ADDF_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCvtdg, ParseUnknown, VAXFP_OP, CVTDG_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szAddg, ParseUnknown, VAXFP_OP, ADDG_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmpgeq, ParseUnknown, VAXFP_OP, CMPGEQ_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmpglt, ParseUnknown, VAXFP_OP, CMPGLT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmpgle, ParseUnknown, VAXFP_OP, CMPGLE_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCvtgf, ParseUnknown, VAXFP_OP, CVTGF_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtgd, ParseUnknown, VAXFP_OP, CVTGD_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtqf, ParseUnknown, VAXFP_OP, CVTQF_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtqg, ParseUnknown, VAXFP_OP, CVTQG_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szDivf, ParseUnknown, VAXFP_OP, DIVF_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szDivg, ParseUnknown, VAXFP_OP, DIVG_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szMulf, ParseUnknown, VAXFP_OP, MULF_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szMulg, ParseUnknown, VAXFP_OP, MULG_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szSubf, ParseUnknown, VAXFP_OP, SUBF_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szSubg, ParseUnknown, VAXFP_OP, SUBG_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCvtgq, ParseUnknown, VAXFP_OP, CVTGQ_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+ //
+ // The IEEE Floating point functions
+ //
+
+{ szAdds, ParseUnknown, IEEEFP_OP, ADDS_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szSubs, ParseUnknown, IEEEFP_OP, SUBS_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szMuls, ParseUnknown, IEEEFP_OP, MULS_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szDivs, ParseUnknown, IEEEFP_OP, DIVS_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szAddt, ParseUnknown, IEEEFP_OP, ADDT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szSubt, ParseUnknown, IEEEFP_OP, SUBT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szMult, ParseUnknown, IEEEFP_OP, MULT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szDivt, ParseUnknown, IEEEFP_OP, DIVT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmptun, ParseUnknown, IEEEFP_OP, CMPTUN_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmpteq, ParseUnknown, IEEEFP_OP, CMPTEQ_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmptlt, ParseUnknown, IEEEFP_OP, CMPTLT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCmptle, ParseUnknown, IEEEFP_OP, CMPTLE_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCvtts, ParseUnknown, IEEEFP_OP, CVTTS_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvttq, ParseUnknown, IEEEFP_OP, CVTTQ_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtqs, ParseUnknown, IEEEFP_OP, CVTQS_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtqt, ParseUnknown, IEEEFP_OP, CVTQT_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+
+ //
+ // The Common Floating point functions
+ //
+
+
+{ szCvtlq, ParseUnknown, FPOP_OP, CVTLQ_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCpys, ParseUnknown, FPOP_OP, CPYS_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCpysn, ParseUnknown, FPOP_OP, CPYSN_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCpyse, ParseUnknown, FPOP_OP, CPYSE_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szMt_fpcr, ParseUnknown, FPOP_OP, MT_FPCR_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szMf_fpcr, ParseUnknown, FPOP_OP, MF_FPCR_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szFcmoveq, ParseUnknown, FPOP_OP, FCMOVEQ_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szFcmovne, ParseUnknown, FPOP_OP, FCMOVNE_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szFcmovlt, ParseUnknown, FPOP_OP, FCMOVLT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szFcmovge, ParseUnknown, FPOP_OP, FCMOVGE_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szFcmovle, ParseUnknown, FPOP_OP, FCMOVLE_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szFcmovgt, ParseUnknown, FPOP_OP, FCMOVGT_FUNC,
+ ALPHA_FP_OPERATE, FUNCTION_ETYPE },
+{ szCvtql, ParseUnknown, FPOP_OP, CVTQL_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtqlv, ParseUnknown, FPOP_OP, CVTQLV_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+{ szCvtqlsv, ParseUnknown, FPOP_OP, CVTQLSV_FUNC,
+ ALPHA_FP_CONVERT, FUNCTION_ETYPE },
+
+}; // end of opTable
+
+
+#define SEARCHNUM sizeof(opTable) / sizeof(OPTBLENTRY)
+
+
+
+//
+// Here are the tables of Floating Point flags.
+//
+
+FPFLAGS ConvertFlags[] = {
+ { NONE_FLAGS, NONE_FLAGS_STR },
+ { C_FLAGS, C_FLAGS_STR },
+ { V_FLAGS, V_FLAGS_STR },
+ { VC_FLAGS, VC_FLAGS_STR },
+ { SV_FLAGS, SV_FLAGS_STR },
+ { SVC_FLAGS, SVC_FLAGS_STR },
+ { SVI_FLAGS, SVI_FLAGS_STR },
+ { SVIC_FLAGS, SVIC_FLAGS_STR },
+
+ { D_FLAGS, D_FLAGS_STR },
+ { VD_FLAGS, VD_FLAGS_STR },
+ { SVD_FLAGS, SVD_FLAGS_STR },
+ { SVID_FLAGS, SVID_FLAGS_STR },
+ { M_FLAGS, M_FLAGS_STR },
+ { VM_FLAGS, VM_FLAGS_STR },
+ { SVM_FLAGS, SVM_FLAGS_STR },
+ { SVIM_FLAGS, SVIM_FLAGS_STR },
+
+ { S_FLAGS, S_FLAGS_STR },
+ { SC_FLAGS, SC_FLAGS_STR },
+ { FPFLAGS_NOT_AN_ENTRY, "" }
+};
+
+FPFLAGS FloatOpFlags[] = {
+ { C_FLAGS, C_FLAGS_STR },
+ { M_FLAGS, M_FLAGS_STR },
+ { NONE_FLAGS, NONE_FLAGS_STR },
+ { D_FLAGS, D_FLAGS_STR },
+ { UC_FLAGS, UC_FLAGS_STR },
+ { UM_FLAGS, UM_FLAGS_STR },
+ { U_FLAGS, U_FLAGS_STR },
+ { UD_FLAGS, UD_FLAGS_STR },
+ { SC_FLAGS, SC_FLAGS_STR },
+ { S_FLAGS, S_FLAGS_STR },
+ { SUC_FLAGS, SUC_FLAGS_STR },
+ { SUM_FLAGS, SUM_FLAGS_STR },
+ { SU_FLAGS, SU_FLAGS_STR },
+ { SUD_FLAGS, SUD_FLAGS_STR },
+ { SUIC_FLAGS, SUIC_FLAGS_STR },
+ { SUIM_FLAGS, SUIM_FLAGS_STR },
+ { SUI_FLAGS, SUI_FLAGS_STR },
+ { SUID_FLAGS, SUID_FLAGS_STR },
+ { FPFLAGS_NOT_AN_ENTRY, "" }
+};
+
+
+/*** findNameEntry - find POPTBLENTRY based on name
+*
+* Purpose:
+* This routine is used to determine if the opTable has
+* been initialized. If a routine fails, it calls this
+* initialization check. If the table is not initialized,
+* we initialize it, and try again.
+*
+* Input:
+* VOID
+*
+* Returns:
+* TRUE - means table was already initialized; real failure
+* FALSE - just now initialized table; try again
+*
+*************************************************************************/
+BOOLEAN
+opTableInitialized()
+{
+
+ static BOOLEAN opTableInitialized = FALSE;
+
+ if (opTableInitialized == TRUE) {
+ return TRUE;
+ }
+
+ //
+ // it wasn't initialized yet; do so now.
+ //
+
+ opTableInit();
+ opTableInitialized = TRUE;
+ return FALSE;
+}
+
+
+/*** findNameEntry - find POPTBLENTRY based on name
+*
+* Purpose:
+* Search the opTable for a match with the token
+* pointed by *pszOp. Must search through the
+* TERMINAL and the FUNCTION tables
+*
+* Input:
+* *pszOp - string to search as mnemonic
+*
+* Returns:
+* Pointer to entry in the opTable
+*
+*************************************************************************/
+
+POPTBLENTRY
+findStringEntry (PUCHAR pszOp)
+{
+
+ POPTBLENTRY pEntry;
+
+ for (pEntry = TerminalTab;
+ pEntry < &TerminalTab[TerminalTabSize];
+ pEntry++) {
+
+ if (!strcmp(pszOp, pEntry->pszAlphaName))
+ return(pEntry);
+ }
+
+ for (pEntry = FunctionTab;
+ pEntry < &FunctionTab[FunctionTabSize];
+ pEntry++) {
+
+ if (!strcmp(pszOp, pEntry->pszAlphaName))
+ return(pEntry);
+ }
+
+ if (opTableInitialized() == FALSE) {
+ return findStringEntry(pszOp);
+ }
+ return((POPTBLENTRY)-1);
+}
+
+
+/* findOpCodeEntry - find POPTBLENTRY based on opcode
+*
+* Purpose:
+* Search the opTable for a match with the opcode
+* Must search through the
+* INVALID, TERMINAL and NON_TERMINAL tables
+*
+* Input:
+* pOpEntry - pointer to NON_TERMINAL_ETYPE in opTable
+* function - the function value to be looked up
+*
+* Output:
+* pointer to string mnemonic for the function
+*
+***********************************************************************/
+
+POPTBLENTRY
+findOpCodeEntry(ULONG opcode)
+{
+ POPTBLENTRY pEntry;
+
+ for (pEntry = TerminalTab;
+ pEntry < &TerminalTab[TerminalTabSize];
+ pEntry++) {
+
+ if (pEntry->opCode == opcode)
+ return(pEntry);
+ }
+
+ for (pEntry = NonTerminalTab;
+ pEntry < &NonTerminalTab[NonTerminalTabSize];
+ pEntry++) {
+
+ if (pEntry->opCode == opcode)
+ return(pEntry);
+ }
+
+ for (pEntry = InvalidTab;
+ pEntry < &InvalidTab[InvalidTabSize];
+ pEntry++) {
+
+ if (pEntry->opCode == opcode)
+ return(pEntry);
+ }
+
+ if (opTableInitialized() == FALSE) {
+ return findOpCodeEntry(opcode);
+ }
+ return((POPTBLENTRY)-1);
+}
+
+
+/*** findTypeFromOpcode - find the instruction type
+*
+* Purpose:
+* This routine finds the type of the instruction (ALPHA_*)
+* from the opcode. It returns a single value so that it
+* can be called from other dll's without passing storage.
+*
+* Input:
+* the opcode number.
+*
+* Output:
+* the type of the opcode (ALPHA_* in alphaops.h)
+*
+* Errors:
+* returns ALPHA_UNKNOWN for an invalid opcode
+*
+* Exceptions:
+* None.
+*
+*
+*************************************************************************/
+
+ULONG
+findTypeFromOpcode(ULONG opcode)
+{
+ POPTBLENTRY pEntry;
+
+ pEntry = findOpCodeEntry(opcode);
+
+ if (pEntry != (POPTBLENTRY)(-1)) {
+ return(pEntry->iType);
+ } else {
+ return(ALPHA_UNKNOWN);
+ }
+}
+
+
+/*** findNonTerminalEntry - find pointer to set of functions
+*
+* Purpose:
+* This routine finds the entry in the table which the is
+* nonterminal entry for an opcode.
+*
+* Input:
+* The type of function that is interesting
+*
+* Output:
+* Pointer to the nonterminal entry in opTable
+*
+* Errors:
+* If the entry is not found, a message is printed, and the
+* routine exits.
+*
+* Exceptions:
+* None.
+*
+* Note:
+* This routine is called BEFORE NonTerminalTable is established!
+* (it's used to set up these tables, in fact).
+*
+*************************************************************************/
+
+POPTBLENTRY
+findNonTerminalEntry(ULONG opCode)
+{
+ ULONG index;
+
+ for ( index = 0 ; index < SEARCHNUM; index++ ) {
+
+ if ( ( opTable[index].eType == NON_TERMINAL_ETYPE ) &&
+ ( opTable[index].opCode == opCode ) ) {
+
+ return(&opTable[index]);
+ }
+ }
+}
+
+
+/* findFuncName - get string name for a function
+*
+* Purpose:
+* to get function name, given the function number, and a
+* pointer to the opTable entry for the NON_TERMINAL_ETYPE
+* opcode associated with the function
+*
+* Input:
+* pOpEntry - pointer to NON_TERMINAL_ETYPE in opTable
+* function - the function value to be looked up
+*
+* Output:
+* pointer to string mnemonic for the function
+*
+***********************************************************************/
+
+char *
+findFuncName(POPTBLENTRY pEntry, ULONG function)
+{
+ int cIndex;
+ POPTBLENTRY pFncEntry;
+
+ pFncEntry = pEntry->funcTable;
+ cIndex = (int)pEntry->funcTableSize;
+
+ //
+ // make sure that this entry pts to a function table
+ //
+
+ if (pEntry->eType != NON_TERMINAL_ETYPE) {
+ return("???");
+ }
+
+ while(cIndex-- > 0) {
+ if (function == pFncEntry->funcCode)
+ return(pFncEntry->pszAlphaName);
+ pFncEntry++;
+ };
+
+ return("???");
+}
+
+
+/** findFlagName - get the string associated with a flag
+*
+* Purpose - return a string associated with the flags for a
+* floating point instruction
+*
+* Input:
+* flag - the flags on the opcode
+* opcode - the opcode; if it's Cvt*, we use different flags
+*
+* Output:
+* pointer to string describing flags, or "/???"
+*
+***************/
+
+char *
+findFlagName(ULONG flag, ULONG function)
+{
+
+ PFPFLAGS table;
+
+ if ((function == CVTTQ_FUNC) || (function == CVTGQ_FUNC)) {
+ table = ConvertFlags;
+ } else {
+ table = FloatOpFlags;
+ }
+
+ while (table->flags != FPFLAGS_NOT_AN_ENTRY) {
+
+ if (table->flags == flag) {
+ return(table->flagname);
+ }
+ table++;
+ }
+
+ // no match found
+ //
+
+ return("/???");
+}
+
+
+/*** opTableInit - initialize fields used in and with the opTable
+*
+* Purpose:
+* This routine is called once, and sets up pointers to the
+* subtables embedded in the opTable, such as AddOpTab, and
+* sizes for these subtables. It also checks that all like
+* instructions are grouped together in the table, which is
+* the only requirement on it.
+*
+* Input:
+* None.
+*
+* Output:
+* None.
+*
+* Errors:
+* If the table is not properly organized (four types separated,
+* and the functions for a single opcode grouped), this prints a
+* messages and fails
+*
+* Exceptions:
+* None.
+*
+*************************************************************************/
+
+void
+opTableInit()
+{
+
+ ULONG typesDone[4] = {0,0,0,0};
+
+ ULONG palDone, arithDone, bitDone, byteDone, jmpDone;
+ ULONG fpopDone, vaxDone, IEEEDone, mulDone, memSpcDone;
+
+ ULONG index;
+
+ POPTBLENTRY entry;
+
+ ENTRY_TYPE curType = NOT_AN_ETYPE;
+ ULONG curFunc = NO_FUNC; // OPCODE field in func entry
+
+ //
+ // To set the end of the table, and its size, without having
+ // nested case statements, maintain pointers to the entry and
+ // function tables we are currently walking through
+ //
+
+ PULONG curTypeSize, curFuncSize;
+ POPTBLENTRY * curTypeTable, * curFuncTable;
+
+
+ //
+ // these will be reset before they are needed, but not before
+ // they are used.
+ //
+
+ curTypeTable = (POPTBLENTRY *)&curTypeTable;
+ curTypeSize = (PULONG)&curTypeSize;
+ curFuncTable = (POPTBLENTRY *)&curFuncTable;
+ curFuncSize = (PULONG)&curFuncSize;
+
+ palDone = arithDone = bitDone = byteDone = jmpDone = 0;
+ fpopDone = vaxDone = IEEEDone = mulDone = memSpcDone = 0;
+
+ for (index = 0 ; index < SEARCHNUM; index++) {
+
+ entry = &opTable[index];
+
+ switch(entry->eType) {
+
+ case INVALID_ETYPE:
+
+ if (curType == entry->eType)
+ continue;
+
+ //
+ // The entries must be together; if this is a
+ // new type, we must never have seen it before
+ //
+
+ //
+ // Finish off the old tables
+ //
+
+ *curTypeSize = entry - *curTypeTable;
+ if (curType == FUNCTION_ETYPE) {
+ *curFuncSize = entry - *curFuncTable;
+ }
+
+ //
+ // Set up the new table
+ //
+
+ InvalidTab = entry;
+ curTypeSize = &InvalidTabSize;
+ curTypeTable = &InvalidTab;
+ curType = INVALID_ETYPE;
+ typesDone[INVALID_ETYPE] = 1;
+ break;
+
+ case NON_TERMINAL_ETYPE:
+
+ if (curType == entry->eType)
+ continue;
+
+ *curTypeSize = entry - *curTypeTable;
+ if (curType == FUNCTION_ETYPE) {
+ *curFuncSize = entry - *curFuncTable;
+ }
+
+ NonTerminalTab = entry;
+ curTypeSize = &NonTerminalTabSize;
+ curTypeTable = &NonTerminalTab;
+ curType = NON_TERMINAL_ETYPE;
+ typesDone[NON_TERMINAL_ETYPE] = 1;
+ break;
+
+ case TERMINAL_ETYPE:
+
+ if (curType == entry->eType)
+ continue;
+
+ *curTypeSize = entry - *curTypeTable;
+ if (curType == FUNCTION_ETYPE) {
+ *curFuncSize = entry - *curFuncTable;
+ }
+
+ TerminalTab = entry;
+ curTypeSize = &TerminalTabSize;
+ curTypeTable = &TerminalTab;
+ curType = TERMINAL_ETYPE;
+ typesDone[TERMINAL_ETYPE] = 1;
+ break;
+
+
+ case FUNCTION_ETYPE:
+
+ if (entry->opCode == curFunc)
+ continue;
+
+ //
+ // Take care of a new eType table; this exactly
+ // parallels the three cases above (*_ETYPE)
+ //
+
+ if (curType != FUNCTION_ETYPE) {
+
+ *curTypeSize = entry - *curTypeTable;
+
+ FunctionTab = entry;
+ curTypeSize = &FunctionTabSize;
+ curTypeTable = &FunctionTab;
+ curType = FUNCTION_ETYPE;
+ typesDone[FUNCTION_ETYPE] = 1;
+
+ }
+
+ //
+ // Next, handle a new function table when this is a new
+ // function (==> when this is the first entry in the
+ // FunctionTab)
+ //
+
+
+ switch(entry->opCode) {
+
+ POPTBLENTRY e;
+
+ case CALLPAL_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(CALLPAL_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = CALLPAL_OP;
+ palDone = 1;
+
+ break;
+
+ case ARITH_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(ARITH_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = ARITH_OP;
+ arithDone = 1;
+
+ break;
+
+ case BIT_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(BIT_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = BIT_OP;
+ bitDone = 1;
+
+ break;
+
+ case BYTE_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(BYTE_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = BYTE_OP;
+ byteDone = 1;
+
+ break;
+
+ case SEXT_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(SEXT_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = SEXT_OP;
+ byteDone = 1;
+
+ break;
+
+ case MUL_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(MUL_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = MUL_OP;
+ mulDone = 1;
+
+ break;
+
+ case MEMSPC_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(MEMSPC_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = MEMSPC_OP;
+ memSpcDone = 1;
+
+ break;
+
+ case JMP_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(JMP_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = JMP_OP;
+ jmpDone = 1;
+
+ break;
+
+ case VAXFP_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(VAXFP_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = VAXFP_OP;
+ vaxDone = 1;
+
+ break;
+
+ case IEEEFP_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(IEEEFP_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = IEEEFP_OP;
+ IEEEDone = 1;
+
+ break;
+
+ case FPOP_OP:
+
+ *curFuncSize = entry - *curFuncTable;
+
+ e = findNonTerminalEntry(FPOP_OP);
+ e->funcTable = entry;
+ curFuncSize = &(e->funcTableSize);
+ curFuncTable = &(e->funcTable);
+
+ curFunc = FPOP_OP;
+ fpopDone = 1;
+
+ break;
+
+ default:
+ break;
+
+ } // end of Function table switch
+
+ break;
+
+ default:
+ break;
+
+ } // end of etype table switch
+ } // end of For switch
+
+ //
+ // close out the size of the last tables
+ //
+
+ if (curType == FUNCTION_ETYPE) {
+ *curFuncSize = &opTable[SEARCHNUM] - *curFuncTable;
+ }
+ *curTypeSize = &opTable[SEARCHNUM] - *curTypeTable;
+} // end of opTableInit
+
+/*******************************************
+//
+// These routines are part of the assembler, which is not
+// yet referenced in windbg, so these are place holders till then
+//
+
+
+ULONG ParseIntMemory (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseFltMemory (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseMemSpec (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseJump (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseIntBranch (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseFltBranch (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseIntOp (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParsePal (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+ULONG ParseUnknown (PUCHAR a, PUCHAR * b, POPTBLENTRY c, PULONG d)
+{
+ return(0);
+}
+
+*******************************************/
diff --git a/private/windbg/em/p_alpha/optable.h b/private/windbg/em/p_alpha/optable.h
new file mode 100644
index 000000000..97e6a4bfc
--- /dev/null
+++ b/private/windbg/em/p_alpha/optable.h
@@ -0,0 +1,123 @@
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ optable.h
+
+Abstract:
+
+ Definitions for -
+ Table of operations, their names and charactersitics
+ Used by ntsd, windbg and acc's dissassembler
+
+Author:
+
+ Miche Baker-Harvey (mbh) 10-Jan-1993
+
+Revision History:
+
+--*/
+
+#ifndef _OPTABLE_
+#define _OPTABLE_
+
+//
+// Each entry in the opTable is either for a
+// + function - one option on a particular opcode
+// + terminal opcode - an opcode without a function field
+// the above two can both appear directly in disassembly
+//
+// + non terminal opcode - an opcode with a function field:
+// these entries do not represent values which can be
+// executed directly: they require a function entry.
+//
+// + invalid opcode - this is an opcode reserved to digital
+//
+
+typedef enum ENTRY_TYPE {
+
+ INVALID_ETYPE,
+ NON_TERMINAL_ETYPE,
+ TERMINAL_ETYPE,
+ FUNCTION_ETYPE,
+ NOT_AN_ETYPE
+
+} ENTRY_TYPE;
+
+
+#define NO_FUNC (ULONG)-1
+
+typedef ULONG (* PFOPPARSE)();
+
+typedef struct _OPTBLENTRY {
+
+ union {
+
+ struct {
+
+ PUCHAR _pszName; // Name of the instruction
+ PFOPPARSE _parsFunc; // Function to parse operands
+
+ } s0; // functions and terminal opcodes
+
+ struct {
+
+ struct _OPTBLENTRY * _funcTable; // Describes funcs for opcode
+ ULONG _funcTableSize; // Number of possible funcs
+
+ } s1; // non-terminal opcodes
+
+ } u;
+
+ //
+ // These fields describe the instruction
+ //
+
+ ULONG opCode; // Top 6 bits of a 32-bit alpha instr
+ ULONG funcCode; // Function; meaning is opcode dependent
+ ULONG iType; // type of the instr: branch, fp, mem...
+ // values are ALPHA_* in alphaops.h
+
+ ENTRY_TYPE eType; // type of this entry in the opTable
+
+} OPTBLENTRY, * POPTBLENTRY;
+
+//
+// MBH - hack workaround:
+// I tried to do this with nameless functions and structures;
+// it works just fine on ALPHA, but dies on 386, so use this
+// ugly hack instead.
+// The name "pszAlphaName" is used instead of the more obvious
+// "pszName" because other structures contain pszName.
+//
+#define pszAlphaName u.s0._pszName
+#define parsFunc u.s0._parsFunc
+#define funcTable u.s1._funcTable
+#define funcTableSize u.s1._funcTableSize
+
+POPTBLENTRY findNonTerminalEntry(ULONG);
+POPTBLENTRY findStringEntry(PUCHAR);
+POPTBLENTRY findOpCodeEntry(ULONG);
+char * findFuncName(POPTBLENTRY, ULONG);
+char * findFlagName(ULONG, ULONG);
+void printTable();
+void opTableInit();
+
+//
+// This structure is used for the floating point flag names.
+//
+
+#define FPFLAGS_NOT_AN_ENTRY 0xffffffff
+
+typedef struct _FPFLAGS {
+
+ ULONG flags; // the flags on the opcode
+ PUCHAR flagname; // the string mnemonic for the flags
+
+} FPFLAGS, * PFPFLAGS;
+
+
+#endif // _OPTABLE_
diff --git a/private/windbg/em/p_alpha/precomp.h b/private/windbg/em/p_alpha/precomp.h
new file mode 100644
index 000000000..073b263b3
--- /dev/null
+++ b/private/windbg/em/p_alpha/precomp.h
@@ -0,0 +1,67 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "biavst.h"
+
+#include <windows.h>
+#include <dde.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <memory.h>
+#include <string.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#ifdef OSDEBUG4
+
+
+#include "od.h"
+#include "odp.h"
+#include "emdm.h"
+
+#include "emdata.h"
+#include "emproto.h"
+
+#include "dbgver.h"
+
+#else // OSDEBUG4
+
+#include "defs.h"
+
+#include "mm.h"
+#include "ll.h"
+#include "tl.h"
+#include "od.h"
+#include "dbgver.h"
+#include "emdm.h"
+#include "osdem.h"
+#include "emdata.h"
+#include "emproto.h"
+#include "osassert.h"
+
+
+#include "lbhpt.h"
+#include "llhpt.h"
+#include "mhhpt.h"
+
+#endif // OSDEBUG4
diff --git a/private/windbg/em/p_alpha/regs.h b/private/windbg/em/p_alpha/regs.h
new file mode 100644
index 000000000..65bd28d5e
--- /dev/null
+++ b/private/windbg/em/p_alpha/regs.h
@@ -0,0 +1,77 @@
+//
+// Technically, all these registers are 64 bits, not 32 bits
+// but I don't know yet if WINDBG can handle that.
+// MBH TODO bugbug
+#define RSIZE 64
+
+ { szR0, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntV0 },
+ { szR1, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT0 },
+ { szR2, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT1 },
+ { szR3, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT2 },
+ { szR4, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT3 },
+ { szR5, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT4 },
+ { szR6, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT5 },
+ { szR7, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT6 },
+ { szR8, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT7 },
+ { szR9, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntS0 },
+ { szR10, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntS1 },
+ { szR11, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntS2 },
+ { szR12, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntS3 },
+ { szR13, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntS4 },
+ { szR14, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntS5 },
+ { szR15, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntFP },
+ { szR16, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntA0 },
+ { szR17, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntA1 },
+ { szR18, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntA2 },
+ { szR19, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntA3 },
+ { szR20, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntA4 },
+ { szR21, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntA5 },
+ { szR22, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT8 },
+ { szR23, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT9 },
+ { szR24, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT10 },
+ { szR25, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT11 },
+ { szR26, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntRA },
+ { szR27, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntT12 },
+ { szR28, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntAT },
+ { szR29, rtCPU | rtRegular | rtInteger | rtExtended, RSIZE, CV_ALPHA_IntGP },
+ { szR30, rtCPU | rtRegular | rtInteger | rtExtended | rtFrame, RSIZE, CV_ALPHA_IntSP },
+ { szR31, rtCPU | rtInteger | rtInvisible, RSIZE, CV_ALPHA_IntZERO },
+
+ { szFpcr,rtFPU | rtRegular | rtExtended | rtInteger, RSIZE, CV_ALPHA_Fpcr},
+ { szSoftFpcr,
+ rtFPU | rtRegular | rtExtended | rtInteger, RSIZE, CV_ALPHA_SoftFpcr},
+ { szFir, rtCPU | rtExtended | rtInteger | rtExtended | rtPC, 64, CV_ALPHA_Fir },
+ { szPsr, rtCPU | rtExtended | rtInteger | rtExtended, 32, CV_ALPHA_Psr },
+
+ { szF0, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF0 },
+ { szF1, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF1 },
+ { szF2, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF2 },
+ { szF3, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF3 },
+ { szF4, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF4 },
+ { szF5, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF5 },
+ { szF6, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF6 },
+ { szF7, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF7 },
+ { szF8, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF8 },
+ { szF9, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF9 },
+ { szF10, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF10 },
+ { szF11, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF11 },
+ { szF12, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF12 },
+ { szF13, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF13 },
+ { szF14, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF14 },
+ { szF15, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF15 },
+ { szF16, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF16 },
+ { szF17, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF17 },
+ { szF18, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF18 },
+ { szF19, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF19 },
+ { szF20, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF20 },
+ { szF21, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF21 },
+ { szF22, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF22 },
+ { szF23, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF23 },
+ { szF24, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF24 },
+ { szF25, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF25 },
+ { szF26, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF26 },
+ { szF27, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF27 },
+ { szF28, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF28 },
+ { szF29, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF29 },
+ { szF30, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF30 },
+ { szF31, rtFPU | rtRegular | rtFloat | rtExtended, RSIZE, CV_ALPHA_FltF31 }
diff --git a/private/windbg/em/p_alpha/sources b/private/windbg/em/p_alpha/sources
new file mode 100644
index 000000000..64d282096
--- /dev/null
+++ b/private/windbg/em/p_alpha/sources
@@ -0,0 +1,66 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=emalp
+
+TARGETNAME=emalp
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+DLLENTRY=DllInit
+
+SOURCES= \
+ asm.c \
+ asmfront.c \
+ d3.c \
+ emdp.c \
+ emdp2.c \
+ emdp3.c \
+ emdpdev.c \
+ optable.c \
+ wintrans.c \
+ em.rc
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_ALPHA
+
+INCLUDES= \
+ ..; \
+ ..\..\osdebug\include; \
+ ..\..\osdebug; \
+ $(BASEDIR)\private\ntos\inc
+
+CONDITIONAL_INCLUDES=odp.h win32msg.h xosd.h
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/em/p_alpha/strings.h b/private/windbg/em/p_alpha/strings.h
new file mode 100644
index 000000000..df21cff54
--- /dev/null
+++ b/private/windbg/em/p_alpha/strings.h
@@ -0,0 +1,423 @@
+/*
+** STRINGS.H
+**
+** This file contains all strings which are used in the EM for display
+** purposes. This is done for internationalization purposes.
+**
+** strings.c defines DEFINE_STRINGS before including this file. Other
+** source files just include this file normally.
+*/
+
+/*
+** Modified by Miche Baker-Harvey for Alpha - September 12, 1992
+** Copyright 1992 Digital Equipment Corporation
+*/
+
+/*
+** strings.c should define DEFINE_STRINGS before including this file,
+** so that the strings will be defined rather than just declared.
+*/
+
+#ifdef DEFINE_STRINGS
+#define DECL_STR(name, value) char name[] = value
+#undef DEFINE_STRINGS
+#else
+#define DECL_STR(name, value) extern char name[]
+#endif
+
+
+
+//
+// The floating point registers
+//
+
+DECL_STR( szF0 , "f0");
+DECL_STR( szF1 , "f1");
+DECL_STR( szF2 , "f2");
+DECL_STR( szF3 , "f3");
+DECL_STR( szF4 , "f4");
+DECL_STR( szF5 , "f5");
+DECL_STR( szF6 , "f6");
+DECL_STR( szF7 , "f7");
+DECL_STR( szF8 , "f8");
+DECL_STR( szF9 , "f9");
+DECL_STR( szF10 , "f10");
+DECL_STR( szF11 , "f11");
+DECL_STR( szF12 , "f12");
+DECL_STR( szF13 , "f13");
+DECL_STR( szF14 , "f14");
+DECL_STR( szF15 , "f15");
+DECL_STR( szF16 , "f16");
+DECL_STR( szF17 , "f17");
+DECL_STR( szF18 , "f18");
+DECL_STR( szF19 , "f19");
+DECL_STR( szF20 , "f20");
+DECL_STR( szF21 , "f21");
+DECL_STR( szF22 , "f22");
+DECL_STR( szF23 , "f23");
+DECL_STR( szF24 , "f24");
+DECL_STR( szF25 , "f25");
+DECL_STR( szF26 , "f26");
+DECL_STR( szF27 , "f27");
+DECL_STR( szF28 , "f28");
+DECL_STR( szF29 , "f29");
+DECL_STR( szF30 , "f30");
+DECL_STR( szF31 , "f31");
+
+//
+// The integer registers
+//
+
+DECL_STR( szR0 , V0_REG_STR);
+DECL_STR( szR1 , T0_REG_STR);
+DECL_STR( szR2 , T1_REG_STR);
+DECL_STR( szR3 , T2_REG_STR);
+DECL_STR( szR4 , T3_REG_STR);
+DECL_STR( szR5 , T4_REG_STR);
+DECL_STR( szR6 , T5_REG_STR);
+DECL_STR( szR7 , T6_REG_STR);
+DECL_STR( szR8 , T7_REG_STR);
+DECL_STR( szR9 , S0_REG_STR);
+DECL_STR( szR10 , S1_REG_STR);
+DECL_STR( szR11 , S2_REG_STR);
+DECL_STR( szR12 , S3_REG_STR);
+DECL_STR( szR13 , S4_REG_STR);
+DECL_STR( szR14 , S5_REG_STR);
+DECL_STR( szR15 , FP_REG_STR);
+DECL_STR( szR16 , A0_REG_STR);
+DECL_STR( szR17 , A1_REG_STR);
+DECL_STR( szR18 , A2_REG_STR);
+DECL_STR( szR19 , A3_REG_STR);
+DECL_STR( szR20 , A4_REG_STR);
+DECL_STR( szR21 , A5_REG_STR);
+DECL_STR( szR22 , T8_REG_STR);
+DECL_STR( szR23 , T9_REG_STR);
+DECL_STR( szR24 , T10_REG_STR);
+DECL_STR( szR25 , T11_REG_STR);
+DECL_STR( szR26 , RA_REG_STR);
+DECL_STR( szR27 , T12_REG_STR);
+DECL_STR( szR28 , AT_REG_STR);
+DECL_STR( szR29 , GP_REG_STR);
+DECL_STR( szR30 , SP_REG_STR);
+DECL_STR( szR31 , ZERO_REG_STR);
+
+//
+// ALPHA other accessible registers
+//
+
+DECL_STR( szFpcr , "fpcr"); // floating point control register
+DECL_STR( szSoftFpcr , "softFpcr"); // floating point control register
+DECL_STR( szFir , "fir"); // fetched/faulting instruction: nextPC
+DECL_STR( szPsr , "psr"); // processor status register: see flags
+
+//
+// these flags are associated with the psr);
+// defined in ntalpha.h.
+DECL_STR( szFlagMode , "mode"); // mode: 1? user : system
+DECL_STR( szFlagIe , "ie"); // interrupt enable
+DECL_STR( szFlagIrql , "irql"); // IRQL level: 3 bits
+DECL_STR( szFlagInt5 , "int5");
+DECL_STR( szFlagInt4 , "int4");
+DECL_STR( szFlagInt3 , "int3");
+DECL_STR( szFlagInt2 , "int2");
+DECL_STR( szFlagInt1 , "int1");
+DECL_STR( szFlagInt0 , "int0");
+
+DECL_STR( szEaPReg , "$ea");
+DECL_STR( szExpPReg , "$exp");
+DECL_STR( szRaPReg , "$ra");
+DECL_STR( szPPReg , "$p");
+
+DECL_STR( szGPReg , "$gp");
+
+DECL_STR( szU0Preg , "$u0");
+DECL_STR( szU1Preg , "$u1");
+DECL_STR( szU2Preg , "$u2");
+DECL_STR( szU3Preg , "$u3");
+DECL_STR( szU4Preg , "$u4");
+DECL_STR( szU5Preg , "$u5");
+DECL_STR( szU6Preg , "$u6");
+DECL_STR( szU7Preg , "$u7");
+DECL_STR( szU8Preg , "$u8");
+DECL_STR( szU9Preg , "$u9");
+
+
+//
+// Thread states
+//
+
+
+DECL_STR(SzFrozen, "Frozen");
+DECL_STR(SzSuspended, "Suspended");
+DECL_STR(SzBlocked, "Blocked");
+
+DECL_STR(SzRunnable, "Runnable");
+DECL_STR(SzRunning, "Running");
+DECL_STR(SzStopped, "Stopped");
+DECL_STR(SzExiting, "Exiting");
+DECL_STR(SzDead, "Dead");
+DECL_STR(SzUnknown, "UNKNOWN");
+
+DECL_STR(SzExcept1st, "Except1st");
+DECL_STR(SzExcept2nd, "Except2nd");
+DECL_STR(SzRipped, "RIP");
+
+DECL_STR(SzCritSec, "CritSec");
+
+DECL_STR(SzStandard, "Standard");
+
+//
+// taken from alphaops.h, and munged with emacs
+//
+
+DECL_STR( szLda, LDA_OP_STR );
+DECL_STR( szLdah, LDAH_OP_STR );
+DECL_STR( szLdq_u, LDQ_U_OP_STR );
+DECL_STR( szStq_u, STQ_U_OP_STR );
+DECL_STR( szLdf, LDF_OP_STR );
+DECL_STR( szLdg, LDG_OP_STR );
+DECL_STR( szLds, LDS_OP_STR );
+DECL_STR( szLdt, LDT_OP_STR );
+DECL_STR( szLdbu, LDBU_OP_STR );
+DECL_STR( szLdwu, LDWU_OP_STR );
+DECL_STR( szStf, STF_OP_STR );
+DECL_STR( szStg, STG_OP_STR );
+DECL_STR( szSts, STS_OP_STR );
+DECL_STR( szStt, STT_OP_STR );
+DECL_STR( szStb, STB_OP_STR );
+DECL_STR( szStw, STW_OP_STR );
+DECL_STR( szLdl, LDL_OP_STR );
+DECL_STR( szLdq, LDQ_OP_STR );
+DECL_STR( szLdl_l, LDL_L_OP_STR );
+DECL_STR( szLdq_l, LDQ_L_OP_STR );
+DECL_STR( szStl, STL_OP_STR );
+DECL_STR( szStq, STQ_OP_STR );
+DECL_STR( szStl_c, STL_C_OP_STR );
+DECL_STR( szStq_c, STQ_C_OP_STR );
+DECL_STR( szBr, BR_OP_STR );
+DECL_STR( szFbeq, FBEQ_OP_STR );
+DECL_STR( szFblt, FBLT_OP_STR );
+DECL_STR( szFble, FBLE_OP_STR );
+DECL_STR( szBsr, BSR_OP_STR );
+DECL_STR( szFbne, FBNE_OP_STR );
+DECL_STR( szFbge, FBGE_OP_STR );
+DECL_STR( szFbgt, FBGT_OP_STR );
+DECL_STR( szBlbc, BLBC_OP_STR );
+DECL_STR( szBeq, BEQ_OP_STR );
+DECL_STR( szBlt, BLT_OP_STR );
+DECL_STR( szBle, BLE_OP_STR );
+DECL_STR( szBlbs, BLBS_OP_STR );
+DECL_STR( szBne, BNE_OP_STR );
+DECL_STR( szBge, BGE_OP_STR );
+DECL_STR( szBgt, BGT_OP_STR );
+DECL_STR( szMb, MB_FUNC_STR );
+DECL_STR( szWmb, MB1_FUNC_STR );
+DECL_STR( szMb2, MB2_FUNC_STR );
+DECL_STR( szMb3, MB3_FUNC_STR );
+DECL_STR( szFetch, FETCH_FUNC_STR );
+DECL_STR( szRs, RS_FUNC_STR );
+DECL_STR( szTrapb, TRAPB_FUNC_STR );
+DECL_STR( szExcb, EXCB_FUNC_STR );
+DECL_STR( szFetch_m, FETCH_M_FUNC_STR );
+DECL_STR( szRpcc, RPCC_FUNC_STR );
+DECL_STR( szRc, RC_FUNC_STR );
+DECL_STR( szJmp, JMP_FUNC_STR );
+DECL_STR( szJsr, JSR_FUNC_STR );
+DECL_STR( szRet, RET_FUNC_STR );
+DECL_STR( szJsr_co, JSR_CO_FUNC_STR );
+
+DECL_STR( szAddl, ADDL_FUNC_STR );
+DECL_STR( szAddlv, ADDLV_FUNC_STR );
+DECL_STR( szS4addl, S4ADDL_FUNC_STR );
+DECL_STR( szS8addl, S8ADDL_FUNC_STR );
+DECL_STR( szAddq, ADDQ_FUNC_STR );
+DECL_STR( szAddqv, ADDQV_FUNC_STR );
+DECL_STR( szS4addq, S4ADDQ_FUNC_STR );
+DECL_STR( szS8addq, S8ADDQ_FUNC_STR );
+DECL_STR( szSubl, SUBL_FUNC_STR );
+DECL_STR( szSublv, SUBLV_FUNC_STR );
+DECL_STR( szS4subl, S4SUBL_FUNC_STR );
+DECL_STR( szS8subl, S8SUBL_FUNC_STR );
+DECL_STR( szSubq, SUBQ_FUNC_STR );
+DECL_STR( szSubqv, SUBQV_FUNC_STR );
+DECL_STR( szS4subq, S4SUBQ_FUNC_STR );
+DECL_STR( szS8subq, S8SUBQ_FUNC_STR );
+
+
+DECL_STR( szCmpeq, CMPEQ_FUNC_STR );
+DECL_STR( szCmplt, CMPLT_FUNC_STR );
+DECL_STR( szCmple, CMPLE_FUNC_STR );
+DECL_STR( szCmpult, CMPULT_FUNC_STR );
+DECL_STR( szCmpule, CMPULE_FUNC_STR );
+DECL_STR( szCmpbge, CMPBGE_FUNC_STR );
+DECL_STR( szAnd, AND_FUNC_STR );
+DECL_STR( szBic, BIC_FUNC_STR );
+DECL_STR( szBis, BIS_FUNC_STR );
+DECL_STR( szEqv, EQV_FUNC_STR );
+DECL_STR( szOrnot, ORNOT_FUNC_STR );
+DECL_STR( szXor, XOR_FUNC_STR );
+DECL_STR( szCmoveq, CMOVEQ_FUNC_STR );
+DECL_STR( szCmovge, CMOVGE_FUNC_STR );
+DECL_STR( szCmovgt, CMOVGT_FUNC_STR );
+DECL_STR( szCmovlbc, CMOVLBC_FUNC_STR );
+DECL_STR( szCmovlbs, CMOVLBS_FUNC_STR );
+DECL_STR( szCmovle, CMOVLE_FUNC_STR );
+DECL_STR( szCmovlt, CMOVLT_FUNC_STR );
+DECL_STR( szCmovne, CMOVNE_FUNC_STR );
+DECL_STR( szSll, SLL_FUNC_STR );
+DECL_STR( szSrl, SRL_FUNC_STR );
+DECL_STR( szSra, SRA_FUNC_STR );
+DECL_STR( szExtbl, EXTBL_FUNC_STR );
+DECL_STR( szExtwl, EXTWL_FUNC_STR );
+DECL_STR( szExtll, EXTLL_FUNC_STR );
+DECL_STR( szExtql, EXTQL_FUNC_STR );
+DECL_STR( szExtwh, EXTWH_FUNC_STR );
+DECL_STR( szExtlh, EXTLH_FUNC_STR );
+DECL_STR( szExtqh, EXTQH_FUNC_STR );
+DECL_STR( szInsbl, INSBL_FUNC_STR );
+DECL_STR( szInswl, INSWL_FUNC_STR );
+DECL_STR( szInsll, INSLL_FUNC_STR );
+DECL_STR( szInsql, INSQL_FUNC_STR );
+DECL_STR( szInswh, INSWH_FUNC_STR );
+DECL_STR( szInslh, INSLH_FUNC_STR );
+DECL_STR( szInsqh, INSQH_FUNC_STR );
+DECL_STR( szMskbl, MSKBL_FUNC_STR );
+DECL_STR( szMskwl, MSKWL_FUNC_STR );
+DECL_STR( szMskll, MSKLL_FUNC_STR );
+DECL_STR( szMskql, MSKQL_FUNC_STR );
+DECL_STR( szMskwh, MSKWH_FUNC_STR );
+DECL_STR( szMsklh, MSKLH_FUNC_STR );
+DECL_STR( szMskqh, MSKQH_FUNC_STR );
+DECL_STR( szSextb, SEXTB_FUNC_STR );
+DECL_STR( szSextw, SEXTW_FUNC_STR );
+DECL_STR( szZap, ZAP_FUNC_STR );
+DECL_STR( szZapnot, ZAPNOT_FUNC_STR );
+DECL_STR( szMull, MULL_FUNC_STR );
+DECL_STR( szMullv, MULLV_FUNC_STR );
+DECL_STR( szMulq, MULQ_FUNC_STR );
+DECL_STR( szMulqv, MULQV_FUNC_STR );
+DECL_STR( szUmulh, UMULH_FUNC_STR );
+DECL_STR( szCvtlq, CVTLQ_FUNC_STR );
+DECL_STR( szCpys, CPYS_FUNC_STR );
+DECL_STR( szCpysn, CPYSN_FUNC_STR );
+DECL_STR( szCpyse, CPYSE_FUNC_STR );
+DECL_STR( szMt_fpcr, MT_FPCR_FUNC_STR );
+DECL_STR( szMf_fpcr, MF_FPCR_FUNC_STR );
+DECL_STR( szFcmoveq, FCMOVEQ_FUNC_STR );
+DECL_STR( szFcmovne, FCMOVNE_FUNC_STR );
+DECL_STR( szFcmovlt, FCMOVLT_FUNC_STR );
+DECL_STR( szFcmovge, FCMOVGE_FUNC_STR );
+DECL_STR( szFcmovle, FCMOVLE_FUNC_STR );
+DECL_STR( szFcmovgt, FCMOVGT_FUNC_STR );
+DECL_STR( szCvtql, CVTQL_FUNC_STR );
+DECL_STR( szCvtqlv, CVTQLV_FUNC_STR );
+DECL_STR( szCvtqlsv, CVTQLSV_FUNC_STR );
+DECL_STR( szAdds, ADDS_FUNC_STR );
+DECL_STR( szSubs, SUBS_FUNC_STR );
+DECL_STR( szMuls, MULS_FUNC_STR );
+DECL_STR( szDivs, DIVS_FUNC_STR );
+DECL_STR( szAddt, ADDT_FUNC_STR );
+DECL_STR( szSubt, SUBT_FUNC_STR );
+DECL_STR( szMult, MULT_FUNC_STR );
+DECL_STR( szDivt, DIVT_FUNC_STR );
+DECL_STR( szCmptun, CMPTUN_FUNC_STR );
+DECL_STR( szCmpteq, CMPTEQ_FUNC_STR );
+DECL_STR( szCmptlt, CMPTLT_FUNC_STR );
+DECL_STR( szCmptle, CMPTLE_FUNC_STR );
+DECL_STR( szCvtts, CVTTS_FUNC_STR );
+DECL_STR( szCvttq, CVTTQ_FUNC_STR );
+DECL_STR( szCvtqs, CVTQS_FUNC_STR );
+DECL_STR( szCvtqt, CVTQT_FUNC_STR );
+DECL_STR( szAddf, ADDF_FUNC_STR );
+DECL_STR( szCvtdg, CVTDG_FUNC_STR );
+DECL_STR( szAddg, ADDG_FUNC_STR );
+DECL_STR( szCmpgeq, CMPGEQ_FUNC_STR );
+DECL_STR( szCmpglt, CMPGLT_FUNC_STR );
+DECL_STR( szCmpgle, CMPGLE_FUNC_STR );
+DECL_STR( szCvtgf, CVTGF_FUNC_STR );
+DECL_STR( szCvtgd, CVTGD_FUNC_STR );
+DECL_STR( szCvtqf, CVTQF_FUNC_STR );
+DECL_STR( szCvtqg, CVTQG_FUNC_STR );
+DECL_STR( szDivf, DIVF_FUNC_STR );
+DECL_STR( szDivg, DIVG_FUNC_STR );
+DECL_STR( szMulf, MULF_FUNC_STR );
+DECL_STR( szMulg, MULG_FUNC_STR );
+DECL_STR( szSubf, SUBF_FUNC_STR );
+DECL_STR( szSubg, SUBG_FUNC_STR );
+DECL_STR( szCvtgq, CVTGQ_FUNC_STR );
+DECL_STR( szC, C_FLAGS_STR );
+DECL_STR( szM, M_FLAGS_STR );
+DECL_STR( szNone, NONE_FLAGS_STR );
+DECL_STR( szD, D_FLAGS_STR );
+DECL_STR( szUc, UC_FLAGS_STR );
+DECL_STR( szVc, VC_FLAGS_STR );
+DECL_STR( szUm, UM_FLAGS_STR );
+DECL_STR( szVm, VM_FLAGS_STR );
+DECL_STR( szU, U_FLAGS_STR );
+DECL_STR( szV, V_FLAGS_STR );
+DECL_STR( szUd, UD_FLAGS_STR );
+DECL_STR( szVd, VD_FLAGS_STR );
+DECL_STR( szSc, SC_FLAGS_STR );
+DECL_STR( szS, S_FLAGS_STR );
+DECL_STR( szSuc, SUC_FLAGS_STR );
+DECL_STR( szSvc, SVC_FLAGS_STR );
+DECL_STR( szSum, SUM_FLAGS_STR );
+DECL_STR( szSvm, SVM_FLAGS_STR );
+DECL_STR( szSu, SU_FLAGS_STR );
+DECL_STR( szSv, SV_FLAGS_STR );
+DECL_STR( szSud, SUD_FLAGS_STR );
+DECL_STR( szSvd, SVD_FLAGS_STR );
+DECL_STR( szSuic, SUIC_FLAGS_STR );
+DECL_STR( szSvic, SVIC_FLAGS_STR );
+DECL_STR( szSuim, SUIM_FLAGS_STR );
+DECL_STR( szSvim, SVIM_FLAGS_STR );
+DECL_STR( szSui, SUI_FLAGS_STR );
+DECL_STR( szSvi, SVI_FLAGS_STR );
+DECL_STR( szSuid, SUID_FLAGS_STR );
+DECL_STR( szSvid, SVID_FLAGS_STR );
+
+DECL_STR( szBpt, BPT_FUNC_STR );
+DECL_STR( szCallsys, CALLSYS_FUNC_STR );
+DECL_STR( szImb, IMB_FUNC_STR );
+DECL_STR( szRdteb, RDTEB_FUNC_STR );
+DECL_STR( szGentrap, GENTRAP_FUNC_STR );
+DECL_STR( szKbpt, KBPT_FUNC_STR );
+DECL_STR( szCallKD, CALLKD_FUNC_STR );
+DECL_STR( szHalt, HALT_FUNC_STR );
+DECL_STR( szRestart, RESTART_FUNC_STR );
+DECL_STR( szDraina, DRAINA_FUNC_STR );
+DECL_STR( szInitpal, INITPAL_FUNC_STR );
+DECL_STR( szWrentry, WRENTRY_FUNC_STR );
+DECL_STR( szSwpirql, SWPIRQL_FUNC_STR );
+DECL_STR( szRdirql, RDIRQL_FUNC_STR );
+DECL_STR( szDi, DI_FUNC_STR );
+DECL_STR( szEi, EI_FUNC_STR );
+DECL_STR( szSwppal, SWPPAL_FUNC_STR );
+DECL_STR( szSsir, SSIR_FUNC_STR );
+DECL_STR( szCsir, CSIR_FUNC_STR );
+DECL_STR( szRfe, RFE_FUNC_STR );
+DECL_STR( szRetsys, RETSYS_FUNC_STR );
+DECL_STR( szSwpctx, SWPCTX_FUNC_STR );
+DECL_STR( szSwpprocess, SWPPROCESS_FUNC_STR );
+DECL_STR( szRdmces, RDMCES_FUNC_STR );
+DECL_STR( szWrmces, WRMCES_FUNC_STR );
+DECL_STR( szTbia, TBIA_FUNC_STR );
+DECL_STR( szTbis, TBIS_FUNC_STR );
+DECL_STR( szDtbis, DTBIS_FUNC_STR );
+DECL_STR( szRdksp, RDKSP_FUNC_STR );
+DECL_STR( szSwpksp, SWPKSP_FUNC_STR );
+DECL_STR( szRdpsr, RDPSR_FUNC_STR );
+DECL_STR( szRdpcr, RDPCR_FUNC_STR );
+DECL_STR( szRdthread, RDTHREAD_FUNC_STR );
+DECL_STR( szRdcounters, RDCOUNTERS_FUNC_STR );
+DECL_STR( szRdstate, RDSTATE_FUNC_STR );
+DECL_STR( szInitpcr, INITPCR_FUNC_STR );
+DECL_STR( szWrperfmon, WRPERFMON_FUNC_STR );
+DECL_STR( szMt, MTPR_OP_STR );
+DECL_STR( szMf, MFPR_OP_STR );
+DECL_STR( szHwld, HWLD_OP_STR );
+DECL_STR( szHwst, HWST_OP_STR );
+DECL_STR( szRei, REI_OP_STR );
+
+
+
diff --git a/private/windbg/em/p_alpha/wintrans.c b/private/windbg/em/p_alpha/wintrans.c
new file mode 100644
index 000000000..c5276532e
--- /dev/null
+++ b/private/windbg/em/p_alpha/wintrans.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\wintrans.c"
diff --git a/private/windbg/em/p_i386/asm.c b/private/windbg/em/p_i386/asm.c
new file mode 100644
index 000000000..287d9f543
--- /dev/null
+++ b/private/windbg/em/p_i386/asm.c
@@ -0,0 +1,1116 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "asm.h"
+
+#ifdef HOSTDOS
+extern int _far _cdecl toupper( int );
+extern int _far _cdecl tolower( int );
+#else // HOSTDOS
+#endif // HOSTDOS
+
+
+
+
+XOSD asm386 ( LPADDR, LSZ, LPBYTE, LPDWORD );
+
+int CheckData(void);
+LPBYTE ProcessOpcode ( LPXOSD );
+LPBYTE GetTemplate(LPBYTE);
+BYTE MatchTemplate ( LPDWORD );
+XOSD CheckTemplate(void);
+BYTE CheckPrefix(LPBYTE);
+XOSD AssembleInstr(void);
+BYTE MatchOperand(PASM_VALUE, BYTE);
+void OutputInstr(void);
+void OutputValue(BYTE size, LPBYTE pchValue);
+
+extern void error(ULONG);
+extern BYTE PeekAsmChar(void);
+extern ULONG PeekAsmToken(LPDWORD);
+extern void AcceptAsmToken(void);
+
+extern XOSD GetAsmExpr(PASM_VALUE, BYTE);
+extern XOSD GetAsmOperand(PASM_VALUE);
+extern LPBYTE SearchOpcode(LPBYTE);
+extern ULONG savedAsmClass;
+extern OPNDTYPE mapOpndType[];
+
+// flags and values to build the assembled instruction
+
+static BYTE fWaitPrfx; // if set, use WAIT prefix for float instr
+static BYTE fOpndOvrd; // if set, use operand override prefix
+static BYTE fAddrOvrd; // if set, use address override prefix
+static BYTE segOvrd; // if nonzero, use segment override prefix
+static BYTE preOpcode; // if nonzero, use byte before opcode
+static BYTE inOpcode; // opcode of instruction
+static BYTE postOpcode; // if nonzero, use byte after opcode
+static BYTE fModrm; // if set, modrm byte is defined
+static BYTE modModrm; // if fModrm, mod component of modrm
+static BYTE regModrm; // if fModrm, reg component of modrm
+static BYTE rmModrm; // if fModrm, rm component of modrm
+static BYTE fSib; // if set, sib byte is defined
+static BYTE scaleSib; // if fSib, scale component of sib
+static BYTE indexSib; // if fSib, index component of sib
+static BYTE baseSib; // if fSib, base component of sib
+static BYTE fSegPtr; // if set, segment for far call defined
+static USHORT segPtr; // if fSegPtr, value of far call segment
+static BYTE addrSize; // size of address: 0, 1, 2, 4
+static LONG addrValue; // value of address, if used
+static BYTE immedSize; // size of immediate: 0, 1, 2, 4
+static LONG immedValue; // value of immediate, if used
+static BYTE immedSize2; // size of second immediate, if used
+static LONG immedValue2; // value of second immediate, if used
+ ADDR addrAssem; // assembly address (formal)
+static LPBYTE lpbBin; // pointer to binary result string
+
+// flags and values of the current instruction template being used
+
+static BYTE cntTmplOpnd; // count of operands in template
+static BYTE tmplType[3]; // operand types for current template
+static BYTE tmplSize[3]; // operand sizes for current template
+static BYTE fForceSize; // set if operand size must be specified
+static BYTE fAddToOp; // set if addition to opcode
+static BYTE fNextOpnd; // set if character exists for next operand
+static BYTE fSegOnly; // set if only segment is used for operand
+static BYTE fMpNext; // set on 'Mv' tmpl if next tmpl is 'Mp'
+static BYTE segIndex; // index of segment for PUSH/POP
+
+// values describing the operands processed from the command line
+
+static BYTE cntInstOpnd; // count of operands read from input line
+static BYTE sizeOpnd; // size of operand for template with size v
+static ASM_VALUE avInstOpnd[3]; // asm values from input line
+
+ULONG baseDefault = 16;
+
+LSZ lszAsmLine = (LSZ)0L; // pointer to input line (formal)
+BYTE fDBit = TRUE; // set for 32-bit addr/operand mode
+
+HPID hpidAsm = 0;
+HTID htidAsm = 0;
+
+BYTE segToOvrdByte[] = {
+ 0x00, // segX
+ 0x26, // segES
+ 0x2e, // segCS
+ 0x36, // segSS
+ 0x3e, // segDS
+ 0x64, // segFS
+ 0x65 // segGS
+ };
+
+XOSD
+Assemble (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ LSZ lszInput
+ )
+{
+ XOSD xosd = xosdNone;
+ int cbLength;
+ BYTE rgb [ 60 ];
+
+ hpidAsm = hpid;
+ htidAsm = htid;
+
+ fDBit = ADDR_IS_FLAT(*lpaddr);
+
+ xosd = asm386 ( lpaddr, lszInput, rgb, &cbLength );
+
+ if ( xosd == xosdNone ) {
+#ifdef OSDEBUG4
+ DWORD cbw;
+ xosd = WriteBufferCache(hpid, htid, lpaddr, cbLength, rgb, &cbw);
+#else
+ (void) EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) lpaddr );
+ xosd = EMFunc ( emfWriteBuf, hpid, htid, cbLength, (LONG) rgb );
+#endif
+ if ( xosd == xosdNone ) {
+ lpaddr->addr.off += cbLength;
+ }
+ }
+
+ return xosd;
+}
+
+XOSD
+asm386 (
+ LPADDR lpaddr,
+ LSZ lszAssemble,
+ LPBYTE lpb,
+ LPDWORD lpcb
+ )
+{
+ LPBYTE lpbTemplate;
+
+ BYTE index; // loop index and temp
+ ULONG temp; // general temporary value
+
+ BYTE errIndex; // error index of all templates
+ int errType; // error type of all templates
+
+ // initialize flags and state variables
+
+ addrAssem = *lpaddr; // make assembly address global
+ lszAsmLine = lszAssemble; // make input string pointer global
+ lpbBin = lpb; // make binary string pointer global
+
+ savedAsmClass = (ULONG)-1; // no peeked token
+
+ segOvrd = 0; // no segment override
+ cntInstOpnd = 0; // no input operands read yet
+ fModrm = fSib = fSegPtr = FALSE; // no modrm, sib, or far seg
+ addrSize = immedSize = immedSize2 = 0; // no addr or immed
+
+ // from the string in lszAsmLine, parse and lookup the opcode
+ // to return a pointer to its template. check and process
+ // any prefixes, reading the next opcode for each prefix
+
+ do {
+ XOSD xosd = xosdNone;
+
+ lpbTemplate = ProcessOpcode ( &xosd );
+ if ( xosd != xosdNone ) {
+ return xosd;
+ }
+
+ } while ( CheckPrefix ( lpbTemplate ) );
+
+ // if a pending opcode to process, lpbTemplate is not NULL
+
+ if ( lpbTemplate ) {
+
+ // fNextOpnd is initially set on the condition of characters
+ // being available for the first operand on the input line
+
+ fNextOpnd = (BYTE)(PeekAsmToken(&temp) != ASM_EOL_CLASS);
+
+ // continue until match occurs or last template read
+
+ errIndex = 0; // start with no error
+ do {
+
+ // get infomation on next template - return pointer to
+ // next template or NULL if last in list
+
+ lpbTemplate = GetTemplate(lpbTemplate);
+
+ // match the loaded template against the operands input
+ // if mismatch, index has the operand index + 1 of
+ // the error while temp has the error type.
+
+ index = MatchTemplate(&temp);
+
+ if ( temp == (ULONG) xosdAsmExtraChars ) {
+ errType = (int) temp;
+ lpbTemplate = NULL;
+ }
+
+
+ // determine the error to report as templates are matched
+ // update errIndex to index if later operand
+ // if same operand index, prioritize to give best error:
+ // high: SIZE, BADRANGE, OVERFLOW
+ // medium: OPERAND
+ // low: TOOFEW, TOOMANY
+
+ if ( index > errIndex ||
+ ( index == errIndex &&
+ ( errType == xosdAsmTooFew ||
+ errType == xosdAsmTooMany ||
+ temp == (ULONG) xosdAsmSize ||
+ temp == (ULONG) xosdAsmBadRange ||
+ temp == (ULONG) xosdAsmOverFlow
+ )
+ )
+ ) {
+ errIndex = index;
+ errType = (int) temp;
+ }
+
+ } while ( index && lpbTemplate );
+
+ // if error occured on template match, process it
+
+ if ( index ) {
+ return errType;
+ }
+
+ // preliminary type and size matching has been
+ // successful on the current template.
+ // perform further checks for size ambiguity.
+ // at this point, the assembly is committed to the current
+ // template. either an error or a successful assembly
+ // follows.
+
+ if ( ( errType = CheckTemplate ( ) ) != xosdNone ) {
+ return errType;
+ }
+
+ // from the template and operand information, set the field
+ // information of the assembled instruction
+
+ if ( ( errType = AssembleInstr ( ) ) != xosdNone ) {
+ return errType;
+ }
+
+ // from the assembled instruction information, create the
+ // corresponding binary information
+
+ OutputInstr ( );
+
+ }
+
+ // return the size of the binary string output (can be zero)
+
+ *lpcb = (lpbBin - lpb); // length of binary string
+ return xosdNone;
+}
+
+LPBYTE ProcessOpcode ( LPXOSD lpxosd ) {
+ BYTE ch;
+ BYTE cbOpcode = 0;
+ LPBYTE lpbTemplate;
+ BYTE szOpcode[10];
+
+ // skip over any leading white space
+
+ do {
+ ch = *lszAsmLine++;
+ } while (ch == ' ' || ch == '\t');
+
+ // return NULL if end of line
+
+ if ( ch == '\0' ) {
+ return NULL;
+ }
+
+ // parse out opcode - first string [a-z] [0-9] (case insensitive)
+
+ ch = (BYTE) tolower ( ch );
+ while (
+ ( ( ch >= 'a' && ch <= 'z' ) || ( ch >= '0' && ch <= '9' ) ) &&
+ cbOpcode < 9
+ ) {
+ szOpcode [ cbOpcode++ ] = ch;
+ ch = (BYTE)tolower ( *lszAsmLine );
+
+ lszAsmLine += 1;
+ }
+
+ // if empty or too long, then error
+
+ if ( cbOpcode == 0 || cbOpcode == 9 ) {
+ *lpxosd = xosdAsmBadOpcode;
+ return NULL;
+ }
+
+ // allow opcode to have trailing colon and terminate
+
+ if (ch == ':') {
+ szOpcode[cbOpcode++] = ch;
+ ch = (BYTE)tolower(*lszAsmLine++);
+ }
+ szOpcode[cbOpcode] = '\0';
+ lszAsmLine--;
+
+ // get pointer to template series for opcode found
+
+ lpbTemplate = SearchOpcode(szOpcode);
+ if ( lpbTemplate == NULL ) {
+ *lpxosd = xosdAsmBadOpcode;
+ }
+
+ return lpbTemplate;
+}
+
+LPBYTE GetTemplate (LPBYTE lpbTemplate)
+{
+ BYTE ch;
+ BYTE ftEnd; // set if tEnd for last template in list
+ BYTE feEnd; // set if eEnd for last token in template
+
+ // initialize template variables and flags
+
+ cntTmplOpnd = segIndex = 0;
+ tmplType[0] = tmplType[1] = tmplType[2] = typNULL;
+ tmplSize[0] = tmplSize[1] = tmplSize[2] = sizeX;
+ fForceSize = fAddToOp = fSegOnly = fMpNext = FALSE;
+
+ fWaitPrfx = FALSE; // no WAIT prefix
+ fOpndOvrd = fAddrOvrd = FALSE; // no operand or addr overrides
+ preOpcode = postOpcode = 0; // no pre- or post-opcode
+ regModrm = 0; // this is part of some opcodes
+
+ ch = *lpbTemplate++;
+
+ // set pre-opcode for two-byte opcodes (0x0f??) and advance
+ // template if needed
+
+ if (ch == 0x0f) {
+ preOpcode = ch;
+ ch = *lpbTemplate++;
+ }
+
+ inOpcode = ch; // set opcode
+
+ // set post-opcode and advance template for floating-point
+ // instructions (0xd8 - 0xdf) using a second byte in
+ // the range 0xc0 - 0xff that is read from the template
+
+ if ((ch & ~0x7) == 0xd8) {
+ ch = *lpbTemplate;
+ if (ch >= 0xc0) {
+ postOpcode = ch;
+ lpbTemplate++;
+ }
+ }
+
+ // loop for each flag and/or operand token in template
+ // the last token in the list has the eEnd bit set.
+
+ do {
+ // read the next template token
+
+ ch = *lpbTemplate++;
+
+ // extract the tEnd and eEnd bits from the token
+
+ ftEnd = (BYTE)(ch & tEnd);
+ feEnd = (BYTE)(ch & eEnd);
+ ch &= ~(tEnd | eEnd);
+
+ // if extracted token is a flag, do the appropriate action
+
+ if (ch < asRegBase)
+ switch (ch) {
+ case as0x0a:
+
+ // the postOpcode is set for some decimal instructions
+
+ postOpcode = 0x0a;
+ break;
+
+ case asOpRg:
+
+ // fAddToOp is set if the register index is added
+ // directly to the base opcode value
+
+ fAddToOp = TRUE;
+ break;
+
+ case asSiz0:
+
+ // fOpndOvrd is set or cleared to force a 16-bit operand
+
+ fOpndOvrd = fDBit;
+ break;
+
+ case asSiz1:
+
+ // fOpndOvrd is set or cleared to force a 32-bit operand
+
+ fOpndOvrd = (BYTE)!fDBit;
+ break;
+
+ case asWait:
+
+ // the flag fWaitPrfx is set to emit WAIT before the
+ // instruction
+
+ fWaitPrfx = TRUE;
+ break;
+
+ case asSeg:
+
+ // in XLAT, the optional memory operand is used to
+ // just specify a segment override prefix
+
+ fSegOnly = TRUE;
+ break;
+
+ case asFSiz:
+
+ // fForceSize is set when a specific size of a memory
+ // operand must be given for some floating instrs
+
+ fForceSize = TRUE;
+ break;
+
+ case asMpNx:
+
+ // fMpNext is set when the next template operand is
+ // 'Mp' and is used to determine how to match
+ // 'Md' since it matches both 'Mp' and 'Mv'
+
+ fMpNext = TRUE;
+ break;
+ }
+
+ // if token is REG value bit, set the variable regModrm to
+ // set the opcode-dependent reg value in the modrm byte
+
+ else if (ch < opnBase)
+ regModrm = (BYTE)(ch - asRegBase);
+
+ // otherwise, token is operand descriptor.
+ // if segment operand, get segment number from template
+ // normalize and map to get operand type and size.
+
+ else {
+ if (ch == opnSeg)
+ segIndex = *lpbTemplate++;
+ ch -= opnBase;
+ tmplType[cntTmplOpnd] = mapOpndType[ch].type;
+ tmplSize[cntTmplOpnd++] = mapOpndType[ch].size;
+ }
+ }
+ while (!ftEnd);
+
+ // return either the pointer to the next template or NULL if
+ // the last template for the opcode has been processed
+
+ return (feEnd ? NULL : lpbTemplate);
+}
+
+BYTE MatchTemplate ( LPDWORD lpulErr ) {
+ BYTE fMatch = TRUE;
+ BYTE index;
+ ULONG temp;
+ PASM_VALUE pavInstOpnd; // pointer to current operand from input
+
+ // process matching for each operand in the specified template
+ // stop at last operand or when mismatch occurs
+
+ for (index = 0; index < cntTmplOpnd && fMatch; index++) {
+
+ // set pointer to current instruction operand
+
+ pavInstOpnd = &avInstOpnd[index];
+
+ // if input operand has not yet been read, check flag
+ // for existence and process it.
+
+ if (index == cntInstOpnd) {
+ fMatch = fNextOpnd;
+ *((XOSD*)lpulErr) = xosdAsmTooFew;
+ if ( fMatch ) {
+ cntInstOpnd++;
+ *lpulErr = (ULONG) GetAsmOperand(pavInstOpnd);
+
+ if ( *lpulErr != (ULONG) xosdNone ) {
+ return (BYTE) (index + 1);
+ }
+
+ // recompute existence of next possible operand
+ // comma implies TRUE, EOL implies FALSE, else error
+
+ temp = PeekAsmToken(&temp);
+ if (temp == ASM_COMMA_CLASS) {
+ AcceptAsmToken();
+ fNextOpnd = TRUE;
+ }
+ else if (temp == ASM_EOL_CLASS) {
+ fNextOpnd = FALSE;
+ }
+ else {
+ *lpulErr = (ULONG) xosdAsmExtraChars; // bad parse - immediate error
+ return cntTmplOpnd;
+ }
+ }
+ }
+
+ if (fMatch) {
+ fMatch = MatchOperand(pavInstOpnd, tmplType[index]);
+ *lpulErr = (ULONG) xosdAsmOperand;
+ }
+
+ // if the template and operand type match, do preliminary
+ // check on size based solely on template size specified
+
+ if (fMatch) {
+ if (tmplType[index] == typJmp) {
+
+ // for relative jumps, test if byte offset is
+ // sufficient by computing offset which is
+ // the target offset less the offset of the
+ // next instruction. (assume Jb instructions
+ // are two bytes in length.
+
+ temp = pavInstOpnd->value - ( offAddr ( addrAssem ) + 2);
+ fMatch = (BYTE)(tmplSize[index] == sizeV
+ || ((LONG)temp >= -0x80 && (LONG)temp <= 0x7f));
+ *lpulErr = (ULONG) xosdAsmBadRange;
+ }
+
+ else if (tmplType[index] == typImm) {
+
+ // for immediate operand,
+ // template sizeV matches sizeB, sizeW, sizeV (all)
+ // template sizeW matches sizeB, sizeW
+ // template sizeB matches sizeB
+
+ fMatch = (BYTE)(tmplSize[index] == sizeV
+ || pavInstOpnd->size == tmplSize[index]
+ || pavInstOpnd->size == sizeB);
+ *lpulErr = (ULONG) xosdAsmOverFlow;
+ }
+ else {
+
+ // for nonimmediate operand,
+ // template sizeX (unspecified) matches all
+ // operand sizeX (unspecified) matches all
+ // same template and operand size matches
+ // template sizeV matches operand sizeW and sizeD
+ // (EXCEPT for sizeD when fMpNext and fDBit set)
+ // template sizeP matches operand sizeD and sizeF
+ // template sizeA matches operand sizeD and sizeQ
+
+ fMatch = (BYTE)(tmplSize[index] == sizeX
+ || pavInstOpnd->size == sizeX
+ || tmplSize[index] == pavInstOpnd->size
+ || (tmplSize[index] == sizeV
+ && (pavInstOpnd->size == sizeW
+ || (pavInstOpnd->size == sizeD
+ && (!fMpNext || fDBit))))
+ || (tmplSize[index] == sizeP
+ && (pavInstOpnd->size == sizeD
+ || pavInstOpnd->size == sizeF))
+ || (tmplSize[index] == sizeA
+ && (pavInstOpnd->size == sizeD
+ || pavInstOpnd->size == sizeQ)));
+ *lpulErr = (ULONG) xosdAsmSize;
+ }
+ }
+ }
+
+ // if more operands to read, then no match
+
+ if (fMatch & fNextOpnd) {
+ fMatch = FALSE;
+ index++; // next operand is in error
+ *lpulErr = (ULONG) xosdAsmTooMany;
+ }
+
+ return fMatch ? (BYTE)0 : index;
+}
+
+XOSD CheckTemplate ( void ) {
+ BYTE index;
+
+ // if fForceSize is set, then the first (and only) operand is a
+ // memory type. return an error if its size is unspecified.
+
+ if (fForceSize && avInstOpnd[0].size == sizeX) {
+ return xosdAsmOperand;
+ }
+
+ // test for template with leading entries of 'Xb', where
+ // 'X' includes all types except immediate ('I'). if any
+ // are defined, at least one operand must have a byte size.
+ // this handles the cases of byte or word/dword ambiguity for
+ // instructions with no register operands.
+
+ sizeOpnd = sizeX;
+ for (index = 0; index < 2; index++)
+ if (tmplType[index] != typImm && tmplSize[index] == sizeB) {
+ if (avInstOpnd[index].size != sizeX)
+ sizeOpnd = avInstOpnd[index].size;
+ }
+ else
+ break;
+ if (index != 0 && sizeOpnd == sizeX) {
+ return xosdAsmSize;
+ }
+
+ // for templates with one entry of 'Xp', where 'X' is
+ // not 'A', allowable sizes are sizeX (unspecified),
+ // sizeD (dword), and sizeF (fword). process by
+ // mapping entry sizes 'p' -> 'v', sizeD -> sizeW,
+ // and sizeF -> sizeD
+ // (template 'Ap' is absolute with explicit segment and
+ // 'v'-sized offset - really treated as 'Av')
+
+ if (tmplSize[0] == sizeP) {
+ tmplSize[0] = sizeV;
+ if (avInstOpnd[0].size == sizeD)
+ avInstOpnd[0].size = sizeW;
+ if (avInstOpnd[0].size == sizeF)
+ avInstOpnd[0].size = sizeD;
+ }
+
+ // for templates with the second entry of 'Ma', the
+ // allowable sizes are sizeX (unspecified),
+ // sizeD (dword), and sizeQ (qword). process by
+ // mapping entry sizes 'a' -> 'v', sizeD -> sizeW,
+ // and sizeQ -> sizeD
+ // (template entry 'Ma' is used only with the BOUND instruction)
+
+ if (tmplSize[1] == sizeA) {
+ tmplSize[1] = sizeV;
+ if (avInstOpnd[1].size == sizeD)
+ avInstOpnd[1].size = sizeW;
+ if (avInstOpnd[1].size == sizeQ)
+ avInstOpnd[1].size = sizeD;
+ }
+
+ // test for template with leading entries of 'Xv' optionally
+ // followed by one 'Iv' entry. if two 'Xv' entries, set
+ // size error if one is word and the other is dword. if
+ // 'Iv' entry, test for overflow.
+
+ sizeOpnd = sizeX;
+ for (index = 0; index < 3; index++)
+ if (tmplSize[index] == sizeV)
+ if (tmplType[index] != typImm) {
+
+ // template entry is 'Xv', set size and check size
+
+ if (avInstOpnd[index].size != sizeX) {
+ if (
+ sizeOpnd != sizeX &&
+ sizeOpnd != avInstOpnd[index].size
+ ) {
+ return xosdAsmSize;
+ }
+ sizeOpnd = avInstOpnd[index].size;
+ }
+ }
+ else {
+
+ // template entry is 'Iv', set sizeOpnd to either
+ // sizeW or sizeD and check for overflow
+
+ if (sizeOpnd == sizeX)
+ sizeOpnd = (BYTE)(fDBit ? sizeD : sizeW);
+ if (sizeOpnd == sizeW && avInstOpnd[index].size == sizeD) {
+ return xosdAsmOverFlow;
+ }
+ }
+
+ return xosdNone;
+}
+
+BYTE CheckPrefix (LPBYTE lpbTemplate)
+{
+ BYTE fPrefix;
+
+ fPrefix = (BYTE)(lpbTemplate && *lpbTemplate != 0x0f
+ && (*lpbTemplate & ~7) != 0xd8
+ && *(lpbTemplate + 1) == (asPrfx + tEnd + eEnd));
+ if (fPrefix)
+ *lpbBin++ = *lpbTemplate;
+
+ return fPrefix;
+}
+
+XOSD AssembleInstr ( void ) {
+ BYTE size;
+ BYTE index;
+ PASM_VALUE pavInstOpnd;
+
+ // set operand override flag if operand size differs than fDBit
+ // (the flag may already be set due to opcode template flag)
+
+ if ((sizeOpnd == sizeW && fDBit)
+ || (sizeOpnd == sizeD && !fDBit))
+ fOpndOvrd = TRUE;
+
+ // for each operand of the successfully matched template,
+ // build the assembled instruction
+ // for template entries with size 'v', sizeOpnd has the size
+
+ for (index = 0; index < cntTmplOpnd; index++) {
+ pavInstOpnd = &avInstOpnd[index];
+ size = tmplSize[index];
+ if (size == sizeV)
+ size = sizeOpnd;
+
+ switch ( tmplType [ index ] ) {
+
+ case typExp:
+ case typMem:
+
+ if ( !segOvrd ) { // first one only (movsb...)
+ segOvrd = segToOvrdByte[pavInstOpnd->segovr];
+ }
+
+ if ( fSegOnly ) {
+ break;
+ }
+
+ fModrm = TRUE;
+ if ( pavInstOpnd->flags == fREG ) {
+ modModrm = 3;
+ rmModrm = pavInstOpnd->base;
+ }
+ else {
+ addrValue = (LONG)pavInstOpnd->value;
+
+ // for 16-bit or 32-bit index off (E)BP, make
+ // zero displacement a byte one
+
+ if (
+ addrValue == 0 &&
+ ( pavInstOpnd->flags != fPTR16 || pavInstOpnd->base != 6 ) &&
+ ( pavInstOpnd->flags != fPTR32 || pavInstOpnd->base != indBP )
+ ) {
+ modModrm = 0;
+ }
+ else if (addrValue >= -0x80L && addrValue <= 0x7fL) {
+ modModrm = 1;
+ addrSize = 1;
+ }
+ else if (
+ pavInstOpnd->flags == fPTR32 ||
+ ( pavInstOpnd->flags == fPTR && fDBit )
+ ) {
+ modModrm = 2;
+ addrSize = 4;
+ }
+ else if ( addrValue >= -0x8000L && addrValue <= 0xffffL ) {
+ modModrm = 2;
+ addrSize = 2;
+ }
+ else {
+ return xosdAsmOverFlow;
+ }
+
+ if ( pavInstOpnd->flags == fPTR ) {
+ modModrm = 0;
+ addrSize = (BYTE)((1 + fDBit) << 1);
+ rmModrm = (BYTE)(6 - fDBit);
+ }
+ else if (pavInstOpnd->flags == fPTR16) {
+ fAddrOvrd = fDBit;
+ rmModrm = pavInstOpnd->base;
+ if ( modModrm == 0 && rmModrm == 6 ) {
+ modModrm = 1;
+ }
+ }
+ else {
+ fAddrOvrd = (BYTE)!fDBit;
+ if (
+ pavInstOpnd->index == 0xff &&
+ pavInstOpnd->base != indSP
+ ) {
+ rmModrm = pavInstOpnd->base;
+ if ( modModrm == 0 && rmModrm == 5 ) {
+ modModrm++;
+ }
+ }
+ else {
+ rmModrm = 4;
+ fSib = TRUE;
+ if (pavInstOpnd->base != 0xff) {
+ baseSib = pavInstOpnd->base;
+ if (modModrm == 0 && baseSib == 5)
+ modModrm++;
+ }
+ else {
+ baseSib = 5;
+ }
+
+ if ( pavInstOpnd->index != 0xff ) {
+ indexSib = pavInstOpnd->index;
+ scaleSib = pavInstOpnd->scale;
+ }
+ else {
+ indexSib = 4;
+ scaleSib = 0;
+ }
+ }
+ }
+ }
+ break;
+
+ case typGen:
+
+ if ( fAddToOp ) {
+ inOpcode += pavInstOpnd->base;
+ }
+ else {
+ regModrm = pavInstOpnd->base;
+ }
+ break;
+
+ case typSgr:
+
+ regModrm = (BYTE)( pavInstOpnd->base - 1 );
+ // remove list offset
+ break;
+
+ case typReg:
+
+ rmModrm = pavInstOpnd->base;
+ break;
+
+ case typImm:
+
+ if ( immedSize == 0 ) {
+ immedSize = size;
+ immedValue = pavInstOpnd->value;
+ }
+ else {
+ immedSize2 = size;
+ immedValue2 = pavInstOpnd->value;
+ }
+ break;
+
+ case typJmp:
+
+ // compute displacment for byte offset instruction
+ // and test if in range
+
+ addrValue = pavInstOpnd->value - ( offAddr ( addrAssem ) + 2);
+ if ( addrValue >= -0x80L && addrValue <= 0x7fL ) {
+ addrSize = 1;
+ }
+ else {
+
+ // too large for byte, compute for word offset
+ // and test again if in range
+ // also allow for two-byte opcode 0f xx
+
+ addrValue -= 1 + (preOpcode == 0x0f);
+ if (!fDBit) {
+ if (addrValue >= -0x8000L && addrValue <= 0x7fffL)
+ addrSize = 2;
+ else
+ return xosdAsmBadRange;
+ }
+ else {
+
+ // recompute again for dword offset instruction
+
+ addrValue -= 2;
+ addrSize = 4;
+ }
+ }
+ fOpndOvrd = FALSE; // operand size override is NOT set
+ break;
+
+ case typCtl:
+ case typDbg:
+ case typTrc:
+ fModrm = TRUE;
+ modModrm = 3;
+ regModrm = pavInstOpnd->base;
+ break;
+
+ case typSti:
+ postOpcode += pavInstOpnd->base;
+ break;
+
+ case typSeg:
+ break;
+
+ case typXsi:
+ case typYdi:
+ fAddrOvrd = (BYTE)
+ ((BYTE)(pavInstOpnd->flags == fPTR32) != fDBit);
+ break;
+
+ case typOff:
+ segOvrd = segToOvrdByte[pavInstOpnd->segovr];
+ goto jumpAssem;
+
+ case typAbs:
+ fSegPtr = TRUE;
+ segPtr = pavInstOpnd->segment;
+jumpAssem:
+ addrValue = (LONG)pavInstOpnd->value;
+ if (!fDBit)
+ if (addrValue >= -0x8000L && addrValue <= 0xffffL)
+ addrSize = 2;
+ else
+ return xosdAsmOverFlow;
+ else
+ addrSize = 4;
+ break;
+ }
+ }
+
+ return xosdNone;
+}
+
+BYTE MatchOperand ( PASM_VALUE pavOpnd, BYTE tmplType ) {
+ BYTE fMatch;
+
+ // if immediate operand, set minimum unsigned size
+
+ if (pavOpnd->flags == fIMM) {
+ if ((LONG)pavOpnd->value >= -0x80L && (LONG)pavOpnd->value <= 0xffL)
+ pavOpnd->size = sizeB;
+ else if ((LONG)pavOpnd->value >= -0x8000L
+ && (LONG)pavOpnd->value <= 0xffffL)
+ pavOpnd->size = sizeW;
+ else
+ pavOpnd->size = sizeD;
+ }
+
+ // start matching of operands
+ // compare the template and input operand types
+
+ switch (tmplType) {
+ case typAX:
+ fMatch = (BYTE)((pavOpnd->flags & fREG)
+ && pavOpnd->index == regG && pavOpnd->base == indAX);
+ break;
+
+ case typCL:
+ fMatch = (BYTE)((pavOpnd->flags & fREG)
+ && pavOpnd->index == regG && pavOpnd->size == sizeB
+ && pavOpnd->base == indCX);
+ break;
+
+ case typDX:
+ fMatch = (BYTE)((pavOpnd->flags & fREG)
+ && pavOpnd->index == regG && pavOpnd->size == sizeW
+ && pavOpnd->base == indDX);
+ break;
+
+ case typAbs:
+ fMatch = (BYTE)(pavOpnd->flags & fFPTR);
+ break;
+
+ case typExp:
+ fMatch = (BYTE)((pavOpnd->flags == fREG
+ && pavOpnd->index == regG)
+ || (pavOpnd->flags == fIMM && pavOpnd->reloc == 1)
+ || (pavOpnd->flags & (fPTR | fPTR16 | fPTR32)) != 0);
+ break;
+
+ case typGen:
+ case typReg:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regG);
+ break;
+
+ case typIm1:
+ fMatch = (BYTE)(pavOpnd->flags == fIMM && pavOpnd->value == 1);
+ break;
+
+ case typIm3:
+ fMatch = (BYTE)(pavOpnd->flags == fIMM && pavOpnd->value == 3);
+ break;
+
+ case typImm:
+ fMatch = (BYTE)(pavOpnd->flags == fIMM && pavOpnd->reloc == 0);
+ break;
+
+ case typJmp:
+ fMatch = (BYTE)(pavOpnd->flags == fIMM);
+ break;
+
+ case typMem:
+ fMatch = (BYTE)((pavOpnd->flags == fIMM && pavOpnd->reloc == 1)
+ || ((pavOpnd->flags & (fPTR | fPTR16 | fPTR32)) != 0));
+ break;
+
+ case typCtl:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regC);
+ break;
+
+ case typDbg:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regD);
+ break;
+
+ case typTrc:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regT);
+ break;
+
+ case typSt:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regF);
+ break;
+
+ case typSti:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regI);
+ break;
+
+ case typSeg:
+ fMatch = (BYTE)(pavOpnd->flags == fREG && pavOpnd->index == regS
+ && pavOpnd->base == segIndex);
+ break;
+
+ case typSgr:
+ fMatch = (BYTE)(pavOpnd->flags == fREG
+ && pavOpnd->index == regS);
+ break;
+
+ case typXsi:
+ fMatch = (BYTE)(((pavOpnd->flags == fPTR16 && pavOpnd->base == 4)
+ || (pavOpnd->flags == fPTR32 && pavOpnd->base == indSI
+ && pavOpnd->index == 0xff))
+ && pavOpnd->value == 0
+ && (pavOpnd->segovr == segX
+ || pavOpnd->segovr == segDS));
+ break;
+
+ case typYdi:
+ fMatch = (BYTE)(((pavOpnd->flags == fPTR16 && pavOpnd->base == 5)
+ || (pavOpnd->flags == fPTR32 && pavOpnd->base == indDI
+ && pavOpnd->index == 0xff))
+ && pavOpnd->value == 0
+ && pavOpnd->segovr == segES);
+ break;
+
+ case typOff:
+ fMatch = (BYTE)((pavOpnd->flags == fIMM && pavOpnd->reloc == 1)
+ || pavOpnd->flags == fPTR);
+ break;
+
+ default:
+ fMatch = FALSE;
+ break;
+ }
+
+ return fMatch;
+}
+
+void OutputInstr ( void ) {
+ if ( fWaitPrfx ) {
+ *lpbBin++ = 0x9b;
+ }
+ if ( fAddrOvrd ) {
+ *lpbBin++ = 0x67;
+ }
+ if ( fOpndOvrd ) {
+ *lpbBin++ = 0x66;
+ }
+ if ( segOvrd ) {
+ *lpbBin++ = segOvrd;
+ }
+ if ( preOpcode ) {
+ *lpbBin++ = preOpcode;
+ }
+
+ *lpbBin++ = inOpcode;
+
+ if ( postOpcode ) {
+ *lpbBin++ = postOpcode;
+ }
+ if ( fModrm ) {
+ *lpbBin++ = (BYTE)((((modModrm << 3) + regModrm) << 3) + rmModrm);
+ }
+ if ( fSib ) {
+ *lpbBin++ = (BYTE)((((scaleSib << 3) + indexSib) << 3) + baseSib);
+ }
+
+ OutputValue ( addrSize, (LPBYTE)&addrValue); // size = 0, 1, 2, 4
+ OutputValue ( (BYTE)(fSegPtr << 1), (LPBYTE)&segPtr); // size = 0, 2
+ OutputValue ( immedSize, (LPBYTE)&immedValue); // size = 0, 1, 2, 4
+ OutputValue ( immedSize2, (LPBYTE)&immedValue2); // size = 0, 1, 2, 4
+}
+
+void OutputValue ( BYTE size, LPBYTE pchValue ) {
+ while (size--)
+ *lpbBin++ = *pchValue++;
+}
diff --git a/private/windbg/em/p_i386/asm.h b/private/windbg/em/p_i386/asm.h
new file mode 100644
index 000000000..ab6a49683
--- /dev/null
+++ b/private/windbg/em/p_i386/asm.h
@@ -0,0 +1,202 @@
+// token classes and types
+
+#define ASM_CLASS_MASK 0xff00
+#define ASM_TYPE_MASK 0x00ff
+
+#define ASM_EOL_CLASS 0x000
+
+#define ASM_ADDOP_CLASS 0x100
+#define ASM_ADDOP_PLUS 0x101
+#define ASM_ADDOP_MINUS 0x102
+
+#define ASM_MULOP_CLASS 0x200
+#define ASM_MULOP_MULT 0x201
+#define ASM_MULOP_DIVIDE 0x202
+#define ASM_MULOP_MOD 0x203
+#define ASM_MULOP_SHL 0x204
+#define ASM_MULOP_SHR 0x205
+
+#define ASM_ANDOP_CLASS 0x300
+
+#define ASM_NOTOP_CLASS 0x400
+
+#define ASM_OROP_CLASS 0x500
+#define ASM_OROP_OR 0x501
+#define ASM_OROP_XOR 0x502
+
+#define ASM_RELOP_CLASS 0x600
+#define ASM_RELOP_EQ 0x601
+#define ASM_RELOP_NE 0x602
+#define ASM_RELOP_LE 0x603
+#define ASM_RELOP_LT 0x604
+#define ASM_RELOP_GE 0x605
+#define ASM_RELOP_GT 0x606
+
+#define ASM_UNOP_CLASS 0x700
+#define ASM_UNOP_BY 0x701 // UNDONE
+#define ASM_UNOP_WO 0x702 // UNDONE
+#define ASM_UNOP_DW 0x703 // UNDONE
+#define ASM_UNOP_POI 0x704 // UNDONE
+
+#define ASM_LOWOP_CLASS 0x800
+#define ASM_LOWOP_LOW 0x801
+#define ASM_LOWOP_HIGH 0x802
+
+#define ASM_PTROP_CLASS 0x900
+
+#define ASM_SIZE_CLASS 0xa00
+#define ASM_SIZE_BYTE (0xa00 + sizeB)
+#define ASM_SIZE_WORD (0xa00 + sizeW)
+#define ASM_SIZE_DWORD (0xa00 + sizeD)
+#define ASM_SIZE_FWORD (0xa00 + sizeF)
+#define ASM_SIZE_QWORD (0xa00 + sizeQ)
+#define ASM_SIZE_TBYTE (0xa00 + sizeT)
+#define ASM_SIZE_SWORD (0xa00 + sizeS)
+
+#define ASM_OFFOP_CLASS 0xb00
+#define ASM_COLNOP_CLASS 0xc00
+#define ASM_LPAREN_CLASS 0xd00
+#define ASM_RPAREN_CLASS 0xe00
+#define ASM_LBRACK_CLASS 0xf00
+#define ASM_RBRACK_CLASS 0x1000
+#define ASM_DOTOP_CLASS 0x1100
+#define ASM_SEGOVR_CLASS 0x1200
+#define ASM_SEGMENT_CLASS 0x1300 // value has 16-bit value
+#define ASM_COMMA_CLASS 0x1400
+
+#define ASM_REG_CLASS 0x1500
+#define ASM_REG_BYTE 0x1501
+#define ASM_REG_WORD 0x1502
+#define ASM_REG_DWORD 0x1503
+#define ASM_REG_SEGMENT 0x1504
+#define ASM_REG_CONTROL 0x1505
+#define ASM_REG_DEBUG 0x1506
+#define ASM_REG_TRACE 0x1507
+#define ASM_REG_FLOAT 0x1508
+#define ASM_REG_INDFLT 0x1509
+
+#define ASM_NUMBER_CLASS 0x1600
+
+#define ASM_SYMBOL_CLASS 0x1700
+#define ASM_SYMBOL_IMM 0x1701
+#define ASM_SYMBOL_PTR 0x1702
+#define ASM_SYMBOL_BASE 0x1703
+
+#define ASM_ERROR_CLASS 0xff00 // only used for PeekToken
+
+#define tEnd 0x80
+#define eEnd 0x40
+
+// template flag and operand tokens
+
+enum {
+ asNone, as0x0a, asOpRg, asSiz0, asSiz1, asWait, asSeg, asFSiz,
+ asMpNx, asPrfx,
+
+ asReg0, asReg1, asReg2, asReg3, asReg4, asReg5, asReg6, asReg7,
+
+ opnAL, opnAX, opneAX, opnCL, opnDX, opnAp, opnEb, opnEw,
+ opnEv, opnGb, opnGw, opnGv, opnGd, opnIm1, opnIm3, opnIb,
+ opnIw, opnIv, opnJb, opnJv, opnM, opnMa, opnMb, opnMw,
+ opnMd, opnMp, opnMs, opnMq, opnMt, opnMv, opnCd, opnDd,
+ opnTd, opnRd, opnSt, opnSti, opnSeg, opnSw, opnXb, opnXv,
+ opnYb, opnYv, opnOb, opnOv
+ };
+
+#define asRegBase asReg0 // first of REG flags
+#define opnBase opnAL // first template operand type
+ // if less, then flag, else operand
+
+enum {
+ segX, segES, segCS, segSS, segDS, segFS, segGS
+ };
+
+enum {
+ typNULL, // no defined type
+ typAX, // general register, value EAX
+ typCL, // general register, value ECX
+ typDX, // general register, value EDX
+ typAbs, // absolute type (direct address)
+ typExp, // expr (mod-r/m) general register or memory pointer
+ typGen, // general register
+ typReg, // general register (special reg MOV)
+ typIm1, // immediate, value 1
+ typIm3, // immediate, value 3
+ typImm, // immediate
+ typJmp, // jump relative offset
+ typMem, // memory pointer
+ typCtl, // control register
+ typDbg, // debug register
+ typTrc, // trace register
+ typSt, // floating point top-of-stack
+ typSti, // floating point index-on-stack
+ typSeg, // segment register (PUSH/POP opcode)
+ typSgr, // segment register (MOV opcode)
+ typXsi, // string source address
+ typYdi, // string destination address
+ typOff // memory offset
+ };
+
+enum {
+ regG, // general register
+ regS, // segment register
+ regC, // control register
+ regD, // debug register
+ regT, // trace register
+ regF, // float register (st)
+ regI // float-index register (st(n))
+ };
+
+enum {
+ indAX, // index for EAX, AX, AL
+ indCX, // index for ECX, CX, CL
+ indDX, // index for EDX, DX, DL
+ indBX, // index for EBX, BX, BL
+ indSP, // index for ESP, SP, AH
+ indBP, // index for EBP, BP, CH
+ indSI, // index for ESI, SI, DH
+ indDI // index for EDI, DI, BH
+ };
+
+enum {
+ sizeX, // no size
+ sizeB, // byte size
+ sizeW, // word size
+ sizeV, // variable size (word or dword)
+ sizeD, // dword size
+ sizeP, // pointer size (dword or fword)
+ sizeA, // dword or qword
+ sizeF, // fword
+ sizeQ, // qword
+ sizeT, // ten-byte
+ sizeS // sword
+ };
+
+// mapping from operand token to operand type (class and opt. value)
+
+typedef struct tagOPNDTYPE {
+ BYTE type;
+ BYTE size;
+ } OPNDTYPE, *POPNDTYPE;
+
+typedef struct tagASM_VALUE {
+ ULONG value;
+ USHORT segment;
+ BYTE reloc;
+ BYTE size;
+ BYTE flags;
+ BYTE segovr;
+ BYTE index;
+ BYTE base;
+ BYTE scale;
+ } ASM_VALUE, *PASM_VALUE;
+
+// bit values of flags in ASM_VALUE
+// flags are mutually exclusive
+
+#define fREG 0x80 // set if register
+#define fIMM 0x40 // set if immediate
+#define fFPTR 0x20 // set if far ptr
+#define fPTR 0x10 // set if memory ptr (no reg index)
+#define fPTR16 0x08 // set if memory ptr with 16-bit reg index
+#define fPTR32 0x04 // set if memory ptr with 32-bit reg index
diff --git a/private/windbg/em/p_i386/asmexp.c b/private/windbg/em/p_i386/asmexp.c
new file mode 100644
index 000000000..36da8c09e
--- /dev/null
+++ b/private/windbg/em/p_i386/asmexp.c
@@ -0,0 +1,1576 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "asm.h"
+
+#ifdef HOSTDOS
+extern int _far _cdecl toupper( int );
+extern int _far _cdecl tolower( int );
+#else // HOSTDOS
+#endif // HOSTDOS
+
+#ifdef WIN32
+#define _fstrcmp strcmp
+#endif
+
+
+
+
+
+
+
+
+BYTE PeekAsmChar(void);
+ULONG PeekAsmToken(LPDWORD);
+void AcceptAsmToken(void);
+ULONG GetAsmToken(LPDWORD);
+ULONG NextAsmToken(LPDWORD);
+ULONG GetAsmReg(LPBYTE, LPDWORD);
+ULONG GetSymReg(WORD, LPDWORD);
+
+XOSD GetAsmOperand(PASM_VALUE);
+XOSD GetAsmExpr(PASM_VALUE, BYTE);
+XOSD GetAsmOrTerm(PASM_VALUE, BYTE);
+XOSD GetAsmAndTerm(PASM_VALUE, BYTE);
+XOSD GetAsmNotTerm(PASM_VALUE, BYTE);
+XOSD GetAsmRelTerm(PASM_VALUE, BYTE);
+XOSD GetAsmAddTerm(PASM_VALUE, BYTE);
+XOSD GetAsmMulTerm(PASM_VALUE, BYTE);
+XOSD GetAsmSignTerm(PASM_VALUE, BYTE);
+XOSD GetAsmByteTerm(PASM_VALUE, BYTE);
+XOSD GetAsmOffTerm(PASM_VALUE, BYTE);
+XOSD GetAsmColnTerm(PASM_VALUE, BYTE);
+XOSD GetAsmDotTerm(PASM_VALUE, BYTE);
+XOSD GetAsmIndxTerm(PASM_VALUE, BYTE);
+XOSD AddAsmValues(PASM_VALUE, PASM_VALUE);
+void SwapPavs(PASM_VALUE, PASM_VALUE);
+
+extern ULONG baseDefault;
+extern LSZ lszAsmLine;
+
+extern ADDR addrAssem; // assembly address (formal)
+extern BYTE fDBit;
+
+struct _AsmRes {
+ LPBYTE pchRes;
+ ULONG valueRes;
+ } AsmReserved[] = {
+ { "mod", ASM_MULOP_MOD },
+ { "shl", ASM_MULOP_SHL },
+ { "shr", ASM_MULOP_SHR },
+ { "and", ASM_ANDOP_CLASS },
+ { "not", ASM_NOTOP_CLASS },
+ { "or", ASM_OROP_OR },
+ { "xor", ASM_OROP_XOR },
+ { "eq", ASM_RELOP_EQ },
+ { "ne", ASM_RELOP_NE },
+ { "le", ASM_RELOP_LE },
+ { "lt", ASM_RELOP_LT },
+ { "ge", ASM_RELOP_GE },
+ { "gt", ASM_RELOP_GT },
+ { "by", ASM_UNOP_BY },
+ { "wo", ASM_UNOP_WO },
+ { "dw", ASM_UNOP_DW },
+ { "poi", ASM_UNOP_POI },
+ { "low", ASM_LOWOP_LOW },
+ { "high", ASM_LOWOP_HIGH },
+ { "offset", ASM_OFFOP_CLASS },
+ { "ptr", ASM_PTROP_CLASS },
+ { "byte", ASM_SIZE_BYTE },
+ { "word", ASM_SIZE_WORD },
+ { "dword", ASM_SIZE_DWORD },
+ { "fword", ASM_SIZE_FWORD },
+ { "qword", ASM_SIZE_QWORD },
+ { "tbyte", ASM_SIZE_TBYTE }
+ };
+
+#define RESERVESIZE (sizeof(AsmReserved) / sizeof(struct _AsmRes))
+
+BYTE regSize[] = {
+ sizeB, // byte
+ sizeW, // word
+ sizeD, // dword
+ sizeW, // segment
+ sizeD, // control
+ sizeD, // debug
+ sizeD, // trace
+ sizeT, // float
+ sizeT // float with index
+ };
+
+BYTE regType[] = {
+ regG, // byte - general
+ regG, // word - general
+ regG, // dword - general
+ regS, // segment
+ regC, // control
+ regD, // debug
+ regT, // trace
+ regF, // float (st)
+ regI // float-index (st(n))
+ };
+
+BYTE tabWordReg[8] = { // rm value
+(BYTE) -1, // AX - error
+(BYTE) -1, // CX - error
+(BYTE) -1, // DX - error
+(BYTE) 7, // BX - 111
+(BYTE) -1, // SP - error
+(BYTE) 6, // BP - 110
+(BYTE) 4, // SI - 100
+(BYTE) 5, // DI - 101
+ };
+
+BYTE rm16Table[16] = { // new rm left rm right rm
+(BYTE) -1, // error 100 = [SI] 100 = [SI]
+(BYTE) -1, // error 100 = [SI] 101 = [DI]
+(BYTE) 2, // 010 = [BP+SI] 100 = [SI] 110 = [BP]
+(BYTE) 0, // 000 = [BX+SI] 100 = [SI] 111 = [BX]
+(BYTE) -1, // error 101 = [DI] 100 = [SI]
+(BYTE) -1, // error 101 = [DI] 101 = [DI]
+(BYTE) 3, // 011 = [BP+DI] 101 = [DI] 110 = [BP]
+(BYTE) 1, // 001 = [BX+DI] 101 = [DI] 111 = [BX]
+(BYTE) 2, // 010 = [BP+SI] 110 = [BP] 100 = [SI]
+(BYTE) 3, // 011 = [BP+DI] 110 = [BP] 101 = [DI]
+(BYTE) -1, // error 110 = [BP] 110 = [BP]
+(BYTE) -1, // error 110 = [BP] 111 = [BX]
+(BYTE) 0, // 000 = [BX+SI] 111 = [BX] 100 = [SI]
+(BYTE) 1, // 001 = [BX+DI] 111 = [BX] 101 = [DI]
+(BYTE) -1, // error 111 = [BX] 110 = [BP]
+(BYTE) -1 // error 111 = [BX] 111 = [BX]
+ };
+
+LSZ savedlszAsmLine = (LSZ)0L;
+ULONG savedAsmClass = 0L;
+ULONG savedAsmValue = 0L;
+
+/*** PeekAsmChar - peek the next non-white-space character
+*
+* Purpose:
+* Return the next non-white-space character and update
+* lszAsmLine to point to it.
+*
+* Input:
+* lszAsmLine - present command line position.
+*
+* Returns:
+* next non-white-space character
+*
+*************************************************************************/
+
+BYTE PeekAsmChar (void)
+{
+ BYTE ch;
+
+ do
+ ch = *lszAsmLine++;
+ while (ch == ' ' || ch == '\t');
+ lszAsmLine--;
+
+ return ch;
+}
+
+/*** PeekAsmToken - peek the next command line token
+*
+* Purpose:
+* Return the next command line token, but do not advance
+* the lszAsmLine pointer.
+*
+* Input:
+* lszAsmLine - present command line position.
+*
+* Output:
+* *lpulValue - optional value of token
+* Returns:
+* class of token
+*
+* Notes:
+* savedAsmClass, savedAsmValue, and savedlszAsmLine saves the
+* token getting state for future peeks.
+* To get the next token, a GetAsmToken or AcceptAsmToken call
+* must first be made.
+*
+*************************************************************************/
+
+ULONG PeekAsmToken (LPDWORD lpulValue)
+{
+ BYTE *pchTemp;
+
+ // Get next class and value, but do not
+ // move lszAsmLine, but save it in savedlszAsmLine.
+ // Do not report any error condition.
+
+ if (savedAsmClass == -1) {
+ pchTemp = lszAsmLine;
+ savedAsmClass = NextAsmToken(&savedAsmValue);
+ savedlszAsmLine = lszAsmLine;
+ lszAsmLine = pchTemp;
+ }
+ *lpulValue = savedAsmValue;
+ return savedAsmClass;
+}
+
+/*** AcceptAsmToken - accept any peeked token
+*
+* Purpose:
+* To reset the PeekAsmToken saved variables so the next PeekAsmToken
+* will get the next token in the command line.
+*
+* Input:
+* None.
+*
+* Output:
+* None.
+*
+*************************************************************************/
+
+void AcceptAsmToken (void)
+{
+ savedAsmClass = (ULONG)-1;
+ lszAsmLine = savedlszAsmLine;
+}
+
+/*** GetAsmToken - peek and accept the next token
+*
+* Purpose:
+* Combines the functionality of PeekAsmToken and AcceptAsmToken
+* to return the class and optional value of the next token
+* as well as updating the command pointer lszAsmLine.
+*
+* Input:
+* lszAsmLine - present command string pointer
+*
+* Output:
+* *lpulValue - pointer to the token value optionally set.
+* Returns:
+* class of the token read.
+*
+* Notes:
+* An illegal token returns the value of ERROR_CLASS with *lpulValue
+* being the error number, but produces no actual error.
+*
+*************************************************************************/
+
+ULONG
+GetAsmToken (
+ LPDWORD lpulValue
+ )
+{
+ ULONG opclass;
+
+ if (savedAsmClass != (ULONG)-1) {
+ opclass = savedAsmClass;
+ savedAsmClass = (ULONG)-1;
+ *lpulValue = savedAsmValue;
+ lszAsmLine = savedlszAsmLine;
+ }
+ else {
+ opclass = NextAsmToken ( lpulValue );
+ }
+
+ return opclass;
+}
+
+/*** NextAsmToken - process the next token
+*
+* Purpose:
+* Parse the next token from the present command string.
+* After skipping any leading white space, first check for
+* any single character tokens or register variables. If
+* no match, then parse for a number or variable. If a
+* possible variable, check the reserved word list for operators.
+*
+* Input:
+* lszAsmLine - pointer to present command string
+*
+* Output:
+* *lpulValue - optional value of token returned
+* lszAsmLine - updated to point past processed token
+* Returns:
+* class of token returned
+*
+* Notes:
+* An illegal token returns the value of ERROR_CLASS with *lpulValue
+* being the error number, but produces no actual error.
+*
+*************************************************************************/
+
+#define SYMBOLSIZE 100
+
+ULONG
+NextAsmToken (
+ LPDWORD lpulValue
+ )
+{
+ ULONG base;
+ BYTE chSymbol [ SYMBOLSIZE ];
+ BYTE chPreSym[9];
+ ULONG cbSymbol = 0;
+ BYTE fNumber = TRUE;
+ BYTE fSymbol = TRUE;
+ BYTE fForceReg = FALSE;
+ ULONG errNumber = 0;
+ BYTE ch;
+ BYTE chlow;
+ BYTE chtemp;
+ BYTE limit1 = '9';
+ BYTE limit2 = '9';
+ BYTE fDigit = FALSE;
+ ULONG value = 0;
+ ULONG tmpvalue;
+ ULONG index;
+
+ static ADDR addrSym = {0};
+
+ base = baseDefault;
+
+ // skip leading white space
+
+ chlow = (BYTE)tolower(ch = PeekAsmChar());
+ lszAsmLine++;
+
+ // test for special character operators and register variable
+
+ switch (chlow) {
+ case '\0':
+ lszAsmLine--;
+ return ASM_EOL_CLASS;
+ case ',':
+ return ASM_COMMA_CLASS;
+ case '+':
+ *lpulValue = ASM_ADDOP_PLUS;
+ return ASM_ADDOP_CLASS;
+ case '-':
+ *lpulValue = ASM_ADDOP_MINUS;
+ return ASM_ADDOP_CLASS;
+ case '*':
+ *lpulValue = ASM_MULOP_MULT;
+ return ASM_MULOP_CLASS;
+ case '/':
+ *lpulValue = ASM_MULOP_DIVIDE;
+ return ASM_MULOP_CLASS;
+ case ':':
+ return ASM_COLNOP_CLASS;
+ case '(':
+ return ASM_LPAREN_CLASS;
+ case ')':
+ return ASM_RPAREN_CLASS;
+ case '[':
+ return ASM_LBRACK_CLASS;
+ case ']':
+ return ASM_RBRACK_CLASS;
+ case '@':
+ fForceReg = TRUE;
+ chlow = (BYTE)tolower(*lszAsmLine++);
+ break;
+ case '.':
+ return ASM_DOTOP_CLASS;
+ case '\'':
+ for (index = 0; index < 5; index++) {
+ ch = *lszAsmLine++;
+ if (ch == '\'' || ch == '\0') {
+ break;
+ }
+ value = (value << 8) + (ULONG)ch;
+ }
+ if (ch == '\0' || index == 0 || index == 5) {
+ lszAsmLine--;
+ *((XOSD*)lpulValue) = xosdAsmSyntax;
+ return ASM_ERROR_CLASS;
+ }
+ lszAsmLine++;
+ *lpulValue = value;
+ return ASM_NUMBER_CLASS;
+ }
+
+ // if first character is a decimal digit, it cannot
+ // be a symbol. leading '0' implies octal, except
+ // a leading '0x' implies hexadecimal.
+
+ if ( chlow >= '0' && chlow <= '9' ) {
+ if ( fForceReg ) {
+ *lpulValue = (ULONG) xosdAsmSyntax;
+ return ASM_ERROR_CLASS;
+ }
+ fSymbol = FALSE;
+ if ( chlow == '0' ) {
+ ch = *lszAsmLine++;
+ chlow = (BYTE)tolower ( ch );
+ if ( chlow == 'x' ) {
+ base = 16;
+ ch = *lszAsmLine++;
+ chlow = (BYTE)tolower(ch);
+ }
+ else if (chlow == 'n') {
+ base = 10;
+ ch = *lszAsmLine++;
+ chlow = (BYTE)tolower(ch);
+ }
+ else {
+ base = 8;
+ fDigit = TRUE;
+ }
+ }
+ }
+
+ // a number can start with a letter only if base is
+ // hexadecimal and it is a hexadecimal digit 'a'-'f'.
+
+ else if ( ( chlow < 'a' && chlow > 'f') || base != 16 ) {
+ fNumber = FALSE;
+ }
+
+ // set limit characters for the appropriate base.
+
+ if ( base == 8 ) {
+ limit1 = '7';
+ }
+ if ( base == 16 ) {
+ limit2 = 'f';
+ }
+
+ // perform processing while character is a letter,
+ // digit, or underscore.
+
+ while (
+ ( chlow >= 'a' && chlow <= 'z' ) ||
+ ( chlow >= '0' && chlow <= '9' ) ||
+ (chlow == '_')
+ ) {
+
+ // if possible number, test if within proper range,
+ // and if so, accumulate sum.
+
+ if ( fNumber ) {
+ if (
+ ( chlow >= '0' && chlow <= limit1 ) ||
+ ( chlow >= 'a' && chlow <= limit2 )
+ ) {
+ fDigit = TRUE;
+ tmpvalue = value * base;
+ if ( tmpvalue < value ) {
+ errNumber = (ULONG) xosdAsmOverFlow;
+ }
+ chtemp = (BYTE) ( chlow - '0' );
+ if ( chtemp > 9 ) {
+ chtemp -= 'a' - '0' - 10;
+ }
+ value = tmpvalue + (ULONG) chtemp;
+ if ( value < tmpvalue ) {
+ errNumber = (ULONG) xosdAsmOverFlow;
+ }
+ }
+ else {
+ fNumber = FALSE;
+ errNumber = (ULONG) xosdAsmSyntax;
+ }
+ }
+
+ if ( fSymbol ) {
+ if ( cbSymbol < 9 ) {
+ chPreSym[cbSymbol] = chlow;
+ }
+ if ( cbSymbol < SYMBOLSIZE - 1 ) {
+ chSymbol[cbSymbol++] = ch;
+ }
+ }
+
+ ch = *lszAsmLine++;
+ chlow = (BYTE)tolower ( ch );
+ }
+
+ // back up pointer to first character after token.
+
+ lszAsmLine--;
+
+ if ( cbSymbol < 9 ) {
+ chPreSym [ cbSymbol ] = '\0';
+ }
+
+ // if fForceReg, check for register name and return
+ // success or failure
+
+ if ( fForceReg ) {
+ if ( ( index = GetAsmReg ( chPreSym, lpulValue ) ) != 0) {
+ if ( index == ASM_REG_SEGMENT ) {
+ if ( PeekAsmChar() == ':' ) {
+ lszAsmLine++;
+ index = ASM_SEGOVR_CLASS;
+ }
+ return index; // class type returned by GetAsmReg
+ }
+ }
+ else {
+ *lpulValue = (ULONG) xosdAsmBadReg;
+ return ASM_ERROR_CLASS;
+ }
+ }
+
+ // next test for reserved word and symbol string
+
+ if ( fSymbol ) {
+ ASR asr;
+ asr.ast = asr.fcd = 0;
+
+ // if possible symbol, check lowercase string in chPreSym
+ // for text operator or register name.
+ // otherwise, return symbol value from name in chSymbol.
+
+ for ( index = 0; index < RESERVESIZE; index++ ) {
+ if ( !_fstrcmp ( chPreSym, AsmReserved[index].pchRes ) ) {
+ *lpulValue = AsmReserved[index].valueRes;
+ return AsmReserved[index].valueRes & ASM_CLASS_MASK;
+ }
+ }
+
+ // start processing string as symbol
+
+ chSymbol [ cbSymbol ] = '\0';
+
+ SHFindSymbol ( chSymbol, &addrAssem, &asr );
+
+ addrSym = asr.addr;
+
+ switch ( asr.ast ) {
+
+ case astNone:
+ break; // Not a symbol, but may be a reg or hex
+
+ case astAddress:
+
+ switch ( asr.fcd ) {
+
+ case fcdUnknown:
+ *lpulValue = (ULONG) &addrSym;
+ return ASM_SYMBOL_PTR;
+
+ case fcdFar:
+ *lpulValue = (ULONG) &addrSym;
+ return ASM_SYMBOL_PTR;
+
+ case fcdData:
+ *lpulValue = offAddr ( asr.addr );
+ return ASM_SYMBOL_IMM;
+
+ case fcdNear:
+ *lpulValue = offAddr ( asr.addr );
+ return ASM_SYMBOL_IMM;
+ }
+ break;
+
+ case astRegister:
+
+ return GetSymReg ( asr.ireg, lpulValue );
+ break;
+
+ case astBaseOff:
+
+ *lpulValue = (ULONG) asr.off;
+ return ASM_SYMBOL_BASE;
+ break;
+
+ default:
+
+ // assert ( FALSE );
+ break;
+ }
+
+ // symbol is undefined.
+ // if a possible hex number, do not set the error type
+
+ if ( !fNumber ) {
+ errNumber = (ULONG) xosdAsmSymbol;
+ }
+ }
+
+
+ // if possible number and no error, return the number
+
+ if ( fNumber && !errNumber ) {
+
+ if ( fDigit ) {
+
+ // check for possible segment specification
+ // "<16-bit number>:"
+
+ if ( PeekAsmChar() == ':' ) {
+ lszAsmLine++;
+ if ( value > 0xffff ) {
+ *lpulValue = (ULONG) xosdAsmBadSeg;
+ return ASM_ERROR_CLASS;
+ }
+ *lpulValue = value;
+ return ASM_SEGMENT_CLASS;
+ }
+
+ *lpulValue = value;
+ return ASM_NUMBER_CLASS;
+ }
+ else {
+ errNumber = (ULONG) xosdAsmSyntax;
+ }
+ }
+
+ // last chance, undefined symbol and illegal number,
+ // so test for register, will handle old format
+
+ if ( ( index = GetAsmReg ( chPreSym, lpulValue ) ) != 0 ) {
+ if ( index == ASM_REG_SEGMENT ) {
+ if ( PeekAsmChar ( ) == ':' ) {
+ lszAsmLine++;
+ index = ASM_SEGOVR_CLASS;
+ }
+ }
+ return index; // class type returned by GetAsmReg
+ }
+
+ *lpulValue = (ULONG) errNumber;
+ return ASM_ERROR_CLASS;
+}
+
+ULONG
+GetAsmReg (
+ LPBYTE pSymbol,
+ LPDWORD lpulValue
+ )
+{
+ static BYTE vRegList[] = "axcxdxbxspbpsidi";
+ static BYTE bRegList[] = "alcldlblahchdhbh";
+ static BYTE sRegList[] = "ecsdfg"; // second char is 's'
+ // same order as seg enum
+
+ ULONG index;
+ BYTE ch0 = *pSymbol;
+ BYTE ch1 = *(pSymbol + 1);
+ BYTE ch2 = *(pSymbol + 2);
+ BYTE ch3 = *(pSymbol + 3);
+
+ // only test strings with two or three characters
+
+ if (ch0 && ch1) {
+ if (ch2 == '\0') {
+
+ // symbol has two characters, first test for 16-bit register
+
+ for (index = 0; index < 8; index++) {
+ if (*(LPWORD)pSymbol == *((LPWORD)vRegList + index)) {
+ *lpulValue = index;
+ return ASM_REG_WORD;
+ }
+ }
+
+ // next test for 8-bit register
+
+ for (index = 0; index < 8; index++) {
+ if (*(LPWORD)pSymbol == *((LPWORD)bRegList + index)) {
+ *lpulValue = index;
+ return ASM_REG_BYTE;
+ }
+ }
+
+ // test for segment register
+
+ if (ch1 == 's') {
+ for (index = 0; index < 6; index++) {
+ if (ch0 == *(sRegList + index)) {
+ *lpulValue = index + 1; // list offset is 1
+ return ASM_REG_SEGMENT;
+ }
+ }
+ }
+
+ // finally test for floating register "st" or "st(n)"
+ // parse the arg here as '(', <octal value>, ')'
+ // return value for "st" is REG_FLOAT,
+ // for "st(n)" is REG_INDFLT with value 0-7
+
+ if (ch0 == 's' && ch1 == 't') {
+ if (PeekAsmChar() != '(') {
+ return ASM_REG_FLOAT;
+ } else {
+ lszAsmLine++;
+ index = (ULONG)(PeekAsmChar() - '0');
+ if (index < 8) {
+ lszAsmLine++;
+ if (PeekAsmChar() == ')') {
+ lszAsmLine++;
+ *lpulValue = index;
+ return ASM_REG_INDFLT;
+ }
+ }
+ }
+ }
+ }
+
+ else if (ch3 == '\0') {
+
+ // if three-letter symbol, test for leading 'e' and
+ // second and third character being in the 16-bit list
+
+ if (ch0 == 'e') {
+ for (index = 0; index < 8; index++) {
+ if (*(LPWORD)(pSymbol + 1) ==
+ *((LPWORD)vRegList + index)) {
+ *lpulValue = index;
+ return ASM_REG_DWORD;
+ }
+ }
+ }
+
+ // test for control, debug, and test registers
+
+ else if (ch1 == 'r') {
+ ch2 -= '0';
+ *lpulValue = ch2;
+
+ // legal control registers are CR0, CR2, CR3
+
+ if (ch0 == 'c') {
+ if (ch2 == 0 || ch2 == 2 || ch2 == 3) {
+ return ASM_REG_CONTROL;
+ }
+ }
+
+ // legal debug registers are DR0 - DR3, DR6, DR7
+
+ else if (ch0 == 'd') {
+ if (ch2 <= 3 || ch2 == 6 || ch2 == 7) {
+ return ASM_REG_DEBUG;
+ }
+ }
+
+ // legal trace registers are TR3 - TR7
+
+ else if (ch0 == 't') {
+ if (ch2 >= 3 && ch2 <= 7) {
+ return ASM_REG_TRACE;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+ULONG GetSymReg ( WORD ireg, LPDWORD lpul ) {
+
+ if ( ireg >= CV_REG_AL && ireg <= CV_REG_BH ) {
+ *lpul = ireg - CV_REG_AL;
+ return ASM_REG_BYTE;
+ }
+ else if ( ireg >= CV_REG_AX && ireg <= CV_REG_DI ) {
+ *lpul = ireg - CV_REG_AX;
+ return ASM_REG_WORD;
+ }
+ else if ( ireg >= CV_REG_EAX && ireg <= CV_REG_EDI ) {
+ *lpul = ireg - CV_REG_EAX;
+ return ASM_REG_DWORD;
+ }
+ else if ( ireg >= CV_REG_ES && ireg <= CV_REG_GS ) {
+ *lpul = ireg - CV_REG_ES;
+ return ASM_REG_SEGMENT;
+ }
+ else if ( ireg >= CV_REG_ST0 && ireg <= CV_REG_ST7 ) {
+ *lpul = ireg - CV_REG_ST0;
+ return ASM_REG_INDFLT;
+ }
+ else {
+ *((XOSD*)lpul) = xosdAsmSymbol;
+ return ASM_ERROR_CLASS;
+ }
+}
+
+// Operand parser - recursive descent
+//
+// Grammar productions:
+//
+// <Operand> ::= <register> | <Expr>
+// <Expr> ::= <orTerm> [(XOR | OR) <orTerm>]*
+// <orTerm> ::= <andTerm> [AND <andTerm>]*
+// <andTerm> ::= [NOT]* <notTerm>
+// <notTerm> ::= <relTerm> [(EQ | NE | GE | GT | LE | LT) <relTerm>]*
+// <relTerm> ::= <addTerm> [(- | +) <addTerm>]*
+// <addTerm> ::= <mulTerm> [(* | / | MOD | SHL | SHR) <mulTerm>]*
+// <mulTerm> ::= [(- | +)]* <signTerm>
+// <signTerm> ::= [(HIGH | LOW)]* <byteTerm>
+// <byteTerm> ::= [(OFFSET | <type> PTR)]* <offTerm>
+// <offTerm> ::= [<segovr>] <colnTerm>
+// <colnTerm> ::= <dotTerm> [.<dotTerm>]*
+// <dotTerm> ::= <indxTerm> ['['<Expr>']']*
+// <indxTerm> ::= <index-reg> | <symbol> | <number> | '('<Expr>')'
+// | '['<Expr>']'
+
+// <Operand> ::= <register> | <Expr>
+
+XOSD GetAsmOperand ( PASM_VALUE pavExpr ) {
+ ULONG tokenvalue;
+ ULONG classvalue;
+
+ classvalue = PeekAsmToken ( &tokenvalue );
+ if ( ( classvalue & ASM_CLASS_MASK ) == ASM_REG_CLASS ) {
+ AcceptAsmToken();
+ classvalue &= ASM_TYPE_MASK;
+ pavExpr->flags = fREG;
+ pavExpr->base = (BYTE)tokenvalue; // index within reg group
+ pavExpr->index = regType[classvalue - 1];
+ pavExpr->size = regSize[classvalue - 1];
+ }
+ else {
+ XOSD xosd = GetAsmExpr ( pavExpr, FALSE );
+
+ if ( xosd != xosdNone ) {
+ return xosd;
+ }
+
+ if (pavExpr->reloc > 1) { // only 0 and 1 are allowed
+ return xosdAsmOperand;
+ }
+ }
+
+ return xosdNone;
+}
+
+// <Expr> ::= <orTerm> [(XOR | OR) <orTerm>]*
+
+XOSD GetAsmExpr ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ASM_VALUE avTerm;
+ XOSD xosd = xosdNone;
+
+ if ( ( xosd = GetAsmOrTerm ( pavValue, fBracket ) ) != xosdNone ) {
+ return xosd;
+ }
+
+ while ( PeekAsmToken ( &tokenvalue ) == ASM_OROP_CLASS ) {
+
+ AcceptAsmToken ( );
+ if ( ( xosd = GetAsmOrTerm ( &avTerm, fBracket ) ) != xosdNone ) {
+ return xosd;
+ }
+
+ if ( !( pavValue->flags & avTerm.flags & fIMM ) ) {
+ return xosdAsmOperand;
+ }
+ if ( tokenvalue == ASM_OROP_OR ) {
+ pavValue->value |= avTerm.value;
+ }
+ else {
+ pavValue->value ^= avTerm.value;
+ }
+ }
+
+ return xosdNone;
+}
+
+// <orTerm> ::= <andTerm> [AND <andTerm>]*
+
+XOSD GetAsmOrTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ASM_VALUE avTerm;
+ XOSD xosd = xosdNone;
+
+ if ( ( xosd = GetAsmAndTerm ( pavValue, fBracket ) ) == xosdNone ) {
+ while ( PeekAsmToken ( &tokenvalue ) == ASM_ANDOP_CLASS ) {
+ AcceptAsmToken ( );
+ if ( ( xosd = GetAsmAndTerm ( &avTerm, fBracket ) ) == xosdNone ) {
+ if ( !( pavValue->flags & avTerm.flags & fIMM ) ) {
+ xosd = xosdAsmOperand;
+ }
+ else {
+ pavValue->value &= avTerm.value;
+ }
+ }
+ }
+ }
+ return xosd;
+}
+
+// <andTerm> ::= [NOT]* <notTerm>
+
+XOSD GetAsmAndTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ XOSD xosd = xosdNone;
+
+ if ( PeekAsmToken ( &tokenvalue ) == ASM_NOTOP_CLASS ) {
+ AcceptAsmToken ( );
+ if ( ( xosd = GetAsmAndTerm ( pavValue, fBracket ) ) == xosdNone ) {
+ if ( !( pavValue->flags & fIMM ) ) {
+ xosd = xosdAsmOperand;
+ }
+ else {
+ pavValue->value = ~pavValue->value;
+ }
+ }
+ }
+ else {
+ xosd = GetAsmNotTerm ( pavValue, fBracket );
+ }
+
+ return xosd;
+}
+
+// <notTerm> ::= <relTerm> [(EQ | NE | GE | GT | LE | LT) <relTerm>]*
+
+XOSD GetAsmNotTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ULONG fTest;
+ ULONG fAddress;
+ ASM_VALUE avTerm;
+ XOSD xosd = xosdNone;
+
+ if ( ( xosd = GetAsmRelTerm ( pavValue, fBracket ) ) == xosdNone ) {
+ while ( PeekAsmToken ( &tokenvalue ) == ASM_RELOP_CLASS ) {
+
+ AcceptAsmToken ( );
+ xosd = GetAsmRelTerm ( &avTerm, fBracket );
+
+ if (
+ xosd == xosdNone &&
+ ( !( pavValue->flags & avTerm.flags & fIMM ) ||
+ pavValue->reloc > 1 || avTerm.reloc > 1
+ )
+ ) {
+ xosd = xosdAsmOperand;
+ }
+ else if ( xosd == xosdNone ) {
+ fAddress = pavValue->reloc | avTerm.reloc;
+ switch ( tokenvalue ) {
+ case ASM_RELOP_EQ:
+ fTest = pavValue->value == avTerm.value;
+ break;
+
+ case ASM_RELOP_NE:
+ fTest = pavValue->value != avTerm.value;
+ break;
+
+ case ASM_RELOP_GE:
+ if ( fAddress ) {
+ fTest = pavValue->value >= avTerm.value;
+ }
+ else {
+ fTest = (LONG)pavValue->value >= (LONG)avTerm.value;
+ }
+ break;
+
+ case ASM_RELOP_GT:
+ if ( fAddress ) {
+ fTest = pavValue->value > avTerm.value;
+ }
+ else {
+ fTest = (LONG)pavValue->value > (LONG)avTerm.value;
+ }
+ break;
+ case ASM_RELOP_LE:
+ if ( fAddress ) {
+ fTest = pavValue->value <= avTerm.value;
+ }
+ else {
+ fTest = (LONG)pavValue->value <= (LONG)avTerm.value;
+ }
+ break;
+
+ case ASM_RELOP_LT:
+ if ( fAddress ) {
+ fTest = pavValue->value < avTerm.value;
+ }
+ else {
+ fTest = (LONG)pavValue->value < (LONG)avTerm.value;
+ }
+ break;
+
+ default:
+ // printf ( "bad RELOP type\n" );
+ break;
+ }
+
+ pavValue->value = -((signed)fTest); // FALSE = 0; TRUE = -1
+ pavValue->reloc = 0;
+ pavValue->size = sizeB; // immediate value is byte
+ }
+ }
+ }
+
+ return xosd;
+}
+
+// <relTerm> ::= <addTerm> [(- | +) <addTerm>]*
+
+XOSD GetAsmRelTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ASM_VALUE avTerm;
+ XOSD xosd = xosdNone;
+
+ if ( ( xosd = GetAsmAddTerm ( pavValue, fBracket ) ) == xosdNone ) {
+ while ( PeekAsmToken ( &tokenvalue ) == ASM_ADDOP_CLASS ) {
+
+ AcceptAsmToken ( );
+
+ if ( ( xosd = GetAsmAddTerm ( &avTerm, fBracket ) ) == xosdNone ) {
+ if ( tokenvalue == ASM_ADDOP_MINUS ) {
+ if ( !( avTerm.flags & (fIMM | fPTR ) ) ) {
+ xosd = xosdAsmOperand;
+ }
+ else {
+ avTerm.value = -((signed)avTerm.value);
+ avTerm.reloc = (BYTE)(-avTerm.reloc);
+ }
+ }
+
+ if ( xosd == xosdNone ) {
+ xosd = AddAsmValues ( pavValue, &avTerm );
+ }
+ }
+ }
+ }
+
+ return xosd;
+}
+
+// <addTerm> ::= <mulTerm> [(* | / | MOD | SHL | SHR) <mulTerm>]*
+
+XOSD GetAsmAddTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ASM_VALUE avTerm;
+ XOSD xosd = xosdNone;
+
+ if ( ( xosd = GetAsmMulTerm ( pavValue, fBracket ) ) == xosdNone ) {
+
+ while ( PeekAsmToken ( &tokenvalue ) == ASM_MULOP_CLASS ) {
+ AcceptAsmToken ( );
+ xosd = GetAsmMulTerm ( &avTerm, fBracket );
+
+ if ( xosd != xosdNone ) {
+ break;
+ }
+ else if ( tokenvalue == ASM_MULOP_MULT ) {
+ if (pavValue->flags & fIMM) {
+ SwapPavs(pavValue, &avTerm);
+ }
+ if (!(avTerm.flags & fIMM)) {
+ xosd = xosdAsmOperand;
+ break;
+ }
+ if (pavValue->flags & fIMM) {
+ pavValue->value *= avTerm.value;
+ }
+ else if (
+ ( pavValue->flags & fPTR32 ) &&
+ pavValue->value == 0 &&
+ pavValue->base != indSP &&
+ pavValue->index == 0xff
+ ) {
+ pavValue->index = pavValue->base;
+ pavValue->base = 0xff;
+ pavValue->scale = 0xff;
+ if (avTerm.value == 1) {
+ pavValue->scale = 0;
+ }
+ if (avTerm.value == 2) {
+ pavValue->scale = 1;
+ }
+ if (avTerm.value == 4) {
+ pavValue->scale = 2;
+ }
+ if (avTerm.value == 8) {
+ pavValue->scale = 3;
+ }
+ if (pavValue->scale == 0xff) {
+ xosd = xosdAsmOperand;
+ break;
+ }
+ }
+ else {
+ xosd = xosdAsmOperand;
+ break;
+ }
+ }
+ else if ( !( pavValue->flags & avTerm.flags & fIMM ) ) {
+ xosd = xosdAsmOperand;
+ break;
+ }
+ else if (
+ tokenvalue == ASM_MULOP_DIVIDE || tokenvalue == ASM_MULOP_MOD
+ ) {
+ if ( avTerm.value == 0 ) {
+ xosd = xosdAsmDivide;
+ break;
+ }
+ if ( tokenvalue == ASM_MULOP_DIVIDE ) {
+ pavValue->value /= avTerm.value;
+ }
+ else {
+ pavValue->value %= avTerm.value;
+ }
+ }
+ else if ( tokenvalue == ASM_MULOP_SHL ) {
+ pavValue->value <<= avTerm.value;
+ }
+ else {
+ pavValue->value >>= avTerm.value;
+ }
+ }
+ }
+
+ return xosd;
+}
+
+// <mulTerm> ::= [(- | +)]* <signTerm>
+
+// C-6 ICEs when this is optimized
+
+#pragma optimize ( "", off )
+
+XOSD GetAsmMulTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ XOSD xosd = xosdNone;
+
+ if ( PeekAsmToken ( &tokenvalue ) == ASM_ADDOP_CLASS ) { // BY WO DW POI UNDN
+ AcceptAsmToken();
+
+ if ( ( xosd = GetAsmMulTerm ( pavValue, fBracket ) ) == xosdNone ) {
+
+ if ( tokenvalue == ASM_ADDOP_MINUS ) {
+ if ( !( pavValue->flags & ( fIMM | fPTR ) ) ) {
+ xosd = xosdAsmOperand;
+ }
+ else {
+ pavValue->value = -((signed)pavValue->value);
+ pavValue->reloc = (BYTE)(-pavValue->reloc);
+ }
+ }
+ }
+ }
+ else {
+ xosd = GetAsmSignTerm ( pavValue, fBracket );
+ }
+
+ return xosd;
+}
+#pragma optimize ( "", on )
+
+// <signTerm> ::= [(HIGH | LOW)]* <byteTerm>
+
+XOSD GetAsmSignTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ XOSD xosd = xosdNone;
+
+ if ( PeekAsmToken ( &tokenvalue ) == ASM_LOWOP_CLASS ) {
+ AcceptAsmToken();
+ if ( ( xosd = GetAsmSignTerm ( pavValue, fBracket ) ) == xosdNone ) {
+
+ if ( !( pavValue->flags & ( fIMM | fPTR ) ) ) {
+ xosd = xosdAsmOperand;
+ }
+ else if ( tokenvalue == ASM_LOWOP_LOW ) {
+ pavValue->value = pavValue->value & 0xff;
+ }
+ else {
+ pavValue->value = (pavValue->value & ~0xff) >> 8;
+ }
+ if ( xosd == xosdNone ) {
+ pavValue->flags = fIMM; // make an immediate value
+ pavValue->reloc = 0;
+ pavValue->segment = segX;
+ pavValue->size = sizeB; // byte value
+ }
+ }
+ }
+ else {
+ xosd = GetAsmByteTerm ( pavValue, fBracket );
+ }
+
+ return xosd;
+}
+
+// <byteTerm> ::= [(OFFSET | <size> PTR)]* <offTerm>
+
+XOSD GetAsmByteTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ULONG classvalue;
+ XOSD xosd = xosdNone;
+
+ classvalue = PeekAsmToken ( &tokenvalue );
+ if ( classvalue == ASM_OFFOP_CLASS ) {
+ AcceptAsmToken();
+ if ( ( xosd = GetAsmByteTerm ( pavValue, fBracket ) ) == xosdNone ) {
+ if ( !(pavValue->flags & (fIMM | fPTR)) || pavValue->reloc > 1 ) {
+ xosd = xosdAsmOperand;
+ }
+ pavValue->flags = fIMM; // make offset an immediate value
+ pavValue->reloc = 0;
+ pavValue->size = sizeX;
+ pavValue->segment = segX;
+ }
+ }
+ else if ( classvalue == ASM_SIZE_CLASS ) {
+ ULONG ulAsmClass;
+
+ AcceptAsmToken();
+ ulAsmClass = GetAsmToken ( &classvalue );
+ if ( ulAsmClass == ASM_ERROR_CLASS ) {
+ xosd = (XOSD) classvalue;
+ }
+ else if ( ulAsmClass != ASM_PTROP_CLASS ) { // dummy token
+ xosd = xosdAsmSyntax;
+ }
+ else if ( ( xosd = GetAsmByteTerm ( pavValue, fBracket ) ) != xosdNone ) {
+ if (
+ !(pavValue->flags & (fIMM | fPTR | fPTR16 | fPTR32))
+ || pavValue->reloc > 1
+ || pavValue->size != sizeX
+ ) {
+ xosd = xosdAsmOperand;
+ }
+ else {
+ pavValue->reloc = 1; // make ptr a relocatable value
+ if ( pavValue->flags & fIMM ) {
+ pavValue->flags = fPTR;
+ }
+ pavValue->size = (BYTE)(tokenvalue & ASM_TYPE_MASK);
+ // value has "size?"
+ }
+ }
+ }
+ else {
+ xosd = GetAsmOffTerm ( pavValue, fBracket );
+ }
+
+ return xosd;
+}
+
+// <offTerm> ::= [<segovr>] <colnTerm>
+
+XOSD GetAsmOffTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG classvalue;
+ ULONG tokenvalue;
+ XOSD xosd = xosdNone;
+
+ classvalue = PeekAsmToken(&tokenvalue);
+ if ( classvalue == ASM_SEGOVR_CLASS || classvalue == ASM_SEGMENT_CLASS ) {
+ if ( fBracket ) {
+ return xosdAsmSyntax;
+ }
+ else {
+ AcceptAsmToken ( );
+ }
+ }
+
+ if ( ( xosd = GetAsmColnTerm ( pavValue, fBracket ) ) != xosdNone ) {
+ return xosd;
+ }
+
+ if ( classvalue == ASM_SEGOVR_CLASS ) {
+ if ( pavValue->reloc > 1 || pavValue->segovr != segX ) {
+ return xosdAsmOperand;
+ }
+ pavValue->reloc = 1; // make ptr a relocatable value
+ if ( pavValue->flags & fIMM ) {
+ pavValue->flags = fPTR;
+ }
+ pavValue->segovr = (BYTE)tokenvalue; // has segment override
+ }
+ else if (classvalue == ASM_SEGMENT_CLASS) {
+ if (!(pavValue->flags & fIMM) || pavValue->reloc > 1) {
+ return xosdAsmOperand;
+ }
+ pavValue->segment = (USHORT)tokenvalue; // segment has segment value
+ pavValue->flags = fFPTR; // set flag for far pointer
+ }
+
+ return xosd;
+}
+
+// <colnTerm> ::= <dotTerm> [.<dotTerm>]*
+
+XOSD GetAsmColnTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ASM_VALUE avTerm;
+ XOSD xosd = xosdNone;
+
+ xosd = GetAsmDotTerm ( pavValue, fBracket );
+ while (
+ xosd == xosdNone &&
+ PeekAsmToken(&tokenvalue) == ASM_DOTOP_CLASS
+ ) {
+ AcceptAsmToken ( );
+ if ( ( xosd = GetAsmDotTerm ( &avTerm, fBracket ) ) == xosdNone ) {
+ xosd = AddAsmValues ( pavValue, &avTerm );
+ }
+ }
+
+ return xosd;
+}
+
+// <dotTerm> ::= <indxTerm> ['['<Expr>']']*
+
+XOSD GetAsmDotTerm ( PASM_VALUE pavValue, BYTE fBracket ) {
+ ULONG tokenvalue;
+ ASM_VALUE avExpr;
+ XOSD xosd = xosdNone;
+
+ if ( ( xosd = GetAsmIndxTerm ( pavValue, fBracket ) ) == xosdNone ) {
+
+ if ( pavValue->reloc > 1 ) {
+ xosd = xosdAsmOperand;
+ }
+ else {
+ while ( PeekAsmToken ( &tokenvalue ) == ASM_LBRACK_CLASS ) {
+ AcceptAsmToken();
+ if ( fBracket ) {
+ xosd = xosdAsmSyntax;
+ break;
+ }
+ if (
+ ( xosd = GetAsmExpr ( &avExpr, TRUE ) ) != xosdNone ||
+ ( xosd = AddAsmValues ( pavValue, &avExpr ) ) != xosdNone
+ ) {
+ break;
+ }
+
+ if ( GetAsmToken ( &tokenvalue ) != ASM_RBRACK_CLASS ) {
+ xosd = xosdAsmSyntax;
+ break;
+ }
+
+ if ( pavValue->flags & fIMM ) {
+ pavValue->flags = fPTR;
+ }
+ }
+ }
+ }
+
+ return xosd;
+}
+
+// <indxTerm> ::= <index-reg> | <symbol> | <number> | '('<Expr>')'
+// | '['<Expr>']'
+
+XOSD GetAsmIndxTerm (PASM_VALUE pavValue, BYTE fBracket) {
+ ULONG tokenvalue;
+ ULONG classvalue;
+ XOSD xosd = xosdNone;
+
+ classvalue = GetAsmToken ( &tokenvalue );
+ pavValue->segovr = segX;
+ pavValue->size = sizeX;
+ pavValue->reloc = 0;
+ pavValue->value = 0;
+ if ( classvalue == ASM_ERROR_CLASS ) {
+ xosd = (XOSD) classvalue;
+ }
+ if ( classvalue == ASM_LPAREN_CLASS ) {
+
+ if ( ( xosd = GetAsmExpr ( pavValue, fBracket ) ) == xosdNone ) {
+ if ( GetAsmToken ( &tokenvalue ) != ASM_RPAREN_CLASS ) {
+ xosd = xosdAsmSyntax;
+ }
+ }
+ }
+ else if (classvalue == ASM_LBRACK_CLASS) {
+ if ( fBracket ) {
+ xosd = xosdAsmSyntax;
+ }
+ else if ( ( xosd = GetAsmExpr ( pavValue, TRUE ) ) == xosdNone ) {
+
+ if ( GetAsmToken ( &tokenvalue ) != ASM_RBRACK_CLASS ) {
+ xosd = xosdAsmSyntax;
+ }
+ else if ( pavValue->flags == fIMM ) {
+ pavValue->flags = fPTR;
+ }
+ }
+ }
+ else if ( classvalue == ASM_SYMBOL_IMM ) {
+ pavValue->value = tokenvalue;
+ pavValue->flags = fIMM;
+ pavValue->reloc = 1;
+ }
+ else if ( classvalue == ASM_SYMBOL_PTR ) {
+ pavValue->value = offAddr ( *( (LPADDR) tokenvalue ) );
+ pavValue->segment = segAddr ( *( (LPADDR) tokenvalue ) );
+ pavValue->flags = fFPTR;
+ pavValue->size = (BYTE)( ADDR_IS_FLAT(*((LPADDR)tokenvalue)) ? 4: 2);
+
+ }
+ else if ( classvalue == ASM_SYMBOL_BASE ) {
+ if ( !fBracket ) {
+ xosd = xosdAsmSyntax;
+ }
+ else {
+ pavValue->value = tokenvalue;
+ if ( fDBit ) {
+ pavValue->base = 5;
+ pavValue->flags = fPTR32;
+ }
+ else {
+ pavValue->base = 6;
+ pavValue->flags = fPTR16;
+ }
+ }
+ }
+ else if (classvalue == ASM_NUMBER_CLASS) {
+ pavValue->value = tokenvalue;
+ pavValue->flags = fIMM;
+ }
+ else if (classvalue == ASM_REG_WORD) {
+ if ( !fBracket ) {
+ xosd = xosdAsmSyntax;
+ }
+ else {
+ pavValue->flags = fPTR16;
+ pavValue->base = tabWordReg [ tokenvalue ];
+ if ( pavValue->base == 0xff ) {
+ xosd = xosdAsmOperand;
+ }
+ }
+ }
+ else if ( classvalue == ASM_REG_DWORD ) {
+ if ( !fBracket ) {
+ xosd = xosdAsmSyntax;
+ }
+ else {
+ pavValue->flags = fPTR32;
+ pavValue->base = (BYTE)tokenvalue;
+ pavValue->index = 0xff;
+ }
+ }
+ else {
+ xosd = xosdAsmSyntax;
+ }
+
+ return xosd;
+}
+
+XOSD AddAsmValues ( PASM_VALUE pavLeft, PASM_VALUE pavRight ) {
+ // swap values if left one is a pointer
+
+ if ( pavLeft->flags & fPTR ) {
+ SwapPavs ( pavLeft, pavRight );
+ }
+
+ // swap values if left one is an immediate
+
+ if ( pavLeft->flags & fIMM ) {
+ SwapPavs ( pavLeft, pavRight );
+ }
+
+ // the above swaps reduce the cases to test.
+ // pairs with an immediate will have it on the right
+ // pairs with a pointer will have it on the right,
+ // except for a pointer-immediate pair
+
+ // if both values are 16-bit pointers, combine them
+
+ if ( pavLeft->flags & pavRight->flags & fPTR16 ) {
+
+ // if either side has both registers (rm < 4), error
+
+ if ( !(pavLeft->base & pavRight->base & 4) ) {
+ return xosdAsmOperand;
+ }
+
+ // use lookup table to compute new rm value
+
+ pavLeft->base = rm16Table[((pavLeft->base & 3) << 2) +
+ (pavRight->base & 3)];
+ if ( pavLeft->base == 0xff ) {
+ return xosdAsmOperand;
+ }
+
+ pavRight->flags = fPTR;
+ }
+
+ // if both values are 32-bit pointers, combine them
+
+ if ( pavLeft->flags & pavRight->flags & fPTR32 ) {
+
+ // error if either side has both base and index,
+ // or if both have index
+
+ if (
+ ((pavLeft->base | pavLeft->index) != 0xff) ||
+ ((pavRight->base | pavRight->index) != 0xff) ||
+ ((pavLeft->index | pavRight->index) != 0xff)
+ ) {
+ return xosdAsmOperand;
+ }
+
+ // if left side has base, swap sides
+
+ if ( pavLeft->base != 0xff ) {
+ SwapPavs(pavLeft, pavRight);
+ }
+
+ // two cases remaining, index-base and base-base
+
+ if ( pavLeft->base != 0xff ) {
+
+ // left side has base, promote to index but swap if left
+ // base is ESP since it cannot be an index register
+
+ if ( pavLeft->base == indSP ) {
+ SwapPavs(pavLeft, pavRight);
+ }
+
+ if ( pavLeft->base == indSP ) {
+ return xosdAsmOperand;
+ }
+ else {
+ pavLeft->index = pavLeft->base;
+ pavLeft->scale = 0;
+ }
+ }
+
+ // finish by setting left side base to right side value
+
+ pavLeft->base = pavRight->base;
+
+ pavRight->flags = fPTR;
+ }
+
+ // if left side is any pointer and right is nonindex pointer,
+ // combine them. (above cases set right side to use this code)
+
+ if (
+ ( pavLeft->flags & ( fPTR | fPTR16 | fPTR32 ) ) &&
+ ( pavRight->flags & fPTR)
+ ) {
+ if (
+ pavLeft->segovr + pavRight->segovr != segX &&
+ pavLeft->segovr != pavRight->segovr
+ ) {
+ return xosdAsmOperand;
+ }
+
+ if (
+ pavLeft->size + pavRight->size != sizeX &&
+ pavLeft->size != pavRight->size
+ ) {
+ return xosdAsmOperand;
+ }
+ pavRight->flags = fIMM;
+ }
+
+ // if right side is immediate, add values and relocs
+ // (above case sets right side to use this code)
+ // illegal value types do not have right side set to fIMM
+
+ if ( pavRight->flags & fIMM ) {
+ pavLeft->value += pavRight->value;
+ pavLeft->reloc += pavRight->reloc;
+ }
+ else {
+ return xosdAsmOperand;
+ }
+
+ return xosdNone;
+}
+
+void SwapPavs (PASM_VALUE pavFirst, PASM_VALUE pavSecond)
+{
+ ASM_VALUE temp;
+
+ _fmemcpy ( &temp, pavFirst, sizeof ( ASM_VALUE ) );
+ _fmemcpy ( pavFirst, pavSecond, sizeof ( ASM_VALUE ) );
+ _fmemcpy ( pavSecond, &temp, sizeof ( ASM_VALUE ) );
+}
diff --git a/private/windbg/em/p_i386/asmtpl.c b/private/windbg/em/p_i386/asmtpl.c
new file mode 100644
index 000000000..98c8d156c
--- /dev/null
+++ b/private/windbg/em/p_i386/asmtpl.c
@@ -0,0 +1,1660 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "asm.h"
+
+//
+
+
+LPBYTE SearchOpcode(LPBYTE);
+
+// type and size table is ordered on enum of operand types
+
+OPNDTYPE mapOpndType[] = {
+ { typAX, sizeB }, // opnAL - AL register - byte
+ { typAX, sizeW }, // opnAX - AX register - word
+ { typAX, sizeV }, // opneAX - eAX register - (d)word
+ { typCL, sizeB }, // opnCL - CX register - byte
+ { typDX, sizeW }, // opnDX - DX register - word (DX)
+ { typAbs, sizeV }, // opnAp - absolute pointer (16:16/32)
+ { typExp, sizeB }, // opnEb - expression (mem/reg) - byte
+ { typExp, sizeW }, // opnEw - expression (mem/reg) - word
+ { typExp, sizeV }, // opnEv - expression (mem/reg) - (d)word
+ { typGen, sizeB }, // opnGb - general register - byte
+ { typGen, sizeW }, // opnGw - general register - word
+ { typGen, sizeV }, // opnGv - general register - (d)word
+ { typGen, sizeD }, // opnGd - general register - dword
+ { typIm1, sizeB }, // opnIm1 - immediate - value 1
+ { typIm3, sizeB }, // opnIm3 - immediate - value 3
+ { typImm, sizeB }, // opnIb - immediate - byte
+ { typImm, sizeW }, // opnIw - immediate - word
+ { typImm, sizeV }, // opnIv - immediate - (d)word
+ { typJmp, sizeB }, // opnJb - relative jump - byte
+ { typJmp, sizeV }, // opnJv - relative jump - (d)word
+ { typMem, sizeX }, // opnM - memory pointer - nosize
+ { typMem, sizeA }, // opnMa - memory pointer - (16:16, 32:32)
+ { typMem, sizeB }, // opnMb - memory pointer - byte
+ { typMem, sizeW }, // opnMw - memory pointer - word
+ { typMem, sizeD }, // opnMd - memory pointer - dword
+ { typMem, sizeP }, // opnMp - memory pointer - (d)(f)word
+ { typMem, sizeS }, // opnMs - memory pointer - sword
+ { typMem, sizeQ }, // opnMq - memory pointer - qword
+ { typMem, sizeT }, // opnMt - memory pointer - ten-byte
+ { typMem, sizeV }, // opnMv - memory pointer - (d)word
+ { typCtl, sizeD }, // opnCd - control register - dword
+ { typDbg, sizeD }, // opnDd - debug register - dword
+ { typTrc, sizeD }, // opnTd - trace register - dword
+ { typReg, sizeD }, // opnRd - general register - dword
+ { typSt, sizeT }, // opnSt - floating point top-of-stack
+ { typSti, sizeT }, // opnSti - floating point index-on-stack
+ { typSeg, sizeW }, // opnSeg - segment register - PUSH / POP
+ { typSgr, sizeW }, // opnSw - segment register - MOV
+ { typXsi, sizeB }, // opnXb - string source - byte
+ { typXsi, sizeV }, // opnXv - string source - (d)word
+ { typYdi, sizeB }, // opnYb - string destination - byte
+ { typYdi, sizeV }, // opnYv - string destination - (d)word
+ { typOff, sizeB }, // opnOb - memory offset - byte
+ { typOff, sizeV } // opnOv - memory offset - (d)word
+ };
+
+BYTE szAAA[] = {
+ 'a', 'a', 'a', '\0',
+ 0x37, asNone + tEnd + eEnd };
+
+BYTE szAAD[] = {
+ 'a', 'a', 'd', '\0',
+ 0xd5, as0x0a + tEnd + eEnd };
+
+BYTE szAAM[] = {
+ 'a', 'a', 'm', '\0',
+ 0xd4, as0x0a + tEnd + eEnd };
+
+BYTE szAAS[] = {
+ 'a', 'a', 's', '\0',
+ 0x3f, asNone + tEnd + eEnd };
+
+BYTE szADC[] = {
+ 'a', 'd', 'c', '\0',
+ 0x14, opnAL, opnIb + tEnd,
+ 0x15, opneAX, opnIv + tEnd,
+ 0x80, asReg2, opnEb, opnIb + tEnd,
+ 0x83, asReg2, opnEv, opnIb + tEnd,
+ 0x81, asReg2, opnEv, opnIv + tEnd,
+ 0x10, opnEb, opnGb + tEnd,
+ 0x11, opnEv, opnGv + tEnd,
+ 0x12, opnGb, opnEb + tEnd,
+ 0x13, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szADD[] = {
+ 'a', 'd', 'd', '\0',
+ 0x04, opnAL, opnIb + tEnd,
+ 0x05, opneAX, opnIv + tEnd,
+ 0x80, asReg0, opnEb, opnIb + tEnd,
+ 0x83, asReg0, opnEv, opnIb + tEnd,
+ 0x81, asReg0, opnEv, opnIv + tEnd,
+ 0x00, opnEb, opnGb + tEnd,
+ 0x01, opnEv, opnGv + tEnd,
+ 0x02, opnGb, opnEb + tEnd,
+ 0x03, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szAND[] = {
+ 'a', 'n', 'd', '\0',
+ 0x24, opnAL, opnIb + tEnd,
+ 0x25, opneAX, opnIv + tEnd,
+ 0x80, asReg4, opnEb, opnIb + tEnd,
+ 0x83, asReg4, opnEv, opnIb + tEnd,
+ 0x81, asReg4, opnEv, opnIv + tEnd,
+ 0x20, opnEb, opnGb + tEnd,
+ 0x21, opnEv, opnGv + tEnd,
+ 0x22, opnGb, opnEb + tEnd,
+ 0x23, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szARPL[] = {
+ 'a', 'r', 'p', 'l', '\0',
+ 0x63, opnEw, opnGw + tEnd + eEnd };
+
+BYTE szBOUND[] = {
+ 'b', 'o', 'u', 'n', 'd', '\0',
+ 0x62, opnGv, opnMa + tEnd + eEnd };
+
+BYTE szBSF[] = {
+ 'b', 's', 'f', '\0',
+ 0x0f, 0xbc, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szBSR[] = {
+ 'b', 's', 'r', '\0',
+ 0x0f, 0xbd, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szBSWAP[] = {
+ 'b', 's', 'w', 'a', 'p', '\0',
+ 0x0f, 0xc8, asOpRg, opnGd + tEnd + eEnd };
+
+BYTE szBT[] = {
+ 'b', 't', '\0',
+ 0x0f, 0xa3, opnEv, opnGv + tEnd,
+ 0x0f, 0xba, asReg4, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szBTC[] = {
+ 'b', 't', 'c', '\0',
+ 0x0f, 0xbb, opnEv, opnGv + tEnd,
+ 0x0f, 0xba, asReg7, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szBTR[] = {
+ 'b', 't', 'r', '\0',
+ 0x0f, 0xb3, opnEv, opnGv + tEnd,
+ 0x0f, 0xba, asReg6, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szBTS[] = {
+ 'b', 't', 's', '\0',
+ 0x0f, 0xab, opnEv, opnGv + tEnd,
+ 0x0f, 0xba, asReg5, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szCALL[] = {
+ 'c', 'a', 'l', 'l', '\0',
+ 0xe8, opnJv + tEnd,
+ 0xff, asReg2, asMpNx, opnEv + tEnd,
+ 0xff, asReg3, opnMp + tEnd,
+ 0x9a, opnAp + tEnd + eEnd };
+
+BYTE szCBW[] = {
+ 'c', 'b', 'w', '\0',
+ 0x98, asSiz0 + tEnd + eEnd };
+
+BYTE szCDQ[] = {
+ 'c', 'd', 'q', '\0',
+ 0x99, asSiz1 + tEnd + eEnd };
+
+BYTE szCLC[] = {
+ 'c', 'l', 'c', '\0',
+ 0xf8, asNone + tEnd + eEnd };
+
+BYTE szCLD[] = {
+ 'c', 'l', 'd', '\0',
+ 0xfc, asNone + tEnd + eEnd };
+
+BYTE szCLI[] = {
+ 'c', 'l', 'i', '\0',
+ 0xfa, asNone + tEnd + eEnd };
+
+BYTE szCLTS[] = {
+ 'c', 'l', 't', 's', '\0',
+ 0x0f, 0x06, asNone + tEnd + eEnd };
+
+BYTE szCMC[] = {
+ 'c', 'm', 'c', '\0',
+ 0xf5, asNone + tEnd + eEnd };
+
+BYTE szCMP[] = {
+ 'c', 'm', 'p', '\0',
+ 0x3c, opnAL, opnIb + tEnd,
+ 0x3d, opneAX, opnIv + tEnd,
+ 0x80, asReg7, opnEb, opnIb + tEnd,
+ 0x83, asReg7, opnEv, opnIb + tEnd,
+ 0x81, asReg7, opnEv, opnIv + tEnd,
+ 0x38, opnEb, opnGb + tEnd,
+ 0x39, opnEv, opnGv + tEnd,
+ 0x3a, opnGb, opnEb + tEnd,
+ 0x3b, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szCMPS[] = {
+ 'c', 'm', 'p', 's', '\0',
+ 0xa6, opnXb, opnYb + tEnd,
+ 0xa7, opnXv, opnYv + tEnd + eEnd };
+
+BYTE szCMPSB[] = {
+ 'c', 'm', 'p', 's', 'b', '\0',
+ 0xa6, asNone + tEnd + eEnd };
+
+BYTE szCMPSD[] = {
+ 'c', 'm', 'p', 's', 'd', '\0',
+ 0xa7, asSiz1 + tEnd + eEnd };
+
+BYTE szCMPSW[] = {
+ 'c', 'm', 'p', 's', 'w', '\0',
+ 0xa7, asSiz0 + tEnd + eEnd };
+
+BYTE szCMPXCHG[] = {
+ 'c', 'm', 'p', 'x', 'c', 'h', 'g', '\0',
+ 0x0f, 0xa6, opnEb, opnGb + tEnd,
+ 0x0f, 0xa7, opnEv, opnGv + tEnd + eEnd };
+
+BYTE szCS_A[] = {
+ 'c', 's', ':', '\0',
+ 0x2e, asPrfx + tEnd + eEnd };
+
+BYTE szCWD[] = {
+ 'c', 'w', 'd', '\0',
+ 0x99, asSiz0 + tEnd + eEnd };
+
+BYTE szCWDE[] = {
+ 'c', 'w', 'd', 'e', '\0',
+ 0x98, asSiz1 + tEnd + eEnd };
+
+BYTE szDAA[] = {
+ 'd', 'a', 'a', '\0',
+ 0x27, asNone + tEnd + eEnd };
+
+BYTE szDAS[] = {
+ 'd', 'a', 's', '\0',
+ 0x2f, asNone + tEnd + eEnd };
+
+BYTE szDEC[] = {
+ 'd', 'e', 'c', '\0',
+ 0x48, asOpRg, opnGv + tEnd,
+ 0xfe, asReg1, opnEb + tEnd,
+ 0xff, asReg1, opnEv + tEnd + eEnd };
+
+BYTE szDIV[] = {
+ 'd', 'i', 'v', '\0',
+ 0xf6, asReg6, opnEb + tEnd,
+ 0xf7, asReg6, opnEv + tEnd,
+ 0xf6, asReg6, opnAL, opnEb + tEnd,
+ 0xf7, asReg6, opneAX, opnEv + tEnd + eEnd };
+
+BYTE szDS_A[] = {
+ 'd', 's', ':', '\0',
+ 0x3e, asPrfx + tEnd + eEnd };
+
+BYTE szENTER[] = {
+ 'e', 'n', 't', 'e', 'r', '\0',
+ 0xc8, opnIw, opnIb + tEnd + eEnd };
+
+BYTE szES_A[] = {
+ 'e', 's', ':', '\0',
+ 0x36, asPrfx + tEnd + eEnd };
+
+BYTE szF2XM1[] = {
+ 'f', '2', 'x', 'm', '1', '\0',
+ 0xd8, 0xf0, asNone + tEnd + eEnd };
+
+BYTE szFABS[] = {
+ 'f', 'a', 'b', 's', '\0',
+ 0xd9, 0xe1, asNone + tEnd + eEnd };
+
+BYTE szFADD[] = {
+ 'f', 'a', 'd', 'd', '\0',
+ 0xd8, asReg0, opnMd, asFSiz + tEnd,
+ 0xdc, asReg0, opnMq + tEnd,
+ 0xd8, 0xc0, opnSt, opnSti + tEnd,
+ 0xdc, 0xc0, opnSti, opnSt + tEnd,
+ 0xdc, 0xc1, asNone + tEnd + eEnd };
+
+BYTE szFADDP[] = {
+ 'f', 'a', 'd', 'd', 'p', '\0',
+ 0xde, 0xc0, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFBLD[] = {
+ 'f', 'b', 'l', 'd', '\0',
+ 0xdf, asReg4, opnMt + tEnd + eEnd };
+
+BYTE szFBSTP[] = {
+ 'f', 'b', 's', 't', 'p', '\0',
+ 0xdf, asReg6, opnMt + tEnd + eEnd };
+
+BYTE szFCHS[] = {
+ 'f', 'c', 'h', 's', '\0',
+ 0xd9, 0xe0, asNone + tEnd + eEnd };
+
+BYTE szFCLEX[] = {
+ 'f', 'c', 'l', 'e', 'x', '\0',
+ 0xdb, 0xe2, asWait + tEnd + eEnd };
+
+BYTE szFCOM[] = {
+ 'f', 'c', 'o', 'm', '\0',
+ 0xd8, 0xd1, asNone + tEnd,
+ 0xd8, 0xd0, opnSti + tEnd,
+ 0xd8, asReg2, opnMd, asFSiz + tEnd,
+ 0xdc, asReg2, opnMq + tEnd + eEnd };
+
+BYTE szFCOMP[] = {
+ 'f', 'c', 'o', 'm', 'p', '\0',
+ 0xd8, 0xd9, asNone + tEnd,
+ 0xd8, 0xd8, opnSti + tEnd,
+ 0xd8, asReg3, opnMd, asFSiz + tEnd,
+ 0xdc, asReg3, opnMq + tEnd + eEnd };
+
+BYTE szFCOMPP[] = {
+ 'f', 'c', 'o', 'm', 'p', 'p', '\0',
+ 0xde, 0xd9, asNone + tEnd + eEnd };
+
+BYTE szFCOS[] = {
+ 'f', 'c', 'o', 's', '\0',
+ 0xd9, 0xff, asNone + tEnd + eEnd };
+
+BYTE szFDECSTP[] = {
+ 'f', 'd', 'e', 'c', 's', 't', 'p', '\0',
+ 0xd9, 0xf6, asWait + tEnd + eEnd };
+
+BYTE szFDISI[] = {
+ 'f', 'd', 'i', 's', 'i', '\0',
+ 0xdb, 0xe1, asWait + tEnd + eEnd };
+
+BYTE szFDIV[] = {
+ 'f', 'd', 'i', 'v', '\0',
+ 0xdc, 0xf9, asNone + tEnd,
+ 0xd8, asReg6, opnMd, asFSiz + tEnd,
+ 0xdc, asReg6, opnMq + tEnd,
+ 0xd8, 0xf0, opnSt, opnSti + tEnd,
+ 0xdc, 0xf8, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFDIVP[] = {
+ 'f', 'd', 'i', 'v', 'p', '\0',
+ 0xde, 0xf8, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFDIVR[] = {
+ 'f', 'd', 'i', 'v', 'r', '\0',
+ 0xde, 0xf1, asNone + tEnd,
+ 0xd8, asReg7, opnMd, asFSiz + tEnd,
+ 0xdc, asReg7, opnMq + tEnd,
+ 0xd8, 0xf8, opnSt, opnSti + tEnd,
+ 0xdc, 0xf0, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFDIVRP[] = {
+ 'f', 'd', 'i', 'v', 'r', 'p', '\0',
+ 0xde, 0xf0, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFENI[] = {
+ 'f', 'e', 'n', 'i', '\0',
+ 0xdb, 0xe0, asWait + tEnd + eEnd };
+
+BYTE szFFREE[] = {
+ 'f', 'f', 'r', 'e', 'e', '\0',
+ 0xdd, 0xc0, asWait, opnSti + tEnd + eEnd };
+
+BYTE szFIADD[] = {
+ 'f', 'i', 'a', 'd', 'd', '\0',
+ 0xde, asReg0, opnMw, asFSiz + tEnd,
+ 0xda, asReg0, opnMd + tEnd + eEnd };
+
+BYTE szFICOM[] = {
+ 'f', 'i', 'c', 'o', 'm', '\0',
+ 0xde, asReg2, opnMw, asFSiz + tEnd,
+ 0xda, asReg2, opnMd + tEnd + eEnd };
+
+BYTE szFICOMP[] = {
+ 'f', 'i', 'c', 'o', 'm', 'p', '\0',
+ 0xde, asReg3, opnMw, asFSiz + tEnd,
+ 0xda, asReg3, opnMd + tEnd + eEnd };
+
+BYTE szFIDIV[] = {
+ 'f', 'i', 'd', 'i', 'v', '\0',
+ 0xde, asReg6, opnMw, asFSiz + tEnd,
+ 0xda, asReg6, opnMd + tEnd + eEnd };
+
+BYTE szFIDIVR[] = {
+ 'f', 'i', 'd', 'i', 'v', 'r', '\0',
+ 0xde, asReg7, opnMw, asFSiz + tEnd,
+ 0xda, asReg7, opnMd + tEnd + eEnd };
+
+BYTE szFILD[] = {
+ 'f', 'i', 'l', 'd', '\0',
+ 0xdf, asReg0, opnMw, asFSiz + tEnd,
+ 0xdb, asReg0, opnMd + tEnd,
+ 0xdf, asReg5, opnMq + tEnd + eEnd };
+
+BYTE szFIMUL[] = {
+ 'f', 'i', 'm', 'u', 'l', '\0',
+ 0xde, asReg1, opnMw, asFSiz + tEnd,
+ 0xda, asReg1, opnMd + tEnd + eEnd };
+
+BYTE szFINCSTP[] = {
+ 'f', 'i', 'n', 'c', 's', 't', 'p', '\0',
+ 0xd9, 0xf7, asWait + tEnd + eEnd };
+
+BYTE szFINIT[] = {
+ 'f', 'i', 'n', 'i', 't', '\0',
+ 0xdb, 0xe3, asWait + tEnd + eEnd };
+
+BYTE szFIST[] = {
+ 'f', 'i', 's', 't', '\0',
+ 0xdf, asReg2, opnMw, asFSiz + tEnd,
+ 0xdb, asReg2, opnMd + tEnd + eEnd };
+
+BYTE szFISTP[] = {
+ 'f', 'i', 's', 't', 'p', '\0',
+ 0xdf, asReg3, opnMw, asFSiz + tEnd,
+ 0xdb, asReg3, opnMd + tEnd,
+ 0xdf, asReg7, opnMq + tEnd + eEnd };
+
+BYTE szFISUB[] = {
+ 'f', 'i', 's', 'u', 'b', '\0',
+ 0xde, asReg4, opnMw, asFSiz + tEnd,
+ 0xda, asReg4, opnMd + tEnd + eEnd };
+
+BYTE szFISUBR[] = {
+ 'f', 'i', 's', 'u', 'b', 'r', '\0',
+ 0xde, asReg5, opnMw, asFSiz + tEnd,
+ 0xda, asReg5, opnMd + tEnd + eEnd };
+
+BYTE szFLD[] = {
+ 'f', 'l', 'd', '\0',
+ 0xd9, asReg0, opnMd, asFSiz + tEnd,
+ 0xdd, asReg0, opnMq + tEnd,
+ 0xdb, asReg5, opnMt + tEnd,
+ 0xd9, 0xc0, opnSti + tEnd + eEnd };
+
+BYTE szFLD1[] = {
+ 'f', 'l', 'd', '1', '\0',
+ 0xd9, 0xe8, asNone + tEnd + eEnd };
+
+BYTE szFLDCW[] = {
+ 'f', 'l', 'd', 'c', 'w', '\0',
+ 0xd9, asWait, asReg5, opnMw + tEnd + eEnd };
+
+BYTE szFLDENV[] = {
+ 'f', 'l', 'd', 'e', 'n', 'v', '\0',
+ 0xd9, asWait, asReg4, opnMw + tEnd + eEnd };
+
+BYTE szFLDL2E[] = {
+ 'f', 'l', 'd', 'l', '2', 'e', '\0',
+ 0xd9, 0xea, asNone + tEnd + eEnd };
+
+BYTE szFLDL2T[] = {
+ 'f', 'l', 'd', 'l', '2', 't', '\0',
+ 0xd9, 0xe9, asNone + tEnd + eEnd };
+
+BYTE szFLDLG2[] = {
+ 'f', 'l', 'd', 'l', 'g', '2', '\0',
+ 0xd9, 0xec, asNone + tEnd + eEnd };
+
+BYTE szFLDLN2[] = {
+ 'f', 'l', 'd', 'l', 'n', '2', '\0',
+ 0xd9, 0xed, asNone + tEnd + eEnd };
+
+BYTE szFLDPI[] = {
+ 'f', 'l', 'd', 'p', 'i', '\0',
+ 0xd9, 0xeb, asNone + tEnd + eEnd };
+
+BYTE szFLDZ[] = {
+ 'f', 'l', 'd', 'z', '\0',
+ 0xd9, 0xee, asNone + tEnd + eEnd };
+
+BYTE szFMUL[] = {
+ 'f', 'm', 'u', 'l', '\0',
+ 0xde, 0xc9, asNone + tEnd,
+ 0xd8, asReg1, opnMd, asFSiz + tEnd,
+ 0xdc, asReg1, opnMq + tEnd,
+ 0xd8, 0xc8, opnSt, opnSti + tEnd,
+ 0xdc, 0xc8, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFMULP[] = {
+ 'f', 'm', 'u', 'l', 'p', '\0',
+ 0xde, 0xc8, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFNCLEX[] = {
+ 'f', 'n', 'c', 'l', 'e', 'x', '\0',
+ 0xdb, 0xe2, asNone + tEnd + eEnd };
+
+BYTE szFNDISI[] = {
+ 'f', 'n', 'd', 'i', 's', 'i', '\0',
+ 0xdb, 0xe1, asNone + tEnd + eEnd };
+
+BYTE szFNENI[] = {
+ 'f', 'n', 'e', 'n', 'i', '\0',
+ 0xdb, 0xe0, asNone + tEnd + eEnd };
+
+BYTE szFNINIT[] = {
+ 'f', 'n', 'i', 'n', 'i', 't', '\0',
+ 0xdb, 0xe3, asNone + tEnd + eEnd };
+
+BYTE szFNOP[] = {
+ 'f', 'n', 'o', 'p', '\0',
+ 0xd9, 0xd0, asNone + tEnd + eEnd };
+
+BYTE szFNSAVE[] = {
+ 'f', 'n', 's', 'a', 'v', 'e', '\0',
+ 0xdd, asReg6, opnM + tEnd + eEnd };
+
+BYTE szFNSTCW[] = {
+ 'f', 'n', 's', 't', 'c', 'w', '\0',
+ 0xd9, asReg7, opnMw + tEnd + eEnd };
+
+BYTE szFNSTENV[] = {
+ 'f', 'n', 's', 't', 'e', 'n', 'v', '\0',
+ 0xd9, asReg6, opnM + tEnd + eEnd };
+
+BYTE szFNSTSW[] = {
+ 'f', 'n', 's', 't', 's', 'w', '\0',
+ 0xdf, 0xe0, asNone + tEnd,
+ 0xdf, 0xe0, opnAX + tEnd,
+ 0xdf, asReg7, opnMw + tEnd + eEnd };
+
+BYTE szFPATAN[] = {
+ 'f', 'p', 'a', 't', 'a', 'n', '\0',
+ 0xd9, 0xf3, asNone + tEnd + eEnd };
+
+BYTE szFPREM[] = {
+ 'f', 'p', 'r', 'e', 'm', '\0',
+ 0xd9, 0xf8, asNone + tEnd + eEnd };
+
+BYTE szFPREM1[] = {
+ 'f', 'p', 'r', 'e', 'm', '1', '\0',
+ 0xd9, 0xf5, asNone + tEnd + eEnd };
+
+BYTE szFPTAN[] = {
+ 'f', 'p', 't', 'a', 'n', '\0',
+ 0xd9, 0xf2, asNone + tEnd + eEnd };
+
+BYTE szFRNDINT[] = {
+ 'f', 'r', 'n', 'd', 'i', 'n', 't', '\0',
+ 0xd9, 0xfc, asNone + tEnd + eEnd };
+
+BYTE szFRSTOR[] = {
+ 'f', 'r', 's', 't', 'o', 'r', '\0',
+ 0xdd, asWait, asReg4, opnM + tEnd + eEnd };
+
+BYTE szFS_A[] = {
+ 'f', 's', ':', '\0',
+ 0x64, asPrfx + tEnd + eEnd };
+
+BYTE szFSAVE[] = {
+ 'f', 's', 'a', 'v', 'e', '\0',
+ 0xdd, asWait, asReg6, opnM + tEnd + eEnd };
+
+BYTE szFSCALE[] = {
+ 'f', 's', 'c', 'a', 'l', 'e', '\0',
+ 0xd9, 0xfd, asNone + tEnd + eEnd };
+
+BYTE szFSETPM[] = {
+ 'f', 's', 'e', 't', 'p', 'm', '\0',
+ 0xdb, 0xe4, asWait + tEnd + eEnd };
+
+BYTE szFSIN[] = {
+ 'f', 's', 'i', 'n', '\0',
+ 0xd9, 0xfe, asNone + tEnd + eEnd };
+
+BYTE szFSINCOS[] = {
+ 'f', 's', 'i', 'n', 'c', 'o', 's', '\0',
+ 0xd9, 0xfb, asNone + tEnd + eEnd };
+
+BYTE szFSQRT[] = {
+ 'f', 's', 'q', 'r', 't', '\0',
+ 0xd9, 0xfa, asNone + tEnd + eEnd };
+
+BYTE szFST[] = {
+ 'f', 's', 't', '\0',
+ 0xd9, asReg2, opnMd, asFSiz + tEnd,
+ 0xdd, asReg2, opnMq + tEnd,
+ 0xdd, 0xd0, opnSti + tEnd + eEnd };
+
+BYTE szFSTCW[] = {
+ 'f', 's', 't', 'c', 'w', '\0',
+ 0xd9, asWait, asReg7, opnMw + tEnd + eEnd };
+
+BYTE szFSTENV[] = {
+ 'f', 's', 't', 'e', 'n', 'v', '\0',
+ 0xd9, asWait, asReg6, opnM + tEnd + eEnd };
+
+BYTE szFSTP[] = {
+ 'f', 's', 't', 'p', '\0',
+ 0xd9, asReg3, opnMd, asFSiz + tEnd,
+ 0xdd, asReg3, opnMq + tEnd,
+ 0xdb, asReg7, opnMt + tEnd,
+ 0xdd, 0xd8, opnSti + tEnd + eEnd };
+
+BYTE szFSTSW[] = {
+ 'f', 's', 't', 's', 'w', '\0',
+ 0xdf, 0xe0, asWait + tEnd,
+ 0xdf, 0xe0, asWait, opnAX + tEnd,
+ 0xdd, asWait, asReg7, opnMw + tEnd + eEnd };
+
+BYTE szFSUB[] = {
+ 'f', 's', 'u', 'b', '\0',
+ 0xde, 0xe9, asNone + tEnd,
+ 0xd8, asReg4, opnMd, asFSiz + tEnd,
+ 0xdc, asReg4, opnMq + tEnd,
+ 0xd8, 0xe0, opnSt, opnSti + tEnd,
+ 0xdc, 0xe8, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFSUBP[] = {
+ 'f', 's', 'u', 'b', 'p', '\0',
+ 0xde, 0xe8, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFSUBR[] = {
+ 'f', 's', 'u', 'b', 'r', '\0',
+ 0xde, 0xe1, asNone + tEnd,
+ 0xd8, asReg5, opnMd, asFSiz + tEnd,
+ 0xdc, asReg5, opnMq + tEnd,
+ 0xd8, 0xe8, opnSt, opnSti + tEnd,
+ 0xdc, 0xe0, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFSUBRP[] = {
+ 'f', 's', 'u', 'b', 'r', 'p', '\0',
+ 0xde, 0xe0, opnSti, opnSt + tEnd + eEnd };
+
+BYTE szFTST[] = {
+ 'f', 't', 's', 't', '\0',
+ 0xd9, 0xe4, asNone + tEnd + eEnd };
+
+BYTE szFUCOM[] = {
+ 'f', 'u', 'c', 'o', 'm', '\0',
+ 0xdd, 0xe1, asNone, + tEnd,
+ 0xdd, 0xe0, opnSti + tEnd + eEnd };
+
+BYTE szFUCOMP[] = {
+ 'f', 'u', 'c', 'o', 'm', 'p', '\0',
+ 0xdd, 0xe9, asNone + tEnd,
+ 0xdd, 0xe8, opnSti + tEnd + eEnd };
+
+BYTE szFUCOMPP[] = {
+ 'f', 'u', 'c', 'o', 'm', 'p', 'p', '\0',
+ 0xda, 0xe9, asNone + tEnd + eEnd };
+
+BYTE szFWAIT[] = { // same as WAIT
+ 'f', 'w', 'a', 'i', 't', '\0',
+ 0x9b, asPrfx + tEnd + eEnd };
+
+BYTE szFXAM[] = {
+ 'f', 'x', 'a', 'm', '\0',
+ 0xd9, 0xe5, asNone + tEnd + eEnd };
+
+BYTE szFXCH[] = {
+ 'f', 'x', 'c', 'h', '\0',
+ 0xd9, 0xc9, asNone + tEnd,
+ 0xd9, 0xc8, opnSti + tEnd + eEnd };
+
+BYTE szFXTRACT[] = {
+ 'f', 'x', 't', 'r', 'a', 'c', 't', '\0',
+ 0xd9, 0xf4, asNone + tEnd + eEnd };
+
+BYTE szFYL2X[] = {
+ 'f', 'y', 'l', '2', 'x', '\0',
+ 0xd9, 0xf1, asNone + tEnd + eEnd };
+
+BYTE szFYL2XP1[] = {
+ 'f', 'y', 'l', '2', 'x', 'p', '1', '\0',
+ 0xd9, 0xf9, asNone + tEnd + eEnd };
+
+BYTE szGS_A[] = {
+ 'g', 's', ':', '\0',
+ 0x65, asPrfx + tEnd + eEnd };
+
+BYTE szHLT[] = {
+ 'h', 'l', 't', '\0',
+ 0xf4, asNone + tEnd + eEnd };
+
+BYTE szIDIV[] = {
+ 'i', 'd', 'i', 'v', '\0',
+ 0xf6, asReg7, opnEb + tEnd,
+ 0xf7, asReg7, opnEv + tEnd,
+ 0xf6, asReg7, opnAL, opnEb + tEnd,
+ 0xf7, asReg7, opneAX, opnEv + tEnd + eEnd };
+
+BYTE szIMUL[] = {
+ 'i', 'm', 'u', 'l', '\0',
+ 0xf6, asReg5, opnEb + tEnd,
+ 0xf7, asReg5, opnEv + tEnd,
+ 0xf6, asReg5, opnAL, opnEb + tEnd,
+ 0xf7, asReg5, opneAX, opnEv + tEnd,
+ 0x0f, 0xaf, opnGv, opnEv + tEnd,
+ 0x6b, opnGv, opnIb + tEnd,
+ 0x69, opnGv, opnIv + tEnd,
+ 0x6b, opnGv, opnEv, opnIb + tEnd,
+ 0x69, opnGv, opnEv, opnIv + tEnd + eEnd };
+
+BYTE szIN[] = {
+ 'i', 'n', '\0',
+ 0xe4, opnAL, opnIb + tEnd,
+ 0xe5, opneAX, opnIb + tEnd,
+ 0xec, opnAL, opnDX + tEnd,
+ 0xed, opneAX, opnDX + tEnd + eEnd };
+
+BYTE szINC[] = {
+ 'i', 'n', 'c', '\0',
+ 0x40, asOpRg, opnGv + tEnd,
+ 0xfe, asReg0, opnEb + tEnd,
+ 0xff, asReg0, opnEv + tEnd + eEnd };
+
+BYTE szINS[] = {
+ 'i', 'n', 's', '\0',
+ 0x6c, opnYb, opnDX + tEnd,
+ 0x6d, opnYv, opnDX + tEnd + eEnd };
+
+BYTE szINSB[] = {
+ 'i', 'n', 's', 'b', '\0',
+ 0x6c, asNone + tEnd + eEnd };
+
+BYTE szINSD[] = {
+ 'i', 'n', 's', 'd', '\0',
+ 0x6d, asSiz1 + tEnd + eEnd };
+
+BYTE szINSW[] = {
+ 'i', 'n', 's', 'w', '\0',
+ 0x6d, asSiz0 + tEnd + eEnd };
+
+BYTE szINT[] = {
+ 'i', 'n', 't', '\0',
+ 0xcc, opnIm3 + tEnd,
+ 0xcd, opnIb + tEnd + eEnd };
+
+BYTE szINTO[] = {
+ 'i', 'n', 't', 'o', '\0',
+ 0xce, asNone + tEnd + eEnd };
+
+BYTE szINVD[] = {
+ 'i', 'n', 'v', 'd', '\0',
+ 0x0f, 0x08, asNone + tEnd + eEnd };
+
+BYTE szINVLPG[] = {
+ 'i', 'n', 'v', 'l', 'p', 'g', '\0',
+ 0x0f, 0x01, asReg7, opnM + tEnd + eEnd };
+
+BYTE szIRET[] = {
+ 'i', 'r', 'e', 't', '\0',
+ 0xcf, asSiz0 + tEnd + eEnd };
+
+BYTE szIRETD[] = {
+ 'i', 'r', 'e', 't', 'd', '\0',
+ 0xcf, asSiz1 + tEnd + eEnd };
+
+BYTE szJA[] = { // same as JNBE
+ 'j', 'a', '\0',
+ 0x77, opnJb + tEnd,
+ 0x0f, 0x87, opnJv + tEnd + eEnd };
+
+BYTE szJAE[] = { // same as JNB, JNC
+ 'j', 'a', 'e', '\0',
+ 0x73, opnJb + tEnd,
+ 0x0f, 0x83, opnJv + tEnd + eEnd };
+
+BYTE szJB[] = { // same as JC, JNAE
+ 'j', 'b', '\0',
+ 0x72, opnJb + tEnd,
+ 0x0f, 0x82, opnJv + tEnd + eEnd };
+
+BYTE szJBE[] = { // same as JNA
+ 'j', 'b', 'e', '\0',
+ 0x76, opnJb + tEnd,
+ 0x0f, 0x86, opnJv + tEnd + eEnd };
+
+BYTE szJC[] = { // same as JB, JNAE
+ 'j', 'c', '\0',
+ 0x72, opnJb + tEnd,
+ 0x0f, 0x82, opnJv + tEnd + eEnd };
+
+BYTE szJCXZ[] = {
+ 'j', 'c', 'x', 'z', '\0',
+ 0xe3, asSiz0, opnJb + tEnd + eEnd };
+
+BYTE szJECXZ[] = {
+ 'j', 'e', 'c', 'x', 'z', '\0',
+ 0xe3, asSiz1, opnJb + tEnd + eEnd };
+
+BYTE szJE[] = { // same as JZ
+ 'j', 'e', '\0',
+ 0x74, opnJb + tEnd,
+ 0x0f, 0x84, opnJv + tEnd + eEnd };
+
+BYTE szJG[] = { // same as JNLE
+ 'j', 'g', '\0',
+ 0x7f, opnJb + tEnd,
+ 0x0f, 0x8f, opnJv + tEnd + eEnd };
+
+BYTE szJGE[] = { // same as JNL
+ 'j', 'g', 'e', '\0',
+ 0x7d, opnJb + tEnd,
+ 0x0f, 0x8d, opnJv + tEnd + eEnd };
+
+BYTE szJL[] = { // same as JNGE
+ 'j', 'l', '\0',
+ 0x7c, opnJb + tEnd,
+ 0x0f, 0x8c, opnJv + tEnd + eEnd };
+
+BYTE szJLE[] = { // same as JNG
+ 'j', 'l', 'e', '\0',
+ 0x7e, opnJb + tEnd,
+ 0x0f, 0x8e, opnJv + tEnd + eEnd };
+
+BYTE szJMP[] = {
+ 'j', 'm', 'p', '\0',
+ 0xeb, opnJb + tEnd,
+ 0xe9, opnJv + tEnd,
+ 0xff, asReg4, opnEv, asMpNx + tEnd,
+ 0xff, asReg5, opnMp + tEnd,
+ 0xea, opnAp + tEnd, + eEnd };
+
+BYTE szJNA[] = { // same as JBE
+ 'j', 'n', 'a', '\0',
+ 0x76, opnJb + tEnd,
+ 0x0f, 0x86, opnJv + tEnd + eEnd };
+
+BYTE szJNAE[] = { // same as JB, JC
+ 'j', 'n', 'a', 'e','\0',
+ 0x72, opnJb + tEnd,
+ 0x0f, 0x82, opnJv + tEnd + eEnd };
+
+BYTE szJNB[] = { // same as JAE, JNC
+ 'j', 'n', 'b', '\0',
+ 0x73, opnJb + tEnd,
+ 0x0f, 0x83, opnJv + tEnd + eEnd };
+
+BYTE szJNBE[] = { // same as JA
+ 'j', 'n', 'b', 'e', '\0',
+ 0x77, opnJb + tEnd,
+ 0x0f, 0x87, opnJv + tEnd + eEnd };
+
+BYTE szJNC[] = { // same as JAE, JNB
+ 'j', 'n', 'c', '\0',
+ 0x73, opnJb + tEnd,
+ 0x0f, 0x83, opnJv + tEnd + eEnd };
+
+BYTE szJNG[] = { // same as JLE
+ 'j', 'n', 'g', '\0',
+ 0x7e, opnJb + tEnd,
+ 0x0f, 0x8e, opnJv + tEnd + eEnd };
+
+BYTE szJNGE[] = { // same as JNL
+ 'j', 'n', 'g', 'e', '\0',
+ 0x7c, opnJb + tEnd,
+ 0x0f, 0x8c, opnJv + tEnd + eEnd };
+
+BYTE szJNE[] = { // same as JNZ
+ 'j', 'n', 'e', '\0',
+ 0x75, opnJb + tEnd,
+ 0x0f, 0x85, opnJv + tEnd + eEnd };
+
+BYTE szJNL[] = { // same as JGE
+ 'j', 'n', 'l', '\0',
+ 0x7d, opnJb + tEnd,
+ 0x0f, 0x8d, opnJv + tEnd + eEnd };
+
+BYTE szJNLE[] = { // same as JNG
+ 'j', 'n', 'l', 'e', '\0',
+ 0x7f, opnJb + tEnd,
+ 0x0f, 0x8f, opnJv + tEnd + eEnd };
+
+BYTE szJNO[] = {
+ 'j', 'n', 'o', '\0',
+ 0x71, opnJb + tEnd,
+ 0x0f, 0x81, opnJv + tEnd + eEnd };
+
+BYTE szJNP[] = { // same as JPO
+ 'j', 'n', 'p', '\0',
+ 0x7b, opnJb + tEnd,
+ 0x0f, 0x8b, opnJv + tEnd + eEnd };
+
+BYTE szJNS[] = {
+ 'j', 'n', 's', '\0',
+ 0x79, opnJb + tEnd,
+ 0x0f, 0x89, opnJv + tEnd + eEnd };
+
+BYTE szJNZ[] = { // same as JNE
+ 'j', 'n', 'z', '\0',
+ 0x75, opnJb + tEnd,
+ 0x0f, 0x85, opnJv + tEnd + eEnd };
+
+BYTE szJO[] = {
+ 'j', 'o', '\0',
+ 0x70, opnJb + tEnd,
+ 0x0f, 0x80, opnJv + tEnd + eEnd };
+
+BYTE szJP[] = { // same as JPE
+ 'j', 'p', '\0',
+ 0x7a, opnJb + tEnd,
+ 0x0f, 0x8a, opnJv + tEnd + eEnd };
+
+BYTE szJPE[] = { // same as JP
+ 'j', 'p', 'e', '\0',
+ 0x7a, opnJb + tEnd,
+ 0x0f, 0x8a, opnJv + tEnd + eEnd };
+
+BYTE szJPO[] = { // same as JNP
+ 'j', 'p', 'o', '\0',
+ 0x7b, opnJb + tEnd,
+ 0x0f, 0x8b, opnJv + tEnd + eEnd };
+
+BYTE szJS[] = {
+ 'j', 's', '\0',
+ 0x78, opnJb + tEnd,
+ 0x0f, 0x88, opnJv + tEnd + eEnd };
+
+BYTE szJZ[] = { // same as JE
+ 'j', 'z', '\0',
+ 0x74, opnJb + tEnd,
+ 0x0f, 0x84, opnJv + tEnd + eEnd };
+
+BYTE szLAHF[] = {
+ 'l', 'a', 'h', 'f', '\0',
+ 0x9f, asNone + tEnd + eEnd };
+
+BYTE szLAR[] = {
+ 'l', 'a', 'r', '\0',
+ 0x0f, 0x02, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szLDS[] = {
+ 'l', 'd', 's', '\0',
+ 0xc5, opnGv, opnMp + tEnd + eEnd };
+
+BYTE szLEA[] = {
+ 'l', 'e', 'a', '\0',
+ 0x8d, opnGv, opnM + tEnd + eEnd };
+
+BYTE szLEAVE[] = {
+ 'l', 'e', 'a', 'v', 'e', '\0',
+ 0xc9, asNone + tEnd + eEnd };
+
+BYTE szLES[] = {
+ 'l', 'e', 's', '\0',
+ 0xc4, opnGv, opnMp + tEnd + eEnd };
+
+BYTE szLFS[] = {
+ 'l', 'f', 's', '\0',
+ 0x0f, 0xb4, opnGv, opnMp + tEnd + eEnd };
+
+BYTE szLGDT[] = {
+ 'l', 'g', 'd', 't', '\0',
+ 0x0f, 0x01, asReg2, opnMs + tEnd + eEnd };
+
+BYTE szLGS[] = {
+ 'l', 'g', 's', '\0',
+ 0x0f, 0xb5, opnGv, opnMp + tEnd + eEnd };
+
+BYTE szLIDT[] = {
+ 'l', 'i', 'd', 't', '\0',
+ 0x0f, 0x01, asReg3, opnMs + tEnd + eEnd };
+
+BYTE szLLDT[] = {
+ 'l', 'l', 'd', 't', '\0',
+ 0x0f, 0x00, asReg2, opnEw + tEnd + eEnd };
+
+BYTE szLMSW[] = {
+ 'l', 'm', 's', 'w', '\0',
+ 0x0f, 0x01, asReg6, opnEw + tEnd + eEnd };
+
+BYTE szLOCK[] = {
+ 'l', 'o', 'c', 'k', '\0',
+ 0xf0, asPrfx + tEnd + eEnd };
+
+BYTE szLODS[] = {
+ 'l', 'o', 'd', 's', '\0',
+ 0xac, opnXb + tEnd,
+ 0xad, opnXv + tEnd + eEnd };
+
+BYTE szLODSB[] = {
+ 'l', 'o', 'd', 's', 'b', '\0',
+ 0xac, asNone + tEnd + eEnd };
+
+BYTE szLODSD[] = {
+ 'l', 'o', 'd', 's', 'd', '\0',
+ 0xad, asSiz1 + tEnd + eEnd };
+
+BYTE szLODSW[] = {
+ 'l', 'o', 'd', 's', 'w', '\0',
+ 0xad, asSiz0 + tEnd + eEnd };
+
+BYTE szLOOP[] = {
+ 'l', 'o', 'o', 'p', '\0',
+ 0xe2, opnJb + tEnd + eEnd };
+
+BYTE szLOOPE[] = { // same as LOOPZ
+ 'l', 'o', 'o', 'p', 'e', '\0',
+ 0xe1, opnJb + tEnd + eEnd };
+
+BYTE szLOOPNE[] = { // same as LOOPNZ
+ 'l', 'o', 'o', 'p', 'n', 'e', '\0',
+ 0xe0, opnJb + tEnd + eEnd };
+
+BYTE szLOOPNZ[] = { // same as LOOPNE
+ 'l', 'o', 'o', 'p', 'n', 'z', '\0',
+ 0xe0, opnJb + tEnd + eEnd };
+
+BYTE szLOOPZ[] = { // same as LOOPE
+ 'l', 'o', 'o', 'p', 'z', '\0',
+ 0xe1, opnJb + tEnd + eEnd };
+
+BYTE szLSL[] = {
+ 'l', 's', 'l', '\0',
+ 0x0f, 0x03, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szLSS[] = {
+ 'l', 's', 's', '\0',
+ 0x0f, 0xb2, opnGv, opnMp + tEnd + eEnd };
+
+BYTE szLTR[] = {
+ 'l', 't', 'r', '\0',
+ 0x0f, 0x00, asReg3, opnEw + tEnd + eEnd };
+
+BYTE szMOV[] = {
+ 'm', 'o', 'v', '\0',
+ 0xa0, opnAL, opnOb + tEnd,
+ 0xa1, opneAX, opnOv + tEnd,
+ 0xa2, opnOb, opnAL + tEnd,
+ 0xa3, opnOv, opneAX + tEnd,
+ 0x8a, opnGb, opnEb + tEnd,
+ 0x8b, opnGv, opnEv + tEnd,
+ 0x88, opnEb, opnGb + tEnd,
+ 0x89, opnEv, opnGv + tEnd,
+ 0x8c, asSiz0, opnEw, opnSw + tEnd,
+ 0x8e, asSiz0, opnSw, opnEw + tEnd,
+ 0xb0, asOpRg, opnGb, opnIb + tEnd,
+ 0xb8, asOpRg, opnGv, opnIv + tEnd,
+ 0xc6, opnEb, opnIb + tEnd,
+ 0xc7, opnEv, opnIv + tEnd,
+ 0x0f, 0x20, opnRd, opnCd + tEnd,
+ 0x0f, 0x21, opnRd, opnDd + tEnd,
+ 0x0f, 0x22, opnCd, opnRd + tEnd,
+ 0x0f, 0x23, opnDd, opnRd + tEnd,
+ 0x0f, 0x24, opnRd, opnTd + tEnd,
+ 0x0f, 0x26, opnTd, opnRd + tEnd + eEnd };
+
+BYTE szMOVS[] = {
+ 'm', 'o', 'v', 's', '\0',
+ 0xa4, opnXb, opnYb + tEnd,
+ 0xa5, opnXv, opnYv + tEnd + eEnd };
+
+BYTE szMOVSB[] = {
+ 'm', 'o', 'v', 's', 'b', '\0',
+ 0xa4, asNone + tEnd + eEnd };
+
+BYTE szMOVSD[] = {
+ 'm', 'o', 'v', 's', 'd', '\0',
+ 0xa5, asSiz1 + tEnd + eEnd };
+
+BYTE szMOVSW[] = {
+ 'm', 'o', 'v', 's', 'w', '\0',
+ 0xa5, asSiz0 + tEnd + eEnd };
+
+BYTE szMOVSX[] = {
+ 'm', 'o', 'v', 's', 'x', '\0',
+ 0x0f, 0xbe, opnGv, opnEb + tEnd,
+ 0x0f, 0xbf, opnGv, opnEw + tEnd + eEnd };
+
+BYTE szMOVZX[] = {
+ 'm', 'o', 'v', 'z', 'x', '\0',
+ 0x0f, 0xb6, opnGv, opnEb + tEnd,
+ 0x0f, 0xb7, opnGv, opnEw + tEnd + eEnd };
+
+BYTE szMUL[] = {
+ 'm', 'u', 'l', '\0',
+ 0xf6, asReg4, opnEb + tEnd,
+ 0xf7, asReg4, opnEv + tEnd,
+ 0xf6, asReg4, opnAL, opnEb + tEnd,
+ 0xf7, asReg4, opneAX, opnEv + tEnd + eEnd };
+
+BYTE szNEG[] = {
+ 'n', 'e', 'g', '\0',
+ 0xf6, asReg3, opnEb + tEnd,
+ 0xf7, asReg3, opnEv + tEnd + eEnd };
+
+BYTE szNOP[] = {
+ 'n', 'o', 'p', '\0',
+ 0x90, asNone + tEnd };
+
+BYTE szNOT[] = {
+ 'n', 'o', 't', '\0',
+ 0xf6, asReg2, opnEb + tEnd,
+ 0xf7, asReg2, opnEv + tEnd + eEnd };
+
+BYTE szOR[] = {
+ 'o', 'r', '\0',
+ 0x0c, opnAL, opnIb + tEnd,
+ 0x0d, opneAX, opnIv + tEnd,
+ 0x80, asReg1, opnEb, opnIb + tEnd,
+ 0x83, asReg1, opnEv, opnIb + tEnd,
+ 0x81, asReg1, opnEv, opnIv + tEnd,
+ 0x08, opnEb, opnGb + tEnd,
+ 0x09, opnEv, opnGv + tEnd,
+ 0x0a, opnGb, opnEb + tEnd,
+ 0x0b, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szOUT[] = {
+ 'o', 'u', 't', '\0',
+ 0xe6, opnIb, opnAL + tEnd,
+ 0xe7, opnIb, opneAX + tEnd,
+ 0xee, opnDX, opnAL + tEnd,
+ 0xef, opnDX, opneAX + tEnd + eEnd };
+
+BYTE szOUTS[] = {
+ 'o', 'u', 't', 's', '\0',
+ 0x6e, opnDX, opnYb + tEnd,
+ 0x6f, opnDX, opnYv + tEnd + eEnd };
+
+BYTE szOUTSB[] = {
+ 'o', 'u', 't', 's', 'b', '\0',
+ 0x6e, asNone + tEnd + eEnd };
+
+BYTE szOUTSD[] = {
+ 'o', 'u', 't', 's', 'd', '\0',
+ 0x6f, asSiz1 + tEnd + eEnd };
+
+BYTE szOUTSW[] = {
+ 'o', 'u', 't', 's', 'w', '\0',
+ 0x6f, asSiz0 + tEnd + eEnd };
+
+BYTE szPOP[] = {
+ 'p', 'o', 'p', '\0',
+ 0x58, asOpRg, opnGv + tEnd,
+ 0x8f, asReg0, opnMv + tEnd,
+ 0x1f, opnSeg, segDS, asNone+ tEnd,
+ 0x07, opnSeg, segES, asNone+ tEnd,
+ 0x17, opnSeg, segSS, asNone+ tEnd,
+ 0x0f, 0xa1, opnSeg, segFS, asNone+ tEnd,
+ 0x0f, 0xa9, opnSeg, segGS, asNone+ tEnd + eEnd };
+
+BYTE szPOPA[] = {
+ 'p', 'o', 'p', 'a', '\0',
+ 0x61, asSiz0 + tEnd + eEnd };
+
+BYTE szPOPAD[] = {
+ 'p', 'o', 'p', 'a', 'd', '\0',
+ 0x61, asSiz1 + tEnd + eEnd };
+
+BYTE szPOPF[] = {
+ 'p', 'o', 'p', 'f', '\0',
+ 0x9d, asSiz0 + tEnd + eEnd };
+
+BYTE szPOPFD[] = {
+ 'p', 'o', 'p', 'f', 'd', '\0',
+ 0x9d, asSiz1 + tEnd + eEnd };
+
+BYTE szPUSH[] = {
+ 'p', 'u', 's', 'h', '\0',
+ 0x50, asOpRg, opnGv + tEnd,
+ 0xff, asReg6, opnMv + tEnd,
+ 0x6a, opnIb + tEnd,
+ 0x68, opnIv + tEnd,
+ 0x0e, opnSeg, segCS, asNone+ tEnd,
+ 0x1e, opnSeg, segDS, asNone+ tEnd,
+ 0x06, opnSeg, segES, asNone+ tEnd,
+ 0x16, opnSeg, segSS, asNone+ tEnd,
+ 0x0f, 0xa0, opnSeg, segFS, asNone+ tEnd,
+ 0x0f, 0xa8, opnSeg, segGS, asNone+ tEnd + eEnd };
+
+BYTE szPUSHA[] = {
+ 'p', 'u', 's', 'h', 'a', '\0',
+ 0x60, asSiz0 + tEnd + eEnd };
+
+BYTE szPUSHAD[] = {
+ 'p', 'u', 's', 'h', 'a', 'd', '\0',
+ 0x60, asSiz1 + tEnd + eEnd };
+
+BYTE szPUSHF[] = {
+ 'p', 'u', 's', 'h', 'f', '\0',
+ 0x9c, asSiz0 + tEnd + eEnd };
+
+BYTE szPUSHFD[] = {
+ 'p', 'u', 's', 'h', 'f', 'd', '\0',
+ 0x9c, asSiz1 + tEnd + eEnd };
+
+BYTE szRCL[] = {
+ 'r', 'c', 'l', '\0',
+ 0xd0, asReg2, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg2, opnEb, opnCL + tEnd,
+ 0xc0, asReg2, opnEb, opnIb + tEnd,
+ 0xd1, asReg2, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg2, opnEv, opnCL + tEnd,
+ 0xc1, asReg2, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szRCR[] = {
+ 'r', 'c', 'r', '\0',
+ 0xd0, asReg3, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg3, opnEb, opnCL + tEnd,
+ 0xc0, asReg3, opnEb, opnIb + tEnd,
+ 0xd1, asReg3, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg3, opnEv, opnCL + tEnd,
+ 0xc1, asReg3, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szREP[] = { // same as REPE, REPZ
+ 'r', 'e', 'p', '\0',
+ 0xf3, asPrfx + tEnd + eEnd };
+
+BYTE szREPE[] = { // same as REP, REPZ
+ 'r', 'e', 'p', 'e', '\0',
+ 0xf3, asPrfx + tEnd + eEnd };
+
+BYTE szREPZ[] = { // same as REP, REPE
+ 'r', 'e', 'p', 'z', '\0',
+ 0xf3, asPrfx + tEnd + eEnd };
+
+BYTE szREPNE[] = { // same as REPNZ
+ 'r', 'e', 'p', 'n', 'e', '\0',
+ 0xf2, asPrfx + tEnd + eEnd };
+
+BYTE szREPNZ[] = { // same as REPNE
+ 'r', 'e', 'p', 'n', 'z', '\0',
+ 0xf2, asPrfx + tEnd + eEnd };
+
+BYTE szRET[] = { // same as RETN
+ 'r', 'e', 't', '\0',
+ 0xc3, asNone + tEnd,
+ 0xc2, opnIw + tEnd + eEnd };
+
+BYTE szRETF[] = {
+ 'r', 'e', 't', 'f', '\0',
+ 0xcb, asNone + tEnd,
+ 0xca, opnIw + tEnd + eEnd };
+
+BYTE szRETN[] = { // same as RET
+ 'r', 'e', 't', 'n', '\0',
+ 0xc3, asNone + tEnd,
+ 0xc2, opnIw + tEnd + eEnd };
+
+BYTE szROL[] = {
+ 'r', 'o', 'l', '\0',
+ 0xd0, asReg0, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg0, opnEb, opnCL + tEnd,
+ 0xc0, asReg0, opnEb, opnIb + tEnd,
+ 0xd1, asReg0, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg0, opnEv, opnCL + tEnd,
+ 0xc1, asReg0, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szROR[] = {
+ 'r', 'o', 'r', '\0',
+ 0xd0, asReg1, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg1, opnEb, opnCL + tEnd,
+ 0xc0, asReg1, opnEb, opnIb + tEnd,
+ 0xd1, asReg1, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg1, opnEv, opnCL + tEnd,
+ 0xc1, asReg1, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szSAHF[] = {
+ 's', 'a', 'h', 'f', '\0',
+ 0x9e, asNone + tEnd + eEnd };
+
+BYTE szSAL[] = {
+ 's', 'a', 'l', '\0',
+ 0xd0, asReg4, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg4, opnEb, opnCL + tEnd,
+ 0xc0, asReg4, opnEb, opnIb + tEnd,
+ 0xd1, asReg4, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg4, opnEv, opnCL + tEnd,
+ 0xc1, asReg4, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szSAR[] = {
+ 's', 'a', 'r', '\0',
+ 0xd0, asReg7, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg7, opnEb, opnCL + tEnd,
+ 0xc0, asReg7, opnEb, opnIb + tEnd,
+ 0xd1, asReg7, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg7, opnEv, opnCL + tEnd,
+ 0xc1, asReg7, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szSBB[] = {
+ 's', 'b', 'b', '\0',
+ 0x1c, opnAL, opnIb + tEnd,
+ 0x1d, opneAX, opnIv + tEnd,
+ 0x80, asReg3, opnEb, opnIb + tEnd,
+ 0x83, asReg3, opnEv, opnIb + tEnd,
+ 0x81, asReg3, opnEv, opnIv + tEnd,
+ 0x18, opnEb, opnGb + tEnd,
+ 0x19, opnEv, opnGv + tEnd,
+ 0x1a, opnGb, opnEb + tEnd,
+ 0x1b, opnGv, opnEv + tEnd + eEnd };
+
+
+BYTE szSCAS[] = {
+ 's', 'c', 'a', 's', '\0',
+ 0xae, opnYb + tEnd,
+ 0xaf, opnYv + tEnd + eEnd };
+
+BYTE szSCASB[] = {
+ 's', 'c', 'a', 's', 'b', '\0',
+ 0xae, asNone + tEnd + eEnd };
+
+BYTE szSCASD[] = {
+ 's', 'c', 'a', 's', 'd', '\0',
+ 0xaf, asSiz1 + tEnd + eEnd };
+
+BYTE szSCASW[] = {
+ 's', 'c', 'a', 's', 'w', '\0',
+ 0xaf, asSiz0 + tEnd + eEnd };
+
+BYTE szSETA[] = { // same as SETNBE
+ 's', 'e', 't', 'a', '\0',
+ 0x0f, 0x97, opnEb + tEnd + eEnd };
+
+BYTE szSETAE[] = { // same as SETNB, SETNC
+ 's', 'e', 't', 'a', 'e', '\0',
+ 0x0f, 0x93, opnEb + tEnd + eEnd };
+
+BYTE szSETB[] = { // same as SETC, SETNAE
+ 's', 'e', 't', 'b', '\0',
+ 0x0f, 0x92, opnEb + tEnd + eEnd };
+
+BYTE szSETBE[] = { // same as SETNA
+ 's', 'e', 't', 'b', 'e', '\0',
+ 0x0f, 0x96, opnEb + tEnd + eEnd };
+
+BYTE szSETC[] = { // same as SETB, SETNAE
+ 's', 'e', 't', 'c', '\0',
+ 0x0f, 0x92, opnEb + tEnd + eEnd };
+
+BYTE szSETE[] = { // same as SETZ
+ 's', 'e', 't', 'e', '\0',
+ 0x0f, 0x94, opnEb + tEnd + eEnd };
+
+BYTE szSETG[] = { // same as SETNLE
+ 's', 'e', 't', 'g', '\0',
+ 0x0f, 0x9f, opnEb + tEnd + eEnd };
+
+BYTE szSETGE[] = { // same as SETNL
+ 's', 'e', 't', 'g', 'e', '\0',
+ 0x0f, 0x9d, opnEb + tEnd + eEnd };
+
+BYTE szSETL[] = { // same as SETNGE
+ 's', 'e', 't', 'l', '\0',
+ 0x0f, 0x9c, opnEb + tEnd + eEnd };
+
+BYTE szSETLE[] = { // same as SETNG
+ 's', 'e', 't', 'l', 'e', '\0',
+ 0x0f, 0x9e, opnEb + tEnd + eEnd };
+
+BYTE szSETNA[] = { // same as SETBE
+ 's', 'e', 't', 'n', 'a', '\0',
+ 0x0f, 0x96, opnEb + tEnd + eEnd };
+
+BYTE szSETNAE[] = { // same as SETB, SETC
+ 's', 'e', 't', 'n', 'a', 'e', '\0',
+ 0x0f, 0x92, opnEb + tEnd + eEnd };
+
+BYTE szSETNB[] = { // same as SETAE, SETNC
+ 's', 'e', 't', 'n', 'b', '\0',
+ 0x0f, 0x93, opnEb + tEnd + eEnd };
+
+BYTE szSETNBE[] = { // same as SETA
+ 's', 'e', 't', 'n', 'b', 'e', '\0',
+ 0x0f, 0x97, opnEb + tEnd + eEnd };
+
+BYTE szSETNC[] = { // same as SETAE, SETNC
+ 's', 'e', 't', 'n', 'c', '\0',
+ 0x0f, 0x93, opnEb + tEnd + eEnd };
+
+BYTE szSETNE[] = { // same as SETNZ
+ 's', 'e', 't', 'n', 'e', '\0',
+ 0x0f, 0x95, opnEb + tEnd + eEnd };
+
+BYTE szSETNG[] = { // same as SETLE
+ 's', 'e', 't', 'n', 'g', '\0',
+ 0x0f, 0x9e, opnEb + tEnd + eEnd };
+
+BYTE szSETNGE[] = { // same as SETL
+ 's', 'e', 't', 'n', 'g', 'e', '\0',
+ 0x0f, 0x9c, opnEb + tEnd + eEnd };
+
+BYTE szSETNL[] = { // same as SETGE
+ 's', 'e', 't', 'n', 'l', '\0',
+ 0x0f, 0x9d, opnEb + tEnd + eEnd };
+
+BYTE szSETNLE[] = { // same as SETG
+ 's', 'e', 't', 'n', 'l', 'e', '\0',
+ 0x0f, 0x9f, opnEb + tEnd + eEnd };
+
+BYTE szSETNO[] = {
+ 's', 'e', 't', 'n', 'o', '\0',
+ 0x0f, 0x91, opnEb + tEnd + eEnd };
+
+BYTE szSETNP[] = { // same as SETPO
+ 's', 'e', 't', 'n', 'p', '\0',
+ 0x0f, 0x9b, opnEb + tEnd + eEnd };
+
+BYTE szSETNS[] = {
+ 's', 'e', 't', 'n', 's', '\0',
+ 0x0f, 0x99, opnEb + tEnd + eEnd };
+
+BYTE szSETNZ[] = { // same as SETNE
+ 's', 'e', 't', 'n', 'z', '\0',
+ 0x0f, 0x95, opnEb + tEnd + eEnd };
+
+BYTE szSETO[] = {
+ 's', 'e', 't', 'o', '\0',
+ 0x0f, 0x90, opnEb + tEnd + eEnd };
+
+BYTE szSETP[] = { // same as SETPE
+ 's', 'e', 't', 'p', '\0',
+ 0x0f, 0x9a, opnEb + tEnd + eEnd };
+
+BYTE szSETPE[] = { // same as SETP
+ 's', 'e', 't', 'p', 'e', '\0',
+ 0x0f, 0x9a, opnEb + tEnd + eEnd };
+
+BYTE szSETPO[] = { // same as SETNP
+ 's', 'e', 't', 'p', 'o', '\0',
+ 0x0f, 0x9b, opnEb + tEnd + eEnd };
+
+BYTE szSETS[] = {
+ 's', 'e', 't', 's', '\0',
+ 0x0f, 0x98, opnEb + tEnd + eEnd };
+
+BYTE szSETZ[] = { // same as SETE
+ 's', 'e', 't', 'z', '\0',
+ 0x0f, 0x94, opnEb + tEnd + eEnd };
+
+BYTE szSGDT[] = {
+ 's', 'g', 'd', 't', '\0',
+ 0x0f, 0x01, asReg0, opnMs + tEnd + eEnd };
+
+BYTE szSHL[] = {
+ 's', 'h', 'l', '\0',
+ 0xd0, asReg4, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg4, opnEb, opnCL + tEnd,
+ 0xc0, asReg4, opnEb, opnIb + tEnd,
+ 0xd1, asReg4, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg4, opnEv, opnCL + tEnd,
+ 0xc1, asReg4, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szSHLD[] = {
+ 's', 'h', 'l', 'd', '\0',
+ 0x0f, 0xa4, opnEv, opnGv, opnIb + tEnd,
+ 0x0f, 0xa5, opnEv, opnGv, opnCL + tEnd + eEnd };
+
+BYTE szSHR[] = {
+ 's', 'h', 'r', '\0',
+ 0xd0, asReg5, opnEb, opnIm1 + tEnd,
+ 0xd2, asReg5, opnEb, opnCL + tEnd,
+ 0xc0, asReg5, opnEb, opnIb + tEnd,
+ 0xd1, asReg5, opnEv, opnIm1 + tEnd,
+ 0xd3, asReg5, opnEv, opnCL + tEnd,
+ 0xc1, asReg5, opnEv, opnIb + tEnd + eEnd };
+
+BYTE szSHRD[] = {
+ 's', 'h', 'r', 'd', '\0',
+ 0x0f, 0xac, opnEv, opnGv, opnIb + tEnd,
+ 0x0f, 0xad, opnEv, opnGv, opnCL + tEnd + eEnd };
+
+BYTE szSIDT[] = {
+ 's', 'i', 'd', 't', '\0',
+ 0x0f, 0x01, asReg1, opnMs + tEnd + eEnd };
+
+BYTE szSLDT[] = {
+ 's', 'l', 'd', 't', '\0',
+ 0x0f, 0x00, asReg0, opnEw + tEnd + eEnd };
+
+BYTE szSMSW[] = {
+ 's', 'm', 's', 'w', '\0',
+ 0x0f, 0x01, asReg4, opnEw + tEnd + eEnd };
+
+BYTE szSS_A[] = {
+ 's', 's', ':', '\0',
+ 0x26, asPrfx + tEnd + eEnd };
+
+BYTE szSTC[] = {
+ 's', 't', 'c', '\0',
+ 0xf9, asNone + tEnd + eEnd };
+
+BYTE szSTD[] = {
+ 's', 't', 'd', '\0',
+ 0xfd, asNone + tEnd + eEnd };
+
+BYTE szSTI[] = {
+ 's', 't', 'i', '\0',
+ 0xfb, asNone + tEnd + eEnd };
+
+BYTE szSTOS[] = {
+ 's', 't', 'o', 's', '\0',
+ 0xaa, opnYb + tEnd,
+ 0xab, opnYv + tEnd + eEnd };
+
+BYTE szSTOSB[] = {
+ 's', 't', 'o', 's', 'b', '\0',
+ 0xaa, asNone + tEnd + eEnd };
+
+BYTE szSTOSD[] = {
+ 's', 't', 'o', 's', 'd', '\0',
+ 0xab, asSiz1 + tEnd + eEnd };
+
+BYTE szSTOSW[] = {
+ 's', 't', 'o', 's', 'w', '\0',
+ 0xab, asSiz0 + tEnd + eEnd };
+
+BYTE szSTR[] = {
+ 's', 't', 'r', '\0',
+ 0x0f, 0x00, asReg1, opnEw + tEnd + eEnd };
+
+BYTE szSUB[] = {
+ 's', 'u', 'b', '\0',
+ 0x2c, opnAL, opnIb + tEnd,
+ 0x2d, opneAX, opnIv + tEnd,
+ 0x80, asReg5, opnEb, opnIb + tEnd,
+ 0x83, asReg5, opnEv, opnIb + tEnd,
+ 0x81, asReg5, opnEv, opnIv + tEnd,
+ 0x28, opnEb, opnGb + tEnd,
+ 0x29, opnEv, opnGv + tEnd,
+ 0x2a, opnGb, opnEb + tEnd,
+ 0x2b, opnGv, opnEv + tEnd + eEnd };
+
+BYTE szTEST[] = {
+ 't', 'e', 's', 't', '\0',
+ 0xa8, opnAL, opnIb + tEnd,
+ 0xa9, opneAX, opnIv + tEnd,
+ 0xf6, asReg0, opnEb, opnIb + tEnd,
+ 0xf7, asReg0, opnEv, opnIv + tEnd,
+ 0x84, opnEb, opnGb + tEnd,
+ 0x85, opnEv, opnGv + tEnd + eEnd };
+
+BYTE szVERR[] = {
+ 'v', 'e', 'r', 'r', '\0',
+ 0x0f, 0x00, asReg4, opnEw + tEnd + eEnd };
+
+BYTE szVERW[] = {
+ 'v', 'e', 'r', 'w', '\0',
+ 0x0f, 0x00, asReg5, opnEw + tEnd + eEnd };
+
+BYTE szWAIT[] = { // same as FWAIT
+ 'w', 'a', 'i', 't', '\0',
+ 0x9b, asPrfx + tEnd + eEnd };
+
+BYTE szWBINVD[] = {
+ 'w', 'b', 'i', 'n', 'v', 'd', '\0',
+ 0x0f, 0x09, asNone + tEnd + eEnd };
+
+BYTE szXADD[] = {
+ 'x', 'a', 'd', 'd', '\0',
+ 0x0f, 0xc0, opnEb, opnGb + tEnd,
+ 0x0f, 0xc1, opnEv, opnGv + tEnd + eEnd };
+
+BYTE szXCHG[] = {
+ 'x', 'c', 'h', 'g', '\0',
+ 0x90, asOpRg, opneAX, opnGv + tEnd,
+ 0x90, asOpRg, opnGv, opneAX + tEnd,
+ 0x86, opnGb, opnEb + tEnd,
+ 0x86, opnEb, opnGb + tEnd,
+ 0x87, opnGv, opnEv + tEnd,
+ 0x87, opnEv, opnGv + tEnd + eEnd };
+
+BYTE szXLAT[] = {
+ 'x', 'l', 'a', 't', '\0',
+ 0xd7, asNone + tEnd,
+ 0xd7, asSeg, opnM + tEnd + eEnd };
+
+BYTE szXOR[] = {
+ 'x', 'o', 'r', '\0',
+ 0x34, opnAL, opnIb + tEnd,
+ 0x35, opneAX, opnIv + tEnd,
+ 0x80, asReg6, opnEb, opnIb + tEnd,
+ 0x83, asReg6, opnEv, opnIb + tEnd,
+ 0x81, asReg6, opnEv, opnIv + tEnd,
+ 0x30, opnEb, opnGb + tEnd,
+ 0x31, opnEv, opnGv + tEnd,
+ 0x32, opnGb, opnEb + tEnd,
+ 0x33, opnGv, opnEv + tEnd + eEnd };
+
+LPBYTE OpTable[] = {
+ szAAA, szAAD, szAAM, szAAS, szADC, szADD,
+ szAND, szARPL, szBOUND, szBSF, szBSR, szBSWAP,
+ szBT, szBTC, szBTR, szBTS, szCALL, szCBW,
+ szCDQ, szCLC, szCLD, szCLI, szCLTS, szCMC,
+ szCMP, szCMPS, szCMPSB, szCMPSD, szCMPSW, szCMPXCHG,
+ szCS_A, szCWD, szCWDE, szDAA, szDAS, szDEC,
+ szDIV, szDS_A, szENTER, szES_A, szF2XM1, szFABS,
+ szFADD, szFADDP, szFBLD, szFBSTP, szFCHS, szFCLEX,
+ szFCOM, szFCOMP, szFCOMPP, szFCOS, szFDECSTP, szFDISI,
+ szFDIV, szFDIVP, szFDIVR, szFDIVRP, szFENI, szFFREE,
+ szFIADD, szFICOM, szFICOMP, szFIDIV, szFIDIVR, szFILD,
+ szFIMUL, szFINCSTP, szFINIT, szFIST, szFISTP, szFISUB,
+ szFISUBR, szFLD, szFLD1, szFLDCW, szFLDENV, szFLDL2E,
+ szFLDL2T, szFLDLG2, szFLDLN2, szFLDPI, szFLDZ, szFMUL,
+ szFMULP, szFNCLEX, szFNDISI, szFNENI, szFNINIT, szFNOP,
+ szFNSAVE, szFNSTCW, szFNSTENV, szFNSTSW, szFPATAN, szFPREM,
+ szFPREM1, szFPTAN, szFRNDINT, szFRSTOR, szFS_A, szFSAVE,
+ szFSCALE, szFSETPM, szFSIN, szFSINCOS, szFSQRT, szFST,
+ szFSTCW, szFSTENV, szFSTP, szFSTSW, szFSUB, szFSUBP,
+ szFSUBR, szFSUBRP, szFTST, szFUCOM, szFUCOMP, szFUCOMPP,
+ szFWAIT, szFXAM, szFXCH, szFXTRACT, szFYL2X, szFYL2XP1,
+ szGS_A, szHLT, szIDIV, szIMUL, szIN, szINC,
+ szINS, szINSB, szINSD, szINSW, szINT, szINTO,
+ szINVD, szINVLPG, szIRET, szIRETD, szJA, szJAE,
+ szJB, szJBE, szJC, szJCXZ, szJE, szJECXZ,
+ szJG, szJGE, szJL, szJLE, szJMP, szJNA,
+ szJNAE, szJNB, szJNBE, szJNC, szJNE, szJNG,
+ szJNGE, szJNL, szJNLE, szJNO, szJNP, szJNS,
+ szJNZ, szJO, szJP, szJPE, szJPO, szJS,
+ szJZ, szLAHF, szLAR, szLDS, szLEA, szLEAVE,
+ szLES, szLFS, szLGDT, szLGS, szLIDT, szLLDT,
+ szLMSW, szLOCK, szLODS, szLODSB, szLODSD, szLODSW,
+ szLOOP, szLOOPE, szLOOPNE, szLOOPNZ, szLOOPZ, szLSL,
+ szLSS, szLTR, szMOV, szMOVS, szMOVSB, szMOVSD,
+ szMOVSW, szMOVSX, szMOVZX, szMUL, szNEG, szNOP,
+ szNOT, szOR, szOUT, szOUTS, szOUTSB, szOUTSD,
+ szOUTSW, szPOP, szPOPA, szPOPAD, szPOPF, szPOPFD,
+ szPUSH, szPUSHA, szPUSHAD, szPUSHF, szPUSHFD, szRCL,
+ szRCR, szREP, szREPE, szREPNE, szREPNZ, szREPZ,
+ szRET, szRETF, szRETN, szROL, szROR, szSAHF,
+ szSAL, szSAR, szSBB, szSCAS, szSCASB, szSCASD,
+ szSCASW, szSETA, szSETAE, szSETB, szSETBE, szSETC,
+ szSETE, szSETG, szSETGE, szSETL, szSETLE, szSETNA,
+ szSETNAE, szSETNB, szSETNBE, szSETNC, szSETNE, szSETNG,
+ szSETNGE, szSETNL, szSETNLE, szSETNO, szSETNP, szSETNS,
+ szSETNZ, szSETO, szSETP, szSETPE, szSETPO, szSETS,
+ szSETZ, szSGDT, szSHL, szSHLD, szSHR, szSHRD,
+ szSIDT, szSLDT, szSMSW, szSS_A, szSTC, szSTD,
+ szSTI, szSTOS, szSTOSB, szSTOSD, szSTOSW, szSTR,
+ szSUB, szTEST, szVERR, szVERW, szWAIT, szWBINVD,
+ szXADD, szXCHG, szXLAT, szXOR
+ };
+
+#define OPTABLESIZE (sizeof(OpTable) / sizeof(LPBYTE))
+
+
+/*** SearchOpcode - search for opcode
+*
+* Purpose:
+* Search the opcode table for a match with the string
+* pointed by *pszOp.
+*
+* Input:
+* *pszOp - string to search as opcode
+*
+* Returns:
+* if not -1, index of match entry in opcode table
+* if -1, not found
+*
+*************************************************************************/
+
+LPBYTE SearchOpcode ( LPBYTE pszop ) {
+ ULONG low = 0;
+ ULONG mid;
+ ULONG high = OPTABLESIZE - 1;
+ ULONG match;
+
+ while (low <= high) {
+ mid = (low + high) / 2;
+ match = (ULONG)strcmp(pszop, OpTable[mid]);
+ if (match == -1)
+ high = mid - 1;
+ else if (match == 1)
+ low = mid + 1;
+ else
+ return OpTable[mid] + strlen(OpTable[mid]) + 1;
+ }
+ return NULL;
+}
diff --git a/private/windbg/em/p_i386/d3.c b/private/windbg/em/p_i386/d3.c
new file mode 100644
index 000000000..ef51929f6
--- /dev/null
+++ b/private/windbg/em/p_i386/d3.c
@@ -0,0 +1,1834 @@
+
+/* */
+/* disasm */
+/* disassembler for CodeView */
+/* */
+/***************************************************************************/
+/* */
+/* @ Purpose: To disassemble one 80x86 instruction at address loc and */
+/* return the resulting string in dst. */
+/* */
+/* @ Functions included: */
+/* */
+/* void DIdisasm(ADDR *loc,int option,char *dst, stuct ea *ea) */
+/* */
+/* */
+/* Revision History: */
+/* */
+/* */
+/***************************************************************************/
+
+#include "d3.h"
+
+/***** macros and defines *****/
+
+
+#define BIT20(b) (b & 0x07)
+#define BIT53(b) (b >> 3 & 0x07)
+#define BIT76(b) (b >> 6 & 0x03)
+#define MAXL 20
+#define MAXOPLEN 10
+
+#define OBOFFSET 26
+#define OBOPERAND 34
+#define OBLINEEND 79
+
+#define iregNone (-1)
+
+/***** static tables and variables *****/
+
+
+static int rgbOverride[] = {0x3e, 0x36, 0x2e, 0x26};
+static char lregtab[] = "alcldlblahchdhbhaxcxdxbxspbpsidi"; /* reg table */
+static char uregtab[] = "ALCLDLBLAHCHDHBHAXCXDXBXSPBPSIDI";
+static char *regtab = &uregtab[0];
+
+static PCH mrmtb16[] = { "bx+si", /* modRM string table (16-bit) */
+ "bx+di",
+ "bp+si",
+ "bp+di",
+ "si",
+ "di",
+ "bp",
+ "bx"
+ };
+
+static PCH mrmtb32[] = { "eax", /* modRM string table (32-bit) */
+ "ecx",
+ "edx",
+ "ebx",
+ "esp",
+ "ebp",
+ "esi",
+ "edi"
+ };
+
+static char seg16[8] = { CV_REG_DS, CV_REG_DS, CV_REG_SS, CV_REG_SS,
+ CV_REG_DS, CV_REG_DS, CV_REG_SS, CV_REG_DS };
+static char reg16[8] = { CV_REG_BX, CV_REG_BX, CV_REG_BP, CV_REG_BP,
+ CV_REG_SI, CV_REG_DI, CV_REG_BP, CV_REG_BX };
+static char reg16_2[4] = { CV_REG_SI, CV_REG_DI, CV_REG_SI, CV_REG_DI };
+
+static char seg32[8] = { CV_REG_DS, CV_REG_DS, CV_REG_DS, CV_REG_DS,
+ CV_REG_SS, CV_REG_SS, CV_REG_DS, CV_REG_DS };
+static char reg32[8] = { CV_REG_EAX, CV_REG_ECX, CV_REG_EDX, CV_REG_EBX,
+ CV_REG_ESP, CV_REG_EBP, CV_REG_ESI, CV_REG_EDI };
+
+
+static char lsregtab[] = "ecsdfg"; // first letter of ES, CS, SS, DS, FS, GS
+static char usregtab[] = "ECSDFG";
+static char *sregtab = &usregtab[0];
+
+
+char lhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+char uhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+char *hexdigit = &uhexdigit[0];
+
+static int fUpper = TRUE;
+
+static int mod = 0; /* mod of mod/rm byte */
+static int rm = 0; /* rm of mod/rm byte */
+static int ttt = 0; /* return reg value (of mod/rm) */
+static unsigned char FAR*pMem = (unsigned char *)NULL; /* current position in instruction */
+static int mode_32 = '\0'; /* local addressing mode indicator */
+static int opsize_32 = 0; /* operand size flag */
+
+static char RgchSegOvr[ 8 ];
+static PCH PchSegOvr = NULL; // segment override indicator
+static char segOvrIndx; // Index of overriden segment
+static int EAsize [2] = {0}; // size of effective address item
+static long EAaddr [2] = {0}; // offset of effective address
+static PCH pchEAseg[2] = {0}; // normal segment for operand
+static char EAseg [2] = "\0";
+static BOOL FDwordTable;
+
+// internal function definitions
+
+typedef LPCH FAR *LPLPCH;
+
+#ifdef D3DM
+typedef enum {
+ osoNone = 0,
+ osoSymbols = 1,
+ osoSegment = 2
+} OSO;
+#endif
+
+
+void DIdoModrm(HPID,HTID,BOOL,LPADDR,DOP,LPLPCH, int * );
+int DumpEA ( HPID, HTID, BOOL, LPADDR, LPCH, int );
+void CalcMain ( HPID, HTID, BOOL,DOP, LPADDR, LPB, int, int FAR *,
+ LPCH, int, LPCH, int, LPCH, int );
+void CalcFPInt ( HPID, HTID, BOOL, DOP, LPADDR, int, LPCH, int );
+
+int DumpAddress ( LPADDR, LPCH, int, BOOL );
+int DumpGeneric ( LSZ, LPCH, int );
+int DumpComment ( LSZ, LPCH, int );
+
+void OutputAddr(LPLPCH, int *, LPADDR, int, BOOL );
+void OutputHexString(LPLPCH, int *, LPCH, int);
+void OutputHexValue(LPLPCH, int *, LPCH, int, int);
+void OutputHexCode(LPLPCH , LPCH, int);
+void OutputIString ( LPLPCH, int *, LPCH );
+void OutputString(LPLPCH, int *, LPCH);
+void GetSymbol ( ULONG, LPCH, LONG * );
+ULONG GetNextOffset(BOOL);
+
+char rgindx[] = {CV_REG_ES,CV_REG_CS,CV_REG_SS,CV_REG_DS};
+#define GETINDX(op) (rgindx[(op-0x26) / 8])
+
+
+
+
+//
+// The following functions are module-specific and are defined in a separate
+// file.
+//
+void OutputSymbol ( HPID, HTID, BOOL, BOOL, LPADDR, int, int, LPADDR, LPLPCH, int * );
+XOSD GetRegisterValue( HPID, HTID, UINT, LONG );
+XOSD SetAddress( HPID, HTID, UINT, LONG );
+XOSD ReadMemBuffer( HPID, HTID, UINT, LONG );
+LSZ ObtainSymbol( PADDR, SOP, PADDR, LSZ, LONG* );
+
+
+
+#define CCHMAX 256
+static char rgchDisasm [ CCHMAX ];
+
+static HPID hpidLocal;
+static HTID htidLocal;
+
+XOSD
+Disassemble(
+ HPID hpid,
+ HTID htid,
+ LPSDI lpsdi,
+ PVOID Memory,
+ INT MemorySize,
+ BOOL FullDisasm
+ )
+{
+
+ XOSD xosd = xosdNone;
+ int cchMax = CCHMAX;
+ DOP dop = lpsdi->dop;
+ LPCH lpchOut = rgchDisasm;
+ int ichCur = 0;
+ ADDR addrStart = lpsdi->addr;
+ int cch = 0;
+ int cb;
+ int cbUsed=0;
+
+ BYTE *rgb;
+
+ char rgchRaw [ MAXL * 2 + 1 ];
+ char rgchOpcode [ 20 ];
+ char rgchOperands [ 120 ];
+ char rgchEA [ 44 ];
+ char rgchComment [ 120 ];
+
+ hpidLocal = hpid;
+ htidLocal = htid;
+
+ FDwordTable = FALSE;
+
+ _fmemset ( rgchRaw, 0, sizeof ( rgchRaw ) );
+ _fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
+ _fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
+ _fmemset ( rgchComment, 0, sizeof ( rgchComment ) );
+ _fmemset ( rgchEA, 0, sizeof ( rgchEA ) );
+
+ lpsdi->ichAddr = -1;
+ lpsdi->ichBytes = -1;
+ lpsdi->ichOpcode = -1;
+ lpsdi->ichOperands = -1;
+ lpsdi->ichComment = -1;
+ lpsdi->ichEA0 = -1;
+ lpsdi->ichEA1 = -1;
+ lpsdi->ichEA2 = -1;
+
+ lpsdi->cbEA0 = 0;
+ lpsdi->cbEA1 = 0;
+ lpsdi->cbEA2 = 0;
+
+ lpsdi->fAssocNext = 0;
+ lpsdi->fIsCall = 0;
+ lpsdi->fIsBranch = 0;
+ lpsdi->fJumpTable = 0;
+
+ lpsdi->lpch = rgchDisasm;
+
+ //
+ // Set up for upper or lower case
+ //
+ fUpper = ( dop & dopUpper ) == dopUpper;
+ if ( fUpper ) {
+ hexdigit = uhexdigit;
+ regtab = uregtab;
+ sregtab = usregtab;
+ } else {
+ hexdigit = lhexdigit;
+ regtab = lregtab;
+ sregtab = lsregtab;
+ }
+
+ mode_32 = opsize_32 = ADDR_IS_OFF32(addrStart);
+
+ //
+ // Output the address if it is requested
+ //
+ if ( ( dop & dopAddr ) == dopAddr ) {
+ cch = DumpAddress ( &addrStart, lpchOut, cchMax, (dop & dopFlatAddr) );
+
+ lpsdi->ichAddr = 0;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ rgb = (BYTE *)Memory;
+ cb = MemorySize;
+
+ if ( cb <= 0 ) {
+
+ _fmemcpy ( rgchRaw, " ??", 4 );
+ _fmemcpy ( rgchOpcode, "???", 4 );
+ offAddr ( lpsdi->addr )++;
+
+ } else {
+
+ CalcMain (
+ hpid,
+ htid,
+ FullDisasm,
+ lpsdi->dop, &lpsdi->addr, rgb, cb, &cbUsed,
+ rgchOpcode, sizeof(rgchOpcode),
+ rgchOperands, sizeof(rgchOperands),
+ rgchComment, sizeof(rgchComment));
+
+ if ( offAddr(lpsdi->addr) > 0xFFFFFFFF - cbUsed ) {
+ return xosdBadAddress;
+ }
+
+ lpsdi->fJumpTable = FDwordTable;
+
+ if ( dop & dopRaw ) {
+ LPCH lpchT = rgchRaw;
+
+ OutputHexCode ( &lpchT, rgb, cbUsed );
+
+ *lpchT = '\0';
+ }
+ }
+
+ if ( ( dop & dopRaw ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchRaw, lpchOut, cchMax );
+
+ lpsdi->ichBytes = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+
+ if ( ( dop & dopOpcode ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchOpcode, lpchOut, cchMax );
+
+ lpsdi->ichOpcode = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchOperands [ 0 ] != '\0' ) ) {
+ cch = DumpGeneric ( rgchOperands, lpchOut, cchMax );
+
+ lpsdi->ichOperands = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchComment [ 0 ] != '\0' ) ) {
+ cch = DumpComment ( rgchComment, lpchOut, cchMax );
+
+ lpsdi->ichComment = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( dop & dopEA ) {
+ cch = DumpEA ( hpid, htid, FullDisasm, &lpsdi->addrEA0, lpchOut, cchMax );
+
+ if ( cchMax > 0 && cch > 0 ) {
+ lpsdi->ichEA0 = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+ }
+
+
+ offAddr ( lpsdi->addr ) += cbUsed;
+
+ return xosd;
+}
+
+
+
+int
+DumpAddress(
+ LPADDR lpaddr,
+ LPCH lpch,
+ int cchMax,
+ BOOL fFlatAddr
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to dump an ADDR packet to a buffer.
+
+Arguments:
+
+ lpaddr - Supplies the address packet to be dumped.
+ lpch - Supplies the buffer to format the address in
+ cchMax - Supplies the size of the buffer
+ fFlatAddr - Supplies TRUE if segments are to be suppressed for 32-bit
+ addresses.
+
+Return Value:
+
+ Returns the number of bytes used in the buffer
+
+--*/
+{
+ LPCH lpchT = lpch;
+ ADDR addrT = {0};
+
+ if (ADDR_IS_FLAT(*lpaddr) == FALSE) {
+ fFlatAddr = TRUE;
+ } else {
+ fFlatAddr = !fFlatAddr;
+ }
+
+ OutputAddr (&lpch, &cchMax, lpaddr,
+ (ADDR_IS_OFF32(*lpaddr) + 1) * 2, fFlatAddr );
+ *lpch = '\0';
+ return lpch - lpchT + 1;
+} /* DumpAddress() */
+
+int
+DumpGeneric (
+ LSZ lsz,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ int cb;
+
+ cb = strlen(lsz);
+ if (cb > cchMax - 1) {
+ cb = cchMax - 1;
+ }
+
+ strncpy(lpch, lsz, cb);
+ lpch[cb] = 0;
+ return cb + 1;
+}
+
+int
+DumpComment (
+ LSZ lsz,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ *(lpch) = ';';
+ return DumpGeneric ( lsz, lpch + 1, cchMax - 1 ) + 1;
+}
+
+int
+DumpEA (
+ HPID hpid,
+ HTID htid,
+ BOOL FullDisasm,
+ LPADDR lpaddr,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ LPCH lpchT = lpch;
+ int indx;
+ int cb;
+ BYTE rgb [ MAXL ];
+
+ for ( indx = 0; indx < 2; indx++ ) {
+
+ if ( EAsize [ indx ] ) {
+ ADDR addr = {0};
+
+ OutputString ( &lpchT, &cchMax, PchSegOvr ? PchSegOvr : pchEAseg [indx]);
+ OutputHexString (&lpchT, &cchMax, (LPB) &EAaddr [ indx ],
+ mode_32 ? 4 : 2 );
+
+ *lpchT++ = '=';
+ cchMax -= 1;
+
+ offAddr ( addr ) = (UOFFSET) EAaddr [ indx ];
+ if ( FullDisasm ) {
+
+ GetRegisterValue( hpid, htid,
+ PchSegOvr ? segOvrIndx : EAseg[indx],
+ (LONG) (LPW) ( &segAddr ( addr ) ));
+
+ *lpaddr = addr;
+
+ SetAddress (hpid, htid, adrCurrent, (LONG) (LPADDR) &addr);
+
+ cb = ReadMemBuffer( hpid, htid, EAsize [ indx ],
+ (LONG) (LPV) rgb);
+
+ if ( cb == EAsize [ indx ] ) {
+ OutputHexString ( &lpchT, &cchMax, rgb, EAsize [ indx ] );
+ }
+ else {
+ if (cchMax < EAsize[indx]) {
+ cchMax -= EAsize[indx];
+ while ( EAsize [ indx ]-- ) {
+ *lpchT++ = '?';
+ *lpchT++ = '?';
+ }
+ }
+ }
+ *lpchT++ = '\0';
+ }
+ }
+ }
+
+ return lpchT - lpch;
+}
+
+
+void
+CalcMain (
+ HPID hpid,
+ HTID htid,
+ BOOL FullDisasm,
+ DOP dop,
+ LPADDR lpaddr,
+ LPB rgb,
+ int cbMax,
+ int FAR *lpcbUsed,
+ LPCH rgchOpcode,
+ int cchOpcode,
+ LPCH rgchOperands,
+ int cchOperands,
+ LPCH rgchComment,
+ int cchComment
+ )
+{
+ int opcode; /* current opcode */
+ int opcodeT;
+ int olen = 2; /* operand length */
+ int alen = 2; /* address length */
+ int end = FALSE; /* end of instruction flag */
+ int mrm = FALSE; /* indicator that modrm is generated */
+ PCH action; /* action for operand interpretation */
+ long tmp; /* temporary storage field */
+ int indx; /* temporary index */
+ int action2; /* secondary action */
+ PCH pEAlabel = ""; /* optional label for operand */
+ int cbT;
+
+ int inREP = 0; // needed because we can get into getNxtByte:
+ // from *anywhere*, which is in case(REP):
+ // (note: this is a very good reason why
+ // using 'goto' makes things much harder
+ // during maintenance!).
+
+ char rgchModrm [ 100 ];
+
+ LPCH lpchOpcode = rgchOpcode;
+ LPCH lpchOperands = rgchOperands;
+ LPCH lpchModrm = rgchModrm;
+ LPCH lpchSegOvr = RgchSegOvr;
+
+ PchSegOvr = NULL;
+ EAsize [ 0 ] = EAsize[1] = 0; /* no effective address */
+ pchEAseg [ 0 ] = dszDS_;
+ pchEAseg [ 1 ] = dszES_;
+ EAseg [ 0 ] = CV_REG_DS;
+ EAseg [ 1 ] = CV_REG_ES;
+
+ olen = alen = (1 + mode_32) << 1; /* set operand/address lengths */
+
+ pMem = rgb;
+
+ /*
+ * Get an opcode or prefix & output it to the opcode buffer
+ */
+
+ opcode = *pMem++;
+ OutputString ( &lpchOpcode, &cchOpcode, distbl [ opcode ].instruct );
+ action = actiontbl + distbl [ opcode ].opr; /* get operand action */
+
+ /***** loop through all operand actions *****/
+
+ do {
+
+ action2 = (*action) & 0xc0;
+
+ switch ( (*action++) & 0x3f ) {
+
+ case ALT: /* alter the opcode if 32-bit */
+
+ if ( opsize_32 ) {
+ indx = *action++;
+ switch( indx ) {
+ case 0:
+ /*
+ * Map CBW to CWDE
+ */
+
+ lpchOpcode -= 3;
+ cchOpcode += 3;
+ OutputString( &lpchOpcode, &cchOpcode, dszCWDE );
+ break;
+
+ case 1:
+ /*
+ * Map CWD to CDQ
+ */
+
+ lpchOpcode[-2] = (char) (fUpper ? 'D' : 'd');
+ lpchOpcode[-1] = (char) (fUpper ? 'Q' : 'q');
+ break;
+
+ case 2:
+ /*
+ * Change last letter to 'D' from 'W'
+ */
+
+ lpchOpcode[-1] = (char) (fUpper ? 'D' : 'd');
+ break;
+
+ case 3:
+ /*
+ * Append a 'D' to the end of the opcode
+ */
+
+ OutputString( &lpchOpcode, &cchOpcode, "d");
+ break;
+ }
+ }
+ break;
+
+ case STROP:
+ /*
+ * compute size of operands in indx
+ * also if dword operands, change fifth
+ * opcode letter from 'w' to 'd'.
+ */
+
+ if ( opcode & 1 ) {
+ if ( opsize_32 ) {
+ indx = 4;
+ *(lpchOpcode - 1) = (char)(fUpper ? 'D' : 'd');
+ }
+ else {
+ indx = 2;
+ }
+ }
+ else {
+ indx = 1;
+ }
+
+ if ( *action & 1 ) {
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ CV_REG_SI,
+ (LONG) (LPW) &EAaddr[0]
+ );
+ }
+ EAsize[0] = indx;
+
+ }
+
+ if ( *action++ & 2 ) {
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ CV_REG_DI,
+ (LONG) (LPW) &EAaddr[1]
+ );
+ }
+ EAsize[1] = indx;
+ }
+ break;
+
+ case CHR: /* insert a character */
+
+ *lpchOperands++ = *action++;
+ cchOperands -= 1;
+ break;
+
+ case CREG: /* set debug, test or control reg */
+
+ if ( opcode & 0x04 ) {
+ *lpchOperands++ = (char) ( fUpper ? 'T' : 't' );
+ }
+ else if ( opcode & 0x01 ) {
+ *lpchOperands++ = (char) ( fUpper ? 'D' : 'd' );
+ }
+ else {
+ *lpchOperands++ = (char) ( fUpper ? 'C' : 'c' );
+ }
+ *lpchOperands++ = (char) ( fUpper ? 'R' : 'r' );
+ *lpchOperands++ = (char)('0' + ttt);
+ cchOperands -= 3;
+ break;
+
+ case SREG2: /* segment register */
+ ttt = BIT53(opcode); /* set value to fall through */
+
+ case SREG3: /* segment register */
+ if (ttt > 5) {
+ *lpchOperands++ = '?';
+ *lpchOperands++ = '?';
+ } else {
+ *lpchOperands++ = sregtab[ttt]; /* reg is part of modrm */
+ *lpchOperands++ = (char) (fUpper ? 'S' : 's');
+ }
+ cchOperands -= 2;
+ break;
+
+ case BRSTR: /* get index to register string */
+ ttt = *action++; /* from action table */
+ goto BREGlabel;
+
+ case BOREG: /* byte register (in opcode) */
+ ttt = BIT20(opcode); /* register is part of opcode */
+ goto BREGlabel;
+
+ case ALSTR:
+ ttt = 0; /* point to AL register */
+ BREGlabel:
+ case BREG: /* general register */
+ *lpchOperands++ = regtab[ttt * 2];
+ *lpchOperands++ = regtab[ttt * 2 + 1];
+ cchOperands -= 2;
+ break;
+
+ case WRSTR: /* get index to register string */
+ ttt = *action++; /* from action table */
+ goto WREGlabel;
+
+ case VOREG: /* register is part of opcode */
+ ttt = BIT20(opcode);
+ goto VREGlabel;
+
+ case AXSTR:
+ ttt = 0; /* point to eAX register */
+ VREGlabel:
+ case VREG: /* general register */
+ if (!opsize_32) { /* test for 32bit mode */
+ goto WREGlabel;
+ }
+ case DREG:
+ *lpchOperands++ = (char) ( fUpper ? 'E' : 'e' );
+ cchOperands -= 1;
+
+ WREGlabel:
+ case WREG: /* register is word size */
+ *lpchOperands++ = regtab[ttt * 2 + 16];
+ *lpchOperands++ = regtab[ttt * 2 + 17];
+ cchOperands -= 2;
+ break;
+
+ case IST_ST:
+ OutputString ( &lpchOperands, &cchOperands, "st(0),st" );
+ *(lpchOperands - 5) += rm;
+ break;
+
+ case ST_IST:
+ OutputString ( &lpchOperands, &cchOperands, "st," );
+ case IST:
+ OutputString ( &lpchOperands, &cchOperands, "st(0)" );
+ *(lpchOperands - 2) += rm;
+ break;
+
+ case BYT: /* set instruction to byte only */
+ EAsize[0] = 1;
+ pEAlabel = "byte ptr ";
+ break;
+
+ case VAR:
+ if (opsize_32)
+ goto DWRDlabel;
+
+ case EWRD:
+ opsize_32 = 0;
+
+ case WRD:
+
+ EAsize[0] = 2;
+ pEAlabel = "word ptr ";
+ break;
+
+ case EDWRD:
+ opsize_32 = 1; /* for control reg move, use eRegs */
+ case DWRD:
+ DWRDlabel:
+ EAsize[0] = 4;
+ pEAlabel = "dword ptr ";
+ break;
+
+ case FWRD:
+ EAsize[0] = 6;
+ pEAlabel = "fword ptr ";
+ break;
+
+ case QWRD:
+ EAsize[0] = 8;
+ pEAlabel = "qword ptr ";
+ break;
+
+ case TBYT:
+ EAsize[0] = 10;
+ pEAlabel = "tbyte ptr ";
+ break;
+
+ case FARPTR:
+ if (opsize_32) {
+ EAsize[0] = 6;
+ pEAlabel = "fword ptr ";
+ }
+ else {
+ EAsize[0] = 4;
+ pEAlabel = "dword ptr ";
+ }
+ break;
+
+ case LMODRM: /* output modRM data type */
+ if (mod != 3) {
+ OutputString ( &lpchOperands, &cchOperands, pEAlabel );
+ }
+
+ case MODRM: /* output modrm string */
+ if (mod != 3) {
+ if (PchSegOvr) { /* in case of segment override */
+ OutputString ( &lpchOperands, &cchOperands, PchSegOvr );
+ }
+ }
+ *lpchModrm = '\0';
+ OutputIString ( &lpchOperands, &cchOperands, rgchModrm );
+ break;
+
+ case ADDRP: /* address pointer */
+ {
+ ADDR addrT = {0};
+
+ if ( olen == 2 ) {
+ ADDRSEG16 ( addrT );
+ offAddr ( addrT ) = (UOFFSET) * ( ( unsigned short * ) pMem );
+ }
+ else {
+ ADDRLIN32 ( addrT );
+ offAddr ( addrT ) = (UOFFSET) * ( ( unsigned long * ) pMem );
+ }
+
+ segAddr ( addrT ) = * ( (WORD *) ( pMem + olen ) );
+
+ OutputSymbol (
+ hpidLocal,
+ htidLocal,
+ ( (dop & dopSym) ? osoSymbols : osoNone ) | osoSegment,
+ FALSE,
+ &addrT,
+ CV_REG_CS,
+ olen,
+ lpaddr,
+ &lpchOperands,
+ &cchOperands
+ );
+
+ pMem += olen + 2;
+ }
+ break;
+
+ case REL8: /* relative address 8-bit */
+
+ if ( opcode == 0xe3 && opsize_32 ) {
+ cchOpcode += lpchOpcode - rgchOpcode;
+ lpchOpcode = rgchOpcode;
+ OutputString ( &lpchOpcode, &cchOpcode, dszJECXZ );
+ }
+ tmp = (long) *(PCH)pMem++; /* get the 8-bit rel offset */
+ goto DoRelDispl;
+
+ case REL16: /* relative address 16-/32-bit */
+ if (opsize_32) {
+ tmp = *(long *)pMem; /* get 32-bit relative offset */
+ } else {
+ tmp = *(USHORT *)pMem; /* get 16-bit relative offset */
+ }
+ pMem += olen; /* skip over offset */
+
+ DoRelDispl:
+
+ tmp += offAddr ( *lpaddr ) + (pMem - rgb); /* calculate address */
+ if (!opsize_32) {
+ tmp &= 0xFFFF;
+ }
+
+ {
+ ADDR addrT = {0};
+
+ addrT = *lpaddr;
+ ADDR_IS_LI(addrT) = FALSE;
+ addrT.emi = 0;
+ offAddr ( addrT ) = (UOFFSET) tmp;
+
+ OutputSymbol (
+ hpidLocal,
+ htidLocal,
+ !! ( dop & dopSym ),
+ FALSE,
+ &addrT,
+ CV_REG_CS,
+ opsize_32 ? 4 : 2,
+ lpaddr,
+ &lpchOperands, &cchOperands
+ );
+ }
+ break;
+
+ case UBYT: /* unsigned byte for int/in/out */
+ /*
+ * For floating point emulation interupts in dos, we need
+ * to output the equivalent fp instructions as comments
+ */
+
+ if ((opcode == 0xCD) && (*pMem >= 0x34) && (*pMem <= 0x3D)) {
+ BYTE bT = *pMem;
+
+ CalcFPInt (
+ hpid, htid,
+ FullDisasm,
+ dop, lpaddr, cbMax,
+ rgchComment, cchComment );
+ OutputHexString ( &lpchOperands, &cchOperands, &bT, 1);
+ }
+ else {
+ OutputHexString ( &lpchOperands, &cchOperands, pMem, 1);
+ pMem++;
+ }
+ break;
+
+ case IB: /* operand is immediate byte */
+ if ((opcode & ~1) == 0xd4) { /* postop for AAD/AAM is 0x0a */
+ if (*pMem++ != 0x0a) /* test post-opcode byte */
+ OutputString ( &lpchOperands, &cchOperands, dszRESERVED );
+ break;
+ }
+ olen = 1; /* set operand length */
+ goto DoImmed;
+
+ case IW: /* operand is immediate word */
+ olen = 2; /* set operand length */
+
+ case IV: /* operand is word or dword */
+ DoImmed:
+ OutputHexValue ( &lpchOperands, &cchOperands, pMem, olen, FALSE );
+ pMem += olen;
+ break;
+
+ case OFFS: /* operand is offset */
+ /*
+ * Put out the size of the item the offset points to
+ */
+
+ if ( opcode & 1 ) {
+ EAsize[0] = olen;
+ if ( olen == 2 ) {
+ OutputString ( &lpchOperands, &cchOperands, "word ptr " );
+ } else {
+ OutputString ( &lpchOperands, &cchOperands, "dword ptr " );
+ }
+ } else {
+ EAsize[0] = 1;
+ OutputString ( &lpchOperands, &cchOperands, "byte ptr " );
+ }
+
+ /*
+ * if address length is dword
+ */
+
+ if (alen == 4) {
+ EAaddr[0] = *(long *)pMem; /* get the dword as address */
+ } else {
+ EAaddr[0] = *(WORD *)pMem; /* get a word as address */
+ }
+
+ if (PchSegOvr) {
+ OutputString( &lpchOperands, &cchOperands, PchSegOvr );
+ }
+
+ *lpchOperands++ = '['; /* ] */
+ cchOperands -= 1;
+
+ {
+ ADDR addrT = {0};
+
+ if ( alen == 4 ) {
+ ADDRLIN32 ( addrT );
+ } else {
+ ADDRSEG16 ( addrT );
+ }
+
+ offAddr ( addrT ) = (UOFFSET) EAaddr [ 0 ];
+
+ if ( PchSegOvr ) {
+ if ( FullDisasm ) {
+ GetRegisterValue ( hpid, htid, segOvrIndx,
+ (LONG) (LPW) &segAddr ( addrT ) );
+ }
+ OutputSymbol (
+ hpidLocal,
+ htidLocal,
+ !! ( dop & dopSym ), PchSegOvr != NULL,
+ &addrT, segOvrIndx, alen, lpaddr, &lpchOperands,
+ &cchOperands);
+ } else {
+ WORD wT = 0;
+
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ CV_REG_DS,
+ (LONG) (LPW) &segAddr ( addrT )
+ );
+ }
+ if (reg16[rm] == CV_REG_BP) {
+ pchEAseg[0] = dszSS_;
+ EAseg[0] = CV_REG_SS;
+ }
+
+ if ( FullDisasm ) {
+ if (rm < 4) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ reg16_2[rm],
+ (LONG) (LPW) &wT
+ );
+ EAaddr[0] += wT;
+ }
+ if ( mod == 1 ) {
+ EAaddr[0] += *( (char*)pMem);
+ } else if ( mod == 2 ) {
+ EAaddr[0] += *( (int*)pMem);
+ }
+ }
+
+ OutputSymbol (
+ hpidLocal,
+ htidLocal,
+ !! ( dop & dopSym ),
+ FALSE,
+ &addrT,
+ iregNone,
+ alen,
+ lpaddr,
+ &lpchOperands, &cchOperands
+ );
+
+ }
+ }
+
+ pMem += alen; /* [ */
+ *lpchOperands++ = ']';
+ cchOperands -= 1;
+ break;
+
+ case GROUP:
+ /*
+ * operand is of group 1,2,4,6 or 8
+ * output opcode symbol
+ */
+
+ OutputString ( &lpchOpcode, &cchOpcode, group [*action++][ttt] );
+ break;
+
+ case GROUPT:
+ /*
+ * operand is of group 3,5 or 7
+ */
+
+ indx = *action; /* get indx into group from action */
+ ttt = BIT53(*pMem);
+ goto doGroupT;
+
+ case EGROUPT: /* x87 ESC (D8-DF) group index */
+
+ indx = BIT20(opcode) * 2; /* get group index from opcode */
+ if (mod == 3) { /* some operand variations exists */
+ /* for x87 and mod == 3 */
+ ++indx; /* take the next group table entry */
+ if (indx == 3) { /* for x87 ESC==D9 and mod==3 */
+ if (ttt > 3) { /* for those D9 instructions */
+ indx = 12 + ttt;/* offset index to table by 12 */
+ ttt = rm; /* set secondary index to rm */
+ }
+ }
+ else if (indx == 7) { /* for x87 ESC==DB and mod==3 */
+ if (ttt == 4) /* only valid if ttt==4 */
+ ttt = rm; /* set secondary group table index */
+ else
+ ttt = 7; /* no an x87 instruction */
+ }
+ }
+ doGroupT:
+ /* handle group with different types of operands */
+
+ OutputString ( &lpchOpcode, &cchOpcode,
+ groupt[indx][ttt].instruct );
+ action = actiontbl + groupt[indx][ttt].opr;
+ /* get new action */
+ break;
+
+ case OPC0F: /* secondary opcode table (opcode 0F) */
+ opcodeT = opcode = *pMem++; /* get real opcode */
+ if (opcode < 0x10) /* for the first 10 opcodes */
+ opcodeT += 256;
+ else if (opcode > 0x1f && opcode < 0x27)
+ opcodeT += 256 - (0x20 - 0x10);
+ else if (opcode > 0x7c && opcode < 0xd0)
+ opcodeT += 256 - (0x20 - 0x10) - (0x7d -0x27);
+ else
+ opcodeT = 260; /* all non existing opcodes */
+ goto getNxtByte1;
+
+ case ADR_OVR: /* address override */
+ mode_32 = !mode_32; /* override addressing mode */
+ alen = (mode_32 + 1) << 1; /* toggle address length */
+ goto getNxtByte;
+
+ case OPR16:
+ opsize_32 = 0;
+ olen = 2;
+ break;
+
+ case OPR_OVR: /* operand size override */
+ opsize_32 = !opsize_32; /* override operand size */
+ olen = (opsize_32 + 1) << 1; /* toggle operand length */
+ goto getNxtByte;
+
+ case SEG_OVR: /* handle segment override */
+
+ /* Pointer should be dgroup based */
+
+ lpchSegOvr = RgchSegOvr;
+ cbT = sizeof(RgchSegOvr);
+ OutputString( &lpchSegOvr, &cbT, distbl [ opcode ].instruct );
+ RgchSegOvr [ 3 ] = '\0';
+ PchSegOvr = RgchSegOvr; /* save seg ovr string */
+ segOvrIndx = GETINDX ( opcode );
+ lpchOpcode -= strlen(RgchSegOvr);
+ cchOpcode += strlen(RgchSegOvr);
+ *lpchOpcode = 0;
+ goto getNxtByte;
+
+ case BOP:
+ if (*pMem == 0xc4) {
+ cchOpcode += lpchOpcode - rgchOpcode;
+ lpchOpcode = rgchOpcode;
+ OutputString(&lpchOpcode, &cchOpcode, dszBOP);
+ pMem++;
+ } else {
+ action = actiontbl + O_fReg_Modrm;
+ }
+ break;
+
+ case REP: /* handle rep/lock prefixes */
+ inREP = 1; // kludge!
+ getNxtByte:
+ opcodeT = opcode = *pMem++; /* next byte is opcode */
+ if (inREP
+ &&
+ (opcodeT == 0xa6 || opcodeT == 0xa7
+ || opcodeT == 0xae || opcodeT == 0xaf)
+ )
+ {
+ OutputString ( &lpchOpcode, &cchOpcode, "E");
+ }
+ if ( rgchOpcode != lpchOpcode ) {
+/***
+ *lpchOpcode++ = ' ';
+ cchOpcode -= 1;
+***/
+ OutputString ( &lpchOpcode, &cchOpcode, " ");
+ }
+ getNxtByte1:
+ action = actiontbl + distbl [ opcodeT ].opr;
+ OutputString ( &lpchOpcode, &cchOpcode, distbl [opcodeT].instruct);
+ inREP = 0; // un-kludge!
+ break;
+
+ case O_GROUP5:
+ EAsize [ 0 ] = olen;
+ break;
+
+ default: /* opcode has no operand */
+
+ break;
+ }
+
+ switch ( action2 ) { /* secondary action */
+
+ case MRM: /* generate modrm for later use */
+ if (!mrm) { /* ignore if it has been generated */
+ cbT = sizeof(rgchModrm);
+ DIdoModrm ( hpid, htid, FullDisasm, lpaddr, dop, &lpchModrm, &cbT );
+ mrm = TRUE; /* remember its generation */
+ }
+ break;
+
+ case COM: /* insert a comma after operand */
+ *lpchOperands++ = ',';
+ cchOperands -= 1;
+ break;
+
+ case END: /* end of instruction */
+ end = TRUE;
+ break;
+ }
+
+ } while ( !end ); /* loop til end of instruction */
+
+ *lpcbUsed = pMem - rgb;
+}
+
+void
+CalcFPInt (
+ HPID hpid,
+ HTID htid,
+ BOOL FullDisasm,
+ DOP dop,
+ LPADDR lpaddr,
+ int cbMax,
+ LPCH lpch,
+ int cch
+ )
+{
+ UCHAR FAR *pMemT = pMem;
+ UCHAR rgb [ MAXL ];
+ UCHAR bOp = *pMem;
+
+ if ( bOp == 0x3D ) {
+ OutputString(&lpch, &cch, dszFWAIT );
+ pMem += 1;
+ }
+ else {
+ int cbUsed = 0;
+ char rgchOpcode [ 16 ];
+ char rgchOperands [ 80 ];
+ int ich = 0;
+
+ _fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
+ _fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
+
+ if ( bOp == 0x3C ) {
+ rgb [ 0 ] = (UCHAR) ( rgbOverride [ *(pMem + 1) >> 6 ] );
+ rgb [ 1 ] = (UCHAR) ( *(pMem + 1) | 0xC0 );
+ _fmemcpy ( &rgb [ 2 ], pMem + 2, cbMax - 2 );
+ } else {
+ rgb [ 0 ] = (UCHAR) ( bOp + 0xA4 );
+ _fmemcpy ( &rgb [ 1 ], pMem + 1, cbMax - 2 );
+ }
+
+ CalcMain (
+ hpid,
+ htid,
+ FullDisasm,
+ dop,
+ lpaddr,
+ rgb,
+ cbMax - 1,
+ &cbUsed,
+ rgchOpcode, sizeof(rgchOpcode),
+ rgchOperands, sizeof(rgchOperands),
+ NULL, 0
+ );
+
+ while ( rgchOpcode [ ich ] != '\0' ) {
+ *(lpch + ich ) = rgchOpcode [ ich ];
+ ich += 1;
+ }
+
+ while ( ich < 9 ) {
+ *(lpch + ich) = ' ';
+ ich += 1;
+ }
+
+ while ( rgchOperands [ ich - 9 ] != '\0' ) {
+ *(lpch + ich) = rgchOperands [ ich - 9 ];
+ ich += 1;
+ }
+
+ pMem = pMemT + cbUsed;
+ }
+}
+
+void
+DIdoModrm (
+ HPID hpid,
+ HTID htid,
+ BOOL FullDisasm,
+ LPADDR lpaddr,
+ DOP dop,
+ LPLPCH lplpchBuf,
+ int * pcch
+ )
+{
+ int mrm; /* modrm byte */
+ PCH src; /* source string */
+ int sib;
+ int ss;
+ int ind;
+ int oldrm;
+ int fSymbol = FALSE;
+ ULONG wT;
+
+ BOOL fRegIndirect = FALSE;
+ int iScale;
+
+ mrm = *pMem++; /* get the mrm byte from instruction */
+ mod = BIT76(mrm); /* get mod */
+ ttt = BIT53(mrm); /* get reg - used outside routine */
+ rm = BIT20(mrm); /* get rm */
+
+ if (mod == 3) { /* register only mode */
+ src = &regtab[rm * 2]; /* point to 16-bit register */
+ if (EAsize[0] > 1) {
+ src += 16; /* point to 16-bit register */
+ if (EAsize[0] > 2)
+ *(*lplpchBuf)++ = (char) ( fUpper ? 'E' : 'e' );/* make it a 32bit register */
+ }
+ *(*lplpchBuf)++ = *src++; /* copy register name */
+ *(*lplpchBuf)++ = *src;
+ EAsize[0] = 0; /* no EA value to output */
+ PchSegOvr = NULL;
+ return;
+ }
+
+ if (mode_32) { /* 32-bit addressing mode */
+ *(*lplpchBuf)++ = '['; /* ] */
+
+ oldrm = rm;
+ if (rm == 4) { /* rm == 4 implies sib byte */
+
+ // register indirect
+
+ sib = *pMem++; /* get s_i_b byte */
+ rm = BIT20(sib); /* return base */
+ ind = BIT53(sib);
+
+ if (ind != 4) {
+
+ // not ebp
+ // with offset
+
+ OutputString(lplpchBuf, pcch, mrmtb32[ind]);
+ ss = 1 << BIT76(sib);
+ if (ss != 1) {
+
+ // scaled
+
+ *(*lplpchBuf)++ = '*';
+ *(*lplpchBuf)++ = (char)(ss + '0');
+ }
+ *(*lplpchBuf)++ = '+';
+ fRegIndirect = TRUE;
+ iScale = ss;
+ }
+ }
+
+
+ if ( mod == 0 && rm == 5) {
+ ADDR addrT = {0};
+
+ // memory indirect
+
+ if (fRegIndirect && iScale == 4) {
+ FDwordTable = TRUE;
+ }
+
+ ADDRLIN32 ( addrT );
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ CV_REG_SS,
+ (LONG) (LPW) &( segAddr ( addrT ) )
+ );
+ }
+ EAaddr[0] = (long) ( *(unsigned long *) pMem );
+ offAddr ( addrT ) = (UOFFSET) EAaddr[0];
+
+ OutputSymbol (
+ hpidLocal,
+ htidLocal,
+ !! ( dop & dopSym ),
+ FALSE,
+ &addrT,
+ iregNone,
+ 4,
+ lpaddr,
+ lplpchBuf, pcch
+ );
+ pMem += 4;
+ } else if ( (rm == 5) && ( (mod == 1) || (mod == 2) ) ) {
+ ADDR addrT = {0};
+ CHAR rgchSymbol[60];
+ LPCH lpchSymbol;
+ LONG displacement;
+ ADDRLIN32 ( addrT );
+
+ if ( FullDisasm ) {
+ GetRegisterValue ( hpid,
+ htid,
+ CV_REG_SS,
+ (LONG) (LPW) &(segAddr (addrT)));
+ }
+ if ( mod == 2) {
+ EAaddr [ 0 ] = (long) ( *(long *) pMem );
+ } else { /* mod == 1 */
+ EAaddr [ 0 ] = (long) ( *(PCH) pMem );
+ }
+
+ offAddr ( addrT ) = (UOFFSET) EAaddr [ 0 ];
+
+ pchEAseg[0] = dszSS_;
+ EAseg[0] = CV_REG_SS;
+
+ if ( FullDisasm ) {
+ if ( dop & dopSym ) {
+ lpchSymbol = ObtainSymbol(&addrT, sopStack, lpaddr,
+ rgchSymbol, &displacement);
+
+ if ( fSymbol = (lpchSymbol != NULL ) ) {
+ OutputIString ( lplpchBuf, pcch, rgchSymbol );
+ pMem += ( mod == 1 ) ? 1 : (mode_32 + 1 ) * 2;
+ }
+ }
+
+ GetRegisterValue( hpid, htid, CV_REG_EBP, (LONG) &wT);
+ EAaddr[0] += wT;
+ }
+ if ( !fSymbol ) {
+ OutputString( lplpchBuf, pcch, mrmtb32[rm]);
+ }
+
+ } else {
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ reg32[rm],
+ (LONG) (LPW) &(EAaddr[0])
+ );
+ }
+ if (reg32[rm] == CV_REG_EBP || reg32[rm] == CV_REG_ESP) {
+ pchEAseg[0] = dszSS_;
+ }
+ EAseg[0] = CV_REG_SS;
+ OutputString(lplpchBuf, pcch, mrmtb32[rm]);
+ }
+
+ if ( FullDisasm ) {
+ if (oldrm == 4) { /* finish processing sib */
+ if (ind != 4) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ reg32[ind],
+ (LONG) (LPW) &(wT)
+ );
+ EAaddr[0] += wT * ss;
+ }
+ }
+ }
+ } else { /* 16-bit addressing mode */
+ *(*lplpchBuf)++ = '['; /* ] */
+ if ( mod == 0 && rm == 6 ) {
+ ADDR addrT = {0};
+
+ ADDRSEG16 ( addrT );
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ CV_REG_SS,
+ (LONG) (LPW) &( segAddr ( addrT ) )
+ );
+ }
+ EAaddr [ 0 ] = (long) ( *(unsigned short *) pMem );
+ pMem += 2;
+
+ offAddr ( addrT ) = (UOFFSET) EAaddr [ 0 ];
+
+ OutputSymbol (
+ hpidLocal,
+ htidLocal,
+ !! ( dop & dopSym ),
+ FALSE,
+ &addrT,
+ iregNone,
+ 2,
+ lpaddr,
+ lplpchBuf, pcch
+ );
+ }
+ else if ( rm == 6 && ( mod == 1 || mod == 2 ) ) {
+ ADDR addrT = {0};
+ CHAR rgchSymbol [ 60 ];
+ LPCH lpchSymbol;
+ long displacement;
+ ADDRSEG16 ( addrT );
+
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ CV_REG_SS,
+ (LONG) (LPW) &( segAddr ( addrT ) )
+ );
+ }
+
+ if ( mod == 2 ) {
+ EAaddr [ 0 ] = (long) ( *(short *) pMem );
+ }
+ else { // ( mod == 1 )
+ EAaddr [ 0 ] = (long) ( *(PCH) pMem );
+ }
+
+ offAddr ( addrT ) = (UOFFSET) EAaddr [ 0 ];
+
+ pchEAseg[0] = dszSS_;
+ EAseg[0] = CV_REG_SS;
+
+ if ( FullDisasm ) {
+ if ( dop & dopSym ) {
+ lpchSymbol = ObtainSymbol (
+ &addrT,
+ sopStack,
+ lpaddr,
+ rgchSymbol,
+ &displacement );
+
+ if ( fSymbol = ( lpchSymbol != NULL ) ) {
+
+ OutputIString ( lplpchBuf, pcch, rgchSymbol );
+ pMem += ( mod == 1 ) ? 1 : ( mode_32 + 1 ) * 2;
+ }
+ }
+
+ GetRegisterValue( hpid, htid, CV_REG_EBP, (LONG) &wT);
+ EAaddr[0] += (wT & 0xffff);
+ }
+
+ if ( !fSymbol ) {
+ OutputString(lplpchBuf, pcch, mrmtb16[rm]);
+ }
+ }
+ else {
+ if ( FullDisasm ) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ reg16[rm],
+ (LONG) (LPW) &(EAaddr[0])
+ );
+ if (reg16[rm] == CV_REG_BP)
+ pchEAseg[0] = dszSS_;
+ EAseg[0] = CV_REG_SS;
+ if (rm < 4) {
+ GetRegisterValue (
+ hpid,
+ htid,
+ reg16_2[rm],
+ (LONG) (LPW) &(EAaddr[0])
+ );
+ }
+ }
+ OutputString(lplpchBuf, pcch, mrmtb16[rm]);
+ }
+ }
+
+ // output any displacement
+
+ if ( !fSymbol ) {
+ if (mod == 1) {
+ OutputHexValue(lplpchBuf, pcch, pMem, 1, TRUE);
+ pMem++;
+ }
+ else if (mod == 2) {
+ if (mode_32) {
+ OutputHexValue(lplpchBuf, pcch, pMem, 4, TRUE);
+ pMem += 4;
+ }
+ else {
+ OutputHexValue(lplpchBuf, pcch, pMem, 2, TRUE);
+ pMem += 2;
+ }
+ }
+ }
+
+ if ( !mode_32 ) {
+ EAaddr[0] &= 0xffff;
+ EAaddr[1] &= 0xffff;
+ }
+
+ *(*lplpchBuf)++ = ']';
+
+ return;
+}
+
+/*** OutputHexValue - output hex value
+*
+* Purpose:
+* Output the value pointed by *lplpchBuf of the specified
+* length. The value is treated as unsigned and all leading
+* zeros are output. If fDisplacement is true, treat as signed
+* and always prepend +/-.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* *pchMemBuf - pointer to memory buffer to extract value
+* length - length in bytes of value (1, 2, and 4 supported)
+* fDisp - set if displacement to output '+'
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void
+OutputHexValue (
+ LPLPCH lplpchBuf,
+ int * pcch,
+ PCH pchMemBuf,
+ int length,
+ int fDisp
+ )
+{
+ long value;
+ int index;
+ char digit[8];
+
+ if ( length == 1 ) {
+ value = (long) (*(PCH)pchMemBuf);
+ }
+ else if ( length == 2 ) {
+ value = (long) (*(short FAR *)pchMemBuf);
+ }
+ else {
+ value = *(long FAR *)pchMemBuf;
+ }
+
+ if ( fDisp ) {
+ if ( value < 0 ) {
+ *(*lplpchBuf)++ = '-';
+ value = -value;
+ }
+ else if ( value > 0 ) {
+ *(*lplpchBuf)++ = '+';
+ }
+ else {
+ return;
+ }
+ }
+
+ for (index = 7; index != -1; index--) {
+ digit[index] = (char)(value & 0xf);
+ value >>= 4;
+ }
+
+ index = 8 - ( length * 2 );
+
+ while ( index < 8 ) {
+ *(*lplpchBuf)++ = hexdigit [ digit [ index++ ] ];
+ }
+}
+
+
+
+
+/*** OutputHexString - output hex string
+*
+* Purpose:
+* Output the value pointed by *lplpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* *pchValue - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+* *lplpchMemBuf - pointer update to next memory byte
+*
+*************************************************************************/
+
+void
+OutputHexString (
+ LPLPCH lplpchBuf,
+ int * pcch,
+ PCH pchValue,
+ int length
+ )
+{
+ unsigned char chMem;
+
+ pchValue += length;
+ while ( length-- ) {
+ chMem = *--pchValue;
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
+
+/*** OutputAddr - output address package
+*
+* Purpose:
+* Output the address pointed to by lpaddr.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpaddr - Standard address package.
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void
+OutputAddr (
+ LPLPCH lplpchBuf,
+ int * pcch,
+ LPADDR lpaddr,
+ int alen,
+ BOOL fSeg
+ )
+{
+ ADDR addr = *lpaddr;
+
+ if (fSeg) {
+ OutputString( lplpchBuf, pcch, "0x" );
+ OutputHexString ( lplpchBuf, pcch, (LPCH) &( segAddr ( addr ) ), 2 );
+ *(*lplpchBuf)++ = ADDR_IS_REAL(*lpaddr) ? '#' : ':';
+ *pcch -= 1;
+ }
+ OutputString( lplpchBuf, pcch, "0x" );
+ OutputHexString ( lplpchBuf, pcch, (LPCH) &offAddr ( addr ), alen );
+}
+
+/*** OutputHexCode - output hex code
+*
+* Purpose:
+* Output the code pointed by lpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed. This differs from OutputHexString
+* in that bytes are printed from low to high addresses.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpchMemBuf - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void
+OutputHexCode (
+ LPLPCH lplpchBuf,
+ LPCH lpchMemBuf,
+ int length
+ )
+{
+ unsigned char chMem;
+
+ while (length--) {
+ chMem = *lpchMemBuf++;
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
+
+
+void
+OutputString(
+ LPLPCH lplpchBuf,
+ int * lpcch,
+ LPCH lpchString
+ )
+/*++
+
+Routine Description:
+
+ This function will copy the string pointed to by lpchString to the
+ buffer pointed to by lplpchBuf with the following restrictions:
+
+ 1. The string will be converted to uppercase if need be while
+ being copied.
+ 2. We will cut off the string when the destination buffer is filled
+ 3. We will guarrenttee that the destination buffer is termiatned
+ with a 0.
+
+Arguments:
+
+ lplpchBuf - Supplies a pointer to the buffer to copy into, pointer is
+ - Returns to point to after last character copied
+ lpcch - Supplies a pointer to lenght of destination buffer
+ lpchString - Supplies a pointer to the string to be copied
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int cb;
+
+ /*
+ * Assert on bad input values
+ */
+ assert( lpchString != NULL);
+ assert( lplpchBuf != NULL );
+ assert( lpcch != NULL );
+ assert( *lplpchBuf != NULL );
+
+ /*
+ * If no room left in the buffer -- return
+ */
+
+ if (*lpcch == 0) {
+ return;
+ }
+
+ /*
+ * Copy over as much of the string as will fit
+ */
+
+ cb = strlen(lpchString);
+ if (cb + 1 > *lpcch) {
+ cb = *lpcch - 1;
+ }
+
+ strncpy(*lplpchBuf, lpchString, cb);
+ (*lplpchBuf)[cb] = 0;
+
+ if ( fUpper ) {
+ _strupr(*lplpchBuf);
+ } else {
+ _strlwr(*lplpchBuf);
+ }
+ *lplpchBuf += cb;
+ *lpcch -= cb;
+ return;
+} /* OutputString() */
+
+void
+OutputIString(
+ LPLPCH lplpchBuf,
+ int * pcch,
+ LPCH lpchString
+ )
+{
+ int cb;
+
+ cb = strlen(lpchString);
+ if (cb + 1 > *pcch) {
+ cb = *pcch - 1;
+ }
+ strncpy(*lplpchBuf, lpchString, cb);
+ *lplpchBuf += cb;
+ *pcch -= cb;
+ **lplpchBuf = 0;
+ return;
+} /* OutputIString() */
diff --git a/private/windbg/em/p_i386/d3.h b/private/windbg/em/p_i386/d3.h
new file mode 100644
index 000000000..984bb3e4b
--- /dev/null
+++ b/private/windbg/em/p_i386/d3.h
@@ -0,0 +1,1287 @@
+/********************************** module *********************************/
+/* */
+/* d3.h */
+/* disassembler tables for CodeView's disassembler */
+/* */
+/***************************************************************************/
+/* */
+/* @ Purpose: */
+/* */
+/* @ Functions included: */
+/* */
+/* Revision History: */
+/* */
+/* [03] 31-dec-91 DavidGra */
+/* */
+/* Correctly handle rep/lock prefices. */
+/* */
+/* [02] 15-nov-91 DavidGra */
+/* */
+/* Fix cmpxchg - these are extended opcodes B0 & B1 instead */
+/* of A6 & A7 as the intel documentation claims. */
+/* */
+/* [01] 15-nov-91 DavidGra */
+/* */
+/* Make the 8c form of MOV output WORD PTR [] */
+/* */
+/* [00] 15-nov-91 DavidGra */
+/* */
+/* Added support to correctly handle MOV[S|Z]X */
+/* */
+/* @ Author: Gerd Immeyer @ Version: */
+/* */
+/* @ Creation Date: 10.19.89 @ Modification Date: */
+/* */
+/***************************************************************************/
+
+#ifdef HOST32
+typedef unsigned char CBC;
+#else
+typedef unsigned char _based(_segname("_CODE")) CBC;
+#endif
+
+/* Strings: Operand mnemonics, Segment overrides, etc. for disasm */
+
+CBC dszAAA[] = "aaa";
+CBC dszAAD[] = "aad";
+CBC dszAAM[] = "aam";
+CBC dszAAS[] = "aas";
+CBC dszADC[] = "adc";
+CBC dszADD[] = "add";
+CBC dszADDRPRFX[] = "";
+CBC dszAND[] = "and";
+CBC dszARPL[] = "arpl";
+CBC dszBOP[] = "bop";
+CBC dszBOUND[] = "bound";
+CBC dszBSF[] = "bsf";
+CBC dszBSR[] = "bsr";
+#if 0
+CBC dszBST[] = "bst";
+#endif
+CBC dszBSWAP[] = "bswap";
+CBC dszBT[] = "bt";
+CBC dszBTC[] = "btc";
+CBC dszBTR[] = "btr";
+CBC dszBTS[] = "bts";
+CBC dszCALL[] = "call";
+CBC dszCBW[] = "cbw";
+#if 0
+CBC dszCDQ[] = "cdq";
+#endif
+CBC dszCLC[] = "clc";
+CBC dszCLD[] = "cld";
+CBC dszCLI[] = "cli";
+CBC dszCLTS[] = "clts";
+CBC dszCMC[] = "cmc";
+CBC dszCMP[] = "cmp";
+#if 0
+CBC dszCMPS[] = "cmps";
+#endif
+CBC dszCMPSB[] = "cmpsb";
+#if 0
+CBC dszCMPSD[] = "cmpsd";
+#endif
+CBC dszCMPSW[] = "cmpsw";
+CBC dszCMPXCHG[] = "cmpxchg";
+CBC dszCS_[] = "cs:";
+CBC dszCWD[] = "cwd";
+CBC dszCWDE[] = "cwde";
+CBC dszDAA[] = "daa";
+CBC dszDAS[] = "das";
+CBC dszDEC[] = "dec";
+CBC dszDIV[] = "div";
+CBC dszDS_[] = "ds:";
+CBC dszENTER[] = "enter";
+CBC dszES_[] = "es:";
+CBC dszF2XM1[] = "f2xm1";
+CBC dszFABS[] = "fabs";
+CBC dszFADD[] = "fadd";
+CBC dszFADDP[] = "faddp";
+CBC dszFBLD[] = "fbld";
+CBC dszFBSTP[] = "fbstp";
+CBC dszFCHS[] = "fchs";
+#if 0
+CBC dszFCLEX[] = "fclex";
+#endif
+CBC dszFCOM[] = "fcom";
+CBC dszFCOMP[] = "fcomp";
+CBC dszFCOMPP[] = "fcompp";
+CBC dszFCOS[] = "fcos";
+CBC dszFDECSTP[] = "fdecstp";
+CBC dszFDISI[] = "fdisi";
+CBC dszFDIV[] = "fdiv";
+CBC dszFDIVP[] = "fdivp";
+CBC dszFDIVR[] = "fdivr";
+CBC dszFDIVRP[] = "fdivrp";
+CBC dszFENI[] = "feni";
+CBC dszFFREE[] = "ffree";
+CBC dszFIADD[] = "fiadd";
+CBC dszFICOM[] = "ficom";
+CBC dszFICOMP[] = "ficomp";
+CBC dszFIDIV[] = "fidiv";
+CBC dszFIDIVR[] = "fidivr";
+CBC dszFILD[] = "fild";
+CBC dszFIMUL[] = "fimul";
+CBC dszFINCSTP[] = "fincstp";
+#if 0
+CBC dszFINIT[] = "finit";
+#endif
+CBC dszFIST[] = "fist";
+CBC dszFISTP[] = "fistp";
+CBC dszFISUB[] = "fisub";
+CBC dszFISUBR[] = "fisubr";
+CBC dszFLD[] = "fld";
+CBC dszFLD1[] = "fld1";
+CBC dszFLDCW[] = "fldcw";
+CBC dszFLDENV[] = "fldenv";
+CBC dszFLDL2E[] = "fldl2e";
+CBC dszFLDL2T[] = "fldl2t";
+CBC dszFLDLG2[] = "fldlg2";
+CBC dszFLDLN2[] = "fldln2";
+CBC dszFLDPI[] = "fldpi";
+CBC dszFLDZ[] = "fldz";
+CBC dszFMUL[] = "fmul";
+CBC dszFMULP[] = "fmulp";
+CBC dszFNCLEX[] = "fnclex";
+#if 0
+CBC dszFNDISI[] = "fndisi";
+CBC dszFNENI[] = "fneni";
+#endif
+CBC dszFNINIT[] = "fninit";
+CBC dszFNOP[] = "fnop";
+CBC dszFNSAVE[] = "fnsave";
+CBC dszFNSTCW[] = "fnstcw";
+CBC dszFNSTENV[] = "fnstenv";
+CBC dszFNSTSW[] = "fnstsw";
+CBC dszFPATAN[] = "fpatan";
+CBC dszFPREM[] = "fprem";
+CBC dszFPREM1[] = "fprem1";
+CBC dszFPTAN[] = "fptan";
+CBC dszFRNDINT[] = "frndint";
+CBC dszFRSTOR[] = "frstor";
+#if 0
+CBC dszFSAVE[] = "fsave";
+#endif
+CBC dszFSCALE[] = "fscale";
+CBC dszFSETPM[] = "fsetpm";
+CBC dszFSIN[] = "fsin";
+CBC dszFSINCOS[] = "fsincos";
+CBC dszFSQRT[] = "fsqrt";
+CBC dszFST[] = "fst";
+#if 0
+CBC dszFSTCW[] = "fstcw";
+CBC dszFSTENV[] = "fstenv";
+#endif
+CBC dszFSTP[] = "fstp";
+#if 0
+CBC dszFSTSW[] = "fstsw";
+#endif
+CBC dszFSUB[] = "fsub";
+CBC dszFSUBP[] = "fsubp";
+CBC dszFSUBR[] = "fsubr";
+CBC dszFSUBRP[] = "fsubrp";
+CBC dszFS_[] = "fs:";
+CBC dszFTST[] = "ftst";
+CBC dszFUCOM[] = "fucom";
+CBC dszFUCOMP[] = "fucomp";
+CBC dszFUCOMPP[] = "fucompp";
+CBC dszFWAIT[] = "fwait";
+CBC dszFXAM[] = "fxam";
+CBC dszFXCH[] = "fxch";
+CBC dszFXTRACT[] = "fxtract";
+CBC dszFYL2X[] = "fyl2x";
+CBC dszFYL2XP1[] = "fyl2xp1";
+CBC dszGS_[] = "gs:";
+CBC dszHLT[] = "hlt";
+#if 0
+CBC dszIBTS[] = "ibts";
+#endif
+CBC dszIDIV[] = "idiv";
+CBC dszIMUL[] = "imul";
+CBC dszIN[] = "in";
+CBC dszINC[] = "inc";
+#if 0
+CBC dszINS[] = "ins";
+#endif
+CBC dszINSB[] = "insb";
+#if 0
+CBC dszINSD[] = "insd";
+#endif
+CBC dszINSW[] = "insw";
+CBC dszINT[] = "int";
+CBC dszINTO[] = "into";
+CBC dszINVD[] = "invd";
+CBC dszINVLPG[] = "invlpg";
+CBC dszIRET[] = "iret";
+#if 0
+CBC dszIRETD[] = "iretd";
+#endif
+CBC dszJA[] = "ja";
+CBC dszJAE[] = "jae";
+CBC dszJB[] = "jb";
+CBC dszJBE[] = "jbe";
+CBC dszJCXZ[] = "jcxz";
+CBC dszJE[] = "je";
+CBC dszJECXZ[] = "jecxz";
+CBC dszJG[] = "jg";
+CBC dszJGE[] = "jge";
+CBC dszJL[] = "jl";
+CBC dszJLE[] = "jle";
+CBC dszJMP[] = "jmp";
+CBC dszJNE[] = "jne";
+CBC dszJNO[] = "jno";
+CBC dszJNP[] = "jnp";
+CBC dszJNS[] = "jns";
+CBC dszJO[] = "jo";
+CBC dszJP[] = "jp";
+CBC dszJS[] = "js";
+CBC dszLAHF[] = "lahf";
+CBC dszLAR[] = "lar";
+CBC dszLDS[] = "lds";
+CBC dszLEA[] = "lea";
+CBC dszLEAVE[] = "leave";
+CBC dszLES[] = "les";
+CBC dszLFS[] = "lfs";
+CBC dszLGDT[] = "lgdt";
+CBC dszLGS[] = "lgs";
+CBC dszLIDT[] = "lidt";
+CBC dszLLDT[] = "lldt";
+CBC dszLMSW[] = "lmsw";
+CBC dszLOADALL[] = "loadall";
+CBC dszLOCK[] = "lock";
+#if 0
+CBC dszLODS[] = "lods";
+#endif
+CBC dszLODSB[] = "lodsb";
+#if 0
+CBC dszLODSD[] = "lodsd";
+#endif
+CBC dszLODSW[] = "lodsw";
+CBC dszLOOP[] = "loop";
+CBC dszLOOPE[] = "loope";
+CBC dszLOOPNE[] = "loopne";
+#if 0
+CBC dszLOOPNZ[] = "loopnz";
+CBC dszLOOPZ[] = "loopz";
+#endif
+CBC dszLSL[] = "lsl";
+CBC dszLSS[] = "lss";
+CBC dszLTR[] = "ltr";
+CBC dszMOV[] = "mov";
+#if 0
+CBC dszMOVS[] = "movs";
+#endif
+CBC dszMOVSB[] = "movsb";
+#if 0
+CBC dszMOVSD[] = "movsd";
+#endif
+CBC dszMOVSW[] = "movsw";
+CBC dszMOVSX[] = "movsx";
+CBC dszMOVZX[] = "movzx";
+CBC dszMUL[] = "mul";
+CBC dszMULTI[] = "";
+CBC dszNEG[] = "neg";
+CBC dszNOP[] = "nop";
+CBC dszNOT[] = "not";
+CBC dszOPPRFX[] = "";
+CBC dszOR[] = "or";
+CBC dszOUT[] = "out";
+#if 0
+CBC dszOUTS[] = "outs";
+#endif
+CBC dszOUTSB[] = "outsb";
+#if 0
+CBC dszOUTSD[] = "outsd";
+#endif
+CBC dszOUTSW[] = "outsw";
+CBC dszPOP[] = "pop";
+CBC dszPOPA[] = "popa";
+#if 0
+CBC dszPOPAD[] = "popad";
+#endif
+CBC dszPOPF[] = "popf";
+#if 0
+CBC dszPOPFD[] = "popfd";
+#endif
+CBC dszPUSH[] = "push";
+CBC dszPUSHA[] = "pusha";
+#if 0
+CBC dszPUSHAD[] = "pushad";
+#endif
+CBC dszPUSHF[] = "pushf";
+#if 0
+CBC dszPUSHFD[] = "pushfd";
+#endif
+CBC dszRCL[] = "rcl";
+CBC dszRCR[] = "rcr";
+CBC dszREP[] = "rep";
+#if 0
+CBC dszREPE[] = "repe";
+#endif
+CBC dszREPNE[] = "repne";
+#if 0
+CBC dszREPNZ[] = "repnz";
+CBC dszREPZ[] = "repz";
+CBC dszRET[] = "ret";
+#endif
+CBC dszRETF[] = "retf";
+CBC dszRETN[] = "retn";
+CBC dszROL[] = "rol";
+CBC dszROR[] = "ror";
+CBC dszSAHF[] = "sahf";
+CBC dszSAL[] = "sal";
+CBC dszSAR[] = "sar";
+CBC dszSBB[] = "sbb";
+#if 0
+CBC dszSCAS[] = "scas";
+#endif
+CBC dszSCASB[] = "scasb";
+#if 0
+CBC dszSCASD[] = "scasd";
+#endif
+CBC dszSCASW[] = "scasw";
+CBC dszSETA[] = "seta";
+CBC dszSETAE[] = "setae";
+CBC dszSETB[] = "setb";
+CBC dszSETBE[] = "setbe";
+CBC dszSETE[] = "sete";
+CBC dszSETG[] = "setg";
+CBC dszSETGE[] = "setge";
+CBC dszSETL[] = "setl";
+CBC dszSETLE[] = "setle";
+#if 0
+CBC dszSETNAE[] = "setnae";
+#endif
+CBC dszSETNE[] = "setne";
+CBC dszSETNO[] = "setno";
+CBC dszSETNP[] = "setnp";
+CBC dszSETNS[] = "setns";
+CBC dszSETO[] = "seto";
+CBC dszSETP[] = "setp";
+CBC dszSETS[] = "sets";
+CBC dszSGDT[] = "sgdt";
+CBC dszSHL[] = "shl";
+CBC dszSHLD[] = "shld";
+CBC dszSHR[] = "shr";
+CBC dszSHRD[] = "shrd";
+CBC dszSIDT[] = "sidt";
+CBC dszSLDT[] = "sldt";
+CBC dszSMSW[] = "smsw";
+CBC dszSS_[] = "ss:";
+CBC dszSTC[] = "stc";
+CBC dszSTD[] = "std";
+CBC dszSTI[] = "sti";
+#if 0
+CBC dszSTOS[] = "stos";
+#endif
+CBC dszSTOSB[] = "stosb";
+#if 0
+CBC dszSTOSD[] = "stosd";
+#endif
+CBC dszSTOSW[] = "stosw";
+CBC dszSTR[] = "str";
+CBC dszSUB[] = "sub";
+CBC dszTEST[] = "test";
+CBC dszVERR[] = "verr";
+CBC dszVERW[] = "verw";
+CBC dszWAIT[] = "wait";
+CBC dszWBINVD[] = "wbinvd";
+CBC dszXADD[] = "xadd";
+#if 0
+CBC dszXBTS[] = "xbts";
+#endif
+CBC dszXCHG[] = "xchg";
+CBC dszXLAT[] = "xlat";
+CBC dszXOR[] = "xor";
+CBC dszRESERVED[] = "???";
+#if 0
+CBC dszDB[] = "db";
+#endif // 0
+
+
+#define MRM 0x40 /* (1 << 3) */
+#define COM 0x80 /* (2 << 3) */
+#define END 0xc0 /* (3 << 3) */
+
+/* Enumeration of valid actions that can be included in the action table */
+
+enum oprtyp {
+ ADDRP, ADR_OVR, ALSTR, ALT, /* 00-03 */
+ AXSTR, BOREG, BREG, BRSTR, /* 04-07 */
+ BYT, CHR, CREG, DWRD, /* 08-0b */
+ EDWRD, EGROUPT, FARPTR, GROUP, /* 0c-0f */
+ GROUPT, IB, IST, IST_ST, /* 10-13 */
+ IV, IW, LMODRM, MODRM, /* 14-17 */
+ NOP, OFFS, OPC0F, OPR_OVR, /* 18-1b */
+ QWRD, REL16, REL8, REP, /* 1c-1f */
+ SEG_OVR, SREG2, SREG3, ST_IST, /* 20-23 */
+ STROP, TBYT, UBYT, VAR, /* 24-27 */
+ VOREG, VREG, EWRD, WRD, /* 28-2b */
+ WREG, DREG, WRSTR, OPR16, /* 2c-2f */
+ FWRD, BOP /* 30-33 */
+};
+
+/* Enumeration of indices into the action table for instruction classes */
+
+#define O_DoDB 0
+#define O_NoOperands 0
+#define O_NoOpAlt4 O_NoOperands+1
+#define O_NoOpAlt3 O_NoOpAlt4+2
+#define O_NoOpAlt2 O_NoOpAlt3+2
+#define O_NoOpAlt1 O_NoOpAlt2+2
+#define O_NoOpAlt0 O_NoOpAlt1+2
+#define O_NoOpStrSI O_NoOpAlt0+2
+#define O_NoOpStrDI O_NoOpStrSI+2
+#define O_NoOpStrSIDI O_NoOpStrDI+2
+#define O_bModrm_Reg O_NoOpStrSIDI+2
+#define O_vModrm_Reg O_bModrm_Reg+3
+#define O_Modrm_Reg O_vModrm_Reg+3
+#define O_bReg_Modrm O_Modrm_Reg+3
+#define O_fReg_Modrm O_bReg_Modrm+3
+#define O_Reg_Modrm O_fReg_Modrm+3
+#define O_AL_Ib O_Reg_Modrm+3
+#define O_AX_Iv O_AL_Ib+2
+#define O_sReg2 O_AX_Iv+2
+#define O_oReg O_sReg2+1
+#define O_DoBound O_oReg+1
+#define O_Iv O_DoBound+3
+#define O_wModrm_Reg O_Iv+1
+#define O_Ib O_wModrm_Reg+3
+#define O_Imulb O_Ib+1
+#define O_Imul O_Imulb+4
+#define O_Rel8 O_Imul+4
+#define O_bModrm_Ib O_Rel8+1
+#define O_Modrm_Ib O_bModrm_Ib+3
+#define O_Modrm_Iv O_Modrm_Ib+3
+#define O_Modrm_sReg3 O_Modrm_Iv+3
+#define O_sReg3_Modrm O_Modrm_sReg3+4
+#define O_Modrm O_sReg3_Modrm+4
+#define O_FarPtr O_Modrm+2
+#define O_AL_Offs O_FarPtr+1
+#define O_Offs_AL O_AL_Offs+2
+#define O_AX_Offs O_Offs_AL+2
+#define O_Offs_AX O_AX_Offs+2
+#define O_oReg_Ib O_Offs_AX+2
+#define O_oReg_Iv O_oReg_Ib+2
+#define O_Iw O_oReg_Iv+2
+#define O_Enter O_Iw+1
+#define O_Ubyte_AL O_Enter+2
+#define O_Ubyte_AX O_Ubyte_AL+2
+#define O_AL_Ubyte O_Ubyte_AX+2
+#define O_AX_Ubyte O_AL_Ubyte+2
+#define O_DoInAL O_AX_Ubyte+2
+#define O_DoInAX O_DoInAL+3
+#define O_DoOutAL O_DoInAX+3
+#define O_DoOutAX O_DoOutAL+3
+#define O_Rel16 O_DoOutAX+3
+#define O_ADR_OVERRIDE O_Rel16+1
+#define O_OPR_OVERRIDE O_ADR_OVERRIDE+1
+#define O_SEG_OVERRIDE O_OPR_OVERRIDE+1
+#define O_DoInt3 O_SEG_OVERRIDE+1
+
+#if (O_DoInt3 != 117)
+#error "operand table has been modified!"
+#endif
+/* #define O_DoInt O_DoInt3+2 */
+
+#define O_DoInt 119
+#define O_OPC0F O_DoInt+1
+#define O_GROUP11 O_OPC0F+1
+#define O_GROUP13 O_GROUP11+5
+#define O_GROUP12 O_GROUP13+5
+#define O_GROUP21 O_GROUP12+5
+#define O_GROUP22 O_GROUP21+5
+#define O_GROUP23 O_GROUP22+5
+#define O_GROUP24 O_GROUP23+6
+#define O_GROUP25 O_GROUP24+6
+#define O_GROUP26 O_GROUP25+6
+#define O_GROUP4 O_GROUP26+6
+#define O_GROUP6 O_GROUP4+4
+#define O_GROUP8 O_GROUP6+4
+#define O_GROUP31 O_GROUP8+5
+#define O_GROUP32 O_GROUP31+3
+#define O_GROUP5 O_GROUP32+3
+#define O_GROUP7 O_GROUP5+3
+#define O_x87_ESC O_GROUP7+3
+#define O_bModrm O_x87_ESC+2
+#define O_wModrm O_bModrm+2
+#define O_dModrm O_wModrm+2
+#define O_fModrm O_dModrm+2
+#define O_vModrm O_fModrm+2
+#define O_vModrm_Iv O_vModrm+2
+#define O_Reg_bModrm O_vModrm_Iv+3
+#define O_Reg_wModrm O_Reg_bModrm+3
+#define O_Modrm_Reg_Ib O_Reg_wModrm+3
+#define O_Modrm_Reg_CL O_Modrm_Reg_Ib+4
+#define O_ST_iST O_Modrm_Reg_CL+5
+#define O_iST O_ST_iST+2
+#define O_iST_ST O_iST+2
+#define O_qModrm O_iST_ST+2
+#define O_tModrm O_qModrm+2
+#define O_DoRep O_tModrm+2
+#define O_Modrm_CReg O_DoRep+1
+#define O_CReg_Modrm O_Modrm_CReg+3
+#define O_AX_oReg O_CReg_Modrm+3
+#define O_fw_Modrm O_AX_oReg+2
+#define O_AX O_fw_Modrm+2
+#define O_BOP O_AX+2
+#define O_length O_BOP+2
+
+#if( O_length > 255 )
+#error "operand table too large!"
+#endif
+
+
+/* The action table: range of lists of actions to be taken for each */
+/* possible instruction class. */
+
+static CBC actiontbl[] = {
+/* NoOperands */ (CBC) (NOP+END),
+/* NoOpAlt4 */ (CBC) (ALT+END), (CBC) (4),
+/* NoOpAlt3 */ (CBC) (ALT+END), (CBC) (3),
+/* NoOpAlt2 */ (CBC) (ALT+END), (CBC) (2),
+/* NoOpAlt1 */ (CBC) (ALT+END), (CBC) (1),
+/* NoOpAlt0 */ (CBC) (ALT+END), (CBC) (0),
+/* NoOpStrSI */ (CBC) (STROP+END),(CBC) (1),
+/* NoOpStrDI */ (CBC) (STROP+END),(CBC) (2),
+/* NoOpStrSIDI */ (CBC) (STROP+END),(CBC) (3),
+/* bModrm_Reg */ (CBC) (BYT+MRM), (CBC) (LMODRM+COM),(CBC) (BREG+END),
+/* vModrm_Reg */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM),(CBC) (VREG+END),
+/* Modrm_Reg */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM),(CBC) (VREG+END),
+/* bReg_Modrm */ (CBC) (BYT+MRM), (CBC) (BREG+COM), (CBC) (LMODRM+END),
+/* fReg_Modrm */ (CBC) (FARPTR+MRM),(CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* Reg_Modrm */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* AL_Ib */ (CBC) (ALSTR+COM),(CBC) (IB+END),
+/* AX_Iv */ (CBC) (AXSTR+COM),(CBC) (IV+END),
+/* sReg2 */ (CBC) (SREG2+END),
+/* oReg */ (CBC) (VOREG+END),
+/* DoBound */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+END),
+/* Iv */ (CBC) (IV+END),
+/* wModrm_Reg */ (CBC) (WRD+MRM), (CBC) (LMODRM+COM),(CBC) (WREG+END),
+/* Ib */ (CBC) (IB+END),
+/* Imulb */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* Imul */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+COM),(CBC) (IV+END),
+/* REL8 */ (CBC) (REL8+END),
+/* bModrm_Ib */ (CBC) (BYT+MRM), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* Modrm_Ib */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* Modrm_Iv */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM),(CBC) (IV+END),
+/* Modrm_sReg3 */ OPR16, (CBC) (WRD+MRM), (CBC) (LMODRM+COM), (CBC) (SREG3+END),
+/* sReg3_Modrm */ OPR16, (CBC) (WRD+MRM), (CBC) (SREG3+COM), (CBC) (LMODRM+END),
+/* Modrm */ (CBC) (VAR+MRM), (CBC) (LMODRM+END),
+/* FarPtr */ (CBC) (ADDRP+END),
+/* AL_Offs */ (CBC) (ALSTR+COM),(CBC) (OFFS+END),
+/* Offs_AL */ (CBC) (OFFS+COM), (CBC) (ALSTR+END),
+/* AX_Offs */ (CBC) (AXSTR+COM),(CBC) (OFFS+END),
+/* Offs_AX */ (CBC) (OFFS+COM), (CBC) (AXSTR+END),
+/* oReg_Ib */ (CBC) (BOREG+COM),(CBC) (IB+END),
+/* oReg_Iv */ (CBC) (VOREG+COM),(CBC) (IV+END),
+/* Iw */ (CBC) (IW+END),
+/* enter */ (CBC) (IW+COM), (CBC) (IB+END),
+/* Ubyte_AL */ (CBC) (UBYT+COM), (CBC) (ALSTR+END),
+/* Ubyte_AX */ (CBC) (UBYT+COM), (CBC) (AXSTR+END),
+/* AL_Ubyte */ (CBC) (ALSTR+COM),(CBC) (UBYT+END),
+/* AX_Ubyte */ (CBC) (AXSTR+COM),(CBC) (UBYT+END),
+/* DoInAL */ (CBC) (ALSTR+COM),(CBC) (WRSTR+END), (CBC) (2),
+/* DoInAX */ (CBC) (AXSTR+COM),(CBC) (WRSTR+END), (CBC) (2),
+/* DoOutAL */ (CBC) (WRSTR+COM),(CBC) (2), (CBC) (ALSTR+END),
+/* DoOutAX */ (CBC) (WRSTR+COM),(CBC) (2), (CBC) (AXSTR+END),
+/* REL16 */ (CBC) (REL16+END),
+/* ADR_OVERRIDE*/ (CBC) (ADR_OVR),
+/* OPR_OVERRIDE*/ (CBC) (OPR_OVR),
+/* SEG_OVERRIDE*/ (CBC) (SEG_OVR),
+/* DoInt3 */ (CBC) (CHR+END), (CBC) ('3'),
+/* DoInt */ (CBC) (UBYT+END),
+/* Opcode0F */ (CBC) (OPC0F),
+/* group1_1 */ (CBC) (BYT+MRM), (CBC) (GROUP), (CBC) (0), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* group1_3 */ (CBC) (VAR+MRM), (CBC) (GROUP), (CBC) (0), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* group1_2 */ (CBC) (VAR+MRM), (CBC) (GROUP), (CBC) (0), (CBC) (LMODRM+COM),(CBC) (IV+END),
+/* group2_1 */ (CBC) (BYT+MRM), (CBC) (GROUP), (CBC) (1), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* group2_2 */ (CBC) (VAR+MRM), (CBC) (GROUP), (CBC) (1), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* group2_3 */ (CBC) (BYT+MRM), (CBC) (GROUP), (CBC) (1), (CBC) (LMODRM+COM),(CBC) (CHR+END), (CBC) ('1'),
+/* group2_4 */ (CBC) (VAR+MRM), (CBC) (GROUP), (CBC) (1), (CBC) (LMODRM+COM),(CBC) (CHR+END), (CBC) ('1'),
+/* group2_5 */ (CBC) (BYT+MRM), (CBC) (GROUP), (CBC) (1), (CBC) (LMODRM+COM),(CBC) (BRSTR+END),(CBC) (1),
+/* group2_6 */ (CBC) (VAR+MRM), (CBC) (GROUP), (CBC) (1), (CBC) (LMODRM+COM),(CBC) (BRSTR+END),(CBC) (1),
+/* group4 */ (CBC) (BYT+MRM), (CBC) (GROUP), (CBC) (2), (CBC) (LMODRM+END),
+/* group6 */ (CBC) (WRD+MRM), (CBC) (GROUP), (CBC) (3), (CBC) (LMODRM+END),
+/* group8 */ (CBC) (VAR+MRM), (CBC) (GROUP), (CBC) (4), (CBC) (LMODRM+COM),(CBC) (IB+END),
+/* group3_1 */ (CBC) (BYT), (CBC) (GROUPT),(CBC) (20),
+/* group3_2 */ (CBC) (VAR), (CBC) (GROUPT),(CBC) (21),
+/* group5 */ (CBC) (VAR), (CBC) (GROUPT),(CBC) (22), // ????
+/* group7 */ (CBC) (NOP), (CBC) (GROUPT),(CBC) (23),
+/* x87_ESC */ (CBC) (NOP+MRM), (CBC) (EGROUPT),
+/* bModrm */ (CBC) (BYT+MRM), (CBC) (LMODRM+END),
+/* wModrm */ (CBC) (WRD+MRM), (CBC) (LMODRM+END),
+/* dModrm */ (CBC) (DWRD+MRM), (CBC) (LMODRM+END),
+/* fModrm */ (CBC) (FARPTR+MRM),(CBC) (LMODRM+END),
+/* vModrm */ (CBC) (VAR+MRM), (CBC) (LMODRM+END),
+/* vModrm_Iv */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM),(CBC) (IV+END),
+/* reg_bModrm */ (CBC) (BYT+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* reg_wModrm */ (CBC) (EWRD+MRM), (CBC) (DREG+COM), (CBC) (LMODRM+END), // [00]
+/* Modrm_Reg_Ib*/ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+COM), (CBC) (IB+END),
+/* Modrm_Reg_CL*/ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+COM), (CBC) (BRSTR+END),(CBC) (1),
+/* ST_iST */ (CBC) (NOP+MRM), (CBC) (ST_IST+END),
+/* iST */ (CBC) (NOP+MRM), (CBC) (IST+END),
+/* iST_ST */ (CBC) (NOP+MRM), (CBC) (IST_ST+END),
+/* qModrm */ (CBC) (QWRD+MRM), (CBC) (LMODRM+END),
+/* tModrm */ (CBC) (TBYT+MRM), (CBC) (LMODRM+END),
+/* REP */ (CBC) (REP),
+/* Modrm_CReg */ (CBC) (EDWRD+MRM),(CBC) (MODRM+COM), (CBC) (CREG+END),
+/* CReg_Modrm */ (CBC) (EDWRD+MRM),(CBC) (CREG+COM), (CBC) (MODRM+END),
+/* AX_oReg */ (CBC) (AXSTR+COM), (CBC) (VOREG+END),
+/* fw_Modrm */ (CBC) (FWRD+MRM), (CBC) (LMODRM+END),
+/* AX */ (CBC) (OPR16), (CBC) (AXSTR+END),
+/* BOP */ (CBC) (BOP), (CBC) (UBYT+END)
+};
+#ifdef HOST_i386
+#pragma pack(1)
+#endif
+
+typedef struct Tdistbl{
+ CBC *instruct;
+ unsigned char opr;
+ } Tdistbl;
+
+/* List of ordered pairs for each instruction: */
+/* (pointer to string literal mnemonic, */
+/* instruction class index for action table) */
+
+static Tdistbl distbl[] = {
+ dszADD, O_bModrm_Reg, /* 00 ADD mem/reg, reg (byte) */
+ dszADD, O_Modrm_Reg, /* 01 ADD mem/reg, reg (var) */
+ dszADD, O_bReg_Modrm, /* 02 ADD reg, mem/reg (byte) */
+ dszADD, O_Reg_Modrm, /* 03 ADD reg, mem/reg (var) */
+ dszADD, O_AL_Ib, /* 04 ADD AL, I */
+ dszADD, O_AX_Iv, /* 05 ADD AX, I */
+ dszPUSH, O_sReg2, /* 06 PUSH ES */
+ dszPOP, O_sReg2, /* 07 POP ES */
+ dszOR, O_bModrm_Reg, /* 08 OR mem/reg, reg (byte) */
+ dszOR, O_Modrm_Reg, /* 09 OR mem/reg, reg (word) */
+ dszOR, O_bReg_Modrm, /* 0A OR reg, mem/reg (byte) */
+ dszOR, O_Reg_Modrm, /* 0B OR reg, mem/reg (word) */
+ dszOR, O_AL_Ib, /* 0C OR AL, I */
+ dszOR, O_AX_Iv, /* 0D OR AX, I */
+ dszPUSH, O_sReg2, /* 0E PUSH CS */
+ dszMULTI, O_OPC0F, /* 0F CLTS & protection ctl(286) */
+ dszADC, O_bModrm_Reg, /* 10 ADC mem/reg, reg (byte) */
+ dszADC, O_Modrm_Reg, /* 11 ADC mem/reg, reg (word) */
+ dszADC, O_bReg_Modrm, /* 12 ADC reg, mem/reg (byte) */
+ dszADC, O_Reg_Modrm, /* 13 ADC reg, mem/reg (word) */
+ dszADC, O_AL_Ib, /* 14 ADC AL, I */
+ dszADC, O_AX_Iv, /* 15 ADC AX, I */
+ dszPUSH, O_sReg2, /* 16 PUSH SS */
+ dszPOP, O_sReg2, /* 17 POP SS */
+ dszSBB, O_bModrm_Reg, /* 18 SBB mem/reg, reg (byte) */
+ dszSBB, O_Modrm_Reg, /* 19 SBB mem/reg, reg (word) */
+ dszSBB, O_bReg_Modrm, /* 1A SBB reg, mem/reg (byte) */
+ dszSBB, O_Reg_Modrm, /* 1B SBB reg, mem/reg (word) */
+ dszSBB, O_AL_Ib, /* 1C SBB AL, I */
+ dszSBB, O_AX_Iv, /* 1D SBB AX, I */
+ dszPUSH, O_sReg2, /* 1E PUSH DS */
+ dszPOP, O_sReg2, /* 1F POP DS */
+ dszAND, O_bModrm_Reg, /* 20 AND mem/reg, reg (byte) */
+ dszAND, O_Modrm_Reg, /* 21 AND mem/reg, reg (word) */
+ dszAND, O_bReg_Modrm, /* 22 AND reg, mem/reg (byte) */
+ dszAND, O_Reg_Modrm, /* 23 AND reg, mem/reg (word) */
+ dszAND, O_AL_Ib, /* 24 AND AL, I */
+ dszAND, O_AX_Iv, /* 25 AND AX, I */
+ dszES_, O_SEG_OVERRIDE, /* 26 SEG ES: */
+ dszDAA, O_NoOperands, /* 27 DAA */
+ dszSUB, O_bModrm_Reg, /* 28 SUB mem/reg, reg (byte) */
+ dszSUB, O_Modrm_Reg, /* 29 SUB mem/reg, reg (word) */
+ dszSUB, O_bReg_Modrm, /* 2A SUB reg, mem/reg (byte) */
+ dszSUB, O_Reg_Modrm, /* 2B SUB reg, mem/reg (word) */
+ dszSUB, O_AL_Ib, /* 2C SUB AL, I */
+ dszSUB, O_AX_Iv, /* 2D SUB AX, I */
+ dszCS_, O_SEG_OVERRIDE, /* 2E SEG CS: */
+ dszDAS, O_NoOperands, /* 2F DAS */
+ dszXOR, O_bModrm_Reg, /* 30 XOR mem/reg, reg (byte) */
+ dszXOR, O_Modrm_Reg, /* 31 XOR mem/reg, reg (word) */
+ dszXOR, O_bReg_Modrm, /* 32 XOR reg, mem/reg (byte) */
+ dszXOR, O_Reg_Modrm, /* 33 XOR reg, mem/reg (word) */
+ dszXOR, O_AL_Ib, /* 34 XOR AL, I */
+ dszXOR, O_AX_Iv, /* 35 XOR AX, I */
+ dszSS_, O_SEG_OVERRIDE, /* 36 SEG SS: */
+ dszAAA, O_NoOperands, /* 37 AAA */
+ dszCMP, O_bModrm_Reg, /* 38 CMP mem/reg, reg (byte) */
+ dszCMP, O_Modrm_Reg, /* 39 CMP mem/reg, reg (word) */
+ dszCMP, O_bReg_Modrm, /* 3A CMP reg, mem/reg (byte) */
+ dszCMP, O_Reg_Modrm, /* 3B CMP reg, mem/reg (word) */
+ dszCMP, O_AL_Ib, /* 3C CMP AL, I */
+ dszCMP, O_AX_Iv, /* 3D CMP AX, I */
+ dszDS_, O_SEG_OVERRIDE, /* 3E SEG DS: */
+ dszAAS, O_NoOperands, /* 3F AAS */
+ dszINC, O_oReg, /* 40 INC AX */
+ dszINC, O_oReg, /* 41 INC CX */
+ dszINC, O_oReg, /* 42 INC DX */
+ dszINC, O_oReg, /* 43 INC BX */
+ dszINC, O_oReg, /* 44 INC SP */
+ dszINC, O_oReg, /* 45 INC BP */
+ dszINC, O_oReg, /* 46 INC SI */
+ dszINC, O_oReg, /* 47 INC DI */
+ dszDEC, O_oReg, /* 48 DEC AX */
+ dszDEC, O_oReg, /* 49 DEC CX */
+ dszDEC, O_oReg, /* 4A DEC DX */
+ dszDEC, O_oReg, /* 4B DEC BX */
+ dszDEC, O_oReg, /* 4C DEC SP */
+ dszDEC, O_oReg, /* 4D DEC BP */
+ dszDEC, O_oReg, /* 4E DEC SI */
+ dszDEC, O_oReg, /* 4F DEC DI */
+ dszPUSH, O_oReg, /* 50 PUSH AX */
+ dszPUSH, O_oReg, /* 51 PUSH CX */
+ dszPUSH, O_oReg, /* 52 PUSH DX */
+ dszPUSH, O_oReg, /* 53 PUSH BX */
+ dszPUSH, O_oReg, /* 54 PUSH SP */
+ dszPUSH, O_oReg, /* 55 PUSH BP */
+ dszPUSH, O_oReg, /* 56 PUSH SI */
+ dszPUSH, O_oReg, /* 57 PUSH DI */
+ dszPOP, O_oReg, /* 58 POP AX */
+ dszPOP, O_oReg, /* 59 POP CX */
+ dszPOP, O_oReg, /* 5A POP DX */
+ dszPOP, O_oReg, /* 5B POP BX */
+ dszPOP, O_oReg, /* 5C POP SP */
+ dszPOP, O_oReg, /* 5D POP BP */
+ dszPOP, O_oReg, /* 5E POP SI */
+ dszPOP, O_oReg, /* 5F POP DI */
+ dszPUSHA, O_NoOpAlt3, /* 60 PUSHA (286) / PUSHAD (386) */
+ dszPOPA, O_NoOpAlt3, /* 61 POPA (286) / POPAD (286) */
+ dszBOUND, O_DoBound, /* 62 BOUND reg, Modrm (286) */
+ dszARPL, O_Modrm_Reg, /* 63 ARPL Modrm, reg (286) */
+ dszFS_, O_SEG_OVERRIDE, /* 64 */
+ dszGS_, O_SEG_OVERRIDE, /* 65 */
+ dszOPPRFX,O_OPR_OVERRIDE, /* 66 */
+ dszADDRPRFX,O_ADR_OVERRIDE, /* 67 */
+ dszPUSH, O_Iv, /* 68 PUSH word (286) */
+ dszIMUL, O_Imul, /* 69 IMUL (286) */
+ dszPUSH, O_Ib, /* 6A PUSH byte (286) */
+ dszIMUL, O_Imulb, /* 6B IMUL (286) */
+ dszINSB, O_NoOperands, /* 6C INSB (286) */
+ dszINSW, O_NoOpAlt2, /* 6D INSW (286) / INSD (386) */
+ dszOUTSB, O_NoOperands, /* 6E OUTSB (286) */
+ dszOUTSW, O_NoOpAlt2, /* 6F OUTSW (286) / OUTSD (386) */
+ dszJO, O_Rel8, /* 70 JO */
+ dszJNO, O_Rel8, /* 71 JNO */
+ dszJB, O_Rel8, /* 72 JB or JNAE or JC */
+ dszJAE, O_Rel8, /* 73 JNB or JAE or JNC */
+ dszJE, O_Rel8, /* 74 JE or JZ */
+ dszJNE, O_Rel8, /* 75 JNE or JNZ */
+ dszJBE, O_Rel8, /* 76 JBE or JNA */
+ dszJA, O_Rel8, /* 77 JNBE or JA */
+ dszJS, O_Rel8, /* 78 JS */
+ dszJNS, O_Rel8, /* 79 JNS */
+ dszJP, O_Rel8, /* 7A JP or JPE */
+ dszJNP, O_Rel8, /* 7B JNP or JPO */
+ dszJL, O_Rel8, /* 7C JL or JNGE */
+ dszJGE, O_Rel8, /* 7D JNL or JGE */
+ dszJLE, O_Rel8, /* 7E JLE or JNG */
+ dszJG, O_Rel8, /* 7F JNLE or JG */
+ dszMULTI, O_GROUP11, /* 80 */
+ dszMULTI, O_GROUP12, /* 81 */
+ dszRESERVED, O_DoDB, /* 82 */
+ dszMULTI, O_GROUP13, /* 83 */
+ dszTEST, O_bModrm_Reg, /* 84 TEST reg, mem/reg (byte) */
+ dszTEST, O_Modrm_Reg, /* 85 TEST reg, mem/reg (word) */
+ dszXCHG, O_bModrm_Reg, /* 86 XCHG reg, mem/reg (byte) */
+ dszXCHG, O_Modrm_Reg, /* 87 XCHG reg, mem/reg (word) */
+ dszMOV, O_bModrm_Reg, /* 88 MOV mem/reg, reg (byte) */
+ dszMOV, O_Modrm_Reg, /* 89 MOV mem/reg, reg (word) */
+ dszMOV, O_bReg_Modrm, /* 8A MOV reg, mem/reg (byte) */
+ dszMOV, O_Reg_Modrm, /* 8B MOV reg, mem/reg (word) */
+ dszMOV, O_Modrm_sReg3, /* 8C MOV mem/reg, segreg */
+ dszLEA, O_Reg_Modrm, /* 8D LEA reg, mem */
+ dszMOV, O_sReg3_Modrm, /* 8E MOV segreg, mem/reg */
+ dszPOP, O_Modrm, /* 8F POP mem/reg */
+ dszNOP, O_NoOperands, /* 90 NOP */
+ dszXCHG, O_AX_oReg, /* 91 XCHG AX,CX */
+ dszXCHG, O_AX_oReg, /* 92 XCHG AX,DX */
+ dszXCHG, O_AX_oReg, /* 93 XCHG AX,BX */
+ dszXCHG, O_AX_oReg, /* 94 XCHG AX,SP */
+ dszXCHG, O_AX_oReg, /* 95 XCHG AX,BP */
+ dszXCHG, O_AX_oReg, /* 96 XCHG AX,SI */
+ dszXCHG, O_AX_oReg, /* 97 XCHG AX,DI */
+ dszCBW, O_NoOpAlt0, /* 98 CBW / CWDE (386) */
+ dszCWD, O_NoOpAlt1, /* 99 CWD / CDQ (386) */
+ dszCALL, O_FarPtr, /* 9A CALL seg:off */
+ dszWAIT, O_NoOperands, /* 9B WAIT */
+ dszPUSHF, O_NoOpAlt3, /* 9C PUSHF / PUSHFD (386) */
+ dszPOPF, O_NoOpAlt3, /* 9D POPF / POPFD (386) */
+ dszSAHF, O_NoOperands, /* 9E SAHF */
+ dszLAHF, O_NoOperands, /* 9F LAHF */
+ dszMOV, O_AL_Offs, /* A0 MOV AL, mem */
+ dszMOV, O_AX_Offs, /* A1 MOV AX, mem */
+ dszMOV, O_Offs_AL, /* A2 MOV mem, AL */
+ dszMOV, O_Offs_AX, /* A3 MOV mem, AX */
+ dszMOVSB, O_NoOpStrSIDI, /* A4 MOVSB */
+ dszMOVSW, O_NoOpStrSIDI, /* A5 MOVSW / MOVSD (386) */
+ dszCMPSB, O_NoOpStrSIDI, /* A6 CMPSB */
+ dszCMPSW, O_NoOpStrSIDI, /* A7 CMPSW / CMPSD (386) */
+ dszTEST, O_AL_Ib, /* A8 TEST AL, I */
+ dszTEST, O_AX_Iv, /* A9 TEST AX, I */
+ dszSTOSB, O_NoOpStrDI, /* AA STOSB */
+ dszSTOSW, O_NoOpStrDI, /* AB STOSW / STOSD (386) */
+ dszLODSB, O_NoOpStrSI, /* AC LODSB */
+ dszLODSW, O_NoOpStrSI, /* AD LODSW / LODSD (386) */
+ dszSCASB, O_NoOpStrDI, /* AE SCASB */
+ dszSCASW, O_NoOpStrDI, /* AF SCASW / SCASD (386) */
+ dszMOV, O_oReg_Ib, /* B0 MOV AL, I */
+ dszMOV, O_oReg_Ib, /* B1 MOV CL, I */
+ dszMOV, O_oReg_Ib, /* B2 MOV DL, I */
+ dszMOV, O_oReg_Ib, /* B3 MOV BL, I */
+ dszMOV, O_oReg_Ib, /* B4 MOV AH, I */
+ dszMOV, O_oReg_Ib, /* B5 MOV CH, I */
+ dszMOV, O_oReg_Ib, /* B6 MOV DH, I */
+ dszMOV, O_oReg_Ib, /* B7 MOV BH, I */
+ dszMOV, O_oReg_Iv, /* B8 MOV AX, I */
+ dszMOV, O_oReg_Iv, /* B9 MOV CX, I */
+ dszMOV, O_oReg_Iv, /* BA MOV DX, I */
+ dszMOV, O_oReg_Iv, /* BB MOV BX, I */
+ dszMOV, O_oReg_Iv, /* BC MOV SP, I */
+ dszMOV, O_oReg_Iv, /* BD MOV BP, I */
+ dszMOV, O_oReg_Iv, /* BE MOV SI, I */
+ dszMOV, O_oReg_Iv, /* BF MOV DI, I */
+ dszMULTI, O_GROUP21, /* C0 shifts & rotates (286) */
+ dszMULTI, O_GROUP22, /* C1 shifts & rotates (286) */
+ dszRETN, O_Iw, /* C2 RET Rel16 */
+ dszRETN, O_NoOperands, /* C3 RET */
+ dszLES, O_BOP, /* C4 LES reg, mem */
+ dszLDS, O_fReg_Modrm, /* C5 LDS reg, mem */
+ dszMOV, O_bModrm_Ib, /* C6 MOV mem/reg, I(byte) */
+ dszMOV, O_Modrm_Iv, /* C7 MOV mem/reg, I(word) */
+ dszENTER, O_Enter, /* C8 ENTER (286) */
+ dszLEAVE, O_NoOperands, /* C9 LEAVE (286) */
+ dszRETF, O_Iw, /* CA RETF I(word) */
+ dszRETF, O_NoOperands, /* CB RETF */
+ dszINT, O_DoInt3, /* CC INT 3 */
+ dszINT, O_DoInt, /* CD INT */
+ dszINTO, O_NoOperands, /* CE INTO */
+ dszIRET, O_NoOpAlt3, /* CF IRET / IRETD (386) */
+ dszMULTI, O_GROUP23, /* D0 shifts & rotates,1 (byte) */
+ dszMULTI, O_GROUP24, /* D1 shifts & rotates,1 (word) */
+ dszMULTI, O_GROUP25, /* D2 shifts & rotates,CL (byte) */
+ dszMULTI, O_GROUP26, /* D3 shifts & rotates,CL (word) */
+ dszAAM, O_Ib, /* D4 AAM */
+ dszAAD, O_Ib, /* D5 AAD */
+ dszRESERVED, O_DoDB, /* D6 */
+ dszXLAT, O_NoOperands, /* D7 XLAT */
+ dszMULTI, O_x87_ESC, /* D8 ESC */
+ dszMULTI, O_x87_ESC, /* D9 ESC */
+ dszMULTI, O_x87_ESC, /* DA ESC */
+ dszMULTI, O_x87_ESC, /* DB ESC */
+ dszMULTI, O_x87_ESC, /* DC ESC */
+ dszMULTI, O_x87_ESC, /* DD ESC */
+ dszMULTI, O_x87_ESC, /* DE ESC */
+ dszMULTI, O_x87_ESC, /* DF ESC */
+ dszLOOPNE,O_Rel8, /* E0 LOOPNE or LOOPNZ */
+ dszLOOPE, O_Rel8, /* E1 LOOPE or LOOPZ */
+ dszLOOP, O_Rel8, /* E2 LOOP */
+ dszJCXZ, O_Rel8, /* E3 JCXZ / JECXZ (386) */
+ dszIN, O_AL_Ubyte, /* E4 IN AL, I */
+ dszIN, O_AX_Ubyte, /* E5 IN AX, I */
+ dszOUT, O_Ubyte_AL, /* E6 OUT I, AL */
+ dszOUT, O_Ubyte_AX, /* E7 OUT I, AX */
+ dszCALL, O_Rel16, /* E8 CALL Rel16 */
+ dszJMP, O_Rel16, /* E9 JMP Rel16 */
+ dszJMP, O_FarPtr, /* EA JMP seg:off */
+ dszJMP, O_Rel8, /* EB JMP Rel8 */
+ dszIN, O_DoInAL, /* EC IN AL, DX */
+ dszIN, O_DoInAX, /* ED IN AX, DX */
+ dszOUT, O_DoOutAL, /* EE OUT DX, AL */
+ dszOUT, O_DoOutAX, /* EF OUT DX, AX */
+ dszLOCK, O_DoRep, /* F0 LOCK */
+ dszRESERVED, O_DoDB, /* F1 */
+ dszREPNE, O_DoRep, /* F2 REPNE or REPNZ */
+ dszREP, O_DoRep, /* F3 REP or REPE or REPZ */
+ dszHLT, O_NoOperands, /* F4 HLT */
+ dszCMC, O_NoOperands, /* F5 CMC */
+ dszMULTI, O_GROUP31, /* F6 TEST, NOT, NEG, MUL, IMUL, */
+ dszMULTI, O_GROUP32, /* F7 DIv, IDIv F6=Byte F7=Word */
+ dszCLC, O_NoOperands, /* F8 CLC */
+ dszSTC, O_NoOperands, /* F9 STC */
+ dszCLI, O_NoOperands, /* FA CLI */
+ dszSTI, O_NoOperands, /* FB STI */
+ dszCLD, O_NoOperands, /* FC CLD */
+ dszSTD, O_NoOperands, /* FD STD */
+ dszMULTI, O_GROUP4, /* FE INC, DEC mem/reg (byte) */
+ dszMULTI, O_GROUP5, /* FF INC, DEC, CALL, JMP, PUSH */
+
+ dszMULTI, O_GROUP6, /* 0 MULTI */
+ dszMULTI, O_GROUP7, /* 1 MULTI */
+ dszLAR, O_Reg_Modrm, /* 2 LAR */
+ dszLSL, O_Reg_Modrm, /* 3 LSL */
+ dszRESERVED, O_DoDB, /* 4 */
+ dszLOADALL, O_NoOperands, /* 5 LOADALL */
+ dszCLTS, O_NoOperands, /* 6 CLTS */
+ dszRESERVED, O_DoDB, /* 7 */
+ dszINVD, O_NoOperands, /* 8 INVD */
+ dszWBINVD, O_NoOperands, /* 9 WBINVD */
+ dszRESERVED, O_DoDB, /* A */
+ dszRESERVED, O_DoDB, /* B */
+ dszRESERVED, O_DoDB, /* C */
+ dszRESERVED, O_DoDB, /* D */
+ dszRESERVED, O_DoDB, /* E */
+ dszRESERVED, O_DoDB, /* F */
+ dszMOV, O_Modrm_CReg, /* 20 MOV */
+ dszMOV, O_Modrm_CReg, /* 21 MOV */
+ dszMOV, O_CReg_Modrm, /* 22 MOV */
+ dszMOV, O_CReg_Modrm, /* 23 MOV */
+ dszMOV, O_Modrm_CReg, /* 24 MOV */
+ dszRESERVED, O_DoDB, /* 25 */
+ dszMOV, O_CReg_Modrm, /* 26 MOV */
+
+ dszSETGE, O_bModrm, /* 7D SETGE or SETNL */
+ dszRESERVED, O_DoDB, /* 7E */
+ dszRESERVED, O_DoDB, /* 7F */
+ dszJO, O_Rel16, /* 80 JO */
+ dszJNO, O_Rel16, /* 81 JNO */
+ dszJB, O_Rel16, /* 82 JB */
+ dszJAE, O_Rel16, /* 83 JAE or JNB */
+ dszJE, O_Rel16, /* 84 JE */
+ dszJNE, O_Rel16, /* 85 JNE */
+ dszJBE, O_Rel16, /* 86 JBE */
+ dszJA, O_Rel16, /* 87 JA or JNBE */
+ dszJS, O_Rel16, /* 88 JS */
+ dszJNS, O_Rel16, /* 89 JNS */
+ dszJP, O_Rel16, /* 8A JP */
+ dszJNP, O_Rel16, /* 8B JNP */
+ dszJL, O_Rel16, /* 8C JL */
+ dszJGE, O_Rel16, /* 8D JGE or JNL */
+ dszJLE, O_Rel16, /* 8E JLE */
+ dszJG, O_Rel16, /* 8F JG or JNLE */
+ dszSETO, O_bModrm, /* 90 SETO */
+ dszSETNO, O_bModrm, /* 91 SETNO */
+ dszSETB, O_bModrm, /* 92 SETB */
+ dszSETAE, O_bModrm, /* 93 SETAE or SETNB */
+ dszSETE, O_bModrm, /* 94 SETE */
+ dszSETNE, O_bModrm, /* 95 SETNE */
+ dszSETBE, O_bModrm, /* 96 SETBE */
+ dszSETA, O_bModrm, /* 97 SETNBE */
+ dszSETS, O_bModrm, /* 98 SETS */
+ dszSETNS, O_bModrm, /* 99 SETNS */
+ dszSETP, O_bModrm, /* 9A SETP */
+ dszSETNP, O_bModrm, /* 9B SETNP */
+ dszSETL, O_bModrm, /* 9C SETL */
+ dszSETGE, O_bModrm, /* 9D SETGE */
+ dszSETLE, O_bModrm, /* 9E SETLE */
+ dszSETG, O_bModrm, /* 9F SETG or SETNLE */
+ dszPUSH, O_sReg2, /* A0 PUSH FS */
+ dszPOP, O_sReg2, /* A1 POP FS */
+ dszRESERVED, O_DoDB, /* A2 */
+ dszBT, O_Modrm_Reg, /* A3 BT */
+ dszSHLD, O_Modrm_Reg_Ib, /* A4 SHLD */
+ dszSHLD, O_Modrm_Reg_CL, /* A5 SHLD */
+ dszRESERVED, O_DoDB, /* A6 [02] */
+ dszRESERVED, O_DoDB, /* A7 [02] */
+ dszPUSH, O_sReg2, /* A8 PUSH GS */
+ dszPOP, O_sReg2, /* A9 POP GS */
+ dszRESERVED, O_DoDB, /* AA */
+ dszBTS, O_vModrm_Reg, /* AB BTS */
+ dszSHRD, O_Modrm_Reg_Ib, /* AC SHRD */
+ dszSHRD, O_Modrm_Reg_CL, /* AD SHRD */
+ dszRESERVED, O_DoDB, /* AE */
+ dszIMUL, O_Reg_Modrm, /* AF IMUL */
+ dszCMPXCHG,O_bModrm_Reg, /* B0 XBTS [02] */
+ dszCMPXCHG,O_Modrm_Reg, /* B1 IBTS [02] */
+ dszLSS, O_fReg_Modrm, /* B2 LSS */
+ dszBTR, O_Modrm_Reg, /* B3 BTR */
+ dszLFS, O_fReg_Modrm, /* B4 LFS */
+ dszLGS, O_fReg_Modrm, /* B5 LGS */
+ dszMOVZX, O_Reg_bModrm, /* B6 MOVZX */
+ dszMOVZX, O_Reg_wModrm, /* B7 MOVZX */
+ dszRESERVED, O_DoDB, /* B8 */
+ dszRESERVED, O_DoDB, /* B9 */
+ dszMULTI, O_GROUP8, /* BA MULTI */
+ dszBTC, O_Modrm_Reg, /* BB BTC */
+ dszBSF, O_Reg_Modrm, /* BC BSF */
+ dszBSR, O_Reg_Modrm, /* BD BSR */
+ dszMOVSX, O_Reg_bModrm, /* BE MOVSX */
+ dszMOVSX, O_Reg_wModrm, /* BF MOVSX */
+ dszXADD, O_bModrm_Reg, /* C0 XADD */
+ dszXADD, O_Modrm_Reg, /* C1 XADD */
+ dszRESERVED, O_DoDB, /* C2 */
+ dszRESERVED, O_DoDB, /* C3 */
+ dszRESERVED, O_DoDB, /* C4 */
+ dszRESERVED, O_DoDB, /* C5 */
+ dszRESERVED, O_DoDB, /* C6 */
+ dszRESERVED, O_DoDB, /* C7 */
+ dszBSWAP, O_oReg, /* C8 BSWAP */
+ dszBSWAP, O_oReg, /* C9 BSWAP */
+ dszBSWAP, O_oReg, /* CA BSWAP */
+ dszBSWAP, O_oReg, /* CB BSWAP */
+ dszBSWAP, O_oReg, /* CC BSWAP */
+ dszBSWAP, O_oReg, /* CD BSWAP */
+ dszBSWAP, O_oReg, /* CE BSWAP */
+ dszBSWAP, O_oReg /* CF BSWAP */
+};
+
+/* Auxilary lists of mnemonics for groups of two byte instructions: */
+/* All of the instructions within each of these groups are of the same */
+/* class, so only the mnemonic string is needed, the index into the */
+/* action table is implicit. */
+
+static CBC *group[][8] = {
+
+/* 00 */ {dszADD, dszOR, dszADC, dszSBB, /* group 1 */
+ dszAND, dszSUB, dszXOR, dszCMP},
+
+/* 01 */ {dszROL, dszROR, dszRCL, dszRCR, /* group 2 */
+ dszSHL, dszSHR, dszRESERVED, dszSAR},
+
+/* 02 */ {dszINC, dszDEC, dszRESERVED, dszRESERVED, /* group 4 */
+ dszRESERVED, dszRESERVED, dszRESERVED, dszRESERVED},
+
+/* 03 */ {dszSLDT, dszSTR, dszLLDT, dszLTR, /* group 6 */
+ dszVERR, dszVERW, dszRESERVED, dszRESERVED},
+
+/* 04 */ {dszRESERVED, dszRESERVED, dszRESERVED, dszRESERVED, /* group 8 */
+ dszBT, dszBTS, dszBTR, dszBTC}
+
+ };
+
+/* Auxilary orderd pairs for groups of two byte instructions structured */
+/* the same was as distbl above. */
+
+static Tdistbl groupt[][8] = {
+
+/* 00 00 x87-D8-1 */
+ { dszFADD, O_dModrm, /* D8-0 FADD */
+ dszFMUL, O_dModrm, /* D8-1 FMUL */
+ dszFCOM, O_dModrm, /* D8-2 FCOM */
+ dszFCOMP, O_dModrm, /* D8-3 FCOMP */
+ dszFSUB, O_dModrm, /* D8-4 FSUB */
+ dszFSUBR, O_dModrm, /* D8-5 FSUBR */
+ dszFDIV, O_dModrm, /* D8-6 FDIV */
+ dszFDIVR, O_dModrm }, /* D8-7 FDIVR */
+
+/* 01 x87-D8-2 */
+ { dszFADD, O_ST_iST, /* D8-0 FADD */
+ dszFMUL, O_ST_iST, /* D8-1 FMUL */
+ dszFCOM, O_iST, /* D8-2 FCOM */
+ dszFCOMP, O_iST, /* D8-3 FCOMP */
+ dszFSUB, O_ST_iST, /* D8-4 FSUB */
+ dszFSUBR, O_ST_iST, /* D8-5 FSUBR */
+ dszFDIV, O_ST_iST, /* D8-6 FDIV */
+ dszFDIVR, O_ST_iST }, /* D8-7 FDIVR */
+
+/* 02 01 x87-D9-1 */
+ { dszFLD, O_dModrm, /* D9-0 FLD */
+ dszRESERVED, O_DoDB, /* D9-1 */
+ dszFST, O_dModrm, /* D9-2 FST */
+ dszFSTP, O_dModrm, /* D9-3 FSTP */
+ dszFLDENV, O_Modrm, /* D9-4 FLDENV */
+ dszFLDCW, O_Modrm, /* D9-5 FLDCW */
+ dszFNSTENV, O_Modrm, /* D9-6 FNSTENV */
+ dszFNSTCW, O_Modrm }, /* D9-7 FNSTCW */
+
+/* 03 01 x87-D9-2 TTT=0,1,2,3 */
+ { dszFLD, O_iST, /* D9-0 FLD */
+ dszFXCH, O_iST, /* D9-1 FXCH */
+ dszFNOP, O_NoOperands, /* D9-2 FNOP */
+ dszFSTP, O_iST, /* D9-3 FSTP */
+ dszRESERVED, O_DoDB, /* D9-4 */
+ dszRESERVED, O_DoDB, /* D9-5 */
+ dszRESERVED, O_DoDB, /* D9-6 */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 04 02 x89-DA-1 */
+ { dszFIADD, O_dModrm, /* DA-0 FIADD */
+ dszFIMUL, O_dModrm, /* DA-1 FIMUL */
+ dszFICOM, O_dModrm, /* DA-2 FICOM */
+ dszFICOMP, O_dModrm, /* DA-3 FICOMP */
+ dszFISUB, O_dModrm, /* DA-4 FISUB */
+ dszFISUBR, O_dModrm, /* DA-5 FISUBR */
+ dszFIDIV, O_dModrm, /* DA-6 FIDIV */
+ dszFIDIVR, O_dModrm }, /* DA-7 FIDIVR */
+
+/* 05 x87-DA-2 */
+ { dszRESERVED, O_DoDB, /* DA-0 */
+ dszRESERVED, O_DoDB, /* DA-1 */
+ dszRESERVED, O_DoDB, /* DA-2 */
+ dszRESERVED, O_DoDB, /* DA-3 */
+ dszRESERVED, O_DoDB, /* DA-4 */
+ dszFUCOMPP, O_NoOperands, /* DA-5 */
+ dszRESERVED, O_DoDB, /* DA-6 */
+ dszRESERVED, O_DoDB }, /* DA-7 */
+
+/* 06 03 x87-DB-1 */
+ { dszFILD, O_dModrm, /* DB-0 FILD */
+ dszRESERVED, O_DoDB, /* DB-1 */
+ dszFIST, O_dModrm, /* DB-2 FIST */
+ dszFISTP, O_dModrm, /* DB-3 FISTP */
+ dszRESERVED, O_DoDB, /* DB-4 */
+ dszFLD, O_tModrm, /* DB-5 FLD */
+ dszRESERVED, O_DoDB, /* DB-6 */
+ dszFSTP, O_tModrm }, /* DB-7 FSTP */
+
+/* 07 x87-DB-2 ttt=4 */
+ { dszFENI, O_NoOperands, /* DB-0 FENI */
+ dszFDISI, O_NoOperands, /* DB-1 FDISI */
+ dszFNCLEX, O_NoOperands, /* DB-2 FNCLEX */
+ dszFNINIT, O_NoOperands, /* DB-3 FNINIT */
+ dszFSETPM, O_DoDB, /* DB-4 FSETPM */
+ dszRESERVED, O_DoDB, /* DB-5 */
+ dszRESERVED, O_DoDB, /* DB-6 */
+ dszRESERVED, O_DoDB }, /* DB-7 */
+
+/* 08 04 x87-DC-1 */
+ { dszFADD, O_qModrm, /* DC-0 FADD */
+ dszFMUL, O_qModrm, /* DC-1 FMUL */
+ dszFCOM, O_qModrm, /* DC-2 FCOM */
+ dszFCOMP, O_qModrm, /* DC-3 FCOMP */
+ dszFSUB, O_qModrm, /* DC-4 FSUB */
+ dszFSUBR, O_qModrm, /* DC-5 FSUBR */
+ dszFDIV, O_qModrm, /* DC-6 FDIV */
+ dszFDIVR, O_qModrm }, /* DC-7 FDIVR */
+
+/* 09 x87-DC-2 */
+ { dszFADD, O_iST_ST, /* DC-0 FADD */
+ dszFMUL, O_iST_ST, /* DC-1 FMUL */
+ dszFCOM, O_iST, /* DC-2 FCOM */
+ dszFCOMP, O_iST, /* DC-3 FCOMP */
+ dszFSUBR, O_iST_ST, /* DC-4 FSUBR */
+ dszFSUB, O_iST_ST, /* DC-5 FSUB */
+ dszFDIVR, O_iST_ST, /* DC-6 FDIVR */
+ dszFDIV, O_iST_ST }, /* DC-7 FDIV */
+
+/* 10 05 x87-DD-1 */
+ { dszFLD, O_qModrm, /* DD-0 FLD */
+ dszRESERVED, O_DoDB, /* DD-1 */
+ dszFST, O_qModrm, /* DD-2 FST */
+ dszFSTP, O_qModrm, /* DD-3 FSTP */
+ dszFRSTOR, O_Modrm, /* DD-4 FRSTOR */
+ dszRESERVED, O_DoDB, /* DD-5 */
+ dszFNSAVE, O_Modrm, /* DD-6 FNSAVE */
+ dszFNSTSW, O_Modrm }, /* DD-7 FNSTSW */
+
+/* 11 x87-DD-2 */
+ { dszFFREE, O_iST, /* DD-0 FFREE */
+ dszFSTP, O_iST, /* DD-1 FSTP */
+ dszFST, O_iST, /* DD-2 FST */
+ dszFSTP, O_iST, /* DD-3 FSTP */
+ dszFUCOM, O_iST, /* DD-4 FUCOM */
+ dszFUCOMP, O_iST, /* DD-5 FUCOMP */
+ dszRESERVED, O_DoDB, /* DD-6 */
+ dszRESERVED, O_DoDB }, /* DD-7 */
+
+/* 12 06 x87-DE-1 */
+ { dszFIADD, O_wModrm, /* DE-0 FIADD */
+ dszFIMUL, O_wModrm, /* DE-1 FIMUL */
+ dszFICOM, O_wModrm, /* DE-2 FICOM */
+ dszFICOMP, O_wModrm, /* DE-3 FICOMP */
+ dszFISUB, O_wModrm, /* DE-4 FISUB */
+ dszFISUBR, O_wModrm, /* DE-5 FISUBR */
+ dszFIDIV, O_wModrm, /* DE-6 FIDIV */
+ dszFIDIVR, O_wModrm }, /* DE-7 FIDIVR */
+
+/* 13 x87-DE-2 */
+ { dszFADDP, O_iST_ST, /* DE-0 FADDP */
+ dszFMULP, O_iST_ST, /* DE-1 FMULP */
+ dszFCOMP, O_iST, /* DE-2 FCOMP */
+ dszFCOMPP, O_NoOperands, /* DE-3 FCOMPP */
+ dszFSUBRP, O_iST_ST, /* DE-4 FSUBRP */
+ dszFSUBP, O_iST_ST, /* DE-5 FSUBP */
+ dszFDIVRP, O_iST_ST, /* DE-6 FDIVRP */
+ dszFDIVP, O_iST_ST}, /* DE-7 FDIVP */
+
+/* 14 07 x87-DF-1 */
+ { dszFILD, O_wModrm, /* DF-0 FILD */
+ dszRESERVED, O_DoDB, /* DF-1 */
+ dszFIST, O_wModrm, /* DF-2 FIST */
+ dszFISTP, O_wModrm, /* DF-3 FISTP */
+ dszFBLD, O_tModrm, /* DF-4 FBLD */
+ dszFILD, O_qModrm, /* DF-5 FILD */
+ dszFBSTP, O_tModrm, /* DF-6 FBSTP */
+ dszFISTP, O_qModrm }, /* DF-7 FISTP */
+
+/* 15 x87-DF-2 */
+ { dszFFREE, O_iST, /* DF-0 FFREE */
+ dszFXCH, O_iST, /* DF-1 FXCH */
+ dszFST, O_iST, /* DF-2 FST */
+ dszFSTP, O_iST, /* DF-3 FSTP */
+ dszFNSTSW, O_AX, /* DF-4 FNSTSW */
+ dszRESERVED, O_DoDB, /* DF-5 */
+ dszRESERVED, O_DoDB, /* DF-6 */
+ dszRESERVED, O_DoDB }, /* DF-7 */
+
+/* 16 01 x87-D9 Mod=3 TTT=4 */
+ { dszFCHS, O_NoOperands, /* D9-0 FCHS */
+ dszFABS, O_NoOperands, /* D9-1 FABS */
+ dszRESERVED, O_DoDB, /* D9-2 */
+ dszRESERVED, O_DoDB, /* D9-3 */
+ dszFTST, O_NoOperands, /* D9-4 FTST */
+ dszFXAM, O_NoOperands, /* D9-5 FXAM */
+ dszRESERVED, O_DoDB, /* D9-6 */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 17 01 x87-D9 Mod=3 TTT=5 */
+ { dszFLD1, O_NoOperands, /* D9-0 FLD1 */
+ dszFLDL2T, O_NoOperands, /* D9-1 FLDL2T */
+ dszFLDL2E, O_NoOperands, /* D9-2 FLDL2E */
+ dszFLDPI, O_NoOperands, /* D9-3 FLDPI */
+ dszFLDLG2, O_NoOperands, /* D9-4 FLDLG2 */
+ dszFLDLN2, O_NoOperands, /* D9-5 FLDLN2 */
+ dszFLDZ, O_NoOperands, /* D9-6 FLDZ */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 18 01 x87-D9 Mod=3 TTT=6 */
+ { dszF2XM1, O_NoOperands, /* D9-0 F2XM1 */
+ dszFYL2X, O_NoOperands, /* D9-1 FYL2X */
+ dszFPTAN, O_NoOperands, /* D9-2 FPTAN */
+ dszFPATAN, O_NoOperands, /* D9-3 FPATAN */
+ dszFXTRACT, O_NoOperands, /* D9-4 FXTRACT */
+ dszFPREM1, O_NoOperands, /* D9-5 FPREM1 */
+ dszFDECSTP, O_NoOperands, /* D9-6 FDECSTP */
+ dszFINCSTP, O_NoOperands }, /* D9-7 FINCSTP */
+
+/* 19 01 x87-D9 Mod=3 TTT=7 */
+ { dszFPREM, O_NoOperands, /* D9-0 FPREM */
+ dszFYL2XP1, O_NoOperands, /* D9-1 FYL2XP1 */
+ dszFSQRT, O_NoOperands, /* D9-2 FSQRT */
+ dszFSINCOS, O_NoOperands, /* D9-3 FSINCOS */
+ dszFRNDINT, O_NoOperands, /* D9-4 FRNDINT */
+ dszFSCALE, O_NoOperands, /* D9-5 FSCALE */
+ dszFSIN, O_NoOperands, /* D9-6 FSIN */
+ dszFCOS, O_NoOperands }, /* D9-7 FCOS */
+
+/* 20 group 3 */
+ { dszTEST, O_bModrm_Ib, /* F6-0 TEST */
+ dszRESERVED, O_DoDB, /* F6-1 */
+ dszNOT, O_bModrm, /* F6-2 NOT */
+ dszNEG, O_bModrm, /* F6-3 NEG */
+ dszMUL, O_bModrm, /* F6-4 MUL */
+ dszIMUL, O_bModrm, /* F6-5 IMUL */
+ dszDIV, O_bModrm, /* F6-6 DIV */
+ dszIDIV, O_bModrm }, /* F6-7 IDIV */
+
+/* 21 group 3 */
+ { dszTEST, O_vModrm_Iv, /* F7-0 TEST */
+ dszRESERVED, O_DoDB, /* F7-1 */
+ dszNOT, O_vModrm, /* F7-2 NOT */
+ dszNEG, O_vModrm, /* F7-3 NEG */
+ dszMUL, O_vModrm, /* F7-4 MUL */
+ dszIMUL, O_vModrm, /* F7-5 IMUL */
+ dszDIV, O_vModrm, /* F7-6 DIV */
+ dszIDIV, O_vModrm }, /* F7-7 IDIV */
+
+/* 22 group 5 */
+ { dszINC, O_vModrm, /* FF-0 INC */
+ dszDEC, O_vModrm, /* FF-1 DEC */
+ dszCALL, O_vModrm, /* FF-2 CALL */
+ dszCALL, O_fModrm, /* FF-3 CALL */
+ dszJMP, O_vModrm, /* FF-4 JMP */
+ dszJMP, O_fModrm, /* FF-5 JMP */
+ dszPUSH, O_vModrm, /* FF-6 PUSH */
+ dszRESERVED, O_DoDB }, /* FF-7 */
+
+/* 23 group 7 */
+ { dszSGDT, O_fw_Modrm, /* 0F-0 SGDT */
+ dszSIDT, O_fw_Modrm, /* 0F-1 SIDT */
+ dszLGDT, O_fw_Modrm, /* 0F-2 LGDT */
+ dszLIDT, O_fw_Modrm, /* 0F-3 LIDT */
+ dszSMSW, O_wModrm, /* 0F-4 MSW */
+ dszRESERVED, O_DoDB, /* 0F-5 */
+ dszLMSW, O_wModrm, /* 0F-6 LMSW */
+ dszINVLPG, O_bModrm } /* 0F-7 INVLPG */
+
+ };
+#pragma pack ()
+
+/*************************** end of d3.h ********************************/
diff --git a/private/windbg/em/p_i386/d3em.c b/private/windbg/em/p_i386/d3em.c
new file mode 100644
index 000000000..e2b1db6e0
--- /dev/null
+++ b/private/windbg/em/p_i386/d3em.c
@@ -0,0 +1,262 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ d3em.c
+
+Abstract:
+
+ This module contains the disassembler code that is specific to the
+ EM.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 22-August-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#define MAX_BUFFER_SIZE 20
+
+typedef LPCH FAR *LPLPCH;
+
+typedef enum {
+ osoNone = 0,
+ osoSymbols = 1,
+ osoSegment = 2
+} OSO;
+
+extern XOSD Disassemble( HPID, HTID, LPSDI, PVOID, INT, BOOL );
+extern void OutputIString ( LPLPCH, int *, LPCH );
+extern void OutputHexValue(LPLPCH, int *, LPCH, int, int);
+extern void OutputHexString(LPLPCH, int *, LPCH, int);
+
+
+/****disasm - disassemble an 80x86/80x87 instruction
+*
+* Input:
+* pOffset = pointer to offset to start disassembly
+* fEAout = if set, include EA (effective address)
+*
+* Output:
+* pOffset = pointer to offset of next instruction
+* pchDst = pointer to result string
+*
+***************************************************************************/
+
+XOSD
+disasm (
+ HPID hpid,
+ HTID htid,
+ LPSDI lpsdi
+ )
+{
+ BYTE Buffer[ MAX_BUFFER_SIZE ];
+ XOSD xosd = xosdNone;
+ ADDR AddrStart = lpsdi->addr;
+ int cb;
+
+ //
+ // Read memory into our buffer
+ //
+ EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) &AddrStart );
+ cb = EMFunc( emfReadBuf, hpid, htid, sizeof(Buffer), (LONG)(LPV)Buffer );
+
+ //
+ // Disassemble the instruction
+ //
+ return Disassemble( hpid, htid, lpsdi, Buffer, cb, TRUE );
+}
+
+
+XOSD
+GetRegisterValue (
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+{
+ return EMFunc( emfGetReg, hpid, htid, wValue, lValue );
+}
+
+XOSD
+SetAddress (
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+{
+ return EMFunc (emfSetAddr, hpid, htid, wValue, lValue);
+}
+
+XOSD
+ReadMemBuffer (
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+{
+ return EMFunc (emfReadBuf, hpid, htid, wValue, lValue);
+}
+
+
+// UNDONE: Does anyone, anywhere know why this function exists? BryanT
+
+__inline LSZ
+ObtainSymbol (
+ PADDR Addr1,
+ SOP Sop,
+ PADDR Addr2,
+ LSZ Lsz,
+ LONG *Lpl
+ )
+{
+ ODR odr;
+ LPCH lpchSymbol;
+
+ odr.lszName = Lsz;
+
+ lpchSymbol = SHGetSymbol( Addr1, Addr2, Sop, &odr);
+
+ *Lpl = odr.dwDeltaOff;
+
+ return(lpchSymbol);
+}
+
+
+
+
+
+/*** OutputSymbol - output symbolic value
+*
+* Purpose:
+* Output the value in outvalue into the buffer
+* pointed by *pBuf. Express the value as a
+* symbol plus displacment, if possible.
+*
+* Input:
+* *ppBuf - pointer to text buffer to fill
+* *pValue - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *ppBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void OutputSymbol (
+ HPID hpidLocal,
+ HTID htidLocal,
+ BOOL fSymbols,
+ BOOL fSegOvr,
+ LPADDR lpaddrOp,
+ int ireg,
+ int length,
+ LPADDR lpaddrLoc,
+ LPLPCH ppBuf,
+ int * pcch
+
+)
+{
+ UCHAR rgchSymbol[60];
+ LPCH lpchSymbol;
+ SOP sop;
+ ODR odr;
+
+ odr.lszName = rgchSymbol;
+
+ switch ( ireg ) {
+
+ case CV_REG_CS:
+
+ sop = sopNone;
+ break;
+
+ case CV_REG_SS:
+
+ sop = sopStack;
+ break;
+
+ default:
+
+ sop = sopData;
+ break;
+
+ }
+
+ if ( fSymbols & osoSymbols ) {
+
+ lpchSymbol = SHGetSymbol (lpaddrOp,
+ lpaddrLoc,
+ sop,
+ &odr);
+
+ if (lpchSymbol && odr.dwDeltaOff != 0xFFFFFFFF ) {
+ OutputIString ( ppBuf, pcch, rgchSymbol );
+
+ OutputHexValue(ppBuf, pcch, (LPCH) &odr.dwDeltaOff, length, TRUE);
+
+ EMFunc ( emfFixupAddr, hpidLocal, htidLocal, 0, (LONG) lpaddrOp);
+
+ *(*ppBuf)++ = ' ';
+ *(*ppBuf)++ = '(';
+ *pcch -= 2;
+ if ( !fSegOvr && ( fSymbols & osoSegment ) ) {
+ OutputHexString ( ppBuf, pcch,
+ (LPCH) &segAddr ( *lpaddrOp ), 2 );
+ **ppBuf = ':';
+ *ppBuf += 1;
+ *pcch -= 1;
+ }
+
+ if ( ADDR_IS_FLAT(*lpaddrOp) ) {
+ OutputHexString ( ppBuf, pcch,
+ (LPCH) &offAddr ( *lpaddrOp ), 4 );
+ } else {
+ OutputHexString ( ppBuf, pcch,
+ (LPCH) &offAddr ( *lpaddrOp ), 2 );
+ }
+ *(*ppBuf)++ = ')';
+ *pcch -= 1;
+
+ return;
+ }
+ }
+
+ if ( !fSegOvr && ( fSymbols & osoSegment ) ) {
+ OutputHexString ( ppBuf, pcch, (LPCH) &segAddr ( *lpaddrOp ), 2 );
+ **ppBuf = ':';
+ *ppBuf += 1;
+ *pcch -= 1;
+ }
+
+ if ( ADDR_IS_FLAT(*lpaddrOp) ) {
+ if ((offAddr(*lpaddrOp) >= 0x80000000) &&
+ ((*ppBuf)[-1] == '+')) {
+ odr.dwDeltaOff = (ULONG) -( (LONG) offAddr(*lpaddrOp));
+ (*ppBuf)[-1] = '-';
+ OutputHexString ( ppBuf, pcch, (LPCH) &odr.dwDeltaOff, length );
+ } else {
+ OutputHexString ( ppBuf, pcch,
+ (LPCH) &offAddr ( *lpaddrOp ), length );
+ }
+
+ } else {
+ OutputHexString ( ppBuf, pcch, (LPCH) &offAddr ( *lpaddrOp ), length );
+ }
+}
+
+#include "d3.c"
diff --git a/private/windbg/em/p_i386/em.rc b/private/windbg/em/p_i386/em.rc
new file mode 100644
index 000000000..ff15b97de
--- /dev/null
+++ b/private/windbg/em/p_i386/em.rc
@@ -0,0 +1 @@
+#include "..\em\em.rc"
diff --git a/private/windbg/em/p_i386/emdp.c b/private/windbg/em/p_i386/emdp.c
new file mode 100644
index 000000000..96568b2ed
--- /dev/null
+++ b/private/windbg/em/p_i386/emdp.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp.c"
diff --git a/private/windbg/em/p_i386/emdp2.c b/private/windbg/em/p_i386/emdp2.c
new file mode 100644
index 000000000..5e0024775
--- /dev/null
+++ b/private/windbg/em/p_i386/emdp2.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp2.c"
diff --git a/private/windbg/em/p_i386/emdp3.c b/private/windbg/em/p_i386/emdp3.c
new file mode 100644
index 000000000..57d71318d
--- /dev/null
+++ b/private/windbg/em/p_i386/emdp3.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp3.c"
diff --git a/private/windbg/em/p_i386/emdpdev.c b/private/windbg/em/p_i386/emdpdev.c
new file mode 100644
index 000000000..a77752a90
--- /dev/null
+++ b/private/windbg/em/p_i386/emdpdev.c
@@ -0,0 +1,1802 @@
+/**** EMDPDEV.C - Debugger end Execution Model (x86 dependent code) **
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 15, 1990 by David W. Gray *
+ * *
+ * Revision History: *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+#include "strings.h"
+
+
+DWORD ConvertOmapToSrc(LPMDI lpmdi, DWORD addr);
+
+
+typedef struct _L_DOUBLE {
+ BYTE b[10];
+} L_DOUBLE, FAR *LPL_DOUBLE;
+
+
+#ifndef SMARTALIAS
+void PurgeCache ( void );
+#endif
+
+#define CEXM_MDL_native 0x20
+
+
+/*
+** This is the description of all registers and flags contained on the
+** x86 machine
+*/
+
+extern RD Rgrd[];
+
+extern struct {
+ FD fd;
+ USHORT iShift;
+} Rgfd[];
+
+#ifdef TARGET32
+#define SIZEOF_STACK_OFFSET sizeof(LONG)
+#else // TARGET32
+#define SIZEOF_STACK_OFFSET sizeof(WORD)
+#endif // TARGET32
+
+#ifndef OSDEBUG4
+
+#pragma pack ( 1 )
+
+typedef union _PLG {
+
+ struct std {
+ unsigned char PushBP;
+ unsigned short MovBPSP;
+ } std;
+
+ struct enter {
+ unsigned char C8;
+ unsigned short cbStack;
+ unsigned char cNesting;
+ } enter;
+
+} PLG;
+#pragma pack()
+
+#define ENTERINS 0xC8
+#define PUSHBP 0x55
+#define PUSHSI 0x56
+#define PUSHDI 0x57
+#define MOVBPSP 0xEC8B
+
+BOOL NEAR PASCAL IsStackSetup(
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddrProc
+) {
+ BOOL rval = TRUE;
+ PLG plg;
+ UOFFSET cbInProlog;
+ LPTHD lpthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ HTHD hthd;
+ if (!hprc) {
+ return FALSE;
+ }
+ hthd = HthdFromHtid(hprc, htid);
+ if (!hthd) {
+ return FALSE;
+ }
+ lpthd = LLLock ( hthd );
+
+ lpthd->addrCurrent = *lpaddrProc;
+
+ if (ReadBuffer(hpid, htid, 0, sizeof ( PLG ), (char FAR *) &plg, NULL)) {
+
+ /* Stack is set up but is it Parents Stack?
+ */
+
+ if( plg.enter.C8 == ENTERINS || plg.std.MovBPSP == MOVBPSP ) {
+ cbInProlog = (UOFFSET) lpthd->regs.Eip - offAddr ( *lpaddrProc );
+
+ /* Are we beyond the push bp, mov bp, sp combo or an enter?
+ */
+ rval = cbInProlog >= 3;
+ }
+ }
+
+ LLUnlock( hthd );
+ return( rval );
+}
+#endif // OSDEBUG4
+
+
+XOSD
+GetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ This function will get return a specific type of address.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to retrive the address from
+ htid - Supplies the handle to the thread to retrieve the address from
+ adr - Supplies the type of address to be retrieved
+ lpaddr - Returns the requested address
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+ XOSD xosd = xosdNone;
+ HEMI hemi = emiAddr(*lpaddr);
+ HMDI hmdi;
+ LPMDI lpmdi;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != hpidNull );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != hthdNull ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ _fmemset ( lpaddr, 0, sizeof ( ADDR ) );
+
+ switch ( adr ) {
+ case adrPC:
+ if ( lpthd && !(lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrBase:
+ case adrStack:
+ case adrData:
+ if ( lpthd && !(lpthd->drt & drtAllPresent )) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+#ifndef OSDEBUG4
+ case adrCurrent:
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ *lpaddr = lpthd->addrCurrent;
+ } else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ *lpaddr = lpprc->addrCurrent;
+
+ LLUnlock ( hprc );
+ }
+ break;
+#endif
+
+ case adrPC:
+ AddrInit(lpaddr, 0, (SEGMENT) lpthd->regs.SegCs,
+ (UOFFSET) lpthd->regs.Eip, lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrBase:
+ AddrInit(lpaddr, 0, (SEGMENT) 0,
+ (UOFFSET) lpthd->regs.Ebp, lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrStack:
+ AddrInit(lpaddr, 0, (SEGMENT) lpthd->regs.SegSs,
+ (UOFFSET) lpthd->regs.Esp, lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrData:
+ AddrInit(lpaddr, 0, (SEGMENT) lpthd->regs.SegDs, 0,
+ lpthd->fFlat, lpthd->fOff32, FALSE, lpthd->fReal);
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrTlsBase:
+ /*
+ * If -1 then we have not gotten a value from the DM yet.
+ */
+
+ assert(hemi != 0);
+
+ if (hemi == 0) {
+ return xosdBadAddress;
+ }
+
+ if (hemi != emiAddr(lpthd->addrTls)) {
+ hmdi = LLFind( LlmdiFromHprc( hprc ), wNull, (LPB) &hemi, emdiEMI);
+ assert(hmdi != 0);
+
+ if (hmdi == 0) {
+ return xosdBadAddress;
+ }
+
+ lpmdi = LLLock( hmdi );
+
+ SendRequestX( dmfQueryTlsBase, hpid, htid, sizeof(OFFSET),
+ &lpmdi->lpBaseOfDll);
+
+ lpthd->addrTls = *((LPADDR) LpDmMsg->rgb);
+ emiAddr(lpthd->addrTls) = hemi;
+ LLUnlock( hmdi );
+
+ }
+
+ *lpaddr = lpthd->addrTls;
+ emiAddr(*lpaddr) = 0;
+ break;
+
+ default:
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != hthdNull ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosd;
+} /* GetAddr() */
+
+
+XOSD
+SetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != hpidNull );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+
+ if ( hthd != hthdNull ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ switch ( adr ) {
+ case adrPC:
+ if ( !( lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+
+ case adrBase:
+ case adrStack:
+ case adrData:
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ }
+ switch ( adr ) {
+#ifndef OSDEBUG4
+ case adrCurrent:
+ if ( lpaddr->emi == hmemNull ) {
+ SetEmi ( hpid, lpaddr );
+ }
+
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ lpthd->addrCurrent = *lpaddr;
+ }
+ else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ lpprc->addrCurrent = *lpaddr;
+
+ LLUnlock ( hprc );
+ }
+ break;
+#endif
+
+ case adrPC:
+ lpthd->regs.SegCs = segAddr ( *lpaddr );
+ lpthd->regs.Eip = offAddr ( *lpaddr );
+ lpthd->drt |= drtCntrlDirty;
+ break;
+
+ case adrBase:
+ lpthd->regs.Ebp = offAddr ( *lpaddr );
+ lpthd->drt |= drtAllDirty;
+ break;
+
+ case adrStack:
+ lpthd->regs.SegSs = segAddr ( *lpaddr );
+ lpthd->regs.Esp = offAddr ( *lpaddr );
+ lpthd->drt |= drtAllDirty;
+ break;
+
+ case adrData:
+ case adrTlsBase:
+ default:
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != hthdNull ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosdNone;
+} /* SetAddr() */
+
+
+XOSD
+SetAddrFromCSIP (
+ HTHD hthd
+ )
+{
+
+ ADDR addr = {0};
+ LPTHD lpthd;
+
+ assert ( hthd != hthdNull && hthd != hthdInvalid );
+
+ lpthd = LLLock ( hthd );
+
+ segAddr ( addr ) = (SEGMENT) lpthd->regs.SegCs;
+ offAddr ( addr ) = (UOFFSET) lpthd->regs.Eip;
+ emiAddr ( addr ) = 0;
+ SETADDRMODE ( addr );
+
+ lpthd->addrCurrent = addr;
+
+ LLUnlock ( hthd );
+
+ return xosdNone;
+}
+
+
+CMP
+CmpAddr (
+ LPADDR lpaddr1,
+ LPADDR lpaddr2
+ )
+{
+// NOTENOTE -- segmented addresses
+ if ( offAddr ( *lpaddr1 ) < offAddr ( *lpaddr2 ) )
+ return ( fCmpLT );
+ else if ( offAddr ( *lpaddr1 ) > offAddr ( *lpaddr2 ) )
+ return ( fCmpGT );
+ else
+ return ( fCmpEQ );
+}
+
+
+LPV
+DoGetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to extract the value of a single register from
+ the debuggee.
+
+Arguments:
+
+ lpregs - Supplies pointer to the register set for the debuggee
+
+ ireg - Supplies the index of the register to be read
+
+ lpvRegValue - Supplies the buffer to place the register value in
+
+Return Value:
+
+ return-value - lpvRegValue + size of register on sucess and NULL on
+ failure
+--*/
+
+{
+ int i;
+
+ switch ( ireg ) {
+
+ case CV_REG_AL:
+ *( (LPB) lpvRegValue ) = (BYTE) lpregs->Eax;
+ break;
+
+ case CV_REG_CL:
+ *( (LPB) lpvRegValue ) = (BYTE) lpregs->Ecx;
+ break;
+
+ case CV_REG_DL:
+ *( (LPB) lpvRegValue ) = (BYTE) lpregs->Edx;
+ break;
+
+ case CV_REG_BL:
+ *( (LPB) lpvRegValue ) = (BYTE) lpregs->Ebx;
+ break;
+
+ case CV_REG_AH:
+ *( (LPB) lpvRegValue ) = (BYTE) (lpregs->Eax >> 8);
+ break;
+
+ case CV_REG_CH:
+ *( (LPB) lpvRegValue ) = (BYTE) (lpregs->Ecx >> 8);
+ break;
+
+ case CV_REG_DH:
+ *( (LPB) lpvRegValue ) = (BYTE) (lpregs->Edx >> 8);
+ break;
+
+ case CV_REG_BH:
+ *( (LPB) lpvRegValue ) = (BYTE) (lpregs->Ebx >> 8);
+ break;
+
+ case CV_REG_AX:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Eax;
+ break;
+
+ case CV_REG_CX:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Ecx;
+ break;
+
+ case CV_REG_DX:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Edx;
+ break;
+
+ case CV_REG_BX:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Ebx;
+ break;
+
+ case CV_REG_SP:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Esp;
+ break;
+
+ case CV_REG_BP:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Ebp;
+ break;
+
+ case CV_REG_SI:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Esi;
+ break;
+
+ case CV_REG_DI:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Edi;
+ break;
+
+ case CV_REG_IP:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->Eip;
+ break;
+
+ case CV_REG_FLAGS:
+ *( (LPW) lpvRegValue ) = (WORD) lpregs->EFlags;
+ break;
+
+ case CV_REG_ES:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegEs;
+ break;
+
+ case CV_REG_CS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegCs;
+ break;
+
+ case CV_REG_SS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegSs;
+ break;
+
+ case CV_REG_DS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegDs;
+ break;
+
+ case CV_REG_FS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegFs;
+ break;
+
+ case CV_REG_GS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->SegGs;
+ break;
+
+ case CV_REG_EAX:
+ *( (LPL) lpvRegValue ) = lpregs->Eax;
+ break;
+
+ case CV_REG_ECX:
+ *( (LPL) lpvRegValue ) = lpregs->Ecx;
+ break;
+
+ case CV_REG_EDX:
+ *( (LPL) lpvRegValue ) = lpregs->Edx;
+ break;
+
+ case CV_REG_EBX:
+ *( (LPL) lpvRegValue ) = lpregs->Ebx;
+ break;
+
+ case CV_REG_ESP:
+ *( (LPL) lpvRegValue ) = lpregs->Esp;
+ break;
+
+ case CV_REG_EBP:
+ *( (LPL) lpvRegValue ) = lpregs->Ebp;
+ break;
+
+ case CV_REG_ESI:
+ *( (LPL) lpvRegValue ) = lpregs->Esi;
+ break;
+
+ case CV_REG_EDI:
+ *( (LPL) lpvRegValue ) = lpregs->Edi;
+ break;
+
+ case CV_REG_EIP:
+ *( (LPL) lpvRegValue ) = lpregs->Eip;
+ break;
+
+ case CV_REG_EFLAGS:
+ *( (LPL) lpvRegValue ) = lpregs->EFlags;
+ break;
+
+ case CV_REG_ST0:
+ case CV_REG_ST1:
+ case CV_REG_ST2:
+ case CV_REG_ST3:
+ case CV_REG_ST4:
+ case CV_REG_ST5:
+ case CV_REG_ST6:
+ case CV_REG_ST7:
+
+// i = (lpregs->FloatSave.StatusWord >> 11) & 0x7;
+// i = (i + ireg - CV_REG_ST0) % 8;
+
+ i = ireg - CV_REG_ST0;
+
+ *( (LPL_DOUBLE) lpvRegValue ) =
+ ((LPL_DOUBLE)(lpregs->FloatSave.RegisterArea))[ i ];
+ break;
+
+ case CV_REG_CTRL:
+ *( (LPL) lpvRegValue ) = lpregs->FloatSave.ControlWord;
+ break;
+
+ case CV_REG_STAT:
+ *( (LPL) lpvRegValue ) = lpregs->FloatSave.StatusWord;
+ break;
+
+ case CV_REG_TAG:
+ *( (LPL) lpvRegValue ) = lpregs->FloatSave.TagWord;
+ break;
+
+ case CV_REG_FPIP:
+ *( (LPW) lpvRegValue ) = (OFF16) lpregs->FloatSave.ErrorOffset;
+ break;
+
+ case CV_REG_FPEIP:
+ *( (LPL) lpvRegValue ) = lpregs->FloatSave.ErrorOffset;
+ break;
+
+ case CV_REG_FPCS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->FloatSave.ErrorSelector;
+ break;
+
+ case CV_REG_FPDO:
+ *( (LPL) lpvRegValue ) = (OFF16) lpregs->FloatSave.DataOffset;
+ break;
+
+ case CV_REG_FPEDO:
+ *( (LPL) lpvRegValue ) = lpregs->FloatSave.DataOffset;
+ break;
+
+ case CV_REG_FPDS:
+ *( (LPW) lpvRegValue ) = (SEGMENT) lpregs->FloatSave.DataSelector;
+ break;
+
+#define lpsr ((PKSPECIAL_REGISTERS)lpregs)
+ case CV_REG_GDTR:
+ *( (LPDWORD) lpvRegValue ) = lpsr->Gdtr.Base;
+ break;
+
+ case CV_REG_GDTL:
+ *( (LPWORD) lpvRegValue ) = lpsr->Gdtr.Limit;
+ break;
+
+ case CV_REG_IDTR:
+ *( (LPDWORD) lpvRegValue ) = lpsr->Idtr.Base;
+ break;
+
+ case CV_REG_IDTL:
+ *( (LPWORD) lpvRegValue ) = lpsr->Idtr.Limit;
+ break;
+
+ case CV_REG_LDTR:
+ *( (LPWORD) lpvRegValue ) = lpsr->Ldtr;
+ break;
+
+ case CV_REG_TR:
+ *( (LPWORD) lpvRegValue ) = lpsr->Tr;
+ break;
+
+ case CV_REG_CR0:
+ *( (LPDWORD) lpvRegValue ) = lpsr->Cr0;
+ break;
+
+ case CV_REG_CR2:
+ *( (LPDWORD) lpvRegValue ) = lpsr->Cr2;
+ break;
+
+ case CV_REG_CR3:
+ *( (LPDWORD) lpvRegValue ) = lpsr->Cr3;
+ break;
+
+ case CV_REG_CR4:
+ *( (LPDWORD) lpvRegValue ) = lpsr->Cr4;
+ break;
+#undef lpsr
+
+ case CV_REG_DR0:
+ *( (PULONG) lpvRegValue ) = lpregs->Dr0;
+ break;
+
+ case CV_REG_DR1:
+ *( (PULONG) lpvRegValue ) = lpregs->Dr1;
+ break;
+
+ case CV_REG_DR2:
+ *( (PULONG) lpvRegValue ) = lpregs->Dr2;
+ break;
+
+ case CV_REG_DR3:
+ *( (PULONG) lpvRegValue ) = lpregs->Dr3;
+ break;
+
+ case CV_REG_DR6:
+ *( (PULONG) lpvRegValue ) = lpregs->Dr6;
+ break;
+
+ case CV_REG_DR7:
+ *( (PULONG) lpvRegValue ) = lpregs->Dr7;
+ break;
+
+ }
+
+ switch ( ireg ) {
+
+ case CV_REG_AL:
+ case CV_REG_CL:
+ case CV_REG_DL:
+ case CV_REG_BL:
+ case CV_REG_AH:
+ case CV_REG_CH:
+ case CV_REG_DH:
+ case CV_REG_BH:
+
+ (LPB) lpvRegValue += sizeof ( BYTE );
+ break;
+
+ case CV_REG_AX:
+ case CV_REG_CX:
+ case CV_REG_DX:
+ case CV_REG_BX:
+ case CV_REG_SP:
+ case CV_REG_BP:
+ case CV_REG_SI:
+ case CV_REG_DI:
+ case CV_REG_IP:
+ case CV_REG_FLAGS:
+ case CV_REG_ES:
+ case CV_REG_CS:
+ case CV_REG_SS:
+ case CV_REG_DS:
+ case CV_REG_FS:
+ case CV_REG_GS:
+ case CV_REG_FPCS:
+ case CV_REG_FPDS:
+ case CV_REG_CTRL:
+ case CV_REG_STAT:
+ case CV_REG_TAG:
+ case CV_REG_FPIP:
+ case CV_REG_FPDO:
+
+ case CV_REG_GDTL:
+ case CV_REG_IDTL:
+ case CV_REG_LDTR:
+ case CV_REG_TR:
+
+ (LPB) lpvRegValue += sizeof ( WORD );
+ break;
+
+ case CV_REG_EAX:
+ case CV_REG_ECX:
+ case CV_REG_EDX:
+ case CV_REG_EBX:
+ case CV_REG_ESP:
+ case CV_REG_EBP:
+ case CV_REG_ESI:
+ case CV_REG_EDI:
+ case CV_REG_EIP:
+ case CV_REG_EFLAGS:
+ case CV_REG_FPEIP:
+ case CV_REG_FPEDO:
+
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+
+ case CV_REG_DR0:
+ case CV_REG_DR1:
+ case CV_REG_DR2:
+ case CV_REG_DR3:
+ case CV_REG_DR4:
+ case CV_REG_DR5:
+ case CV_REG_DR6:
+ case CV_REG_DR7:
+
+ case CV_REG_GDTR:
+ case CV_REG_IDTR:
+
+ (LPB) lpvRegValue += sizeof ( LONG );
+ break;
+
+ case CV_REG_ST0:
+ case CV_REG_ST1:
+ case CV_REG_ST2:
+ case CV_REG_ST3:
+ case CV_REG_ST4:
+ case CV_REG_ST5:
+ case CV_REG_ST6:
+ case CV_REG_ST7:
+
+ (LPB) lpvRegValue += sizeof ( L_DOUBLE );
+ break;
+
+ default:
+ lpvRegValue = NULL;
+ break;
+ }
+
+ return lpvRegValue;
+} /* DoGetReg() */
+
+
+LPV
+DoSetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to set a specific register in a threads
+ context
+
+Arguments:
+
+ lpregs - Supplies pointer to register context for thread
+ ireg - Supplies the index of the register to be modified
+ lpvRegValue - Supplies the buffer containning the new data
+
+Return Value:
+
+ return-value - the pointer the the next location where a register
+ value could be.
+
+--*/
+
+{
+ int i;
+
+ switch ( ireg ) {
+
+ case CV_REG_AL:
+ lpregs->Eax = (lpregs->Eax & 0xFFFFFF00) | *( (LPB) lpvRegValue );
+ break;
+
+ case CV_REG_CL:
+ lpregs->Ecx = (lpregs->Ecx & 0xFFFFFF00) | *( (LPB) lpvRegValue );
+ break;
+
+ case CV_REG_DL:
+ lpregs->Edx = (lpregs->Edx & 0xFFFFFF00) | *( (LPB) lpvRegValue );
+ break;
+
+ case CV_REG_BL:
+ lpregs->Ebx = (lpregs->Ebx & 0xFFFFFF00) | *( (LPB) lpvRegValue );
+ break;
+
+ case CV_REG_AH:
+ lpregs->Eax = (lpregs->Eax & 0xFFFF00FF) |
+ (((WORD) *( (LPB) lpvRegValue )) << 8);
+ break;
+
+ case CV_REG_CH:
+ lpregs->Ecx = (lpregs->Ecx & 0xFFFF00FF) |
+ (((WORD) *( (LPB) lpvRegValue )) << 8);
+ break;
+
+ case CV_REG_DH:
+ lpregs->Edx = (lpregs->Edx & 0xFFFF00FF) |
+ (((WORD) *( (LPB) lpvRegValue )) << 8);
+ break;
+
+ case CV_REG_BH:
+ lpregs->Ebx = (lpregs->Ebx & 0xFFFF00FF) |
+ (((WORD) *( (LPB) lpvRegValue )) << 8);
+ break;
+
+ case CV_REG_AX:
+ lpregs->Eax = (lpregs->Eax & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_CX:
+ lpregs->Ecx = (lpregs->Ecx & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_DX:
+ lpregs->Edx = (lpregs->Edx & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_BX:
+ lpregs->Ebx = (lpregs->Ebx & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_SP:
+ lpregs->Esp = (lpregs->Esp & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_BP:
+ lpregs->Ebp = (lpregs->Ebp & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_SI:
+ lpregs->Esi = (lpregs->Esi & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_DI:
+ lpregs->Edi = (lpregs->Edi & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_IP:
+ lpregs->Eip = (lpregs->Eip & 0xFFFF0000) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FLAGS:
+ lpregs->EFlags = (lpregs->EFlags & 0xFFFF0000 ) | *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_ES:
+ lpregs->SegEs = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_CS:
+ lpregs->SegCs = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_SS:
+ lpregs->SegSs = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_DS:
+ lpregs->SegDs = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FS:
+ lpregs->SegFs = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_GS:
+ lpregs->SegGs = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_EAX:
+ lpregs->Eax = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_ECX:
+ lpregs->Ecx = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_EDX:
+ lpregs->Edx = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_EBX:
+ lpregs->Ebx = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_ESP:
+ lpregs->Esp = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_EBP:
+ lpregs->Ebp = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_ESI:
+ lpregs->Esi = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_EDI:
+ lpregs->Edi = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_EIP:
+ lpregs->Eip = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_EFLAGS:
+ lpregs->EFlags = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_ST0:
+ case CV_REG_ST1:
+ case CV_REG_ST2:
+ case CV_REG_ST3:
+ case CV_REG_ST4:
+ case CV_REG_ST5:
+ case CV_REG_ST6:
+ case CV_REG_ST7:
+// i = (lpregs->FloatSave.StatusWord >> 11) & 0x7;
+// i = (i + ireg - CV_REG_ST0) % 8;
+ i = ireg - CV_REG_ST0;
+ memcpy(&lpregs->FloatSave.RegisterArea[10*(i)], lpvRegValue, 10);
+ break;
+
+ case CV_REG_CTRL:
+ lpregs->FloatSave.ControlWord = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_STAT:
+ lpregs->FloatSave.StatusWord = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_TAG:
+ lpregs->FloatSave.TagWord = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FPIP:
+ lpregs->FloatSave.ErrorOffset = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FPEIP:
+ lpregs->FloatSave.ErrorOffset = *( (LPL) lpvRegValue );
+ break;
+
+ case CV_REG_FPCS:
+ lpregs->FloatSave.ErrorSelector = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FPDO:
+ lpregs->FloatSave.DataOffset = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FPEDO:
+ lpregs->FloatSave.DataOffset = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_FPDS:
+ lpregs->FloatSave.DataSelector = *( (LPW) lpvRegValue );
+ break;
+
+#define lpsr ((PKSPECIAL_REGISTERS)lpregs)
+ case CV_REG_GDTR:
+ lpsr->Gdtr.Base = *( (LPDWORD) lpvRegValue );
+ break;
+
+ case CV_REG_GDTL:
+ lpsr->Gdtr.Limit = *( (LPWORD) lpvRegValue );
+ break;
+
+ case CV_REG_IDTR:
+ lpsr->Idtr.Base = *( (LPDWORD) lpvRegValue );
+ break;
+
+ case CV_REG_IDTL:
+ lpsr->Idtr.Limit = *( (LPWORD) lpvRegValue );
+ break;
+
+ case CV_REG_LDTR:
+ lpsr->Ldtr = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_TR:
+ lpsr->Tr = *( (LPW) lpvRegValue );
+ break;
+
+ case CV_REG_CR0:
+ lpsr->Cr0 = *( (LPDWORD) lpvRegValue );
+ break;
+
+ case CV_REG_CR2:
+ lpsr->Cr2 = *( (LPDWORD) lpvRegValue );
+ break;
+
+ case CV_REG_CR3:
+ lpsr->Cr3 = *( (LPDWORD) lpvRegValue );
+ break;
+
+ case CV_REG_CR4:
+ lpsr->Cr4 = *( (LPDWORD) lpvRegValue );
+ break;
+#undef lpsr
+
+ case CV_REG_DR0:
+ lpregs->Dr0 = *( (PULONG) lpvRegValue );
+ break;
+
+ case CV_REG_DR1:
+ lpregs->Dr1 = *( (PULONG) lpvRegValue );
+ break;
+
+ case CV_REG_DR2:
+ lpregs->Dr2 = *( (PULONG) lpvRegValue );
+ break;
+
+ case CV_REG_DR3:
+ lpregs->Dr3 = *( (PULONG) lpvRegValue );
+ break;
+
+ case CV_REG_DR6:
+ lpregs->Dr6 = *( (PULONG) lpvRegValue );
+ break;
+
+ case CV_REG_DR7:
+ lpregs->Dr7 = *( (PULONG) lpvRegValue );
+
+ }
+
+
+ switch ( ireg ) {
+
+ case CV_REG_AL:
+ case CV_REG_CL:
+ case CV_REG_DL:
+ case CV_REG_BL:
+ case CV_REG_AH:
+ case CV_REG_CH:
+ case CV_REG_DH:
+ case CV_REG_BH:
+
+ (LPB) lpvRegValue += sizeof ( BYTE );
+ break;
+
+ case CV_REG_AX:
+ case CV_REG_CX:
+ case CV_REG_DX:
+ case CV_REG_BX:
+ case CV_REG_SP:
+ case CV_REG_BP:
+ case CV_REG_SI:
+ case CV_REG_DI:
+ case CV_REG_IP:
+ case CV_REG_FLAGS:
+ case CV_REG_ES:
+ case CV_REG_CS:
+ case CV_REG_SS:
+ case CV_REG_DS:
+ case CV_REG_FS:
+ case CV_REG_GS:
+ case CV_REG_CTRL:
+ case CV_REG_STAT:
+ case CV_REG_TAG:
+ case CV_REG_FPIP:
+ case CV_REG_FPCS:
+ case CV_REG_FPDO:
+ case CV_REG_FPDS:
+ case CV_REG_GDTL:
+ case CV_REG_IDTL:
+ case CV_REG_LDTR:
+ case CV_REG_TR:
+
+ (LPB) lpvRegValue += sizeof ( WORD );
+ break;
+
+ case CV_REG_EAX:
+ case CV_REG_ECX:
+ case CV_REG_EDX:
+ case CV_REG_EBX:
+ case CV_REG_ESP:
+ case CV_REG_EBP:
+ case CV_REG_ESI:
+ case CV_REG_EDI:
+ case CV_REG_EIP:
+ case CV_REG_EFLAGS:
+ case CV_REG_FPEIP:
+ case CV_REG_FPEDO:
+ case CV_REG_CR0:
+ case CV_REG_CR1:
+ case CV_REG_CR2:
+ case CV_REG_CR3:
+ case CV_REG_CR4:
+ case CV_REG_DR0:
+ case CV_REG_DR1:
+ case CV_REG_DR2:
+ case CV_REG_DR3:
+ case CV_REG_DR4:
+ case CV_REG_DR5:
+ case CV_REG_DR6:
+ case CV_REG_DR7:
+ case CV_REG_GDTR:
+ case CV_REG_IDTR:
+
+ (LPB) lpvRegValue += sizeof ( LONG );
+ break;
+
+ case CV_REG_ST0:
+ case CV_REG_ST1:
+ case CV_REG_ST2:
+ case CV_REG_ST3:
+ case CV_REG_ST4:
+ case CV_REG_ST5:
+ case CV_REG_ST6:
+ case CV_REG_ST7:
+
+ (LPB) lpvRegValue += sizeof ( L_DOUBLE );
+ break;
+
+ default:
+
+ lpvRegValue = NULL;
+ break;
+ }
+
+ return lpvRegValue;
+} /* DoSetReg() */
+
+
+
+LPV
+DoSetFrameReg(
+ HPID hpid,
+ HTID htid,
+ LPTHD lpthd,
+ PKNONVOLATILE_CONTEXT_POINTERS contextPtrs,
+ DWORD ireg,
+ LPV lpvRegValue
+ )
+{
+
+ return DoSetReg(&lpthd->regs, ireg, lpvRegValue);
+}
+
+XOSD
+GetFlagValue (
+ HPID hpid,
+ HTID htid,
+ DWORD iFlag,
+ LPV lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPCONTEXT lpregs;
+ LONG l;
+ UINT cbytes;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+ hthd = HthdFromHtid(hprc, htid);
+
+ assert ( hthd != hthdNull );
+ lpthd = LLLock( hthd );
+
+ lpregs = &lpthd->regs;
+
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &l ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidRegister;
+ }
+
+ l = l >> Rgfd[iFlag].iShift;
+ l &= (1 << Rgfd[iFlag].fd.cbits) - 1;
+ cbytes = (Rgfd[iFlag].fd.cbits <= 8) ? 1 : ((Rgfd[iFlag].fd.cbits + 15)/16 * 2);
+ switch (cbytes ) {
+ case 1:
+ *((BYTE FAR *) lpvRegValue) = (BYTE) l;
+ break;
+
+ case 2:
+ *((USHORT FAR *) lpvRegValue) = (USHORT) l;
+ break;
+
+ case 4:
+ *((ULONG FAR *) lpvRegValue) = (ULONG) l;
+ break;
+
+ default:
+ assert(FALSE);
+
+ break;
+ }
+ LLUnlock( hthd );
+ return xosdNone;
+}
+
+
+#ifndef OSDEBUG4
+
+XOSD
+StackWalkSetup(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to setup the StackWalk Structure.
+ This routine will defer the processing to the dm
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk
+
+ hthd - Supplies handle to thread to stack walk
+
+ lpstkframe - Supplies pointer the stack walk structure
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ ADDRESS_MODE mode;
+ ULONG ul;
+
+
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == hthdNull) {
+ return xosdInvalidThread;
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (lpthd->drt & (drtCntrlDirty|drtAllDirty)) {
+ SendRequestX(dmfWriteReg, hpid, htid, sizeof(CONTEXT), &lpthd->regs);
+ lpthd->drt &= ~(drtCntrlDirty|drtAllDirty);
+ }
+
+ UpdateRegisters( hprc, hthd );
+ GetRegValue( hpid, htid, CV_REG_EBP, &ul);
+
+ //
+ // set the addressing mode
+ //
+ if (lpthd->fFlat) {
+ mode = AddrModeFlat;
+ } else
+ if (lpthd->fReal) {
+ mode = AddrModeReal;
+ } else
+ if (lpthd->fOff32) {
+ mode = AddrMode1632;
+ } else {
+ mode = AddrMode1616;
+ }
+
+ //
+ // setup the program counter
+ //
+ if (!lpstkframe->AddrPC.Offset) {
+ if (mode == AddrModeFlat) {
+ lpstkframe->AddrPC.Offset = lpthd->regs.Eip;
+ } else {
+ lpstkframe->AddrPC.Offset = (WORD)lpthd->regs.Eip;
+ }
+ lpstkframe->AddrPC.Segment = (WORD)lpthd->regs.SegCs;
+ lpstkframe->AddrPC.Mode = mode;
+ }
+
+ //
+ // setup the frame pointer
+ //
+ if (!lpstkframe->AddrFrame.Offset) {
+ if (mode == AddrModeFlat) {
+ lpstkframe->AddrFrame.Offset = lpthd->regs.Ebp;
+ } else {
+ lpstkframe->AddrFrame.Offset = (WORD)lpthd->regs.Ebp;
+ }
+ lpstkframe->AddrFrame.Segment = (WORD)lpthd->regs.SegSs;
+ lpstkframe->AddrFrame.Mode = mode;
+ }
+
+ //
+ // setup the stack pointer
+ //
+ if (!lpstkframe->AddrStack.Offset) {
+ if (mode == AddrModeFlat) {
+ lpstkframe->AddrStack.Offset = lpthd->regs.Esp;
+ } else {
+ lpstkframe->AddrStack.Offset = (WORD)lpthd->regs.Esp;
+ }
+ lpstkframe->AddrStack.Segment = (WORD)lpthd->regs.SegSs;
+ lpstkframe->AddrStack.Mode = mode;
+ }
+
+ LLUnlock( hthd );
+
+ if (StackWalk( IMAGE_FILE_MACHINE_I386,
+ hpid,
+ htid,
+ lpstkframe,
+ NULL,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ SwGetModuleBase,
+ SwTranslateAddress
+ )) {
+
+ return xosdNone;
+
+ }
+
+ return xosdEndOfStack;
+} /* StackWalkSetup() */
+
+
+XOSD
+StackWalkNext(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to move up a level in the call stack.
+ We defer down to the DM to do this.
+
+Arguments:
+
+ hpid - Supplies process handle to stack walk
+ htid - Supplies thread handle to stack walk
+ lpstkframe - Supplies pointer to stack walk data
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ if (StackWalk( IMAGE_FILE_MACHINE_I386,
+ hpid,
+ htid,
+ lpstkframe,
+ NULL,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ SwGetModuleBase,
+ SwTranslateAddress
+ )) {
+
+ return xosdNone;
+
+ }
+
+ return xosdEndOfStack;
+} /* StackWalkNext() */
+
+#endif
+
+PFPO_DATA
+SwSearchFpoData(
+ DWORD key,
+ PFPO_DATA base,
+ DWORD num
+ )
+{
+ PFPO_DATA lo = base;
+ PFPO_DATA hi = base + (num - 1);
+ PFPO_DATA mid;
+ DWORD half;
+
+ while (lo <= hi) {
+ if (half = num / 2) {
+ mid = lo + ((num & 1) ? half : (half - 1));
+ if ((key >= mid->ulOffStart)&&(key < (mid->ulOffStart+mid->cbProcSize))) {
+ return mid;
+ }
+ if (key < mid->ulOffStart) {
+ hi = mid - 1;
+ num = (num & 1) ? half : half-1;
+ }
+ else {
+ lo = mid + 1;
+ num = half;
+ }
+ }
+ else
+ if (num) {
+ if ((key >= lo->ulOffStart)&&(key < (lo->ulOffStart+lo->cbProcSize))) {
+ return lo;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ return(NULL);
+}
+
+LPVOID
+SwFunctionTableAccess(
+ HPID hpid,
+ DWORD AddrBase
+ )
+{
+ HLLI hlli = 0;
+ HMDI hmdi = 0;
+ LPMDI lpmdi = 0;
+ DWORD off;
+ PFPO_DATA pFpo;
+
+
+ hmdi = SwGetMdi( hpid, AddrBase );
+ if (!hmdi) {
+ return NULL;
+ }
+
+ lpmdi = LLLock( hmdi );
+
+ if (lpmdi && lpmdi->lpDebug) {
+ off = ConvertOmapToSrc( lpmdi, AddrBase );
+ if (off) {
+ AddrBase = off;
+ }
+ pFpo = SwSearchFpoData( AddrBase - lpmdi->lpBaseOfDll,
+ lpmdi->lpDebug->lpFpo,
+ lpmdi->lpDebug->cRtf
+ );
+ LLUnlock( hmdi );
+ if (pFpo) {
+ return (LPVOID)pFpo;
+ }
+ } else {
+ LLUnlock( hmdi );
+ }
+
+ return NULL;
+}
+
+
+DWORD
+SwTranslateAddress(
+ HPID hpid,
+ HTID htid,
+ LPADDRESS lpaddress
+ )
+{
+ XOSD xosd;
+ ADDR addr;
+ BYTE buf[256];
+ LPIOL lpiol = (LPIOL)buf;
+ PIOCTLGENERIC pig = (PIOCTLGENERIC)lpiol->rgbVar;
+
+
+ ZeroMemory( &addr, sizeof(addr) );
+ addr.addr.off = lpaddress->Offset;
+ addr.addr.seg = lpaddress->Segment;
+ addr.mode.fFlat = lpaddress->Mode == AddrModeFlat;
+ addr.mode.fOff32 = lpaddress->Mode == AddrMode1632;
+ addr.mode.fReal = lpaddress->Mode == AddrModeReal;
+
+ memcpy( pig->data, &addr, sizeof(addr) );
+ lpiol->wFunction = ioctlGeneric;
+ pig->length = sizeof(addr) + 4;
+ pig->ioctlSubType = IG_TRANSLATE_ADDRESS;
+
+ xosd = IoctlCmd( hpid, htid, pig->length+sizeof(*pig), lpiol );
+
+ if (xosd == xosdNone) {
+ addr = *((LPADDR)pig->data);
+
+ lpaddress->Offset = addr.addr.off;
+ lpaddress->Segment = addr.addr.seg;
+
+ if (addr.mode.fFlat) {
+ lpaddress->Mode = AddrModeFlat;
+ } else
+ if (addr.mode.fOff32) {
+ lpaddress->Mode == AddrMode1632;
+ } else
+ if (addr.mode.fReal) {
+ lpaddress->Mode == AddrModeReal;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL
+SwReadMemory(
+ HPID hpid,
+ LPCVOID lpBaseAddress,
+ LPVOID lpBuffer,
+ DWORD nSize,
+ LPDWORD lpNumberOfBytesRead
+ )
+{
+ ADDR addr;
+ DWORD cb;
+ XOSD xosd;
+ BYTE buf[256];
+ LPIOL lpiol;
+ PIOCTLGENERIC pig;
+ PREADCONTROLSPACE prc;
+
+
+ if ((LONG)lpNumberOfBytesRead == -1) {
+
+ lpiol = (LPIOL)buf;
+ pig = (PIOCTLGENERIC)lpiol->rgbVar;
+ prc = (PREADCONTROLSPACE) pig->data;
+
+ prc->Processor = (USHORT)-1;
+ prc->Address = (DWORD)lpBaseAddress;
+ prc->BufLen = nSize;
+
+ lpiol->wFunction = ioctlGeneric;
+ pig->length = sizeof(*prc) + nSize;
+ pig->ioctlSubType = IG_READ_CONTROL_SPACE;
+
+ xosd = IoctlCmd( hpid, htidNull, pig->length+sizeof(*pig), lpiol );
+ if (xosd == xosdNone) {
+ memcpy( lpBuffer, prc->Buf, nSize );
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+ addr.addr.off = (OFFSET)lpBaseAddress;
+ addr.addr.seg = 0;
+ addr.emi = 0;
+ addr.mode.fFlat = TRUE;
+ addr.mode.fOff32 = FALSE;
+ addr.mode.fIsLI = FALSE;
+ addr.mode.fReal = FALSE;
+
+ xosd = ReadBuffer( hpid, NULL, &addr, nSize, lpBuffer, &cb );
+ if (xosd != xosdNone) {
+ return FALSE;
+ }
+
+ if (lpNumberOfBytesRead) {
+ *lpNumberOfBytesRead = cb;
+ }
+
+ return TRUE;
+}
+
+
+
+XOSD
+SetFrame(
+ HPID hpid,
+ HTID htid,
+ PFRAME pframe
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to setup the StackWalk Structure.
+ This routine will fill in the first stack walk structure element.
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk in
+ hthd - Supplies handle to thread to stack walk in
+ pframe - Supplies pointer to the frame structure to fill in
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ ULONG ul;
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+
+ hprc = ValidHprcFromHpid( hpid );
+ if (!hprc) {
+ return xosdInvalidProc;
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == hthdNull) {
+ return xosdInvalidThread;
+ }
+
+ lpthd = LLLock( hthd );
+
+ FrameFlat ( *pframe ) = lpthd->fFlat;
+ FrameOff32 ( *pframe ) = lpthd->fOff32;
+ FrameReal (*pframe ) = lpthd->fReal;
+
+ if (lpthd->fOff32) {
+ GetRegValue( hpid, htid, CV_REG_EBP, &ul);
+ } else {
+ GetRegValue( hpid, htid, CV_REG_BP, &ul);
+ ul &= 0xffff;
+ }
+ SetFrameBPOff ( *pframe, (UOFFSET) ul );
+
+ GetRegValue( hpid, htid, CV_REG_SS, &ul);
+ SetFrameBPSeg ( *pframe, (USHORT) ul);
+ pframe->SS = (USHORT) ul;
+ GetRegValue( hpid, htid, CV_REG_DS, &ul);
+ pframe->DS = (USHORT) ul;
+ pframe->PID = hpid;
+ pframe->TID = htid;
+
+ return xosdNone;
+} /* SetFrame() */
+
+
+
+
+
+XOSD
+SetPath(
+ HPID hpid,
+ HTID htid,
+ BOOL Set,
+ LSZ Path
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path in the DM
+
+Arguments:
+
+ hpid - process
+ htid - thread
+ Set - set flag
+ Path - Path to search, PATH if null
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ char Buffer[ MAX_PATH ];
+ SETPTH *SetPth = (SETPTH *)&Buffer;
+
+ if ( Set ) {
+
+ SetPth->Set = TRUE;
+ if ( Path ) {
+ strcpy(SetPth->Path, Path );
+ } else {
+ SetPth->Path[0] = '\0';
+ }
+ } else {
+ SetPth->Set = FALSE;
+ SetPth->Path[0] = '\0';
+ }
+
+ return SendRequestX( dmfSetPath, hpid, htid, sizeof(SETPTH) + strlen(SetPth->Path), SetPth );
+}
+
+
+XOSD
+GetFunctionInfo(
+ HPID hpid,
+ PADDR Addr,
+ PFUNCTION_INFO FunctionInfo
+ )
+/*++
+
+Routine Description:
+
+ Gets function information for a particular address.
+
+Arguments:
+
+ hpid - process
+ Addr - Address
+ FunctionInfo - Function information
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+{
+ UNREFERENCED_PARAMETER( Addr );
+ UNREFERENCED_PARAMETER( FunctionInfo );
+
+ return xosdUnknown;
+}
diff --git a/private/windbg/em/p_i386/emx86.def b/private/windbg/em/p_i386/emx86.def
new file mode 100644
index 000000000..69f2d9c2e
--- /dev/null
+++ b/private/windbg/em/p_i386/emx86.def
@@ -0,0 +1,4 @@
+LIBRARY emx86 initinstance
+EXPORTS
+ DBGVersionCheck PRIVATE
+ EMFunc PRIVATE
diff --git a/private/windbg/em/p_i386/flags.h b/private/windbg/em/p_i386/flags.h
new file mode 100644
index 000000000..19eddfd63
--- /dev/null
+++ b/private/windbg/em/p_i386/flags.h
@@ -0,0 +1,9 @@
+ { SzOverflow, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 11 },
+ { SzDirection, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 10 },
+ { SzInterrupt, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 9 },
+ { SzTrap, ftInvisible, 1, CV_REG_FLAGS, 8 },
+ { SzSign, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 7 },
+ { SzZero, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 6 },
+ { SzACarry, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 4 },
+ { SzParity, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 2 },
+ { SzCarry, ftRegular|ftRegularExt, 1, CV_REG_FLAGS, 0 },
diff --git a/private/windbg/em/p_i386/makefile b/private/windbg/em/p_i386/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/em/p_i386/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/em/p_i386/makefile.inc b/private/windbg/em/p_i386/makefile.inc
new file mode 100644
index 000000000..18cb3a0cd
--- /dev/null
+++ b/private/windbg/em/p_i386/makefile.inc
@@ -0,0 +1,27 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
+
+obj\$(TARGET_DIRECTORY)\d3em.obj: d3.c
diff --git a/private/windbg/em/p_i386/precomp.h b/private/windbg/em/p_i386/precomp.h
new file mode 100644
index 000000000..0e4a17773
--- /dev/null
+++ b/private/windbg/em/p_i386/precomp.h
@@ -0,0 +1,67 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <biavst.h>
+
+#include <windows.h>
+#include <dde.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <memory.h>
+#include <string.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#ifdef OSDEBUG4
+
+#include "od.h"
+#include "odp.h"
+#include "emdm.h"
+
+#include "emdata.h"
+#include "emproto.h"
+
+#include "dbgver.h"
+
+#else // OSDEBUG4
+
+#include "defs.h"
+
+#include "mm.h"
+#include "ll.h"
+#include "tl.h"
+#include "od.h"
+#include "dbgver.h"
+#include "emdm.h"
+#include "osdem.h"
+#include "emdata.h"
+#include "emproto.h"
+#include "osassert.h"
+
+#include "lbhpt.h"
+#include "llhpt.h"
+#include "mhhpt.h"
+
+#endif // OSDEBUG4
+#define NOEXTAPI
+#include <wdbgexts.h>
diff --git a/private/windbg/em/p_i386/regs.h b/private/windbg/em/p_i386/regs.h
new file mode 100644
index 000000000..6cc0498d9
--- /dev/null
+++ b/private/windbg/em/p_i386/regs.h
@@ -0,0 +1,71 @@
+ { SzAH, rtCPU | rtInvisible | rtInteger, 8, CV_REG_AH },
+ { SzAL, rtCPU | rtInvisible | rtInteger, 8, CV_REG_AL },
+ { SzAX, rtCPU | rtRegular | rtInteger, 16, CV_REG_AX },
+ { SzEAX, rtCPU | rtExtended | rtInteger, 32, CV_REG_EAX },
+ { SzBH, rtCPU | rtInvisible | rtInteger, 8, CV_REG_BH },
+ { SzBL, rtCPU | rtInvisible | rtInteger, 8, CV_REG_BL },
+ { SzBX, rtCPU | rtRegular | rtInteger, 16, CV_REG_BX },
+ { SzEBX, rtCPU | rtExtended | rtInteger, 32, CV_REG_EBX },
+ { SzCH, rtCPU | rtInvisible | rtInteger, 8, CV_REG_CH },
+ { SzCL, rtCPU | rtInvisible | rtInteger, 8, CV_REG_CL },
+ { SzCX, rtCPU | rtRegular | rtInteger, 16, CV_REG_CX },
+ { SzECX, rtCPU | rtExtended | rtInteger, 32, CV_REG_ECX },
+ { SzDH, rtCPU | rtInvisible | rtInteger, 8, CV_REG_DH },
+ { SzDL, rtCPU | rtInvisible | rtInteger, 8, CV_REG_DL },
+ { SzDX, rtCPU | rtRegular | rtInteger, 16, CV_REG_DX },
+ { SzEDX, rtCPU | rtExtended | rtInteger, 32, CV_REG_EDX },
+ { SzSI, rtCPU | rtRegular | rtInteger, 16, CV_REG_SI },
+ { SzESI, rtCPU | rtExtended | rtInteger, 32, CV_REG_ESI },
+ { SzDI, rtCPU | rtRegular | rtInteger, 16, CV_REG_DI },
+ { SzEDI, rtCPU | rtExtended | rtInteger, 32, CV_REG_EDI },
+
+ { SzIP, rtCPU | rtRegular | rtInteger | rtPC | rtNewLine, 16, CV_REG_IP },
+ { SzEIP, rtCPU | rtExtended | rtInteger | rtPC | rtNewLine, 32, CV_REG_EIP },
+ { SzSP, rtCPU | rtRegular | rtInteger | rtFrame, 16, CV_REG_SP },
+ { SzESP, rtCPU | rtExtended | rtInteger | rtFrame, 32, CV_REG_ESP },
+ { SzBP, rtCPU | rtRegular | rtInteger | rtFrame, 16, CV_REG_BP },
+ { SzEBP, rtCPU | rtExtended | rtInteger | rtFrame, 32, CV_REG_EBP },
+ { SzFlags, rtCPU | rtRegular | rtInteger, 16, CV_REG_FLAGS },
+ { SzEFlags, rtCPU | rtExtended | rtInteger, 32, CV_REG_EFLAGS },
+
+ { SzCS, rtCPU | rtExtended | rtRegular | rtInteger | rtPC | rtNewLine, 16, CV_REG_CS },
+ { SzDS, rtCPU | rtExtended | rtRegular | rtInteger, 16, CV_REG_DS },
+ { SzES, rtCPU | rtExtended | rtRegular | rtInteger, 16, CV_REG_ES },
+ { SzSS, rtCPU | rtExtended | rtRegular | rtInteger | rtFrame, 16, CV_REG_SS },
+ { SzFS, rtCPU | rtExtended | rtRegular | rtInteger, 16, CV_REG_FS },
+ { SzGS, rtCPU | rtExtended | rtRegular | rtInteger, 16, CV_REG_GS },
+
+ { SzCr0, rtCPU | rtSpecial | rtInteger | rtNewLine, 32, CV_REG_CR0 },
+ { SzCr2, rtCPU | rtSpecial | rtInteger, 32, CV_REG_CR2 },
+ { SzCr3, rtCPU | rtSpecial | rtInteger, 32, CV_REG_CR3 },
+ { SzCr4, rtCPU | rtSpecial | rtInteger, 32, CV_REG_CR4 },
+ { SzDr0, rtCPU | rtSpecial | rtInteger | rtNewLine, 32, CV_REG_DR0 },
+ { SzDr1, rtCPU | rtSpecial | rtInteger, 32, CV_REG_DR1 },
+ { SzDr2, rtCPU | rtSpecial | rtInteger, 32, CV_REG_DR2 },
+ { SzDr3, rtCPU | rtSpecial | rtInteger, 32, CV_REG_DR3 },
+ { SzDr6, rtCPU | rtSpecial | rtInteger, 32, CV_REG_DR6 },
+ { SzDr7, rtCPU | rtSpecial | rtInteger, 32, CV_REG_DR7 },
+ { SzGdtr, rtCPU | rtSpecial | rtInteger | rtNewLine, 32, CV_REG_GDTR },
+ { SzGdtl, rtCPU | rtSpecial | rtInteger, 16, CV_REG_GDTL },
+ { SzIdtr, rtCPU | rtSpecial | rtInteger, 32, CV_REG_IDTR },
+ { SzIdtl, rtCPU | rtSpecial | rtInteger, 16, CV_REG_IDTL },
+ { SzTr, rtCPU | rtSpecial | rtInteger, 16, CV_REG_TR },
+ { SzLdtr, rtCPU | rtSpecial | rtInteger, 16, CV_REG_LDTR },
+
+ { SzST0, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST0 },
+ { SzST1, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST1 },
+ { SzST2, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST2 },
+ { SzST3, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST3 },
+ { SzST4, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST4 },
+ { SzST5, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST5 },
+ { SzST6, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST6 },
+ { SzST7, rtFPU | rtRegular | rtExtended | rtFloat, 80, CV_REG_ST7 },
+ { SzCtrl, rtFPU | rtRegular | rtExtended | rtInteger | rtNewLine, 16, CV_REG_CTRL },
+ { SzStat, rtFPU | rtRegular | rtExtended | rtInteger, 16, CV_REG_STAT },
+ { SzTag, rtFPU | rtRegular | rtExtended | rtInteger, 16, CV_REG_TAG },
+ { SzFpIp, rtFPU | rtRegular | rtInteger, 16, CV_REG_FPIP },
+ { SzFpEip, rtFPU | rtExtended | rtInteger, 32, CV_REG_FPEIP },
+ { SzFpCs, rtFPU | rtRegular | rtExtended | rtInteger | rtNewLine, 16, CV_REG_FPCS },
+ { SzFpDs, rtFPU | rtRegular | rtExtended | rtInteger, 16, CV_REG_FPDS },
+ { SzFpEdo, rtFPU | rtExtended | rtInteger, 32, CV_REG_FPEDO },
+ { SzFpDo, rtFPU | rtRegular | rtInteger, 16, CV_REG_FPDO }
diff --git a/private/windbg/em/p_i386/sources b/private/windbg/em/p_i386/sources
new file mode 100644
index 000000000..4f2116805
--- /dev/null
+++ b/private/windbg/em/p_i386/sources
@@ -0,0 +1,63 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=emx86
+
+TARGETNAME=emx86
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+DLLENTRY=DllInit
+
+SOURCES= \
+ asm.c \
+ asmexp.c \
+ asmtpl.c \
+ d3em.c \
+ emdp.c \
+ emdp2.c \
+ emdp3.c \
+ emdpdev.c \
+ strings.c \
+ wintrans.c \
+ em.rc
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_i386
+
+INCLUDES=..;..\..\osdebug\include;..\..\osdebug
+
+CONDITIONAL_INCLUDES=odp.h win32msg.h xosd.h
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/em/p_i386/strings.c b/private/windbg/em/p_i386/strings.c
new file mode 100644
index 000000000..62c352bbd
--- /dev/null
+++ b/private/windbg/em/p_i386/strings.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\strings.c"
diff --git a/private/windbg/em/p_i386/strings.h b/private/windbg/em/p_i386/strings.h
new file mode 100644
index 000000000..0da54c1b2
--- /dev/null
+++ b/private/windbg/em/p_i386/strings.h
@@ -0,0 +1,119 @@
+/*
+** STRINGS.H
+**
+** This file contains all strings which are used in the EM for display
+** purposes. This is done for internationalization purposes.
+**
+** strings.c defines DEFINE_STRINGS before including this file. Other
+** source files just include this file normally.
+*/
+
+/*
+** strings.c should define DEFINE_STRINGS before including this file,
+** so that the strings will be defined rather than just declared.
+*/
+
+#ifdef DEFINE_STRINGS
+ #define DECL_STR(name, value) char name[] = value
+#else
+ #define DECL_STR(name, value) extern char name[]
+#endif
+
+DECL_STR(SzAH, "AH");
+DECL_STR(SzAL, "AL");
+DECL_STR(SzAX, "AX");
+DECL_STR(SzEAX, "EAX");
+DECL_STR(SzBH, "BH");
+DECL_STR(SzBL, "BL");
+DECL_STR(SzBX, "BX");
+DECL_STR(SzEBX, "EBX");
+DECL_STR(SzCH, "CH");
+DECL_STR(SzCL, "CL");
+DECL_STR(SzCX, "CX");
+DECL_STR(SzECX, "ECX");
+DECL_STR(SzDH, "DH");
+DECL_STR(SzDL, "DL");
+DECL_STR(SzDX, "DX");
+DECL_STR(SzEDX, "EDX");
+DECL_STR(SzSI, "SI");
+DECL_STR(SzESI, "ESI");
+DECL_STR(SzDI, "DI");
+DECL_STR(SzEDI, "EDI");
+DECL_STR(SzSP, "SP");
+DECL_STR(SzESP, "ESP");
+DECL_STR(SzBP, "BP");
+DECL_STR(SzEBP, "EBP");
+DECL_STR(SzIP, "IP");
+DECL_STR(SzEIP, "EIP");
+DECL_STR(SzFlags, "FL");
+DECL_STR(SzEFlags, "EFL");
+DECL_STR(SzCS, "CS");
+DECL_STR(SzDS, "DS");
+DECL_STR(SzES, "ES");
+DECL_STR(SzSS, "SS");
+DECL_STR(SzFS, "FS");
+DECL_STR(SzGS, "GS");
+DECL_STR(SzST0, "ST0");
+DECL_STR(SzST1, "ST1");
+DECL_STR(SzST2, "ST2");
+DECL_STR(SzST3, "ST3");
+DECL_STR(SzST4, "ST4");
+DECL_STR(SzST5, "ST5");
+DECL_STR(SzST6, "ST6");
+DECL_STR(SzST7, "ST7");
+DECL_STR(SzCtrl, "CTRL");
+DECL_STR(SzStat, "STAT");
+DECL_STR(SzTag, "TAGS");
+DECL_STR(SzFpIp, "IP");
+DECL_STR(SzFpEip, "EIP");
+DECL_STR(SzFpCs, "CS");
+DECL_STR(SzFpDo, "DO");
+DECL_STR(SzFpEdo, "EDO");
+DECL_STR(SzFpDs, "DS");
+
+DECL_STR(SzCr0, "Cr0");
+DECL_STR(SzCr2, "Cr2");
+DECL_STR(SzCr3, "Cr3");
+DECL_STR(SzCr4, "Cr4");
+
+DECL_STR(SzDr0, "Dr0");
+DECL_STR(SzDr1, "Dr1");
+DECL_STR(SzDr2, "Dr2");
+DECL_STR(SzDr3, "Dr3");
+DECL_STR(SzDr6, "Dr6");
+DECL_STR(SzDr7, "Dr7");
+DECL_STR(SzGdtr, "GDTR");
+DECL_STR(SzGdtl, "GDTL");
+DECL_STR(SzIdtr, "IDTR");
+DECL_STR(SzIdtl, "IDTL");
+DECL_STR(SzTr, "TR");
+DECL_STR(SzLdtr, "LDTR");
+
+DECL_STR(SzOverflow, "OV");
+DECL_STR(SzDirection, "UP");
+DECL_STR(SzInterrupt, "EI");
+DECL_STR(SzTrap, "TP");
+DECL_STR(SzSign, "PL");
+DECL_STR(SzZero, "ZR");
+DECL_STR(SzACarry, "AC");
+DECL_STR(SzParity, "PE");
+DECL_STR(SzCarry, "CY");
+
+DECL_STR(SzFrozen, "Frozen");
+DECL_STR(SzSuspended, "Suspended");
+DECL_STR(SzBlocked, "Blocked");
+
+DECL_STR(SzRunnable, "Runnable");
+DECL_STR(SzRunning, "Running");
+DECL_STR(SzStopped, "Stopped");
+DECL_STR(SzExiting, "Exiting");
+DECL_STR(SzDead, "Dead");
+DECL_STR(SzUnknown, "UNKNOWN");
+
+DECL_STR(SzExcept1st, "Except1st");
+DECL_STR(SzExcept2nd, "Except2nd");
+DECL_STR(SzRipped, "RIP");
+
+DECL_STR(SzCritSec, "CritSec");
+
+DECL_STR(SzStandard, "Standard");
diff --git a/private/windbg/em/p_i386/wintrans.c b/private/windbg/em/p_i386/wintrans.c
new file mode 100644
index 000000000..c5276532e
--- /dev/null
+++ b/private/windbg/em/p_i386/wintrans.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\wintrans.c"
diff --git a/private/windbg/em/p_mips/asm.c b/private/windbg/em/p_mips/asm.c
new file mode 100644
index 000000000..6dce4e45d
--- /dev/null
+++ b/private/windbg/em/p_mips/asm.c
@@ -0,0 +1,12 @@
+#include "precomp.h"
+#pragma hdrstop
+
+XOSD Assemble (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ LSZ lszInput
+ )
+{
+ return xosdUnsupported;
+}
diff --git a/private/windbg/em/p_mips/d3.c b/private/windbg/em/p_mips/d3.c
new file mode 100644
index 000000000..2982b13b9
--- /dev/null
+++ b/private/windbg/em/p_mips/d3.c
@@ -0,0 +1,1442 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "ntdis.h"
+
+
+
+typedef LPCH FAR *LPLPCH;
+
+#define MAXL 20
+
+char lhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+char uhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+char *hexdigit = &uhexdigit[0];
+static int fUpper = TRUE;
+
+/* current position in instruction */
+static unsigned char FAR*pMem = (unsigned char *)NULL;
+
+static int EAsize [2] = {0}; // size of effective address item
+static long EAaddr [2] = {0}; // offset of effective address
+
+int DumpAddress ( LPADDR, LPCH, int );
+int DumpGeneric ( LSZ, LPCH, int );
+int DumpComment ( LSZ, LPCH, int );
+int DumpEA ( HPID, HTID, LPADDR, LPCH, int );
+
+void OutputAddr(LPLPCH, LPADDR, int );
+void OutputHexString(LPLPCH, LPCH, int);
+void OutputHexCode(LPLPCH, LPCH, int);
+
+UCHAR pszUndef[] = "????";
+UCHAR pszNull[] = "";
+
+UCHAR pszAbs_s[] = "abs.s";
+UCHAR pszAdd[] = "add";
+UCHAR pszAdd_s[] = "add.s";
+UCHAR pszAddi[] = "addi";
+UCHAR pszAddiu[] = "addiu";
+UCHAR pszAddu[] = "addu";
+UCHAR pszAnd[] = "and";
+UCHAR pszAndi[] = "andi";
+UCHAR pszBc0f[] = "bc0f";
+UCHAR pszBc0fl[] = "bc0fl";
+UCHAR pszBc0t[] = "bc0t";
+UCHAR pszBc0tl[] = "bc0tl";
+UCHAR pszBc1f[] = "bc1f";
+UCHAR pszBc1fl[] = "bc1fl";
+UCHAR pszBc1t[] = "bc1t";
+UCHAR pszBc1tl[] = "bc1tl";
+UCHAR pszBc2f[] = "bc2f";
+UCHAR pszBc2fl[] = "bc2fl";
+UCHAR pszBc2t[] = "bc2t";
+UCHAR pszBc2tl[] = "bc2tl";
+UCHAR pszBc3f[] = "bc3f";
+UCHAR pszBc3fl[] = "bc3fl";
+UCHAR pszBc3t[] = "bc3t";
+UCHAR pszBc3tl[] = "bc3tl";
+UCHAR pszBgez[] = "bgez";
+UCHAR pszBgezal[] = "bgezal";
+UCHAR pszBgezall[] = "bgezall";
+UCHAR pszBgezl[] = "bgezl";
+UCHAR pszBgtz[] = "bgtz";
+UCHAR pszBgtzl[] = "bgtzl";
+UCHAR pszBeq[] = "beq";
+UCHAR pszBeql[] = "beql";
+UCHAR pszBlez[] = "blez";
+UCHAR pszBlezl[] = "blezl";
+UCHAR pszBltz[] = "bltz";
+UCHAR pszBltzal[] = "bltzal";
+UCHAR pszBltzall[] = "bltzall";
+UCHAR pszBltzl[] = "bltzl";
+UCHAR pszBne[] = "bne";
+UCHAR pszBnel[] = "bnel";
+UCHAR pszBreak[] = "break";
+UCHAR pszCache[] = "cache";
+UCHAR pszCeil_w_s[] = "ceil.w.s";
+UCHAR pszCfc0[] = "cfc0";
+UCHAR pszCfc1[] = "cfc1";
+UCHAR pszCfc2[] = "cfc2";
+UCHAR pszCfc3[] = "cfc3";
+UCHAR pszCtc0[] = "ctc0";
+UCHAR pszCtc1[] = "ctc1";
+UCHAR pszCtc2[] = "ctc2";
+UCHAR pszCtc3[] = "ctc3";
+UCHAR pszCop0[] = "cop0";
+UCHAR pszCop1[] = "cop1";
+UCHAR pszCop2[] = "cop2";
+UCHAR pszCop3[] = "cop3";
+UCHAR pszCvt_d_s[] = "cvt.d.s";
+UCHAR pszCvt_e_s[] = "cvt.e.s";
+UCHAR pszCvt_q_s[] = "cvt.q.s";
+UCHAR pszCvt_s_s[] = "cvt.s.s";
+UCHAR pszCvt_w_s[] = "cvt.w.s";
+UCHAR pszC_eq_s[] = "c.eq.s";
+UCHAR pszC_f_s[] = "c.f.s";
+UCHAR pszC_le_s[] = "c.le.s";
+UCHAR pszC_lt_s[] = "c.lt.s";
+UCHAR pszC_nge_s[] = "c.nge.s";
+UCHAR pszC_ngl_s[] = "c.ngl.s";
+UCHAR pszC_ngle_s[] = "c.ngle.s";
+UCHAR pszC_ngt_s[] = "c.ngt.s";
+UCHAR pszC_ole_s[] = "c.ole.s";
+UCHAR pszC_olt_s[] = "c.olt.s";
+UCHAR pszC_seq_s[] = "c.seq.s";
+UCHAR pszC_sf_s[] = "c.sf.s";
+UCHAR pszC_ueq_s[] = "c.ueq.s";
+UCHAR pszC_ule_s[] = "c.ule.s";
+UCHAR pszC_ult_s[] = "c.ult.s";
+UCHAR pszC_un_s[] = "c.un.s";
+UCHAR pszDiv[] = "div";
+UCHAR pszDivu[] = "divu";
+UCHAR pszDiv_s[] = "div.s";
+UCHAR pszEret[] = "eret";
+UCHAR pszFloor_w_s[] = "floor.w.s";
+UCHAR pszJ[] = "j";
+UCHAR pszJal[] = "jal";
+UCHAR pszJalr[] = "jalr";
+UCHAR pszJr[] = "jr";
+UCHAR pszLb[] = "lb";
+UCHAR pszLbu[] = "lbu";
+UCHAR pszLdc1[] = "ldc1";
+UCHAR pszLdc2[] = "ldc2";
+UCHAR pszLdc3[] = "ldc3";
+UCHAR pszLh[] = "lh";
+UCHAR pszLhu[] = "lhu";
+UCHAR pszLl[] = "ll";
+UCHAR pszLui[] = "lui";
+UCHAR pszLw[] = "lw";
+UCHAR pszLwc1[] = "lwc1";
+UCHAR pszLwc2[] = "lwc2";
+UCHAR pszLwc3[] = "lwc3";
+UCHAR pszLwl[] = "lwl";
+UCHAR pszLwr[] = "lwr";
+UCHAR pszMfc0[] = "mfc0";
+UCHAR pszMfc1[] = "mfc1";
+UCHAR pszMfc2[] = "mfc2";
+UCHAR pszMfc3[] = "mfc3";
+UCHAR pszMfhi[] = "mfhi";
+UCHAR pszMflo[] = "mflo";
+UCHAR pszMov_s[] = "mov.s";
+UCHAR pszMtc0[] = "mtc0";
+UCHAR pszMtc1[] = "mtc1";
+UCHAR pszMtc2[] = "mtc2";
+UCHAR pszMtc3[] = "mtc3";
+UCHAR pszMthi[] = "mthi";
+UCHAR pszMtlo[] = "mtlo";
+UCHAR pszMul_s[] = "mul.s";
+UCHAR pszMult[] = "mult";
+UCHAR pszMultu[] = "multu";
+UCHAR pszNeg_s[] = "neg.s";
+UCHAR pszNop[] = "nop";
+UCHAR pszNor[] = "nor";
+UCHAR pszOr[] = "or";
+UCHAR pszOri[] = "ori";
+UCHAR pszRfe[] = "rfe";
+UCHAR pszRound_w_s[] = "round.w.s";
+UCHAR pszSb[] = "sb";
+UCHAR pszSc[] = "sc";
+UCHAR pszSdc1[] = "sdc1";
+UCHAR pszSdc2[] = "sdc2";
+UCHAR pszSdc3[] = "sdc3";
+UCHAR pszSh[] = "sh";
+UCHAR pszSll[] = "sll";
+UCHAR pszSllv[] = "sllv";
+UCHAR pszSlt[] = "slt";
+UCHAR pszSlti[] = "slti";
+UCHAR pszSltiu[] = "sltiu";
+UCHAR pszSltu[] = "sltu";
+UCHAR pszSqrt_s[] = "sqrt.s";
+UCHAR pszSra[] = "sra";
+UCHAR pszSrav[] = "srav";
+UCHAR pszSrl[] = "srl";
+UCHAR pszSrlv[] = "srlv";
+UCHAR pszSub[] = "sub";
+UCHAR pszSub_s[] = "sub.s";
+UCHAR pszSubu[] = "subu";
+UCHAR pszSw[] = "sw";
+UCHAR pszSwc1[] = "swc1";
+UCHAR pszSwc2[] = "swc2";
+UCHAR pszSwc3[] = "swc3";
+UCHAR pszSwl[] = "swl";
+UCHAR pszSwr[] = "swr";
+UCHAR pszSync[] = "sync";
+UCHAR pszSyscall[] = "syscall";
+UCHAR pszTeq[] = "teq";
+UCHAR pszTeqi[] = "teqi";
+UCHAR pszTge[] = "tge";
+UCHAR pszTgei[] = "tgei";
+UCHAR pszTgeiu[] = "tgeiu";
+UCHAR pszTgeu[] = "tgeu";
+UCHAR pszTlbp[] = "tlbp";
+UCHAR pszTlbr[] = "tlbr";
+UCHAR pszTlbwi[] = "tlbwi";
+UCHAR pszTlbwr[] = "tlbwr";
+UCHAR pszTlt[] = "tlt";
+UCHAR pszTlti[] = "tlti";
+UCHAR pszTltiu[] = "tltiu";
+UCHAR pszTltu[] = "tltu";
+UCHAR pszTne[] = "tne";
+UCHAR pszTnei[] = "tnei";
+UCHAR pszTrunc_w_s[] = "trunc.w.s";
+UCHAR pszXor[] = "xor";
+UCHAR pszXori[] = "xori";
+
+
+typedef struct optabentry {
+ PUCHAR pszOpcode;
+ ULONG fInstruction;
+ } OPTABENTRY, *POPTABENTRY;
+
+OPTABENTRY opTable[] = {
+ { pszNull, 0 }, // 00
+ { pszNull, 0 }, // 01
+ { pszJ, opnAddr26 }, // 02
+ { pszJal, opnAddr26 }, // 03
+ { pszBeq, opnRsRtRel16 }, // 04
+ { pszBne, opnRsRtRel16 }, // 05
+ { pszBlez, opnRsRel16 }, // 06
+ { pszBgtz, opnRsRel16 }, // 07
+ { pszAddi, opnRtRsImm16 }, // 08
+ { pszAddiu, opnRtRsImm16 }, // 09
+ { pszSlti, opnRtRsImm16 }, // 0a
+ { pszSltiu, opnRtRsImm16 }, // 0b
+ { pszAndi, opnRtRsUImm16 }, // 0c
+ { pszOri, opnRtRsUImm16 }, // 0d
+ { pszXori, opnRtRsUImm16 }, // 0e
+ { pszLui, opnRtUImm16 }, // 0f
+ { pszCop0, opnImm26 }, // 10
+ { pszCop1, opnImm26 }, // 11
+ { pszCop2, opnImm26 }, // 12
+ { pszCop3, opnImm26 }, // 13
+ { pszBeql, opnRsRtRel16 + opnR4000 }, // 14
+ { pszBnel, opnRsRtRel16 + opnR4000 }, // 15
+ { pszBlezl, opnRsRel16 + opnR4000 }, // 16
+ { pszBgtzl, opnRsRel16 + opnR4000 }, // 17
+ { pszUndef, 0 }, // 18
+ { pszUndef, 0 }, // 19
+ { pszUndef, 0 }, // 1a
+ { pszUndef, 0 }, // 1b
+ { pszUndef, 0 }, // 1c
+ { pszUndef, 0 }, // 1d
+ { pszUndef, 0 }, // 1e
+ { pszUndef, 0 }, // 1f
+ { pszLb, opnRtByteIndex }, // 20
+ { pszLh, opnRtWordIndex }, // 21
+ { pszLwl, opnRtLeftIndex }, // 22
+ { pszLw, opnRtDwordIndex }, // 23
+ { pszLbu, opnRtByteIndex }, // 24
+ { pszLhu, opnRtWordIndex }, // 25
+ { pszLwr, opnRtRightIndex }, // 26
+ { pszUndef, 0 }, // 27
+ { pszSb, opnRtByteIndex }, // 28
+ { pszSh, opnRtWordIndex }, // 29
+ { pszSwl, opnRtLeftIndex }, // 2a
+ { pszSw, opnRtDwordIndex }, // 2b
+ { pszUndef, 0 }, // 2c
+ { pszUndef, 0 }, // 2d
+ { pszSwr, opnRtRightIndex }, // 2e
+ { pszCache, opnCacheRightIndex + opnR4000 }, // 2f
+ { pszLl, opnRtDwordIndex }, // 30
+ { pszLwc1, opnFtDwordIndex }, // 31
+ { pszLwc2, opnRxtDwordIndex }, // 32
+ { pszLwc3, opnRxtDwordIndex }, // 33
+ { pszUndef, 0 }, // 34
+ { pszLdc1, opnFtDwordIndex + opnR4000 }, // 35 Qword?
+ { pszLdc2, opnRxtDwordIndex + opnR4000 }, // 36 Qword?
+ { pszLdc3, opnRxtDwordIndex + opnR4000 }, // 37 Qword?
+ { pszSc, opnRtDwordIndex }, // 38
+ { pszSwc1, opnFtDwordIndex }, // 39
+ { pszSwc2, opnRxtDwordIndex }, // 3a
+ { pszSwc3, opnRxtDwordIndex }, // 3b
+ { pszUndef, 0 }, // 3c
+ { pszSdc1, opnFtDwordIndex + opnR4000 }, // 3d Qword?
+ { pszSdc2, opnRxtDwordIndex + opnR4000 }, // 3e Qword?
+ { pszSdc3, opnRxtDwordIndex + opnR4000 }, // 3f Qword?
+ };
+
+OPTABENTRY opSpecialTable[] = {
+ { pszSll, opnRdRtShift }, // 00
+ { pszUndef, 0 }, // 01
+ { pszSrl, opnRdRtShift }, // 02
+ { pszSra, opnRdRtShift }, // 03
+ { pszSllv, opnRdRtRs }, // 04
+ { pszUndef, 0 }, // 05
+ { pszSrlv, opnRdRtRs }, // 06
+ { pszSrav, opnRdRtRs }, // 07
+ { pszJr, opnRs }, // 08
+ { pszJalr, opnRdOptRs }, // 09
+ { pszUndef, 0 }, // 0a
+ { pszUndef, 0 }, // 0b
+ { pszSyscall, opnNone }, // 0c
+ { pszBreak, opnImm20 }, // 0d
+ { pszUndef, 0 }, // 0e
+ { pszSync, opnNone + opnR4000 }, // 0f
+ { pszMfhi, opnRd }, // 10
+ { pszMthi, opnRs }, // 11
+ { pszMflo, opnRd }, // 12
+ { pszMtlo, opnRs }, // 13
+ { pszUndef, 0 }, // 14
+ { pszUndef, 0 }, // 15
+ { pszUndef, 0 }, // 16
+ { pszUndef, 0 }, // 17
+ { pszMult, opnRsRt }, // 18
+ { pszMultu, opnRsRt }, // 19
+ { pszDiv, opnRsRt }, // 1a
+ { pszDivu, opnRsRt }, // 1b
+ { pszUndef, 0 }, // 1c
+ { pszUndef, 0 }, // 1d
+ { pszUndef, 0 }, // 1e
+ { pszUndef, 0 }, // 1f
+ { pszAdd, opnRdRsRt }, // 20
+ { pszAddu, opnRdRsRt }, // 21
+ { pszSub, opnRdRsRt }, // 22
+ { pszSubu, opnRdRsRt }, // 23
+ { pszAnd, opnRdRsRt }, // 24
+ { pszOr, opnRdRsRt }, // 25
+ { pszXor, opnRdRsRt }, // 26
+ { pszNor, opnRdRsRt }, // 27
+ { pszUndef, 0 }, // 28
+ { pszUndef, 0 }, // 29
+ { pszSlt, opnRdRsRt }, // 2a
+ { pszSltu, opnRdRsRt }, // 2b
+ { pszUndef, 0 }, // 2c
+ { pszUndef, 0 }, // 2d
+ { pszUndef, 0 }, // 2e
+ { pszUndef, 0 }, // 2f
+ { pszTge, opnRsRtImm10 + opnR4000 }, // 30
+ { pszTgeu, opnRsRtImm10 + opnR4000 }, // 31
+ { pszTlt, opnRsRtImm10 + opnR4000 }, // 32
+ { pszTltu, opnRsRtImm10 + opnR4000 }, // 33
+ { pszTeq, opnRsRtImm10 + opnR4000 }, // 34
+ { pszUndef, 0 }, // 35
+ { pszTne, opnRsRtImm10 + opnR4000 }, // 36
+ { pszUndef, 0 }, // 37
+ { pszUndef, 0 }, // 38
+ { pszUndef, 0 }, // 39
+ { pszUndef, 0 }, // 3a
+ { pszUndef, 0 }, // 3b
+ { pszUndef, 0 }, // 3c
+ { pszUndef, 0 }, // 3d
+ { pszUndef, 0 }, // 3e
+ { pszUndef, 0 } // 3f
+ };
+
+OPTABENTRY opBcondTable[] = {
+ { pszBltz, opnRsRel16 }, // 00
+ { pszBgez, opnRsRel16 }, // 01
+ { pszBltzl, opnRsRel16 + opnR4000 }, // 02
+ { pszBgezl, opnRsRel16 + opnR4000 }, // 03
+ { pszUndef, 0 }, // 04
+ { pszUndef, 0 }, // 05
+ { pszUndef, 0 }, // 06
+ { pszUndef, 0 }, // 07
+ { pszTgei, opnRsImm16 + opnR4000 }, // 08
+ { pszTgeiu, opnRsImm16 + opnR4000 }, // 09
+ { pszTlti, opnRsImm16 + opnR4000 }, // 0a
+ { pszTltiu, opnRsImm16 + opnR4000 }, // 0b
+ { pszTeqi, opnRsImm16 + opnR4000 }, // 0c
+ { pszUndef, 0 }, // 0d
+ { pszTnei, opnRsImm16 + opnR4000 }, // 0e
+ { pszUndef, 0 }, // 0f
+ { pszBltzal, opnRsRel16 }, // 10
+ { pszBgezal, opnRsRel16 }, // 11
+ { pszBltzall, opnRsRel16 + opnR4000 }, // 12
+ { pszBgezall, opnRsRel16 + opnR4000 } // 13
+ };
+
+OPTABENTRY opCopnTable[] = {
+ { pszMfc0, opnRtRxd }, // 00
+ { pszMfc1, opnRtFs }, // 01
+ { pszMfc2, opnRtRxd }, // 02
+ { pszMfc3, opnRtRxd }, // 03
+ { pszCfc0, opnRtRxd }, // 04
+ { pszCfc1, opnRtFs }, // 05
+ { pszCfc2, opnRtRxd }, // 06
+ { pszCfc3, opnRtRxd }, // 07
+ { pszMtc0, opnRtRxd }, // 08
+ { pszMtc1, opnRtFs }, // 09
+ { pszMtc2, opnRtRxd }, // 0a
+ { pszMtc3, opnRtRxd }, // 0b
+ { pszCtc0, opnRtRxd }, // 0c
+ { pszCtc1, opnRtFs }, // 0d
+ { pszCtc2, opnRtRxd }, // 0e
+ { pszCtc3, opnRtRxd }, // 0f
+ { pszBc0f, opnRel16 }, // 10
+ { pszBc1f, opnRel16 }, // 11
+ { pszBc2f, opnRel16 }, // 12
+ { pszBc3f, opnRel16 }, // 13
+ { pszBc0t, opnRel16 }, // 14
+ { pszBc1t, opnRel16 }, // 15
+ { pszBc2t, opnRel16 }, // 16
+ { pszBc3t, opnRel16 }, // 17
+ { pszBc0fl, opnRel16 + opnR4000 }, // 18
+ { pszBc1fl, opnRel16 + opnR4000 }, // 19
+ { pszBc2fl, opnRel16 + opnR4000 }, // 1a
+ { pszBc3fl, opnRel16 + opnR4000 }, // 1b
+ { pszBc0tl, opnRel16 + opnR4000 }, // 1c
+ { pszBc1tl, opnRel16 + opnR4000 }, // 1d
+ { pszBc2tl, opnRel16 + opnR4000 }, // 1e
+ { pszBc3tl, opnRel16 + opnR4000 } // 1f
+ };
+
+OPTABENTRY opFloatTable[] = {
+ { pszAdd_s, opnFdFsFt }, // 00
+ { pszSub_s, opnFdFsFt }, // 01
+ { pszMul_s, opnFdFsFt }, // 02
+ { pszDiv_s, opnFdFsFt }, // 03
+ { pszSqrt_s, opnFdFs + opnR4000 }, // 04
+ { pszAbs_s, opnFdFs }, // 05
+ { pszMov_s, opnFdFs }, // 06
+ { pszNeg_s, opnFdFs }, // 07
+ { pszUndef, 0 }, // 08
+ { pszUndef, 0 }, // 09
+ { pszUndef, 0 }, // 0a
+ { pszUndef, 0 }, // 0b
+ { pszRound_w_s, opnFdFs + opnR4000 }, // 0c
+ { pszTrunc_w_s, opnFdFs + opnR4000 }, // 0d
+ { pszCeil_w_s, opnFdFs + opnR4000 }, // 0e
+ { pszFloor_w_s, opnFdFs + opnR4000 }, // 0f
+ { pszUndef, 0 }, // 10
+ { pszUndef, 0 }, // 11
+ { pszUndef, 0 }, // 12
+ { pszUndef, 0 }, // 13
+ { pszUndef, 0 }, // 14
+ { pszUndef, 0 }, // 15
+ { pszUndef, 0 }, // 16
+ { pszUndef, 0 }, // 17
+ { pszUndef, 0 }, // 18
+ { pszUndef, 0 }, // 19
+ { pszUndef, 0 }, // 1a
+ { pszUndef, 0 }, // 1b
+ { pszUndef, 0 }, // 1c
+ { pszUndef, 0 }, // 1d
+ { pszUndef, 0 }, // 1e
+ { pszUndef, 0 }, // 1f
+ { pszCvt_s_s, opnFdFs }, // 20
+ { pszCvt_d_s, opnFdFs }, // 21
+ { pszCvt_e_s, opnFdFs + opnR4000 }, // 22
+ { pszCvt_q_s, opnFdFs + opnR4000 }, // 23
+ { pszCvt_w_s, opnFdFs }, // 24
+ { pszUndef, 0 }, // 25
+ { pszUndef, 0 }, // 26
+ { pszUndef, 0 }, // 27
+ { pszUndef, 0 }, // 28
+ { pszUndef, 0 }, // 29
+ { pszUndef, 0 }, // 2a
+ { pszUndef, 0 }, // 2b
+ { pszUndef, 0 }, // 2c
+ { pszUndef, 0 }, // 2d
+ { pszUndef, 0 }, // 2e
+ { pszUndef, 0 }, // 2f
+ { pszC_f_s, opnFsFt }, // 30
+ { pszC_un_s, opnFsFt }, // 31
+ { pszC_eq_s, opnFsFt }, // 32
+ { pszC_ueq_s, opnFsFt }, // 33
+ { pszC_olt_s, opnFsFt }, // 34
+ { pszC_ult_s, opnFsFt }, // 35
+ { pszC_ole_s, opnFsFt }, // 36
+ { pszC_ule_s, opnFsFt }, // 37
+ { pszC_sf_s, opnFsFt }, // 38
+ { pszC_ngle_s, opnFsFt }, // 39
+ { pszC_seq_s, opnFsFt }, // 3a
+ { pszC_ngl_s, opnFsFt }, // 3b
+ { pszC_lt_s, opnFsFt }, // 3c
+ { pszC_nge_s, opnFsFt }, // 3d
+ { pszC_le_s, opnFsFt }, // 3e
+ { pszC_ngt_s, opnFsFt } // 3f
+ };
+
+#include "strings.h"
+
+LPCH pszReg[] = {
+ szFr0, szFr1, szFr2, szFr3, szFr4, szFr5, szFr6, szFr7,
+ szFr8, szFr9, szFr10, szFr11, szFr12, szFr13, szFr14, szFr15,
+ szFr16, szFr17, szFr18, szFr19, szFr20, szFr21, szFr22, szFr23,
+ szFr24, szFr25, szFr26, szFr27, szFr28, szFr29, szFr30, szFr31,
+
+ szR0, szR1, szR2, szR3, szR4, szR5, szR6, szR7,
+ szR8, szR9, szR10, szR11, szR12, szR13, szR14, szR15,
+ szR16, szR17, szR18, szR19, szR20, szR21, szR22, szR23,
+ szR24, szR25, szR26, szR27, szR28, szR29, szR30, szR31,
+
+ szLo, szHi, szFsr, szFir, szPsr,
+
+ szFlagCu, szFlagCu3, szFlagCu2, szFlagCu1, szFlagCu0,
+ szFlagImsk,
+ szFlagInt5, szFlagInt4, szFlagInt3, szFlagInt2, szFlagInt1, szFlagInt0,
+ szFlagSw1, szFlagSw0,
+ szFlagKuo, szFlagIeo, // R3000 flags
+ szFlagKup, szFlagIep, // ...
+ szFlagKuc, szFlagIec, // ...
+ szFlagKsu, szFlagErl, szFlagExl, szFlagIe, // R4000 flags
+
+ szFlagFpc, // fl pt condition
+
+ szEaPReg, szExpPReg, szRaPReg, szPPReg, // psuedo-registers
+ szU0Preg, szU1Preg, szU2Preg, szU3Preg, szU4Preg,
+ szU5Preg, szU6Preg, szU7Preg, szU8Preg, szU9Preg
+ };
+
+OPTABENTRY TlbrEntry = { pszTlbr, opnNone };
+OPTABENTRY TlbwiEntry = { pszTlbwi, opnNone };
+OPTABENTRY TlbwrEntry = { pszTlbwr, opnNone };
+OPTABENTRY TlbpEntry = { pszTlbp, opnNone };
+OPTABENTRY RfeEntry = { pszRfe, opnNone };
+OPTABENTRY EretEntry = { pszEret, opnNone };
+OPTABENTRY UndefEntry = { pszUndef, 0 };
+OPTABENTRY NopEntry = { pszNop, opnNone };
+
+static UCHAR * PBuf;
+static int CchBuf;
+INSTR disinstr;
+
+void CalcMain (HPID,HTID,DOP,LPADDR,LPBYTE,int,int*,LPCH,int, LPCH,int, LPCH, int);
+
+/****disasm - disassemble a MIPS R3/4000 instruction
+*
+* Input:
+* pOffset = pointer to offset to start disassembly
+* fEAout = if set, include EA (effective address)
+*
+* Output:
+* pOffset = pointer to offset of next instruction
+* pchDst = pointer to result string
+*
+***************************************************************************/
+
+#define CCHMAX 256
+static char rgchDisasm [ CCHMAX ];
+static HPID hpidLocal;
+static HTID htidLocal;
+
+XOSD disasm ( HPID hpid, HTID htid, LPSDI lpsdi ) {
+ XOSD xosd = xosdNone;
+ int cchMax = CCHMAX;
+ DOP dop = lpsdi->dop;
+ LPCH lpchOut = rgchDisasm;
+ int ichCur = 0;
+ ADDR addrStart = lpsdi->addr;
+ int cch = 0;
+ int cb;
+ int cbUsed=0;
+ BYTE rgb [ MAXL ];
+
+ char rgchRaw [ MAXL * 2 + 1 ];
+ char rgchOpcode [ 80 ];
+ char rgchOperands [ 80 ];
+ char rgchEA [ 44 ];
+ char rgchComment [ 80 ];
+
+ hpidLocal = hpid;
+ htidLocal = htid;
+ _fmemset ( rgchRaw, 0, sizeof ( rgchRaw ) );
+ _fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
+ _fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
+ _fmemset ( rgchComment, 0, sizeof ( rgchComment ) );
+ _fmemset ( rgchEA, 0, sizeof ( rgchEA ) );
+
+ lpsdi->ichAddr = -1;
+ lpsdi->ichBytes = -1;
+ lpsdi->ichOpcode = -1;
+ lpsdi->ichOperands = -1;
+ lpsdi->ichComment = -1;
+ lpsdi->ichEA0 = -1;
+ lpsdi->ichEA1 = -1;
+ lpsdi->ichEA2 = -1;
+
+ lpsdi->cbEA0 = 0;
+ lpsdi->cbEA1 = 0;
+ lpsdi->cbEA2 = 0;
+
+ lpsdi->fAssocNext = 0;
+
+ lpsdi->lpch = rgchDisasm;
+
+ // Set up for upper or lower case
+
+ fUpper = ( dop & dopUpper ) == dopUpper;
+ if ( fUpper ) {
+ hexdigit = uhexdigit;
+ }
+ else {
+ hexdigit = lhexdigit;
+ }
+
+ ADDR_IS_FLAT( addrStart ) = TRUE;
+
+ // Output the address if it is requested
+
+ if ( ( dop & dopAddr ) == dopAddr ) {
+ cch = DumpAddress ( &addrStart, lpchOut, cchMax );
+
+ lpsdi->ichAddr = 0;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+#ifdef OSDEBUG4
+ xosd = ReadBuffer(hpid, htid, &addrStart, MAXL, rgb, &cb);
+ if (xosd != xosdNone) {
+ cb = 0;
+ }
+#else
+ EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) &addrStart );
+ cb = EMFunc ( emfReadBuf, hpid, htid, MAXL, (LONG) (LPV) rgb );
+#endif
+
+ if ( cb <= 0 ) {
+
+ _fmemcpy ( rgchRaw, " ??", 4 );
+ _fmemcpy ( rgchOpcode, "???", 4 );
+ lpsdi->addr.addr.off++;
+ }
+ else {
+
+ CalcMain (
+ hpid,
+ htid,
+ lpsdi->dop,
+ &lpsdi->addr,
+ rgb,
+ cb,
+ &cbUsed,
+ rgchOpcode, sizeof(rgchOpcode),
+ rgchOperands, sizeof(rgchOperands),
+ rgchComment, sizeof(rgchComment)
+ );
+
+ // NOTENOTE jimsch - cbUsed must be 4
+ cbUsed = 4;
+
+ if ( GetAddrOff(lpsdi->addr) > 0xFFFFFFFF - cbUsed ) {
+ return xosdBadAddress;
+ }
+
+ if ( dop & dopRaw ) {
+ LPCH lpchT = rgchRaw;
+
+ OutputHexCode ( &lpchT, rgb, cbUsed );
+
+ *lpchT = '\0';
+ }
+ }
+
+ if ( ( dop & dopRaw ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchRaw, lpchOut, cchMax );
+
+ lpsdi->ichBytes = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+
+ if ( ( dop & dopOpcode ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchOpcode, lpchOut, cchMax );
+
+ lpsdi->ichOpcode = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchOperands [ 0 ] != '\0' ) ) {
+ cch = DumpGeneric ( rgchOperands, lpchOut, cchMax );
+
+ lpsdi->ichOperands = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchComment [ 0 ] != '\0' ) ) {
+ cch = DumpComment ( rgchComment, lpchOut, cchMax );
+
+ lpsdi->ichComment = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( dop & dopEA ) {
+ cch = DumpEA ( hpid, htid, &lpsdi->addrEA0, lpchOut, cchMax );
+
+ if ( cchMax > 0 && cch > 0 ) {
+ lpsdi->ichEA0 = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+ }
+
+ lpsdi->addr.addr.off += cbUsed;
+
+ return xosd;
+}
+
+void OutputStringM (PUCHAR pStr)
+{
+ int cb;
+
+ if (CchBuf == 0) {
+ return;
+ }
+
+ cb = strlen(pStr);
+ if (cb > CchBuf) {
+ cb = CchBuf - 1;
+ }
+
+ strncpy(PBuf, pStr, cb);
+ PBuf[cb] = 0;
+ if (fUpper) {
+ _strupr(PBuf);
+ } else {
+ _strlwr(PBuf);
+ }
+ PBuf += cb;
+ CchBuf -= cb;
+ return;
+}
+
+void OutputReg (ULONG regnum)
+{
+ OutputStringM(pszReg[regnum + 32]);
+}
+
+void OutputRxReg ( ULONG regnum)
+{
+ if (CchBuf < 3) {
+ CchBuf = 0;
+ return;
+ }
+
+ *PBuf++ = 'r';
+ if (regnum > 9) {
+ *PBuf++ = (UCHAR) ('0' + regnum / 10);
+ }
+ *PBuf++ = (UCHAR) ('0' + regnum % 10);
+ CchBuf -= 2 + (regnum > 9);
+ return;
+}
+
+void OutputFReg (ULONG regnum, ULONG opn)
+{
+ if (CchBuf < 4) {
+ CchBuf = 0;
+ return;
+ }
+
+ *PBuf++ = 'f';
+ if (opn & opnDwordIndex) {
+ *PBuf++ = 'p';
+ } else {
+ *PBuf++ = 'r';
+ }
+
+ if (regnum > 9) {
+ *PBuf++ = (UCHAR)('0' + regnum / 10);
+ }
+ *PBuf++ = (UCHAR)('0' + regnum % 10);
+ CchBuf -= 3 + (regnum > 9);
+ return;
+}
+
+void OutputHex (ULONG outvalue, ULONG length, BOOL fSigned)
+{
+ UCHAR digit[8];
+ LONG index = 0;
+
+ if (fSigned && (long)outvalue < 0) {
+ if (CchBuf > 1) {
+ *PBuf++ = '-';
+ CchBuf -= 1;
+ }
+ outvalue = (ULONG) (- (LONG) outvalue);
+ }
+
+ if (CchBuf > 2) {
+ *PBuf++ = '0';
+ *PBuf++ = (fUpper) ? 'X' :'x';
+ CchBuf -= 2;
+ }
+
+ do {
+ digit[index++] = hexdigit[outvalue & 0xf];
+ outvalue >>= 4;
+ }
+ while (outvalue || (!fSigned && index < (LONG)length));
+
+ if (CchBuf > index) {
+ CchBuf -= index;
+ while (--index >= 0) {
+ *PBuf++ = digit[index];
+ }
+ }
+ return;
+}
+
+
+/*** OutputDisSymbol - output symbol for disassembly
+*
+* Purpose:
+* Access symbol table with given offset and put string into buffer.
+*
+* Input:
+* offset - offset of address to output
+*
+* Output:
+* buffer pointed by PBuf updated with string:
+* if symbol, no disp: <symbol>(<offset>)
+* if symbol, disp: <symbol>+<disp>(<offset>)
+* if no symbol, no disp: <offset>
+*
+*************************************************************************/
+
+void
+OutputDisSymbol (
+ ULONG offset,
+ BOOL fSymbol
+ )
+{
+ UCHAR chAddrBuffer[512];
+ LPCH lpchSymbol;
+ ADDR addrT={0}, addr={0};
+ int cb;
+ ODR odr;
+
+ odr.lszName = chAddrBuffer;
+
+ addr.addr.off = addrT.addr.off = offset;
+ MODE_IS_FLAT(addr.mode) = TRUE;
+ MODE_IS_FLAT(addrT.mode) = TRUE;
+
+ if (fSymbol) {
+ lpchSymbol = SHGetSymbol (&addrT, &addr, sopNone, &odr);
+ if (odr.dwDeltaOff == -1) {
+ lpchSymbol = NULL;
+ }
+ } else {
+ lpchSymbol = NULL;
+ }
+
+ if (lpchSymbol != NULL) {
+ cb = strlen(chAddrBuffer);
+ if (cb > CchBuf) {
+ cb = CchBuf;
+ }
+ strncpy(PBuf, chAddrBuffer, cb);
+ CchBuf -= cb;
+ PBuf += cb;
+ *PBuf = 0;
+
+ if (odr.dwDeltaOff) {
+ if (CchBuf > 1) {
+ *PBuf++ = '+';
+ CchBuf -= 1;
+ }
+ OutputHex(odr.dwDeltaOff, 8, TRUE);
+ }
+ if (CchBuf > 1) {
+ *PBuf++ = '(';
+ CchBuf -= 1;
+ }
+ }
+ OutputHex(offset, 8, FALSE);
+ if (lpchSymbol != NULL) {
+ if (CchBuf > 1) {
+ CchBuf -= 1;
+ *PBuf++ = ')';
+ }
+ }
+
+ return;
+}
+
+
+
+void
+CalcMain (
+ HPID hpid,
+ HTID htid,
+ DOP dop,
+ LPADDR lpaddr,
+ LPBYTE rgb,
+ int cbMax,
+ int FAR *lpcbUsed,
+ LPCH rgchOpcode,
+ int cchOpcode,
+ LPCH rgchOperands,
+ int cchOperands,
+ LPCH rgchComment,
+ int cchComment
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ hpid - Supplies the process handle
+ hthd - Supplies a thread handle
+ dop - Supplies the set of disassembly options
+ lpaddr - Supplies the address to be disassembled
+ rgb - Supplies the buffer to dissassemble into
+ cbMax - Supplies the size of rgb
+ lpcbUsed - Returns the acutal size used
+ rgchOpcode - Supplies location to place opcode
+ rgchOperands - Supplies location to place operands
+ rgchComment - Supplies location to place comment
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG opcode;
+ ULONG temp;
+ POPTABENTRY pEntry;
+ UCHAR chSuffix = '\0';
+ PULONG poffset = &lpaddr->addr.off;
+ BOOL fEAout = TRUE;
+ DWORDLONG ull;
+ RD rd;
+
+ Unreferenced(cbMax);
+ Unreferenced(lpcbUsed);
+
+ *rgchComment = *rgchOperands = 0;
+ EAsize[0] = EAsize[1] = 0;
+
+ PBuf = rgchOpcode;
+ disinstr = *((INSTR*)rgb);
+
+ /*
+ * output the opcode in the table entry
+ */
+
+ opcode = disinstr.jump_instr.Opcode;
+ pEntry = &opTable[opcode]; /* default value */
+
+ /*
+ * Check to see if in the table of special opcodes
+ */
+
+ if (opcode == 0x00) {
+ if (disinstr.instruction) {
+ pEntry = &opSpecialTable[disinstr.special_instr.Funct];
+ } else {
+ pEntry = &NopEntry; /* special opcode for no-op */
+ }
+ }
+
+ /*
+ * Check to see if in the table of regimm opcodes
+ *
+ */
+
+ else if (opcode == 0x01) {
+ opcode = disinstr.immed_instr.RT;
+ if (opcode < 0x14) {
+ pEntry = &opBcondTable[opcode];
+ } else {
+ pEntry = &UndefEntry;
+ }
+ }
+
+ /*
+ * Check to see if in the table of COPz opcodes
+ */
+
+ else if ((opcode & ~0x3) == 0x10) {
+ temp = disinstr.immed_instr.RS;
+ if (temp & 0x10) { /* test for CO bit */
+ if (opcode == 0x10) { /* test if COP0 */
+ temp = disinstr.special_instr.Funct;
+ if (temp == 0x01) {
+ pEntry = &TlbrEntry;
+ } else if (temp == 0x02) {
+ pEntry = &TlbwiEntry;
+ } else if (temp == 0x06) {
+ pEntry = &TlbwrEntry;
+ } else if (temp == 0x08) {
+ pEntry = &TlbpEntry;
+ } else if (temp == 0x10) {
+ pEntry = &RfeEntry;
+ } else if (temp == 0x18) {
+ pEntry = &EretEntry;
+ } else {
+// pEntry = &UndefEntry;
+;
+ }
+ }
+ else if (opcode == 0x11) { /* coprocessor operations */
+ opcode = disinstr.float_instr.Funct;
+ pEntry = &opFloatTable[opcode]; /* get opcode */
+ if (temp == 0x11) {
+ chSuffix = 'd';
+ } else if (temp == 0x12) {
+ chSuffix = 'e';
+ pEntry->fInstruction |= opnR4000;
+ } else if (temp == 0x13) {
+ chSuffix = 'q';
+ pEntry->fInstruction |= opnR4000;
+ } else if (temp == 0x14) {
+ chSuffix = 'w';
+ } else if (temp != 0x10) {
+// pEntry = &UndefEntry;
+;
+ }
+ } else {
+// pEntry = &UndefEntry;
+;
+ }
+ } else { /* no CO bit, general COPz ops */
+ if (!(temp & ~0x06)) {
+ /*
+ * rs = 0, 2, 4, 6
+ */
+
+ pEntry = &opCopnTable[temp * 2 + (opcode - 0x10)];
+ } else if ((temp & ~0x04) == 0x08) {
+ /*
+ * rs = 8 or 0xc, rt = 0 to 3
+ */
+
+ pEntry = &opCopnTable[(4 + (disinstr.immed_instr.RT & 3)) * 4
+ + (opcode - 0x10)];
+ }
+ }
+ }
+
+ /*
+ * pEntry has the opcode string and operand template needed to
+ * output the instruction.
+ */
+
+ strcpy(PBuf, pEntry->pszOpcode);
+ PBuf += strlen(PBuf);
+
+ if (PBuf[-1] != '?' && chSuffix) {
+ /*
+ * change xxx.s to xxx.d, xxx.w,
+ * xxx.e, or xxx.q (R4000 for e, q)
+ */
+
+ PBuf[-1] = chSuffix;
+ }
+
+ PBuf = rgchOperands;
+ CchBuf = cchOperands;
+
+ /*
+ * cache instruction has special codes for RT field value:
+ * 0 = 'i'; 1 = 'd'; 2 = 'si'; 3 = 'sd'
+ */
+
+ if (pEntry->fInstruction & opnCache) {
+ temp = disinstr.special_instr.RT;
+
+ if ((temp & 0x3) > 1) {
+ *PBuf++ = 's';
+ CchBuf -= 1;
+ temp -= 2;
+ }
+ if ((temp & 0x1) == 0) {
+ *PBuf++ = 'i';
+ } else {
+ *PBuf++ = 'd';
+ }
+ *PBuf++ = ',';
+ *PBuf++ = (char) ('0' + temp / 4);
+ *PBuf++ = ',';
+ CchBuf -= 4;
+ }
+
+ if (pEntry->fInstruction & opnPreRt) {
+ OutputReg(disinstr.special_instr.RT);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ }
+
+ if (pEntry->fInstruction & opnPreRxt) {
+ OutputRxReg(disinstr.special_instr.RT);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ }
+
+ if (pEntry->fInstruction & opnRd) {
+ OutputReg(disinstr.special_instr.RD);
+ }
+
+ if (pEntry->fInstruction & opnFd) {
+ OutputFReg(disinstr.float_instr.FD,
+ pEntry->fInstruction & opnAnyIndex);
+ }
+
+ if (pEntry->fInstruction & opnRxd) {
+ OutputRxReg(disinstr.special_instr.RD);
+ }
+
+ if (pEntry->fInstruction & opnRdOptRs) {
+ if (disinstr.special_instr.RD != 0x1f) {
+ OutputReg(disinstr.special_instr.RD);
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ }
+ OutputReg(disinstr.immed_instr.RS);
+ }
+
+ if (pEntry->fInstruction & opnRdComma) {
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ }
+
+ if (pEntry->fInstruction & opnRs) {
+ OutputReg(disinstr.immed_instr.RS);
+ }
+
+ if (pEntry->fInstruction & opnFs) {
+ OutputFReg(disinstr.float_instr.FS, 0);
+ }
+
+ if (pEntry->fInstruction & opnRsComma) {
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ }
+
+ if (pEntry->fInstruction & opnRt) {
+ OutputReg(disinstr.immed_instr.RT);
+ }
+
+ if (pEntry->fInstruction & opnFt) {
+ OutputFReg(disinstr.float_instr.FT, 0);
+ }
+
+ if (pEntry->fInstruction & opnRtComma) {
+ *PBuf++ = ',';
+ CchBuf -= 1;
+ }
+
+ if (pEntry->fInstruction & opnPostRs) {
+ OutputReg(disinstr.immed_instr.RS);
+ }
+
+ if (pEntry->fInstruction & opnImm10) {
+ OutputHex((long)(short)disinstr.trap_instr.Value, 0, TRUE);
+ }
+
+ if (pEntry->fInstruction & opnImm16) {
+ OutputHex((long)(short)disinstr.immed_instr.Value, 0, TRUE);
+ }
+
+ if (pEntry->fInstruction & opnUImm16) {
+ OutputHex((long)(USHORT) disinstr.immed_instr.Value, 0, FALSE);
+ }
+
+ if (pEntry->fInstruction & opnRel16) {
+ OutputDisSymbol(((long)(short)disinstr.immed_instr.Value << 2)
+ + *poffset + sizeof(ULONG), dop & dopSym);
+ }
+
+ if (pEntry->fInstruction & opnImm20) {
+ OutputHex(disinstr.break_instr.Value, 0, TRUE);
+ }
+
+ if (pEntry->fInstruction & opnImm26) {
+ OutputHex(disinstr.jump_instr.Target & 0x1ffffff, 0, TRUE);
+ }
+
+ if (pEntry->fInstruction & opnAddr26) {
+ OutputDisSymbol((disinstr.jump_instr.Target << 2)
+ + (*poffset & 0xf0000000), dop & dopSym);
+ }
+
+ if (pEntry->fInstruction & opnAnyIndex) {
+
+ OutputHex((long)(short)disinstr.immed_instr.Value, 0, TRUE);
+ if (CchBuf > 1) {
+ *PBuf++ = '(';
+ CchBuf -= 1;
+ }
+ OutputReg(disinstr.immed_instr.RS);
+ if (CchBuf > 1) {
+ *PBuf++ = ')';
+ CchBuf -= 1;
+ }
+
+ EMFunc(emfGetRegStruct, hpid, htid,
+ disinstr.immed_instr.RS + CV_M4_IntZERO,
+ (LONG)(LPV)&rd);
+
+ if (rd.cbits > 32) {
+ EMFunc (emfGetReg, hpid, htid,
+ disinstr.immed_instr.RS + CV_M4_IntZERO,
+ (LONG)(LPV)&ull
+ );
+ EAaddr[0] = (DWORD)ull;
+ } else {
+ EMFunc (emfGetReg, hpid, htid,
+ disinstr.immed_instr.RS + CV_M4_IntZERO,
+ (LONG)(LPV)&EAaddr[0]
+ );
+ }
+
+ EAaddr[0] += (long)(short) disinstr.immed_instr.Value;
+
+ if (pEntry->fInstruction & opnByteIndex) {
+ EAsize[0] = 1;
+ } else if (pEntry->fInstruction & opnWordIndex) {
+ EAsize[0] = 2;
+ } else if (pEntry->fInstruction & opnDwordIndex) {
+ EAsize[0] = 4;
+ } else if (pEntry->fInstruction & opnLeftIndex) {
+ EAsize[0] = (UCHAR)(4 - (EAaddr[0] & 3));
+ } else { /* opnRightIndex */
+ EAsize[0] = (UCHAR)((EAaddr[0] & 3) + 1);
+ }
+ }
+
+ if (pEntry->fInstruction & opnShift) {
+ OutputHex(disinstr.special_instr.RE, 2, FALSE);
+ }
+
+ return;
+}
+
+
+
+int DumpAddress ( LPADDR lpaddr, LPCH lpch, int cchMax ) {
+ LPCH lpchT = lpch;
+
+ Unreferenced(cchMax);
+
+ OutputAddr ( &lpch, lpaddr, (ADDR_IS_FLAT(*lpaddr) + 1) * 2 );
+ *lpch = '\0';
+ return lpch - lpchT + 1;
+}
+
+
+int
+DumpGeneric (
+ LSZ lsz,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ int ich = 0;
+
+ while ( *(lsz + ich) != 0 && ich < cchMax - 1 ) {
+ *(lpch+ich) = *(lsz+ich);
+ ich += 1;
+ }
+ *( lpch + ich ) = '\0';
+
+ return ich + 1;
+}
+
+
+int
+DumpComment (
+ LSZ lsz,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ *(lpch) = ';';
+ return DumpGeneric ( lsz, lpch + 1, cchMax - 1 ) + 1;
+}
+
+int
+DumpEA (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ LPCH lpchT = lpch;
+ BYTE rgb [ MAXL ];
+ int indx;
+ int cb;
+#ifdef OSDEBUG4
+ XOSD xosd;
+#endif
+
+ Unreferenced(cchMax);
+
+ for ( indx = 0; indx < 2; indx++ ) {
+
+ if ( EAsize [ indx ] ) {
+ ADDR addr = {0};
+
+ OutputHexString ( &lpchT, (LPBYTE) &EAaddr [ indx ], 4 );
+
+ *lpchT++ = '=';
+
+ addr.addr.off = (UOFFSET) EAaddr [ indx ];
+ addr.addr.seg = (SEGMENT) 0;
+
+ *lpaddr = addr;
+
+#ifdef OSDEBUG4
+ xosd = ReadBuffer(hpid, htid, &addr, EAsize[indx], rgb, &cb);
+ if (xosd != xosdNone) {
+ cb = 0;
+ }
+#else
+ EMFunc (
+ emfSetAddr,
+ hpid,
+ htid,
+ adrCurrent,
+ (LONG) (LPADDR) &addr
+ );
+
+ cb = EMFunc (
+ emfReadBuf,
+ hpid,
+ htid,
+ EAsize [ indx ],
+ (LONG) (LPV) rgb
+ );
+#endif
+
+ if ( cb == EAsize [ indx ] ) {
+ OutputHexString ( &lpchT, rgb, EAsize [ indx ] );
+ }
+ else {
+ while ( EAsize [ indx ]-- ) {
+ *lpchT++ = '?';
+ *lpchT++ = '?';
+ }
+ }
+ *lpchT++ = '\0';
+ }
+ }
+
+ return lpchT - lpch;
+}
+
+
+
+/*** OutputHexString - output hex string
+*
+* Purpose:
+* Output the value pointed by *lplpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* *pchValue - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+* *lplpchMemBuf - pointer update to next memory byte
+*
+*************************************************************************/
+
+void OutputHexString (LPLPCH lplpchBuf, PCH pchValue, int length)
+{
+ unsigned char chMem;
+
+ pchValue += length;
+ while ( length-- ) {
+ chMem = *--pchValue;
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
+
+
+/*** OutputAddr - output address package
+*
+* Purpose:
+* Output the address pointed to by lpaddr.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpaddr - Standard address package.
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+VOID
+OutputAddr (
+ LPLPCH lplpchBuf,
+ LPADDR lpaddr,
+ int alen
+ )
+{
+ ADDR addr = *lpaddr;
+
+ *(*lplpchBuf)++ = '0';
+ *(*lplpchBuf)++ = (fUpper) ? 'X' : 'x';
+ OutputHexString ( lplpchBuf, (LPCH) &addr.addr.off, alen );
+
+ return;
+} /* OutputAddr() */
+
+
+/*** OutputHexCode - output hex code
+*
+* Purpose:
+* Output the code pointed by lpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed. This differs from OutputHexString
+* in that bytes are printed from low to high addresses.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpchMemBuf - - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void OutputHexCode (LPLPCH lplpchBuf, LPCH lpchMemBuf, int length)
+{
+ unsigned char chMem;
+
+ while (length--) {
+ chMem = lpchMemBuf[length];
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
diff --git a/private/windbg/em/p_mips/d3.h b/private/windbg/em/p_mips/d3.h
new file mode 100644
index 000000000..29be290a1
--- /dev/null
+++ b/private/windbg/em/p_mips/d3.h
@@ -0,0 +1,1238 @@
+/********************************** module *********************************/
+/* */
+/* d3.h */
+/* disassembler tables for CodeView's disassembler */
+/* */
+/***************************************************************************/
+/* */
+/* @ Purpose: */
+/* */
+/* @ Functions included: */
+/* */
+/* Revision History: */
+/* */
+/* [03] 31-dec-91 DavidGra */
+/* */
+/* Correctly handle rep/lock prefices. */
+/* */
+/* [02] 15-nov-91 DavidGra */
+/* */
+/* Fix cmpxchg - these are extended opcodes B0 & B1 instead */
+/* of A6 & A7 as the intel documentation claims. */
+/* */
+/* [01] 15-nov-91 DavidGra */
+/* */
+/* Make the 8c form of MOV output WORD PTR [] */
+/* */
+/* [00] 15-nov-91 DavidGra */
+/* */
+/* Added support to correctly handle MOV[S|Z]X */
+/* */
+/* @ Author: Gerd Immeyer @ Version: */
+/* */
+/* @ Creation Date: 10.19.89 @ Modification Date: */
+/* */
+/***************************************************************************/
+
+#ifdef HOST32
+typedef unsigned char CBC;
+#else
+typedef unsigned char _based(_segname("_CODE")) CBC;
+#endif
+
+/* Strings: Operand mnemonics, Segment overrides, etc. for disasm */
+
+CBC dszAAA[] = "aaa";
+CBC dszAAD[] = "aad";
+CBC dszAAM[] = "aam";
+CBC dszAAS[] = "aas";
+CBC dszADC[] = "adc";
+CBC dszADD[] = "add";
+CBC dszADDRPRFX[] = "";
+CBC dszAND[] = "and";
+CBC dszARPL[] = "arpl";
+CBC dszBOUND[] = "bound";
+CBC dszBSF[] = "bsf";
+CBC dszBSR[] = "bsr";
+CBC dszBST[] = "bst";
+CBC dszBSWAP[] = "bswap";
+CBC dszBT[] = "bt";
+CBC dszBTC[] = "btc";
+CBC dszBTR[] = "btr";
+CBC dszBTS[] = "bts";
+CBC dszCALL[] = "call";
+CBC dszCBW[] = "cbw";
+CBC dszCDQ[] = "cdq";
+CBC dszCLC[] = "clc";
+CBC dszCLD[] = "cld";
+CBC dszCLI[] = "cli";
+CBC dszCLTS[] = "clts";
+CBC dszCMC[] = "cmc";
+CBC dszCMP[] = "cmp";
+CBC dszCMPS[] = "cmps";
+CBC dszCMPSB[] = "cmpsb";
+CBC dszCMPSD[] = "cmpsd";
+CBC dszCMPSW[] = "cmpsw";
+CBC dszCMPXCHG[] = "cmpxchg";
+CBC dszCS_[] = "cs:";
+CBC dszCWD[] = "cwd";
+CBC dszCWDE[] = "cwde";
+CBC dszDAA[] = "daa";
+CBC dszDAS[] = "das";
+CBC dszDEC[] = "dec";
+CBC dszDIV[] = "div";
+CBC dszDS_[] = "ds:";
+CBC dszENTER[] = "enter";
+CBC dszES_[] = "es:";
+CBC dszF2XM1[] = "f2xm1";
+CBC dszFABS[] = "fabs";
+CBC dszFADD[] = "fadd";
+CBC dszFADDP[] = "faddp";
+CBC dszFBLD[] = "fbld";
+CBC dszFBSTP[] = "fbstp";
+CBC dszFCHS[] = "fchs";
+CBC dszFCLEX[] = "fclex";
+CBC dszFCOM[] = "fcom";
+CBC dszFCOMP[] = "fcomp";
+CBC dszFCOMPP[] = "fcompp";
+CBC dszFCOS[] = "fcos";
+CBC dszFDECSTP[] = "fdecstp";
+CBC dszFDISI[] = "fdisi";
+CBC dszFDIV[] = "fdiv";
+CBC dszFDIVP[] = "fdivp";
+CBC dszFDIVR[] = "fdivr";
+CBC dszFDIVRP[] = "fdivrp";
+CBC dszFENI[] = "feni";
+CBC dszFFREE[] = "ffree";
+CBC dszFIADD[] = "fiadd";
+CBC dszFICOM[] = "ficom";
+CBC dszFICOMP[] = "ficomp";
+CBC dszFIDIV[] = "fidiv";
+CBC dszFIDIVR[] = "fidivr";
+CBC dszFILD[] = "fild";
+CBC dszFIMUL[] = "fimul";
+CBC dszFINCSTP[] = "fincstp";
+CBC dszFINIT[] = "finit";
+CBC dszFIST[] = "fist";
+CBC dszFISTP[] = "fistp";
+CBC dszFISUB[] = "fisub";
+CBC dszFISUBR[] = "fisubr";
+CBC dszFLD[] = "fld";
+CBC dszFLD1[] = "fld1";
+CBC dszFLDCW[] = "fldcw";
+CBC dszFLDENV[] = "fldenv";
+CBC dszFLDL2E[] = "fldl2e";
+CBC dszFLDL2T[] = "fldl2t";
+CBC dszFLDLG2[] = "fldlg2";
+CBC dszFLDLN2[] = "fldln2";
+CBC dszFLDPI[] = "fldpi";
+CBC dszFLDZ[] = "fldz";
+CBC dszFMUL[] = "fmul";
+CBC dszFMULP[] = "fmulp";
+CBC dszFNCLEX[] = "fnclex";
+CBC dszFNDISI[] = "fndisi";
+CBC dszFNENI[] = "fneni";
+CBC dszFNINIT[] = "fninit";
+CBC dszFNLEX[] = "fnlex";
+CBC dszFNOP[] = "fnop";
+CBC dszFNSAVE[] = "fnsave";
+CBC dszFNSTCW[] = "fnstcw";
+CBC dszFNSTENV[] = "fnstenv";
+CBC dszFNSTSW[] = "fnstsw";
+CBC dszFNSTSWAX[] = "fnstsw ax";
+CBC dszFPATAN[] = "fpatan";
+CBC dszFPREM[] = "fprem";
+CBC dszFPREM1[] = "fprem1";
+CBC dszFPTAN[] = "fptan";
+CBC dszFRNDINT[] = "frndint";
+CBC dszFRSTOR[] = "frstor";
+CBC dszFSAVE[] = "fsave";
+CBC dszFSCALE[] = "fscale";
+CBC dszFSETPM[] = "fsetpm";
+CBC dszFSIN[] = "fsin";
+CBC dszFSINCOS[] = "fsincos";
+CBC dszFSQRT[] = "fsqrt";
+CBC dszFST[] = "fst";
+CBC dszFSTCW[] = "fstcw";
+CBC dszFSTENV[] = "fstenv";
+CBC dszFSTP[] = "fstp";
+CBC dszFSTSW[] = "fstsw";
+CBC dszFSTSWAX[] = "fstswax";
+CBC dszFSUB[] = "fsub";
+CBC dszFSUBP[] = "fsubp";
+CBC dszFSUBR[] = "fsubr";
+CBC dszFSUBRP[] = "fsubrp";
+CBC dszFS_[] = "fs:";
+CBC dszFTST[] = "ftst";
+CBC dszFUCOM[] = "fucom";
+CBC dszFUCOMP[] = "fucomp";
+CBC dszFUCOMPP[] = "fucompp";
+CBC dszFWAIT[] = "fwait";
+CBC dszFXAM[] = "fxam";
+CBC dszFXCH[] = "fxch";
+CBC dszFXTRACT[] = "fxtract";
+CBC dszFYL2X[] = "fyl2x";
+CBC dszFYL2XP1[] = "fyl2xp1";
+CBC dszGS_[] = "gs:";
+CBC dszHLT[] = "hlt";
+CBC dszIBTS[] = "ibts";
+CBC dszIDIV[] = "idiv";
+CBC dszIMUL[] = "imul";
+CBC dszIN[] = "in";
+CBC dszINC[] = "inc";
+CBC dszINS[] = "ins";
+CBC dszINSB[] = "insb";
+CBC dszINSD[] = "insd";
+CBC dszINSW[] = "insw";
+CBC dszINT[] = "int";
+CBC dszINTO[] = "into";
+CBC dszIRET[] = "iret";
+CBC dszIRETD[] = "iretd";
+CBC dszJA[] = "ja";
+CBC dszJAE[] = "jae";
+CBC dszJB[] = "jb";
+CBC dszJBE[] = "jbe";
+CBC dszJC[] = "jc";
+CBC dszJCXZ[] = "jcxz";
+CBC dszJE[] = "je";
+CBC dszJECXZ[] = "jecxz";
+CBC dszJG[] = "jg";
+CBC dszJGE[] = "jge";
+CBC dszJL[] = "jl";
+CBC dszJLE[] = "jle";
+CBC dszJMP[] = "jmp";
+CBC dszJNA[] = "jna";
+CBC dszJNAE[] = "jnae";
+CBC dszJNB[] = "jnb";
+CBC dszJNBE[] = "jnbe";
+CBC dszJNC[] = "jnc";
+CBC dszJNE[] = "jne";
+CBC dszJNG[] = "jng";
+CBC dszJNGE[] = "jnge";
+CBC dszJNL[] = "jnl";
+CBC dszJNLE[] = "jnle";
+CBC dszJNO[] = "jno";
+CBC dszJNP[] = "jnp";
+CBC dszJNS[] = "jns";
+CBC dszJNZ[] = "jnz";
+CBC dszJO[] = "jo";
+CBC dszJP[] = "jp";
+CBC dszJPE[] = "jpe";
+CBC dszJPO[] = "jpo";
+CBC dszJS[] = "js";
+CBC dszJZ[] = "jz";
+CBC dszLAHF[] = "lahf";
+CBC dszLAR[] = "lar";
+CBC dszLDS[] = "lds";
+CBC dszLEA[] = "lea";
+CBC dszLEAVE[] = "leave";
+CBC dszLES[] = "les";
+CBC dszLFS[] = "lfs";
+CBC dszLGDT[] = "lgdt";
+CBC dszLGS[] = "lgs";
+CBC dszLIDT[] = "lidt";
+CBC dszLLDT[] = "lldt";
+CBC dszLMSW[] = "lmsw";
+CBC dszLOADALL[] = "loadall";
+CBC dszLOCK[] = "lock";
+CBC dszLODS[] = "lods";
+CBC dszLODSB[] = "lodsb";
+CBC dszLODSD[] = "lodsd";
+CBC dszLODSW[] = "lodsw";
+CBC dszLOOP[] = "loop";
+CBC dszLOOPE[] = "loope";
+CBC dszLOOPNE[] = "loopne";
+CBC dszLOOPNZ[] = "loopnz";
+CBC dszLOOPZ[] = "loopz";
+CBC dszLSL[] = "lsl";
+CBC dszLSS[] = "lss";
+CBC dszLTR[] = "ltr";
+CBC dszMOV[] = "mov";
+CBC dszMOVS[] = "movs";
+CBC dszMOVSB[] = "movsb";
+CBC dszMOVSD[] = "movsd";
+CBC dszMOVSW[] = "movsw";
+CBC dszMOVSX[] = "movsx";
+CBC dszMOVZX[] = "movzx";
+CBC dszMUL[] = "mul";
+CBC dszNEG[] = "neg";
+CBC dszNOP[] = "nop";
+CBC dszNOT[] = "not";
+CBC dszOPPRFX[] = "";
+CBC dszOR[] = "or";
+CBC dszOUT[] = "out";
+CBC dszOUTS[] = "outs";
+CBC dszOUTSB[] = "outsb";
+CBC dszOUTSD[] = "outsd";
+CBC dszOUTSW[] = "outsw";
+CBC dszPOP[] = "pop";
+CBC dszPOPA[] = "popa";
+CBC dszPOPAD[] = "popad";
+CBC dszPOPF[] = "popf";
+CBC dszPOPFD[] = "popfd";
+CBC dszPUSH[] = "push";
+CBC dszPUSHA[] = "pusha";
+CBC dszPUSHAD[] = "pushad";
+CBC dszPUSHF[] = "pushf";
+CBC dszPUSHFD[] = "pushfd";
+CBC dszRCL[] = "rcl";
+CBC dszRCR[] = "rcr";
+CBC dszREP[] = "rep"; // [03]
+CBC dszREPE[] = "repe";
+CBC dszREPNE[] = "repne"; // [03]
+CBC dszREPNZ[] = "repnz";
+CBC dszREPZ[] = "repz";
+CBC dszRET[] = "ret";
+CBC dszRETF[] = "retf";
+CBC dszRETN[] = "retn";
+CBC dszROL[] = "rol";
+CBC dszROR[] = "ror";
+CBC dszSAHF[] = "sahf";
+CBC dszSAL[] = "sal";
+CBC dszSAR[] = "sar";
+CBC dszSBB[] = "sbb";
+CBC dszSCAS[] = "scas";
+CBC dszSCASB[] = "scasb";
+CBC dszSCASD[] = "scasd";
+CBC dszSCASW[] = "scasw";
+CBC dszSETA[] = "seta";
+CBC dszSETAE[] = "setae";
+CBC dszSETB[] = "setb";
+CBC dszSETBE[] = "setbe";
+CBC dszSETC[] = "setc";
+CBC dszSETE[] = "sete";
+CBC dszSETG[] = "setg";
+CBC dszSETGE[] = "setge";
+CBC dszSETL[] = "setl";
+CBC dszSETLE[] = "setle";
+CBC dszSETNA[] = "setna";
+CBC dszSETNAE[] = "setnae";
+CBC dszSETNB[] = "setnb";
+CBC dszSETNBE[] = "setnbe";
+CBC dszSETNC[] = "setnc";
+CBC dszSETNE[] = "setne";
+CBC dszSETNG[] = "setng";
+CBC dszSETNGE[] = "setnge";
+CBC dszSETNL[] = "setnl";
+CBC dszSETNLE[] = "setnle";
+CBC dszSETNO[] = "setno";
+CBC dszSETNP[] = "setnp";
+CBC dszSETNS[] = "setns";
+CBC dszSETNZ[] = "setnz";
+CBC dszSETO[] = "seto";
+CBC dszSETP[] = "setp";
+CBC dszSETPE[] = "setpe";
+CBC dszSETPO[] = "setpo";
+CBC dszSETS[] = "sets";
+CBC dszSETZ[] = "setz";
+CBC dszSGDT[] = "sgdt";
+CBC dszSHL[] = "shl";
+CBC dszSHLD[] = "shld";
+CBC dszSHR[] = "shr";
+CBC dszSHRD[] = "shrd";
+CBC dszSIDT[] = "sidt";
+CBC dszSLDT[] = "sldt";
+CBC dszSMSW[] = "smsw";
+CBC dszSS_[] = "ss:";
+CBC dszSTC[] = "stc";
+CBC dszSTD[] = "std";
+CBC dszSTI[] = "sti";
+CBC dszSTOS[] = "stos";
+CBC dszSTOSB[] = "stosb";
+CBC dszSTOSD[] = "stosd";
+CBC dszSTOSW[] = "stosw";
+CBC dszSTR[] = "str";
+CBC dszSUB[] = "sub";
+CBC dszTEST[] = "test";
+CBC dszVERR[] = "verr";
+CBC dszVERW[] = "verw";
+CBC dszWAIT[] = "wait";
+CBC dszXADD[] = "xadd";
+CBC dszXBTS[] = "xbts";
+CBC dszXCHG[] = "xchg";
+CBC dszXLAT[] = "xlat";
+CBC dszXOR[] = "xor";
+CBC dszRESERVED[] = "???";
+CBC dszMULTI[] = "";
+CBC dszDB[] = "db";
+
+#define MRM 0x40
+#define COM 0x80
+#define END 0xc0
+
+/* Enumeration of valid actions that can be included in the action table */
+
+enum oprtyp { ADDRP, ADR_OVR, ALSTR, ALT, AXSTR, BOREG,
+ BREG, BRSTR, BYT, CHR, CREG, DWRD,
+ EDWRD, EGROUPT, FARPTR, GROUP, GROUPT, IB,
+ IST, IST_ST, IV, IW, LMODRM, MODRM,
+ NOP, OFFS, OPC0F, OPR_OVR, QWRD, REL16,
+ REL8, REP, SEG_OVR, SREG2, SREG3, ST_IST,
+ STROP, TBYT, UBYT, VAR, VOREG, VREG,
+ EWRD, WRD, WREG, DREG, WRSTR // [00]
+ };
+
+/* Enumeration of indices into the action table for instruction classes */
+
+#define O_DoDB 0
+#define O_NoOperands 0
+#define O_NoOpAlt5 O_NoOperands+1
+#define O_NoOpAlt4 O_NoOpAlt5+2
+#define O_NoOpAlt3 O_NoOpAlt4+2
+#define O_NoOpAlt1 O_NoOpAlt3+2
+#define O_NoOpAlt0 O_NoOpAlt1+2
+#define O_NoOpStrSI O_NoOpAlt0+2
+#define O_NoOpStrDI O_NoOpStrSI+2
+#define O_NoOpStrSIDI O_NoOpStrDI+2
+#define O_bModrm_Reg O_NoOpStrSIDI+2
+#define O_vModrm_Reg O_bModrm_Reg+3
+#define O_Modrm_Reg O_vModrm_Reg+3
+#define O_bReg_Modrm O_Modrm_Reg+3
+#define O_fReg_Modrm O_bReg_Modrm+3
+#define O_Reg_Modrm O_fReg_Modrm+3
+#define O_AL_Ib O_Reg_Modrm+3
+#define O_AX_Iv O_AL_Ib+2
+#define O_sReg2 O_AX_Iv+2
+#define O_oReg O_sReg2+1
+#define O_DoBound O_oReg+1
+#define O_Iv O_DoBound+3
+#define O_wModrm_Reg O_Iv+1
+#define O_Ib O_wModrm_Reg+3
+#define O_Imulb O_Ib+1
+#define O_Imul O_Imulb+4
+#define O_Rel8 O_Imul+4
+#define O_bModrm_Ib O_Rel8+1
+#define O_Modrm_Ib O_bModrm_Ib+3
+#define O_Modrm_Iv O_Modrm_Ib+3
+#define O_Modrm_sReg3 O_Modrm_Iv+3
+#define O_sReg3_Modrm O_Modrm_sReg3+3
+#define O_Modrm O_sReg3_Modrm+3
+#define O_FarPtr O_Modrm+2
+#define O_AL_Offs O_FarPtr+1
+#define O_Offs_AL O_AL_Offs+2
+#define O_AX_Offs O_Offs_AL+2
+#define O_Offs_AX O_AX_Offs+2
+#define O_oReg_Ib O_Offs_AX+2
+#define O_oReg_Iv O_oReg_Ib+2
+#define O_Iw O_oReg_Iv+2
+#define O_Enter O_Iw+1
+#define O_Ubyte_AL O_Enter+2
+#define O_Ubyte_AX O_Ubyte_AL+2
+#define O_AL_Ubyte O_Ubyte_AX+2
+#define O_AX_Ubyte O_AL_Ubyte+2
+#define O_DoInAL O_AX_Ubyte+2
+#define O_DoInAX O_DoInAL+3
+#define O_DoOutAL O_DoInAX+3
+#define O_DoOutAX O_DoOutAL+3
+#define O_Rel16 O_DoOutAX+3
+#define O_ADR_OVERRIDE O_Rel16+1
+#define O_OPR_OVERRIDE O_ADR_OVERRIDE+1
+#define O_SEG_OVERRIDE O_OPR_OVERRIDE+1
+#define O_DoInt3 O_SEG_OVERRIDE+1
+
+#if (O_DoInt3 != 115)
+#error "operand table has been modified!"
+#endif
+/* #define O_DoInt O_DoInt3+2 */
+
+#define O_DoInt 117
+#define O_OPC0F O_DoInt+1
+#define O_GROUP11 O_OPC0F+1
+#define O_GROUP13 O_GROUP11+5
+#define O_GROUP12 O_GROUP13+5
+#define O_GROUP21 O_GROUP12+5
+#define O_GROUP22 O_GROUP21+5
+#define O_GROUP23 O_GROUP22+5
+#define O_GROUP24 O_GROUP23+6
+#define O_GROUP25 O_GROUP24+6
+#define O_GROUP26 O_GROUP25+6
+#define O_GROUP4 O_GROUP26+6
+#define O_GROUP6 O_GROUP4+4
+#define O_GROUP8 O_GROUP6+4
+#define O_GROUP31 O_GROUP8+5
+#define O_GROUP32 O_GROUP31+3
+#define O_GROUP5 O_GROUP32+3
+#define O_GROUP7 O_GROUP5+3
+#define O_x87_ESC O_GROUP7+3
+#define O_bModrm O_x87_ESC+2
+#define O_wModrm O_bModrm+2
+#define O_dModrm O_wModrm+2
+#define O_fModrm O_dModrm+2
+#define O_vModrm O_fModrm+2
+#define O_vModrm_Iv O_vModrm+2
+#define O_Reg_bModrm O_vModrm_Iv+3
+#define O_Reg_wModrm O_Reg_bModrm+3
+#define O_Modrm_Reg_Ib O_Reg_wModrm+3
+#define O_Modrm_Reg_CL O_Modrm_Reg_Ib+4
+#define O_ST_iST O_Modrm_Reg_CL+5
+#define O_iST O_ST_iST+2
+#define O_iST_ST O_iST+2
+#define O_qModrm O_iST_ST+2
+#define O_tModrm O_qModrm+2
+#define O_DoRep O_tModrm+2
+#define O_Modrm_CReg O_DoRep+1
+#define O_CReg_Modrm O_Modrm_CReg+3
+#define O_AX_oReg O_CReg_Modrm+3
+#define O_length O_AX_oReg+3
+
+#if( O_length > 255 )
+#error "operand table too large!"
+#endif
+
+
+/* The action table: range of lists of actions to be taken for each */
+/* possible instruction class. */
+
+static CBC actiontbl[] = {
+/* NoOperands */ (CBC) (NOP+END),
+/* NoOpAlt5 */ (CBC) (ALT+END), 5,
+/* NoOpAlt4 */ (CBC) (ALT+END), 4,
+/* NoOpAlt3 */ (CBC) (ALT+END), 3,
+/* NoOpAlt1 */ (CBC) (ALT+END), 1,
+/* NoOpAlt0 */ (CBC) (ALT+END), 0,
+/* NoOpStrSI */ (CBC) (STROP+END), 1,
+/* NoOpStrDI */ (CBC) (STROP+END), 2,
+/* NoOpStrSIDI */ (CBC) (STROP+END), 3,
+/* bModrm_Reg */ (CBC) (BYT+MRM), (CBC) (LMODRM+COM), (CBC) (BREG+END),
+/* vModrm_Reg */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+END),
+/* Modrm_Reg */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+END),
+/* bReg_Modrm */ (CBC) (BYT+MRM), (CBC) (BREG+COM), (CBC) (LMODRM+END),
+/* fReg_Modrm */ (CBC) (FARPTR+MRM),(CBC) (VREG+COM), (CBC) (MODRM+END),
+/* Reg_Modrm */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* AL_Ib */ (CBC) (ALSTR+COM), (CBC) (IB+END),
+/* AX_Iv */ (CBC) (AXSTR+COM), (CBC) (IV+END),
+/* sReg2 */ (CBC) (SREG2+END),
+/* oReg */ (CBC) (VOREG+END),
+/* DoBound */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+END),
+/* Iv */ (CBC) (IV+END),
+/* wModrm_Reg */ (CBC) (WRD+MRM), (CBC) (LMODRM+COM), (CBC) (WREG+END),
+/* Ib */ (CBC) (IB+END),
+/* Imulb */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+COM),
+ (CBC) (IB+END),
+/* Imul */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+COM),
+ (CBC) (IV+END),
+/* REL8 */ (CBC) (REL8+END),
+/* bModrm_Ib */ (CBC) (BYT+MRM), (CBC) (LMODRM+COM), (CBC) (IB+END),
+/* Modrm_Ib */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (IB+END),
+/* Modrm_Iv */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (IV+END),
+/* Modrm_sReg3 */ (CBC) (WRD+MRM), (CBC) (LMODRM+COM), (CBC) (SREG3+END),
+/* sReg3_Modrm */ (CBC) (WRD+MRM), (CBC) (SREG3+COM), (CBC) (MODRM+END),
+/* Modrm */ (CBC) (VAR+MRM), (CBC) (MODRM+END),
+/* FarPtr */ (CBC) (ADDRP+END),
+/* AL_Offs */ (CBC) (ALSTR+COM), (CBC) (OFFS+END),
+/* Offs_AL */ (CBC) (OFFS+COM), (CBC) (ALSTR+END),
+/* AX_Offs */ (CBC) (AXSTR+COM), (CBC) (OFFS+END),
+/* Offs_AX */ (CBC) (OFFS+COM), (CBC) (AXSTR+END),
+/* oReg_Ib */ (CBC) (BOREG+COM), (CBC) (IB+END),
+/* oReg_Iv */ (CBC) (VOREG+COM), (CBC) (IV+END),
+/* Iw */ (CBC) (IW+END),
+/* enter */ (CBC) (IW+COM), (CBC) (IB+END),
+/* Ubyte_AL */ (CBC) (UBYT+COM), (CBC) (ALSTR+END),
+/* Ubyte_AX */ (CBC) (UBYT+COM), (CBC) (AXSTR+END),
+/* AL_Ubyte */ (CBC) (ALSTR+COM), (CBC) (UBYT+END),
+/* AX_Ubyte */ (CBC) (AXSTR+COM), (CBC) (UBYT+END),
+/* DoInAL */ (CBC) (ALSTR+COM), (CBC) (WRSTR+END), 2,
+/* DoInAX */ (CBC) (AXSTR+COM), (CBC) (WRSTR+END), 2,
+/* DoOutAL */ (CBC) (WRSTR+COM), 2, (CBC) (ALSTR+END),
+/* DoOutAX */ (CBC) (WRSTR+COM), 2, (CBC) (AXSTR+END),
+/* REL16 */ (CBC) (REL16+END),
+/* ADR_OVERRIDE*/ ADR_OVR,
+/* OPR_OVERRIDE*/ OPR_OVR,
+/* SEG_OVERRIDE*/ SEG_OVR,
+/* DoInt3 */ (CBC) (CHR+END), '3',
+/* DoInt */ (CBC) (UBYT+END),
+/* Opcode0F */ OPC0F,
+/* group1_1 */ (CBC) (BYT+MRM), GROUP, 0, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group1_3 */ (CBC) (VAR+MRM), GROUP, 0, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group1_2 */ (CBC) (VAR+MRM), GROUP, 0, (CBC) (LMODRM+COM),
+ (CBC) (IV+END),
+/* group2_1 */ (CBC) (BYT+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group2_2 */ (CBC) (VAR+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group2_3 */ (CBC) (BYT+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (CHR+END), '1',
+/* group2_4 */ (CBC) (VAR+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (CHR+END), '1',
+/* group2_5 */ (CBC) (BYT+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (BRSTR+END), 1,
+/* group2_6 */ (CBC) (VAR+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (BRSTR+END), 1,
+/* group4 */ (CBC) (BYT+MRM), GROUP, 2, (CBC) (LMODRM+END),
+/* group6 */ (CBC) (WRD+MRM), GROUP, 3, (CBC) (LMODRM+END),
+/* group8 */ (CBC) (VAR+MRM), GROUP, 4, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group3_1 */ (CBC) (BYT+MRM), GROUPT, 20,
+/* group3_2 */ (CBC) (VAR+MRM), GROUPT, 21,
+/* group5 */ (CBC) (VAR+MRM), GROUPT, 22,
+/* group7 */ (CBC) (NOP+MRM), GROUPT, 23,
+/* x87_ESC */ (CBC) (NOP+MRM), EGROUPT,
+/* bModrm */ (CBC) (BYT+MRM), (CBC) (LMODRM+END),
+/* wModrm */ (CBC) (WRD+MRM), (CBC) (LMODRM+END),
+/* dModrm */ (CBC) (DWRD+MRM), (CBC) (LMODRM+END),
+/* fModrm */ (CBC) (FARPTR+MRM),(CBC) (LMODRM+END),
+/* vModrm */ (CBC) (VAR+MRM), (CBC) (LMODRM+END),
+/* vModrm_Iv */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (IV+END),
+/* reg_bModrm */ (CBC) (BYT+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* reg_wModrm */ (CBC) (EWRD+MRM), (CBC) (DREG+COM), (CBC) (LMODRM+END),
+/* Modrm_Reg_Ib*/ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+COM),
+ (CBC) (IB+END),
+/* Modrm_Reg_CL*/ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+COM),
+ (CBC) (BRSTR+END), 1,
+/* ST_iST */ (CBC) (NOP+MRM), (CBC) (ST_IST+END),
+/* iST */ (CBC) (NOP+MRM), (CBC) (IST+END),
+/* iST_ST */ (CBC) (NOP+MRM), (CBC) (IST_ST+END),
+/* qModrm */ (CBC) (QWRD+MRM), (CBC) (LMODRM+END),
+/* tModrm */ (CBC) (TBYT+MRM), (CBC) (LMODRM+END),
+/* REP */ REP,
+/* Modrm_CReg */ (CBC) (EDWRD+MRM), (CBC) (MODRM+COM), (CBC) (CREG+END),
+/* CReg_Modrm */ (CBC) (EDWRD+MRM), (CBC) (CREG+COM), (CBC) (MODRM+END),
+/* AX_oReg */ (CBC) (AXSTR+COM), (CBC) (VOREG+END)
+ };
+
+#ifdef HOST_i386
+#pragma pack(1)
+#endif
+
+typedef struct Tdistbl{
+ CBC *instruct;
+ unsigned char opr;
+ } Tdistbl;
+
+/* List of ordered pairs for each instruction: */
+/* (pointer to string literal mnemonic, */
+/* instruction class index for action table) */
+
+static Tdistbl distbl[] = {
+ dszADD, O_bModrm_Reg, /* 00 ADD mem/reg, reg (byte) */
+ dszADD, O_Modrm_Reg, /* 01 ADD mem/reg, reg (var) */
+ dszADD, O_bReg_Modrm, /* 02 ADD reg, mem/reg (byte) */
+ dszADD, O_Reg_Modrm, /* 03 ADD reg, mem/reg (var) */
+ dszADD, O_AL_Ib, /* 04 ADD AL, I */
+ dszADD, O_AX_Iv, /* 05 ADD AX, I */
+ dszPUSH, O_sReg2, /* 06 PUSH ES */
+ dszPOP, O_sReg2, /* 07 POP ES */
+ dszOR, O_bModrm_Reg, /* 08 OR mem/reg, reg (byte) */
+ dszOR, O_Modrm_Reg, /* 09 OR mem/reg, reg (word) */
+ dszOR, O_bReg_Modrm, /* 0A OR reg, mem/reg (byte) */
+ dszOR, O_Reg_Modrm, /* 0B OR reg, mem/reg (word) */
+ dszOR, O_AL_Ib, /* 0C OR AL, I */
+ dszOR, O_AX_Iv, /* 0D OR AX, I */
+ dszPUSH, O_sReg2, /* 0E PUSH CS */
+ dszMULTI, O_OPC0F, /* 0F CLTS & protection ctl(286) */
+ dszADC, O_bModrm_Reg, /* 10 ADC mem/reg, reg (byte) */
+ dszADC, O_Modrm_Reg, /* 11 ADC mem/reg, reg (word) */
+ dszADC, O_bReg_Modrm, /* 12 ADC reg, mem/reg (byte) */
+ dszADC, O_Reg_Modrm, /* 13 ADC reg, mem/reg (word) */
+ dszADC, O_AL_Ib, /* 14 ADC AL, I */
+ dszADC, O_AX_Iv, /* 15 ADC AX, I */
+ dszPUSH, O_sReg2, /* 16 PUSH SS */
+ dszPOP, O_sReg2, /* 17 POP SS */
+ dszSBB, O_bModrm_Reg, /* 18 SBB mem/reg, reg (byte) */
+ dszSBB, O_Modrm_Reg, /* 19 SBB mem/reg, reg (word) */
+ dszSBB, O_bReg_Modrm, /* 1A SBB reg, mem/reg (byte) */
+ dszSBB, O_Reg_Modrm, /* 1B SBB reg, mem/reg (word) */
+ dszSBB, O_AL_Ib, /* 1C SBB AL, I */
+ dszSBB, O_AX_Iv, /* 1D SBB AX, I */
+ dszPUSH, O_sReg2, /* 1E PUSH DS */
+ dszPOP, O_sReg2, /* 1F POP DS */
+ dszAND, O_bModrm_Reg, /* 20 AND mem/reg, reg (byte) */
+ dszAND, O_Modrm_Reg, /* 21 AND mem/reg, reg (word) */
+ dszAND, O_bReg_Modrm, /* 22 AND reg, mem/reg (byte) */
+ dszAND, O_Reg_Modrm, /* 23 AND reg, mem/reg (word) */
+ dszAND, O_AL_Ib, /* 24 AND AL, I */
+ dszAND, O_AX_Iv, /* 25 AND AX, I */
+ dszES_, O_SEG_OVERRIDE, /* 26 SEG ES: */
+ dszDAA, O_NoOperands, /* 27 DAA */
+ dszSUB, O_bModrm_Reg, /* 28 SUB mem/reg, reg (byte) */
+ dszSUB, O_Modrm_Reg, /* 29 SUB mem/reg, reg (word) */
+ dszSUB, O_bReg_Modrm, /* 2A SUB reg, mem/reg (byte) */
+ dszSUB, O_Reg_Modrm, /* 2B SUB reg, mem/reg (word) */
+ dszSUB, O_AL_Ib, /* 2C SUB AL, I */
+ dszSUB, O_AX_Iv, /* 2D SUB AX, I */
+ dszCS_, O_SEG_OVERRIDE, /* 2E SEG CS: */
+ dszDAS, O_NoOperands, /* 2F DAS */
+ dszXOR, O_bModrm_Reg, /* 30 XOR mem/reg, reg (byte) */
+ dszXOR, O_Modrm_Reg, /* 31 XOR mem/reg, reg (word) */
+ dszXOR, O_bReg_Modrm, /* 32 XOR reg, mem/reg (byte) */
+ dszXOR, O_Reg_Modrm, /* 33 XOR reg, mem/reg (word) */
+ dszXOR, O_AL_Ib, /* 34 XOR AL, I */
+ dszXOR, O_AX_Iv, /* 35 XOR AX, I */
+ dszSS_, O_SEG_OVERRIDE, /* 36 SEG SS: */
+ dszAAA, O_NoOperands, /* 37 AAA */
+ dszCMP, O_bModrm_Reg, /* 38 CMP mem/reg, reg (byte) */
+ dszCMP, O_Modrm_Reg, /* 39 CMP mem/reg, reg (word) */
+ dszCMP, O_bReg_Modrm, /* 3A CMP reg, mem/reg (byte) */
+ dszCMP, O_Reg_Modrm, /* 3B CMP reg, mem/reg (word) */
+ dszCMP, O_AL_Ib, /* 3C CMP AL, I */
+ dszCMP, O_AX_Iv, /* 3D CMP AX, I */
+ dszDS_, O_SEG_OVERRIDE, /* 3E SEG DS: */
+ dszAAS, O_NoOperands, /* 3F AAS */
+ dszINC, O_oReg, /* 40 INC AX */
+ dszINC, O_oReg, /* 41 INC CX */
+ dszINC, O_oReg, /* 42 INC DX */
+ dszINC, O_oReg, /* 43 INC BX */
+ dszINC, O_oReg, /* 44 INC SP */
+ dszINC, O_oReg, /* 45 INC BP */
+ dszINC, O_oReg, /* 46 INC SI */
+ dszINC, O_oReg, /* 47 INC DI */
+ dszDEC, O_oReg, /* 48 DEC AX */
+ dszDEC, O_oReg, /* 49 DEC CX */
+ dszDEC, O_oReg, /* 4A DEC DX */
+ dszDEC, O_oReg, /* 4B DEC BX */
+ dszDEC, O_oReg, /* 4C DEC SP */
+ dszDEC, O_oReg, /* 4D DEC BP */
+ dszDEC, O_oReg, /* 4E DEC SI */
+ dszDEC, O_oReg, /* 4F DEC DI */
+ dszPUSH, O_oReg, /* 50 PUSH AX */
+ dszPUSH, O_oReg, /* 51 PUSH CX */
+ dszPUSH, O_oReg, /* 52 PUSH DX */
+ dszPUSH, O_oReg, /* 53 PUSH BX */
+ dszPUSH, O_oReg, /* 54 PUSH SP */
+ dszPUSH, O_oReg, /* 55 PUSH BP */
+ dszPUSH, O_oReg, /* 56 PUSH SI */
+ dszPUSH, O_oReg, /* 57 PUSH DI */
+ dszPOP, O_oReg, /* 58 POP AX */
+ dszPOP, O_oReg, /* 59 POP CX */
+ dszPOP, O_oReg, /* 5A POP DX */
+ dszPOP, O_oReg, /* 5B POP BX */
+ dszPOP, O_oReg, /* 5C POP SP */
+ dszPOP, O_oReg, /* 5D POP BP */
+ dszPOP, O_oReg, /* 5E POP SI */
+ dszPOP, O_oReg, /* 5F POP DI */
+ dszPUSHA, O_NoOpAlt5, /* 60 PUSHA (286) / PUSHAD (386) */
+ dszPOPA, O_NoOpAlt4, /* 61 POPA (286) / POPAD (286) */
+ dszBOUND, O_DoBound, /* 62 BOUND reg, Modrm (286) */
+ dszARPL, O_Modrm_Reg, /* 63 ARPL Modrm, reg (286) */
+ dszFS_, O_SEG_OVERRIDE, /* 64 */
+ dszGS_, O_SEG_OVERRIDE, /* 65 */
+ dszOPPRFX,O_OPR_OVERRIDE, /* 66 */
+ dszADDRPRFX,O_ADR_OVERRIDE, /* 67 */
+ dszPUSH, O_Iv, /* 68 PUSH word (286) */
+ dszIMUL, O_Imul, /* 69 IMUL (286) */
+ dszPUSH, O_Ib, /* 6A PUSH byte (286) */
+ dszIMUL, O_Imulb, /* 6B IMUL (286) */
+ dszINSB, O_NoOperands, /* 6C INSB (286) */
+ dszINSW, O_NoOpAlt3, /* 6D INSW (286) / INSD (386) */
+ dszOUTSB, O_NoOperands, /* 6E OUTSB (286) */
+ dszOUTSW, O_NoOpAlt4, /* 6F OUTSW (286) / OUTSD (386) */
+ dszJO, O_Rel8, /* 70 JO */
+ dszJNO, O_Rel8, /* 71 JNO */
+ dszJB, O_Rel8, /* 72 JB or JNAE or JC */
+ dszJNB, O_Rel8, /* 73 JNB or JAE or JNC */
+ dszJZ, O_Rel8, /* 74 JE or JZ */
+ dszJNZ, O_Rel8, /* 75 JNE or JNZ */
+ dszJBE, O_Rel8, /* 76 JBE or JNA */
+ dszJA, O_Rel8, /* 77 JNBE or JA */
+ dszJS, O_Rel8, /* 78 JS */
+ dszJNS, O_Rel8, /* 79 JNS */
+ dszJPE, O_Rel8, /* 7A JP or JPE */
+ dszJPO, O_Rel8, /* 7B JNP or JPO */
+ dszJL, O_Rel8, /* 7C JL or JNGE */
+ dszJGE, O_Rel8, /* 7D JNL or JGE */
+ dszJLE, O_Rel8, /* 7E JLE or JNG */
+ dszJG, O_Rel8, /* 7F JNLE or JG */
+ dszMULTI, O_GROUP11, /* 80 */
+ dszMULTI, O_GROUP12, /* 81 */
+ dszRESERVED, O_DoDB, /* 82 */
+ dszMULTI, O_GROUP13, /* 83 */
+ dszTEST, O_bModrm_Reg, /* 84 TEST reg, mem/reg (byte) */
+ dszTEST, O_Modrm_Reg, /* 85 TEST reg, mem/reg (word) */
+ dszXCHG, O_bModrm_Reg, /* 86 XCHG reg, mem/reg (byte) */
+ dszXCHG, O_Modrm_Reg, /* 87 XCHG reg, mem/reg (word) */
+ dszMOV, O_bModrm_Reg, /* 88 MOV mem/reg, reg (byte) */
+ dszMOV, O_Modrm_Reg, /* 89 MOV mem/reg, reg (word) */
+ dszMOV, O_bReg_Modrm, /* 8A MOV reg, mem/reg (byte) */
+ dszMOV, O_Reg_Modrm, /* 8B MOV reg, mem/reg (word) */
+ dszMOV, O_Modrm_sReg3, /* 8C MOV mem/reg, segreg */
+ dszLEA, O_Reg_Modrm, /* 8D LEA reg, mem */
+ dszMOV, O_sReg3_Modrm, /* 8E MOV segreg, mem/reg */
+ dszPOP, O_Modrm, /* 8F POP mem/reg */
+ dszNOP, O_NoOperands, /* 90 NOP */
+ dszXCHG, O_AX_oReg, /* 91 XCHG AX,CX */
+ dszXCHG, O_AX_oReg, /* 92 XCHG AX,DX */
+ dszXCHG, O_AX_oReg, /* 93 XCHG AX,BX */
+ dszXCHG, O_AX_oReg, /* 94 XCHG AX,SP */
+ dszXCHG, O_AX_oReg, /* 95 XCHG AX,BP */
+ dszXCHG, O_AX_oReg, /* 96 XCHG AX,SI */
+ dszXCHG, O_AX_oReg, /* 97 XCHG AX,DI */
+ dszCBW, O_NoOpAlt0, /* 98 CBW / CWDE (386) */
+ dszCWD, O_NoOpAlt1, /* 99 CWD / CDQ (386) */
+ dszCALL, O_FarPtr, /* 9A CALL seg:off */
+ dszWAIT, O_NoOperands, /* 9B WAIT */
+ dszPUSHF, O_NoOpAlt5, /* 9C PUSHF / PUSHFD (386) */
+ dszPOPF, O_NoOpAlt4, /* 9D POPF / POPFD (386) */
+ dszSAHF, O_NoOperands, /* 9E SAHF */
+ dszLAHF, O_NoOperands, /* 9F LAHF */
+ dszMOV, O_AL_Offs, /* A0 MOV AL, mem */
+ dszMOV, O_AX_Offs, /* A1 MOV AX, mem */
+ dszMOV, O_Offs_AL, /* A2 MOV mem, AL */
+ dszMOV, O_Offs_AX, /* A3 MOV mem, AX */
+ dszMOVSB, O_NoOpStrSIDI, /* A4 MOVSB */
+ dszMOVSW, O_NoOpStrSIDI, /* A5 MOVSW / MOVSD (386) */
+ dszCMPSB, O_NoOpStrSIDI, /* A6 CMPSB */
+ dszCMPSW, O_NoOpStrSIDI, /* A7 CMPSW / CMPSD (386) */
+ dszTEST, O_AL_Ib, /* A8 TEST AL, I */
+ dszTEST, O_AX_Iv, /* A9 TEST AX, I */
+ dszSTOSB, O_NoOpStrDI, /* AA STOSB */
+ dszSTOSW, O_NoOpStrDI, /* AB STOSW / STOSD (386) */
+ dszLODSB, O_NoOpStrSI, /* AC LODSB */
+ dszLODSW, O_NoOpStrSI, /* AD LODSW / LODSD (386) */
+ dszSCASB, O_NoOpStrDI, /* AE SCASB */
+ dszSCASW, O_NoOpStrDI, /* AF SCASW / SCASD (386) */
+ dszMOV, O_oReg_Ib, /* B0 MOV AL, I */
+ dszMOV, O_oReg_Ib, /* B1 MOV CL, I */
+ dszMOV, O_oReg_Ib, /* B2 MOV DL, I */
+ dszMOV, O_oReg_Ib, /* B3 MOV BL, I */
+ dszMOV, O_oReg_Ib, /* B4 MOV AH, I */
+ dszMOV, O_oReg_Ib, /* B5 MOV CH, I */
+ dszMOV, O_oReg_Ib, /* B6 MOV DH, I */
+ dszMOV, O_oReg_Ib, /* B7 MOV BH, I */
+ dszMOV, O_oReg_Iv, /* B8 MOV AX, I */
+ dszMOV, O_oReg_Iv, /* B9 MOV CX, I */
+ dszMOV, O_oReg_Iv, /* BA MOV DX, I */
+ dszMOV, O_oReg_Iv, /* BB MOV BX, I */
+ dszMOV, O_oReg_Iv, /* BC MOV SP, I */
+ dszMOV, O_oReg_Iv, /* BD MOV BP, I */
+ dszMOV, O_oReg_Iv, /* BE MOV SI, I */
+ dszMOV, O_oReg_Iv, /* BF MOV DI, I */
+ dszMULTI, O_GROUP21, /* C0 shifts & rotates (286) */
+ dszMULTI, O_GROUP22, /* C1 shifts & rotates (286) */
+ dszRET, O_Iw, /* C2 RET Rel16 */
+ dszRET, O_NoOperands, /* C3 RET */
+ dszLES, O_fReg_Modrm, /* C4 LES reg, mem */
+ dszLDS, O_fReg_Modrm, /* C5 LDS reg, mem */
+ dszMOV, O_bModrm_Ib, /* C6 MOV mem/reg, I(byte) */
+ dszMOV, O_Modrm_Iv, /* C7 MOV mem/reg, I(word) */
+ dszENTER, O_Enter, /* C8 ENTER (286) */
+ dszLEAVE, O_NoOperands, /* C9 LEAVE (286) */
+ dszRETF, O_Iw, /* CA RETF I(word) */
+ dszRETF, O_NoOperands, /* CB RETF */
+ dszINT, O_DoInt3, /* CC INT 3 */
+ dszINT, O_DoInt, /* CD INT */
+ dszINTO, O_NoOperands, /* CE INTO */
+ dszIRET, O_NoOpAlt4, /* CF IRET / IRETD (386) */
+ dszMULTI, O_GROUP23, /* D0 shifts & rotates,1 (byte) */
+ dszMULTI, O_GROUP24, /* D1 shifts & rotates,1 (word) */
+ dszMULTI, O_GROUP25, /* D2 shifts & rotates,CL (byte) */
+ dszMULTI, O_GROUP26, /* D3 shifts & rotates,CL (word) */
+ dszAAM, O_Ib, /* D4 AAM */
+ dszAAD, O_Ib, /* D5 AAD */
+ dszRESERVED, O_DoDB, /* D6 */
+ dszXLAT, O_NoOperands, /* D7 XLAT */
+ dszMULTI, O_x87_ESC, /* D8 ESC */
+ dszMULTI, O_x87_ESC, /* D9 ESC */
+ dszMULTI, O_x87_ESC, /* DA ESC */
+ dszMULTI, O_x87_ESC, /* DB ESC */
+ dszMULTI, O_x87_ESC, /* DC ESC */
+ dszMULTI, O_x87_ESC, /* DD ESC */
+ dszMULTI, O_x87_ESC, /* DE ESC */
+ dszMULTI, O_x87_ESC, /* DF ESC */
+ dszLOOPNE,O_Rel8, /* E0 LOOPNE or LOOPNZ */
+ dszLOOPE, O_Rel8, /* E1 LOOPE or LOOPZ */
+ dszLOOP, O_Rel8, /* E2 LOOP */
+ dszJCXZ, O_Rel8, /* E3 JCXZ / JECXZ (386) */
+ dszIN, O_AL_Ubyte, /* E4 IN AL, I */
+ dszIN, O_AX_Ubyte, /* E5 IN AX, I */
+ dszOUT, O_Ubyte_AL, /* E6 OUT I, AL */
+ dszOUT, O_Ubyte_AX, /* E7 OUT I, AX */
+ dszCALL, O_Rel16, /* E8 CALL Rel16 */
+ dszJMP, O_Rel16, /* E9 JMP Rel16 */
+ dszJMP, O_FarPtr, /* EA JMP seg:off */
+ dszJMP, O_Rel8, /* EB JMP Rel8 */
+ dszIN, O_DoInAL, /* EC IN AL, DX */
+ dszIN, O_DoInAX, /* ED IN AX, DX */
+ dszOUT, O_DoOutAL, /* EE OUT DX, AL */
+ dszOUT, O_DoOutAX, /* EF OUT DX, AX */
+ dszLOCK, O_DoRep, /* F0 LOCK */
+ dszRESERVED, O_DoDB, /* F1 */
+ dszREPNE, O_DoRep, /* F2 REPNE or REPNZ */
+ dszREP, O_DoRep, /* F3 REP or REPE or REPZ */
+ dszHLT, O_NoOperands, /* F4 HLT */
+ dszCMC, O_NoOperands, /* F5 CMC */
+ dszMULTI, O_GROUP31, /* F6 TEST, NOT, NEG, MUL, IMUL, */
+ dszMULTI, O_GROUP32, /* F7 DIv, IDIv F6=Byte F7=Word */
+ dszCLC, O_NoOperands, /* F8 CLC */
+ dszSTC, O_NoOperands, /* F9 STC */
+ dszCLI, O_NoOperands, /* FA CLI */
+ dszSTI, O_NoOperands, /* FB STI */
+ dszCLD, O_NoOperands, /* FC CLD */
+ dszSTD, O_NoOperands, /* FD STD */
+ dszMULTI, O_GROUP4, /* FE INC, DEC mem/reg (byte) */
+ dszMULTI, O_GROUP5, /* FF INC, DEC, CALL, JMP, PUSH */
+
+ dszMULTI, O_GROUP6, /* 0 MULTI */
+ dszMULTI, O_GROUP7, /* 1 MULTI */
+ dszLAR, O_Reg_Modrm, /* 2 LAR */
+ dszLSL, O_Reg_Modrm, /* 3 LSL */
+ dszRESERVED, O_DoDB, /* 4 */
+ dszLOADALL, O_NoOperands, /* 5 LOADALL */
+ dszCLTS, O_NoOperands, /* 6 CLTS */
+ dszMOV, O_Modrm_CReg, /* 20 MOV */
+ dszMOV, O_Modrm_CReg, /* 21 MOV */
+ dszMOV, O_CReg_Modrm, /* 22 MOV */
+ dszMOV, O_CReg_Modrm, /* 23 MOV */
+ dszMOV, O_Modrm_CReg, /* 24 MOV */
+ dszRESERVED, O_DoDB, /* 25 */
+ dszMOV, O_CReg_Modrm, /* 26 MOV */
+
+ dszSETNL, O_bModrm, /* 7D SETNL */
+ dszRESERVED, O_DoDB, /* 7E */
+ dszRESERVED, O_DoDB, /* 7F */
+ dszJO, O_Rel16, /* 80 JO */
+ dszJNO, O_Rel16, /* 81 JNO */
+ dszJB, O_Rel16, /* 82 JB */
+ dszJNB, O_Rel16, /* 83 JNB */
+ dszJE, O_Rel16, /* 84 JE */
+ dszJNE, O_Rel16, /* 85 JNE */
+ dszJBE, O_Rel16, /* 86 JBE */
+ dszJNBE, O_Rel16, /* 87 JNBE */
+ dszJS, O_Rel16, /* 88 JS */
+ dszJNS, O_Rel16, /* 89 JNS */
+ dszJP, O_Rel16, /* 8A JP */
+ dszJNP, O_Rel16, /* 8B JNP */
+ dszJL, O_Rel16, /* 8C JL */
+ dszJNL, O_Rel16, /* 8D JNL */
+ dszJLE, O_Rel16, /* 8E JLE */
+ dszJNLE, O_Rel16, /* 8F JNLE */
+ dszSETO, O_bModrm, /* 90 SETO */
+ dszSETNO, O_bModrm, /* 91 SETNO */
+ dszSETB, O_bModrm, /* 92 SETB */
+ dszSETNB, O_bModrm, /* 93 SETNB */
+ dszSETE, O_bModrm, /* 94 SETE */
+ dszSETNE, O_bModrm, /* 95 SETNE */
+ dszSETBE, O_bModrm, /* 96 SETBE */
+ dszSETA, O_bModrm, /* 97 SETNBE */
+ dszSETS, O_bModrm, /* 98 SETS */
+ dszSETNS, O_bModrm, /* 99 SETNS */
+ dszSETP, O_bModrm, /* 9A SETP */
+ dszSETNP, O_bModrm, /* 9B SETNP */
+ dszSETL, O_bModrm, /* 9C SETL */
+ dszSETGE, O_bModrm, /* 9D SETGE */
+ dszSETLE, O_bModrm, /* 9E SETLE */
+ dszSETNLE,O_bModrm, /* 9F SETNLE */
+ dszPUSH, O_sReg2, /* A0 PUSH FS */
+ dszPOP, O_sReg2, /* A1 POP FS */
+ dszRESERVED, O_DoDB, /* A2 */
+ dszBT, O_Modrm_Reg, /* A3 BT */
+ dszSHLD, O_Modrm_Reg_Ib, /* A4 SHLD */
+ dszSHLD, O_Modrm_Reg_CL, /* A5 SHLD */
+ dszRESERVED, O_DoDB, /* A6 [02] */
+ dszRESERVED, O_DoDB, /* A7 [02] */
+ dszPUSH, O_sReg2, /* A8 PUSH GS */
+ dszPOP, O_sReg2, /* A9 POP GS */
+ dszRESERVED, O_DoDB, /* AA */
+ dszBTS, O_vModrm_Reg, /* AB BTS */
+ dszSHRD, O_Modrm_Reg_Ib, /* AC SHRD */
+ dszSHRD, O_Modrm_Reg_CL, /* AD SHRD */
+ dszRESERVED, O_DoDB, /* AE */
+ dszIMUL, O_Reg_Modrm, /* AF IMUL */
+ dszCMPXCHG,O_bModrm_Reg, /* B0 XBTS [02] */
+ dszCMPXCHG,O_Modrm_Reg, /* B1 IBTS [02] */
+ dszLSS, O_fReg_Modrm, /* B2 LSS */
+ dszBTR, O_Modrm_Reg, /* B3 BTR */
+ dszLFS, O_fReg_Modrm, /* B4 LFS */
+ dszLGS, O_fReg_Modrm, /* B5 LGS */
+ dszMOVZX, O_Reg_bModrm, /* B6 MOVZX */
+ dszMOVZX, O_Reg_wModrm, /* B7 MOVZX */
+ dszRESERVED, O_DoDB, /* B8 */
+ dszRESERVED, O_DoDB, /* B9 */
+ dszMULTI, O_GROUP8, /* BA MULTI */
+ dszBTC, O_Modrm_Reg, /* BB BTC */
+ dszBSF, O_Reg_Modrm, /* BC BSF */
+ dszBSR, O_Reg_Modrm, /* BD BSR */
+ dszMOVSX, O_Reg_bModrm, /* BE MOVSX */
+ dszMOVSX, O_Reg_wModrm, /* BF MOVSX */
+ dszXADD, O_bModrm_Reg, /* C0 XADD */
+ dszXADD, O_Modrm_Reg, /* C1 XADD */
+ dszRESERVED, O_DoDB, /* C2 */
+ dszRESERVED, O_DoDB, /* C3 */
+ dszRESERVED, O_DoDB, /* C4 */
+ dszRESERVED, O_DoDB, /* C5 */
+ dszRESERVED, O_DoDB, /* C6 */
+ dszRESERVED, O_DoDB, /* C7 */
+ dszBSWAP, O_oReg, /* C8 BSWAP */
+ dszBSWAP, O_oReg, /* C9 BSWAP */
+ dszBSWAP, O_oReg, /* CA BSWAP */
+ dszBSWAP, O_oReg, /* CB BSWAP */
+ dszBSWAP, O_oReg, /* CC BSWAP */
+ dszBSWAP, O_oReg, /* CD BSWAP */
+ dszBSWAP, O_oReg, /* CE BSWAP */
+ dszBSWAP, O_oReg /* CF BSWAP */
+};
+
+/* Auxilary lists of mnemonics for groups of two byte instructions: */
+/* All of the instructions within each of these groups are of the same */
+/* class, so only the mnemonic string is needed, the index into the */
+/* action table is implicit. */
+
+static CBC *group[][8] = {
+
+/* 00 */ {dszADD, dszOR, dszADC, dszSBB, /* group 1 */
+ dszAND, dszSUB, dszXOR, dszCMP},
+
+/* 01 */ {dszROL, dszROR, dszRCL, dszRCR, /* group 2 */
+ dszSHL, dszSHR, dszRESERVED, dszSAR},
+
+/* 02 */ {dszINC, dszDEC, dszRESERVED, dszRESERVED, /* group 4 */
+ dszRESERVED, dszRESERVED, dszRESERVED, dszRESERVED},
+
+/* 03 */ {dszSLDT, dszSTR, dszLLDT, dszLTR, /* group 6 */
+ dszVERR, dszVERW, dszRESERVED, dszRESERVED},
+
+/* 04 */ {dszRESERVED, dszRESERVED, dszRESERVED, dszRESERVED, /* group 8 */
+ dszBT, dszBTS, dszBTR, dszBTC}
+
+ };
+
+/* Auxilary orderd pairs for groups of two byte instructions structured */
+/* the same was as distbl above. */
+
+static Tdistbl groupt[][8] = {
+
+/* 00 00 x87-D8-1 */
+ { dszFADD, O_dModrm, /* D8-0 FADD */
+ dszFMUL, O_dModrm, /* D8-1 FMUL */
+ dszFCOM, O_dModrm, /* D8-2 FCOM */
+ dszFCOMP, O_dModrm, /* D8-3 FCOMP */
+ dszFSUB, O_dModrm, /* D8-4 FSUB */
+ dszFSUBR, O_dModrm, /* D8-5 FSUBR */
+ dszFDIV, O_dModrm, /* D8-6 FDIV */
+ dszFDIVR, O_dModrm }, /* D8-7 FDIVR */
+
+/* 01 x87-D8-2 */
+ { dszFADD, O_ST_iST, /* D8-0 FADD */
+ dszFMUL, O_ST_iST, /* D8-1 FMUL */
+ dszFCOM, O_iST, /* D8-2 FCOM */
+ dszFCOMP, O_iST, /* D8-3 FCOMP */
+ dszFSUB, O_ST_iST, /* D8-4 FSUB */
+ dszFSUBR, O_ST_iST, /* D8-5 FSUBR */
+ dszFDIV, O_ST_iST, /* D8-6 FDIV */
+ dszFDIVR, O_ST_iST }, /* D8-7 FDIVR */
+
+/* 02 01 x87-D9-1 */
+ { dszFLD, O_dModrm, /* D9-0 FLD */
+ dszRESERVED, O_DoDB, /* D9-1 */
+ dszFST, O_dModrm, /* D9-2 FST */
+ dszFSTP, O_dModrm, /* D9-3 FSTP */
+ dszFLDENV, O_Modrm, /* D9-4 FLDENV */
+ dszFLDCW, O_Modrm, /* D9-5 FLDCW */
+ dszFNSTENV, O_Modrm, /* D9-6 FNSTENV */
+ dszFNSTCW, O_Modrm }, /* D9-7 FNSTCW */
+
+/* 03 01 x87-D9-2 TTT=0,1,2,3 */
+ { dszFLD, O_iST, /* D9-0 FLD */
+ dszFXCH, O_iST, /* D9-1 FXCH */
+ dszFNOP, O_NoOperands, /* D9-2 FNOP */
+ dszFSTP, O_iST, /* D9-3 FSTP */
+ dszRESERVED, O_DoDB, /* D9-4 */
+ dszRESERVED, O_DoDB, /* D9-5 */
+ dszRESERVED, O_DoDB, /* D9-6 */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 04 02 x89-DA-1 */
+ { dszFIADD, O_dModrm, /* DA-0 FIADD */
+ dszFIMUL, O_dModrm, /* DA-1 FIMUL */
+ dszFICOM, O_dModrm, /* DA-2 FICOM */
+ dszFICOMP, O_dModrm, /* DA-3 FICOMP */
+ dszFISUB, O_dModrm, /* DA-4 FISUB */
+ dszFISUBR, O_dModrm, /* DA-5 FISUBR */
+ dszFIDIV, O_dModrm, /* DA-6 FIDIV */
+ dszFIDIVR, O_dModrm }, /* DA-7 FIDIVR */
+
+/* 05 x87-DA-2 */
+ { dszRESERVED, O_DoDB, /* DA-0 */
+ dszRESERVED, O_DoDB, /* DA-1 */
+ dszRESERVED, O_DoDB, /* DA-2 */
+ dszRESERVED, O_DoDB, /* DA-3 */
+ dszRESERVED, O_DoDB, /* DA-4 */
+ dszFUCOMPP, O_NoOperands, /* DA-5 */
+ dszRESERVED, O_DoDB, /* DA-6 */
+ dszRESERVED, O_DoDB }, /* DA-7 */
+
+/* 06 03 x87-DB-1 */
+ { dszFILD, O_dModrm, /* DB-0 FILD */
+ dszRESERVED, O_DoDB, /* DB-1 */
+ dszFIST, O_dModrm, /* DB-2 FIST */
+ dszFISTP, O_dModrm, /* DB-3 FISTP */
+ dszRESERVED, O_DoDB, /* DB-4 */
+ dszFLD, O_tModrm, /* DB-5 FLD */
+ dszRESERVED, O_DoDB, /* DB-6 */
+ dszFSTP, O_tModrm }, /* DB-7 FSTP */
+
+/* 07 x87-DB-2 ttt=4 */
+ { dszFENI, O_NoOperands, /* DB-0 FENI */
+ dszFDISI, O_NoOperands, /* DB-1 FDISI */
+ dszFNLEX, O_NoOperands, /* DB-2 FNLEX */
+ dszFNINIT, O_NoOperands, /* DB-3 FNINIT */
+ dszFSETPM, O_DoDB, /* DB-4 FSETPM */
+ dszRESERVED, O_DoDB, /* DB-5 */
+ dszRESERVED, O_DoDB, /* DB-6 */
+ dszRESERVED, O_DoDB }, /* DB-7 */
+
+/* 08 04 x87-DC-1 */
+ { dszFADD, O_qModrm, /* DC-0 FADD */
+ dszFMUL, O_qModrm, /* DC-1 FMUL */
+ dszFCOM, O_qModrm, /* DC-2 FCOM */
+ dszFCOMP, O_qModrm, /* DC-3 FCOMP */
+ dszFSUB, O_qModrm, /* DC-4 FSUB */
+ dszFSUBR, O_qModrm, /* DC-5 FSUBR */
+ dszFDIV, O_qModrm, /* DC-6 FDIV */
+ dszFDIVR, O_qModrm }, /* DC-7 FDIVR */
+
+/* 09 x87-DC-2 */
+ { dszFADD, O_iST_ST, /* DC-0 FADD */
+ dszFMUL, O_iST_ST, /* DC-1 FMUL */
+ dszFCOM, O_iST, /* DC-2 FCOM */
+ dszFCOMP, O_iST, /* DC-3 FCOMP */
+ dszFSUB, O_iST_ST, /* DC-4 FSUB */
+ dszFSUBR, O_iST_ST, /* DC-5 FSUBR */
+ dszFDIV, O_iST_ST, /* DC-6 FDIVR */
+ dszFDIVR, O_iST_ST }, /* DC-7 FDIV */
+
+/* 10 05 x87-DD-1 */
+ { dszFLD, O_qModrm, /* DD-0 FLD */
+ dszRESERVED, O_DoDB, /* DD-1 */
+ dszFST, O_qModrm, /* DD-2 FST */
+ dszFSTP, O_qModrm, /* DD-3 FSTP */
+ dszFRSTOR, O_Modrm, /* DD-4 FRSTOR */
+ dszRESERVED, O_DoDB, /* DD-5 */
+ dszFNSAVE, O_Modrm, /* DD-6 FNSAVE */
+ dszFNSTSW, O_Modrm }, /* DD-7 FNSTSW */
+
+/* 11 x87-DD-2 */
+ { dszFFREE, O_iST, /* DD-0 FFREE */
+ dszFXCH, O_iST, /* DD-1 FXCH */
+ dszFST, O_iST, /* DD-2 FST */
+ dszFSTP, O_iST, /* DD-3 FSTP */
+ dszFUCOM, O_iST, /* DD-4 FUCOM */
+ dszFUCOMP, O_iST, /* DD-5 FUCOMP */
+ dszRESERVED, O_DoDB, /* DD-6 */
+ dszRESERVED, O_DoDB }, /* DD-7 */
+
+/* 12 06 x87-DE-1 */
+ { dszFIADD, O_wModrm, /* DE-0 FIADD */
+ dszFIMUL, O_wModrm, /* DE-1 FIMUL */
+ dszFICOM, O_wModrm, /* DE-2 FICOM */
+ dszFICOMP, O_wModrm, /* DE-3 FICOMP */
+ dszFISUB, O_wModrm, /* DE-4 FISUB */
+ dszFISUBR, O_wModrm, /* DE-5 FISUBR */
+ dszFIDIV, O_wModrm, /* DE-6 FIDIV */
+ dszFIDIVR, O_wModrm }, /* DE-7 FIDIVR */
+
+/* 13 x87-DE-2 */
+ { dszFADDP, O_iST_ST, /* DE-0 FADDP */
+ dszFMULP, O_iST_ST, /* DE-1 FMULP */
+ dszFCOMP, O_iST, /* DE-2 FCOMP */
+ dszFCOMPP, O_NoOperands, /* DE-3 FCOMPP */
+ dszFSUBP, O_iST_ST, /* DE-4 FSUBP */
+ dszFSUBRP, O_iST_ST, /* DE-5 FSUBRP */
+ dszFDIVRP, O_iST_ST, /* DE-6 FDIVRP */
+ dszFDIVP, O_iST_ST}, /* DE-7 FDIVP */
+
+/* 14 07 x87-DF-1 */
+ { dszFILD, O_wModrm, /* DF-0 FILD */
+ dszRESERVED, O_DoDB, /* DF-1 */
+ dszFIST, O_wModrm, /* DF-2 FIST */
+ dszFISTP, O_wModrm, /* DF-3 FISTP */
+ dszFBLD, O_tModrm, /* DF-4 FBLD */
+ dszFILD, O_qModrm, /* DF-5 FILD */
+ dszFBSTP, O_tModrm, /* DF-6 FBSTP */
+ dszFISTP, O_qModrm }, /* DF-7 FISTP */
+
+/* 15 x87-DF-2 */
+ { dszFFREE, O_iST, /* DF-0 FFREE */
+ dszFXCH, O_iST, /* DF-1 FXCH */
+ dszFST, O_iST, /* DF-2 FST */
+ dszFSTP, O_iST, /* DF-3 FSTP */
+ dszFNSTSW, O_NoOperands, /* DF-4 FNSTSW */
+ dszRESERVED, O_DoDB, /* DF-5 */
+ dszRESERVED, O_DoDB, /* DF-6 */
+ dszRESERVED, O_DoDB }, /* DF-7 */
+
+/* 16 01 x87-D9 Mod=3 TTT=4 */
+ { dszFCHS, O_NoOperands, /* D9-0 FCHS */
+ dszFABS, O_NoOperands, /* D9-1 FABS */
+ dszRESERVED, O_DoDB, /* D9-2 */
+ dszRESERVED, O_DoDB, /* D9-3 */
+ dszFTST, O_NoOperands, /* D9-4 FTST */
+ dszFXAM, O_NoOperands, /* D9-5 FXAM */
+ dszRESERVED, O_DoDB, /* D9-6 */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 17 01 x87-D9 Mod=3 TTT=5 */
+ { dszFLD1, O_NoOperands, /* D9-0 FLD1 */
+ dszFLDL2T, O_NoOperands, /* D9-1 FLDL2T */
+ dszFLDL2E, O_NoOperands, /* D9-2 FLDL2E */
+ dszFLDPI, O_NoOperands, /* D9-3 FLDPI */
+ dszFLDLG2, O_NoOperands, /* D9-4 FLDLG2 */
+ dszFLDLN2, O_NoOperands, /* D9-5 FLDLN2 */
+ dszFLDZ, O_NoOperands, /* D9-6 FLDZ */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 18 01 x87-D9 Mod=3 TTT=6 */
+ { dszF2XM1, O_NoOperands, /* D9-0 F2XM1 */
+ dszFYL2X, O_NoOperands, /* D9-1 FYL2X */
+ dszFPTAN, O_NoOperands, /* D9-2 FPTAN */
+ dszFPATAN, O_NoOperands, /* D9-3 FPATAN */
+ dszFXTRACT, O_NoOperands, /* D9-4 FXTRACT */
+ dszFPREM1, O_NoOperands, /* D9-5 FPREM1 */
+ dszFDECSTP, O_NoOperands, /* D9-6 FDECSTP */
+ dszFINCSTP, O_NoOperands }, /* D9-7 FINCSTP */
+
+/* 19 01 x87-D9 Mod=3 TTT=7 */
+ { dszFPREM, O_NoOperands, /* D9-0 FPREM */
+ dszFYL2XP1, O_NoOperands, /* D9-1 FYL2XP1 */
+ dszFSQRT, O_NoOperands, /* D9-2 FSQRT */
+ dszFSINCOS, O_NoOperands, /* D9-3 FSINCOS */
+ dszFRNDINT, O_NoOperands, /* D9-4 FRNDINT */
+ dszFSCALE, O_NoOperands, /* D9-5 FSCALE */
+ dszFSIN, O_NoOperands, /* D9-6 FSIN */
+ dszFCOS, O_NoOperands }, /* D9-7 FCOS */
+
+/* 20 group 3 */
+ { dszTEST, O_bModrm_Ib, /* F6-0 TEST */
+ dszRESERVED, O_DoDB, /* F6-1 */
+ dszNOT, O_bModrm, /* F6-2 NOT */
+ dszNEG, O_bModrm, /* F6-3 NEG */
+ dszMUL, O_bModrm, /* F6-4 MUL */
+ dszIMUL, O_bModrm, /* F6-5 IMUL */
+ dszDIV, O_bModrm, /* F6-6 DIV */
+ dszIDIV, O_bModrm }, /* F6-7 IDIV */
+
+/* 21 group 3 */
+ { dszTEST, O_vModrm_Iv, /* F7-0 TEST */
+ dszRESERVED, O_DoDB, /* F7-1 */
+ dszNOT, O_vModrm, /* F7-2 NOT */
+ dszNEG, O_vModrm, /* F7-3 NEG */
+ dszMUL, O_vModrm, /* F7-4 MUL */
+ dszIMUL, O_vModrm, /* F7-5 IMUL */
+ dszDIV, O_vModrm, /* F7-6 DIV */
+ dszIDIV, O_vModrm }, /* F7-7 IDIV */
+
+/* 22 group 5 */
+ { dszINC, O_vModrm, /* FF-0 INC */
+ dszDEC, O_vModrm, /* FF-1 DEC */
+ dszCALL, O_vModrm, /* FF-2 CALL */
+ dszCALL, O_fModrm, /* FF-3 CALL */
+ dszJMP, O_vModrm, /* FF-4 JMP */
+ dszJMP, O_fModrm, /* FF-5 JMP */
+ dszPUSH, O_vModrm, /* FF-6 PUSH */
+ dszRESERVED, O_DoDB }, /* FF-7 */
+
+/* 23 group 7 */
+ { dszSGDT, O_Modrm, /* 0F-0 SGDT */
+ dszSIDT, O_Modrm, /* 0F-1 SIDT */
+ dszLGDT, O_Modrm, /* 0F-2 LGDT */
+ dszLIDT, O_Modrm, /* 0F-3 LIDT */
+ dszSMSW, O_wModrm, /* 0F-4 MSW */
+ dszRESERVED, O_DoDB, /* 0F-5 */
+ dszLMSW, O_wModrm, /* 0F-6 LMSW */
+ dszRESERVED, O_DoDB } /* 0F-7 */
+
+ };
+#pragma pack ()
+
+/*************************** end of d3.h ********************************/
diff --git a/private/windbg/em/p_mips/em.rc b/private/windbg/em/p_mips/em.rc
new file mode 100644
index 000000000..ff15b97de
--- /dev/null
+++ b/private/windbg/em/p_mips/em.rc
@@ -0,0 +1 @@
+#include "..\em\em.rc"
diff --git a/private/windbg/em/p_mips/emdp.c b/private/windbg/em/p_mips/emdp.c
new file mode 100644
index 000000000..96568b2ed
--- /dev/null
+++ b/private/windbg/em/p_mips/emdp.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp.c"
diff --git a/private/windbg/em/p_mips/emdp2.c b/private/windbg/em/p_mips/emdp2.c
new file mode 100644
index 000000000..5e0024775
--- /dev/null
+++ b/private/windbg/em/p_mips/emdp2.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp2.c"
diff --git a/private/windbg/em/p_mips/emdp3.c b/private/windbg/em/p_mips/emdp3.c
new file mode 100644
index 000000000..57d71318d
--- /dev/null
+++ b/private/windbg/em/p_mips/emdp3.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp3.c"
diff --git a/private/windbg/em/p_mips/emdpdev.c b/private/windbg/em/p_mips/emdpdev.c
new file mode 100644
index 000000000..dc55c423e
--- /dev/null
+++ b/private/windbg/em/p_mips/emdpdev.c
@@ -0,0 +1,1107 @@
+/**** EMDPDEV.C - Debugger end Execution Model (MIPS dependent code) **
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 15, 1990 by David W. Gray *
+ * *
+ * Revision History: *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+#include "strings.h"
+
+
+CONTEXT ContextSave;
+
+#ifndef SMARTALIAS
+void PurgeCache ( void );
+#endif
+
+#define CEXM_MDL_native 0x20
+
+
+/*
+** This is the description of all registers and flags containned on the
+** mips machine
+*/
+
+extern RD Rgrd[];
+
+extern struct {
+ FD fd;
+ USHORT iShift;
+} Rgfd[];
+
+#define SIZEOF_STACK_OFFSET sizeof(LONG)
+
+BOOL NEAR PASCAL IsStackSetup(
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddrProc
+) {
+ Unreferenced(hpid);
+ Unreferenced(htid);
+ Unreferenced(lpaddrProc);
+ return TRUE;
+}
+
+
+XOSD
+GetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ This function will get return a specific type of address.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to retrive the address from
+ htid - Supplies the handle to the thread to retrieve the address from
+ adr - Supplies the type of address to be retrieved
+ lpaddr - Returns the requested address
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+ XOSD xosd = xosdNone;
+ HEMI hemi = emiAddr(*lpaddr);
+ HMDI hmdi;
+ LPMDI lpmdi;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != NULL );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != NULL ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ _fmemset ( lpaddr, 0, sizeof ( ADDR ) );
+
+ switch ( adr ) {
+
+ case adrPC:
+ if ( lpthd && !(lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrData:
+ if ( lpthd && !(lpthd->drt & drtAllPresent )) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+
+#ifndef OSDEBUG4
+ case adrCurrent:
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ *lpaddr = lpthd->addrCurrent;
+ } else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ *lpaddr = lpprc->addrCurrent;
+
+ LLUnlock ( hprc );
+ }
+ break;
+#endif
+
+ case adrPC:
+ AddrInit(lpaddr, 0, 0,
+ (UOFFSET) lpthd->regs.XFir, lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrData:
+ AddrInit(lpaddr, 0, 0, 0,
+ lpthd->fFlat, lpthd->fOff32, FALSE, lpthd->fReal);
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrTlsBase:
+ /*
+ * If -1 then we have not gotten a value from the DM yet.
+ */
+
+ assert(hemi != 0);
+
+ if (hemi == 0) {
+ return xosdBadAddress;
+ }
+
+ if (hemi != emiAddr(lpthd->addrTls)) {
+ hmdi = LLFind( LlmdiFromHprc( hprc ), 0, (LPBYTE) &hemi, emdiEMI);
+ assert(hmdi != 0);
+
+ if (hmdi == 0) {
+ return xosdBadAddress;
+ }
+
+ lpmdi = LLLock( hmdi );
+
+ SendRequestX( dmfQueryTlsBase, hpid, htid, sizeof(OFFSET),
+ &lpmdi->lpBaseOfDll);
+
+ lpthd->addrTls = *((LPADDR) LpDmMsg->rgb);
+ emiAddr(lpthd->addrTls) = hemi;
+ LLUnlock( hmdi );
+
+ }
+
+ *lpaddr = lpthd->addrTls;
+ emiAddr(*lpaddr) = 0;
+ break;
+
+ default:
+
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != NULL ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosd;
+} /* GetAddr() */
+
+
+XOSD
+SetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != NULL );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != NULL ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ switch ( adr ) {
+ case adrPC:
+ if ( !( lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrData:
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+
+#ifndef OSDEBUG4
+ case adrCurrent:
+
+ if ( lpaddr->emi == NULL ) {
+ SetEmi ( hpid, lpaddr );
+ }
+
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ lpthd->addrCurrent = *lpaddr;
+ }
+ else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ lpprc->addrCurrent = *lpaddr;
+
+ LLUnlock ( hprc );
+ }
+ break;
+#endif
+
+ case adrPC:
+ lpthd->regs.XFir = GetAddrOff ( *lpaddr );
+ lpthd->drt |= drtCntrlDirty;
+ break;
+
+ case adrData:
+ case adrTlsBase:
+ default:
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != NULL ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosdNone;
+} /* SetAddr() */
+
+
+XOSD
+SetAddrFromCSIP (
+ HTHD hthd
+ )
+{
+
+ ADDR addr = {0};
+ LPTHD lpthd;
+
+ assert ( hthd != NULL && hthd != hthdInvalid );
+
+ lpthd = LLLock ( hthd );
+
+ GetAddrSeg ( addr ) = 0;
+ GetAddrOff ( addr ) = (UOFFSET) lpthd->regs.XFir;
+ emiAddr ( addr ) = 0;
+ ADDR_IS_FLAT ( addr ) = TRUE;
+
+#ifndef OSDEBUG4
+ lpthd->addrCurrent = addr;
+#endif
+
+ LLUnlock ( hthd );
+
+ return xosdNone;
+}
+
+
+LPVOID
+DoGetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPVOID lpvRegValue
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to extract the value of a single register from
+ the debuggee.
+
+Arguments:
+
+ lpregs - Supplies pointer to the register set for the debuggee
+ ireg - Supplies the index of the register to be read
+ lpvRegValue - Supplies the buffer to place the register value in
+
+Return Value:
+
+ return-value - lpvRegValue + size of register on sucess and NULL on
+ failure
+--*/
+
+{
+ switch ( ireg ) {
+ case CV_M4_IntZERO:
+ case CV_M4_IntAT:
+ case CV_M4_IntV0:
+ case CV_M4_IntV1:
+ case CV_M4_IntA0:
+ case CV_M4_IntA1:
+ case CV_M4_IntA2:
+ case CV_M4_IntA3:
+ case CV_M4_IntT0:
+ case CV_M4_IntT1:
+ case CV_M4_IntT2:
+ case CV_M4_IntT3:
+ case CV_M4_IntT4:
+ case CV_M4_IntT5:
+ case CV_M4_IntT6:
+ case CV_M4_IntT7:
+ case CV_M4_IntS0:
+ case CV_M4_IntS1:
+ case CV_M4_IntS2:
+ case CV_M4_IntS3:
+ case CV_M4_IntS4:
+ case CV_M4_IntS5:
+ case CV_M4_IntS6:
+ case CV_M4_IntS7:
+ case CV_M4_IntT8:
+ case CV_M4_IntT9:
+ case CV_M4_IntKT0:
+ case CV_M4_IntKT1:
+ case CV_M4_IntGP:
+ case CV_M4_IntSP:
+ case CV_M4_IntS8:
+ case CV_M4_IntRA:
+ case CV_M4_IntLO:
+ case CV_M4_IntHI:
+ //assert( ((DWORD)lpvRegValue & 0x7) == 0 );
+ *((PDWORDLONG) lpvRegValue) = ((PDWORDLONG)(&lpregs->XIntZero))[ireg - CV_M4_IntZERO];
+ (LPLONG) lpvRegValue += 2;
+ break;
+
+ case CV_M4_Fir:
+ *((LPLONG) lpvRegValue) = lpregs->XFir;
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ case CV_M4_Psr:
+ *((LPLONG) lpvRegValue) = lpregs->XPsr;
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ case CV_M4_FltF0:
+ case CV_M4_FltF1:
+ case CV_M4_FltF2:
+ case CV_M4_FltF3:
+ case CV_M4_FltF4:
+ case CV_M4_FltF5:
+ case CV_M4_FltF6:
+ case CV_M4_FltF7:
+ case CV_M4_FltF8:
+ case CV_M4_FltF9:
+ case CV_M4_FltF10:
+ case CV_M4_FltF11:
+ case CV_M4_FltF12:
+ case CV_M4_FltF13:
+ case CV_M4_FltF14:
+ case CV_M4_FltF15:
+ case CV_M4_FltF16:
+ case CV_M4_FltF17:
+ case CV_M4_FltF18:
+ case CV_M4_FltF19:
+ case CV_M4_FltF20:
+ case CV_M4_FltF21:
+ case CV_M4_FltF22:
+ case CV_M4_FltF23:
+ case CV_M4_FltF24:
+ case CV_M4_FltF25:
+ case CV_M4_FltF26:
+ case CV_M4_FltF27:
+ case CV_M4_FltF28:
+ case CV_M4_FltF29:
+ case CV_M4_FltF30:
+ case CV_M4_FltF31:
+ *((LPLONG) lpvRegValue) = ((LONG *)(&lpregs->FltF0))[ireg - CV_M4_FltF0];
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ case CV_M4_FltFsr:
+ *((LPLONG) lpvRegValue) = lpregs->Fsr;
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ default:
+ assert(FALSE);
+ }
+
+ return lpvRegValue;
+}
+
+
+LPVOID
+DoSetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPVOID lpvRegValue
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to set a specific register in a threads
+ context
+
+Arguments:
+
+ lpregs - Supplies pointer to register context for thread
+
+ ireg - Supplies the index of the register to be modified
+
+ lpvRegValue - Supplies the buffer containning the new data
+
+Return Value:
+
+ return-value - the pointer the the next location where a register
+ value could be.
+
+--*/
+
+{
+ switch ( ireg ) {
+ case CV_M4_IntZERO:
+ return NULL;
+
+ case CV_M4_IntAT:
+ case CV_M4_IntV0:
+ case CV_M4_IntV1:
+ case CV_M4_IntA0:
+ case CV_M4_IntA1:
+ case CV_M4_IntA2:
+ case CV_M4_IntA3:
+ case CV_M4_IntT0:
+ case CV_M4_IntT1:
+ case CV_M4_IntT2:
+ case CV_M4_IntT3:
+ case CV_M4_IntT4:
+ case CV_M4_IntT5:
+ case CV_M4_IntT6:
+ case CV_M4_IntT7:
+ case CV_M4_IntS0:
+ case CV_M4_IntS1:
+ case CV_M4_IntS2:
+ case CV_M4_IntS3:
+ case CV_M4_IntS4:
+ case CV_M4_IntS5:
+ case CV_M4_IntS6:
+ case CV_M4_IntS7:
+ case CV_M4_IntT8:
+ case CV_M4_IntT9:
+ case CV_M4_IntKT0:
+ case CV_M4_IntKT1:
+ case CV_M4_IntGP:
+ case CV_M4_IntSP:
+ case CV_M4_IntS8:
+ case CV_M4_IntRA:
+ case CV_M4_IntLO:
+ case CV_M4_IntHI:
+
+ //assert( ((DWORD)lpvRegValue & 0x7) == 0);
+ ((PDWORDLONG)(&lpregs->XIntZero))[ireg - CV_M4_IntZERO] = *((PDWORDLONG) lpvRegValue);
+ (LPLONG) lpvRegValue += 2;
+ break;
+
+ case CV_M4_Fir:
+ lpregs->XFir = *((LPLONG) lpvRegValue);
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ case CV_M4_Psr:
+ lpregs->XPsr = *((LPLONG) lpvRegValue);
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ case CV_M4_FltF0:
+ case CV_M4_FltF1:
+ case CV_M4_FltF2:
+ case CV_M4_FltF3:
+ case CV_M4_FltF4:
+ case CV_M4_FltF5:
+ case CV_M4_FltF6:
+ case CV_M4_FltF7:
+ case CV_M4_FltF8:
+ case CV_M4_FltF9:
+ case CV_M4_FltF10:
+ case CV_M4_FltF11:
+ case CV_M4_FltF12:
+ case CV_M4_FltF13:
+ case CV_M4_FltF14:
+ case CV_M4_FltF15:
+ case CV_M4_FltF16:
+ case CV_M4_FltF17:
+ case CV_M4_FltF18:
+ case CV_M4_FltF19:
+ case CV_M4_FltF20:
+ case CV_M4_FltF21:
+ case CV_M4_FltF22:
+ case CV_M4_FltF23:
+ case CV_M4_FltF24:
+ case CV_M4_FltF25:
+ case CV_M4_FltF26:
+ case CV_M4_FltF27:
+ case CV_M4_FltF28:
+ case CV_M4_FltF29:
+ case CV_M4_FltF30:
+ case CV_M4_FltF31:
+ ((LONG *)(&lpregs->FltF0))[ireg - CV_M4_FltF0] = *((LPLONG) lpvRegValue);
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ case CV_M4_FltFsr:
+ lpregs->XPsr = *((LPLONG) lpvRegValue);
+ *((LPLONG) lpvRegValue) = lpregs->Fsr;
+ (LPLONG) lpvRegValue += 1;
+ break;
+
+ default:
+ assert(FALSE);
+ return NULL;
+ }
+
+ return lpvRegValue;
+}
+
+LPVOID
+DoSetFrameReg(
+ HPID hpid,
+ HTID htid,
+ LPTHD lpthd,
+ PKNONVOLATILE_CONTEXT_POINTERS contextPtrs,
+ DWORD ireg,
+ LPVOID lpvRegValue
+ )
+{
+
+ return DoSetReg(&lpthd->regs, ireg, lpvRegValue);
+}
+
+XOSD
+GetFlagValue (
+ HPID hpid,
+ HTID htid,
+ DWORD iFlag,
+ LPVOID lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPCONTEXT lpregs;
+ DWORD value;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+ hthd = HthdFromHtid(hprc, htid);
+
+ assert ( hthd != NULL );
+ lpthd = LLLock ( hthd );
+
+ lpregs = &lpthd->regs;
+
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+
+
+ //
+ // MIPS Psr is 32 bits:
+ //
+#ifdef OSDEBUG4
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.dwId, &value ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidParameter;
+ }
+
+ value = (value >> Rgfd[iFlag].iShift) & ((1 << Rgfd[iFlag].fd.dwcbits) - 1);
+ if (Rgfd[iFlag].fd.dwcbits > 32) {
+ *( (LPLONG) lpvRegValue) = value;
+#else
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &value ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidRegister;
+ }
+
+ value = (value >> Rgfd[iFlag].iShift) & ((1 << Rgfd[iFlag].fd.cbits) - 1);
+ *( (LPLONG) lpvRegValue) = value;
+#endif
+
+ LLUnlock(hthd);
+ return xosdNone;
+}
+
+#ifndef OSDEBUG4
+
+XOSD
+StackWalkSetup(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to setup the StackWalk Structure.
+ This routine will defer the processing to the dm
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk
+
+ hthd - Supplies handle to thread to stack walk
+
+ lpstkframe - Supplies pointer the stack walk structure
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+
+
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == NULL) {
+#ifdef OSDEBUG4
+ return xosdBadThread;
+#else
+ return xosdInvalidThread;
+#endif
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (lpthd->drt & (drtCntrlDirty|drtAllDirty)) {
+ SendRequestX(dmfWriteReg, hpid, htid, sizeof(CONTEXT), &lpthd->regs);
+ lpthd->drt &= ~(drtCntrlDirty|drtAllDirty);
+ }
+
+ UpdateRegisters( hprc, hthd );
+
+ ContextSave = lpthd->regs;
+
+ if (StackWalk( IMAGE_FILE_MACHINE_R4000,
+ hpid,
+ htid,
+ lpstkframe,
+ &ContextSave,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ NULL,
+ NULL
+ )) {
+
+ LLUnlock( hthd );
+ return xosdNone;
+
+ }
+
+ LLUnlock( hthd );
+
+ return xosdEndOfStack;
+} /* StackWalkSetup() */
+
+
+XOSD
+StackWalkNext(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to move up a level in the call stack.
+ We defer down to the DM to do this.
+
+Arguments:
+
+ hpid - Supplies process handle to stack walk
+
+ htid - Supplies thread handle to stack walk
+
+ lpstkframe - Supplies pointer to stack walk data
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+
+
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == NULL) {
+#ifdef OSDEBUG4
+ return xosdBadThread;
+#else
+ return xosdInvalidThread;
+#endif
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (StackWalk( IMAGE_FILE_MACHINE_R4000,
+ hpid,
+ htid,
+ lpstkframe,
+ &ContextSave,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ NULL,
+ NULL
+ )) {
+
+ LLUnlock( hthd );
+ return xosdNone;
+
+ }
+
+ LLUnlock( hthd );
+
+ return xosdEndOfStack;
+} /* StackWalkNext() */
+
+
+XOSD
+SetFrame(
+ HPID hpid,
+ HTID htid,
+ PFRAME pframe
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to fill in the FRAME structure.
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk in
+
+ hthd - Supplies handle to thread to stack walk in
+
+ pframe - Supplies pointer to the frame structure to fill in
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ DWORDLONG ull;
+
+ GetRegValue( hpid, htid, CV_M4_IntSP, &ull);
+
+ FrameFlat ( *pframe ) = TRUE;
+ FrameOff32 ( *pframe ) = TRUE;
+ FrameReal (*pframe ) = FALSE;
+
+ SetFrameBPOff( *pframe, (DWORD)ull );
+ SetFrameBPSeg( *pframe, 0);
+
+ pframe->SS = 0;
+ pframe->DS = 0;
+ pframe->PID = hpid;
+ pframe->TID = htid;
+
+ return xosdNone;
+} /* SetFrame() */
+
+#endif // !OSDEBUG4
+
+
+PIMAGE_RUNTIME_FUNCTION_ENTRY
+LookupFunctionEntry (
+ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable,
+ DWORD NumberOfFunctions,
+ DWORD ControlPc
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the currently active function tables for an entry
+ that corresponds to the specified PC value.
+
+Arguments:
+
+ ControlPc - Supplies the address of an instruction within the specified
+ function.
+
+Return Value:
+
+ If there is no entry in the function table for the specified PC, then
+ NULL is returned. Otherwise, the address of the function table entry
+ that corresponds to the specified PC is returned.
+
+--*/
+
+{
+
+ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
+ LONG High;
+ LONG Low;
+ LONG Middle;
+
+ //
+ // Initialize search indicies.
+ //
+
+ Low = 0;
+ High = NumberOfFunctions - 1;
+
+ //
+ // Perform binary search on the function table for a function table
+ // entry that subsumes the specified PC.
+ //
+
+ while (High >= Low) {
+
+ //
+ // Compute next probe index and test entry. If the specified PC
+ // is greater than of equal to the beginning address and less
+ // than the ending address of the function table entry, then
+ // return the address of the function table entry. Otherwise,
+ // continue the search.
+ //
+
+ Middle = (Low + High) >> 1;
+ FunctionEntry = &FunctionTable[Middle];
+ if (ControlPc < FunctionEntry->BeginAddress) {
+ High = Middle - 1;
+
+ } else if (ControlPc >= FunctionEntry->EndAddress) {
+ Low = Middle + 1;
+
+ } else {
+ return FunctionEntry;
+ }
+ }
+
+ //
+ // A function table entry for the specified PC was not found.
+ //
+
+ return NULL;
+}
+
+
+LPVOID
+SwFunctionTableAccess(
+ HPID hpid,
+ DWORD AddrBase
+ )
+{
+ HLLI hlli = 0;
+ HMDI hmdi = 0;
+ LPMDI lpmdi = 0;
+ PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
+
+
+ hmdi = SwGetMdi( hpid, AddrBase );
+ if (!hmdi) {
+ return NULL;
+ }
+
+ lpmdi = LLLock( hmdi );
+ if (lpmdi) {
+
+ rf = LookupFunctionEntry( lpmdi->lpDebug->lpRtf,
+ lpmdi->lpDebug->cRtf,
+ AddrBase
+ );
+
+ LLUnlock( hmdi );
+ return (LPVOID)rf;
+ }
+ return NULL;
+}
+
+BOOL
+SwReadMemory(
+ HPID hpid,
+ LPCVOID lpBaseAddress,
+ LPVOID lpBuffer,
+ DWORD nSize,
+ LPDWORD lpNumberOfBytesRead
+ )
+{
+ ADDR addr;
+ DWORD cb;
+ XOSD xosd;
+
+ addr.addr.off = (OFFSET)lpBaseAddress;
+ addr.addr.seg = 0;
+ addr.emi = 0;
+ addr.mode.fFlat = TRUE;
+ addr.mode.fOff32 = FALSE;
+ addr.mode.fIsLI = FALSE;
+ addr.mode.fReal = FALSE;
+
+ xosd = ReadBuffer( hpid, NULL, &addr, nSize, lpBuffer, &cb );
+ if (xosd != xosdNone) {
+ return FALSE;
+ }
+
+ if (lpNumberOfBytesRead) {
+ *lpNumberOfBytesRead = cb;
+ }
+
+ return TRUE;
+}
+
+
+XOSD
+SetPath(
+ HPID hpid,
+ HTID htid,
+ BOOL Set,
+ LSZ Path
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path in the DM
+
+Arguments:
+
+ hpid - process
+ htid - thread
+ Set - set flag
+ Path - Path to search, PATH if null
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ char Buffer[ MAX_PATH ];
+ SETPTH *SetPth = (SETPTH *)&Buffer;
+
+ if ( Set ) {
+
+ SetPth->Set = TRUE;
+ if ( Path ) {
+ strcpy(SetPth->Path, Path );
+ } else {
+ SetPth->Path[0] = '\0';
+ }
+ } else {
+ SetPth->Set = FALSE;
+ SetPth->Path[0] = '\0';
+ }
+
+ return SendRequestX( dmfSetPath, hpid, htid, sizeof(SETPTH) + strlen(SetPth->Path), SetPth );
+}
+
+
+
+
+XOSD
+GetFunctionInfo(
+ HPID hpid,
+ PADDR Addr,
+ PFUNCTION_INFO FunctionInfo
+ )
+/*++
+
+Routine Description:
+
+ Gets function information for a particular address.
+
+Arguments:
+
+ hpid - process
+ Addr - Address
+ FunctionInfo - Function information
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ PIMAGE_RUNTIME_FUNCTION_ENTRY pfe;
+
+
+ pfe = SwFunctionTableAccess( hpid, GetAddrOff( *Addr ) );
+
+ if ( pfe ) {
+
+ AddrInit( &FunctionInfo->AddrStart, 0,0, pfe->BeginAddress,
+ TRUE, TRUE, FALSE, FALSE );
+ AddrInit( &FunctionInfo->AddrEnd, 0,0, pfe->EndAddress,
+ TRUE, TRUE, FALSE, FALSE );
+ AddrInit( &FunctionInfo->AddrPrologEnd, 0,0, pfe->PrologEndAddress,
+ TRUE, TRUE, FALSE, FALSE );
+
+ } else {
+
+ xosd = xosdUnknown;
+ }
+
+ return xosd;
+}
diff --git a/private/windbg/em/p_mips/emmip.def b/private/windbg/em/p_mips/emmip.def
new file mode 100644
index 000000000..d5db1f150
--- /dev/null
+++ b/private/windbg/em/p_mips/emmip.def
@@ -0,0 +1,4 @@
+LIBRARY emmip initinstance
+EXPORTS
+ DBGVersionCheck PRIVATE
+ EMFunc PRIVATE
diff --git a/private/windbg/em/p_mips/flags.h b/private/windbg/em/p_mips/flags.h
new file mode 100644
index 000000000..5043994be
--- /dev/null
+++ b/private/windbg/em/p_mips/flags.h
@@ -0,0 +1,69 @@
+#ifdef OSDEBUG4
+ { szFlagCu, rtRegular|rtExtended, 4, CV_M4_Psr, 28 },
+ { szFlagCu3, rtRegular|rtExtended, 1, CV_M4_Psr, 31 },
+ { szFlagCu2, rtRegular|rtExtended, 1, CV_M4_Psr, 30 },
+ { szFlagCu1, rtRegular|rtExtended, 1, CV_M4_Psr, 29 },
+ { szFlagCu0, rtRegular|rtExtended, 1, CV_M4_Psr, 28 },
+ { szFlagRP, rtRegular|rtExtended, 1, CV_M4_Psr, 27 },
+ { szFlagFR, rtRegular|rtExtended, 1, CV_M4_Psr, 26 },
+ { szFlagRE, rtRegular|rtExtended, 1, CV_M4_Psr, 25 },
+ { szFlagDS, rtRegular|rtExtended, 9, CV_M4_Psr, 16 },
+
+ { szFlagImsk, rtRegular|rtExtended, 8, CV_M4_Psr, 8},
+ { szFlagInt5, rtRegular|rtExtended, 1, CV_M4_Psr, 15 },
+ { szFlagInt4, rtRegular|rtExtended, 1, CV_M4_Psr, 14 },
+ { szFlagInt3, rtRegular|rtExtended, 1, CV_M4_Psr, 13 },
+ { szFlagInt2, rtRegular|rtExtended, 1, CV_M4_Psr, 12 },
+ { szFlagInt1, rtRegular|rtExtended, 1, CV_M4_Psr, 11 },
+ { szFlagInt0, rtRegular|rtExtended, 1, CV_M4_Psr, 10 },
+ { szFlagSw1, rtRegular|rtExtended, 1, CV_M4_Psr, 9 },
+ { szFlagSw0, rtRegular|rtExtended, 1, CV_M4_Psr, 8 },
+
+// R{2,3,6}000 flags
+// { szFlagKuo, rtRegular|rtExtended, 1, CV_M4_Psr, 5 },
+// { szFlagIeo, rtRegular|rtExtended, 1, CV_M4_Psr, 4 },
+// { szFlagKup, rtRegular|rtExtended, 1, CV_M4_Psr, 3 },
+// { szFlagIep, rtRegular|rtExtended, 1, CV_M4_Psr, 2 },
+// { szFlagKuc, rtRegular|rtExtended, 1, CV_M4_Psr, 1 },
+// { szFlagIec, rtRegular|rtExtended, 1, CV_M4_Psr, 0 },
+
+ { szFlagKsu, rtRegular|rtExtended, 2, CV_M4_Psr, 3 },
+ { szFlagErl, rtRegular|rtExtended, 1, CV_M4_Psr, 2 },
+ { szFlagExl, rtRegular|rtExtended, 1, CV_M4_Psr, 1 },
+ { szFlagIe, rtRegular|rtExtended, 1, CV_M4_Psr, 0 },
+ { szFlagFpc, rtFPU|rtExtended, 1, CV_M4_FltFsr, 23 }
+#else
+ { szFlagCu, ftRegular|ftRegularExt, 4, CV_M4_Psr, 28 },
+ { szFlagCu3, ftRegular|ftRegularExt, 1, CV_M4_Psr, 31 },
+ { szFlagCu2, ftRegular|ftRegularExt, 1, CV_M4_Psr, 30 },
+ { szFlagCu1, ftRegular|ftRegularExt, 1, CV_M4_Psr, 29 },
+ { szFlagCu0, ftRegular|ftRegularExt, 1, CV_M4_Psr, 28 },
+ { szFlagRP, ftRegular|ftRegularExt, 1, CV_M4_Psr, 27 },
+ { szFlagFR, ftRegular|ftRegularExt, 1, CV_M4_Psr, 26 },
+ { szFlagRE, ftRegular|ftRegularExt, 1, CV_M4_Psr, 25 },
+ { szFlagDS, ftRegular|ftRegularExt, 9, CV_M4_Psr, 16 },
+
+ { szFlagImsk, ftRegular|ftRegularExt, 8, CV_M4_Psr, 8},
+ { szFlagInt5, ftRegular|ftRegularExt, 1, CV_M4_Psr, 15 },
+ { szFlagInt4, ftRegular|ftRegularExt, 1, CV_M4_Psr, 14 },
+ { szFlagInt3, ftRegular|ftRegularExt, 1, CV_M4_Psr, 13 },
+ { szFlagInt2, ftRegular|ftRegularExt, 1, CV_M4_Psr, 12 },
+ { szFlagInt1, ftRegular|ftRegularExt, 1, CV_M4_Psr, 11 },
+ { szFlagInt0, ftRegular|ftRegularExt, 1, CV_M4_Psr, 10 },
+ { szFlagSw1, ftRegular|ftRegularExt, 1, CV_M4_Psr, 9 },
+ { szFlagSw0, ftRegular|ftRegularExt, 1, CV_M4_Psr, 8 },
+
+// R{2,3,6}000 flags
+// { szFlagKuo, ftRegular|ftRegularExt, 1, CV_M4_Psr, 5 },
+// { szFlagIeo, ftRegular|ftRegularExt, 1, CV_M4_Psr, 4 },
+// { szFlagKup, ftRegular|ftRegularExt, 1, CV_M4_Psr, 3 },
+// { szFlagIep, ftRegular|ftRegularExt, 1, CV_M4_Psr, 2 },
+// { szFlagKuc, ftRegular|ftRegularExt, 1, CV_M4_Psr, 1 },
+// { szFlagIec, ftRegular|ftRegularExt, 1, CV_M4_Psr, 0 },
+
+ { szFlagKsu, ftRegular|ftRegularExt, 2, CV_M4_Psr, 3 },
+ { szFlagErl, ftRegular|ftRegularExt, 1, CV_M4_Psr, 2 },
+ { szFlagExl, ftRegular|ftRegularExt, 1, CV_M4_Psr, 1 },
+ { szFlagIe, ftRegular|ftRegularExt, 1, CV_M4_Psr, 0 },
+ { szFlagFpc, ftFP|ftFPExt, 1, CV_M4_FltFsr, 23 }
+#endif
diff --git a/private/windbg/em/p_mips/makefile b/private/windbg/em/p_mips/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/em/p_mips/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/em/p_mips/makefile.inc b/private/windbg/em/p_mips/makefile.inc
new file mode 100644
index 000000000..8b520faa0
--- /dev/null
+++ b/private/windbg/em/p_mips/makefile.inc
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/em/p_mips/ntdis.h b/private/windbg/em/p_mips/ntdis.h
new file mode 100644
index 000000000..147d538e3
--- /dev/null
+++ b/private/windbg/em/p_mips/ntdis.h
@@ -0,0 +1,277 @@
+#define opnNone 0x00000000
+#define opnPreRt 0x00000001 // contains trailing comma
+#define opnRd 0x00000002
+#define opnFd 0x00000004
+#define opnRdComma 0x00000008
+#define opnRdOptRs 0x00000010 // [Rd,] Rs
+#define opnRs 0x00000020
+#define opnFs 0x00000040
+#define opnRsComma 0x00000080
+#define opnRt 0x00000100
+#define opnFt 0x00000200
+#define opnRtComma 0x00000400
+#define opnPostRs 0x00000800
+#define opnImm16 0x00001000
+#define opnRel16 0x00002000
+#define opnImm10 0x00004000
+#define opnImm20 0x00008000
+#define opnImm26 0x00010000
+#define opnAddr26 0x00020000
+#define opnUImm16 0x01000000
+#define opnRxd 0x02000000
+#define opnPreRxt 0x04000000
+
+#define opnByteIndex 0x00040000
+#define opnWordIndex 0x00080000
+#define opnDwordIndex 0x00100000
+#define opnLeftIndex 0x00200000
+#define opnRightIndex 0x00400000
+#define opnAnyIndex 0x007c0000
+
+#define opnShift 0x00800000
+#define opnCache 0x10000000
+
+#define opnR4000 0x20000000
+
+#define opnRdRsRt opnRd + opnRdComma + opnRs + opnRsComma + opnRt
+#define opnRtRsImm16 opnPreRt + opnRs + opnRsComma + opnImm16
+#define opnRtRsUImm16 opnPreRt + opnRs + opnRsComma + opnUImm16
+#define opnRsRtRel16 opnRs + opnRsComma + opnRt + opnRtComma + opnRel16
+#define opnRsRel16 opnRs + opnRsComma + opnRel16
+#define opnRtRd opnPreRt + opnRd
+#define opnRtFd opnPreRt + opnFd
+#define opnRtRxd opnPreRt + opnRxd
+#define opnRsRt opnRs + opnRsComma + opnRt
+#define opnRsRtImm10 opnRs + opnRsComma + opnRt + opnRtComma + opnImm10
+#define opnRdRs opnRd + opnRdComma + opnRs
+#define opnRtByteIndex opnPreRt + opnByteIndex
+#define opnRtWordIndex opnPreRt + opnWordIndex
+#define opnRtDwordIndex opnPreRt + opnDwordIndex
+#define opnRxtDwordIndex opnPreRxt + opnDwordIndex
+#define opnRtLeftIndex opnPreRt + opnLeftIndex
+#define opnRtRightIndex opnPreRt + opnRightIndex
+#define opnRtUImm16 opnPreRt + opnUImm16
+#define opnRdRtShift opnRd + opnRdComma + opnRt + opnRtComma + opnShift
+#define opnRdRtRs opnRd + opnRdComma + opnRt + opnRtComma + opnPostRs
+#define opnFdFs opnFd + opnRdComma + opnFs
+#define opnFdFsFt opnFd + opnRdComma + opnFs + opnRsComma + opnFt
+#define opnFsFt opnFs + opnRsComma + opnFt
+#define opnRtFs opnPreRt + opnFs
+#define opnFtDwordIndex opnFt + opnRtComma + opnDwordIndex
+#define opnRsImm16 opnRs + opnRsComma + opnImm16
+#define opnCacheRightIndex opnCache + opnRightIndex
+
+typedef union instr {
+ ULONG instruction;
+ struct _jump_instr {
+ ULONG Target : 26;
+ ULONG Opcode : 6;
+ } jump_instr;
+ struct _break_instr {
+ ULONG Opcode : 6;
+ ULONG Value : 20;
+ ULONG Special : 6;
+ } break_instr;
+ struct _trap_instr {
+ ULONG Opcode : 6;
+ ULONG Value : 10;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Special : 6;
+ } trap_instr;
+ struct _immed_instr {
+ ULONG Value : 16;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Opcode : 6;
+ } immed_instr;
+ struct _special_instr {
+ ULONG Funct : 6;
+ ULONG RE : 5;
+ ULONG RD : 5;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Opcode : 6;
+ } special_instr;
+ struct _float_instr {
+ ULONG Funct : 6;
+ ULONG FD : 5;
+ ULONG FS : 5;
+ ULONG FT : 5;
+ ULONG Format : 5;
+ ULONG Opcode : 6;
+ } float_instr;
+ } INSTR;
+
+extern LPCH pszReg[];
+
+extern UCHAR pszAbs_s[];
+extern UCHAR pszAdd[];
+extern UCHAR pszAddi[];
+extern UCHAR pszAddiu[];
+extern UCHAR pszAddu[];
+extern UCHAR pszAdd_s[];
+extern UCHAR pszAnd[];
+extern UCHAR pszAndi[];
+extern UCHAR pszBc0f[];
+extern UCHAR pszBc0fl[];
+extern UCHAR pszBc0t[];
+extern UCHAR pszBc0tl[];
+extern UCHAR pszBc1f[];
+extern UCHAR pszBc1fl[];
+extern UCHAR pszBc1t[];
+extern UCHAR pszBc1tl[];
+extern UCHAR pszBc2f[];
+extern UCHAR pszBc2fl[];
+extern UCHAR pszBc2t[];
+extern UCHAR pszBc2tl[];
+extern UCHAR pszBc3f[];
+extern UCHAR pszBc3fl[];
+extern UCHAR pszBc3t[];
+extern UCHAR pszBc3tl[];
+extern UCHAR pszBgez[];
+extern UCHAR pszBgezal[];
+extern UCHAR pszBgezall[];
+extern UCHAR pszBgezl[];
+extern UCHAR pszBgtz[];
+extern UCHAR pszBgtzl[];
+extern UCHAR pszBeq[];
+extern UCHAR pszBeql[];
+extern UCHAR pszBlez[];
+extern UCHAR pszBlezl[];
+extern UCHAR pszBltz[];
+extern UCHAR pszBltzal[];
+extern UCHAR pszBltzall[];
+extern UCHAR pszBltzl[];
+extern UCHAR pszBne[];
+extern UCHAR pszBnel[];
+extern UCHAR pszBreak[];
+extern UCHAR pszC_eq_s[];
+extern UCHAR pszC_f_s[];
+extern UCHAR pszC_le_s[];
+extern UCHAR pszC_lt_s[];
+extern UCHAR pszC_nge_s[];
+extern UCHAR pszC_ngl_s[];
+extern UCHAR pszC_ngle_s[];
+extern UCHAR pszC_ngt_s[];
+extern UCHAR pszC_ole_s[];
+extern UCHAR pszC_olt_s[];
+extern UCHAR pszC_seq_s[];
+extern UCHAR pszC_sf_s[];
+extern UCHAR pszC_ueq_s[];
+extern UCHAR pszC_ule_s[];
+extern UCHAR pszC_ult_s[];
+extern UCHAR pszC_un_s[];
+extern UCHAR pszCache[];
+extern UCHAR pszCeil_w_s[];
+extern UCHAR pszCfc0[];
+extern UCHAR pszCfc1[];
+extern UCHAR pszCfc2[];
+extern UCHAR pszCfc3[];
+extern UCHAR pszCtc0[];
+extern UCHAR pszCtc1[];
+extern UCHAR pszCtc2[];
+extern UCHAR pszCtc3[];
+extern UCHAR pszCop0[];
+extern UCHAR pszCop1[];
+extern UCHAR pszCop2[];
+extern UCHAR pszCop3[];
+extern UCHAR pszCvt_d_s[];
+extern UCHAR pszCvt_e_s[];
+extern UCHAR pszCvt_q_s[];
+extern UCHAR pszCvt_s_s[];
+extern UCHAR pszCvt_w_s[];
+extern UCHAR pszDiv[];
+extern UCHAR pszDiv_s[];
+extern UCHAR pszDivu[];
+extern UCHAR pszEret[];
+extern UCHAR pszFloor_w_s[];
+extern UCHAR pszJ[];
+extern UCHAR pszJr[];
+extern UCHAR pszJal[];
+extern UCHAR pszJalr[];
+extern UCHAR pszLb[];
+extern UCHAR pszLbu[];
+extern UCHAR pszLdc1[];
+extern UCHAR pszLdc2[];
+extern UCHAR pszLdc3[];
+extern UCHAR pszLh[];
+extern UCHAR pszLhu[];
+extern UCHAR pszLui[];
+extern UCHAR pszLwc0[];
+extern UCHAR pszLwc1[];
+extern UCHAR pszLwc2[];
+extern UCHAR pszLwc3[];
+extern UCHAR pszLw[];
+extern UCHAR pszLwl[];
+extern UCHAR pszLwr[];
+extern UCHAR pszMfc0[];
+extern UCHAR pszMfc1[];
+extern UCHAR pszMfc2[];
+extern UCHAR pszMfc3[];
+extern UCHAR pszMfhi[];
+extern UCHAR pszMflo[];
+extern UCHAR pszMov_s[];
+extern UCHAR pszMtc0[];
+extern UCHAR pszMtc1[];
+extern UCHAR pszMtc2[];
+extern UCHAR pszMtc3[];
+extern UCHAR pszMthi[];
+extern UCHAR pszMtlo[];
+extern UCHAR pszMul_s[];
+extern UCHAR pszMult[];
+extern UCHAR pszMultu[];
+extern UCHAR pszNeg_s[];
+extern UCHAR pszNop[];
+extern UCHAR pszNor[];
+extern UCHAR pszOr[];
+extern UCHAR pszOri[];
+extern UCHAR pszRfe[];
+extern UCHAR pszRound_w_s[];
+extern UCHAR pszSb[];
+extern UCHAR pszSdc1[];
+extern UCHAR pszSdc2[];
+extern UCHAR pszSdc3[];
+extern UCHAR pszSh[];
+extern UCHAR pszSll[];
+extern UCHAR pszSllv[];
+extern UCHAR pszSlt[];
+extern UCHAR pszSlti[];
+extern UCHAR pszSltiu[];
+extern UCHAR pszSltu[];
+extern UCHAR pszSqrt_s[];
+extern UCHAR pszSra[];
+extern UCHAR pszSrl[];
+extern UCHAR pszSrav[];
+extern UCHAR pszSrlv[];
+extern UCHAR pszSub[];
+extern UCHAR pszSub_s[];
+extern UCHAR pszSubu[];
+extern UCHAR pszSw[];
+extern UCHAR pszSwc0[];
+extern UCHAR pszSwc1[];
+extern UCHAR pszSwc2[];
+extern UCHAR pszSwc3[];
+extern UCHAR pszSwl[];
+extern UCHAR pszSwr[];
+extern UCHAR pszSync[];
+extern UCHAR pszSyscall[];
+extern UCHAR pszTeq[];
+extern UCHAR pszTeqi[];
+extern UCHAR pszTge[];
+extern UCHAR pszTgei[];
+extern UCHAR pszTgeiu[];
+extern UCHAR pszTgeu[];
+extern UCHAR pszTlbr[];
+extern UCHAR pszTlbwi[];
+extern UCHAR pszTlbwr[];
+extern UCHAR pszTlbp[];
+extern UCHAR pszTlt[];
+extern UCHAR pszTlti[];
+extern UCHAR pszTltiu[];
+extern UCHAR pszTltu[];
+extern UCHAR pszTne[];
+extern UCHAR pszTnei[];
+extern UCHAR pszTrunc_w_s[];
+extern UCHAR pszXor[];
+extern UCHAR pszXori[];
diff --git a/private/windbg/em/p_mips/precomp.h b/private/windbg/em/p_mips/precomp.h
new file mode 100644
index 000000000..f6748b4f6
--- /dev/null
+++ b/private/windbg/em/p_mips/precomp.h
@@ -0,0 +1,75 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <biavst.h>
+
+#include <windows.h>
+#include <dde.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <memory.h>
+#include <string.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#ifdef OSDEBUG4
+
+#include "od.h"
+#include "odp.h"
+#include "odassert.h"
+
+#include "dbgver.h"
+
+// BUGBUG kentf have to include shapi.hxx for LPDEBUGDATA?
+#include "shapi.hxx"
+
+#include "emdm.h"
+#include "win32dm.h"
+#include "emdata.h"
+#include "emproto.h"
+
+#include "cvinfo.h"
+
+
+#else // OSDEBUG4
+
+
+#include "defs.h"
+
+#include "mm.h"
+#include "ll.h"
+#include "tl.h"
+#include "od.h"
+#include "dbgver.h"
+#include "emdm.h"
+#include "osdem.h"
+#include "emdata.h"
+#include "emproto.h"
+
+#include "osassert.h"
+
+#include "lbhpt.h"
+#include "llhpt.h"
+#include "mhhpt.h"
+
+#endif // OSDEBUG4
diff --git a/private/windbg/em/p_mips/regs.h b/private/windbg/em/p_mips/regs.h
new file mode 100644
index 000000000..2b080b498
--- /dev/null
+++ b/private/windbg/em/p_mips/regs.h
@@ -0,0 +1,120 @@
+
+#define SIZE 64
+
+ { szR0, rtCPU | rtInvisible| rtInteger, SIZE, CV_M4_IntZERO },
+ { szR1, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntAT },
+ { szR2, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntV0 },
+ { szR3, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntV1 },
+ { szR4, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntA0 },
+ { szR5, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntA1 },
+ { szR6, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntA2 },
+ { szR7, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntA3 },
+ { szR8, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT0 },
+ { szR9, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT1 },
+ { szR10, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT2 },
+ { szR11, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT3 },
+ { szR12, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT4 },
+ { szR13, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT5 },
+ { szR14, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT6 },
+ { szR15, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT7 },
+ { szR24, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT8 },
+ { szR25, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntT9 },
+ { szR16, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS0 },
+ { szR17, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS1 },
+ { szR18, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS2 },
+ { szR19, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS3 },
+ { szR20, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS4 },
+ { szR21, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS5 },
+ { szR22, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS6 },
+ { szR23, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS7 },
+ { szR30, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntS8 },
+ { szR26, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntKT0 },
+ { szR27, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntKT1 },
+ { szR28, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntGP },
+ { szR29, rtCPU | rtRegular | rtExtended | rtInteger | rtFrame, SIZE, CV_M4_IntSP },
+ { szR31, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntRA },
+ { szLo, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntLO },
+ { szHi, rtCPU | rtRegular | rtExtended | rtInteger, SIZE, CV_M4_IntHI },
+ { szFir, rtCPU | rtRegular | rtExtended | rtInteger | rtPC, 32, CV_M4_Fir },
+ { szPsr, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_M4_Psr },
+
+ { szFr0, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF0 },
+ { szFr1, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF1 },
+ { szFr2, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF2 },
+ { szFr3, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF3 },
+ { szFr4, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF4 },
+ { szFr5, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF5 },
+ { szFr6, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF6 },
+ { szFr7, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF7 },
+ { szFr8, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF8 },
+ { szFr9, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF9 },
+ { szFr10, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF10 },
+ { szFr11, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF11 },
+ { szFr12, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF12 },
+ { szFr13, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF13 },
+ { szFr14, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF14 },
+ { szFr15, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF15 },
+ { szFr16, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF16 },
+ { szFr17, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF17 },
+ { szFr18, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF18 },
+ { szFr19, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF19 },
+ { szFr20, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF20 },
+ { szFr21, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF21 },
+ { szFr22, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF22 },
+ { szFr23, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF23 },
+ { szFr24, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF24 },
+ { szFr25, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF25 },
+ { szFr26, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF26 },
+ { szFr27, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF27 },
+ { szFr28, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF28 },
+ { szFr29, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF29 },
+ { szFr30, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF30 },
+ { szFr31, rtFPU | rtRegular | rtFloat, 32, CV_M4_FltF31 },
+
+
+ { szFp0, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF0 << 8) | CV_M4_FltF1 },
+ { szFp2, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF2 << 8) | CV_M4_FltF3 },
+ { szFp4, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF4 << 8) | CV_M4_FltF5 },
+ { szFp6, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF6 << 8) | CV_M4_FltF7 },
+ { szFp8, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF8 << 8) | CV_M4_FltF9 },
+ { szFp10, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF10 << 8) | CV_M4_FltF11 },
+ { szFp12, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF12 << 8) | CV_M4_FltF13 },
+ { szFp14, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF14 << 8) | CV_M4_FltF15 },
+ { szFp16, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF16 << 8) | CV_M4_FltF17 },
+ { szFp18, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF18 << 8) | CV_M4_FltF19 },
+ { szFp20, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF20 << 8) | CV_M4_FltF21 },
+ { szFp22, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF22 << 8) | CV_M4_FltF23 },
+ { szFp24, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF24 << 8) | CV_M4_FltF25 },
+ { szFp26, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF26 << 8) | CV_M4_FltF27 },
+ { szFp28, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF28 << 8) | CV_M4_FltF29 },
+ { szFp30, rtFPU | rtExtended | rtFloat, 64,
+ (CV_M4_FltF30 << 8) | CV_M4_FltF31 },
+/*
+
+ { szFq0, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF0 },
+ { szFq4, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF4 },
+ { szFq8, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF8 },
+ { szFq12, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF12 },
+ { szFq16, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF16 },
+ { szFq20, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF20 },
+ { szFq24, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF24 },
+ { szFq28, rtFPU | rtExtended | rtFloat, 128, CV_M4_FltF28 }
+*/
+
+
+ { szFsr, rtFPU | rtRegular | rtExtended | rtInteger, 32, CV_M4_FltFsr }
diff --git a/private/windbg/em/p_mips/sources b/private/windbg/em/p_mips/sources
new file mode 100644
index 000000000..9b7e52213
--- /dev/null
+++ b/private/windbg/em/p_mips/sources
@@ -0,0 +1,61 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=emmip
+
+TARGETNAME=emmip
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+DLLENTRY=DllInit
+
+SOURCES= \
+ asm.c \
+ d3.c \
+ emdp.c \
+ emdp2.c \
+ emdp3.c \
+ emdpdev.c \
+ strings.c \
+ wintrans.c \
+ em.rc
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_MIPS
+
+INCLUDES=..;..\..\osdebug\include;..\..\osdebug
+
+CONDITIONAL_INCLUDES=odp.h win32msg.h xosd.h odassert.h win32dm.h
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/em/p_mips/strings.c b/private/windbg/em/p_mips/strings.c
new file mode 100644
index 000000000..62c352bbd
--- /dev/null
+++ b/private/windbg/em/p_mips/strings.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\strings.c"
diff --git a/private/windbg/em/p_mips/strings.h b/private/windbg/em/p_mips/strings.h
new file mode 100644
index 000000000..ac9f70634
--- /dev/null
+++ b/private/windbg/em/p_mips/strings.h
@@ -0,0 +1,185 @@
+/*
+** STRINGS.H
+**
+** This file contains all strings which are used in the EM for display
+** purposes. This is done for internationalization purposes.
+**
+** strings.c defines DEFINE_STRINGS before including this file. Other
+** source files just include this file normally.
+*/
+
+/*
+** strings.c should define DEFINE_STRINGS before including this file,
+** so that the strings will be defined rather than just declared.
+*/
+
+#ifdef DEFINE_STRINGS
+#define DECL_STR(name, value) char name[] = value
+#undef DEFINE_STRINGS
+#else
+#define DECL_STR(name, value) extern char name[]
+#endif
+
+
+DECL_STR( szFr0 , "fr0");
+DECL_STR( szFr1 , "fr1");
+DECL_STR( szFr2 , "fr2");
+DECL_STR( szFr3 , "fr3");
+DECL_STR( szFr4 , "fr4");
+DECL_STR( szFr5 , "fr5");
+DECL_STR( szFr6 , "fr6");
+DECL_STR( szFr7 , "fr7");
+DECL_STR( szFr8 , "fr8");
+DECL_STR( szFr9 , "fr9");
+DECL_STR( szFr10 , "fr10");
+DECL_STR( szFr11 , "fr11");
+DECL_STR( szFr12 , "fr12");
+DECL_STR( szFr13 , "fr13");
+DECL_STR( szFr14 , "fr14");
+DECL_STR( szFr15 , "fr15");
+DECL_STR( szFr16 , "fr16");
+DECL_STR( szFr17 , "fr17");
+DECL_STR( szFr18 , "fr18");
+DECL_STR( szFr19 , "fr19");
+DECL_STR( szFr20 , "fr20");
+DECL_STR( szFr21 , "fr21");
+DECL_STR( szFr22 , "fr22");
+DECL_STR( szFr23 , "fr23");
+DECL_STR( szFr24 , "fr24");
+DECL_STR( szFr25 , "fr25");
+DECL_STR( szFr26 , "fr26");
+DECL_STR( szFr27 , "fr27");
+DECL_STR( szFr28 , "fr28");
+DECL_STR( szFr29 , "fr29");
+DECL_STR( szFr30 , "fr30");
+DECL_STR( szFr31 , "fr31");
+
+DECL_STR( szFp0 , "fp0");
+DECL_STR( szFp2 , "fp2");
+DECL_STR( szFp4 , "fp4");
+DECL_STR( szFp6 , "fp6");
+DECL_STR( szFp8 , "fp8");
+DECL_STR( szFp10 , "fp10");
+DECL_STR( szFp12 , "fp12");
+DECL_STR( szFp14 , "fp14");
+DECL_STR( szFp16 , "fp16");
+DECL_STR( szFp18 , "fp18");
+DECL_STR( szFp20 , "fp20");
+DECL_STR( szFp22 , "fp22");
+DECL_STR( szFp24 , "fp24");
+DECL_STR( szFp26 , "fp26");
+DECL_STR( szFp28 , "fp28");
+DECL_STR( szFp30 , "fp30");
+
+DECL_STR( szFq0 , "fq0");
+DECL_STR( szFq4 , "fq4");
+DECL_STR( szFq8 , "fq8");
+DECL_STR( szFq12 , "fq12");
+DECL_STR( szFq16 , "fq16");
+DECL_STR( szFq20 , "fq20");
+DECL_STR( szFq24 , "fq24");
+DECL_STR( szFq28 , "fq28");
+
+DECL_STR( szR0 , "zero");
+DECL_STR( szR1 , "at");
+DECL_STR( szR2 , "v0");
+DECL_STR( szR3 , "v1");
+DECL_STR( szR4 , "a0");
+DECL_STR( szR5 , "a1");
+DECL_STR( szR6 , "a2");
+DECL_STR( szR7 , "a3");
+DECL_STR( szR8 , "t0");
+DECL_STR( szR9 , "t1");
+DECL_STR( szR10 , "t2");
+DECL_STR( szR11 , "t3");
+DECL_STR( szR12 , "t4");
+DECL_STR( szR13 , "t5");
+DECL_STR( szR14 , "t6");
+DECL_STR( szR15 , "t7");
+DECL_STR( szR16 , "s0");
+DECL_STR( szR17 , "s1");
+DECL_STR( szR18 , "s2");
+DECL_STR( szR19 , "s3");
+DECL_STR( szR20 , "s4");
+DECL_STR( szR21 , "s5");
+DECL_STR( szR22 , "s6");
+DECL_STR( szR23 , "s7");
+DECL_STR( szR24 , "t8");
+DECL_STR( szR25 , "t9");
+DECL_STR( szR26 , "k0");
+DECL_STR( szR27 , "k1");
+DECL_STR( szR28 , "gp");
+DECL_STR( szR29 , "sp");
+DECL_STR( szR30 , "s8");
+DECL_STR( szR31 , "ra");
+DECL_STR( szLo , "lo");
+DECL_STR( szHi , "hi");
+DECL_STR( szFsr , "fsr");
+DECL_STR( szFir , "fir");
+
+DECL_STR( szPsr , "psr");
+DECL_STR( szFlagCu , "cu"); // 31..28
+DECL_STR( szFlagCu3 , "cu3"); // 31
+DECL_STR( szFlagCu2 , "cu2"); // 30
+DECL_STR( szFlagCu1 , "cu1"); // 29
+DECL_STR( szFlagCu0 , "cu0"); // 28
+DECL_STR( szFlagRP , "rp"); // 27
+DECL_STR( szFlagFR , "fr"); // 26
+DECL_STR( szFlagRE , "re"); // 25
+DECL_STR( szFlagDS , "ds"); // 24..16
+DECL_STR( szFlagImsk , "im"); // 15..8
+DECL_STR( szFlagInt5 , "int5"); // 15
+DECL_STR( szFlagInt4 , "int4"); // 14
+DECL_STR( szFlagInt3 , "int3"); // 13
+DECL_STR( szFlagInt2 , "int2"); // 12
+DECL_STR( szFlagInt1 , "int1"); // 11
+DECL_STR( szFlagInt0 , "int0"); // 10
+DECL_STR( szFlagSw1 , "sw1"); // 9
+DECL_STR( szFlagSw0 , "sw0"); // 8
+
+DECL_STR( szFlagKuo , "kuo"); // R{2,3,6}000 regs
+DECL_STR( szFlagIeo , "ieo");
+DECL_STR( szFlagKup , "kup");
+DECL_STR( szFlagIep , "iep");
+DECL_STR( szFlagKuc , "kuc");
+DECL_STR( szFlagIec , "iec");
+
+DECL_STR( szFlagKsu , "ksu"); // 4..3
+DECL_STR( szFlagErl , "erl"); // 2
+DECL_STR( szFlagExl , "exl"); // 1
+DECL_STR( szFlagIe , "ie"); // 0
+
+DECL_STR( szFlagFpc , "fpc");
+DECL_STR( szU0Preg , "$u0");
+DECL_STR( szU1Preg , "$u1");
+DECL_STR( szU2Preg , "$u2");
+DECL_STR( szU3Preg , "$u3");
+DECL_STR( szU4Preg , "$u4");
+DECL_STR( szU5Preg , "$u5");
+DECL_STR( szU6Preg , "$u6");
+DECL_STR( szU7Preg , "$u7");
+DECL_STR( szU8Preg , "$u8");
+DECL_STR( szU9Preg , "$u9");
+DECL_STR( szEaPReg , "$ea");
+DECL_STR( szExpPReg , "$exp");
+DECL_STR( szRaPReg , "$ra");
+DECL_STR( szPPReg , "$p");
+
+DECL_STR(SzFrozen, "Frozen");
+DECL_STR(SzSuspended, "Suspended");
+DECL_STR(SzBlocked, "Blocked");
+
+DECL_STR(SzRunnable, "Runnable");
+DECL_STR(SzRunning, "Running");
+DECL_STR(SzStopped, "Stopped");
+DECL_STR(SzExiting, "Exiting");
+DECL_STR(SzDead, "Dead");
+DECL_STR(SzUnknown, "UNKNOWN");
+
+DECL_STR(SzExcept1st, "Except1st");
+DECL_STR(SzExcept2nd, "Except2nd");
+DECL_STR(SzRipped, "RIP");
+
+DECL_STR(SzCritSec, "CritSec");
+
+DECL_STR(SzStandard, "Standard");
diff --git a/private/windbg/em/p_mips/wintrans.c b/private/windbg/em/p_mips/wintrans.c
new file mode 100644
index 000000000..c5276532e
--- /dev/null
+++ b/private/windbg/em/p_mips/wintrans.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\wintrans.c"
diff --git a/private/windbg/em/p_ppc/asm.c b/private/windbg/em/p_ppc/asm.c
new file mode 100644
index 000000000..e6becfffa
--- /dev/null
+++ b/private/windbg/em/p_ppc/asm.c
@@ -0,0 +1,13 @@
+#include "precomp.h"
+#pragma hdrstop
+
+XOSD Assemble (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ LSZ lszInput
+ )
+{
+ return xosdUnsupported;
+}
+
diff --git a/private/windbg/em/p_ppc/d3.c b/private/windbg/em/p_ppc/d3.c
new file mode 100644
index 000000000..01f4eeec7
--- /dev/null
+++ b/private/windbg/em/p_ppc/d3.c
@@ -0,0 +1,1097 @@
+#include "precomp.h"
+#pragma hdrstop
+
+
+#include "ntdis.h"
+#include "ntdisppc.h"
+
+INSTRUCTION *find_eop(); /* Searches a table for extended opcodes */
+void output_mnemonic(); /* Outputs instruction mnemonic string */
+void output_operands(); /* Decodes operands */
+
+typedef LPCH FAR *LPLPCH;
+#define MAXL 20
+char lhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+char uhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+char *hexdigit = &uhexdigit[0];
+static int fUpper = TRUE;
+
+/* current position in instruction */
+static unsigned char FAR*pMem = (unsigned char *)NULL;
+
+static int EAsize [2] = {0}; // size of effective address item
+static long EAaddr [2] = {0}; // offset of effective address
+
+int DumpAddress ( LPADDR, LPCH, int );
+int DumpGeneric ( LSZ, LPCH, int );
+int DumpComment ( LSZ, LPCH, int );
+int DumpEA ( HPID, HTID, LPADDR, LPCH, int );
+
+void OutputAddr(LPLPCH, LPADDR, int );
+void OutputHexString(LPLPCH, LPCH, int);
+void OutputHexCode(LPLPCH, LPCH, int);
+
+#include "strings.h"
+
+static UCHAR * PBuf;
+static int CchBuf;
+INSTR disinstr;
+
+void CalcMain (HPID,HTID,DOP,LPADDR,LPBYTE,int,int*,LPCH,int, LPCH,int, LPCH, int);
+
+/****disasm - disassemble a PowerPC instruction
+*
+* Input:
+* pOffset = pointer to offset to start disassembly
+* fEAout = if set, include EA (effective address)
+*
+* Output:
+* pOffset = pointer to offset of next instruction
+* pchDst = pointer to result string
+*
+***************************************************************************/
+
+#define CCHMAX 256
+static char rgchDisasm [ CCHMAX ];
+static HPID hpidLocal;
+static HTID htidLocal;
+
+XOSD disasm ( HPID hpid, HTID htid, LPSDI lpsdi ) {
+ XOSD xosd = xosdNone;
+ int cchMax = CCHMAX;
+ DOP dop = lpsdi->dop;
+ LPCH lpchOut = rgchDisasm;
+ int ichCur = 0;
+ ADDR addrStart = lpsdi->addr;
+ int cch = 0;
+ int cb;
+ int cbUsed=0;
+ BYTE rgb [ MAXL ];
+
+ char rgchRaw [ MAXL * 2 + 1 ];
+ char rgchOpcode [ 80 ];
+ char rgchOperands [ 80 ];
+ char rgchEA [ 44 ];
+ char rgchComment [ 80 ];
+
+ hpidLocal = hpid;
+ htidLocal = htid;
+ _fmemset ( rgchRaw, 0, sizeof ( rgchRaw ) );
+ _fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
+ _fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
+ _fmemset ( rgchComment, 0, sizeof ( rgchComment ) );
+ _fmemset ( rgchEA, 0, sizeof ( rgchEA ) );
+
+ lpsdi->ichAddr = -1;
+ lpsdi->ichBytes = -1;
+ lpsdi->ichOpcode = -1;
+ lpsdi->ichOperands = -1;
+ lpsdi->ichComment = -1;
+ lpsdi->ichEA0 = -1;
+ lpsdi->ichEA1 = -1;
+ lpsdi->ichEA2 = -1;
+
+ lpsdi->cbEA0 = 0;
+ lpsdi->cbEA1 = 0;
+ lpsdi->cbEA2 = 0;
+
+ lpsdi->fAssocNext = 0;
+
+ lpsdi->lpch = rgchDisasm;
+
+ // Set up for upper or lower case
+
+ fUpper = ( dop & dopUpper ) == dopUpper;
+ if ( fUpper ) {
+ hexdigit = uhexdigit;
+ }
+ else {
+ hexdigit = lhexdigit;
+ }
+
+ ADDR_IS_FLAT( addrStart ) = TRUE;
+
+ // Output the address if it is requested
+
+ if ( ( dop & dopAddr ) == dopAddr ) {
+ cch = DumpAddress ( &addrStart, lpchOut, cchMax );
+
+ lpsdi->ichAddr = 0;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+#ifdef OSDEBUG4
+ xosd = ReadBuffer(hpid, htid, &addrStart, MAXL, rgb, &cb);
+ if (xosd != xosdNone) {
+ cb = 0;
+ }
+#else
+ EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) &addrStart );
+ cb = EMFunc ( emfReadBuf, hpid, htid, MAXL, (LONG) (LPV) rgb );
+#endif
+
+ if ( cb <= 0 ) {
+
+ _fmemcpy ( rgchRaw, " ??", 4 );
+ _fmemcpy ( rgchOpcode, "???", 4 );
+ lpsdi->addr.addr.off++;
+ }
+ else {
+
+ CalcMain (
+ hpid,
+ htid,
+ lpsdi->dop,
+ &lpsdi->addr,
+ rgb,
+ cb,
+ &cbUsed,
+ rgchOpcode, sizeof(rgchOpcode),
+ rgchOperands, sizeof(rgchOperands),
+ rgchComment, sizeof(rgchComment)
+ );
+
+ // NOTENOTE jimsch - cbUsed must be 4
+ cbUsed = 4;
+
+ if ( GetAddrOff(lpsdi->addr) > 0xFFFFFFFF - cbUsed ) {
+ return xosdBadAddress;
+ }
+
+ if ( dop & dopRaw ) {
+ LPCH lpchT = rgchRaw;
+
+ OutputHexCode ( &lpchT, rgb, cbUsed );
+
+ *lpchT = '\0';
+ }
+ }
+
+ if ( ( dop & dopRaw ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchRaw, lpchOut, cchMax );
+
+ lpsdi->ichBytes = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+
+ if ( ( dop & dopOpcode ) && ( cchMax > 0 ) ) {
+ cch = DumpGeneric ( rgchOpcode, lpchOut, cchMax );
+
+ lpsdi->ichOpcode = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchOperands [ 0 ] != '\0' ) ) {
+ cch = DumpGeneric ( rgchOperands, lpchOut, cchMax );
+
+ lpsdi->ichOperands = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchComment [ 0 ] != '\0' ) ) {
+ cch = DumpComment ( rgchComment, lpchOut, cchMax );
+
+ lpsdi->ichComment = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+
+ if ( dop & dopEA ) {
+ cch = DumpEA ( hpid, htid, &lpsdi->addrEA0, lpchOut, cchMax );
+
+ if ( cchMax > 0 && cch > 0 ) {
+ lpsdi->ichEA0 = ichCur;
+ cchMax -= cch;
+ lpchOut += cch;
+ ichCur += cch;
+ }
+ }
+
+ lpsdi->addr.addr.off += cbUsed;
+
+ return xosd;
+}
+
+void OutputStringM (PUCHAR pStr)
+{
+ int cb;
+
+ if (CchBuf == 0) {
+ return;
+ }
+
+ cb = strlen(pStr);
+ if (cb > CchBuf) {
+ cb = CchBuf - 1;
+ }
+
+ strncpy(PBuf, pStr, cb);
+ PBuf[cb] = 0;
+ if (fUpper) {
+ _strupr(PBuf);
+ } else {
+ _strlwr(PBuf);
+ }
+ PBuf += cb;
+ CchBuf -= cb;
+ return;
+}
+
+void OutputReg (ULONG regnum)
+{
+ /* OutputStringM(pszReg[regnum + 32]); */
+}
+
+void OutputRxReg ( ULONG regnum)
+{
+ if (CchBuf < 3) {
+ CchBuf = 0;
+ return;
+ }
+
+ *PBuf++ = 'r';
+ if (regnum > 9) {
+ *PBuf++ = (UCHAR) ('0' + regnum / 10);
+ }
+ *PBuf++ = (UCHAR) ('0' + regnum % 10);
+ CchBuf -= 2 + (regnum > 9);
+ return;
+}
+
+void OutputHex (ULONG outvalue, ULONG length, BOOL fSigned)
+{
+ UCHAR digit[8];
+ LONG index = 0;
+
+ if (fSigned && (long)outvalue < 0) {
+ if (CchBuf > 1) {
+ *PBuf++ = '-';
+ CchBuf -= 1;
+ }
+ outvalue = (ULONG) (- (LONG) outvalue);
+ }
+
+ if (CchBuf > 2) {
+ *PBuf++ = '0';
+ *PBuf++ = (fUpper) ? 'X' :'x';
+ CchBuf -= 2;
+ }
+
+ do {
+ digit[index++] = hexdigit[outvalue & 0xf];
+ outvalue >>= 4;
+ }
+ while (outvalue || (!fSigned && index < (LONG)length));
+
+ if (CchBuf > index) {
+ CchBuf -= index;
+ while (--index >= 0) {
+ *PBuf++ = digit[index];
+ }
+ }
+ return;
+}
+
+
+/*** OutputDisSymbol - output symbol for disassembly
+*
+* Purpose:
+* Access symbol table with given offset and put string into buffer.
+*
+* Input:
+* offset - offset of address to output
+*
+* Output:
+* buffer pointed by PBuf updated with string:
+* if symbol, no disp: <symbol>(<offset>)
+* if symbol, disp: <symbol>+<disp>(<offset>)
+* if no symbol, no disp: <offset>
+*
+*************************************************************************/
+
+void
+OutputDisSymbol (
+ ULONG offset,
+ BOOL fSymbol
+ )
+{
+ UCHAR chAddrBuffer[512];
+ LPCH lpchSymbol;
+ ADDR addrT={0}, addr={0};
+ int cb;
+ ODR odr;
+
+ odr.lszName = chAddrBuffer;
+
+ addr.addr.off = addrT.addr.off = offset;
+ MODE_IS_FLAT(addr.mode) = TRUE;
+ MODE_IS_FLAT(addrT.mode) = TRUE;
+
+ if (fSymbol) {
+ lpchSymbol = SHGetSymbol (&addrT, &addr, sopNone, &odr);
+ if (odr.dwDeltaOff == -1) {
+ lpchSymbol = NULL;
+ }
+ } else {
+ lpchSymbol = NULL;
+ }
+
+ if (lpchSymbol != NULL) {
+ cb = strlen(chAddrBuffer);
+ if (cb > CchBuf) {
+ cb = CchBuf;
+ }
+ strncpy(PBuf, chAddrBuffer, cb);
+ CchBuf -= cb;
+ PBuf += cb;
+ *PBuf = 0;
+
+ if (odr.dwDeltaOff) {
+ if (CchBuf > 1) {
+ *PBuf++ = '+';
+ CchBuf -= 1;
+ }
+ OutputHex(odr.dwDeltaOff, 8, TRUE);
+ }
+ if (CchBuf > 1) {
+ *PBuf++ = '(';
+ CchBuf -= 1;
+ }
+ }
+ OutputHex(offset, 8, FALSE);
+ if (lpchSymbol != NULL) {
+ if (CchBuf > 1) {
+ CchBuf -= 1;
+ *PBuf++ = ')';
+ }
+ }
+
+ return;
+}
+
+
+
+void
+CalcMain (
+ HPID hpid,
+ HTID htid,
+ DOP dop,
+ LPADDR lpaddr,
+ LPBYTE rgb,
+ int cbMax,
+ int FAR *lpcbUsed,
+ LPCH rgchOpcode,
+ int cchOpcode,
+ LPCH rgchOperands,
+ int cchOperands,
+ LPCH rgchComment,
+ int cchComment
+ )
+/*++
+
+Routine Description:
+
+ Decode the 32-bit opword and put the operator, operands, and comments
+ into the appropriate character string buffers.
+
+Arguments:
+
+ hpid - Supplies the process handle
+ hthd - Supplies a thread handle
+ dop - Supplies the set of disassembly options
+ lpaddr - Supplies the address to be disassembled
+ rgb - Supplies the 32 bit opword to disassemble
+ cbMax - Unused
+ lpcbUsed - Unused
+ rgchOpcode - Supplies location to place instruction mnemonic
+ cchOpcode - Unused, size of rgchOpcode
+ rgchOperands - Supplies location to place operands
+ cchOperands - Character count remaining in rgchOperands
+ rgchComment - Supplies location to place comment
+ cchComment - Unused, size of rgchComment
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR chSuffix = '\0';
+ BOOL fEAout = TRUE;
+
+ INSTRUCTION *iptr; /* All of the information on any instruction */
+ ULONG pop; /* primary opcode */
+ ULONG opword; /* 32 bit instruction word */
+ ULONG address; /* address to disassemble */
+
+
+ Unreferenced(cbMax);
+ Unreferenced(lpcbUsed);
+
+ *rgchComment = *rgchOperands = 0;
+ EAsize[0] = EAsize[1] = 0;
+
+ /* Get the address to be disassembled out of the ADDR structure */
+ address = lpaddr->addr.off;
+
+ /* Extract the primary opcode */
+ opword = ((INSTR *)rgb)->instruction;
+ pop = (unsigned)(opword >> 26);
+
+ /* Some primary opcodes have extended opcodes. For those, pass the
+ information about which tables to search and which instruction formats
+ to use for that primary opcode. Otherwise, just use the primary opcode
+ as an array index to get the information. */
+
+ switch ( pop ) {
+ case 19:
+ iptr = find_eop (opword, &pop19_fmts, &pop19_insn, COUNT19);
+ break;
+ case 30:
+ iptr = find_eop (opword, &pop30_fmts, &pop30_insn, COUNT30);
+ break;
+ case 31:
+ iptr = find_eop (opword, &pop31_fmts, &pop31_insn, COUNT31);
+ break;
+ case 58:
+ iptr = find_eop (opword, &pop58_fmts, &pop58_insn, COUNT58);
+ break;
+ case 59:
+ iptr = find_eop (opword, &pop59_fmts, &pop59_insn, COUNT59);
+ break;
+ case 62:
+ iptr = find_eop (opword, &pop62_fmts, &pop62_insn, COUNT62);
+ break;
+ case 63:
+ iptr = find_eop (opword, &pop63_fmts, &pop63_insn, COUNT63);
+ break;
+ default:
+ /* no extended opcode for this primary opcode, use it as index */
+ if ( pop_insn[pop].ext_opcode == 0 )
+ iptr = (INSTRUCTION *)0;
+ else
+ iptr = &pop_insn[pop];
+ }
+
+ /* Establish pointer to output buffer for instruction mnemonic */
+ PBuf = rgchOpcode;
+
+ /* If match was found, output mnemonic and operands */
+ if ( iptr != (INSTRUCTION *)0 ) {
+ output_mnemonic (opword, iptr);
+
+ /* If option is set, convert operator to upper case */
+ if ( fUpper )
+ for(PBuf = rgchOpcode;*PBuf != '\0';PBuf++)
+ *PBuf = toupper(*PBuf);
+
+ /* Establish pointer to output buffer for operands */
+ PBuf = rgchOperands;
+ CchBuf = cchOperands; /* Character count remaining in buffer */
+ output_operands (address, opword, iptr, dop);
+
+ /* If no match, just output the 32 bit instruction word */
+ } else {
+ OutputHex(opword,8,FALSE);
+ PBuf += sprintf(PBuf, "\tUnknown opcode or extended opcode");
+
+ }
+ return;
+}
+
+/* Search the given extended opcode table. If a match is found return
+ address of matching instruction, otherwise NULL */
+INSTRUCTION *
+find_eop (opword, insn_format, insn_table, table_size)
+ ULONG opword; /* 32-bit word to disassemble */
+ int *insn_format; /* list of possible instruction formats */
+ INSTRUCTION *insn_table; /* table of instructions to search */
+ int table_size; /* number of entries in intruction table */
+{
+ int eop; /* extended opcode */
+ int last_eop; /* previous search key */
+ int here; /* extended opcode search index */
+ int max, min; /* search bounds */
+
+ /* A lot of the time, extended opcode formats will extract the
+ same value twice because of leading zeros. This is used to
+ save the previous value to avoid repeating the search for the
+ same key that was not found before. */
+ last_eop = -1;
+
+ /* Search for extended opcode. A -1 marks the end of each table
+ because the table size can be different for different primary
+ opcodes. */
+ while ( *insn_format != -1 ) {
+
+ /* Extract the extended opcode */
+ eop = (opword >> eopFormat[*insn_format][1]) & eopFormat[*insn_format][0];
+
+ /* Avoid duplicate searches */
+ if ( eop != last_eop ) {
+
+ /* Set up bounds for binary search */
+ min = 0;
+ max = table_size - 1;
+
+ /* Use binary initially, linear when it gets small */
+ while ((here = (max + min) / 2) > (min + 5)) {
+
+ /* If not in bottom half, adjust minimum up */
+ if ( eop > insn_table[here].ext_opcode ) min = here+1;
+
+ /* If not in top half, adjust maximum down */
+ else if ( eop < insn_table[here].ext_opcode ) max = here-1;
+
+ /* Otherwise, return address of matching table entry */
+ else return &insn_table[here];
+ }
+
+ /* Switching to linear search */
+ for (;min <= max; min++) {
+
+ /* If match is found, return pointer to table entry */
+ if ( eop == insn_table[min].ext_opcode ) return &insn_table[min];
+ }
+ }
+
+ /* Will compare the next extended opcode to avoid duplicates */
+ last_eop = eop;
+
+ /* Set up for the next instruction format */
+ insn_format++;
+ }
+
+ /* If it falls through, search fails */
+ return (INSTRUCTION *)0;
+}
+
+/* Output the instruction mnemonic, with extensions */
+void
+output_mnemonic (opword, iptr)
+ ULONG opword; /* 32 bit opword to disassemble */
+ INSTRUCTION *iptr; /* corresponding instruction data table entry */
+{
+ char options [40]; /* buffer to build mnemonic extensions string */
+ char *qq = options;
+ char *pp = iptr->mne_ext; /* possible extensions for given instruction mnemonic */
+
+ /* Put any appropriate mnemonic optional characters into trailing buffer */
+ if (pp) {
+ while (*pp) {
+
+ switch ( *pp ) {
+ case '.':
+ if (opword & 0x1)
+ *qq++ = '.';
+ break;
+
+ case 'l':
+ if (opword & 0x1)
+ *qq++ = 'l';
+ break;
+
+ case 't':
+ if ((opword & 0x03e00000) == 0x01800000)
+ *qq++ = 't';
+ break;
+
+ case 'f':
+ if ((opword & 0x03e00000) == 0x00800000)
+ *qq++ = 'f';
+ break;
+
+ case 'a':
+ if (opword & 0x2)
+ *qq++ = 'a';
+ break;
+
+ case 'o':
+ if (opword & 0x400)
+ *qq++ = 'o';
+ break;
+
+ default:
+ break;
+ }
+ ++pp;
+ }
+ }
+ *qq = '\0';
+
+ PBuf += sprintf(PBuf, "%s%s", iptr->mnemonic, options);
+ return;
+}
+
+/* Output all the operands, based on formats from instruction table. */
+void
+output_operands (address, opword, iptr, dop)
+ ULONG address; /* address being disassemble, for effective address calculation */
+ ULONG opword; /* 32 bit opword to disassemble */
+ INSTRUCTION *iptr; /* corresponding instruction data table entry */
+ DOP dop; /* disassembly options */
+{
+ unsigned int tmp;
+ long effective_address;
+ int print_comma = 1; /* nonzero if comma is needed */
+
+ char *pp = iptr->operand_fmt; /* the operand formats for the given instruction */
+
+ while (*pp != '\0') {
+ switch (*pp) {
+ case BA : /* specifies bit in CR to be used as source */
+ PBuf += sprintf(PBuf, "%d", (opword >> 16) & 0x1f);
+ break;
+
+ case BB : /* specifies bit in CR to be used as source */
+ PBuf += sprintf(PBuf, "%d", (opword >> 11) & 0x1f);
+ break;
+
+ case BD : /* conditional branch displacement/absolute target */
+ effective_address = opword & 0xfffc;
+ if (effective_address & 0x8000) /* Perform sign extension */
+ effective_address -= 0x10000;
+
+ if ((opword & 0x2) == 0) { /* if AA bit not set */
+ if (!(dop & dopSym)) {
+ if ( effective_address >= 0 ) {
+ PBuf += sprintf(PBuf, "$+");
+ OutputHex(effective_address,8,FALSE);
+ } else {
+ PBuf += sprintf(PBuf, "$-");
+ OutputHex( - effective_address,8,FALSE);
+ }
+ }
+ effective_address += address;
+ }
+
+ if (!(dop & dopSym)) {
+ PBuf += sprintf(PBuf, "$-");
+ OutputHex(effective_address,8,FALSE);
+ }
+
+ /* If requested, print the associated symbol */
+ if (dop & dopSym)
+ OutputDisSymbol((long)effective_address , dop & dopSym);
+ break;
+
+ case BF : /* CR field or FPSCR field as target */
+ PBuf += sprintf(PBuf, "%d", (opword >> 23) & 0x7);
+ break;
+
+ case BFA : /* CR field or FPSCR field as source */
+ PBuf += sprintf(PBuf, "%d", (opword >> 18) & 0x7);
+ break;
+
+ case BI : /* bit in CR as condition of branch conditional */
+ PBuf += sprintf(PBuf, "%d", (opword >> 16) & 0x1f);
+ break;
+
+ case BO : /* options for branch conditional */
+ PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1f);
+ break;
+
+ case BT : /* bit in CR or FPSCR as target for result of instr */
+ PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1f);
+ break;
+
+ case D : /* 16 bit signed imm, sign extended to 64 bits */
+ print_comma=0;
+ tmp = opword & 0xffff;
+ if (tmp & 0x8000)
+ tmp -= 0x10000;
+ PBuf += sprintf(PBuf, "%d(", tmp);
+ break;
+
+ case DS : /* like D form except for two low order bits */
+ print_comma=0;
+ tmp = opword & 0xfffc;
+ if (tmp & 0x8000)
+ tmp -= 0x10000;
+ PBuf += sprintf(PBuf, "%d(", tmp);
+ break;
+
+ case FLM : /* FPSRC fields updated by mtfsf */
+ OutputHex(((opword >> 17) & 0xff),0,FALSE);
+ break;
+
+ case FRA : /* specifies source floating point register */
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "F%d", (opword >> 16) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "f%d", (opword >> 16) & 0x1f);
+ break;
+
+ case FRB : /* specifies source floating point register */
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "F%d", (opword >> 11) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "f%d", (opword >> 11) & 0x1f);
+ break;
+
+ case FRC : /* specifies source floating point register */
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "F%d", (opword >> 6) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "f%d", (opword >> 6) & 0x1f);
+ break;
+
+ case FRS : /* specifies source floating point register */
+ case FRT : /* specifies target floating point register */
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "F%d", (opword >> 21) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "f%d", (opword >> 21) & 0x1f);
+ break;
+
+ case FXM : /* CR fields updated by mtcrf */
+ OutputHex(((opword >> 12) & 0xff),0,FALSE);
+ break;
+
+ case L : /* specifies 32 or 64 bit fixed point compare */
+ PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1);
+ break;
+
+ case LI : /* branch displacement/absolute target */
+ effective_address = opword & 0x03fffffc;
+ if (effective_address & 0x2000000) /* Perform sign extension */
+ effective_address -= 0x4000000;
+
+ if ((opword & 0x2) == 0) { /* if AA bit not set */
+ if (!(dop & dopSym)) {
+ if ( effective_address >= 0 ) {
+ PBuf += sprintf(PBuf, "$+");
+ OutputHex(effective_address,8,FALSE);
+ } else {
+ PBuf += sprintf(PBuf, "$-");
+ OutputHex( - effective_address,8,FALSE);
+ }
+ }
+ effective_address += address;
+ }
+
+ if (!(dop & dopSym)) {
+ PBuf += sprintf(PBuf, "$-");
+ OutputHex(effective_address,8,FALSE);
+ }
+
+ /* If requested, print the associated symbol */
+ if (dop & dopSym)
+ OutputDisSymbol((long)effective_address , dop & dopSym);
+ break;
+
+ case PPC_MB : /* mask field for M-form instructions */
+ OutputHex(((opword >> 6) & 0x1f),0,FALSE);
+ break;
+
+ case ME : /* mask field for M-form instructions */
+ OutputHex(((opword >> 1) & 0x1f),0,FALSE);
+ break;
+
+ case MBE64: /* 64 bit implementation MB and ME fields */
+ OutputHex(((opword >> 5) & 0x3f),0,FALSE);
+ break;
+
+ case NB : /* number of bytes to move */
+ PBuf += sprintf(PBuf, "%d", (opword >> 11) & 0x1f);
+ break;
+
+ case RA : /* specifies gpr source or target */
+ if (!print_comma) {
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "R%d)", (opword >> 16) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "r%d)", (opword >> 16) & 0x1f);
+ print_comma++;
+ }
+ else
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "R%d", (opword >> 16) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "r%d", (opword >> 16) & 0x1f);
+ break;
+
+ case RB : /* specifies gpr source */
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "R%d", (opword >> 11) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "r%d", (opword >> 11) & 0x1f);
+ break;
+
+ case RS : /* specifies gpr source */
+ case PPC_RT : /* specifies gpr target */
+ if ( fUpper )
+ PBuf += sprintf(PBuf, "R%d", (opword >> 21) & 0x1f);
+ else
+ PBuf += sprintf(PBuf, "r%d", (opword >> 21) & 0x1f);
+ break;
+
+ case SH : /* shift amount for 32 bit implementation */
+ PBuf += sprintf(PBuf, "%d", (opword >> 11) & 0x1f);
+ break;
+
+ case SH64 : /* shift amount for 64 bit implementation */
+ PBuf += sprintf(PBuf, "%d", (((opword << 4) & 0x20) | ((opword >> 11) & 0x1f)));
+ break;
+
+ case SI : /* 16 bit signed immediate */
+ tmp = opword & 0xffff;
+ if (tmp & 0x8000)
+ tmp -= 0x10000;
+ PBuf += sprintf(PBuf, "%d", tmp);
+ break;
+
+ case SPR : /* special purpose register, two halves are reversed */
+ case TBR : /* time base register, two halves are reversed */
+ tmp = ((opword >> 16) & 0x1f);
+ tmp |= ((opword >> 6) & 0x3e0);
+ PBuf += sprintf(PBuf, "%d", tmp);
+ break;
+
+ case SR : /* specifies segment register */
+ PBuf += sprintf(PBuf, "%d", (opword >> 16) & 0xf);
+ break;
+
+ case TO : /* trap condition */
+ PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1f);
+ break;
+
+ case U : /* immediate data for FPSCR */
+ PBuf += sprintf(PBuf, "%d", (opword >> 12) & 0xf);
+ break;
+
+ case UI : /* 16 bit unsigned integer data field */
+ PBuf += sprintf(PBuf, "%d", opword & 0xffff);
+ break;
+
+ default :
+ PBuf += sprintf(PBuf, "Disassembly error: Unknown operand format %d", *pp);
+ }
+
+ /* Point to next format in the operand formats table */
+ ++pp;
+
+ if ((*pp != '\0') && print_comma) PBuf += sprintf(PBuf, ",");
+ }
+ return;
+}
+
+
+int DumpAddress ( LPADDR lpaddr, LPCH lpch, int cchMax ) {
+ LPCH lpchT = lpch;
+
+ Unreferenced(cchMax);
+
+ OutputAddr ( &lpch, lpaddr, (ADDR_IS_FLAT(*lpaddr) + 1) * 2 );
+ *lpch = '\0';
+ return lpch - lpchT + 1;
+}
+
+
+int
+DumpGeneric (
+ LSZ lsz,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ int ich = 0;
+
+ while ( *(lsz + ich) != 0 && ich < cchMax - 1 ) {
+ *(lpch+ich) = *(lsz+ich);
+ ich += 1;
+ }
+ *( lpch + ich ) = '\0';
+
+ return ich + 1;
+}
+
+
+int
+DumpComment (
+ LSZ lsz,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ *(lpch) = ';';
+ return DumpGeneric ( lsz, lpch + 1, cchMax - 1 ) + 1;
+}
+
+int
+DumpEA (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ LPCH lpch,
+ int cchMax
+ )
+{
+ LPCH lpchT = lpch;
+ BYTE rgb [ MAXL ];
+ int indx;
+ int cb;
+#ifdef OSDEBUG4
+ XOSD xosd;
+#endif
+
+ Unreferenced(cchMax);
+
+ for ( indx = 0; indx < 2; indx++ ) {
+
+ if ( EAsize [ indx ] ) {
+ ADDR addr = {0};
+
+ OutputHexString ( &lpchT, (LPBYTE) &EAaddr [ indx ], 4 );
+
+ *lpchT++ = '=';
+
+ addr.addr.off = (UOFFSET) EAaddr [ indx ];
+ addr.addr.seg = (SEGMENT) 0;
+
+ *lpaddr = addr;
+
+#ifdef OSDEBUG4
+ xosd = ReadBuffer(hpid, htid, &addr, EAsize[indx], rgb, &cb);
+ if (xosd != xosdNone) {
+ cb = 0;
+ }
+#else
+ EMFunc (
+ emfSetAddr,
+ hpid,
+ htid,
+ adrCurrent,
+ (LONG) (LPADDR) &addr
+ );
+
+ cb = EMFunc (
+ emfReadBuf,
+ hpid,
+ htid,
+ EAsize [ indx ],
+ (LONG) (LPV) rgb
+ );
+#endif
+
+ if ( cb == EAsize [ indx ] ) {
+ OutputHexString ( &lpchT, rgb, EAsize [ indx ] );
+ }
+ else {
+ while ( EAsize [ indx ]-- ) {
+ *lpchT++ = '?';
+ *lpchT++ = '?';
+ }
+ }
+ *lpchT++ = '\0';
+ }
+ }
+
+ return lpchT - lpch;
+}
+
+
+
+/*** OutputHexString - output hex string
+*
+* Purpose:
+* Output the value pointed by *lplpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* *pchValue - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+* *lplpchMemBuf - pointer update to next memory byte
+*
+*************************************************************************/
+
+void OutputHexString (LPLPCH lplpchBuf, PCH pchValue, int length)
+{
+ unsigned char chMem;
+
+ pchValue += length;
+ while ( length-- ) {
+ chMem = *--pchValue;
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
+
+
+/*** OutputAddr - output address package
+*
+* Purpose:
+* Output the address pointed to by lpaddr.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpaddr - Standard address package.
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+VOID
+OutputAddr (
+ LPLPCH lplpchBuf,
+ LPADDR lpaddr,
+ int alen
+ )
+{
+ ADDR addr = *lpaddr;
+
+ *(*lplpchBuf)++ = '0';
+ *(*lplpchBuf)++ = (fUpper) ? 'X' : 'x';
+ OutputHexString ( lplpchBuf, (LPCH) &addr.addr.off, alen );
+
+ return;
+} /* OutputAddr() */
+
+
+/*** OutputHexCode - output hex code
+*
+* Purpose:
+* Output the code pointed by lpchMemBuf of the specified
+* length. The value is treated as unsigned and leading
+* zeroes are printed. This differs from OutputHexString
+* in that bytes are printed from low to high addresses.
+*
+* Input:
+* *lplpchBuf - pointer to text buffer to fill
+* lpchMemBuf - - pointer to memory buffer to extract value
+* length - length in bytes of value
+*
+* Output:
+* *lplpchBuf - pointer updated to next text character
+*
+*************************************************************************/
+
+void OutputHexCode (LPLPCH lplpchBuf, LPCH lpchMemBuf, int length)
+{
+ unsigned char chMem;
+
+ while (length--) {
+ chMem = lpchMemBuf[length];
+ *(*lplpchBuf)++ = hexdigit[chMem >> 4];
+ *(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
+ }
+}
diff --git a/private/windbg/em/p_ppc/d3.h b/private/windbg/em/p_ppc/d3.h
new file mode 100644
index 000000000..89373683c
--- /dev/null
+++ b/private/windbg/em/p_ppc/d3.h
@@ -0,0 +1,1238 @@
+/********************************** module *********************************/
+/* */
+/* d3.h */
+/* disassembler tables for CodeView's disassembler */
+/* */
+/***************************************************************************/
+/* */
+/* @ Purpose: */
+/* */
+/* @ Functions included: */
+/* */
+/* Revision History: */
+/* */
+/* [03] 31-dec-91 DavidGra */
+/* */
+/* Correctly handle rep/lock prefices. */
+/* */
+/* [02] 15-nov-91 DavidGra */
+/* */
+/* Fix cmpxchg - these are extended opcodes B0 & B1 instead */
+/* of A6 & A7 as the intel documentation claims. */
+/* */
+/* [01] 15-nov-91 DavidGra */
+/* */
+/* Make the 8c form of MOV output WORD PTR [] */
+/* */
+/* [00] 15-nov-91 DavidGra */
+/* */
+/* Added support to correctly handle MOV[S|Z]X */
+/* */
+/* @ Author: Gerd Immeyer @ Version: */
+/* */
+/* @ Creation Date: 10.19.89 @ Modification Date: */
+/* */
+/***************************************************************************/
+
+#ifdef HOST32
+typedef unsigned char CBC;
+#else
+typedef unsigned char _based(_segname("_CODE")) CBC;
+#endif
+
+/* Strings: Operand mnemonics, Segment overrides, etc. for disasm */
+
+CBC dszAAA[] = "aaa";
+CBC dszAAD[] = "aad";
+CBC dszAAM[] = "aam";
+CBC dszAAS[] = "aas";
+CBC dszADC[] = "adc";
+CBC dszADD[] = "add";
+CBC dszADDRPRFX[] = "";
+CBC dszAND[] = "and";
+CBC dszARPL[] = "arpl";
+CBC dszBOUND[] = "bound";
+CBC dszBSF[] = "bsf";
+CBC dszBSR[] = "bsr";
+CBC dszBST[] = "bst";
+CBC dszBSWAP[] = "bswap";
+CBC dszBT[] = "bt";
+CBC dszBTC[] = "btc";
+CBC dszBTR[] = "btr";
+CBC dszBTS[] = "bts";
+CBC dszCALL[] = "call";
+CBC dszCBW[] = "cbw";
+CBC dszCDQ[] = "cdq";
+CBC dszCLC[] = "clc";
+CBC dszCLD[] = "cld";
+CBC dszCLI[] = "cli";
+CBC dszCLTS[] = "clts";
+CBC dszCMC[] = "cmc";
+CBC dszCMP[] = "cmp";
+CBC dszCMPS[] = "cmps";
+CBC dszCMPSB[] = "cmpsb";
+CBC dszCMPSD[] = "cmpsd";
+CBC dszCMPSW[] = "cmpsw";
+CBC dszCMPXCHG[] = "cmpxchg";
+CBC dszCS_[] = "cs:";
+CBC dszCWD[] = "cwd";
+CBC dszCWDE[] = "cwde";
+CBC dszDAA[] = "daa";
+CBC dszDAS[] = "das";
+CBC dszDEC[] = "dec";
+CBC dszDIV[] = "div";
+CBC dszDS_[] = "ds:";
+CBC dszENTER[] = "enter";
+CBC dszES_[] = "es:";
+CBC dszF2XM1[] = "f2xm1";
+CBC dszFABS[] = "fabs";
+CBC dszFADD[] = "fadd";
+CBC dszFADDP[] = "faddp";
+CBC dszFBLD[] = "fbld";
+CBC dszFBSTP[] = "fbstp";
+CBC dszFCHS[] = "fchs";
+CBC dszFCLEX[] = "fclex";
+CBC dszFCOM[] = "fcom";
+CBC dszFCOMP[] = "fcomp";
+CBC dszFCOMPP[] = "fcompp";
+CBC dszFCOS[] = "fcos";
+CBC dszFDECSTP[] = "fdecstp";
+CBC dszFDISI[] = "fdisi";
+CBC dszFDIV[] = "fdiv";
+CBC dszFDIVP[] = "fdivp";
+CBC dszFDIVR[] = "fdivr";
+CBC dszFDIVRP[] = "fdivrp";
+CBC dszFENI[] = "feni";
+CBC dszFFREE[] = "ffree";
+CBC dszFIADD[] = "fiadd";
+CBC dszFICOM[] = "ficom";
+CBC dszFICOMP[] = "ficomp";
+CBC dszFIDIV[] = "fidiv";
+CBC dszFIDIVR[] = "fidivr";
+CBC dszFILD[] = "fild";
+CBC dszFIMUL[] = "fimul";
+CBC dszFINCSTP[] = "fincstp";
+CBC dszFINIT[] = "finit";
+CBC dszFIST[] = "fist";
+CBC dszFISTP[] = "fistp";
+CBC dszFISUB[] = "fisub";
+CBC dszFISUBR[] = "fisubr";
+CBC dszFLD[] = "fld";
+CBC dszFLD1[] = "fld1";
+CBC dszFLDCW[] = "fldcw";
+CBC dszFLDENV[] = "fldenv";
+CBC dszFLDL2E[] = "fldl2e";
+CBC dszFLDL2T[] = "fldl2t";
+CBC dszFLDLG2[] = "fldlg2";
+CBC dszFLDLN2[] = "fldln2";
+CBC dszFLDPI[] = "fldpi";
+CBC dszFLDZ[] = "fldz";
+CBC dszFMUL[] = "fmul";
+CBC dszFMULP[] = "fmulp";
+CBC dszFNCLEX[] = "fnclex";
+CBC dszFNDISI[] = "fndisi";
+CBC dszFNENI[] = "fneni";
+CBC dszFNINIT[] = "fninit";
+CBC dszFNLEX[] = "fnlex";
+CBC dszFNOP[] = "fnop";
+CBC dszFNSAVE[] = "fnsave";
+CBC dszFNSTCW[] = "fnstcw";
+CBC dszFNSTENV[] = "fnstenv";
+CBC dszFNSTSW[] = "fnstsw";
+CBC dszFNSTSWAX[] = "fnstswax";
+CBC dszFPATAN[] = "fpatan";
+CBC dszFPREM[] = "fprem";
+CBC dszFPREM1[] = "fprem1";
+CBC dszFPTAN[] = "fptan";
+CBC dszFRNDINT[] = "frndint";
+CBC dszFRSTOR[] = "frstor";
+CBC dszFSAVE[] = "fsave";
+CBC dszFSCALE[] = "fscale";
+CBC dszFSETPM[] = "fsetpm";
+CBC dszFSIN[] = "fsin";
+CBC dszFSINCOS[] = "fsincos";
+CBC dszFSQRT[] = "fsqrt";
+CBC dszFST[] = "fst";
+CBC dszFSTCW[] = "fstcw";
+CBC dszFSTENV[] = "fstenv";
+CBC dszFSTP[] = "fstp";
+CBC dszFSTSW[] = "fstsw";
+CBC dszFSTSWAX[] = "fstswax";
+CBC dszFSUB[] = "fsub";
+CBC dszFSUBP[] = "fsubp";
+CBC dszFSUBR[] = "fsubr";
+CBC dszFSUBRP[] = "fsubrp";
+CBC dszFS_[] = "fs:";
+CBC dszFTST[] = "ftst";
+CBC dszFUCOM[] = "fucom";
+CBC dszFUCOMP[] = "fucomp";
+CBC dszFUCOMPP[] = "fucompp";
+CBC dszFWAIT[] = "fwait";
+CBC dszFXAM[] = "fxam";
+CBC dszFXCH[] = "fxch";
+CBC dszFXTRACT[] = "fxtract";
+CBC dszFYL2X[] = "fyl2x";
+CBC dszFYL2XP1[] = "fyl2xp1";
+CBC dszGS_[] = "gs:";
+CBC dszHLT[] = "hlt";
+CBC dszIBTS[] = "ibts";
+CBC dszIDIV[] = "idiv";
+CBC dszIMUL[] = "imul";
+CBC dszIN[] = "in";
+CBC dszINC[] = "inc";
+CBC dszINS[] = "ins";
+CBC dszINSB[] = "insb";
+CBC dszINSD[] = "insd";
+CBC dszINSW[] = "insw";
+CBC dszINT[] = "int";
+CBC dszINTO[] = "into";
+CBC dszIRET[] = "iret";
+CBC dszIRETD[] = "iretd";
+CBC dszJA[] = "ja";
+CBC dszJAE[] = "jae";
+CBC dszJB[] = "jb";
+CBC dszJBE[] = "jbe";
+CBC dszJC[] = "jc";
+CBC dszJCXZ[] = "jcxz";
+CBC dszJE[] = "je";
+CBC dszJECXZ[] = "jecxz";
+CBC dszJG[] = "jg";
+CBC dszJGE[] = "jge";
+CBC dszJL[] = "jl";
+CBC dszJLE[] = "jle";
+CBC dszJMP[] = "jmp";
+CBC dszJNA[] = "jna";
+CBC dszJNAE[] = "jnae";
+CBC dszJNB[] = "jnb";
+CBC dszJNBE[] = "jnbe";
+CBC dszJNC[] = "jnc";
+CBC dszJNE[] = "jne";
+CBC dszJNG[] = "jng";
+CBC dszJNGE[] = "jnge";
+CBC dszJNL[] = "jnl";
+CBC dszJNLE[] = "jnle";
+CBC dszJNO[] = "jno";
+CBC dszJNP[] = "jnp";
+CBC dszJNS[] = "jns";
+CBC dszJNZ[] = "jnz";
+CBC dszJO[] = "jo";
+CBC dszJP[] = "jp";
+CBC dszJPE[] = "jpe";
+CBC dszJPO[] = "jpo";
+CBC dszJS[] = "js";
+CBC dszJZ[] = "jz";
+CBC dszLAHF[] = "lahf";
+CBC dszLAR[] = "lar";
+CBC dszLDS[] = "lds";
+CBC dszLEA[] = "lea";
+CBC dszLEAVE[] = "leave";
+CBC dszLES[] = "les";
+CBC dszLFS[] = "lfs";
+CBC dszLGDT[] = "lgdt";
+CBC dszLGS[] = "lgs";
+CBC dszLIDT[] = "lidt";
+CBC dszLLDT[] = "lldt";
+CBC dszLMSW[] = "lmsw";
+CBC dszLOADALL[] = "loadall";
+CBC dszLOCK[] = "lock";
+CBC dszLODS[] = "lods";
+CBC dszLODSB[] = "lodsb";
+CBC dszLODSD[] = "lodsd";
+CBC dszLODSW[] = "lodsw";
+CBC dszLOOP[] = "loop";
+CBC dszLOOPE[] = "loope";
+CBC dszLOOPNE[] = "loopne";
+CBC dszLOOPNZ[] = "loopnz";
+CBC dszLOOPZ[] = "loopz";
+CBC dszLSL[] = "lsl";
+CBC dszLSS[] = "lss";
+CBC dszLTR[] = "ltr";
+CBC dszMOV[] = "mov";
+CBC dszMOVS[] = "movs";
+CBC dszMOVSB[] = "movsb";
+CBC dszMOVSD[] = "movsd";
+CBC dszMOVSW[] = "movsw";
+CBC dszMOVSX[] = "movsx";
+CBC dszMOVZX[] = "movzx";
+CBC dszMUL[] = "mul";
+CBC dszNEG[] = "neg";
+CBC dszNOP[] = "nop";
+CBC dszNOT[] = "not";
+CBC dszOPPRFX[] = "";
+CBC dszOR[] = "or";
+CBC dszOUT[] = "out";
+CBC dszOUTS[] = "outs";
+CBC dszOUTSB[] = "outsb";
+CBC dszOUTSD[] = "outsd";
+CBC dszOUTSW[] = "outsw";
+CBC dszPOP[] = "pop";
+CBC dszPOPA[] = "popa";
+CBC dszPOPAD[] = "popad";
+CBC dszPOPF[] = "popf";
+CBC dszPOPFD[] = "popfd";
+CBC dszPUSH[] = "push";
+CBC dszPUSHA[] = "pusha";
+CBC dszPUSHAD[] = "pushad";
+CBC dszPUSHF[] = "pushf";
+CBC dszPUSHFD[] = "pushfd";
+CBC dszRCL[] = "rcl";
+CBC dszRCR[] = "rcr";
+CBC dszREP[] = "rep"; // [03]
+CBC dszREPE[] = "repe";
+CBC dszREPNE[] = "repne"; // [03]
+CBC dszREPNZ[] = "repnz";
+CBC dszREPZ[] = "repz";
+CBC dszRET[] = "ret";
+CBC dszRETF[] = "retf";
+CBC dszRETN[] = "retn";
+CBC dszROL[] = "rol";
+CBC dszROR[] = "ror";
+CBC dszSAHF[] = "sahf";
+CBC dszSAL[] = "sal";
+CBC dszSAR[] = "sar";
+CBC dszSBB[] = "sbb";
+CBC dszSCAS[] = "scas";
+CBC dszSCASB[] = "scasb";
+CBC dszSCASD[] = "scasd";
+CBC dszSCASW[] = "scasw";
+CBC dszSETA[] = "seta";
+CBC dszSETAE[] = "setae";
+CBC dszSETB[] = "setb";
+CBC dszSETBE[] = "setbe";
+CBC dszSETC[] = "setc";
+CBC dszSETE[] = "sete";
+CBC dszSETG[] = "setg";
+CBC dszSETGE[] = "setge";
+CBC dszSETL[] = "setl";
+CBC dszSETLE[] = "setle";
+CBC dszSETNA[] = "setna";
+CBC dszSETNAE[] = "setnae";
+CBC dszSETNB[] = "setnb";
+CBC dszSETNBE[] = "setnbe";
+CBC dszSETNC[] = "setnc";
+CBC dszSETNE[] = "setne";
+CBC dszSETNG[] = "setng";
+CBC dszSETNGE[] = "setnge";
+CBC dszSETNL[] = "setnl";
+CBC dszSETNLE[] = "setnle";
+CBC dszSETNO[] = "setno";
+CBC dszSETNP[] = "setnp";
+CBC dszSETNS[] = "setns";
+CBC dszSETNZ[] = "setnz";
+CBC dszSETO[] = "seto";
+CBC dszSETP[] = "setp";
+CBC dszSETPE[] = "setpe";
+CBC dszSETPO[] = "setpo";
+CBC dszSETS[] = "sets";
+CBC dszSETZ[] = "setz";
+CBC dszSGDT[] = "sgdt";
+CBC dszSHL[] = "shl";
+CBC dszSHLD[] = "shld";
+CBC dszSHR[] = "shr";
+CBC dszSHRD[] = "shrd";
+CBC dszSIDT[] = "sidt";
+CBC dszSLDT[] = "sldt";
+CBC dszSMSW[] = "smsw";
+CBC dszSS_[] = "ss:";
+CBC dszSTC[] = "stc";
+CBC dszSTD[] = "std";
+CBC dszSTI[] = "sti";
+CBC dszSTOS[] = "stos";
+CBC dszSTOSB[] = "stosb";
+CBC dszSTOSD[] = "stosd";
+CBC dszSTOSW[] = "stosw";
+CBC dszSTR[] = "str";
+CBC dszSUB[] = "sub";
+CBC dszTEST[] = "test";
+CBC dszVERR[] = "verr";
+CBC dszVERW[] = "verw";
+CBC dszWAIT[] = "wait";
+CBC dszXADD[] = "xadd";
+CBC dszXBTS[] = "xbts";
+CBC dszXCHG[] = "xchg";
+CBC dszXLAT[] = "xlat";
+CBC dszXOR[] = "xor";
+CBC dszRESERVED[] = "???";
+CBC dszMULTI[] = "";
+CBC dszDB[] = "db";
+
+#define MRM 0x40
+#define COM 0x80
+#define END 0xc0
+
+/* Enumeration of valid actions that can be included in the action table */
+
+enum oprtyp { ADDRP, ADR_OVR, ALSTR, ALT, AXSTR, BOREG,
+ BREG, BRSTR, BYT, CHR, CREG, DWRD,
+ EDWRD, EGROUPT, FARPTR, GROUP, GROUPT, IB,
+ IST, IST_ST, IV, IW, LMODRM, MODRM,
+ NOP, OFFS, OPC0F, OPR_OVR, QWRD, REL16,
+ REL8, REP, SEG_OVR, SREG2, SREG3, ST_IST,
+ STROP, TBYT, UBYT, VAR, VOREG, VREG,
+ EWRD, WRD, WREG, DREG, WRSTR // [00]
+ };
+
+/* Enumeration of indices into the action table for instruction classes */
+
+#define O_DoDB 0
+#define O_NoOperands 0
+#define O_NoOpAlt5 O_NoOperands+1
+#define O_NoOpAlt4 O_NoOpAlt5+2
+#define O_NoOpAlt3 O_NoOpAlt4+2
+#define O_NoOpAlt1 O_NoOpAlt3+2
+#define O_NoOpAlt0 O_NoOpAlt1+2
+#define O_NoOpStrSI O_NoOpAlt0+2
+#define O_NoOpStrDI O_NoOpStrSI+2
+#define O_NoOpStrSIDI O_NoOpStrDI+2
+#define O_bModrm_Reg O_NoOpStrSIDI+2
+#define O_vModrm_Reg O_bModrm_Reg+3
+#define O_Modrm_Reg O_vModrm_Reg+3
+#define O_bReg_Modrm O_Modrm_Reg+3
+#define O_fReg_Modrm O_bReg_Modrm+3
+#define O_Reg_Modrm O_fReg_Modrm+3
+#define O_AL_Ib O_Reg_Modrm+3
+#define O_AX_Iv O_AL_Ib+2
+#define O_sReg2 O_AX_Iv+2
+#define O_oReg O_sReg2+1
+#define O_DoBound O_oReg+1
+#define O_Iv O_DoBound+3
+#define O_wModrm_Reg O_Iv+1
+#define O_Ib O_wModrm_Reg+3
+#define O_Imulb O_Ib+1
+#define O_Imul O_Imulb+4
+#define O_Rel8 O_Imul+4
+#define O_bModrm_Ib O_Rel8+1
+#define O_Modrm_Ib O_bModrm_Ib+3
+#define O_Modrm_Iv O_Modrm_Ib+3
+#define O_Modrm_sReg3 O_Modrm_Iv+3
+#define O_sReg3_Modrm O_Modrm_sReg3+3
+#define O_Modrm O_sReg3_Modrm+3
+#define O_FarPtr O_Modrm+2
+#define O_AL_Offs O_FarPtr+1
+#define O_Offs_AL O_AL_Offs+2
+#define O_AX_Offs O_Offs_AL+2
+#define O_Offs_AX O_AX_Offs+2
+#define O_oReg_Ib O_Offs_AX+2
+#define O_oReg_Iv O_oReg_Ib+2
+#define O_Iw O_oReg_Iv+2
+#define O_Enter O_Iw+1
+#define O_Ubyte_AL O_Enter+2
+#define O_Ubyte_AX O_Ubyte_AL+2
+#define O_AL_Ubyte O_Ubyte_AX+2
+#define O_AX_Ubyte O_AL_Ubyte+2
+#define O_DoInAL O_AX_Ubyte+2
+#define O_DoInAX O_DoInAL+3
+#define O_DoOutAL O_DoInAX+3
+#define O_DoOutAX O_DoOutAL+3
+#define O_Rel16 O_DoOutAX+3
+#define O_ADR_OVERRIDE O_Rel16+1
+#define O_OPR_OVERRIDE O_ADR_OVERRIDE+1
+#define O_SEG_OVERRIDE O_OPR_OVERRIDE+1
+#define O_DoInt3 O_SEG_OVERRIDE+1
+
+#if (O_DoInt3 != 115)
+#error "operand table has been modified!"
+#endif
+/* #define O_DoInt O_DoInt3+2 */
+
+#define O_DoInt 117
+#define O_OPC0F O_DoInt+1
+#define O_GROUP11 O_OPC0F+1
+#define O_GROUP13 O_GROUP11+5
+#define O_GROUP12 O_GROUP13+5
+#define O_GROUP21 O_GROUP12+5
+#define O_GROUP22 O_GROUP21+5
+#define O_GROUP23 O_GROUP22+5
+#define O_GROUP24 O_GROUP23+6
+#define O_GROUP25 O_GROUP24+6
+#define O_GROUP26 O_GROUP25+6
+#define O_GROUP4 O_GROUP26+6
+#define O_GROUP6 O_GROUP4+4
+#define O_GROUP8 O_GROUP6+4
+#define O_GROUP31 O_GROUP8+5
+#define O_GROUP32 O_GROUP31+3
+#define O_GROUP5 O_GROUP32+3
+#define O_GROUP7 O_GROUP5+3
+#define O_x87_ESC O_GROUP7+3
+#define O_bModrm O_x87_ESC+2
+#define O_wModrm O_bModrm+2
+#define O_dModrm O_wModrm+2
+#define O_fModrm O_dModrm+2
+#define O_vModrm O_fModrm+2
+#define O_vModrm_Iv O_vModrm+2
+#define O_Reg_bModrm O_vModrm_Iv+3
+#define O_Reg_wModrm O_Reg_bModrm+3
+#define O_Modrm_Reg_Ib O_Reg_wModrm+3
+#define O_Modrm_Reg_CL O_Modrm_Reg_Ib+4
+#define O_ST_iST O_Modrm_Reg_CL+5
+#define O_iST O_ST_iST+2
+#define O_iST_ST O_iST+2
+#define O_qModrm O_iST_ST+2
+#define O_tModrm O_qModrm+2
+#define O_DoRep O_tModrm+2
+#define O_Modrm_CReg O_DoRep+1
+#define O_CReg_Modrm O_Modrm_CReg+3
+#define O_AX_oReg O_CReg_Modrm+3
+#define O_length O_AX_oReg+3
+
+#if( O_length > 255 )
+#error "operand table too large!"
+#endif
+
+
+/* The action table: range of lists of actions to be taken for each */
+/* possible instruction class. */
+
+static CBC actiontbl[] = {
+/* NoOperands */ (CBC) (NOP+END),
+/* NoOpAlt5 */ (CBC) (ALT+END), 5,
+/* NoOpAlt4 */ (CBC) (ALT+END), 4,
+/* NoOpAlt3 */ (CBC) (ALT+END), 3,
+/* NoOpAlt1 */ (CBC) (ALT+END), 1,
+/* NoOpAlt0 */ (CBC) (ALT+END), 0,
+/* NoOpStrSI */ (CBC) (STROP+END), 1,
+/* NoOpStrDI */ (CBC) (STROP+END), 2,
+/* NoOpStrSIDI */ (CBC) (STROP+END), 3,
+/* bModrm_Reg */ (CBC) (BYT+MRM), (CBC) (LMODRM+COM), (CBC) (BREG+END),
+/* vModrm_Reg */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+END),
+/* Modrm_Reg */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+END),
+/* bReg_Modrm */ (CBC) (BYT+MRM), (CBC) (BREG+COM), (CBC) (LMODRM+END),
+/* fReg_Modrm */ (CBC) (FARPTR+MRM),(CBC) (VREG+COM), (CBC) (MODRM+END),
+/* Reg_Modrm */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* AL_Ib */ (CBC) (ALSTR+COM), (CBC) (IB+END),
+/* AX_Iv */ (CBC) (AXSTR+COM), (CBC) (IV+END),
+/* sReg2 */ (CBC) (SREG2+END),
+/* oReg */ (CBC) (VOREG+END),
+/* DoBound */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+END),
+/* Iv */ (CBC) (IV+END),
+/* wModrm_Reg */ (CBC) (WRD+MRM), (CBC) (LMODRM+COM), (CBC) (WREG+END),
+/* Ib */ (CBC) (IB+END),
+/* Imulb */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+COM),
+ (CBC) (IB+END),
+/* Imul */ (CBC) (VAR+MRM), (CBC) (VREG+COM), (CBC) (MODRM+COM),
+ (CBC) (IV+END),
+/* REL8 */ (CBC) (REL8+END),
+/* bModrm_Ib */ (CBC) (BYT+MRM), (CBC) (LMODRM+COM), (CBC) (IB+END),
+/* Modrm_Ib */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (IB+END),
+/* Modrm_Iv */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (IV+END),
+/* Modrm_sReg3 */ (CBC) (WRD+MRM), (CBC) (LMODRM+COM), (CBC) (SREG3+END),
+/* sReg3_Modrm */ (CBC) (WRD+MRM), (CBC) (SREG3+COM), (CBC) (MODRM+END),
+/* Modrm */ (CBC) (VAR+MRM), (CBC) (MODRM+END),
+/* FarPtr */ (CBC) (ADDRP+END),
+/* AL_Offs */ (CBC) (ALSTR+COM), (CBC) (OFFS+END),
+/* Offs_AL */ (CBC) (OFFS+COM), (CBC) (ALSTR+END),
+/* AX_Offs */ (CBC) (AXSTR+COM), (CBC) (OFFS+END),
+/* Offs_AX */ (CBC) (OFFS+COM), (CBC) (AXSTR+END),
+/* oReg_Ib */ (CBC) (BOREG+COM), (CBC) (IB+END),
+/* oReg_Iv */ (CBC) (VOREG+COM), (CBC) (IV+END),
+/* Iw */ (CBC) (IW+END),
+/* enter */ (CBC) (IW+COM), (CBC) (IB+END),
+/* Ubyte_AL */ (CBC) (UBYT+COM), (CBC) (ALSTR+END),
+/* Ubyte_AX */ (CBC) (UBYT+COM), (CBC) (AXSTR+END),
+/* AL_Ubyte */ (CBC) (ALSTR+COM), (CBC) (UBYT+END),
+/* AX_Ubyte */ (CBC) (AXSTR+COM), (CBC) (UBYT+END),
+/* DoInAL */ (CBC) (ALSTR+COM), (CBC) (WRSTR+END), 2,
+/* DoInAX */ (CBC) (AXSTR+COM), (CBC) (WRSTR+END), 2,
+/* DoOutAL */ (CBC) (WRSTR+COM), 2, (CBC) (ALSTR+END),
+/* DoOutAX */ (CBC) (WRSTR+COM), 2, (CBC) (AXSTR+END),
+/* REL16 */ (CBC) (REL16+END),
+/* ADR_OVERRIDE*/ ADR_OVR,
+/* OPR_OVERRIDE*/ OPR_OVR,
+/* SEG_OVERRIDE*/ SEG_OVR,
+/* DoInt3 */ (CBC) (CHR+END), '3',
+/* DoInt */ (CBC) (UBYT+END),
+/* Opcode0F */ OPC0F,
+/* group1_1 */ (CBC) (BYT+MRM), GROUP, 0, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group1_3 */ (CBC) (VAR+MRM), GROUP, 0, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group1_2 */ (CBC) (VAR+MRM), GROUP, 0, (CBC) (LMODRM+COM),
+ (CBC) (IV+END),
+/* group2_1 */ (CBC) (BYT+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group2_2 */ (CBC) (VAR+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group2_3 */ (CBC) (BYT+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (CHR+END), '1',
+/* group2_4 */ (CBC) (VAR+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (CHR+END), '1',
+/* group2_5 */ (CBC) (BYT+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (BRSTR+END), 1,
+/* group2_6 */ (CBC) (VAR+MRM), GROUP, 1, (CBC) (LMODRM+COM),
+ (CBC) (BRSTR+END), 1,
+/* group4 */ (CBC) (BYT+MRM), GROUP, 2, (CBC) (LMODRM+END),
+/* group6 */ (CBC) (WRD+MRM), GROUP, 3, (CBC) (LMODRM+END),
+/* group8 */ (CBC) (VAR+MRM), GROUP, 4, (CBC) (LMODRM+COM),
+ (CBC) (IB+END),
+/* group3_1 */ (CBC) (BYT+MRM), GROUPT, 20,
+/* group3_2 */ (CBC) (VAR+MRM), GROUPT, 21,
+/* group5 */ (CBC) (VAR+MRM), GROUPT, 22,
+/* group7 */ (CBC) (NOP+MRM), GROUPT, 23,
+/* x87_ESC */ (CBC) (NOP+MRM), EGROUPT,
+/* bModrm */ (CBC) (BYT+MRM), (CBC) (LMODRM+END),
+/* wModrm */ (CBC) (WRD+MRM), (CBC) (LMODRM+END),
+/* dModrm */ (CBC) (DWRD+MRM), (CBC) (LMODRM+END),
+/* fModrm */ (CBC) (FARPTR+MRM),(CBC) (LMODRM+END),
+/* vModrm */ (CBC) (VAR+MRM), (CBC) (LMODRM+END),
+/* vModrm_Iv */ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (IV+END),
+/* reg_bModrm */ (CBC) (BYT+MRM), (CBC) (VREG+COM), (CBC) (LMODRM+END),
+/* reg_wModrm */ (CBC) (EWRD+MRM), (CBC) (DREG+COM), (CBC) (LMODRM+END),
+/* Modrm_Reg_Ib*/ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+COM),
+ (CBC) (IB+END),
+/* Modrm_Reg_CL*/ (CBC) (VAR+MRM), (CBC) (LMODRM+COM), (CBC) (VREG+COM),
+ (CBC) (BRSTR+END), 1,
+/* ST_iST */ (CBC) (NOP+MRM), (CBC) (ST_IST+END),
+/* iST */ (CBC) (NOP+MRM), (CBC) (IST+END),
+/* iST_ST */ (CBC) (NOP+MRM), (CBC) (IST_ST+END),
+/* qModrm */ (CBC) (QWRD+MRM), (CBC) (LMODRM+END),
+/* tModrm */ (CBC) (TBYT+MRM), (CBC) (LMODRM+END),
+/* REP */ REP,
+/* Modrm_CReg */ (CBC) (EDWRD+MRM), (CBC) (MODRM+COM), (CBC) (CREG+END),
+/* CReg_Modrm */ (CBC) (EDWRD+MRM), (CBC) (CREG+COM), (CBC) (MODRM+END),
+/* AX_oReg */ (CBC) (AXSTR+COM), (CBC) (VOREG+END)
+ };
+
+#ifdef HOST_i386
+#pragma pack(1)
+#endif
+
+typedef struct Tdistbl{
+ CBC *instruct;
+ unsigned char opr;
+ } Tdistbl;
+
+/* List of ordered pairs for each instruction: */
+/* (pointer to string literal mnemonic, */
+/* instruction class index for action table) */
+
+static Tdistbl distbl[] = {
+ dszADD, O_bModrm_Reg, /* 00 ADD mem/reg, reg (byte) */
+ dszADD, O_Modrm_Reg, /* 01 ADD mem/reg, reg (var) */
+ dszADD, O_bReg_Modrm, /* 02 ADD reg, mem/reg (byte) */
+ dszADD, O_Reg_Modrm, /* 03 ADD reg, mem/reg (var) */
+ dszADD, O_AL_Ib, /* 04 ADD AL, I */
+ dszADD, O_AX_Iv, /* 05 ADD AX, I */
+ dszPUSH, O_sReg2, /* 06 PUSH ES */
+ dszPOP, O_sReg2, /* 07 POP ES */
+ dszOR, O_bModrm_Reg, /* 08 OR mem/reg, reg (byte) */
+ dszOR, O_Modrm_Reg, /* 09 OR mem/reg, reg (word) */
+ dszOR, O_bReg_Modrm, /* 0A OR reg, mem/reg (byte) */
+ dszOR, O_Reg_Modrm, /* 0B OR reg, mem/reg (word) */
+ dszOR, O_AL_Ib, /* 0C OR AL, I */
+ dszOR, O_AX_Iv, /* 0D OR AX, I */
+ dszPUSH, O_sReg2, /* 0E PUSH CS */
+ dszMULTI, O_OPC0F, /* 0F CLTS & protection ctl(286) */
+ dszADC, O_bModrm_Reg, /* 10 ADC mem/reg, reg (byte) */
+ dszADC, O_Modrm_Reg, /* 11 ADC mem/reg, reg (word) */
+ dszADC, O_bReg_Modrm, /* 12 ADC reg, mem/reg (byte) */
+ dszADC, O_Reg_Modrm, /* 13 ADC reg, mem/reg (word) */
+ dszADC, O_AL_Ib, /* 14 ADC AL, I */
+ dszADC, O_AX_Iv, /* 15 ADC AX, I */
+ dszPUSH, O_sReg2, /* 16 PUSH SS */
+ dszPOP, O_sReg2, /* 17 POP SS */
+ dszSBB, O_bModrm_Reg, /* 18 SBB mem/reg, reg (byte) */
+ dszSBB, O_Modrm_Reg, /* 19 SBB mem/reg, reg (word) */
+ dszSBB, O_bReg_Modrm, /* 1A SBB reg, mem/reg (byte) */
+ dszSBB, O_Reg_Modrm, /* 1B SBB reg, mem/reg (word) */
+ dszSBB, O_AL_Ib, /* 1C SBB AL, I */
+ dszSBB, O_AX_Iv, /* 1D SBB AX, I */
+ dszPUSH, O_sReg2, /* 1E PUSH DS */
+ dszPOP, O_sReg2, /* 1F POP DS */
+ dszAND, O_bModrm_Reg, /* 20 AND mem/reg, reg (byte) */
+ dszAND, O_Modrm_Reg, /* 21 AND mem/reg, reg (word) */
+ dszAND, O_bReg_Modrm, /* 22 AND reg, mem/reg (byte) */
+ dszAND, O_Reg_Modrm, /* 23 AND reg, mem/reg (word) */
+ dszAND, O_AL_Ib, /* 24 AND AL, I */
+ dszAND, O_AX_Iv, /* 25 AND AX, I */
+ dszES_, O_SEG_OVERRIDE, /* 26 SEG ES: */
+ dszDAA, O_NoOperands, /* 27 DAA */
+ dszSUB, O_bModrm_Reg, /* 28 SUB mem/reg, reg (byte) */
+ dszSUB, O_Modrm_Reg, /* 29 SUB mem/reg, reg (word) */
+ dszSUB, O_bReg_Modrm, /* 2A SUB reg, mem/reg (byte) */
+ dszSUB, O_Reg_Modrm, /* 2B SUB reg, mem/reg (word) */
+ dszSUB, O_AL_Ib, /* 2C SUB AL, I */
+ dszSUB, O_AX_Iv, /* 2D SUB AX, I */
+ dszCS_, O_SEG_OVERRIDE, /* 2E SEG CS: */
+ dszDAS, O_NoOperands, /* 2F DAS */
+ dszXOR, O_bModrm_Reg, /* 30 XOR mem/reg, reg (byte) */
+ dszXOR, O_Modrm_Reg, /* 31 XOR mem/reg, reg (word) */
+ dszXOR, O_bReg_Modrm, /* 32 XOR reg, mem/reg (byte) */
+ dszXOR, O_Reg_Modrm, /* 33 XOR reg, mem/reg (word) */
+ dszXOR, O_AL_Ib, /* 34 XOR AL, I */
+ dszXOR, O_AX_Iv, /* 35 XOR AX, I */
+ dszSS_, O_SEG_OVERRIDE, /* 36 SEG SS: */
+ dszAAA, O_NoOperands, /* 37 AAA */
+ dszCMP, O_bModrm_Reg, /* 38 CMP mem/reg, reg (byte) */
+ dszCMP, O_Modrm_Reg, /* 39 CMP mem/reg, reg (word) */
+ dszCMP, O_bReg_Modrm, /* 3A CMP reg, mem/reg (byte) */
+ dszCMP, O_Reg_Modrm, /* 3B CMP reg, mem/reg (word) */
+ dszCMP, O_AL_Ib, /* 3C CMP AL, I */
+ dszCMP, O_AX_Iv, /* 3D CMP AX, I */
+ dszDS_, O_SEG_OVERRIDE, /* 3E SEG DS: */
+ dszAAS, O_NoOperands, /* 3F AAS */
+ dszINC, O_oReg, /* 40 INC AX */
+ dszINC, O_oReg, /* 41 INC CX */
+ dszINC, O_oReg, /* 42 INC DX */
+ dszINC, O_oReg, /* 43 INC BX */
+ dszINC, O_oReg, /* 44 INC SP */
+ dszINC, O_oReg, /* 45 INC BP */
+ dszINC, O_oReg, /* 46 INC SI */
+ dszINC, O_oReg, /* 47 INC DI */
+ dszDEC, O_oReg, /* 48 DEC AX */
+ dszDEC, O_oReg, /* 49 DEC CX */
+ dszDEC, O_oReg, /* 4A DEC DX */
+ dszDEC, O_oReg, /* 4B DEC BX */
+ dszDEC, O_oReg, /* 4C DEC SP */
+ dszDEC, O_oReg, /* 4D DEC BP */
+ dszDEC, O_oReg, /* 4E DEC SI */
+ dszDEC, O_oReg, /* 4F DEC DI */
+ dszPUSH, O_oReg, /* 50 PUSH AX */
+ dszPUSH, O_oReg, /* 51 PUSH CX */
+ dszPUSH, O_oReg, /* 52 PUSH DX */
+ dszPUSH, O_oReg, /* 53 PUSH BX */
+ dszPUSH, O_oReg, /* 54 PUSH SP */
+ dszPUSH, O_oReg, /* 55 PUSH BP */
+ dszPUSH, O_oReg, /* 56 PUSH SI */
+ dszPUSH, O_oReg, /* 57 PUSH DI */
+ dszPOP, O_oReg, /* 58 POP AX */
+ dszPOP, O_oReg, /* 59 POP CX */
+ dszPOP, O_oReg, /* 5A POP DX */
+ dszPOP, O_oReg, /* 5B POP BX */
+ dszPOP, O_oReg, /* 5C POP SP */
+ dszPOP, O_oReg, /* 5D POP BP */
+ dszPOP, O_oReg, /* 5E POP SI */
+ dszPOP, O_oReg, /* 5F POP DI */
+ dszPUSHA, O_NoOpAlt5, /* 60 PUSHA (286) / PUSHAD (386) */
+ dszPOPA, O_NoOpAlt4, /* 61 POPA (286) / POPAD (286) */
+ dszBOUND, O_DoBound, /* 62 BOUND reg, Modrm (286) */
+ dszARPL, O_Modrm_Reg, /* 63 ARPL Modrm, reg (286) */
+ dszFS_, O_SEG_OVERRIDE, /* 64 */
+ dszGS_, O_SEG_OVERRIDE, /* 65 */
+ dszOPPRFX,O_OPR_OVERRIDE, /* 66 */
+ dszADDRPRFX,O_ADR_OVERRIDE, /* 67 */
+ dszPUSH, O_Iv, /* 68 PUSH word (286) */
+ dszIMUL, O_Imul, /* 69 IMUL (286) */
+ dszPUSH, O_Ib, /* 6A PUSH byte (286) */
+ dszIMUL, O_Imulb, /* 6B IMUL (286) */
+ dszINSB, O_NoOperands, /* 6C INSB (286) */
+ dszINSW, O_NoOpAlt3, /* 6D INSW (286) / INSD (386) */
+ dszOUTSB, O_NoOperands, /* 6E OUTSB (286) */
+ dszOUTSW, O_NoOpAlt4, /* 6F OUTSW (286) / OUTSD (386) */
+ dszJO, O_Rel8, /* 70 JO */
+ dszJNO, O_Rel8, /* 71 JNO */
+ dszJB, O_Rel8, /* 72 JB or JNAE or JC */
+ dszJNB, O_Rel8, /* 73 JNB or JAE or JNC */
+ dszJZ, O_Rel8, /* 74 JE or JZ */
+ dszJNZ, O_Rel8, /* 75 JNE or JNZ */
+ dszJBE, O_Rel8, /* 76 JBE or JNA */
+ dszJA, O_Rel8, /* 77 JNBE or JA */
+ dszJS, O_Rel8, /* 78 JS */
+ dszJNS, O_Rel8, /* 79 JNS */
+ dszJPE, O_Rel8, /* 7A JP or JPE */
+ dszJPO, O_Rel8, /* 7B JNP or JPO */
+ dszJL, O_Rel8, /* 7C JL or JNGE */
+ dszJGE, O_Rel8, /* 7D JNL or JGE */
+ dszJLE, O_Rel8, /* 7E JLE or JNG */
+ dszJG, O_Rel8, /* 7F JNLE or JG */
+ dszMULTI, O_GROUP11, /* 80 */
+ dszMULTI, O_GROUP12, /* 81 */
+ dszRESERVED, O_DoDB, /* 82 */
+ dszMULTI, O_GROUP13, /* 83 */
+ dszTEST, O_bModrm_Reg, /* 84 TEST reg, mem/reg (byte) */
+ dszTEST, O_Modrm_Reg, /* 85 TEST reg, mem/reg (word) */
+ dszXCHG, O_bModrm_Reg, /* 86 XCHG reg, mem/reg (byte) */
+ dszXCHG, O_Modrm_Reg, /* 87 XCHG reg, mem/reg (word) */
+ dszMOV, O_bModrm_Reg, /* 88 MOV mem/reg, reg (byte) */
+ dszMOV, O_Modrm_Reg, /* 89 MOV mem/reg, reg (word) */
+ dszMOV, O_bReg_Modrm, /* 8A MOV reg, mem/reg (byte) */
+ dszMOV, O_Reg_Modrm, /* 8B MOV reg, mem/reg (word) */
+ dszMOV, O_Modrm_sReg3, /* 8C MOV mem/reg, segreg */
+ dszLEA, O_Reg_Modrm, /* 8D LEA reg, mem */
+ dszMOV, O_sReg3_Modrm, /* 8E MOV segreg, mem/reg */
+ dszPOP, O_Modrm, /* 8F POP mem/reg */
+ dszNOP, O_NoOperands, /* 90 NOP */
+ dszXCHG, O_AX_oReg, /* 91 XCHG AX,CX */
+ dszXCHG, O_AX_oReg, /* 92 XCHG AX,DX */
+ dszXCHG, O_AX_oReg, /* 93 XCHG AX,BX */
+ dszXCHG, O_AX_oReg, /* 94 XCHG AX,SP */
+ dszXCHG, O_AX_oReg, /* 95 XCHG AX,BP */
+ dszXCHG, O_AX_oReg, /* 96 XCHG AX,SI */
+ dszXCHG, O_AX_oReg, /* 97 XCHG AX,DI */
+ dszCBW, O_NoOpAlt0, /* 98 CBW / CWDE (386) */
+ dszCWD, O_NoOpAlt1, /* 99 CWD / CDQ (386) */
+ dszCALL, O_FarPtr, /* 9A CALL seg:off */
+ dszWAIT, O_NoOperands, /* 9B WAIT */
+ dszPUSHF, O_NoOpAlt5, /* 9C PUSHF / PUSHFD (386) */
+ dszPOPF, O_NoOpAlt4, /* 9D POPF / POPFD (386) */
+ dszSAHF, O_NoOperands, /* 9E SAHF */
+ dszLAHF, O_NoOperands, /* 9F LAHF */
+ dszMOV, O_AL_Offs, /* A0 MOV AL, mem */
+ dszMOV, O_AX_Offs, /* A1 MOV AX, mem */
+ dszMOV, O_Offs_AL, /* A2 MOV mem, AL */
+ dszMOV, O_Offs_AX, /* A3 MOV mem, AX */
+ dszMOVSB, O_NoOpStrSIDI, /* A4 MOVSB */
+ dszMOVSW, O_NoOpStrSIDI, /* A5 MOVSW / MOVSD (386) */
+ dszCMPSB, O_NoOpStrSIDI, /* A6 CMPSB */
+ dszCMPSW, O_NoOpStrSIDI, /* A7 CMPSW / CMPSD (386) */
+ dszTEST, O_AL_Ib, /* A8 TEST AL, I */
+ dszTEST, O_AX_Iv, /* A9 TEST AX, I */
+ dszSTOSB, O_NoOpStrDI, /* AA STOSB */
+ dszSTOSW, O_NoOpStrDI, /* AB STOSW / STOSD (386) */
+ dszLODSB, O_NoOpStrSI, /* AC LODSB */
+ dszLODSW, O_NoOpStrSI, /* AD LODSW / LODSD (386) */
+ dszSCASB, O_NoOpStrDI, /* AE SCASB */
+ dszSCASW, O_NoOpStrDI, /* AF SCASW / SCASD (386) */
+ dszMOV, O_oReg_Ib, /* B0 MOV AL, I */
+ dszMOV, O_oReg_Ib, /* B1 MOV CL, I */
+ dszMOV, O_oReg_Ib, /* B2 MOV DL, I */
+ dszMOV, O_oReg_Ib, /* B3 MOV BL, I */
+ dszMOV, O_oReg_Ib, /* B4 MOV AH, I */
+ dszMOV, O_oReg_Ib, /* B5 MOV CH, I */
+ dszMOV, O_oReg_Ib, /* B6 MOV DH, I */
+ dszMOV, O_oReg_Ib, /* B7 MOV BH, I */
+ dszMOV, O_oReg_Iv, /* B8 MOV AX, I */
+ dszMOV, O_oReg_Iv, /* B9 MOV CX, I */
+ dszMOV, O_oReg_Iv, /* BA MOV DX, I */
+ dszMOV, O_oReg_Iv, /* BB MOV BX, I */
+ dszMOV, O_oReg_Iv, /* BC MOV SP, I */
+ dszMOV, O_oReg_Iv, /* BD MOV BP, I */
+ dszMOV, O_oReg_Iv, /* BE MOV SI, I */
+ dszMOV, O_oReg_Iv, /* BF MOV DI, I */
+ dszMULTI, O_GROUP21, /* C0 shifts & rotates (286) */
+ dszMULTI, O_GROUP22, /* C1 shifts & rotates (286) */
+ dszRET, O_Iw, /* C2 RET Rel16 */
+ dszRET, O_NoOperands, /* C3 RET */
+ dszLES, O_fReg_Modrm, /* C4 LES reg, mem */
+ dszLDS, O_fReg_Modrm, /* C5 LDS reg, mem */
+ dszMOV, O_bModrm_Ib, /* C6 MOV mem/reg, I(byte) */
+ dszMOV, O_Modrm_Iv, /* C7 MOV mem/reg, I(word) */
+ dszENTER, O_Enter, /* C8 ENTER (286) */
+ dszLEAVE, O_NoOperands, /* C9 LEAVE (286) */
+ dszRETF, O_Iw, /* CA RETF I(word) */
+ dszRETF, O_NoOperands, /* CB RETF */
+ dszINT, O_DoInt3, /* CC INT 3 */
+ dszINT, O_DoInt, /* CD INT */
+ dszINTO, O_NoOperands, /* CE INTO */
+ dszIRET, O_NoOpAlt4, /* CF IRET / IRETD (386) */
+ dszMULTI, O_GROUP23, /* D0 shifts & rotates,1 (byte) */
+ dszMULTI, O_GROUP24, /* D1 shifts & rotates,1 (word) */
+ dszMULTI, O_GROUP25, /* D2 shifts & rotates,CL (byte) */
+ dszMULTI, O_GROUP26, /* D3 shifts & rotates,CL (word) */
+ dszAAM, O_Ib, /* D4 AAM */
+ dszAAD, O_Ib, /* D5 AAD */
+ dszRESERVED, O_DoDB, /* D6 */
+ dszXLAT, O_NoOperands, /* D7 XLAT */
+ dszMULTI, O_x87_ESC, /* D8 ESC */
+ dszMULTI, O_x87_ESC, /* D9 ESC */
+ dszMULTI, O_x87_ESC, /* DA ESC */
+ dszMULTI, O_x87_ESC, /* DB ESC */
+ dszMULTI, O_x87_ESC, /* DC ESC */
+ dszMULTI, O_x87_ESC, /* DD ESC */
+ dszMULTI, O_x87_ESC, /* DE ESC */
+ dszMULTI, O_x87_ESC, /* DF ESC */
+ dszLOOPNE,O_Rel8, /* E0 LOOPNE or LOOPNZ */
+ dszLOOPE, O_Rel8, /* E1 LOOPE or LOOPZ */
+ dszLOOP, O_Rel8, /* E2 LOOP */
+ dszJCXZ, O_Rel8, /* E3 JCXZ / JECXZ (386) */
+ dszIN, O_AL_Ubyte, /* E4 IN AL, I */
+ dszIN, O_AX_Ubyte, /* E5 IN AX, I */
+ dszOUT, O_Ubyte_AL, /* E6 OUT I, AL */
+ dszOUT, O_Ubyte_AX, /* E7 OUT I, AX */
+ dszCALL, O_Rel16, /* E8 CALL Rel16 */
+ dszJMP, O_Rel16, /* E9 JMP Rel16 */
+ dszJMP, O_FarPtr, /* EA JMP seg:off */
+ dszJMP, O_Rel8, /* EB JMP Rel8 */
+ dszIN, O_DoInAL, /* EC IN AL, DX */
+ dszIN, O_DoInAX, /* ED IN AX, DX */
+ dszOUT, O_DoOutAL, /* EE OUT DX, AL */
+ dszOUT, O_DoOutAX, /* EF OUT DX, AX */
+ dszLOCK, O_DoRep, /* F0 LOCK */
+ dszRESERVED, O_DoDB, /* F1 */
+ dszREPNE, O_DoRep, /* F2 REPNE or REPNZ */
+ dszREP, O_DoRep, /* F3 REP or REPE or REPZ */
+ dszHLT, O_NoOperands, /* F4 HLT */
+ dszCMC, O_NoOperands, /* F5 CMC */
+ dszMULTI, O_GROUP31, /* F6 TEST, NOT, NEG, MUL, IMUL, */
+ dszMULTI, O_GROUP32, /* F7 DIv, IDIv F6=Byte F7=Word */
+ dszCLC, O_NoOperands, /* F8 CLC */
+ dszSTC, O_NoOperands, /* F9 STC */
+ dszCLI, O_NoOperands, /* FA CLI */
+ dszSTI, O_NoOperands, /* FB STI */
+ dszCLD, O_NoOperands, /* FC CLD */
+ dszSTD, O_NoOperands, /* FD STD */
+ dszMULTI, O_GROUP4, /* FE INC, DEC mem/reg (byte) */
+ dszMULTI, O_GROUP5, /* FF INC, DEC, CALL, JMP, PUSH */
+
+ dszMULTI, O_GROUP6, /* 0 MULTI */
+ dszMULTI, O_GROUP7, /* 1 MULTI */
+ dszLAR, O_Reg_Modrm, /* 2 LAR */
+ dszLSL, O_Reg_Modrm, /* 3 LSL */
+ dszRESERVED, O_DoDB, /* 4 */
+ dszLOADALL, O_NoOperands, /* 5 LOADALL */
+ dszCLTS, O_NoOperands, /* 6 CLTS */
+ dszMOV, O_Modrm_CReg, /* 20 MOV */
+ dszMOV, O_Modrm_CReg, /* 21 MOV */
+ dszMOV, O_CReg_Modrm, /* 22 MOV */
+ dszMOV, O_CReg_Modrm, /* 23 MOV */
+ dszMOV, O_Modrm_CReg, /* 24 MOV */
+ dszRESERVED, O_DoDB, /* 25 */
+ dszMOV, O_CReg_Modrm, /* 26 MOV */
+
+ dszSETNL, O_bModrm, /* 7D SETNL */
+ dszRESERVED, O_DoDB, /* 7E */
+ dszRESERVED, O_DoDB, /* 7F */
+ dszJO, O_Rel16, /* 80 JO */
+ dszJNO, O_Rel16, /* 81 JNO */
+ dszJB, O_Rel16, /* 82 JB */
+ dszJNB, O_Rel16, /* 83 JNB */
+ dszJE, O_Rel16, /* 84 JE */
+ dszJNE, O_Rel16, /* 85 JNE */
+ dszJBE, O_Rel16, /* 86 JBE */
+ dszJNBE, O_Rel16, /* 87 JNBE */
+ dszJS, O_Rel16, /* 88 JS */
+ dszJNS, O_Rel16, /* 89 JNS */
+ dszJP, O_Rel16, /* 8A JP */
+ dszJNP, O_Rel16, /* 8B JNP */
+ dszJL, O_Rel16, /* 8C JL */
+ dszJNL, O_Rel16, /* 8D JNL */
+ dszJLE, O_Rel16, /* 8E JLE */
+ dszJNLE, O_Rel16, /* 8F JNLE */
+ dszSETO, O_bModrm, /* 90 SETO */
+ dszSETNO, O_bModrm, /* 91 SETNO */
+ dszSETB, O_bModrm, /* 92 SETB */
+ dszSETNB, O_bModrm, /* 93 SETNB */
+ dszSETE, O_bModrm, /* 94 SETE */
+ dszSETNE, O_bModrm, /* 95 SETNE */
+ dszSETBE, O_bModrm, /* 96 SETBE */
+ dszSETA, O_bModrm, /* 97 SETNBE */
+ dszSETS, O_bModrm, /* 98 SETS */
+ dszSETNS, O_bModrm, /* 99 SETNS */
+ dszSETP, O_bModrm, /* 9A SETP */
+ dszSETNP, O_bModrm, /* 9B SETNP */
+ dszSETL, O_bModrm, /* 9C SETL */
+ dszSETGE, O_bModrm, /* 9D SETGE */
+ dszSETLE, O_bModrm, /* 9E SETLE */
+ dszSETNLE,O_bModrm, /* 9F SETNLE */
+ dszPUSH, O_sReg2, /* A0 PUSH FS */
+ dszPOP, O_sReg2, /* A1 POP FS */
+ dszRESERVED, O_DoDB, /* A2 */
+ dszBT, O_Modrm_Reg, /* A3 BT */
+ dszSHLD, O_Modrm_Reg_Ib, /* A4 SHLD */
+ dszSHLD, O_Modrm_Reg_CL, /* A5 SHLD */
+ dszRESERVED, O_DoDB, /* A6 [02] */
+ dszRESERVED, O_DoDB, /* A7 [02] */
+ dszPUSH, O_sReg2, /* A8 PUSH GS */
+ dszPOP, O_sReg2, /* A9 POP GS */
+ dszRESERVED, O_DoDB, /* AA */
+ dszBTS, O_vModrm_Reg, /* AB BTS */
+ dszSHRD, O_Modrm_Reg_Ib, /* AC SHRD */
+ dszSHRD, O_Modrm_Reg_CL, /* AD SHRD */
+ dszRESERVED, O_DoDB, /* AE */
+ dszIMUL, O_Reg_Modrm, /* AF IMUL */
+ dszCMPXCHG,O_bModrm_Reg, /* B0 XBTS [02] */
+ dszCMPXCHG,O_Modrm_Reg, /* B1 IBTS [02] */
+ dszLSS, O_fReg_Modrm, /* B2 LSS */
+ dszBTR, O_Modrm_Reg, /* B3 BTR */
+ dszLFS, O_fReg_Modrm, /* B4 LFS */
+ dszLGS, O_fReg_Modrm, /* B5 LGS */
+ dszMOVZX, O_Reg_bModrm, /* B6 MOVZX */
+ dszMOVZX, O_Reg_wModrm, /* B7 MOVZX */
+ dszRESERVED, O_DoDB, /* B8 */
+ dszRESERVED, O_DoDB, /* B9 */
+ dszMULTI, O_GROUP8, /* BA MULTI */
+ dszBTC, O_Modrm_Reg, /* BB BTC */
+ dszBSF, O_Reg_Modrm, /* BC BSF */
+ dszBSR, O_Reg_Modrm, /* BD BSR */
+ dszMOVSX, O_Reg_bModrm, /* BE MOVSX */
+ dszMOVSX, O_Reg_wModrm, /* BF MOVSX */
+ dszXADD, O_bModrm_Reg, /* C0 XADD */
+ dszXADD, O_Modrm_Reg, /* C1 XADD */
+ dszRESERVED, O_DoDB, /* C2 */
+ dszRESERVED, O_DoDB, /* C3 */
+ dszRESERVED, O_DoDB, /* C4 */
+ dszRESERVED, O_DoDB, /* C5 */
+ dszRESERVED, O_DoDB, /* C6 */
+ dszRESERVED, O_DoDB, /* C7 */
+ dszBSWAP, O_oReg, /* C8 BSWAP */
+ dszBSWAP, O_oReg, /* C9 BSWAP */
+ dszBSWAP, O_oReg, /* CA BSWAP */
+ dszBSWAP, O_oReg, /* CB BSWAP */
+ dszBSWAP, O_oReg, /* CC BSWAP */
+ dszBSWAP, O_oReg, /* CD BSWAP */
+ dszBSWAP, O_oReg, /* CE BSWAP */
+ dszBSWAP, O_oReg /* CF BSWAP */
+};
+
+/* Auxilary lists of mnemonics for groups of two byte instructions: */
+/* All of the instructions within each of these groups are of the same */
+/* class, so only the mnemonic string is needed, the index into the */
+/* action table is implicit. */
+
+static CBC *group[][8] = {
+
+/* 00 */ {dszADD, dszOR, dszADC, dszSBB, /* group 1 */
+ dszAND, dszSUB, dszXOR, dszCMP},
+
+/* 01 */ {dszROL, dszROR, dszRCL, dszRCR, /* group 2 */
+ dszSHL, dszSHR, dszRESERVED, dszSAR},
+
+/* 02 */ {dszINC, dszDEC, dszRESERVED, dszRESERVED, /* group 4 */
+ dszRESERVED, dszRESERVED, dszRESERVED, dszRESERVED},
+
+/* 03 */ {dszSLDT, dszSTR, dszLLDT, dszLTR, /* group 6 */
+ dszVERR, dszVERW, dszRESERVED, dszRESERVED},
+
+/* 04 */ {dszRESERVED, dszRESERVED, dszRESERVED, dszRESERVED, /* group 8 */
+ dszBT, dszBTS, dszBTR, dszBTC}
+
+ };
+
+/* Auxilary orderd pairs for groups of two byte instructions structured */
+/* the same was as distbl above. */
+
+static Tdistbl groupt[][8] = {
+
+/* 00 00 x87-D8-1 */
+ { dszFADD, O_dModrm, /* D8-0 FADD */
+ dszFMUL, O_dModrm, /* D8-1 FMUL */
+ dszFCOM, O_dModrm, /* D8-2 FCOM */
+ dszFCOMP, O_dModrm, /* D8-3 FCOMP */
+ dszFSUB, O_dModrm, /* D8-4 FSUB */
+ dszFSUBR, O_dModrm, /* D8-5 FSUBR */
+ dszFDIV, O_dModrm, /* D8-6 FDIV */
+ dszFDIVR, O_dModrm }, /* D8-7 FDIVR */
+
+/* 01 x87-D8-2 */
+ { dszFADD, O_ST_iST, /* D8-0 FADD */
+ dszFMUL, O_ST_iST, /* D8-1 FMUL */
+ dszFCOM, O_iST, /* D8-2 FCOM */
+ dszFCOMP, O_iST, /* D8-3 FCOMP */
+ dszFSUB, O_ST_iST, /* D8-4 FSUB */
+ dszFSUBR, O_ST_iST, /* D8-5 FSUBR */
+ dszFDIV, O_ST_iST, /* D8-6 FDIV */
+ dszFDIVR, O_ST_iST }, /* D8-7 FDIVR */
+
+/* 02 01 x87-D9-1 */
+ { dszFLD, O_dModrm, /* D9-0 FLD */
+ dszRESERVED, O_DoDB, /* D9-1 */
+ dszFST, O_dModrm, /* D9-2 FST */
+ dszFSTP, O_dModrm, /* D9-3 FSTP */
+ dszFLDENV, O_Modrm, /* D9-4 FLDENV */
+ dszFLDCW, O_Modrm, /* D9-5 FLDCW */
+ dszFNSTENV, O_Modrm, /* D9-6 FNSTENV */
+ dszFNSTCW, O_Modrm }, /* D9-7 FNSTCW */
+
+/* 03 01 x87-D9-2 TTT=0,1,2,3 */
+ { dszFLD, O_iST, /* D9-0 FLD */
+ dszFXCH, O_iST, /* D9-1 FXCH */
+ dszFNOP, O_NoOperands, /* D9-2 FNOP */
+ dszFSTP, O_iST, /* D9-3 FSTP */
+ dszRESERVED, O_DoDB, /* D9-4 */
+ dszRESERVED, O_DoDB, /* D9-5 */
+ dszRESERVED, O_DoDB, /* D9-6 */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 04 02 x89-DA-1 */
+ { dszFIADD, O_dModrm, /* DA-0 FIADD */
+ dszFIMUL, O_dModrm, /* DA-1 FIMUL */
+ dszFICOM, O_dModrm, /* DA-2 FICOM */
+ dszFICOMP, O_dModrm, /* DA-3 FICOMP */
+ dszFISUB, O_dModrm, /* DA-4 FISUB */
+ dszFISUBR, O_dModrm, /* DA-5 FISUBR */
+ dszFIDIV, O_dModrm, /* DA-6 FIDIV */
+ dszFIDIVR, O_dModrm }, /* DA-7 FIDIVR */
+
+/* 05 x87-DA-2 */
+ { dszRESERVED, O_DoDB, /* DA-0 */
+ dszRESERVED, O_DoDB, /* DA-1 */
+ dszRESERVED, O_DoDB, /* DA-2 */
+ dszRESERVED, O_DoDB, /* DA-3 */
+ dszRESERVED, O_DoDB, /* DA-4 */
+ dszFUCOMPP, O_NoOperands, /* DA-5 */
+ dszRESERVED, O_DoDB, /* DA-6 */
+ dszRESERVED, O_DoDB }, /* DA-7 */
+
+/* 06 03 x87-DB-1 */
+ { dszFILD, O_dModrm, /* DB-0 FILD */
+ dszRESERVED, O_DoDB, /* DB-1 */
+ dszFIST, O_dModrm, /* DB-2 FIST */
+ dszFISTP, O_dModrm, /* DB-3 FISTP */
+ dszRESERVED, O_DoDB, /* DB-4 */
+ dszFLD, O_tModrm, /* DB-5 FLD */
+ dszRESERVED, O_DoDB, /* DB-6 */
+ dszFSTP, O_tModrm }, /* DB-7 FSTP */
+
+/* 07 x87-DB-2 ttt=4 */
+ { dszFENI, O_NoOperands, /* DB-0 FENI */
+ dszFDISI, O_NoOperands, /* DB-1 FDISI */
+ dszFNLEX, O_NoOperands, /* DB-2 FNLEX */
+ dszFNINIT, O_NoOperands, /* DB-3 FNINIT */
+ dszFSETPM, O_DoDB, /* DB-4 FSETPM */
+ dszRESERVED, O_DoDB, /* DB-5 */
+ dszRESERVED, O_DoDB, /* DB-6 */
+ dszRESERVED, O_DoDB }, /* DB-7 */
+
+/* 08 04 x87-DC-1 */
+ { dszFADD, O_qModrm, /* DC-0 FADD */
+ dszFMUL, O_qModrm, /* DC-1 FMUL */
+ dszFCOM, O_qModrm, /* DC-2 FCOM */
+ dszFCOMP, O_qModrm, /* DC-3 FCOMP */
+ dszFSUB, O_qModrm, /* DC-4 FSUB */
+ dszFSUBR, O_qModrm, /* DC-5 FSUBR */
+ dszFDIV, O_qModrm, /* DC-6 FDIV */
+ dszFDIVR, O_qModrm }, /* DC-7 FDIVR */
+
+/* 09 x87-DC-2 */
+ { dszFADD, O_iST_ST, /* DC-0 FADD */
+ dszFMUL, O_iST_ST, /* DC-1 FMUL */
+ dszFCOM, O_iST, /* DC-2 FCOM */
+ dszFCOMP, O_iST, /* DC-3 FCOMP */
+ dszFSUB, O_iST_ST, /* DC-4 FSUB */
+ dszFSUBR, O_iST_ST, /* DC-5 FSUBR */
+ dszFDIV, O_iST_ST, /* DC-6 FDIVR */
+ dszFDIVR, O_iST_ST }, /* DC-7 FDIV */
+
+/* 10 05 x87-DD-1 */
+ { dszFLD, O_qModrm, /* DD-0 FLD */
+ dszRESERVED, O_DoDB, /* DD-1 */
+ dszFST, O_qModrm, /* DD-2 FST */
+ dszFSTP, O_qModrm, /* DD-3 FSTP */
+ dszFRSTOR, O_Modrm, /* DD-4 FRSTOR */
+ dszRESERVED, O_DoDB, /* DD-5 */
+ dszFNSAVE, O_Modrm, /* DD-6 FNSAVE */
+ dszFNSTSW, O_Modrm }, /* DD-7 FNSTSW */
+
+/* 11 x87-DD-2 */
+ { dszFFREE, O_iST, /* DD-0 FFREE */
+ dszFXCH, O_iST, /* DD-1 FXCH */
+ dszFST, O_iST, /* DD-2 FST */
+ dszFSTP, O_iST, /* DD-3 FSTP */
+ dszFUCOM, O_iST, /* DD-4 FUCOM */
+ dszFUCOMP, O_iST, /* DD-5 FUCOMP */
+ dszRESERVED, O_DoDB, /* DD-6 */
+ dszRESERVED, O_DoDB }, /* DD-7 */
+
+/* 12 06 x87-DE-1 */
+ { dszFIADD, O_wModrm, /* DE-0 FIADD */
+ dszFIMUL, O_wModrm, /* DE-1 FIMUL */
+ dszFICOM, O_wModrm, /* DE-2 FICOM */
+ dszFICOMP, O_wModrm, /* DE-3 FICOMP */
+ dszFISUB, O_wModrm, /* DE-4 FISUB */
+ dszFISUBR, O_wModrm, /* DE-5 FISUBR */
+ dszFIDIV, O_wModrm, /* DE-6 FIDIV */
+ dszFIDIVR, O_wModrm }, /* DE-7 FIDIVR */
+
+/* 13 x87-DE-2 */
+ { dszFADDP, O_iST_ST, /* DE-0 FADDP */
+ dszFMULP, O_iST_ST, /* DE-1 FMULP */
+ dszFCOMP, O_iST, /* DE-2 FCOMP */
+ dszFCOMPP, O_NoOperands, /* DE-3 FCOMPP */
+ dszFSUBP, O_iST_ST, /* DE-4 FSUBP */
+ dszFSUBRP, O_iST_ST, /* DE-5 FSUBRP */
+ dszFDIVRP, O_iST_ST, /* DE-6 FDIVRP */
+ dszFDIVP, O_iST_ST}, /* DE-7 FDIVP */
+
+/* 14 07 x87-DF-1 */
+ { dszFILD, O_wModrm, /* DF-0 FILD */
+ dszRESERVED, O_DoDB, /* DF-1 */
+ dszFIST, O_wModrm, /* DF-2 FIST */
+ dszFISTP, O_wModrm, /* DF-3 FISTP */
+ dszFBLD, O_tModrm, /* DF-4 FBLD */
+ dszFILD, O_qModrm, /* DF-5 FILD */
+ dszFBSTP, O_tModrm, /* DF-6 FBSTP */
+ dszFISTP, O_qModrm }, /* DF-7 FISTP */
+
+/* 15 x87-DF-2 */
+ { dszFFREE, O_iST, /* DF-0 FFREE */
+ dszFXCH, O_iST, /* DF-1 FXCH */
+ dszFST, O_iST, /* DF-2 FST */
+ dszFSTP, O_iST, /* DF-3 FSTP */
+ dszFNSTSW, O_NoOperands, /* DF-4 FNSTSW */
+ dszRESERVED, O_DoDB, /* DF-5 */
+ dszRESERVED, O_DoDB, /* DF-6 */
+ dszRESERVED, O_DoDB }, /* DF-7 */
+
+/* 16 01 x87-D9 Mod=3 TTT=4 */
+ { dszFCHS, O_NoOperands, /* D9-0 FCHS */
+ dszFABS, O_NoOperands, /* D9-1 FABS */
+ dszRESERVED, O_DoDB, /* D9-2 */
+ dszRESERVED, O_DoDB, /* D9-3 */
+ dszFTST, O_NoOperands, /* D9-4 FTST */
+ dszFXAM, O_NoOperands, /* D9-5 FXAM */
+ dszRESERVED, O_DoDB, /* D9-6 */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 17 01 x87-D9 Mod=3 TTT=5 */
+ { dszFLD1, O_NoOperands, /* D9-0 FLD1 */
+ dszFLDL2T, O_NoOperands, /* D9-1 FLDL2T */
+ dszFLDL2E, O_NoOperands, /* D9-2 FLDL2E */
+ dszFLDPI, O_NoOperands, /* D9-3 FLDPI */
+ dszFLDLG2, O_NoOperands, /* D9-4 FLDLG2 */
+ dszFLDLN2, O_NoOperands, /* D9-5 FLDLN2 */
+ dszFLDZ, O_NoOperands, /* D9-6 FLDZ */
+ dszRESERVED, O_DoDB }, /* D9-7 */
+
+/* 18 01 x87-D9 Mod=3 TTT=6 */
+ { dszF2XM1, O_NoOperands, /* D9-0 F2XM1 */
+ dszFYL2X, O_NoOperands, /* D9-1 FYL2X */
+ dszFPTAN, O_NoOperands, /* D9-2 FPTAN */
+ dszFPATAN, O_NoOperands, /* D9-3 FPATAN */
+ dszFXTRACT, O_NoOperands, /* D9-4 FXTRACT */
+ dszFPREM1, O_NoOperands, /* D9-5 FPREM1 */
+ dszFDECSTP, O_NoOperands, /* D9-6 FDECSTP */
+ dszFINCSTP, O_NoOperands }, /* D9-7 FINCSTP */
+
+/* 19 01 x87-D9 Mod=3 TTT=7 */
+ { dszFPREM, O_NoOperands, /* D9-0 FPREM */
+ dszFYL2XP1, O_NoOperands, /* D9-1 FYL2XP1 */
+ dszFSQRT, O_NoOperands, /* D9-2 FSQRT */
+ dszFSINCOS, O_NoOperands, /* D9-3 FSINCOS */
+ dszFRNDINT, O_NoOperands, /* D9-4 FRNDINT */
+ dszFSCALE, O_NoOperands, /* D9-5 FSCALE */
+ dszFSIN, O_NoOperands, /* D9-6 FSIN */
+ dszFCOS, O_NoOperands }, /* D9-7 FCOS */
+
+/* 20 group 3 */
+ { dszTEST, O_bModrm_Ib, /* F6-0 TEST */
+ dszRESERVED, O_DoDB, /* F6-1 */
+ dszNOT, O_bModrm, /* F6-2 NOT */
+ dszNEG, O_bModrm, /* F6-3 NEG */
+ dszMUL, O_bModrm, /* F6-4 MUL */
+ dszIMUL, O_bModrm, /* F6-5 IMUL */
+ dszDIV, O_bModrm, /* F6-6 DIV */
+ dszIDIV, O_bModrm }, /* F6-7 IDIV */
+
+/* 21 group 3 */
+ { dszTEST, O_vModrm_Iv, /* F7-0 TEST */
+ dszRESERVED, O_DoDB, /* F7-1 */
+ dszNOT, O_vModrm, /* F7-2 NOT */
+ dszNEG, O_vModrm, /* F7-3 NEG */
+ dszMUL, O_vModrm, /* F7-4 MUL */
+ dszIMUL, O_vModrm, /* F7-5 IMUL */
+ dszDIV, O_vModrm, /* F7-6 DIV */
+ dszIDIV, O_vModrm }, /* F7-7 IDIV */
+
+/* 22 group 5 */
+ { dszINC, O_vModrm, /* FF-0 INC */
+ dszDEC, O_vModrm, /* FF-1 DEC */
+ dszCALL, O_vModrm, /* FF-2 CALL */
+ dszCALL, O_fModrm, /* FF-3 CALL */
+ dszJMP, O_vModrm, /* FF-4 JMP */
+ dszJMP, O_fModrm, /* FF-5 JMP */
+ dszPUSH, O_vModrm, /* FF-6 PUSH */
+ dszRESERVED, O_DoDB }, /* FF-7 */
+
+/* 23 group 7 */
+ { dszSGDT, O_Modrm, /* 0F-0 SGDT */
+ dszSIDT, O_Modrm, /* 0F-1 SIDT */
+ dszLGDT, O_Modrm, /* 0F-2 LGDT */
+ dszLIDT, O_Modrm, /* 0F-3 LIDT */
+ dszSMSW, O_wModrm, /* 0F-4 MSW */
+ dszRESERVED, O_DoDB, /* 0F-5 */
+ dszLMSW, O_wModrm, /* 0F-6 LMSW */
+ dszRESERVED, O_DoDB } /* 0F-7 */
+
+ };
+#pragma pack ()
+
+/*************************** end of d3.h ********************************/
diff --git a/private/windbg/em/p_ppc/em.rc b/private/windbg/em/p_ppc/em.rc
new file mode 100644
index 000000000..ff15b97de
--- /dev/null
+++ b/private/windbg/em/p_ppc/em.rc
@@ -0,0 +1 @@
+#include "..\em\em.rc"
diff --git a/private/windbg/em/p_ppc/emdp.c b/private/windbg/em/p_ppc/emdp.c
new file mode 100644
index 000000000..96568b2ed
--- /dev/null
+++ b/private/windbg/em/p_ppc/emdp.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp.c"
diff --git a/private/windbg/em/p_ppc/emdp2.c b/private/windbg/em/p_ppc/emdp2.c
new file mode 100644
index 000000000..5e0024775
--- /dev/null
+++ b/private/windbg/em/p_ppc/emdp2.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp2.c"
diff --git a/private/windbg/em/p_ppc/emdp3.c b/private/windbg/em/p_ppc/emdp3.c
new file mode 100644
index 000000000..57d71318d
--- /dev/null
+++ b/private/windbg/em/p_ppc/emdp3.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\emdp3.c"
diff --git a/private/windbg/em/p_ppc/emdpdev.c b/private/windbg/em/p_ppc/emdpdev.c
new file mode 100644
index 000000000..488dba82e
--- /dev/null
+++ b/private/windbg/em/p_ppc/emdpdev.c
@@ -0,0 +1,1135 @@
+/**** EMDPDEV.C - Debugger end Execution Model (PPC dependent code) **
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 15, 1990 by David W. Gray *
+ * Much modified by Farooq Butt (fmbutt@engage.sps.mot.com), Motorola *
+ * *
+ * Revision History: *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+#include <precomp.h>
+#pragma hdrstop
+#include "strings.h"
+
+
+CONTEXT ContextSave;
+
+#ifndef SMARTALIAS
+void PurgeCache ( void );
+#endif
+
+#define CEXM_MDL_native 0x20
+
+
+/*
+** This is the description of all registers and flags containned on the
+** ppc 601 machine
+*/
+
+extern RD Rgrd[];
+
+extern struct {
+ FD fd;
+ USHORT iShift;
+} Rgfd[];
+
+#define SIZEOF_STACK_OFFSET sizeof(LONG)
+
+BOOL NEAR PASCAL IsStackSetup(
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddrProc
+) {
+ Unreferenced(hpid);
+ Unreferenced(htid);
+ Unreferenced(lpaddrProc);
+ return TRUE;
+}
+
+
+XOSD
+GetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ This function will get return a specific type of address.
+
+Arguments:
+
+ hpid - Supplies the handle to the process to retrive the address from
+ htid - Supplies the handle to the thread to retrieve the address from
+ adr - Supplies the type of address to be retrieved
+ lpaddr - Returns the requested address
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+ XOSD xosd = xosdNone;
+ HEMI hemi = emiAddr(*lpaddr);
+ HMDI hmdi;
+ LPMDI lpmdi;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != NULL );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != NULL ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ _fmemset ( lpaddr, 0, sizeof ( ADDR ) );
+
+ switch ( adr ) {
+
+ case adrPC:
+ if ( lpthd && !(lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrData:
+ if ( lpthd && !(lpthd->drt & drtAllPresent )) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+
+#ifndef OSDEBUG4
+ case adrCurrent:
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ *lpaddr = lpthd->addrCurrent;
+ } else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ *lpaddr = lpprc->addrCurrent;
+
+ LLUnlock ( hprc );
+ }
+ break;
+#endif
+
+ case adrPC:
+ AddrInit(lpaddr, 0, 0,
+ (UOFFSET) lpthd->regs.Iar, lpthd->fFlat,
+ lpthd->fOff32, FALSE, lpthd->fReal)
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrData:
+ AddrInit(lpaddr, 0, 0, 0,
+ lpthd->fFlat, lpthd->fOff32, FALSE, lpthd->fReal);
+ SetEmi ( hpid, lpaddr );
+ break;
+
+ case adrTlsBase:
+ /*
+ * If -1 then we have not gotten a value from the DM yet.
+ */
+
+ assert(hemi != 0);
+
+ if (hemi == 0) {
+ return xosdBadAddress;
+ }
+
+ if (hemi != emiAddr(lpthd->addrTls)) {
+ hmdi = LLFind( LlmdiFromHprc( hprc ), 0, (LPBYTE) &hemi, emdiEMI);
+ assert(hmdi != 0);
+
+ if (hmdi == 0) {
+ return xosdBadAddress;
+ }
+
+ lpmdi = LLLock( hmdi );
+
+ SendRequestX( dmfQueryTlsBase, hpid, htid, sizeof(OFFSET),
+ &lpmdi->lpBaseOfDll);
+
+ lpthd->addrTls = *((LPADDR) LpDmMsg->rgb);
+ emiAddr(lpthd->addrTls) = hemi;
+ LLUnlock( hmdi );
+
+ }
+
+ *lpaddr = lpthd->addrTls;
+ emiAddr(*lpaddr) = 0;
+ break;
+
+ default:
+
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != NULL ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosd;
+} /* GetAddr() */
+
+
+XOSD
+SetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd = NULL;
+
+ assert ( lpaddr != NULL );
+ assert ( hpid != NULL );
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+
+ if ( hthd != NULL ) {
+ lpthd = LLLock ( hthd );
+ }
+
+ switch ( adr ) {
+ case adrPC:
+ if ( !( lpthd->drt & drtCntrlPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+
+ case adrData:
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+ break;
+ }
+
+ switch ( adr ) {
+
+#ifndef OSDEBUG4
+ case adrCurrent:
+
+ if ( lpaddr->emi == NULL ) {
+ SetEmi ( hpid, lpaddr );
+ }
+
+ // If a non-NULL HTHD was passed in, use addrCurrent from that
+ // thread. Otherwise use addrCurrent from the HPRC.
+
+ if ( lpthd ) {
+ lpthd->addrCurrent = *lpaddr;
+ }
+ else {
+ LPPRC lpprc = LLLock ( hprc );
+
+ lpprc->addrCurrent = *lpaddr;
+
+ LLUnlock ( hprc );
+ }
+ break;
+#endif
+
+ case adrPC:
+ lpthd->regs.Iar = GetAddrOff ( *lpaddr );
+ lpthd->drt |= drtCntrlDirty;
+ break;
+
+ case adrData:
+ case adrTlsBase:
+ default:
+ assert ( FALSE );
+ break;
+ }
+
+ if ( hthd != NULL ) {
+ LLUnlock ( hthd );
+ }
+
+ return xosdNone;
+} /* SetAddr() */
+
+
+XOSD
+SetAddrFromCSIP (
+ HTHD hthd
+ )
+{
+
+ ADDR addr = {0};
+ LPTHD lpthd;
+
+ assert ( hthd != NULL && hthd != hthdInvalid );
+
+ lpthd = LLLock ( hthd );
+
+ GetAddrSeg ( addr ) = 0;
+ GetAddrOff ( addr ) = (UOFFSET) lpthd->regs.Iar;
+ emiAddr ( addr ) = 0;
+ ADDR_IS_FLAT ( addr ) = TRUE;
+
+#ifndef OSDEBUG4
+ lpthd->addrCurrent = addr;
+#endif
+
+ LLUnlock ( hthd );
+
+ return xosdNone;
+}
+
+
+LPVOID
+DoGetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPVOID lpvRegValue
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to extract the value of a single register from
+ the debuggee.
+
+Arguments:
+
+ lpregs - Supplies pointer to the register set for the debuggee
+ ireg - Supplies the index of the register to be read
+ lpvRegValue - Supplies the buffer to place the register value in
+
+Return Value:
+
+ return-value - lpvRegValue + size of register on sucess and NULL on
+ failure
+--*/
+
+{
+ switch ( ireg ) {
+
+ case CV_PPC_GPR0:
+ case CV_PPC_GPR1:
+ case CV_PPC_GPR2:
+ case CV_PPC_GPR3:
+ case CV_PPC_GPR4:
+ case CV_PPC_GPR5:
+ case CV_PPC_GPR6:
+ case CV_PPC_GPR7:
+ case CV_PPC_GPR8:
+ case CV_PPC_GPR9:
+ case CV_PPC_GPR10:
+ case CV_PPC_GPR11:
+ case CV_PPC_GPR12:
+ case CV_PPC_GPR13:
+ case CV_PPC_GPR14:
+ case CV_PPC_GPR15:
+ case CV_PPC_GPR16:
+ case CV_PPC_GPR17:
+ case CV_PPC_GPR18:
+ case CV_PPC_GPR19:
+ case CV_PPC_GPR20:
+ case CV_PPC_GPR21:
+ case CV_PPC_GPR22:
+ case CV_PPC_GPR23:
+ case CV_PPC_GPR24:
+ case CV_PPC_GPR25:
+ case CV_PPC_GPR26:
+ case CV_PPC_GPR27:
+ case CV_PPC_GPR28:
+ case CV_PPC_GPR29:
+ case CV_PPC_GPR30:
+ case CV_PPC_GPR31:
+ *((LPL) lpvRegValue) = ((LONG *)(&lpregs->Gpr0))[ireg - CV_PPC_GPR0];
+ break;
+
+ case CV_PPC_FPSCR:
+ *((double *) lpvRegValue) = lpregs->Fpscr;
+ break;
+
+ case CV_PPC_PC:
+ *((LPL) lpvRegValue) = lpregs->Iar;
+ break;
+
+ case CV_PPC_MSR:
+ *((LPL) lpvRegValue) = lpregs->Msr;
+ break;
+
+ case CV_PPC_XER:
+ *((LPL) lpvRegValue) = lpregs->Xer;
+ break;
+
+ case CV_PPC_LR:
+ *((LPL) lpvRegValue) = lpregs->Lr;
+ break;
+
+ case CV_PPC_CTR:
+ *((LPL) lpvRegValue) = lpregs->Ctr;
+ break;
+
+ case CV_PPC_CR:
+ *((LPL) lpvRegValue) = lpregs->Cr;
+ break;
+
+
+ case CV_PPC_FPR0:
+ case CV_PPC_FPR1:
+ case CV_PPC_FPR2:
+ case CV_PPC_FPR3:
+ case CV_PPC_FPR4:
+ case CV_PPC_FPR5:
+ case CV_PPC_FPR6:
+ case CV_PPC_FPR7:
+ case CV_PPC_FPR8:
+ case CV_PPC_FPR9:
+ case CV_PPC_FPR10:
+ case CV_PPC_FPR11:
+ case CV_PPC_FPR12:
+ case CV_PPC_FPR13:
+ case CV_PPC_FPR14:
+ case CV_PPC_FPR15:
+ case CV_PPC_FPR16:
+ case CV_PPC_FPR17:
+ case CV_PPC_FPR18:
+ case CV_PPC_FPR19:
+ case CV_PPC_FPR20:
+ case CV_PPC_FPR21:
+ case CV_PPC_FPR22:
+ case CV_PPC_FPR23:
+ case CV_PPC_FPR24:
+ case CV_PPC_FPR25:
+ case CV_PPC_FPR26:
+ case CV_PPC_FPR27:
+ case CV_PPC_FPR28:
+ case CV_PPC_FPR29:
+ case CV_PPC_FPR30:
+ case CV_PPC_FPR31:
+ *((double *) lpvRegValue) = ((double *)(&lpregs->Fpr0))[ireg - CV_PPC_FPR0];
+ break;
+
+ default:
+ assert(FALSE);
+ }
+
+ (LPLONG) lpvRegValue += 1;
+ return lpvRegValue;
+}
+
+
+LPVOID
+DoSetReg(
+ LPCONTEXT lpregs,
+ DWORD ireg,
+ LPVOID lpvRegValue
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to set a specific register in a threads
+ context
+
+Arguments:
+
+ lpregs - Supplies pointer to register context for thread
+ ireg - Supplies the index of the register to be modified
+ lpvRegValue - Supplies the buffer containning the new data
+
+Return Value:
+
+ return-value - the pointer the the next location where a register
+ value could be.
+
+--*/
+
+{
+ switch ( ireg ) {
+
+ case CV_PPC_GPR0:
+ case CV_PPC_GPR1:
+ case CV_PPC_GPR2:
+ case CV_PPC_GPR3:
+ case CV_PPC_GPR4:
+ case CV_PPC_GPR5:
+ case CV_PPC_GPR6:
+ case CV_PPC_GPR7:
+ case CV_PPC_GPR8:
+ case CV_PPC_GPR9:
+ case CV_PPC_GPR10:
+ case CV_PPC_GPR11:
+ case CV_PPC_GPR12:
+ case CV_PPC_GPR13:
+ case CV_PPC_GPR14:
+ case CV_PPC_GPR15:
+ case CV_PPC_GPR16:
+ case CV_PPC_GPR17:
+ case CV_PPC_GPR18:
+ case CV_PPC_GPR19:
+ case CV_PPC_GPR20:
+ case CV_PPC_GPR21:
+ case CV_PPC_GPR22:
+ case CV_PPC_GPR23:
+ case CV_PPC_GPR24:
+ case CV_PPC_GPR25:
+ case CV_PPC_GPR26:
+ case CV_PPC_GPR27:
+ case CV_PPC_GPR28:
+ case CV_PPC_GPR29:
+ case CV_PPC_GPR30:
+ case CV_PPC_GPR31:
+ ((LONG *)(&lpregs->Gpr0))[ireg - CV_PPC_GPR0] = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_FPSCR:
+ lpregs->Fpscr = *((double *) lpvRegValue);
+ break;
+
+ case CV_PPC_LR:
+ lpregs->Lr = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_PC:
+ lpregs->Iar = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_XER:
+ lpregs->Xer = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_MSR:
+ lpregs->Msr = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_CTR:
+ lpregs->Ctr = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_CR:
+ lpregs->Cr = *((LPL) lpvRegValue);
+ break;
+
+ case CV_PPC_FPR0:
+ case CV_PPC_FPR1:
+ case CV_PPC_FPR2:
+ case CV_PPC_FPR3:
+ case CV_PPC_FPR4:
+ case CV_PPC_FPR5:
+ case CV_PPC_FPR6:
+ case CV_PPC_FPR7:
+ case CV_PPC_FPR8:
+ case CV_PPC_FPR9:
+ case CV_PPC_FPR10:
+ case CV_PPC_FPR11:
+ case CV_PPC_FPR12:
+ case CV_PPC_FPR13:
+ case CV_PPC_FPR14:
+ case CV_PPC_FPR15:
+ case CV_PPC_FPR16:
+ case CV_PPC_FPR17:
+ case CV_PPC_FPR18:
+ case CV_PPC_FPR19:
+ case CV_PPC_FPR20:
+ case CV_PPC_FPR21:
+ case CV_PPC_FPR22:
+ case CV_PPC_FPR23:
+ case CV_PPC_FPR24:
+ case CV_PPC_FPR25:
+ case CV_PPC_FPR26:
+ case CV_PPC_FPR27:
+ case CV_PPC_FPR28:
+ case CV_PPC_FPR29:
+ case CV_PPC_FPR30:
+ case CV_PPC_FPR31:
+ ((double *)(&lpregs->Fpr0))[ireg - CV_PPC_FPR0] = *((double *) lpvRegValue);
+ break;
+
+
+ default:
+ assert(FALSE);
+ return NULL;
+ }
+
+ (LPLONG) lpvRegValue += 1;
+ return lpvRegValue;
+}
+
+LPVOID
+DoSetFrameReg(
+ HPID hpid,
+ HTID htid,
+ LPTHD lpthd,
+ PKNONVOLATILE_CONTEXT_POINTERS contextPtrs,
+ DWORD ireg,
+ LPVOID lpvRegValue
+ )
+{
+
+ return DoSetReg(&lpthd->regs, ireg, lpvRegValue);
+}
+
+XOSD
+GetFlagValue (
+ HPID hpid,
+ HTID htid,
+ DWORD iFlag,
+ LPVOID lpvRegValue
+ )
+{
+ HPRC hprc;
+ HTHD hthd;
+ LPTHD lpthd;
+ LPCONTEXT lpregs;
+ DWORD value;
+
+ hprc = ValidHprcFromHpid(hpid);
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+ hthd = HthdFromHtid(hprc, htid);
+
+ assert ( hthd != NULL );
+ lpthd = LLLock ( hthd );
+
+ lpregs = &lpthd->regs;
+
+ if ( !(lpthd->drt & drtAllPresent) ) {
+ UpdateRegisters ( hprc, hthd );
+ }
+
+#ifdef OSDEBUG4
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.dwId, &value ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidParameter;
+ }
+
+ value = (value >> Rgfd[iFlag].iShift) & ((1 << Rgfd[iFlag].fd.dwcbits) - 1);
+ *( (LPLONG) lpvRegValue) = value;
+#else
+ if (DoGetReg ( lpregs, Rgfd[iFlag].fd.hReg, &value ) == NULL) {
+ LLUnlock( hthd );
+ return xosdInvalidRegister;
+ }
+
+ value = (value >> Rgfd[iFlag].iShift) & ((1 << Rgfd[iFlag].fd.cbits) - 1);
+ *( (LPLONG) lpvRegValue) = value;
+#endif
+
+ LLUnlock(hthd);
+ return xosdNone;
+}
+
+#ifndef OSDEBUG4
+
+XOSD
+StackWalkSetup(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to setup the StackWalk Structure.
+ This routine will defer the processing to the dm
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk
+ hthd - Supplies handle to thread to stack walk
+ lpstkframe - Supplies pointer the stack walk structure
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+ ULONG ul;
+
+
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == NULL) {
+#ifdef OSDEBUG4
+ return xosdBadThread;
+#else
+ return xosdInvalidThread;
+#endif
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (lpthd->drt & (drtCntrlDirty|drtAllDirty)) {
+ SendRequestX(dmfWriteReg, hpid, htid, sizeof(CONTEXT), &lpthd->regs);
+ lpthd->drt &= ~(drtCntrlDirty|drtAllDirty);
+ }
+
+ UpdateRegisters( hprc, hthd );
+ GetRegValue( hpid, htid, CV_PPC_GPR1, &ul);
+
+ ContextSave = lpthd->regs;
+
+ if (StackWalk( IMAGE_FILE_MACHINE_POWERPC,
+ hpid,
+ htid,
+ lpstkframe,
+ &ContextSave,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ NULL,
+ NULL
+ )) {
+
+ LLUnlock( hthd );
+ return xosdNone;
+
+ }
+
+ LLUnlock( hthd );
+
+ return xosdEndOfStack;
+} /* StackWalkSetup() */
+
+
+XOSD
+StackWalkNext(
+ HPID hpid,
+ HTID htid,
+ LPSTACKFRAME lpstkframe
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to move up a level in the call stack.
+ We defer down to the DM to do this.
+
+Arguments:
+
+ hpid - Supplies process handle to stack walk
+ htid - Supplies thread handle to stack walk
+ lpstkframe - Supplies pointer to stack walk data
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ LPTHD lpthd;
+ HTHD hthd;
+ HPRC hprc = ValidHprcFromHpid(hpid);
+
+
+ if (!hprc) {
+#ifdef OSDEBUG4
+ return xosdBadProcess;
+#else
+ return xosdInvalidProc;
+#endif
+ }
+
+ hthd = HthdFromHtid(hprc, htid);
+ if (hthd == NULL) {
+#ifdef OSDEBUG4
+ return xosdBadThread;
+#else
+ return xosdInvalidThread;
+#endif
+ }
+
+ lpthd = LLLock( hthd );
+
+ assert(lpthd != NULL);
+
+ if (StackWalk( IMAGE_FILE_MACHINE_POWERPC,
+ hpid,
+ htid,
+ lpstkframe,
+ &ContextSave,
+ SwReadMemory,
+ SwFunctionTableAccess,
+ NULL,
+ NULL
+ )) {
+
+ LLUnlock( hthd );
+ return xosdNone;
+
+ }
+
+ LLUnlock( hthd );
+
+ return xosdEndOfStack;
+} /* StackWalkNext() */
+
+
+XOSD
+SetFrame(
+ HPID hpid,
+ HTID htid,
+ PFRAME pframe
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to fill in the FRAME structure.
+
+Arguments:
+
+ hprc - Supplies handle to process to stack walk in
+ hthd - Supplies handle to thread to stack walk in
+ pframe - Supplies pointer to the frame structure to fill in
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ ULONG ul;
+
+ GetRegValue( hpid, htid, CV_PPC_GPR1, &ul);
+
+ FrameFlat ( *pframe ) = TRUE;
+ FrameOff32 ( *pframe ) = TRUE;
+ FrameReal (*pframe ) = FALSE;
+
+ SetFrameBPOff( *pframe, ul );
+ SetFrameBPSeg( *pframe, 0);
+
+ pframe->SS = 0;
+ pframe->DS = 0;
+ pframe->PID = hpid;
+ pframe->TID = htid;
+
+ return xosdNone;
+} /* SetFrame() */
+
+#endif // !OSDEBUG4
+
+
+PIMAGE_RUNTIME_FUNCTION_ENTRY
+LookupFunctionEntry (
+ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable,
+ DWORD NumberOfFunctions,
+ DWORD ControlPc
+ )
+
+/*++
+
+Routine Description:
+
+ This function searches the currently active function tables for an entry
+ that corresponds to the specified PC value.
+
+Arguments:
+
+ ControlPc - Supplies the address of an instruction within the specified
+ function.
+
+Return Value:
+
+ If there is no entry in the function table for the specified PC, then
+ NULL is returned. Otherwise, the address of the function table entry
+ that corresponds to the specified PC is returned.
+
+--*/
+
+{
+
+ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
+ LONG High;
+ LONG Low;
+ LONG Middle;
+
+ //
+ // Initialize search indicies.
+ //
+
+ Low = 0;
+ High = NumberOfFunctions - 1;
+
+ //
+ // Perform binary search on the function table for a function table
+ // entry that subsumes the specified PC.
+ //
+
+ while (High >= Low) {
+
+ //
+ // Compute next probe index and test entry. If the specified PC
+ // is greater than of equal to the beginning address and less
+ // than the ending address of the function table entry, then
+ // return the address of the function table entry. Otherwise,
+ // continue the search.
+ //
+
+ Middle = (Low + High) >> 1;
+ FunctionEntry = &FunctionTable[Middle];
+ if (ControlPc < FunctionEntry->BeginAddress) {
+ High = Middle - 1;
+
+ } else if (ControlPc >= FunctionEntry->EndAddress) {
+ Low = Middle + 1;
+
+ } else {
+
+#if 0 // This requires some work...
+ //
+ // The capability exists for more than one function entry
+ // to map to the same function. This permits a function to
+ // have (within reason) discontiguous code segment(s). If
+ // EndOfPrologue is out of range, it is re-interpreted
+ // as a pointer to the primary function table entry for
+ // that function. The out of range test takes into account
+ // the redundant encoding of millicode and glue code.
+ //
+
+ if (((FunctionEntry->EndOfPrologue < FunctionEntry->StartingAddress) ||
+ (FunctionEntry->EndOfPrologue > FunctionEntry->EndingAddress)) &&
+ (FunctionEntry->EndOfPrologue & 3) == 0) {
+ FunctionEntry = (PRUNTIME_FUNCTION)FunctionEntry->EndOfPrologue;
+ }
+#endif
+
+ return FunctionEntry;
+ }
+ }
+
+ //
+ // A function table entry for the specified PC was not found.
+ //
+
+ return NULL;
+}
+
+
+LPVOID
+SwFunctionTableAccess(
+ HPID hpid,
+ DWORD AddrBase
+ )
+{
+ HLLI hlli = 0;
+ HMDI hmdi = 0;
+ LPMDI lpmdi = 0;
+ PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
+
+
+ hmdi = SwGetMdi( hpid, AddrBase );
+ if (!hmdi) {
+ return NULL;
+ }
+
+ lpmdi = LLLock( hmdi );
+ if (lpmdi) {
+
+ rf = LookupFunctionEntry( lpmdi->lpDebug->lpRtf,
+ lpmdi->lpDebug->cRtf,
+ AddrBase
+ );
+
+ LLUnlock( hmdi );
+ return (LPVOID)rf;
+ }
+ return NULL;
+}
+
+BOOL
+SwReadMemory(
+ HPID hpid,
+ LPCVOID lpBaseAddress,
+ LPVOID lpBuffer,
+ DWORD nSize,
+ LPDWORD lpNumberOfBytesRead
+ )
+{
+ ADDR addr;
+ DWORD cb;
+ XOSD xosd;
+
+ addr.addr.off = (OFFSET)lpBaseAddress;
+ addr.addr.seg = 0;
+ addr.emi = 0;
+ addr.mode.fFlat = TRUE;
+ addr.mode.fOff32 = FALSE;
+ addr.mode.fIsLI = FALSE;
+ addr.mode.fReal = FALSE;
+
+ xosd = ReadBuffer( hpid, NULL, &addr, nSize, lpBuffer, &cb );
+ if (xosd != xosdNone) {
+ return FALSE;
+ }
+
+ if (lpNumberOfBytesRead) {
+ *lpNumberOfBytesRead = cb;
+ }
+
+ return TRUE;
+}
+
+
+XOSD
+SetPath(
+ HPID hpid,
+ HTID htid,
+ BOOL Set,
+ LSZ Path
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path in the DM
+
+Arguments:
+
+ hpid - process
+ htid - thread
+ Set - set flag
+ Path - Path to search, PATH if null
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ char Buffer[ MAX_PATH ];
+ SETPTH *SetPth = (SETPTH *)&Buffer;
+
+ if ( Set ) {
+
+ SetPth->Set = TRUE;
+ if ( Path ) {
+ strcpy(SetPth->Path, Path );
+ } else {
+ SetPth->Path[0] = '\0';
+ }
+ } else {
+ SetPth->Set = FALSE;
+ SetPth->Path[0] = '\0';
+ }
+
+ return SendRequestX( dmfSetPath, hpid, htid, sizeof(SETPTH) + strlen(SetPth->Path), SetPth );
+}
+
+
+
+
+XOSD
+GetFunctionInfo(
+ HPID hpid,
+ PADDR Addr,
+ PFUNCTION_INFO FunctionInfo
+ )
+/*++
+
+Routine Description:
+
+ Gets function information for a particular address.
+
+Arguments:
+
+ hpid - process
+ Addr - Address
+ FunctionInfo - Function information
+
+
+Return Value:
+
+ xosd error code
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ PIMAGE_RUNTIME_FUNCTION_ENTRY pfe;
+
+
+ pfe = SwFunctionTableAccess( hpid, GetAddrOff( *Addr ) );
+
+ if ( pfe ) {
+
+ AddrInit( &FunctionInfo->AddrStart, 0,0, pfe->BeginAddress,
+ TRUE, TRUE, FALSE, FALSE );
+ AddrInit( &FunctionInfo->AddrEnd, 0,0, pfe->EndAddress,
+ TRUE, TRUE, FALSE, FALSE );
+ AddrInit( &FunctionInfo->AddrPrologEnd, 0,0, pfe->PrologEndAddress,
+ TRUE, TRUE, FALSE, FALSE );
+
+ } else {
+
+ xosd = xosdUnknown;
+ }
+
+ return xosd;
+}
+
diff --git a/private/windbg/em/p_ppc/emppc.def b/private/windbg/em/p_ppc/emppc.def
new file mode 100644
index 000000000..0c1e2f090
--- /dev/null
+++ b/private/windbg/em/p_ppc/emppc.def
@@ -0,0 +1,4 @@
+LIBRARY emppc initinstance
+EXPORTS
+ DBGVersionCheck PRIVATE
+ EMFunc PRIVATE
diff --git a/private/windbg/em/p_ppc/flags.h b/private/windbg/em/p_ppc/flags.h
new file mode 100644
index 000000000..d11bc8efb
--- /dev/null
+++ b/private/windbg/em/p_ppc/flags.h
@@ -0,0 +1,8 @@
+ { szFlagCR0, ftRegular|ftRegularExt, 4, CV_PPC_CR, 28 },
+ { szFlagCR1, ftRegular|ftRegularExt, 4, CV_PPC_CR, 24},
+ { szFlagCR2, ftRegular|ftRegularExt, 4, CV_PPC_CR, 20 },
+ { szFlagCR3, ftRegular|ftRegularExt, 4, CV_PPC_CR, 16 },
+ { szFlagCR4, ftRegular|ftRegularExt, 4, CV_PPC_CR, 12},
+ { szFlagCR5, ftRegular|ftRegularExt, 4, CV_PPC_CR, 8},
+ { szFlagCR6, ftRegular|ftRegularExt, 4, CV_PPC_CR, 4},
+ { szFlagCR7, ftRegular|ftRegularExt, 4, CV_PPC_CR, 0},
diff --git a/private/windbg/em/p_ppc/makefile b/private/windbg/em/p_ppc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/em/p_ppc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/em/p_ppc/makefile.inc b/private/windbg/em/p_ppc/makefile.inc
new file mode 100644
index 000000000..8b520faa0
--- /dev/null
+++ b/private/windbg/em/p_ppc/makefile.inc
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
diff --git a/private/windbg/em/p_ppc/ntdis.h b/private/windbg/em/p_ppc/ntdis.h
new file mode 100644
index 000000000..c6db41883
--- /dev/null
+++ b/private/windbg/em/p_ppc/ntdis.h
@@ -0,0 +1,277 @@
+#define opnNone 0x00000000
+#define opnPreRt 0x00000001 // contains trailing comma
+#define opnRd 0x00000002
+#define opnFd 0x00000004
+#define opnRdComma 0x00000008
+#define opnRdOptRs 0x00000010 // [Rd,] Rs
+#define opnRs 0x00000020
+#define opnFs 0x00000040
+#define opnRsComma 0x00000080
+#define opnRt 0x00000100
+#define opnFt 0x00000200
+#define opnRtComma 0x00000400
+#define opnPostRs 0x00000800
+#define opnImm16 0x00001000
+#define opnRel16 0x00002000
+#define opnImm10 0x00004000
+#define opnImm20 0x00008000
+#define opnImm26 0x00010000
+#define opnAddr26 0x00020000
+#define opnUImm16 0x01000000
+#define opnRxd 0x02000000
+#define opnPreRxt 0x04000000
+
+#define opnByteIndex 0x00040000
+#define opnWordIndex 0x00080000
+#define opnDwordIndex 0x00100000
+#define opnLeftIndex 0x00200000
+#define opnRightIndex 0x00400000
+#define opnAnyIndex 0x007c0000
+
+#define opnShift 0x00800000
+#define opnCache 0x10000000
+
+#define opnR4000 0x20000000
+
+#define opnRdRsRt opnRd + opnRdComma + opnRs + opnRsComma + opnRt
+#define opnRtRsImm16 opnPreRt + opnRs + opnRsComma + opnImm16
+#define opnRtRsUImm16 opnPreRt + opnRs + opnRsComma + opnUImm16
+#define opnRsRtRel16 opnRs + opnRsComma + opnRt + opnRtComma + opnRel16
+#define opnRsRel16 opnRs + opnRsComma + opnRel16
+#define opnRtRd opnPreRt + opnRd
+#define opnRtFd opnPreRt + opnFd
+#define opnRtRxd opnPreRt + opnRxd
+#define opnRsRt opnRs + opnRsComma + opnRt
+#define opnRsRtImm10 opnRs + opnRsComma + opnRt + opnRtComma + opnImm10
+#define opnRdRs opnRd + opnRdComma + opnRs
+#define opnRtByteIndex opnPreRt + opnByteIndex
+#define opnRtWordIndex opnPreRt + opnWordIndex
+#define opnRtDwordIndex opnPreRt + opnDwordIndex
+#define opnRxtDwordIndex opnPreRxt + opnDwordIndex
+#define opnRtLeftIndex opnPreRt + opnLeftIndex
+#define opnRtRightIndex opnPreRt + opnRightIndex
+#define opnRtUImm16 opnPreRt + opnUImm16
+#define opnRdRtShift opnRd + opnRdComma + opnRt + opnRtComma + opnShift
+#define opnRdRtRs opnRd + opnRdComma + opnRt + opnRtComma + opnPostRs
+#define opnFdFs opnFd + opnRdComma + opnFs
+#define opnFdFsFt opnFd + opnRdComma + opnFs + opnRsComma + opnFt
+#define opnFsFt opnFs + opnRsComma + opnFt
+#define opnRtFs opnPreRt + opnFs
+#define opnFtDwordIndex opnFt + opnRtComma + opnDwordIndex
+#define opnRsImm16 opnRs + opnRsComma + opnImm16
+#define opnCacheRightIndex opnCache + opnRightIndex
+
+typedef union instr {
+ ULONG instruction;
+ struct _jump_instr {
+ ULONG Target : 26;
+ ULONG Opcode : 6;
+ } jump_instr;
+ struct _break_instr {
+ ULONG Opcode : 6;
+ ULONG Value : 20;
+ ULONG Special : 6;
+ } break_instr;
+ struct _trap_instr {
+ ULONG Opcode : 6;
+ ULONG Value : 10;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Special : 6;
+ } trap_instr;
+ struct _immed_instr {
+ ULONG Value : 16;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Opcode : 6;
+ } immed_instr;
+ struct _special_instr {
+ ULONG Funct : 6;
+ ULONG RE : 5;
+ ULONG RD : 5;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Opcode : 6;
+ } special_instr;
+ struct _float_instr {
+ ULONG Funct : 6;
+ ULONG FD : 5;
+ ULONG FS : 5;
+ ULONG FT : 5;
+ ULONG Format : 5;
+ ULONG Opcode : 6;
+ } float_instr;
+ } INSTR;
+
+extern LPCH pszReg[];
+
+extern UCHAR pszAbs_s[];
+extern UCHAR pszAdd[];
+extern UCHAR pszAddi[];
+extern UCHAR pszAddiu[];
+extern UCHAR pszAddu[];
+extern UCHAR pszAdd_s[];
+extern UCHAR pszAnd[];
+extern UCHAR pszAndi[];
+extern UCHAR pszBc0f[];
+extern UCHAR pszBc0fl[];
+extern UCHAR pszBc0t[];
+extern UCHAR pszBc0tl[];
+extern UCHAR pszBc1f[];
+extern UCHAR pszBc1fl[];
+extern UCHAR pszBc1t[];
+extern UCHAR pszBc1tl[];
+extern UCHAR pszBc2f[];
+extern UCHAR pszBc2fl[];
+extern UCHAR pszBc2t[];
+extern UCHAR pszBc2tl[];
+extern UCHAR pszBc3f[];
+extern UCHAR pszBc3fl[];
+extern UCHAR pszBc3t[];
+extern UCHAR pszBc3tl[];
+extern UCHAR pszBgez[];
+extern UCHAR pszBgezal[];
+extern UCHAR pszBgezall[];
+extern UCHAR pszBgezl[];
+extern UCHAR pszBgtz[];
+extern UCHAR pszBgtzl[];
+extern UCHAR pszBeq[];
+extern UCHAR pszBeql[];
+extern UCHAR pszBlez[];
+extern UCHAR pszBlezl[];
+extern UCHAR pszBltz[];
+extern UCHAR pszBltzal[];
+extern UCHAR pszBltzall[];
+extern UCHAR pszBltzl[];
+extern UCHAR pszBne[];
+extern UCHAR pszBnel[];
+extern UCHAR pszBreak[];
+extern UCHAR pszC_eq_s[];
+extern UCHAR pszC_f_s[];
+extern UCHAR pszC_le_s[];
+extern UCHAR pszC_lt_s[];
+extern UCHAR pszC_nge_s[];
+extern UCHAR pszC_ngl_s[];
+extern UCHAR pszC_ngle_s[];
+extern UCHAR pszC_ngt_s[];
+extern UCHAR pszC_ole_s[];
+extern UCHAR pszC_olt_s[];
+extern UCHAR pszC_seq_s[];
+extern UCHAR pszC_sf_s[];
+extern UCHAR pszC_ueq_s[];
+extern UCHAR pszC_ule_s[];
+extern UCHAR pszC_ult_s[];
+extern UCHAR pszC_un_s[];
+extern UCHAR pszCache[];
+extern UCHAR pszCeil_w_s[];
+extern UCHAR pszCfc0[];
+extern UCHAR pszCfc1[];
+extern UCHAR pszCfc2[];
+extern UCHAR pszCfc3[];
+extern UCHAR pszCtc0[];
+extern UCHAR pszCtc1[];
+extern UCHAR pszCtc2[];
+extern UCHAR pszCtc3[];
+extern UCHAR pszCop0[];
+extern UCHAR pszCop1[];
+extern UCHAR pszCop2[];
+extern UCHAR pszCop3[];
+extern UCHAR pszCvt_d_s[];
+extern UCHAR pszCvt_e_s[];
+extern UCHAR pszCvt_q_s[];
+extern UCHAR pszCvt_s_s[];
+extern UCHAR pszCvt_w_s[];
+extern UCHAR pszDiv[];
+extern UCHAR pszDiv_s[];
+extern UCHAR pszDivu[];
+extern UCHAR pszEret[];
+extern UCHAR pszFloor_w_s[];
+extern UCHAR pszJ[];
+extern UCHAR pszJr[];
+extern UCHAR pszJal[];
+extern UCHAR pszJalr[];
+extern UCHAR pszLb[];
+extern UCHAR pszLbu[];
+extern UCHAR pszLdc1[];
+extern UCHAR pszLdc2[];
+extern UCHAR pszLdc3[];
+extern UCHAR pszLh[];
+extern UCHAR pszLhu[];
+extern UCHAR pszLui[];
+extern UCHAR pszLwc0[];
+extern UCHAR pszLwc1[];
+extern UCHAR pszLwc2[];
+extern UCHAR pszLwc3[];
+extern UCHAR pszLw[];
+extern UCHAR pszLwl[];
+extern UCHAR pszLwr[];
+extern UCHAR pszMfc0[];
+extern UCHAR pszMfc1[];
+extern UCHAR pszMfc2[];
+extern UCHAR pszMfc3[];
+extern UCHAR pszMfhi[];
+extern UCHAR pszMflo[];
+extern UCHAR pszMov_s[];
+extern UCHAR pszMtc0[];
+extern UCHAR pszMtc1[];
+extern UCHAR pszMtc2[];
+extern UCHAR pszMtc3[];
+extern UCHAR pszMthi[];
+extern UCHAR pszMtlo[];
+extern UCHAR pszMul_s[];
+extern UCHAR pszMult[];
+extern UCHAR pszMultu[];
+extern UCHAR pszNeg_s[];
+extern UCHAR pszNop[];
+extern UCHAR pszNor[];
+extern UCHAR pszOr[];
+extern UCHAR pszOri[];
+extern UCHAR pszRfe[];
+extern UCHAR pszRound_w_s[];
+extern UCHAR pszSb[];
+extern UCHAR pszSdc1[];
+extern UCHAR pszSdc2[];
+extern UCHAR pszSdc3[];
+extern UCHAR pszSh[];
+extern UCHAR pszSll[];
+extern UCHAR pszSllv[];
+extern UCHAR pszSlt[];
+extern UCHAR pszSlti[];
+extern UCHAR pszSltiu[];
+extern UCHAR pszSltu[];
+extern UCHAR pszSqrt_s[];
+extern UCHAR pszSra[];
+extern UCHAR pszSrl[];
+extern UCHAR pszSrav[];
+extern UCHAR pszSrlv[];
+extern UCHAR pszSub[];
+extern UCHAR pszSub_s[];
+extern UCHAR pszSubu[];
+extern UCHAR pszSw[];
+extern UCHAR pszSwc0[];
+extern UCHAR pszSwc1[];
+extern UCHAR pszSwc2[];
+extern UCHAR pszSwc3[];
+extern UCHAR pszSwl[];
+extern UCHAR pszSwr[];
+extern UCHAR pszSync[];
+extern UCHAR pszSyscall[];
+extern UCHAR pszTeq[];
+extern UCHAR pszTeqi[];
+extern UCHAR pszTge[];
+extern UCHAR pszTgei[];
+extern UCHAR pszTgeiu[];
+extern UCHAR pszTgeu[];
+extern UCHAR pszTlbr[];
+extern UCHAR pszTlbwi[];
+extern UCHAR pszTlbwr[];
+extern UCHAR pszTlbp[];
+extern UCHAR pszTlt[];
+extern UCHAR pszTlti[];
+extern UCHAR pszTltiu[];
+extern UCHAR pszTltu[];
+extern UCHAR pszTne[];
+extern UCHAR pszTnei[];
+extern UCHAR pszTrunc_w_s[];
+extern UCHAR pszXor[];
+extern UCHAR pszXori[];
diff --git a/private/windbg/em/p_ppc/ntdisppc.h b/private/windbg/em/p_ppc/ntdisppc.h
new file mode 100644
index 000000000..ce24a75ff
--- /dev/null
+++ b/private/windbg/em/p_ppc/ntdisppc.h
@@ -0,0 +1,398 @@
+/* #ifdef _MOTO_EXTENSIONS */
+/* PowerPC instruction set from IBM PowerPC User Instruction Set Architecture
+Book 1, Version 1.04 May 4,1993 */
+
+/* These are the instruction format types. Keep them in the same order as the
+ eopFormat array below. */
+enum { I=0, B, SC, Dform, DSform, X, XL, XFX, XFL, XS, XO, A, M, MD, MDS };
+
+/* The values in this array are used to isolate the extended opcodes.
+ The first is the mask, the second is the amount to shift.
+ Keep them in the same order as the enum'ed instruction format types above. */
+
+static int eopFormat[15][2] = {
+ 0, 1, /* I */
+ 0, 1, /* B */
+ 0x1, 1, /* SC */
+ 0, 1, /* Dform */
+ 0x3, 0, /* DSform */
+ 0x3ff, 1, /* X */
+ 0x3ff, 1, /* XL */
+ 0x3ff, 1, /* XFX */
+ 0x3ff, 1, /* XFL */
+ 0x1ff, 2, /* XS */
+ 0x1ff, 1, /* XO */
+ 0x1f, 1, /* A */
+ 0, 1, /* M */
+ 0x7, 2, /* MD */
+ 0xf, 1 /* MDS */
+ };
+
+/* Information about each instruction */
+
+typedef struct ppc_instruction {
+ char *mnemonic; /* instruction mnemonic */
+ char *mne_ext; /* instruction mnemonic extension */
+ int ext_opcode; /* extended opcode */
+ char operand_fmt[6]; /* operand formats */
+} INSTRUCTION;
+
+/* These are the operand formats. */
+enum { BA=1,
+ BB,
+ BD,
+ BF,
+ BFA,
+ BI,
+ BO,
+ BT,
+ D,
+ DS,
+ FLM,
+ FRA,
+ FRB,
+ FRC,
+ FRS,
+ FRT,
+ FXM,
+ L,
+ LI,
+ PPC_MB,
+ ME,
+ MBE64,
+ NB,
+ RA,
+ RB,
+ RS,
+ PPC_RT,
+ SH,
+ SH64,
+ SI,
+ SPR,
+ SR,
+ TBR,
+ TO,
+ U,
+ UI
+ };
+
+/* PowerPC instruction set as defined in
+ IBM PowerPC Architecture Books, Version 1.04 May 4,1993
+
+ Many of the PowerPC instructions map to the same primary opcode
+ and are unique only in the extended opcode. There is a table for
+ each group of extended opcodes (i.e., those with the same primary
+ opcode) and a table of instructions with unique primary opcodes.
+ The unique primary opcode can be used as a direct index into the
+ primary opcode table. A binary search is performed on the extended
+ opcode tables. The size and location of the extended opcode bit field
+ varies according to the instruction, so all format variations must be
+ checked when searching for extended opcodes. All the unique format
+ variations for a given primary opcode are kept in an associated table. All format variations need not be present in the format table, just the
+ ones so that all unique extended opcode fields are represented.
+
+ Note that the primary and extended opcode tables use the same
+ structure, so that the code that uses the information in the table
+ need not know which table it is from.
+
+ mnemonic options eop operand formats opcode */
+
+struct ppc_instruction pop_insn [] = {
+ {"Illegal", 0, 0, {0} }, /* 0 */
+ {"Illegal", 0, 0, {0} }, /* 1 */
+ {"tdi", 0, -1, {TO,RA,SI,0} }, /* 2 */
+ {"twi", 0, -1, {TO,RA,SI,0} }, /* 3 */
+ {"Illegal", 0, 0, {0} }, /* 4 */
+ {"Illegal", 0, 0, {0} }, /* 5 */
+ {"Illegal", 0, 0, {0} }, /* 6 */
+ {"mulli", 0, -1, {PPC_RT,RA,SI,0} }, /* 7 */
+ {"subfic", 0, -1, {PPC_RT,RA,SI,0} }, /* 8 */
+ {"Illegal", 0, 0, {0} }, /* 9 */
+ {"cmpli", 0, -1, {BF,L,RA,UI,0} }, /* 10 */
+ {"cmpi", 0, -1, {BF,L,RA,SI,0} }, /* 11 */
+ {"addic", 0, -1, {PPC_RT,RA,SI,0} }, /* 12 */
+ {"addic.", 0, -1, {PPC_RT,RA,SI,0} }, /* 13 */
+ {"addi", 0, -1, {PPC_RT,RA,SI,0} }, /* 14 */
+ {"addis", 0, -1, {PPC_RT,RA,SI,0} }, /* 15 */
+ {"bc", "la", -1, {BO,BI,BD,0} }, /* 16 */
+ {"sc", 0, -1, {0} }, /* 17 */
+ {"b", "la", -1, {LI,0} }, /* 18 */
+ {"Unknown", 0, 0, {0} }, /* 19 */
+ {"rlwimi", ".", -1, {RA,RS,SH,PPC_MB,ME,0} }, /* 20 */
+ {"rlwinm", ".", -1, {RA,RS,SH,PPC_MB,ME,0} }, /* 21 */
+ {"Illegal", 0, 0, {0} }, /* 22 */
+ {"rlwnm", ".", -1, {RA,RS,RB,PPC_MB,ME,0} }, /* 23 */
+ {"ori", 0, -1, {RA,RS,UI,0} }, /* 24 */
+ {"oris", 0, -1, {RA,RS,UI,0} }, /* 25 */
+ {"xori", 0, -1, {RA,RS,UI,0} }, /* 26 */
+ {"xoris", 0, -1, {RA,RS,UI,0} }, /* 27 */
+ {"andi.", 0, -1, {RA,RS,UI,0} }, /* 28 */
+ {"andis.", 0, -1, {RA,RS,UI,0} }, /* 29 */
+ {"Unknown", 0, 0, {0} }, /* 30 */
+ {"Unknown", 0, 0, {0} }, /* 31 */
+ {"lwz", 0, -1, {PPC_RT,D,RA,0} }, /* 32 */
+ {"lwzu", 0, -1, {PPC_RT,D,RA,0} }, /* 33 */
+ {"lbz", 0, -1, {PPC_RT,D,RA,0} }, /* 34 */
+ {"lbzu", 0, -1, {PPC_RT,D,RA,0} }, /* 35 */
+ {"stw", 0, -1, {RS,D,RA,0} }, /* 36 */
+ {"stwu", 0, -1, {RS,D,RA,0} }, /* 37 */
+ {"stb", 0, -1, {RS,D,RA,0} }, /* 38 */
+ {"stbu", 0, -1, {RS,D,RA,0} }, /* 39 */
+ {"lhz", 0, -1, {PPC_RT,D,RA,0} }, /* 40 */
+ {"lhzu", 0, -1, {PPC_RT,D,RA,0} }, /* 41 */
+ {"lha", 0, -1, {PPC_RT,D,RA,0} }, /* 42 */
+ {"lhau", 0, -1, {PPC_RT,D,RA,0} }, /* 43 */
+ {"sth", 0, -1, {RS,D,RA,0} }, /* 44 */
+ {"sthu", 0, -1, {RS,D,RA,0} }, /* 45 */
+ {"lmw", 0, -1, {PPC_RT,D,RA,0} }, /* 46 */
+ {"stmw", 0, -1, {RS,D,RA,0} }, /* 47 */
+ {"lfs", 0, -1, {FRT,D,RA,0} }, /* 48 */
+ {"lfsu", 0, -1, {FRT,D,RA,0} }, /* 49 */
+ {"lfd", 0, -1, {FRT,D,RA,0} }, /* 50 */
+ {"lfdu", 0, -1, {FRT,D,RA,0} }, /* 51 */
+ {"stfs", 0, -1, {FRS,D,RA,0} }, /* 52 */
+ {"stfsu", 0, -1, {FRS,D,RA,0} }, /* 53 */
+ {"stfd", 0, -1, {FRS,D,RA,0} }, /* 54 */
+ {"stfdu", 0, -1, {FRS,D,RA,0} }, /* 55 */
+ {"Illegal", 0, 0, {0} }, /* 56 */
+ {"Illegal", 0, 0, {0} }, /* 57 */
+ {"Unknown", 0, 0, {0} }, /* 58 */
+ {"Unknown", 0, 0, {0} }, /* 59 */
+ {"Illegal", 0, 0, {0} }, /* 60 */
+ {"Illegal", 0, 0, {0} }, /* 61 */
+ {"Unknown", 0, 0, {0} }, /* 62 */
+ {"Unknown", 0, 0, {0} }, /* 63 */
+};
+
+struct ppc_instruction pop19_insn [] = {
+ {"mcrf", 0, 0, {BF,BFA,0} },
+ {"bclr", "l", 16, {BO,BI,0} },
+ {"crnor", 0, 33, {BT,BA,BB,0} },
+ {"rfi", 0, 50, {0} },
+ {"crandc", 0, 129, {BT,BA,BB,0} },
+ {"isync", 0, 150, {0} },
+ {"crxor", 0, 193, {BT,BA,BB,0} },
+ {"crnand", 0, 225, {BT,BA,BB,0} },
+ {"crand", 0, 257, {BT,BA,BB,0} },
+ {"creqv", 0, 289, {BT,BA,BB,0} },
+ {"crorc", 0, 417, {BT,BA,BB,0} },
+ {"cror", 0, 449, {BT,BA,BB,0} },
+ {"bcctr", "l", 528, {BO,BI,0} },
+};
+
+struct ppc_instruction pop30_insn [] = {
+ {"rldicl", ".", 0, {RA,RS,SH64,MBE64,0} },
+ {"rldicr", ".", 1, {RA,RS,SH64,MBE64,0} },
+ {"rldic", ".", 2, {RA,RS,SH64,MBE64,0} },
+ {"rldimi", ".", 3, {RA,RS,SH64,MBE64,0} },
+ {"rldcl", ".", 8, {RA,RS,RB,MBE64,0} },
+ {"rldcr", ".", 9, {RA,RS,RB,MBE64,0} },
+};
+
+struct ppc_instruction pop31_insn [] = {
+ {"cmp", 0, 0, {BF,L,RA,RB,0} },
+ {"tw", 0, 4, {TO,RA,RB,0} },
+ {"subfc", "o.", 8, {PPC_RT,RA,RB,0} },
+ {"mulhdu", ".", 9, {PPC_RT,RA,RB,0} },
+ {"addc", "o.", 10, {PPC_RT,RA,RB,0} },
+ {"mulhwu", ".", 11, {PPC_RT,RA,RB,0} },
+ {"mfcr", 0, 19, {PPC_RT,0} },
+ {"lwarx", 0, 20, {PPC_RT,RA,RB,0} },
+ {"ldx", 0, 21, {PPC_RT,RA,RB,0} },
+ {"lwzx", 0, 23, {PPC_RT,RA,RB,0} },
+ {"slw", ".", 24, {RA,RS,RB,0} },
+ {"cntlzw", ".", 26, {RA,RS,0} },
+ {"sld", ".", 27, {RA,RS,RB,0} },
+ {"and", ".", 28, {RA,RS,RB,0} },
+ {"cmpl", 0, 32, {BF,L,RA,RB,0} },
+ {"subf", "o.", 40, {PPC_RT,RA,RB,0} },
+ {"ldux", 0, 53, {PPC_RT,RA,RB,0} },
+ {"dcbst", 0, 54, {RA,RB,0} },
+ {"lwzux", 0, 55, {PPC_RT,RA,RB,0} },
+ {"cntlzd", ".", 58, {RA,RS,0} },
+ {"andc", ".", 60, {RA,RS,RB,0} },
+ {"td", 0, 68, {TO,RA,RB,0} },
+ {"mulhd", ".", 73, {PPC_RT,RA,RB,0} },
+ {"mulhw", ".", 75, {PPC_RT,RA,RB,0} },
+ {"mfmsr", 0, 83, {PPC_RT,0} },
+ {"ldarx", 0, 84, {PPC_RT,RA,RB,0} },
+ {"dcbf", 0, 86, {RA,RB,0} },
+ {"lbzx", 0, 87, {PPC_RT,RA,RB,0} },
+ {"neg", "o.", 104, {PPC_RT,RA,0} },
+ {"mfpmr", 0, 115, {PPC_RT,0} },
+ {"lbzux", 0, 119, {PPC_RT,RA,RB,0} },
+ {"nor", ".", 124, {RA,RS,RB,0} },
+ {"subfe", "o.", 136, {PPC_RT,RA,RB,0} },
+ {"adde", "o.", 138, {PPC_RT,RA,RB,0} },
+ {"mtcrf", 0, 144, {FXM,RS,0} },
+ {"mtmsr", 0, 146, {RS,0} },
+ {"stdx", 0, 149, {RS,RA,RB,0} },
+ {"stwcx.", 0, 150, {RS,RA,RB,0} },
+ {"stwx", 0, 151, {RS,RA,RB,0} },
+ {"mtpmr", 0, 178, {RS,0} },
+ {"stdux", 0, 181, {RS,RA,RB,0} },
+ {"stwux", 0, 183, {RS,RA,RB,0} },
+ {"subfze", "o.", 200, {PPC_RT,RA,0} },
+ {"addze", "o.", 202, {PPC_RT,RA,0} },
+ {"mtsr", 0, 210, {SR,RS,0} },
+ {"stdcx.", 0, 214, {RS,RA,RB,0} },
+ {"stbx", 0, 215, {RS,RA,RB,0} },
+ {"subfme", "o.", 232, {PPC_RT,RA,0} },
+ {"addme", "o.", 234, {PPC_RT,RA,0} },
+ {"mull", "o.", 235, {PPC_RT,RA,RB,0} },
+ {"mtsrin", 0, 242, {RS,RB,0} },
+ {"dcbtst", 0, 246, {RA,RB,0} },
+ {"stbux", 0, 247, {RS,RA,RB,0} },
+ {"add", "o.", 266, {PPC_RT,RA,RB,0} },
+ {"dcbt", 0, 278, {RA,RB,0} },
+ {"lhzx", 0, 279, {PPC_RT,RA,RB,0} },
+ {"eqv", ".", 284, {RA,RS,RB,0} },
+ {"tlbie", 0, 306, {RB,0} },
+ {"eciwx", 0, 310, {PPC_RT,RA,RB,0} },
+ {"lhzux", 0, 311, {PPC_RT,RA,RB,0} },
+ {"xor", ".", 316, {RA,RS,RB,0} },
+ {"tlbiex", 0, 338, {RB,0} },
+ {"mfspr", 0, 339, {PPC_RT,SPR,0} },
+ {"lwax", 0, 341, {PPC_RT,RA,RB,0} },
+ {"lhax", 0, 343, {PPC_RT,RA,RB,0} },
+ {"tlbia", 0, 370, {0} },
+ {"mftb", 0, 371, {PPC_RT,TBR,0} },
+ {"lwaux", 0, 373, {PPC_RT,RA,RB,0} },
+ {"lhaux", 0, 375, {PPC_RT,RA,RB,0} },
+ {"mttb", 0, 403, {RB,0} },
+ {"sthx", 0, 407, {RS,RA,RB,0} },
+ {"orc", ".", 412, {RA,RS,RB,0} },
+ {"sradi", ".", 413, {RA,RS,SH64,0} },
+ {"slbie", 0, 434, {RB,0} },
+ {"mttbu", 0, 435, {RB,0} },
+ {"ecowx", 0, 438, {RS,RA,RB,0} },
+ {"sthux", 0, 439, {RS,RA,RB,0} },
+ {"or", ".", 444, {RA,RS,RB,0} },
+ {"divdu", "o.", 457, {PPC_RT,RA,RB,0} },
+ {"divwu", "o.", 459, {PPC_RT,RA,RB,0} },
+ {"slbiex", 0, 466, {RB,0} },
+ {"mtspr", 0, 467, {SPR,RS,0} },
+ {"dcbi", 0, 470, {RA,RB,0} },
+ {"nand", ".", 476, {RA,RS,RB,0} },
+ {"divd", "o.", 489, {PPC_RT,RA,RB,0} },
+ {"divw", "o.", 491, {PPC_RT,RA,RB,0} },
+ {"slbia", 0, 498, {0} },
+ {"mcrxr", 0, 512, {BF,0} },
+ {"lswx", 0, 533, {PPC_RT,RA,RB,0} },
+ {"lwbrx", 0, 534, {PPC_RT,RA,RB,0} },
+ {"lfsx", 0, 535, {FRT,RA,RB,0} },
+ {"srw", ".", 536, {RA,RS,RB,0} },
+ {"srd", ".", 539, {RA,RS,RB,0} },
+ {"lfsux", 0, 567, {FRT,RA,RB,0} },
+ {"mfsr", 0, 595, {PPC_RT,SR,0} },
+ {"lswi", 0, 597, {PPC_RT,RA,NB,0} },
+ {"sync", 0, 598, {0} },
+ {"lfdx", 0, 599, {FRT,RA,RB,0} },
+ {"lfdux", 0, 631, {FRT,RA,RB,0} },
+ {"mfsrin", 0, 659, {PPC_RT,RB,0} },
+ {"stswx", 0, 661, {RS,RA,RB,0} },
+ {"stwbrx", 0, 662, {RS,RA,RB,0} },
+ {"stfsx", 0, 663, {FRS,RA,RB,0} },
+ {"stfsux", 0, 695, {FRS,RA,RB,0} },
+ {"stswi", 0, 725, {RS,RA,NB,0} },
+ {"stfdx", 0, 727, {FRS,RA,RB,0} },
+ {"stfdux", 0, 759, {FRS,RA,RB,0} },
+ {"lhbrx", 0, 790, {PPC_RT,RA,RB,0} },
+ {"sraw", ".", 792, {RA,RS,RB,0} },
+ {"srad", ".", 794, {RA,RS,RB,0} },
+ {"srawi", ".", 824, {RA,RS,SH,0} },
+ {"eieio", 0, 854, {0} },
+ {"sthbrx", 0, 918, {RS,RA,RB,0} },
+ {"extsh", ".", 922, {RA,RS,0} },
+ {"extsb", ".", 954, {RA,RS,0} },
+ {"icbi", 0, 982, {RA,RB,0} },
+ {"stfiwx", 0, 983, {FRS,RA,RB,0} },
+ {"extsw", ".", 986, {RA,RS,0} },
+ {"dcbz", 0, 1014, {RA,RB,0} },
+};
+
+struct ppc_instruction pop58_insn [] = {
+ {"ld", 0, 0, {PPC_RT,DS,RA,0} },
+ {"ldu", 0, 1, {PPC_RT,DS,RA,0} },
+ {"lwa", 0, 2, {PPC_RT,DS,RA,0} },
+ {"lmd", 0, 3, {PPC_RT,DS,RA,0} },
+};
+
+struct ppc_instruction pop59_insn [] = {
+ {"fdivs", ".", 18, {FRT,FRA,FRB,0} },
+ {"fsubs", ".", 20, {FRT,FRA,FRB,0} },
+ {"fadds", ".", 21, {FRT,FRA,FRB,0} },
+ {"fsqrts", ".", 22, {FRT,FRB,0} },
+ {"fres", ".", 24, {FRT,FRB,0} },
+ {"fmuls", ".", 25, {FRT,FRA,FRC,0} },
+ {"fmsubs", ".", 28, {FRT,FRA,FRC,FRB,0} },
+ {"fmadds", ".", 29, {FRT,FRA,FRC,FRB,0} },
+ {"fnmsubs", ".", 30, {FRT,FRA,FRC,FRB,0} },
+ {"fnmadds", ".", 31, {FRT,FRA,FRC,FRB,0} },
+};
+
+struct ppc_instruction pop62_insn [] = {
+ {"std", 0, 0, {RS,DS,RA,0} },
+ {"stdu", 0, 1, {RS,DS,RA,0} },
+ {"stmd", 0, 3, {RS,DS,RA,0} },
+};
+
+struct ppc_instruction pop63_insn [] = {
+ {"fcmpu", 0, 0, {BF,FRA,FRB,0} },
+ {"frsp", ".", 12, {FRT,FRB,0} },
+ {"fctiw", ".", 14, {FRT,FRB,0} },
+ {"fctiwz", ".", 15, {FRT,FRB,0} },
+ {"fdiv", ".", 18, {FRT,FRA,FRB,0} },
+ {"fsub", ".", 20, {FRT,FRA,FRB,0} },
+ {"fadd", ".", 21, {FRT,FRA,FRB,0} },
+ {"fsqrt", ".", 22, {FRT,FRB,0} },
+ {"fsel", ".", 23, {FRT,FRA,FRB,FRC,0} },
+ {"fmul", ".", 25, {FRT,FRA,FRC,0} },
+ {"frsqrte", ".", 26, {FRT,FRB,0} },
+ {"fmsub", ".", 28, {FRT,FRA,FRC,FRB,0} },
+ {"fmadd", ".", 29, {FRT,FRA,FRC,FRB,0} },
+ {"fnmsub", ".", 30, {FRT,FRA,FRC,FRB,0} },
+ {"fnmadd", ".", 31, {FRT,FRA,FRC,FRB,0} },
+ {"fcmpo", 0, 32, {BF,FRA,FRB,0} },
+ {"mtfsb1", ".", 38, {BT,0} },
+ {"fneg", ".", 40, {FRT,FRB,0} },
+ {"mcrfs", 0, 64, {BF,BFA,0} },
+ {"mtfsb0", ".", 70, {BT,0} },
+ {"fmr", ".", 72, {FRT,FRB,0} },
+ {"mtfsfi", ".", 134, {BF,U,0} },
+ {"fnabs", ".", 136, {FRT,FRB,0} },
+ {"fabs", ".", 264, {FRT,FRB,0} },
+ {"mffs", ".", 583, {FRT,0} },
+ {"mtfsf", ".", 711, {FLM,FRB,0} },
+ {"fctid", ".", 814, {FRT,FRB,0} },
+ {"fctidz", ".", 815, {FRT,FRB,0} },
+ {"fcfid", ".", 846, {FRT,FRB,0} },
+};
+
+/* popXX_fmts is a list of instruction formats for the corresponding
+ extended opcode instruction table. When adding an instruction to the
+ table, add a format to the list if the extended opcode maps differently
+ than one that is already on the list. Leave the "-1" at the end to
+ terminate searches.
+ Note that it is best to keep the most common format first in the
+ tables, because formats are checked in the order they appear.
+ Also note that XFX is not in the format list because it is not
+ a unique mapping. */
+int pop19_fmts [] = { XL, -1 };
+int pop30_fmts [] = { MD, MDS, -1 };
+int pop31_fmts [] = { X, XO, XS, -1 };
+int pop58_fmts [] = { DS, -1 };
+int pop59_fmts [] = { A, -1 };
+int pop62_fmts [] = { DS, -1 };
+int pop63_fmts [] = { X, A, -1 };
+
+/* This calculates the number of entries in each table */
+#define COUNT19 (sizeof (pop19_insn) / sizeof (struct ppc_instruction))
+#define COUNT30 (sizeof (pop30_insn) / sizeof (struct ppc_instruction))
+#define COUNT31 (sizeof (pop31_insn) / sizeof (struct ppc_instruction))
+#define COUNT58 (sizeof (pop58_insn) / sizeof (struct ppc_instruction))
+#define COUNT59 (sizeof (pop59_insn) / sizeof (struct ppc_instruction))
+#define COUNT62 (sizeof (pop62_insn) / sizeof (struct ppc_instruction))
+#define COUNT63 (sizeof (pop63_insn) / sizeof (struct ppc_instruction))
+
+/* #endif _MOTO_EXTENSIONS */
diff --git a/private/windbg/em/p_ppc/precomp.h b/private/windbg/em/p_ppc/precomp.h
new file mode 100644
index 000000000..f7056298d
--- /dev/null
+++ b/private/windbg/em/p_ppc/precomp.h
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "biavst.h"
+
+#include <windows.h>
+#include <dde.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <memory.h>
+#include <string.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#ifdef OSDEBUG4
+
+#include "od.h"
+#include "odp.h"
+#include "odassert.h"
+
+#include "dbgver.h"
+
+// BUGBUG kentf have to include shapi.hxx for LPDEBUGDATA?
+#include "shapi.hxx"
+
+#include "emdm.h"
+#include "win32dm.h"
+#include "emdata.h"
+#include "emproto.h"
+
+#include "cvinfo.h"
+
+
+#else // OSDEBUG4
+
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "tl.h"
+#include "od.h"
+#include "dbgver.h"
+#include "emdm.h"
+#include "osdem.h"
+#include "emdata.h"
+#include "emproto.h"
+
+#include "osassert.h"
+
+#include "lbhpt.h"
+#include "llhpt.h"
+#include "mhhpt.h"
+
+#endif // OSDEBUG4
diff --git a/private/windbg/em/p_ppc/regs.h b/private/windbg/em/p_ppc/regs.h
new file mode 100644
index 000000000..393e05e4b
--- /dev/null
+++ b/private/windbg/em/p_ppc/regs.h
@@ -0,0 +1,79 @@
+// first all the gprs
+
+ { szGpr0, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR0},
+ { szGpr1, rtCPU | rtRegular | rtExtended | rtInteger | rtFrame, 32, CV_PPC_GPR1},
+ { szGpr2, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR2},
+ { szGpr3, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR3},
+ { szGpr4, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR4},
+ { szGpr5, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR5},
+ { szGpr6, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR6},
+ { szGpr7, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR7},
+ { szGpr8, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR8},
+ { szGpr9, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR9},
+ { szGpr10, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR10},
+ { szGpr11, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR11},
+ { szGpr12, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR12},
+ { szGpr13, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR13},
+ { szGpr14, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR14},
+ { szGpr15, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR15},
+ { szGpr16, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR16},
+ { szGpr17, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR17},
+ { szGpr18, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR18},
+ { szGpr19, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR19},
+ { szGpr20, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR20},
+ { szGpr21, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR21},
+ { szGpr22, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR22},
+ { szGpr23, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR23},
+ { szGpr24, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR24},
+ { szGpr25, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR25},
+ { szGpr26, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR26},
+ { szGpr27, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR27},
+ { szGpr28, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR28},
+ { szGpr29, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR29},
+ { szGpr30, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR30},
+ { szGpr31, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_GPR31},
+
+// floating point registers follow
+
+ { szFpr0, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR0 },
+ { szFpr1, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR1 },
+ { szFpr2, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR2 },
+ { szFpr3, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR3 },
+ { szFpr4, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR4 },
+ { szFpr5, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR5 },
+ { szFpr6, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR6 },
+ { szFpr7, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR7 },
+ { szFpr8, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR8 },
+ { szFpr9, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR9 },
+ { szFpr10, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR10 },
+ { szFpr11, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR11 },
+ { szFpr12, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR12 },
+ { szFpr13, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR13 },
+ { szFpr14, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR14 },
+ { szFpr15, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR15 },
+ { szFpr16, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR16 },
+ { szFpr17, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR17 },
+ { szFpr18, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR18 },
+ { szFpr19, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR19 },
+ { szFpr20, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR20 },
+ { szFpr21, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR21 },
+ { szFpr22, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR22 },
+ { szFpr23, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR23 },
+ { szFpr24, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR24 },
+ { szFpr25, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR25 },
+ { szFpr26, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR26 },
+ { szFpr27, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR27 },
+ { szFpr28, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR28 },
+ { szFpr29, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR29 },
+ { szFpr30, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR30 },
+ { szFpr31, rtFPU | rtRegular | rtExtended | rtFloat, 64, CV_PPC_FPR31 },
+
+ { szFpscr, rtFPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_FPSCR },
+ { szLr, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_LR },
+ { szCr, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_CR },
+ { szCtr, rtCPU | rtRegular | rtExtended | rtInteger, 32, CV_PPC_CTR },
+ { szCIA, rtCPU | rtRegular | rtExtended | rtInteger | rtPC, 32, CV_PPC_PC},
+ { szMsr, rtCPU | rtExtended | rtInteger | rtSpecial , 32, CV_PPC_MSR},
+ { szXer, rtCPU | rtExtended | rtInteger | rtSpecial , 32, CV_PPC_XER}
+
+
diff --git a/private/windbg/em/p_ppc/sources b/private/windbg/em/p_ppc/sources
new file mode 100644
index 000000000..b1bae811e
--- /dev/null
+++ b/private/windbg/em/p_ppc/sources
@@ -0,0 +1,61 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=emppc
+
+TARGETNAME=emppc
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+DLLENTRY=DllInit
+
+SOURCES= \
+ asm.c \
+ d3.c \
+ emdp.c \
+ emdp2.c \
+ emdp3.c \
+ emdpdev.c \
+ strings.c \
+ wintrans.c \
+ em.rc
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_PPC
+
+INCLUDES=..;..\..\osdebug\include;..\..\osdebug
+
+CONDITIONAL_INCLUDES=odp.h win32msg.h xosd.h odassert.h win32dm.h
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/em/p_ppc/strings.c b/private/windbg/em/p_ppc/strings.c
new file mode 100644
index 000000000..62c352bbd
--- /dev/null
+++ b/private/windbg/em/p_ppc/strings.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\strings.c"
diff --git a/private/windbg/em/p_ppc/strings.h b/private/windbg/em/p_ppc/strings.h
new file mode 100644
index 000000000..fa4100ae9
--- /dev/null
+++ b/private/windbg/em/p_ppc/strings.h
@@ -0,0 +1,130 @@
+/*
+** STRINGS.H
+**
+** This file contains all strings which are used in the EM for display
+** purposes. This is done for internationalization purposes.
+**
+** strings.c defines DEFINE_STRINGS before including this file. Other
+** source files just include this file normally.
+*/
+
+/*
+** strings.c should define DEFINE_STRINGS before including this file,
+** so that the strings will be defined rather than just declared.
+*/
+
+#ifdef DEFINE_STRINGS
+#define DECL_STR(name, value) char name[] = value
+#undef DEFINE_STRINGS
+#else
+#define DECL_STR(name, value) extern char name[]
+#endif
+
+
+DECL_STR( szGpr0 , "Gpr0");
+DECL_STR( szGpr1 , "Gpr1");
+DECL_STR( szGpr2 , "Gpr2");
+DECL_STR( szGpr3, "Gpr3");
+DECL_STR( szGpr4, "Gpr4");
+DECL_STR( szGpr5, "Gpr5");
+DECL_STR( szGpr6, "Gpr6");
+DECL_STR( szGpr7, "Gpr7");
+DECL_STR( szGpr8, "Gpr8");
+DECL_STR( szGpr9, "Gpr9");
+DECL_STR( szGpr10, "Gpr10");
+DECL_STR( szGpr11, "Gpr11");
+DECL_STR( szGpr12, "Gpr12");
+DECL_STR( szGpr13, "Gpr13");
+DECL_STR( szGpr14, "Gpr14");
+DECL_STR( szGpr15, "Gpr15");
+DECL_STR( szGpr16, "Gpr16");
+DECL_STR( szGpr17, "Gpr17");
+DECL_STR( szGpr18, "Gpr18");
+DECL_STR( szGpr19, "Gpr19");
+DECL_STR( szGpr20, "Gpr20");
+DECL_STR( szGpr21, "Gpr21");
+DECL_STR( szGpr22, "Gpr22");
+DECL_STR( szGpr23, "Gpr23");
+DECL_STR( szGpr24, "Gpr24");
+DECL_STR( szGpr25, "Gpr25");
+DECL_STR( szGpr26, "Gpr26");
+DECL_STR( szGpr27, "Gpr27");
+DECL_STR( szGpr28, "Gpr28");
+DECL_STR( szGpr29, "Gpr29");
+DECL_STR( szGpr30, "Gpr30");
+DECL_STR( szGpr31, "Gpr31");
+
+ /*
+ ** PowerPC Floating Point Registers ( User Level )
+ */
+
+DECL_STR( szFpr0 , "Fpr0");
+DECL_STR( szFpr1 , "Fpr1");
+DECL_STR( szFpr2 , "Fpr2");
+DECL_STR( szFpr3 , "Fpr3");
+DECL_STR( szFpr4 , "Fpr4");
+DECL_STR( szFpr5 , "Fpr5");
+DECL_STR( szFpr6 , "Fpr6");
+DECL_STR( szFpr7 , "Fpr7");
+DECL_STR( szFpr8 , "Fpr8");
+DECL_STR( szFpr9 , "Fpr9");
+DECL_STR( szFpr10 , "Fpr10");
+DECL_STR( szFpr11 , "Fpr11");
+DECL_STR( szFpr12 , "Fpr12");
+DECL_STR( szFpr13 , "Fpr13");
+DECL_STR( szFpr14 , "Fpr14");
+DECL_STR( szFpr15 , "Fpr15");
+DECL_STR( szFpr16 , "Fpr16");
+DECL_STR( szFpr17 , "Fpr17");
+DECL_STR( szFpr18 , "Fpr18");
+DECL_STR( szFpr19 , "Fpr19");
+DECL_STR( szFpr20 , "Fpr20");
+DECL_STR( szFpr21 , "Fpr21");
+DECL_STR( szFpr22 , "Fpr22");
+DECL_STR( szFpr23 , "Fpr23");
+DECL_STR( szFpr24 , "Fpr24");
+DECL_STR( szFpr25 , "Fpr25");
+DECL_STR( szFpr26 , "Fpr26");
+DECL_STR( szFpr27 , "Fpr27");
+DECL_STR( szFpr28 , "Fpr28");
+DECL_STR( szFpr29 , "Fpr29");
+DECL_STR( szFpr30 , "Fpr30");
+DECL_STR( szFpr31 , "Fpr31");
+
+DECL_STR( szFpscr , "FPSCR");
+DECL_STR( szLr , "LR");
+DECL_STR( szCtr, "CTR");
+DECL_STR( szCr, "CR");
+
+DECL_STR( szFlagCR0, "CR0");
+DECL_STR( szFlagCR1, "CR1");
+DECL_STR( szFlagCR2, "CR2");
+DECL_STR( szFlagCR3, "CR3");
+DECL_STR( szFlagCR4, "CR4");
+DECL_STR( szFlagCR5, "CR5");
+DECL_STR( szFlagCR6, "CR6");
+DECL_STR( szFlagCR7, "CR7");
+
+DECL_STR( szCIA, "CIA");
+
+DECL_STR( szXer, "XER");
+DECL_STR( szMsr, "MSR");
+
+DECL_STR(SzFrozen, "Frozen");
+DECL_STR(SzSuspended, "Suspended");
+DECL_STR(SzBlocked, "Blocked");
+
+DECL_STR(SzRunnable, "Runnable");
+DECL_STR(SzRunning, "Running");
+DECL_STR(SzStopped, "Stopped");
+DECL_STR(SzExiting, "Exiting");
+DECL_STR(SzDead, "Dead");
+DECL_STR(SzUnknown, "UNKNOWN");
+
+DECL_STR(SzExcept1st, "Except1st");
+DECL_STR(SzExcept2nd, "Except2nd");
+DECL_STR(SzRipped, "RIP");
+
+DECL_STR(SzCritSec, "CritSec");
+
+DECL_STR(SzStandard, "Standard");
diff --git a/private/windbg/em/p_ppc/wintrans.c b/private/windbg/em/p_ppc/wintrans.c
new file mode 100644
index 000000000..c5276532e
--- /dev/null
+++ b/private/windbg/em/p_ppc/wintrans.c
@@ -0,0 +1,4 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#include "..\wintrans.c"
diff --git a/private/windbg/em/strings.c b/private/windbg/em/strings.c
new file mode 100644
index 000000000..76d6ba3ac
--- /dev/null
+++ b/private/windbg/em/strings.c
@@ -0,0 +1,17 @@
+/*
+** STRINGS.C
+**
+** This file defines all strings which are used in the EM for display
+** purposes. This is done for internationalization purposes.
+**
+** strings.h contains all declarations for the data in this file.
+*/
+
+/*
+** We define DEFINE_STRINGS before including strings.h so that all the
+** strings will be defined rather than just declared.
+*/
+
+#define DEFINE_STRINGS
+
+#include "strings.h"
diff --git a/private/windbg/em/win32msg.h b/private/windbg/em/win32msg.h
new file mode 100644
index 000000000..8128861cb
--- /dev/null
+++ b/private/windbg/em/win32msg.h
@@ -0,0 +1,183 @@
+
+
+//
+// This file may be included many times, with different definitions
+// for DECL_MASK and DECL_MSG.
+//
+
+
+//
+// Windows Mesage mask values
+//
+
+DECL_MASK( MSG_TYPE_MOUSE, 0x0001, "Mouse")
+DECL_MASK( MSG_TYPE_WINDOW, 0x0002, "Window")
+DECL_MASK( MSG_TYPE_INPUT, 0x0004, "Input")
+DECL_MASK( MSG_TYPE_SYSTEM, 0x0008, "System")
+DECL_MASK( MSG_TYPE_INIT, 0x0010, "Init")
+DECL_MASK( MSG_TYPE_CLIPBOARD, 0x0020, "Clipboard")
+DECL_MASK( MSG_TYPE_DDE, 0x0040, "DDE")
+DECL_MASK( MSG_TYPE_NONCLIENT, 0x0080, "Non-Client")
+DECL_MASK( MSG_TYPE_OTHER, 0x0100, "Other")
+
+
+//
+// Windows messages
+//
+
+DECL_MSG(WM_NULL , "WM_NULL" , MSG_TYPE_OTHER)
+DECL_MSG(WM_CREATE , "WM_CREATE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_DESTROY , "WM_DESTROY" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MOVE , "WM_MOVE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SIZE , "WM_SIZE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_ACTIVATE , "WM_ACTIVATE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SETFOCUS , "WM_SETFOCUS" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_KILLFOCUS , "WM_KILLFOCUS" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_ENABLE , "WM_ENABLE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SETREDRAW , "WM_SETREDRAW" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SETTEXT , "WM_SETTEXT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_GETTEXT , "WM_GETTEXT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_GETTEXTLENGTH , "WM_GETTEXTLENGTH" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_PAINT , "WM_PAINT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CLOSE , "WM_CLOSE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_QUERYENDSESSION , "WM_QUERYENDSESSION" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_QUIT , "WM_QUIT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_QUERYOPEN , "WM_QUERYOPEN" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_ERASEBKGND , "WM_ERASEBKGND" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SYSCOLORCHANGE , "WM_SYSCOLORCHANGE" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_ENDSESSION , "WM_ENDSESSION" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_SHOWWINDOW , "WM_SHOWWINDOW" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_WININICHANGE , "WM_WININICHANGE" , MSG_TYPE_SYSTEM)
+
+DECL_MSG(WM_DEVMODECHANGE , "WM_DEVMODECHANGE" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_ACTIVATEAPP , "WM_ACTIVATEAPP" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_FONTCHANGE , "WM_FONTCHANGE" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_TIMECHANGE , "WM_TIMECHANGE" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_CANCELMODE , "WM_CANCELMODE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SETCURSOR , "WM_SETCURSOR" , MSG_TYPE_MOUSE)
+DECL_MSG(WM_MOUSEACTIVATE , "WM_MOUSEACTIVATE" , MSG_TYPE_MOUSE)
+DECL_MSG(WM_CHILDACTIVATE , "WM_CHILDACTIVATE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_QUEUESYNC , "WM_QUEUESYNC" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_GETMINMAXINFO , "WM_GETMINMAXINFO" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_PAINTICON , "WM_PAINTICON" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_ICONERASEBKGND , "WM_ICONERASEBKGND" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_NEXTDLGCTL , "WM_NEXTDLGCTL" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SPOOLERSTATUS , "WM_SPOOLERSTATUS" , MSG_TYPE_OTHER)
+DECL_MSG(WM_DRAWITEM , "WM_DRAWITEM" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MEASUREITEM , "WM_MEASUREITEM" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_DELETEITEM , "WM_DELETEITEM" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_VKEYTOITEM , "WM_VKEYTOITEM" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CHARTOITEM , "WM_CHARTOITEM" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SETFONT , "WM_SETFONT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_GETFONT , "WM_GETFONT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_SETHOTKEY , "WM_SETHOTKEY" , MSG_TYPE_INPUT )
+DECL_MSG(WM_GETHOTKEY , "WM_GETHOTKEY" , MSG_TYPE_INPUT )
+DECL_MSG(WM_QUERYDRAGICON , "WM_QUERYDRAGICON" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_COMPAREITEM , "WM_COMPAREITEM" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_COMPACTING , "WM_COMPACTING" , MSG_TYPE_SYSTEM)
+//DECL_MSG(WM_OTHERWINDOWCREATED , "WM_OTHERWINDOWCREATED" , MSG_TYPE_SYSTEM)
+//DECL_MSG(WM_OTHERWINDOWDESTROYED, "WM_OTHERWINDOWDESTROYED", MSG_TYPE_SYSTEM)
+//DECL_MSG(WM_COMMNOTIFY , "WM_COMMNOTIFY" , MSG_TYPE_SYSTEM)
+//DECL_MSG(WM_HOTKEYEVENT , "WM_HOTKEYEVENT" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_WINDOWPOSCHANGING , "WM_WINDOWPOSCHANGING" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_WINDOWPOSCHANGED , "WM_WINDOWPOSCHANGED" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_POWER , "WM_POWER" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_COPYDATA , "WM_COPYDATA" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_CANCELJOURNAL , "WM_CANCELJOURNAL" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_NCCREATE , "WM_NCCREATE" , MSG_TYPE_NONCLIENT)
+DECL_MSG(WM_NCDESTROY , "WM_NCDESTROY" , MSG_TYPE_NONCLIENT)
+DECL_MSG(WM_NCCALCSIZE , "WM_NCCALCSIZE" , MSG_TYPE_NONCLIENT)
+DECL_MSG(WM_NCHITTEST , "WM_NCHITTEST" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCPAINT , "WM_NCPAINT" , MSG_TYPE_NONCLIENT)
+DECL_MSG(WM_NCACTIVATE , "WM_NCACTIVATE" , MSG_TYPE_NONCLIENT)
+DECL_MSG(WM_GETDLGCODE , "WM_GETDLGCODE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_NCMOUSEMOVE , "WM_NCMOUSEMOVE" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCLBUTTONDOWN , "WM_NCLBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCLBUTTONUP , "WM_NCLBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCLBUTTONDBLCLK , "WM_NCLBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCRBUTTONDOWN , "WM_NCRBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCRBUTTONUP , "WM_NCRBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCRBUTTONDBLCLK , "WM_NCRBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCMBUTTONDOWN , "WM_NCMBUTTONDOWN" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCMBUTTONUP , "WM_NCMBUTTONUP" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_NCMBUTTONDBLCLK , "WM_NCMBUTTONDBLCLK" , MSG_TYPE_NONCLIENT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_KEYDOWN , "WM_KEYDOWN" , MSG_TYPE_INPUT)
+DECL_MSG(WM_KEYUP , "WM_KEYUP" , MSG_TYPE_INPUT)
+DECL_MSG(WM_CHAR , "WM_CHAR" , MSG_TYPE_INPUT)
+DECL_MSG(WM_DEADCHAR , "WM_DEADCHAR" , MSG_TYPE_INPUT)
+DECL_MSG(WM_SYSKEYDOWN , "WM_SYSKEYDOWN" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT)
+DECL_MSG(WM_SYSKEYUP , "WM_SYSKEYUP" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT)
+DECL_MSG(WM_SYSCHAR , "WM_SYSCHAR" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT)
+DECL_MSG(WM_SYSDEADCHAR , "WM_SYSDEADCHAR" , MSG_TYPE_SYSTEM | MSG_TYPE_INPUT)
+DECL_MSG(WM_INITDIALOG , "WM_INITDIALOG" , MSG_TYPE_INIT)
+DECL_MSG(WM_COMMAND , "WM_COMMAND" , MSG_TYPE_INPUT)
+DECL_MSG(WM_SYSCOMMAND , "WM_SYSCOMMAND" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_TIMER , "WM_TIMER" , MSG_TYPE_INPUT)
+DECL_MSG(WM_HSCROLL , "WM_HSCROLL" , MSG_TYPE_INPUT)
+DECL_MSG(WM_VSCROLL , "WM_VSCROLL" , MSG_TYPE_INPUT)
+DECL_MSG(WM_INITMENU , "WM_INITMENU" , MSG_TYPE_INIT)
+DECL_MSG(WM_INITMENUPOPUP , "WM_INITMENUPOPUP" , MSG_TYPE_INIT)
+DECL_MSG(WM_MENUSELECT , "WM_MENUSELECT" , MSG_TYPE_INPUT)
+DECL_MSG(WM_MENUCHAR , "WM_MENUCHAR" , MSG_TYPE_INPUT)
+DECL_MSG(WM_ENTERIDLE , "WM_ENTERIDLE" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_CTLCOLORMSGBOX , "WM_CTLCOLORMSGBOX" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CTLCOLOREDIT , "WM_CTLCOLOREDIT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CTLCOLORLISTBOX , "WM_CTLCOLORLISTBOX" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CTLCOLORBTN , "WM_CTLCOLORBTN" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CTLCOLORDLG , "WM_CTLCOLORDLG" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CTLCOLORSCROLLBAR , "WM_CTLCOLORSCROLLBAR" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CTLCOLORSTATIC , "WM_CTLCOLORSTATIC" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MOUSEMOVE , "WM_MOUSEMOVE" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_LBUTTONDOWN , "WM_LBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_LBUTTONUP , "WM_LBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_LBUTTONDBLCLK , "WM_LBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_RBUTTONDOWN , "WM_RBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_RBUTTONUP , "WM_RBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_RBUTTONDBLCLK , "WM_RBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_MBUTTONDOWN , "WM_MBUTTONDOWN" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_MBUTTONUP , "WM_MBUTTONUP" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_MBUTTONDBLCLK , "WM_MBUTTONDBLCLK" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+DECL_MSG(WM_PARENTNOTIFY , "WM_PARENTNOTIFY" , MSG_TYPE_INPUT | MSG_TYPE_MOUSE)
+//DECL_MSG(WM_ENTERMENULOOP , "WM_ENTERMENULOOP" , MSG_TYPE_SYSTEM)
+//DECL_MSG(WM_EXITMENULOOP , "WM_EXITMENULOOP" , MSG_TYPE_SYSTEM)
+DECL_MSG(WM_MDICREATE , "WM_MDICREATE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIDESTROY , "WM_MDIDESTROY" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIACTIVATE , "WM_MDIACTIVATE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIRESTORE , "WM_MDIRESTORE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDINEXT , "WM_MDINEXT" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIMAXIMIZE , "WM_MDIMAXIMIZE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDITILE , "WM_MDITILE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDICASCADE , "WM_MDICASCADE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIICONARRANGE , "WM_MDIICONARRANGE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIGETACTIVE , "WM_MDIGETACTIVE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDISETMENU , "WM_MDISETMENU" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_DROPFILES , "WM_DROPFILES" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_MDIREFRESHMENU , "WM_MDIREFRESHMENU" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_CUT , "WM_CUT" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_COPY , "WM_COPY" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_PASTE , "WM_PASTE" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_CLEAR , "WM_CLEAR" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_UNDO , "WM_UNDO" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_RENDERFORMAT , "WM_RENDERFORMAT" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_RENDERALLFORMATS , "WM_RENDERALLFORMATS" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_DESTROYCLIPBOARD , "WM_DESTROYCLIPBOARD" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_DRAWCLIPBOARD , "WM_DRAWCLIPBOARD" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_PAINTCLIPBOARD , "WM_PAINTCLIPBOARD" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_VSCROLLCLIPBOARD , "WM_VSCROLLCLIPBOARD" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_SIZECLIPBOARD , "WM_SIZECLIPBOARD" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_ASKCBFORMATNAME , "WM_ASKCBFORMATNAME" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_CHANGECBCHAIN , "WM_CHANGECBCHAIN" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_HSCROLLCLIPBOARD , "WM_HSCROLLCLIPBOARD" , MSG_TYPE_CLIPBOARD)
+DECL_MSG(WM_QUERYNEWPALETTE , "WM_QUERYNEWPALETTE" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_PALETTEISCHANGING , "WM_PALETTEISCHANGING" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_PALETTECHANGED , "WM_PALETTECHANGED" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_HOTKEY , "WM_HOTKEY" , MSG_TYPE_WINDOW)
+DECL_MSG(WM_DDE_INITIATE , "WM_DDE_INITIATE" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_TERMINATE , "WM_DDE_TERMINATE" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_ADVISE , "WM_DDE_ADVISE" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_UNADVISE , "WM_DDE_UNADVISE" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_ACK , "WM_DDE_ACK" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_DATA , "WM_DDE_DATA" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_REQUEST , "WM_DDE_REQUEST" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_POKE , "WM_DDE_POKE" , MSG_TYPE_DDE)
+DECL_MSG(WM_DDE_EXECUTE , "WM_DDE_EXECUTE" , MSG_TYPE_DDE)
diff --git a/private/windbg/em/wintrans.c b/private/windbg/em/wintrans.c
new file mode 100644
index 000000000..5c3a13e1f
--- /dev/null
+++ b/private/windbg/em/wintrans.c
@@ -0,0 +1,629 @@
+/*** wintrans.c - To translate windows message names
+*
+* Copyright <C> 1988, Microsoft Corporation
+*
+* Purpose: To implement user-interface functions specific to windows:
+*
+* Revision History:
+*
+*************************************************************************/
+#if defined (WIN) || defined (OS2)
+
+
+#if defined ( WIN )
+#else
+#define INCL_WIN
+#endif
+
+
+#if defined(WIN)
+
+/* DDE window messages */
+
+#define WM_DDE_FIRST 0x03E0
+#define WM_DDE_INITIATE (WM_DDE_FIRST)
+#define WM_DDE_TERMINATE (WM_DDE_FIRST+1)
+#define WM_DDE_ADVISE (WM_DDE_FIRST+2)
+#define WM_DDE_UNADVISE (WM_DDE_FIRST+3)
+#define WM_DDE_ACK (WM_DDE_FIRST+4)
+#define WM_DDE_DATA (WM_DDE_FIRST+5)
+#define WM_DDE_REQUEST (WM_DDE_FIRST+6)
+#define WM_DDE_POKE (WM_DDE_FIRST+7)
+#define WM_DDE_EXECUTE (WM_DDE_FIRST+8)
+#define WM_DDE_LAST (WM_DDE_FIRST+8)
+
+/* Other Windows 3.0 message not in windows.h */
+
+#define WM_COMPAREITEM 0x0039
+#define WM_VKEYTOITEM 0x002E
+#define WM_CHARTOITEM 0x002F
+#define WM_DROPOBJECT 0x022A
+#define WM_QUERYDROPOBJECT 0x022B
+#define WM_BEGINDRAG 0x022C
+#define WM_DRAGLOOP 0x022D
+#define WM_DRAGSELECT 0x022E
+#define WM_DRAGMOVE 0x022F
+
+#define WM_COMMNOTIFY 0x0044
+#define WM_COALESCE_FIRST 0x0390
+#define WM_COALESCE_LAST 0x039F
+
+#define BOOL BOOL
+
+/*
+ * This is the structure of an entry in a table of message names, numbers
+ * and classes. It is the same structure as SPY uses.
+ */
+typedef struct {
+ char *pchText; /* Message Text */
+ WORD wMsg; /* Message Number */
+ WORD wMask; /* Message Class */
+} MSGINFO;
+
+/*
+ * This is a table of message names, numbers
+ * and classes. It is the same structure as SPY uses.
+ */
+static MSGINFO arMsgInfo[] = {
+ "WM_NULL" ,WM_NULL , msgMaskOther
+ ,"WM_CREATE" ,WM_CREATE , msgMaskWin
+ ,"WM_DESTROY" ,WM_DESTROY , msgMaskWin
+ ,"WM_MOVE" ,WM_MOVE , msgMaskWin
+ ,"WM_SIZE" ,WM_SIZE , msgMaskWin
+ ,"WM_ACTIVATE" ,WM_ACTIVATE , msgMaskWin
+ ,"WM_SETFOCUS" ,WM_SETFOCUS , msgMaskWin
+ ,"WM_KILLFOCUS" ,WM_KILLFOCUS , msgMaskWin
+ ,"WM_ENABLE" ,WM_ENABLE , msgMaskWin
+ ,"WM_SETREDRAW" ,WM_SETREDRAW , msgMaskWin
+ ,"WM_SETTEXT" ,WM_SETTEXT , msgMaskWin
+ ,"WM_GETTEXT" ,WM_GETTEXT , msgMaskWin
+ ,"WM_GETTEXTLENGTH" ,WM_GETTEXTLENGTH , msgMaskWin
+ ,"WM_SETFONT" ,WM_SETFONT , msgMaskWin
+ ,"WM_GETFONT" ,WM_GETFONT , msgMaskWin
+ ,"WM_PAINT" ,WM_PAINT , msgMaskWin
+ ,"WM_CLOSE" ,WM_CLOSE , msgMaskWin
+ ,"WM_QUERYENDSESSION" ,WM_QUERYENDSESSION , msgMaskWin
+ ,"WM_QUIT" ,WM_QUIT , msgMaskWin
+ ,"WM_QUERYOPEN" ,WM_QUERYOPEN , msgMaskWin
+ ,"WM_ERASEBKGND" ,WM_ERASEBKGND , msgMaskWin
+ ,"WM_SYSCOLORCHANGE" ,WM_SYSCOLORCHANGE , msgMaskSys
+ ,"WM_ENDSESSION" ,WM_ENDSESSION , msgMaskSys
+ ,"WM_SHOWWINDOW" ,WM_SHOWWINDOW , msgMaskWin
+ ,"WM_CTLCOLOR" ,WM_CTLCOLOR , msgMaskWin
+ ,"WM_WININICHANGE" ,WM_WININICHANGE , msgMaskSys
+ ,"WM_DEVMODECHANGE" ,WM_DEVMODECHANGE , msgMaskSys
+ ,"WM_ACTIVATEAPP" ,WM_ACTIVATEAPP , msgMaskWin
+ ,"WM_FONTCHANGE" ,WM_FONTCHANGE , msgMaskSys
+ ,"WM_TIMECHANGE" ,WM_TIMECHANGE , msgMaskSys
+ ,"WM_COMPACTING" ,WM_COMPACTING , msgMaskSys
+ ,"WM_COMMNOTIFY" ,WM_COMMNOTIFY , msgMaskSys | msgMaskInput
+ ,"WM_CANCELMODE" ,WM_CANCELMODE , msgMaskWin
+ ,"WM_SETCURSOR" ,WM_SETCURSOR , msgMaskMouse
+ ,"WM_MOUSEACTIVATE" ,WM_MOUSEACTIVATE , msgMaskMouse
+ ,"WM_CHILDACTIVATE" ,WM_CHILDACTIVATE , msgMaskWin
+ ,"WM_QUEUESYNC" ,WM_QUEUESYNC , msgMaskSys
+ ,"WM_GETMINMAXINFO" ,WM_GETMINMAXINFO , msgMaskWin
+ ,"WM_PAINTICON" ,WM_PAINTICON , msgMaskWin
+ ,"WM_ICONERASEBKGND" ,WM_ICONERASEBKGND , msgMaskWin
+ ,"WM_NEXTDLGCTL" ,WM_NEXTDLGCTL , msgMaskWin
+ ,"WM_DRAWITEM" ,WM_DRAWITEM , msgMaskWin
+ ,"WM_MEASUREITEM" ,WM_MEASUREITEM , msgMaskWin
+ ,"WM_DELETEITEM" ,WM_DELETEITEM , msgMaskWin
+ ,"WM_COMPAREITEM" ,WM_COMPAREITEM , msgMaskWin
+ ,"WM_NCCREATE" ,WM_NCCREATE , msgMaskNC
+ ,"WM_NCDESTROY" ,WM_NCDESTROY , msgMaskNC
+ ,"WM_NCCALCSIZE" ,WM_NCCALCSIZE , msgMaskNC
+ ,"WM_NCHITTEST" ,WM_NCHITTEST , msgMaskNC | msgMaskMouse
+ ,"WM_NCPAINT" ,WM_NCPAINT , msgMaskNC
+ ,"WM_NCACTIVATE" ,WM_NCACTIVATE , msgMaskNC
+ ,"WM_GETDLGCODE" ,WM_GETDLGCODE , msgMaskWin
+ ,"WM_NCMOUSEMOVE" ,WM_NCMOUSEMOVE , msgMaskNC | msgMaskMouse
+ ,"WM_NCLBUTTONDOWN" ,WM_NCLBUTTONDOWN , msgMaskNC | msgMaskMouse
+ ,"WM_NCLBUTTONUP" ,WM_NCLBUTTONUP , msgMaskNC | msgMaskMouse
+ ,"WM_NCLBUTTONDBLCLK" ,WM_NCLBUTTONDBLCLK , msgMaskNC | msgMaskMouse
+ ,"WM_NCRBUTTONDOWN" ,WM_NCRBUTTONDOWN , msgMaskNC | msgMaskMouse
+ ,"WM_NCRBUTTONUP" ,WM_NCRBUTTONUP , msgMaskNC | msgMaskMouse
+ ,"WM_NCRBUTTONDBLCLK" ,WM_NCRBUTTONDBLCLK , msgMaskNC | msgMaskMouse
+ ,"WM_NCMBUTTONDOWN" ,WM_NCMBUTTONDOWN , msgMaskNC | msgMaskMouse
+ ,"WM_NCMBUTTONUP" ,WM_NCMBUTTONUP , msgMaskNC | msgMaskMouse
+ ,"WM_NCMBUTTONDBLCLK" ,WM_NCMBUTTONDBLCLK , msgMaskNC | msgMaskMouse
+ ,"WM_KEYDOWN" ,WM_KEYDOWN , msgMaskInput
+ ,"WM_KEYUP" ,WM_KEYUP , msgMaskInput
+ ,"WM_CHAR" ,WM_CHAR , msgMaskInput
+ ,"WM_DEADCHAR" ,WM_DEADCHAR , msgMaskInput
+ ,"WM_SYSKEYDOWN" ,WM_SYSKEYDOWN , msgMaskSys | msgMaskInput
+ ,"WM_SYSKEYUP" ,WM_SYSKEYUP , msgMaskSys | msgMaskInput
+ ,"WM_SYSCHAR" ,WM_SYSCHAR , msgMaskSys | msgMaskInput
+ ,"WM_SYSDEADCHAR" ,WM_SYSDEADCHAR , msgMaskSys | msgMaskInput
+ ,"WM_INITDIALOG" ,WM_INITDIALOG , msgMaskInit
+ ,"WM_COMMAND" ,WM_COMMAND , msgMaskInput
+ ,"WM_SYSCOMMAND" ,WM_SYSCOMMAND , msgMaskSys
+ ,"WM_TIMER" ,WM_TIMER , msgMaskInput
+ ,"WM_HSCROLL" ,WM_HSCROLL , msgMaskInput
+ ,"WM_VSCROLL" ,WM_VSCROLL , msgMaskInput
+ ,"WM_INITMENU" ,WM_INITMENU , msgMaskInit
+ ,"WM_INITMENUPOPUP" ,WM_INITMENUPOPUP , msgMaskInit
+ ,"WM_MENUSELECT" ,WM_MENUSELECT , msgMaskInput
+ ,"WM_MENUCHAR" ,WM_MENUCHAR , msgMaskInput
+ ,"WM_ENTERIDLE" ,WM_ENTERIDLE , msgMaskSys
+ ,"WM_MOUSEMOVE" ,WM_MOUSEMOVE , msgMaskInput | msgMaskMouse
+ ,"WM_LBUTTONDOWN" ,WM_LBUTTONDOWN , msgMaskInput | msgMaskMouse
+ ,"WM_LBUTTONUP" ,WM_LBUTTONUP , msgMaskInput | msgMaskMouse
+ ,"WM_LBUTTONDBLCLK" ,WM_LBUTTONDBLCLK , msgMaskInput | msgMaskMouse
+ ,"WM_RBUTTONDOWN" ,WM_RBUTTONDOWN , msgMaskInput | msgMaskMouse
+ ,"WM_RBUTTONUP" ,WM_RBUTTONUP , msgMaskInput | msgMaskMouse
+ ,"WM_RBUTTONDBLCLK" ,WM_RBUTTONDBLCLK , msgMaskInput | msgMaskMouse
+ ,"WM_MBUTTONDOWN" ,WM_MBUTTONDOWN , msgMaskInput | msgMaskMouse
+ ,"WM_MBUTTONUP" ,WM_MBUTTONUP , msgMaskInput | msgMaskMouse
+ ,"WM_MBUTTONDBLCLK" ,WM_MBUTTONDBLCLK , msgMaskInput | msgMaskMouse
+ ,"WM_PARENTNOTIFY" ,WM_PARENTNOTIFY , msgMaskInput | msgMaskMouse
+ ,"WM_CUT" ,WM_CUT , msgMaskClip
+ ,"WM_COPY" ,WM_COPY , msgMaskClip
+ ,"WM_PASTE" ,WM_PASTE , msgMaskClip
+ ,"WM_CLEAR" ,WM_CLEAR , msgMaskClip
+ ,"WM_UNDO" ,WM_UNDO , msgMaskClip
+ ,"WM_RENDERFORMAT" ,WM_RENDERFORMAT , msgMaskClip
+ ,"WM_RENDERALLFORMATS" ,WM_RENDERALLFORMATS , msgMaskClip
+ ,"WM_DESTROYCLIPBOARD" ,WM_DESTROYCLIPBOARD , msgMaskClip
+ ,"WM_DRAWCLIPBOARD" ,WM_DRAWCLIPBOARD , msgMaskClip
+ ,"WM_PAINTCLIPBOARD" ,WM_PAINTCLIPBOARD , msgMaskClip
+ ,"WM_VSCROLLCLIPBOARD" ,WM_VSCROLLCLIPBOARD , msgMaskClip
+ ,"WM_SIZECLIPBOARD" ,WM_SIZECLIPBOARD , msgMaskClip
+ ,"WM_ASKCBFORMATNAME" ,WM_ASKCBFORMATNAME , msgMaskClip
+ ,"WM_CHANGECBCHAIN" ,WM_CHANGECBCHAIN , msgMaskClip
+ ,"WM_HSCROLLCLIPBOARD" ,WM_HSCROLLCLIPBOARD , msgMaskClip
+ ,"WM_QUERYNEWPALETTE" ,WM_QUERYNEWPALETTE , msgMaskWin
+ ,"WM_PALETTEISCHANGING",WM_PALETTEISCHANGING , msgMaskWin
+ ,"WM_PALETTECHANGED" ,WM_PALETTECHANGED , msgMaskWin
+ ,"WM_USER" ,WM_USER , msgMaskOther
+ ,"WM_DDE_INITIATE" ,WM_DDE_INITIATE , msgMaskDDE
+ ,"WM_DDE_TERMINATE" ,WM_DDE_TERMINATE , msgMaskDDE
+ ,"WM_DDE_ADVISE" ,WM_DDE_ADVISE , msgMaskDDE
+ ,"WM_DDE_UNADVISE" ,WM_DDE_UNADVISE , msgMaskDDE
+ ,"WM_DDE_ACK" ,WM_DDE_ACK , msgMaskDDE
+ ,"WM_DDE_DATA" ,WM_DDE_DATA , msgMaskDDE
+ ,"WM_DDE_REQUEST" ,WM_DDE_REQUEST , msgMaskDDE
+ ,"WM_DDE_POKE" ,WM_DDE_POKE , msgMaskDDE
+ ,"WM_DDE_EXECUTE" ,WM_DDE_EXECUTE , msgMaskDDE
+ ,"WM_MDICREATE" ,WM_MDICREATE , msgMaskWin
+ ,"WM_MDIDESTROY" ,WM_MDIDESTROY , msgMaskWin
+ ,"WM_MDIACTIVATE" ,WM_MDIACTIVATE , msgMaskWin
+ ,"WM_MDIRESTORE" ,WM_MDIRESTORE , msgMaskWin
+ ,"WM_MDINEXT" ,WM_MDINEXT , msgMaskWin
+ ,"WM_MDIMAXIMIZE" ,WM_MDIMAXIMIZE , msgMaskWin
+ ,"WM_MDITILE" ,WM_MDITILE , msgMaskWin
+ ,"WM_MDICASCADE" ,WM_MDICASCADE , msgMaskWin
+ ,"WM_SPOOLERSTATUS" ,WM_SPOOLERSTATUS , msgMaskOther
+ ,"WM_VKEYTOITEM" ,WM_VKEYTOITEM , msgMaskWin
+ ,"WM_CHARTOITEM" ,WM_CHARTOITEM , msgMaskWin
+ ,"WM_SETFONT" ,WM_SETFONT , msgMaskWin
+ ,"WM_GETFONT" ,WM_GETFONT , msgMaskWin
+ ,"WM_QUERYDRAGICON" ,WM_QUERYDRAGICON , msgMaskWin
+ ,"WM_MDIICONARRANGE" ,WM_MDIICONARRANGE , msgMaskWin
+ ,"WM_MDIGETACTIVE" ,WM_MDIGETACTIVE , msgMaskWin
+ ,"WM_COALESCE_FIRST" ,WM_COALESCE_FIRST , msgMaskSys
+ ,"WM_COALESCE_2" ,WM_COALESCE_FIRST+1 , msgMaskSys
+ ,"WM_COALESCE_3" ,WM_COALESCE_FIRST+2 , msgMaskSys
+ ,"WM_COALESCE_4" ,WM_COALESCE_FIRST+3 , msgMaskSys
+ ,"WM_COALESCE_5" ,WM_COALESCE_FIRST+4 , msgMaskSys
+ ,"WM_COALESCE_6" ,WM_COALESCE_FIRST+5 , msgMaskSys
+ ,"WM_COALESCE_7" ,WM_COALESCE_FIRST+6 , msgMaskSys
+ ,"WM_COALESCE_8" ,WM_COALESCE_FIRST+7 , msgMaskSys
+ ,"WM_COALESCE_9" ,WM_COALESCE_FIRST+8 , msgMaskSys
+ ,"WM_COALESCE_10" ,WM_COALESCE_FIRST+9 , msgMaskSys
+ ,"WM_COALESCE_11" ,WM_COALESCE_FIRST+10 , msgMaskSys
+ ,"WM_COALESCE_12" ,WM_COALESCE_FIRST+11 , msgMaskSys
+ ,"WM_COALESCE_13" ,WM_COALESCE_FIRST+12 , msgMaskSys
+ ,"WM_COALESCE_14" ,WM_COALESCE_FIRST+13 , msgMaskSys
+ ,"WM_COALESCE_15" ,WM_COALESCE_FIRST+14 , msgMaskSys
+ ,"WM_COALESCE_LAST" ,WM_COALESCE_LAST , msgMaskSys
+
+#ifdef INTERNAL
+ ,"WM_SIZEWAIT" ,WM_SIZEWAIT , msgMaskWin
+ ,"WM_SETVISIBLE" ,WM_SETVISIBLE , msgMaskWin
+ ,"WM_SYSTEMERROR" ,WM_SYSTEMERROR , msgMaskSys
+ ,"WM_FILESYSCHANGE" ,WM_FILESYSCHANGE , msgMaskSys
+ ,"WM_ALTTABACTIVE" ,WM_ALTTABACTIVE , msgMaskSys
+ ,"WM_SYNCPAINT" ,WM_SYNCPAINT , msgMaskWin
+ ,"WM_SYNCTASK" ,WM_SYNCTASK , msgMaskWin
+ ,"WM_YOMICHAR" ,WM_YOMICHAR , msgMaskInput
+ ,"WM_CONVERTREQUEST" ,WM_CONVERTREQUEST , msgMaskInput
+ ,"WM_CONVERTRESULT" ,WM_CONVERTRESULT , msgMaskInput
+ ,"WM_SYSTIMER" ,WM_SYSTIMER , msgMaskSys
+ ,"WM_ENTERMENULOOP" ,WM_ENTERMENULOOP , msgMaskSys | msgMaskInput
+ ,"WM_EXITMENULOOP" ,WM_EXITMENULOOP , msgMaskSys | msgMaskInput
+ ,"WM_ENTERSIZEMOVE" ,WM_ENTERSIZEMOVE , msgMaskSys | msgMaskInput
+ ,"WM_EXITSIZEMOVE" ,WM_EXITSIZEMOVE , msgMaskSys | msgMaskInput
+ ,"WM_YOMICHAR" ,WM_YOMICHAR , msgMaskOther
+ ,"WM_CONVERTREQUEST" ,WM_CONVERTREQUEST , msgMaskOther
+ ,"WM_CONVERTRESULT" ,WM_CONVERTRESULT , msgMaskOther
+ ,"WM_ISACTIVEICON" ,WM_ISACTIVEICON , msgMaskWin
+ ,"WM_QUERYPARKICON" ,WM_QUERYPARKICON , msgMaskWin
+ ,"WM_DROPOBJECT" ,WM_DROPOBJECT , msgMaskWin
+ ,"WM_QUERYDROPOBJECT" ,WM_QUERYDROPOBJECT , msgMaskWin
+ ,"WM_BEGINDRAG" ,WM_BEGINDRAG , msgMaskWin
+ ,"WM_DRAGLOOP" ,WM_DRAGLOOP , msgMaskWin
+ ,"WM_DRAGSELECT" ,WM_DRAGSELECT , msgMaskWin
+ ,"WM_DRAGMOVE" ,WM_DRAGMOVE , msgMaskWin
+ ,"WM_TESTING" ,WM_TESTING , msgMaskSys
+#endif
+
+ ,NULL,0,0
+};
+#elif defined(OS2)
+
+/*
+ * Define Message output information
+ */
+
+#define MSGI_ENABLED 0x0001
+#define MSGI_MOUSE 0x0002 /* Mouse type messages */
+#define MSGI_KEY 0x0004 /* Key type messages */
+#define MSGI_FREQ 0x0010 /* Frequent messages generaly ignored */
+
+#define MPT_NORMAL 0x00
+#define MPT_SWP 0x01
+#define MPT_RECTL 0x02
+#define MPT_WNDPRMS 0x03
+#define MPT_QMSG 0x04
+#define MP_ENABLED 0x80
+#define MP_MASK 0x07
+#define MPTS(mp1,mp2) ((UCHAR)mp2 << 3 | (UCHAR)mp1)
+
+typedef struct {
+ USHORT wMsg;
+ char *pchText;
+ USHORT wOptions;
+ UCHAR bMPTypes;
+ SHORT iListBox;
+} MSGINFO;
+
+static MSGINFO arMsgInfo[] = {
+ // WM_NULL not currently support by CV
+ {0x0001, "WM_CREATE", MSGI_ENABLED, 0, 0},
+ {0x0002, "WM_DESTROY", MSGI_ENABLED, 0, 0},
+ {0x0004, "WM_ENABLE", MSGI_ENABLED, 0, 0},
+ {0x0005, "WM_SHOW", MSGI_ENABLED, 0, 0},
+ {0x0006, "WM_MOVE", MSGI_ENABLED, 0, 0},
+ {0x0007, "WM_SIZE", MSGI_ENABLED, 0, 0},
+ {0x0008, "WM_ADJUSTWINDOWPOS", MSGI_ENABLED, MPTS(MPT_SWP, 0), 0},
+ {0x0009, "WM_CALCVALIDRECTS", MSGI_ENABLED, MPTS(MPT_RECTL, MPT_SWP), 0},
+ {0x000a, "WM_SETWINDOWPARAMS", MSGI_ENABLED, MPTS(MPT_WNDPRMS, 0), 0},
+ {0x000b, "WM_QUERYWINDOWPARAMS", MSGI_ENABLED, 0, 0},
+ {0x000c, "WM_HITTEST", MSGI_FREQ, 0, 0},
+ {0x000d, "WM_ACTIVATE", MSGI_ENABLED, 0, 0},
+ {0x000f, "WM_SETFOCUS", MSGI_ENABLED, 0, 0},
+ {0x0010, "WM_SETSELECTION", MSGI_ENABLED, 0, 0},
+ {0x0020, "WM_COMMAND", MSGI_ENABLED, 0, 0},
+ {0x0021, "WM_SYSCOMMAND", MSGI_ENABLED, 0, 0},
+ {0x0022, "WM_HELP", MSGI_ENABLED, 0, 0},
+ {0x0023, "WM_PAINT", MSGI_ENABLED, 0, 0},
+ {0x0024, "WM_TIMER", MSGI_FREQ, 0, 0},
+ {0x0025, "WM_SEM1", MSGI_ENABLED, 0, 0},
+ {0x0026, "WM_SEM2", MSGI_ENABLED, 0, 0},
+ {0x0027, "WM_SEM3", MSGI_ENABLED, 0, 0},
+ {0x0028, "WM_SEM4", MSGI_ENABLED, 0, 0},
+ {0x0029, "WM_CLOSE", MSGI_ENABLED, 0, 0},
+ {0x002a, "WM_QUIT", MSGI_ENABLED, 0, 0},
+ {0x002b, "WM_SYSCOLORCHANGE", MSGI_ENABLED, 0, 0},
+ {0x002d, "WM_SYSVALUECHANGED", MSGI_ENABLED, 0, 0},
+ {0x0030, "WM_CONTROL", MSGI_ENABLED, 0, 0},
+ {0x0031, "WM_VSCROLL", MSGI_ENABLED, 0, 0},
+ {0x0032, "WM_HSCROLL", MSGI_ENABLED, 0, 0},
+ {0x0033, "WM_INITMENU", MSGI_ENABLED, 0, 0},
+ {0x0034, "WM_MENUSELECT", MSGI_ENABLED, 0, 0},
+ {0x0035, "WM_MENUEND", MSGI_ENABLED, 0, 0},
+ {0x0036, "WM_DRAWITEM", MSGI_ENABLED, 0, 0},
+ {0x0037, "WM_MEASUREITEM", MSGI_ENABLED, 0, 0},
+ {0x0038, "WM_CONTROLPOINTER", MSGI_FREQ, 0, 0},
+ {0x0039, "WM_CONTROLHEAP", MSGI_ENABLED, 0, 0},
+ {0x003a, "WM_QUERYDLGCODE", MSGI_ENABLED, 0, 0},
+ {0x003b, "WM_INITDLG", MSGI_ENABLED, 0, 0},
+ {0x003c, "WM_SUBSTITUTESTRING", MSGI_ENABLED, 0, 0},
+ {0x003d, "WM_MATCHMNEMONIC", MSGI_ENABLED, 0, 0},
+ {0x0040, "WM_FLASHWINDOW", MSGI_ENABLED, 0, 0},
+ {0x0041, "WM_FORMATFRAME", MSGI_ENABLED, 0, 0},
+ {0x0042, "WM_UPDATEFRAME", MSGI_ENABLED, 0, 0},
+ {0x0043, "WM_FOCUSCHANGE", MSGI_ENABLED, 0, 0},
+ {0x0044, "WM_SETBORDERSIZE", MSGI_ENABLED, 0, 0},
+ {0x0045, "WM_TRACKFRAME", MSGI_ENABLED, 0, 0},
+ {0x0046, "WM_MINMAXFRAME", MSGI_ENABLED, MPTS(MPT_SWP, 0), 0},
+ {0x0047, "WM_SETICON", MSGI_ENABLED, 0, 0},
+ {0x0048, "WM_QUERYICON", MSGI_ENABLED, 0, 0},
+ {0x0049, "WM_SETACCELTABLE", MSGI_ENABLED, 0, 0},
+ {0x004a, "WM_QUERYACCELTABLE", MSGI_ENABLED, 0, 0},
+ {0x004b, "WM_TRANSLATEACCEL", MSGI_ENABLED, MPTS(MPT_QMSG, 0), 0},
+ {0x004c, "WM_QUERYTRACKINFO", MSGI_ENABLED, 0, 0},
+ {0x004d, "WM_QUERYBORDERSIZE", MSGI_ENABLED, 0, 0},
+ {0x004e, "WM_NEXTMENU", MSGI_ENABLED, 0, 0},
+ {0x004f, "WM_ERASEBACKGROUND", MSGI_ENABLED, MPTS(MPT_RECTL, 0), 0},
+ {0x0050, "WM_QUERYFRAMEINFO", MSGI_ENABLED, 0, 0},
+ {0x0051, "WM_QUERYFOCUSCHAIN", MSGI_ENABLED, MPTS(MPT_SWP, 0), 0},
+ {0x0053, "WM_CALCFRAMERECT", MSGI_ENABLED, MPTS(MPT_RECTL, 0), 0},
+ {0x0059, "WM_QUERYFRAMECTLCOUNT", MSGI_ENABLED, 0, 0},
+ {0x0060, "WM_RENDERFMT", MSGI_ENABLED, 0, 0},
+ {0x0061, "WM_RENDERALLFMTS", MSGI_ENABLED, 0, 0},
+ {0x0062, "WM_DESTROYCLIPBOARD", MSGI_ENABLED, 0, 0},
+ {0x0063, "WM_PAINTCLIPBOARD", MSGI_ENABLED, 0, 0},
+ {0x0064, "WM_SIZECLIPBOARD", MSGI_ENABLED, 0, 0},
+ {0x0065, "WM_HSCROLLCLIPBOARD", MSGI_ENABLED, 0, 0},
+ {0x0066, "WM_VSCROLLCLIPBOARD", MSGI_ENABLED, 0, 0},
+ {0x0067, "WM_DRAWCLIPBOARD", MSGI_ENABLED, 0, 0},
+ {0x0070, "WM_MOUSEMOVE", MSGI_FREQ| MSGI_MOUSE, 0, 0},
+ {0x0071, "WM_BUTTON1DOWN", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0072, "WM_BUTTON1UP", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0073, "WM_BUTTON1DBLCLK", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0074, "WM_BUTTON2DOWN", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0075, "WM_BUTTON2UP", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0076, "WM_BUTTON2DBLCLK", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0077, "WM_BUTTON3DOWN", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0078, "WM_BUTTON3UP", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x0079, "WM_BUTTON3DBLCLK", MSGI_ENABLED| MSGI_MOUSE, 0, 0},
+ {0x007a, "WM_CHAR", MSGI_ENABLED | MSGI_KEY, 0, 0},
+ {0x00A0, "WM_DDE_INITIATE", MSGI_ENABLED, 0, 0},
+ {0x00A1, "WM_DDE_REQUEST", MSGI_ENABLED, 0, 0},
+ {0x00A2, "WM_DDE_ACK", MSGI_ENABLED, 0, 0},
+ {0x00A3, "WM_DDE_DATA", MSGI_ENABLED, 0, 0},
+ {0x00A4, "WM_DDE_ADVISE", MSGI_ENABLED, 0, 0},
+ {0x00A5, "WM_DDE_UNADVISE", MSGI_ENABLED, 0, 0},
+ {0x00A6, "WM_DDE_POKE", MSGI_ENABLED, 0, 0},
+ {0x00A7, "WM_DDE_EXECUTE", MSGI_ENABLED, 0, 0},
+ {0x00A8, "WM_DDE_TERMINATE", MSGI_ENABLED, 0, 0},
+ {0x00A9, "WM_DDE_INITIATEACK", MSGI_ENABLED, 0, 0},
+ {0x00af, "WM_DDE_LAST", MSGI_ENABLED, 0, 0},
+ {0x00b0, "WM_QUERYCONVERTPOS", MSGI_ENABLED, 0, 0},
+ {0x0120, "BM_CLICK", MSGI_ENABLED, 0, 0},
+ {0x0121, "BM_QUERYCHECKINDEX", MSGI_ENABLED, 0, 0},
+ {0x0122, "BM_QUERYHILITE", MSGI_ENABLED, 0, 0},
+ {0x0123, "BM_SETHILITE", MSGI_ENABLED, 0, 0},
+ {0x0124, "BM_QUERYCHECK", MSGI_ENABLED, 0, 0},
+ {0x0125, "BM_SETCHECK", MSGI_ENABLED, 0, 0},
+ {0x0126, "BM_SETDEFAULT", MSGI_ENABLED, 0, 0},
+ {0x0140, "EM_QUERYCHANGED", MSGI_ENABLED, 0, 0},
+ {0x0141, "EM_QUERYSEL", MSGI_ENABLED, 0, 0},
+ {0x0142, "EM_SETSEL", MSGI_ENABLED, 0, 0},
+ {0x0143, "EM_SETTEXTLIMIT", MSGI_ENABLED, 0, 0},
+ {0x0144, "EM_CUT", MSGI_ENABLED, 0, 0},
+ {0x0145, "EM_COPY", MSGI_ENABLED, 0, 0},
+ {0x0146, "EM_CLEAR", MSGI_ENABLED, 0, 0},
+ {0x0147, "EM_PASTE", MSGI_ENABLED, 0, 0},
+ {0x0148, "EM_QUERYFIRSTCHAR", MSGI_ENABLED, 0, 0},
+ {0x0149, "EM_SETFIRSTCHAR", MSGI_ENABLED, 0, 0},
+ {0x0160, "LM_QUERYITEMCOUNT", MSGI_ENABLED, 0, 0},
+ {0x0161, "LM_INSERTITEM", MSGI_ENABLED, 0, 0},
+ {0x0162, "LM_SETTOPINDEX", MSGI_ENABLED, 0, 0},
+ {0x0163, "LM_DELETEITEM", MSGI_ENABLED, 0, 0},
+ {0x0164, "LM_SELECTITEM", MSGI_ENABLED, 0, 0},
+ {0x0165, "LM_QUERYSELECTION", MSGI_ENABLED, 0, 0},
+ {0x0166, "LM_SETITEMTEXT", MSGI_ENABLED, 0, 0},
+ {0x0167, "LM_QUERYITEMTEXTLENGTH", MSGI_ENABLED, 0, 0},
+ {0x0168, "LM_QUERYITEMTEXT", MSGI_ENABLED, 0, 0},
+ {0x0169, "LM_SETITEMHANDLE", MSGI_ENABLED, 0, 0},
+ {0x016a, "LM_QUERYITEMHANDLE", MSGI_ENABLED, 0, 0},
+ {0x016b, "LM_SEARCHSTRING", MSGI_ENABLED, 0, 0},
+ {0x016c, "LM_SETITEMHEIGHT", MSGI_ENABLED, 0, 0},
+ {0x016d, "LM_QUERYTOPINDEX", MSGI_ENABLED, 0, 0},
+ {0x016e, "LM_DELETEALL", MSGI_ENABLED, 0, 0},
+ {0x0180, "MM_INSERTITEM", MSGI_ENABLED, 0, 0},
+ {0x0181, "MM_DELETEITEM", MSGI_ENABLED, 0, 0},
+ {0x0182, "MM_QUERYITEM", MSGI_ENABLED, 0, 0},
+ {0x0183, "MM_SETITEM", MSGI_ENABLED, 0, 0},
+ {0x0184, "MM_QUERYITEMCOUNT", MSGI_ENABLED, 0, 0},
+ {0x0185, "MM_STARTMENUMODE", MSGI_ENABLED, 0, 0},
+ {0x0186, "MM_ENDMENUMODE", MSGI_ENABLED, 0, 0},
+ {0x0187, "MM_DISMISSMENU", MSGI_ENABLED, 0, 0},
+ {0x0188, "MM_REMOVEITEM", MSGI_ENABLED, 0, 0},
+ {0x0189, "MM_SELECTITEM", MSGI_ENABLED, 0, 0},
+ {0x018a, "MM_QUERYSELITEMID", MSGI_ENABLED, 0, 0},
+ {0x018b, "MM_QUERYITEMTEXT", MSGI_ENABLED, 0, 0},
+ {0x018c, "MM_QUERYITEMTEXTLENGTH", MSGI_ENABLED, 0, 0},
+ {0x018d, "MM_SETITEMHANDLE", MSGI_ENABLED, 0, 0},
+ {0x018e, "MM_SETITEMTEXT", MSGI_ENABLED, 0, 0},
+ {0x018f, "MM_ITEMPOSITIONFROMID", MSGI_ENABLED, 0, 0},
+ {0x0190, "MM_ITEMIDFROMPOSITION", MSGI_ENABLED, 0, 0},
+ {0x0191, "MM_QUERYITEMATTR", MSGI_ENABLED, 0, 0},
+ {0x0192, "MM_SETITEMATTR", MSGI_ENABLED, 0, 0},
+ {0x0193, "MM_ISITEMVALID", MSGI_ENABLED, 0, 0},
+ {0x01a0, "SBM_SETSCROLLBAR", MSGI_ENABLED, 0, 0},
+ {0x01a1, "SBM_SETPOS", MSGI_ENABLED, 0, 0},
+ {0x01a2, "SBM_QUERYPOS", MSGI_ENABLED, 0, 0},
+ {0x01a3, "SBM_QUERYRANGE", MSGI_ENABLED, 0, 0},
+ {0x01a4, "SBM_SETHILITE", MSGI_ENABLED, 0, 0},
+ {0x01a5, "SBM_QUERYHILITE", MSGI_ENABLED, 0, 0},
+ {0x01e3, "TBM_SETHILITE", MSGI_ENABLED, 0, 0},
+ {0x01e4, "TBM_QUERYHILITE", MSGI_ENABLED, 0, 0},
+ {0x0000, NULL, 0, 0, 0}
+};
+
+#endif
+
+
+
+/***********************************************************************
+ *
+ * WMSGFarStringCompare
+ *
+ *
+ * Purpose: Determine if two far strings are equal
+ *
+ * Input: lpchTo - Pointer to one of the strings
+ * lpchFrom - Pointer to the other string
+ *
+ * Returns TRUE if the strings match
+ *
+ * Exceptions: None
+ *
+ *
+ ************************************************************************
+ */
+
+int WMSGFarStringCompare(char far *lpchTo, char far *lpchFrom)
+{
+ do {
+ if(*lpchTo++ != *lpchFrom) {
+ if((!lpchTo[-1] || (lpchTo[-1] == ';')) &&
+ (!*lpchFrom || (*lpchFrom == ';'))) return(TRUE);
+ return(FALSE);
+ }
+ } while(*lpchFrom++);
+ return(TRUE);
+}
+
+/***********************************************************************
+ *
+ * WMSGFarStringCopy
+ *
+ *
+ * Purpose: Copies a far string to a far buffer
+ *
+ * Input: lpchTo - Pointer to the buffer
+ * lpchFrom - Pointer to the string
+ *
+ * Returns The number of characters copied (excluding the terminator)
+ *
+ * Exceptions: None
+ *
+ *
+ ************************************************************************
+ */
+
+int WMSGFarStringCopy(char far *lpchTo, char far *lpchFrom)
+{
+ int wResult;
+
+ for(wResult = 0;*lpchTo++ = *lpchFrom++;wResult++);
+ return(wResult);
+}
+
+/***********************************************************************
+ *
+ * WMSGTranslate
+ *
+ *
+ * Purpose: Translate from text to messages and classes, or from a message
+ * number to class and text.
+ *
+ * Input: lpwMsg - Used to specify or return a message number
+ * lpwType - Used to return msgTypeClass or msgTypeType. If lpwType is
+ * NULL the callis to translate FROM a message type number
+ * szMessage- A buffer for the message name
+ * lpWmask - Used to return the class of the message
+ *
+ * Returns TRUE if the message was found
+ *
+ * Exceptions: The message name is filled in as User_Message of no find
+ *
+ *
+ ************************************************************************
+ */
+
+WORD WMSGTranslate( LPW lpwMsg, LPW lpwType, LSZ szMsg, LPW lpwMask) {
+ int fContinue;
+ int static fInit = FALSE;
+ int static cMsg;
+ int iMsgLast,iMsgFirst,iMsgCur;
+ MSGINFO *pMSGINFO = arMsgInfo,Temp;
+
+ if(!fInit) {
+ fInit = TRUE;
+/*
+ * Bubble sort the table This is probably not needed
+ */
+ do {
+ fContinue = FALSE;
+ for( pMSGINFO = arMsgInfo; (++pMSGINFO)->pchText; ) {
+ if(pMSGINFO->wMsg < pMSGINFO[-1].wMsg) {
+ Temp = pMSGINFO[-1];
+ pMSGINFO[-1] = *pMSGINFO;
+ *pMSGINFO = Temp;
+ fContinue = TRUE;
+ }
+ }
+ cMsg = pMSGINFO - arMsgInfo;
+ pMSGINFO = arMsgInfo;
+ } while(fContinue);
+ }
+ if(lpwType) {
+/*
+ * We are being asked to translate user text into a message type number
+ * or a union of message classes.
+ * First look for a message name match
+ */
+
+ for(;pMSGINFO->pchText; pMSGINFO++) {
+
+ if(WMSGFarStringCompare(szMsg,(char far *)(pMSGINFO->pchText))) {
+/*
+ * Message type name found
+ */
+ *lpwType = msgTypeType;
+ *lpwMsg = pMSGINFO->wMsg;
+ return(TRUE);
+ }
+ }
+/*
+ * No specific message type found. Translate into a union of classes
+ */
+ *lpwType = msgTypeClass;
+ *lpwMsg = 0;
+ do {
+ switch(*szMsg++) {
+ case 'm': *lpwMsg |= msgMaskMouse; break;
+ case 'w': *lpwMsg |= msgMaskWin; break;
+ case 'n': *lpwMsg |= msgMaskInput; break;
+ case 's': *lpwMsg |= msgMaskSys; break;
+ case 'i': *lpwMsg |= msgMaskInit; break;
+ case 'c': *lpwMsg |= msgMaskClip; break;
+ case 'd': *lpwMsg |= msgMaskDDE; break;
+ case 'z': *lpwMsg |= msgMaskNC; break;
+ case 'M': *lpwMsg |= msgMaskMouse; break;
+ case 'W': *lpwMsg |= msgMaskWin; break;
+ case 'N': *lpwMsg |= msgMaskInput; break;
+ case 'S': *lpwMsg |= msgMaskSys; break;
+ case 'I': *lpwMsg |= msgMaskInit; break;
+ case 'C': *lpwMsg |= msgMaskClip; break;
+ case 'D': *lpwMsg |= msgMaskDDE; break;
+ case 'Z': *lpwMsg |= msgMaskNC; break;
+
+ case ' ': case '\0': case ';': return(TRUE);
+
+ default: return(FALSE);
+ }
+ } while(TRUE);
+ }
+ else {
+/*
+ * We are being asked to look up a message type number.
+ * Do a binary search.
+ */
+ iMsgFirst = 0;
+ iMsgLast = cMsg;
+ while(iMsgFirst < iMsgLast) {
+ iMsgCur = (iMsgFirst + iMsgLast) >> 1;
+ if(*lpwMsg < arMsgInfo[iMsgCur].wMsg) {
+ iMsgLast = iMsgCur;
+ }
+ else if(*lpwMsg > arMsgInfo[iMsgCur].wMsg) {
+ iMsgFirst = iMsgCur + 1;
+ }
+ else {
+/*
+ * We found the message. Set up return buffers.
+ */
+#if defined(WIN)
+ if(lpwMask) *lpwMask = arMsgInfo[iMsgCur].wMask;
+#endif
+ if(szMsg) WMSGFarStringCopy(szMsg,(char far *)arMsgInfo[iMsgCur].pchText);
+ return(TRUE);
+ }
+ }
+ }
+/*
+ * Message not recognized - return a default value
+ */
+ if(szMsg) WMSGFarStringCopy(szMsg,"User_Message");
+ if(lpwMask) *lpwMask = 0;
+ return(FALSE);
+}
+
+#endif // defined (WIN) || defined (OS2)
diff --git a/private/windbg/lib/assrt.c b/private/windbg/lib/assrt.c
new file mode 100644
index 000000000..945793461
--- /dev/null
+++ b/private/windbg/lib/assrt.c
@@ -0,0 +1,31 @@
+/***
+*assrt.c - assertions needed for string conversion routines
+*
+* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Make sure that the data types used by the string conversion
+* routines have the right size. If this file does not compile,
+* the type definitions in cv.h should change appropriately.
+*
+*Revision History:
+* 07-25-91 GDP written
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+
+#include "cv.h"
+
+static void assertion_test(void)
+{
+ sizeof(u_char) == 1 ? 0 : 1/0,
+ sizeof(u_short) == 2 ? 0 : 1/0,
+ sizeof(u_long) == 4 ? 0 : 1/0,
+ sizeof(s_char) == 1 ? 0 : 1/0,
+ sizeof(s_short) == 2 ? 0 : 1/0,
+ sizeof(s_long) == 4 ? 0 : 1/0;
+#ifdef _ULDSUPPORT
+ sizeof(long double) == 10 ? 0 : 1/0;
+#endif
+}
diff --git a/private/windbg/lib/atold.c b/private/windbg/lib/atold.c
new file mode 100644
index 000000000..fa9e035a4
--- /dev/null
+++ b/private/windbg/lib/atold.c
@@ -0,0 +1,54 @@
+/***
+*atold.c - convert char string to long double
+*
+* Copyright (c) 1989-1989, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts a character string into a long double.
+*
+*Revision History:
+* 03-09-89 WAJ Initial version.
+* 06-05-89 WAJ Made changes for C6 compiler.
+* 05-17-91 WAJ Now uses long double.
+* 07-22-91 GDP Now uses _ULDOUBLE so that it can be used
+* even if 'long double' is not supported.
+* It also uses the C version of __strgtold()
+* 04-30-92 GDP Now calls _atoldbl
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+#include "cv.h"
+
+
+
+/***
+*_ULDOUBLE _atold( char * string ) - convert string to a long double
+*
+*Purpose:
+* _atold() recognizes an optional string of whitespace, then
+* an optional sign, then a string of digits optionally
+* containing a decimal point, then an optional e or E followed
+* by an optionally signed integer, and converts all this to
+* to a long double. The first unrecognized character ends the string.
+*
+*Entry:
+* string - pointer to string to convert
+*
+*Exit:
+* returns long double value of character representation
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+_ULDOUBLE _atold(char * string )
+{
+ _ULDOUBLE x;
+
+ _atoldbl( (_ULDOUBLE *)&x, string);
+
+ return( x );
+}
+
diff --git a/private/windbg/lib/cfin.c b/private/windbg/lib/cfin.c
new file mode 100644
index 000000000..15582de0b
--- /dev/null
+++ b/private/windbg/lib/cfin.c
@@ -0,0 +1,73 @@
+/***
+*cfin.c - Encode interface for C
+*
+* Copyright (c) 19xx-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 07-20-91 GDP Ported to C from assembly
+* 04-30-92 GDP use __strgtold12 and _ld12tod
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+#include <string.h>
+#include "cv.h"
+
+
+
+
+#ifndef MTHREAD
+static struct _flt ret;
+static FLT flt = &ret;
+#endif
+
+/* The only three conditions that this routine detects */
+#define CFIN_NODIGITS 512
+#define CFIN_OVERFLOW 128
+#define CFIN_UNDERFLOW 256
+
+/* This version ignores the last two arguments (radix and scale)
+ * Input string should be null terminated
+ * len is also ignored
+ */
+#ifdef MTHREAD
+FLT _fltin2(FLT flt, const char *str, int len_ignore, int scale_ignore, int radix_ignore)
+#else
+FLT _fltin(const char *str, int len_ignore, int scale_ignore, int radix_ignore)
+#endif
+{
+ _ULDBL12 ld12;
+ UDOUBLE x;
+ char *EndPtr;
+ unsigned flags;
+ int retflags = 0;
+
+ flags = __strgtold12(&ld12, &EndPtr, (char *)str, 0);
+ if (flags & SLD_NODIGITS) {
+ retflags |= CFIN_NODIGITS;
+ *(u_long *)&x = 0;
+ *((u_long *)&x+1) = 0;
+ }
+ else {
+ INTRNCVT_STATUS intrncvt;
+
+ intrncvt = _ld12tod(&ld12, &x);
+
+ if (flags & SLD_OVERFLOW ||
+ intrncvt == INTRNCVT_OVERFLOW) {
+ retflags |= CFIN_OVERFLOW;
+ }
+ if (flags & SLD_UNDERFLOW ||
+ intrncvt == INTRNCVT_UNDERFLOW) {
+ retflags |= CFIN_UNDERFLOW;
+ }
+ }
+
+ flt->flags = retflags;
+ flt->nbytes = EndPtr - (char *)str;
+ flt->dval = *(double *)&x;
+
+ return flt;
+}
diff --git a/private/windbg/lib/cfout.c b/private/windbg/lib/cfout.c
new file mode 100644
index 000000000..94814be20
--- /dev/null
+++ b/private/windbg/lib/cfout.c
@@ -0,0 +1,132 @@
+/***
+*cfout.c - Encode interface for C
+*
+* Copyright (c) 19xx-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 07-20-91 GDP Ported to C from assembly
+* 04-30-92 GDP Added _dtold routine (moved here from ldtod.c)
+* 05-14-92 GDP NDIGITS is now 17 (instead of 16)
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+
+#include <string.h>
+#include "cv.h"
+
+
+
+
+#define NDIGITS 17
+
+void __dtold(_ULDOUBLE *pld, UDOUBLE *px);
+
+
+#ifndef MTHREAD
+static struct _strflt ret;
+static FOS fos;
+#endif
+
+#ifdef MTHREAD
+STRFLT _fltout2(UDOUBLE x, STRFLT flt, char *resultstr)
+{
+ _ULDOUBLE ld;
+ FOS autofos;
+
+ __dtold(&ld, &x);
+ flt->flag = $I10_OUTPUT(ld,NDIGITS,0,&autofos);
+ flt->sign = autofos.sign;
+ flt->decpt = autofos.exp;
+ strcpy(resultstr,autofos.man);
+ flt->mantissa = resultstr;
+
+ return flt;
+}
+
+#else
+
+STRFLT _fltout(UDOUBLE x)
+{
+ _ULDOUBLE ld;
+
+ __dtold(&ld, &x);
+ ret.flag = $I10_OUTPUT(ld,NDIGITS,0,&fos);
+ ret.sign = fos.sign;
+ ret.decpt = fos.exp;
+ ret.mantissa = fos.man;
+
+ return &ret;
+}
+
+#endif
+
+
+
+
+/***
+* __dtold - convert a double into a _ULDOUBLE
+*
+*Purpose: Use together with i10_output() to get string conversion
+* for double
+*
+*Entry: double *px
+*
+*Exit: the corresponding _ULDOUBLE value is returned in *pld
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __dtold(_ULDOUBLE *pld, UDOUBLE *px)
+{
+ u_short exp;
+ u_short sign;
+ u_long manhi, manlo;
+ u_long msb = MSB_ULONG;
+ u_short ldexp = 0;
+
+ exp = (*U_SHORT4_D(px) & (u_short)0x7ff0) >> 4;
+ sign = *U_SHORT4_D(px) & (u_short)0x8000;
+ manhi = *UL_HI_D(px) & 0xfffff;
+ manlo = *UL_LO_D(px);
+
+ switch (exp) {
+ case D_MAXEXP:
+ ldexp = LD_MAXEXP;
+ break;
+ case 0:
+ /* check for zero */
+ if (manhi == 0 && manlo == 0) {
+ *UL_MANHI_LD(pld) = 0;
+ *UL_MANLO_LD(pld) = 0;
+ *U_EXP_LD(pld) = 0;
+ return;
+ }
+ /* we have a denormal -- we'll normalize later */
+ ldexp = (u_short) ((s_short)exp - D_BIAS + LD_BIAS + 1);
+ msb = 0;
+ break;
+ default:
+ exp -= D_BIAS;
+ ldexp = (u_short) ((s_short)exp + LD_BIAS);
+ break;
+ }
+
+ *UL_MANHI_LD(pld) = msb | manhi << 11 | manlo >> 21;
+ *UL_MANLO_LD(pld) = manlo << 11;
+
+ /* normalize if necessary */
+ while ((*UL_MANHI_LD(pld) & MSB_ULONG) == 0) {
+ /* shift left */
+ *UL_MANHI_LD(pld) = *UL_MANHI_LD(pld) << 1 |
+ (MSB_ULONG & *UL_MANLO_LD(pld) ? 1: 0);
+ (*UL_MANLO_LD(pld)) <<= 1;
+ ldexp --;
+ }
+
+ *U_EXP_LD(pld) = sign | ldexp;
+
+}
diff --git a/private/windbg/lib/constpow.c b/private/windbg/lib/constpow.c
new file mode 100644
index 000000000..d8fb3156c
--- /dev/null
+++ b/private/windbg/lib/constpow.c
@@ -0,0 +1,161 @@
+/***
+*constpow.c - constant powers of ten
+*
+* Copyright (c) 19xx-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Provide powers of ten in long double form:
+* 10^(2^i), i=0,1,2,...
+*
+*Revision History:
+* 7-17-91 GDP Initial version (ported from assembly)
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+
+#include "cv.h"
+
+
+
+/* Format: A 10 byte long double + 2 bytes of extra precision
+ * If the extra precision is desired, the 10-byte long double
+ * should be "unrounded" first.
+ * This may change in later versions
+ */
+
+#ifdef L_END
+
+_ULDBL12 _pow10pos[] = {
+ /*P0001*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0x02,0x40}},
+ /*P0002*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x05,0x40}},
+ /*P0003*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFA,0x08,0x40}},
+ /*P0004*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9C,0x0C,0x40}},
+ /*P0005*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xC3,0x0F,0x40}},
+ /*P0006*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xF4,0x12,0x40}},
+ /*P0007*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x80,0x96,0x98,0x16,0x40}},
+ /*P0008*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x20,0xBC,0xBE,0x19,0x40}},
+ /*P0016*/ {{0x00,0x00, 0x00,0x00,0x00,0x04,0xBF,0xC9,0x1B,0x8E,0x34,0x40}},
+ /*P0024*/ {{0x00,0x00, 0x00,0xA1,0xED,0xCC,0xCE,0x1B,0xC2,0xD3,0x4E,0x40}},
+ /*P0032*/ {{0x20,0xF0, 0x9E,0xB5,0x70,0x2B,0xA8,0xAD,0xC5,0x9D,0x69,0x40}},
+ /*P0040*/ {{0xD0,0x5D, 0xFD,0x25,0xE5,0x1A,0x8E,0x4F,0x19,0xEB,0x83,0x40}},
+ /*P0048*/ {{0x71,0x96, 0xD7,0x95,0x43,0x0E,0x05,0x8D,0x29,0xAF,0x9E,0x40}},
+ /*P0056*/ {{0xF9,0xBF, 0xA0,0x44,0xED,0x81,0x12,0x8F,0x81,0x82,0xB9,0x40}},
+ /*P0064*/ {{0xBF,0x3C, 0xD5,0xA6,0xCF,0xFF,0x49,0x1F,0x78,0xC2,0xD3,0x40}},
+ /*P0128*/ {{0x6F,0xC6, 0xE0,0x8C,0xE9,0x80,0xC9,0x47,0xBA,0x93,0xA8,0x41}},
+ /*P0192*/ {{0xBC,0x85, 0x6B,0x55,0x27,0x39,0x8D,0xF7,0x70,0xE0,0x7C,0x42}},
+ /*P0256*/ {{0xBC,0xDD, 0x8E,0xDE,0xF9,0x9D,0xFB,0xEB,0x7E,0xAA,0x51,0x43}},
+ /*P0320*/ {{0xA1,0xE6, 0x76,0xE3,0xCC,0xF2,0x29,0x2F,0x84,0x81,0x26,0x44}},
+ /*P0384*/ {{0x28,0x10, 0x17,0xAA,0xF8,0xAE,0x10,0xE3,0xC5,0xC4,0xFA,0x44}},
+ /*P0448*/ {{0xEB,0xA7, 0xD4,0xF3,0xF7,0xEB,0xE1,0x4A,0x7A,0x95,0xCF,0x45}},
+ /*P0512*/ {{0x65,0xCC, 0xC7,0x91,0x0E,0xA6,0xAE,0xA0,0x19,0xE3,0xA3,0x46}},
+ /*P1024*/ {{0x0D,0x65, 0x17,0x0C,0x75,0x81,0x86,0x75,0x76,0xC9,0x48,0x4D}},
+ /*P1536*/ {{0x58,0x42, 0xE4,0xA7,0x93,0x39,0x3B,0x35,0xB8,0xB2,0xED,0x53}},
+ /*P2048*/ {{0x4D,0xA7, 0xE5,0x5D,0x3D,0xC5,0x5D,0x3B,0x8B,0x9E,0x92,0x5A}},
+ /*P2560*/ {{0xFF,0x5D, 0xA6,0xF0,0xA1,0x20,0xC0,0x54,0xA5,0x8C,0x37,0x61}},
+ /*P3072*/ {{0xD1,0xFD, 0x8B,0x5A,0x8B,0xD8,0x25,0x5D,0x89,0xF9,0xDB,0x67}},
+ /*P3584*/ {{0xAA,0x95, 0xF8,0xF3,0x27,0xBF,0xA2,0xC8,0x5D,0xDD,0x80,0x6E}},
+ /*P4096*/ {{0x4C,0xC9, 0x9B,0x97,0x20,0x8A,0x02,0x52,0x60,0xC4,0x25,0x75}}
+};
+
+_ULDBL12 _pow10neg[] = {
+ /*N0001*/ {{0xCD,0xCC, 0xCD,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFB,0x3F}},
+ /*N0002*/ {{0x71,0x3D, 0x0A,0xD7,0xA3,0x70,0x3D,0x0A,0xD7,0xA3,0xF8,0x3F}},
+ /*N0003*/ {{0x5A,0x64, 0x3B,0xDF,0x4F,0x8D,0x97,0x6E,0x12,0x83,0xF5,0x3F}},
+ /*N0004*/ {{0xC3,0xD3, 0x2C,0x65,0x19,0xE2,0x58,0x17,0xB7,0xD1,0xF1,0x3F}},
+ /*N0005*/ {{0xD0,0x0F, 0x23,0x84,0x47,0x1B,0x47,0xAC,0xC5,0xA7,0xEE,0x3F}},
+ /*N0006*/ {{0x40,0xA6, 0xB6,0x69,0x6C,0xAF,0x05,0xBD,0x37,0x86,0xEB,0x3F}},
+ /*N0007*/ {{0x33,0x3D, 0xBC,0x42,0x7A,0xE5,0xD5,0x94,0xBF,0xD6,0xE7,0x3F}},
+ /*N0008*/ {{0xC2,0xFD, 0xFD,0xCE,0x61,0x84,0x11,0x77,0xCC,0xAB,0xE4,0x3F}},
+ /*N0016*/ {{0x2F,0x4C, 0x5B,0xE1,0x4D,0xC4,0xBE,0x94,0x95,0xE6,0xC9,0x3F}},
+ /*N0024*/ {{0x92,0xC4, 0x53,0x3B,0x75,0x44,0xCD,0x14,0xBE,0x9A,0xAF,0x3F}},
+ /*N0032*/ {{0xDE,0x67, 0xBA,0x94,0x39,0x45,0xAD,0x1E,0xB1,0xCF,0x94,0x3F}},
+ /*N0040*/ {{0x24,0x23, 0xC6,0xE2,0xBC,0xBA,0x3B,0x31,0x61,0x8B,0x7A,0x3F}},
+ /*N0048*/ {{0x61,0x55, 0x59,0xC1,0x7E,0xB1,0x53,0x7C,0x12,0xBB,0x5F,0x3F}},
+ /*N0056*/ {{0xD7,0xEE, 0x2F,0x8D,0x06,0xBE,0x92,0x85,0x15,0xFB,0x44,0x3F}},
+ /*N0064*/ {{0x24,0x3F, 0xA5,0xE9,0x39,0xA5,0x27,0xEA,0x7F,0xA8,0x2A,0x3F}},
+ /*N0128*/ {{0x7D,0xAC, 0xA1,0xE4,0xBC,0x64,0x7C,0x46,0xD0,0xDD,0x55,0x3E}},
+ /*N0192*/ {{0x63,0x7B, 0x06,0xCC,0x23,0x54,0x77,0x83,0xFF,0x91,0x81,0x3D}},
+ /*N0256*/ {{0x91,0xFA, 0x3A,0x19,0x7A,0x63,0x25,0x43,0x31,0xC0,0xAC,0x3C}},
+ /*N0320*/ {{0x21,0x89, 0xD1,0x38,0x82,0x47,0x97,0xB8,0x00,0xFD,0xD7,0x3B}},
+ /*N0384*/ {{0xDC,0x88, 0x58,0x08,0x1B,0xB1,0xE8,0xE3,0x86,0xA6,0x03,0x3B}},
+ /*N0448*/ {{0xC6,0x84, 0x45,0x42,0x07,0xB6,0x99,0x75,0x37,0xDB,0x2E,0x3A}},
+ /*N0512*/ {{0x33,0x71, 0x1C,0xD2,0x23,0xDB,0x32,0xEE,0x49,0x90,0x5A,0x39}},
+ /*N1024*/ {{0xA6,0x87, 0xBE,0xC0,0x57,0xDA,0xA5,0x82,0xA6,0xA2,0xB5,0x32}},
+ /*N1536*/ {{0xE2,0x68, 0xB2,0x11,0xA7,0x52,0x9F,0x44,0x59,0xB7,0x10,0x2C}},
+ /*N2048*/ {{0x25,0x49, 0xE4,0x2D,0x36,0x34,0x4F,0x53,0xAE,0xCE,0x6B,0x25}},
+ /*N2560*/ {{0x8F,0x59, 0x04,0xA4,0xC0,0xDE,0xC2,0x7D,0xFB,0xE8,0xC6,0x1E}},
+ /*N3072*/ {{0x9E,0xE7, 0x88,0x5A,0x57,0x91,0x3C,0xBF,0x50,0x83,0x22,0x18}},
+ /*N3584*/ {{0x4E,0x4B, 0x65,0x62,0xFD,0x83,0x8F,0xAF,0x06,0x94,0x7D,0x11}},
+ /*N4096*/ {{0xE4,0x2D, 0xDE,0x9F,0xCE,0xD2,0xC8,0x04,0xDD,0xA6,0xD8,0x0A}}
+};
+
+#endif
+
+#ifdef B_END
+
+_ULDBL12 _pow10pos[] = {
+ /*P0001*/ {{0x40,0x02,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0002*/ {{0x40,0x05,0xC8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0003*/ {{0x40,0x08,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0004*/ {{0x40,0x0C,0x9C,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0005*/ {{0x40,0x0F,0xC3,0x50,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0006*/ {{0x40,0x12,0xF4,0x24,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0007*/ {{0x40,0x16,0x98,0x96,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0008*/ {{0x40,0x19,0xBE,0xBC,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0016*/ {{0x40,0x34,0x8E,0x1B,0xC9,0xBF,0x04,0x00,0x00,0x00, 0x00,0x00}},
+ /*P0024*/ {{0x40,0x4E,0xD3,0xC2,0x1B,0xCE,0xCC,0xED,0xA1,0x00, 0x00,0x00}},
+ /*P0032*/ {{0x40,0x69,0x9D,0xC5,0xAD,0xA8,0x2B,0x70,0xB5,0x9E, 0xF0,0x20}},
+ /*P0040*/ {{0x40,0x83,0xEB,0x19,0x4F,0x8E,0x1A,0xE5,0x25,0xFD, 0x5D,0xD0}},
+ /*P0048*/ {{0x40,0x9E,0xAF,0x29,0x8D,0x05,0x0E,0x43,0x95,0xD7, 0x96,0x71}},
+ /*P0056*/ {{0x40,0xB9,0x82,0x81,0x8F,0x12,0x81,0xED,0x44,0xA0, 0xBF,0xF9}},
+ /*P0064*/ {{0x40,0xD3,0xC2,0x78,0x1F,0x49,0xFF,0xCF,0xA6,0xD5, 0x3C,0xBF}},
+ /*P0128*/ {{0x41,0xA8,0x93,0xBA,0x47,0xC9,0x80,0xE9,0x8C,0xE0, 0xC6,0x6F}},
+ /*P0192*/ {{0x42,0x7C,0xE0,0x70,0xF7,0x8D,0x39,0x27,0x55,0x6B, 0x85,0xBC}},
+ /*P0256*/ {{0x43,0x51,0xAA,0x7E,0xEB,0xFB,0x9D,0xF9,0xDE,0x8E, 0xDD,0xBC}},
+ /*P0320*/ {{0x44,0x26,0x81,0x84,0x2F,0x29,0xF2,0xCC,0xE3,0x76, 0xE6,0xA1}},
+ /*P0384*/ {{0x44,0xFA,0xC4,0xC5,0xE3,0x10,0xAE,0xF8,0xAA,0x17, 0x10,0x28}},
+ /*P0448*/ {{0x45,0xCF,0x95,0x7A,0x4A,0xE1,0xEB,0xF7,0xF3,0xD4, 0xA7,0xEB}},
+ /*P0512*/ {{0x46,0xA3,0xE3,0x19,0xA0,0xAE,0xA6,0x0E,0x91,0xC7, 0xCC,0x65}},
+ /*P1024*/ {{0x4D,0x48,0xC9,0x76,0x75,0x86,0x81,0x75,0x0C,0x17, 0x65,0x0D}},
+ /*P1536*/ {{0x53,0xED,0xB2,0xB8,0x35,0x3B,0x39,0x93,0xA7,0xE4, 0x42,0x58}},
+ /*P2048*/ {{0x5A,0x92,0x9E,0x8B,0x3B,0x5D,0xC5,0x3D,0x5D,0xE5, 0xA7,0x4D}},
+ /*P2560*/ {{0x61,0x37,0x8C,0xA5,0x54,0xC0,0x20,0xA1,0xF0,0xA6, 0x5D,0xFF}},
+ /*P3072*/ {{0x67,0xDB,0xF9,0x89,0x5D,0x25,0xD8,0x8B,0x5A,0x8B, 0xFD,0xD1}},
+ /*P3584*/ {{0x6E,0x80,0xDD,0x5D,0xC8,0xA2,0xBF,0x27,0xF3,0xF8, 0x95,0xAA}},
+ /*P4096*/ {{0x75,0x25,0xC4,0x60,0x52,0x02,0x8A,0x20,0x97,0x9B, 0xC9,0x4C}}
+};
+
+_ULDBL12 _pow10neg[] = {
+ /*N0001*/ {{0x3F,0xFB,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCD, 0xCC,0xCD}},
+ /*N0002*/ {{0x3F,0xF8,0xA3,0xD7,0x0A,0x3D,0x70,0xA3,0xD7,0x0A, 0x3D,0x71}},
+ /*N0003*/ {{0x3F,0xF5,0x83,0x12,0x6E,0x97,0x8D,0x4F,0xDF,0x3B, 0x64,0x5A}},
+ /*N0004*/ {{0x3F,0xF1,0xD1,0xB7,0x17,0x58,0xE2,0x19,0x65,0x2C, 0xD3,0xC3}},
+ /*N0005*/ {{0x3F,0xEE,0xA7,0xC5,0xAC,0x47,0x1B,0x47,0x84,0x23, 0x0F,0xD0}},
+ /*N0006*/ {{0x3F,0xEB,0x86,0x37,0xBD,0x05,0xAF,0x6C,0x69,0xB6, 0xA6,0x40}},
+ /*N0007*/ {{0x3F,0xE7,0xD6,0xBF,0x94,0xD5,0xE5,0x7A,0x42,0xBC, 0x3D,0x33}},
+ /*N0008*/ {{0x3F,0xE4,0xAB,0xCC,0x77,0x11,0x84,0x61,0xCE,0xFD, 0xFD,0xC2}},
+ /*N0016*/ {{0x3F,0xC9,0xE6,0x95,0x94,0xBE,0xC4,0x4D,0xE1,0x5B, 0x4C,0x2F}},
+ /*N0024*/ {{0x3F,0xAF,0x9A,0xBE,0x14,0xCD,0x44,0x75,0x3B,0x53, 0xC4,0x92}},
+ /*N0032*/ {{0x3F,0x94,0xCF,0xB1,0x1E,0xAD,0x45,0x39,0x94,0xBA, 0x67,0xDE}},
+ /*N0040*/ {{0x3F,0x7A,0x8B,0x61,0x31,0x3B,0xBA,0xBC,0xE2,0xC6, 0x23,0x24}},
+ /*N0048*/ {{0x3F,0x5F,0xBB,0x12,0x7C,0x53,0xB1,0x7E,0xC1,0x59, 0x55,0x61}},
+ /*N0056*/ {{0x3F,0x44,0xFB,0x15,0x85,0x92,0xBE,0x06,0x8D,0x2F, 0xEE,0xD7}},
+ /*N0064*/ {{0x3F,0x2A,0xA8,0x7F,0xEA,0x27,0xA5,0x39,0xE9,0xA5, 0x3F,0x24}},
+ /*N0128*/ {{0x3E,0x55,0xDD,0xD0,0x46,0x7C,0x64,0xBC,0xE4,0xA1, 0xAC,0x7D}},
+ /*N0192*/ {{0x3D,0x81,0x91,0xFF,0x83,0x77,0x54,0x23,0xCC,0x06, 0x7B,0x63}},
+ /*N0256*/ {{0x3C,0xAC,0xC0,0x31,0x43,0x25,0x63,0x7A,0x19,0x3A, 0xFA,0x91}},
+ /*N0320*/ {{0x3B,0xD7,0xFD,0x00,0xB8,0x97,0x47,0x82,0x38,0xD1, 0x89,0x21}},
+ /*N0384*/ {{0x3B,0x03,0xA6,0x86,0xE3,0xE8,0xB1,0x1B,0x08,0x58, 0x88,0xDC}},
+ /*N0448*/ {{0x3A,0x2E,0xDB,0x37,0x75,0x99,0xB6,0x07,0x42,0x45, 0x84,0xC6}},
+ /*N0512*/ {{0x39,0x5A,0x90,0x49,0xEE,0x32,0xDB,0x23,0xD2,0x1C, 0x71,0x33}},
+ /*N1024*/ {{0x32,0xB5,0xA2,0xA6,0x82,0xA5,0xDA,0x57,0xC0,0xBE, 0x87,0xA6}},
+ /*N1536*/ {{0x2C,0x10,0xB7,0x59,0x44,0x9F,0x52,0xA7,0x11,0xB2, 0x68,0xE2}},
+ /*N2048*/ {{0x25,0x6B,0xCE,0xAE,0x53,0x4F,0x34,0x36,0x2D,0xE4, 0x49,0x25}},
+ /*N2560*/ {{0x1E,0xC6,0xE8,0xFB,0x7D,0xC2,0xDE,0xC0,0xA4,0x04, 0x59,0x8F}},
+ /*N3072*/ {{0x18,0x22,0x83,0x50,0xBF,0x3C,0x91,0x57,0x5A,0x88, 0xE7,0x9E}},
+ /*N3584*/ {{0x11,0x7D,0x94,0x06,0xAF,0x8F,0x83,0xFD,0x62,0x65, 0x4B,0x4E}},
+ /*N4096*/ {{0x0A,0xD8,0xA6,0xDD,0x04,0xC8,0xD2,0xCE,0x9F,0xDE, 0x2D,0xE4}}
+};
+
+#endif
diff --git a/private/windbg/lib/cv.h b/private/windbg/lib/cv.h
new file mode 100644
index 000000000..2650c9628
--- /dev/null
+++ b/private/windbg/lib/cv.h
@@ -0,0 +1,518 @@
+/***
+*cv.h - definitions for floating point conversion
+*
+* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* define types, macros, and constants used in floating point
+* conversion routines
+*
+*Revision History:
+* 7-17-91 GDP initial version
+* 9-21-91 GDP restructured 'ifdef' directives
+* 10-29-91 GDP MIPS port: new defs for ALIGN and UDOUBLE
+* 3-03-92 GDP removed os2 16-bit stuff
+* 4-30-92 GDP support intrncvt.c --cleanup and reorganize
+*
+*******************************************************************************/
+#ifndef _INC_CV
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _WINDOWS_ // NOTENOTE Davegi This needs to be cleaned up!
+typedef float FLOAT;
+#endif // _WINDOWS_
+
+// #include <cruntime.h>
+
+#ifndef _MIPS_
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#endif
+#endif
+
+
+//
+// For MIPS, define UDOUBLE as 'double' before including fltintrn.h,
+// so that the definition in fltintrn.h is not used.
+// This is done because floating point arguments are passed in the
+// fp register.
+//
+
+#ifdef MIPS
+#define UDOUBLE double
+#endif
+
+//
+// definitions from crt32\h\fltintrn.h -- keep in sync
+//
+
+
+/*
+ * structs used to fool the compiler into not generating floating point
+ * instructions when copying and pushing [long] double values
+ */
+
+#ifndef UDOUBLE
+
+typedef struct {
+ double x;
+} UDOUBLE;
+
+#endif
+
+
+/*
+ * typedef for _fltout
+ */
+
+typedef struct _strflt
+{
+ int sign; /* zero if positive otherwise negative */
+ int decpt; /* exponent of floating point number */
+ int flag; /* zero if okay otherwise IEEE overflow */
+ char *mantissa; /* pointer to mantissa in string form */
+}
+ *STRFLT;
+
+
+/*
+ * typedef for _fltin
+ */
+
+typedef struct _flt
+{
+ int flags;
+ int nbytes; /* number of characters read */
+ long lval;
+ double dval; /* the returned floating point number */
+}
+ *FLT;
+
+
+char *_cftoe(double *, char *, int, int);
+char *_cftof(double *, char *, int);
+void _fptostr(char *, int, STRFLT);
+
+#ifdef MTHREAD
+
+STRFLT _fltout2( double, STRFLT, char * );
+FLT _fltin2( FLT , const char *, int, int, int );
+
+#else
+
+STRFLT _fltout( UDOUBLE );
+FLT _fltin( const char *, int, int, int );
+
+#endif
+
+
+//
+// end of definitions from crt32\h\fltintrn.h
+//
+
+
+
+/* define little endian or big endian memory */
+
+#ifdef i386
+#define L_END
+#endif
+
+#ifdef MIPS
+#define L_END
+#endif
+
+#ifdef ALPHA
+#define L_END
+#endif
+
+#ifdef PPC
+#define L_END
+#endif
+
+typedef unsigned char u_char; /* should have 1 byte */
+typedef char s_char; /* should have 1 byte */
+typedef unsigned short u_short; /* should have 2 bytes */
+typedef signed short s_short; /* should have 2 bytes */
+typedef unsigned int u_long; /* sholuld have 4 bytes */
+typedef int s_long; /* sholuld have 4 bytes */
+
+
+//
+// defining _LDSUPPORT enables using long double computations
+// for string conversion. We do not do this even for i386,
+// since we want to avoid using floating point code that
+// may generate IEEE exceptions.
+//
+// Currently our string conversion routines do not conform
+// to the special requirements of the IEEE standard for
+// floating point conversions
+//
+
+
+#ifndef _LDSUPPORT
+
+#pragma pack(4)
+typedef struct {
+ u_char ld[10];
+} _ULDOUBLE;
+#pragma pack()
+
+#define PTR_LD(x) ((u_char *)(&(x)->ld))
+
+#else
+
+typedef long double _ULDOUBLE;
+
+#define PTR_LD(x) ((u_char *)(x))
+
+#endif
+
+
+#pragma pack(4)
+typedef struct {
+ u_char ld12[12];
+} _ULDBL12;
+#pragma pack()
+
+#if 0
+typedef struct {
+ float f;
+} FLOAT;
+#endif
+
+
+
+//
+// return values for internal conversion routines
+// (12-byte to long double, double, or float)
+//
+
+typedef enum {
+ INTRNCVT_OK,
+ INTRNCVT_OVERFLOW,
+ INTRNCVT_UNDERFLOW
+} INTRNCVT_STATUS;
+
+
+//
+// return values for strgtold12 routine
+//
+
+#define SLD_UNDERFLOW 1
+#define SLD_OVERFLOW 2
+#define SLD_NODIGITS 4
+
+#define MAX_MAN_DIGITS 21
+
+
+// specifies '%f' format
+
+#define SO_FFORMAT 1
+
+typedef struct _FloatOutStruct {
+ short exp;
+ char sign;
+ char ManLen;
+ char man[MAX_MAN_DIGITS+1];
+ } FOS;
+
+
+
+#define PTR_12(x) ((u_char *)(&(x)->ld12))
+
+#define MAX_USHORT ((u_short)0xffff)
+#define MSB_USHORT ((u_short)0x8000)
+#define MAX_ULONG ((u_long)0xffffffff)
+#define MSB_ULONG ((u_long)0x80000000)
+
+#define TMAX10 5200 /* maximum temporary decimal exponent */
+#define TMIN10 -5200 /* minimum temporary decimal exponent */
+#define LD_MAX_EXP_LEN 4 /* maximum number of decimal exponent digits */
+#define LD_MAX_MAN_LEN 24 /* maximum length of mantissa (decimal)*/
+#define LD_MAX_MAN_LEN1 25 /* MAX_MAN_LEN+1 */
+
+#define LD_BIAS 0x3fff /* exponent bias for long double */
+#define LD_BIASM1 0x3ffe /* LD_BIAS - 1 */
+#define LD_MAXEXP 0x7fff /* maximum biased exponent */
+
+#define D_BIAS 0x3ff /* exponent bias for double */
+#define D_BIASM1 0x3fe /* D_BIAS - 1 */
+#define D_MAXEXP 0x7ff /* maximum biased exponent */
+
+
+
+/* Recognizing special patterns in the mantissa field */
+#define _EXP_SP 0x7fff
+#define NAN_BIT (1<<30)
+
+#define _IS_MAN_INF(signbit, manhi, manlo) \
+ ( (manhi)==MSB_ULONG && (manlo)==0x0 )
+
+
+#ifdef i386
+#define _IS_MAN_IND(signbit, manhi, manlo) \
+ ((signbit) && (manhi)==0xc0000000 && (manlo)==0)
+
+#define _IS_MAN_QNAN(signbit, manhi, manlo) \
+ ( (manhi)&NAN_BIT )
+
+#define _IS_MAN_SNAN(signbit, manhi, manlo) \
+ (!( _IS_MAN_INF(signbit, manhi, manlo) || \
+ _IS_MAN_QNAN(signbit, manhi, manlo) ))
+
+
+#else
+#ifdef MIPS
+#define _IS_MAN_IND(signbit, manhi, manlo) \
+ (!(signbit) && (manhi)==0xbfffffff && (manlo)==0xfffff800)
+
+#define _IS_MAN_SNAN(signbit, manhi, manlo) \
+ ( (manhi)&NAN_BIT )
+
+#define _IS_MAN_QNAN(signbit, manhi, manlo) \
+ (!( _IS_MAN_INF(signbit, manhi, manlo) || \
+ _IS_MAN_SNAN(signbit, manhi, manlo) ))
+#else
+#ifdef PPC
+// copied alpha crap below bugbug fmbutt
+#define _IS_MAN_IND(signbit, manhi, manlo) 1
+#define _IS_MAN_SNAN(signbit, manhi, manlo) 1
+#define _IS_MAN_QNAN(signbit, manhi, manlo) 1
+#else // ALPHA
+// MBH - bugbug - just put anything in here because its
+// only used to determine string size!
+//
+#define _IS_MAN_IND(signbit, manhi, manlo) 1
+#define _IS_MAN_SNAN(signbit, manhi, manlo) 1
+#define _IS_MAN_QNAN(signbit, manhi, manlo) 1
+#endif
+#endif
+#endif
+
+
+//
+// MBH -bugbug
+// We probaby don't look just like 386 in this regard.
+// Figure out ALPHA stuff for FP here.
+//
+
+#if defined (L_END) && !defined (MIPS)
+/* "little endian" memory */
+/* Note: MIPS has alignment requirements and has different macros */
+/*
+ * Manipulation of a 12-byte long double number (an ordinary
+ * 10-byte long double plus two extra bytes of mantissa).
+ */
+
+/* a pointer to the exponent/sign portion */
+#define U_EXP_12(p) ((u_short *)(PTR_12(p)+10))
+
+/* a pointer to the 4 hi-order bytes of the mantissa */
+#define UL_MANHI_12(p) ((u_long *)(PTR_12(p)+6))
+
+/* a pointer to the 4 lo-order bytes of the ordinary (8-byte) mantissa */
+#define UL_MANLO_12(p) ((u_long *)(PTR_12(p)+2))
+
+/* a pointer to the 2 extra bytes of the mantissa */
+#define U_XT_12(p) ((u_short *)PTR_12(p))
+
+/* a pointer to the 4 lo-order bytes of the extended (10-byte) mantissa */
+#define UL_LO_12(p) ((u_long *)PTR_12(p))
+
+/* a pointer to the 4 mid-order bytes of the extended (10-byte) mantissa */
+#define UL_MED_12(p) ((u_long *)(PTR_12(p)+4))
+
+/* a pointer to the 4 hi-order bytes of the extended long double */
+#define UL_HI_12(p) ((u_long *)(PTR_12(p)+8))
+
+/* a pointer to the byte of order i (LSB=0, MSB=9)*/
+#define UCHAR_12(p,i) ((u_char *)PTR_12(p)+(i))
+
+/* a pointer to a u_short with offset i */
+#define USHORT_12(p,i) ((u_short *)((u_char *)PTR_12(p)+(i)))
+
+/* a pointer to a u_long with offset i */
+#define ULONG_12(p,i) ((u_long *)((u_char *)PTR_12(p)+(i)))
+
+/* a pointer to the 10 MSBytes of a 12-byte long double */
+#define TEN_BYTE_PART(p) ((u_char *)PTR_12(p)+2)
+
+/*
+ * Manipulation of a 10-byte long double number
+ */
+#define U_EXP_LD(p) ((u_short *)(PTR_LD(p)+8))
+#define UL_MANHI_LD(p) ((u_long *)(PTR_LD(p)+4))
+#define UL_MANLO_LD(p) ((u_long *)PTR_LD(p))
+
+/*
+ * Manipulation of a 64bit IEEE double
+ */
+#define U_SHORT4_D(p) ((u_short *)(p) + 3)
+#define UL_HI_D(p) ((u_long *)(p) + 1)
+#define UL_LO_D(p) ((u_long *)(p))
+
+#endif
+
+#ifdef B_END /* big endian */
+
+#define U_EXP_12(p) ((u_short *)PTR_12(p))
+#define UL_MANHI_12(p) ((u_long *)(PTR_12(p)+2))
+#define UL_MANLO_12(p) ((u_long *)(PTR_12(p)+6))
+#define U_XT_12(p) ((u_short *)(PTR_12(p)+10))
+
+#define UL_LO_12(p) ((u_long *)PTR_12(p))
+#define UL_MED_12(p) ((u_long *)(PTR_12(p)+4))
+#define UL_HI_12(p) ((u_long *)(PTR_12(p)+8))
+
+#define UCHAR_12(p,i) ((u_char *)PTR_12(p)+(11-(i)))
+#define USHORT_12(p,i) ((u_short *)((u_char *)PTR_12(p)+10-(i)))
+#define ULONG_12(p,i) ((u_long *)((u_char *)PTR_12(p)+8-(i)))
+#define TEN_BYTE_PART(p) (u_char *)PTR_12(p)
+
+#define U_EXP_LD(p) ((u_short *)PTR_LD(p))
+#define UL_MANHI_LD(p) ((u_long *)(PTR_LD(p)+4))
+#define UL_MANLO_LD(p) ((u_long *)(PTR_LD(p)+8))
+
+/*
+ * Manipulation of a 64bit IEEE double
+ */
+#define U_SHORT4_D(p) ((u_short *)(p) + 3)
+#define UL_HI_D(p) ((u_long *)(p) + 1)
+#define UL_LO_D(p) ((u_long *)(p))
+
+#endif
+
+#ifdef MIPS
+
+#define MIPSALIGN(x) ( (unsigned long __unaligned *) (x))
+
+#define U_EXP_12(p) ((u_short *)(PTR_12(p)+10))
+
+#define UL_MANHI_12(p) ((u_long __unaligned *) (PTR_12(p)+6) )
+#define UL_MANLO_12(p) ((u_long __unaligned *) (PTR_12(p)+2) )
+
+
+#define U_XT_12(p) ((u_short *)PTR_12(p))
+#define UL_LO_12(p) ((u_long *)PTR_12(p))
+#define UL_MED_12(p) ((u_long *)(PTR_12(p)+4))
+#define UL_HI_12(p) ((u_long *)(PTR_12(p)+8))
+
+/* the following 3 macros do not take care of proper alignment */
+#define UCHAR_12(p,i) ((u_char *)PTR_12(p)+(i))
+#define USHORT_12(p,i) ((u_short *)((u_char *)PTR_12(p)+(i)))
+#define ULONG_12(p,i) ((u_long *) ((u_char *)PTR_12(p)+(i) ))
+
+#define TEN_BYTE_PART(p) ((u_char *)PTR_12(p)+2)
+
+/*
+ * Manipulation of a 10-byte long double number
+ */
+#define U_EXP_LD(p) ((u_short *)(PTR_LD(p)+8))
+
+#define UL_MANHI_LD(p) ((u_long *) (PTR_LD(p)+4) )
+#define UL_MANLO_LD(p) ((u_long *) PTR_LD(p) )
+
+/*
+ * Manipulation of a 64bit IEEE double
+ */
+#define U_SHORT4_D(p) ((u_short *)(p) + 3)
+#define UL_HI_D(p) ((u_long *)(p) + 1)
+#define UL_LO_D(p) ((u_long *)(p))
+
+#endif
+
+
+#define PUT_INF_12(p,sign) \
+ *UL_HI_12(p) = (sign)?0xffff8000:0x7fff8000; \
+ *UL_MED_12(p) = 0; \
+ *UL_LO_12(p) = 0;
+
+#define PUT_ZERO_12(p) *UL_HI_12(p) = 0; \
+ *UL_MED_12(p) = 0; \
+ *UL_LO_12(p) = 0;
+
+#define ISZERO_12(p) ((*UL_HI_12(p)&0x7fffffff) == 0 && \
+ *UL_MED_12(p) == 0 && \
+ *UL_LO_12(p) == 0 )
+
+#define PUT_INF_LD(p,sign) \
+ *U_EXP_LD(p) = (sign)?0xffff:0x7fff; \
+ *UL_MANHI_LD(p) = 0x8000; \
+ *UL_MANLO_LD(p) = 0;
+
+#define PUT_ZERO_LD(p) *U_EXP_LD(p) = 0; \
+ *UL_MANHI_LD(p) = 0; \
+ *UL_MANLO_LD(p) = 0;
+
+#define ISZERO_LD(p) ((*U_EXP_LD(p)&0x7fff) == 0 && \
+ *UL_MANHI_LD(p) == 0 && \
+ *UL_MANLO_LD(p) == 0 )
+
+
+/*********************************************************
+ *
+ * Function Prototypes
+ *
+ *********************************************************/
+
+/* from mantold.c */
+void __mtold12(char *manptr, unsigned manlen,_ULDBL12 *ld12);
+int __addl(u_long x, u_long y, u_long *sum);
+void __shl_12(_ULDBL12 *ld12);
+void __shr_12(_ULDBL12 *ld12);
+void __add_12(_ULDBL12 *x, _ULDBL12 *y);
+
+/* from tenpow.c */
+void __multtenpow12(_ULDBL12 *pld12,int pow, unsigned mult12);
+void __ld12mul(_ULDBL12 *px, _ULDBL12 *py);
+
+/* from strgtold.c */
+unsigned int __strgtold12(_ULDBL12 *pld12,
+ char * *p_end_ptr,
+ char *str,
+ int mult12);
+
+
+/* from x10fout.c */
+
+char * _uldtoa (_ULDOUBLE *px, int maxchars, char *ldtext);
+
+
+
+/* this is defined as void in convert.h
+ * After porting the asm files to c, we need a return value for
+ * i10_output, that used to reside in reg. ax
+ */
+int $I10_OUTPUT(_ULDOUBLE ld, int ndigits,
+ unsigned output_flags, FOS *fos);
+
+
+/* for cvt.c and fltused.c */
+void _cfltcvt(double *arg, char *buffer,
+ int format, int precision,
+ int caps);
+void _cropzeros(char *buf);
+void _fassign(int flag, char *argument, char *number);
+void _forcdecpt(char *buf);
+int _positive(double *arg);
+
+/* from intrncvt.c */
+void _atodbl(UDOUBLE *d, char *str);
+void _atoldbl(_ULDOUBLE *ld, char *str);
+void _atoflt(FLOAT *f, char *str);
+INTRNCVT_STATUS _ld12tod(_ULDBL12 *ifp, UDOUBLE *d);
+INTRNCVT_STATUS _ld12tof(_ULDBL12 *ifp, FLOAT *f);
+void _ld12told(_ULDBL12 *ifp, _ULDOUBLE *ld);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_CV
+#endif /* _INC_CV */
diff --git a/private/windbg/lib/cvt.c b/private/windbg/lib/cvt.c
new file mode 100644
index 000000000..4932f98ea
--- /dev/null
+++ b/private/windbg/lib/cvt.c
@@ -0,0 +1,768 @@
+/***
+*cvt.c - C floating-point output conversions
+*
+* Copyright (c) 1987-89, Microsoft Corporation
+*
+*Purpose:
+* contains routines for performing %e, %f, and %g output conversions
+* for printf, etc.
+*
+* routines include _cfltcvt(), _cftoe(), _cftof(), _cftog(), _fassign(),
+* _positive(), _cropzeros(), _forcdecpt()
+*
+*Revision History:
+* 04-18-84 RN author
+* 01-15-87 BCM corrected processing of %g formats (to handle precision
+* as the maximum number of signifcant digits displayed)
+* 03-24-87 BCM Evaluation Issues: (fccvt.obj version for ?LIBFA)
+* ------------------
+* SDS - no problem
+* GD/TS :
+* char g_fmt = 0; (local, initialized)
+* int g_magnitude =0; (local, initialized)
+* char g_round_expansion = 0; (local, initialized)
+* STRFLT g_pflt; (local, uninitialized)
+* other INIT :
+* ALTMATH __fpmath() initialization (perhaps)
+* TERM - nothing
+* 10-22-87 BCM changes for OS/2 Support Library -
+* including elimination of g_... static variables
+* in favor of stack-based variables & function arguments
+* under MTHREAD switch; changed interfaces to _cfto? routines
+* 01-15-88 BCM remove IBMC20 switches; use only memmove, not memcpy;
+* use just MTHREAD switch, not SS_NEQ_DGROUP
+* 06-13-88 WAJ Fixed %.1g processing for small x
+* 08-02-88 WAJ Made changes to _fassign() for new input().
+* 03-09-89 WAJ Added some long double support.
+* 06-05-89 WAJ Made changes for C6. ULDOUBLE => long double
+* 06-12-89 WAJ Renamed this file from cvtn.c to cvt.c
+* 11-02-89 WAJ Removed register.h
+* 06-28-90 WAJ Removed fars.
+* 11-15-90 WAJ Added _cdecl where needed. Also "pascal" => "_pascal".
+* 09-12-91 GDP _cdecl=>_CALLTYPE2 _pascal=>_CALLTYPE5 near=>_NEAR
+* 04-30-92 GDP Removed floating point code. Instead used S/W routines
+* (_atodbl, _atoflt _atoldbl), so that to avoid generation
+* of IEEE exceptions from the lib code.
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+
+
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include "cv.h"
+
+
+//NOTENOTE the following takes the place of the isdigit() macro
+// which does not work for a yet to be determined reason
+#define ISADIGIT(x) ((x)>='0' && (x)<='9' )
+
+
+
+
+#ifdef i386
+// Uncomment this for enabling 10-byte long double string conversions
+#define LONG_DOUBLE
+#endif
+
+
+/* this routine resides in the crt32 tree */
+extern void _fptostr(char *buf, int digits, STRFLT pflt);
+
+
+static void _shift( char *s, int dist );
+
+#ifdef MTHREAD
+ static char * _cftoe2( char * buf, int ndec, int caps, STRFLT pflt, char g_fmt );
+ static char * _cftof2( char * buf, int ndec, STRFLT pflt, char g_fmt );
+
+#else /* not MTHREAD */
+ static char * _cftoe_g( double * pvalue, char * buf, int ndec, int caps );
+ static char * _cftof_g( double * pvalue, char * buf, int ndec );
+#endif /* not MTHREAD */
+
+/***
+*_forcdecpt(buffer) - force a decimal point in floating-point output
+*Purpose:
+* force a decimal point in floating point output. we are only called if '#'
+* flag is given and precision is 0; so we know the number has no '.'. insert
+* the '.' and move everybody else back one position, until '\0' seen
+*
+* side effects: futzes around with the buffer, trying to insert a '.'
+* after the initial string of digits. the first char can usually be
+* skipped since it will be a digit or a '-'. but in the 0-precision case,
+* the number could start with 'e' or 'E', so we'd want the '.' before the
+* exponent in that case.
+*
+*Entry:
+* buffer = (char *) pointer to buffer to modify
+*
+*Exit:
+* returns : (void)
+*
+*Exceptions:
+*******************************************************************************/
+
+void _forcdecpt( char * buffer )
+{
+char holdchar;
+char nextchar;
+
+ if (tolower(*buffer) != 'e'){
+ do {
+ buffer++;
+ }
+ while (ISADIGIT(*buffer));
+ }
+
+ holdchar = *buffer;
+ *buffer++ = '.';
+
+ do {
+ nextchar = *buffer;
+ *buffer = holdchar;
+ holdchar = nextchar;
+ }
+
+ while(*buffer++);
+}
+
+
+/***
+*_cropzeros(buffer) - removes trailing zeros from floating-point output
+*Purpose:
+* removes trailing zeros (after the '.') from floating-point output;
+* called only when we're doing %g format, there's no '#' flag, and
+* precision is non-zero. plays around with the buffer, looking for
+* trailing zeros. when we find them, then we move everbody else forward
+* so they overlay the zeros. if we eliminate the entire fraction part,
+* then we overlay the decimal point ('.'), too.
+*
+* side effects: changes the buffer from
+* [-] digit [digit...] [ . [digits...] [0...] ] [(exponent part)]
+* to
+* [-] digit [digit...] [ . digit [digits...] ] [(exponent part)]
+* or
+* [-] digit [digit...] [(exponent part)]
+*
+*Entry:
+* buffer = (char *) pointer to buffer to modify
+*
+*Exit:
+* returns : (void)
+*
+*Exceptions:
+*******************************************************************************/
+
+void _cropzeros( char * buf )
+{
+char *stop;
+
+ while (*buf && *buf != '.')
+ buf++;
+
+ if (*buf++) {
+ while (*buf && *buf != 'e' && *buf != 'E')
+ buf++;
+
+ stop = buf--;
+
+ while (*buf == '0')
+ buf--;
+
+ if (*buf == '.')
+ buf--;
+
+ while( (*++buf = *stop++) != '\0' );
+ }
+}
+
+
+int _positive( double * arg )
+{
+ return( (*arg >= 0.0) );
+}
+
+
+void _fassign( int flag, char * argument, char * number )
+{
+
+/* flag should normally be 2 for long double and 1 for double
+ * The 32bit input.c sets 3 for long double and 2 for double
+ * Until this is fixed, decrement flag before use
+ */
+
+ --flag;
+
+#ifdef LONG_DOUBLE
+
+ switch( flag ){
+ case 2:
+ _atoldbl( (_ULDOUBLE *)argument, number );
+ break;
+
+ case 1:
+ _atodbl( (UDOUBLE *)argument, number );
+ break;
+
+ default:
+ _atoflt( (FLOAT *)argument, number );
+ }
+
+#else /* not LONG_DOUBLE */
+ if (flag)
+ _atodbl( (UDOUBLE *)argument, number );
+ else
+ _atoflt( (FLOAT *)argument, number );
+#endif /* not LONG_DOUBLE */
+}
+
+
+#ifndef MTHREAD
+ static char g_fmt = 0;
+ static int g_magnitude = 0;
+ static char g_round_expansion = 0;
+ static STRFLT g_pflt;
+#endif
+
+
+/*
+ * Function name: _cftoe
+ *
+ * Arguments: pvalue - double * pointer
+ * buf - char * pointer
+ * ndec - int
+ * caps - int
+ *
+ * Description: _cftoe converts the double pointed to by pvalue to a null
+ * terminated string of ASCII digits in the c language
+ * printf %e format, nad returns a pointer to the result.
+ * This format has the form [-]d.ddde(+/-)ddd, where there
+ * will be ndec digits following the decimal point. If
+ * ndec <= 0, no decimal point will appear. The low order
+ * digit is rounded. If caps is nonzero then the exponent
+ * will appear as E(+/-)ddd.
+ *
+ * Side Effects: the buffer 'buf' is assumed to have a minimum length
+ * of CVTBUFSIZE (defined in cvt.h) and the routines will
+ * not write over this size.
+ *
+ * Copyright: written R.K. Wyss, Microsoft, Sept. 9, 1983
+ * copyright (c) Microsoft Corp. 1983
+ *
+ * History:
+ *
+ */
+
+#ifdef MTHREAD
+ static char * _cftoe2( char * buf, int ndec, int caps, STRFLT pflt, char g_fmt )
+#else
+ char * _cftoe( double * pvalue, char * buf, int ndec, int caps )
+#endif
+{
+#ifndef MTHREAD
+ STRFLT pflt;
+#endif
+
+char *p;
+int exp;
+
+#ifdef MTHREAD
+ int g_magnitude = pflt->decpt - 1;
+#endif
+
+ /* first convert the value */
+
+ /* place the output in the buffer and round. Leave space in the buffer
+ * for the '-' sign (if any) and the decimal point (if any)
+ */
+
+ if (g_fmt) {
+#ifndef MTHREAD
+ pflt = g_pflt;
+#endif
+ /* shift it right one place if nec. for '.' */
+
+ p = buf + (pflt->sign == '-');
+ _shift(p, (ndec > 0));
+ }
+#ifndef MTHREAD
+ else {
+
+
+#ifdef MIPS
+
+ UDOUBLE dtemp;
+ dtemp = *pvalue;
+
+ pflt = _fltout(dtemp);
+
+
+#else
+
+ UDOUBLE dtemp;
+ dtemp.x = *pvalue; //i386 case
+
+ pflt = _fltout(dtemp);
+
+
+
+#endif
+
+ _fptostr(buf + (pflt->sign == '-') + (ndec > 0), ndec + 1, pflt);
+ }
+#endif
+
+
+ /* now fix the number up to be in e format */
+
+ p = buf;
+
+ /* put in negative sign if needed */
+
+ if (pflt->sign == '-')
+ *p++ = '-';
+
+ /* put in decimal point if needed. Copy the first digit to the place
+ * left for it and put the decimal point in its place
+ */
+
+ if (ndec > 0) {
+ *p = *(p+1);
+ *(++p) = '.';
+ }
+
+ /* find the end of the string and attach the exponent field */
+
+ p = strcpy(p+ndec+(!g_fmt), "e+000");
+
+ /* adjust exponent indicator according to caps flag and increment
+ * pointer to point to exponent sign
+ */
+
+ if (caps)
+ *p = 'E';
+
+ p++;
+
+ /* if mantissa is zero, then the number is 0 and we are done; otherwise
+ * adjust the exponent sign (if necessary) and value.
+ */
+
+ if (*pflt->mantissa != '0') {
+
+ /* check to see if exponent is negative; if so adjust exponent sign and
+ * exponent value.
+ */
+
+ if( (exp = pflt->decpt - 1) < 0 ) {
+ exp = -exp;
+ *p = '-';
+ }
+
+ p++;
+
+ if (exp >= 100) {
+ *p += (char)(exp / 100);
+ exp %= 100;
+ }
+ p++;
+
+ if (exp >= 10) {
+ *p += (char)(exp / 10);
+ exp %= 10;
+ }
+
+ *++p += (char)exp;
+ }
+
+ return(buf);
+}
+
+
+#ifdef MTHREAD
+
+char * _cftoe( double * pvalue, char * buf, int ndec, int caps )
+{
+struct _strflt retstrflt;
+char resstr[21];
+STRFLT pflt = &retstrflt;
+
+ _fltout2(*pvalue, (struct _strflt *)&retstrflt,
+ (char *)resstr);
+ _fptostr(buf + (pflt->sign == '-') + (ndec > 0), ndec + 1, pflt);
+ _cftoe2(buf, ndec, caps, pflt, /* g_fmt = */ 0);
+
+ return( buf );
+}
+
+#else /* not MTHREAD */
+
+static char * _cftoe_g( double * pvalue, char * buf, int ndec, int caps )
+{
+ char *res;
+ g_fmt = 1;
+ res = _cftoe(pvalue, buf, ndec, caps);
+ g_fmt = 0;
+ return (res);
+}
+
+#endif /* not MTHREAD */
+
+
+#ifdef MTHREAD
+static char * _cftof2( char * buf, int ndec, STRFLT pflt, char g_fmt )
+
+#else
+char * _cftof( double * pvalue, char * buf, int ndec )
+#endif
+
+{
+#ifndef MTHREAD
+STRFLT pflt;
+#endif
+
+char *p;
+char addzero = 0;
+
+#ifdef MTHREAD
+int g_magnitude = pflt->decpt - 1;
+#endif
+
+
+ /* first convert the value */
+
+ /* place the output in the users buffer and round. Save space for
+ * the minus sign now if it will be needed
+ */
+
+ if (g_fmt) {
+#ifndef MTHREAD
+ pflt = g_pflt;
+#endif
+
+ p = buf + (pflt->sign == '-');
+ if (g_magnitude == ndec) {
+ char *q = p + g_magnitude;
+ *q++ = '0';
+ *q = '\0';
+ /* allows for extra place-holding '0' in the exponent == precision
+ * case of the g format
+ */
+ }
+ }
+#ifndef MTHREAD
+ else {
+
+
+#ifdef MIPS
+
+ UDOUBLE dtemp;
+ dtemp = *pvalue;
+
+ pflt = _fltout(dtemp);
+
+
+#else
+
+ UDOUBLE dtemp;
+ dtemp.x = *pvalue; //i386 case
+
+ pflt = _fltout(dtemp);
+
+
+
+#endif
+
+ _fptostr(buf+(pflt->sign == '-'), ndec + pflt->decpt, pflt);
+ }
+#endif
+
+
+ /* now fix up the number to be in the correct f format */
+
+ p = buf;
+
+ /* put in negative sign, if necessary */
+
+ if (pflt->sign == '-')
+ *p++ = '-';
+
+ /* insert leading 0 for purely fractional values and position ourselves
+ * at the correct spot for inserting the decimal point
+ */
+
+ if (pflt->decpt <= 0) {
+ _shift(p, 1);
+ *p++ = '0';
+ }
+ else
+ p += pflt->decpt;
+
+ /* put in decimal point if required and any zero padding needed */
+
+ if (ndec > 0) {
+ _shift(p, 1);
+ *p++ = '.';
+
+ /* if the value is less than 1 then we may need to put 0's out in
+ * front of the first non-zero digit of the mantissa
+ */
+
+ if (pflt->decpt < 0) {
+ if( g_fmt )
+ ndec = -pflt->decpt;
+ else
+ ndec = (ndec < -pflt->decpt ) ? ndec : -pflt->decpt;
+ _shift(p, ndec);
+ memset( p, '0', ndec);
+ }
+ }
+
+ return( buf);
+}
+
+
+/*
+ * Function name: _cftof
+ *
+ * Arguments: value - double * pointer
+ * buf - char * pointer
+ * ndec - int
+ *
+ * Description: _cftof converts the double pointed to by pvalue to a null
+ * terminated string of ASCII digits in the c language
+ * printf %f format, and returns a pointer to the result.
+ * This format has the form [-]ddddd.ddddd, where there will
+ * be ndec digits following the decimal point. If ndec <= 0,
+ * no decimal point will appear. The low order digit is
+ * rounded.
+ *
+ * Side Effects: the buffer 'buf' is assumed to have a minimum length
+ * of CVTBUFSIZE (defined in cvt.h) and the routines will
+ * not write over this size.
+ *
+ * Copyright: written R.K. Wyss, Microsoft, Sept. 9, 1983
+ * copyright (c) Microsoft Corp. 1983
+ *
+ * History:
+ *
+ */
+
+#ifdef MTHREAD
+
+char * _cftof( double * pvalue, char * buf, int ndec )
+{
+ struct _strflt retstrflt;
+ char resstr[21];
+ STRFLT pflt = &retstrflt;
+ _fltout2(*pvalue, (struct _strflt *) &retstrflt,
+ (char *) resstr);
+ _fptostr(buf+(pflt->sign == '-'), ndec + pflt->decpt, pflt);
+ _cftof2(buf, ndec, pflt, /* g_fmt = */ 0);
+
+ return( buf );
+}
+
+#else /* not MTHREAD */
+
+
+static char * _cftof_g( double * pvalue, char * buf, int ndec )
+{
+ char *res;
+ g_fmt = 1;
+ res = _cftof(pvalue, buf, ndec);
+ g_fmt = 0;
+ return (res);
+}
+
+#endif /* not MTHREAD */
+
+/*
+ * Function name: _cftog
+ *
+ * Arguments: value - double * pointer
+ * buf - char * pointer
+ * ndec - int
+ *
+ * Description: _cftog converts the double pointed to by pvalue to a null
+ * terminated string of ASCII digits in the c language
+ * printf %g format, and returns a pointer to the result.
+ * The form used depends on the value converted. The printf
+ * %e form will be used if the magnitude of valude is less
+ * than -4 or is greater than ndec, otherwise printf %f will
+ * be used. ndec always specifies the number of digits
+ * following the decimal point. The low order digit is
+ * appropriately rounded.
+ *
+ * Side Effects: the buffer 'buf' is assumed to have a minimum length
+ * of CVTBUFSIZE (defined in cvt.h) and the routines will
+ * not write over this size.
+ *
+ * Copyright: written R.K. Wyss, Microsoft, Sept. 9, 1983
+ * copyright (c) Microsoft Corp. 1983
+ *
+ * History:
+ *
+ */
+
+char * _cftog( double * pvalue, char * buf, int ndec, int caps )
+{
+char *p;
+
+#ifdef MTHREAD
+char g_round_expansion = 0;
+STRFLT g_pflt;
+int g_magnitude;
+struct _strflt retstrflt;
+char resstr[21];
+
+ /* first convert the number */
+
+ g_pflt = &retstrflt;
+ _fltout2(*pvalue, (struct _strflt *)&retstrflt,
+ (char *)resstr);
+
+#else /* not MTHREAD */
+
+ /* first convert the number */
+
+
+#ifdef MIPS
+
+ UDOUBLE dtemp;
+ dtemp = *pvalue;
+
+ g_pflt = _fltout(dtemp);
+
+
+#else
+
+ UDOUBLE dtemp;
+ dtemp.x = *pvalue; //i386 case
+
+ g_pflt = _fltout(dtemp);
+
+
+
+#endif
+
+
+#endif /* not MTHREAD */
+
+ g_magnitude = g_pflt->decpt - 1;
+ p = buf + (g_pflt->sign == '-');
+
+ _fptostr(p, ndec, g_pflt);
+ g_round_expansion = (char)(g_magnitude < (g_pflt->decpt-1));
+
+
+ /* compute the magnitude of value */
+
+ g_magnitude = g_pflt->decpt - 1;
+
+ /* convert value to the c language g format */
+
+ if (g_magnitude < -4 || g_magnitude >= ndec){ /* use e format */
+ /* (g_round_expansion ==>
+ * extra digit will be overwritten by 'e+xxx')
+ */
+
+#ifdef MTHREAD
+ return(_cftoe2(buf, ndec, caps, g_pflt, /* g_fmt = */ 1));
+#else
+ return(_cftoe_g(pvalue, buf, ndec, caps));
+#endif
+
+ }
+ else { /* use f format */
+ if (g_round_expansion) {
+ /* throw away extra final digit from expansion */
+ while (*p++);
+ *(p-2) = '\0';
+ }
+
+#ifdef MTHREAD
+ return(_cftof2(buf, ndec, g_pflt, /* g_fmt = */ 1));
+#else
+ return(_cftof_g(pvalue, buf, ndec));
+#endif
+
+ }
+}
+
+/***
+*_cfltcvt(arg, buf, format, precision, caps) - convert floating-point output
+*Purpose:
+*
+*Entry:
+* arg = (double *) pointer to double-precision floating-point number
+* buf = (char *) pointer to buffer into which to put the converted
+* ASCII form of the number
+* format = (int) 'e', 'f', or 'g'
+* precision = (int) giving number of decimal places for %e and %f formats,
+* and giving maximum number of significant digits for
+* %g format
+* caps = (int) flag indicating whether 'E' in exponent should be capatilized
+* (for %E and %G formats only)
+*
+*Exit:
+* returns : (void)
+*
+*Exceptions:
+*******************************************************************************/
+/*
+ * Function name: _cfltcvt
+ *
+ * Arguments: arg - double * pointer
+ * buf - char * pointer
+ * format - int
+ * ndec - int
+ * caps - int
+ *
+ * Description: _cfltcvt determines from the format, what routines to
+ * call to generate the correct floating point format
+ *
+ * Side Effects: none
+ *
+ * Author: Dave Weil, Jan 12, 1985
+ *
+ * Copyright: Copyright (C) Microsoft Corp. 1985
+ */
+
+void _cfltcvt( double * arg, char * buffer, int format, int precision, int caps )
+{
+ if (format == 'e' || format == 'E')
+ _cftoe(arg, buffer, precision, caps);
+ else if (format == 'f')
+ _cftof(arg, buffer, precision);
+ else
+ _cftog(arg, buffer, precision, caps);
+}
+
+/***
+*_shift(s, dist) - shift a null-terminated string in memory (internal routine)
+*Purpose:
+* _shift is a helper routine that shifts a null-terminated string
+* in memory, e.g., moves part of a buffer used for floating-point output
+*
+* modifies memory locations (s+dist) through (s+dist+strlen(s))
+*
+*Entry:
+* s = (char *) pointer to string to move
+* dist = (int) distance to move the string to the right (if negative, to left)
+*
+*Exit:
+* returns : (void)
+*
+*Exceptions:
+*******************************************************************************/
+
+static void _shift( char *s, int dist )
+{
+ if( dist )
+ memmove(s+dist, s, strlen(s)+1);
+}
+
diff --git a/private/windbg/lib/heap.c b/private/windbg/lib/heap.c
new file mode 100644
index 000000000..60c22834a
--- /dev/null
+++ b/private/windbg/lib/heap.c
@@ -0,0 +1,106 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ heap.c
+
+Abstract:
+
+ This file contains a heap validation routines.
+
+Author:
+
+ Wesley Witt (wesw) 2-Feb-94
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <heap.h>
+
+
+//
+// used to globally enable or disable heap checking
+//
+DWORD fHeapCheck = TRUE;
+
+
+
+VOID
+ValidateTheHeap(
+ LPSTR fName,
+ DWORD dwLine
+ )
+/*++
+
+Routine Description:
+
+ Validate the process's heap. If the heap is found to be
+ invalid then a messagebox is displayed that indicates the
+ caller's file & line number. If the BO button is pressed
+ on the message box then DebugBreak is called.
+
+Arguments:
+
+ fName - caller's source filename
+ dwLine - caller's source line number
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CHAR buf[256];
+ INT id;
+
+ //
+ // we don't really want to allocate memory here, since the
+ // whole point was to look for heap corruption. Instead,
+ // just preallocate an unreasonable number of slots...
+ //
+
+ PVOID ProcessHeaps[64];
+ DWORD NumberOfHeaps = 64;
+ DWORD Heap;
+
+
+ if (fHeapCheck) {
+
+ NumberOfHeaps = GetProcessHeaps(NumberOfHeaps, ProcessHeaps);
+
+ for (Heap = 0; Heap < NumberOfHeaps; Heap++) {
+
+ if (!HeapValidate( ProcessHeaps[Heap], 0, 0 )) {
+
+ _snprintf( buf, sizeof(buf),
+ "Heap corruption detected in heap 0x%08x at line %d in %s.\n",
+ ProcessHeaps[Heap], fName, dwLine );
+
+ id = MessageBox( NULL, buf, "WinDbg Error",
+ MB_YESNO | MB_ICONHAND |
+ MB_TASKMODAL | MB_SETFOREGROUND );
+
+ OutputDebugString( buf );
+ OutputDebugString("\n\r");
+
+ if (id != IDYES) {
+ DebugBreak();
+ }
+
+ }
+
+ }
+
+ }
+}
diff --git a/private/windbg/lib/intrncvt.c b/private/windbg/lib/intrncvt.c
new file mode 100644
index 000000000..9ce055ffb
--- /dev/null
+++ b/private/windbg/lib/intrncvt.c
@@ -0,0 +1,703 @@
+/***
+* intrncvt.c - internal floating point conversions
+*
+* Copyright (c) 1992-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* All fp string conversion routines use the same core conversion code
+* that converts strings into an internal long double representation
+* with an 80-bit mantissa field. The mantissa is represented
+* as an array (man) of 32-bit unsigned longs, with man[0] holding
+* the high order 32 bits of the mantissa. The binary point is assumed
+* to be between the MSB and MSB-1 of man[0].
+*
+* Bits are counted as follows:
+*
+*
+* +-- binary point
+* |
+* v MSB LSB
+* ---------------- ------------------ --------------------
+* |0 1 .... 31| | 32 33 ... 63| | 64 65 ... 95|
+* ---------------- ------------------ --------------------
+*
+* man[0] man[1] man[2]
+*
+* This file provides the final conversion routines from this internal
+* form to the single, double, or long double precision floating point
+* format.
+*
+* All these functions do not handle NaNs (it is not necessary)
+*
+*
+*Revision History:
+* 04-29-92 GDP written
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+
+#include <assert.h>
+#include "cv.h"
+
+
+
+
+#define INTRNMAN_LEN 3 /* internal mantissa length in int's */
+
+//
+// internal mantissaa representation
+// for string conversion routines
+//
+
+typedef u_long *intrnman;
+
+
+typedef struct {
+ int max_exp; // maximum base 2 exponent (reserved for special values)
+ int min_exp; // minimum base 2 exponent (reserved for denormals)
+ int precision; // bits of precision carried in the mantissa
+ int exp_width; // number of bits for exponent
+ int format_width; // format width in bits
+ int bias; // exponent bias
+} FpFormatDescriptor;
+
+
+
+static FpFormatDescriptor
+DoubleFormat = {
+ 0x7ff - 0x3ff, // 1024, maximum base 2 exponent (reserved for special values)
+ 0x0 - 0x3ff, // -1023, minimum base 2 exponent (reserved for denormals)
+ 53, // bits of precision carried in the mantissa
+ 11, // number of bits for exponent
+ 64, // format width in bits
+ 0x3ff, // exponent bias
+};
+
+static FpFormatDescriptor
+FloatFormat = {
+ 0xff - 0x7f, // 128, maximum base 2 exponent (reserved for special values)
+ 0x0 - 0x7f, // -127, minimum base 2 exponent (reserved for denormals)
+ 24, // bits of precision carried in the mantissa
+ 8, // number of bits for exponent
+ 32, // format width in bits
+ 0x7f, // exponent bias
+};
+
+
+
+//
+// function prototypes
+//
+
+int _RoundMan (intrnman man, int nbit);
+int _ZeroTail (intrnman man, int nbit);
+int _IncMan (intrnman man, int nbit);
+void _CopyMan (intrnman dest, intrnman src);
+void _CopyMan (intrnman dest, intrnman src);
+void _FillZeroMan(intrnman man);
+void _Shrman (intrnman man, int n);
+
+INTRNCVT_STATUS _ld12cvt(_ULDBL12 *pld12, void *d, FpFormatDescriptor *format);
+
+/***
+* _ZeroTail - check if a mantissa ends in 0's
+*
+*Purpose:
+* Return TRUE if all mantissa bits after nbit (including nbit) are 0,
+* otherwise return FALSE
+*
+*
+*Entry:
+* man: mantissa
+* nbit: order of bit where the tail begins
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+int _ZeroTail (intrnman man, int nbit)
+{
+ int nl = nbit / 32;
+ int nb = 31 - nbit % 32;
+
+
+ //
+ // |<---- tail to be checked --->
+ //
+ // -- ------------------------ ----
+ // |... | | ... |
+ // -- ------------------------ ----
+ // ^ ^ ^
+ // | | |<----nb----->
+ // man nl nbit
+ //
+
+
+
+ u_long bitmask = ~(MAX_ULONG << nb);
+
+ if (man[nl] & bitmask)
+ return 0;
+
+ nl++;
+
+ for (;nl < INTRNMAN_LEN; nl++)
+ if (man[nl])
+ return 0;
+
+ return 1;
+}
+
+
+
+
+/***
+* _IncMan - increment mantissa
+*
+*Purpose:
+*
+*
+*Entry:
+* man: mantissa in internal long form
+* nbit: order of bit that specifies the end of the part to be incremented
+*
+*Exit:
+* returns 1 on overflow, 0 otherwise
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _IncMan (intrnman man, int nbit)
+{
+ int nl = nbit / 32;
+ int nb = 31 - nbit % 32;
+
+ //
+ // |<--- part to be incremented -->|
+ //
+ // -- --------------------------- ----
+ // |... | | ... |
+ // -- --------------------------- ----
+ // ^ ^ ^
+ // | | |<--nb-->
+ // man nl nbit
+ //
+
+ u_long one = (u_long) 1 << nb;
+ int carry;
+
+ carry = __addl(man[nl], one, &man[nl]);
+
+ nl--;
+
+ for (; nl >= 0 && carry; nl--) {
+ carry = (u_long) __addl(man[nl], (u_long) 1, &man[nl]);
+ }
+
+ return carry;
+}
+
+
+
+
+/***
+* _RoundMan - round mantissa
+*
+*Purpose:
+* round mantissa to nbit precision
+*
+*
+*Entry:
+* man: mantissa in internal form
+* precision: number of bits to be kept after rounding
+*
+*Exit:
+* returns 1 on overflow, 0 otherwise
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _RoundMan (intrnman man, int precision)
+{
+ int i,rndbit,nl,nb;
+ u_long rndmask;
+ int nbit;
+ int retval = 0;
+
+ //
+ // The order of the n'th bit is n-1, since the first bit is bit 0
+ // therefore decrement precision to get the order of the last bit
+ // to be kept
+ //
+ nbit = precision - 1;
+
+ rndbit = nbit+1;
+
+ nl = rndbit / 32;
+ nb = 31 - rndbit % 32;
+
+ //
+ // Get value of round bit
+ //
+
+ rndmask = (u_long)1 << nb;
+
+ if ((man[nl] & rndmask) &&
+ !_ZeroTail(man, rndbit+1)) {
+
+ //
+ // round up
+ //
+
+ retval = _IncMan(man, nbit);
+ }
+
+
+ //
+ // fill rest of mantissa with zeroes
+ //
+
+ man[nl] &= MAX_ULONG << nb;
+ for(i=nl+1; i<INTRNMAN_LEN; i++) {
+ man[i] = (u_long)0;
+ }
+
+ return retval;
+}
+
+
+/***
+* _CopyMan - copy mantissa
+*
+*Purpose:
+* copy src to dest
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+void _CopyMan (intrnman dest, intrnman src)
+{
+ u_long *p, *q;
+ int i;
+
+ p = src;
+ q = dest;
+
+ for (i=0; i < INTRNMAN_LEN; i++) {
+ *q++ = *p++;
+ }
+}
+
+
+
+/***
+* _FillZeroMan - fill mantissa with zeroes
+*
+*Purpose:
+*
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+void _FillZeroMan(intrnman man)
+{
+ int i;
+ for (i=0; i < INTRNMAN_LEN; i++)
+ man[i] = (u_long)0;
+}
+
+
+
+/***
+* _IsZeroMan - check if mantissa is zero
+*
+*Purpose:
+*
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+int _IsZeroMan(intrnman man)
+{
+ int i;
+ for (i=0; i < INTRNMAN_LEN; i++)
+ if (man[i])
+ return 0;
+
+ return 1;
+}
+
+
+
+
+
+/***
+* _ShrMan - shift mantissa to the right
+*
+*Purpose:
+* shift man by n bits to the right
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+void _ShrMan (intrnman man, int n)
+{
+ int i, n1, n2, mask;
+ int carry_from_left;
+
+ //
+ // declare this as volatile in order to work around a C8
+ // optimization bug
+ //
+
+ volatile int carry_to_right;
+
+ n1 = n / 32;
+ n2 = n % 32;
+
+ mask = ~(MAX_ULONG << n2);
+
+
+ //
+ // first deal with shifts by less than 32 bits
+ //
+
+ carry_from_left = 0;
+ for (i=0; i<INTRNMAN_LEN; i++) {
+
+ carry_to_right = man[i] & mask;
+
+ man[i] >>= n2;
+
+ man[i] |= carry_from_left;
+
+ carry_from_left = carry_to_right << (32 - n2);
+ }
+
+
+ //
+ // now shift whole 32-bit ints
+ //
+
+ for (i=INTRNMAN_LEN-1; i>=0; i--) {
+ if (i >= n1) {
+ man[i] = man[i-n1];
+ }
+ else {
+ man[i] = 0;
+ }
+ }
+}
+
+
+
+
+/***
+* _ld12tocvt - _ULDBL12 floating point conversion
+*
+*Purpose:
+* convert a internal _LBL12 structure into an IEEE floating point
+* representation
+*
+*
+*Entry:
+* pld12: pointer to the _ULDBL12
+* format: pointer to the format descriptor structure
+*
+*Exit:
+* *d contains the IEEE representation
+* returns the INTRNCVT_STATUS
+*
+*Exceptions:
+*
+*******************************************************************************/
+INTRNCVT_STATUS _ld12cvt(_ULDBL12 *pld12, void *d, FpFormatDescriptor *format)
+{
+ u_long man[INTRNMAN_LEN];
+ u_long saved_man[INTRNMAN_LEN];
+ u_long msw;
+ unsigned int bexp; // biased exponent
+ int exp_shift;
+ int exponent, sign;
+ INTRNCVT_STATUS retval;
+
+ exponent = (*U_EXP_12(pld12) & 0x7fff) - 0x3fff; // unbias exponent
+ sign = *U_EXP_12(pld12) & 0x8000;
+
+ //
+ // bexp is the final biased value of the exponent to be used
+ // Each of the following blocks should provide appropriate
+ // values for man, bexp and retval. The mantissa is also
+ // shifted to the right, leaving space for the exponent
+ // and sign to be inserted
+ //
+
+
+ if (exponent == 0 - 0x3fff) {
+
+ // either a denormal or zero
+ bexp = 0;
+
+ if (_IsZeroMan(man)) {
+
+ retval = INTRNCVT_OK;
+ }
+ else {
+
+ _FillZeroMan(man);
+
+ // denormal has been flushed to zero
+
+ retval = INTRNCVT_UNDERFLOW;
+ }
+ }
+ else {
+
+ man[0] = *UL_MANHI_12(pld12);
+ man[1] = *UL_MANLO_12(pld12);
+ man[2] = *U_XT_12(pld12) << 16;
+
+ // save mantissa in case it needs to be rounded again
+ // at a different point (e.g., if the result is a denormal)
+
+ _CopyMan(saved_man, man);
+
+ if (_RoundMan(man, format->precision)) {
+ exponent ++;
+ }
+
+ if (exponent < format->min_exp - format->precision ) {
+
+ //
+ // underflow that produces a zero
+ //
+
+ _FillZeroMan(man);
+ bexp = 0;
+ retval = INTRNCVT_UNDERFLOW;
+ }
+
+ else if (exponent <= format->min_exp) {
+
+ //
+ // underflow that produces a denormal
+ //
+ //
+
+ // The (unbiased) exponent will be MIN_EXP
+ // Find out how much the mantissa should be shifted
+ // One shift is done implicitly by moving the
+ // binary point one bit to the left, i.e.,
+ // we treat the mantissa as .ddddd instead of d.dddd
+ // (where d is a binary digit)
+
+ int shift = format->min_exp - exponent;
+
+ // The mantissa should be rounded again, so it
+ // has to be restored
+
+ _CopyMan(man,saved_man);
+
+ _ShrMan(man, shift);
+ _RoundMan(man, format->precision); // need not check for carry
+
+ // make room for the exponent + sign
+
+ _ShrMan(man, format->exp_width + 1);
+
+ bexp = 0;
+ retval = INTRNCVT_UNDERFLOW;
+
+ }
+
+ else if (exponent >= format->max_exp) {
+
+ //
+ // overflow, return infinity
+ //
+
+ _FillZeroMan(man);
+ man[0] |= (1 << 31); // set MSB
+
+ // make room for the exponent + sign
+
+ _ShrMan(man, (format->exp_width + 1) - 1);
+
+ bexp = format->max_exp + format->bias;
+
+ retval = INTRNCVT_OVERFLOW;
+ }
+
+ else {
+
+ //
+ // valid, normalized result
+ //
+
+ bexp = exponent + format->bias;
+
+
+ // clear implied bit
+
+ man[0] &= (~( 1 << 31));
+
+ //
+ // shift right to make room for exponent + sign
+ //
+
+ _ShrMan(man, (format->exp_width + 1) - 1);
+
+ retval = INTRNCVT_OK;
+
+ }
+ }
+
+
+ exp_shift = 32 - (format->exp_width + 1);
+ msw = man[0] |
+ (bexp << exp_shift) |
+ (sign ? 1<<31 : 0);
+
+ if (format->format_width == 64) {
+
+ *UL_HI_D(d) = msw;
+ *UL_LO_D(d) = man[1];
+ }
+
+ else if (format->format_width == 32) {
+
+ *(u_long *)d = msw;
+
+ }
+
+ return retval;
+}
+
+
+/***
+* _ld12tod - convert _ULDBL12 to double
+*
+*Purpose:
+*
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+INTRNCVT_STATUS _ld12tod(_ULDBL12 *pld12, UDOUBLE *d)
+{
+ return _ld12cvt(pld12, d, &DoubleFormat);
+}
+
+
+
+/***
+* _ld12tof - convert _ULDBL12 to float
+*
+*Purpose:
+*
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+INTRNCVT_STATUS _ld12tof(_ULDBL12 *pld12, FLOAT *f)
+{
+ return _ld12cvt(pld12, f, &FloatFormat);
+}
+
+
+/***
+* _ld12told - convert _ULDBL12 to 80 bit long double
+*
+*Purpose:
+*
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+void _ld12told(_ULDBL12 *pld12, _ULDOUBLE *pld)
+{
+
+ //
+ // This implementation is based on the fact that the _ULDBL12 format is
+ // identical to the long double and has 2 extra bytes of mantissa
+ //
+
+ u_short exp, sign;
+ u_long man[INTRNMAN_LEN];
+
+ exp = *U_EXP_12(pld12) & (u_short)0x7fff;
+ sign = *U_EXP_12(pld12) & (u_short)0x8000;
+
+ man[0] = *UL_MANHI_12(pld12);
+ man[1] = *UL_MANLO_12(pld12);
+ man[2] = *U_XT_12(pld12) << 16;
+
+ if (_RoundMan(man, 64))
+ exp ++;
+
+ *UL_MANHI_LD(pld) = man[0];
+ *UL_MANLO_LD(pld) = man[1];
+ *U_EXP_LD(pld) = sign | exp;
+}
+
+
+void _atodbl(UDOUBLE *d, char *str)
+{
+ char *EndPtr;
+ _ULDBL12 ld12;
+
+ __strgtold12(&ld12, &EndPtr, str, 0 );
+ _ld12tod(&ld12, d);
+}
+
+
+void _atoldbl(_ULDOUBLE *ld, char *str)
+{
+ char *EndPtr;
+ _ULDBL12 ld12;
+
+ __strgtold12(&ld12, &EndPtr, str, 0 );
+ _ld12told(&ld12, ld);
+}
+
+
+void _atoflt(FLOAT *f, char *str)
+{
+ char *EndPtr;
+ _ULDBL12 ld12;
+
+ __strgtold12(&ld12, &EndPtr, str, 0 );
+ _ld12tof(&ld12, f);
+}
diff --git a/private/windbg/lib/makefile b/private/windbg/lib/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/lib/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/lib/mantold.c b/private/windbg/lib/mantold.c
new file mode 100644
index 000000000..05dc6db7c
--- /dev/null
+++ b/private/windbg/lib/mantold.c
@@ -0,0 +1,184 @@
+/***
+*mantold.c - conversion of a decimal mantissa to _ULDBL12
+*
+* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Conversion of a decimal mantissa into _ULDBL12 format (i.e. long
+* double with two additional bytes of significand)
+*
+*Revision History:
+* 7-17-91 GDP Initial version (ported from assembly)
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+#include "cv.h"
+
+
+
+
+
+
+/***
+*int __addl(u_long x, u_long y, u_long *sum) - u_long addition
+*
+*Purpose: add two u_long numbers and return carry
+*
+*Entry: u_long x, u_long y : the numbers to be added
+* u_long *sum : where to store the result
+*
+*Exit: *sum receives the value of x+y
+* the value of the carry is returned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int __addl(u_long x, u_long y, u_long *sum)
+{
+ u_long r;
+ int carry=0;
+ r = x+y;
+ if (r < x || r < y)
+ carry++;
+ *sum = r;
+ return carry;
+}
+
+
+
+
+
+
+/***
+*void __add_12(_ULDBL12 *x, _ULDBL12 *y) - _ULDBL12 addition
+*
+*Purpose: add two _ULDBL12 numbers. The numbers are added
+* as 12-byte integers. Overflow is ignored.
+*
+*Entry: x,y: pointers to the operands
+*
+*Exit: *x receives the sum
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __add_12(_ULDBL12 *x, _ULDBL12 *y)
+{
+ int c0,c1,c2;
+ c0 = __addl(*UL_LO_12(x),*UL_LO_12(y),UL_LO_12(x));
+ if (c0) {
+ c1 = __addl(*UL_MED_12(x),(u_long)1,UL_MED_12(x));
+ if (c1) {
+ (*UL_HI_12(x))++;
+ }
+ }
+ c2 = __addl(*UL_MED_12(x),*UL_MED_12(y),UL_MED_12(x));
+ if (c2) {
+ (*UL_HI_12(x))++;
+ }
+ /* ignore next carry -- assume no overflow will occur */
+ (void) __addl(*UL_HI_12(x),*UL_HI_12(y),UL_HI_12(x));
+}
+
+
+
+
+
+/***
+*void __shl_12(_ULDBL12 *x) - _ULDBL12 shift left
+*void __shr_12(_ULDBL12 *x) - _ULDBL12 shift right
+*
+*Purpose: Shift a _ULDBL12 number one bit to the left (right). The number
+* is shifted as a 12-byte integer. The MSB is lost.
+*
+*Entry: x: a pointer to the operand
+*
+*Exit: *x is shifted one bit to the left (or right)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __shl_12(_ULDBL12 *p)
+{
+ u_long c0,c1;
+
+ c0 = *UL_LO_12(p) & MSB_ULONG ? 1: 0;
+ c1 = *UL_MED_12(p) & MSB_ULONG ? 1: 0;
+ *UL_LO_12(p) <<= 1;
+ *UL_MED_12(p) = *UL_MED_12(p)<<1 | c0;
+ *UL_HI_12(p) = *UL_HI_12(p)<<1 | c1;
+}
+
+void __shr_12(_ULDBL12 *p)
+{
+ u_long c2,c1;
+ c2 = *UL_HI_12(p) & 0x1 ? MSB_ULONG: 0;
+ c1 = *UL_MED_12(p) & 0x1 ? MSB_ULONG: 0;
+ *UL_HI_12(p) >>= 1;
+ *UL_MED_12(p) = *UL_MED_12(p)>>1 | c2;
+ *UL_LO_12(p) = *UL_LO_12(p)>>1 | c1;
+}
+
+
+
+
+
+
+/***
+*void __mtold12(char *manptr,unsigned manlen,_ULDBL12 *ld12) -
+* convert a mantissa into a _ULDBL12
+*
+*Purpose: convert a mantissa into a _ULDBL12. The mantissa is
+* in the form of an array of manlen BCD digits and is
+* considered to be an integer.
+*
+*Entry: manptr: the array containing the packed BCD digits of the mantissa
+* manlen: the size of the array
+* ld12: a pointer to the long double where the result will be stored
+*
+*Exit:
+* ld12 gets the result of the conversion
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __mtold12(char *manptr,
+ unsigned manlen,
+ _ULDBL12 *ld12)
+{
+ _ULDBL12 tmp;
+ u_short expn = LD_BIASM1+80;
+
+ *UL_LO_12(ld12) = 0;
+ *UL_MED_12(ld12) = 0;
+ *UL_HI_12(ld12) = 0;
+ for (;manlen>0;manlen--,manptr++){
+ tmp = *ld12;
+ __shl_12(ld12);
+ __shl_12(ld12);
+ __add_12(ld12,&tmp);
+ __shl_12(ld12); /* multiply by 10 */
+ *UL_LO_12(&tmp) = (u_long)*manptr;
+ *UL_MED_12(&tmp) = 0;
+ *UL_HI_12(&tmp) = 0;
+ __add_12(ld12,&tmp);
+ }
+
+ /* normalize mantissa -- first shift word by word */
+ while (*UL_HI_12(ld12) == 0) {
+ *UL_HI_12(ld12) = *UL_MED_12(ld12) >> 16;
+ *UL_MED_12(ld12) = *UL_MED_12(ld12) << 16 | *UL_LO_12(ld12) >> 16;
+ (*UL_LO_12(ld12)) <<= 16;
+ expn -= 16;
+ }
+ while ((*UL_HI_12(ld12) & 0x8000) == 0) {
+ __shl_12(ld12);
+ expn--;
+ }
+ *U_EXP_12(ld12) = expn;
+}
diff --git a/private/windbg/lib/rtlproto.h b/private/windbg/lib/rtlproto.h
new file mode 100644
index 000000000..b0c3e76ca
--- /dev/null
+++ b/private/windbg/lib/rtlproto.h
@@ -0,0 +1,88 @@
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+
+//
+// Convert between signed and unsigned
+//
+
+// LARGE_INTEGER
+// _CRTAPI1
+// RtlConvertULargeIntegerToSigned(ULARGE_INTEGER uli);
+#define RtlConvertULargeIntegerToSigned(uli) (*(PLARGE_INTEGER)(&(uli)))
+
+
+// ULARGE_INTEGER
+// _CRTAPI1
+// RtlConvertLargeIntegerToUnsigned(LARGE_INTEGER li);
+#define RtlConvertLargeIntegerToUnsigned(li) (*((PULARGE_INTEGER)(&(li))))
+
+
+//
+// math routines for ULARGE_INTEGERs
+//
+
+ULARGE_INTEGER
+// _CRTAPI1
+RtlULargeIntegerNegate(ULARGE_INTEGER);
+
+
+/*
+ * #define RtlULargeIntegerNegate(uli) RtlConvertLargeIntegerToUnsigned( \
+ * RtlLargeIntegerNegate( \
+ * RtlConvertULargeIntegerToSigned(uli)))
+**/
+
+BOOLEAN
+// _CRTAPI1
+RtlULargeIntegerEqualToZero(ULARGE_INTEGER);
+/* #define RtlULargeIntegerEqualToZero(uli) RtlConvertLargeIntegerToUnsigned( \
+ * RtlLargeIntegerEqualToZero( \
+ * RtlConvertULargeIntegerToSigned(uli)))
+**/
+
+
+//
+// from strtoli.c
+//
+
+LARGE_INTEGER
+// _CRTAPI1
+strtoli ( const char *, char **, int );
+
+ULARGE_INTEGER
+// _CRTAPI1
+strtouli ( const char *, char **, int );
+
+
+
+//
+// Large integer and - 64-bite & 64-bits -> 64-bits.
+//
+
+#define RtlLargeIntegerOr(Result, Source, Mask) \
+ { \
+ Result.HighPart = Source.HighPart | Mask.HighPart; \
+ Result.LowPart = Source.LowPart | Mask.LowPart; \
+ }
+
+
+
+
+//
+// Arithmetic right shift (the one in ntrtl.h is logical)
+//
+
+LARGE_INTEGER
+// _CRTAPI1
+RtlLargeIntegerArithmeticShiftRight(LARGE_INTEGER, CCHAR);
+
+
+//
+// bit-wise negation
+//
+#define RtlLargeIntegerBitwiseNot(li) \
+ li.LowPart = ~li.LowPart; \
+ li.HighPart = ~li.HighPart;
diff --git a/private/windbg/lib/sources b/private/windbg/lib/sources
new file mode 100644
index 000000000..609a6a8f4
--- /dev/null
+++ b/private/windbg/lib/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Miche Baker-Harvey (v-michbh)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=mathlib
+
+TARGETNAME=mathlib
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES=strtoli.c \
+ strgtold.c \
+ mantold.c \
+ tenpow.c \
+ constpow.c \
+ x10fout.c \
+ cvt.c \
+ cfout.c \
+ cfin.c \
+ intrncvt.c \
+ atold.c \
+ heap.c
+
+
+UMTYPE=windows
+
+INCLUDES=..\osdebug\include
+
+!include ..\common.src
diff --git a/private/windbg/lib/strgtold.c b/private/windbg/lib/strgtold.c
new file mode 100644
index 000000000..5f2d374d0
--- /dev/null
+++ b/private/windbg/lib/strgtold.c
@@ -0,0 +1,393 @@
+/***
+*strgtold.c - conversion of a string into a long double
+*
+* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose: convert a fp constant into a 10 byte long double (IEEE format)
+*
+*Revision History:
+* 7-17-91 GDP Initial version (ported from assembly)
+* 4-03-92 GDP Preserve sign of -0
+* 4-30-92 GDP Now returns _ULDBL12 instead of _ULDOUBLE
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+//#include <ctype.h> /* for 'isdigit' macro */
+#include "cv.h"
+
+
+
+/* local macros */
+#define ISNZDIGIT(x) ((x)>='1' && (x)<='9' )
+
+//NOTENOTE the following takes the place of the isdigit() macro
+// which does not work for a yet to be determined reason
+#define ISADIGIT(x) ((x)>='0' && (x)<='9' )
+
+#define ISWHITE(x) ((x)==' ' || (x)=='\t' || (x)=='\n' || (x)=='\r' )
+
+
+
+
+/****
+*unsigned int __strgtold( _ULDBL12 *pld12,
+* char * * pEndPtr,
+* char * str,
+* int Mult12 )
+*
+*Purpose:
+* converts a character string into a long double
+*
+*Entry:
+* pld12 - pointer to the _ULDBL12 where the result should go.
+* pEndStr - pointer to a far pointer that will be set to the end of string.
+* str - pointer to the string to be converted.
+* Mult12 - set to non zero if the _ULDBL12 multiply should be used instead of
+* the long double mulitiply.
+*
+*Exit:
+* Returns the SLD_* flags or'ed together.
+*
+*Uses:
+*
+*Exceptions:
+*
+********************************************************************************/
+
+unsigned int
+__strgtold12(_ULDBL12 *pld12,
+ char * *p_end_ptr,
+ char *str,
+ int mult12)
+{
+ typedef enum {
+ S_INIT, /* initial state */
+ S_EAT0L, /* eat 0's at the left of mantissa */
+ S_SIGNM, /* just read sign of mantissa */
+ S_GETL, /* get integer part of mantissa */
+ S_GETR, /* get decimal part of mantissa */
+ S_POINT, /* just found decimal point */
+ S_E, /* just found 'E', or 'e', etc */
+ S_SIGNE, /* just read sign of exponent */
+ S_EAT0E, /* eat 0's at the left of exponent */
+ S_GETE, /* get exponent */
+ S_END /* final state */
+ } state_t;
+
+ /* this will accomodate the digits of the mantissa in BCD form*/
+ static char buf[LD_MAX_MAN_LEN1];
+ char *manp = buf;
+
+ /* a temporary _ULDBL12 */
+ _ULDBL12 tmpld12;
+
+ u_short man_sign = 0; /* to be ORed with result */
+ int exp_sign = 1; /* default sign of exponent (values: +1 or -1)*/
+ /* number of decimal significant mantissa digits so far*/
+ unsigned manlen = 0;
+ int found_digit = 0;
+ int overflow = 0;
+ int underflow = 0;
+ int pow = 0;
+ int exp_adj = 0; /* exponent adjustment */
+ u_long ul0,ul1;
+ u_short u,uexp;
+
+ unsigned int result_flags = 0;
+
+ state_t state = S_INIT;
+
+ char c; /* the current input symbol */
+ char *p; /* a pointer to the next input symbol */
+ char *savedp;
+
+ for(savedp=p=str;ISWHITE(*p);p++); /* eat up white space */
+
+ while (state != S_END) {
+ c = *p++;
+ switch (state) {
+ case S_INIT:
+ if (ISNZDIGIT(c)) {
+ state = S_GETL;
+ p--;
+ }
+ else
+ switch (c) {
+ case '0':
+ state = S_EAT0L;
+ break;
+ case '+':
+ state = S_SIGNM;
+ man_sign = 0x0000;
+ break;
+ case '-':
+ state = S_SIGNM;
+ man_sign = 0x8000;
+ break;
+ case '.':
+ state = S_POINT;
+ break;
+ default:
+ state = S_END;
+ p--;
+ break;
+ }
+ break;
+ case S_EAT0L:
+ found_digit = 1;
+ if (ISNZDIGIT(c)) {
+ state = S_GETL;
+ p--;
+ }
+ else
+ switch (c) {
+ case '0':
+ state = S_EAT0L;
+ break;
+ case 'E':
+ case 'e':
+ case 'D':
+ case 'd':
+ state = S_E;
+ break;
+ case '.':
+ state = S_GETR;
+ break;
+ default:
+ state = S_END;
+ p--;
+ }
+ break;
+ case S_SIGNM:
+ if (ISNZDIGIT(c)) {
+ state = S_GETL;
+ p--;
+ }
+ else
+ switch (c) {
+ case '0':
+ state = S_EAT0L;
+ break;
+ case '.':
+ state = S_POINT;
+ break;
+ default:
+ state = S_END;
+ p = savedp;
+ }
+ break;
+ case S_GETL:
+ found_digit = 1;
+ for (;ISADIGIT(c);c=*p++) {
+ if (manlen < LD_MAX_MAN_LEN+1){
+ manlen++;
+ *manp++ = c - (char)'0';
+ }
+ else
+ exp_adj++;
+ }
+ switch (c) {
+ case '.':
+ state = S_GETR;
+ break;
+ case 'E':
+ case 'e':
+ case 'D':
+ case 'd':
+ state = S_E;
+ break;
+ default:
+ state = S_END;
+ p--;
+ }
+ break;
+ case S_GETR:
+ found_digit = 1;
+ if (manlen == 0)
+ for (;c=='0';c=*p++)
+ exp_adj--;
+ for(;ISADIGIT(c);c=*p++){
+ if (manlen < LD_MAX_MAN_LEN+1){
+ manlen++;
+ *manp++ = c - (char)'0';
+ exp_adj--;
+ }
+ }
+ switch (c){
+ case 'E':
+ case 'e':
+ case 'D':
+ case 'd':
+ state = S_E;
+ break;
+ default:
+ state = S_END;
+ p--;
+ }
+ break;
+ case S_POINT:
+ if (ISADIGIT(c)){
+ state = S_GETR;
+ p--;
+ }
+ else{
+ state = S_END;
+ p = savedp;
+ }
+ break;
+ case S_E:
+ savedp = p-2; /* savedp points to 'E' */
+ if (ISNZDIGIT(c)){
+ state = S_GETE;
+ p--;
+ }
+ else
+ switch (c){
+ case '0':
+ state = S_EAT0E;
+ break;
+ case '-':
+ state = S_SIGNE;
+ exp_sign = -1;
+ break;
+ case '+':
+ state = S_SIGNE;
+ break;
+ default:
+ state = S_END;
+ p = savedp;
+ }
+ break;
+ case S_EAT0E:
+ for(;c=='0';c=*p++);
+ if (ISNZDIGIT(c)){
+ state = S_GETE;
+ p--;
+ }
+ else {
+ state = S_END;
+ p--;
+ }
+ break;
+ case S_SIGNE:
+ if (ISNZDIGIT(c)){
+ state = S_GETE;
+ p--;
+ }
+ else
+ switch (c){
+ case '0':
+ state = S_EAT0E;
+ break;
+ default:
+ state = S_END;
+ p = savedp;
+ }
+ break;
+ case S_GETE:
+ {
+ long longpow=0; /* TMAX10*10 should fit in a long */
+ for(;ISADIGIT(c);c=*p++){
+ longpow = longpow*10 + (c - '0');
+ if (longpow > TMAX10){
+ longpow = TMAX10+1; /* will force overflow */
+ break;
+ }
+ }
+ pow = (int)longpow;
+ }
+ for(;ISADIGIT(c);c=*p++); /* eat up remaining digits */
+ state = S_END;
+ p--;
+ break;
+ } /* switch */
+ } /* while */
+
+ *p_end_ptr = p; /* set end pointer */
+
+ /*
+ * Compute result
+ */
+
+ if (found_digit && !overflow && !underflow) {
+ if (manlen>LD_MAX_MAN_LEN){
+ if (buf[LD_MAX_MAN_LEN-1]>=5) {
+ /*
+ * Round mantissa to MAX_MAN_LEN digits
+ * It's ok to round 9 to 0ah
+ */
+ buf[LD_MAX_MAN_LEN-1]++;
+ }
+ manlen = LD_MAX_MAN_LEN;
+ manp--;
+ exp_adj++;
+ }
+ if (manlen>0) {
+ /*
+ * Remove trailing zero's from mantissa
+ */
+ for(manp--;*manp==0;manp--) {
+ /* there is at least one non-zero digit */
+ manlen--;
+ exp_adj++;
+ }
+ __mtold12(buf,manlen,&tmpld12);
+
+ if (exp_sign < 0)
+ pow = -pow;
+ pow += exp_adj;
+ if (pow > TMAX10)
+ overflow = 1;
+ else if (pow < TMIN10)
+ underflow = 1;
+ else {
+ __multtenpow12(&tmpld12,pow,mult12);
+
+ u = *U_XT_12(&tmpld12);
+ ul0 =*UL_MANLO_12(&tmpld12);
+ ul1 = *UL_MANHI_12(&tmpld12);
+ uexp = *U_EXP_12(&tmpld12);
+
+ }
+ }
+ else {
+ /* manlen == 0, so return 0 */
+ u = (u_short)0;
+ ul0 = ul1 = uexp = 0;
+ }
+ }
+
+ if (!found_digit) {
+ /* return 0 */
+ u = (u_short)0;
+ ul0 = ul1 = uexp = 0;
+ result_flags |= SLD_NODIGITS;
+ }
+ else if (overflow) {
+ /* return +inf or -inf */
+ uexp = (u_short)0x7fff;
+ ul1 = 0x80000000;
+ ul0 = 0;
+ u = (u_short)0;
+ result_flags |= SLD_OVERFLOW;
+ }
+ else if (underflow) {
+ /* return 0 */
+ u = (u_short)0;
+ ul0 = ul1 = uexp = 0;
+ result_flags |= SLD_UNDERFLOW;
+ }
+
+ /*
+ * Assemble result
+ */
+
+ *U_XT_12(pld12) = u;
+ *UL_MANLO_12(pld12) = ul0;
+ *UL_MANHI_12(pld12) = ul1;
+ *U_EXP_12(pld12) = uexp | man_sign;
+
+ return result_flags;
+}
+
diff --git a/private/windbg/lib/strtoli.c b/private/windbg/lib/strtoli.c
new file mode 100644
index 000000000..9d834c39f
--- /dev/null
+++ b/private/windbg/lib/strtoli.c
@@ -0,0 +1,242 @@
+/***
+*strtoli.c - Contains C runtimes strtol and strtoul
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+* Copyright (c) 1989-1993, Digital Equipment Corporation. All rights reserved.
+*
+*Purpose:
+* strtoli - convert ascii string to long signed large integer
+* strtouli - convert ascii string to long unsigned large integer
+*
+*Revision History:
+* 04-28-93 MBH Module created, based on strtol.c
+*
+*******************************************************************************/
+
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+
+
+#include <windows.h>
+#include <shellapi.h>
+
+
+
+
+// #include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+
+
+/***
+*strtoli, strtouli(nptr,endptr,ibase) - Convert ascii string to long un/signed
+* large integer.
+*
+*Purpose:
+* Convert an ascii string to a long 64-bit value. The base
+* used for the caculations is supplied by the caller. The base
+* must be in the range 0, 2-36. If a base of 0 is supplied, the
+* ascii string must be examined to determine the base of the
+* number:
+* (a) First char = '0', second char = 'x' or 'X',
+* use base 16.
+* (b) First char = '0', use base 8
+* (c) First char in range '1' - '9', use base 10.
+*
+* If the 'endptr' value is non-NULL, then strtoli/strtouli places
+* a pointer to the terminating character in this value.
+* See ANSI standard for details
+*
+*Entry:
+* nptr == NEAR/FAR pointer to the start of string.
+* endptr == NEAR/FAR pointer to the end of the string.
+* ibase == integer base to use for the calculations.
+*
+* string format: [whitespace] [sign] [0] [x] [digits/letters]
+*
+*Exit:
+* Good return:
+* result
+*
+* Overflow return:
+* strtoli -- LONG_MAX or LONG_MIN in HighPart
+* strtouli -- ULONG_MAX in HighPart
+* strtoli/strtouli -- errno == ERANGE
+*
+* No digits or bad base return:
+* 0
+* endptr = nptr*
+*
+*Exceptions:
+* None.
+*******************************************************************************/
+
+/* flag values */
+#define FL_UNSIGNED 1 /* strtoul called */
+#define FL_NEG 2 /* negative sign found */
+#define FL_OVERFLOW 4 /* overflow occured */
+#define FL_READDIGIT 8 /* we've read at least one correct digit */
+
+static
+LARGE_INTEGER
+// MBH - if this is a library, this should be CRTAPI3
+_CRTAPI2 strtoxl (
+ const char *nptr,
+ const char **endptr,
+ int ibase,
+ int flags
+ )
+{
+ const char *p;
+ char c;
+
+ LARGE_INTEGER number; // being computed
+ unsigned long digval; // each digit in turn
+ LARGE_INTEGER maxval; // value more than which --> overflow
+ LARGE_INTEGER maxli; // largest possible large integer
+ unsigned long remainder; // maxli=maxval/radix + remainder
+
+ p = nptr; /* p is our scanning pointer */
+ number.QuadPart = 0;
+ maxli.QuadPart = -1;
+
+ c = *p++; /* read char */
+ while ( isspace((int)(unsigned char)c) )
+ c = *p++; /* skip whitespace */
+
+ if (c == '-') {
+ flags |= FL_NEG; /* remember minus sign */
+ c = *p++;
+ }
+ else if (c == '+')
+ c = *p++; /* skip sign */
+
+ if (ibase < 0 || ibase == 1 || ibase > 36) {
+ /* bad base! */
+ if (endptr)
+ /* store beginning of string in endptr */
+ *endptr = nptr;
+ number.QuadPart = 0;
+ return number;
+ }
+ else if (ibase == 0) {
+ /* determine base free-lance, based on first two chars of
+ string */
+ if (c != '0')
+ ibase = 10;
+ else if (*p == 'x' || *p == 'X')
+ ibase = 16;
+ else
+ ibase = 8;
+ }
+
+ if (ibase == 16) {
+ /* we might have 0x in front of number; remove if there */
+ if (c == '0' && (*p == 'x' || *p == 'X')) {
+ ++p;
+ c = *p++; /* advance past prefix */
+ }
+ }
+
+ /* if our number exceeds this, we will overflow on multiply */
+ maxval.QuadPart = maxli.QuadPart / ibase;
+ remainder = (unsigned long)(maxli.QuadPart - maxval.QuadPart);
+
+ for (;;) { /* exit in middle of loop */
+ /* convert c to value */
+ if ( isdigit((int)(unsigned char)c) )
+ digval = c - '0';
+ else if ( isalpha((int)(unsigned char)c) )
+ digval = toupper(c) - 'A' + 10;
+ else
+ break;
+ if (digval >= (unsigned)ibase)
+ break; /* exit loop if bad digit found */
+
+ /* record the fact we have read one digit */
+ flags |= FL_READDIGIT;
+
+ /* we now need to compute number = number * base + digval,
+ but we need to know if overflow occured. This requires
+ a tricky pre-check. */
+
+ if (number.QuadPart <= maxval.QuadPart && digval <= remainder) {
+ //
+ // we won't overflow, go ahead and multiply
+ //
+ number.QuadPart = (number.QuadPart * ibase) + digval;
+ } else {
+ //
+ // we would have overflowed -- set the overflow flag
+ //
+ flags |= FL_OVERFLOW;
+ }
+
+ c = *p++; /* read next digit */
+ }
+
+ --p; /* point to place that stopped scan */
+
+ if (!(flags & FL_READDIGIT)) {
+ /* no number there; return 0 and point to beginning of
+ string */
+ if (endptr)
+ /* store beginning of string in endptr later on */
+ p = nptr;
+ /* return 0 */
+ number.QuadPart = 0;
+ }
+ else if ((flags & FL_OVERFLOW) || (!(flags & FL_UNSIGNED) && (number.QuadPart < 0))) {
+
+ /* overflow occurred or signed overflow occurred */
+ errno = ERANGE;
+ if (flags & FL_UNSIGNED)
+ number.QuadPart = maxli.QuadPart >> 1;
+ else
+ /* set error code, will be negated if necc. */
+ number = maxli;
+ }
+
+ if (endptr != NULL)
+ /* store pointer to char that stopped the scan */
+ *endptr = p;
+
+ if (flags & FL_NEG)
+ /* negate result if there was a neg sign */
+ number.QuadPart = number.QuadPart * -1;
+
+ return number; /* done. */
+}
+
+LARGE_INTEGER
+// _CRTAPI1
+strtoli (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return strtoxl(nptr, endptr, ibase, 0);
+}
+
+ULARGE_INTEGER
+// _CRTAPI1
+strtouli (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ ULARGE_INTEGER uli;
+ LARGE_INTEGER li;
+
+ li = strtoxl(nptr, endptr, ibase, FL_UNSIGNED);
+ uli.LowPart = li.LowPart;
+ uli.HighPart = li.HighPart;
+ return uli;
+}
diff --git a/private/windbg/lib/tenpow.c b/private/windbg/lib/tenpow.c
new file mode 100644
index 000000000..0c7cad76b
--- /dev/null
+++ b/private/windbg/lib/tenpow.c
@@ -0,0 +1,240 @@
+/***
+*tenpow.c - multiply a _ULDBL12 by a power of 10
+*
+* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 7-17-91 GDP Initial version (ported from assembly)
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+
+#include "cv.h"
+
+
+
+extern _ULDBL12 _pow10pos[];
+extern _ULDBL12 _pow10neg[];
+
+
+
+
+/***
+*void __ld12mul(_ULDBL12 *px, _ULDBL12 *py) -
+* _ULDBL12 multiplication
+*
+*Purpose: multiply two _ULDBL12 numbers
+*
+*Entry: px,py: pointers to the _ULDBL12 operands
+*
+*Exit: *px contains the product
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __ld12mul(_ULDBL12 *px, _ULDBL12 *py)
+{
+ u_short sign = 0;
+ u_short sticky_bits = 0;
+ _ULDBL12 tempman; /*this is actually a 12-byte mantissa,
+ not a 12-byte long double */
+ int i;
+ u_short expx, expy, expsum;
+ int roffs,poffs,qoffs;
+ int sticky;
+
+ *UL_LO_12(&tempman) = 0;
+ *UL_MED_12(&tempman) = 0;
+ *UL_HI_12(&tempman) = 0;
+
+ expx = *U_EXP_12(px);
+ expy = *U_EXP_12(py);
+
+ sign = (expx ^ expy) & (u_short)0x8000;
+ expx &= 0x7fff;
+ expy &= 0x7fff;
+ expsum = expx+expy;
+ if (expx >= LD_MAXEXP
+ || expy >= LD_MAXEXP
+ || expsum > LD_MAXEXP+ LD_BIASM1){
+ /* overflow to infinity */
+ PUT_INF_12(px,sign);
+ return;
+ }
+ if (expsum <= LD_BIASM1-63) {
+ /* underflow to zero */
+ PUT_ZERO_12(px);
+ return;
+ }
+ if (expx == 0) {
+ /*
+ * If this is a denormal temp real then the mantissa
+ * was shifted right once to set bit 63 to zero.
+ */
+ expsum++; /* Correct for this */
+ if (ISZERO_12(px)) {
+ /* put positive sign */
+ *U_EXP_12(px) = 0;
+ return;
+ }
+ }
+ if (expy == 0) {
+ expsum++; /* because arg2 is denormal */
+ if (ISZERO_12(py)) {
+ PUT_ZERO_12(px);
+ return;
+ }
+ }
+
+ roffs = 0;
+ for (i=0;i<5;i++) {
+ int j;
+ poffs = i<<1;
+ qoffs = 8;
+ for (j=5-i;j>0;j--) {
+ u_long prod;
+#ifdef MIPS
+ /* a variable to hold temprary sums */
+ u_long sum;
+#endif
+ int carry;
+ u_short *p, *q;
+ u_long *r;
+ p = USHORT_12(px,poffs);
+ q = USHORT_12(py,qoffs);
+ r = ULONG_12(&tempman,roffs);
+ prod = (u_long)*p * (u_long)*q;
+#ifdef MIPS
+ /* handle misalignment problems */
+ if (i&0x1){ /* i is odd */
+ carry = __addl(*MIPSALIGN(r), prod, &sum);
+ *MIPSALIGN(r) = sum;
+ }
+ else /* i is even */
+ carry = __addl(*r, prod, r);
+#else
+ carry = __addl(*r,prod,r);
+#endif
+ if (carry) {
+ /* roffs should be less than 8 in this case */
+ (*USHORT_12(&tempman,roffs+4))++;
+ }
+ poffs+=2;
+ qoffs-=2;
+ }
+ roffs+=2;
+ }
+
+ expsum -= LD_BIASM1;
+
+ /* normalize */
+ while ((s_short)expsum > 0 &&
+ ((*UL_HI_12(&tempman) & MSB_ULONG) == 0)) {
+ __shl_12(&tempman);
+ expsum--;
+ }
+
+ if ((s_short)expsum <= 0) {
+ expsum--;
+ while ((s_short)expsum < 0) {
+ if (*U_XT_12(&tempman) & 0x1)
+ sticky++;
+ __shr_12(&tempman);
+ expsum++;
+ }
+ if (sticky)
+ *U_XT_12(&tempman) |= 0x1;
+ }
+
+ if (*U_XT_12(&tempman) > 0x8000 ||
+ ((*UL_LO_12(&tempman) & 0x1ffff) == 0x18000)) {
+ /* round up */
+ if (*UL_MANLO_12(&tempman) == MAX_ULONG) {
+ *UL_MANLO_12(&tempman) = 0;
+ if (*UL_MANHI_12(&tempman) == MAX_ULONG) {
+ *UL_MANHI_12(&tempman) = 0;
+ if (*U_EXP_12(&tempman) == MAX_USHORT) {
+ /* 12-byte mantissa overflow */
+ *U_EXP_12(&tempman) = MSB_USHORT;
+ expsum++;
+ }
+ else
+ (*U_EXP_12(&tempman))++;
+ }
+ else
+ (*UL_MANHI_12(&tempman))++;
+ }
+ else
+ (*UL_MANLO_12(&tempman))++;
+ }
+
+
+ /* check for exponent overflow */
+ if (expsum >= 0x7fff){
+ PUT_INF_12(px, sign);
+ return;
+ }
+
+ /* put result in px */
+ *U_XT_12(px) = *USHORT_12(&tempman,2);
+ *UL_MANLO_12(px) = *UL_MED_12(&tempman);
+ *UL_MANHI_12(px) = *UL_HI_12(&tempman);
+ *U_EXP_12(px) = expsum | sign;
+}
+
+
+
+void __multtenpow12(_ULDBL12 *pld12, int pow, unsigned mult12)
+{
+ _ULDBL12 *pow_10p = _pow10pos-8;
+ if (pow == 0)
+ return;
+ if (pow < 0) {
+ pow = -pow;
+ pow_10p = _pow10neg-8;
+ }
+
+ if (!mult12)
+ *U_XT_12(pld12) = 0;
+
+
+ while (pow) {
+ int last3; /* the 3 LSBits of pow */
+ _ULDBL12 unround;
+ _ULDBL12 *py;
+
+ pow_10p += 7;
+ last3 = pow & 0x7;
+ pow >>= 3;
+ if (last3 == 0)
+ continue;
+ py = pow_10p + last3;
+
+#ifdef _ULDSUPPORT
+ if (mult12) {
+#endif
+ /* do an exact 12byte multiplication */
+ if (*U_XT_12(py) >= 0x8000) {
+ /* copy number */
+ unround = *py;
+ /* unround adjacent byte */
+ (*UL_MANLO_12(&unround))--;
+ /* point to new operand */
+ py = &unround;
+ }
+ __ld12mul(pld12,py);
+#ifdef _ULDSUPPORT
+ }
+ else {
+ /* do a 10byte multiplication */
+ py = (_ULDBL12 *)TEN_BYTE_PART(py);
+ *(long double *)TEN_BYTE_PART(pld12) *=
+ *(long double *)py;
+ }
+#endif
+ }
+}
diff --git a/private/windbg/lib/x10fout.c b/private/windbg/lib/x10fout.c
new file mode 100644
index 000000000..a71fc9019
--- /dev/null
+++ b/private/windbg/lib/x10fout.c
@@ -0,0 +1,464 @@
+/***
+*x10fout.c - floating point output for 10-byte long double
+*
+* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Support conversion of a long double into a string
+*
+*Revision History:
+* 07/15/91 GDP Initial version in C (ported from assembly)
+* 01/23/92 GDP Support MIPS encoding for NaN
+* 05-26-92 GWK Windbg srcs
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "cv.h"
+
+
+
+#define STRCPY strcpy
+
+#define PUT_ZERO_FOS(fos) \
+ fos->exp = 1, \
+ fos->sign = ' ', \
+ fos->ManLen = 1, \
+ fos->man[0] = '0',\
+ fos->man[1] = 0;
+
+#define SNAN_STR "1#SNAN"
+#define SNAN_STR_LEN 6
+#define QNAN_STR "1#QNAN"
+#define QNAN_STR_LEN 6
+#define INF_STR "1#INF"
+#define INF_STR_LEN 5
+#define IND_STR "1#IND"
+#define IND_STR_LEN 5
+
+#define MAX_10_LEN 30 //max length of string including NULL
+
+/***
+char * _uldtoa (_ULDOUBLE *px,
+* int maxchars,
+* char *ldtext)
+*
+*
+*Purpose:
+* Return pointer to filled in string "ldtext" for
+* a given _UDOUBLE ponter px
+* with a maximum character width of maxchars
+*
+*Entry:
+* _ULDOUBLE * px: a pointer to the long double to be converted into a string
+* int maxchars: number of digits allowed in the output format.
+*
+* (default is 'e' format)
+*
+* char * ldtext: a pointer to the output string
+*
+*Exit:
+* returns pointer to the output string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+char * _uldtoa (_ULDOUBLE *px, int maxchars, char *ldtext)
+{
+ char in_str [250];
+ char in_str2 [250];
+ char cExp[20];
+ FOS foss;
+ char * lpszMan;
+ char * lpIndx;
+ int nErr;
+ int len1, len2;
+
+ maxchars -= 8; /* sign, dot, E+0001 */
+
+ nErr = $I10_OUTPUT (*px, maxchars, 0, &foss);
+
+ lpszMan = foss.man;
+
+ ldtext[0] = foss.sign;
+ ldtext[1] = *lpszMan;
+ ldtext[2] = '.';
+ ldtext[3] = '\0';
+
+ maxchars += 2; /* sign, dot */
+
+ lpszMan++;
+ strcat (ldtext, lpszMan);
+
+ len1 = strlen (ldtext); // for 'e'
+
+
+ strcpy (cExp, "e");
+
+ foss.exp -= 1; /* Adjust for the shift decimal shift above */
+ _itoa (foss.exp, in_str, 10);
+
+
+ if (foss.exp < 0) {
+ strcat (cExp, "-");
+
+ strcpy (in_str2, &in_str[1]);
+ strcpy (in_str, in_str2);
+
+ while (strlen(in_str) < 4) {
+ strcpy (in_str2, in_str);
+ strcpy (in_str,"0");
+ strcat (in_str,in_str2);
+ }
+ } else {
+ while (strlen(in_str) < 4) {
+ strcpy (in_str2, in_str);
+ strcpy (in_str,"0");
+ strcat (in_str,in_str2);
+ }
+ }
+
+ if (foss.exp >= 0) {
+ strcat (cExp, "+");
+ }
+
+ strcat (cExp, in_str);
+
+ len2 = strlen (cExp);
+
+ if (len1 == maxchars) {
+ ;
+ }
+ else if (len1 < maxchars) {
+ do {
+ strcat (ldtext,"0");
+ len1++;
+ } while (len1 < maxchars);
+ }
+ else {
+ lpIndx = &ldtext[len1 - 1]; // point to last char and round
+ do {
+ *lpIndx = '\0';
+ lpIndx--;
+ len1--; //NOTENOTE v-griffk we really need to round
+ } while (len1 > maxchars);
+ }
+
+ strcat (ldtext, cExp);
+ return ldtext;
+}
+
+
+/***
+*int _$i10_output(_ULDOUBLE ld,
+* int ndigits,
+* unsigned output_flags,
+* FOS *fos) - output conversion of a 10-byte _ULDOUBLE
+*
+*Purpose:
+* Fill in a FOS structure for a given _ULDOUBLE
+*
+*Entry:
+* _ULDOUBLE ld: The long double to be converted into a string
+* int ndigits: number of digits allowed in the output format.
+* unsigned output_flags: The following flags can be used:
+* SO_FFORMAT: Indicates 'f' format
+* (default is 'e' format)
+* FOS *fos: the structure that i10_output will fill in
+*
+*Exit:
+* modifies *fos
+* return 1 if original number was ok, 0 otherwise (infinity, NaN, etc)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int $I10_OUTPUT(_ULDOUBLE ld, int ndigits,
+ unsigned output_flags, FOS *fos)
+{
+ u_short expn;
+ u_long manhi,manlo;
+ u_short sign;
+
+ /* useful constants (see algorithm explanation below) */
+ u_short const log2hi = 0x4d10;
+ u_short const log2lo = 0x4d;
+ u_short const log4hi = 0x9a;
+ u_long const c = 0x134312f4;
+#if defined(L_END)
+ _ULDBL12 ld12_one_tenth = {
+ {0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xfb,0x3f}
+ };
+#elif defined(B_END)
+ _ULDBL12 ld12_one_tenth = {
+ {0x3f,0xfb,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc}
+ };
+#endif
+
+ _ULDBL12 ld12; /* space for a 12-byte long double */
+ _ULDBL12 tmp12;
+ u_short hh,ll; /* the bytes of the exponent grouped in 2 words*/
+ u_short mm; /* the two MSBytes of the mantissa */
+ s_long r; /* the corresponding power of 10 */
+ s_short ir; /* ir = floor(r) */
+ int retval = 1; /* assume valid number */
+ char round; /* an additional character at the end of the string */
+ char *p;
+ int i;
+ int ub_exp;
+ int digcount;
+
+ /* grab the components of the long double */
+ expn = *U_EXP_LD(&ld);
+ manhi = *UL_MANHI_LD(&ld);
+ manlo = *UL_MANLO_LD(&ld);
+ sign = expn & MSB_USHORT;
+ expn &= 0x7fff;
+
+ if (sign)
+ fos->sign = '-';
+ else
+ fos->sign = ' ';
+
+ if (expn==0 && manhi==0 && manlo==0) {
+ PUT_ZERO_FOS(fos);
+ return 1;
+ }
+
+ if (expn == 0x7fff) {
+ fos->exp = 1; /* set a positive exponent for proper output */
+
+ /* check for special cases */
+ if (_IS_MAN_SNAN(sign, manhi, manlo)) {
+ /* signaling NAN */
+ STRCPY(fos->man,SNAN_STR);
+ fos->ManLen = SNAN_STR_LEN;
+ retval = 0;
+ }
+ else if (_IS_MAN_IND(sign, manhi, manlo)) {
+ /* indefinite */
+ STRCPY(fos->man,IND_STR);
+ fos->ManLen = IND_STR_LEN;
+ retval = 0;
+ }
+ else if (_IS_MAN_INF(sign, manhi, manlo)) {
+ /* infinity */
+ STRCPY(fos->man,INF_STR);
+ fos->ManLen = INF_STR_LEN;
+ retval = 0;
+ }
+ else {
+ /* quiet NAN */
+ STRCPY(fos->man,QNAN_STR);
+ fos->ManLen = QNAN_STR_LEN;
+ retval = 0;
+ }
+ }
+ else {
+ /*
+ * Algorithm for the decoding of a valid real number x
+ *
+ * In the following INT(r) is the largest integer less than or
+ * equal to r (i.e. r rounded toward -infinity). We want a result
+ * r equal to 1 + log(x), because then x = mantissa
+ * * 10^(INT(r)) so that .1 <= mantissa < 1. Unfortunately,
+ * we cannot compute s exactly so we must alter the procedure
+ * slightly. We will instead compute an estimate r of 1 +
+ * log(x) which is always low. This will either result
+ * in the correctly normalized number on the top of the stack
+ * or perhaps a number which is a factor of 10 too large. We
+ * will then check to see that if x is larger than one
+ * and if so multiply x by 1/10.
+ *
+ * We will use a low precision (fixed point 24 bit) estimate
+ * of of 1 + log base 10 of x. We have approximately .mm
+ * * 2^hhll on the top of the stack where m, h, and l represent
+ * hex digits, mm represents the high 2 hex digits of the
+ * mantissa, hh represents the high 2 hex digits of the exponent,
+ * and ll represents the low 2 hex digits of the exponent. Since
+ * .mm is a truncated representation of the mantissa, using it
+ * in this monotonically increasing polynomial approximation
+ * of the logarithm will naturally give a low result. Let's
+ * derive a formula for a lower bound r on 1 + log(x):
+ *
+ * .4D104D42H < log(2)=.30102999...(base 10) < .4D104D43H
+ * .9A20H < log(4)=.60205999...(base 10) < .9A21H
+ *
+ * 1/2 <= .mm < 1
+ * ==> log(.mm) >= .mm * log(4) - log(4)
+ *
+ * Substituting in truncated hex constants in the formula above
+ * gives r = 1 + .4D104DH * hhll. + .9AH * .mm - .9A21H. Now
+ * multiplication of hex digits 5 and 6 of log(2) by ll has an
+ * insignificant effect on the first 24 bits of the result so
+ * it will not be calculated. This gives the expression r =
+ * 1 + .4D10H * hhll. + .4DH * .hh + .9A * .mm - .9A21H.
+ * Finally we must add terms to our formula to subtract out the
+ * effect of the exponent bias. We obtain the following formula:
+ *
+ * (implied decimal point)
+ * < >.< >
+ * |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|0|0|0|0|0|0|0|0|0|0|
+ * |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|
+ * + < 1 >
+ * + < .4D10H * hhll. >
+ * + < .00004DH * hh00. >
+ * + < .9AH * .mm >
+ * - < .9A21H >
+ * - < .4D10H * 3FFEH >
+ * - < .00004DH * 3F00H >
+ *
+ * ==> r = .4D10H * hhll. + .4DH * .hh + .9AH * .mm - 1343.12F4H
+ *
+ * The difference between the lower bound r and the upper bound
+ * s is calculated as follows:
+ *
+ * .937EH < 1/ln(10)-log(1/ln(4))=.57614993...(base 10) < .937FH
+ *
+ * 1/2 <= .mm < 1
+ * ==> log(.mm) <= .mm * log(4) - [1/ln(10) - log(1/ln(4))]
+ *
+ * so tenatively s = r + log(4) - [1/ln(10) - log(1/ln(4))],
+ * but we must also add in terms to ensure we will have an upper
+ * bound even after the truncation of various values. Because
+ * log(2) * hh00. is truncated to .4D104DH * hh00. we must
+ * add .0043H, because log(2) * ll. is truncated to .4D10H *
+ * ll. we must add .0005H, because <mantissa> * log(4) is
+ * truncated to .mm * .9AH we must add .009AH and .0021H.
+ *
+ * Thus s = r - .937EH + .9A21H + .0043H + .0005H + .009AH + .0021H
+ * = r + .07A6H
+ * ==> s = .4D10H * hhll. + .4DH * .hh + .9AH * .mm - 1343.0B4EH
+ *
+ * r is equal to 1 + log(x) more than (10000H - 7A6H) /
+ * 10000H = 97% of the time.
+ *
+ * In the above formula, a u_long is use to accomodate r, and
+ * there is an implied decimal point in the middle.
+ */
+
+ hh = expn >> 8;
+ ll = expn & (u_short)0xff;
+ mm = (u_short) (manhi >> 24);
+ r = (s_long)log2hi*(s_long)expn + log2lo*hh + log4hi*mm - c;
+ ir = (s_short)(r >> 16);
+
+ /*
+ *
+ * We stated that we wanted to normalize x so that
+ *
+ * .1 <= x < 1
+ *
+ * This was a slight oversimplification. Actually we want a
+ * number which when rounded to 16 significant digits is in the
+ * desired range. To do this we must normalize x so that
+ *
+ * .1 - 5*10^(-18) <= x < 1 - 5*10^(-17)
+ *
+ * and then round.
+ *
+ * If we had f = INT(1+log(x)) we could multiply by 10^(-f)
+ * to get x into the desired range. We do not quite have
+ * f but we do have INT(r) from the last step which is equal
+ * to f 97% of the time and 1 less than f the rest of the time.
+ * We can multiply by 10^-[INT(r)] and if the result is greater
+ * than 1 - 5*10^(-17) we can then multiply by 1/10. This final
+ * result will lie in the proper range.
+ */
+
+ /* convert _ULDOUBLE to _ULDBL12) */
+ *U_EXP_12(&ld12) = expn;
+ *UL_MANHI_12(&ld12) = manhi;
+ *UL_MANLO_12(&ld12) = manlo;
+ *U_XT_12(&ld12) = 0;
+
+ /* multiply by 10^(-ir) */
+ __multtenpow12(&ld12,-ir,1);
+
+ /* if ld12 >= 1.0 then divide by 10.0 */
+ if (*U_EXP_12(&ld12) >= 0x3fff) {
+ ir++;
+ __ld12mul(&ld12,&ld12_one_tenth);
+ }
+
+ fos->exp = ir;
+ if (output_flags & SO_FFORMAT){
+ /* 'f' format, add exponent to ndigits */
+ ndigits += ir;
+ if (ndigits <= 0) {
+ /* return 0 */
+ PUT_ZERO_FOS(fos);
+ return 1;
+ }
+ }
+ if (ndigits > MAX_MAN_DIGITS)
+ ndigits = MAX_MAN_DIGITS;
+
+ ub_exp = *U_EXP_12(&ld12) - 0x3ffe; /* unbias exponent */
+ *U_EXP_12(&ld12) = 0;
+
+ /*
+ * Now the mantissa has to be converted to fixed point.
+ * Then we will use the MSB of ld12 for generating
+ * the decimal digits. The next 11 bytes will hold
+ * the mantissa (after it has been converted to
+ * fixed point).
+ */
+
+ for (i=0;i<8;i++)
+ __shl_12(&ld12); /* make space for an extra byte,
+ in case we shift right later */
+ if (ub_exp < 0) {
+ int shift_count = (-ub_exp) & 0xff;
+ for (;shift_count>0;shift_count--)
+ __shr_12(&ld12);
+ }
+
+ p = fos->man;
+ for(digcount=ndigits+1;digcount>0;digcount--) {
+ tmp12 = ld12;
+ __shl_12(&ld12);
+ __shl_12(&ld12);
+ __add_12(&ld12,&tmp12);
+ __shl_12(&ld12); /* ld12 *= 10 */
+
+ /* Now we have the first decimal digit in the msbyte of exponent */
+ *p++ = (char) (*UCHAR_12(&ld12,11) + '0');
+ *UCHAR_12(&ld12,11) = 0;
+ }
+
+ round = *(--p);
+ p--; /* p points now to the last character of the string
+ excluding the rounding digit */
+ if (round >= '5') {
+ /* look for a non-9 digit starting from the end of string */
+ for (;p>=fos->man && *p=='9';p--) {
+ *p = '0';
+ }
+ if (p < fos->man){
+ p++;
+ fos->exp ++;
+ }
+ (*p)++;
+ }
+ else {
+ /* remove zeros */
+ for (;p>=fos->man && *p=='0';p--);
+ if (p < fos->man) {
+ /* return 0 */
+ PUT_ZERO_FOS(fos);
+ return 1;
+ }
+ }
+ fos->ManLen = (char) (p - fos->man + 1);
+ fos->man[fos->ManLen] = '\0';
+ }
+ return retval;
+}
diff --git a/private/windbg/newdm/align.h b/private/windbg/newdm/align.h
new file mode 100644
index 000000000..0ff2bd6ca
--- /dev/null
+++ b/private/windbg/newdm/align.h
@@ -0,0 +1,2 @@
+void FixAlign(void);
+
diff --git a/private/windbg/newdm/alpmach.c b/private/windbg/newdm/alpmach.c
new file mode 100644
index 000000000..f13a6792f
--- /dev/null
+++ b/private/windbg/newdm/alpmach.c
@@ -0,0 +1,783 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ mach.c
+
+Abstract:
+
+ This file contains the ALPHA specific code for dealing with
+ the process of stepping a single instruction. This includes
+ determination of the next offset to be stopped at and if the
+ instruction is all call type instruction.
+
+Author:
+
+ Miche Baker-Harvey (miche) - stole the appropriate parts
+ from ntsd for the alpha version.
+
+Environment:
+
+ Win32 - User
+
+Notes:
+
+ There are equivalent INTEL and MIPS files.
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+extern BOOL FVerbose;
+extern char rgchDebug[];
+
+extern LPDM_MSG LpDmMsg;
+
+extern CRITICAL_SECTION csContinueQueue;
+
+#define FALSE 0
+#define TRUE 1
+#define STATIC static
+
+
+void OutputHex(ULONG, ULONG, BOOLEAN);
+void OutputEffectiveAddress(ULONG);
+void OutputString(char *);
+void OutputReg(ULONG);
+void OutputFReg(ULONG);
+
+DWORD VirtualUnwind (HPRCX, HTHDX, DWORD, PRUNTIME_FUNCTION, PCONTEXT,
+ PKNONVOLATILE_CONTEXT_POINTERS OPTIONAL);
+
+ALPHA_INSTRUCTION disinstr;
+
+ULONG findTypeFromOpcode(ULONG);
+
+BOOL
+IsRet(
+ HTHDX hthd,
+ LPADDR addr
+ )
+{
+ DWORD instr;
+ DWORD cBytes;
+ if (!AddrReadMemory( hthd->hprc, hthd, addr, &instr, 4, &cBytes )) {
+ return FALSE;
+ }
+ return (instr == 0x6bfa8001);
+}
+
+void
+IsCall (
+ HTHDX hthd,
+ LPADDR lpaddr,
+ LPINT lpf,
+ BOOL fStepOver
+ )
+
+/*++
+
+Routine Description:
+
+ IsCall
+
+Arguments:
+
+ hthd - Supplies the handle to the thread
+ lpaddr - Supplies the address to be check for a call instruction
+ lpf - Returns class of instruction:
+ INSTR_IS_CALL
+ INSTR_BREAKPOINT
+ INSTR_SOFT_INTERRUPT
+ INSTR_TRACE_BIT
+ fStepOver - Supplies step over vs step into flag
+
+Side Effects:
+ The value of lpaddr is set to point to the returned-to
+ instruction when the instruction is type INSTR_IS_CALL.
+
+Return Value:
+
+ lpf - see Arguments.
+
+--*/
+
+{
+ HANDLE rwHand = hthd->hprc->rwHand;
+ DWORD opcode, function;
+ ADDR firaddr = *lpaddr;
+ DWORD length;
+ ALPHA_INSTRUCTION disinstr;
+ BOOL r;
+
+ if (hthd->fIsCallDone) {
+ *lpaddr = hthd->addrIsCall;
+ *lpf = hthd->iInstrIsCall;
+ return;
+ }
+
+ /*
+ * Assume that this is not a call instruction
+ */
+
+ *lpf = INSTR_TRACE_BIT;
+
+ /*
+ * Read in the dword which contains the instruction under
+ * inspection.
+ */
+
+ r = AddrReadMemory(hthd->hprc,
+ hthd,
+ &firaddr,
+ &disinstr.Long,
+ sizeof(DWORD),
+ &length );
+
+ if (!r || length != sizeof(DWORD)) {
+ DPRINT(1, ("AddrReadMemory in IsCall FAILED"));
+ return;
+ }
+
+ /*
+ * Assume that this is a jump instruction and get the opcode.
+ * This is the top 6 bits of the instruction dword.
+ */
+
+ opcode = disinstr.Jump.Opcode;
+
+ /*
+ * Jump and Branch to Subroutine are CALLs
+ */
+ if (opcode == JMP_OP) {
+ function = disinstr.Jump.Function;
+ if (function == JSR_FUNC) {
+ *lpf = INSTR_IS_CALL;
+ }
+ }
+ if (opcode == BSR_OP) {
+ *lpf = INSTR_IS_CALL;
+ }
+
+ /*
+ * There are several PAL breakpoint operations,
+ * and a couple operations redirect control
+ */
+ if (opcode == CALLPAL_OP) {
+ function = disinstr.Pal.Function;
+ switch(function) {
+ case (BPT_FUNC):
+ case (CALLKD_FUNC):
+ case (KBPT_FUNC):
+ *lpf = INSTR_BREAKPOINT;
+ break;
+
+ case (CALLSYS_FUNC):
+ case (GENTRAP_FUNC):
+ *lpf = INSTR_IS_CALL;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ DPRINT(1, ("(IsCall?) FIR=%08x Type=%s\n", firaddr,
+ *lpf==INSTR_IS_CALL ? "CALL":
+ (*lpf==INSTR_BREAKPOINT ? "BREAKPOINT":
+ (*lpf==INSTR_SOFT_INTERRUPT ? "INTERRUPT":
+ "NORMAL"))));
+
+ if (*lpf==INSTR_IS_CALL) {
+ lpaddr->addr.off += sizeof (disinstr);
+ hthd->addrIsCall = *lpaddr;
+ }
+ hthd->iInstrIsCall = *lpf;
+
+ return;
+} /* IsCall() */
+
+
+ULONG
+GetNextOffset (
+ HTHDX hthd,
+ BOOL fStep
+ )
+
+/*++
+
+Routine Description:
+
+
+ From a limited disassembly of the instruction pointed
+ by the FIR register, compute the offset of the next
+ instruction for either a trace or step operation.
+
+ trace -> the next instruction to execute
+ step -> the instruction in the next memory location or the
+ next instruction executed due to a branch (step
+ over subroutine calls).
+
+Arguments:
+
+ hthd - Supplies the handle to the thread to get the next offset for
+
+ fStep - Supplies TRUE for STEP offset and FALSE for trace offset
+
+Returns:
+ step or trace offset if input is TRUE or FALSE, respectively
+
+Version Information:
+ This copy of GetNextOffset is from ntsd\alpha\ntdis.c@v16 (11/14/92)
+
+--*/
+
+{
+ ULONG returnvalue;
+ ULONG opcode;
+ ULONG updatedpc;
+ ULONG branchTarget;
+ BOOL r;
+
+
+ ULONGLONG Rav;
+ ULONGLONG Fav;
+ ULONGLONG Rbv;
+
+ DWORD length;
+ PULONGLONG RegArray = &hthd->context.IntV0;
+ ADDR firaddr;
+ ALPHA_INSTRUCTION disinstr;
+
+
+ AddrFromHthdx(&firaddr, hthd);
+
+ //
+ // relative addressing updates PC first
+ // Assume next sequential instruction is next offset
+ //
+
+ updatedpc = firaddr.addr.off + sizeof(ULONG);
+
+ r = AddrReadMemory(hthd->hprc,
+ hthd,
+ &firaddr,
+ &disinstr.Long,
+ sizeof(DWORD),
+ &length );
+
+ if (!r || length != sizeof(DWORD)) {
+ DPRINT(1, ("GetNextOffset: failed AddrReadMemory %x\n", disinstr.Long));
+ assert(FALSE);
+ return 4;
+ }
+
+
+ opcode = disinstr.Memory.Opcode;
+ returnvalue = updatedpc;
+
+ switch(findTypeFromOpcode(opcode)) {
+
+ case ALPHA_CALLPAL:
+
+ if (disinstr.Pal.Function == CALLSYS_FUNC) {
+ return (DWORD)RegArray[RA_REG];
+ }
+ break;
+
+ case ALPHA_JUMP:
+
+ switch(disinstr.Jump.Function) {
+
+ case JSR_FUNC:
+ case JSR_CO_FUNC:
+
+ if (fStep) {
+
+ //
+ // Step over the subroutine call;
+ //
+
+ return(returnvalue);
+ }
+
+ //
+ // fall through
+ //
+
+ case JMP_FUNC:
+ case RET_FUNC:
+
+ Rbv = RegArray[disinstr.Memory.Rb];
+ return (DWORD)(Rbv & (~3));
+ break;
+
+ }
+ break;
+
+ case ALPHA_BRANCH:
+
+ branchTarget = (updatedpc + (disinstr.Branch.BranchDisp * 4));
+
+ Rav = RegArray[disinstr.Memory.Ra];
+
+ if (FVerbose) {
+ DPRINT(1, ("Rav %08Lx returnValue %08lx branchTarget %08lx\n",
+ Rav, returnvalue, branchTarget));
+ }
+
+ switch(opcode) {
+ case BR_OP: return(branchTarget); break;
+ case BSR_OP: if (!fStep) return(branchTarget); break;
+ case BEQ_OP: if (Rav == 0) return(branchTarget); break;
+ case BLT_OP: if (Rav < 0) return(branchTarget); break;
+ case BLE_OP: if (Rav <= 0) return(branchTarget); break;
+ case BNE_OP: if (Rav != 0) return(branchTarget); break;
+ case BGE_OP: if (Rav >= 0) return(branchTarget); break;
+ case BGT_OP: if (Rav > 0) return(branchTarget); break;
+ case BLBC_OP: if ((Rav & 0x1) == 0) return(branchTarget); break;
+ case BLBS_OP: if ((Rav & 0x1) == 1) return(branchTarget); break;
+ };
+
+ return returnvalue;
+ break;
+
+
+ case ALPHA_FP_BRANCH:
+
+ branchTarget = (updatedpc + (disinstr.Branch.BranchDisp * 4));
+
+ RegArray = &hthd->context.FltF0;
+ Fav = RegArray[disinstr.Branch.Ra];
+
+ if (Fav == 0x8000000000000000) {
+ Fav = 0;
+ }
+
+ if (FVerbose) {
+ DPRINT(1, ("Fav %08Lx returnValue %08lx branchTarget %08lx\n",
+ Fav, returnvalue, branchTarget));
+ }
+
+ switch(opcode) {
+ case FBEQ_OP: if (Fav == 0) return (branchTarget); break;
+ case FBLT_OP: if (Fav < 0) return (branchTarget); break;
+ case FBNE_OP: if (Fav != 0) return (branchTarget); break;
+ case FBLE_OP: if (Fav <= 0) return (branchTarget); break;
+ case FBGE_OP: if (Fav >= 0) return (branchTarget); break;
+ case FBGT_OP: if (Fav > 0) return (branchTarget); break;
+ };
+ return returnvalue;
+ break;
+ }
+
+ return returnvalue;
+}
+
+
+
+XOSD
+SetupFunctionCall(
+ LPEXECUTE_OBJECT_DM lpeo,
+ LPEXECUTE_STRUCT lpes
+ )
+{
+ /*
+ * Can only execute functions on the current stopped thread. Therefore
+ * assert that the current thread is stopped.
+ */
+
+ assert(lpeo->hthd->tstate & ts_stopped);
+ if (!(lpeo->hthd->tstate & ts_stopped)) {
+ return xosdInvalidThread;
+ }
+
+ /*
+ * Now get the current stack offset.
+ */
+
+ lpeo->addrStack.addr.off = (DWORD)lpeo->hthd->context.IntSp;
+
+ /*
+ * Now place the return address correctly
+ */
+
+ lpeo->hthd->context.Fir = lpeo->hthd->context.IntRa =
+ (LONG)lpeo->addrStart.addr.off;
+
+ /*
+ * Set the instruction pointer to the starting addresses
+ * and write the context back out
+ */
+
+ lpeo->hthd->context.Fir = (LONG)lpeo->addrStart.addr.off;
+
+ lpeo->hthd->fContextDirty = TRUE;
+
+ return xosdNone;
+}
+
+
+
+BOOL
+CompareStacks(
+ LPEXECUTE_OBJECT_DM lpeo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to determine if the stack pointers are correct
+ for terminating function evaluation.
+
+Arguments:
+
+ lpeo - Supplies the pointer to the DM Execute Object description
+
+Return Value:
+
+ TRUE if the evaluation is to be terminated and FALSE otherwise
+
+--*/
+
+{
+
+ if (lpeo->addrStack.addr.off <= (DWORD)lpeo->hthd->context.IntSp) {
+ return TRUE;
+ }
+
+ return FALSE;
+} /* CompareStacks() */
+
+
+
+BOOL
+ProcessFrameStackWalkNextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ PCONTEXT context,
+ LPVOID pctxPtrs
+ )
+
+{
+ return FALSE;
+} // ProcessFrameStackWalkNextCmd
+
+
+
+#if DBG
+
+ULONG RtlDebugFlags = 0;
+#define RTL_DBG_VIRTUAL_UNWIND 1
+#define RTL_DBG_VIRTUAL_UNWIND_DETAIL 2
+
+//
+// Define an array of symbolic names for the integer registers.
+//
+
+PCHAR RtlpIntegerRegisterNames[32] = {
+ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", // 0 - 7
+ "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp", // 8 - 15
+ "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", // 16 - 23
+ "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero", // 24 - 31
+};
+
+//
+// This function disassembles the instruction at the given address. It is
+// only used for debugging and recognizes only those few instructions that
+// are relevant during reverse execution of the prologue by virtual unwind.
+//
+
+VOID
+_RtlpDebugDisassemble (
+ IN ULONG ControlPc,
+ IN PCONTEXT ContextRecord
+ )
+{
+ UCHAR Comments[50];
+ PULONGLONG FloatingRegister;
+ ULONG Function;
+ ULONG Hint;
+ ULONG Literal8;
+ ALPHA_INSTRUCTION Instruction;
+ PULONGLONG IntegerRegister;
+ LONG Offset16;
+ UCHAR Operands[20];
+ ULONG Opcode;
+ PCHAR OpName;
+ ULONG Ra;
+ ULONG Rb;
+ ULONG Rc;
+ PCHAR RaName;
+ PCHAR RbName;
+ PCHAR RcName;
+
+ if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND_DETAIL) {
+ Instruction.Long = *((PULONG)ControlPc);
+ Hint = Instruction.Jump.Hint;
+ Literal8 = Instruction.OpLit.Literal;
+ Offset16 = Instruction.Memory.MemDisp;
+ Opcode = Instruction.Memory.Opcode;
+ Ra = Instruction.OpReg.Ra;
+ RaName = RtlpIntegerRegisterNames[Ra];
+ Rb = Instruction.OpReg.Rb;
+ RbName = RtlpIntegerRegisterNames[Rb];
+ Rc = Instruction.OpReg.Rc;
+ RcName = RtlpIntegerRegisterNames[Rc];
+
+ IntegerRegister = &ContextRecord->IntV0;
+ FloatingRegister = &ContextRecord->FltF0;
+
+ OpName = NULL;
+ switch (Opcode) {
+ case JMP_OP :
+ if (Instruction.Jump.Function == RET_FUNC) {
+ OpName = "ret";
+ sprintf(Operands, "%s, (%s), %04lx", RaName, RbName, Hint);
+ sprintf(Comments, "%s = %Lx", RbName, IntegerRegister[Rb]);
+ }
+ break;
+
+ case LDAH_OP :
+ case LDA_OP :
+ case STQ_OP :
+ if (Opcode == LDA_OP) {
+ OpName = "lda";
+
+ } else if (Opcode == LDAH_OP) {
+ OpName = "ldah";
+
+ } else if (Opcode == STQ_OP) {
+ OpName = "stq";
+ }
+ sprintf(Operands, "%s, $%d(%s)", RaName, Offset16, RbName);
+ sprintf(Comments, "%s = %Lx", RaName, IntegerRegister[Ra]);
+ break;
+
+ case ARITH_OP :
+ case BIT_OP :
+ Function = Instruction.OpReg.Function;
+ if ((Opcode == ARITH_OP) && (Function == ADDQ_FUNC)) {
+ OpName = "addq";
+
+ } else if ((Opcode == ARITH_OP) && (Function == SUBQ_FUNC)) {
+ OpName = "subq";
+
+ } else if ((Opcode == BIT_OP) && (Function == BIS_FUNC)) {
+ OpName = "bis";
+
+ } else {
+ break;
+ }
+ if (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT) {
+ sprintf(Operands, "%s, %s, %s", RaName, RbName, RcName);
+
+ } else {
+ sprintf(Operands, "%s, $%d, %s", RaName, Literal8, RcName);
+ }
+ sprintf(Comments, "%s = %Lx", RcName, IntegerRegister[Rc]);
+ break;
+
+ case FPOP_OP :
+ if (Instruction.FpOp.Function == CPYS_FUNC) {
+ OpName = "cpys";
+ sprintf(Operands, "f%d, f%d, f%d", Ra, Rb, Rc);
+ sprintf(Comments, "f%d = %Lx", Rc, FloatingRegister[Rc]);
+ }
+ break;
+
+ case STT_OP :
+ OpName = "stt";
+ sprintf(Operands, "f%d, $%d(%s)", Ra, Offset16, RbName);
+ sprintf(Comments, "f%d = %Lx", Ra, FloatingRegister[Ra]);
+ break;
+ }
+ if (OpName == NULL) {
+ OpName = "???";
+ sprintf(Operands, "...");
+ sprintf(Comments, "Unknown to virtual unwind.");
+ }
+ DEBUG_PRINT_5(" %08lx: %08lx %-5s %-16s // %s\n",
+ ControlPc, Instruction.Long, OpName, Operands, Comments);
+ }
+ return;
+}
+
+#define _RtlpFoundTrapFrame(NextPc) \
+ if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND) { \
+ DEBUG_PRINT_1(" *** Looks like a trap frame (fake prologue), Fir = %lx\n", \
+ NextPc); \
+ }
+
+#else
+
+#define _RtlpDebugDisassemble(ControlPc, ContextRecord)
+#define _RtlpFoundTrapFrame(NextPc)
+
+#endif
+
+//
+// MBH - this value is redefined in windbg common code to be IntSp.
+//
+#define SP_REG 30
+
+
+DWORD
+BranchUnassemble(
+ void *Memory,
+ ADDR *Addr,
+ BOOL *IsBranch,
+ BOOL *TargetKnown,
+ BOOL *IsCall,
+ BOOL *IsTable,
+ ADDR *Target
+ )
+{
+ ULONG OpCode;
+ ALPHA_INSTRUCTION *Instr;
+ UOFF32 TargetOffset;
+
+ UNREFERENCED_PARAMETER( Addr );
+
+ assert( Memory );
+ assert( IsBranch );
+ assert( TargetKnown );
+ assert( IsCall );
+ assert( Target );
+
+ *IsBranch = FALSE;
+ *IsTable = FALSE;
+
+ TargetOffset = 0;
+ Instr = (ALPHA_INSTRUCTION *)Memory;
+ OpCode = Instr->Jump.Opcode;
+
+ switch ( OpCode ) {
+
+ case JMP_OP:
+ switch ( Instr->Jump.Function ) {
+
+ case JMP_FUNC:
+ case RET_FUNC:
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = FALSE;
+ break;
+
+ case JSR_FUNC:
+ case JSR_CO_FUNC:
+ ;*IsBranch = TRUE;
+ *IsCall = TRUE;
+ *TargetKnown = FALSE;
+ break;
+ }
+ break;
+
+ case CALLPAL_OP:
+ switch( Instr->Pal.Function ) {
+ case CALLSYS_FUNC:
+ case GENTRAP_FUNC:
+ *IsBranch = TRUE;
+ *IsCall = TRUE;
+ *TargetKnown = FALSE;
+ break;
+ }
+ break;
+
+ case BSR_OP:
+ *IsBranch = TRUE;
+ *IsCall = TRUE;
+ *TargetKnown = TRUE;
+ TargetOffset = (GetAddrOff(*Addr) + 4) + (Instr->Branch.BranchDisp << 2);
+ break;
+
+ case BR_OP:
+ case FBEQ_OP:
+ case FBLT_OP:
+ case FBLE_OP:
+ case FBNE_OP:
+ case FBGE_OP:
+ case FBGT_OP:
+ case BLBC_OP:
+ case BEQ_OP:
+ case BLT_OP:
+ case BLE_OP:
+ case BLBS_OP:
+ case BNE_OP:
+ case BGE_OP:
+ case BGT_OP:
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = TRUE;
+ TargetOffset = (GetAddrOff(*Addr) + 4) + (Instr->Branch.BranchDisp << 2);
+ break;
+
+ default:
+ break;
+ }
+
+ AddrInit( Target, 0, 0, TargetOffset, TRUE, TRUE, FALSE, FALSE );
+
+ return sizeof( DWORD );
+}
+
+
+#ifndef KERNEL
+
+
+VOID
+MakeThreadSuspendItselfHelper(
+ HTHDX hthd,
+ FARPROC lpSuspendThread
+ )
+{
+ //
+ // set up the args to SuspendThread
+ //
+
+ // GetCurrentThread always returns a magic cookie, safe for any thread.
+ hthd->context.IntA0 = (DWORD)GetCurrentThread();
+ hthd->context.IntRa = PC(hthd);
+ PC(hthd) = (LONG)lpSuspendThread;
+ hthd->fContextDirty = TRUE;
+}
+
+#endif // !KERNEL
+
+BOOL
+DecodeSingleStepEvent(
+ HTHDX hthd,
+ DEBUG_EVENT *de,
+ PDWORD eventCode,
+ PDWORD subClass
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hthd - Supplies thread that has a single step exception pending
+
+ de - Supplies the DEBUG_EVENT structure for the exception
+
+ eventCode - Returns the remapped debug event id
+
+ subClass - Returns the remapped subClass id
+
+
+Return Value:
+
+ TRUE if event was a real single step or was successfully mapped
+ to a breakpoint. FALSE if a register breakpoint occurred which was
+ not expected.
+
+--*/
+{
+ return FALSE;
+}
diff --git a/private/windbg/newdm/biavst.h b/private/windbg/newdm/biavst.h
new file mode 100644
index 000000000..4895d048b
--- /dev/null
+++ b/private/windbg/newdm/biavst.h
@@ -0,0 +1,203 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ biavst.h
+
+Abstract:
+
+ This header file is used to cause the correct machine/platform specific
+ data structures to be used when compiling for a non-hosted platform.
+
+Author:
+
+ Wesley Witt (wesw) 2-Aug-1993
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include "heap.h"
+
+
+#undef i386
+#undef _X86_
+#undef MIPS
+#undef _MIPS_
+#undef ALPHA
+#undef _ALPHA_
+#undef PPC
+#undef _PPC_
+
+#define _NTSYSTEM_
+
+//-----------------------------------------------------------------------------------------
+//
+// mips r4000
+//
+//-----------------------------------------------------------------------------------------
+#if defined(TARGET_MIPS)
+
+#pragma message( "Compiling for target = mips" )
+
+#define _MIPS_
+
+#if defined(HOST_MIPS)
+#define MIPS
+#endif
+
+#if defined(HOST_i386)
+#define __unaligned
+#endif
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+#include <ntos.h>
+#include <iop.h>
+#include <windows.h>
+
+#if !defined(HOST_MIPS)
+#undef MIPS
+#undef _MIPS_
+#endif
+
+#if defined(HOST_i386)
+#undef _cdecl
+#undef UNALIGNED
+#define UNALIGNED
+#endif
+
+//-----------------------------------------------------------------------------------------
+//
+// PowerPC
+//
+//-----------------------------------------------------------------------------------------
+#elif defined(TARGET_PPC)
+
+#pragma message( "Compiling for target = ppc" )
+
+#define _PPC_
+
+#if defined(HOST_PPC)
+#define PPC
+#endif
+
+#if defined(HOST_i386)
+#define __unaligned
+#endif
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+#include <ntos.h>
+#include <iop.h>
+#include <windows.h>
+
+#if !defined(HOST_PPC)
+#undef PPC
+#undef _PPC_
+#endif
+
+#if defined(HOST_i386)
+#undef _cdecl
+#undef UNALIGNED
+#define UNALIGNED
+#endif
+
+//-----------------------------------------------------------------------------------------
+//
+// intel x86
+//
+//-----------------------------------------------------------------------------------------
+#elif defined(TARGET_i386)
+
+#pragma message( "Compiling for target = x86" )
+
+#define _X86_
+
+#if defined(HOST_MIPS)
+#define MIPS
+#endif
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+#include <ntos.h>
+#include <iop.h>
+#include <windows.h>
+
+#if defined(HOST_MIPS)
+#undef _cdecl
+#define _cdecl
+#endif
+
+#if defined(HOST_ALPHA)
+#undef _cdecl
+#define _cdecl
+#endif
+
+#if !defined(HOST_i386)
+#undef _X86_
+#endif
+
+//-----------------------------------------------------------------------------------------
+//
+// alpha axp
+//
+//-----------------------------------------------------------------------------------------
+#elif defined(TARGET_ALPHA)
+
+#pragma message( "Compiling for target = alpha" )
+
+#define _ALPHA_ 1
+
+#if defined(HOST_i386)
+#define __unaligned
+#endif
+
+#if defined(HOST_MIPS)
+#define MIPS
+#endif
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+#include <ntos.h>
+#include <iop.h>
+#include <windows.h>
+
+#if defined(HOST_MIPS)
+#undef _cdecl
+#define _cdecl
+#endif
+
+#if defined(HOST_i386)
+#undef UNALIGNED
+#define UNALIGNED
+#endif
+
+#if !defined(HOST_ALPHA)
+#undef _ALPHA_
+#endif
+
+
+#else
+
+//-----------------------------------------------------------------------------------------
+//
+// unknown platform
+//
+//-----------------------------------------------------------------------------------------
+#error "Unsupported target CPU"
+
+#endif
+
diff --git a/private/windbg/newdm/bp.c b/private/windbg/newdm/bp.c
new file mode 100644
index 000000000..176449833
--- /dev/null
+++ b/private/windbg/newdm/bp.c
@@ -0,0 +1,1346 @@
+#include "precomp.h"
+#pragma hdrstop
+
+SetFile()
+
+
+BREAKPOINT masterBP = {0L,0L};
+PBREAKPOINT bpList = &masterBP;
+
+extern HTHDX thdList;
+extern CRITICAL_SECTION csThreadProcList;
+
+
+PBREAKPOINT
+GetNewBp(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP BpType,
+ BPNS BpNotify,
+ ADDR *AddrBp,
+ HPID id,
+ PBREAKPOINT BpUse
+ )
+/*++
+
+Routine Description:
+
+ Allocates a BREAKPOINT structure and initializes it. Note that
+ this does NOT add the structure to the breakpoint list (bplist).
+ If it is not an address bp (i.e. it is a watchpoint), the hwalk
+ field must be initialized later.
+
+Arguments:
+
+ hprc - Supplies process to put BP in
+
+ hthd - Supplies optional thread
+
+ AddrBp - Supplies address structure for the breakpoint
+
+ id - Supplies EM id for BP
+
+ BpUse - Supplies other BP on same address (so we can steal the
+ original code from it instead of reading).
+ This last one is optional.
+
+Return Value:
+
+ PBREAKPOINT - Pointer to allocated and initialized structure.
+
+--*/
+
+{
+ PBREAKPOINT Bp;
+ ADDR Addr;
+ DWORD i;
+
+ assert( !BpUse || ( BpUse->hthd != hthd ) );
+
+ Bp = (PBREAKPOINT)malloc(sizeof(BREAKPOINT));
+ assert( Bp );
+
+ if ( Bp ) {
+
+ assert( bpList );
+
+ Bp->next = NULL;
+ Bp->hprc = hprc;
+ Bp->hthd = hthd;
+ Bp->id = id;
+ Bp->instances = 1;
+ Bp->isStep = FALSE;
+ Bp->hBreakPoint = 0;
+ Bp->bpType = BpType;
+ Bp->bpNotify = BpNotify;
+ Bp->hWalk = NULL;
+ memset(&Bp->addr, 0, sizeof(Bp->addr));
+
+ //
+ // Get the opcode from the indicated address
+ //
+
+ if ( BpUse ) {
+
+ Bp->instr1 = BpUse->instr1;
+
+ } else if (AddrBp) {
+
+ Bp->instr1 = 0;
+ Addr = *AddrBp;
+
+ Bp->addr = *AddrBp;
+
+ //
+ // Check to make sure that what we have is not a linker index
+ // number in the address structure. If it is then we can not
+ // currently set this breakpoint due to the fact that we
+ // don't have a real address
+ //
+
+ if ( ADDR_IS_LI(Addr) ) {
+
+ assert(!"Addr is LI");
+ free( Bp );
+ Bp = NULL;
+
+ }
+ else if (!AddrReadMemory(hprc, hthd, &Addr, &(Bp->instr1), BP_SIZE,
+ &i) ||
+ (i != BP_SIZE)) {
+
+#ifdef KERNEL
+ Bp->instr1 = 0;
+#else
+ assert(!"AddrReadMemory failed");
+ free(Bp);
+ Bp = NULL;
+#endif
+ }
+ }
+ }
+
+ return Bp;
+}
+
+
+
+PBREAKPOINT
+SetBP(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP bptype,
+ BPNS bpnotify,
+ LPADDR paddr,
+ HPID id
+ )
+/*++
+
+Routine Description:
+
+ Set a breakpoint, or increment instance count on an existing bp.
+ if hthd is non-NULL, BP is only for that thread.
+
+Arguments:
+
+ hprc - Supplies process to put BP in
+
+ hthd - Supplies optional thread
+
+ bptype - Supplies OSDEBUG BP type
+
+ paddr - Supplies address structure for the breakpoint
+
+ id - Supplies EM id for BP
+
+Return Value:
+
+ pointer to bp structure, or NULL for failure
+
+--*/
+{
+ PBREAKPOINT pbp;
+ PBREAKPOINT pbpT;
+ ADDR addr;
+ ADDR addr2;
+
+ if (!hprc) {
+ return (PBREAKPOINT)NULL;
+ }
+
+ EnterCriticalSection(&csThreadProcList);
+
+ /*
+ * First let's try to find a breakpoint that
+ * matches this description
+ */
+
+ pbpT = FindBP(hprc, hthd, bptype, bpnotify, paddr, FALSE);
+
+ /*
+ * If this thread has a breakpoint here,
+ * increment reference count.
+ */
+
+ if (pbpT && pbpT->hthd == hthd) {
+
+ pbp = pbpT;
+ pbp->instances++;
+
+ } else if ( pbp = GetNewBp( hprc, hthd, bptype, bpnotify, paddr, id, pbpT )) {
+
+ if ( !pbpT ) {
+
+ //
+ // Now write the cpu-specific breakpoint code.
+ //
+
+ assert(!ADDR_IS_LI(pbp->addr));
+
+ if ( WriteBreakPoint(pbp) ) {
+ AddBpToList(pbp);
+ } else {
+ free( pbp );
+ pbp = NULL;
+ }
+
+ } else {
+
+ //
+ // Breakpoint exists, but for wrong thread.
+ //
+
+ *pbp = *pbpT;
+
+ pbp->hthd = hthd;
+ pbp->instances = 1;
+ }
+
+
+ /*
+ * Make it a linear address to start with
+ */
+
+ addr2 = *paddr;
+ TranslateAddress(hprc, hthd, &addr2, TRUE);
+
+ /*
+ * Check with the threads to see if we are at this address. If so then
+ * we need to set the BP field so we don't hit the bp imeadiately
+ */
+
+ if (hthd) {
+ AddrFromHthdx(&addr, hthd);
+ if ((hthd->tstate & ts_stopped) &&
+ (AtBP(hthd) == NULL) &&
+ AreAddrsEqual(hprc, hthd, &addr, &addr2)) {
+ SetBPFlag(hthd, pbp);
+ }
+ } else {
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ AddrFromHthdx(&addr, hthd);
+ if ((hthd->tstate & ts_stopped) &&
+ (AtBP(hthd) == NULL) &&
+ AreAddrsEqual(hprc, hthd, &addr, &addr2)) {
+ SetBPFlag(hthd, pbp);
+ }
+ }
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return pbp;
+} /* SetBP() */
+
+
+#ifdef KERNEL
+
+
+BOOL
+SetBPEx(
+ HPRCX hprc,
+ HTHDX hthd,
+ HPID id,
+ DWORD Count,
+ ADDR *Addrs,
+ PBREAKPOINT *Bps,
+ DWORD ContinueStatus
+ )
+
+/*++
+
+Routine Description:
+
+ Allocates a bunch of breakpoints from a given list of linear offsets.
+
+Arguments:
+
+ hprc - Supplies process to put BP in
+
+ hthd - Supplies optional thread
+
+ Count - Supplies count of breakpoints to set
+
+ Addrs - Supplies list with Count addresses
+
+ Bps - Supplies buffer to be filled with Count pointers to
+ BREAKPOINT structures. Original contents is
+ overwritten.
+
+ ContinueStatus -
+
+Return Value:
+
+ BOOL - If TRUE, then ALL breakpoints were set.
+ If FALSE, then NONE of the breakpoints were set.
+
+
+ NOTENOTE - Not sure of what will happen if the list contains duplicated
+ addresses!
+
+--*/
+
+{
+ PDBGKD_WRITE_BREAKPOINT DbgKdBp;
+ PDBGKD_RESTORE_BREAKPOINT DbgKdBpRes;
+ DWORD SetCount = 0;
+ DWORD NewCount = 0;
+ DWORD i;
+ DWORD j;
+ PBREAKPOINT BpT;
+ BOOL Ok;
+ ADDR Addr;
+ ADDR Addr2;
+
+ if (!hprc) {
+ assert(!"hprc == NULL is SetBPEx");
+ return FALSE;
+ }
+
+ assert( Count > 0 );
+ assert( Addrs );
+ assert( Bps );
+
+ if ( Count == 1 ) {
+ //
+ // Only one breakpoint, faster to simply call SetBP
+ //
+ Bps[0] = SetBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[0], id );
+ return ( Bps[0] != NULL );
+ }
+
+ EnterCriticalSection(&csThreadProcList);
+
+ AddrInit( &Addr, 0, 0, 0, TRUE, TRUE, FALSE, FALSE );
+
+ //
+ // Allocate space for Count breakpoints
+ //
+ DbgKdBp = (PDBGKD_WRITE_BREAKPOINT)
+ malloc( sizeof(DBGKD_WRITE_BREAKPOINT) * Count );
+ assert( DbgKdBp );
+
+ if ( !DbgKdBp ) {
+ LeaveCriticalSection(&csThreadProcList);
+ return FALSE;
+ }
+
+ for ( i=0; i<Count; i++ ) {
+
+ //
+ // See if we already have a breakpoint at this address.
+ //
+ Bps[i] = FindBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], FALSE );
+
+ if ( !Bps[i] ) {
+
+ DbgKdBp[ NewCount ].BreakPointAddress =
+ (PVOID)GetAddrOff(Addrs[i]);
+ DbgKdBp[ NewCount++ ].BreakPointHandle = (ULONG)NULL;
+ Bps[i] = GetNewBp( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL );
+ assert( Bps[i] );
+
+ } else if (Bps[i]->hthd != hthd ) {
+
+ BpT = Bps[i];
+ Bps[i] = GetNewBp( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL );
+
+ // BUGBUG kentf should instances be changed?
+
+ *Bps[i] = *BpT;
+ Bps[i]->hthd = hthd;
+
+
+ }
+ }
+
+ Ok = TRUE;
+ if ( NewCount > 0 ) {
+
+ //
+ // Set all new breakpoints
+ //
+ assert( NewCount <= Count );
+ Ok = WriteBreakPointEx( hthd, NewCount, DbgKdBp, ContinueStatus );
+ }
+
+ if ( Ok ) {
+ //
+ // Fill in the breakpoint list
+ //
+ j = 0;
+ for ( i=0; i<Count; i++ ) {
+
+ if ( Bps[i] && Bps[i]->hBreakPoint && Bps[i]->hthd == hthd ) {
+ //
+ // Will reuse BP, just increment reference count.
+ //
+ Bps[i]->instances++;
+
+ } else {
+
+ assert( (PVOID)GetAddrOff(Addrs[i]) ==
+ DbgKdBp[j].BreakPointAddress );
+ //
+ // Allocate new BP structure and get handle from
+ // the breakpoint packet. Note that we rely on the
+ // order of the breakpoints in the breakpoint packet.
+ //
+ Bps[i]->hBreakPoint = DbgKdBp[j].BreakPointHandle;
+ AddBpToList(Bps[i]);
+ j++;
+ }
+
+ SetCount++;
+
+ //
+ // Check with the threads to see if we are at this address.
+ // If so then we need to set the BP field so we don't hit
+ // the bp imeadiately
+ //
+
+ Addr2 = Bps[i]->addr;
+
+ if ( hthd ) {
+ AddrFromHthdx( &Addr, hthd );
+ if ((hthd->tstate & ts_stopped) &&
+ (AtBP(hthd) == NULL) &&
+ AreAddrsEqual(hprc, hthd, &Addr, &Addr2 )) {
+ SetBPFlag(hthd, Bps[i]);
+ }
+ } else {
+ for (hthd=hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ AddrFromHthdx( &Addr, hthd );
+ if ((hthd->tstate & ts_stopped) &&
+ (AtBP(hthd) == NULL) &&
+ AreAddrsEqual(hprc, hthd, &Addr, &Addr2)) {
+ SetBPFlag(hthd, Bps[i]);
+ }
+ }
+ }
+ }
+
+ assert( j == NewCount );
+
+ } else {
+
+ //
+ // Clean up any breakpoints that were set.
+ //
+ DbgKdBpRes = (PDBGKD_RESTORE_BREAKPOINT)
+ malloc( sizeof(DBGKD_RESTORE_BREAKPOINT) * NewCount );
+ assert( DbgKdBpRes );
+
+ if ( DbgKdBpRes ) {
+
+ //
+ // Put all breakpoints with a valid handle on the list of
+ // breakpoints to be removed.
+ //
+ j = 0;
+ for ( i=0; i<NewCount;i++) {
+ if ( DbgKdBp[i].BreakPointHandle != (ULONG)NULL ) {
+ DbgKdBpRes[j++].BreakPointHandle =
+ DbgKdBp[i].BreakPointHandle;
+ }
+ }
+
+ //
+ // Now remove them
+ //
+ if ( j > 0 ) {
+ assert( j <= NewCount );
+ RestoreBreakPointEx( j, DbgKdBpRes );
+ }
+
+ free( DbgKdBpRes );
+
+ //
+ // Remove allocated BP structures
+ //
+ for ( i=0; i<Count; i++ ) {
+ if ( Bps[i] && !Bps[i]->hBreakPoint ) {
+ assert( !Bps[i]->next );
+ free( Bps[i] );
+ Bps[i] = NULL;
+ }
+ }
+ }
+ }
+
+ free( DbgKdBp );
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return (SetCount == Count);
+}
+
+
+#else // KERNEL
+
+BOOL
+SetBPEx(
+ HPRCX hprc,
+ HTHDX hthd,
+ HPID id,
+ DWORD Count,
+ ADDR *Addrs,
+ PBREAKPOINT *Bps,
+ DWORD ContinueStatus
+ )
+
+/*++
+
+Routine Description:
+
+ Allocates a bunch of breakpoints from a given list of linear offsets.
+
+Arguments:
+
+ hprc - Supplies process to put BP in
+
+ hthd - Supplies optional thread
+
+ Count - Supplies count of breakpoints to set
+
+ Addrs - Supplies list with Count addresses
+
+ Bps - Supplies buffer to be filled with Count pointers to
+ BREAKPOINT structures. Original contents is
+ overwritten.
+
+ ContinueStatus -
+
+Return Value:
+
+ BOOL - If TRUE, then ALL breakpoints were set.
+ If FALSE, then NONE of the breakpoints were set.
+
+
+ NOTENOTE - Not sure of what will happen if the list contains duplicated
+ addresses!
+
+--*/
+
+{
+ DWORD SetCount = 0;
+ DWORD NewCount = 0;
+ DWORD i;
+ DWORD j;
+ DWORD k;
+ ADDR Addr;
+ ADDR Addr2;
+ BP_UNIT opcode = BP_OPCODE;
+
+ if (!hprc) {
+ assert(!"hprc == NULL in SetBPEx");
+ return FALSE;
+ }
+
+ assert( Count > 0 );
+ assert( Addrs );
+ assert( Bps );
+
+ if ( Count == 1 ) {
+ //
+ // Only one breakpoint, faster to simply call SetBP
+ //
+ Bps[0] = SetBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[0], id );
+ return ( Bps[0] != NULL );
+ }
+
+ EnterCriticalSection(&csThreadProcList);
+
+ for ( i=0; i<Count; i++ ) {
+
+ //
+ // See if we already have a breakpoint at this address.
+ //
+ Bps[i] = FindBP( hprc, hthd, bptpExec, bpnsStop, &Addrs[i], FALSE );
+
+ if ( Bps[i] && Bps[i]->hthd == hthd ) {
+
+ //
+ // Reuse this breakpoint
+ //
+
+ Bps[i]->instances++;
+ assert( Bps[i]->instances > 1 );
+
+ } else {
+ //
+ // Get new breakpoint
+ //
+ Bps[i] = GetNewBp(hprc, hthd, bptpExec, bpnsStop, &Addrs[i], id, NULL);
+ if ( !Bps[i] ) {
+
+ assert(!"GetNewBp failed in SetBPEx");
+ break;
+ }
+ if ( !ADDR_IS_LI(Bps[i]->addr) ) {
+ if ( !AddrWriteMemory(hprc, hthd, &Bps[i]->addr,
+ (LPBYTE) &opcode, BP_SIZE, &j) ) {
+
+ free( Bps[i] );
+ Bps[i] = NULL;
+ assert(!"DbgWriteMemory failed in SetBPEx");
+ break;
+ }
+ }
+ }
+ }
+
+ if ( i < Count ) {
+ //
+ // Something went wrong, will backtrack
+ //
+
+ assert(!"i < Count in SetBPEx");
+
+ for ( j=0; j<i; j++ ) {
+
+ assert( Bps[j] );
+ Bps[j]->instances--;
+ if ( Bps[j]->instances == 0 ) {
+
+ if ( !ADDR_IS_LI(Bps[j]->addr) ) {
+ AddrWriteMemory(hprc, hthd, &Bps[j]->addr,
+ (LPBYTE) &Bps[j]->instr1, BP_SIZE, &k);
+ }
+ free( Bps[j] );
+ Bps[j] = NULL;
+ }
+ }
+
+ } else {
+
+ //
+ // Add all the new breakpoints to the list
+ //
+ for ( i=0; i<Count; i++ ) {
+
+ if ( Bps[i]->instances == 1 ) {
+ AddBpToList(Bps[i]);
+ }
+
+ //
+ // Check with the threads to see if we are at this address. If so then
+ // we need to set the BP field so we don't hit the bp imeadiately
+ //
+
+ Addr2 = Bps[i]->addr;
+
+ if ( hthd ) {
+ AddrFromHthdx( &Addr, hthd );
+ if ((hthd->tstate & ts_stopped) &&
+ (AtBP(hthd) == NULL) &&
+ AreAddrsEqual(hprc, hthd, &Addr, &Addr2 )) {
+ SetBPFlag(hthd, Bps[i]);
+ }
+ } else {
+ for (hthd=hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ AddrFromHthdx( &Addr, hthd );
+ if ((hthd->tstate & ts_stopped) &&
+ (AtBP(hthd) == NULL) &&
+ AreAddrsEqual(hprc, hthd, &Addr, &Addr2)) {
+ SetBPFlag(hthd, Bps[i]);
+ }
+ }
+ }
+ }
+
+ SetCount = Count;
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return (SetCount == Count);
+}
+
+#endif // KERNEL
+
+BOOL
+BPInRange(
+ HPRCX hprc,
+ HTHDX hthd,
+ PBREAKPOINT bp,
+ LPADDR paddrStart,
+ DWORD cb,
+ LPDWORD offset,
+ BP_UNIT * instr
+ )
+{
+ ADDR addr1;
+ ADDR addr2;
+
+ /*
+ * If the breakpoint has a Loader index address then we can not
+ * possibly match it
+ */
+
+ assert (!ADDR_IS_LI(*paddrStart) );
+ if (ADDR_IS_LI(bp->addr)) {
+ return FALSE;
+ }
+
+ *offset = 0;
+
+ /*
+ * Now check for "equality" of the addresses.
+ *
+ * Need to include size of BP in the address range check. Since
+ * the address may start half way through a breakpoint.
+ */
+
+ if ((ADDR_IS_FLAT(*paddrStart) == TRUE) &&
+ (ADDR_IS_FLAT(bp->addr) == TRUE)) {
+ if ((GetAddrOff(*paddrStart) - sizeof(BP_UNIT) + 1 <=
+ GetAddrOff(bp->addr)) &&
+ (GetAddrOff(bp->addr) < GetAddrOff(*paddrStart) + cb)) {
+
+ *offset = (DWORD) GetAddrOff(bp->addr) -
+ (DWORD) GetAddrOff(*paddrStart);
+ *instr = bp->instr1;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /*
+ * The two addresses did not start out as flat addresses. So change
+ * them to linear addresses so that we can see if the addresses are
+ * are really the same
+ */
+
+ addr1 = *paddrStart;
+ if (!TranslateAddress(hprc, hthd, &addr1, TRUE)) {
+ return FALSE;
+ }
+ addr2 = bp->addr;
+ if (!TranslateAddress(hprc, hthd, &addr2, TRUE)) {
+ return FALSE;
+ }
+
+ if ((GetAddrOff(addr1) - sizeof(BP_UNIT) + 1 <= GetAddrOff(addr2)) &&
+ (GetAddrOff(addr2) < GetAddrOff(addr1) + cb)) {
+ *offset = (DWORD) GetAddrOff(addr2) - (DWORD) GetAddrOff(addr1);
+ *instr = bp->instr1;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+PBREAKPOINT
+FindBP(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP bptype,
+ BPNS bpnotify,
+ LPADDR paddr,
+ BOOL fExact
+ )
+/*++
+
+Routine Description:
+
+ Find and return a pointer to a BP struct. Always returns a BP that
+ matches hthd thread if one exists; if fExact is FALSE and there is no
+ exact match, a BP matching only hprc and address will succeed.
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+ bptype - Supplies OSDEBUG BP type
+
+ paddr - Supplies address
+
+ fExact - Supplies TRUE if must be for a certain thread
+
+Return Value:
+
+ pointer to BREAKPOINT struct, or NULL if not found.
+
+--*/
+{
+ PBREAKPOINT pbp;
+ PBREAKPOINT pbpFound = NULL;
+ ADDR addr;
+
+ EnterCriticalSection(&csThreadProcList);
+
+ /*
+ * Pre-translate the address to a linear address
+ */
+
+ addr = *paddr;
+ TranslateAddress(hprc, hthd, &addr, TRUE);
+
+ /*
+ * Check for an equivalent breakpoint. Breakpoints will be equal if
+ *
+ * 1. The process is the same
+ * 2. The addresses of the breakpoints are the same
+ */
+
+ for (pbp=bpList->next; pbp; pbp=pbp->next) {
+ if ((pbp->hprc == hprc) &&
+ AreAddrsEqual(hprc, hthd, &pbp->addr, &addr)) {
+ pbpFound = pbp;
+ if (pbp->hthd == hthd) {
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ if (!fExact || (pbpFound && pbpFound->hthd == hthd)) {
+ return pbpFound;
+ } else {
+ return NULL;
+ }
+} /* FindBP() */
+
+
+
+
+PBREAKPOINT
+BPNextHprcPbp(
+ HPRCX hprc,
+ PBREAKPOINT pbp
+ )
+
+/*++
+
+Routine Description:
+
+ Find the next breakpoint for the given process after pbp.
+ If pbp is NULL start at the front of the list, for a find
+ first, find next behaviour.
+
+
+Arguments:
+
+ hprc - Supplies the process handle to match breakpoints for
+
+ pbp - Supplies pointer to breakpoint item to start searching after
+
+Return Value:
+
+ NULL if no matching breakpoint is found else a pointer to the
+ matching breakpoint
+
+--*/
+
+{
+ EnterCriticalSection(&csThreadProcList);
+ if (pbp == NULL) {
+ pbp = bpList->next;
+ } else {
+ pbp = pbp->next;
+ }
+
+ for ( ; pbp; pbp = pbp->next ) {
+ if (pbp->hprc == hprc) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+
+ return pbp;
+} /* BPNextHprcPbp() */
+
+
+PBREAKPOINT
+BPNextHthdPbp(
+ HTHDX hthd,
+ PBREAKPOINT pbp
+ )
+/*++
+
+Routine Description:
+
+ Find the next breakpoint for the given thread after pbp.
+ If pbp is NULL start at the front of the list for find
+ first, find next behaviour.
+
+Arguments:
+
+ hthd - Supplies the thread handle to match breakpoints for
+ pbp - Supplies pointer to breakpoint item to start searching after
+
+Return Value:
+
+ NULL if no matching breakpoint is found else a pointer to the
+ matching breakpoint
+
+--*/
+
+{
+ EnterCriticalSection(&csThreadProcList);
+
+ if (pbp == NULL) {
+ pbp = bpList->next;
+ } else {
+ pbp = pbp->next;
+ }
+
+ for ( ; pbp; pbp = pbp->next ) {
+ if (pbp->hthd == hthd) {
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return pbp;
+} /* BPNextHthdPbp() */
+
+
+
+
+BOOL
+RemoveBPHelper(
+ PBREAKPOINT pbp,
+ BOOL fRestore
+ )
+{
+ PBREAKPOINT pbpPrev;
+ PBREAKPOINT pbpCur;
+ PBREAKPOINT pbpT;
+ HTHDX hthd;
+ BOOL rVal = FALSE;
+
+
+ //
+ // first, is it real?
+ //
+ if (!pbp || pbp == EMBEDDED_BP) {
+ return FALSE;
+ }
+
+ EnterCriticalSection(&csThreadProcList);
+
+ /* Decrement the instances counter */
+ if (--pbp->instances) {
+
+ /*
+ * BUGBUG: jimsch -- Feb 29 1993
+ * This piece of code is most likely incorrect. We need to
+ * know if we are the DM freeing a breakpoint or the user
+ * freeing a breakpoint before we clear the step bit. Otherwise
+ * we may be in the following situation
+ *
+ * Set a thread specific breakpoint on an address
+ * Step the thread so that the address is the destination is
+ * where the step ends up (but it takes some time such
+ * as over a function call)
+ * Clear the thread specific breakpoint
+ *
+ * This will cause the step breakpoint to be cleared so we will
+ * stop at the address instead of just continuing stepping.
+ */
+
+ pbp->isStep = FALSE;
+ LeaveCriticalSection(&csThreadProcList);
+ return FALSE;
+ }
+
+ /* Search the list for the specified breakpoint */
+
+
+ for ( pbpPrev = bpList, pbpCur = bpList->next;
+ pbpCur;
+ pbpPrev = pbpCur, pbpCur = pbpCur->next) {
+
+ if (pbpCur == pbp) {
+
+ /*
+ * Remove this bp from the list:
+ */
+
+ pbpPrev->next = pbpCur->next;
+
+ /*
+ * see if there is another bp on the same address:
+ */
+
+ pbpT = FindBP(pbpCur->hprc,
+ pbpCur->hthd,
+ pbpCur->bpType,
+ pbpCur->bpNotify,
+ &pbpCur->addr,
+ FALSE);
+
+ if (!pbpT && pbpCur->bpType == bptpExec) {
+ /*
+ * if this was the only one, put the
+ * opcode back where it belongs.
+ */
+
+ if ( fRestore ) {
+ RestoreBreakPoint( pbpCur );
+ }
+ }
+
+ /*
+ * Now we have to go through all the threads to see
+ * if any of them are on this breakpoint and clear
+ * the breakpoint indicator on these threads
+ */
+
+ /*
+ * Could be on any thread:
+ */
+
+ /*
+ * (We are already in the ThreadProcList critical section)
+ */
+
+ for (hthd = thdList->next; hthd; hthd = hthd->next) {
+ if (hthd->atBP == pbpCur) {
+ hthd->atBP = pbpT;
+ }
+ }
+
+ free(pbpCur);
+ rVal = TRUE;
+ break;
+ }
+
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return rVal;
+
+}
+
+
+
+BOOL
+RemoveBP(
+ PBREAKPOINT pbp
+ )
+{
+ return RemoveBPHelper( pbp, TRUE );
+}
+
+#ifdef KERNEL
+
+BOOL
+RemoveBPEx(
+ DWORD Count,
+ PBREAKPOINT *Bps
+ )
+{
+
+ PDBGKD_RESTORE_BREAKPOINT DbgKdBp;
+ DWORD RestoreCount = 0;
+ DWORD GoneCount = 0;
+ DWORD i;
+ PBREAKPOINT BpCur;
+ PBREAKPOINT BpOther;
+
+ assert( Count > 0 );
+
+ if ( Count == 1 ) {
+ //
+ // Only one breakpoint, its faster to simply call RemoveBP
+ //
+ return RemoveBP( Bps[0] );
+ }
+
+ EnterCriticalSection(&csThreadProcList);
+
+ DbgKdBp = (PDBGKD_RESTORE_BREAKPOINT)malloc( sizeof(DBGKD_RESTORE_BREAKPOINT) * Count );
+ assert( DbgKdBp );
+
+ if ( DbgKdBp ) {
+
+ //
+ // Find out what breakpoints we have to restore and put them in
+ // the list.
+ //
+ for ( i=0; i<Count;i++ ) {
+
+ assert( Bps[i] != EMBEDDED_BP );
+
+ for ( BpCur = bpList->next; BpCur; BpCur = BpCur->next) {
+
+ if ( BpCur == Bps[i] ) {
+
+ //
+ // See if there is another bp on the same address.
+ //
+ for ( BpOther = bpList->next; BpOther; BpOther = BpOther->next ) {
+ if ( (BpOther != BpCur) &&
+ AreAddrsEqual( BpCur->hprc, BpCur->hthd, &BpCur->addr, &BpOther->addr ) ) {
+ break;
+ }
+ }
+
+ if ( !BpOther ) {
+ //
+ // If this was the only one, put it in the list.
+ //
+ DbgKdBp[GoneCount++].BreakPointHandle = Bps[i]->hBreakPoint;
+ }
+
+ break;
+ }
+ }
+ }
+
+ //
+ // Restore the breakpoints in the list.
+ //
+ if ( GoneCount > 0 ) {
+ assert( GoneCount <= Count );
+ RestoreBreakPointEx( GoneCount, DbgKdBp );
+ }
+
+ //
+ // All breakpoints that were to be restored have been
+ // restored, now go ahead and do the cleaning up stuff.
+ //
+ for ( i=0; i<Count;i++ ) {
+ RemoveBPHelper( Bps[i], FALSE );
+ RestoreCount++;
+ }
+
+ free( DbgKdBp );
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return ( RestoreCount == Count );
+}
+
+#else // KERNEL
+
+BOOL
+RemoveBPEx(
+ DWORD Count,
+ PBREAKPOINT *Bps
+ )
+{
+
+ DWORD i;
+
+ assert( Count > 0 );
+
+ for ( i=0; i<Count;i++ ) {
+ RemoveBPHelper( Bps[i], TRUE );
+ }
+
+ return TRUE;
+}
+
+#endif // KERNEL
+
+
+void
+SetBPFlag(
+ HTHDX hthd,
+ PBREAKPOINT bp
+ )
+{
+ hthd->atBP = bp;
+}
+
+
+
+PBREAKPOINT
+AtBP(
+ HTHDX hthd
+ )
+{
+ return hthd->atBP;
+}
+
+
+
+
+void
+ClearBPFlag(
+ HTHDX hthd
+ )
+{
+ hthd->atBP = NULL;
+}
+
+
+
+void
+RestoreInstrBP(
+ HTHDX hthd,
+ PBREAKPOINT bp
+ )
+/*++
+
+Routine Description:
+
+ Replace the instruction for a breakpoint. If it was not
+ the debugger's BP, skip the IP past it.
+
+Arguments:
+
+ hthd - Thread
+
+ bp - breakpoint data
+
+Return Value:
+
+
+--*/
+{
+ //
+ // Check if this is an embedded breakpoint
+ //
+
+ if (bp == EMBEDDED_BP) {
+
+ //
+ // It was, so there is no instruction to restore,
+ // just increment the EIP
+ //
+
+ IncrementIP(hthd);
+ return;
+ }
+
+ if (bp->hWalk) {
+
+ //
+ // This is really a hardware breakpoint. Let the
+ // walk manager fix this.
+ //
+
+ ExprBPClearBPForStep(hthd);
+
+ } else {
+
+ //
+ // Replace the breakpoint current in memory with the correct
+ // instruction
+ //
+
+ RestoreBreakPoint( bp );
+ bp->hBreakPoint = 0;
+
+ }
+
+ return;
+}
+
+
+VOID
+DeleteAllBps(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ PBREAKPOINT pbp, bpn;
+
+ EnterCriticalSection(&csThreadProcList);
+
+ pbp = bpList->next;
+
+ while (pbp) {
+ bpn = pbp->next;
+ if (bpn) {
+ free( pbp );
+ }
+ pbp = bpn;
+ }
+
+ bpList->next = NULL;
+ bpList->hprc = NULL;
+
+ LeaveCriticalSection(&csThreadProcList);
+}
+
+void
+AddBpToList(
+ PBREAKPOINT pbp
+ )
+{
+ assert(bpList);
+ EnterCriticalSection(&csThreadProcList);
+ pbp->next = bpList->next;
+ bpList->next = pbp;
+ LeaveCriticalSection(&csThreadProcList);
+}
+
+PBREAKPOINT
+FindBpForWalk(
+ PVOID pWalk
+ )
+{
+ PBREAKPOINT pbp;
+
+ EnterCriticalSection(&csThreadProcList);
+
+ pbp = bpList;
+ while (pbp) {
+ if (IsWalkInGroup(pbp->hWalk, pWalk)) {
+ break;
+ }
+ pbp = pbp->next;
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return pbp;
+}
+
+PBREAKPOINT
+SetWP(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP bptype,
+ BPNS bpnotify,
+ ADDR addr
+ )
+{
+ return (PBREAKPOINT)0;
+}
+
diff --git a/private/windbg/newdm/bp.h b/private/windbg/newdm/bp.h
new file mode 100644
index 000000000..18d8833f6
--- /dev/null
+++ b/private/windbg/newdm/bp.h
@@ -0,0 +1,80 @@
+/*
+ * Prototypes and structures for breakpoint handler
+ */
+
+extern BOOL BPInRange(HPRCX, HTHDX, BREAKPOINT*, LPADDR, DWORD,
+ LPDWORD, BP_UNIT*);
+extern BREAKPOINT* FindProcBP(HPRCX);
+extern BREAKPOINT* FindThreadBP(HTHDX);
+extern BREAKPOINT* FindIdBP(HDEP);
+extern BOOL RemoveBP(BREAKPOINT*);
+extern void SetBPFlag(HTHDX, BREAKPOINT*);
+extern BREAKPOINT* AtBP(HTHDX);
+extern void ClearBPFlag(HTHDX);
+extern void RestoreInstrBP(HTHDX, BREAKPOINT*);
+extern BREAKPOINT* BPNextHprcPbp( HPRCX hprc, BREAKPOINT * pbp );
+extern BREAKPOINT* BPNextHthdPbp( HTHDX hthd, BREAKPOINT * pbp );
+
+PBREAKPOINT
+SetBP(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP bptype,
+ BPNS bpnotify,
+ LPADDR paddr,
+ HPID id
+ );
+
+PBREAKPOINT
+FindBP(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP bptype,
+ BPNS bpnotify,
+ LPADDR paddr,
+ BOOL fExact
+ );
+
+BOOL
+SetBPEx(
+ HPRCX hprc,
+ HTHDX hthd,
+ HPID id,
+ DWORD Count,
+ ADDR *Addrs,
+ PBREAKPOINT *Bps,
+ DWORD ContinueStatus
+ );
+
+BOOL
+RemoveBPEx(
+ DWORD Count,
+ PBREAKPOINT *Bps
+ );
+
+PBREAKPOINT
+GetNewBp(
+ HPRCX hprc,
+ HTHDX hthd,
+ BPTP BpType,
+ BPNS BpNotify,
+ ADDR *AddrBp,
+ HPID id,
+ BREAKPOINT *BpUse
+ );
+
+BOOL
+WriteBreakPoint(
+ IN PBREAKPOINT Breakpoint
+ );
+
+BOOL
+RestoreBreakPoint(
+ IN PBREAKPOINT Breakpoint
+ );
+
+void
+AddBpToList(
+ PBREAKPOINT pbp
+ );
+
diff --git a/private/windbg/newdm/cache.c b/private/windbg/newdm/cache.c
new file mode 100644
index 000000000..43857b77c
--- /dev/null
+++ b/private/windbg/newdm/cache.c
@@ -0,0 +1,1254 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ cache.c
+
+Abstract:
+
+Author:
+
+ Wesley Witt (wesw) 8-Mar-1992
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+typedef unsigned long DWORD;
+typedef int BOOL;
+
+#define NTINCLUDES
+
+
+
+#define MIN_READ_SIZE 0x80
+#define MIN_CACHE_MISSES 3
+
+ULONG KdMaxCacheSize = 100*1024;
+ULONG KdCacheMisses = 0;
+ULONG KdCachePurges = 0;
+ULONG KdCacheSize = 0;
+ULONG KdNodeCount = 0;
+BOOLEAN KdPurgeOverride = FALSE;
+BOOLEAN KdCacheDecodePTEs = TRUE;
+
+typedef struct {
+ RTL_SPLAY_LINKS SplayLinks;
+ ULONG Offset;
+ USHORT Length;
+ USHORT Flags;
+ union {
+ PUCHAR Data;
+ NTSTATUS Status;
+ } u;
+} CACHE, *PCACHE;
+
+#define C_ERROR 0x0001 // Cache of error code
+#define C_DONTEXTEND 0x0002 // Don't try to extend
+#define C_NONDISCARDABLE 0x0004 // never purge this node
+
+#define LARGECACHENODE 1024 // Size of large cache node
+
+
+PCACHE VirtCacheRoot; // Root of cache node tree
+
+
+//
+// Prototypes...
+//
+
+extern void DebugPrint(char *, ...);
+
+BOOLEAN
+KdConvertToPhysicalAddr (
+ PVOID,
+ PPHYSICAL_ADDRESS
+ );
+
+PCACHE
+CacheLookup (
+ ULONG Offset,
+ ULONG Length,
+ PULONG LengthUsed
+ );
+
+VOID
+InsertCacheNode (
+ IN PCACHE node
+ );
+
+PUCHAR vcmalloc (
+ IN ULONG Length
+ );
+
+VOID vcfree (
+ IN PUCHAR Memory,
+ IN ULONG Length
+ );
+
+NTSTATUS
+VCReadTranslatePTEAndReadMemory (
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ );
+
+VOID
+DmKdSetMaxCacheSize(
+ IN ULONG MaxCacheSize
+ )
+{
+ KdMaxCacheSize = MaxCacheSize;
+}
+
+
+ULONG
+DmKdReadCachedVirtualMemory (
+ IN ULONG BaseAddress,
+ IN ULONG TransferCount,
+ IN PUCHAR UserBuffer,
+ IN PULONG BytesRead,
+ IN ULONG NonDiscardable
+ )
+/*++
+
+ This function returns the specified data from the system being debugged
+ using the current mapping of the processor. If the data is not
+ in the cache, it will then be read from the target system.
+
+Arguments:
+
+ TargetBaseAddress - Supplies the base address of the memory to be
+ copied into the UserBuffer.
+
+ TransferCount - Amount of data to be copied to the UserBuffer.
+
+ UserBuffer - Address to copy the requested data.
+
+ BytesRead - Number of bytes which could actually be copied
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ other (see DmKdReadVirtualMemoryNow).
+
+--*/
+{
+ NTSTATUS st;
+ PCACHE node, node2;
+ ULONG nextlength;
+ ULONG i, br;
+ PUCHAR p;
+
+
+ *BytesRead = 0;
+ if (KdMaxCacheSize == 0) {
+ //
+ // Cache is off
+ //
+
+ goto ReadDirect;
+ }
+
+// DebugPrint( "readcache %x %d\n", BaseAddress, TransferCount );
+
+ node = CacheLookup(BaseAddress, TransferCount, &nextlength);
+ st = STATUS_SUCCESS;
+
+ while( TRUE ) {
+ //
+ // Check if current command has been canceled. If yes, go back to
+ // kd prompt.
+ //
+
+ if (node == NULL || node->Offset > BaseAddress) {
+ //
+ // We are missing the leading data, read it into the cache
+ //
+
+ if (node) {
+ //
+ // Only get (exactly) enough data to reach neighboring cache
+ // node. If an overlapped read occurs between the two nodes,
+ // the data will be concatenated then.
+ //
+
+ nextlength = node->Offset - BaseAddress;
+ }
+
+ //nextlength = max( nextlength, MIN_READ_SIZE );
+
+ p = vcmalloc (nextlength);
+ node = (PCACHE) vcmalloc (sizeof (CACHE));
+
+ if (p == NULL || node == NULL) {
+ //
+ // Out of memory - just read directly to UserBuffer
+ //
+
+ if (p) {
+ vcfree (p, nextlength);
+ }
+ if (node) {
+ vcfree ((PUCHAR)node, sizeof (CACHE));
+ }
+
+ goto ReadDirect;
+ }
+
+ //
+ // Read missing data into cache node
+ //
+
+ node->Offset = BaseAddress;
+ node->u.Data = p;
+ node->Flags = 0;
+ if (NonDiscardable) {
+ node->Flags |= C_NONDISCARDABLE;
+ }
+
+ KdCacheMisses++;
+ while( TRUE ) {
+
+ st = DmKdReadVirtualMemoryNow(
+ (PVOID) BaseAddress,
+ (PVOID) node->u.Data,
+ nextlength,
+ &br
+ );
+
+ if (NT_SUCCESS(st)) {
+ break;
+ }
+
+ //
+ // Before accepting the error, make sure request
+ // didn't fail because it was enlarged for caching.
+ //
+
+ i = nextlength;
+ //nextlength = TransferCount;
+
+ //
+ // If length crosses possible page boundry, shrink request
+ // even furture.
+ //
+
+ if ((BaseAddress & ~0xfff) != ((BaseAddress+nextlength) & ~0xfff)) {
+ nextlength = (BaseAddress | 0xfff) - BaseAddress + 1;
+ }
+
+ //
+ // If nextlength is shorter then failed request, then loop
+ // and try again
+ //
+
+ if (nextlength >= i) {
+ //
+ // If implicit decode of the pte is requested, go
+ // try getting this memory by it's physical address
+ //
+ if (st == STATUS_UNSUCCESSFUL && KdCacheDecodePTEs) {
+ st = VCReadTranslatePTEAndReadMemory (
+ (PVOID) BaseAddress,
+ (PVOID) node->u.Data,
+ nextlength,
+ &br
+ );
+ }
+ break;
+ }
+ }
+
+ if (!NT_SUCCESS(st)) {
+ //
+ // There was an error, cache the error for the starting
+ // byte of this range
+ //
+
+ vcfree (p, nextlength);
+ if (st != STATUS_UNSUCCESSFUL) {
+ //
+ // For now be safe, don't cache this error
+ //
+
+ vcfree ((PUCHAR)node, sizeof (CACHE));
+ return *BytesRead ? STATUS_SUCCESS : st;
+ }
+
+ node->Length = 1;
+ node->Flags |= C_ERROR;
+ node->u.Status = st;
+
+ } else {
+
+ node->Length = (USHORT) br;
+ if (br != nextlength) {
+ //
+ // Some data was not transfered, cache what was returned
+ //
+
+ node->Flags |= C_DONTEXTEND;
+ KdCacheSize -= (nextlength - br);
+ }
+ }
+
+
+ //
+ // Insert cache node into splay tree
+ //
+
+ InsertCacheNode (node);
+ }
+
+ if (node->Flags & C_ERROR) {
+ //
+ // Hit an error range, we're done
+ //
+
+ return *BytesRead ? STATUS_SUCCESS : node->u.Status;
+ }
+
+ //
+ // Move available data to UserBuffer
+ //
+
+ i = BaseAddress - node->Offset;
+ p = node->u.Data + i;
+ i = (ULONG) node->Length - i;
+ if (TransferCount < i) {
+ i = TransferCount;
+ }
+ memcpy (UserBuffer, p, i);
+
+ TransferCount -= i;
+ BaseAddress += i;
+ UserBuffer += i;
+ *BytesRead += i;
+
+ if (!TransferCount) {
+ //
+ // All of the users data has been transfered
+ //
+
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // Look for another cache node with more data
+ //
+
+ node2 = CacheLookup (BaseAddress, TransferCount, &nextlength);
+ if (node2) {
+ if ((node2->Flags & C_ERROR) == 0 &&
+ node2->Offset == BaseAddress &&
+ node2->Length + node->Length < LARGECACHENODE) {
+ //
+ // Data is continued in node2, adjoin the neigboring
+ // cached data in node & node2 together.
+ //
+
+ p = vcmalloc (node->Length + node2->Length);
+ if (p != NULL) {
+ memcpy (p, node->u.Data, node->Length);
+ memcpy (p+node->Length, node2->u.Data, node2->Length);
+ vcfree (node->u.Data, node->Length);
+ node->u.Data = p;
+ node->Length += node2->Length;
+ VirtCacheRoot = (PCACHE) RtlDelete ((PRTL_SPLAY_LINKS)node2);
+ vcfree ((PUCHAR)node2->u.Data, node2->Length);
+ vcfree ((PUCHAR)node2, sizeof (CACHE));
+ KdNodeCount--;
+ continue;
+ }
+ }
+
+ //
+ // Only get enough data to reach the neighboring cache node2
+ //
+
+ nextlength = node2->Offset - BaseAddress;
+ if (nextlength == 0) {
+ //
+ // Data is continued in node2, go get it.
+ //
+
+ node = node2;
+ continue;
+ }
+
+ } else {
+
+ if (node->Length > LARGECACHENODE) {
+ //
+ // Current cache node is already big enough. Don't extend
+ // it, add another cache node.
+ //
+
+ node = NULL;
+ continue;
+ }
+ }
+
+ //
+ // Extend the current node to include missing data
+ //
+
+ if (node->Flags & C_DONTEXTEND) {
+ node = NULL;
+ continue;
+ }
+
+ //nextlength = max( nextlength, MIN_READ_SIZE );
+
+ p = vcmalloc (node->Length + nextlength);
+ if (!p) {
+ node = NULL;
+ continue;
+ }
+
+ memcpy (p, node->u.Data, node->Length);
+ vcfree (node->u.Data, node->Length);
+ node->u.Data = p;
+
+ //
+ // Add new data to end of this node
+ //
+
+ KdCacheMisses++;
+ while( TRUE ) {
+ st = DmKdReadVirtualMemoryNow (
+ (PVOID) BaseAddress,
+ (PVOID) (node->u.Data + node->Length),
+ nextlength,
+ &br
+ );
+
+ if (NT_SUCCESS(st)) {
+ break;
+ }
+
+ //
+ // Before accepting the error, make sure request
+ // didn't fail because it was enlarged for caching.
+ //
+
+ node->Flags |= C_DONTEXTEND;
+ i = TransferCount;
+
+ //
+ // If length crosses possible page boundry, shrink request
+ // even furture.
+ //
+
+ if ((BaseAddress & ~0xfff) != ((BaseAddress + i) & ~0xfff)) {
+ i = (BaseAddress | 0xfff) - BaseAddress + 1;
+ }
+
+ //
+ // If nextlength is shorter, then loop (try the read again)
+ //
+
+ if (i >= nextlength) {
+ //
+ // If implicit decode of the pte is requested, go
+ // try getting this memory by it's physical address
+ //
+ if (st == STATUS_UNSUCCESSFUL && KdCacheDecodePTEs) {
+ st = VCReadTranslatePTEAndReadMemory (
+ (PVOID) BaseAddress,
+ (PVOID) (node->u.Data + node->Length),
+ nextlength,
+ &br
+ );
+ }
+ break;
+ }
+
+ //
+ // Adjust counts for new transfer size
+ //
+
+ KdCacheSize -= (nextlength - i);
+ nextlength = i;
+ }
+
+ if (!NT_SUCCESS(st)) {
+ //
+ // Return to error to the caller
+ //
+
+ node->Flags |= C_DONTEXTEND;
+ KdCacheSize -= nextlength;
+ return *BytesRead ? STATUS_SUCCESS : st;
+ }
+
+ if (br != nextlength) {
+ node->Flags |= C_DONTEXTEND;
+ KdCacheSize -= (nextlength - br);
+ }
+
+ node->Length += (USHORT) br;
+ // Loop, and move data to user's buffer
+ }
+
+ReadDirect:
+ while (TransferCount) {
+ nextlength = TransferCount;
+ while( TRUE ) {
+ st = DmKdReadVirtualMemoryNow (
+ (PVOID) BaseAddress,
+ (PVOID) UserBuffer,
+ nextlength,
+ &br
+ );
+
+ if (NT_SUCCESS(st)) {
+ break;
+ }
+
+ if ((BaseAddress & ~0xfff) != ((BaseAddress+nextlength) & ~0xfff)) {
+ //
+ // Before accepting the error, make sure request
+ // didn't fail because it crossed multiple pages
+ //
+
+ nextlength = (BaseAddress | 0xfff) - BaseAddress + 1;
+
+ } else {
+ if (st == STATUS_UNSUCCESSFUL && KdCacheDecodePTEs) {
+ //
+ // Try getting the memory by looking up the physical
+ // location of the page
+ //
+
+ st = VCReadTranslatePTEAndReadMemory (
+ (PVOID) BaseAddress,
+ (PVOID) UserBuffer,
+ nextlength,
+ &br
+ );
+
+ if (NT_SUCCESS(st)) {
+ break;
+ }
+ }
+
+ //
+ // Return to error to the caller
+ //
+
+ return *BytesRead ? STATUS_SUCCESS : st;
+ }
+ }
+
+ TransferCount -= br;
+ BaseAddress += br;
+ UserBuffer += br;
+ *BytesRead += br;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+PCACHE
+CacheLookup (
+ ULONG Offset,
+ ULONG Length,
+ PULONG LengthUsed
+ )
+/*++
+
+Routine Description:
+
+ Walks the cache tree looking for a matching range closest to
+ the supplied Offset. The length of the range searched is based on
+ the past length, but may be adjusted slightly.
+
+ This function will always search for the starting byte.
+
+Arguments:
+
+ Offset - Starting byte being looked for in cache
+ Length - Length of range being looked for in cache
+ LengthUsed - Length of range which was really search for
+
+Return Value:
+
+ NULL - data for returned range was not found
+ PCACHE - leftmost cachenode which has data for returned range
+
+
+--*/
+{
+ PCACHE node, node2;
+ ULONG SumOffsetLength;
+
+// DebugPrint( "CacheLookup\n" );
+
+ if (Length < MIN_READ_SIZE && KdCacheMisses > MIN_CACHE_MISSES) {
+ // Try to cache more then tiny amount
+ Length = MIN_READ_SIZE;
+ }
+
+ SumOffsetLength = Offset + Length;
+ if (SumOffsetLength < Length) {
+ //
+ // Offset + Length wrapped. Adjust Length to be only
+ // enough bytes before wrapping.
+ //
+
+ Length = 0 - Offset;
+ SumOffsetLength = (ULONG) -1;
+ }
+ *LengthUsed = Length;
+
+ //
+ // Find leftmost cache node for BaseAddress thru BaseAddress+Length
+ //
+
+ node2 = NULL;
+ node = VirtCacheRoot;
+ while (node != NULL) {
+ if (SumOffsetLength <= node->Offset) {
+ node = (PCACHE) RtlLeftChild(&node->SplayLinks);
+ } else if (node->Offset + node->Length <= Offset) {
+ node = (PCACHE) RtlRightChild(&node->SplayLinks);
+ } else {
+ if (node->Offset <= Offset) {
+ //
+ // Found starting byte
+ //
+
+ return node;
+ }
+
+ //
+ // Check to see if there's a node which has a match closer
+ // to the start of the requested range
+ //
+
+ node2 = node;
+ Length = node->Offset - Offset;
+ node = (PCACHE) RtlLeftChild(&node->SplayLinks);
+ }
+ }
+
+ return node2;
+}
+
+VOID
+InsertCacheNode (
+ IN PCACHE node
+ )
+{
+ PCACHE node2;
+ ULONG BaseAddress;
+
+ //
+ // Insert cache node into splay tree
+ //
+
+// DebugPrint( "insertcache\n" );
+
+ RtlInitializeSplayLinks(&node->SplayLinks);
+
+ KdNodeCount++;
+ if (VirtCacheRoot == NULL) {
+ VirtCacheRoot = node;
+ return;
+ }
+
+ node2 = VirtCacheRoot;
+ BaseAddress = node->Offset;
+ while( TRUE ) {
+ if (BaseAddress < node2->Offset) {
+ if (RtlLeftChild(&node2->SplayLinks)) {
+ node2 = (PCACHE) RtlLeftChild(&node2->SplayLinks);
+ continue;
+ }
+ RtlInsertAsLeftChild(node2, node);
+ break;
+
+ } else {
+ if (RtlRightChild(&node2->SplayLinks)) {
+ node2 = (PCACHE) RtlRightChild(&node2->SplayLinks);
+ continue;
+ }
+ RtlInsertAsRightChild(node2, node);
+ break;
+ }
+ }
+ VirtCacheRoot = (PCACHE) RtlSplay((PRTL_SPLAY_LINKS)node2);
+}
+
+VOID
+DmKdInitVirtualCacheEntry (
+ IN ULONG BaseAddress,
+ IN ULONG Length,
+ IN PUCHAR UserBuffer,
+ IN ULONG NonDiscardable
+ )
+/*++
+
+Routine Description:
+
+ Insert some data into the virtual cache.
+
+Arguments:
+
+ BaseAddress - Virtual address
+ Length - length to cache
+ UserBuffer - data to put into cache
+
+Return Value:
+
+--*/
+{
+ PCACHE node;
+ PUCHAR p;
+ ULONG LengthUsed;
+
+ if (KdMaxCacheSize == 0) {
+ //
+ // Cache is off
+ //
+
+ return ;
+ }
+
+// DebugPrint( "DmKdInitVirtualCacheEntry\n" );
+
+ node = CacheLookup( BaseAddress, Length, &LengthUsed );
+ if (node) {
+ return;
+ }
+
+ //
+ // Delete any cached info which hits range
+ //
+
+ DmKdWriteCachedVirtualMemory (BaseAddress, Length, UserBuffer);
+
+
+ p = vcmalloc (Length);
+ node = (PCACHE) vcmalloc (sizeof (CACHE));
+ if (p == NULL || node == NULL) {
+ //
+ // Out of memory - don't bother
+ //
+
+ if (p) {
+ vcfree (p, Length);
+ }
+ if (node) {
+ vcfree ((PUCHAR)node, sizeof (CACHE));
+ }
+
+ return ;
+ }
+
+ //
+ // Put data into cache node
+ //
+
+ node->Offset = BaseAddress;
+ node->Length = (USHORT) Length;
+ node->u.Data = p;
+ node->Flags = 0;
+ if (NonDiscardable) {
+ node->Flags |= C_NONDISCARDABLE;
+ }
+ memcpy (p, UserBuffer, Length);
+ InsertCacheNode (node);
+}
+
+
+
+PUCHAR
+vcmalloc (
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Allocates memory for virtual cache, and tracks total memory
+ usage.
+
+Arguments:
+
+ Length - Amount of memory to allocate
+
+Return Value:
+
+ NULL - too much memory is in use, or memory could not
+ be allocated
+
+ Otherwise, returns to address of the allocated memory
+
+--*/
+{
+ PUCHAR p;
+
+ if (KdCacheSize + Length > KdMaxCacheSize)
+ return NULL;
+
+ if (!(p = (PUCHAR) malloc (Length))) {
+ //
+ // Out of memory - don't get any larger
+ //
+
+ KdCacheSize = KdMaxCacheSize+1;
+ return NULL;
+ }
+
+ KdCacheSize += Length;
+ return p;
+}
+
+
+VOID
+vcfree (
+ IN PUCHAR Memory,
+ IN ULONG Length
+ )
+/*++
+Routine Description:
+
+ Free memory allocated with vcmalloc. Adjusts cache is use totals.
+
+Arguments:
+
+ Memory - Address of allocated memory
+ Length - Length of allocated memory
+
+Return Value:
+
+ NONE
+
+--*/
+{
+ KdCacheSize -= Length;
+ free (Memory);
+}
+
+
+NTSTATUS
+VCReadTranslatePTEAndReadMemory (
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ )
+/*++
+--*/
+{
+static BOOLEAN ConvertingAnAddress;
+ NTSTATUS status;
+ BOOLEAN converted;
+ PHYSICAL_ADDRESS TargetPhysicalAddress;
+
+ if (ConvertingAnAddress) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Memory could not be read, try it's physical address.
+ //
+
+ ConvertingAnAddress = TRUE;
+ converted = KdConvertToPhysicalAddr (
+ TargetBaseAddress,
+ &TargetPhysicalAddress
+ );
+
+ if (converted) {
+ status = DmKdReadPhysicalMemory (
+ TargetPhysicalAddress,
+ UserInterfaceBuffer,
+ TransferCount,
+ ActualBytesRead
+ );
+ } else {
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ ConvertingAnAddress = FALSE;
+ return NT_SUCCESS(status) ? status : STATUS_UNSUCCESSFUL;
+}
+
+VOID
+DmKdWriteCachedVirtualMemory (
+ IN ULONG BaseAddress,
+ IN ULONG TransferCount,
+ IN PUCHAR UserBuffer
+ )
+/*++
+
+Routine Description:
+
+ Invalidates range from the cache.
+
+Arguments:
+
+ BaseAddress - Starting address to purge
+ TransferCount - Length of area to purge
+ UserBuffer - not used
+
+Return Value:
+
+ NONE
+
+--*/
+{
+ PCACHE node;
+ ULONG bogus;
+
+ //
+ // Invalidate any data in the cache which covers this range
+ //
+
+ while (node = CacheLookup(BaseAddress, TransferCount, &bogus)) {
+ //
+ // For now just delete the entire cache node which hits the range
+ //
+
+ VirtCacheRoot = (PCACHE) RtlDelete (&node->SplayLinks);
+ if (!(node->Flags & C_ERROR)) {
+ vcfree (node->u.Data, node->Length);
+ }
+ vcfree ((PUCHAR)node, sizeof (CACHE));
+ KdNodeCount--;
+ }
+}
+
+
+PCACHE
+WalkForDelete(PCACHE node)
+{
+ PCACHE node2;
+
+ if (!(node->Flags & C_NONDISCARDABLE)) {
+ return node;
+ }
+
+ node2 = (PCACHE)RtlRightChild(&node->SplayLinks);
+
+ if (node2) {
+ if (!(node2->Flags & C_NONDISCARDABLE)) {
+ return node2;
+ } else {
+ node2 = WalkForDelete( node2 );
+ if (node2) {
+ return node2;
+ }
+ }
+ }
+
+ node2 = (PCACHE)RtlLeftChild(&node->SplayLinks);
+
+ if (node2) {
+ if (!(node2->Flags & C_NONDISCARDABLE)) {
+ return node2;
+ } else {
+ node2 = WalkForDelete( node2 );
+ if (node2) {
+ return node2;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+VOID
+DmKdPurgeCachedVirtualMemory (
+ BOOL fPurgeNonDiscardable
+ )
+/*++
+
+Routine Description:
+
+ Purges to entire virtual memory cache
+
+Arguments:
+
+ NONE
+
+Return Value:
+
+ NONE
+
+--*/
+{
+ PCACHE node;
+ PCACHE node2;
+
+ if (KdPurgeOverride) {
+ DMPrintShellMsg("** Warning: cache being help\n");
+ return;
+ }
+
+ node = VirtCacheRoot;
+ KdCacheMisses = 0;
+ KdCachePurges++;
+
+ if (fPurgeNonDiscardable) {
+ while( node ) {
+ if (!(node->Flags & C_ERROR)) {
+ free (node->u.Data);
+ }
+ KdNodeCount--;
+ KdCacheSize -= node->Length;
+ node = VirtCacheRoot = (PCACHE)RtlDelete((PRTL_SPLAY_LINKS)node);
+ }
+ KdCacheSize = 0;
+ return;
+ }
+
+ while( node ) {
+ node2 = WalkForDelete( node );
+ if (node2) {
+ if (!(node2->Flags & C_ERROR)) {
+ free (node2->u.Data);
+ }
+ KdNodeCount--;
+ KdCacheSize -= node2->Length;
+ node = VirtCacheRoot = (PCACHE)RtlDelete((PRTL_SPLAY_LINKS)node2);
+ } else {
+ node = node2;
+ }
+ }
+
+ return;
+}
+
+void
+WalkForDump(PCACHE node)
+{
+ PCACHE l,r;
+
+ r = (PCACHE)RtlRightChild(&node->SplayLinks);
+ l = (PCACHE)RtlLeftChild(&node->SplayLinks);
+
+ DMPrintShellMsg( "%08x %8d (%c)\n", node->Offset, node->Length, (node->Flags&C_NONDISCARDABLE) ? 'Y' : 'N' );
+
+ if (r) {
+ WalkForDump( r );
+ }
+
+ if (l) {
+ WalkForDump( l );
+ }
+}
+
+BOOLEAN
+KdConvertToPhysicalAddr (
+ IN PVOID uAddress,
+ OUT PPHYSICAL_ADDRESS PhysicalAddress
+ )
+/*++
+
+Routine Description:
+
+ Convert a virtual address to a physical one.
+
+ Note: that this function is called from within the virtual memory
+ cache code. This function can read from the virtual memory cache
+ so long as it only read's PDE's and PTE's and so long as it fails
+ to convert a PDE or PTE virtual address.
+
+Arguments:
+
+ uAddress - address to convert
+ PhysicalAddress - returned physical address
+
+Return Value:
+
+ TRUE - physical address was returned
+ otherwise, FALSE
+
+--*/
+
+{
+#define PDE_TOP 0xC03FFFFF
+
+#if defined( TARGET_i386 )
+ #define PTE_BASE 0xC0000000
+ #define PDE_BASE 0xC0300000
+ #define MM_PTE_PROTOTYPE_MASK 0x400
+ #define MM_PTE_TRANSITION_MASK 0x800
+ #define PTE_CONT 0x1
+#elif defined( TARGET_PPC )
+ #define MM_PTE_PROTOTYPE_MASK 0x1
+ #define MM_PTE_TRANSITION_MASK 0x2
+ #define PTE_CONT 0x1
+#elif defined( TARGET_MIPS )
+ #define MM_PTE_PROTOTYPE_MASK 0x4
+ #define MM_PTE_TRANSITION_MASK 0x100
+ #define PTE_CONT 0x2
+#elif defined( TARGET_ALPHA )
+ #define MM_PTE_PROTOTYPE_MASK 0x2
+ #define MM_PTE_TRANSITION_MASK 0x4
+ #define PTE_CONT 0x1
+#endif
+
+#define MiGetPdeAddress(va) ((ULONG)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
+#define MiGetPteAddress(va) ((ULONG)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
+
+ ULONG Address;
+ ULONG Pte;
+ ULONG Pde;
+ ULONG PdeContents;
+ ULONG PteContents;
+ NTSTATUS status;
+ ULONG result;
+
+ Address = (ULONG) uAddress;
+ if (Address >= PTE_BASE && Address < PDE_TOP) {
+
+ //
+ // The address is the address of a PTE, rather than
+ // a virtual address. DO NOT CONVERT IT.
+ //
+
+ return FALSE;
+ }
+
+ Pde = MiGetPdeAddress (Address);
+ Pte = MiGetPteAddress (Address);
+
+ status = DmKdReadVirtualMemoryNow((PVOID)Pde,
+ &PdeContents,
+ sizeof(ULONG),
+ &result);
+
+ if ((status != STATUS_SUCCESS) || (result < sizeof(ULONG))) {
+ return FALSE;
+ }
+
+ if (!(PdeContents & PTE_CONT)) {
+ return FALSE;
+ }
+
+ status = DmKdReadVirtualMemoryNow((PVOID)Pte,
+ &PteContents,
+ sizeof(ULONG),
+ &result);
+
+ if ((status != STATUS_SUCCESS) || (result < sizeof(ULONG))) {
+ return FALSE;
+ }
+
+ if (!(PteContents & PTE_CONT)) {
+ if ( (PteContents & MM_PTE_PROTOTYPE_MASK) ||
+ !(PteContents & MM_PTE_TRANSITION_MASK)) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // This is a page which is either present or in transition.
+ // Return the physical address for the request virtual address.
+ //
+
+ PhysicalAddress->LowPart = (PteContents & ~(0xFFF)) | (Address & 0xFFF);
+ PhysicalAddress->HighPart = 0;
+ return TRUE;
+}
+
+VOID
+ProcessCacheCmd(
+ LPSTR pchCommand
+ )
+{
+ ULONG CacheSize;
+ ULONG Address;
+
+
+ while (*pchCommand == ' ') {
+ pchCommand++;
+ }
+
+ _strlwr (pchCommand);
+
+ if (strcmp (pchCommand, "?") == 0) {
+usage:
+ DMPrintShellMsg("\n.cache [{cachesize} | dump | hold | unhold | decodeptes | nodecodeptes]\n");
+ DMPrintShellMsg(".cache [flushall | flushu | flush addr]\n\n");
+ return;
+ } else
+ if (strcmp (pchCommand, "dump") == 0) {
+ if (VirtCacheRoot) {
+ DMPrintShellMsg("\n Address Length Discardable\n");
+ WalkForDump( VirtCacheRoot );
+ }
+ } else
+ if (strcmp (pchCommand, "hold") == 0) {
+ KdPurgeOverride = TRUE;
+ } else
+ if (strcmp (pchCommand, "unhold") == 0) {
+ KdPurgeOverride = FALSE;
+ } else
+ if (strcmp (pchCommand, "decodeptes") == 0) {
+ DmKdPurgeCachedVirtualMemory(TRUE);
+ KdCacheDecodePTEs = TRUE;
+ } else
+ if (strcmp (pchCommand, "nodecodeptes") == 0) {
+ KdCacheDecodePTEs = FALSE;
+ } else
+ if (strcmp (pchCommand, "flushall") == 0) {
+ DmKdPurgeCachedVirtualMemory(TRUE);
+ } else
+ if (strcmp (pchCommand, "flushu") == 0) {
+ DmKdPurgeCachedVirtualMemory(TRUE);
+ } else
+ if (*pchCommand == 'f') {
+ while (*pchCommand >= 'a' && *pchCommand <= 'z') {
+ pchCommand++;
+ }
+ Address = strtoul(pchCommand,NULL,0);
+ DmKdWriteCachedVirtualMemory (Address, 4096, NULL); // this is a flush
+ DMPrintShellMsg("Cached info for address %lx for 4096 bytes was flushed\n", Address);
+ } else if (*pchCommand) {
+ if (*pchCommand < '0' || *pchCommand > '9') {
+ goto usage;
+ } else {
+ CacheSize = strtoul(pchCommand,NULL,0);
+ KdMaxCacheSize = CacheSize * 1024;
+ if (CacheSize == 0) {
+ DmKdPurgeCachedVirtualMemory(TRUE);
+ KdCachePurges = 0;
+ }
+ }
+ }
+
+ DMPrintShellMsg("\n");
+ DMPrintShellMsg("Max cache size is....: %ld %s\n", KdMaxCacheSize,
+ KdMaxCacheSize ? "" : "(cache is off)");
+ DMPrintShellMsg("Total memory in cache: %ld\n", KdCacheSize - KdNodeCount * sizeof (CACHE) );
+ DMPrintShellMsg("No of regions cached.: %ld\n", KdNodeCount);
+ DMPrintShellMsg("Cache misses.........: %ld\n", KdCacheMisses);
+ DMPrintShellMsg("Cache purges.........: %ld\n", KdCachePurges);
+
+ if (KdCacheDecodePTEs) {
+ DMPrintShellMsg("** Transition ptes are implicity decoded\n");
+ }
+
+ if (KdPurgeOverride) {
+ DMPrintShellMsg("** Implicit cache flushing disabled **\n");
+ }
+ DMPrintShellMsg("\n");
+}
diff --git a/private/windbg/newdm/com.c b/private/windbg/newdm/com.c
new file mode 100644
index 000000000..d908a1a30
--- /dev/null
+++ b/private/windbg/newdm/com.c
@@ -0,0 +1,473 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ api.c
+
+Abstract:
+
+ This module implements the all apis that simulate their
+ WIN32 counterparts.
+
+Author:
+
+ Wesley Witt (wesw) 8-Mar-1992
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef min
+#undef min
+#undef max
+#endif
+
+#define COM_PORT_NAME "_NT_DEBUG_PORT"
+#define COM_PORT_BAUD "_NT_DEBUG_BAUD_RATE"
+#define OUT_NORMAL 0
+#define OUT_TERMINAL 1
+
+ULONG KdPollThreadMode = 0;
+
+//
+// Global Data
+//
+HANDLE DmKdComPort;
+
+//
+// This overlapped structure will be used for all serial read
+// operations. We only need one structure since the code is
+// designed so that no more than one serial read operation is
+// outstanding at any one time.
+//
+OVERLAPPED ReadOverlapped;
+
+//
+// This overlapped structure will be used for all serial write
+// operations. We only need one structure since the code is
+// designed so that no more than one serial write operation is
+// outstanding at any one time.
+//
+OVERLAPPED WriteOverlapped;
+
+//
+// This overlapped structure will be used for all event operations.
+// We only need one structure since the code is designed so that no more
+// than one serial event operation is outstanding at any one time.
+//
+OVERLAPPED EventOverlapped;
+
+
+//
+// Global to watch changes in event status. (used for carrier detection)
+//
+DWORD DmKdComEvent;
+
+
+CRITICAL_SECTION csComPort;
+CRITICAL_SECTION csPacket;
+
+
+BOOLEAN
+DmKdInitComPort(
+ BOOLEAN KdModemControl
+ )
+{
+ char ComPortName[16];
+ ULONG Baud;
+ DCB LocalDcb;
+ COMMTIMEOUTS To;
+ DWORD mask;
+
+
+ Baud = KdOptions[KDO_BAUDRATE].value;
+ sprintf( ComPortName, "\\\\.\\com%d", KdOptions[KDO_PORT].value );
+
+ //
+ // Open the device
+ //
+ DmKdComPort = CreateFile(
+ (PSZ)ComPortName,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL
+ );
+
+ if ( DmKdComPort == (HANDLE)-1 ) {
+ return FALSE;
+ }
+
+ SetupComm(DmKdComPort,(DWORD)4096,(DWORD)4096);
+
+ //
+ // Create the events used by the overlapped structures for the
+ // read and write.
+ //
+
+ ReadOverlapped.hEvent = CreateEvent(
+ NULL,
+ TRUE,
+ FALSE,NULL
+ );
+
+ if (!ReadOverlapped.hEvent) {
+ return FALSE;
+ }
+
+ WriteOverlapped.hEvent = CreateEvent(
+ NULL,
+ TRUE,
+ FALSE,NULL
+ );
+
+ if (!WriteOverlapped.hEvent) {
+ return FALSE;
+ }
+
+ ReadOverlapped.Offset = 0;
+ ReadOverlapped.OffsetHigh = 0;
+
+ WriteOverlapped.Offset = 0;
+ WriteOverlapped.OffsetHigh = 0;
+
+ //
+ // Set up the Comm port....
+ //
+
+ if (!GetCommState(
+ DmKdComPort,
+ &LocalDcb
+ )) {
+
+ return FALSE;
+ }
+
+ LocalDcb.BaudRate = Baud;
+ LocalDcb.ByteSize = 8;
+ LocalDcb.Parity = NOPARITY;
+ LocalDcb.StopBits = ONESTOPBIT;
+ LocalDcb.fDtrControl = DTR_CONTROL_ENABLE;
+ LocalDcb.fRtsControl = RTS_CONTROL_ENABLE;
+ LocalDcb.fBinary = TRUE;
+ LocalDcb.fOutxCtsFlow = FALSE;
+ LocalDcb.fOutxDsrFlow = FALSE;
+ LocalDcb.fOutX = FALSE;
+ LocalDcb.fInX = FALSE;
+
+ if (!SetCommState(
+ DmKdComPort,
+ &LocalDcb
+ )) {
+
+ return FALSE;
+ }
+
+ //
+ // Set the normal read and write timeout time.
+ // The symbols are 10 millisecond intervals.
+ //
+
+ To.ReadIntervalTimeout = 0;
+ To.ReadTotalTimeoutMultiplier = 0;
+ To.ReadTotalTimeoutConstant = 4 * 1000;
+ To.WriteTotalTimeoutMultiplier = 0;
+ To.WriteTotalTimeoutConstant = 4 * 1000;
+
+ if (!SetCommTimeouts(
+ DmKdComPort,
+ &To
+ )) {
+
+ return FALSE;
+ }
+
+ DmKdComEvent = 0;
+ if (KdModemControl) {
+
+ //
+ // Debugger is being run over a modem. Set event to watch
+ // carrier detect.
+ //
+
+ GetCommMask (DmKdComPort, &mask);
+ mask = mask | EV_ERR; // | EV_RLSD;
+ if (!SetCommMask (DmKdComPort, mask)) {
+ return FALSE;
+ }
+
+ EventOverlapped.hEvent = CreateEvent(
+ NULL,
+ TRUE,
+ FALSE,NULL
+ );
+
+ if (!EventOverlapped.hEvent) {
+ return FALSE;
+ }
+
+ EventOverlapped.Offset = 0;
+ EventOverlapped.OffsetHigh = 0;
+
+ DmKdComEvent = 1; // Fake an event, so modem status will be checked
+ }
+
+ InitializeCriticalSection(&csComPort);
+ InitializeCriticalSection(&csPacket);
+
+ return TRUE;
+}
+
+BOOLEAN
+DmKdWriteComPort(
+ IN PUCHAR Buffer,
+ IN ULONG SizeOfBuffer,
+ IN PULONG BytesWritten
+ )
+/*++
+
+Routine Description:
+
+ Writes the supplied bytes to the COM port. Handles overlapped
+ IO requirements and other common com port maintanance.
+
+--*/
+{
+ BOOLEAN rc;
+ DWORD TrashErr;
+ COMSTAT TrashStat;
+
+
+ EnterCriticalSection(&csComPort);
+
+// if (DmKdComEvent) {
+// DmKdCheckComStatus ( );
+// }
+
+ rc = WriteFile(
+ DmKdComPort,
+ Buffer,
+ SizeOfBuffer,
+ BytesWritten,
+ &WriteOverlapped
+ );
+
+ if (!rc) {
+
+ if (GetLastError() == ERROR_IO_PENDING) {
+
+ rc = GetOverlappedResult(
+ DmKdComPort,
+ &WriteOverlapped,
+ BytesWritten,
+ TRUE
+ );
+
+ } else {
+
+ //
+ // Device could be locked up. Clear it just in case.
+ //
+ ClearCommError( DmKdComPort, &TrashErr, &TrashStat );
+
+ }
+ }
+
+ //
+ // this is here for digiboards
+ //
+ FlushFileBuffers( DmKdComPort );
+
+ LeaveCriticalSection(&csComPort);
+
+ return rc;
+}
+
+BOOLEAN
+DmKdReadComPort(
+ IN PUCHAR Buffer,
+ IN ULONG SizeOfBuffer,
+ IN PULONG BytesRead
+ )
+/*++
+
+Routine Description:
+
+ Reads bytes from the COM port. Handles overlapped
+ IO requirements and other common com port maintanance.
+
+--*/
+{
+ BOOLEAN rc;
+ DWORD TrashErr;
+ COMSTAT TrashStat;
+
+
+ EnterCriticalSection(&csComPort);
+
+// if (DmKdComEvent) {
+// DmKdCheckComStatus ( );
+// }
+
+ rc = ReadFile(
+ DmKdComPort,
+ Buffer,
+ SizeOfBuffer,
+ BytesRead,
+ &ReadOverlapped
+ );
+
+ if (!rc) {
+
+ if (GetLastError() == ERROR_IO_PENDING) {
+
+ rc = GetOverlappedResult(
+ DmKdComPort,
+ &ReadOverlapped,
+ BytesRead,
+ TRUE
+ );
+
+ } else {
+
+ //
+ // Device could be locked up. Clear it just in case.
+ //
+ ClearCommError( DmKdComPort, &TrashErr, &TrashStat );
+
+ }
+ }
+
+ LeaveCriticalSection(&csComPort);
+
+ return rc;
+}
+
+VOID
+DmKdCheckComStatus (
+ )
+/*++
+
+Routine Description:
+
+ Called when the com port status trigger signals a change.
+ This function handles the change in status.
+
+ Note: status is only monitored when being used over the modem.
+
+--*/
+{
+ DWORD status;
+ DWORD CommErr;
+ COMSTAT CommStat;
+#if 0
+ BOOLEAN rc;
+ ULONG br;
+ UCHAR buf[20];
+#endif
+
+ if (!DmKdComEvent) {
+ //
+ // Not triggered, just return
+ //
+
+ return ;
+ }
+ DmKdComEvent = 0;
+
+ GetCommModemStatus (DmKdComPort, &status);
+#if 0
+ if (!(status & MS_RLSD_ON)) {
+ DEBUG_PRINT ("KD: No carrier detect - in terminal mode\n");
+
+ //
+ // Send any keystrokes to the ComPort
+ //
+
+ KdPollThreadMode = OUT_TERMINAL;
+
+ //
+ // Loop and read any com input
+ //
+
+ while (!(status & 0x80)) {
+ GetCommModemStatus (DmKdComPort, &status);
+ rc = DmKdReadComPort(buf, sizeof buf, &br);
+ if (rc != TRUE || br == 0)
+ continue;
+
+ DMPrintShellMsg( "%s", buf );
+
+ }
+
+ KdPollThreadMode = OUT_NORMAL;
+ DEBUG_PRINT ("KD: Carrier detect - returning to debugger\n");
+
+ ClearCommError (
+ DmKdComPort,
+ &CommErr,
+ &CommStat
+ );
+
+ } else {
+#endif
+
+ CommErr = 0;
+ ClearCommError (
+ DmKdComPort,
+ &CommErr,
+ &CommStat
+ );
+
+ if (CommErr) {
+ DEBUG_PRINT( "Comm Error: " );
+ }
+
+ if (CommErr & CE_OVERRUN) {
+ DEBUG_PRINT (" [overrun err] ");
+ }
+
+ if (CommErr & CE_RXOVER) {
+ DEBUG_PRINT (" [overflow err] ");
+ }
+
+ if (CommErr & CE_RXPARITY) {
+ DEBUG_PRINT (" [parify err] ");
+ }
+
+ if (CommErr & CE_BREAK) {
+ DEBUG_PRINT (" [break err] ");
+ }
+
+ if (CommErr & CE_FRAME) {
+ DEBUG_PRINT (" [frame err] ");
+ }
+
+ if (CommErr & CE_TXFULL) {
+ DEBUG_PRINT (" [txfull err] ");
+ }
+
+ if (CommErr) {
+ DEBUG_PRINT( "\n" );
+ }
+#if 0
+ }
+#endif
+
+
+ //
+ // Reset trigger
+ //
+
+ WaitCommEvent (DmKdComPort, &DmKdComEvent, &EventOverlapped);
+}
diff --git a/private/windbg/newdm/common.inc b/private/windbg/newdm/common.inc
new file mode 100644
index 000000000..6e823a39b
--- /dev/null
+++ b/private/windbg/newdm/common.inc
@@ -0,0 +1,60 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ common.inc
+
+Abstract:
+
+ This is an include file for makefile.inc in each of the
+ directories which has c files that are wrappers for the
+ files in this directory. The WRAPPEDCOBJECTS macro contains
+ a list of the objects which are dependent on the files
+ in this directory.
+
+ SRCDIR must be defined in each makefile.inc, and will
+ always point to the directory that this file is in.
+
+
+Author:
+
+ Wesley Witt (wesw) 10-Aug-1993
+
+!ENDIF
+
+
+WRAPPEDCOBJECTS = \
+ obj\*\align.obj \
+ obj\*\api.obj \
+ obj\*\bp.obj \
+ obj\*\cache.obj \
+ obj\*\com.obj \
+ obj\*\dmx32.obj \
+ obj\*\event.obj \
+ obj\*\funccall.obj \
+ obj\*\packet.obj \
+ obj\*\procem.obj \
+ obj\*\support.obj \
+ obj\*\step.obj \
+ obj\*\util.obj \
+ obj\*\walk.obj \
+ obj\*\wow.obj
+
+$(WRAPPEDCOBJECTS:*=i386): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=mips): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=alpha): $(SRCDIR)\$$(@B).c
+$(WRAPPEDCOBJECTS:*=ppc): $(SRCDIR)\$$(@B).c
+
+PRECOMPDEPEND= $(SRCDIR)\dm.h \
+ $(SRCDIR)\align.h \
+ $(SRCDIR)\biavst.h \
+ $(SRCDIR)\bp.h \
+ $(SRCDIR)\dbgpnt.h \
+ $(SRCDIR)\debug.h \
+ $(SRCDIR)\funccall.h \
+ $(SRCDIR)\kd.h
+
+
+obj\*\precomp.obj obj\*\precomp.pch:
diff --git a/private/windbg/newdm/dbgpnt.h b/private/windbg/newdm/dbgpnt.h
new file mode 100644
index 000000000..e8a1b30ac
--- /dev/null
+++ b/private/windbg/newdm/dbgpnt.h
@@ -0,0 +1,164 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dbgnt.h
+
+Abstract:
+
+ This module contains prototypes and data structures that
+ are needed by the NT specific portion of DbgKd.
+
+Author:
+
+ Mark Lucovsky (markl) 25-Jul-1990
+
+Environment:
+
+Revision History:
+
+--*/
+
+#ifndef _DBGNT_
+#define _DBGNT_
+
+#ifndef OPTIONAL
+#define OPTIONAL
+#endif
+
+#define ARGUMENT_PRESENT(ArgumentPointer) (\
+ (CHAR *)(ArgumentPointer) != (CHAR *)(NULL) )
+
+typedef struct _STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PCHAR Buffer;
+} STRING;
+typedef STRING *PSTRING;
+
+#define STATUS_SUCCESS ((DWORD)0x00000000L)
+#define STATUS_UNSUCCESSFUL ((DWORD)0xC0000001L)
+#define STATUS_BUFFER_OVERFLOW ((DWORD)0x80000005L)
+#define STATUS_INVALID_PARAMETER ((DWORD)0xC000000DL)
+
+//
+// Global Data
+//
+HANDLE DbgKdpComPort;
+
+//
+// This overlapped structure will be used for all serial read
+// operations. We only need one structure since the code is
+// designed so that no more than one serial read operation is
+// outstanding at any one time.
+//
+OVERLAPPED ReadOverlapped;
+
+//
+// This overlapped structure will be used for all serial write
+// operations. We only need one structure since the code is
+// designed so that no more than one serial write operation is
+// outstanding at any one time.
+//
+OVERLAPPED WriteOverlapped;
+
+//
+// This overlapped structure will be used for all event operations.
+// We only need one structure since the code is designed so that no more
+// than one serial event operation is outstanding at any one time.
+//
+OVERLAPPED EventOverlapped;
+
+
+//
+// Global to watch changes in event status. (used for carrier detection)
+//
+DWORD DbgKdpComEvent;
+
+//
+// APIs
+//
+
+VOID
+DbgKdConnectAndInitialize(
+ IN HPRCX hprc,
+ IN PSTRING BootCommand OPTIONAL,
+ );
+
+BOOLEAN
+DbgKdpStartThreads( HPRCX hprc );
+
+VOID
+DbgKdpKbdPollThread(VOID);
+
+BOOL
+DbgKdpGetConsoleByte(
+ PVOID pBuf,
+ DWORD cbBuf,
+ LPDWORD pcbBytesRead
+ );
+
+BOOLEAN
+DbgKdpInitComPort(
+ HPRCX hprc,
+ BOOLEAN KdModemControl
+ );
+
+VOID
+DbgKdpCheckComStatus(
+ VOID
+ );
+
+BOOLEAN
+DbgKdpWriteComPort(
+ IN PUCHAR Buffer,
+ IN ULONG SizeOfBuffer,
+ IN PULONG BytesWritten
+ );
+
+BOOLEAN
+DbgKdpReadComPort(
+ IN PUCHAR Buffer,
+ IN ULONG SizeOfBuffer,
+ IN PULONG BytesRead
+ );
+
+
+#define ERROR_INTERRUPTED 95
+#define ERROR_TIMEOUT 640
+#define HLDSIG_ENABLE 0
+#define HLDSIG_DISABLE 1
+
+extern UCHAR DbgKdpPacketLeader[4];
+
+VOID
+DbgKdpWritePacket(
+ IN PVOID PacketData,
+ IN USHORT PacketDataLength,
+ IN USHORT PacketType,
+ IN PVOID MorePacketData OPTIONAL,
+ IN USHORT MorePacketDataLength OPTIONAL
+ );
+
+BOOLEAN
+DbgKdpWaitForPacket(
+ IN USHORT PacketType,
+ OUT PVOID Packet
+ );
+
+// VOID
+// DbgKdpHandlePromptString(
+// IN PDBGKD_DEBUG_IO IoMessage
+// );
+
+VOID
+DbgKdpPrint(
+ IN USHORT Processor,
+ IN PUCHAR String,
+ IN USHORT StringLength
+ );
+
+#endif // _DBGNT_
+
diff --git a/private/windbg/newdm/debug.h b/private/windbg/newdm/debug.h
new file mode 100644
index 000000000..e190a2504
--- /dev/null
+++ b/private/windbg/newdm/debug.h
@@ -0,0 +1,36 @@
+#define PPDBFromPid(x) (PDB*)x // Take these out when the kernel function
+ // is written
+#define PTDBFromTid(x) (TDB*)x
+
+#define PidFromPPDB(x) (PID)x
+
+#define TidFromPTDB(x) (TID)x
+
+
+//typedef PDB * PID;
+//typedef TDB * TID;
+
+enum {
+ DBERR_NO_ERROR = 0,
+ DBERR_PROCESS_CREATION,
+ DBERR_THREAD_CREATION,
+ DBERR_BAD_ACCESS
+} DB_ERRORS;
+
+
+enum {
+ ACCESS_READ = 0x01,
+ ACCESS_WRITE = 0x02,
+ ACCESS_EXECUTE = 0x04
+} DW_DESIRED_ACCESS;
+
+#define EVENT_UNION_SIZE sizeof(EVENT_UNION)
+
+typedef struct rq {
+ struct rq *next;
+ struct rq *prev;
+ TID thread;
+} RUNQUEUE;
+
+
+void PrintDebug(void);
diff --git a/private/windbg/newdm/dirs b/private/windbg/newdm/dirs
new file mode 100644
index 000000000..65428601e
--- /dev/null
+++ b/private/windbg/newdm/dirs
@@ -0,0 +1,20 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= user \
+ p_i386 \
+ p_mips \
+ p_alpha \
+ p_ppc
diff --git a/private/windbg/newdm/dm.h b/private/windbg/newdm/dm.h
new file mode 100644
index 000000000..8f61a2d1f
--- /dev/null
+++ b/private/windbg/newdm/dm.h
@@ -0,0 +1,1334 @@
+#define DONT_NOTIFY ((METHOD*)0)
+
+#define NO_ACTION ((ACVECTOR)0)
+
+#define INVALID (-1L)
+
+#define NO_SUBCLASS (-1L)
+
+#define DWORDLONG ULONGLONG
+
+// WaitForDebugEvent() timeout, milliseconds
+#define WAITFORDEBUG_MS (50L)
+
+// Wait for loader breakpoint timeout sec * ticks/sec
+#define LDRBP_MAXTICKS (60L * 1000L/WAITFORDEBUG_MS)
+
+#define SetFile()
+
+extern DBF *lpdbf;
+
+
+#ifndef KERNEL
+
+#include <crash.h>
+
+extern BOOL CrashDump;
+
+#endif
+
+
+#if defined(TARGET_i386)
+
+#define PC(x) ((x)->context.Eip)
+#define cPC(x) ((x)->Eip)
+#define STACK_POINTER(x) ((x)->context.Esp)
+#define FRAME_POINTER(x) ((x)->context.Ebp)
+#define PcSegOfHthdx(x) ((SEGMENT) (x->context.SegCs))
+#define SsSegOfHthdx(x) ((SEGMENT) (x->context.SegSs))
+
+#elif defined (TARGET_MIPS)
+
+#define PC(x) ((x)->context.XFir)
+#define cPC(x) ((x)->XFir)
+#define STACK_POINTER(x) ((x)->context.XIntSp)
+#define FRAME_POINTER(x) ((x)->context.XIntSp)
+#define PcSegOfHthdx(x) (0)
+#define SsSegOfHthdx(x) (0)
+
+//
+// Define stack register and zero register numbers.
+//
+
+#define RA 0x1f /* integer register 31 */
+#define SP 0x1d /* integer register 29 */
+#define ZERO 0x0 /* integer register 0 */
+
+typedef union instr {
+ ULONG instruction;
+ struct _jump_instr {
+ ULONG Target : 26;
+ ULONG Opcode : 6;
+ } jump_instr;
+ struct _trap_instr {
+ ULONG Opcode : 6;
+ ULONG Value : 10;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Special : 6;
+ } trap_instr;
+ struct _immed_instr {
+ ULONG Value : 16;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Opcode : 6;
+ } immed_instr;
+ struct _special_instr {
+ ULONG Funct : 6;
+ ULONG RE : 5;
+ ULONG RD : 5;
+ ULONG RT : 5;
+ ULONG RS : 5;
+ ULONG Opcode : 6;
+ } special_instr;
+ struct _float_instr {
+ ULONG Funct : 6;
+ ULONG FD : 5;
+ ULONG FS : 5;
+ ULONG FT : 5;
+ ULONG Format : 5;
+ ULONG Opcode : 6;
+ } float_instr;
+ struct {
+ ULONG Function : 6;
+ ULONG Unused : 10;
+ ULONG Code : 10;
+ ULONG Opcode : 6;
+ } break_instr;
+} INSTR, *PINSTR;
+
+#elif defined (TARGET_PPC)
+
+#define PC(x) ((x)->context.Iar)
+#define cPC(x) ((x)->Iar)
+#define STACK_POINTER(x) ((x)->context.Gpr1)
+#define FRAME_POINTER(x) ((x)->context.Gpr1)
+
+#define PcSegOfHthdx(x) (0)
+#define SsSegOfHthdx(x) (0)
+
+//
+// Define PPC nonvolatile register test macros. */
+//
+
+//#define IS_FLOATING_SAVED(Register) ((SAVED_FLOATING_MASK >> Register) & 1L)
+//#define IS_INTEGER_SAVED(Register) ((SAVED_INTEGER_MASK >> Register) & 1L)
+
+#include <ppcinst.h> // get all ppc opcodes and associated cruft
+
+
+//
+// Define saved register masks. */
+//
+
+//#define SAVED_FLOATING_MASK 0xffffc000 /* saved floating registers */
+//#define SAVED_INTEGER_MASK 0xffffe000 /* saved integer registers */
+
+
+
+
+#elif defined (TARGET_ALPHA)
+
+#include "alphaops.h"
+#include "ctxptrs.h"
+
+
+#define PC(x) ((x)->context.Fir)
+#define cPC(x) ((x)->Fir)
+#define STACK_POINTER(x) ((x)->context.IntSp)
+#define FRAME_POINTER(x) ((x)->context.IntSp)
+
+#define PcSegOfHthdx(x) (0)
+#define SsSegOfHthdx(x) (0)
+
+
+#else
+
+#error "Undefined processor"
+
+#endif
+
+
+//
+// Breakpoint stuff
+//
+
+#if defined(TARGET_i386)
+
+typedef BYTE BP_UNIT;
+#define BP_OPCODE 0xCC
+#define DELAYED_BRANCH_SLOT_SIZE 0
+
+#define HAS_DEBUG_REGS
+// #undef NO_TRACE_FLAG
+
+#define NUMBER_OF_DEBUG_REGISTERS 4
+#define DEBUG_REG_DATA_SIZES { 1, 2, 4 }
+#define MAX_DEBUG_REG_DATA_SIZE 4
+#define DEBUG_REG_LENGTH_MASKS { \
+ 0, \
+ 1, \
+ 2, \
+ 0Xffffffff, \
+ 4 \
+ }
+
+
+#define TF_BIT_MASK 0x00000100 /* This is the right bit map for */
+/* the 286, make sure its correct */
+/* for the 386. */
+
+#elif defined(TARGET_PPC)
+
+typedef DWORD BP_UNIT;
+#define BP_OPCODE 0x0FE00016 // twi 31,0,DEBUG_STOP_BREAKPOINT
+#define PPC_KERNEL_BREAKIN_OPCODE 0x0fe00002
+#define DELAYED_BRANCH_SLOT_SIZE 0
+
+#define HAS_DEBUG_REGS
+#define NO_TRACE_FLAG
+
+#define NUMBER_OF_DEBUG_REGISTERS 1
+#define DEBUG_REG_DATA_SIZES { 8 }
+#define MAX_DEBUG_REG_DATA_SIZE 8
+#define DEBUG_REG_LENGTH_MASKS { \
+ 0, \
+ 0xffffffff, \
+ 0xffffffff, \
+ 0xffffffff, \
+ 0xffffffff, \
+ 0xffffffff, \
+ 0xffffffff, \
+ 0xffffffff, \
+ 3 \
+ }
+
+#elif defined(TARGET_MIPS)
+
+typedef DWORD BP_UNIT;
+#define BP_OPCODE 0x0016000D
+#define DELAYED_BRANCH_SLOT_SIZE (sizeof(DWORD))
+
+// #undef HAS_DEBUG_REGS
+#define NO_TRACE_FLAG
+
+#elif defined(TARGET_ALPHA)
+
+typedef DWORD BP_UNIT;
+#define BP_OPCODE 0x80L
+#define DELAYED_BRANCH_SLOT_SIZE 0
+
+// #undef HAS_DEBUG_REGS
+#define NO_TRACE_FLAG
+
+#else
+
+#error "Unknown target CPU"
+
+#endif
+
+//
+// constant from windbgkd.h:
+//
+#define MAX_KD_BPS BREAKPOINT_TABLE_SIZE
+//
+// machine-dependent BP instruction size
+//
+#define BP_SIZE sizeof(BP_UNIT)
+
+#ifdef HAS_DEBUG_REGS
+typedef struct DEBUGREG {
+ DWORD DataAddr; // Data Address
+ DWORD DataSize; // Data Size
+ BPTP BpType; // read, write, execute, etc
+ BOOL InUse; // In use
+} DEBUGREG;
+typedef DEBUGREG *PDEBUGREG;
+
+extern DWORD DebugRegDataSizes[];
+
+#endif
+
+
+
+
+#define AddrFromHthdx(paddr, hthd) \
+ AddrInit(paddr, 0, PcSegOfHthdx(hthd), (DWORD)PC(hthd), \
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE, hthd->fAddrIsReal)
+
+
+/*
+ * These are "debug events" which are generated internally by the DM.
+ * They are either remappings of certain exceptions or events which
+ * do not correspond directly to a system-generated event or exception.
+ */
+
+enum {
+ BREAKPOINT_DEBUG_EVENT=(RIP_EVENT+1),
+ CHECK_BREAKPOINT_DEBUG_EVENT,
+ SEGMENT_LOAD_DEBUG_EVENT,
+ DESTROY_PROCESS_DEBUG_EVENT,
+ DESTROY_THREAD_DEBUG_EVENT,
+ ATTACH_DEADLOCK_DEBUG_EVENT,
+ ENTRYPOINT_DEBUG_EVENT,
+ LOAD_COMPLETE_DEBUG_EVENT,
+ INPUT_DEBUG_STRING_EVENT,
+ MAX_EVENT_CODE
+ };
+
+/*
+ * This is the set of legal return values from IsCall. The function of
+ * that routine is to analyze the instruction and determine if the
+ * debugger can simply step over it.
+ */
+
+enum {
+ INSTR_TRACE_BIT, /* Use the trace bit stepping or emulation
+ thereof */
+ INSTR_BREAKPOINT, /* This is a breakpoint instruction */
+ INSTR_CANNOT_TRACE, /* Can not trace this instruction */
+ INSTR_SOFT_INTERRUPT, /* This is an interrupt opcode */
+ INSTR_IS_CALL /* This is a call instruction */
+} INSTR_TYPES;
+
+typedef enum {
+ ps_root = 0x0001, /* This is the root process, do not send a */
+ /* dbcDeleteProc when this is continued */
+ /* after a dbcProcTerm. */
+ ps_preStart = 0x0002, /* Process is expecting loader BP */
+ ps_preEntry = 0x0004, /* Process is expecting Entry BP */
+ ps_dead = 0x0010, /* This process is dead. */
+ ps_deadThread = 0x0020, /* This process owns dead threads */
+ ps_exited = 0x0040, /* We have notified the debugger that this */
+ /* process has exited. */
+ ps_destroyed = 0x0080, /* This process has been destroyed (deleted) */
+ ps_killed = 0x0100, /* This process is being killed */
+ ps_connect = 0x0200
+} PSTATE;
+
+typedef void (*VECTOR)();
+
+typedef struct _EXCEPTION_LIST {
+ struct _EXCEPTION_LIST *next;
+ EXCEPTION_DESCRIPTION excp;
+} EXCEPTION_LIST, *LPEXCEPTION_LIST;
+
+typedef struct _DLLLOAD_ITEM {
+ BOOL fValidDll; // is this entry filled?
+ DWORD offBaseOfImage; // offset for base of Image
+ DWORD cbImage; // size of image in bytes
+
+#ifndef KERNEL
+
+ BOOL fReal;
+ BOOL fWow;
+ OFFSET offTlsIndex; // The offset of the TLS index for the DLL
+
+#else
+
+ PIMAGE_SECTION_HEADER Sections; // pointer to section headers
+ DWORD NumberOfSections; // number of section headers
+ DWORD TimeStamp; //
+ DWORD CheckSum; //
+ WORD SegCs; //
+ WORD SegDs; //
+ PIMAGE_SECTION_HEADER sec; //
+
+#endif
+
+ LPSTR szDllName; // dll name
+
+} DLLLOAD_ITEM, * PDLLLOAD_ITEM;
+
+#if defined(INTERNAL) && !defined(WIN32S)
+typedef struct _DLL_DEFER_LIST {
+ struct _DLL_DEFER_LIST * next;
+ LOAD_DLL_DEBUG_INFO LoadDll;
+} DLL_DEFER_LIST, *PDLL_DEFER_LIST;
+#endif
+
+
+typedef struct _HPRCX {
+ // linked lists
+ struct _HPRCX *next;
+ struct _HTHDX *hthdChild;
+
+ PID pid; // OS provided process ID
+ HANDLE rwHand; // OS provided Process handle
+ BOOL CloseProcessHandle; // If we have a private
+ // handle to this process, close it.
+ // Otherwise, it belongs to smss.
+ DWORD dwExitCode; // Process exit status
+
+ HPID hpid; // binding to EM object
+
+ PSTATE pstate; // DM state model
+ BOOL f16bit; // CreateProcess EXE was 16 bit
+ EXCEPTION_LIST *exceptionList; // list of exceptions to silently
+ // continue unhandled
+ int cLdrBPWait; // timeout counter while waiting for ldr BP
+ HANDLE hExitEvent; // synchronization object for
+ // process termination
+ PDLLLOAD_ITEM rgDllList; // module list
+ int cDllList; // item count for module list
+
+ HANDLE hEventCreateThread; // Sync object for thread creation
+
+#ifndef KERNEL
+ DWORD dwKernel32Base; // lpBaseOfDll for kernel32.
+
+#else
+
+ BOOL fRomImage; // rom image
+ BOOL fRelocatable; // relocatable code
+
+#endif
+
+#if defined(TARGET_i386) && !defined(WIN32S)
+ SEGMENT segCode;
+#endif
+
+#if defined(INTERNAL) && !defined(WIN32S)
+ // during process startup, dll name resolution may be
+ // deferred until the loader BP. Once the process is
+ // fully initialized, this deferral is no longer allowed.
+ BOOL fNameRequired;
+ PDLL_DEFER_LIST pDllDeferList;
+#endif
+
+} HPRCXSTRUCT, *HPRCX;
+
+#define hprcxNull ((HPRCX) 0)
+
+typedef enum {
+ //ts_preStart =0x1000, /* Before the starting point of the thread */
+ /* from this state a registers and trace */
+ /* are dealt with specially */
+ ts_running = 1, /* Execution is proceeding on the thead */
+ ts_stopped = 2, /* An event has stopped execution */
+ ts_frozen = 0x010, /* Debugger froze thread. */
+ ts_dead = 0x020, /* Thread is dead. */
+ ts_destroyed =0x040, /* Thread is destroyed (deleted) */
+ ts_first = 0x100, /* Thread is at first chance exception */
+ ts_second = 0x200, /* Thread is at second chance exception */
+ ts_rip = 0x400, /* Thread is in RIP state */
+ ts_stepping = 0x800, /* */
+ ts_funceval = 0x40000000 /* Thread is being used for function call */
+} TSTATEX;
+
+typedef struct _WTNODE {
+ struct _WTNODE *caller; // caller's wtnode
+ struct _WTNODE *callee; // current function called by this function
+ DWORD offset; // address of this function
+ DWORD sp; // SP for this frame
+ int icnt; // number of instructions executed
+ int scnt; // subordinate count
+ int lex; // lexical level of this function
+ LPSTR fname; // function name
+} WTNODE, *LPWTNODE;
+
+typedef struct _HTHDX {
+ struct _HTHDX *next;
+ struct _HTHDX *nextSibling;
+ HPRCX hprc;
+ HTID htid;
+ TID tid;
+ HANDLE rwHand;
+ LPVOID lpStartAddress;
+ CONTEXT context;
+ LPVOID atBP;
+ TSTATEX tstate;
+ BOOL fExceptionHandled;
+ DWORD stackRA;
+ DWORD stackBase;
+ int cFuncEval;
+ DWORD dwExitCode;
+ OFFSET offTeb;
+
+ BOOL fContextDirty; // has the context changed?
+ BOOL fContextStale; // does the context need to be refreshed?
+
+ BOOL fAddrIsFlat; // Is this address segmented?
+ BOOL fAddrIsReal; // Is this address in real mode?
+ BOOL fAddrOff32; // Is the offset of this addres 32 bits?
+ BOOL fDontStepOff; //
+ ADDR addrIsCall;
+ int iInstrIsCall;
+ EXCEPTION_RECORD ExceptionRecord;
+
+ BOOL fIsCallDone;
+ WTNODE wthead; // root of the call tree for a wt command
+ LPWTNODE wtcurr; // current wtnode
+ DWORD wtmode; // wt command executing?
+
+#ifdef HAS_DEBUG_REGS
+ DEBUGREG DebugRegs[NUMBER_OF_DEBUG_REGISTERS];
+#endif
+
+ struct _SUSPENDSTRUCT *pss;
+ BOOL fWowEvent; // Was the last event WOW?
+
+#ifndef KERNEL
+ CRASH_THREAD CrashThread; // State info from crashdump
+#endif
+
+} HTHDXSTRUCT, *HTHDX;
+
+typedef void (*ACVECTOR)(DEBUG_EVENT*, HTHDX, DWORD, LPVOID);
+typedef void (*DDVECTOR)(DEBUG_EVENT*, HTHDX);
+
+#define hthdxNull ((HTHDX) NULL)
+
+typedef struct _BREAKPOINT {
+ struct _BREAKPOINT *next;
+ HPRCX hprc; // The process the BP belongs to
+ HTHDX hthd; // The thread the BP belongs to
+ BPTP bpType; // OSDebug BP type
+ BPNS bpNotify; // OSDebug notify type
+
+ ADDR addr; // The address of the Breakpoint
+ BP_UNIT instr1; // The displaced instruction
+ HANDLE hWalk; // walk handle if it is a watchpoint
+
+ BYTE instances; // The # of instances that exist
+ HPID id; // Id supplied by the EM
+ BOOL isStep; // Single step flag
+ DWORD hBreakPoint; // kernel debugger breakpoint handle
+} BREAKPOINT;
+typedef BREAKPOINT *PBREAKPOINT;
+
+//
+// these are magic values used in the hthd->atBP field.
+//
+
+#define EMBEDDED_BP ((PBREAKPOINT)(-1))
+
+//
+// These are used in the id field of a BREAKPOINT.
+//
+#define ENTRY_BP ((ULONG) -2)
+#define ASYNC_STOP_BP ((ULONG) -3)
+
+extern BREAKPOINT masterBP , *bpList;
+
+typedef struct _METHOD {
+ ACVECTOR notifyFunction; /* The notification function to call */
+ void *lparam; /* The parameter to pass to it */
+ void *lparam2; /* Extra pointer in case the method */
+ /* needs to be freed afterwards */
+} METHOD;
+typedef METHOD *PMETHOD;
+
+typedef struct _EXPECTED_EVENT {
+ struct _EXPECTED_EVENT *next;
+ HPRCX hprc;
+ HTHDX hthd;
+ DWORD eventCode;
+ DWORD subClass;
+ METHOD* notifier;
+ ACVECTOR action;
+ BOOL fPersistent;
+ LPVOID lparam;
+} EXPECTED_EVENT;
+
+
+typedef VOID (*STEPPER)(HTHDX,METHOD*,BOOL, BOOL);
+
+extern DWORD dbDataSelector;
+
+typedef DWORD (*CDVECTOR)(HPRCX,HTHDX,LPDBB);
+
+typedef struct {
+ DMF dmf;
+ CDVECTOR function;
+ WORD type;
+} CMD_DESC;
+
+
+typedef struct _SUSPENDSTRUCT {
+ PBREAKPOINT pbp;
+ LPVOID atBP;
+ CONTEXT context;
+} SUSPENDSTRUCT, *PSUSPENDSTRUCT;
+
+
+enum {
+ BLOCKING,
+ NON_BLOCKING,
+ REPLY
+ };
+
+
+/*
+ * Setup for a CreateProcess to occur
+ */
+
+typedef struct _SPAWN_STRUCT {
+ BOOL fSpawn;
+ HANDLE hEventApiDone;
+
+ BOOL fReturn; // return from API
+ DWORD dwError;
+
+ char * szAppName; // args to API etc
+ char * szArgs;
+ DWORD fdwCreate;
+ BOOL fInheritHandles;
+ STARTUPINFO si;
+} SPAWN_STRUCT, *PSPAWN_STRUCT;
+
+/*
+ * Setup for a DebugActiveProcess to occur
+ */
+
+typedef struct _DEBUG_ACTIVE_STRUCT {
+ volatile BOOL fAttach; // tell DmPoll to act
+ HANDLE hEventApiDone; // signal shell that API finished
+ HANDLE hEventReady; // clear until finished loading
+
+ BOOL fReturn; // API return value
+ DWORD dwError; // GetLastError() value
+
+ DWORD dwProcessId; // pid to debug
+ HANDLE hEventGo; // signal after hitting ldr BP
+} DEBUG_ACTIVE_STRUCT, *PDEBUG_ACTIVE_STRUCT;
+
+typedef struct _WT_STRUCT {
+ BOOL fWt;
+ DWORD dwType;
+ HTHDX hthd;
+} WT_STRUCT, *LPWT_STRUCT;
+
+typedef struct _KILLSTRUCT {
+ struct _KILLSTRUCT * next;
+ HPRCX hprc;
+} KILLSTRUCT, *PKILLSTRUCT;
+
+extern void QueueContinueDebugEvent(DWORD, DWORD, DWORD);
+extern BOOL StartDmPollThread(void);
+extern BOOL StartCrashPollThread(void);
+
+void
+AddQueue(
+ DWORD dwType,
+ DWORD dwProcessId,
+ DWORD dwThreadId,
+ DWORD dwData,
+ DWORD dwLen
+ );
+
+BOOL
+DequeueAllEvents(
+ BOOL fForce,
+ BOOL fConsume
+ );
+
+VOID
+InitEventQueue(
+ VOID
+ );
+
+#define QT_CONTINUE_DEBUG_EVENT 1
+#define QT_RELOAD_MODULES 2
+#define QT_TRACE_DEBUG_EVENT 3
+#define QT_REBOOT 4
+#define QT_RESYNC 5
+#define QT_DEBUGSTRING 6
+#define QT_CRASH 7
+
+extern BOOL SearchPathSet;
+extern char SearchPathString[];
+
+//
+// Single stepping stuff
+//
+typedef struct _BRANCH_NODE {
+ BOOL TargetKnown; // Know target address
+ BOOL IsCall; // Is a call instruction
+ ADDR Addr; // Branch instruction address
+ ADDR Target; // Target address
+} BRANCH_NODE;
+
+
+typedef struct _BRANCH_LIST {
+ ADDR AddrStart; // Start of range
+ ADDR AddrEnd; // End of range
+ DWORD Count; // Count of branch nodes
+ BRANCH_NODE BranchNode[0]; // List of branch nodes
+} BRANCH_LIST;
+
+
+DWORD
+BranchUnassemble(
+ void *Memory,
+ ADDR *Addr,
+ BOOL *IsBranch,
+ BOOL *TargetKnown,
+ BOOL *IsCall,
+ BOOL *IsTable,
+ ADDR *Target
+ );
+
+
+//
+// Structure for doing range stepping
+//
+typedef struct _RANGESTRUCT {
+ HTHDX hthd; // thread
+ BOOL fStepOver; // Step over flag
+ BOOL fStopOnBP; // Stop on BP flag
+ METHOD *Method; // Method
+ DWORD BpCount; // Count of temporary breakpoints
+ ADDR *BpAddrs; // List of breakpoint addresses
+ BREAKPOINT **BpList; // List of breakpoints
+ BRANCH_LIST *BranchList; // branch list
+ BOOL fFromThunk; // Stepping from thunk
+ ADDR PrevAddr; // For single stepping
+ BOOL fSingleStep; // For single stepping
+ ADDR TmpAddr; // For single stepping
+ BOOL fInCall; // For single stepping
+ BREAKPOINT *TmpBp; // For single stepping
+} RANGESTRUCT;
+
+typedef struct _RANGESTEP {
+ HTHDX hthd; // The thread's structure
+ HPRCX hprc; // The thread's parent process
+ SEGMENT segCur; // Segment to do range stepping in
+ UOFF32 addrStart; // starting address of range step
+ UOFF32 addrEnd; // ending address of range step
+ STEPPER stepFunction; // The step function to call
+ METHOD *method; // The method to handle this event
+ BREAKPOINT *safetyBP; // Safety BP
+ BOOL fIsCall; // just traced a call instruction?
+ BOOL fIsRet; // just traced a ret instruction?
+} RANGESTEP;
+
+
+
+extern
+void
+WtMethodRangeStep(
+ DEBUG_EVENT* pde,
+ HTHDX hthd,
+ DWORD unused,
+ RANGESTEP* RangeStep
+ );
+
+extern
+void
+MethodRangeStep(
+ DEBUG_EVENT* pde,
+ HTHDX hthd,
+ DWORD unused,
+ RANGESTEP* RangeStep
+ );
+
+extern
+void
+MethodSmartRangeStep(
+ DEBUG_EVENT* pde,
+ HTHDX hthd,
+ DWORD unused,
+ RANGESTRUCT* RangeStruct
+ );
+
+
+VOID
+MakeThreadSuspendItselfHelper(
+ HTHDX hthd,
+ FARPROC lpSuspendThread
+ );
+
+
+/*
+ *
+ */
+
+#ifdef KERNEL
+extern void ProcessDebugEvent( DEBUG_EVENT *de, DBGKD_WAIT_STATE_CHANGE *sc );
+extern VOID ProcessHandleExceptionCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessIgnoreExceptionCmd(HPRCX,HTHDX,LPDBB);
+extern BOOL ProcessFrameStackWalkNextCmd( HPRCX, HTHDX, PCONTEXT, LPVOID );
+extern VOID ProcessGetExtendedContextCmd(HPRCX hprc,HTHDX hthd,LPDBB lpdbb);
+extern VOID ProcessSetExtendedContextCmd(HPRCX hprc,HTHDX hthd,LPDBB lpdbb);
+extern void DeleteAllBps( VOID );
+extern VOID DmPollTerminate( VOID );
+
+#else
+
+extern VOID ProcessBPAcceptedCmd( HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb );
+extern VOID ProcessGetDRegsCmd(HPRCX hprc, HTHDX hthd, LPDBB lpdbb);
+extern VOID ProcessSetDRegsCmd(HPRCX hprc, HTHDX hthd, LPDBB lpdbb);
+extern BOOL DoMemoryRead(HPRCX, HTHDX, LPADDR, LPVOID, DWORD, LPDWORD);
+
+
+#endif
+
+
+extern void ProcessExceptionEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessCreateThreadEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessCreateProcessEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessExitThreadEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessExitProcessEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessLoadDLLEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessUnloadDLLEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessOutputDebugStringEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessBreakpointEvent(DEBUG_EVENT*, HTHDX);
+extern void ProcessRipEvent(DEBUG_EVENT*, HTHDX);
+
+extern void ProcessSegmentLoadEvent(DEBUG_EVENT *, HTHDX);
+extern void ProcessEntryPointEvent(DEBUG_EVENT *pde, HTHDX hthdx);
+
+extern void NotifyEM(DEBUG_EVENT*, HTHDX, DWORD, LPVOID);
+extern void FreeHthdx(HTHDX hthd);
+extern XOSD FreeProcess( HPRCX hprc, BOOL fKillRoot);
+
+extern VOID ProcessCreateProcessCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessProcStatCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessThreadStatCmd(HPRCX,HTHDX,LPDBB);
+extern void ProcessLoadCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessUnloadCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ExprBPCreateThread( HPRCX, HTHDX );
+extern VOID ExprBPExitThread( HPRCX, HTHDX );
+extern VOID ExprBPContinue( HPRCX, HTHDX );
+extern VOID ExprBPRestoreDebugRegs( HTHDX );
+extern VOID ExprBPClearBPForStep(HTHDX);
+extern VOID ExprBPResetBP(HTHDX, PBREAKPOINT);
+extern VOID ProcessReadMemoryCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessWriteMemoryCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessGetContextCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessGetSectionsCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessSetContextCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessSingleStepCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessRangeStepCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessExecuteCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessContinueCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessFreezeThreadCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessTerminateThreadCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessTerminateProcessCmd(HPRCX,HTHDX,LPDBB);
+extern DWORD ProcessAsyncGoCmd(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessGetFP(HPRCX,HTHDX,LPDBB);
+extern VOID ProcessIoctlCmd( HPRCX, HTHDX, LPDBB );
+extern VOID ClearContextPointers(PKNONVOLATILE_CONTEXT_POINTERS);
+extern VOID ProcessDebugActiveCmd(HPRCX, HTHDX, LPDBB);
+extern VOID ProcessAsyncStopCmd(HPRCX, HTHDX, LPDBB );
+extern VOID ProcessAllProgFreeCmd( HPRCX hprcXX, HTHDX hthd, LPDBB lpdbb );
+extern VOID ProcessSetPathCmd( HPRCX hprcXX, HTHDX hthd, LPDBB lpdbb );
+extern VOID ProcessQueryTlsBaseCmd( HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb );
+extern VOID ProcessQuerySelectorCmd(HPRCX, HTHDX, LPDBB);
+extern VOID ProcessReloadModulesCmd(HPRCX hprcx, HTHDX hthdx, LPDBB lpdbb );
+extern VOID ProcessVirtualQueryCmd(HPRCX hprcx, LPDBB lpdbb);
+extern VOID ProcessGetDmInfoCmd(HPRCX hprc, LPDBB lpdbb, DWORD cb);
+extern VOID ProcessRemoteQuit(VOID);
+
+VOID
+ProcessGetFrameContextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ );
+
+VOID
+ProcessGetExceptionState(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ );
+
+VOID
+ProcessSetExceptionState(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ );
+
+EXCEPTION_FILTER_DEFAULT
+ExceptionAction(
+ HPRCX hprc,
+ DWORD dwExceptionCode
+ );
+
+void
+RemoveExceptionList(
+ HPRCX hprc
+ );
+
+EXCEPTION_LIST *
+InsertException(
+ EXCEPTION_LIST ** ppeList,
+ LPEXCEPTION_DESCRIPTION lpexc
+ );
+
+VOID
+ProcessBreakpointCmd(
+ HPRCX hprcx,
+ HTHDX hthdx,
+ LPDBB lpdbb
+ );
+
+void
+InitExceptionList(
+ HPRCX hprc
+ );
+
+VOID
+CompleteTerminateProcessCmd(
+ VOID
+ );
+
+
+PBREAKPOINT
+FindBpForWalk(
+ PVOID pWalk
+ );
+
+PBREAKPOINT
+GetWalkBPFromBits(
+ HTHDX hthd,
+ DWORD bits
+ );
+
+BOOL
+IsWalkInGroup(
+ HANDLE hWalk,
+ PVOID pWalk
+ );
+
+#ifdef HAS_DEBUG_REGS
+BOOL
+SetupDebugRegister( // implemented in mach.c
+ HTHDX hthd,
+ int Register,
+ int DataSize,
+ DWORD DataAddr,
+ DWORD BpType
+ );
+
+VOID
+ClearDebugRegister(
+ HTHDX hthd,
+ int Register
+ );
+#endif
+
+
+extern HTHDX HTHDXFromPIDTID(PID, TID);
+extern HTHDX HTHDXFromHPIDHTID(HPID, HTID);
+extern HPRCX HPRCFromPID(PID);
+extern HPRCX HPRCFromHPID(HPID);
+extern HPRCX HPRCFromHPRC(HANDLE);
+
+
+extern void SSActionReplaceByte(DEBUG_EVENT*, HTHDX, DWORD, PBREAKPOINT);
+extern void SSActionRemoveBP(DEBUG_EVENT*, HTHDX, DWORD, METHOD*);
+extern void ActionDefineProcess(DEBUG_EVENT*, HTHDX, DWORD, HPRCX);
+extern void ActionAllDllsLoaded(DEBUG_EVENT*, HTHDX, DWORD, HPRCX);
+extern void ActionDebugActiveReady( DEBUG_EVENT * pde, HTHDX hthd, DWORD unused, HPRCX hprc );
+extern void ActionDebugNewReady( DEBUG_EVENT * pde, HTHDX hthd, DWORD unused, HPRCX hprc );
+
+
+BOOL
+CDECL
+DMPrintShellMsg(
+ PCHAR szFormat,
+ ...
+ );
+
+extern EXPECTED_EVENT* RegisterExpectedEvent(HPRCX, HTHDX, DWORD, DWORD,
+ METHOD*, ACVECTOR, BOOL, LPVOID);
+
+extern EXPECTED_EVENT* PeeIsEventExpected(HTHDX, DWORD, DWORD);
+extern void ConsumeAllThreadEvents(HTHDX, BOOL);
+extern void ConsumeAllProcessEvents(HPRCX, BOOL);
+
+extern void IncrementIP(HTHDX);
+
+extern XOSD Load(HPRCX hprc,
+ char*, char*, LPVOID, LPVOID, DWORD, BOOL,
+ char**, char*, STARTUPINFO FAR *);
+
+extern HPRCX InitProcess(HPID);
+
+#if defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
+extern void RemoveFuncList( HPRCX hprc );
+#endif
+
+#if defined(TARGET_MIPS)
+
+typedef enum { Ctx32Bit, Ctx64Bit } MIPSCONTEXTSIZE;
+extern MIPSCONTEXTSIZE MipsContextSize;
+
+BOOL
+CoerceContext64To32(
+ PCONTEXT pContext
+ );
+
+BOOL
+CoerceContext32To64 (
+ PCONTEXT pContext
+ );
+#endif // TARGET_MIPS
+
+extern void RemoveExceptionList( HPRCX hprc );
+
+extern VOID FAR PASCAL DmFunc(HPID, LPBYTE, UINT);
+
+BOOL
+IsRet(
+ HTHDX hthd,
+ LPADDR addr
+ );
+
+void
+IsCall(
+ HTHDX,
+ LPADDR,
+ LPINT,
+ BOOL
+ );
+
+void
+DecrementIP(
+ HTHDX
+ );
+
+BOOL
+SetupSingleStep(
+ HTHDX,
+ BOOL
+ );
+
+void
+SingleStep(
+ HTHDX,
+ METHOD*,
+ BOOL,
+ BOOL
+ );
+
+void
+StepOver(
+ HTHDX,
+ METHOD*,
+ BOOL,
+ BOOL
+ );
+
+void
+RangeStep(
+ HTHDX,
+ DWORD,
+ DWORD,
+ BOOL,
+ BOOL
+ );
+
+VOID
+ReConnectDebugger(
+ DEBUG_EVENT *de,
+ BOOL fNoDllLoad
+ );
+
+BOOL
+DecodeSingleStepEvent(
+ HTHDX hthd,
+ DEBUG_EVENT *de,
+ PDWORD eventCode,
+ PDWORD subClass
+ );
+
+extern
+void
+WtRangeStep(
+ HTHDX
+ );
+
+extern
+BOOL
+SmartRangeStep(
+ HTHDX,
+ DWORD,
+ DWORD,
+ BOOL,
+ BOOL
+ );
+
+
+#if defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
+extern ULONG GetNextOffset (HTHDX, BOOL);
+#endif
+
+extern void SetupEntryBP(HTHDX hthd);
+void DestroyDllLoadItem(PDLLLOAD_ITEM pDll);
+
+
+extern void Reply( UINT length, void * lpbBuffer, HPID hpid );
+
+
+HANDLE
+SetWalk(
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD Addr,
+ DWORD Size,
+ DWORD BpType
+ );
+
+BOOL
+RemoveWalk (
+ HANDLE hWalk
+ );
+
+#ifdef HAS_DEBUG_REGS
+BOOL
+SetupDebugRegister( // implemented in mach.c
+ HTHDX hthd,
+ int Register,
+ int DataSize,
+ DWORD DataAddr,
+ DWORD BpType
+ );
+
+VOID
+ClearDebugRegister(
+ HTHDX hthd,
+ int Register
+ );
+#endif
+
+/*
+ **
+ */
+
+#if DBG
+
+#define assert(exp) if (!(exp)) {lpdbf->lpfnLBPrintf(#exp,__FILE__,__LINE__);}
+
+extern BOOL FVerbose;
+extern BOOL FUseOutputDebugString;
+extern char rgchDebug[];
+extern void DebugPrint(char *, ...);
+
+#define DPRINT(level, args) \
+ if (FVerbose >= level) { ((FUseOutputDebugString)? (DebugPrint) : (DMPrintShellMsg)) args; }
+
+#define DEBUG_PRINT(str) DPRINT(5, (str))
+#define DEBUG_PRINT_1(str, a1) DPRINT(5, (str, a1))
+#define DEBUG_PRINT_2(str, a1, a2) DPRINT(5, (str, a1, a2))
+#define DEBUG_PRINT_3(str, a1, a2, a3) DPRINT(5, (str, a1, a2, a3))
+#define DEBUG_PRINT_4(str, a1, a2, a3, a4) DPRINT(5, (str, a1, a2, a3, a4))
+#define DEBUG_PRINT_5(str, a1, a2, a3, a4, a5) DPRINT(5, (str, a1, a2, a3, a4, a5))
+#define DEBUG_LEVEL_PRINT(level, str) DPRINT(level, (str))
+
+#else
+
+#define assert(exp)
+
+#define DPRINT(level, args)
+
+#define DEBUG_PRINT(str)
+#define DEBUG_PRINT_1(str, a1)
+#define DEBUG_PRINT_2(str, a1, a2)
+#define DEBUG_PRINT_3(str, a1, a2, a3)
+#define DEBUG_PRINT_4(str, a1, a2, a3, a4)
+#define DEBUG_PRINT_5(str, a1, a2, a3, a4, a5)
+
+#define DEBUG_LEVEL_PRINT(level, str)
+#endif
+
+
+extern DMTLFUNCTYPE DmTlFunc;
+
+
+/*
+** WOW functions
+*/
+
+BOOL TranslateAddress(HPRCX, HTHDX, LPADDR, BOOL);
+BOOL IsWOWPresent(VOID);
+
+
+/*
+** Prototypes from util.c
+*/
+
+ULONG SetReadPointer(ULONG cbOffset, int iFrom);
+VOID SetPointerToFile(HANDLE hFile);
+VOID SetPointerToMemory(HPRCX hprcx, LPVOID lpv);
+BOOL DoRead(LPVOID lpv, DWORD cb);
+BOOL AreAddrsEqual(HPRCX, HTHDX, LPADDR, LPADDR);
+
+
+BOOL WOWGetThreadContext(HTHDX hthdx, LPCONTEXT lpcxt);
+BOOL WOWSetThreadContext(HTHDX hthdx, LPCONTEXT lpcxt);
+
+VOID
+DmSetFocus (
+ HPRCX phprc
+ );
+
+VOID
+GetMachineType(
+ LPPROCESSOR p
+ );
+
+
+#ifndef WIN32S
+VOID
+GetTaskList(
+ PTASK_LIST pTask,
+ DWORD dwNumTasks
+ );
+#endif
+
+
+BOOL
+AddrReadMemory(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR paddr,
+ LPVOID lpb,
+ DWORD cb,
+ LPDWORD pcbRead
+ );
+
+BOOL
+AddrWriteMemory(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR paddr,
+ LPVOID lpv,
+ DWORD cb,
+ LPDWORD pcbWritten
+ );
+
+
+BOOL
+DbgReadMemory(
+ HPRCX hprc,
+ LPVOID lpOffset,
+ LPVOID lpv,
+ DWORD cb,
+ LPDWORD pcbRead
+ );
+
+BOOL
+DbgWriteMemory(
+ HPRCX hprc,
+ LPVOID lpOffset,
+ LPVOID lpb,
+ DWORD cb,
+ LPDWORD pcbWritten
+ );
+
+BOOL
+DbgGetThreadContext(
+ HTHDX hthd,
+ LPCONTEXT lpContext
+ );
+
+BOOL
+DbgSetThreadContext(
+ IN HTHDX hthd,
+ IN LPCONTEXT lpContext
+ );
+
+#ifdef WIN32S
+/*
+** Win32s DM32s specifics
+*/
+typedef enum {
+ WIN32S_TRACE_OK,
+ WIN32S_THUNK_CALL,
+ WIN32S_THUNK_JUMP
+} WIN32S_TRACE_CHECK;
+
+extern
+WIN32S_TRACE_CHECK
+IsWin32sSystemThunk(
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD currAddr,
+ DWORD stackPtr
+ ); // i386/mach.c
+
+#endif // WIN32S
+
+
+#ifdef KERNEL
+/*
+** Kernel Debugger Specific Functions
+*/
+
+BOOL MyFindExecutable( PCHAR PathName, PCHAR OutputBuffer );
+BOOLEAN DmKdConnectAndInitialize( LPSTR lpProgName );
+VOID QueueActionEvent( HTHDX hthd, DWORD dwAction, LPVOID lpv, DWORD dwLength );
+VOID ReloadModulesWorker( ULONG ListHead, LPSTR lpModules, DWORD dwLength );
+
+BOOL
+WriteBreakPointEx(
+ IN HTHDX hthd,
+ IN ULONG BreakPointCount,
+ IN OUT PDBGKD_WRITE_BREAKPOINT BreakPoints,
+ IN ULONG ContinueStatus
+ );
+
+BOOL
+RestoreBreakPointEx(
+ IN ULONG BreakPointCount,
+ IN PDBGKD_RESTORE_BREAKPOINT BreakPointHandles
+ );
+
+
+VOID ContinueTargetSystem(DWORD ContinueStatus, PDBGKD_CONTROL_SET ControlSet);
+VOID RestoreKernelBreakpoints(HTHDX hthd, UOFF32 Offset);
+BOOL ReadControlSpace(USHORT Processor, PVOID TargetBaseAddress, PVOID UserInterfaceBuffer, ULONG TransferCount, PULONG ActualBytesRead);
+
+#if defined(HAS_DEBUG_REGS)
+BOOL GetExtendedContext(HTHDX hthd, PKSPECIAL_REGISTERS pksr);
+BOOL SetExtendedContext(HTHDX hthd, PKSPECIAL_REGISTERS pksr);
+#endif
+
+#define KERNEL_MODULE_NAME "nt"
+#define KERNEL_IMAGE_NAME "ntoskrnl.exe"
+#define KERNEL_IMAGE_NAME_MP "ntkrnlmp.exe"
+#define OSLOADER_IMAGE_NAME "osloader.exe"
+#define HAL_IMAGE_NAME "hal.dll"
+#define HAL_MODULE_NAME "HAL"
+
+
+extern BOOL ApiIsAllowed;
+
+
+typedef struct MODULEALIAS {
+ CHAR ModuleName[16];
+ CHAR Alias[16];
+ BOOL Special;
+} MODULEALIAS, *LPMODULEALIAS;
+
+#define MAX_MODULEALIAS 100
+
+LPMODULEALIAS
+FindAliasByImageName(
+ LPSTR lpImageName
+ );
+
+LPMODULEALIAS
+FindAddAliasByModule(
+ LPSTR lpImageName,
+ LPSTR lpModuleName
+ );
+
+typedef struct IMAGEINFO {
+ DWORD CheckSum;
+ DWORD TimeStamp;
+ DWORD SizeOfImage;
+ DWORD BaseOfImage;
+ DWORD NumberOfSections;
+ PIMAGE_SECTION_HEADER Sections;
+} IMAGEINFO, *LPIMAGEINFO;
+
+void ParseDmParams( LPSTR p );
+BOOL ReadImageInfo(LPSTR,LPSTR,LPSTR,LPIMAGEINFO);
+
+#endif
diff --git a/private/windbg/newdm/dmkd.rc b/private/windbg/newdm/dmkd.rc
new file mode 100644
index 000000000..c06073da1
--- /dev/null
+++ b/private/windbg/newdm/dmkd.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Kernel Debugger Debuggee Module for WinDbg"
+#define VER_INTERNALNAME_STR "dmkd.dll\0"
+#define VER_ORIGINALFILENAME_STR "dmkd.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/newdm/dmx32.c b/private/windbg/newdm/dmx32.c
new file mode 100644
index 000000000..60bff8183
--- /dev/null
+++ b/private/windbg/newdm/dmx32.c
@@ -0,0 +1,7162 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ dmx32.c
+
+Abstract:
+
+Author:
+
+ Wesley Witt (wesw) 15-Aug-1992
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+DBF *lpdbf;
+
+#undef LOCAL
+
+typedef enum {
+ Image_Unknown,
+ Image_16,
+ Image_32,
+ Image_Dump
+} IMAGETYPE;
+typedef IMAGETYPE *PIMAGETYPE;
+
+
+enum {
+ System_Invalid = -1, /* The exe can not be debugged */
+ System_Console = 1, /* The exe needs a console */
+ System_GUI = 0 /* The exe is a Windows exe */
+};
+
+static char cModuleDemarcator = '|';
+int pCharMode(char* szAppName, PIMAGETYPE Image);
+
+static char __szSrcFile[] = "dm.c";
+char rgchDebug[256];
+BOOL FVerbose = 0;
+
+
+DMTLFUNCTYPE DmTlFunc = NULL;
+
+static BOOL FDMRemote = FALSE; // set true for remote debug
+
+BOOL FUseOutputDebugString = FALSE;
+
+// NOTENOTE a-kentf does this ever get munged by the shell thread?
+// NOTENOTE if so, it needs a critical section
+EXPECTED_EVENT masterEE = {0L,0L};
+EXPECTED_EVENT *eeList = &masterEE;
+
+static HTHDXSTRUCT masterTH = {0L,0L};
+HTHDX thdList = &masterTH;
+
+static HPRCXSTRUCT masterPR = {0L,0L};
+HPRCX prcList = &masterPR;
+
+// control access to thread and process lists:
+CRITICAL_SECTION csThreadProcList;
+CRITICAL_SECTION csEventList;
+
+// control access to Walk list
+CRITICAL_SECTION csWalk;
+
+HPID hpidRoot = (HPID)INVALID; // this hpid is our hook to the native EM
+BOOL fUseRoot; // next CREATE_PROCESS will use hpidRoot
+
+DEBUG_EVENT falseSSEvent;
+DEBUG_EVENT falseBPEvent;
+METHOD EMNotifyMethod;
+
+// Don't allow debug event processing during some shell operations
+CRITICAL_SECTION csProcessDebugEvent;
+
+// Event handles for synchronizing with the shell on proc/thread creates.
+HANDLE hEventCreateProcess;
+HANDLE hEventContinue;
+
+// event handle for synchronizing connnect/reconnect with the tl
+HANDLE hEventRemoteQuit;
+
+HANDLE hEventNoDebuggee; // set when no debuggee is attached
+
+int nWaitingForLdrBreakpoint = 0;
+
+BOOL FLoading16 = FALSE;
+BOOL fDisconnected = FALSE;
+
+#ifndef KERNEL
+//
+// crash dump stuff
+//
+BOOL CrashDump;
+PCONTEXT CrashContext;
+PEXCEPTION_RECORD CrashException;
+PUSERMODE_CRASHDUMP_HEADER CrashDumpHeader;
+ULONG KiPcrBaseAddress;
+ULONG KiProcessors;
+
+HANDLE hDmPollThread = 0; // Handle for event loop thread.
+BOOL fDmPollQuit = FALSE; // tell poll thread to exit NOW
+
+SYSTEM_INFO SystemInfo;
+OSVERSIONINFO OsVersionInfo;
+
+WT_STRUCT WtStruct; // .. for wt
+
+VOID
+Cleanup(
+ VOID
+ );
+
+VOID
+CallDmPoll(
+ LPVOID lpv
+ );
+
+VOID
+CrashDumpThread(
+ LPVOID lpv
+ );
+
+#endif // !KERNEL
+
+#ifdef WIN32S
+
+BOOL fCanGetThreadContext = FALSE; // set true while in exception dbg evt
+BOOL fWaitForDebugEvent = FALSE; // semaphore to prevent reentrance of
+ // WaitForDebugEvent. Set TRUE just
+ // before doing the Wait. Set FALSE
+ // when it returns without an event, or
+ // when the event has been continued.
+BOOL fProcessingDebugEvent = FALSE; // semaphore to protect non-reentrant
+ // polling routines. Should be set
+ // TRUE when WaitForDebugEvent has
+ // returned TRUE. Should be set FALSE
+ // when ContinueDebugEvent has
+ // returned.
+DWORD tidExit; // valid only if
+ // fExitProcessDebugEvent is true.
+BOOL fExitProcessDebugEvent = FALSE; // set true when the last debug event
+ // we got was an EXIT_PROCESS_DEBUG_EVENT
+extern FARPROC Win32sBackTo32; // in mach.c
+
+BOOL DmPoll(void);
+void DmPollMessageLoop(void);
+void ProcessNextDebugEvent(void);
+BOOL IsWin32sSystemDll(UCHAR * szImageName);
+void AddWin32sSystemDllAddr(DWORD dwOffset, DWORD cbObject);
+void FreeWin32sDllList(void);
+BOOL IsWin32sSystemDllAddr(DWORD dwOffset);
+
+
+#endif // WIN32S
+
+
+#ifdef KERNEL
+extern BOOL fCrashDump;
+
+KDOPTIONS KdOptions[] = {
+ "BaudRate", KDO_BAUDRATE, KDT_DWORD, 9600,
+ "Port", KDO_PORT, KDT_DWORD, 2,
+ "Cache", KDO_CACHE, KDT_DWORD, 8192,
+ "Verbose", KDO_VERBOSE, KDT_DWORD, 0,
+ "InitialBp", KDO_INITIALBP, KDT_DWORD, 0,
+ "Defer", KDO_DEFER, KDT_DWORD, 0,
+ "UseModem", KDO_USEMODEM, KDT_DWORD, 0,
+ "LogfileAppend", KDO_LOGFILEAPPEND, KDT_DWORD, 0,
+ "GoExit", KDO_GOEXIT, KDT_DWORD, 0,
+ "SymbolPath", KDO_SYMBOLPATH, KDT_STRING, 0,
+ "LogfileName", KDO_LOGFILENAME, KDT_STRING, 0,
+ "CrashDump", KDO_CRASHDUMP, KDT_STRING, 0
+};
+
+VOID
+GetKernelSymbolAddresses(
+ VOID
+ );
+
+MODULEALIAS ModuleAlias[MAX_MODULEALIAS];
+
+#endif // KERNEL
+
+
+char nameBuffer[256];
+
+// Reply buffers to and from em
+char abEMReplyBuf[1024]; // Buffer for EM to reply to us in
+char abDMReplyBuf[1024]; // Buffer for us to reply to EM requests in
+LPDM_MSG LpDmMsg = (LPDM_MSG)abDMReplyBuf;
+
+DDVECTOR DebugDispatchTable[] = {
+ ProcessExceptionEvent,
+ ProcessCreateThreadEvent,
+ ProcessCreateProcessEvent,
+ ProcessExitThreadEvent,
+ ProcessExitProcessEvent,
+ ProcessLoadDLLEvent,
+ ProcessUnloadDLLEvent,
+ ProcessOutputDebugStringEvent,
+ ProcessRipEvent,
+ ProcessBreakpointEvent,
+ NULL,
+ ProcessSegmentLoadEvent,
+ NULL, /* DESTROY_PROCESS_DEBUG_EVENT */
+ NULL, /* DESTROY_THREAD_DEBUG_EVENT */
+ NULL, /* ATTACH_DEADLOCK_DEBUG_EVENT */
+ ProcessEntryPointEvent, /* ENTRYPOINT_DEBUG_EVENT */
+ NULL
+};
+
+/*
+ * This array contains the set of default actions to be taken for
+ * all debug events if the thread has the "In Function Evaluation"
+ * bit set.
+ */
+
+DDVECTOR RgfnFuncEventDispatch[] = {
+ EvntException,
+ NULL, /* This can never happen */
+ NULL, /* This can never happen */
+ ProcessExitThreadEvent,
+ EvntExitProcess,
+ ProcessLoadDLLEvent, /* Use normal processing */
+ ProcessUnloadDLLEvent, /* Use normal processing */
+ ProcessOutputDebugStringEvent, /* Use normal processing */
+ NULL,
+ EvntBreakpoint, /* Breakpoint processor */
+ NULL,
+ ProcessSegmentLoadEvent, /* WOW event */
+ NULL,
+ NULL,
+ NULL,
+ ProcessEntryPointEvent,
+ NULL
+};
+
+void UNREFERENCED_PARAMETERS(LPVOID lpv,...)
+{
+ lpv=NULL;
+}
+
+SPAWN_STRUCT SpawnStruct; // packet for causing CreateProcess()
+
+#ifndef WIN32S
+DEBUG_ACTIVE_STRUCT DebugActiveStruct; // ... for DebugActiveProcess()
+
+PKILLSTRUCT KillQueue;
+CRITICAL_SECTION csKillQueue;
+#endif
+
+BOOL IsExceptionIgnored(HPRCX, DWORD);
+
+char SearchPathString[ 10000 ];
+BOOL SearchPathSet;
+BOOL fUseRealName = FALSE;
+
+BOOL
+ResolveFile(
+ LPSTR lpName,
+ LPSTR lpFullName,
+ BOOL fUseRealName
+ )
+{
+ DWORD dwAttr;
+ LPSTR lpFilePart;
+ BOOL fOk;
+
+ if (fUseRealName) {
+ dwAttr = GetFileAttributes(lpName);
+ fOk = ((dwAttr != 0xffffffff)
+ && ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0));
+
+ if (fOk) {
+ strcpy(lpFullName, lpName);
+ }
+
+ } else {
+
+ fOk = SearchPath(SearchPathString,
+ lpName,
+ NULL,
+ MAX_PATH,
+ lpFullName,
+ &lpFilePart
+ );
+ if (!fOk) {
+ *lpFullName = 0;
+ }
+ }
+ return fOk;
+}
+
+
+#ifndef KERNEL
+XOSD
+Load(
+ HPRCX hprc,
+ char* szAppName,
+ char* szArg,
+ LPVOID pattrib,
+ LPVOID tattrib,
+ DWORD creationFlags,
+ BOOL inheritHandles,
+ char** environment,
+ char* currentDirectory,
+ STARTUPINFO FAR * pstartupInfo
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE if the process was successfully created and FALSE otherwise.
+
+--*/
+{
+ XOSD xosd;
+ SHORT type;
+ char ch, chTerm;
+ int fQuotedFileName;
+ int l;
+ IMAGETYPE Image;
+ LPSTR lpch;
+#ifdef WIN32S
+ PROCESS_INFORMATION pi;
+#endif
+
+ static char szFullName[MAX_PATH];
+ static char szCommandLine[8192];
+
+ Unreferenced( pattrib );
+ Unreferenced( tattrib );
+ Unreferenced( creationFlags );
+
+ assert(szArg == NULL); // in case someone think this arg is
+ // being used meaningfully
+
+ /* NOTE: Might have to do the same sort of copying for
+ * szArg, pattrib, tattrib, currentDirectory and
+ * startupInfo. Determine if this is necessary.
+ */
+
+ //
+ // global flag to help with special handling of DOS/WOW apps.
+ //
+
+ FLoading16 = FALSE;
+
+
+ //
+ // Form the command line.
+ //
+
+ //
+ // First, we extract the program name and get its full path. Then
+ // we append the arguments.
+ //
+
+ if (szAppName[0] == '"') {
+ // If the user specified a quoted name (ie: a Long File Name, perhaps?),
+ // terminate on the next quote.
+ chTerm = '"';
+ fQuotedFileName=TRUE;
+ szAppName++; // Advance past the quote.
+ } else {
+ // No Quote. Search for the first space.
+ chTerm = ' ';
+ fQuotedFileName=FALSE;
+ }
+ //
+ // Find end of the command line
+ //
+
+ for(szArg = szAppName; *szArg && *szArg!= chTerm; szArg++);
+ ch = *szArg;
+
+ //
+ // Null terminate the command line
+ //
+
+ *szArg = 0;
+
+ if ( (strlen(szAppName) > 2 && szAppName[1] == ':')
+ || szAppName[0] == '\\') {
+
+ strcpy(szCommandLine, szAppName);
+ fUseRealName = TRUE;
+
+ } else if (strchr(szAppName, '\\') || !SearchPathSet) {
+
+ strcpy(szCommandLine, ".\\" );
+ strcat(szCommandLine, szAppName );
+ fUseRealName = TRUE;
+
+ } else {
+
+ if (!*SearchPathString) {
+ strcpy(SearchPathString, ".;");
+ l = 2;
+ l += GetSystemDirectory(SearchPathString+l,
+ sizeof(SearchPathString)-l);
+ SearchPathString[l++] = ';';
+ l += GetWindowsDirectory(SearchPathString+l,
+ sizeof(SearchPathString)-l);
+ SearchPathString[l++] = ';';
+ GetEnvironmentVariable("PATH",
+ SearchPathString+l,
+ sizeof(SearchPathString)-l);
+ }
+
+ strcpy(szCommandLine, szAppName);
+ fUseRealName = FALSE;
+ }
+
+ if (fQuotedFileName) {
+ szAppName--;
+ }
+
+ //
+ // to be similar to the shell, we look for:
+ //
+ // .COM
+ // .EXE
+ // nothing
+ //
+ // since '.' is a valid filename character on many filesystems,
+ // we don't automatically assume that anything following a '.'
+ // is an "extension." If the extension is "COM" or "EXE", leave
+ // it alone; otherwise try the extensions.
+ //
+
+ lpch = strrchr(szCommandLine, '.');
+ if (lpch &&
+ ( lpch[1] == 0
+ || _stricmp(lpch, ".COM") == 0
+ || _stricmp(lpch, ".EXE") == 0)
+ ) {
+ lpch = NULL;
+ } else {
+ lpch = szCommandLine + strlen(szCommandLine);
+ }
+
+ *szFullName = 0;
+ if (lpch) {
+ strcpy(lpch, ".COM");
+ ResolveFile(szCommandLine, szFullName, fUseRealName);
+ }
+ if (!*szFullName && lpch) {
+ strcpy(lpch, ".EXE");
+ ResolveFile(szCommandLine, szFullName, fUseRealName);
+ }
+ if (!*szFullName) {
+ if (lpch) {
+ *lpch = 0;
+ }
+ ResolveFile(szCommandLine, szFullName, fUseRealName);
+ }
+
+ if (!*szFullName) {
+
+ return xosdFileNotFound;
+
+ }
+
+
+ if ((type = pCharMode(szFullName, &Image)) == INVALID) {
+
+ return xosdFileNotFound;
+
+ } else {
+
+ switch ( Image ) {
+ case Image_Unknown:
+ // treat as a com file
+ //return xosdBadFormat;
+
+ case Image_16:
+ FLoading16 = TRUE;
+#ifdef OSDEBUG4
+#if defined(TARGET_i386)
+ if ( (type == System_GUI) &&
+ !(creationFlags & CREATE_SEPARATE_WOW_VDM) &&
+ IsWOWPresent() )
+ {
+ // TODO need dbcError here
+ return xosdGeneral;
+ }
+ break;
+#else
+ // TODO all platforms will suppport this
+ return xosdGeneral;
+#endif
+
+#else
+
+#if defined(TARGET_i386)
+ if ( (type == System_GUI) &&
+ !(creationFlags & CREATE_SEPARATE_WOW_VDM) &&
+ IsWOWPresent() )
+ {
+ return xosdVDMRunning;
+ }
+ break;
+#else
+ return xosdCannotDebug;
+#endif
+
+#endif
+
+ default:
+ break;
+
+ }
+ }
+
+ creationFlags |= (type?CREATE_NEW_CONSOLE:0);
+
+ //
+ // Add rest of arguments
+ //
+ if (szArg) {
+ *szArg = ch;
+ }
+ strcpy(szCommandLine, szAppName);
+
+#ifdef WIN32S
+
+
+ /*
+ * Win32S doesn't have threads, so we can't start one here. Create
+ * the process inline instead.
+ */
+ SpawnStruct.szAppName = szFullName;
+ SpawnStruct.szArgs = szCommandLine;
+ SpawnStruct.fdwCreate = creationFlags;
+ SpawnStruct.si = *pstartupInfo;
+ SpawnStruct.fInheritHandles = inheritHandles;
+ SpawnStruct.fSpawn = TRUE;
+
+ SpawnStruct.fReturn =
+ CreateProcess(SpawnStruct.szAppName,
+ SpawnStruct.szArgs,
+ NULL,
+ NULL,
+ SpawnStruct.fInheritHandles,
+ SpawnStruct.fdwCreate,
+ NULL,
+ NULL,
+ &SpawnStruct.si,
+ &pi
+ );
+
+ DEBUG_PRINT_4("CreateProcess: hthread:%x, hprocess:%x, tid:%x, pid:%x\r\n",
+ pi.hThread, pi.hProcess, pi.dwThreadId, pi.dwProcessId);
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ if (SpawnStruct.fReturn) {
+ SpawnStruct.dwError = NO_ERROR;
+ } else {
+ SpawnStruct.dwError = GetLastError();
+ }
+
+#else
+
+ if (Image == Image_Dump) {
+ //
+ // must be a crash dump file
+ //
+ if (!StartCrashPollThread()) {
+ return xosdUnknown;
+ }
+ return xosdNone;
+ }
+
+ if (!StartDmPollThread()) {
+ return xosdUnknown;
+ }
+
+
+ ResetEvent(SpawnStruct.hEventApiDone);
+
+ SpawnStruct.szAppName = szFullName;
+ SpawnStruct.szArgs = szCommandLine;
+ SpawnStruct.fdwCreate = creationFlags;
+ SpawnStruct.si = *pstartupInfo;
+ SpawnStruct.fInheritHandles = inheritHandles;
+
+ //
+ // This is a semaphore! Set it last!
+ //
+
+ SpawnStruct.fSpawn = TRUE;
+
+ //
+ //
+
+ if (WaitForSingleObject( SpawnStruct.hEventApiDone, INFINITE ) != 0) {
+ SpawnStruct.fReturn = FALSE;
+ SpawnStruct.dwError = GetLastError();
+ }
+
+#endif // WIN32S
+
+ if (SpawnStruct.fReturn) {
+
+ xosd = xosdNone;
+
+ } else {
+
+ DPRINT(1, ("Failed.\n"));
+
+#ifdef OSDEBUG4
+ xosd = xosdGeneral;
+ // make a dbcError with SpawnStruct.dwError
+
+#else
+ switch (SpawnStruct.dwError){
+ case ERROR_FILE_NOT_FOUND:
+ xosd = xosdFileNotFound;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ xosd = xosdOutOfMemory;
+ break;
+ case ERROR_ACCESS_DENIED:
+ xosd = xosdAccessDenied;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ xosd = xosdSharingViolation;
+ break;
+ case ERROR_OPEN_FAILED:
+ xosd = xosdOpenFailed;
+ break;
+ case ERROR_BAD_FORMAT:
+ xosd = xosdBadFormat;
+ break;
+ default:
+ xosd = xosdUnknown;
+ }
+#endif
+
+ }
+
+ return xosd;
+}
+
+#endif // !KERNEL
+
+
+HPRCX
+InitProcess(
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+ HPRCX hprc;
+
+ /*
+ * Create a process structure, place it
+ * at the head of the master list.
+ */
+
+ hprc = (HPRCX)malloc(sizeof(HPRCXSTRUCT));
+ memset(hprc, 0, sizeof(*hprc));
+
+ EnterCriticalSection(&csThreadProcList);
+
+ hprc->next = prcList->next;
+ prcList->next = hprc;
+ hprc->hpid = hpid;
+ hprc->exceptionList = NULL;
+ hprc->pid = (PID)-1; // Indicates prenatal process
+ hprc->pstate = 0;
+ hprc->cLdrBPWait = 0;
+ hprc->hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hprc->hEventCreateThread = CreateEvent(NULL, TRUE, TRUE, NULL);
+ hprc->f16bit = FALSE;
+#ifndef KERNEL
+ hprc->dwKernel32Base = 0;
+#endif
+
+ InitExceptionList(hprc);
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return hprc;
+}
+
+
+void
+ActionDebugNewReady(
+ DEBUG_EVENT * pde,
+ HTHDX hthd,
+ DWORD unused,
+ HPRCX hprc
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a new child process is ready to run.
+ The process is in exactly the same state as in ActionAllDllsLoaded.
+ However, in this case the debugger is not waiting for a reply.
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+ XOSD xosd = xosdNone;
+#if defined(INTERNAL) && !defined(WIN32S)
+ LPSTR lpbPacket;
+ WORD cbPacket;
+ PDLL_DEFER_LIST pddl;
+ PDLL_DEFER_LIST pddlT;
+ DEBUG_EVENT de;
+#endif
+
+ DPRINT(5, ("Child finished loading\n"));
+
+#ifdef TARGET_i386
+ hthd->fContextDirty = FALSE; // Undo the change made in ProcessDebugEvent
+#endif
+
+ hprc->pstate &= ~ps_preStart; // Clear the loading state flag
+ hprc->pstate |= ps_preEntry; // next stage...
+ hthd->tstate |= ts_stopped; // Set that we have stopped on event
+ --nWaitingForLdrBreakpoint;
+
+#if defined(INTERNAL) && !defined(WIN32S)
+ hprc->fNameRequired = TRUE;
+
+ for (pddl = hprc->pDllDeferList; pddl; pddl = pddlT) {
+
+ pddlT = pddl->next;
+
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = pde->dwProcessId;
+ de.dwThreadId = pde->dwThreadId;
+ de.u.LoadDll = pddl->LoadDll;
+
+ if (LoadDll(&de, hthd, &cbPacket, &lpbPacket) && (cbPacket != 0)) {
+ LeaveCriticalSection(&csProcessDebugEvent);
+ NotifyEM(&de, hthd, cbPacket, lpbPacket);
+ EnterCriticalSection(&csProcessDebugEvent);
+ }
+
+ free(pddl);
+ }
+ hprc->pDllDeferList = NULL;
+#endif
+
+ /*
+ * Prepare to stop on thread entry point
+ */
+
+ SetupEntryBP(hthd);
+
+ /*
+ * leave it stopped and notify the debugger.
+ */
+#if defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
+ SetBPFlag(hthd, EMBEDDED_BP);
+#endif
+ pde->dwDebugEventCode = LOAD_COMPLETE_DEBUG_EVENT;
+
+ NotifyEM(pde, hthd, 0, 0L);
+
+ return;
+} /* ActionDebugNewReady() */
+
+
+void
+ActionDebugActiveReady(
+ DEBUG_EVENT * pde,
+ HTHDX hthd,
+ DWORD unused,
+ HPRCX hprc
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a newly attached process is ready to run.
+ This process is not the same as the previous two. It is either running
+ or at an exception, and a thread has been created by DebugActiveProcess
+ for the sole purpose of hitting a breakpoint.
+
+ If we have an event handle, it needs to be signalled before the
+ breakpoint is continued.
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+#ifndef WIN32S
+ XOSD xosd = xosdNone;
+
+ DPRINT(5, ("Active process finished loading\n"));
+
+#ifdef TARGET_i386
+ hthd->fContextDirty = FALSE; // Undo the change made in ProcessDebugEvent
+#endif // i386
+
+ hprc->pstate &= ~ps_preStart;
+ hthd->tstate |= ts_stopped; // Set that we have stopped on event
+ --nWaitingForLdrBreakpoint;
+
+ /*
+ * If this is a crashed process, tell the OS
+ * to raise the exception.
+ * Tell the EM that we are finished loading;
+ * it will say GO, and we will catch the exception
+ * soon after.
+ */
+
+ if (pde->dwProcessId == DebugActiveStruct.dwProcessId) {
+ if (DebugActiveStruct.hEventGo) {
+ SetEvent(DebugActiveStruct.hEventGo);
+ CloseHandle(DebugActiveStruct.hEventGo);
+ }
+ DebugActiveStruct.dwProcessId = 0;
+ DebugActiveStruct.hEventGo = 0;
+ SetEvent(DebugActiveStruct.hEventReady);
+
+ }
+
+#if defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
+ SetBPFlag(hthd, EMBEDDED_BP);
+#endif
+ pde->dwDebugEventCode = LOAD_COMPLETE_DEBUG_EVENT;
+
+ NotifyEM(pde, hthd, 0, 0L);
+
+#endif
+ return;
+} /* ActionDebugActiveReady() */
+
+
+void
+ActionEntryPoint16(
+ DEBUG_EVENT * pde,
+ HTHDX hthdx,
+ DWORD unused,
+ LPVOID lpv
+ )
+/*++
+
+Routine Description:
+
+ This is the registered event routine called when vdm
+ sends a DBG_TASKSTART notification.
+
+Arguments:
+
+
+Return Value:
+
+ None
+
+--*/
+{
+ hthdx->hprc->pstate &= ~ps_preEntry;
+ hthdx->tstate |= ts_stopped;
+ NotifyEM(pde, hthdx, 0, (LPVOID)ENTRY_BP);
+}
+
+
+void
+ActionEntryPoint(
+ DEBUG_EVENT * pde,
+ HTHDX hthd,
+ DWORD unused,
+ LPVOID lpv
+ )
+/*++
+
+Routine Description:
+
+ This is the registered event routine called when the base
+ exe's entry point is executed. The action we take here
+ depends on whether we are debugging a 32 bit or 16 bit exe.
+
+Arguments:
+
+ pde - Supplies debug event for breakpoint
+
+ hthd - Supplies descriptor for thread that hit BP
+
+ unused - unused
+
+ lpv - unused
+
+Return Value:
+
+ None
+
+--*/
+{
+ PBREAKPOINT pbp;
+
+ Unreferenced(lpv);
+
+ pbp = AtBP(hthd);
+ assert(pbp);
+ RemoveBP(pbp);
+
+ // the main reason we are here.
+ ExprBPRestoreDebugRegs(hthd);
+
+ // if this is a 32 bit exe, stay stopped and notify the EM
+ if (hthd->hprc->f16bit) {
+ // if this is a 16 bit exe, continue and watch for
+ // the task start event.
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ } else {
+ hthd->hprc->pstate &= ~ps_preEntry;
+ hthd->tstate |= ts_stopped;
+ pde->dwDebugEventCode = ENTRYPOINT_DEBUG_EVENT;
+ NotifyEM(pde, hthd, 0, (LPVOID)ENTRY_BP);
+ }
+}
+
+
+void
+HandleDebugActiveDeadlock(
+ HPRCX hprc
+ )
+{
+#ifndef WIN32S
+ DEBUG_EVENT de;
+ HTHDX hthd;
+
+ // This timed out waiting for the loader
+ // breakpoint. Clear the prestart state,
+ // and tell the EM we are screwed up.
+ // The shell should then stop waiting for
+ // the loader BP.
+
+ hprc->pstate &= ~ps_preStart;
+ --nWaitingForLdrBreakpoint;
+ ConsumeAllProcessEvents(hprc, TRUE);
+
+ if (hprc->pid == DebugActiveStruct.dwProcessId) {
+ if (DebugActiveStruct.hEventGo) {
+ SetEvent(DebugActiveStruct.hEventGo);
+ CloseHandle(DebugActiveStruct.hEventGo);
+ }
+ DebugActiveStruct.dwProcessId = 0;
+ DebugActiveStruct.hEventGo = 0;
+ SetEvent(DebugActiveStruct.hEventReady);
+ }
+
+ de.dwDebugEventCode = ATTACH_DEADLOCK_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ hthd = hprc->hthdChild;
+ if (hthd) {
+ de.dwThreadId = hthd->tid;
+ } else {
+ de.dwThreadId = 0;
+ }
+ NotifyEM(&de, hthd, 0, 0);
+#endif
+} /* HandleDebugActiveDeadlock() */
+
+
+BOOL
+SetupSingleStep(
+ HTHDX hthd,
+ BOOL DoContinue
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ hthd - Supplies The handle to the thread which is to
+ be single stepped
+ DoContinue - Supplies continuation flag
+
+Return Value:
+
+ TRUE if successfly started step and FALSE otherwise
+
+--*/
+{
+#if defined(NO_TRACE_FLAG)
+ PBREAKPOINT pbp;
+ ADDR addr;
+
+ /*
+ * Set a breakpoint at the next legal offset and mark the breakpoint
+ * as being for a single step.
+ */
+
+ AddrInit(&addr, 0, 0, GetNextOffset(hthd, FALSE), TRUE, TRUE, FALSE, FALSE);
+ pbp = SetBP( hthd->hprc, hthd, bptpExec, bpnsStop, &addr, (HPID) INVALID);
+ if ( pbp != NULL ) {
+ pbp->isStep = TRUE;
+ }
+
+ /*
+ * Now issue the command to execute the child
+ */
+
+ if ( DoContinue ) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ }
+
+
+#else // NO_TRACE_FLAG
+
+
+
+ assert( hthd->tstate & (ts_stopped | ts_frozen) );
+
+#if defined(TARGET_i386)
+#ifndef KERNEL
+ /*
+ * Set the single step flag in the context and then start the
+ * thread running
+ *
+ * Modify the processor flags in the child's context
+ */
+
+ hthd->context.EFlags |= TF_BIT_MASK;
+ hthd->fContextDirty = TRUE;
+#endif // KERNEL
+
+#else // i386
+
+#error "Need code for new CPU with trace bit"
+
+#endif // i386
+
+ /*
+ * Now issue the command to execute the child
+ */
+
+ if ( DoContinue ) {
+ AddQueue( QT_TRACE_DEBUG_EVENT, hthd->hprc->pid, hthd->tid, DBG_CONTINUE, 0 );
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ }
+
+#endif // NO_TRACE_FLAG
+
+ return TRUE;
+} /* SetupSingleStep() */
+
+
+void
+SetupEntryBP(
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Set a breakpoint and make a persistent expected event for the
+ entry point of the first thread in a new process.
+
+Arguments:
+
+ hthd - Supplies descriptor for thread to act on.
+
+Return Value:
+
+ None
+
+--*/
+{
+ ADDR addr;
+ BREAKPOINT * bp;
+#if defined(TARGET_PPC)
+ OFFSET real_addr_entry_pt;
+ DWORD cb;
+#endif
+
+ AddrInit(&addr,
+ 0,
+ 0,
+ (OFFSET)hthd->lpStartAddress,
+ TRUE,
+ TRUE,
+ FALSE,
+ FALSE);
+
+#if defined(TARGET_PPC)
+
+ // for PPC we have a function entry at lpStartAddress because
+ // of the darn TOC, so we need to dereference it
+ // All other BP's work out fine 'cause we use the CV info. which
+ // gets around the problem.
+
+
+ AddrReadMemory(hthd->hprc, hthd, &addr,
+ &real_addr_entry_pt,
+ sizeof(real_addr_entry_pt),&cb);
+
+ if (cb != sizeof(real_addr_entry_pt)) {
+
+ DPRINT(1,("Could not read the info located at 0x%lx -- cb = %ld",addr.addr.off,cb));
+ assert(FALSE);
+ return;
+ }
+
+ DPRINT(1,("The dereferenced address of the entry pt is 0x%lx",
+ real_addr_entry_pt));
+
+
+ AddrInit(&addr,
+ 0,
+ 0,
+ real_addr_entry_pt,
+ TRUE,
+ TRUE,
+ FALSE,
+ FALSE);
+
+#endif // PPC
+
+ bp = SetBP(hthd->hprc, hthd, bptpExec, bpnsStop, &addr, (HPID)ENTRY_BP);
+
+ // register expected event
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)bp,
+ DONT_NOTIFY,
+ ActionEntryPoint,
+ TRUE, // Persistent!
+ NULL
+ );
+} /* SetupEntryBP() */
+
+
+#ifdef KERNEL
+VOID
+RestoreKernelBreakpoints (
+ HTHDX hthd,
+ UOFF32 Offset
+ )
+/*++
+
+Routine Description:
+
+ Restores all breakpoints in our bp list that fall in the range of
+ offset -> offset+dbgkd_maxstream. This is necessary because the kd
+ stub in the target system clears all breakpoints in this range before
+ delivering an exception to the debugger.
+
+Arguments:
+
+ hthd - handle to the current thread
+
+ Offset - beginning of the range, usually the current pc
+
+Return Value:
+
+ None
+
+--*/
+{
+
+ BREAKPOINT *pbp;
+ DBGKD_WRITE_BREAKPOINT bps[MAX_KD_BPS];
+ DWORD i = 0;
+
+
+ EnterCriticalSection(&csThreadProcList);
+
+ ZeroMemory( bps, sizeof(bps) );
+
+ for (pbp=bpList->next; pbp; pbp=pbp->next) {
+
+ if (GetAddrOff(pbp->addr) >= Offset &&
+ GetAddrOff(pbp->addr) < Offset+DBGKD_MAXSTREAM) {
+ if (i < MAX_KD_BPS) {
+ bps[i++].BreakPointAddress = (LPVOID)GetAddrOff(pbp->addr);
+ }
+ }
+ }
+
+ if (i) {
+ WriteBreakPointEx( hthd, i, bps, 0 );
+
+ for (i=0,pbp=bpList->next; pbp; pbp=pbp->next) {
+
+ if (GetAddrOff(pbp->addr) == (DWORD)bps[i].BreakPointAddress) {
+ pbp->hBreakPoint = bps[i++].BreakPointHandle;
+
+ }
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+}
+#endif // KERNEL
+
+
+#ifndef KERNEL
+
+
+void
+ProcessDebugEvent(
+ DEBUG_EVENT * de
+ )
+/*++
+
+Routine Description:
+
+ This routine is called whenever a debug event notification comes from
+ the operating system.
+
+Arguments:
+
+ de - Supplies a pointer to the debug event which just occured
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ EXPECTED_EVENT * ee;
+ DWORD eventCode = de->dwDebugEventCode;
+ DWORD subClass = 0L;
+ HTHDX hthd = NULL;
+ HPRCX hprc;
+ BREAKPOINT * bp;
+ ADDR addr;
+ ADDR addr2;
+ BP_UNIT instr;
+ DWORD len;
+ BOOL fInstrIsBp;
+#if defined(i386) && !defined(WIN32S)
+ LDT_ENTRY ldtEntry;
+#endif
+
+ DPRINT(3, ("Event Code == %x\n", eventCode));
+
+#ifdef WIN32S
+ fProcessingDebugEvent = TRUE;
+ if (fExitProcessDebugEvent = (eventCode == EXIT_PROCESS_DEBUG_EVENT)) {
+ tidExit = de->dwThreadId; // save for later use
+ }
+#endif
+
+ hprc = HPRCFromPID(de->dwProcessId);
+
+ /*
+ * While killing process, ignore everything
+ * except for exit events.
+ */
+
+ if (hprc) {
+ hprc->cLdrBPWait = 0;
+ }
+
+ if ( hprc && (hprc->pstate & ps_killed) ) {
+ if (eventCode == EXCEPTION_DEBUG_EVENT) {
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ (DWORD)DBG_EXCEPTION_NOT_HANDLED,
+ 0);
+ return;
+
+ } else if (eventCode != EXIT_THREAD_DEBUG_EVENT
+ && eventCode != EXIT_PROCESS_DEBUG_EVENT ) {
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ (DWORD)DBG_EXCEPTION_NOT_HANDLED,
+ 0);
+ return;
+ }
+ }
+
+ EnterCriticalSection(&csProcessDebugEvent);
+
+ if (eventCode == CREATE_THREAD_DEBUG_EVENT){
+
+ DPRINT(3, ("*** NEW TID = (PID,TID)(%08lx, %08lx)\n",
+ de->dwProcessId, de->dwThreadId));
+
+ } else {
+
+ /*
+ * Find our structure for this event's process
+ */
+
+ DEBUG_PRINT("Not Create Thread Debug Event\r\n");
+ hthd = HTHDXFromPIDTID((PID)de->dwProcessId,(TID)de->dwThreadId);
+
+ /*
+ * Update our context structure for this thread if we found one
+ * in our list. If we did not find a thread and this is
+ * not a create process debug event then return without
+ * processing the event as we are in big trouble.
+ */
+
+ if (hthd) {
+ if (eventCode == EXCEPTION_DEBUG_EVENT) {
+ hthd->ExceptionRecord = de->u.Exception.ExceptionRecord;
+ }
+#ifdef WIN32S
+ DPRINT(1, ("Processing debug event for Thread handle:0x%x\r\n",
+ hthd->rwHand));
+
+ // Can't do GetThreadContext outside an exception in win32s
+ switch (eventCode) {
+ case EXIT_PROCESS_DEBUG_EVENT:
+ // close the process and thread handles
+ CloseHandle(hthd->hprc->rwHand);
+ CloseHandle(hthd->rwHand);
+ // fall through.
+
+ case CREATE_THREAD_DEBUG_EVENT:
+ case EXIT_THREAD_DEBUG_EVENT:
+ case UNLOAD_DLL_DEBUG_EVENT:
+ case OUTPUT_DEBUG_STRING_EVENT:
+ fCanGetThreadContext = FALSE;
+ DEBUG_PRINT("WARNING: Can't get ThreadContext at this debug event.\r\n");
+ break;
+
+
+ case CREATE_PROCESS_DEBUG_EVENT:
+ case LOAD_DLL_DEBUG_EVENT:
+ fCanGetThreadContext = FALSE;
+ // Fake up the context segment registers with the values
+ // for WindbgRm (Win32s has a single address space and
+ // doesn't allow GetThreadContext at these events. The
+ // shell requires this information, though, so we should
+ // fill it in to the best of our knowledge now.
+
+ hthd->context.Eax = // zero out all regs except segs
+ hthd->context.Ebx =
+ hthd->context.Ecx =
+ hthd->context.Edx =
+ hthd->context.Eip =
+ hthd->context.Esp =
+ hthd->context.EFlags =
+ hthd->context.Ebp = 0;
+ {
+ WORD Selector;
+
+ _asm { // Win32S ONLY!
+ mov ax, ds
+ mov Selector, ax
+ }
+ hthd->context.SegEs =
+ hthd->context.SegDs =
+ hthd->context.SegSs = Selector;
+
+ _asm {
+ mov ax, cs
+ mov Selector, ax
+ }
+ hthd->context.SegCs = Selector;
+ }
+ hthd->fContextDirty = FALSE;
+ DEBUG_PRINT_4(
+ "Kludge: Faking a ThreadContext: es:0x%x, ds:0x%x, ss:0x%x, cs:0x%x\r\n",
+ hthd->context.SegEs, hthd->context.SegDs,
+ hthd->context.SegSs, hthd->context.SegCs);
+ break;
+
+ case EXCEPTION_DEBUG_EVENT:
+ hthd->context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+ DEBUG_PRINT_2("Calling GetThreadContext(0x%x, 0x%x)\r\n",
+ hthd->rwHand, &hthd->context);
+
+ DbgGetThreadContext(hthd, &hthd->context);
+ DEBUG_PRINT("Context:\r\n");
+ DEBUG_PRINT_4(">>ES:0x%04x, DS:0x%04x, SS:0x%04x, CS:0x%04x\r\n",
+ hthd->context.SegEs,
+ hthd->context.SegDs,
+ hthd->context.SegSs,
+ hthd->context.SegCs);
+
+ DEBUG_PRINT_3(">>EIP:0x%08x, ESP:0x%08x, EBP:0x%08x\r\n",
+ hthd->context.Eip,
+ hthd->context.Esp,
+ hthd->context.Ebp);
+
+ DEBUG_PRINT_4(">>EAX:0x%08x, EBX:0x%08x, ECX:0x%08x, EDX:0x%08x\r\n",
+ hthd->context.Eax,
+ hthd->context.Ebx,
+ hthd->context.Ecx,
+ hthd->context.Edx);
+
+ // WARNWARN: WIN32S bug #130.
+ // Make sure that if we just did a single-step, we
+ // don't still have the trace flag set. This
+ // is due to a bug in Win32s that leaves the flag set
+ // after a traced instruction.
+ if (hthd->context.EFlags & TF_BIT_MASK) {
+ // clear trace flag in the child's context
+ hthd->context.EFlags &= ~(TF_BIT_MASK);
+ SetThreadContext(hthd->rwHand, &hthd->context);
+ }
+ fCanGetThreadContext = TRUE;
+ hthd->fContextDirty = FALSE;
+ hthd->fIsCallDone = FALSE;
+ break;
+
+ default:
+ DEBUG_PRINT_1("Whoa! ProcessDebugEvent: unknown event type:%u\r\n",
+ eventCode);
+ }
+
+ hthd->fAddrIsReal = FALSE;
+ hthd->fAddrIsFlat = hthd->fAddrOff32 = TRUE;
+#else // WIN32s
+ hthd->context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+ DbgGetThreadContext( hthd, &hthd->context );
+ hthd->fContextDirty = FALSE;
+ hthd->fIsCallDone = FALSE;
+#if !defined( i386 )
+ hthd->fAddrIsReal = FALSE;
+ hthd->fAddrIsFlat = hthd->fAddrOff32 = TRUE;
+#else // !i386
+ if (hthd->context.EFlags & V86FLAGS_V86) {
+ hthd->fAddrIsReal = TRUE;
+ hthd->fAddrIsFlat = FALSE;
+ hthd->fAddrOff32 = FALSE;
+ } else {
+ hthd->fAddrIsReal = FALSE;
+ if (PcSegOfHthdx(hthd) != hthd->hprc->segCode) {
+ hthd->fAddrIsFlat = FALSE;
+ if (GetThreadSelectorEntry(hthd->rwHand,
+ PcSegOfHthdx(hthd),
+ &ldtEntry)) {
+ if (!ldtEntry.HighWord.Bits.Default_Big) {
+ hthd->fAddrOff32 = FALSE;
+ } else {
+ hthd->fAddrOff32 = TRUE;
+ }
+ } else {
+ hthd->fAddrOff32 = FALSE;
+ }
+ } else {
+ hthd->fAddrIsFlat = hthd->fAddrOff32 = TRUE;
+ }
+ }
+#endif // !i386
+#endif // WIN32s
+
+ } else if (hprc && (hprc->pstate & ps_killed)) {
+
+ /*
+ * this is an event for a thread that
+ * we never created:
+ */
+ if (eventCode == EXIT_PROCESS_DEBUG_EVENT) {
+ /* Process exited on a thread we didn't pick up */
+ ProcessExitProcessEvent(de, NULL);
+ } else {
+ /* this is an exit thread for a thread we never picked up */
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ DBG_CONTINUE,
+ 0);
+ }
+ goto done;
+
+ } else if (eventCode!=CREATE_PROCESS_DEBUG_EVENT) {
+
+ //
+ // This will happen sometimes when killing a process with
+ // ProcessTerminateProcessCmd and ProcessUnloadCmd.
+ //
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ DBG_CONTINUE,
+ 0);
+ goto done;
+
+ }
+ }
+
+ /*
+ * Mark the thread as having been stopped for some event.
+ */
+
+ if (hthd) {
+ hthd->tstate &= ~ts_running;
+ hthd->tstate |= ts_stopped;
+ }
+
+ /* If it is an exception event get the subclass */
+
+ if (eventCode==EXCEPTION_DEBUG_EVENT){
+
+ subClass = de->u.Exception.ExceptionRecord.ExceptionCode;
+ DPRINT(1, ("Exception Event: subclass = %x ", subClass));
+
+ switch (subClass) {
+ case (DWORD)STATUS_SEGMENT_NOTIFICATION:
+ eventCode = de->dwDebugEventCode = SEGMENT_LOAD_DEBUG_EVENT;
+ break;
+
+ case (DWORD)EXCEPTION_BREAKPOINT:
+
+ /*
+ * Check if it is a BREAKPOINT exception:
+ * If it is, change the debug event to our pseudo-event,
+ * BREAKPOINT_DEBUG_EVENT (this is a pseudo-event because
+ * the API does not define such an event, and we are
+ * synthesizing not only the class of event but the
+ * subclass as well -- the subclass is set to the appropriate
+ * breakpoint structure)
+ */
+
+ AddrFromHthdx(&addr, hthd);
+#if defined(TARGET_i386)
+ /*
+ * correct for machine overrun on a breakpoint
+ */
+
+ addr.addr.off -= 1;
+#endif
+
+ /*
+ * Determine the start of the breakpoint instruction
+ */
+
+ if ((AddrReadMemory(hprc, hthd, &addr, &instr, BP_SIZE, &len) == 0)
+ || (len != BP_SIZE)) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ assert(FALSE);
+ instr = 0;
+ }
+#if defined(TARGET_ALPHA)
+
+ switch (instr) {
+ case CALLPAL_OP | CALLKD_FUNC:
+ case CALLPAL_OP | BPT_FUNC:
+ case CALLPAL_OP | KBPT_FUNC:
+ fInstrIsBp = TRUE;
+ break;
+ default:
+ fInstrIsBp = FALSE;
+ }
+ DPRINT(3, ("Looking for BP@%lx\n", addr.addr.off));
+
+#elif defined(TARGET_i386)
+
+ /*
+ * It may have been a 0xcd 0x03 rather than a 0xcc
+ * (ie: check if it is a 1 or a 2 byte INT 3)
+ */
+
+ fInstrIsBp = FALSE;
+ if (instr == BP_OPCODE) {
+ fInstrIsBp = TRUE;
+ } else if (instr == 0x3) { // 0xcd?
+ --addr2.addr.off;
+ if (AddrReadMemory(hprc,
+ hthd,
+ &addr2,
+ &instr,
+ 1,
+ &len)
+ && (len == 1)
+ && (instr == 0xcd)) {
+
+ --addr.addr.off;
+ fInstrIsBp = TRUE;
+ }
+ }
+
+ PC(hthd) = (LONG)addr.addr.off;
+ hthd->fContextDirty = TRUE;
+
+ DPRINT(3, ("Looking for BP@%lx (instr=%x)\n", addr.addr.off,
+ instr));
+
+#elif defined(TARGET_PPC)
+
+ if ((instr == BP_OPCODE) || (instr == 0))
+ fInstrIsBp = TRUE;
+
+#elif defined(TARGET_MIPS)
+
+ fInstrIsBp = (instr == BP_OPCODE);
+ DPRINT(3, ("Looking for BP@%lx\n", addr.addr.off));
+
+#else
+#pragma error( "unknown processor type" )
+#endif
+
+ /*
+ * Lookup the breakpoint in our (the dm) table
+ */
+
+ bp = FindBP(hthd->hprc, hthd, bptpExec, (BPNS)-1, &addr, FALSE);
+ SetBPFlag(hthd, bp?bp:EMBEDDED_BP);
+
+
+ if (!bp && !fInstrIsBp) {
+#if 0
+ //
+ // It is possible that this is an instruction followed by
+ // a delay slot, and the breakpoint is not really in the
+ // current address but in the delay slot. So we have to
+ // disassemble the current instruction, figure out if it
+ // has a delay slot, and look for a breakpoint there!
+ //
+ bp = FindBPInDelaySlot( hthd, &fInstrIsBp );
+
+ if ( !bp && !fInstrIsBp ) {
+
+ DPRINT(1, ("Continuing false BP.\n"));
+
+ AddQueue(QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ goto done;
+ }
+
+#else // MIPS
+ //
+ // If the instruction is not a bp, and there is no record of
+ // the bp, this happened because the exception was already
+ // in the queue when we cleared the bp.
+ //
+ // We will just continue it.
+ //
+ DPRINT(1, ("Continuing false BP.\n"));
+ AddQueue(QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ goto done;
+#endif // MIPS
+ }
+
+
+ /*
+ * What does it mean if we find the bp record, but the
+ * instruction is not a bp???
+ */
+
+ //assert(!bp || fInstrIsBp);
+
+ /*
+ * Reassign the event code to our pseudo-event code
+ */
+ DPRINT(3, ("Reassigning event code!\n"));
+
+ /*
+ * For some machines there is not single instruction tracing
+ * on the chip. In this case we need to do it in software.
+ *
+ * Check to see if the breakpoint we just hit was there for
+ * doing single step emulation. If so then remap it to
+ * a single step exception.
+ */
+
+ if (bp && bp->isStep){
+ de->u.Exception.ExceptionRecord.ExceptionCode
+ = subClass = (DWORD)EXCEPTION_SINGLE_STEP;
+ RemoveBP(bp);
+ break;
+ }
+
+ /*
+ * Reassign the subclass to point to the correct
+ * breakpoint structure
+ *
+ */
+
+ de->dwDebugEventCode = eventCode = BREAKPOINT_DEBUG_EVENT;
+ de->u.Exception.ExceptionRecord.ExceptionAddress =
+ (PVOID) addr.addr.off;
+ de->u.Exception.ExceptionRecord.ExceptionCode =
+ subClass = (DWORD)bp;
+
+ break;
+ }
+ }
+
+ /*
+ * Check if this debug event was expected
+ */
+
+ ee = PeeIsEventExpected(hthd, eventCode, subClass);
+
+
+ /*
+ * If it wasn't, clear all consummable events
+ * and then run the standard handler with
+ * notifications going to the execution model
+ */
+
+ assert((0 < eventCode) && (eventCode < MAX_EVENT_CODE));
+
+ if (!ee) {
+
+ if ((hthd != NULL) && (hthd->tstate & ts_funceval)) {
+ assert(RgfnFuncEventDispatch[eventCode-EXCEPTION_DEBUG_EVENT]);
+ RgfnFuncEventDispatch[eventCode-EXCEPTION_DEBUG_EVENT](de, hthd);
+ } else {
+ assert(DebugDispatchTable[eventCode-EXCEPTION_DEBUG_EVENT]);
+ DebugDispatchTable[eventCode-EXCEPTION_DEBUG_EVENT](de,hthd);
+ }
+
+ } else {
+
+ /*
+ * If it was expected then call the action
+ * function if one was specified
+ */
+
+ if (ee->action) {
+ (ee->action)(de, hthd, 0, ee->lparam);
+ }
+
+ /*
+ * And call the notifier if one was specified
+ */
+
+ if (ee->notifier) {
+ METHOD *nm = ee->notifier;
+ (nm->notifyFunction)(de, hthd, 0, nm->lparam);
+ }
+
+ free(ee);
+ }
+
+done:
+
+ LeaveCriticalSection(&csProcessDebugEvent);
+ return;
+} /* ProcessDebugEvent() */
+
+
+
+#else // KERNEL
+
+
+
+
+void
+ProcessDebugEvent(
+ DEBUG_EVENT *de,
+ DBGKD_WAIT_STATE_CHANGE *sc
+ )
+/*++
+
+Routine Description:
+
+ This routine is called whenever a debug event notification comes from
+ the operating system.
+
+Arguments:
+
+ de - Supplies a pointer to the debug event which just occured
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ EXPECTED_EVENT * ee;
+ DWORD eventCode = de->dwDebugEventCode;
+ DWORD subClass = 0L;
+ HTHDX hthd = NULL;
+ HPRCX hprc;
+ PBREAKPOINT bp;
+ ADDR addr;
+ DWORD cb;
+ BP_UNIT instr;
+ BOOL fInstrIsBp = FALSE;
+
+
+ DPRINT(3, ("Event Code == %x\n", eventCode));
+
+ hprc = HPRCFromPID(de->dwProcessId);
+
+ /*
+ * While killing process, ignore everything
+ * except for exit events.
+ */
+
+ if (hprc) {
+ hprc->cLdrBPWait = 0;
+ }
+
+ if ( hprc && (hprc->pstate & ps_killed) ) {
+ if (eventCode == EXCEPTION_DEBUG_EVENT) {
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ (DWORD)DBG_EXCEPTION_NOT_HANDLED,
+ 0);
+ return;
+
+ } else if (eventCode != EXIT_THREAD_DEBUG_EVENT
+ && eventCode != EXIT_PROCESS_DEBUG_EVENT ) {
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ (DWORD)DBG_EXCEPTION_NOT_HANDLED,
+ 0);
+ return;
+ }
+ }
+
+ EnterCriticalSection(&csProcessDebugEvent);
+
+ if (eventCode == CREATE_THREAD_DEBUG_EVENT){
+
+ DPRINT(3, ("*** NEW TID = (PID,TID)(%08lx, %08lx)\n",
+ de->dwProcessId, de->dwThreadId));
+
+ } else {
+
+ /*
+ * Find our structure for this event's process
+ */
+
+ hthd = HTHDXFromPIDTID((PID)de->dwProcessId,(TID)de->dwThreadId);
+
+ /*
+ * Update our context structure for this thread if we found one
+ * in our list. If we did not find a thread and this is
+ * not a create process debug event then return without
+ * processing the event as we are in big trouble.
+ */
+
+ if (hthd) {
+ if (eventCode == EXCEPTION_DEBUG_EVENT) {
+ hthd->ExceptionRecord = de->u.Exception.ExceptionRecord;
+ }
+ hthd->context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+ DbgGetThreadContext(hthd,&hthd->context);
+ hthd->fContextDirty = FALSE;
+ hthd->fIsCallDone = FALSE;
+ hthd->fAddrIsReal = FALSE;
+ hthd->fAddrIsFlat = TRUE;
+ hthd->fAddrOff32 = TRUE;
+ } else
+ if (hprc && (hprc->pstate & ps_killed)) {
+
+ /*
+ * this is an event for a thread that
+ * we never created:
+ */
+ if (eventCode == EXIT_PROCESS_DEBUG_EVENT) {
+ /* Process exited on a thread we didn't pick up */
+ ProcessExitProcessEvent(de, NULL);
+ } else {
+ /* this is an exit thread for a thread we never picked up */
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ DBG_CONTINUE,
+ 0);
+ }
+ goto done;
+
+ } else if (eventCode!=CREATE_PROCESS_DEBUG_EVENT) {
+
+ assert(FALSE);
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ de->dwProcessId,
+ de->dwThreadId,
+ DBG_CONTINUE,
+ 0);
+ goto done;
+
+ }
+ }
+
+ /*
+ * Mark the thread as having been stopped for some event.
+ */
+
+ if (hthd) {
+ hthd->tstate &= ~ts_running;
+ hthd->tstate |= ts_stopped;
+ }
+
+ /* If it is an exception event get the subclass */
+
+ if (eventCode==EXCEPTION_DEBUG_EVENT){
+
+ subClass = de->u.Exception.ExceptionRecord.ExceptionCode;
+ DPRINT(1, ("Exception Event: subclass = %x ", subClass));
+
+ switch (subClass) {
+ case (DWORD)STATUS_SEGMENT_NOTIFICATION:
+ eventCode = de->dwDebugEventCode = SEGMENT_LOAD_DEBUG_EVENT;
+ break;
+
+ case (DWORD)EXCEPTION_SINGLE_STEP:
+#if !defined(TARGET_i386)
+ assert("!EXCEPTION_SINGLE_STEP on non-x86!");
+#endif
+ AddrFromHthdx(&addr, hthd);
+ RestoreKernelBreakpoints( hthd, GetAddrOff(addr) );
+
+ //
+ // This may be a single step or a hardware breakpoint.
+ // If it is a single step, leave it at that. If it is
+ // a hardware breakpoint, convert it to a BREAKPOINT_DEBUG_EVENT.
+ //
+
+ DecodeSingleStepEvent( hthd, de, &eventCode, &subClass );
+ break;
+
+ case (DWORD)EXCEPTION_BREAKPOINT:
+
+ /*
+ * Check if it is a BREAKPOINT exception:
+ * If it is, change the debug event to our pseudo-event,
+ * BREAKPOINT_DEBUG_EVENT (this is a pseudo-event because
+ * the API does not define such an event, and we are
+ * synthesizing not only the class of event but the
+ * subclass as well -- the subclass is set to the appropriate
+ * breakpoint structure)
+ */
+
+ hthd->fDontStepOff = FALSE;
+
+ AddrFromHthdx(&addr, hthd);
+
+ /*
+ * Lookup the breakpoint in our (the dm) table
+ */
+
+ bp = FindBP(hthd->hprc, hthd, bptpExec, (BPNS)-1, &addr, FALSE);
+ SetBPFlag(hthd, bp?bp:EMBEDDED_BP);
+
+ /*
+ * Reassign the event code to our pseudo-event code
+ */
+ DPRINT(3, ("Reassigning event code!\n"));
+
+ /*
+ * For some machines there is not single instruction tracing
+ * on the chip. In this case we need to do it in software.
+ *
+ * Check to see if the breakpoint we just hit was there for
+ * doing single step emulation. If so then remap it to
+ * a single step exception.
+ */
+
+ if (bp) {
+ if (bp->isStep){
+ de->u.Exception.ExceptionRecord.ExceptionCode
+ = subClass = (DWORD)EXCEPTION_SINGLE_STEP;
+ RemoveBP(bp);
+ RestoreKernelBreakpoints( hthd, GetAddrOff(addr) );
+ break;
+ } else {
+ RestoreKernelBreakpoints( hthd, GetAddrOff(addr) );
+ }
+ }
+
+ //
+ // Determine the start of the breakpoint instruction
+ //
+
+ if (fCrashDump) {
+ cb = DmpReadMemory((LPVOID)GetAddrOff(addr),&instr,BP_SIZE);
+ if (cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ } else {
+ if (DmKdReadVirtualMemoryNow((LPVOID)GetAddrOff(addr),&instr,BP_SIZE,&cb) || cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ }
+
+#if defined(TARGET_ALPHA)
+
+ switch (instr) {
+ case 0:
+ case CALLPAL_OP | CALLKD_FUNC:
+ case CALLPAL_OP | BPT_FUNC:
+ case CALLPAL_OP | KBPT_FUNC:
+ fInstrIsBp = TRUE;
+ break;
+ default:
+ addr.addr.off -= BP_SIZE;
+ if (fCrashDump) {
+ cb = DmpReadMemory((LPVOID)GetAddrOff(addr),&instr,BP_SIZE);
+ if (cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ } else {
+ if (DmKdReadVirtualMemoryNow((LPVOID)GetAddrOff(addr),&instr,BP_SIZE,&cb) || cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ }
+ switch (instr) {
+ case 0:
+ case CALLPAL_OP | CALLKD_FUNC:
+ case CALLPAL_OP | BPT_FUNC:
+ case CALLPAL_OP | KBPT_FUNC:
+ fInstrIsBp = TRUE;
+ hthd->fDontStepOff = TRUE;
+ break;
+ default:
+ fInstrIsBp = FALSE;
+ }
+ }
+
+#elif defined(TARGET_PPC)
+ if ((instr == BP_OPCODE) || (instr == 0))
+ fInstrIsBp = TRUE;
+
+ if ((!fInstrIsBp) && (LPVOID) GetAddrOff(addr)) {
+ addr.addr.off -= BP_SIZE;
+ if (fCrashDump) {
+ cb = DmpReadMemory((LPVOID)GetAddrOff(addr),&instr,BP_SIZE);
+ if (cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ } else {
+ if (DmKdReadVirtualMemoryNow((LPVOID)GetAddrOff(addr),&instr,BP_SIZE,&cb) || cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ }
+
+ if (instr == PPC_KERNEL_BREAKIN_OPCODE)
+ {
+ fInstrIsBp = TRUE;
+ hthd->fDontStepOff = TRUE;
+
+ }
+}
+
+#elif defined(TARGET_i386)
+
+ /*
+ * It may have been a 0xcd 0x03 rather than a 0xcc
+ * (ie: check if it is a 1 or a 2 byte INT 3)
+ */
+
+ fInstrIsBp = FALSE;
+ if (instr == BP_OPCODE || instr == 0) {
+ fInstrIsBp = TRUE;
+ } else
+ if (instr == 0x3) { // 0xcd?
+ --addr.addr.off;
+ if (fCrashDump) {
+ cb = DmpReadMemory((LPVOID)GetAddrOff(addr),&instr,BP_SIZE);
+ if (cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ } else {
+ if (DmKdReadVirtualMemoryNow((LPVOID)GetAddrOff(addr),&instr,BP_SIZE,&cb) || cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ }
+ if (cb == 1 && instr == 0xcd) {
+ --addr.addr.off;
+ fInstrIsBp = TRUE;
+ }
+ } else {
+ hthd->fDontStepOff = TRUE;
+ }
+
+#elif defined(TARGET_MIPS)
+
+ {
+ PINSTR bi = (PINSTR)&instr;
+ if ((bi->break_instr.Opcode == SPEC_OP &&
+ bi->break_instr.Function == BREAK_OP) || (instr == 0)) {
+
+ fInstrIsBp = TRUE;
+
+ }
+
+ if (!fInstrIsBp) {
+ addr.addr.off -= BP_SIZE;
+ if (fCrashDump) {
+ cb = DmpReadMemory((LPVOID)GetAddrOff(addr),&instr,BP_SIZE);
+ if (cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ } else {
+ if (DmKdReadVirtualMemoryNow((LPVOID)GetAddrOff(addr),&instr,BP_SIZE,&cb) || cb != BP_SIZE) {
+ DPRINT(1, ("Memory read failed!!!\n"));
+ instr = 0;
+ }
+ }
+ if (bi->break_instr.Opcode == SPEC_OP &&
+ bi->break_instr.Function == BREAK_OP &&
+ bi->break_instr.Code == BREAKIN_BREAKPOINT) {
+
+ fInstrIsBp = TRUE;
+ hthd->fDontStepOff = TRUE;
+
+ }
+ }
+ }
+
+#else
+
+#pragma error( "undefined processor type" );
+
+#endif
+
+ if (!bp && !fInstrIsBp) {
+ DMPrintShellMsg( "Stopped at an unexpected exception: code=%08x addr=%08x\n",
+ de->u.Exception.ExceptionRecord.ExceptionCode,
+ de->u.Exception.ExceptionRecord.ExceptionAddress
+ );
+ }
+
+ /*
+ * Reassign the subclass to point to the correct
+ * breakpoint structure
+ *
+ */
+
+ de->dwDebugEventCode = eventCode = BREAKPOINT_DEBUG_EVENT;
+ de->u.Exception.ExceptionRecord.ExceptionAddress =
+ (PVOID) addr.addr.off;
+ de->u.Exception.ExceptionRecord.ExceptionCode =
+ subClass = (DWORD)bp;
+
+ break;
+ }
+ }
+
+ /*
+ * Check if this debug event was expected
+ */
+
+ ee = PeeIsEventExpected(hthd, eventCode, subClass);
+
+
+ /*
+ * If it wasn't, clear all consummable events
+ * and then run the standard handler with
+ * notifications going to the execution model
+ */
+
+ assert((0 < eventCode) && (eventCode < MAX_EVENT_CODE));
+
+ if (!ee) {
+
+ if ((hthd != NULL) && (hthd->tstate & ts_funceval)) {
+ assert(RgfnFuncEventDispatch[eventCode-EXCEPTION_DEBUG_EVENT]);
+ RgfnFuncEventDispatch[eventCode-EXCEPTION_DEBUG_EVENT](de, hthd);
+ } else {
+ assert(DebugDispatchTable[eventCode-EXCEPTION_DEBUG_EVENT]);
+ DebugDispatchTable[eventCode-EXCEPTION_DEBUG_EVENT](de,hthd);
+ }
+
+ } else {
+
+ /*
+ * If it was expected then call the action
+ * function if one was specified
+ */
+
+ if (ee->action) {
+ (ee->action)(de, hthd, 0, ee->lparam);
+ }
+
+ /*
+ * And call the notifier if one was specified
+ */
+
+ if (ee->notifier) {
+ METHOD *nm = ee->notifier;
+ (nm->notifyFunction)(de, hthd, 0, nm->lparam);
+ }
+
+ free(ee);
+ }
+
+done:
+ LeaveCriticalSection(&csProcessDebugEvent);
+ return;
+} /* ProcessDebugEvent() */
+
+
+
+#endif // KERNEL
+
+
+
+#ifndef KERNEL
+////////////////////////////////////////////////////////////////////
+
+// Helper functions for LoadDll.
+
+////////////////////////////////////////////////////////////////////
+
+//
+// iTemp1 is a magic module ID number for when we have to make
+// up a name for a module.
+//
+
+static iTemp1 = 0;
+
+BOOL
+GetModnameFromImage(
+ PIMAGE_NT_HEADERS pNtHdr,
+ PIMAGE_SECTION_HEADER pSH,
+ LOAD_DLL_DEBUG_INFO * pldd,
+ LPSTR lpName,
+ int cbName
+ )
+/*++
+
+Routine Description:
+
+ This routine attempts to get the name of the exe as placed
+ in the debug section section by the linker.
+
+Arguments:
+
+ pNtHdr - Supplies pointer to NT headers in image PE header
+
+ pSH - Supplies pointer to section headers
+
+ pldd - Supplies the info structure from the debug event
+
+ lpName - Returns the exe name
+
+ cbName - Supplies the size of the buffer at lpName
+
+Return Value:
+
+ TRUE if a name was found, FALSE if not.
+ The exe name is returned as an ANSI string in lpName.
+
+--*/
+{
+ /*
+ * See if the exe name is in the image
+ */
+ PIMAGE_OPTIONAL_HEADER pOptHdr = &pNtHdr->OptionalHeader;
+ PIMAGE_DEBUG_DIRECTORY pDebugDir;
+ IMAGE_DEBUG_DIRECTORY DebugDir;
+ PIMAGE_DEBUG_MISC pMisc;
+ PIMAGE_DEBUG_MISC pT;
+ DWORD rva;
+ int nDebugDirs;
+ int i;
+ int l;
+ BOOL rVal = FALSE;
+ nDebugDirs = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
+ sizeof(IMAGE_DEBUG_DIRECTORY);
+
+ if (!nDebugDirs) {
+ return FALSE;
+ }
+
+ rva = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+
+ for(i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++) {
+ if (rva >= pSH[i].VirtualAddress
+ && rva < pSH[i].VirtualAddress + pSH[i].SizeOfRawData)
+ {
+ break;
+ }
+ }
+
+ if (i >= pNtHdr->FileHeader.NumberOfSections) {
+ return FALSE;
+ }
+
+ //
+ // this is a pointer in the debuggee image:
+ //
+ if (pldd->hFile == 0) {
+ pDebugDir = (PIMAGE_DEBUG_DIRECTORY)
+ ((rva - pSH[i].VirtualAddress) + pSH[i].VirtualAddress);
+ } else {
+ pDebugDir = (PIMAGE_DEBUG_DIRECTORY)
+ (rva - pSH[i].VirtualAddress + pSH[i].PointerToRawData);
+ }
+
+ for (i = 0; i < nDebugDirs; i++) {
+
+ SetReadPointer((ULONG)(&pDebugDir[i]), FILE_BEGIN);
+ DoRead((LPV)&DebugDir, sizeof(DebugDir));
+
+ if (DebugDir.Type == IMAGE_DEBUG_TYPE_MISC) {
+
+ l = DebugDir.SizeOfData;
+ pMisc = pT = malloc(l);
+
+ if (pldd->hFile == 0) {
+ SetReadPointer((ULONG)DebugDir.AddressOfRawData, FILE_BEGIN);
+ } else {
+ SetReadPointer((ULONG)DebugDir.PointerToRawData, FILE_BEGIN);
+ }
+
+ DoRead((LPV)pMisc, l);
+
+ while (l > 0) {
+ if (pMisc->DataType != IMAGE_DEBUG_MISC_EXENAME) {
+ l -= pMisc->Length;
+ pMisc = (PIMAGE_DEBUG_MISC)
+ (((LPSTR)pMisc) + pMisc->Length);
+ } else {
+
+ PVOID pExeName;
+
+ pExeName = (PVOID)&pMisc->Data[ 0 ];
+
+ if (!pMisc->Unicode) {
+ strcpy(lpName, (LPSTR)pExeName);
+ rVal = TRUE;
+ } else {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ (LPWSTR)pExeName,
+ -1,
+ lpName,
+ cbName,
+ NULL,
+ NULL);
+ rVal = TRUE;
+ }
+
+ /*
+ * Undo stevewo's error
+ */
+
+ if (_stricmp(&lpName[strlen(lpName)-4], ".DBG") == 0) {
+ char rgchPath[_MAX_PATH];
+ char rgchBase[_MAX_FNAME];
+
+ _splitpath(lpName, NULL, rgchPath, rgchBase, NULL);
+ if (strlen(rgchPath)==4) {
+ rgchPath[strlen(rgchPath)-1] = 0;
+ strcpy(lpName, rgchBase);
+ strcat(lpName, ".");
+ strcat(lpName, rgchPath);
+ } else {
+ strcpy(lpName, rgchBase);
+ strcat(lpName, ".exe");
+ }
+ }
+ break;
+ }
+ }
+
+ free(pT);
+
+ break;
+
+ }
+ }
+
+ return rVal;
+}
+
+
+BOOL
+GetModnameFromExportTable(
+ PIMAGE_NT_HEADERS pNtHdr,
+ PIMAGE_SECTION_HEADER pSH,
+ LOAD_DLL_DEBUG_INFO * pldd,
+ LPSTR lpName,
+ int cbName
+ )
+/*++
+
+Routine Descriotion:
+
+ This routine attempts to invent an exe name for a DLL
+ from the module name found in the export table. This
+ will fail if there is no export table, so it is not
+ usually useful for EXEs.
+
+Arguments:
+
+ pNtHdr - Supplies pointer to NT header in image PE header
+ pSH - Supplies pointer to section header table
+ pldd - Supplies ptr to info record from debug event
+ lpName - Returns name when successful
+ cbName - Supplies size of buffer at lpName
+
+Return Value:
+
+ TRUE if successful and name is copied to lpName, FALSE
+ if not successful.
+
+--*/
+{
+ IMAGE_EXPORT_DIRECTORY expDir;
+ ULONG ExportVA;
+ ULONG oExports;
+ int iobj;
+ int cobj;
+
+ /*
+ * Find object which has the same RVA as the
+ * export table.
+ */
+
+ cobj = pNtHdr->FileHeader.NumberOfSections;
+
+ ExportVA = pNtHdr->
+ OptionalHeader.
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].
+ VirtualAddress;
+
+ if (!ExportVA) {
+ return FALSE;
+ }
+
+ for (iobj=0; iobj<cobj; iobj++) {
+ if (pSH[iobj].VirtualAddress == ExportVA) {
+ oExports = pSH[iobj].PointerToRawData;
+ break;
+ }
+ }
+
+ if (iobj >= cobj) {
+ return FALSE;
+ }
+
+ if ( (SetReadPointer(oExports, FILE_BEGIN) == -1L)
+ || !DoRead(&expDir, sizeof(expDir)) ) {
+
+ return FALSE;
+ }
+
+ SetReadPointer(oExports + (ULONG) expDir.Name - ExportVA,
+ FILE_BEGIN);
+
+ strcpy(lpName, "#:\\");
+
+ if (!DoRead(lpName+3, cbName - 3)) {
+ // It's a DLL, but we can't get the name...
+ sprintf(lpName+3, "DLL%02d.DLL", ++iTemp1);
+ }
+
+ return TRUE;
+}
+
+
+
+
+#ifdef INTERNAL
+void
+DeferIt(
+ HTHDX hthd,
+ DEBUG_EVENT *pde
+ )
+{
+ PDLL_DEFER_LIST pddl;
+ PDLL_DEFER_LIST *ppddl;
+
+ pddl = malloc(sizeof(DLL_DEFER_LIST));
+ pddl->next = NULL;
+ pddl->LoadDll = pde->u.LoadDll;
+ for (ppddl = &hthd->hprc->pDllDeferList; *ppddl; ) {
+ ppddl = & ((*ppddl)->next);
+ }
+ *ppddl = pddl;
+}
+#endif // INTERNAL
+
+
+BOOL
+LoadDll(
+ DEBUG_EVENT * de,
+ HTHDX hthd,
+ LPWORD lpcbPacket,
+ LPBYTE * lplpbPacket
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to load the signification information about
+ a PE exe file. This information consists of the name of the exe
+ just loaded (hopefully this will be provided later by the OS) and
+ a description of the sections in the exe file.
+
+Arguments:
+
+ de - Supplies a pointer to the current debug event
+
+ hthd - Supplies a pointer to the current thread structure
+
+ lpcbPacket - Returns the count of bytes in the created packet
+
+ lplpbPacket - Returns the pointer to the created packet
+
+Return Value:
+
+ True on success and FALSE on failure
+
+--*/
+
+{
+ LOAD_DLL_DEBUG_INFO * ldd = &de->u.LoadDll;
+ LPMODULELOAD lpmdl;
+ char szModName[512];
+ DWORD offset, cbObject;
+ DWORD lenSz, lenTable;
+ DWORD cobj, iobj;
+ IMAGE_DOS_HEADER dosHdr;
+ IMAGE_NT_HEADERS ntHdr;
+ IMAGE_SECTION_HEADER * rgSecHdr = NULL;
+ HANDLE hFile;
+ int iDll;
+ HPRCX hprc = hthd->hprc;
+ DWORD cb;
+ char rgch[512];
+ LPVOID lpv;
+ LPSTR lpsz;
+ ADDR addr;
+#ifdef WIN32S
+ BOOL fWin32sSystemDll;
+#else
+ OFFSET off;
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+#endif // WIN32S
+
+
+ if ( hprc->pstate & (ps_killed | ps_dead) ) {
+ //
+ // Process is dead, don't bother doing anything.
+ //
+ return FALSE;
+ }
+
+
+ //
+ // Create an entry in the DLL list and set the index to it so that
+ // we can have information about all DLLs for the current system.
+ //
+ for (iDll=0; iDll<hprc->cDllList; iDll+=1) {
+ if ((hprc->rgDllList[iDll].offBaseOfImage == (DWORD)ldd->lpBaseOfDll) ||
+ (!hprc->rgDllList[iDll].fValidDll)) {
+ break;
+ }
+ }
+
+ if (iDll == hprc->cDllList) {
+ //
+ // the dll list needs to be expanded
+ //
+ hprc->cDllList += 10;
+ if (!hprc->rgDllList) {
+ hprc->rgDllList = (PDLLLOAD_ITEM) malloc(sizeof(DLLLOAD_ITEM) * 10);
+ memset(hprc->rgDllList, 0, sizeof(DLLLOAD_ITEM)*10);
+ } else {
+ hprc->rgDllList = realloc(hprc->rgDllList,
+ hprc->cDllList * sizeof(DLLLOAD_ITEM));
+ memset(&hprc->rgDllList[hprc->cDllList-10], 0, 10*sizeof(DLLLOAD_ITEM));
+ }
+ } else
+ if (hprc->rgDllList[iDll].offBaseOfImage != (DWORD)ldd->lpBaseOfDll) {
+ memset(&hprc->rgDllList[iDll], 0, sizeof(DLLLOAD_ITEM));
+ }
+
+ //
+ // stick the demarcator at the start of the string so that we
+ // don't have to move the string over later.
+ //
+ *szModName = cModuleDemarcator;
+#ifdef WIN32S
+
+ /*
+ * WIN32S KNOWS what the module is called and doesn't need
+ * to futz around in the exe header to figure it out.
+ */
+
+ if (ldd->fUnicode) {
+ DEBUG_PRINT("Win32s doesn't do Unicode. Where'd this come from?\r\n");
+ }
+
+ //
+ // Read the image name from the module
+ //
+ rgch[0] = '\0'; // start with empty string
+ if ((ldd->lpImageName != NULL) &&
+ DbgReadMemory(hprc,
+ ldd->lpImageName,
+ &lpv,
+ sizeof(lpv),
+ (int *) &cb) &&
+ (cb == sizeof(lpv)) &&
+ (lpv != NULL)) {
+ DbgReadMemory(hprc, lpv, rgch, sizeof(rgch), (int *) &cb);
+ }
+
+ strcpy(szModName + 1, rgch);
+ hprc->rgDllList[iDll].szDllName = _strdup(rgch);
+
+ DEBUG_PRINT_1("Module name: %s\r\n", szModName + 1);
+
+ fWin32sSystemDll = IsWin32sSystemDll(szModName + 1);
+
+ if (fWin32sSystemDll) {
+ DEBUG_PRINT_1("Found system dll %s\r\n", szModName + 1);
+ }
+
+ // overwrite the module handle with a file handle.
+ ldd->hFile = CreateFile(szModName + 1, GENERIC_READ, OF_SHARE_COMPAT,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (ldd->hFile == INVALID_HANDLE_VALUE) {
+ DEBUG_PRINT_2("CreateFile<%s> failed, --> %u", szModName + 1,
+ GetLastError());
+ return FALSE;
+ }
+
+ // Now, continue with the dos header processing...
+
+#endif // WIN32S
+
+ //
+ // Process the DOS header. It is currently regarded as mandatory
+ //
+ // This has to be read before attempting to resolve the
+ // name of a module on NT. If the name resolution is aborted,
+ // the memory allocated for the IMAGE_SECTION_HEADER must be
+ // freed.
+ //
+ if (ldd->hFile == 0) {
+ SetPointerToMemory(hprc, ldd->lpBaseOfDll);
+ } else {
+ SetPointerToFile(ldd->hFile);
+ }
+
+ SetReadPointer(0, FILE_BEGIN);
+
+ if (DoRead(&dosHdr, sizeof(dosHdr)) == FALSE) {
+ DPRINT(1, ("ReadFile got error %u\r\n", GetLastError()));
+ return FALSE;
+ }
+
+ //
+ // Read in the PE header record
+ //
+
+ if ((dosHdr.e_magic != IMAGE_DOS_SIGNATURE) ||
+ (SetReadPointer(dosHdr.e_lfanew, FILE_BEGIN) == -1L)) {
+ return FALSE;
+ }
+
+ if (!DoRead(&ntHdr, sizeof(ntHdr))) {
+ return FALSE;
+ }
+
+ if (sizeof(ntHdr.OptionalHeader) != ntHdr.FileHeader.SizeOfOptionalHeader) {
+ SetReadPointer(ntHdr.FileHeader.SizeOfOptionalHeader -
+ sizeof(ntHdr.OptionalHeader), FILE_CURRENT);
+ }
+
+ //
+ // Save off the count of objects in the dll/exe file
+ //
+ cobj = ntHdr.FileHeader.NumberOfSections;
+
+ //
+ // Save away the offset in the file where the object table
+ // starts. We will need this later to get information about
+ // each of the objects.
+ //
+ rgSecHdr = (IMAGE_SECTION_HEADER *) malloc( cobj * sizeof(IMAGE_SECTION_HEADER));
+ if (!DoRead( rgSecHdr, cobj * sizeof(IMAGE_SECTION_HEADER))) {
+ assert (FALSE );
+ free(rgSecHdr);
+ return FALSE;
+ }
+
+
+#ifndef WIN32S
+
+
+ if (hprc->rgDllList[iDll].offBaseOfImage == (DWORD)ldd->lpBaseOfDll) {
+
+ //
+ // in this case we are re-doing a mod load for a dll
+ // that is part of a process that is being reconnected
+ //
+ assert( hprc->rgDllList[iDll].szDllName != NULL );
+ strcpy( szModName + 1, hprc->rgDllList[iDll].szDllName );
+
+ } else {
+
+
+ if (CrashDump) {
+ strcpy( szModName+1, ldd->lpImageName );
+ } else if ((ldd->lpImageName != NULL)
+ && DbgReadMemory(hprc,
+ ldd->lpImageName,
+ &lpv,
+ sizeof(lpv),
+ (int *) &cb)
+ && (cb == sizeof(lpv))
+ && (lpv != NULL)
+ && DbgReadMemory(hprc,
+ lpv,
+ rgch,
+ sizeof(rgch),
+ (int *) &cb))
+ {
+
+ // we're happy...
+ if (!ldd->fUnicode) {
+ strcpy(szModName+1, rgch);
+ } else {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ (LPWSTR)rgch,
+ -1,
+ nameBuffer,
+ sizeof(nameBuffer),
+ NULL,
+ NULL);
+ strcpy(szModName + 1, nameBuffer);
+ hprc->rgDllList[iDll].szDllName = _strdup(nameBuffer);
+ }
+
+ }
+
+ else if (*nameBuffer && !FLoading16) {
+
+ /*
+ * If *nameBuffer != 0 then we know we are really
+ * dealing with the root exe and we can steal the
+ * name from there.
+ */
+
+ if (FDMRemote) {
+ _splitpath( nameBuffer, NULL, NULL, fname, ext );
+ sprintf( szModName+1, "#:\\%s%s", fname, ext );
+ } else {
+ strcpy(szModName + 1, nameBuffer);
+ }
+ hprc->rgDllList[iDll].szDllName = _strdup(nameBuffer);
+
+ } else if (GetModnameFromImage(&ntHdr, rgSecHdr, ldd, rgch, sizeof(rgch))) {
+
+ // joyful...
+ lpsz = strrchr(rgch, '\\');
+ if (!lpsz) {
+ lpsz = strrchr(rgch, ':');
+ }
+ if (lpsz) {
+ ++lpsz;
+ } else {
+ lpsz = rgch;
+ }
+ strcpy(szModName + 1, "#:\\");
+ strcpy(szModName + 4, lpsz);
+ hprc->rgDllList[iDll].szDllName = _strdup(lpsz);
+
+ } else if (GetModnameFromExportTable(&ntHdr, rgSecHdr, ldd, rgch, sizeof(rgch))) {
+
+ // serene...
+ strcpy(szModName + 1, rgch);
+ hprc->rgDllList[iDll].szDllName = _strdup(rgch);
+
+ } else {
+
+ // hopeless...
+ sprintf(szModName+1, "#:\\APP%02d.EXE", ++iTemp1);
+ hprc->rgDllList[iDll].szDllName = _strdup(szModName+1);
+ }
+
+ if (!FLoading16) {
+ *nameBuffer = 0;
+ }
+ }
+
+#endif // !WIN32S
+
+ //
+ // for remote case, kill the drive letter to
+ // prevent finding same exe on wrong platform,
+ // except when user gave path to exe.
+ //
+ if (fUseRealName) {
+ fUseRealName = FALSE;
+ }
+ lenSz=strlen(szModName);
+ DPRINT(10, ("*** LoadDll %s base=%x\n", szModName, ldd->lpBaseOfDll));
+
+ szModName[lenSz] = '\0';
+
+ lpsz = strrchr(szModName, '\\');
+ if (!lpsz) {
+ lpsz = strrchr(szModName, ':');
+ }
+ if (lpsz) {
+ lpsz++;
+ } else {
+ lpsz = szModName;
+ }
+
+ if (_stricmp(lpsz, "kernel32.dll") == 0) {
+ hprc->dwKernel32Base = (DWORD)ldd->lpBaseOfDll;
+ }
+
+ if (hprc->rgDllList[iDll].offBaseOfImage != (DWORD)ldd->lpBaseOfDll) {
+ //
+ // new dll to add to the list
+ //
+ hprc->rgDllList[iDll].fValidDll = TRUE;
+ hprc->rgDllList[iDll].offBaseOfImage = (OFFSET) ldd->lpBaseOfDll;
+ hprc->rgDllList[iDll].cbImage = ntHdr.OptionalHeader.SizeOfImage;
+ }
+
+ szModName[lenSz] = cModuleDemarcator;
+ if (FDMRemote) {
+ if (ldd->hFile != 0 && ldd->hFile != (HANDLE)-1) {
+ CloseHandle(ldd->hFile); // don't need this anymore
+ }
+ hFile = (HANDLE)-1; // remote: can't send file handle across wire
+ }
+ else {
+
+ if (ldd->hFile == 0) {
+ hFile = (HANDLE)-1;
+ } else {
+ hFile = ldd->hFile; // local: let SH use our handle
+ }
+ }
+
+ /*
+ * Make up a record to send back from the name.
+ * Additionally send back:
+ * The file handle (if local)
+ * The load base of the dll
+ * The time and date stamp of the exe
+ * The checksum of the file
+ */
+
+ sprintf( szModName+lenSz+1,"0x%08lX%c0x%08lX%c0x%08lX%c0x%08lX%c",
+ ntHdr.FileHeader.TimeDateStamp, cModuleDemarcator,
+ ntHdr.OptionalHeader.CheckSum, cModuleDemarcator,
+ hFile, cModuleDemarcator,
+ (long) ldd->lpBaseOfDll, cModuleDemarcator);
+ lenSz = strlen(szModName);
+ /*
+ * Allocate the packet which will be sent across to the EM.
+ * The packet will consist of:
+ * The MODULELOAD structure sizeof(MODULELOAD) +
+ * The section description array cobj*sizeof(OBJD) +
+ * The name of the DLL lenSz+1
+ */
+
+ lenTable = (cobj * sizeof(OBJD));
+ *lpcbPacket = (WORD)(sizeof(MODULELOAD) + lenTable + (lenSz+1));
+ *lplpbPacket= (LPBYTE)(lpmdl=(LPMODULELOAD)malloc(*lpcbPacket));
+ lpmdl->lpBaseOfDll = ldd->lpBaseOfDll;
+ lpmdl->cobj = cobj;
+ lpmdl->mte = (WORD) -1;
+#ifdef TARGET_i386
+ lpmdl->CSSel = (unsigned short)hthd->context.SegCs;
+ lpmdl->DSSel = (unsigned short)hthd->context.SegDs;
+#else
+ lpmdl->CSSel = lpmdl->DSSel = 0;
+#endif // i386
+
+ /*
+ * Set up the descriptors for each of the section headers
+ * so that the EM can map between section numbers and flat addresses.
+ */
+
+ for (iobj=0; iobj<cobj; iobj++) {
+ offset = rgSecHdr[iobj].VirtualAddress + (long) ldd->lpBaseOfDll;
+ cbObject = rgSecHdr[iobj].Misc.VirtualSize;
+ if (cbObject == 0) {
+ cbObject = rgSecHdr[iobj].SizeOfRawData;
+ }
+
+ lpmdl->rgobjd[iobj].offset = offset;
+ lpmdl->rgobjd[iobj].cb = cbObject;
+ lpmdl->rgobjd[iobj].wPad = 1;
+
+#ifdef WIN32S
+ if (fWin32sSystemDll) {
+ AddWin32sSystemDllAddr(offset, cbObject);
+ }
+
+#endif // WIN32S
+
+#if defined(TARGET_i386)
+ if (IMAGE_SCN_CNT_CODE & rgSecHdr[iobj].Characteristics) {
+ lpmdl->rgobjd[iobj].wSel = (WORD) hthd->context.SegCs;
+ } else {
+ lpmdl->rgobjd[iobj].wSel = (WORD) hthd->context.SegDs;
+ }
+#else
+ lpmdl->rgobjd[iobj].wSel = 0;
+#endif // TARGET_i386
+ }
+
+ lpmdl->fRealMode = FALSE;
+ lpmdl->fFlatMode = TRUE;
+ lpmdl->fOffset32 = TRUE;
+ lpmdl->dwSizeOfDll = ntHdr.OptionalHeader.SizeOfImage;
+
+ /*
+ * Copy the name of the dll to the end of the packet.
+ */
+
+ _fmemcpy(((BYTE*)&lpmdl->rgobjd)+lenTable, szModName, lenSz+1);
+
+#ifndef WIN32S
+// WIN32S doesn't support TLS yet (will it ever?) Neither does the
+// linker, so it dumps random garbage in my header.
+ /*
+ * Locate the TLS section if one exists. If so then get the
+ * pointer to the TLS index
+ *
+ * Structure at the address is:
+ *
+ * VA lpRawData
+ * ULONG cbRawData
+ * VA lpIndex
+ * VA lpCallBacks
+ */
+
+ if (ntHdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0) {
+ if ((DbgReadMemory(hprc,
+ ntHdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress + (char *) ldd->lpBaseOfDll + 8,
+ &off,
+ sizeof(OFFSET),
+ &cb) == 0) ||
+ (cb != sizeof(OFFSET))) {
+ assert(FALSE);
+ }
+
+ hprc->rgDllList[iDll].offTlsIndex = off;
+ }
+#endif // WIN32S
+
+ /*
+ * free up the memory used for holding the section headers
+ */
+
+ free(rgSecHdr);
+
+ if (fDisconnected) {
+
+ //
+ // this will prevent the dm from sending a message up to
+ // the shell. the dm's data structures are setup just fine
+ // so that when the debugger re-connects we can deliver the
+ // mod loads correctly.
+ //
+
+ return FALSE;
+
+ }
+
+ return TRUE;
+} /* LoadDll() */
+
+#endif // !KERNEL
+
+
+
+
+#ifdef KERNEL
+
+BOOL
+GetModnameFromImage(
+ HPRCX hprc,
+ LOAD_DLL_DEBUG_INFO *ldd,
+ LPSTR lpName
+ )
+/*++
+
+Routine Description:
+
+ This routine attempts to get the name of the exe as placed
+ in the debug section by the linker.
+
+Arguments:
+
+Return Value:
+
+ TRUE if a name was found, FALSE if not.
+ The exe name is returned as an ANSI string in lpName.
+
+--*/
+{
+ #define ReadMem(b,s) DbgReadMemory( hprc, (LPVOID)(address), (b), (s), NULL ); address += (s)
+
+ IMAGE_DEBUG_DIRECTORY DebugDir;
+ PIMAGE_DEBUG_MISC pMisc;
+ PIMAGE_DEBUG_MISC pT;
+ DWORD rva;
+ int nDebugDirs;
+ int i;
+ int j;
+ int l;
+ BOOL rVal = FALSE;
+ PVOID pExeName;
+ IMAGE_NT_HEADERS nh;
+ IMAGE_DOS_HEADER dh;
+ IMAGE_ROM_OPTIONAL_HEADER rom;
+ DWORD address;
+ DWORD sig;
+ PIMAGE_SECTION_HEADER pSH;
+ DWORD cb;
+
+
+ lpName[0] = 0;
+
+ address = (ULONG)ldd->lpBaseOfDll;
+
+ ReadMem( &dh, sizeof(dh) );
+
+ if (dh.e_magic == IMAGE_DOS_SIGNATURE) {
+ address = (ULONG)ldd->lpBaseOfDll + dh.e_lfanew;
+ } else {
+ address = (ULONG)ldd->lpBaseOfDll;
+ }
+
+ ReadMem( &sig, sizeof(sig) );
+ address -= sizeof(sig);
+
+ if (sig != IMAGE_NT_SIGNATURE) {
+ ReadMem( &nh.FileHeader, sizeof(IMAGE_FILE_HEADER) );
+ if (nh.FileHeader.SizeOfOptionalHeader == IMAGE_SIZEOF_ROM_OPTIONAL_HEADER) {
+ ReadMem( &rom, sizeof(rom) );
+ ZeroMemory( &nh.OptionalHeader, sizeof(nh.OptionalHeader) );
+ nh.OptionalHeader.SizeOfImage = rom.SizeOfCode;
+ nh.OptionalHeader.ImageBase = rom.BaseOfCode;
+ } else {
+ return FALSE;
+ }
+ } else {
+ ReadMem( &nh, sizeof(nh) );
+ }
+
+ cb = nh.FileHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER;
+ pSH = malloc( cb );
+ ReadMem( pSH, cb );
+
+ nDebugDirs = nh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
+ sizeof(IMAGE_DEBUG_DIRECTORY);
+
+ if (!nDebugDirs) {
+ return FALSE;
+ }
+
+ rva = nh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+
+ for(i = 0; i < nh.FileHeader.NumberOfSections; i++) {
+ if (rva >= pSH[i].VirtualAddress &&
+ rva < pSH[i].VirtualAddress + pSH[i].SizeOfRawData) {
+ break;
+ }
+ }
+
+ if (i >= nh.FileHeader.NumberOfSections) {
+ return FALSE;
+ }
+
+ rva = ((rva - pSH[i].VirtualAddress) + pSH[i].VirtualAddress);
+
+ for (j = 0; j < nDebugDirs; j++) {
+
+ address = rva + (sizeof(DebugDir) * j) + (ULONG)ldd->lpBaseOfDll;
+ ReadMem( &DebugDir, sizeof(DebugDir) );
+
+ if (DebugDir.Type == IMAGE_DEBUG_TYPE_MISC) {
+
+ l = DebugDir.SizeOfData;
+ pMisc = pT = malloc(l);
+
+ if ((ULONG)DebugDir.AddressOfRawData < pSH[i].VirtualAddress ||
+ (ULONG)DebugDir.AddressOfRawData >=
+ pSH[i].VirtualAddress + pSH[i].SizeOfRawData) {
+ //
+ // the misc debug data MUST be in the .rdata section
+ // otherwise windbg cannot access it as it is not mapped in
+ //
+ continue;
+ }
+
+ address = (ULONG)DebugDir.AddressOfRawData + (ULONG)ldd->lpBaseOfDll;
+ ReadMem( pMisc, l );
+
+ while (l > 0) {
+ if (pMisc->DataType != IMAGE_DEBUG_MISC_EXENAME) {
+ l -= pMisc->Length;
+ pMisc = (PIMAGE_DEBUG_MISC)
+ (((LPSTR)pMisc) + pMisc->Length);
+ } else {
+
+ pExeName = (PVOID)&pMisc->Data[ 0 ];
+
+ if (!pMisc->Unicode) {
+ strcpy(lpName, (LPSTR)pExeName);
+ rVal = TRUE;
+ } else {
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ (LPWSTR)pExeName,
+ -1,
+ lpName,
+ MAX_PATH,
+ NULL,
+ NULL);
+ rVal = TRUE;
+ }
+
+ /*
+ * Undo stevewo's error
+ */
+
+ if (_stricmp(&lpName[strlen(lpName)-4], ".DBG") == 0) {
+ char rgchPath[_MAX_PATH];
+ char rgchBase[_MAX_FNAME];
+
+ _splitpath(lpName, NULL, rgchPath, rgchBase, NULL);
+ if (strlen(rgchPath)==4) {
+ rgchPath[strlen(rgchPath)-1] = 0;
+ strcpy(lpName, rgchBase);
+ strcat(lpName, ".");
+ strcat(lpName, rgchPath);
+ } else {
+ strcpy(lpName, rgchBase);
+ strcat(lpName, ".exe");
+ }
+ }
+ break;
+ }
+ }
+
+ free(pT);
+
+ break;
+
+ }
+ }
+
+ return rVal;
+}
+
+LPMODULEALIAS
+FindAddAliasByModule(
+ LPSTR lpImageName,
+ LPSTR lpModuleName
+ )
+/*++
+
+Routine Description:
+
+ Look for an alias entry by its "common" name, for example, look
+ for "NT". If it does not exist, and a new image name has been
+ provided, add it. If it does exist and a new image name has been
+ provided, replace the image name. Return the new or found record.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ int i;
+
+ for (i=0; i<MAX_MODULEALIAS; i++) {
+ if (ModuleAlias[i].ModuleName[0] == 0) {
+ if (!lpImageName) {
+ return NULL;
+ } else {
+ strcpy( ModuleAlias[i].Alias, lpImageName );
+ strcpy( ModuleAlias[i].ModuleName, lpModuleName );
+ ModuleAlias[i].Special = 1;
+ return &ModuleAlias[i];
+ }
+ }
+ if (_stricmp( ModuleAlias[i].ModuleName, lpModuleName ) == 0) {
+ if (lpImageName) {
+ strcpy( ModuleAlias[i].Alias, lpImageName);
+ }
+ return &ModuleAlias[i];
+ }
+ }
+}
+
+LPMODULEALIAS
+FindAliasByImageName(
+ LPSTR lpImageName
+ )
+{
+ int i;
+
+ for (i=0; i<MAX_MODULEALIAS; i++) {
+ if (ModuleAlias[i].ModuleName[0] == 0) {
+ return NULL;
+ }
+ if (_stricmp( ModuleAlias[i].Alias, lpImageName ) == 0) {
+ return &ModuleAlias[i];
+ }
+ }
+}
+
+LPMODULEALIAS
+CheckForRenamedImage(
+ HPRCX hprc,
+ LOAD_DLL_DEBUG_INFO *ldd,
+ LPSTR lpOrigImageName,
+ LPSTR lpModuleName
+ )
+{
+ CHAR ImageName[MAX_PATH];
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ DWORD i;
+
+
+ if (_stricmp( ldd->lpImageName, lpOrigImageName ) != 0) {
+ return NULL;
+ }
+
+ if (GetModnameFromImage( hprc, ldd, ImageName ) && ImageName[0]) {
+ _splitpath( ImageName, NULL, NULL, fname, ext );
+ sprintf( ImageName, "%s%s", fname, ext );
+ return FindAddAliasByModule(ImageName, lpModuleName);
+ }
+
+ return NULL;
+}
+
+
+BOOL
+LoadDll(
+ DEBUG_EVENT * de,
+ HTHDX hthd,
+ LPWORD lpcbPacket,
+ LPBYTE * lplpbPacket
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to load the signification information about
+ a PE exe file. This information consists of the name of the exe
+ just loaded (hopefully this will be provided later by the OS) and
+ a description of the sections in the exe file.
+
+Arguments:
+
+ de - Supplies a pointer to the current debug event
+
+ hthd - Supplies a pointer to the current thread structure
+
+ lpcbPacket - Returns the count of bytes in the created packet
+
+ lplpbPackt - Returns the pointer to the created packet
+
+Return Value:
+
+ True on success and FALSE on failure
+
+--*/
+
+{
+ LOAD_DLL_DEBUG_INFO * ldd = &de->u.LoadDll;
+ LPMODULELOAD lpmdl;
+ CHAR szModName[MAX_PATH];
+ DWORD lenSz;
+ INT iDll;
+ HPRCX hprc = hthd->hprc;
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ CHAR szFoundName[_MAX_PATH];
+ LPMODULEALIAS Alias = NULL;
+ DWORD i;
+ IMAGEINFO ii;
+
+ static int FakeDllNumber = 0;
+ char FakeDllName[13];
+
+ //
+ // extern owned by kdapi.c:
+ //
+ extern DWORD CacheProcessors;
+
+
+ if ( hprc->pstate & (ps_killed | ps_dead) ) {
+ //
+ // Process is dead, don't bother doing anything.
+ //
+ return FALSE;
+ }
+
+ if ( *(LPSTR)ldd->lpImageName == 0 ) {
+ ldd->lpImageName = FakeDllName;
+ sprintf(FakeDllName, "DLL%05x", FakeDllNumber++);
+ }
+
+ if (_stricmp( ldd->lpImageName, HAL_IMAGE_NAME ) == 0) {
+ Alias = CheckForRenamedImage( hprc, ldd, HAL_IMAGE_NAME, HAL_MODULE_NAME );
+ }
+
+ if (_stricmp( ldd->lpImageName, KERNEL_IMAGE_NAME ) == 0) {
+ Alias = CheckForRenamedImage( hprc, ldd, KERNEL_IMAGE_NAME, KERNEL_MODULE_NAME );
+ if (!Alias && CacheProcessors > 1) {
+ Alias = FindAddAliasByModule( KERNEL_IMAGE_NAME_MP, KERNEL_MODULE_NAME );
+ }
+ }
+
+ if (!Alias) {
+ Alias = FindAliasByImageName(ldd->lpImageName);
+ }
+
+ //
+ // Create an entry in the DLL list and set the index to it so that
+ // we can have information about all DLLs for the current system.
+ //
+ for (iDll=0; iDll<hprc->cDllList; iDll+=1) {
+ if (!hprc->rgDllList[iDll].fValidDll) {
+ break;
+ }
+ }
+
+ if (iDll == hprc->cDllList) {
+ //
+ // the dll list needs to be expanded
+ //
+ hprc->cDllList += 10;
+ hprc->rgDllList = realloc(hprc->rgDllList,
+ hprc->cDllList * sizeof(DLLLOAD_ITEM));
+ memset(&hprc->rgDllList[hprc->cDllList-10], 0, 10*sizeof(DLLLOAD_ITEM));
+ } else {
+ memset(&hprc->rgDllList[iDll], 0, sizeof(DLLLOAD_ITEM));
+ }
+
+ hprc->rgDllList[iDll].fValidDll = TRUE;
+ hprc->rgDllList[iDll].offBaseOfImage = (OFFSET) ldd->lpBaseOfDll;
+ hprc->rgDllList[iDll].cbImage = ldd->dwDebugInfoFileOffset;
+ if (Alias) {
+ _splitpath( Alias->ModuleName, NULL, NULL, fname, ext );
+ } else {
+ _splitpath( ldd->lpImageName, NULL, NULL, fname, ext );
+ }
+ hprc->rgDllList[iDll].szDllName = malloc(strlen(fname)+strlen(ext)+4);
+ sprintf( hprc->rgDllList[iDll].szDllName, "%s%s", fname, ext );
+ hprc->rgDllList[iDll].NumberOfSections = 0;
+ hprc->rgDllList[iDll].Sections = NULL;
+ hprc->rgDllList[iDll].sec = NULL;
+
+ *szFoundName = 0;
+ if (!((ULONG)ldd->lpBaseOfDll & 0x80000000)) {
+ //
+ // must be a usermode module
+ //
+ if (ReadImageInfo( hprc->rgDllList[iDll].szDllName,
+ szFoundName,
+ (LPSTR)KdOptions[KDO_SYMBOLPATH].value,
+ &ii )) {
+ //
+ // we found the debug info, so now save the sections
+ // this data is used by processgetsectionscmd()
+ //
+ hprc->rgDllList[iDll].NumberOfSections = ii.NumberOfSections;
+ hprc->rgDllList[iDll].sec = ii.Sections;
+ hprc->rgDllList[iDll].offBaseOfImage = ii.BaseOfImage;
+ hprc->rgDllList[iDll].cbImage = ii.SizeOfImage;
+ ldd->hFile = (HANDLE)ii.CheckSum;
+ }
+ }
+
+#ifdef TARGET_i386
+ hprc->rgDllList[iDll].SegCs = (WORD) hthd->context.SegCs;
+ hprc->rgDllList[iDll].SegDs = (WORD) hthd->context.SegDs;
+#endif
+
+ //
+ // Make up a record to send back from the name.
+ // Additionally send back:
+ // The file handle (if local)
+ // The load base of the dll
+ // The time and date stamp of the exe
+ // The checksum of the file
+ // ... and optionally the string "MP" to signal
+ // a multi-processor system to the symbol handler
+ //
+ *szModName = cModuleDemarcator;
+
+ //
+ // Send the name found by ReadImageInfo if it found an exe; if it
+ // only found a dbg, send the default name.
+ //
+ strcpy( szModName + 1,
+ *szFoundName ? szFoundName : hprc->rgDllList[iDll].szDllName);
+ lenSz=strlen(szModName);
+ szModName[lenSz] = cModuleDemarcator;
+ sprintf( szModName+lenSz+1,"0x%08lX%c0x%08lX%c0x%08lX%c0x%08lX%c",
+ -1, cModuleDemarcator, // timestamp
+ ldd->hFile, cModuleDemarcator, // checksum
+ -1, cModuleDemarcator,
+ hprc->rgDllList[iDll].offBaseOfImage, cModuleDemarcator
+ );
+
+ if (Alias) {
+ strcat( szModName, Alias->Alias );
+ lenSz = strlen(szModName);
+ szModName[lenSz] = cModuleDemarcator;
+ szModName[lenSz+1] = 0;
+ if (Alias->Special == 2) {
+ // If it's a one-shot alias, nuke it.
+ memset(Alias, 0, sizeof(MODULEALIAS));
+ }
+ }
+
+ lenSz = strlen(szModName);
+ _strupr(szModName);
+
+ //
+ // Allocate the packet which will be sent across to the EM.
+ // The packet will consist of:
+ // The MDL structure sizeof(MDL) +
+ // The section description array cobj*sizeof(OBJD) +
+ // The name of the DLL lenSz+1
+ //
+ *lpcbPacket = (WORD)(sizeof(MODULELOAD) + (lenSz+1));
+ *lplpbPacket= (LPBYTE)(lpmdl=(LPMODULELOAD)malloc(*lpcbPacket));
+ ZeroMemory( lpmdl, *lpcbPacket );
+ lpmdl->lpBaseOfDll = (LPVOID) hprc->rgDllList[iDll].offBaseOfImage;
+ // mark the MDL packet as deferred:
+ lpmdl->cobj = -1;
+ lpmdl->mte = (WORD) -1;
+#ifdef TARGET_i386
+ lpmdl->CSSel = (unsigned short)hthd->context.SegCs;
+ lpmdl->DSSel = (unsigned short)hthd->context.SegDs;
+#else
+ lpmdl->CSSel = lpmdl->DSSel = 0;
+#endif
+
+ lpmdl->fRealMode = 0;
+ lpmdl->fFlatMode = 1;
+ lpmdl->fOffset32 = 1;
+
+ lpmdl->dwSizeOfDll = hprc->rgDllList[iDll].cbImage;
+
+ //
+ // Copy the name of the dll to the end of the packet.
+ //
+ memcpy(((BYTE*)&lpmdl->rgobjd), szModName, lenSz+1);
+
+ if (fDisconnected) {
+
+ //
+ // this will prevent the dm from sending a message up to
+ // the shell. the dm's data structures are setup just fine
+ // so that when the debugger re-connects we can deliver the
+ // mod loads correctly.
+ //
+
+ return FALSE;
+
+ }
+
+ return TRUE;
+} /* LoadDll() */
+
+
+
+
+#endif // KERNEL
+
+
+
+
+/*** NotifyEM
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Given a debug event from the OS send the correct information
+** back to the debugger.
+**
+*/
+
+
+void
+NotifyEM(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD wparam,
+ LPVOID lparam
+ )
+/*++
+
+Routine Description:
+
+ This is the interface for telling the EM about debug events.
+
+ In general, de describes an event which the debugger needs
+ to know about. In some cases, a reply is needed. In those
+ cases this routine handles the reply and does the appropriate
+ thing with the data from the reply.
+
+Arguments:
+
+ de - Supplies debug event structure
+ hthd - Supplies thread that got the event
+ lparam - Supplies data specific to event
+
+Return Value:
+
+ None
+
+--*/
+{
+ DWORD eventCode = de->dwDebugEventCode;
+ DWORD subClass;
+ RTP rtp;
+ RTP * lprtp;
+ WORD cbPacket=0;
+ LPBYTE lpbPacket;
+ LPVOID toFree=(LPVOID)0;
+ WORD packetType = tlfDebugPacket;
+
+
+ if (hthd) {
+ rtp.hpid = hthd->hprc->hpid;
+ rtp.htid = hthd->htid;
+ } else if (hpidRoot == (HPID)INVALID) {
+ return;
+ } else {
+ // cheat:
+ rtp.hpid = hpidRoot;
+ rtp.htid = NULL;
+ }
+ subClass = de->u.Exception.ExceptionRecord.ExceptionCode;
+
+ switch(eventCode){
+
+ case EXCEPTION_DEBUG_EVENT:
+ if (subClass!=EXCEPTION_SINGLE_STEP){
+ PEXCEPTION_RECORD pexr=&de->u.Exception.ExceptionRecord;
+ DWORD cParam = pexr->NumberParameters;
+ DWORD nBytes = sizeof(EPR)+sizeof(DWORD)*cParam;
+ LPEPR lpepr = malloc(nBytes);
+
+ toFree = (LPVOID) lpepr;
+ cbPacket = (WORD) nBytes;
+ lpbPacket = (LPBYTE) lpepr;
+#ifdef TARGET_i386
+ lpepr->bpr.segCS = (SEGMENT)hthd->context.SegCs;
+ lpepr->bpr.segSS = (SEGMENT)hthd->context.SegSs;
+#endif
+ lpepr->bpr.offEBP = (DWORD)FRAME_POINTER(hthd);
+ lpepr->bpr.offESP = (DWORD)STACK_POINTER(hthd);
+ lpepr->bpr.offEIP = (DWORD)PC(hthd);
+ lpepr->bpr.fFlat = hthd->fAddrIsFlat;
+ lpepr->bpr.fOff32 = hthd->fAddrOff32;
+ lpepr->bpr.fReal = hthd->fAddrIsReal;
+
+ lpepr->dwFirstChance = de->u.Exception.dwFirstChance;
+ lpepr->ExceptionCode = pexr->ExceptionCode;
+ lpepr->ExceptionFlags = pexr->ExceptionFlags;
+ lpepr->NumberParameters = cParam;
+ for(;cParam;cParam--) {
+ lpepr->ExceptionInformation[cParam-1]=
+ pexr->ExceptionInformation[cParam-1];
+ }
+
+ rtp.dbc = dbcException;
+ break;
+ };
+
+ // Fall through when subClass == EXCEPTION_SINGLE_STEP
+
+ case BREAKPOINT_DEBUG_EVENT:
+ case ENTRYPOINT_DEBUG_EVENT:
+ case CHECK_BREAKPOINT_DEBUG_EVENT:
+ case LOAD_COMPLETE_DEBUG_EVENT:
+ {
+ LPBPR lpbpr = malloc ( sizeof ( BPR ) );
+#ifdef TARGET_i386
+ DWORD bpAddr = (UOFFSET)PC(hthd)-1L;
+#else
+ DWORD bpAddr = (UOFFSET)PC(hthd);
+#endif
+ toFree=lpbpr;
+ cbPacket = sizeof ( BPR );
+ lpbPacket = (LPBYTE) lpbpr;
+
+#ifdef TARGET_i386
+ lpbpr->segCS = (SEGMENT)hthd->context.SegCs;
+ lpbpr->segSS = (SEGMENT)hthd->context.SegSs;
+#endif
+
+ lpbpr->offEBP = (DWORD)FRAME_POINTER(hthd);
+ lpbpr->offESP = (DWORD)STACK_POINTER(hthd);
+ lpbpr->offEIP = (DWORD)PC(hthd);
+ lpbpr->fFlat = hthd->fAddrIsFlat;
+ lpbpr->fOff32 = hthd->fAddrOff32;
+ lpbpr->fReal = hthd->fAddrIsReal;
+ lpbpr->dwNotify = (DWORD)lparam;
+
+ if (eventCode==EXCEPTION_DEBUG_EVENT){
+ rtp.dbc = dbcStep;
+ break;
+ } else { /* (the breakpoint case) */
+
+ if (eventCode == ENTRYPOINT_DEBUG_EVENT) {
+ rtp.dbc = dbcEntryPoint;
+ } else if (eventCode == LOAD_COMPLETE_DEBUG_EVENT) {
+ rtp.dbc = dbcLoadComplete;
+ } else if (eventCode == CHECK_BREAKPOINT_DEBUG_EVENT) {
+ rtp.dbc = dbcCheckBpt;
+ packetType = tlfRequest;
+ } else {
+ rtp.dbc = dbcBpt;
+ }
+
+ /* NOTE: Ok try to follow this: If this was one
+ * of our breakpoints then we have already
+ * decremented the IP to point to the actual
+ * INT3 instruction (0xCC), this is so we
+ * can just replace the byte and continue
+ * execution from that point on.
+ *
+ * But if it was hard coded in by the user
+ * then we can't do anything but execute the
+ * NEXT instruction (because there is no
+ * instruction "under" this INT3 instruction)
+ * So the IP is left pointing at the NEXT
+ * instruction. But we don't want the EM
+ * think that we stopped at the instruction
+ * after the INT3, so we need to decrement
+ * offEIP so it's pointing at the hard-coded
+ * INT3. Got it?
+ *
+ * On an ENTRYPOINT_DEBUG_EVENT, the address is
+ * already right, and lparam is ENTRY_BP.
+ */
+
+ if (!lparam) {
+ lpbpr->offEIP = (UOFFSET)de->
+ u.Exception.ExceptionRecord.ExceptionAddress;
+ }
+ }
+
+ }
+ break;
+
+
+ case CREATE_PROCESS_DEBUG_EVENT:
+ /*
+ * A Create Process event has occured. The following
+ * messages need to be sent back
+ *
+ * dbceAssignPID: Associate our handle with the debugger
+ *
+ * dbcModLoad: Inform the debugger of the module load for
+ * the main exe (this is done at the end of this routine)
+ */
+ {
+ HPRCX hprc = (HPRCX)lparam;
+
+ /*
+ * Has the debugger requested this process?
+ * ie: has it already given us the HPID for this process?
+ */
+ if (hprc->hpid != (HPID)INVALID){
+
+ lpbPacket = (LPBYTE)&(hprc->pid);
+ cbPacket = sizeof(hprc->pid);
+
+ /* Want the hprc for the child NOT the DM */
+ rtp.hpid = hprc->hpid;
+
+#ifndef KERNEL
+ //
+ // hack for made-up image names:
+ //
+ iTemp1 = 0;
+#endif
+ rtp.dbc = dbceAssignPID;
+ }
+
+ /*
+ * The debugger doesn't know about this process yet,
+ * request an HPID for this new process.
+ */
+
+ else {
+ LPNPP lpnpp = malloc(cbPacket=sizeof(NPP));
+
+ toFree = lpnpp;
+ lpbPacket = (LPBYTE)lpnpp;
+ packetType = tlfRequest;
+
+ /*
+ * We must temporarily assign a valid HPID to this HPRC
+ * because OSDebug will try to de-reference it in the
+ * TL callback function
+ */
+ rtp.hpid = hpidRoot;
+ lpnpp->pid = hprc->pid;
+ lpnpp->fReallyNew = TRUE;
+ rtp.dbc = dbcNewProc;
+ }
+ }
+ break;
+
+ case CREATE_THREAD_DEBUG_EVENT:
+ {
+ cbPacket = sizeof(hthd->tid);
+ lpbPacket = (LPBYTE)&(hthd->tid);
+ packetType = tlfRequest;
+
+ rtp.hpid = hthd->hprc->hpid;
+ rtp.htid = hthd->htid;
+ rtp.dbc = dbcCreateThread;
+ }
+ break;
+
+ case EXIT_PROCESS_DEBUG_EVENT:
+ cbPacket = sizeof(DWORD);
+ lpbPacket = (LPBYTE) &(de->u.ExitProcess.dwExitCode);
+
+ hthd->hprc->pstate |= ps_exited;
+ rtp.hpid = hthd->hprc->hpid;
+ rtp.htid = hthd->htid;
+ rtp.dbc = dbcProcTerm;
+ break;
+
+ case EXIT_THREAD_DEBUG_EVENT:
+ cbPacket = sizeof(DWORD);
+ lpbPacket = (LPBYTE) &(de->u.ExitThread.dwExitCode);
+
+ hthd->tstate |= ts_dead; /* Mark thread as dead */
+ hthd->hprc->pstate |= ps_deadThread;
+ rtp.dbc = dbcThreadTerm;
+ break;
+
+ case DESTROY_PROCESS_DEBUG_EVENT:
+ DPRINT(3, ("DESTROY PROCESS\n"));
+ hthd->hprc->pstate |= ps_destroyed;
+ rtp.dbc = dbcDeleteProc;
+ break;
+
+ case DESTROY_THREAD_DEBUG_EVENT:
+ /*
+ * Check if already destroyed
+ */
+
+ assert( (hthd->tstate & ts_destroyed) == 0 );
+
+ DPRINT(3, ("DESTROY THREAD\n"));
+
+ hthd->tstate |= ts_destroyed;
+ cbPacket = sizeof(DWORD);
+//NOTENOTE a-kentf exit code is bogus here
+ lpbPacket = (LPBYTE) &(de->u.ExitThread.dwExitCode);
+#ifdef OSDEBUG4
+ rtp.dbc = dbcDeleteThread;
+#else
+ rtp.dbc = dbcThreadDestroy;
+#endif
+ break;
+
+
+ case LOAD_DLL_DEBUG_EVENT:
+ packetType = tlfRequest;
+ rtp.dbc = dbcModLoad;
+
+ ValidateHeap();
+
+#ifndef KERNEL
+ //
+ // this was changed for a deadlock problem in user mode.
+ // if somebody gets ambitious, they can match the change
+ // for the KD side.
+ //
+ lpbPacket = lparam;
+ cbPacket = (USHORT)wparam;
+#else
+ if (!LoadDll(de, hthd, &cbPacket, &lpbPacket) || (cbPacket == 0)) {
+ return;
+ }
+#endif
+ ValidateHeap();
+ toFree = (LPVOID)lpbPacket;
+ break;
+
+ case UNLOAD_DLL_DEBUG_EVENT:
+ packetType = tlfRequest;
+ cbPacket = sizeof(DWORD);
+ lpbPacket = (LPBYTE) &(de->u.UnloadDll.lpBaseOfDll);
+
+ rtp.dbc = dbceModFree32;
+ break;
+
+ case OUTPUT_DEBUG_STRING_EVENT:
+ {
+#ifdef OSDEBUG4
+ LPINFOAVAIL lpinf;
+#else
+ LPINF lpinf;
+#endif
+ DWORD cbR;
+
+ rtp.dbc = dbcInfoAvail;
+
+#ifdef OSDEBUG4
+ cbPacket = (WORD)(sizeof(INFOAVAIL) +
+ de->u.DebugString.nDebugStringLength + 1);
+ lpinf = (LPINFOAVAIL) lpbPacket = malloc(cbPacket);
+#else
+ cbPacket = (WORD)(sizeof(INF) +
+ de->u.DebugString.nDebugStringLength + 1);
+ lpinf = (LPINF) lpbPacket = malloc(cbPacket);
+#endif
+ toFree = lpbPacket;
+
+ lpinf->fReply = FALSE;
+ lpinf->fUniCode = de->u.DebugString.fUnicode;
+
+ DbgReadMemory(hthd->hprc,
+ de->u.DebugString.lpDebugStringData,
+ &lpinf->buffer[0],
+ de->u.DebugString.nDebugStringLength,
+ &cbR);
+ lpinf->buffer[cbR] = 0;
+
+ // NYI
+ // if this is a magic message, change the dbc to
+ // INPUT_DEBUG_STRING_EVENT before sending it.
+ }
+ break;
+
+
+ case INPUT_DEBUG_STRING_EVENT:
+ {
+ LPINF lpinf;
+
+ packetType = tlfRequest;
+ rtp.dbc = dbcInfoReq;
+
+ cbPacket =
+ (WORD)(sizeof(INF) + de->u.DebugString.nDebugStringLength + 1);
+ lpinf = (LPINF) lpbPacket = malloc(cbPacket);
+ toFree = lpbPacket;
+
+ lpinf->fReply = TRUE;
+ lpinf->fUniCode = de->u.DebugString.fUnicode;
+
+ memcpy( &lpinf->buffer[0],
+ de->u.DebugString.lpDebugStringData,
+ de->u.DebugString.nDebugStringLength);
+ lpinf->buffer[ de->u.DebugString.nDebugStringLength ] = 0;
+ }
+ break;
+
+#ifndef OSDEBUG4
+ case RIP_EVENT:
+ {
+ LPRIP_INFO prip = &de->u.RipInfo;
+ DWORD nBytes = sizeof(NT_RIP);
+ LPNT_RIP lprip = malloc(nBytes);
+
+ toFree = (LPVOID) lprip;
+ cbPacket = (WORD) nBytes;
+ lpbPacket = (LPBYTE) lprip;
+
+#ifdef TARGET_i386
+ lprip->bpr.segCS = (SEGMENT)hthd->context.SegCs;
+ lprip->bpr.segSS = (SEGMENT)hthd->context.SegSs;
+#endif
+ lprip->bpr.offEBP = (DWORD)FRAME_POINTER(hthd);
+ lprip->bpr.offESP = (DWORD)STACK_POINTER(hthd);
+ lprip->bpr.offEIP = (DWORD)PC(hthd);
+ lprip->bpr.fFlat = hthd->fAddrIsFlat;
+ lprip->bpr.fOff32 = hthd->fAddrOff32;
+ lprip->bpr.fReal = hthd->fAddrIsReal;
+
+ lprip->ulErrorCode = prip->dwError;
+ lprip->ulErrorLevel = prip->dwType;
+
+ rtp.dbc = dbcNtRip;
+ }
+#endif
+
+ break;
+
+ case ATTACH_DEADLOCK_DEBUG_EVENT:
+ {
+ static XOSD xosd;
+ xosd = xosdAttachDeadlock;
+ cbPacket = sizeof(xosd);
+ lpbPacket = (LPBYTE) &xosd;
+ rtp.dbc = dbcError;
+ }
+ break;
+
+ default:
+ DPRINT(1, ("Error, unknown event\n\r"));
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ return;
+ }
+
+
+ DPRINT(3, ("Notify the debugger: dbc=%x, hpid=%x, htid=%x, cbpacket=%d ",
+ rtp.dbc, rtp.hpid, rtp.htid, cbPacket+sizeof(RTP)));
+
+ ValidateHeap();
+
+ if (!(rtp.cb=cbPacket)) {
+ DmTlFunc(packetType, rtp.hpid, sizeof(RTP), (LONG)(LPV) &rtp);
+ }
+ else {
+ lprtp = (LPRTP)malloc(sizeof(RTP)+cbPacket);
+ _fmemcpy(lprtp, &rtp, sizeof(RTP));
+ _fmemcpy(lprtp->rgbVar, lpbPacket, cbPacket);
+
+ ValidateHeap();
+
+ DmTlFunc(packetType, rtp.hpid,(WORD)(sizeof(RTP)+cbPacket),
+ (LONG)(LPV) lprtp);
+
+ ValidateHeap();
+
+ free(lprtp);
+ }
+
+ if (toFree) {
+ free(toFree);
+ }
+
+ DPRINT(3, ("\n"));
+
+ ValidateHeap();
+
+ switch(eventCode){
+
+ case CREATE_THREAD_DEBUG_EVENT:
+ if (packetType == tlfRequest) {
+ hthd->htid = *((HTID *) abEMReplyBuf);
+ }
+ SetEvent(hthd->hprc->hEventCreateThread);
+ break;
+
+ case CREATE_PROCESS_DEBUG_EVENT:
+ if (packetType == tlfRequest) {
+ ((HPRCX)lparam)->hpid = *((HPID *) abEMReplyBuf);
+ } else {
+ XOSD xosd = xosdNone;
+ DmTlFunc( tlfReply,
+ ((HPRCX)lparam)->hpid,
+ sizeof(XOSD),
+ (LONG)(LPV) &xosd);
+ }
+
+ SetEvent(hEventCreateProcess);
+
+ break;
+
+ case OUTPUT_DEBUG_STRING_EVENT:
+ // just here to synchronize
+ break;
+
+ case INPUT_DEBUG_STRING_EVENT:
+ de->u.DebugString.nDebugStringLength = strlen(abEMReplyBuf) + 1;
+ memcpy(de->u.DebugString.lpDebugStringData,
+ abEMReplyBuf,
+ de->u.DebugString.nDebugStringLength);
+ break;
+
+#ifdef KERNEL
+ // as noted above, synchronization is done differently in
+ // the user and KD versions:
+ case LOAD_DLL_DEBUG_EVENT:
+ if (_stricmp( de->u.LoadDll.lpImageName, KERNEL_IMAGE_NAME ) == 0) {
+ GetKernelSymbolAddresses();
+ }
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ ValidateHeap();
+ return;
+} /* NotifyEM() */
+
+
+
+void
+ProcessExceptionEvent(
+ DEBUG_EVENT* de,
+ HTHDX hthd
+ )
+{
+ DWORD subclass = de->u.Exception.ExceptionRecord.ExceptionCode;
+ DWORD firstChance = de->u.Exception.dwFirstChance;
+ PBREAKPOINT bp=NULL;
+
+ //
+ // If the thread is in a pre-start state we failed in the
+ // program loader, probably because a link couldn't be resolved.
+ //
+ if ( hthd->hprc->pstate & ps_preStart ) {
+ XOSD xosd = xosdUnknown;
+ DPRINT(1, ("Exception during init\n"));
+
+ //
+ // since we will probably never see the expected BP,
+ // clear it out, and clear the prestart flag on the
+ // thread, then go ahead and deliver the exception
+ // to the shell.
+ //
+ ConsumeAllProcessEvents(hthd->hprc, TRUE);
+ hthd->hprc->pstate &= ~ps_preStart;
+ hthd->tstate |= ts_stopped;
+ }
+
+
+ switch(subclass) {
+
+ case (DWORD)EXCEPTION_SINGLE_STEP:
+ break;
+
+
+ default:
+
+
+ /*
+ * The user can define a set of exceptions for which we do not do
+ * notify the shell on a first chance occurance.
+ */
+
+ if (!firstChance) {
+
+ DPRINT(3, ("2nd Chance Exception %08lx.\n",subclass));
+ hthd->tstate |= ts_second;
+
+ } else {
+
+ hthd->tstate |= ts_first;
+
+ switch (ExceptionAction(hthd->hprc,subclass)) {
+
+ case efdNotify:
+
+ NotifyEM(de,hthd,0,(LPVOID)bp);
+ // fall through to ignore case
+
+ case efdIgnore:
+
+ DPRINT(3, ("Ignoring Exception %08lx.\n",subclass));
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ (DWORD)DBG_EXCEPTION_NOT_HANDLED,
+ 0);
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ return;
+
+ case efdStop:
+ case efdCommand:
+ break;
+ }
+ }
+
+ break;
+ }
+
+ NotifyEM(de,hthd,0,(LPVOID)bp);
+} /* ProcessExceptionEvent() */
+
+
+
+void
+ProcessRipEvent(
+ DEBUG_EVENT * de,
+ HTHDX hthd
+ )
+{
+ if (hthd) {
+ hthd->tstate |= ts_rip;
+ }
+ NotifyEM( de, hthd, 0,NULL );
+} /* ProcessRipEvent() */
+
+
+void
+ProcessBreakpointEvent(
+ DEBUG_EVENT * pde,
+ HTHDX hthd
+ )
+{
+ PBREAKPOINT pbp = (BREAKPOINT*)pde->u.Exception.ExceptionRecord.ExceptionCode;
+ void MethodContinueSS(DEBUG_EVENT*, HTHDX, DWORD, METHOD*);
+ METHOD *ContinueSSMethod;
+
+ DPRINT(1, ("Hit a breakpoint -- "));
+
+ if (!pbp) {
+
+ DPRINT(1, ("[Embedded BP]\n"));
+ // already set this in ProcessDebugEvent
+ //SetBPFlag(hthd, EMBEDDED_BP);
+ NotifyEM(pde, hthd, 0,(LPVOID)pbp);
+
+ } else if (!pbp->hthd || pbp->hthd == hthd) {
+
+ DPRINT(1, ("[One of our own BP's.]\n"));
+ SetBPFlag(hthd, pbp);
+ NotifyEM(pde, hthd, 0,(LPVOID)pbp);
+
+ } else {
+
+ DPRINT(1, ("[BP for another thread]\n"));
+
+ /*
+ * When this is a bp for some other thread, we need to step.
+ * We mustn't step over calls, but trace them, since the right
+ * thread might pass over before we put the breakpoint back.
+ */
+
+ ContinueSSMethod = (METHOD*)malloc(sizeof(METHOD));
+ ContinueSSMethod->notifyFunction = (ACVECTOR)MethodContinueSS;
+ ContinueSSMethod->lparam = ContinueSSMethod;
+ ContinueSSMethod->lparam2 = pbp;
+
+ RestoreInstrBP(hthd, pbp);
+ SingleStep(hthd, ContinueSSMethod, FALSE, FALSE);
+ }
+}
+
+
+void
+ProcessCreateProcessEvent(
+ DEBUG_EVENT * pde,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ This routine does the processing needed for a create process
+ event from the OS. We need to do the following:
+
+ - Set up our internal structures for the newly created thread
+ and process
+ - Get notifications back to the debugger
+
+Arguments:
+
+ pde - Supplies pointer to the DEBUG_EVENT structure from the OS
+
+ hthd - Supplies thread descriptor that thread event occurred on
+
+Return Value:
+
+ none
+
+--*/
+{
+ DEBUG_EVENT de2;
+ CREATE_PROCESS_DEBUG_INFO *pcpd = &pde->u.CreateProcessInfo;
+ HPRCX hprc;
+ LPSTR lpbPacket;
+ WORD cbPacket;
+
+ DEBUG_PRINT("ProcessCreateProcessEvent\r\n");
+
+ ResetEvent(hEventCreateProcess);
+
+ hprc = InitProcess((HPID)INVALID);
+
+ ResetEvent(hprc->hEventCreateThread);
+
+ /*
+ * Create the first thread structure for this app
+ */
+ hthd = (HTHDX)malloc(sizeof(HTHDXSTRUCT));
+ memset(hthd, 0, sizeof(*hthd));
+
+ EnterCriticalSection(&csThreadProcList);
+
+ hthd->next = thdList->next;
+ thdList->next = hthd;
+
+ hthd->nextSibling = hprc->hthdChild;
+
+ hthd->hprc = hprc;
+ hthd->htid = 0;
+ hthd->tid = pde->dwThreadId;
+ hthd->atBP = 0L;
+ hthd->rwHand = pcpd->hThread;
+ hthd->tstate = ts_stopped;
+ hthd->offTeb = (OFFSET) pcpd->lpThreadLocalBase;
+ hthd->lpStartAddress = (LPVOID)pcpd->lpStartAddress;
+
+ hthd->fAddrIsReal = FALSE;
+ hthd->fAddrIsFlat = TRUE;
+ hthd->fAddrOff32 = TRUE;
+ hthd->fWowEvent = FALSE;
+
+#ifndef KERNEL
+#if defined(TARGET_i386) && !defined(WIN32S)
+ hthd->context.ContextFlags = CONTEXT_FULL;
+ DbgGetThreadContext( hthd, &hthd->context );
+ hprc->segCode = (SEGMENT) hthd->context.SegCs;
+#endif
+#endif
+
+ /*
+ * Stuff the process structure
+ */
+
+#ifndef KERNEL
+ //
+ // try to create a handle with more permissions
+ //
+ if (!CrashDump) {
+ hprc->rwHand = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pde->dwProcessId);
+ if (hprc->rwHand) {
+ // CloseHandle(pcpd->hProcess);
+ } else {
+ hprc->rwHand = pcpd->hProcess;
+ }
+ }
+#endif // KERNEL
+
+ hprc->pid = pde->dwProcessId;
+ hprc->hthdChild = hthd;
+ hprc->pstate = ps_preStart;
+
+ if (fUseRoot) {
+ hprc->pstate |= ps_root;
+ hprc->hpid = hpidRoot;
+ fUseRoot = FALSE;
+ if (pcpd->lpStartAddress && FLoading16) {
+ hprc->f16bit = TRUE;
+ } else {
+ hprc->f16bit = FALSE;
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ /*
+ * There is going to be a breakpoint to announce that the
+ * process is loaded and runnable.
+ */
+ nWaitingForLdrBreakpoint++;
+ if (pcpd->lpStartAddress == NULL) {
+ // in an attach, the BP will be in another thread.
+ RegisterExpectedEvent( hprc,
+ (HTHDX)NULL,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ DONT_NOTIFY,
+ (ACVECTOR)ActionDebugActiveReady,
+ FALSE,
+ hprc);
+#ifndef KERNEL
+#if defined(INTERNAL) && !defined(WIN32S)
+ // don't ever let it defer name resolutions
+ hprc->fNameRequired = TRUE;
+#endif
+#endif
+
+ } else {
+ // On a real start, the BP will be in the first thread.
+ RegisterExpectedEvent( hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ DONT_NOTIFY,
+ (ACVECTOR)ActionDebugNewReady,
+ FALSE,
+ hprc);
+ }
+
+ /*
+ * Notify the EM of this newly created process.
+ * If not the root proc, an hpid will be created and added
+ * to the hprc by the em.
+ */
+ NotifyEM(pde, hthd, 0,hprc);
+
+#ifndef KERNEL
+ /*
+ * We also need to drop out a module load notification
+ * on this exe.
+ */
+
+ de2.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de2.dwProcessId = pde->dwProcessId;
+ de2.dwThreadId = pde->dwThreadId;
+ de2.u.LoadDll.hFile = pde->u.CreateProcessInfo.hFile;
+ de2.u.LoadDll.lpBaseOfDll = pde->u.CreateProcessInfo.lpBaseOfImage;
+ de2.u.LoadDll.lpImageName = pde->u.CreateProcessInfo.lpImageName;
+ de2.u.LoadDll.fUnicode = pde->u.CreateProcessInfo.fUnicode;
+
+ if (LoadDll(&de2, hthd, &cbPacket, &lpbPacket) && (cbPacket != 0)) {
+ LeaveCriticalSection(&csProcessDebugEvent);
+ NotifyEM(&de2, hthd, cbPacket, lpbPacket);
+ EnterCriticalSection(&csProcessDebugEvent);
+ }
+#endif // !KERNEL
+
+ /*
+ * Fake up a thread creation notification.
+ */
+ pde->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
+ NotifyEM(pde, hthd, 0, hprc);
+
+ /*
+ * Dont let the new process run: the shell will say Go()
+ * after receiving a CreateThread event.
+ */
+
+} /* ProcessCreateProcessEvent() */
+
+
+void
+ProcessCreateThreadEvent(
+ DEBUG_EVENT * de,
+ HTHDX creatorHthd
+ )
+{
+ CREATE_THREAD_DEBUG_INFO * ctd = &de->u.CreateThread;
+ HTHDX hthd;
+ HPRCX hprc;
+ TID tid;
+ PID pid;
+ CONTEXT context;
+#if defined(KERNEL) && defined(HAS_DEBUG_REGS)
+ KSPECIAL_REGISTERS ksr;
+#endif // KERNEL && i386
+
+ Unreferenced(creatorHthd);
+
+ DPRINT(3, ("\n***CREATE THREAD EVENT\n"));
+
+ /* Determine the tid, pid and hprc */
+ pid = de->dwProcessId;
+ tid = de->dwThreadId;
+ hprc= HPRCFromPID(pid);
+
+ ResetEvent(hprc->hEventCreateThread);
+
+ if (ctd->hThread == NULL)
+ {
+ DPRINT(1, ("BAD HANDLE! BAD HANDLE!(%08lx)\n", ctd->hThread));
+ AddQueue( QT_CONTINUE_DEBUG_EVENT, pid, tid, DBG_CONTINUE, 0);
+ return;
+ }
+
+ if (!hprc) {
+ DPRINT(1, ("BAD PID! BAD PID!\n"));
+ AddQueue( QT_CONTINUE_DEBUG_EVENT, pid, tid, DBG_CONTINUE, 0);
+ return;
+ }
+
+ /* Create the thread structure */
+ hthd = (HTHDX)malloc(sizeof(HTHDXSTRUCT));
+ memset( hthd, 0, sizeof(*hthd));
+
+ /* Stuff the structure */
+
+ EnterCriticalSection(&csThreadProcList);
+
+ hthd->next = thdList->next;
+ thdList->next = hthd;
+
+ hthd->nextSibling = hprc->hthdChild;
+ hprc->hthdChild = (LPVOID)hthd;
+
+ hthd->hprc = hprc;
+ hthd->htid = (HTID)INVALID;
+ hthd->tid = tid;
+ hthd->rwHand = ctd->hThread;
+ hthd->offTeb = (OFFSET) ctd->lpThreadLocalBase;
+ hthd->pss = NULL;
+
+ hthd->lpStartAddress= (LPVOID)ctd->lpStartAddress;
+ hthd->atBP = (BREAKPOINT*)0;
+ hthd->tstate = ts_stopped;
+
+ hthd->fAddrIsReal = FALSE;
+ hthd->fAddrIsFlat = TRUE;
+ hthd->fAddrOff32 = TRUE;
+ hthd->fWowEvent = FALSE;
+#ifdef KERNEL
+ hthd->fContextStale = TRUE;
+#endif
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ //
+ // initialize cache entries
+ //
+
+ context.ContextFlags = CONTEXT_FULL;
+ DbgGetThreadContext( hthd, &context );
+
+ //
+ // Let the expression breakpoint manager that a new thread
+ // has been created.
+ //
+ ExprBPCreateThread( hprc, hthd );
+
+#if defined(KERNEL) && defined(HAS_DEBUG_REGS)
+ GetExtendedContext( hthd, &ksr );
+#endif // KERNEL && i386
+
+ //
+ // Notify the EM of this new thread
+ //
+
+ if (fDisconnected) {
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT, hthd->hprc->pid, hthd->tid, DBG_CONTINUE, 0 );
+ } else {
+ NotifyEM(de, hthd, 0, hprc);
+ }
+
+ return;
+}
+
+
+#ifndef KERNEL
+VOID
+UnloadAllModules(
+ HPRCX hprc,
+ HTHDX hthd
+ )
+{
+ DEBUG_EVENT de;
+ DWORD i;
+
+
+ for (i=0; i<(DWORD)hprc->cDllList; i++) {
+ if ((hprc->rgDllList[i].fValidDll) && (!hprc->rgDllList[i].fWow)) {
+ de.dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ de.u.UnloadDll.lpBaseOfDll = (LPVOID)hprc->rgDllList[i].offBaseOfImage;
+ NotifyEM( &de, hthd, 0, NULL );
+ DestroyDllLoadItem( &hprc->rgDllList[i] );
+ }
+ }
+
+ return;
+}
+#endif // !KERNEL
+
+
+void
+ProcessExitProcessEvent(
+ DEBUG_EVENT* pde,
+ HTHDX hthd
+ )
+{
+ HPRCX hprc;
+ XOSD xosd;
+ HTHDX hthdT;
+ PBREAKPOINT pbp;
+
+ DPRINT(3, ("ProcessExitProcessEvent\n"));
+
+ if (!hthd) {
+ hprc = HPRCFromPID(pde->dwProcessId);
+ } else {
+ hprc = hthd->hprc;
+ }
+
+#ifndef KERNEL
+ DEBUG_PRINT("Try unloading modules.\r\n");
+
+ UnloadAllModules( hprc, hthd? hthd:hprc->hthdChild );
+
+ DEBUG_PRINT("Done with UnloadAllModules.\r\n");
+#endif
+
+ /*
+ * do all exit thread handling:
+ *
+ * If thread was created during/after the
+ * beginning of termination processing, we didn't
+ * pick it up, so don't try to destroy it.
+ */
+
+ if (hthd) {
+ hthd->tstate |= ts_dead;
+ hthd->dwExitCode = pde->u.ExitProcess.dwExitCode;
+ }
+
+ /* and exit process */
+
+ hprc->pstate |= ps_dead;
+ hprc->dwExitCode = pde->u.ExitProcess.dwExitCode;
+ ConsumeAllProcessEvents(hprc, TRUE);
+
+ /*
+ * Clean up BP records
+ */
+
+ while (pbp = BPNextHprcPbp(hprc, NULL)) {
+ RemoveBP(pbp);
+ }
+
+ /*
+ * If we haven't seen EXIT_THREAD events for any
+ * threads, we aren't going to, so consider them done.
+ */
+
+ for (hthdT = hprc->hthdChild; hthdT; hthdT = hthdT->nextSibling) {
+ if ( !(hthdT->tstate & ts_dead) ) {
+ hthdT->tstate |= ts_dead;
+ hthdT->tstate &= ~ts_stopped;
+ }
+ }
+
+ /*
+ * If process hasn't initialized yet, we were expecting
+ * a breakpoint to notify us that all the DLLs are here.
+ * We didn't get that yet, so reply here.
+ */
+ if (hprc->pstate & ps_preStart) {
+ xosd = xosdUnknown;
+ DmTlFunc( tlfReply, hprc->hpid, sizeof(XOSD), (LONG)(LPV) &xosd);
+ }
+
+
+ if (!(hprc->pstate & ps_killed)) {
+
+ assert(hthd);
+
+ pde->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
+ pde->u.ExitThread.dwExitCode = hprc->dwExitCode;
+ NotifyEM(pde, hthd, 0, (LPVOID)0);
+
+ } else {
+
+ /*
+ * If ProcessTerminateProcessCmd() killed this,
+ * silently continue the event and release the semaphore.
+ *
+ * Don't notify the EM of anything; ProcessUnloadCmd()
+ * will do that for any undestroyed threads.
+ */
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ pde->dwProcessId,
+ pde->dwThreadId,
+ DBG_CONTINUE,
+ 0);
+ }
+
+#if defined(WIN32S)
+ ProcessUnloadCmd(hprc, NULL, NULL);
+#else
+ SetEvent(hprc->hExitEvent);
+#endif
+} /* ProcessExitProcessEvent() */
+
+
+
+void
+ProcessExitThreadEvent(
+ DEBUG_EVENT* pde,
+ HTHDX hthd
+ )
+{
+ HPRCX hprc = hthd->hprc;
+ PBREAKPOINT pbp;
+
+ DPRINT(3, ("***** ProcessExitThreadEvent, hthd == %x\n", (DWORD)hthd));
+
+
+ hthd->tstate |= ts_dead;
+
+ if (hthd->tstate & ts_frozen) {
+ ResumeThread(hthd->rwHand);
+ hthd->tstate &= ~ts_frozen;
+ }
+
+ hthd->dwExitCode = pde->u.ExitThread.dwExitCode;
+
+ //
+ // Free all events for this thread
+ //
+
+ ConsumeAllThreadEvents(hthd, TRUE);
+
+ //
+ // Clean up BP records
+ //
+
+ while (pbp = BPNextHthdPbp(hthd, NULL)) {
+ RemoveBP(pbp);
+ }
+
+ //
+ // Let the Expression Breakpoint manager know that this thread
+ // is gone.
+ //
+
+ ExprBPExitThread( hprc, hthd );
+
+
+ if (hprc->pstate & ps_killed) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ } else if (fDisconnected) {
+ hthd->hprc->pstate |= ps_exited;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ } else {
+ NotifyEM(pde, hthd, 0, (LPVOID)0);
+ }
+
+ return;
+} /* ProcessExitThreadEvent() */
+
+
+void
+ProcessLoadDLLEvent(
+ DEBUG_EVENT* de,
+ HTHDX hthd
+)
+{
+
+
+#ifndef KERNEL
+ LPSTR lpbPacket;
+ WORD cbPacket;
+
+ if (LoadDll(de, hthd, &cbPacket, &lpbPacket) || (cbPacket == 0)) {
+ LeaveCriticalSection(&csProcessDebugEvent);
+ NotifyEM(de, hthd, cbPacket, lpbPacket);
+ EnterCriticalSection(&csProcessDebugEvent);
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+#endif // !KERNEL
+
+
+#ifdef KERNEL
+ NotifyEM(de, hthd, 0, (LPVOID)0);
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+#endif // KERNEL
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+
+ return;
+} /* ProcessLoadDLLEvent() */
+
+
+void
+ProcessUnloadDLLEvent(
+ DEBUG_EVENT* pde,
+ HTHDX hthd
+ )
+{
+ int iDll;
+ HPRCX hprc = hthd->hprc;
+
+ DPRINT(10, ("*** UnloadDll %x\n", pde->u.UnloadDll.lpBaseOfDll));
+
+ for (iDll = 0; iDll < hprc->cDllList; iDll++) {
+ if (hprc->rgDllList[iDll].fValidDll &&
+ (hprc->rgDllList[iDll].offBaseOfImage ==
+ (OFFSET) pde->u.UnloadDll.lpBaseOfDll)) {
+ break;
+ }
+ }
+
+ /*
+ * Make sure that we found a legal address. If not then assert
+ * and check for problems.
+ */
+
+#ifndef KERNEL
+ // this happens all the time in kernel mode
+ // when user mode modloads are enabled
+ assert( iDll != hprc->cDllList );
+#endif
+
+ if (iDll != hprc->cDllList) {
+
+ if (!fDisconnected) {
+ LeaveCriticalSection(&csProcessDebugEvent);
+ NotifyEM(pde, hthd, 0, (LPVOID)0);
+ EnterCriticalSection(&csProcessDebugEvent);
+ }
+
+ DestroyDllLoadItem( &hprc->rgDllList[iDll] );
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+
+ return;
+}
+
+
+void
+DestroyDllLoadItem(
+ PDLLLOAD_ITEM pDll
+ )
+{
+ if (pDll->szDllName) {
+ free(pDll->szDllName);
+ pDll->szDllName = NULL;
+ }
+
+#ifdef KERNEL
+ if (pDll->sec) {
+ free(pDll->sec);
+ pDll->sec = NULL;
+ }
+#endif
+
+ pDll->offBaseOfImage = 0;
+ pDll->cbImage = 0;
+ pDll->fValidDll = FALSE;
+
+ return;
+}
+
+
+void
+ProcessOutputDebugStringEvent(
+ DEBUG_EVENT* de,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Handle an OutputDebugString from the debuggee
+
+Arguments:
+
+ de - Supplies DEBUG_EVENT struct
+
+ hthd - Supplies thread descriptor for thread
+ that generated the event
+
+Return Value:
+
+ None
+
+--*/
+{
+ int cb = de->u.DebugString.nDebugStringLength;
+
+#if DBG
+ DWORD cbR;
+ char rgch[256];
+ HANDLE rwHand;
+
+ if (FVerbose) {
+ cb = min(cb, 256);
+ rwHand = hthd->hprc->rwHand;
+ DbgReadMemory(hthd->hprc, de->u.DebugString.lpDebugStringData,
+ rgch, cb, &cbR);
+ rgch[cbR] = 0;
+
+ DPRINT(3, ("%s\n", rgch));
+ }
+#endif
+
+ NotifyEM(de, hthd, 0, NULL);
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+ hthd->tstate &= ~(ts_stopped | ts_first | ts_second );
+ hthd->tstate |= ts_running;
+
+ return;
+}
+
+
+
+void
+Reply(
+ UINT length,
+ LPVOID lpbBuffer,
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+ Send a reply packet to a tlfRequest from the EM
+
+Arguments:
+
+ length - Supplies length of reply
+
+ lpbBuffer - Supplies reply data
+
+ hpid - Supplies handle to EM process descriptor
+
+Return Value:
+
+ None
+
+--*/
+{
+ /*
+ * Add the size of the xosd return code to the message length
+ */
+
+ length += FIELD_OFFSET(DM_MSG, rgb);
+
+ DPRINT(5, ("Reply to EM [%d]\n", length));
+
+ assert(length <= sizeof(abDMReplyBuf) || lpbBuffer != abDMReplyBuf);
+
+ if (DmTlFunc) { // IF there is a TL loaded, reply
+ DmTlFunc(tlfReply, hpid, length, (LONG)(LPV) lpbBuffer);
+ }
+
+ return;
+}
+
+
+VOID FAR PASCAL
+DMFunc(
+ DWORD cb,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This is the main entry point for the DM. This takes dmf
+ message packets from the debugger and handles them, usually
+ by dispatching to a worker function.
+
+Arguments:
+
+ cb - supplies size of data packet
+ lpdbb - supplies pointer to packet
+
+Return Value:
+
+
+--*/
+{
+ DMF dmf;
+ HPRCX hprc;
+ HTHDX hthd;
+ XOSD xosd = xosdNone;
+
+
+ dmf = (DMF) (lpdbb->dmf & 0xffff);
+ DEBUG_PRINT("DMFunc\r\n");
+
+#ifdef WIN32S // Special cases to handle polling the dm for debug events
+ // and messages. None of these need hprc or hthd and in fact
+ // won't supply one. Don't even try to get it, you'll fault!
+ switch (dmf) {
+ case dmfPollForDebugEvents:
+ DmPoll();
+ return;
+
+ case dmfPollMessageLoop: // empty message queue
+ DmPollMessageLoop();
+ return;
+
+ default: // must be a normal dmf message, fall through
+ break;
+ }
+#endif
+
+ DPRINT(5, ("DmFunc [%2x] ", dmf));
+
+ hprc = HPRCFromHPID(lpdbb->hpid);
+ hthd = HTHDXFromHPIDHTID(lpdbb->hpid, lpdbb->htid);
+
+
+ ValidateHeap();
+ switch ( dmf ) {
+#ifndef OSDEBUG4
+ case dmfGetPrompt:
+ {
+ LPPROMPTMSG pm;
+ DPRINT(5, ("dmfGetPrompt\n"));
+ pm = (LPPROMPTMSG) LpDmMsg->rgb;
+ *pm = *((LPPROMPTMSG) lpdbb->rgbVar);
+ memcpy( pm, lpdbb->rgbVar, pm->len+sizeof(PROMPTMSG) );
+
+#if defined(WIN32S)
+ strcpy( pm->szPrompt, "WIN32S> " );
+#elif defined(KERNEL) && defined(TARGET_i386)
+ strcpy( pm->szPrompt, "KDx86> " );
+#elif defined(KERNEL) && defined(TARGET_PPC)
+ strcpy( pm->szPrompt, "KDppc> " );
+#elif defined(KERNEL) && defined(TARGET_MIPS)
+ strcpy( pm->szPrompt, "KDmips> " );
+#elif defined(KERNEL) && defined(TARGET_ALPHA)
+ strcpy( pm->szPrompt, "KDalpha> " );
+#elif defined(KERNEL)
+
+#pragma error( "unknown target machine" );
+
+#else
+
+ // don't change prompt in user mode
+
+#endif
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( pm->len+sizeof(PROMPTMSG), LpDmMsg, lpdbb->hpid );
+ }
+ break;
+#endif
+
+ case dmfSetMulti:
+ DPRINT(5, ("dmfSetMulti\n"));
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case dmfClearMulti:
+ DPRINT(5, ("dmfClearMulti\n"));
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case dmfDebugger:
+ DPRINT(5, ("dmfDebugger\n"));
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case dmfCreatePid:
+ DPRINT(5,("dmfCreatePid\r\n"));
+ ProcessCreateProcessCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfDestroyPid:
+ DPRINT(5, ("dmfDestroyPid\n"));
+ LpDmMsg->xosdRet = FreeProcess(hprc, TRUE);
+ Reply( 0, LpDmMsg, lpdbb->hpid);
+ break;
+
+ case dmfProgLoad:
+ DPRINT(5, ("dmfProgLoad\n"));
+ ProcessLoadCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfProgFree:
+ DPRINT(5, ("dmfProgFree\n"));
+
+
+#ifndef KERNEL
+
+ ProcessTerminateProcessCmd(hprc, hthd, lpdbb);
+
+#else // KERNEL
+ if (!hprc) {
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid);
+ break;
+ }
+
+ if (KdOptions[KDO_GOEXIT].value) {
+ HTHDX hthdT;
+ PBREAKPOINT bp;
+ KdOptions[KDO_GOEXIT].value = 0;
+ for (hthdT = hprc->hthdChild; hthdT; hthdT = hthdT->nextSibling) {
+ if (hthdT->tstate & ts_stopped) {
+ if (bp = AtBP(hthdT)) {
+ if (!hthdT->fDontStepOff) {
+ IncrementIP(hthdT);
+ }
+ }
+ if (hthdT->fContextDirty) {
+ DbgSetThreadContext( hthdT, &hthdT->context );
+ hthdT->fContextDirty = FALSE;
+ }
+ KdOptions[KDO_GOEXIT].value = 1;
+ break;
+ }
+ }
+ }
+
+ ClearBps();
+
+ ProcessTerminateProcessCmd(hprc, hthd, lpdbb);
+ ProcessUnloadCmd(hprc, hthd, lpdbb);
+
+ if (KdOptions[KDO_GOEXIT].value) {
+ ContinueTargetSystem( DBG_CONTINUE, NULL );
+ }
+
+
+#endif // KERNEL
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid);
+ break;
+
+ case dmfBreakpoint:
+ DEBUG_PRINT("dmfBreakpoint\r\n");
+ ProcessBreakpointCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfReadMem:
+ // This replies in the function
+ DPRINT(5, ("dmfReadMem\n"));
+ ProcessReadMemoryCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfWriteMem:
+ DPRINT(5, ("dmfWriteMem\n"));
+ ProcessWriteMemoryCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfReadReg:
+ DPRINT(5, ("dmfReadReg\n"));
+ ProcessGetContextCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfWriteReg:
+ DPRINT(5, ("dmfWriteReg\n"));
+ ProcessSetContextCmd(hprc, hthd, lpdbb);
+ break;
+
+
+#ifdef HAS_DEBUG_REGS
+ case dmfReadRegEx:
+ DPRINT(5, ("dmfReadRegEx\n"));
+#ifdef KERNEL
+ ProcessGetExtendedContextCmd(hprc, hthd, lpdbb);
+#else
+ ProcessGetDRegsCmd(hprc, hthd, lpdbb);
+#endif
+ break;
+
+ case dmfWriteRegEx:
+ DPRINT(5, ("dmfWriteRegEx\n"));
+#ifdef KERNEL
+ ProcessSetExtendedContextCmd(hprc, hthd, lpdbb);
+#else
+ ProcessSetDRegsCmd(hprc, hthd, lpdbb);
+#endif
+ break;
+
+#else // i386 || PPC
+ case dmfReadRegEx:
+ case dmfWriteRegEx:
+ DEBUG_PRINT("Read/WriteRegEx\r\n");
+ assert(dmf != dmfReadRegEx && dmf != dmfWriteRegEx);
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+#endif // !i386 || PPC
+
+ case dmfReadFrameReg:
+ DPRINT(5, ("dmfReadFrameReg\n"));
+ ProcessGetFrameContextCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfGo:
+ DPRINT(5, ("dmfGo\n"));
+ ProcessContinueCmd(hprc, hthd, lpdbb);
+ break;
+
+#if defined(KERNEL)
+ case dmfTerm:
+ DPRINT(5, ("dmfTerm\n"));
+ ProcessTerminateProcessCmd(hprc, hthd, lpdbb);
+ break;
+#endif
+
+ case dmfStop:
+ DPRINT(5, ("dmfStop\n"));
+ ProcessAsyncStopCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfFreeze:
+ DPRINT(5, ("dmfFreeze\n"));
+ ProcessFreezeThreadCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfResume:
+ DPRINT(5, ("dmfResume\n"));
+ ProcessAsyncGoCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfInit:
+ DPRINT(5, ("dmfInit\n"));
+ Reply( 0, &xosd, lpdbb->hpid);
+ break;
+
+ case dmfUnInit:
+ DPRINT(5, ("dmfUnInit\n"));
+#ifdef KERNEL
+ DmPollTerminate();
+#endif
+ Reply ( 1, LpDmMsg, lpdbb->hpid);
+#ifndef KERNEL
+ Cleanup();
+#endif
+ break;
+
+ case dmfGetDmInfo:
+ DEBUG_PRINT("getDmInfo\r\n");
+ ProcessGetDmInfoCmd(hprc, lpdbb, cb);
+ break;
+
+ case dmfSetupExecute:
+ DPRINT(5, ("dmfSetupExecute\n"));
+ ProcessSetupExecuteCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfStartExecute:
+ DPRINT(5, ("dmfStartExecute\n"));
+ ProcessStartExecuteCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfCleanUpExecute:
+ DPRINT(5, ("dmfCleanupExecute\n"));
+ ProcessCleanUpExecuteCmd(hprc, hthd, lpdbb);
+ break;
+
+#ifdef OSDEBUG4
+ case dmfSystemService:
+ assert(0);
+ break;
+#else
+ case dmfIOCTL:
+ DPRINT(5, ("dmfIOCTL\n"));
+ ProcessIoctlCmd( hprc, hthd, lpdbb );
+ break;
+#endif
+
+ case dmfDebugActive:
+ DPRINT(5, ("dmfDebugActive\n"));
+ ProcessDebugActiveCmd( hprc, hthd, lpdbb);
+ break;
+
+ case dmfSetPath:
+ DPRINT(5, ("dmfSetPath\n"));
+ ProcessSetPathCmd( hprc, hthd, lpdbb );
+ break;
+
+ case dmfQueryTlsBase:
+ DPRINT(5, ("dmfQueryTlsBase\n"));
+ ProcessQueryTlsBaseCmd(hprc, hthd, lpdbb );
+ break;
+
+ case dmfQuerySelector:
+ //DPRINT(5, ("dmfQuerySelector\n"));
+ ProcessQuerySelectorCmd(hprc, hthd, lpdbb );
+ break;
+
+ case dmfVirtualQuery:
+ DEBUG_PRINT("VirtualQuery\r\n");
+ ProcessVirtualQueryCmd(hprc, lpdbb);
+ break;
+
+ case dmfRemoteQuit:
+ DEBUG_PRINT("RemoteQuit\r\n");
+ ProcessRemoteQuit();
+ break;
+
+#ifdef KERNEL
+ case dmfGetSections:
+ ProcessGetSectionsCmd( hprc, hthd, lpdbb );
+ break;
+#endif
+
+ case dmfSetExceptionState:
+ DEBUG_PRINT("SetExceptionState\r\n");
+ ProcessSetExceptionState(hprc, hthd, lpdbb);
+ break;
+
+ case dmfGetExceptionState:
+ DEBUG_PRINT("GetExceptionState\r\n");
+ ProcessGetExceptionState(hprc, hthd, lpdbb);
+ break;
+
+ case dmfSingleStep:
+ DEBUG_PRINT("SingleStep\r\n");
+ ProcessSingleStepCmd(hprc, hthd, lpdbb);
+ break;
+
+ case dmfRangeStep:
+ DEBUG_PRINT("RangeStep\r\n");
+ ProcessRangeStepCmd(hprc, hthd, lpdbb);
+ break;
+
+#if 0
+ case dmfReturnStep:
+ ProcessReturnStepCmd(hprc, hthd, lpdbb);
+ break;
+#endif
+
+ case dmfThreadStatus:
+ DEBUG_PRINT("ThreadStatus\r\n");
+ Reply( ProcessThreadStatCmd(hprc, hthd, lpdbb), LpDmMsg, lpdbb->hpid);
+ break;
+
+ case dmfProcessStatus:
+ DEBUG_PRINT("ProcessStatus\r\n");
+ Reply( ProcessProcStatCmd(hprc, hthd, lpdbb), LpDmMsg, lpdbb->hpid);
+ break;
+
+ default:
+ DPRINT(5, ("Unknown\n"));
+ assert(FALSE);
+ break;
+ }
+
+ return;
+} /* DMFunc() */
+
+
+#ifndef KERNEL
+
+#ifndef WIN32S
+BOOL
+StartDmPollThread(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This creates the DM poll thread.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE if the thread was successfully created or already
+ existed.
+
+--*/
+{
+ DWORD tid;
+
+ if (hDmPollThread) {
+ return TRUE;
+ }
+
+ hDmPollThread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)CallDmPoll,0,0,&tid);
+ SetThreadPriority( hDmPollThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ return hDmPollThread != 0;
+}
+BOOL
+StartCrashPollThread(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This creates the DM poll thread for a crash dump file.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE if the thread was successfully created or already existed.
+
+--*/
+{
+ DWORD tid;
+
+ if (hDmPollThread) {
+ return TRUE;
+ }
+
+ hDmPollThread = CreateThread(0,0,(LPTHREAD_START_ROUTINE)CrashDumpThread,0,0,&tid);
+ SetThreadPriority( hDmPollThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ return hDmPollThread != 0;
+}
+
+VOID
+CrashDumpThread(
+ LPVOID lpv
+ )
+{
+ HPRCX hprc;
+ HTHDX hthd;
+ HTHDX hthdNew;
+ LPSTR lpbPacket;
+ WORD cbPacket;
+ PCRASH_MODULE CrashModule;
+ DEBUG_EVENT de;
+ DWORD i;
+ CHAR buf[32];
+ LPSTR lpProgName = (LPSTR)lpv;
+ DWORD DumpVer = CrashDumpHeader->MajorVersion;
+
+
+ CrashDump = TRUE;
+
+ //
+ // simulate a create process debug event
+ //
+ CrashModule = (PCRASH_MODULE)((PUCHAR)CrashDumpHeader+CrashDumpHeader->ModuleOffset);
+ de.dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
+ de.dwProcessId = 1;
+ de.dwThreadId = 1;
+ de.u.CreateProcessInfo.hFile = NULL;
+ de.u.CreateProcessInfo.hProcess = NULL;
+ de.u.CreateProcessInfo.hThread = NULL;
+ de.u.CreateProcessInfo.lpBaseOfImage = (LPVOID)CrashModule->BaseOfImage;
+ de.u.CreateProcessInfo.dwDebugInfoFileOffset = 0;
+ de.u.CreateProcessInfo.nDebugInfoSize = 0;
+ de.u.CreateProcessInfo.lpStartAddress = NULL;
+ de.u.CreateProcessInfo.lpThreadLocalBase = NULL;
+ if (!CrashModule->ImageName[0]) {
+ de.u.CreateProcessInfo.lpImageName = "mod0.dll";
+ } else {
+ de.u.CreateProcessInfo.lpImageName = CrashModule->ImageName;
+ }
+ strcpy( nameBuffer, de.u.CreateProcessInfo.lpImageName);
+ de.u.CreateProcessInfo.fUnicode = FALSE;
+ ProcessDebugEvent(&de);
+ WaitForSingleObject( hEventCreateProcess, INFINITE );
+
+ //
+ // mark the process as 'being connected' so that the continue debug
+ // events that are received from the shell are ignored
+ //
+ hprc = HPRCFromPID(1);
+ hthd = hprc->hthdChild;
+ hprc->pstate |= ps_connect;
+
+ if (DumpVer >= 4) {
+ DmpGetThread( 0, &hthd->CrashThread );
+ } else {
+ ZeroMemory(&hthd->CrashThread, sizeof(CRASH_THREAD));
+ hthd->CrashThread.ThreadId = hthd->tid;
+ }
+
+ //
+ // generates the mod load events
+ //
+ for (i=1; i<CrashDumpHeader->ModuleCount; i++) {
+ CrashModule = (PCRASH_MODULE) ( (PUCHAR)CrashModule +
+ sizeof(CRASH_MODULE) +
+ CrashModule->ImageNameLength );
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = 1;
+ de.dwThreadId = 1;
+ de.u.LoadDll.hFile = NULL;
+ de.u.LoadDll.lpBaseOfDll = (LPVOID)CrashModule->BaseOfImage;
+ if (!CrashModule->ImageName[0]) {
+ sprintf( buf, "mod%d.dll", i );
+ de.u.LoadDll.lpImageName = buf;
+ } else {
+ de.u.LoadDll.lpImageName = CrashModule->ImageName;
+ }
+ de.u.LoadDll.fUnicode = FALSE;
+ de.u.LoadDll.nDebugInfoSize = 0;
+ de.u.LoadDll.dwDebugInfoFileOffset = 0;
+ if (LoadDll(&de,hthd,&cbPacket,&lpbPacket) && (cbPacket != 0)) {
+ NotifyEM(&de, hthd, cbPacket, lpbPacket);
+ }
+ }
+
+ //
+ // create all of the threads
+ //
+ for (i=1; i<CrashDumpHeader->ThreadCount; i++) {
+ //
+ // generate a thread create event
+ //
+ ResetEvent( hprc->hEventCreateThread );
+ ResetEvent( hEventContinue );
+ de.dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = i + 1;
+ de.u.CreateThread.hThread = (HANDLE) (i + 1);
+ de.u.CreateThread.lpThreadLocalBase = 0;
+ de.u.CreateThread.lpStartAddress = 0;
+
+ //
+ // Take critical section here so that it is still
+ // held after leaving ProcessDebugEvent
+ //
+ EnterCriticalSection(&csProcessDebugEvent);
+ ProcessDebugEvent(&de);
+ hthdNew = HTHDXFromPIDTID(1,(i+1));
+ DbgGetThreadContext( hthdNew, &hthdNew->context );
+ if (DumpVer >= 4) {
+ DmpGetThread( i, &hthdNew->CrashThread );
+ } else {
+ ZeroMemory(&hthdNew->CrashThread, sizeof(CRASH_THREAD));
+ hthdNew->CrashThread.ThreadId = hthdNew->tid;
+ }
+ LeaveCriticalSection(&csProcessDebugEvent);
+ WaitForSingleObject( hprc->hEventCreateThread, INFINITE );
+
+ //
+ // wait for the shell to continue the new thread
+ //
+ WaitForSingleObject( hEventContinue, INFINITE );
+ }
+
+ //
+ // generate a load complete debug event
+ //
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hprc->hthdChild->tid;
+ de.dwDebugEventCode = LOAD_COMPLETE_DEBUG_EVENT;
+ NotifyEM( &de, hthd, 0, 0L);
+
+ WaitForSingleObject( hEventContinue, INFINITE );
+
+ //
+ // Get the debug event for the crash
+ //
+ if (DumpVer >= 4) {
+ de = *(LPDEBUG_EVENT)((PUCHAR)CrashDumpHeader+CrashDumpHeader->DebugEventOffset);
+ //
+ // convert the thread and process ids into the internal version...
+ //
+ de.dwProcessId = 1;
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->next) {
+ if (de.dwThreadId == hthd->CrashThread.ThreadId) {
+ de.dwThreadId = hthd->tid;
+ break;
+ }
+ }
+ } else {
+ //
+ // if this is an old crashdump file, try to find the crashed thread
+ //
+ de.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ de.u.Exception.ExceptionRecord = *CrashException;
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->next) {
+ if (PC(hthd) == (DWORD)CrashException->ExceptionAddress) {
+ de.dwThreadId = hthd->tid;
+ }
+ }
+ }
+
+ ProcessDebugEvent( &de );
+
+ while (!fDmPollQuit) {
+ //
+ // Handle kill commands
+ //
+ if (KillQueue) {
+ CompleteTerminateProcessCmd();
+ }
+ Sleep( 500 );
+ }
+}
+
+VOID
+CallDmPoll(
+ LPVOID lpv
+ )
+
+/*++
+
+Routine Description:
+
+ This is the debug event loop. This routine creates or
+ attaches to child process, and monitors them for debug
+ events. It serializes the dispatching of events from
+ multiple process, and continues the events when the
+ worker functions have finished processing the events.
+
+Arguments:
+
+ lpv - Supplies an argument provided by CreateThread.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DEBUG_EVENT de;
+ PROCESS_INFORMATION pi;
+ int nprocs = 0;
+ UINT ErrMode;
+
+ Unreferenced( lpv );
+ DEBUG_PRINT("CallDmPoll\r\n");
+
+ //
+ // Crank up priority to improve performance, and improve our
+ // chances of winning races with the debuggee.
+ //
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+
+ fDmPollQuit = FALSE;
+ while (!fDmPollQuit) {
+
+#ifndef WIN32S
+ //
+ // Handle kill commands
+ //
+ if (KillQueue) {
+ CompleteTerminateProcessCmd();
+ goto doContinues;
+ }
+#endif
+
+ //
+ // Handle spawn commands
+ //
+ if (SpawnStruct.fSpawn) {
+ SpawnStruct.fSpawn = FALSE;
+#ifndef WIN32S
+ ErrMode = SetErrorMode( 0 );
+#endif
+ SpawnStruct.fReturn =
+ CreateProcess( SpawnStruct.szAppName,
+ SpawnStruct.szArgs,
+ NULL,
+ NULL,
+ SpawnStruct.fInheritHandles,
+ SpawnStruct.fdwCreate,
+ NULL,
+ NULL,
+ &SpawnStruct.si,
+ &pi
+ );
+#ifndef WIN32S
+ SetErrorMode( ErrMode );
+#endif
+ if (SpawnStruct.fReturn == 0) {
+ SpawnStruct.dwError = GetLastError();
+ } else {
+ SpawnStruct.dwError = 0;
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ }
+
+ SetEvent(SpawnStruct.hEventApiDone);
+ }
+
+ //
+ // Handle attach commands
+ //
+ if (DebugActiveStruct.fAttach) {
+ DebugActiveStruct.fAttach = FALSE;
+ DebugActiveStruct.fReturn = DebugActiveProcess(DebugActiveStruct.dwProcessId);
+ if (DebugActiveStruct.fReturn == 0) {
+ DebugActiveStruct.dwError = GetLastError();
+ } else {
+ DebugActiveStruct.dwError = 0;
+ }
+ SetEvent(DebugActiveStruct.hEventApiDone);
+ }
+
+ if (WtStruct.fWt) {
+ WtStruct.fWt = FALSE;
+ switch(WtStruct.dwType) {
+ case IG_WATCH_TIME_STOP:
+ WtStruct.hthd->wtmode = 2;
+ break;
+
+ case IG_WATCH_TIME_RECALL:
+ break;
+
+ case IG_WATCH_TIME_PROCS:
+ break;
+ }
+ }
+
+ if (WaitForDebugEvent(&de, (DWORD) WAITFORDEBUG_MS)) {
+
+ if ( de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT ) {
+ assert(HPRCFromPID(de.dwProcessId) == NULL);
+ if (nprocs == 0) {
+ ResetEvent(hEventNoDebuggee);
+ }
+ ++nprocs;
+ } else if ( de.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) {
+ --nprocs;
+ }
+
+ if (fDisconnected) {
+ if (de.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT ||
+ de.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT ||
+ de.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT ||
+ de.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT ) {
+
+ //
+ // we can process these debug events very carefully
+ // while disconnected from the shell. the only requirement
+ // is that the dm doesn't call NotifyEM while disconnected.
+ //
+
+ } else {
+
+ WaitForSingleObject( hEventRemoteQuit, INFINITE );
+ ResetEvent( hEventRemoteQuit );
+ fDisconnected = FALSE;
+ //
+ // this is a remote session reconnecting
+ //
+ ReConnectDebugger( &de, FALSE );
+
+ }
+ }
+
+ ProcessDebugEvent(&de);
+
+ } else if (WaitForSingleObject( hEventRemoteQuit, 0 ) ==
+ WAIT_OBJECT_0) {
+
+ //
+ // this is a remote session reconnecting
+ //
+ ResetEvent( hEventRemoteQuit );
+ ReConnectDebugger( NULL, FALSE );
+
+ } else if (nWaitingForLdrBreakpoint) {
+
+ // look for processes that are looking for a loader bp.
+ // See how long it has been since they got an event.
+
+ HPRCX hprc;
+
+ EnterCriticalSection(&csThreadProcList);
+ for (hprc = prcList->next; hprc; hprc = hprc->next) {
+ if (hprc->pstate & ps_preStart) {
+ if (++hprc->cLdrBPWait > LDRBP_MAXTICKS) {
+ // Signal a timeout for this one.
+ // just jump out of this loop - if
+ // another one is going to time out,
+ // it can do it on the next pass.
+ break;
+ }
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+
+ if (hprc) {
+ HandleDebugActiveDeadlock(hprc);
+ }
+
+ } else if (nprocs == 0) {
+
+ Sleep(WAITFORDEBUG_MS);
+
+ }
+
+ doContinues:
+ if (DequeueAllEvents(TRUE, FALSE) && nprocs <= 0) {
+ SetEvent(hEventNoDebuggee);
+ }
+ }
+
+ DEBUG_PRINT("CallDmPoll Exit\r\n");
+ return;
+} /* CallDmPoll() */
+#endif // !WIN32S
+
+
+#ifdef WIN32S
+
+/*
+ * DmPollMessageLoop
+ *
+ * INPUTS none
+ *
+ * OUTPUTS none
+ *
+ * SUMMARY while there are messages, process them. If we are processing
+ * a debug event, don't allow a task switch. (Win32s doesn't like
+ * that.)
+ */
+
+void DmPollMessageLoop(void) {
+ UINT uFlags;
+ MSG msg;
+
+
+ uFlags = fProcessingDebugEvent ? PM_REMOVE | PM_NOYIELD : PM_REMOVE;
+
+ if (PeekMessage(&msg, NULL, 0, 0, uFlags)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+
+ // update flags in case the ContinueDebugEvent has been called during
+ // the Dispatch.
+ uFlags = fProcessingDebugEvent ? PM_REMOVE | PM_NOYIELD : PM_REMOVE;
+ }
+}
+
+
+/*
+ * DmPoll
+ *
+ * INPUTS none
+ *
+ * OUTPUT returns TRUE if we've processed a debug event.
+ *
+ * SUMMARY If there is a debug event ready, process it.
+ *
+ *
+ */
+BOOL DmPoll(void)
+{
+ DEBUG_EVENT de;
+ BOOL fRet = FALSE;
+
+
+ if (! fWaitForDebugEvent) {
+
+ fWaitForDebugEvent = TRUE;
+ if (WaitForDebugEvent(&de, 0)) {
+ ProcessDebugEvent(&de);
+ fRet = TRUE;
+ }
+ else {
+ fWaitForDebugEvent = FALSE;
+ }
+ }
+ return(fRet);
+}
+#endif // WIN32S
+
+#ifndef WIN32S
+BOOL
+SetDebugPrivilege(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Enables SeDebugPrivilege if possible.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE on success, FALSE on failure
+
+--*/
+{
+ HANDLE hToken;
+ LUID DebugValue;
+ TOKEN_PRIVILEGES tkp;
+ BOOL rVal = TRUE;
+
+ if (!OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+ return FALSE;
+ }
+
+ if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &DebugValue)) {
+
+ rVal = FALSE;
+
+ } else {
+
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Luid = DebugValue;
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ AdjustTokenPrivileges(hToken,
+ FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
+
+ if (GetLastError() != ERROR_SUCCESS) {
+ rVal = FALSE;
+ }
+ }
+
+ CloseHandle(hToken);
+
+ return rVal;
+}
+#endif // !WIN32S
+
+#endif // !KERNEL
+
+
+/********************************************************************/
+/* */
+/* Dll Version */
+/* */
+/********************************************************************/
+
+#ifdef KERNEL
+
+#ifdef DEBUGVER
+DEBUG_VERSION('D','M',"WIN32 Kernel Debugger Monitor")
+#else
+RELEASE_VERSION('D','M',"WIN32 Kernel Debugger Monitor")
+#endif
+
+#else // KERNEL
+
+#ifdef DEBUGVER
+DEBUG_VERSION('D','M',"WIN32 Debugger Monitor")
+#else
+RELEASE_VERSION('D','M',"WIN32 Debugger Monitor")
+#endif
+
+#endif // KERNEL
+
+DBGVERSIONCHECK()
+
+
+DllInit(
+ HANDLE hModule,
+ DWORD dwReason,
+ DWORD dwReserved
+ )
+/*++
+
+Routine Description:
+
+ Entry point called by the loader during DLL initialization
+ and deinitialization. This creates and destroys some per-
+ instance objects.
+
+Arguments:
+
+ hModule - Supplies base address of dll
+
+ dwReason - Supplies flags describing why we are here
+
+ dwReserved - depends on dwReason.
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+ Unreferenced(hModule);
+ Unreferenced(dwReserved);
+
+ switch (dwReason) {
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ CloseHandle(SpawnStruct.hEventApiDone);
+ CloseHandle(hEventCreateProcess);
+ CloseHandle(hEventRemoteQuit);
+ CloseHandle(hEventNoDebuggee);
+ CloseHandle(hEventContinue);
+
+ DeleteCriticalSection(&csProcessDebugEvent);
+ DeleteCriticalSection(&csThreadProcList);
+ DeleteCriticalSection(&csEventList);
+ DeleteCriticalSection(&csWalk);
+#if !defined(KERNEL) && !defined(WIN32S)
+ CloseHandle(DebugActiveStruct.hEventApiDone);
+ CloseHandle(DebugActiveStruct.hEventReady);
+ DeleteCriticalSection(&csKillQueue);
+#endif
+ break;
+
+ case DLL_PROCESS_ATTACH:
+
+ InitializeCriticalSection(&csProcessDebugEvent);
+ InitializeCriticalSection(&csThreadProcList);
+ InitializeCriticalSection(&csEventList);
+ InitializeCriticalSection(&csWalk);
+
+ hEventCreateProcess = CreateEvent(NULL, TRUE, FALSE, NULL);
+ hEventRemoteQuit = CreateEvent(NULL, TRUE, FALSE, NULL);
+ hEventContinue = CreateEvent(NULL, TRUE, FALSE, NULL);
+ hEventNoDebuggee = CreateEvent(NULL, TRUE, FALSE, NULL);
+ SpawnStruct.hEventApiDone = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+#if !defined(KERNEL) && !defined(WIN32S)
+ InitializeCriticalSection(&csKillQueue);
+ DebugActiveStruct.hEventApiDone = CreateEvent(NULL, TRUE, TRUE, NULL);
+ DebugActiveStruct.hEventReady = CreateEvent(NULL, TRUE, TRUE, NULL);
+
+ SetDebugPrivilege();
+
+ /*
+ * These parameters are from SCOTTLU
+ */
+
+ SetProcessShutdownParameters(0x3ff, 0);
+
+#endif
+#if !defined(KERNEL)
+ //
+ // get helpful info
+ //
+
+ GetSystemInfo(&SystemInfo);
+ OsVersionInfo.dwOSVersionInfoSize = sizeof(OsVersionInfo);
+ GetVersionEx(&OsVersionInfo);
+
+#if defined (TARGET_MIPS)
+
+ if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
+ (OsVersionInfo.dwBuildNumber & 0xffff) > 1144) {
+ MipsContextSize = Ctx64Bit;
+ } else {
+ MipsContextSize = Ctx32Bit;
+ }
+
+#endif // TARGET_MIPS
+
+#endif // KERNEL
+
+ break;
+ }
+
+ return TRUE;
+}
+
+
+
+BOOL FAR PASCAL
+DmDllInit(
+ LPDBF lpb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the shell (debugger or remote stub)
+ to provide a service callback vector to the DM.
+
+Arguments:
+
+ lpb - Supplies an array of functions for callbacks
+
+Return Value:
+
+ TRUE if successfully initialized and FALSE othewise.
+
+--*/
+
+{
+ lpdbf = lpb;
+ return TRUE;
+} /* DmDllInit() */
+
+#ifdef KERNEL
+
+
+XOSD FAR PASCAL
+DMInit(
+ DMTLFUNCTYPE lpfnTl,
+ LPSTR lpch
+ )
+/*++
+
+Routine Description:
+
+ This is the entry point called by the TL to initialize the
+ connection from DM to TL.
+
+Arguments:
+
+ lpfnTl - Supplies entry point to TL
+ lpch - Supplies command line arg list
+
+Return Value:
+
+ XOSD value: xosdNone for success, other values reflect reason
+ for failure to initialize properly.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ LPSTR p;
+
+
+ if (strlen(lpch)) {
+ p = lpch;
+ if (strncmp(p, DM_SIDE_L_INIT_SWITCH, sizeof(DM_SIDE_L_INIT_SWITCH))==0) {
+ FDMRemote = TRUE;
+ p += sizeof(DM_SIDE_L_INIT_SWITCH);
+ }
+ ParseDmParams( p );
+ }
+
+ if (lpfnTl != NULL) {
+ // Are we the DM side of a remote debug session (DBTarget passes this)?
+ if (strstr(lpch, DM_SIDE_L_INIT_SWITCH)) {
+ FDMRemote = TRUE;
+ }
+
+ /* Define a false single step event */
+ falseSSEvent.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ falseSSEvent.u.Exception.ExceptionRecord.ExceptionCode
+ = EXCEPTION_SINGLE_STEP;
+
+ falseBPEvent.dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;
+ falseBPEvent.u.Exception.ExceptionRecord.ExceptionCode
+ = EXCEPTION_BREAKPOINT;
+
+ /* Define the standard notification method */
+ EMNotifyMethod.notifyFunction = NotifyEM;
+ EMNotifyMethod.lparam = (LPVOID)0;
+
+ SearchPathString[0] = '\0';
+ SearchPathSet = FALSE;
+
+ SetDebugErrorLevel(SLE_WARNING);
+
+ /*
+ ** Save the pointer to the Transport layer entry function
+ */
+
+ DmTlFunc = lpfnTl;
+
+ /*
+ ** Try and connect up to the other side of the link
+ */
+
+ DmTlFunc( tlfSetBuffer, NULL, sizeof(abEMReplyBuf), (LONG)(LPV) abEMReplyBuf );
+
+ xosd = DmTlFunc( tlfConnect, hpidNull, 0, 0 );
+
+ DPRINT(10, ("DM & TL are now connected\n"));
+
+ } else {
+
+ DmTlFunc( tlfDisconnect, hpidNull, 0, 0);
+ DmTlFunc( tlfSetBuffer, hpidNull, 0, 0);
+ FDMRemote = FALSE;
+ DmTlFunc = (DMTLFUNCTYPE) NULL;
+
+ }
+
+ return xosd;
+} /* DmInit() */
+
+
+void
+ParseDmParams(
+ LPSTR p
+ )
+{
+ DWORD i;
+ CHAR szPath[MAX_PATH];
+ CHAR szStr[_MAX_PATH];
+ LPSTR lpPathNext;
+ LPSTR lpsz1;
+ LPSTR lpsz2;
+ LPSTR lpsz3;
+
+
+ for (i=0; i<MAX_MODULEALIAS; i++) {
+ if (!ModuleAlias[i].Special) {
+ ZeroMemory( &ModuleAlias[i], sizeof(MODULEALIAS) );
+ }
+ }
+
+ do {
+ p = strtok( p, "=" );
+ if (p) {
+ for (i=0; i<MAXKDOPTIONS; i++) {
+ if (_stricmp(KdOptions[i].keyword,p)==0) {
+ break;
+ }
+ }
+ if (i < MAXKDOPTIONS) {
+ p = strtok( NULL, " " );
+ if (p) {
+ switch (KdOptions[i].typ) {
+ case KDT_DWORD:
+ KdOptions[i].value = atol( p );
+ break;
+
+ case KDT_STRING:
+ KdOptions[i].value = (DWORD) _strdup( p );
+ break;
+ }
+ p = p + (strlen(p) + 1);
+ }
+ } else {
+ if (_stricmp( p, "alias" ) == 0) {
+ p = strtok( NULL, "#" );
+ if (p) {
+ for (i=0; i<MAX_MODULEALIAS; i++) {
+ if (ModuleAlias[i].ModuleName[0] == 0) {
+ break;
+ }
+ }
+ if (i < MAX_MODULEALIAS) {
+ strcpy( ModuleAlias[i].ModuleName, p );
+ p = strtok( NULL, " " );
+ if (p) {
+ strcpy( ModuleAlias[i].Alias, p );
+ p = p + (strlen(p) + 1);
+ }
+ } else {
+ p = strtok( NULL, " " );
+ }
+ }
+ } else {
+ p = strtok( NULL, " " );
+ }
+ }
+ }
+ } while(p && *p);
+
+ if (KdOptions[KDO_VERBOSE].value > 1) {
+ FVerbose = KdOptions[KDO_VERBOSE].value;
+ }
+ else {
+ FVerbose = 0;
+ }
+
+ szPath[0] = 0;
+ lpPathNext = strtok((LPSTR)KdOptions[KDO_SYMBOLPATH].value, ";");
+ while (lpPathNext) {
+ lpsz1 = szStr;
+ while ((lpsz2 = strchr(lpPathNext, '%')) != NULL) {
+ strncpy(lpsz1, lpPathNext, lpsz2 - lpPathNext);
+ lpsz1 += lpsz2 - lpPathNext;
+ lpsz2++;
+ lpPathNext = strchr(lpsz2, '%');
+ if (lpPathNext != NULL) {
+ *lpPathNext++ = 0;
+ lpsz3 = getenv(lpsz2);
+ if (lpsz3 != NULL) {
+ strcpy(lpsz1, lpsz3);
+ lpsz1 += strlen(lpsz3);
+ }
+ } else {
+ lpPathNext = "";
+ }
+ }
+ strcpy(lpsz1, lpPathNext);
+ strcat( szPath, szStr );
+ strcat( szPath, ";" );
+ lpPathNext = strtok(NULL, ";");
+ }
+
+ if ( szPath[0] != 0 ) {
+ if (szPath[strlen(szPath)-1] == ';') {
+ szPath[strlen(szPath)-1] = '\0';
+ }
+ strcpy( (LPSTR)KdOptions[KDO_SYMBOLPATH].value, szPath );
+ }
+}
+
+
+VOID
+ProcessRemoteQuit(
+ VOID
+ )
+{
+ HPRCX hprc;
+ PBREAKPOINT pbp;
+ PBREAKPOINT pbpT;
+
+
+ EnterCriticalSection(&csThreadProcList);
+
+ for(hprc=prcList->next; hprc; hprc=hprc->next) {
+ for (pbp = BPNextHprcPbp(hprc, NULL); pbp; pbp = pbpT) {
+ pbpT = BPNextHprcPbp(hprc, pbp);
+ RemoveBP(pbp);
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ fDisconnected = TRUE;
+ ResetEvent( hEventRemoteQuit );
+}
+
+#endif // KERNEL
+
+
+#ifndef KERNEL
+
+
+
+XOSD FAR PASCAL
+DMInit(
+ DMTLFUNCTYPE lpfnTl,
+ LPSTR lpch
+ )
+/*++
+
+Routine Description:
+
+ This is the entry point called by the TL to initialize the
+ connection from DM to TL.
+
+Arguments:
+
+ lpfnTl - Supplies entry point to TL
+
+ lpch - Supplies command line arg list
+
+Return Value:
+
+ XOSD value: xosdNone for success, other values reflect reason
+ for failure to initialize properly.
+
+--*/
+{
+ int i, n;
+ XOSD xosd;
+#ifdef WIN32S
+ HMODULE hModule;
+#endif
+
+ DEBUG_PRINT("DMInit\r\n");
+
+ if (lpfnTl != NULL) {
+ /*
+ ** Parse out anything interesting from the command line args
+ */
+
+#ifndef OSDEBUG4
+#if DBG
+ if (strstr(lpch, "V=10")) {
+ lpch += 5;
+ FVerbose = 10;
+ } else if (strstr(lpch, "V=1")) {
+ lpch += 4;
+ FVerbose = 1;
+ }
+#endif
+
+ // Are we the DM side of a remote debug session (DBTarget passes this)?
+ if (strstr(lpch, DM_SIDE_L_INIT_SWITCH)) {
+ FDMRemote = TRUE;
+ }
+#else
+
+ while (*lpch) {
+
+ while (isspace(*lpch)) {
+ lpch++;
+ }
+
+ if (*lpch != '/' && *lpch != '-') {
+ break;
+ }
+
+ lpch++;
+
+ switch (*lpch++) {
+
+ case 0: // don't skip over end of string
+ --lpch;
+
+ default: // assert, continue is ok.
+ assert(FALSE);
+ break;
+
+
+ case 'v':
+ case 'V':
+
+ while (isspace(*lpch)) {
+ lpch++;
+ }
+ FVerbose = atoi(lpch);
+ while (isdigit(*lpch)) {
+ lpch++;
+ }
+ break;
+
+ case 'r':
+ case 'R':
+ FDMRemote = TRUE;
+ break;
+
+ case 'd':
+ case 'D':
+ FUseOutputDebugString = TRUE;
+ break;
+
+ }
+ }
+#endif // OSDEBUG4
+
+
+ /* Define a false single step event */
+ falseSSEvent.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ falseSSEvent.u.Exception.ExceptionRecord.ExceptionCode
+ = EXCEPTION_SINGLE_STEP;
+
+ falseBPEvent.dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;
+ falseBPEvent.u.Exception.ExceptionRecord.ExceptionCode
+ = EXCEPTION_BREAKPOINT;
+
+ /* Define the standard notification method */
+ EMNotifyMethod.notifyFunction = NotifyEM;
+ EMNotifyMethod.lparam = (LPVOID)0;
+
+ SearchPathString[0] = '\0';
+ SearchPathSet = FALSE;
+
+ InitEventQueue();
+
+#ifdef WIN32S
+ // Find the BackTo32 entry point in W32SKRNL.DLL. This is the point
+ // at which all thunks return from 16-bit to 32-bit code. We need
+ // to know this because it is the place that the hot-key puts a
+ // breakpoint for an async stop. This entry point will be at the
+ // same address for the debuggee as for the debugger, thus we can just
+ // do GetProcAddress to find it.
+ hModule = GetModuleHandle("W32SKRNL.DLL");
+ if (hModule) {
+ Win32sBackTo32 = GetProcAddress(hModule, "_DbgBackTo32");
+ } else {
+ Win32sBackTo32 = NULL; // it isn't there!
+ }
+#endif
+
+#ifndef WIN32S
+ SetDebugErrorLevel(SLE_WARNING);
+#endif
+
+
+ /*
+ ** Save the pointer to the Transport layer entry function
+ */
+
+ DmTlFunc = lpfnTl;
+
+ /*
+ ** Try and connect up to the other side of the link
+ */
+
+ DmTlFunc( tlfSetBuffer, NULL, sizeof(abEMReplyBuf), (LONG)(LPV) abEMReplyBuf );
+
+ if ((xosd = DmTlFunc( tlfConnect, NULL, 0, 0)) != xosdNone ) {
+ return(xosd);
+ }
+
+ DPRINT(10, ("DM & TL are now connected\n"));
+
+ } else {
+
+ DmTlFunc( tlfDisconnect, NULL, 0, 0);
+ DmTlFunc( tlfSetBuffer, NULL, 0, 0);
+ FDMRemote = FALSE;
+ DmTlFunc = (DMTLFUNCTYPE) NULL;
+
+ }
+
+ return xosdNone;
+} /* DmInit() */
+
+
+
+VOID
+Cleanup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Cleanup of DM, prepare for exit.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ HTHDX pht, phtt;
+ HPRCX php, phpt;
+ BREAKPOINT *bp, *bpt;
+ int iDll;
+
+
+ /* Free all threads and close their handles */
+ for (pht = thdList->next; pht; pht = phtt) {
+ phtt = pht->next;
+ if (pht->rwHand != (HANDLE)INVALID) {
+ CloseHandle(pht->rwHand);
+ }
+ free(pht);
+ }
+ thdList->next = NULL;
+
+ /* Free all processes and close their handles */
+ for(php = prcList->next; php; php = phpt) {
+ phpt = php->next;
+
+ RemoveExceptionList(php);
+
+ for (iDll = 0; iDll < php->cDllList; iDll++) {
+ DestroyDllLoadItem(&php->rgDllList[iDll]);
+ }
+ free(php->rgDllList);
+
+ if (php->rwHand != (HANDLE)INVALID) {
+ CloseHandle(php->rwHand);
+ }
+ CloseHandle(php->hExitEvent);
+ CloseHandle(php->hEventCreateThread);
+ free(php);
+ }
+ prcList->next = NULL;
+
+ /* Free all breakpoints */
+ for(bp = bpList->next; bp; bp = bpt) {
+ bpt = bp->next;
+ free(bp);
+ }
+ bpList->next = NULL;
+
+ if (hDmPollThread) {
+ fDmPollQuit = TRUE;
+ WaitForSingleObject(hDmPollThread, INFINITE);
+ hDmPollThread = 0;
+ }
+
+#ifdef WIN32S
+ // clean up the win32s system dll list
+ FreeWin32sDllList();
+#endif
+
+}
+
+
+#endif
+
+
+
+BOOL CDECL
+DMPrintShellMsg(
+ char *szFormat,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ This function prints a string on the shell's
+ command window.
+
+Arguments:
+
+ szFormat - Supplies format string for sprintf
+ ... - Supplies variable argument list
+
+Return Value:
+
+ TRUE -> all is ok and the string was printed
+ FALSE -> something's hosed and no string printed
+
+--*/
+{
+ char buf[512];
+ DWORD bufLen;
+ va_list marker;
+#ifdef OSDEBUG4
+ LPINFOAVAIL lpinf;
+#else
+ LPINF lpinf;
+#endif
+ LPRTP lprtp = NULL;
+ BOOL rVal = TRUE;
+
+ va_start( marker, szFormat );
+ bufLen = _vsnprintf(buf, sizeof(buf), szFormat, marker );
+ va_end( marker);
+
+ if (bufLen == -1) {
+ buf[sizeof(buf) - 1] = '\0';
+ }
+
+ __try {
+ DEBUG_PRINT( buf );
+
+ bufLen = strlen(buf) + 1;
+#ifdef OSDEBUG4
+ lprtp = (LPRTP) malloc( sizeof(RTP)+sizeof(INFOAVAIL)+bufLen );
+ lpinf = (LPINFOAVAIL)(lprtp->rgbVar);
+#else
+ lprtp = (LPRTP) malloc( sizeof(RTP)+sizeof(INF)+bufLen );
+ lpinf = (LPINF)(lprtp->rgbVar);
+#endif
+
+ lprtp->dbc = dbcInfoAvail;
+ lprtp->hpid = hpidRoot;
+ lprtp->htid = NULL;
+ lprtp->cb = (int)bufLen;
+
+ lpinf->fReply = FALSE;
+ lpinf->fUniCode = FALSE;
+ memcpy( lpinf->buffer, buf, bufLen );
+
+#ifdef OSDEBUG4
+ DmTlFunc( tlfDebugPacket,
+ lprtp->hpid,
+ (WORD)(sizeof(RTP)+sizeof(INFOAVAIL)+bufLen),
+ (LONG)(LPV) lprtp
+ );
+#else
+ DmTlFunc( tlfDebugPacket,
+ lprtp->hpid,
+ (WORD)(sizeof(RTP)+sizeof(INF)+bufLen),
+ (LONG)(LPV) lprtp
+ );
+#endif
+
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ rVal = FALSE;
+
+ }
+
+ if (lprtp) {
+ free( lprtp );
+ }
+
+ return rVal;
+}
+
+VOID
+DebugPrint(
+ char * szFormat,
+ ...
+ )
+{
+ va_list marker;
+ int n;
+
+ va_start( marker, szFormat );
+ n = _vsnprintf(rgchDebug, sizeof(rgchDebug), szFormat, marker );
+ va_end( marker);
+
+ if (n == -1) {
+ rgchDebug[sizeof(rgchDebug)-1] = '\0';
+ }
+
+ OutputDebugString( rgchDebug );
+ return;
+} /* DebugPrint() */
+
+
+int
+pCharMode(
+ char * szAppName,
+ PIMAGETYPE pImageType
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to determine the type of exe which we are going
+ to be debugging. This is decided by looking for exe headers and making
+ decisions based on the information in the exe headers.
+
+Arguments:
+
+ szAppName - Supplies the path to the debugger exe
+ pImageType - Returns the type of the image
+
+Return Value:
+
+ System_Invalid - could not find the exe file
+ System_GUI - GUI application
+ System_Console - console application
+
+--*/
+
+{
+ IMAGE_DOS_HEADER dosHdr;
+ IMAGE_OS2_HEADER os2Hdr;
+ IMAGE_NT_HEADERS ntHdr;
+ DWORD cb;
+ HANDLE hFile;
+ int ret;
+ BOOL GotIt;
+ OFSTRUCT reOpenBuff = {0};
+
+ strcpy(nameBuffer, szAppName);
+
+#ifdef WIN32S
+ hFile =(HANDLE)OpenFile(szAppName,&reOpenBuff,OF_READ|OF_SHARE_COMPAT);
+#else
+ hFile =(HANDLE)OpenFile(szAppName,&reOpenBuff,OF_READ|OF_SHARE_DENY_NONE);
+#endif
+
+ if (hFile == (HANDLE)-1) {
+
+ /*
+ * Could not open file!
+ */
+
+ DEBUG_PRINT_2("OpenFile(%s) --> %u\r\n", szAppName, GetLastError());
+ return System_Invalid;
+
+ }
+
+ /*
+ * Try and read an MZ Header. If you can't then it can not possibly
+ * be a legal exe file. (Not strictly true but we will ignore really
+ * short com files since they are unintersting).
+ */
+
+ SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
+ if ((!ReadFile(hFile, &dosHdr, sizeof(dosHdr), &cb, NULL)) ||
+ (cb != sizeof(dosHdr))) {
+
+ if (_stricmp(&szAppName[strlen(szAppName) - 4], ".COM") == 0) {
+ *pImageType = Image_16;
+ } else {
+ DPRINT(1, ("dosHdr problem.\n"));
+ *pImageType = Image_Unknown;
+ }
+
+ CloseHandle(hFile);
+ return System_GUI;
+
+ }
+
+ /*
+ * Verify the MZ header.
+ *
+ * NOTENOTE Messup the case of no MZ header.
+ */
+
+ if (dosHdr.e_magic != IMAGE_DOS_SIGNATURE) {
+ /*
+ * We did not start with the MZ signature. If the extension
+ * is .COM then it is a COM file.
+ */
+
+ if (_stricmp(&szAppName[strlen(szAppName) - 4], ".COM") == 0) {
+ *pImageType = Image_16;
+ } else {
+ DPRINT(1, ("MAGIC problem(MZ).\n"));
+ *pImageType = Image_Unknown;
+ }
+
+ CloseHandle(hFile);
+#ifndef KERNEL
+#ifndef WIN32S
+ if (DmpInitialize( szAppName, &CrashContext, &CrashException, &CrashDumpHeader )) {
+ if (
+#if defined(TARGET_i386)
+ CrashDumpHeader->MachineImageType != IMAGE_FILE_MACHINE_I386
+#elif defined(TARGET_MIPS)
+ CrashDumpHeader->MachineImageType != IMAGE_FILE_MACHINE_R4000 ||
+ CrashDumpHeader->MachineImageType != IMAGE_FILE_MACHINE_R10000
+#elif defined(TARGET_ALPHA)
+ CrashDumpHeader->MachineImageType != IMAGE_FILE_MACHINE_ALPHA
+#elif defined(TARGET_PPC)
+ CrashDumpHeader->MachineImageType != IMAGE_FILE_MACHINE_POWERPC
+#else
+#error( "unknown target machine" );
+#endif
+ ) {
+ return System_Invalid;
+ }
+ *pImageType = Image_Dump;
+ }
+#endif // !WIN32S
+#endif // !KERNEL
+ return System_Console;
+ }
+
+ if ( dosHdr.e_lfanew == 0 ) {
+ /*
+ * Straight DOS exe.
+ */
+
+ DPRINT(1, ("[DOS image].\n"));
+ *pImageType = Image_16;
+
+ CloseHandle(hFile);
+ return System_Console;
+ }
+
+ /*
+ * Now look at the next EXE header (either NE or PE)
+ */
+
+ SetFilePointer(hFile, dosHdr.e_lfanew, NULL, FILE_BEGIN);
+ GotIt = FALSE;
+ ret = System_GUI;
+
+ /*
+ * See if this is a Win16 program
+ */
+
+ if (ReadFile(hFile, &os2Hdr, sizeof(os2Hdr), &cb, NULL) &&
+ (cb == sizeof(os2Hdr))) {
+
+ if ( os2Hdr.ne_magic == IMAGE_OS2_SIGNATURE ) {
+ /*
+ * Win16 program (may be an OS/2 exe also)
+ */
+
+ DPRINT(1, ("[Win16 image].\n"));
+ *pImageType = Image_16;
+ GotIt = TRUE;
+ } else if ( os2Hdr.ne_magic == IMAGE_OS2_SIGNATURE_LE ) {
+ /*
+ * OS2 program - Not supported
+ */
+
+ DPRINT(1, ("[OS/2 image].\n"));
+ *pImageType = Image_Unknown;
+ GotIt = TRUE;
+ }
+ }
+
+ /*
+ * If the above failed, see if it is an NT program
+ */
+
+ if ( !GotIt ) {
+ SetFilePointer(hFile, dosHdr.e_lfanew, NULL, FILE_BEGIN);
+
+ if (ReadFile(hFile, &ntHdr, sizeof(ntHdr), &cb, NULL) &&
+ (cb == sizeof(ntHdr)) &&
+ (ntHdr.Signature == IMAGE_NT_SIGNATURE)) {
+ /*
+ * All CUI (Character user interface) subsystems
+ * have the lowermost bit set.
+ */
+
+ DPRINT(1, ((ntHdr.OptionalHeader.Subsystem & 1) ?
+ "[*Character mode app*]\n" : "[*Windows mode app*]\n"));
+
+ ret = ((ntHdr.OptionalHeader.Subsystem & 1)) ?
+ System_Console : System_GUI;
+ *pImageType = Image_32;
+ } else {
+ DWORD FileSize;
+
+ FileSize = SetFilePointer(hFile, 0, NULL, FILE_END);
+
+ if ( (DWORD)dosHdr.e_lfanew > FileSize ) {
+ //
+ // Bogus e_lfanew, assume DOS
+ //
+ DPRINT(1, ("[DOS image assumed].\n"));
+ *pImageType = Image_16;
+ ret = System_Console;
+
+ } else {
+
+ //
+ // Not an NT image.
+ //
+ DPRINT(1, ("MAGIC problem(PE).\n"));
+ *pImageType = Image_Unknown;
+ }
+ }
+ }
+
+ CloseHandle(hFile);
+ return ret;
+} /* pCharMode() */
+
+
+VOID
+ReConnectDebugger(
+ DEBUG_EVENT *lpde,
+ BOOL fNoDllLoad
+ )
+
+/*++
+
+Routine Description:
+
+ This function handles the case where the dm/tl is re-connected to
+ a debugger. This function must re-instate the debugger to the
+ correct state that existed before the disconnect action.
+
+ (wesw) 11-3-93
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD i;
+ DEBUG_EVENT de;
+ HPRCX hprc;
+ HTHDX hthd;
+ HTHDX hthd_lb;
+ DWORD id;
+ HANDLE hThread;
+ HPID hpidNext = hpidRoot;
+ BOOL fException = FALSE;
+
+
+ //
+ // the dm is now connected
+ //
+ fDisconnected = FALSE;
+
+ //
+ // check to see if a re-connection is occurring while the
+ // process is running or after a non-servicable debug event
+ //
+ if (lpde && lpde->dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
+
+ hprc = HPRCFromPID(lpde->dwProcessId);
+ hthd = HTHDXFromPIDTID((PID)lpde->dwProcessId,(TID)lpde->dwThreadId);
+
+ if (lpde->u.Exception.dwFirstChance) {
+ hthd->tstate |= ts_first;
+ } else {
+ hthd->tstate |= ts_second;
+ }
+
+ hthd->tstate &= ~ts_running;
+ hthd->tstate |= ts_stopped;
+ }
+
+ //
+ // generate a create process event
+ //
+ hprc=prcList->next;
+ hprc->hpid = hpidNext;
+ hpidNext = (HPID) INVALID;
+ hthd=hprc->hthdChild;
+ ResetEvent(hEventCreateProcess);
+ de.dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ de.u.CreateProcessInfo.hFile = NULL;
+ de.u.CreateProcessInfo.hProcess = hprc->rwHand;
+ de.u.CreateProcessInfo.hThread = hthd->rwHand;
+ de.u.CreateProcessInfo.lpBaseOfImage = (LPVOID)hprc->rgDllList[0].offBaseOfImage;
+ de.u.CreateProcessInfo.dwDebugInfoFileOffset = 0;
+ de.u.CreateProcessInfo.nDebugInfoSize = 0;
+ de.u.CreateProcessInfo.lpStartAddress = (LPVOID)(DWORD)PC(hthd);
+ de.u.CreateProcessInfo.lpThreadLocalBase = NULL;
+ de.u.CreateProcessInfo.lpImageName = NULL;
+ de.u.CreateProcessInfo.fUnicode = 0;
+ NotifyEM(&de, hthd, 0, hprc);
+ WaitForSingleObject(hEventCreateProcess, INFINITE);
+
+ //
+ // mark the process as 'being connected' so that the continue debug
+ // events that are received from the shell are ignored
+ //
+ hprc->pstate |= ps_connect;
+
+
+ //
+ // look for a thread that is stopped and not dead
+ //
+ for (hthd=hprc->hthdChild,hthd_lb=NULL; hthd; hthd=hthd->nextSibling) {
+ if ((!(hthd->tstate & ts_dead)) && (hthd->tstate & ts_stopped)) {
+ hthd_lb = hthd;
+ break;
+ }
+ }
+
+ if (hthd_lb == NULL) {
+ //
+ // if we get here then there are no threads that are stopped
+ // so we must look for the first alive thread
+ //
+ for (hthd=hprc->hthdChild,hthd_lb=NULL; hthd; hthd=hthd->nextSibling) {
+ if (!(hthd->tstate & ts_dead)) {
+ hthd_lb = hthd;
+ break;
+ }
+ }
+ }
+
+ if (hthd_lb == NULL) {
+ //
+ // if this happens then we are really screwed. there are no valid
+ // threads to use, so lets bail out.
+ //
+ return;
+ }
+
+ if ((hthd_lb->tstate & ts_first) || (hthd_lb->tstate & ts_second)) {
+ fException = TRUE;
+ }
+
+ //
+ // generate mod loads for all the dlls for this process
+ //
+ // this MUST be done before the thread creates because the
+ // current PC of each thread can be in any of the loaded
+ // modules.
+ //
+ hthd = hthd_lb;
+ if (!fNoDllLoad) {
+ for (i=0; i<(DWORD)hprc->cDllList; i++) {
+ if (hprc->rgDllList[i].fValidDll) {
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ de.u.LoadDll.hFile = NULL;
+ de.u.LoadDll.lpBaseOfDll = (LPVOID)hprc->rgDllList[i].offBaseOfImage;
+ de.u.LoadDll.lpImageName = hprc->rgDllList[i].szDllName;
+ de.u.LoadDll.fUnicode = FALSE;
+ NotifyEM(&de, hthd, 0, hprc);
+ }
+ }
+ }
+
+
+ //
+ // loop thru all the threads for this process and
+ // generate a thread create event for each one
+ //
+ for (hthd=hprc->hthdChild; hthd; hthd=hthd->nextSibling) {
+ if (!(hthd->tstate & ts_dead)) {
+ if (fException && hthd_lb == hthd) {
+ //
+ // do this one last
+ //
+ continue;
+ }
+
+ //
+ // generate a thread create event
+ //
+ ResetEvent( hprc->hEventCreateThread );
+ ResetEvent( hEventContinue );
+ de.dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ NotifyEM( &de, hthd, 0, hprc );
+
+ WaitForSingleObject( hprc->hEventCreateThread, INFINITE );
+
+ //
+ // wait for the shell to continue the new thread
+ //
+ WaitForSingleObject( hEventContinue, INFINITE );
+ }
+ }
+
+ if (fException) {
+ hthd = hthd_lb;
+ //
+ // generate a thread create event
+ //
+ ResetEvent( hprc->hEventCreateThread );
+ ResetEvent( hEventContinue );
+ de.dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ NotifyEM( &de, hthd, 0, hprc );
+
+ WaitForSingleObject( hprc->hEventCreateThread, INFINITE );
+
+ //
+ // wait for the shell to continue the new thread
+ //
+ WaitForSingleObject( hEventContinue, INFINITE );
+ }
+
+ //
+ // generate a breakpoint event
+ //
+ hthd = hthd_lb;
+
+ if (hthd->tstate & ts_running) {
+
+ //
+ // this will create a thread in the debuggee that will
+ // immediatly stop at a breakpoint. this will cause the
+ // shell to think that we are processing a normal attach.
+ //
+
+ HMODULE hModule = GetModuleHandle("ntdll.dll");
+ FARPROC ProcAddr = GetProcAddress(hModule, "DbgBreakPoint" );
+
+
+ hThread = CreateRemoteThread( (HANDLE) hprc->rwHand,
+ NULL,
+ 4096,
+ (LPTHREAD_START_ROUTINE) ProcAddr,
+ 0,
+ 0,
+ &id
+ );
+
+ } else if (!lpde) {
+
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ if ((hthd->tstate & ts_first) || (hthd->tstate & ts_second)) {
+ de.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ } else {
+ de.dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;
+ }
+ de.u.Exception.dwFirstChance = hthd->tstate & ts_first;
+ de.u.Exception.ExceptionRecord = hthd->ExceptionRecord;
+ NotifyEM(&de, hthd, 0, 0);
+
+ }
+
+ //
+ // reset the process state
+ //
+ hprc->pstate &= ~ps_connect;
+
+ return;
+}
+
diff --git a/private/windbg/newdm/event.c b/private/windbg/newdm/event.c
new file mode 100644
index 000000000..d652840b4
--- /dev/null
+++ b/private/windbg/newdm/event.c
@@ -0,0 +1,338 @@
+/*************************************************************************
+** **
+** EVENT.C **
+** **
+**************************************************************************
+** **
+** This file contains the expected event checker. When the default **
+** event handling for a debug event (from the OS) is not the **
+** desired handling, then an expected event may be registered. **
+** For every event which occurs the expected event handler checks **
+** to see if it is the expected event and if so then it will **
+** cause the action function associated with the expected event **
+** to be executed. The default event handler will not be executed **
+** **
+*************************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+/************************************************************************/
+
+
+/************************************************************************/
+
+extern EXPECTED_EVENT masterEE, *eeList;
+extern HTHDXSTRUCT masterTH;
+extern HPRCXSTRUCT masterPR;
+extern HTHDX thdList;
+extern HPRCX prcList;
+extern HTHDX ourHTHD;
+extern HPRCX ourHPRC;
+extern DEBUG_EVENT falseSSEvent;
+extern METHOD EMNotifyMethod;
+extern char lpbBuffer;
+extern DDVECTOR DebugDispatchTable[];
+extern CMD_DESC CommandDispatchTable[];
+extern CRITICAL_SECTION csEventList;
+
+/************************************************************************/
+
+/************************************************************************/
+
+
+
+EXPECTED_EVENT *
+RegisterExpectedEvent(
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD eventCode,
+ DWORD subClass,
+ METHOD * notifier,
+ ACVECTOR action,
+ BOOL fPersistent,
+ LPVOID lparam
+ )
+/*++
+
+
+Routine Description:
+
+ This function is used to register an expected event. When a registered
+ event occurs, the normal dispatcher is not called; instead an optional
+ notifier function and an action function are called.
+
+ If an event is marked Persistent, it will not be discarded when another
+ event occurs.
+
+ If hthd is supplied, an exact process/thread match is required to score
+ a hit. If hthd is 0 then any thread in hprc will be matched to it.
+
+Arguments:
+
+ hprc - Supplies descriptor for process to check for expected event
+ hthd - Supplies optional thread to check for expected event
+ eventCode - Supplies event code to check for
+ subClass - Supplies sub-class of event code (for exceptions)
+ notifier - Supplies optional notifier procedure
+ action - Supplies procedure to be called on event
+ fPersistent - Supplies flag to mark event as persistent
+ lparam - Supplies Optional data for action routine.
+
+Return Value:
+
+ Address of the event just registered (NULL on failure)
+
+--*/
+{
+ EXPECTED_EVENT * ee;
+
+ DPRINT(5, ("[REE: DE=%x, SC=%x, HTHD=%x]\n", eventCode, subClass, hthd));
+
+ /* Allocate the structure */
+
+ ee = (EXPECTED_EVENT*) malloc(sizeof(EXPECTED_EVENT));
+ if (ee == NULL)
+ return NULL;
+
+ /* Attach it to the expected event list */
+
+ EnterCriticalSection(&csEventList);
+
+ ee->next = eeList->next;
+ eeList->next = ee;
+
+ /* Stuff it */
+
+ ee->hprc = hprc;
+ ee->hthd = hthd;
+ ee->eventCode = eventCode;
+ ee->subClass = subClass;
+ ee->notifier = notifier;
+ ee->action = action;
+ ee->fPersistent = fPersistent;
+ ee->lparam = lparam;
+
+ LeaveCriticalSection(&csEventList);
+
+ return ee;
+} /* RegisterExpectedEvent() */
+
+
+
+EXPECTED_EVENT *
+PeeIsEventExpected(
+ HTHDX hthd,
+ DWORD eventCode,
+ DWORD subClass
+ )
+/*++
+
+Routine Description:
+
+ This function will go though the list of expected events and
+ return the first event which matches all of the required criteria.
+ The event is removed from the list of expected events if it is
+ found.
+
+Arguments:
+
+ hthd - Supplies descriptor for Thread in which the event occured
+ eventCode - Supplies Event code which occured
+ subClass - Supplies sub-class of the event code
+
+Return Value:
+
+ TRUE if the event was located.
+
+--*/
+{
+ EXPECTED_EVENT * prev=eeList;
+ EXPECTED_EVENT * ee;
+
+
+ if ((hthd == NULL) && ((eventCode == CREATE_THREAD_DEBUG_EVENT) ||
+ (eventCode == CREATE_PROCESS_DEBUG_EVENT))) {
+ return (EXPECTED_EVENT *) NULL;
+ }
+
+ EnterCriticalSection(&csEventList);
+
+ assert(hthd != NULL);
+
+ /* Try to find an event with the given description */
+
+
+ for(ee = prev->next; ee; prev=prev->next,ee=ee->next){
+
+ if (((ee->hthd==hthd) ||
+ (ee->hprc == hthd->hprc && ee->hthd==(HTHDX)0)) &&
+ (ee->eventCode==eventCode) &&
+ ((ee->subClass==NO_SUBCLASS) ||
+ ee->subClass==subClass)) {
+
+ /* Found it, remove it from the list */
+
+ prev->next = ee->next;
+
+ LeaveCriticalSection(&csEventList);
+
+ DPRINT(5, ("Event Expected: %x\n", ee));
+
+ /* and return it to the caller */
+
+ return ee;
+ }
+ }
+
+ LeaveCriticalSection(&csEventList);
+
+ DPRINT(5, ("\n"));
+
+ return (EXPECTED_EVENT*) NULL;
+} /* PeeIsEventExpected() */
+
+
+void
+ConsumeAllThreadEvents(
+ HTHDX hthd,
+ BOOL fClearPersistent
+ )
+/*++
+
+Routine Description:
+
+ This function will go through the list of expected events and
+ remove all events found associated with the specified Thread.
+
+Arguments:
+
+ hthd - Supplies thread descriptor
+ fClearPersistent - If FALSE, events marked "persistent" will
+ not be cleared.
+
+Return Value:
+
+ None
+
+--*/
+{
+ EXPECTED_EVENT * prev;
+ EXPECTED_EVENT * ee;
+ EXPECTED_EVENT * eet;
+
+ /* Try to find events for the specified thread */
+
+ EnterCriticalSection(&csEventList);
+
+ prev = eeList;
+ for (ee = eeList->next; ee; ee = eet){
+
+ eet = ee->next;
+
+ if (ee->hthd != hthd || (!fClearPersistent && ee->fPersistent)) {
+
+ prev = ee;
+
+ } else {
+
+ /* Found one, remove it from the list */
+
+ prev->next = eet;
+
+ /* Check if it was a breakpoint event*/
+
+ if (ee->eventCode==EXCEPTION_DEBUG_EVENT
+ && ee->subClass==EXCEPTION_BREAKPOINT) {
+
+ /* it was a breakpoint event, */
+ /* must free the bp structure */
+ RemoveBP(ee->lparam);
+
+ } else if ( ee->eventCode==BREAKPOINT_DEBUG_EVENT ) {
+
+ RemoveBP((BREAKPOINT *)ee->subClass);
+
+ }
+
+ /* Free the event structure */
+ free(ee);
+ }
+ }
+
+ LeaveCriticalSection(&csEventList);
+
+ return;
+}
+
+
+void
+ConsumeAllProcessEvents(
+ HPRCX hprc,
+ BOOL fClearPersistent
+ )
+/*++
+
+Routine Description:
+
+ This function will go through the list of expected events and
+ remove all events found associated with the specified Process.
+
+Arguments:
+
+ hprc - Supplies process descriptor
+ fClearPersistent - If FALSE, events marked "persistent" will
+ not be cleared.
+
+Return Value:
+
+ None
+
+--*/
+{
+ EXPECTED_EVENT * prev;
+ EXPECTED_EVENT * ee;
+ EXPECTED_EVENT * eet;
+
+ /* Try to find events for the specified prcess */
+
+ EnterCriticalSection(&csEventList);
+
+ prev = eeList;
+ for ( ee = prev->next; ee; ee = eet ) {
+
+ eet = ee->next;
+
+ if (ee->hprc != hprc || (!fClearPersistent && ee->fPersistent)) {
+
+ prev = ee;
+
+ } else {
+
+ /* Found one, remove it from the list */
+
+ prev->next = ee->next;
+
+ /* Check if it was a breakpoint event*/
+
+ if (ee->eventCode==EXCEPTION_DEBUG_EVENT
+ && ee->subClass==EXCEPTION_BREAKPOINT) {
+
+ /* it was a breakpoint event, */
+ /* must free the bp structure */
+ RemoveBP(ee->lparam);
+
+ } else if ( ee->eventCode==BREAKPOINT_DEBUG_EVENT ) {
+
+ RemoveBP((BREAKPOINT *)ee->subClass);
+
+ }
+
+ /* Free the event structure */
+ free(ee);
+ }
+ }
+
+ LeaveCriticalSection(&csEventList);
+ return;
+}
diff --git a/private/windbg/newdm/funccall.c b/private/windbg/newdm/funccall.c
new file mode 100644
index 000000000..0ad0efbcb
--- /dev/null
+++ b/private/windbg/newdm/funccall.c
@@ -0,0 +1,476 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ funchdr.c
+
+Abstract:
+
+ This file contians the code used for supporting function evaluation
+ from the expression evaluator.
+
+Author:
+
+ Jim Schaad (jimsch) 06-04-92
+
+Environment:
+
+ Win32 - User
+
+
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+SetFile()
+
+
+/**********************************************************************/
+
+void NtfyFuncCall(DEBUG_EVENT * lpde, HTHDX hthd, DWORD unused, LPVOID lpvoid);
+
+/**********************************************************************/
+
+
+METHOD MthdFuncNotify = {NtfyFuncCall};
+
+extern DMTLFUNCTYPE DmTlFunc;
+extern LPDM_MSG LpDmMsg;
+
+/**********************************************************************/
+
+
+
+VOID
+ProcessSetupExecuteCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This function is called in response to a dmfSetupExecute request.
+ It will create a local Execute Object and return the handle to
+ the object.
+
+Arguments:
+
+ hprc - Supplies the process handle for the operation
+ hthd - Supplies the thread handle for the operation
+ lpdbb - Supplies a pointer to possible futher information
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPEXECUTE_OBJECT_DM lpeo;
+
+ Unreferenced( hprc );
+
+ DPRINT(1, ("Setup Execute"));
+
+ /*
+ * In order for this to be a valid operation the requested
+ * thread must be in a stopped state.
+ */
+
+ if ( ((hthd->tstate & ts_stopped) == 0) ||
+ ((hthd->tstate & (ts_dead|ts_destroyed)) != 0) ) {
+
+#ifdef OSDEBUG4
+ LpDmMsg->xosdRet = xosdBadThread;
+#else
+ LpDmMsg->xosdRet = xosdInvalidThread;
+ goto Exit;
+ }
+#endif
+
+ lpeo = malloc(sizeof(EXECUTE_OBJECT_DM));
+ if (lpeo == NULL) {
+ LpDmMsg->xosdRet = xosdOutOfMemory;
+ goto Exit;
+ }
+ memset(lpeo, 0, sizeof(EXECUTE_OBJECT_DM));
+
+ LpDmMsg->xosdRet = xosdNone;
+ *((HIND *)LpDmMsg->rgb) = (HIND) lpeo;
+
+ hthd->tstate |= ts_funceval;
+ hthd->cFuncEval += 1;
+
+Exit:
+ Reply(sizeof(HIND), LpDmMsg, lpdbb->hpid);
+ return;
+} /* ProcessSetupExecute() */
+
+
+VOID
+ProcessStartExecuteCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ hprc - Supplies the process handle for the operation
+ hthd - Supplies the thread handle for the operation
+ lpdbb - Supplies a pointer to possible futher information
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPEXECUTE_STRUCT lpes = (LPEXECUTE_STRUCT) (lpdbb->rgbVar);
+ LPEXECUTE_OBJECT_DM lpeo;
+ XOSD xosd;
+
+
+ /*
+ * Start by saving the information in the EXECUTE_STRUCT in
+ * the local Execute Object structure.
+ */
+
+ lpeo = (LPEXECUTE_OBJECT_DM) lpes->hindDm;
+
+ DPRINT(1, ("Start Execute @%08x", lpes->addr.addr.off));
+
+ lpeo->addrStart = lpes->addr;
+ lpeo->pbpSave = AtBP(hthd);
+ lpeo->fIgnoreEvents = lpes->fIgnoreEvents;
+ lpeo->hthd = hthd;
+ lpeo->lpbp = SetBP(hprc, hthd, bptpExec, bpnsStop, &(lpeo->addrStart), (HPID) lpeo);
+
+ /*
+ * Mark a breakpoint at the current address
+ */
+
+ SetBPFlag(hthd, lpeo->lpbp);
+
+ /*
+ * Call a machine specific fucntion to setup stacks and some
+ * work in the Execute Object for later use.
+ */
+
+ xosd = SetupFunctionCall(lpeo, lpes);
+
+ /*
+ * If the set up worked successfully, the next step to to register
+ * an expected debug event and
+ * step the child.
+ */
+
+ if (xosd == xosdNone) {
+ SingleStep(hthd, &MthdFuncNotify, FALSE, TRUE);
+ }
+
+ LpDmMsg->xosdRet = xosd;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+} /* ProcessStartExecute() */
+
+
+
+VOID
+ProcessCleanUpExecuteCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ hprc - Supplies the process handle for the operation
+ hthd - Supplies the thread handle for the operation
+ lpdbb - Supplies a pointer to possible futher information
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPEXECUTE_OBJECT_DM lpeo = *(LPEXECUTE_OBJECT_DM *) (lpdbb->rgbVar);
+
+ DPRINT(1, ("Cleanup Execute"));
+
+ hthd->cFuncEval -= 1;
+ if (hthd->cFuncEval == 0) {
+ hthd->tstate &= ~ts_funceval;
+ }
+
+ if (lpeo->lpbp) {
+ RemoveBP(lpeo->lpbp);
+ }
+
+ /*
+ * This is wrong if the BP could be removed during function evaluation
+ */
+
+ SetBPFlag(hthd, lpeo->pbpSave);
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+
+ free( lpeo );
+ return;
+} /* ProcessCleanUpCmd() */
+
+
+
+void
+NtfyFuncCall(
+ DEBUG_EVENT * lpde,
+ HTHDX hthd,
+ DWORD unused,
+ LPVOID lpv
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called as the notifyer function for expected events
+ for executing of functions for the expression evaluator.
+
+Arguments:
+
+ lpde - Supplies the pointer to the debug event exception structure
+ hthd - Supplies the handle to the thread of the exception
+ lpv - Supplies a pointer to extra data for the expectation
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ Unreferenced( lpde );
+ Unreferenced( lpv );
+
+ /*
+ * Debug output first
+ */
+
+ DEBUG_PRINT("** NtfyFuncCall **\n");
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+ return;
+} /* NtfyFuncCall() */
+
+
+
+
+VOID
+EvntBreakpoint(
+ DEBUG_EVENT * de,
+ HTHDX hthd
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called if the current thread is processing a function
+ evaluation and a breakpoint debug event occurs. The routine checks
+ to see if the desired breakpoint has been reached. If it has not
+ then the breakpoint will be consumed and the thread continued. If it
+ has then a dbcExecuteDone notification will be sent to the debugger.
+
+Arguments:
+
+ de - Supplies a pointer to the current debug event.
+ hthd - Supplies the handle of the current thread
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ union {
+ RTP rtp;
+ char rgb[sizeof(RTP)+sizeof(HIND)];
+ } rtpbuf;
+
+ LPEXECUTE_OBJECT_DM lpeo;
+ BREAKPOINT * lpbpp;
+
+
+ lpbpp = (BREAKPOINT *) de->u.Exception.ExceptionRecord.ExceptionCode;
+ if (lpbpp) {
+ lpeo = (LPEXECUTE_OBJECT_DM) lpbpp->id;
+ } else {
+ lpeo = NULL;
+ }
+
+ DPRINT(1, ("Hit Execute Breakpoint (%08x)", lpbpp));
+
+ /*
+ * This may have been a recursive call. TO deal with this we need
+ * to check that the stack pointers are the same as when we started
+ * doing the function evaluation.
+ *
+ * If it is not ok on the stacks then merely continue. Note that this
+ * requires doing a single step event.
+ *
+ */
+
+ if ((lpeo != NULL) && !CompareStacks(lpeo)) {
+ SetBPFlag(hthd, lpbpp);
+
+#if defined(TARGET_i386) && defined(KERNEL)
+ DecrementIP( hthd );
+#endif
+
+ DPRINT(1, (" Compare Stacks fail\n"));
+
+ SingleStep(hthd, &MthdFuncNotify, FALSE, TRUE);
+ return;
+ }
+
+ DPRINT(1, (" Execute done\n"));
+
+ /*
+ * We really did finish so send a message to that effect
+ */
+
+ rtpbuf.rtp.hpid = hthd->hprc->hpid;
+ rtpbuf.rtp.htid = hthd->htid;
+ rtpbuf.rtp.dbc = dbcExecuteDone;
+ *((HIND *) &rtpbuf.rtp.rgbVar[0]) = 0;
+
+ DmTlFunc( tlfDebugPacket, rtpbuf.rtp.hpid, sizeof(rtpbuf), (LONG)&rtpbuf);
+
+ return;
+} /* EvntBreakpoint() */
+
+
+
+VOID
+EvntException(
+ DEBUG_EVENT * de,
+ HTHDX hthd
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ union {
+ RTP rtp;
+ char rgb[sizeof(RTP)+sizeof(HIND)];
+ } rtpbuf;
+
+ DPRINT(1, ("Execute -- Exececption Occured\n"));
+
+ hthd->fExceptionHandled = TRUE;
+
+ rtpbuf.rtp.hpid = hthd->hprc->hpid;
+ rtpbuf.rtp.htid = hthd->htid;
+ rtpbuf.rtp.dbc = dbcExecuteDone;
+ *((HIND *) &rtpbuf.rtp.rgbVar[0]) = 0;
+
+ DmTlFunc( tlfDebugPacket, rtpbuf.rtp.hpid, sizeof(rtpbuf), (LONG)&rtpbuf);
+
+ return;
+} /* EvntException() */
+
+
+
+VOID
+EvntExitProcess(
+ DEBUG_EVENT * de,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ This function is called if an exit process event is called while
+ a function is being evaluated.
+
+ This is a pain to deal with. First the function evaluation must
+ be killed and then we need to do normal processing
+
+Arguments:
+
+ de - Supplies the Exit Process Debug event
+ hthd - Supplies the handle to the current thread
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ union {
+ RTP rtp;
+ char rgb[sizeof(RTP)+sizeof(HIND)];
+ } rtpbuf;
+
+ DPRINT(1, ("Execute -- Exit Process Occurred\n"));
+
+ hthd->fExceptionHandled = TRUE;
+
+ rtpbuf.rtp.hpid = hthd->hprc->hpid;
+ rtpbuf.rtp.htid = hthd->htid;
+ rtpbuf.rtp.dbc = dbcExecuteDone;
+ *((HIND *) &rtpbuf.rtp.rgbVar[0]) = 0;
+
+ DmTlFunc( tlfDebugPacket, rtpbuf.rtp.hpid, sizeof(rtpbuf), (LONG) &rtpbuf);
+
+ ProcessExitProcessEvent(de, hthd);
+ return;
+} /* EvntExitProcess() */
diff --git a/private/windbg/newdm/funccall.h b/private/windbg/newdm/funccall.h
new file mode 100644
index 000000000..00c617b24
--- /dev/null
+++ b/private/windbg/newdm/funccall.h
@@ -0,0 +1,49 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ funccall.h
+
+Abstract:
+
+ Contains the types and protypes for funccall.c
+
+Author:
+
+ Jim Schaad (jimsch) 05-06-92
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+/*
+ *
+ */
+
+typedef struct _EXECUTE_OBJECT_DM {
+ ADDR addrStart; /* Starting address of function call */
+ ADDR addrStack; /* Starting stack offset */
+ BOOL fIgnoreEvents; /* Ignore events during execution */
+ HTHDX hthd; /* Thread for evaluating fucntion */
+ BREAKPOINT * lpbp; /* Pointer to breakpoint at starting addres */
+ BREAKPOINT * pbpSave; /* Breakpoint thread is on at start */
+ int tmp;
+} EXECUTE_OBJECT_DM;
+
+typedef EXECUTE_OBJECT_DM FAR * LPEXECUTE_OBJECT_DM;
+
+/**********************************************************************/
+
+extern VOID ProcessSetupExecuteCmd(HPRCX, HTHDX, LPDBB);
+extern VOID ProcessStartExecuteCmd(HPRCX, HTHDX, LPDBB);
+extern VOID ProcessCleanUpExecuteCmd(HPRCX, HTHDX, LPDBB);
+extern VOID EvntException(DEBUG_EVENT *, HTHDX);
+extern VOID EvntExitProcess(DEBUG_EVENT *, HTHDX);
+extern VOID EvntBreakpoint(DEBUG_EVENT *, HTHDX);
+
+extern XOSD SetupFunctionCall(LPEXECUTE_OBJECT_DM, LPEXECUTE_STRUCT);
+extern BOOL CompareStacks(LPEXECUTE_OBJECT_DM);
diff --git a/private/windbg/newdm/i386d3dm.c b/private/windbg/newdm/i386d3dm.c
new file mode 100644
index 000000000..b2f4985ee
--- /dev/null
+++ b/private/windbg/newdm/i386d3dm.c
@@ -0,0 +1,145 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ d3dm.c
+
+Abstract:
+
+ This module contains the disassembler code that is specific to the
+ DM
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 22-August-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+typedef LPCH FAR *LPLPCH;
+
+extern XOSD Disassemble( HPID, HTID, LPSDI, PVOID, INT, BOOL );
+extern void OutputHexString(LPLPCH, int *, LPCH, int);
+
+
+XOSD
+disasm (
+ LPSDI lpsdi,
+ void *Memory,
+ int Size
+ )
+{
+ return Disassemble( (HPID)0, (HTID)0, lpsdi, Memory, Size, FALSE );
+}
+
+
+XOSD
+GetRegisterValue (
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+{
+ UNREFERENCED_PARAMETER( hpid );
+ UNREFERENCED_PARAMETER( htid );
+ UNREFERENCED_PARAMETER( wValue );
+ UNREFERENCED_PARAMETER( lValue );
+
+ return xosdNone;
+}
+
+XOSD
+SetAddress (
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+{
+ UNREFERENCED_PARAMETER( hpid );
+ UNREFERENCED_PARAMETER( htid );
+ UNREFERENCED_PARAMETER( wValue );
+ UNREFERENCED_PARAMETER( lValue );
+
+ return xosdNone;
+}
+
+XOSD
+ReadMemBuffer (
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+{
+ UNREFERENCED_PARAMETER( hpid );
+ UNREFERENCED_PARAMETER( htid );
+ UNREFERENCED_PARAMETER( wValue );
+ UNREFERENCED_PARAMETER( lValue );
+
+ return xosdNone;
+}
+
+
+LSZ
+ObtainSymbol (
+ PADDR Addr1,
+ SOP Sop,
+ PADDR Addr2,
+ LSZ Lsz,
+ LONG *Lpl
+ )
+{
+ UNREFERENCED_PARAMETER( Addr1 );
+ UNREFERENCED_PARAMETER( Sop );
+ UNREFERENCED_PARAMETER( Addr2 );
+ UNREFERENCED_PARAMETER( Lsz );
+ UNREFERENCED_PARAMETER( Lpl );
+
+ return NULL;
+}
+
+
+
+
+
+
+void OutputSymbol (
+ HPID hpidLocal,
+ HTID htidLocal,
+ BOOL fSymbols,
+ BOOL fSegOvr,
+ LPADDR lpaddrOp,
+ int ireg,
+ int length,
+ LPADDR lpaddrLoc,
+ LPLPCH ppBuf,
+ int * pcch
+)
+{
+ UNREFERENCED_PARAMETER( hpidLocal );
+ UNREFERENCED_PARAMETER( htidLocal );
+ UNREFERENCED_PARAMETER( fSymbols );
+ UNREFERENCED_PARAMETER( fSegOvr );
+ UNREFERENCED_PARAMETER( ireg );
+ UNREFERENCED_PARAMETER( length );
+ UNREFERENCED_PARAMETER( lpaddrLoc );
+
+ OutputHexString ( ppBuf, pcch, (LPCH) &offAddr( *lpaddrOp ), 4 );
+}
+
+#define D3DM 1
+#undef GetSymbol
+#include "..\..\em\p_i386\d3.c"
+
diff --git a/private/windbg/newdm/i386mach.c b/private/windbg/newdm/i386mach.c
new file mode 100644
index 000000000..41d390666
--- /dev/null
+++ b/private/windbg/newdm/i386mach.c
@@ -0,0 +1,1617 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ mach.c
+
+Abstract:
+
+ This file contains the x86 specific code for dealing with
+ machine dependent issues that invlove registers, instruction
+ disassembly, function calling and other interesting things.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+Notes:
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+extern CRITICAL_SECTION csContinueQueue;
+
+/**********************************************************************/
+
+extern LPDM_MSG LpDmMsg;
+
+/**********************************************************************/
+
+#ifdef WIN32S
+
+extern BOOL fCanGetThreadContext;
+
+typedef struct tagWin32sSystemDll {
+ struct tagWin32sSystemDll * pNext;
+ DWORD dwStart;
+ DWORD dwEnd;
+} WIN32S_SYSTEM_DLL, * LPWIN32S_SYSTEM_DLL;
+
+// sorted list of win32s system dll names. NULL terminated.
+UCHAR * szWin32sSystemDllTable[] = {
+ "advapi32.dll",
+ "comdlg32.dll",
+ "gdi32.dll",
+ "kernel32.dll",
+ "lz32.dll",
+ "ntdll.dll",
+ "olecli32.dll",
+ "olesrv32.dll",
+ "shell32.dll",
+ "user32.dll",
+ "version.dll",
+ "w32skrnl.dll",
+ NULL
+};
+
+#define WIN32S_LOAD_EPSILON 15 // 15 bytes min between sections
+
+DWORD Win32sSystemDllFirst = 0xFFFFFFFF;
+DWORD Win32sSystemDllLast = 0;
+
+LPWIN32S_SYSTEM_DLL pWin32sSystemDlls = NULL; // start list empty
+FARPROC Win32sBackTo32 = NULL; // BackTo32 thunk return address
+
+#endif // WIN32S
+
+#if DBG
+static char * rgszTrace[] = {
+ "Trace", "BreakPoint", "Cannot Trace", "Soft Int", "Call"
+};
+#endif // DBG
+
+#define MAXL 20L
+
+#define BIT20(b) (b & 0x07)
+#define BIT53(b) (b >> 3 & 0x07)
+#define BIT76(b) (b >> 6 & 0x03)
+
+static int mod; /* mod of mod/rm byte */
+
+
+
+//
+// Stuff for debug registers
+//
+
+
+typedef struct _DR7 *PDR7;
+typedef struct _DR7 {
+ DWORD L0 : 1;
+ DWORD G0 : 1;
+ DWORD L1 : 1;
+ DWORD G1 : 1;
+ DWORD L2 : 1;
+ DWORD G2 : 1;
+ DWORD L3 : 1;
+ DWORD G3 : 1;
+ DWORD LE : 1;
+ DWORD GE : 1;
+ DWORD Pad1 : 3;
+ DWORD GD : 1;
+ DWORD Pad2 : 1;
+ DWORD Pad3 : 1;
+ DWORD Rwe0 : 2;
+ DWORD Len0 : 2;
+ DWORD Rwe1 : 2;
+ DWORD Len1 : 2;
+ DWORD Rwe2 : 2;
+ DWORD Len2 : 2;
+ DWORD Rwe3 : 2;
+ DWORD Len3 : 2;
+} DR7;
+
+
+#define RWE_EXEC 0x00
+#define RWE_WRITE 0x01
+#define RWE_RESERVED 0x02
+#define RWE_READWRITE 0x03
+
+
+DWORD LenMask[ MAX_DEBUG_REG_DATA_SIZE + 1 ] = DEBUG_REG_LENGTH_MASKS;
+
+
+BOOL
+IsRet(
+ HTHDX hthd,
+ LPADDR addr
+ )
+{
+ BYTE instr;
+ DWORD cBytes;
+ if (!AddrReadMemory( hthd->hprc, hthd, addr, &instr, 1, &cBytes )) {
+ return FALSE;
+ }
+ return ((instr == 0xc2) || (instr == 0xc3) || (instr == 0xca) || (instr == 0xcb));
+}
+
+void
+IsCall(
+ HTHDX hthd,
+ LPADDR lpaddr,
+ LPINT lpf,
+ BOOL fStepOver
+ )
+
+/*++
+
+Routine Description:
+
+ This function checks to see if the specified instruction is
+ a call instruction.
+
+Arguments:
+
+ hthd - Supplies the handle to the current thread
+
+ lpaddr - Supplies the address to check for the call instruction at
+
+ lpf - Returns TRUE if is a call instruction
+
+ fStepOver - Supplies TRUE if doing a step over
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int mode_32;
+ int opsize_32;
+ DWORD cBytes;
+ DWORD cb;
+ char membuf [ MAXL ];
+ char *pMem;
+ UCHAR opcode;
+ int fPrefix;
+ int fRepPrefix;
+ int ttt;
+ int mode;
+ int rm;
+ BOOL fAddrSet;
+ ULONG rgul[2];
+ USHORT rgus[2];
+ ADDR addrSp;
+
+ /*
+ * If we have already done this work and cached the answer then
+ * pick up the answer from the cache. The cache marker is cleared
+ * at the start of ProcessDebugEvent.
+ */
+
+ if (hthd->fIsCallDone) {
+ *lpaddr = hthd->addrIsCall;
+ *lpf = hthd->iInstrIsCall;
+ return;
+ }
+
+ /*
+ * local addressing mode
+ */
+
+ mode_32 = opsize_32 = hthd->fAddrOff32;
+
+ /*
+ * Read enough bytes to get the longest possible instruction
+ */
+
+ if (!AddrReadMemory( hthd->hprc,
+ hthd,
+ lpaddr,
+ membuf,
+ MAXL,
+ &cBytes) ||
+ (cBytes == 0)) {
+ *lpf = INSTR_CANNOT_TRACE;
+ goto done;
+ }
+
+ DPRINT(1, ("(IsCall?) EIP=%08x Type=", *lpaddr));
+
+ /*
+ * point to begin of instruction
+ */
+
+ pMem = membuf;
+
+ /*
+ * read and process any prefixes first
+ */
+
+ fPrefix = TRUE;
+ fRepPrefix = FALSE;
+
+ do {
+ opcode = (UCHAR) *pMem++; /* get opcode */
+
+ /*
+ * Operand size prefix
+ */
+
+ if (opcode == 0x66) {
+ opsize_32 = !opsize_32;
+ }
+ /*
+ * Address size prefix
+ */
+
+ else if (opcode == 0x67) {
+ mode_32 = !mode_32;
+ }
+ /*
+ * REP and REPNE prefix
+ */
+ else if ((opcode & ~1) == 0xf2) {
+ fRepPrefix = TRUE;
+ }
+ /*
+ * LOCK prefix (0xf0)
+ * Segment Override (0x26, 0x36, 0x2e, 0x3e, 0x64, 0x65)
+ */
+ else if ( opcode != 0xf0 &&
+ (opcode & ~0x18) != 0x26 &&
+ (opcode & ~1) != 0x64 ) {
+ fPrefix = FALSE;
+ }
+ } while ( fPrefix );
+
+ /*
+ * Now start checking for the instructions which must be treated
+ * in a special manner. Any instruction which does not respect
+ * the trace bit (either due to flag munging or faulting) needs
+ * to be treated specially. Also all call ops need to be treated
+ * specially (step in vs step over). Finally interupts need to
+ * be treated specially since they could cause faults in 16-bit mode
+ */
+
+ fAddrSet = FALSE;
+
+ /*
+ * Break point instruction
+ */
+ if (opcode == 0xcc) {
+ *lpf = INSTR_BREAKPOINT;
+ }
+ // NOTENOTE -- missing the INTO instruction
+ /*
+ * all other interrrupt instructions
+ */
+ else if (opcode == 0xcd) {
+ opcode = (UCHAR) *pMem++;
+
+ /*
+ * Is this really a 2-byte version of INT 3 ?
+ */
+ if (opcode == 0x3) {
+ *lpf = INSTR_BREAKPOINT;
+ }
+ /*
+ * Is this a funky 16-bit floating point instruction? if so then
+ * we need to make sure and step over it
+ */
+ else if (!ADDR_IS_FLAT(*lpaddr) &&
+ (0x34 <= opcode) && (opcode <= 0x3c)) {
+ if (opcode == 0x3C) {
+ pMem++;
+ }
+ opcode = *pMem++;
+ mode = opcode & 0xc0;
+ rm = opcode & 0x03;
+ switch ( mode) {
+ case 0:
+ if (rm == 0x6) {
+ pMem += 2;
+ }
+ break;
+
+ case 1:
+ pMem += 1;
+ break;
+
+ case 2:
+ pMem += 2;
+ break;
+ }
+ *lpf = INSTR_CANNOT_TRACE;
+ GetAddrOff(*lpaddr) += pMem - membuf;
+ fAddrSet = TRUE;
+ }
+ /*
+ * This is an FWAIT instr -- 2 bytes long
+ */
+ else if (!ADDR_IS_FLAT(*lpaddr) && opcode == 0x3d) {
+ *lpf = INSTR_CANNOT_TRACE;
+ GetAddrOff(*lpaddr) += 2;
+ fAddrSet = TRUE;
+ }
+ /*
+ * This is a 0x3f interrupt -- I think this is for
+ * overlays in dos
+ */
+ else if (!ADDR_IS_FLAT(*lpaddr) && (opcode == 0x3f)) {
+ if (fStepOver) {
+ *lpf = INSTR_CANNOT_TRACE;
+ AddrInit(&addrSp, 0, SsSegOfHthdx(hthd), STACK_POINTER(hthd),
+ FALSE, FALSE, FALSE, hthd->fAddrIsReal);
+ if (!AddrReadMemory(hthd->hprc,
+ hthd,
+ &addrSp,
+ rgus,
+ 4,
+ &cb) ||
+ (cb != 4) ) {
+ goto done;
+ }
+ AddrInit(lpaddr, 0, rgus[1], (UOFF32) rgus[0], FALSE, FALSE,
+ FALSE, hthd->fAddrIsReal);
+ fAddrSet = TRUE;
+ }
+ }
+ /*
+ * OK its really an interrupt --- deal with it
+ */
+ else {
+ if (!fStepOver && hthd->fAddrIsReal) {
+ *lpf = INSTR_CANNOT_TRACE;
+ AddrInit(&addrSp, 0, 0, opcode*4, FALSE, FALSE, FALSE, TRUE);
+ if (!AddrReadMemory(hthd->hprc,
+ hthd,
+ &addrSp,
+ rgus,
+ 4,
+ &cb) ||
+ (cb != 4) ) {
+ goto done;
+ }
+ AddrInit(lpaddr, 0, rgus[1], (UOFF32) rgus[0], FALSE, FALSE,
+ FALSE, TRUE);
+ fAddrSet = TRUE;
+ }
+ }
+ }
+ /*
+ * Now check for various call instructions
+ */
+ else if (opcode == 0xe8) { /* near direct call */
+ *lpf = INSTR_IS_CALL;
+ pMem += (1 + opsize_32)*2;
+ } else if (opcode == 0x9a) { /* far direct call */
+ *lpf = INSTR_IS_CALL;
+ pMem += (2 + opsize_32)*2;
+ } else if (opcode == 0xff) {
+ opcode = *pMem++; /* compute the modRM bits for instruction */
+ ttt = BIT53(opcode);
+ if ((ttt & ~1) == 2) { /* indirect call */
+ *lpf = INSTR_IS_CALL;
+
+ mod = BIT76(opcode);
+ if (mod != 3) { /* non-register operand */
+ rm = BIT20( opcode );
+ if (mode_32) {
+ if (rm == 4) {
+ rm = BIT20(*pMem++); /* get base from SIB */
+ }
+
+ if (mod == 0) {
+ if (rm == 5) {
+ pMem += 4; /* long direct address */
+ }
+ } else if (mod == 1) {
+ pMem++; /* register with byte offset */
+ } else {
+ pMem += 4; /* register with long offset */
+ }
+ } else { /* 16-bit mode */
+ if (mod == 0) {
+ if (rm == 6) {
+ pMem += 2; /* short direct address */
+ }
+ } else {
+ pMem += mod; /* reg, byte, word offset */
+ }
+ }
+ }
+ }
+ }
+ /*
+ * Now catch all of the repeated instructions
+ *
+ * INSB (0x6c) INSW (0x6d) OUTSB (0x6e) OUTSW (0x6f)
+ * MOVSB (0xa4) MOVSW (0xa5) CMPSB (0xa6) CMPSW (0xa7)
+ * STOSB (0xaa) STOSW (0xab)
+ * LODSB (0xac) LODSW (0xad) SCASB (0xae) SCASW (0xaf)
+ */
+ else if (fRepPrefix && (((opcode & ~3) == 0x6c) ||
+ ((opcode & ~3) == 0xa4) ||
+ ((opcode & ~1) == 0xaa) ||
+ ((opcode & ~3) == 0xac))) {
+ if (fStepOver) {
+ *lpf = INSTR_CANNOT_TRACE;
+ } else {
+ /*
+ * Cannot trace the ins/outs instructions
+ */
+ if ((opcode & ~3) == 0x6c) {
+ *lpf = INSTR_CANNOT_TRACE;
+ }
+ }
+ }
+ /*
+ * Now catch IO instructions -- these will generally fault and
+ * be interpreted.
+ */
+ else if ((opcode & ~3) == 0x6c) {
+ *lpf = INSTR_CANNOT_TRACE;
+ }
+ /*
+ * Now catch other instructions which change registers
+ */
+ else if ((opcode == 0xfa) || (opcode == 0xfb) ||
+ (opcode == 0x9d) || (opcode == 0x9c)) {
+ *lpf = INSTR_CANNOT_TRACE;
+ }
+ /*
+ * Now catch irets
+ */
+ else if (opcode == 0xcf) {
+ *lpf = INSTR_CANNOT_TRACE;
+ AddrInit(&addrSp, 0, SsSegOfHthdx(hthd), STACK_POINTER(hthd),
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE,
+ hthd->fAddrIsReal);
+ if (opsize_32) {
+ if (!AddrReadMemory(hthd->hprc,
+ hthd,
+ &addrSp,
+ rgul,
+ 8,
+ &cb) ||
+ (cb != 8) ) {
+ goto done;
+ }
+ AddrInit(lpaddr, 0, (SEGMENT) rgul[1], rgul[0],
+ hthd->fAddrIsFlat, TRUE, FALSE, FALSE);
+ } else {
+ if (!AddrReadMemory(hthd->hprc,
+ hthd,
+ &addrSp,
+ rgus,
+ 4,
+ &cb) ||
+ (cb != 4) ) {
+ goto done;
+ }
+ AddrInit(lpaddr, 0, rgus[1], (UOFF32) rgus[0], FALSE, FALSE,
+ FALSE, hthd->fAddrIsReal);
+ }
+ fAddrSet = TRUE;
+ }
+ /*
+ * Assume that we want to just trace the instruction
+ */
+ else {
+ *lpf = INSTR_TRACE_BIT;
+ goto done;
+ }
+
+ /*
+ *
+ */
+
+ DPRINT(1, ("%s", rgszTrace[*lpf]));
+
+ /*
+ * Have read enough bytes? no -- expect somebody else to blow up
+ */
+
+ if (cBytes < (DWORD)(pMem - membuf)) {
+ *lpf = INSTR_TRACE_BIT;
+ goto done;
+ }
+
+ if (!fAddrSet) {
+ GetAddrOff(*lpaddr) += pMem - membuf;
+ }
+
+ /*
+ * Dump out the bytes for later checking
+ */
+
+#if DBG
+ if (FVerbose) {
+ DWORD i;
+ DPRINT(1, ("length = %d bytes=", cBytes & 0xff));
+ for (i=0; i<cBytes; i++) {
+ DPRINT(1, (" %02x", membuf[i]));
+ }
+ }
+#endif
+
+ done:
+ hthd->fIsCallDone = TRUE;
+ hthd->addrIsCall = *lpaddr;
+ hthd->iInstrIsCall = *lpf;
+ return;
+} /* IsCall() */
+
+
+
+
+XOSD
+SetupFunctionCall(
+ LPEXECUTE_OBJECT_DM lpeo,
+ LPEXECUTE_STRUCT lpes
+ )
+/*++
+
+Routine Description:
+
+ This function contains the machine dependent code for initializing
+ the function call system.
+
+Arguments:
+
+ lpeo - Supplies a pointer to the Execute Object for the Function call
+
+ lpes - Supplies a pointer to the Execute Struct from the DM
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ CONTEXT context;
+ OFFSET off;
+ int cb;
+ ULONG ul;
+ HPRCX hprc = lpeo->hthd->hprc;
+ ADDR addr;
+
+ /*
+ * Can only execute functions on the current stopped thread. Therefore
+ * assert that the current thread is stopped.
+ */
+
+ assert(lpeo->hthd->tstate & ts_stopped);
+ if (!(lpeo->hthd->tstate & ts_stopped)) {
+ return xosdInvalidThread;
+ }
+
+ /*
+ * Can copy the context from the cached context in the thread structure
+ */
+
+ context = lpeo->hthd->context;
+
+ /*
+ * Now get the current stack offset
+ */
+
+ lpeo->addrStack.addr.off = context.Esp;
+ lpeo->addrStack.addr.seg = (SEGMENT) context.SegSs;
+ if (!lpeo->hthd->fAddrOff32) {
+ lpeo->addrStack.addr.off &= 0xffff;
+ }
+
+ /*
+ * Put the return address onto the stack. If this is a far address
+ * then it needs to be a far return address. Else it must be a
+ * near return address.
+ */
+
+ if (lpeo->hthd->fAddrOff32) {
+ if (lpes->fFar) {
+ assert(FALSE); /* Not used for Win32 */
+ }
+
+ off = context.Esp - 4;
+ if (DbgWriteMemory(hprc, (char *) off, &lpeo->addrStart.addr.off,
+ 4, &cb) == 0 ||
+ (cb != 4)) {
+ return xosdUnknown;
+ }
+ } else {
+ if (lpes->fFar) {
+ off = context.Esp - 4;
+ ul = (lpeo->addrStart.addr.seg << 16) | lpeo->addrStart.addr.off;
+ addr = lpeo->addrStack;
+ GetAddrOff(addr) -= 4;
+ TranslateAddress(hprc, lpeo->hthd, &addr, TRUE);
+ if ((DbgWriteMemory(hprc, (char *) GetAddrOff(addr),
+ &ul, 4, &cb) == 0) ||
+ (cb != 4)) {
+ return xosdUnknown;
+ }
+ } else {
+ off = context.Esp & 0xffff - 2;
+ addr = lpeo->addrStack;
+ GetAddrOff(addr) -= 2;
+ TranslateAddress(hprc, lpeo->hthd, &addr, TRUE);
+ if ((DbgWriteMemory(hprc, (char *) GetAddrOff(addr),
+ &lpeo->addrStart.addr.off, 2, &cb) == 0) ||
+ (cb != 2)) {
+ return xosdUnknown;
+ }
+ }
+ }
+
+ /*
+ * Set the new stack pointer and starting address in the context and
+ * write them back to the thread.
+ */
+
+ lpeo->hthd->context.Esp = off;
+ lpeo->hthd->context.Eip = lpeo->addrStart.addr.off;
+
+ lpeo->hthd->fContextDirty = TRUE;
+
+ return xosdNone;
+} /* SetupFunctionCall() */
+
+
+
+
+BOOL
+CompareStacks(
+ LPEXECUTE_OBJECT_DM lpeo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to determine if the stack pointers are currect
+ for terminating function evaluation.
+
+Arguments:
+
+ lpeo - Supplies the pointer to the DM Execute Object description
+
+Return Value:
+
+ TRUE if the evaluation is to be terminated and FALSE otherwise
+
+--*/
+
+{
+ if (lpeo->hthd->fAddrOff32) {
+ if (lpeo->addrStack.addr.off <= lpeo->hthd->context.Esp) {
+ return TRUE;
+ }
+ } else if ((lpeo->addrStack.addr.off <= (lpeo->hthd->context.Esp & 0xffff)) &&
+ (lpeo->addrStack.addr.seg == (SEGMENT) lpeo->hthd->context.SegSs)) {
+ return TRUE;
+ }
+ return FALSE;
+} /* CompareStacks() */
+
+#ifdef WIN32S
+/*
+ * IsWin32sSystemDll
+ *
+ * INPUTS szImageName = asciiz name of dll (may include path)
+ * OUTPUTS returns TRUE if the dll name is in the set of Win32s system dlls.
+ * SUMMARY Simple table search. The table of names is sorted and NULL
+ * terminated.
+ */
+BOOL IsWin32sSystemDll(UCHAR * szImageName) {
+ USHORT i = 0;
+ int cmp;
+ UCHAR * pTemp;
+
+
+ if (! szImageName) {
+ return(FALSE);
+ }
+
+ // break off path
+ pTemp = szImageName + strlen(szImageName) - 1; // point to end of string
+ while ((pTemp > szImageName) && (*pTemp != ':') && (*pTemp != '\\')) {
+ pTemp--;
+ }
+ if (*pTemp == ':' || *pTemp == '\\') {
+ pTemp++;
+ }
+
+ // linear search in sorted table (NULL terminated)
+ while (szWin32sSystemDllTable[i] &&
+ ((cmp = _stricmp(szWin32sSystemDllTable[i], pTemp)) < 0)) {
+ i++;
+ }
+
+ return(cmp == 0); // _stricmp --> 0 on match
+}
+
+
+/*
+ * IsWin32sSystemDllAddr
+ *
+ * INPUTS dwOffset
+ * OUTPUTS TRUE if dwOffset fits into a range found in the system dll table.
+ * SUMMARY Search the ranges in the table until the Start value is > dwOffset.
+ */
+BOOL
+IsWin32sSystemDllAddr(
+ DWORD dwOffset
+ )
+{
+ LPWIN32S_SYSTEM_DLL pNode = pWin32sSystemDlls;
+ if (dwOffset < Win32sSystemDllFirst || dwOffset > Win32sSystemDllLast) {
+ return(FALSE); // quick check
+ }
+
+ // otherwise, do the search
+ while (pNode && (pNode->dwStart <= dwOffset)) {
+ if (dwOffset <= pNode->dwEnd && dwOffset >= pNode->dwStart) {
+ return(TRUE); // in range
+ }
+ pNode = pNode->pNext;
+ }
+
+ return(FALSE);
+}
+
+
+/*
+ * AddWin32sSystemDllAddr
+ *
+ * INPUTS dwOffset = start address for object
+ * cbObject = size of object
+ * OUTPUTS none
+ * SUMMARY Add the addresses in between {offset, offset+cbObject} to the
+ * Win32s System Dlls list. If the offset is within
+ * WIN32S_LOAD_EPSILON of another entry, tack them together. (The
+ * idea is that the loader won't load any of the user's code in
+ * there anyway and we want to speed up list searches.) The list
+ * will be maintained in sorted order. We will also maintain the
+ * Win32sSystemDllFirst and Win32sSystemDllLast offsets for a quick
+ * elimination of most list searches.
+ */
+void
+AddWin32sSystemDllAddr(
+ DWORD dwOffset,
+ DWORD cbObject
+ )
+{
+ DWORD dwEnd = dwOffset + cbObject - 1; // ending offset
+ LPWIN32S_SYSTEM_DLL pNode, pPrev, pNew;
+
+ assert(dwOffset < dwEnd);
+
+ // Update Win32sSystemDllFirst/Last
+
+ Win32sSystemDllFirst = min(Win32sSystemDllFirst, dwOffset);
+ Win32sSystemDllLast = max(Win32sSystemDllLast, dwEnd);
+
+ // find insert point and insert new node for section
+ pPrev = NULL;
+ pNode = pWin32sSystemDlls; // head of list
+
+ while (pNode && pNode->dwStart < dwOffset) {
+ pPrev = pNode;
+ pNode = pNode->pNext;
+ }
+
+ if ((pNew = malloc(sizeof(WIN32S_SYSTEM_DLL))) == NULL) {
+ assert(FALSE);
+ return; //error, no memory
+ }
+
+ if (pPrev) { // insert point is middle or end, not head
+ pPrev->pNext = pNew;
+ } else { // insert at head, update global head pointer
+ pWin32sSystemDlls = pNew;
+ }
+
+ // fill in new node
+ pNew->dwStart = dwOffset;
+ pNew->dwEnd = dwEnd;
+ pNew->pNext = pNode;
+
+ // Remove overlap. It can only happen near the new node.
+ // merge with prev
+ if (pPrev && pPrev->dwEnd + WIN32S_LOAD_EPSILON >= pNew->dwStart) {
+ pPrev->dwEnd = max(pNew->dwEnd, pPrev->dwEnd);
+ pPrev->pNext = pNew->pNext;
+ free(pNew);
+ pNew = pPrev;
+ }
+
+ // merge with next (may be more than one if we have large dwEnd)
+ while (pNode && pNode->dwStart <= pNew->dwEnd + WIN32S_LOAD_EPSILON) {
+ pNew->dwEnd = max(pNode->dwEnd, pNew->dwEnd);
+ pNew->pNext = pNode->pNext;
+ free(pNode);
+ pNode = pNew->pNext;
+ }
+}
+
+/*
+ * FreeWin32sDllList
+ *
+ * INPUTS none
+ * OUTPUTS none
+ * SUMMARY free all the memory in the win32s system dll list and set the
+ * global head pointer to null.
+ */
+void
+FreeWin32sDllList(
+ void
+ )
+{
+
+ LPWIN32S_SYSTEM_DLL pNode, pNext;
+
+ pNode = pWin32sSystemDlls;
+ pWin32sSystemDlls = NULL;
+
+ while (pNode) {
+ pNext = pNode->pNext;
+ free(pNode);
+ pNode = pNext;
+ }
+}
+
+WIN32S_TRACE_CHECK
+IsWin32sSystemThunk(
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD currAddr,
+ DWORD stackPtr
+ )
+/*
+ * IsWin32sSystemThunk
+ *
+ * INPUTS rwHand = handle to the process
+ * currAddr = EIP to check for a thunk call
+ * stackPtr = current ESP
+ * OUTPUT WIN32S_TRACE_OK: not a jump or call to win32s code
+ * WIN32S_THUNK_CALL: the instr is a call to win32s code
+ * WIN32S_THUNK_JUMP: the instr is a jump or ret to win32s code
+ * SUMMARY This is kinda twisted: Thunks look like this:
+ *
+ * ApiCall(p1, p2, etc);
+ * push
+ * push
+ * etc.
+ * call _ApiCall@8
+ * e8 {offset} where offset is the distance from the start
+ * of the next instruction. The destination of
+ * the call is eip+5+offset.
+ *
+ * _ApiCall@8:
+ * jmp dword ptr [system call address]
+ * ff 25 {address} where address is the address to read the
+ * destination from.
+ *
+ * Anyway, we want to recognize this situation and check the final
+ * destination against the known address space of the system dlls.
+ * For this, we will look in the table compiled during dll loads.
+ *
+ * WARNWARN This code is very i386 specific, but that should be ok since it is
+ * only intended to run on Win32s machines.
+ *
+ */
+
+{
+ WIN32S_TRACE_CHECK wtcReturn = WIN32S_TRACE_OK;
+ BYTE InstructionBuffer[6] = {0};
+ DWORD dwDestination;
+ DWORD * pdwDestination;
+ DWORD dwIndirect;
+ DWORD * pdwIndirect;
+ DWORD dwBytesRead;
+ ADDR addr;
+
+
+
+ DEBUG_PRINT_1("\r\nIsWin32sSystemThunk(0x%x)\r\n", currAddr);
+
+ try { // in case instruction would generate gp-fault
+
+ // read the current instruction
+ AddrInit(&addr, 0, 0, (OFFSET)currAddr, TRUE, TRUE, FALSE, FALSE);
+ if (AddrReadMemory(hprc, hthd, &addr, InstructionBuffer, 5,
+ &dwBytesRead)) {
+
+ // got the current instruction. What is it?
+ switch (InstructionBuffer[0]) {
+ case (BYTE)0xe8: // Near call
+ // call to where?
+ pdwDestination = (DWORD *)(&InstructionBuffer[1]);
+ dwDestination = *pdwDestination + currAddr + 5;
+ DEBUG_PRINT_1("Found a call to 0x%x\r\n", dwDestination);
+ AddrInit(&addr, 0, 0, (OFFSET)dwDestination, TRUE, TRUE, FALSE, FALSE);
+ if (AddrReadMemory(hprc, hthd, &addr, InstructionBuffer, 6,
+ &dwBytesRead)) {
+ // Got the destination instruction, is it a jmp
+ // indirect?
+ if (InstructionBuffer[0] == (BYTE)0xff &&
+ InstructionBuffer[1] == (BYTE)0x25) {
+ // Jump indirect to where?
+ pdwIndirect = (DWORD *)(&InstructionBuffer[2]);
+ dwIndirect = *pdwIndirect;
+ DEBUG_PRINT_1(
+ "Found a call -> jump indirect to 0x%x\r\n",
+ dwIndirect);
+ AddrInit(&addr, 0, 0, (OFFSET)dwIndirect, TRUE, TRUE, FALSE, FALSE);
+ if (AddrReadMemory(hprc, hthd, &addr,
+ InstructionBuffer, 4, &dwBytesRead)) {
+ pdwDestination = (DWORD *)InstructionBuffer;
+ if (IsWin32sSystemDllAddr(*pdwDestination)) {
+ wtcReturn = WIN32S_THUNK_CALL;
+ }
+ }
+ }
+ }
+ break;
+
+ case (BYTE)0xc2: // retn N
+ case (BYTE)0xc3: // retn
+ // check if we are about to return to win32s system code...
+ // look at [esp]. If it is in system dll, do a Go
+ // Special case: If the current address is Win32sBackTo32+4
+ // don't do the check, we want to allow the trace back to
+ // User32.dll.
+ if (currAddr == (DWORD)Win32sBackTo32) {
+ break;
+ }
+ // read return address from stack
+ AddrInit(&addr, 0, 0, (OFFSET)stackPtr, TRUE, TRUE, FALSE, FALSE);
+ if (AddrReadMemory(hprc, hthd, &addr, InstructionBuffer, 4,
+ &dwBytesRead)) {
+ pdwDestination = (DWORD *)InstructionBuffer;
+ if (IsWin32sSystemDllAddr(*pdwDestination)) {
+ wtcReturn = WIN32S_THUNK_JUMP;
+ }
+ }
+ break;
+
+ // BRUCEK: should also check for JUMP FAR to 16-bit. What does
+ // that look like?
+
+ default:
+ break;
+ }
+ }
+
+ } except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
+ }
+
+ switch (wtcReturn) {
+ case WIN32S_THUNK_CALL:
+ DEBUG_PRINT("IsWin32sSystemThunk --> WIN32S_THUNK_CALL\r\n");
+ break;
+ case WIN32S_THUNK_JUMP:
+ DEBUG_PRINT("IsWin32sSystemThunk --> WIN32S_THUNK_JUMP\r\n");
+ break;
+ case WIN32S_TRACE_OK:
+ DEBUG_PRINT("IsWin32sSystemThunk --> WIN32S_TRACE_OK\r\n");
+ break;
+ default:
+ DEBUG_PRINT_1("ERROR: IsWin32sSystemThunk --> UNKNOWN %u\r\n",
+ wtcReturn);
+ }
+
+ return(wtcReturn);
+}
+
+#endif // WIN32S
+
+#ifndef KERNEL
+
+void
+ProcessGetDRegsCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPDWORD lpdw = (LPDWORD)LpDmMsg->rgb;
+ CONTEXT cxt;
+ int rs = 0;
+
+ DEBUG_PRINT( "ProcessGetDRegsCmd :\n");
+
+
+#ifdef WIN32S
+ // Can't yet get thread context within a non-exception event.
+ if (hthd == 0 || ! fCanGetThreadContext) {
+ DEBUG_PRINT("\r\nProcessGetDRegsCmd\r\n");
+// DebugBreak();
+#else
+ if (hthd == 0) {
+#endif
+ rs = 0;
+ } else {
+ cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (!GetThreadContext(hthd->rwHand, &cxt)) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ rs = 0;
+ } else {
+ lpdw[0] = hthd->context.Dr0;
+ lpdw[1] = hthd->context.Dr1;
+ lpdw[2] = hthd->context.Dr2;
+ lpdw[3] = hthd->context.Dr3;
+ lpdw[4] = hthd->context.Dr6;
+ lpdw[5] = hthd->context.Dr7;
+ LpDmMsg->xosdRet = xosdNone;
+ rs = sizeof(CONTEXT);
+ }
+ }
+
+ Reply( rs, LpDmMsg, lpdbb->hpid );
+ return;
+} /* ProcessGetDRegsCmd() */
+
+
+void
+ProcessSetDRegsCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPDWORD lpdw = (LPDWORD)(lpdbb->rgbVar);
+ XOSD_ xosd = xosdNone;
+
+ Unreferenced(hprc);
+
+ DPRINT(5, ("ProcessSetDRegsCmd : "));
+
+ hthd->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
+ hthd->context.Dr0 = lpdw[0];
+ hthd->context.Dr1 = lpdw[1];
+ hthd->context.Dr2 = lpdw[2];
+ hthd->context.Dr3 = lpdw[3];
+ hthd->context.Dr6 = lpdw[4];
+ hthd->context.Dr7 = lpdw[5];
+
+
+ if (hthd->fWowEvent) {
+ WOWSetThreadContext(hthd, &hthd->context);
+ } else {
+ SetThreadContext(hthd->rwHand, &hthd->context);
+ }
+
+ Reply(0, &xosd, lpdbb->hpid);
+
+ return;
+} /* ProcessSetDRegsCmd() */
+
+
+
+VOID
+MakeThreadSuspendItselfHelper(
+ HTHDX hthd,
+ FARPROC lpSuspendThread
+ )
+{
+ HANDLE h;
+ DWORD dw;
+
+ //
+ // set up the args to SuspendThread
+ //
+
+ hthd->context.Esp -= 4;
+ h = GetCurrentThread();
+ WriteProcessMemory(hthd->hprc->rwHand,
+ (PVOID)hthd->context.Esp,
+ &h,
+ sizeof(h),
+ &dw);
+
+ hthd->context.Esp -= 4;
+ WriteProcessMemory(hthd->hprc->rwHand,
+ (PVOID)hthd->context.Esp,
+ &(PC(hthd)),
+ sizeof(DWORD),
+ &dw);
+
+ PC(hthd) = (DWORD)lpSuspendThread;
+ hthd->fContextDirty = TRUE;
+}
+
+#endif // !KERNEL
+
+BOOL
+ProcessFrameStackWalkNextCmd(HPRCX hprc,
+ HTHDX hthd,
+ PCONTEXT context,
+ LPVOID pctxPtrs)
+
+{
+ return FALSE;
+}
+
+
+
+XOSD disasm ( LPSDI lpsdi, void*Memory, int Size );
+BOOL ParseAddr ( char*, ADDR* );
+BOOL ParseNumber( char*, DWORD*, int );
+
+
+typedef struct _BTNODE {
+ char *Name;
+ BOOL IsCall;
+ BOOL TargetAvail;
+} BTNODE;
+
+
+BTNODE BranchTable[] = {
+ { "call" , TRUE , TRUE },
+ { "ja" , FALSE , TRUE },
+ { "jae" , FALSE , TRUE },
+ { "jb" , FALSE , TRUE },
+ { "jbe" , FALSE , TRUE },
+ { "jcxz" , FALSE , TRUE },
+ { "je" , FALSE , TRUE },
+ { "jecxz" , FALSE , TRUE },
+ { "jg" , FALSE , TRUE },
+ { "jge" , FALSE , TRUE },
+ { "jl" , FALSE , TRUE },
+ { "jle" , FALSE , TRUE },
+ { "jmp" , FALSE , TRUE },
+ { "jne" , FALSE , TRUE },
+ { "jno" , FALSE , TRUE },
+ { "jnp" , FALSE , TRUE },
+ { "jns" , FALSE , TRUE },
+ { "jo" , FALSE , TRUE },
+ { "jp" , FALSE , TRUE },
+ { "js" , FALSE , TRUE },
+ { "loop" , FALSE , FALSE },
+ { "loope" , FALSE , FALSE },
+ { "loopne" , FALSE , FALSE },
+ { "loopnz" , FALSE , FALSE },
+ { "loopz" , FALSE , FALSE },
+ { "ret" , FALSE , FALSE },
+ { "retf" , FALSE , FALSE },
+ { "retn" , FALSE , FALSE },
+ { NULL , FALSE , FALSE }
+};
+
+
+
+DWORD
+BranchUnassemble(
+ void *Memory,
+ ADDR *Addr,
+ BOOL *IsBranch,
+ BOOL *TargetKnown,
+ BOOL *IsCall,
+ BOOL *IsTable,
+ ADDR *Target
+ )
+{
+ XOSD xosd;
+ SDI Sdi;
+ DWORD Consumed = 0;
+ DWORD i;
+ int s;
+ char *p;
+ ADDR Trgt;
+
+ AddrInit( &Trgt, 0, 0, 0, TRUE, TRUE, FALSE, FALSE );
+
+ *IsBranch = FALSE;
+ *IsTable = FALSE;
+
+ Sdi.dop = dopOpcode| dopOperands | dopEA;
+ Sdi.addr = *Addr;
+
+ xosd = disasm( &Sdi, Memory, 16 );
+
+ if ( xosd == xosdNone ) {
+
+ *IsTable = Sdi.fJumpTable;
+
+ for ( i=0; BranchTable[i].Name != NULL; i++ ) {
+
+ s = strcmp( Sdi.lpch, BranchTable[i].Name );
+
+ if ( s == 0 ) {
+
+ *IsBranch = TRUE;
+ *IsCall = BranchTable[i].IsCall;
+ if (*IsTable) {
+ *Target = Sdi.addrEA0;
+ //
+ // We might know the target, but for this
+ // purpose, we don't want to deal with it.
+ //
+ *TargetKnown = FALSE;
+ }
+ else if (BranchTable[i].TargetAvail &&
+ (p = Sdi.lpch) &&
+ *(p += (strlen(p)+1)) ) {
+
+ Trgt = *Addr;
+ if ( ParseAddr( p, &Trgt ) ) {
+ *TargetKnown = TRUE;
+ } else {
+ AddrInit( &Trgt, 0, 0, 0, TRUE, TRUE, FALSE, FALSE );
+ *TargetKnown = FALSE;
+ }
+ *Target = Trgt;
+ }
+ else {
+ *Target = Trgt;
+ *TargetKnown = FALSE;
+ }
+
+ break;
+
+ } else if ( s < 0 ) {
+
+ break;
+ }
+ }
+
+ Consumed = GetAddrOff( Sdi.addr ) - GetAddrOff(*Addr);
+ }
+
+ return Consumed;
+}
+
+
+
+BOOL
+ParseAddr (
+ char *szAddr,
+ ADDR *Addr
+ )
+{
+
+ char *p;
+ BOOL fParsed;
+ SEGMENT Segment;
+ UOFF16 Off16;
+ UOFF32 Off32;
+ DWORD Dword;
+
+ assert( szAddr );
+ assert( Addr );
+
+ fParsed = FALSE;
+
+ p = strchr( szAddr, ':' );
+
+ if ( p ) {
+
+ *p = '\0';
+ p++;
+
+ if ( ParseNumber( szAddr, &Dword, 16 ) ) {
+
+ Segment = (SEGMENT)Dword;
+
+ if ( ParseNumber( p, &Dword, 16 ) ) {
+
+ Off16 = (UOFF16)Dword;
+ fParsed = TRUE;
+
+ GetAddrSeg(*Addr) = Segment;
+ GetAddrOff(*Addr) = Off16;
+ }
+ }
+ } else {
+
+ if ( ParseNumber( szAddr, &Dword, 16 ) ) {
+
+ Off32 = (UOFF32)Dword;
+ fParsed = TRUE;
+
+ GetAddrOff(*Addr) = Off32;
+ }
+ }
+
+ return fParsed;
+}
+
+
+BOOL
+ParseNumber (
+ char *szNumber,
+ DWORD *Number,
+ int Radix
+ )
+{
+ BOOL fParsed = FALSE;
+ char *p = szNumber;
+ char *q;
+
+ assert( szNumber );
+ assert( Number );
+
+ if ( strlen(p) > 2 &&
+ p[0]=='0' &&
+ (p[1]=='x' || p[1]=='X') ) {
+
+ p+=2;
+ assert( Radix == 16 );
+ }
+
+ q = p;
+ while ( *q && isxdigit(*q) ) {
+ q++;
+ }
+
+ if ( !*q ) {
+ *Number = strtoul( p, NULL, Radix );
+ fParsed = TRUE;
+ }
+
+ return fParsed;
+}
+
+
+
+BOOL
+SetupDebugRegister(
+ HTHDX hthd,
+ int Register,
+ int DataSize,
+ DWORD DataAddr,
+ DWORD BpType
+ )
+{
+ DWORD Len;
+ DWORD rwMask;
+
+#ifdef KERNEL
+ KSPECIAL_REGISTERS ksr;
+ PDWORD Dr0 = &ksr.KernelDr0;
+ PDWORD Dr1 = &ksr.KernelDr1;
+ PDWORD Dr2 = &ksr.KernelDr2;
+ PDWORD Dr3 = &ksr.KernelDr3;
+ PDR7 Dr7 = (PDR7)&(ksr.KernelDr7);
+#else
+ CONTEXT Context;
+ PDWORD Dr0 = &Context.Dr0;
+ PDWORD Dr1 = &Context.Dr1;
+ PDWORD Dr2 = &Context.Dr2;
+ PDWORD Dr3 = &Context.Dr3;
+ PDR7 Dr7 = (PDR7)&(Context.Dr7);
+#endif
+
+
+#ifdef KERNEL
+ if (!GetExtendedContext(hthd, &ksr))
+#else
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (!GetThreadContext(hthd->rwHand, &Context))
+#endif
+ {
+ return FALSE;
+ }
+
+
+ Len = LenMask[ DataSize ];
+
+ switch ( BpType ) {
+ case bptpDataR:
+ rwMask = RWE_READWRITE;
+ break;
+
+ case bptpDataW:
+ case bptpDataC:
+ rwMask = RWE_WRITE;
+ break;
+
+ case bptpDataExec:
+ rwMask = RWE_EXEC;
+ //
+ // length must be 0 for exec bp
+ //
+ Len = 0;
+ break;
+
+ default:
+ assert(!"Invalid BpType!!");
+ break;
+ }
+
+
+ switch( Register ) {
+ case 0:
+ *Dr0 = DataAddr;
+ Dr7->Len0 = Len;
+ Dr7->Rwe0 = rwMask;
+ Dr7->L0 = 0x01;
+ break;
+ case 1:
+ *Dr1 = DataAddr;
+ Dr7->Len1 = Len;
+ Dr7->Rwe1 = rwMask;
+ Dr7->L1 = 0x01;
+ break;
+ case 2:
+ *Dr2 = DataAddr;
+ Dr7->Len2 = Len;
+ Dr7->Rwe2 = rwMask;
+ Dr7->L2 = 0x01;
+ break;
+ case 3:
+ *Dr3 = DataAddr;
+ Dr7->Len3 = Len;
+ Dr7->Rwe3 = rwMask;
+ Dr7->L3 = 0x01;
+ break;
+ }
+
+#ifdef KERNEL
+ ksr.KernelDr6 = 0;
+ return SetExtendedContext(hthd, &ksr);
+#else
+ Context.Dr6 = 0;
+ return SetThreadContext(hthd->rwHand, &Context);
+#endif
+
+}
+
+VOID
+ClearDebugRegister(
+ HTHDX hthd,
+ int Register
+ )
+{
+#ifdef KERNEL
+ KSPECIAL_REGISTERS ksr;
+ PDWORD Dr0 = &ksr.KernelDr0;
+ PDWORD Dr1 = &ksr.KernelDr1;
+ PDWORD Dr2 = &ksr.KernelDr2;
+ PDWORD Dr3 = &ksr.KernelDr3;
+ PDR7 Dr7 = (PDR7)&(ksr.KernelDr7);
+#else
+ CONTEXT Context;
+ PDWORD Dr0 = &Context.Dr0;
+ PDWORD Dr1 = &Context.Dr1;
+ PDWORD Dr2 = &Context.Dr2;
+ PDWORD Dr3 = &Context.Dr3;
+ PDR7 Dr7 = (PDR7)&(Context.Dr7);
+#endif
+
+
+#ifdef KERNEL
+ if (GetExtendedContext(hthd, &ksr))
+#else
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (GetThreadContext(hthd->rwHand, &Context))
+#endif
+ {
+
+ switch( Register ) {
+ case 0:
+ *Dr0 = 0;
+ Dr7->Len0 = 0;
+ Dr7->Rwe0 = 0;
+ Dr7->L0 = 0;
+ break;
+ case 1:
+ *Dr1 = 0;
+ Dr7->Len1 = 0;
+ Dr7->Rwe1 = 0;
+ Dr7->L1 = 0;
+ break;
+ case 2:
+ *Dr2 = 0;
+ Dr7->Len2 = 0;
+ Dr7->Rwe2 = 0;
+ Dr7->L2 = 0;
+ break;
+ case 3:
+ *Dr3 = 0;
+ Dr7->Len3 = 0;
+ Dr7->Rwe3 = 0;
+ Dr7->L3 = 0;
+ break;
+ }
+
+#ifdef KERNEL
+ ksr.KernelDr6 = 0;
+ SetExtendedContext(hthd, &ksr);
+#else
+ Context.Dr6 = 0;
+ SetThreadContext( hthd->rwHand, &Context );
+#endif
+ }
+}
+
+
+BOOL
+DecodeSingleStepEvent(
+ HTHDX hthd,
+ DEBUG_EVENT *de,
+ PDWORD eventCode,
+ PDWORD subClass
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hthd - Supplies thread that has a single step exception pending
+
+ de - Supplies the DEBUG_EVENT structure for the exception
+
+ eventCode - Returns the remapped debug event id
+
+ subClass - Returns the remapped subClass id
+
+
+Return Value:
+
+ TRUE if event was a real single step or was successfully mapped
+ to a breakpoint. FALSE if a register breakpoint occurred which was
+ not expected.
+
+--*/
+{
+ DWORD dr6;
+ PBREAKPOINT bp;
+
+#ifdef KERNEL
+
+ KSPECIAL_REGISTERS ksr;
+
+ GetExtendedContext( hthd, &ksr);
+ dr6 = ksr.KernelDr6;
+
+#else
+
+ CONTEXT Context;
+
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ DbgGetThreadContext( hthd, &Context);
+ dr6 = Context.Dr6;
+
+#endif
+
+ //
+ // if it was a single step, look no further:
+ //
+
+ if ((dr6 & 0x4000) != 0) {
+ return TRUE;
+ }
+
+ //
+ // Search for a matching walk...
+ //
+
+ bp = GetWalkBPFromBits(hthd, (dr6 & 0xf));
+
+ if (bp) {
+ de->dwDebugEventCode = *eventCode = BREAKPOINT_DEBUG_EVENT;
+ de->u.Exception.ExceptionRecord.ExceptionCode = *subClass = (DWORD)bp;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/private/windbg/newdm/kd.h b/private/windbg/newdm/kd.h
new file mode 100644
index 000000000..7f698c949
--- /dev/null
+++ b/private/windbg/newdm/kd.h
@@ -0,0 +1,427 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dbgnt.h
+
+Abstract:
+
+ This module contains prototypes and data structures that
+ are needed by the NT specific portion of DmKd.
+
+Author:
+
+ Wesley Witt (wesw) 2-Aug-1993
+
+Environment:
+
+Revision History:
+
+--*/
+
+#include "crash.h"
+
+#ifndef _KDH_
+#define _KDH_
+
+#ifndef OPTIONAL
+#define OPTIONAL
+#endif
+
+#ifndef ARGUMENT_PRESENT
+#define ARGUMENT_PRESENT(ArgumentPointer) ((CHAR *)(ArgumentPointer) != (CHAR *)(NULL) )
+#endif
+
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((DWORD)0x00000000L)
+#define STATUS_UNSUCCESSFUL ((DWORD)0xC0000001L)
+#define STATUS_BUFFER_OVERFLOW ((DWORD)0x80000005L)
+#define STATUS_INVALID_PARAMETER ((DWORD)0xC000000DL)
+#define STATUS_WAIT_RETURN ((DWORD)0xF0000001L)
+#endif
+
+
+extern DBGKD_WAIT_STATE_CHANGE sc;
+
+#define KD_PROCESSID 1
+#define KD_THREADID (sc.Processor + 1)
+
+
+
+extern DWORD DmKdState;
+//
+// DmKdState defines
+//
+#define S_UNINITIALIZED 0
+#define S_REBOOTED 1
+#define S_INITIALIZED 2
+#define S_READY 3
+
+//---------------------------------------------------------------------------
+// prototypes for: SUPPORT.C
+//---------------------------------------------------------------------------
+
+VOID
+ClearBps(
+ VOID
+ );
+
+DWORD
+DmKdReadPhysicalMemory(
+ IN PHYSICAL_ADDRESS TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ );
+
+DWORD
+DmKdWritePhysicalMemory(
+ IN PHYSICAL_ADDRESS TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesWritten OPTIONAL
+ );
+
+DWORD
+DmKdReboot( VOID );
+
+DWORD
+DmKdCrash( DWORD BugCheckCode );
+
+DWORD
+DmKdGetContext(
+ IN USHORT Processor,
+ IN OUT PCONTEXT Context
+ );
+
+DWORD
+DmKdSetContext(
+ IN USHORT Processor,
+ IN CONST CONTEXT *Context
+ );
+
+DWORD
+DmKdWriteBreakPoint(
+ IN PVOID BreakPointAddress,
+ OUT PULONG BreakPointHandle
+ );
+
+DWORD
+DmKdRestoreBreakPoint(
+ IN ULONG BreakPointHandle
+ );
+
+DWORD
+DmKdReadIoSpace(
+ IN PVOID IoAddress,
+ OUT PVOID ReturnedData,
+ IN ULONG DataSize
+ );
+
+DWORD
+DmKdWriteIoSpace(
+ IN PVOID IoAddress,
+ IN ULONG DataValue,
+ IN ULONG DataSize
+ );
+
+DWORD
+DmKdReadIoSpaceEx(
+ IN PVOID IoAddress,
+ OUT PVOID ReturnedData,
+ IN ULONG DataSize,
+ IN ULONG InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG AddressSpace
+ );
+
+DWORD
+DmKdWriteIoSpaceEx(
+ IN PVOID IoAddress,
+ IN ULONG DataValue,
+ IN ULONG DataSize,
+ IN ULONG InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG AddressSpace
+ );
+
+DWORD
+DmKdReadVirtualMemory(
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ );
+
+DWORD
+DmKdReadVirtualMemoryNow(
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ );
+
+DWORD
+DmKdWriteVirtualMemory(
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesWritten OPTIONAL
+ );
+
+DWORD
+DmKdReadControlSpace(
+ IN USHORT Processor,
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ );
+
+DWORD
+DmKdWriteControlSpace(
+ IN USHORT Processor,
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesWritten OPTIONAL
+ );
+
+DWORD
+DmKdContinue (
+ IN DWORD ContinueStatus
+ );
+
+DWORD
+DmKdContinue2 (
+ IN DWORD ContinueStatus,
+ IN PDBGKD_CONTROL_SET ControlSet
+ );
+
+DWORD
+DmKdSetSpecialCalls (
+ IN ULONG NumSpecialCalls,
+ IN PULONG Calls
+ );
+
+DWORD
+DmKdSetInternalBp (
+ ULONG addr,
+ ULONG flags
+ );
+
+DWORD
+DmKdGetInternalBp (
+ ULONG addr,
+ PULONG flags,
+ PULONG calls,
+ PULONG minInstr,
+ PULONG maxInstr,
+ PULONG totInstr,
+ PULONG maxCPS
+ );
+
+DWORD
+DmKdGetVersion (
+ PDBGKD_GET_VERSION GetVersion
+ );
+
+DWORD
+DmKdPageIn(
+ ULONG Address
+ );
+
+DWORD
+DmKdWriteBreakPointEx(
+ IN ULONG BreakPointCount,
+ IN OUT PDBGKD_WRITE_BREAKPOINT BreakPoints,
+ IN DWORD ContinueStatus
+ );
+
+DWORD
+DmKdRestoreBreakPointEx(
+ IN ULONG BreakPointCount,
+ IN PDBGKD_RESTORE_BREAKPOINT BreakPointHandles
+ );
+
+
+//---------------------------------------------------------------------------
+// prototypes for: COM.C
+//---------------------------------------------------------------------------
+
+BOOLEAN
+DmKdInitComPort(
+ BOOLEAN KdModemControl
+ );
+
+BOOLEAN
+DmKdWriteComPort(
+ IN PUCHAR Buffer,
+ IN ULONG SizeOfBuffer,
+ IN PULONG BytesWritten
+ );
+
+BOOLEAN
+DmKdReadComPort(
+ IN PUCHAR Buffer,
+ IN ULONG SizeOfBuffer,
+ IN PULONG BytesRead
+ );
+
+VOID
+DmKdCheckComStatus (
+ );
+
+
+//---------------------------------------------------------------------------
+// prototypes for: PACKET.C
+//---------------------------------------------------------------------------
+
+VOID
+DmKdWriteControlPacket(
+ IN USHORT PacketType,
+ IN ULONG PacketId OPTIONAL
+ );
+
+ULONG
+DmKdComputeChecksum (
+ IN PUCHAR Buffer,
+ IN ULONG Length
+ );
+
+BOOL
+DmKdSynchronizeTarget ( VOID );
+
+VOID
+DmKdSendBreakin( VOID );
+
+BOOL
+DmKdWritePacket(
+ IN PVOID PacketData,
+ IN USHORT PacketDataLength,
+ IN USHORT PacketType,
+ IN PVOID MorePacketData OPTIONAL,
+ IN USHORT MorePacketDataLength OPTIONAL
+ );
+
+BOOL
+DmKdReadPacketLeader(
+ IN ULONG PacketType,
+ OUT PULONG PacketLeader
+ );
+
+BOOL
+DmKdWaitForPacket(
+ IN USHORT PacketType,
+ OUT PVOID Packet
+ );
+
+DWORD
+DmKdWaitStateChange(
+ OUT PDBGKD_WAIT_STATE_CHANGE StateChange,
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ );
+
+
+
+//---------------------------------------------------------------------------
+// prototypes for: CACHE.C
+//---------------------------------------------------------------------------
+
+ULONG
+DmKdReadCachedVirtualMemory (
+ IN ULONG BaseAddress,
+ IN ULONG TransferCount,
+ IN PUCHAR UserBuffer,
+ IN PULONG BytesRead,
+ IN ULONG NonDiscardable
+ );
+
+VOID
+DmKdInitVirtualCacheEntry (
+ IN ULONG BaseAddress,
+ IN ULONG Length,
+ IN PUCHAR UserBuffer,
+ IN ULONG NonDiscardable
+ );
+
+VOID
+DmKdWriteCachedVirtualMemory (
+ IN ULONG BaseAddress,
+ IN ULONG TransferCount,
+ IN PUCHAR UserBuffer
+ );
+
+VOID
+DmKdPurgeCachedVirtualMemory (
+ BOOL fPurgeNonDiscardable
+ );
+
+VOID
+DmKdSetCacheDecodePTEs (
+ BOOL Flag
+ );
+
+VOID
+DmKdSetMaxCacheSize(
+ IN ULONG MaxCacheSize
+ );
+
+BOOL
+DmpInitialize (
+ IN LPSTR FileName,
+ OUT PCONTEXT *Context,
+ OUT PEXCEPTION_RECORD *Exception,
+ OUT PVOID *DmpHeader
+ );
+
+VOID
+DmpUnInitialize (
+ VOID
+ );
+
+DWORD
+DmpReadMemory (
+ IN PVOID BaseAddress,
+ IN PVOID Buffer,
+ IN ULONG Size
+ );
+
+DWORD
+DmpWriteMemory (
+ IN PVOID BaseAddress,
+ IN PVOID Buffer,
+ IN ULONG Size
+ );
+
+typedef struct tagKDOPTIONS {
+ LPSTR keyword; // data keyword
+ USHORT id; // data identifier
+ USHORT typ; // data type
+ DWORD value; // data value, beware usage depends on typ field
+} KDOPTIONS, *PKDOPTIONS;
+
+#define KDT_DWORD 0
+#define KDT_STRING 1
+
+#define KDO_BAUDRATE 0 // these constants must be consecutive because
+#define KDO_PORT 1 // they are used as indexes into the kdoptions
+#define KDO_CACHE 2 // array of structures.
+#define KDO_VERBOSE 3
+#define KDO_INITIALBP 4
+#define KDO_DEFER 5
+#define KDO_USEMODEM 6
+#define KDO_LOGFILEAPPEND 7
+#define KDO_GOEXIT 8
+#define KDO_SYMBOLPATH 9
+#define KDO_LOGFILENAME 10
+#define KDO_CRASHDUMP 11
+
+#define MAXKDOPTIONS (sizeof(KdOptions) / sizeof(KDOPTIONS))
+
+extern KDOPTIONS KdOptions[];
+
+#endif
diff --git a/private/windbg/newdm/kdapi.c b/private/windbg/newdm/kdapi.c
new file mode 100644
index 000000000..ae237a175
--- /dev/null
+++ b/private/windbg/newdm/kdapi.c
@@ -0,0 +1,3768 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ api.c
+
+Abstract:
+
+ This module implements the all apis that simulate their
+ WIN32 counterparts.
+
+Author:
+
+ Wesley Witt (wesw) 8-Mar-1992
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// structures & defines for queue management
+//
+typedef struct tagCQUEUE {
+ struct tagCQUEUE *next;
+ DWORD pid;
+ DWORD tid;
+ DWORD typ;
+ DWORD len;
+ DWORD data;
+} CQUEUE, *LPCQUEUE;
+
+LPCQUEUE lpcqFirst;
+LPCQUEUE lpcqLast;
+LPCQUEUE lpcqFree;
+CQUEUE cqueue[200];
+CRITICAL_SECTION csContinueQueue;
+
+
+//
+// context cache
+//
+typedef struct _tagCONTEXTCACHE {
+ CONTEXT Context;
+#if defined(TARGET_i386) || defined(TARGET_PPC)
+ KSPECIAL_REGISTERS sregs;
+ BOOL fSContextStale;
+ BOOL fSContextDirty;
+#endif // i386 || PPC
+ BOOL fContextStale;
+ BOOL fContextDirty;
+} CONTEXTCACHE, *LPCONTEXTCACHE;
+
+CONTEXTCACHE ContextCache[MAXIMUM_PROCESSORS];
+DWORD CacheProcessors = 1; // up machine by default
+
+#if defined(TARGET_MIPS)
+MIPSCONTEXTSIZE MipsContextSize;
+#endif
+
+extern MODULEALIAS ModuleAlias[];
+
+//
+// globals
+//
+DWORD DmKdState = S_UNINITIALIZED;
+BOOL DmKdExit;
+DBGKD_WAIT_STATE_CHANGE sc;
+BOOL fScDirty;
+BOOL ApiIsAllowed;
+HANDLE hEventContinue;
+BOOL fCrashDump;
+DBGKD_WRITE_BREAKPOINT bps[64];
+BOOL bpcheck[64];
+HANDLE hThreadDmPoll;
+DBGKD_GET_VERSION vs;
+PDUMP_HEADER DmpHeader;
+char szProgName[MAX_PATH];
+DWORD PollThreadId;
+PKPRCB KiProcessors[MAXIMUM_PROCESSORS];
+PCONTEXT DmpContext;
+BOOL fPacketTrace;
+
+//
+// kernel symbol addresses
+//
+ULONG DcbAddr;
+ULONG MmLoadedUserImageList;
+ULONG KiPcrBaseAddress;
+ULONG KiProcessorBlockAddr;
+
+
+
+
+#define IsApiAllowed() if (!ApiIsAllowed) return 0;
+#define NoApiForCrashDump() if (fCrashDump) return 0;
+#define ConsumeAllEvents() DequeueAllEvents(FALSE,TRUE)
+
+#define END_OF_CONTROL_SPACE (sizeof(KPROCESSOR_STATE))
+
+#define CRASH_BUGCHECK_CODE 0xDEADDEAD
+
+//
+// local prototypes
+//
+BOOL GenerateKernelModLoad(HPRCX hprc, LPSTR lpProgName);
+
+
+//
+// externs
+//
+extern jmp_buf JumpBuffer;
+extern BOOL DmKdBreakIn;
+extern BOOL KdResync;
+extern BOOL InitialBreak;
+extern HANDLE hEventCreateProcess;
+extern HANDLE hEventCreateThread;
+extern HANDLE hEventRemoteQuit;
+extern HANDLE hEventContinue;
+extern HPRCX prcList;
+extern BOOL fDisconnected;
+
+extern LPDM_MSG LpDmMsg;
+
+extern PKILLSTRUCT KillQueue;
+extern CRITICAL_SECTION csKillQueue;
+
+extern HTHDX thdList;
+extern HPRCX prcList;
+extern CRITICAL_SECTION csThreadProcList;
+
+extern BOOL fSmartRangeStep;
+extern HANDLE hEventNoDebuggee;
+extern HANDLE hEventRemoteQuit;
+extern BOOL fDisconnected;
+extern BOOL fUseRoot;
+extern char nameBuffer[];
+
+
+
+DWORD GetSymbolAddress( LPSTR sym );
+BOOL UnloadModule( DWORD BaseOfDll, LPSTR NameOfDll );
+VOID UnloadAllModules( VOID );
+VOID DisableEmCache( VOID );
+VOID InitializeKiProcessor(VOID);
+VOID ProcessCacheCmd(LPSTR pchCommand);
+
+
+
+BOOL
+DbgReadMemory(
+ HPRCX hprc,
+ PVOID lpBaseAddress,
+ PVOID lpBuffer,
+ DWORD nSize,
+ PDWORD lpcbRead
+ )
+{
+ DWORD cb;
+ int iDll;
+ int iobj;
+ static PIMAGE_SECTION_HEADER s = NULL;
+ BOOL non_discardable = FALSE;
+ PDLLLOAD_ITEM d;
+
+
+ IsApiAllowed();
+
+ if (nSize == 0) {
+ return TRUE;
+ }
+
+ //
+ // the following code is necessary to determine if the requested
+ // base address is in a read-only page or is in a page that contains
+ // code. if the base address meets these conditions then is is marked
+ // as non-discardable and will never be purged from the cache.
+ //
+ if (s &&
+ (DWORD)lpBaseAddress >= s->VirtualAddress &&
+ (DWORD)lpBaseAddress < s->VirtualAddress+s->SizeOfRawData &&
+ ((s->Characteristics & IMAGE_SCN_CNT_CODE) ||
+ (!s->Characteristics & IMAGE_SCN_MEM_WRITE))) {
+
+ non_discardable = TRUE;
+
+ }
+ else {
+ d = prcList->next->rgDllList;
+ for (iDll=0; iDll<prcList->next->cDllList; iDll++) {
+ if ((DWORD)lpBaseAddress >= d[iDll].offBaseOfImage &&
+ (DWORD)lpBaseAddress < d[iDll].offBaseOfImage+d[iDll].cbImage) {
+
+ if (!d[iDll].Sections) {
+ if (d[iDll].sec) {
+ d[iDll].Sections = d[iDll].sec;
+ for (iobj=0; iobj<(int)d[iDll].NumberOfSections; iobj++) {
+ d[iDll].Sections[iobj].VirtualAddress += (DWORD)d[iDll].offBaseOfImage;
+ }
+ }
+ }
+
+ s = d[iDll].Sections;
+
+ cb = d[iDll].NumberOfSections;
+ while (cb) {
+ if ((DWORD)lpBaseAddress >= s->VirtualAddress &&
+ (DWORD)lpBaseAddress < s->VirtualAddress+s->SizeOfRawData &&
+ ((s->Characteristics & IMAGE_SCN_CNT_CODE) ||
+ (!s->Characteristics & IMAGE_SCN_MEM_WRITE))) {
+
+ non_discardable = TRUE;
+ break;
+
+ }
+ else {
+ s++;
+ cb--;
+ }
+ }
+ if (!cb) {
+ s = NULL;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (fCrashDump) {
+
+ cb = DmpReadMemory( lpBaseAddress, lpBuffer, nSize );
+
+ } else {
+
+ if (DmKdReadCachedVirtualMemory( (DWORD) lpBaseAddress,
+ nSize,
+ (PUCHAR) lpBuffer,
+ &cb,
+ non_discardable) != STATUS_SUCCESS ) {
+ cb = 0;
+ }
+
+ }
+
+ if ( cb > 0 && non_discardable ) {
+ BREAKPOINT *bp;
+ ADDR Addr;
+ BP_UNIT instr;
+ DWORD offset;
+ LPVOID lpb;
+
+ AddrInit( &Addr, 0, 0, (UOFF32)lpBaseAddress, TRUE, TRUE, FALSE, FALSE );
+ lpb = lpBuffer;
+
+ for (bp=bpList->next; bp; bp=bp->next) {
+ if (BPInRange((HPRCX)0, (HTHDX)0, bp, &Addr, cb, &offset, &instr)) {
+ if (instr) {
+ if (offset < 0) {
+ memcpy(lpb, ((char *) &instr) - offset,
+ sizeof(BP_UNIT) + offset);
+ } else if (offset + sizeof(BP_UNIT) > cb) {
+ memcpy(((char *)lpb)+offset, &instr, cb - offset);
+ } else {
+ *((BP_UNIT UNALIGNED *)((char *)lpb+offset)) = instr;
+ }
+ }
+ }
+ }
+ }
+
+ if (cb > 0) {
+ if (lpcbRead) {
+ *lpcbRead = cb;
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOL
+DbgWriteMemory(
+ HPRCX hprc,
+ PVOID lpBaseAddress,
+ PVOID lpBuffer,
+ DWORD nSize,
+ LPDWORD lpcbWrite
+ )
+{
+ ULONG cb;
+
+
+ IsApiAllowed();
+
+ if (nSize == 0) {
+ return TRUE;
+ }
+
+ if (fCrashDump) {
+
+ cb = DmpWriteMemory( lpBaseAddress, lpBuffer, nSize );
+
+ } else {
+
+ if (DmKdWriteVirtualMemory( lpBaseAddress,
+ lpBuffer,
+ nSize,
+ &cb ) != STATUS_SUCCESS ) {
+ cb = 0;
+ }
+
+ }
+
+ if (cb > 0) {
+ if (lpcbWrite) {
+ *lpcbWrite = cb;
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOL
+DbgGetThreadContext(
+ IN HTHDX hthd,
+ OUT LPCONTEXT lpContext
+ )
+{
+ BOOL rc = TRUE;
+ USHORT processor;
+ DWORD Flags = lpContext->ContextFlags;
+
+ DPRINT(1, ( "DbgGetThreadContext( 0x%x )\n", lpContext ));
+
+ IsApiAllowed();
+
+ if (!hthd) {
+ return FALSE;
+ }
+
+ processor = (USHORT)hthd->tid - 1;
+
+ if (fCrashDump) {
+ if (processor == sc.Processor && KiProcessors[processor] == 0) {
+ memcpy( lpContext, DmpContext, sizeof(CONTEXT) );
+ rc = TRUE;
+ } else {
+ rc = DmpGetContext( processor, lpContext );
+#if defined(TARGET_MIPS)
+ if (rc) {
+ if (DmpHeader->MajorVersion > 3) {
+ MipsContextSize = Ctx64Bit;
+ } else {
+ MipsContextSize = Ctx32Bit;
+ CoerceContext32To64(&ContextCache[processor].Context);
+ }
+ }
+#endif
+ }
+
+ } else {
+
+ if (ContextCache[processor].fContextStale) {
+
+ rc = (DmKdGetContext( processor, &ContextCache[processor].Context )
+ == STATUS_SUCCESS);
+ if (rc) {
+ ContextCache[processor].fContextDirty = FALSE;
+ ContextCache[processor].fContextStale = FALSE;
+#if defined(TARGET_MIPS)
+ if ((ContextCache[processor].Context.ContextFlags &
+ CONTEXT_EXTENDED_INTEGER) == CONTEXT_EXTENDED_INTEGER) {
+ MipsContextSize = Ctx64Bit;
+ } else {
+ MipsContextSize = Ctx32Bit;
+ CoerceContext32To64(&ContextCache[processor].Context);
+ }
+#endif
+ }
+ }
+
+ if (rc) {
+ memcpy( lpContext,
+ &ContextCache[processor].Context,
+ sizeof(ContextCache[processor].Context) );
+ }
+
+ }
+
+#if defined(TARGET_MIPS)
+ if (rc) {
+ if ((Flags & CONTEXT_EXTENDED_INTEGER) == CONTEXT_EXTENDED_INTEGER) {
+ CoerceContext32To64(lpContext);
+ } else if ((Flags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
+ CoerceContext64To32(lpContext);
+ }
+ }
+#endif
+
+ if (rc) {
+ hthd->fContextStale = FALSE;
+ }
+
+ return rc;
+}
+
+BOOL
+DbgSetThreadContext(
+ IN HTHDX hthd,
+ IN LPCONTEXT lpContext
+ )
+{
+ BOOL rc = TRUE;
+ USHORT processor;
+#if defined(TARGET_MIPS)
+ CONTEXT LocalContext;
+#endif
+
+
+ DEBUG_PRINT_1( "DbgSetThreadContext( 0x%x )\n", lpContext );
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ processor = (USHORT)hthd->tid - 1;
+ memcpy( &ContextCache[processor].Context, lpContext, sizeof(CONTEXT) );
+
+#if defined(TARGET_MIPS)
+ CoerceContext32To64( &ContextCache[processor].Context );
+#endif
+
+ if (lpContext != &hthd->context) {
+ memcpy(&hthd->context, &ContextCache[processor].Context, sizeof(CONTEXT));
+ }
+
+ ContextCache[processor].fContextDirty = FALSE;
+ ContextCache[processor].fContextStale = FALSE;
+
+
+#if defined(TARGET_MIPS)
+ if (MipsContextSize == Ctx64Bit) {
+ lpContext = &ContextCache[processor].Context;
+ } else {
+ memcpy( &LocalContext, lpContext, sizeof(CONTEXT) );
+ CoerceContext32To64( &LocalContext );
+ lpContext = &LocalContext;
+ }
+#endif
+
+ if (DmKdSetContext( processor, lpContext ) != STATUS_SUCCESS) {
+ rc = FALSE;
+ }
+
+ return rc;
+}
+
+
+BOOL
+WriteBreakPoint(
+ IN PBREAKPOINT Breakpoint
+ )
+{
+ BOOL rc = TRUE;
+
+ DEBUG_PRINT_2( "WriteBreakPoint( 0x%08x, 0x%08x )\n",
+ GetAddrOff(Breakpoint->addr),
+ Breakpoint->hBreakPoint);
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ if (DmKdWriteBreakPoint( (PVOID)GetAddrOff(Breakpoint->addr),
+ &Breakpoint->hBreakPoint ) != STATUS_SUCCESS) {
+ rc = FALSE;
+ }
+
+ return rc;
+}
+
+BOOL
+WriteBreakPointEx(
+ IN HTHDX hthd,
+ IN ULONG BreakPointCount,
+ IN OUT PDBGKD_WRITE_BREAKPOINT BreakPoints,
+ IN ULONG ContinueStatus
+ )
+{
+ BOOL rc = TRUE;
+
+ assert( BreakPointCount > 0 );
+ assert( BreakPoints );
+
+ DEBUG_PRINT_2( "WriteBreakPointEx( %d, 0x%08x )\n",
+ BreakPointCount, BreakPoints );
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ if (DmKdWriteBreakPointEx( BreakPointCount, BreakPoints, ContinueStatus ) != STATUS_SUCCESS) {
+ rc = FALSE;
+ }
+
+ return rc;
+}
+
+
+BOOL
+RestoreBreakPoint(
+ IN PBREAKPOINT Breakpoint
+ )
+{
+ BOOL rc = TRUE;
+
+ DEBUG_PRINT_1( "RestoreBreakPoint( 0x%08x )\n", Breakpoint->hBreakPoint );
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ if (DmKdRestoreBreakPoint( Breakpoint->hBreakPoint ) != STATUS_SUCCESS) {
+ rc = FALSE;
+ }
+
+ return rc;
+}
+
+
+BOOL
+RestoreBreakPointEx(
+ IN ULONG BreakPointCount,
+ IN PDBGKD_RESTORE_BREAKPOINT BreakPointHandles
+ )
+{
+ BOOL rc = TRUE;
+
+ assert( BreakPointCount > 0 );
+ assert( BreakPointHandles );
+
+ DEBUG_PRINT_2( "WriteBreakPointEx( %d, 0x%08x )\n",
+ BreakPointCount, BreakPointHandles );
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ if (DmKdRestoreBreakPointEx( BreakPointCount, BreakPointHandles ) != STATUS_SUCCESS) {
+ rc = FALSE;
+ }
+
+ return rc;
+}
+
+BOOL
+ReadControlSpace(
+ USHORT Processor,
+ PVOID TargetBaseAddress,
+ PVOID UserInterfaceBuffer,
+ ULONG TransferCount,
+ PULONG ActualBytesRead
+ )
+{
+ DWORD Status;
+
+
+ IsApiAllowed();
+
+ if (fCrashDump) {
+ return DmpReadControlSpace(
+ Processor,
+ TargetBaseAddress,
+ UserInterfaceBuffer,
+ TransferCount,
+ ActualBytesRead
+ );
+ }
+
+ Status = DmKdReadControlSpace(
+ Processor,
+ TargetBaseAddress,
+ UserInterfaceBuffer,
+ TransferCount,
+ ActualBytesRead
+ );
+
+ if (Status || (ActualBytesRead && *ActualBytesRead != TransferCount)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID
+ContinueTargetSystem(
+ DWORD ContinueStatus,
+ PDBGKD_CONTROL_SET ControlSet
+ )
+{
+ DWORD rc;
+
+ ApiIsAllowed = FALSE;
+
+ if (ControlSet) {
+
+ rc = DmKdContinue2( ContinueStatus, ControlSet );
+
+ } else {
+
+ rc = DmKdContinue( ContinueStatus );
+
+ }
+}
+
+ULONG
+UnicodeStringToAnsiString(
+ PANSI_STRING DestinationString,
+ PUNICODE_STRING SourceString,
+ BOOLEAN AllocateDestinationString
+ )
+{
+ if (AllocateDestinationString) {
+ DestinationString->Buffer = malloc( DestinationString->MaximumLength );
+ if (!DestinationString->Buffer) {
+ return 1;
+ }
+ }
+
+ DestinationString->Length = WideCharToMultiByte(
+ CP_ACP,
+ WC_COMPOSITECHECK,
+ SourceString->Buffer,
+ SourceString->Length / 2,
+ DestinationString->Buffer,
+ DestinationString->MaximumLength,
+ NULL,
+ NULL
+ );
+
+ return 0;
+}
+
+
+VOID
+InitUnicodeString(
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString
+ )
+{
+ wcsncpy( DestinationString->Buffer, SourceString, DestinationString->MaximumLength );
+ DestinationString->Length = wcslen( DestinationString->Buffer ) * 2;
+}
+
+
+BOOL
+ReloadModule(
+ HTHDX hthd,
+ PLDR_DATA_TABLE_ENTRY DataTableBuffer,
+ BOOL fDontUseLoadAddr,
+ BOOL fLocalBuffer
+ )
+{
+ UNICODE_STRING BaseName;
+ CHAR AnsiBuffer[512];
+ WCHAR UnicodeBuffer[512];
+ ANSI_STRING AnsiString;
+ NTSTATUS Status;
+ DEBUG_EVENT de;
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ ULONG cb;
+
+
+ //
+ // Get the base DLL name.
+ //
+ if (DataTableBuffer->BaseDllName.Length != 0 &&
+ DataTableBuffer->BaseDllName.Buffer != NULL ) {
+
+ BaseName = DataTableBuffer->BaseDllName;
+
+ } else
+ if (DataTableBuffer->FullDllName.Length != 0 &&
+ DataTableBuffer->FullDllName.Buffer != NULL ) {
+
+ BaseName = DataTableBuffer->FullDllName;
+
+ } else {
+
+ return FALSE;
+
+ }
+
+ if (BaseName.Length > sizeof(UnicodeBuffer)) {
+ DMPrintShellMsg( "cannot complete modload %08x\n", BaseName.Length );
+ return FALSE;
+ }
+
+ if (!fLocalBuffer) {
+ if (!DbgReadMemory( hthd->hprc, (PVOID)BaseName.Buffer, (PVOID)UnicodeBuffer, BaseName.Length, &cb )) {
+ return FALSE;
+ }
+ BaseName.Buffer = UnicodeBuffer;
+ BaseName.Length = (USHORT)cb;
+ BaseName.MaximumLength = (USHORT)(cb + sizeof( UNICODE_NULL ));
+ UnicodeBuffer[ cb / sizeof( WCHAR ) ] = UNICODE_NULL;
+ }
+
+ AnsiString.Buffer = AnsiBuffer;
+ AnsiString.MaximumLength = 256;
+ Status = UnicodeStringToAnsiString(&AnsiString, &BaseName, FALSE);
+ if (!NT_SUCCESS(Status)) {
+ return FALSE;
+ }
+ AnsiString.Buffer[AnsiString.Length] = '\0';
+
+ _splitpath( AnsiString.Buffer, NULL, NULL, fname, ext );
+ _makepath( AnsiString.Buffer, NULL, NULL, fname, ext );
+
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.LoadDll.hFile = (HANDLE)DataTableBuffer->CheckSum;
+ de.u.LoadDll.lpBaseOfDll = fDontUseLoadAddr ? 0 : (LPVOID) DataTableBuffer->DllBase;
+ de.u.LoadDll.lpImageName = AnsiString.Buffer;
+ de.u.LoadDll.dwDebugInfoFileOffset = DataTableBuffer->SizeOfImage;
+ de.u.LoadDll.fUnicode = FALSE;
+ de.u.LoadDll.nDebugInfoSize = 0;
+
+ NotifyEM(&de, hthd, 0, (LPVOID)0);
+
+ return TRUE;
+}
+
+
+BOOL
+ReloadModulesFromList(
+ HTHDX hthd,
+ DWORD ListAddr,
+ BOOL fDontUseLoadAddr,
+ LPSTR JustLoadThisOne,
+ ULONG UseThisAddress
+ )
+{
+ LIST_ENTRY List;
+ PLIST_ENTRY Next;
+ ULONG len = 0;
+ PLDR_DATA_TABLE_ENTRY DataTable;
+ LDR_DATA_TABLE_ENTRY DataTableBuffer;
+ WCHAR UnicodeBuffer[_MAX_PATH];
+ WCHAR UnicodeBuffer2[_MAX_PATH];
+ int Len;
+ BOOL LoadedSomething;
+
+
+ if (!ListAddr) {
+ return FALSE;
+ }
+
+ //
+ // convert the module name to unicode
+ //
+
+ *UnicodeBuffer = 0;
+
+ if (JustLoadThisOne) {
+
+
+ Len = strlen(JustLoadThisOne);
+ MultiByteToWideChar(
+ CP_OEMCP,
+ 0,
+ JustLoadThisOne,
+ Len,
+ UnicodeBuffer,
+ sizeof(UnicodeBuffer)
+ );
+ }
+
+ if (!DbgReadMemory( hthd->hprc, (PVOID)ListAddr, (PVOID)&List, sizeof(LIST_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ Next = List.Flink;
+ if (Next == NULL) {
+ return FALSE;
+ }
+
+ LoadedSomething = FALSE;
+
+ while ((ULONG)Next != ListAddr) {
+ DataTable = CONTAINING_RECORD( Next,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks
+ );
+
+ if (!DbgReadMemory( hthd->hprc, (PVOID)DataTable, (PVOID)&DataTableBuffer, sizeof(LDR_DATA_TABLE_ENTRY), NULL)) {
+ break;
+ }
+
+ Next = DataTableBuffer.InLoadOrderLinks.Flink;
+
+ if (!JustLoadThisOne) {
+ ReloadModule( hthd, &DataTableBuffer, fDontUseLoadAddr, FALSE );
+ LoadedSomething = TRUE;
+ } else {
+ if (2*Len == DataTableBuffer.BaseDllName.Length) {
+ if (!DbgReadMemory( hthd->hprc,
+ (PVOID)DataTableBuffer.BaseDllName.Buffer,
+ (PVOID)UnicodeBuffer2,
+ DataTableBuffer.BaseDllName.Length,
+ NULL )) {
+ continue;
+ }
+ if (_wcsnicmp(UnicodeBuffer, UnicodeBuffer2, Len) == 0) {
+ if (UseThisAddress) {
+ DataTableBuffer.DllBase = (PVOID)UseThisAddress;
+ }
+ ReloadModule( hthd, &DataTableBuffer, fDontUseLoadAddr, FALSE );
+ LoadedSomething = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ return LoadedSomething;
+}
+
+
+BOOL
+ReloadCrashModules(
+ HTHDX hthd
+ )
+{
+ ULONG ListAddr;
+ ULONG DcbPtr;
+ ULONG i;
+ DUMP_CONTROL_BLOCK dcb;
+ PLIST_ENTRY Next;
+ ULONG len = 0;
+ PMINIPORT_NODE mpNode;
+ MINIPORT_NODE mpNodeBuf;
+ PLDR_DATA_TABLE_ENTRY DataTable;
+ LDR_DATA_TABLE_ENTRY DataTableBuffer;
+ CHAR AnsiBuffer[512];
+ WCHAR UnicodeBuffer[512];
+
+
+ if (!DcbAddr) {
+ //
+ // kernel symbols are hosed
+ //
+ return FALSE;
+ }
+
+ if (!DbgReadMemory( hthd->hprc, (PVOID)DcbAddr, (PVOID)&DcbPtr, sizeof(DWORD), NULL)) {
+ return FALSE;
+ }
+
+ if (!DcbPtr) {
+ //
+ // crash dumps are not enabled
+ //
+ return FALSE;
+ }
+
+ if (!DbgReadMemory( hthd->hprc, (PVOID)DcbPtr, (PVOID)&dcb, sizeof(dcb), NULL)) {
+ return FALSE;
+ }
+
+ ListAddr = DcbPtr + FIELD_OFFSET( DUMP_CONTROL_BLOCK, MiniportQueue );
+
+ Next = dcb.MiniportQueue.Flink;
+ if (Next == NULL) {
+ return FALSE;
+ }
+
+ while ((ULONG)Next != ListAddr) {
+ mpNode = CONTAINING_RECORD( Next, MINIPORT_NODE, ListEntry );
+
+ if (!DbgReadMemory( hthd->hprc, (PVOID)mpNode, (PVOID)&mpNodeBuf, sizeof(MINIPORT_NODE), NULL )) {
+ return FALSE;
+ }
+
+ Next = mpNodeBuf.ListEntry.Flink;
+
+ DataTable = mpNodeBuf.DriverEntry;
+ if (!DataTable) {
+ continue;
+ }
+
+ if (!DbgReadMemory( hthd->hprc, (PVOID)DataTable, (PVOID)&DataTableBuffer, sizeof(LDR_DATA_TABLE_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ //
+ // find an empty module alias slot
+ //
+ for (i=0; i<MAX_MODULEALIAS; i++) {
+ if (ModuleAlias[i].ModuleName[0] == 0) {
+ break;
+ }
+ }
+
+ if (i == MAX_MODULEALIAS) {
+ //
+ // module alias table is full, ignore this module
+ //
+ continue;
+ }
+
+ //
+ // convert the module name to ansi
+ //
+
+ ZeroMemory( UnicodeBuffer, sizeof(UnicodeBuffer) );
+ ZeroMemory( AnsiBuffer, sizeof(AnsiBuffer) );
+
+ if (!DbgReadMemory( hthd->hprc,
+ (PVOID)DataTableBuffer.BaseDllName.Buffer,
+ (PVOID)UnicodeBuffer,
+ DataTableBuffer.BaseDllName.Length,
+ NULL )) {
+ continue;
+ }
+
+ WideCharToMultiByte(
+ CP_OEMCP,
+ 0,
+ UnicodeBuffer,
+ DataTableBuffer.BaseDllName.Length / 2,
+ AnsiBuffer,
+ sizeof(AnsiBuffer),
+ NULL,
+ NULL
+ );
+
+ //
+ // establish an alias for the crash driver
+ //
+ strcpy( ModuleAlias[i].Alias, AnsiBuffer );
+ ModuleAlias[i].ModuleName[0] = 'c';
+ _splitpath( AnsiBuffer, NULL, NULL, &ModuleAlias[i].ModuleName[1], NULL );
+ ModuleAlias[i].ModuleName[8] = 0;
+ ModuleAlias[i].Special = 2; // One shot alias...
+
+ //
+ // reload the module
+ //
+ ReloadModule( hthd, &DataTableBuffer, FALSE, FALSE );
+ }
+
+ //
+ // now do the magic diskdump.sys driver
+ //
+ if (!DbgReadMemory( hthd->hprc, (PVOID)dcb.DiskDumpDriver, (PVOID)&DataTableBuffer, sizeof(LDR_DATA_TABLE_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ //
+ // change the driver name from scsiport.sys to diskdump.sys
+ //
+ DataTableBuffer.BaseDllName.Buffer = UnicodeBuffer;
+ InitUnicodeString( &DataTableBuffer.BaseDllName, L"diskdump.sys" );
+
+ //
+ // load the module
+ //
+ ReloadModule( hthd, &DataTableBuffer, FALSE, TRUE );
+
+ return TRUE;
+}
+
+
+BOOL
+FindModuleInList(
+ HPRCX hprc,
+ LPSTR lpModName,
+ DWORD ListAddr,
+ LPIMAGEINFO ii
+ )
+{
+ LIST_ENTRY List;
+ PLIST_ENTRY Next;
+ ULONG len = 0;
+ ULONG cb;
+ PLDR_DATA_TABLE_ENTRY DataTable;
+ LDR_DATA_TABLE_ENTRY DataTableBuffer;
+ UNICODE_STRING BaseName;
+ CHAR AnsiBuffer[512];
+ WCHAR UnicodeBuffer[512];
+ ANSI_STRING AnsiString;
+ NTSTATUS Status;
+
+
+ ii->CheckSum = 0;
+ ii->SizeOfImage = 0;
+ ii->BaseOfImage = 0;
+
+ if (!ListAddr) {
+ return FALSE;
+ }
+
+ if (!DbgReadMemory( hprc, (PVOID)ListAddr, (PVOID)&List, sizeof(LIST_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ Next = List.Flink;
+ if (Next == NULL) {
+ return FALSE;
+ }
+
+ while ((ULONG)Next != ListAddr) {
+ DataTable = CONTAINING_RECORD( Next,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks
+ );
+ if (!DbgReadMemory( hprc, (PVOID)DataTable, (PVOID)&DataTableBuffer, sizeof(LDR_DATA_TABLE_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ Next = DataTableBuffer.InLoadOrderLinks.Flink;
+
+ //
+ // Get the base DLL name.
+ //
+ if (DataTableBuffer.BaseDllName.Length != 0 &&
+ DataTableBuffer.BaseDllName.Buffer != NULL
+ ) {
+ BaseName = DataTableBuffer.BaseDllName;
+ }
+ else
+ if (DataTableBuffer.FullDllName.Length != 0 &&
+ DataTableBuffer.FullDllName.Buffer != NULL
+ ) {
+ BaseName = DataTableBuffer.FullDllName;
+ }
+ else {
+ continue;
+ }
+
+ if (BaseName.Length > sizeof(UnicodeBuffer)) {
+ continue;
+ }
+
+ cb = DbgReadMemory( hprc,
+ (PVOID)BaseName.Buffer,
+ (PVOID)UnicodeBuffer,
+ BaseName.Length,
+ NULL );
+ if (!cb) {
+ return FALSE;
+ }
+
+ BaseName.Buffer = UnicodeBuffer;
+ BaseName.Length = (USHORT)cb;
+ BaseName.MaximumLength = (USHORT)(cb + sizeof( UNICODE_NULL ));
+ UnicodeBuffer[ cb / sizeof( WCHAR ) ] = UNICODE_NULL;
+ AnsiString.Buffer = AnsiBuffer;
+ AnsiString.MaximumLength = 256;
+ Status = UnicodeStringToAnsiString(&AnsiString, &BaseName, FALSE);
+ if (!NT_SUCCESS(Status)) {
+ return FALSE;
+ }
+ AnsiString.Buffer[AnsiString.Length] = '\0';
+
+ if (_stricmp(AnsiString.Buffer, lpModName) == 0) {
+ ii->BaseOfImage = (DWORD)DataTableBuffer.DllBase;
+ ii->SizeOfImage = (DWORD)DataTableBuffer.SizeOfImage;
+ ii->CheckSum = (DWORD)DataTableBuffer.CheckSum;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+ReadImageInfo(
+ LPSTR lpImageName,
+ LPSTR lpFoundName,
+ LPSTR lpPath,
+ LPIMAGEINFO ii
+ )
+
+/*++
+
+Routine Description:
+
+ This routine locates the file specified by lpImageName and reads the
+ IMAGE_NT_HEADERS and the IMAGE_SECTION_HEADER from the image.
+
+Arguments:
+
+
+Return Value:
+
+ True on success and FALSE on failure
+
+--*/
+
+{
+ HANDLE hFile;
+ IMAGE_DOS_HEADER dh;
+ IMAGE_NT_HEADERS nh;
+ IMAGE_SEPARATE_DEBUG_HEADER sdh;
+ IMAGE_ROM_OPTIONAL_HEADER rom;
+ DWORD sig;
+ DWORD cb;
+ char rgch[MAX_PATH];
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ CHAR drive[_MAX_DRIVE];
+ CHAR dir[_MAX_DIR];
+ CHAR modname[MAX_PATH];
+
+
+ hFile = FindExecutableImage( lpImageName, lpPath, rgch );
+ if (hFile) {
+
+ if (lpFoundName) {
+ strcpy(lpFoundName, rgch);
+ }
+ //
+ // read in the pe/file headers from the EXE file
+ //
+ SetFilePointer( hFile, 0, 0, FILE_BEGIN );
+ ReadFile( hFile, &dh, sizeof(IMAGE_DOS_HEADER), &cb, NULL );
+
+ if (dh.e_magic == IMAGE_DOS_SIGNATURE) {
+ SetFilePointer( hFile, dh.e_lfanew, 0, FILE_BEGIN );
+ } else {
+ SetFilePointer( hFile, 0, 0, FILE_BEGIN );
+ }
+
+ ReadFile( hFile, &sig, sizeof(sig), &cb, NULL );
+ SetFilePointer( hFile, -4, NULL, FILE_CURRENT );
+
+ if (sig != IMAGE_NT_SIGNATURE) {
+ ReadFile( hFile, &nh.FileHeader, sizeof(IMAGE_FILE_HEADER), &cb, NULL );
+ if (nh.FileHeader.SizeOfOptionalHeader == IMAGE_SIZEOF_ROM_OPTIONAL_HEADER) {
+ ReadFile( hFile, &rom, sizeof(rom), &cb, NULL );
+ ZeroMemory( &nh.OptionalHeader, sizeof(nh.OptionalHeader) );
+ nh.OptionalHeader.SizeOfImage = rom.SizeOfCode;
+ nh.OptionalHeader.ImageBase = rom.BaseOfCode;
+ } else {
+ CloseHandle( hFile );
+ return FALSE;
+ }
+ } else {
+ ReadFile( hFile, &nh, sizeof(nh), &cb, NULL );
+ }
+
+ ii->TimeStamp = nh.FileHeader.TimeDateStamp;
+ ii->CheckSum = nh.OptionalHeader.CheckSum;
+ ii->SizeOfImage = nh.OptionalHeader.SizeOfImage;
+ ii->BaseOfImage = nh.OptionalHeader.ImageBase;
+
+ } else {
+
+ if (lpFoundName) {
+ *lpFoundName = 0;
+ }
+ //
+ // read in the pe/file headers from the DBG file
+ //
+ hFile = FindDebugInfoFile( lpImageName, lpPath, rgch );
+ if (!hFile) {
+ _splitpath( lpImageName, NULL, NULL, fname, NULL );
+ sprintf( modname, "%s.dbg", fname );
+ hFile = FindExecutableImage( modname, lpPath, rgch );
+ if (!hFile) {
+ return FALSE;
+ }
+ }
+
+ SetFilePointer( hFile, 0, 0, FILE_BEGIN );
+ ReadFile( hFile, &sdh, sizeof(IMAGE_SEPARATE_DEBUG_HEADER), &cb, NULL );
+
+ nh.FileHeader.NumberOfSections = (USHORT)sdh.NumberOfSections;
+
+ ii->CheckSum = sdh.CheckSum;
+ ii->TimeStamp = sdh.TimeDateStamp;
+ ii->SizeOfImage = sdh.SizeOfImage;
+ ii->BaseOfImage = sdh.ImageBase;
+ }
+
+ cb = nh.FileHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER;
+ ii->NumberOfSections = nh.FileHeader.NumberOfSections;
+ ii->Sections = malloc( cb );
+ ReadFile( hFile, ii->Sections, cb, &cb, NULL );
+
+ CloseHandle( hFile );
+ return TRUE;
+}
+
+
+BOOL
+LookupImageByAddress(
+ IN DWORD Address,
+ OUT PSTR ImageName
+ )
+/*++
+
+Routine Description:
+
+ Look in rebase.log and coffbase.txt for an image which
+ contains the address provided.
+
+Arguments:
+
+ Address - Supplies the address to look for.
+
+ ImageName - Returns the name of the image if found.
+
+Return Value:
+
+ TRUE for success, FALSE for failure. ImageName is not modified
+ if the search fails.
+
+--*/
+{
+ LPSTR RootPath;
+ LPSTR pstr;
+ char FileName[_MAX_PATH];
+ char Buffer[_MAX_PATH];
+ BOOL Replace;
+ DWORD ImageAddress;
+ DWORD Size;
+ FILE *File;
+
+ //
+ // Locate rebase.log file
+ //
+ // SymbolPath or %SystemRoot%\Symbols
+ //
+
+ RootPath = pstr = (LPSTR)KdOptions[KDO_SYMBOLPATH].value;
+
+ Replace = FALSE;
+ File = NULL;
+
+ while (File == NULL && *pstr) {
+
+ while (*pstr) {
+ if (*pstr == ';') {
+ *pstr = 0;
+ Replace = TRUE;
+ break;
+ }
+ pstr++;
+ }
+
+ if (SearchTreeForFile(RootPath, "rebase.log", FileName)) {
+ File = fopen(FileName, "r");
+ }
+
+ if (Replace) {
+ *pstr = ';';
+ RootPath = ++pstr;
+ }
+ }
+
+ if (!File) {
+ return FALSE;
+ }
+
+ //
+ // Search file for image
+ //
+ while (fgets(Buffer, sizeof(Buffer), File)) {
+ ImageAddress = 0xffffffff;
+ Size = 0xffffffff;
+ sscanf( Buffer, "%s %*s %*s 0x%x (size 0x%x)",
+ FileName, &ImageAddress, &Size);
+ if (Size == 0xffffffff) {
+ continue;
+ }
+ if (Address >= ImageAddress && Address < ImageAddress + Size) {
+ strcpy(ImageName, FileName);
+ fclose(File);
+ return TRUE;
+ }
+ }
+
+ fclose(File);
+
+ return FALSE;
+}
+
+VOID
+ReloadModules(
+ HTHDX hthd,
+ LPSTR args
+ )
+{
+ DEBUG_EVENT de;
+ ULONG len = 0;
+ int i;
+ HPRCX hprc;
+ LPRTP rtp;
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ CHAR drive[_MAX_DRIVE];
+ CHAR dir[_MAX_DIR];
+ CHAR modname[MAX_PATH];
+ CHAR modpath[MAX_PATH*2];
+ ULONG Address;
+ ULONG LoadAddress;
+ BOOL UnloadOnly = FALSE;
+ PCHAR p;
+
+
+ //
+ // this is to handle the ".reload foo.exe" command
+ //
+ // we search thru the module list and find the desired module.
+ // the module is then unloaded and re-loaded. the module is re-loaded
+ // at its preferred load address.
+ //
+ if (args && *args) {
+
+ //
+ // skip over any white space
+ //
+ while (*args == ' ' || *args == '\t') {
+ args++;
+ }
+
+ if (args[0] == '/' && args[1] == 'u') {
+ UnloadOnly = TRUE;
+ args += 2;
+ while (*args == ' ' || *args == '\t') {
+ args++;
+ }
+ }
+
+ LoadAddress = 0;
+ if (p = strchr(args, '=')) {
+ *p = 0;
+ sscanf(p+1, "%x", &LoadAddress);
+ }
+
+ _splitpath( args, drive, dir, fname, ext );
+
+ if (p) {
+ *p = '=';
+ }
+
+ _makepath( modname, NULL, NULL, fname, ext );
+
+ if (isdigit(*args)) {
+ sscanf(args, "%x", &Address);
+ if (LookupImageByAddress(Address, modname)) {
+ _splitpath( modname, drive, dir, fname, ext );
+ }
+ }
+
+ hprc = HPRCFromPID( KD_PROCESSID );
+
+ for (i=0; i<hprc->cDllList; i++) {
+ if ((hprc->rgDllList[i].fValidDll) &&
+ (_stricmp(hprc->rgDllList[i].szDllName, modname) == 0)) {
+
+ UnloadModule( (DWORD)hprc->rgDllList[i].offBaseOfImage, modname );
+ break;
+
+ }
+ }
+
+
+ if (!UnloadOnly) {
+
+ if (dir[0]) {
+ sprintf( modpath, "%s%s", drive, dir );
+ } else {
+ strcpy( modpath, (LPSTR)KdOptions[KDO_SYMBOLPATH].value );
+ }
+
+ _makepath( modname, drive, dir, fname, ext );
+
+ if (!ReloadModulesFromList(hthd,
+ vs.PsLoadedModuleList,
+ FALSE,
+ modname,
+ LoadAddress)) {
+ if (!ReloadModulesFromList(hthd,
+ MmLoadedUserImageList,
+ FALSE,
+ modname,
+ LoadAddress)) {
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.LoadDll.hFile = NULL;
+ de.u.LoadDll.lpBaseOfDll = (LPVOID)LoadAddress;
+ de.u.LoadDll.lpImageName = modname;
+ de.u.LoadDll.fUnicode = FALSE;
+ de.u.LoadDll.nDebugInfoSize = 0;
+ de.u.LoadDll.dwDebugInfoFileOffset = 0;
+ NotifyEM(&de, hthd, 0, (LPVOID)0);
+
+ }
+ }
+ }
+
+ } else {
+
+ UnloadAllModules();
+
+ ReloadModulesFromList( hthd, vs.PsLoadedModuleList, FALSE, NULL, 0 );
+ ReloadModulesFromList( hthd, MmLoadedUserImageList, FALSE, NULL, 0 );
+
+ ReloadCrashModules( hthd );
+
+ InitializeKiProcessor();
+ }
+
+ DMPrintShellMsg( "Finished re-loading kernel modules\n" );
+
+ //
+ // tell the shell that the !reload is finished
+ //
+ rtp = (LPRTP)malloc(sizeof(RTP)+sizeof(DWORD));
+ rtp->hpid = hthd->hprc->hpid;
+ rtp->htid = hthd->htid;
+ rtp->dbc = dbcIoctlDone;
+ rtp->cb = sizeof(DWORD);
+ *(LPDWORD)rtp->rgbVar = 1;
+ DmTlFunc( tlfDebugPacket, rtp->hpid, sizeof(RTP)+rtp->cb, (LONG)rtp );
+ free( rtp );
+
+ ConsumeAllEvents();
+ return;
+}
+
+VOID
+ClearBps( VOID )
+{
+ DBGKD_RESTORE_BREAKPOINT bps[MAX_KD_BPS];
+ DWORD i;
+
+ //
+ // clean out the kernel's bp list
+ //
+ for (i=0; i<MAX_KD_BPS; i++) {
+ bps[i].BreakPointHandle = i + 1;
+ }
+
+ RestoreBreakPointEx( MAX_KD_BPS, bps );
+
+ return;
+}
+
+void
+AddQueue(
+ DWORD dwType,
+ DWORD dwProcessId,
+ DWORD dwThreadId,
+ DWORD dwData,
+ DWORD dwLen
+ )
+{
+ LPCQUEUE lpcq;
+
+
+ EnterCriticalSection(&csContinueQueue);
+
+ lpcq = lpcqFree;
+ assert(lpcq);
+
+ lpcqFree = lpcq->next;
+
+ lpcq->next = NULL;
+ if (lpcqLast) {
+ lpcqLast->next = lpcq;
+ }
+ lpcqLast = lpcq;
+
+ if (!lpcqFirst) {
+ lpcqFirst = lpcq;
+ }
+
+ lpcq->pid = dwProcessId;
+ lpcq->tid = dwThreadId;
+ lpcq->typ = dwType;
+ lpcq->len = dwLen;
+
+ if (lpcq->typ == QT_RELOAD_MODULES || lpcq->typ == QT_DEBUGSTRING) {
+ if (dwLen) {
+ lpcq->data = (DWORD) malloc( dwLen );
+ memcpy( (LPVOID)lpcq->data, (LPVOID)dwData, dwLen );
+ }
+ else {
+ lpcq->data = 0;
+ }
+
+ }
+ else {
+ lpcq->data = dwData;
+ }
+
+ if (lpcq->typ == QT_CONTINUE_DEBUG_EVENT) {
+ SetEvent( hEventContinue );
+ }
+
+ LeaveCriticalSection(&csContinueQueue);
+ return;
+}
+
+BOOL
+DequeueOneEvent(
+ LPCQUEUE lpcqReturn
+ )
+{
+ LPCQUEUE lpcq;
+
+ EnterCriticalSection(&csContinueQueue);
+
+ if (!lpcqFirst) {
+ LeaveCriticalSection(&csContinueQueue);
+ return FALSE;
+ }
+
+ lpcq = lpcqFirst;
+
+ lpcqFirst = lpcq->next;
+ if (lpcqFirst == NULL) {
+ lpcqLast = NULL;
+ }
+
+ lpcq->next = lpcqFree;
+ lpcqFree = lpcq;
+
+ if (lpcq->pid == 0 || lpcq->tid == 0) {
+ lpcq->pid = KD_PROCESSID;
+ lpcq->tid = KD_THREADID;
+ }
+
+ *lpcqReturn = *lpcq;
+
+ LeaveCriticalSection(&csContinueQueue);
+
+ return TRUE;
+}
+
+
+BOOL
+DequeueAllEvents(
+ BOOL fForce, // force a dequeue even if the dm isn't initialized
+ BOOL fConsume // delete all events from the queue with no action
+ )
+{
+ CQUEUE qitem;
+ LPCQUEUE lpcq = &qitem;
+ BOOL fDid = FALSE;
+ HTHDX hthd;
+ DBGKD_CONTROL_SET cs = {0};
+ LPSTR d;
+
+
+ ResetEvent(hEventContinue);
+
+ while ( DequeueOneEvent(&qitem) ) {
+
+ if (fConsume) {
+ if (lpcq->typ == QT_CONTINUE_DEBUG_EVENT) {
+ fDid = TRUE;
+ }
+ continue;
+ }
+
+ hthd = HTHDXFromPIDTID(lpcq->pid, lpcq->tid);
+ if (hthd && hthd->fContextDirty) {
+ DbgSetThreadContext( hthd, &hthd->context );
+ hthd->fContextDirty = FALSE;
+ }
+
+ d = (LPSTR)lpcq->data;
+
+ switch (lpcq->typ) {
+ case QT_CONTINUE_DEBUG_EVENT:
+ if (fCrashDump) {
+ break;
+ }
+ if (DmKdState >= S_READY || fForce) {
+ if (!fDid) {
+ fDid = TRUE;
+ ContinueTargetSystem( (DWORD)d, NULL );
+ }
+ }
+ break;
+
+ case QT_TRACE_DEBUG_EVENT:
+ if (fCrashDump) {
+ break;
+ }
+ if (DmKdState >= S_READY || fForce) {
+ if (!fDid) {
+ fDid = TRUE;
+#ifdef TARGET_i386
+ cs.TraceFlag = 1;
+ cs.Dr7 = sc.ControlReport.Dr7;
+ cs.CurrentSymbolStart = 1;
+ cs.CurrentSymbolEnd = 1;
+ ContinueTargetSystem( (DWORD)d, &cs );
+#else
+ ContinueTargetSystem( (DWORD)d, NULL );
+#endif
+ }
+ }
+ break;
+
+ case QT_RELOAD_MODULES:
+ ReloadModules( hthd, d );
+ free( (LPVOID)d );
+ break;
+
+ case QT_REBOOT:
+ if (fCrashDump) {
+ break;
+ }
+ DMPrintShellMsg( "Target system rebooting...\n" );
+ DmKdPurgeCachedVirtualMemory( TRUE );
+ UnloadAllModules();
+ ZeroMemory( ContextCache, sizeof(ContextCache) );
+ DmKdState = S_REBOOTED;
+ DmKdReboot();
+ InitialBreak = (BOOL) KdOptions[KDO_INITIALBP].value;
+ KdResync = TRUE;
+ break;
+
+ case QT_CRASH:
+ if (fCrashDump) {
+ break;
+ }
+ DMPrintShellMsg( "Target system crashing...\n" );
+ DmKdCrash( (DWORD)d );
+ InitialBreak = (BOOL) KdOptions[KDO_INITIALBP].value;
+ KdResync = TRUE;
+ fDid = TRUE;
+ break;
+
+ case QT_RESYNC:
+ if (fCrashDump) {
+ break;
+ }
+ DMPrintShellMsg( "Host and target systems resynchronizing...\n" );
+ KdResync = TRUE;
+ break;
+
+ case QT_DEBUGSTRING:
+ DMPrintShellMsg( "%s", (LPSTR)d );
+ free( (LPVOID)d );
+ break;
+
+ }
+
+ }
+
+ return fDid;
+}
+
+VOID
+WriteKernBase(
+ DWORD KernBase
+ )
+{
+ HKEY hKeyKd;
+
+
+ if ( RegOpenKey( HKEY_CURRENT_USER,
+ "software\\microsoft\\windbg\\0012\\programs\\ntoskrnl",
+ &hKeyKd ) == ERROR_SUCCESS ) {
+ RegSetValueEx( hKeyKd, "KernBase", 0, REG_DWORD, (LPBYTE)&KernBase, sizeof(DWORD) );
+ RegCloseKey( hKeyKd );
+ }
+
+ return;
+}
+
+DWORD
+ReadKernBase(
+ VOID
+ )
+{
+ HKEY hKeyKd;
+ DWORD dwType;
+ DWORD KernBase;
+ DWORD dwSize;
+
+
+ if ( RegOpenKey( HKEY_CURRENT_USER,
+ "software\\microsoft\\windbg\\0012\\programs\\ntoskrnl",
+ &hKeyKd ) == ERROR_SUCCESS ) {
+ dwSize = sizeof(DWORD);
+ RegQueryValueEx( hKeyKd, "KernBase", NULL, &dwType, (LPBYTE)&KernBase, &dwSize );
+ RegCloseKey( hKeyKd );
+ return KernBase;
+ }
+
+ return KernBase;
+}
+
+VOID
+GetVersionInfo(
+ DWORD KernBase
+ )
+{
+ CHAR buf[MAX_PATH];
+
+
+ if (!fCrashDump) {
+ ZeroMemory( &vs, sizeof(vs) );
+ if (DmKdGetVersion( &vs ) == STATUS_SUCCESS) {
+ if (!vs.KernBase) {
+ vs.KernBase = KernBase;
+ }
+ }
+ }
+
+ sprintf( buf, "Kernel Version %d", vs.MinorVersion );
+ if (vs.MajorVersion == 0xC) {
+ strcat( buf, " Checked" );
+ } else if (vs.MajorVersion == 0xF) {
+ strcat( buf, " Free" );
+ }
+ sprintf( &buf[strlen(buf)], " loaded @ 0x%08x", vs.KernBase );
+
+ DMPrintShellMsg( "%s\n", buf );
+
+ return;
+}
+
+VOID
+InitializeExtraProcessors(
+ VOID
+ )
+{
+ HTHDX hthd;
+ DWORD i;
+ DEBUG_EVENT de;
+
+
+ CacheProcessors = sc.NumberProcessors;
+ for (i = 1; i < sc.NumberProcessors; i++) {
+ //
+ // initialize the hthd
+ //
+ hthd = HTHDXFromPIDTID( KD_PROCESSID, i );
+
+ //
+ // refresh the context cache for this processor
+ //
+#if defined(TARGET_i386) || defined(TARGET_PPC)
+ ContextCache[i].fSContextDirty = FALSE;
+ ContextCache[i].fSContextStale = TRUE;
+#endif
+ ContextCache[i].fContextDirty = FALSE;
+ ContextCache[i].fContextStale = TRUE;
+
+ //
+ // tell debugger to create the thread (processor)
+ //
+ de.dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = i + 1;
+ de.u.CreateThread.hThread = (HANDLE)(i + 1);
+ de.u.CreateThread.lpThreadLocalBase = NULL;
+ de.u.CreateThread.lpStartAddress = NULL;
+ ProcessDebugEvent(&de, &sc);
+ WaitForSingleObject(hEventContinue,INFINITE);
+ }
+
+
+
+ //
+ // consume any continues that may have been queued
+ //
+ ConsumeAllEvents();
+
+ //
+ // get out of here
+ //
+ return;
+}
+
+DWORD
+DmKdPollThread(
+ LPSTR lpProgName
+ )
+{
+ char buf[512];
+ DWORD st;
+ DWORD i;
+ DWORD j;
+ BOOL fFirstSc = FALSE;
+ DEBUG_EVENT de;
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+ HTHDX hthd;
+ DWORD n;
+ IMAGEINFO ii;
+ HPRCX hprc;
+
+
+ PollThreadId = GetCurrentThreadId();
+
+ //
+ // initialize the queue variables
+ //
+ n = sizeof(cqueue) / sizeof(CQUEUE);
+ for (i = 0; i < n-1; i++) {
+ cqueue[i].next = &cqueue[i+1];
+ }
+ --n;
+ cqueue[n].next = NULL;
+ lpcqFree = &cqueue[0];
+ lpcqFirst = NULL;
+ lpcqLast = NULL;
+ InitializeCriticalSection(&csContinueQueue);
+
+ DmKdSetMaxCacheSize( KdOptions[KDO_CACHE].value );
+ InitialBreak = (BOOL) KdOptions[KDO_INITIALBP].value;
+
+ //
+ // simulate a create process debug event
+ //
+ de.dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.CreateProcessInfo.hFile = NULL;
+ de.u.CreateProcessInfo.hProcess = NULL;
+ de.u.CreateProcessInfo.hThread = NULL;
+ de.u.CreateProcessInfo.lpBaseOfImage = 0;
+ de.u.CreateProcessInfo.dwDebugInfoFileOffset = 0;
+ de.u.CreateProcessInfo.nDebugInfoSize = 0;
+ de.u.CreateProcessInfo.lpStartAddress = NULL;
+ de.u.CreateProcessInfo.lpThreadLocalBase = NULL;
+ de.u.CreateProcessInfo.lpImageName = lpProgName;
+ de.u.CreateProcessInfo.fUnicode = 0;
+ de.u.LoadDll.nDebugInfoSize = 0;
+ ProcessDebugEvent(&de, &sc);
+ WaitForSingleObject(hEventContinue,INFINITE);
+ hprc = HPRCFromPID( KD_PROCESSID );
+ ConsumeAllEvents();
+
+ //
+ // simulate a loader breakpoint event
+ //
+ de.dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.Exception.dwFirstChance = TRUE;
+ de.u.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
+ de.u.Exception.ExceptionRecord.ExceptionFlags = 0;
+ de.u.Exception.ExceptionRecord.ExceptionRecord = NULL;
+ de.u.Exception.ExceptionRecord.ExceptionAddress = 0;
+ de.u.Exception.ExceptionRecord.NumberParameters = 0;
+ ProcessDebugEvent( &de, &sc );
+ ConsumeAllEvents();
+
+ DMPrintShellMsg( "Kernel debugger waiting to connect on com%d @ %d baud\n",
+ KdOptions[KDO_PORT].value,
+ KdOptions[KDO_BAUDRATE].value
+ );
+
+ setjmp( JumpBuffer );
+
+ while (TRUE) {
+
+ if (DmKdExit) {
+ return 0;
+ }
+
+ ApiIsAllowed = FALSE;
+
+ st = DmKdWaitStateChange( &sc, buf, sizeof(buf) );
+
+ if (st != STATUS_SUCCESS ) {
+ DEBUG_PRINT_1( "DmKdWaitStateChange failed: %08lx\n", st );
+ return 0;
+ }
+
+ ApiIsAllowed = TRUE;
+
+ fFirstSc = FALSE;
+
+ if (sc.NewState == DbgKdLoadSymbolsStateChange) {
+ _splitpath( buf, NULL, NULL, fname, ext );
+ _makepath( buf, NULL, NULL, fname, ext );
+ if ((DmKdState == S_UNINITIALIZED) &&
+ (_stricmp( buf, KERNEL_IMAGE_NAME ) == 0)) {
+ WriteKernBase( (DWORD)sc.u.LoadSymbols.BaseOfDll );
+ fFirstSc = TRUE;
+ }
+ }
+
+ if ((DmKdState == S_UNINITIALIZED) ||
+ (DmKdState == S_REBOOTED)) {
+ hthd = HTHDXFromPIDTID( KD_PROCESSID, KD_THREADID );
+ ContextCache[sc.Processor].fContextStale = TRUE;
+ DbgGetThreadContext( hthd, &sc.Context );
+#if defined(TARGET_i386) || defined(TARGET_PPC)
+ ContextCache[sc.Processor].fSContextStale = TRUE;
+#endif
+ } else if (sc.NewState != DbgKdLoadSymbolsStateChange) {
+#if defined(TARGET_i386) || defined(TARGET_PPC)
+ ContextCache[sc.Processor].fSContextStale = TRUE;
+#endif
+
+ //
+ // put the context record into the cache
+ //
+ memcpy( &ContextCache[sc.Processor].Context,
+ &sc.Context,
+ sizeof(sc.Context)
+ );
+
+#if defined(TARGET_MIPS)
+ if ((ContextCache[sc.Processor].Context.ContextFlags &
+ CONTEXT_EXTENDED_INTEGER) == CONTEXT_EXTENDED_INTEGER) {
+
+ MipsContextSize = Ctx64Bit;
+ } else {
+ MipsContextSize = Ctx32Bit;
+ CoerceContext32To64(&ContextCache[sc.Processor].Context);
+ }
+#endif // MIPS
+ }
+
+ ContextCache[sc.Processor].fContextDirty = FALSE;
+ ContextCache[sc.Processor].fContextStale = FALSE;
+
+ if (sc.NumberProcessors > 1 && CacheProcessors == 1) {
+ InitializeExtraProcessors();
+ }
+
+ if (DmKdState == S_REBOOTED) {
+
+ DmKdState = S_INITIALIZED;
+
+ //
+ // get the version/info packet from the target
+ //
+ if (fFirstSc) {
+ GetVersionInfo( (DWORD)sc.u.LoadSymbols.BaseOfDll );
+ } else {
+ GetVersionInfo( 0 );
+ }
+
+ InitialBreak = (BOOL) KdOptions[KDO_INITIALBP].value;
+
+ } else
+ if (DmKdState == S_UNINITIALIZED) {
+
+ DMPrintShellMsg( "Kernel Debugger connection established on com%d @ %d baud\n",
+ KdOptions[KDO_PORT].value,
+ KdOptions[KDO_BAUDRATE].value
+ );
+
+ //
+ // we're now initialized
+ //
+ DmKdState = S_INITIALIZED;
+
+ //
+ // get the version/info packet from the target
+ //
+ if (fFirstSc) {
+ GetVersionInfo( (DWORD)sc.u.LoadSymbols.BaseOfDll );
+ } else {
+ GetVersionInfo( 0 );
+ }
+
+ //
+ // clean out the kernel's bp list
+ //
+ ClearBps();
+
+ if (sc.NewState != DbgKdLoadSymbolsStateChange) {
+ //
+ // generate a mod load for the kernel/osloader
+ //
+ GenerateKernelModLoad( hprc, lpProgName );
+ }
+
+ DisableEmCache();
+ }
+
+ if (fDisconnected) {
+ if (sc.NewState == DbgKdLoadSymbolsStateChange) {
+
+ //
+ // we can process these debug events very carefully
+ // while disconnected from the shell. the only requirement
+ // is that the dm doesn't call NotifyEM while disconnected.
+ //
+
+ } else {
+
+ WaitForSingleObject( hEventRemoteQuit, INFINITE );
+ ResetEvent( hEventRemoteQuit );
+
+ }
+ }
+
+ if (sc.NewState == DbgKdExceptionStateChange) {
+ DmKdInitVirtualCacheEntry( (ULONG)sc.ProgramCounter,
+ (ULONG)sc.ControlReport.InstructionCount,
+ sc.ControlReport.InstructionStream,
+ TRUE
+ );
+
+ de.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.Exception.ExceptionRecord = sc.u.Exception.ExceptionRecord;
+ de.u.Exception.dwFirstChance = sc.u.Exception.FirstChance;
+
+ //
+ // HACK-HACK: this is here to wrongly handle the case where
+ // the kernel delivers an exception during initialization
+ // that is NOT a breakpoint exception.
+ //
+ if (DmKdState != S_READY) {
+ de.u.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
+ }
+
+ if (fDisconnected) {
+ ReConnectDebugger( &de, DmKdState == S_INITIALIZED );
+ }
+
+ ProcessDebugEvent( &de, &sc );
+
+ if (DmKdState == S_INITIALIZED) {
+ free( lpProgName );
+ DmKdState = S_READY;
+ }
+ }
+ else
+ if (sc.NewState == DbgKdLoadSymbolsStateChange) {
+ if (sc.u.LoadSymbols.UnloadSymbols) {
+ if (sc.u.LoadSymbols.PathNameLength == 0 &&
+ sc.u.LoadSymbols.BaseOfDll == (PVOID)-1 &&
+ sc.u.LoadSymbols.ProcessId == 0
+ ) {
+ //
+ // the target system was just restarted
+ //
+ DMPrintShellMsg( "Target system restarted...\n" );
+ DmKdPurgeCachedVirtualMemory( TRUE );
+ UnloadAllModules();
+ ContinueTargetSystem( DBG_CONTINUE, NULL );
+ InitialBreak = (BOOL) KdOptions[KDO_INITIALBP].value;
+ KdResync = TRUE;
+ DmKdState = S_REBOOTED;
+ continue;
+ }
+ de.dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.UnloadDll.lpBaseOfDll = (LPVOID)sc.u.LoadSymbols.BaseOfDll;
+
+ if (fDisconnected) {
+ ReConnectDebugger( &de, DmKdState == S_INITIALIZED );
+ }
+
+ ProcessDebugEvent( &de, &sc );
+ ConsumeAllEvents();
+ ContinueTargetSystem( DBG_CONTINUE, NULL );
+ continue;
+ } else {
+ //
+ // if the mod load is for the kernel image then we must
+ // assume that the target system was rebooted while
+ // the debugger was connected. in this case we need to
+ // unload all modules. this will allow the mod loads that
+ // are forthcoming to work correctly and cause the shell to
+ // reinstanciate all of it's breakpoints.
+ //
+ if (_stricmp( buf, KERNEL_IMAGE_NAME ) == 0) {
+ UnloadAllModules();
+ DeleteAllBps();
+ ConsumeAllEvents();
+ }
+
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.LoadDll.hFile = (HANDLE)sc.u.LoadSymbols.CheckSum;
+ de.u.LoadDll.lpBaseOfDll = (LPVOID)sc.u.LoadSymbols.BaseOfDll;
+ de.u.LoadDll.lpImageName = buf;
+ de.u.LoadDll.fUnicode = FALSE;
+ de.u.LoadDll.nDebugInfoSize = 0;
+ if (sc.u.LoadSymbols.SizeOfImage == 0) {
+ //
+ // this is likely a firmware image. in such cases the boot
+ // loader on the target may not be able to deliver the size.
+ //
+ if (!ReadImageInfo(
+ buf,
+ NULL,
+ (LPSTR)KdOptions[KDO_SYMBOLPATH].value,
+ &ii )) {
+ //
+ // can't read the image correctly
+ //
+ DMPrintShellMsg( "Module load failed, missing size & image [%s]\n", buf );
+ ContinueTargetSystem( DBG_CONTINUE, NULL );
+ continue;
+ }
+ de.u.LoadDll.dwDebugInfoFileOffset = ii.SizeOfImage;
+ } else {
+ de.u.LoadDll.dwDebugInfoFileOffset = sc.u.LoadSymbols.SizeOfImage;
+ }
+
+ if (fDisconnected) {
+ ReConnectDebugger( &de, DmKdState == S_INITIALIZED );
+ }
+
+ //
+ // HACK ALERT
+ //
+ // this code is here to allow the presence of the
+ // mirrored disk drivers in a system that has crashdump
+ // enabled. if the modload is for a driver and the
+ // image name for that driver is alread present in the
+ // dm's module table then we alias the driver.
+ //
+ _splitpath( buf, NULL, NULL, fname, ext );
+ if (_stricmp( ext, ".sys" ) == 0) {
+ UnloadModule( (DWORD)sc.u.LoadSymbols.BaseOfDll, NULL );
+ for (i=0; i<(DWORD)hprc->cDllList; i++) {
+ if (hprc->rgDllList[i].fValidDll &&
+ _stricmp(hprc->rgDllList[i].szDllName,buf)==0) {
+ break;
+ }
+ }
+ if (i < (DWORD)hprc->cDllList) {
+ for (j=0; j<MAX_MODULEALIAS; j++) {
+ if (ModuleAlias[j].ModuleName[0] == 0) {
+ break;
+ }
+ }
+ if (j < MAX_MODULEALIAS) {
+ strcpy( ModuleAlias[j].Alias, buf );
+ ModuleAlias[j].ModuleName[0] = 'c';
+ _splitpath( buf, NULL, NULL, &ModuleAlias[j].ModuleName[1], NULL );
+ ModuleAlias[j].ModuleName[8] = 0;
+ ModuleAlias[j].Special = 2; // One shot alias...
+ }
+ }
+ } else {
+ UnloadModule( (DWORD)sc.u.LoadSymbols.BaseOfDll, buf );
+ }
+
+ ProcessDebugEvent( &de, &sc );
+ ConsumeAllEvents();
+ ContinueTargetSystem( DBG_CONTINUE, NULL );
+ continue;
+ }
+ }
+
+ if (DequeueAllEvents(FALSE,FALSE)) {
+ continue;
+ }
+
+ //
+ // this loop is executed while the target system is not running
+ // the dm sits here and processes queue event and waits for a go
+ //
+ while (TRUE) {
+ WaitForSingleObject( hEventContinue, 100 );
+ ResetEvent( hEventContinue );
+
+ if (WaitForSingleObject( hEventRemoteQuit, 0 ) == WAIT_OBJECT_0) {
+ fDisconnected = TRUE;
+ DmKdBreakIn = TRUE;
+ }
+
+ if (DmKdExit) {
+ return 0;
+ }
+ if (DmKdBreakIn || KdResync) {
+ break;
+ }
+ if (DequeueAllEvents(FALSE,FALSE)) {
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+VOID
+InitializeKiProcessor(
+ VOID
+ )
+{
+ if (!fCrashDump) {
+ return;
+ }
+
+ //
+ // get the address of the KiProcessorBlock
+ //
+ if (!KiProcessorBlockAddr) {
+ DMPrintShellMsg( "Could not get address of KiProcessorBlock\n" );
+ }
+
+ //
+ // read the contents of the KiProcessorBlock
+ //
+ DmpReadMemory( (PVOID)KiProcessorBlockAddr, &KiProcessors, sizeof(KiProcessors) );
+}
+
+
+DWORD
+DmKdPollThreadCrash(
+ LPSTR lpProgName
+ )
+{
+ DWORD i;
+ BOOL fFirstSc = FALSE;
+ DEBUG_EVENT de;
+ DWORD n;
+ PEXCEPTION_RECORD Exception;
+ LIST_ENTRY List;
+ PLIST_ENTRY Next;
+ PLDR_DATA_TABLE_ENTRY DataTable;
+ LDR_DATA_TABLE_ENTRY DataTableBuffer;
+ INT CurrProcessor;
+ HPRCX hprc;
+
+
+
+ PollThreadId = GetCurrentThreadId();
+
+ hprc = HPRCFromPID( KD_PROCESSID );
+
+ //
+ // initialize the queue variables
+ //
+ n = sizeof(cqueue) / sizeof(CQUEUE);
+ for (i = 0; i < n-1; i++) {
+ cqueue[i].next = &cqueue[i+1];
+ }
+ --n;
+ cqueue[n].next = NULL;
+ lpcqFree = &cqueue[0];
+ lpcqFirst = NULL;
+ lpcqLast = NULL;
+ InitializeCriticalSection(&csContinueQueue);
+
+ DmKdSetMaxCacheSize( KdOptions[KDO_CACHE].value );
+ InitialBreak = FALSE;
+
+ //
+ // initialize for crash debugging
+ //
+ if (!DmpInitialize( (LPSTR)KdOptions[KDO_CRASHDUMP].value,
+ &DmpContext,
+ &Exception,
+ &DmpHeader
+ )) {
+ DMPrintShellMsg( "Could not initialize crash dump file %s\n",
+ (LPSTR)KdOptions[KDO_CRASHDUMP].value );
+ return 0;
+ }
+
+#if defined(TARGET_MIPS)
+ if (DmpHeader->MajorVersion > 3) {
+ MipsContextSize = Ctx64Bit;
+ } else {
+ MipsContextSize = Ctx32Bit;
+ CoerceContext32To64(DmpContext);
+ }
+#endif // MIPS
+
+ memcpy( &sc.Context, DmpContext, sizeof(CONTEXT) );
+ memcpy( &ContextCache[0].Context, DmpContext, sizeof(CONTEXT) );
+
+ ContextCache[0].fContextDirty = FALSE;
+ ContextCache[0].fContextStale = FALSE;
+
+#if defined(TARGET_i386) || defined(TARGET_PPC)
+ ContextCache[0].fSContextDirty = FALSE;
+ ContextCache[0].fSContextStale = TRUE;
+#endif
+
+ sc.NewState = DbgKdExceptionStateChange;
+ sc.u.Exception.ExceptionRecord = *Exception;
+ sc.u.Exception.FirstChance = FALSE;
+ //
+ // For the createprocess and loader bp, use cpu 0
+ //
+ CurrProcessor = 0;
+ sc.Processor = 0;
+ sc.NumberProcessors = DmpHeader->NumberProcessors;
+ sc.ProgramCounter = Exception->ExceptionAddress;
+ sc.ControlReport.InstructionCount = 0;
+
+ vs.MajorVersion = (USHORT)DmpHeader->MajorVersion;
+ vs.MinorVersion = (USHORT)DmpHeader->MinorVersion;
+ vs.KernBase = 0;
+ vs.PsLoadedModuleList = (DWORD) DmpHeader->PsLoadedModuleList;
+
+ if (DmpReadMemory( DmpHeader->PsLoadedModuleList, (PVOID)&List, sizeof(LIST_ENTRY) )) {
+ Next = List.Flink;
+ DataTable = CONTAINING_RECORD( Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks );
+ if (DmpReadMemory( (PVOID)DataTable, (PVOID)&DataTableBuffer, sizeof(LDR_DATA_TABLE_ENTRY) )) {
+ vs.KernBase = (DWORD) DataTableBuffer.DllBase;
+ }
+ } else {
+ DMPrintShellMsg( "Could not get base of kernel 0x%08x\n",
+ DmpHeader->PsLoadedModuleList );
+ }
+
+#if defined(TARGET_i386)
+ if ( DmpHeader->MachineImageType != IMAGE_FILE_MACHINE_I386)
+#elif defined(TARGET_MIPS)
+ if ((DmpHeader->MachineImageType != IMAGE_FILE_MACHINE_R4000) &&
+ (DmpHeader->MachineImageType != IMAGE_FILE_MACHINE_R10000) )
+#elif defined(TARGET_ALPHA)
+ if ( DmpHeader->MachineImageType != IMAGE_FILE_MACHINE_ALPHA)
+#elif defined(TARGET_PPC)
+ if ( DmpHeader->MachineImageType != IMAGE_FILE_MACHINE_POWERPC)
+#else
+#pragma error( "unknown target machine" );
+#endif
+ {
+ DMPrintShellMsg( "Dumpfile is of an unknown machine type\n" );
+ }
+
+ ApiIsAllowed = TRUE;
+
+ //
+ // simulate a create process debug event
+ //
+ de.dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.CreateProcessInfo.hFile = NULL;
+ de.u.CreateProcessInfo.hProcess = NULL;
+ de.u.CreateProcessInfo.hThread = NULL;
+ de.u.CreateProcessInfo.lpBaseOfImage = 0;
+ de.u.CreateProcessInfo.dwDebugInfoFileOffset = 0;
+ de.u.CreateProcessInfo.nDebugInfoSize = 0;
+ de.u.CreateProcessInfo.lpStartAddress = NULL;
+ de.u.CreateProcessInfo.lpThreadLocalBase = NULL;
+ de.u.CreateProcessInfo.lpImageName = lpProgName;
+ de.u.CreateProcessInfo.fUnicode = 0;
+ ProcessDebugEvent(&de, &sc);
+ WaitForSingleObject(hEventContinue,INFINITE);
+ ConsumeAllEvents();
+
+ //
+ // LoadDll needs this to load the right kernel symbols:
+ //
+ CacheProcessors = DmpHeader->NumberProcessors;
+
+ //
+ // generate a mod load for the kernel/osloader
+ //
+
+ GenerateKernelModLoad( hprc, lpProgName );
+
+ CurrProcessor = DmpGetCurrentProcessor();
+ if (CurrProcessor == -1) {
+ sc.Processor = 0;
+ } else {
+ sc.Processor = (USHORT)CurrProcessor;
+ }
+
+ //
+ // initialize the other processors
+ //
+ InitializeKiProcessor();
+ if (DmpHeader->NumberProcessors > 1) {
+ InitializeExtraProcessors();
+ }
+
+ //
+ // simulate a loader breakpoint event
+ //
+ de.dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.Exception.dwFirstChance = TRUE;
+ de.u.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
+ de.u.Exception.ExceptionRecord.ExceptionFlags = 0;
+ de.u.Exception.ExceptionRecord.ExceptionRecord = NULL;
+ de.u.Exception.ExceptionRecord.ExceptionAddress = 0;
+ de.u.Exception.ExceptionRecord.NumberParameters = 0;
+ ProcessDebugEvent( &de, &sc );
+ ConsumeAllEvents();
+
+ DMPrintShellMsg( "Kernel Debugger connection established for %s\n",
+ (LPSTR)KdOptions[KDO_CRASHDUMP].value
+ );
+
+ //
+ // get the version/info packet from the target
+ //
+ GetVersionInfo( (DWORD)sc.u.LoadSymbols.BaseOfDll );
+
+ DMPrintShellMsg( "Bugcheck %08x : %08x %08x %08x %08x\n",
+ DmpHeader->BugCheckCode,
+ DmpHeader->BugCheckParameter1,
+ DmpHeader->BugCheckParameter2,
+ DmpHeader->BugCheckParameter3,
+ DmpHeader->BugCheckParameter4 );
+
+
+ DisableEmCache();
+
+ DmKdInitVirtualCacheEntry( (ULONG)sc.ProgramCounter,
+ (ULONG)sc.ControlReport.InstructionCount,
+ sc.ControlReport.InstructionStream,
+ TRUE
+ );
+
+ de.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.Exception.ExceptionRecord = sc.u.Exception.ExceptionRecord;
+ de.u.Exception.dwFirstChance = sc.u.Exception.FirstChance;
+
+ ProcessDebugEvent( &de, &sc );
+
+ free( lpProgName );
+
+ while (TRUE) {
+ DequeueAllEvents(FALSE,FALSE);
+ Sleep( 1000 );
+ }
+
+ return 0;
+}
+
+BOOLEAN
+DmKdConnectAndInitialize( LPSTR lpProgName )
+{
+ DWORD dwThreadId;
+ LPSTR szProgName = malloc( MAX_PATH );
+
+
+ //
+ // bail out if we're already initialized
+ //
+ if (DmKdState != S_UNINITIALIZED) {
+ return TRUE;
+ }
+
+
+ szProgName[0] = '\0';
+ if (lpProgName) {
+ strcpy( szProgName, lpProgName );
+ }
+
+ fCrashDump = (BOOL) (KdOptions[KDO_CRASHDUMP].value != 0);
+
+ if (fCrashDump) {
+ hThreadDmPoll = CreateThread( NULL,
+ 16000,
+ (LPTHREAD_START_ROUTINE)DmKdPollThreadCrash,
+ (LPVOID)szProgName,
+ THREAD_SET_INFORMATION,
+ (LPDWORD)&dwThreadId
+ );
+ } else {
+
+ //
+ // initialize the com port
+ //
+
+ if (!DmKdInitComPort( (BOOLEAN) KdOptions[KDO_USEMODEM].value )) {
+ DMPrintShellMsg( "Could not initialize COM%d @ %d baud, error == 0x%x\n",
+ KdOptions[KDO_PORT].value,
+ KdOptions[KDO_BAUDRATE].value,
+ GetLastError()
+ );
+ return FALSE;
+ }
+
+ hThreadDmPoll = CreateThread( NULL,
+ 16000,
+ (LPTHREAD_START_ROUTINE)DmKdPollThread,
+ (LPVOID)szProgName,
+ THREAD_SET_INFORMATION,
+ (LPDWORD)&dwThreadId
+ );
+ }
+
+
+ if ( hThreadDmPoll == (HANDLE)NULL ) {
+ return FALSE;
+ }
+
+ if (!SetThreadPriority(hThreadDmPoll, THREAD_PRIORITY_ABOVE_NORMAL)) {
+ return FALSE;
+ }
+
+ KdResync = TRUE;
+ return TRUE;
+}
+
+VOID
+DmPollTerminate( VOID )
+{
+ extern HANDLE DmKdComPort;
+ extern ULONG MaxRetries;
+
+ if (hThreadDmPoll) {
+ DmKdExit = TRUE;
+ WaitForSingleObject(hThreadDmPoll, INFINITE);
+
+ DmKdState = S_UNINITIALIZED;
+ DeleteCriticalSection(&csContinueQueue);
+ ResetEvent( hEventContinue );
+ if (fCrashDump) {
+ DmpUnInitialize();
+ } else {
+ CloseHandle( DmKdComPort );
+ MaxRetries = 5;
+ }
+ DmKdExit = FALSE;
+ }
+
+ return;
+}
+
+VOID
+DisableEmCache( VOID )
+{
+ LPRTP rtp;
+ HTHDX hthd;
+
+
+ hthd = HTHDXFromPIDTID(1, 1);
+
+ rtp = (LPRTP)malloc(sizeof(RTP)+sizeof(DWORD));
+
+ rtp->hpid = hthd->hprc->hpid;
+ rtp->htid = hthd->htid;
+ rtp->dbc = dbceEnableCache;
+ rtp->cb = sizeof(DWORD);
+
+ *(LPDWORD)rtp->rgbVar = 1;
+
+ DmTlFunc( tlfRequest, rtp->hpid, sizeof(RTP)+rtp->cb, (LONG)rtp );
+
+ free( rtp );
+
+ return;
+}
+
+DWORD
+GetSymbolAddress( LPSTR sym )
+{
+ extern char abEMReplyBuf[];
+ LPRTP rtp;
+ HTHDX hthd;
+ DWORD offset;
+ BOOL fUseUnderBar = FALSE;
+
+
+ __try {
+
+try_underbar:
+ hthd = HTHDXFromPIDTID(1, 1);
+
+ rtp = (LPRTP)malloc(sizeof(RTP)+strlen(sym)+16);
+
+ rtp->hpid = hthd->hprc->hpid;
+ rtp->htid = hthd->htid;
+ rtp->dbc = dbceGetOffsetFromSymbol;
+ rtp->cb = strlen(sym) + (fUseUnderBar ? 2 : 1);
+
+ if (fUseUnderBar) {
+ ((LPSTR)rtp->rgbVar)[0] = '_';
+ memcpy( (LPSTR)rtp->rgbVar+1, sym, rtp->cb-1 );
+ } else {
+ memcpy( rtp->rgbVar, sym, rtp->cb );
+ }
+
+ DmTlFunc( tlfRequest, rtp->hpid, sizeof(RTP)+rtp->cb, (LONG)rtp );
+
+ free( rtp );
+
+ offset = *(LPDWORD)abEMReplyBuf;
+ if (!offset && !fUseUnderBar) {
+ fUseUnderBar = TRUE;
+ goto try_underbar;
+ }
+
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ offset = 0;
+
+ }
+
+ return offset;
+}
+
+BOOL
+UnloadModule(
+ DWORD BaseOfDll,
+ LPSTR NameOfDll
+ )
+{
+ HPRCX hprc;
+ HTHDX hthd;
+ DEBUG_EVENT de;
+ DWORD i;
+ BOOL fUnloaded = FALSE;
+
+
+ hprc = HPRCFromPID( KD_PROCESSID );
+ hthd = HTHDXFromPIDTID( KD_PROCESSID, KD_THREADID );
+
+ //
+ // first lets look for the image by dll base
+ //
+ for (i=0; i<(DWORD)hprc->cDllList; i++) {
+ if (hprc->rgDllList[i].fValidDll && hprc->rgDllList[i].offBaseOfImage == BaseOfDll) {
+ de.dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.UnloadDll.lpBaseOfDll = (LPVOID)hprc->rgDllList[i].offBaseOfImage;
+ NotifyEM( &de, hthd, 0, (LPVOID)0);
+ DestroyDllLoadItem(&hprc->rgDllList[i]);
+ fUnloaded = TRUE;
+ break;
+ }
+ }
+
+ //
+ // now we look by dll name
+ //
+ if (NameOfDll) {
+ for (i=0; i<(DWORD)hprc->cDllList; i++) {
+ if (hprc->rgDllList[i].fValidDll &&
+ _stricmp(hprc->rgDllList[i].szDllName,NameOfDll)==0) {
+
+ de.dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.UnloadDll.lpBaseOfDll = (LPVOID)hprc->rgDllList[i].offBaseOfImage;
+ NotifyEM( &de, hthd, 0, (LPVOID)0);
+ DestroyDllLoadItem(&hprc->rgDllList[i]);
+ fUnloaded = TRUE;
+ break;
+
+ }
+ }
+ }
+
+ return fUnloaded;
+}
+
+VOID
+UnloadAllModules(
+ VOID
+ )
+{
+ HPRCX hprc;
+ HTHDX hthd;
+ DEBUG_EVENT de;
+ DWORD i;
+
+
+ hprc = HPRCFromPID( KD_PROCESSID );
+ hthd = HTHDXFromPIDTID( KD_PROCESSID, KD_THREADID );
+
+ for (i=0; i<(DWORD)hprc->cDllList; i++) {
+ if (hprc->rgDllList[i].fValidDll) {
+ de.dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.UnloadDll.lpBaseOfDll = (LPVOID)hprc->rgDllList[i].offBaseOfImage;
+ NotifyEM( &de, hthd, 0, (LPVOID)0);
+ DestroyDllLoadItem(&hprc->rgDllList[i]);
+ }
+ }
+
+ return;
+}
+
+
+BOOL
+GenerateKernelModLoad(
+ HPRCX hprc,
+ LPSTR lpProgName
+ )
+{
+ DEBUG_EVENT de;
+ LIST_ENTRY List;
+ PLDR_DATA_TABLE_ENTRY DataTable;
+ LDR_DATA_TABLE_ENTRY DataTableBuffer;
+
+
+
+ if (!DbgReadMemory( hprc, (PVOID)vs.PsLoadedModuleList, (PVOID)&List, sizeof(LIST_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ DataTable = CONTAINING_RECORD( List.Flink,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks
+ );
+ if (!DbgReadMemory( hprc, (PVOID)DataTable, (PVOID)&DataTableBuffer, sizeof(LDR_DATA_TABLE_ENTRY), NULL)) {
+ return FALSE;
+ }
+
+ de.dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
+ de.dwProcessId = KD_PROCESSID;
+ de.dwThreadId = KD_THREADID;
+ de.u.LoadDll.hFile = (HANDLE)DataTableBuffer.CheckSum;
+ de.u.LoadDll.lpBaseOfDll = (LPVOID)vs.KernBase;
+ de.u.LoadDll.lpImageName = lpProgName;
+ de.u.LoadDll.fUnicode = FALSE;
+ de.u.LoadDll.nDebugInfoSize = 0;
+ de.u.LoadDll.dwDebugInfoFileOffset = DataTableBuffer.SizeOfImage;
+
+ ProcessDebugEvent( &de, &sc );
+ ConsumeAllEvents();
+
+ return TRUE;
+}
+
+VOID
+GetKernelSymbolAddresses(
+ VOID
+ )
+{
+ DcbAddr = GetSymbolAddress( "IopDumpControlBlock" );
+ MmLoadedUserImageList = GetSymbolAddress( "MmLoadedUserImageList" );
+ KiProcessorBlockAddr = GetSymbolAddress( "KiProcessorBlock" );
+#if defined(TARGET_ALPHA)
+ KiPcrBaseAddress = GetSymbolAddress( "KiPcrBaseAddress" );
+#endif
+}
+
+VOID
+GetMachineType(
+ LPPROCESSOR p
+ )
+{
+#if defined(TARGET_i386)
+
+ if (DmKdState != S_INITIALIZED) {
+ p->Level = 3;
+ } else {
+ p->Level = sc.ProcessorLevel;
+ }
+
+ p->Type = mptix86;
+ p->Endian = endLittle;
+
+#elif defined(TARGET_PPC)
+
+ if (DmKdState != S_INITIALIZED) {
+ p->Level = 601;
+ } else {
+ p->Level = sc.ProcessorLevel + 600;
+ }
+
+ p->Type = mptmppc;
+ p->Endian = endLittle;
+
+#elif defined(TARGET_MIPS)
+
+// BUGBUG handle R10000
+ p->Level = 4000;
+ p->Type = mptmips;
+ p->Endian = endLittle;
+
+#elif defined(TARGET_ALPHA)
+
+ p->Type = mptdaxp;
+ p->Endian = endLittle;
+ p->Level = 21064;
+
+#else
+#pragma error( "unknown target machine" );
+#endif
+
+}
+
+#if defined(TARGET_i386) || defined(TARGET_PPC)
+BOOL
+GetExtendedContext(
+ HTHDX hthd,
+ PKSPECIAL_REGISTERS pksr
+ )
+{
+ DWORD cb;
+ DWORD Status;
+ USHORT processor;
+
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ if (!hthd) {
+ return FALSE;
+ }
+
+ processor = (USHORT)(hthd->tid - 1);
+ if (ContextCache[processor].fSContextStale) {
+ if (!ReadControlSpace( processor,
+ (PVOID)sizeof(CONTEXT),
+ (PVOID)pksr,
+ sizeof(KSPECIAL_REGISTERS),
+ &cb
+ )) {
+ return FALSE;
+ }
+ memcpy( &ContextCache[processor].sregs,
+ pksr,
+ sizeof(KSPECIAL_REGISTERS)
+ );
+ ContextCache[processor].fSContextStale = FALSE;
+ ContextCache[processor].fSContextDirty = FALSE;
+ return TRUE;
+ } else {
+ memcpy( pksr,
+ &ContextCache[processor].sregs,
+ sizeof(KSPECIAL_REGISTERS)
+ );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL
+SetExtendedContext(
+ HTHDX hthd,
+ PKSPECIAL_REGISTERS pksr
+ )
+{
+ DWORD cb;
+ DWORD Status;
+ USHORT processor;
+
+
+ IsApiAllowed();
+ NoApiForCrashDump();
+
+ processor = (USHORT)(hthd->tid - 1);
+ Status = DmKdWriteControlSpace( processor,
+ (PVOID)sizeof(CONTEXT),
+ (PVOID)pksr,
+ sizeof(KSPECIAL_REGISTERS),
+ &cb
+ );
+
+ if (Status || cb != sizeof(KSPECIAL_REGISTERS)) {
+ return FALSE;
+ }
+
+ memcpy( &ContextCache[processor].sregs, pksr, sizeof(KSPECIAL_REGISTERS) );
+ ContextCache[processor].fSContextStale = FALSE;
+ ContextCache[processor].fSContextDirty = FALSE;
+ return TRUE;
+}
+#endif // i386 || PPC
+
+
+
+DWORD
+ProcessTerminateProcessCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ extern ULONG MaxRetries;
+ BREAKPOINT *pbpT;
+ BREAKPOINT *pbp;
+ HTHDX hthdT;
+
+
+ DEBUG_PRINT_2("ProcessTerminateProcessCmd called hprc=0x%x, hthd=0x%x\n",
+ hprc, hthd);
+
+ MaxRetries = 1;
+
+ if (!ApiIsAllowed) {
+ return TRUE;
+ }
+
+ if (hprc) {
+ hprc->pstate |= ps_dead;
+ hprc->dwExitCode = 0;
+ ConsumeAllProcessEvents(hprc, TRUE);
+
+ for (pbp = BPNextHprcPbp(hprc, NULL); pbp; pbp = pbpT) {
+ pbpT = BPNextHprcPbp(hprc, pbp);
+ RemoveBP(pbp);
+ }
+
+ for (hthdT = hprc->hthdChild; hthdT; hthdT = hthdT->nextSibling) {
+ if ( !(hthdT->tstate & ts_dead) ) {
+ hthdT->tstate |= ts_dead;
+ hthdT->tstate &= ~ts_stopped;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+VOID
+ProcessAllProgFreeCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ ProcessTerminateProcessCmd(hprc, hthd, lpdbb);
+}
+
+
+
+DWORD
+ProcessAsyncGoCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ XOSD xosd = xosdNone;
+
+ DEBUG_PRINT("ProcessAsyncGoCmd called\n");
+
+ hthd->tstate &= ~ts_frozen;
+ Reply(0, &xosd, lpdbb->hpid);
+ return(xosd);
+}
+
+
+VOID
+ProcessAsyncStopCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to a asynchronous stop request.
+ In order to do this we will set breakpoints the current PC for
+ every thread in the system and wait for the fireworks to start.
+
+Arguments:
+
+ hprc - Supplies a process handle
+ hthd - Supplies a thread handle
+ lpdbb - Supplies the command information packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DmKdBreakIn = TRUE;
+ LpDmMsg->xosdRet = xosdNone;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+} /* ProcessAsyncStopCmd() */
+
+
+VOID
+ProcessDebugActiveCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ if (!DmKdConnectAndInitialize( KERNEL_IMAGE_NAME )) {
+ LpDmMsg->xosdRet = xosdFileNotFound;
+ } else {
+ LpDmMsg->xosdRet = xosdNone;
+ }
+
+ if (fDisconnected) {
+ DmKdBreakIn = TRUE;
+ SetEvent( hEventRemoteQuit );
+ }
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+}
+
+
+VOID
+ProcessQueryTlsBaseCmd(
+ HPRCX hprcx,
+ HTHDX hthdx,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to an EM request to get the base
+ of the thread local storage for a given thread and DLL.
+
+Arguments:
+
+ hprcx - Supplies a process handle
+
+ hthdx - Supplies a thread handle
+
+ lpdbb - Supplies the command information packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( sizeof(ADDR), LpDmMsg, lpdbb->hpid );
+ return;
+} /* ProcessQueryTlsBaseCmd() */
+
+
+VOID
+ProcessQuerySelectorCmd(
+ HPRCX hprcx,
+ HTHDX hthdx,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This command is send from the EM to fill-in a LDT_ENTRY structure
+ for a given selector.
+
+Arguments:
+
+ hprcx - Supplies the handle to the process
+
+ hthdx - Supplies the handle to the thread and is optional
+
+ lpdbb - Supplies the pointer to the full query packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+
+ xosd = xosdInvalidSelector;
+ Reply( sizeof(xosd), &xosd, lpdbb->hpid);
+
+ return;
+}
+
+
+VOID
+ProcessReloadModulesCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This command is send from the EM to cause all modules to be reloaded.
+
+Arguments:
+
+ hprcx - Supplies the handle to the process
+ hthdx - Supplies the handle to the thread and is optional
+ lpdbb - Supplies the pointer to the full query packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+ LPIOL lpiol = (LPIOL) lpdbb->rgbVar;
+
+ AddQueue( QT_RELOAD_MODULES,
+ hprc->pid,
+ hthd->tid,
+ *((PULONG)lpiol->rgbVar),
+ 0
+ );
+
+ xosd = xosdNone;
+ Reply( sizeof(xosd), &xosd, lpdbb->hpid);
+
+ return;
+}
+
+
+VOID
+ProcessVirtualQueryCmd(
+ HPRCX hprc,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+#define vaddr(va) ((hprc->fRomImage) ? d[iDll].offBaseOfImage+(va) : (va))
+
+ ADDR addr;
+ DWORD cb;
+ PDLLLOAD_ITEM d = prcList->next->rgDllList;
+
+ PMEMORY_BASIC_INFORMATION lpmbi = (PMEMORY_BASIC_INFORMATION)LpDmMsg->rgb;
+ XOSD xosd = xosdNone;
+
+ static int iDll = 0;
+ static PIMAGE_SECTION_HEADER s = NULL;
+
+
+ addr = *(LPADDR)(lpdbb->rgbVar);
+
+ lpmbi->BaseAddress = (LPVOID)(addr.addr.off & (PAGE_SIZE - 1));
+ lpmbi->RegionSize = PAGE_SIZE;
+
+ // first guess
+ lpmbi->AllocationBase = lpmbi->BaseAddress;
+
+ lpmbi->Protect = PAGE_READWRITE;
+ lpmbi->AllocationProtect = PAGE_READWRITE;
+ lpmbi->State = MEM_COMMIT;
+ lpmbi->Type = MEM_PRIVATE;
+
+ //
+ // the following code is necessary to determine if the requested
+ // base address is in a page that contains code. if the base address
+ // meets these conditions then reply that it is executable.
+ //
+
+ if ( !s ||
+ addr.addr.off < vaddr(s->VirtualAddress) ||
+ addr.addr.off >= vaddr(s->VirtualAddress+s->SizeOfRawData) ) {
+
+ for (iDll=0; iDll<prcList->next->cDllList; iDll++) {
+
+ if (addr.addr.off >= d[iDll].offBaseOfImage &&
+ addr.addr.off < d[iDll].offBaseOfImage+d[iDll].cbImage) {
+
+ s = d[iDll].Sections;
+ cb = d[iDll].NumberOfSections;
+ while (cb) {
+ if (addr.addr.off >= vaddr(s->VirtualAddress) &&
+ addr.addr.off < vaddr(s->VirtualAddress+s->SizeOfRawData) )
+ {
+ break;
+ }
+ else {
+ s++;
+ cb--;
+ }
+ }
+ if (cb == 0) {
+ s = NULL;
+ }
+ break;
+ }
+ }
+ }
+
+ if (s) {
+ lpmbi->BaseAddress = (LPVOID)(vaddr(s->VirtualAddress));
+ lpmbi->RegionSize = vaddr(s->VirtualAddress);
+
+ switch ( s->Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE) ) {
+
+ case IMAGE_SCN_MEM_EXECUTE:
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_EXECUTE;
+ break;
+
+ case IMAGE_SCN_CNT_CODE:
+ case (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE):
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_EXECUTE_READ;
+ break;
+
+ case (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE):
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_EXECUTE_READWRITE;
+ break;
+
+ // This one probably never happens
+ case (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE):
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_EXECUTE_READWRITE;
+ break;
+
+ case IMAGE_SCN_MEM_READ:
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_READONLY;
+ break;
+
+ case (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE):
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_READWRITE;
+ break;
+
+ // This one probably never happens
+ case IMAGE_SCN_MEM_WRITE:
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_READWRITE;
+ break;
+
+ case 0:
+ lpmbi->Protect =
+ lpmbi->AllocationProtect = PAGE_NOACCESS;
+ break;
+
+ }
+ }
+
+ LpDmMsg->xosdRet = xosd;
+ Reply( sizeof(MEMORY_BASIC_INFORMATION), LpDmMsg, lpdbb->hpid );
+
+ return;
+}
+
+VOID
+ProcessGetDmInfoCmd(
+ HPRCX hprc,
+ LPDBB lpdbb,
+ DWORD cb
+ )
+{
+ extern DBGKD_GET_VERSION vs;
+ LPDMINFO lpi = (LPDMINFO)LpDmMsg->rgb;
+
+ LpDmMsg->xosdRet = xosdNone;
+
+ lpi->fAsync = 0;
+ lpi->fHasThreads = 1;
+ lpi->fReturnStep = 0;
+ //lpi->fRemote = ???
+ lpi->fAsyncStop = 1;
+ lpi->fAlwaysFlat = 1;
+ lpi->fHasReload = 1;
+
+#ifdef HAS_DEBUG_REGS
+ lpi->cbSpecialRegs = sizeof(KSPECIAL_REGISTERS);
+#else
+ lpi->cbSpecialRegs = 0;
+#endif
+
+ lpi->MajorVersion = vs.MajorVersion;
+ lpi->MinorVersion = vs.MinorVersion;
+
+ lpi->Breakpoints = bptsExec |
+ bptsDataC |
+ bptsDataW |
+ bptsDataR |
+ bptsDataExec;
+
+ GetMachineType(&lpi->Processor);
+
+ //
+ // hack so that TL can call tlfGetVersion before
+ // reply buffer is initialized.
+ //
+ if ( cb >= (sizeof(DBB) + sizeof(DMINFO)) ) {
+ memcpy(lpdbb->rgbVar, lpi, sizeof(DMINFO));
+ }
+
+ Reply( sizeof(DMINFO), LpDmMsg, lpdbb->hpid );
+}
+
+#ifdef HAS_DEBUG_REGS
+VOID
+ProcessGetExtendedContextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ PKSPECIAL_REGISTERS pksr = (PKSPECIAL_REGISTERS)LpDmMsg->rgb;
+
+
+ if (GetExtendedContext( hthd, pksr )) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ } else {
+ LpDmMsg->xosdRet = xosdNone;
+ }
+
+ Reply(sizeof(KSPECIAL_REGISTERS), LpDmMsg, lpdbb->hpid);
+}
+
+void
+ProcessSetExtendedContextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ PKSPECIAL_REGISTERS pksr = (PKSPECIAL_REGISTERS)lpdbb->rgbVar;
+
+
+ if (SetExtendedContext( hthd, pksr )) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ } else {
+ LpDmMsg->xosdRet = xosdNone;
+ }
+
+ Reply(0, LpDmMsg, lpdbb->hpid);
+}
+#endif // HAS_DEBUG_REGS
+
+void
+ProcessGetSectionsCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ DWORD dwBaseOfDll = *((LPDWORD) lpdbb->rgbVar);
+ LPOBJD rgobjd = (LPOBJD) LpDmMsg->rgb;
+ IMAGE_DOS_HEADER dh;
+ IMAGE_NT_HEADERS nh;
+ PIMAGE_SECTION_HEADER sec;
+ IMAGE_ROM_OPTIONAL_HEADER rom;
+ DWORD fpos;
+ DWORD iobj;
+ DWORD offset;
+ DWORD cbObject;
+ DWORD iDll;
+ DWORD sig;
+ IMAGEINFO ii;
+
+
+ //
+ // find the module
+ //
+ for (iDll=0; iDll<(DWORD)hprc->cDllList; iDll++) {
+ if (hprc->rgDllList[iDll].offBaseOfImage == dwBaseOfDll) {
+
+ if (hprc->rgDllList[iDll].sec) {
+
+ sec = hprc->rgDllList[iDll].sec;
+ nh.FileHeader.NumberOfSections =
+ (USHORT)hprc->rgDllList[iDll].NumberOfSections;
+
+ } else {
+ fpos = dwBaseOfDll;
+
+ if (!DbgReadMemory( hprc, (LPVOID)fpos, &dh, sizeof(IMAGE_DOS_HEADER), NULL )) {
+ break;
+ }
+
+ if (dh.e_magic == IMAGE_DOS_SIGNATURE) {
+ fpos += dh.e_lfanew;
+ } else {
+ fpos = dwBaseOfDll;
+ }
+
+ if (!DbgReadMemory( hprc, (LPVOID)fpos, &sig, sizeof(sig), NULL )) {
+ break;
+ }
+
+ if (sig != IMAGE_NT_SIGNATURE) {
+ if (!DbgReadMemory( hprc, (LPVOID)fpos, &nh.FileHeader, sizeof(IMAGE_FILE_HEADER), NULL )) {
+ break;
+ }
+ fpos += sizeof(IMAGE_FILE_HEADER);
+ if (nh.FileHeader.SizeOfOptionalHeader == IMAGE_SIZEOF_ROM_OPTIONAL_HEADER) {
+ if (!DbgReadMemory( hprc, (LPVOID)fpos, &rom, sizeof(rom), NULL )) {
+ break;
+ }
+ ZeroMemory( &nh.OptionalHeader, sizeof(nh.OptionalHeader) );
+ nh.OptionalHeader.SizeOfImage = rom.SizeOfCode;
+ nh.OptionalHeader.ImageBase = rom.BaseOfCode;
+ } else {
+ //
+ // maybe its a firmware image?
+ //
+ if (! ReadImageInfo(
+ hprc->rgDllList[iDll].szDllName,
+ NULL,
+ (LPSTR)KdOptions[KDO_SYMBOLPATH].value,
+ &ii )) {
+ //
+ // can't read the image correctly
+ //
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+ }
+ sec = ii.Sections;
+ nh.FileHeader.NumberOfSections = (USHORT)ii.NumberOfSections;
+ nh.FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_ROM_OPTIONAL_HEADER;
+ }
+ } else {
+ if (!DbgReadMemory( hprc, (LPVOID)fpos, &nh, sizeof(IMAGE_NT_HEADERS), NULL )) {
+ break;
+ }
+
+ fpos += sizeof(IMAGE_NT_HEADERS);
+
+ if (nh.Signature != IMAGE_NT_SIGNATURE) {
+ break;
+ }
+
+ if (hprc->rgDllList[iDll].TimeStamp == 0) {
+ hprc->rgDllList[iDll].TimeStamp = nh.FileHeader.TimeDateStamp;
+ }
+
+ if (hprc->rgDllList[iDll].CheckSum == 0) {
+ hprc->rgDllList[iDll].CheckSum = nh.OptionalHeader.CheckSum;
+ }
+
+ sec = malloc( nh.FileHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER );
+ if (!sec) {
+ break;
+ }
+
+ DbgReadMemory( hprc, (LPVOID)fpos, sec, nh.FileHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER, NULL );
+ }
+ }
+
+ if (hprc->rgDllList[iDll].Sections == NULL) {
+ hprc->rgDllList[iDll].Sections = sec;
+ hprc->rgDllList[iDll].NumberOfSections =
+ nh.FileHeader.NumberOfSections;
+
+ if (nh.FileHeader.SizeOfOptionalHeader !=
+ IMAGE_SIZEOF_ROM_OPTIONAL_HEADER) {
+ for (iobj=0; iobj<nh.FileHeader.NumberOfSections; iobj++) {
+ hprc->rgDllList[iDll].Sections[iobj].VirtualAddress +=
+ (DWORD)dwBaseOfDll;
+ }
+ }
+ }
+
+ *((LPDWORD)LpDmMsg->rgb) = nh.FileHeader.NumberOfSections;
+ rgobjd = (LPOBJD) (LpDmMsg->rgb + sizeof(DWORD));
+ //
+ // Set up the descriptors for each of the section headers
+ // so that the EM can map between section numbers and flat
+ // addresses.
+ //
+ for (iobj=0; iobj<nh.FileHeader.NumberOfSections; iobj++) {
+ offset = hprc->rgDllList[iDll].Sections[iobj].VirtualAddress;
+ cbObject =
+ hprc->rgDllList[iDll].Sections[iobj].Misc.VirtualSize;
+ if (cbObject == 0) {
+ cbObject =
+ hprc->rgDllList[iDll].Sections[iobj].SizeOfRawData;
+ }
+ rgobjd[iobj].offset = offset;
+ rgobjd[iobj].cb = cbObject;
+ rgobjd[iobj].wPad = 1;
+#ifdef TARGET_i386
+ if (IMAGE_SCN_CNT_CODE &
+ hprc->rgDllList[iDll].Sections[iobj].Characteristics) {
+ rgobjd[iobj].wSel = (WORD) hprc->rgDllList[iDll].SegCs;
+ } else {
+ rgobjd[iobj].wSel = (WORD) hprc->rgDllList[iDll].SegDs;
+ }
+#else
+ rgobjd[iobj].wSel = 0;
+#endif
+ }
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(DWORD) +
+ (hprc->rgDllList[iDll].NumberOfSections * sizeof(OBJD)),
+ LpDmMsg,
+ lpdbb->hpid);
+
+ return;
+ }
+ }
+
+
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+}
+
+
+
+VOID
+ProcessIoctlGenericCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ static USHORT Processor = (USHORT)-1;
+ LPIOL lpiol = (LPIOL)lpdbb->rgbVar;
+ PIOCTLGENERIC pig = (PIOCTLGENERIC)lpiol->rgbVar;
+ PPROCESSORINFO pi;
+ PREADCONTROLSPACE prc;
+ PIOSPACE pis;
+ PIOSPACE_EX pisex;
+ PPHYSICAL phy;
+ DWORD len;
+ PKDHELP KdHelp;
+
+ static ULONG SavedThread;
+
+
+ if (!ApiIsAllowed) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( sizeof(IOCTLGENERIC)+pig->length, LpDmMsg, lpdbb->hpid );
+ return;
+ }
+
+ switch( pig->ioctlSubType ) {
+ case IG_READ_CONTROL_SPACE:
+ prc = (PREADCONTROLSPACE) pig->data;
+ if ((SHORT)prc->Processor == -1) {
+ if (Processor == (USHORT)-1) {
+ prc->Processor = sc.Processor;
+ } else {
+ prc->Processor = Processor;
+ }
+ }
+ if (!ReadControlSpace( (USHORT)prc->Processor,
+ (PVOID)prc->Address,
+ (PVOID)prc->Buf,
+ prc->BufLen,
+ &len
+ )) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ }
+ prc->BufLen = len;
+ break;
+
+ case IG_WRITE_CONTROL_SPACE:
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+
+ case IG_READ_IO_SPACE:
+ pis = (PIOSPACE) pig->data;
+ if (DmKdReadIoSpace( (PVOID)pis->Address,
+ &pis->Data, pis->Length ) != STATUS_SUCCESS) {
+ pis->Length = 0;
+ }
+ break;
+
+ case IG_WRITE_IO_SPACE:
+ pis = (PIOSPACE) pig->data;
+ if (DmKdWriteIoSpace( (PVOID)pis->Address,
+ pis->Data, pis->Length ) != STATUS_SUCCESS) {
+ pis->Length = 0;
+ }
+ break;
+
+ case IG_READ_IO_SPACE_EX:
+ pisex = (PIOSPACE_EX) pig->data;
+ if (DmKdReadIoSpaceEx(
+ (PVOID)pisex->Address,
+ &pisex->Data,
+ pisex->Length,
+ pisex->InterfaceType,
+ pisex->BusNumber,
+ pisex->AddressSpace
+ ) != STATUS_SUCCESS) {
+ pisex->Length = 0;
+ }
+ break;
+
+ case IG_WRITE_IO_SPACE_EX:
+ pisex = (PIOSPACE_EX) pig->data;
+ if (DmKdWriteIoSpaceEx(
+ (PVOID)pisex->Address,
+ pisex->Data,
+ pisex->Length,
+ pisex->InterfaceType,
+ pisex->BusNumber,
+ pisex->AddressSpace
+ ) != STATUS_SUCCESS) {
+ pisex->Length = 0;
+ }
+ break;
+
+ case IG_READ_PHYSICAL:
+ phy = (PPHYSICAL) pig->data;
+ if (DmKdReadPhysicalMemory( phy->Address, phy->Buf, phy->BufLen, &len )) {
+ phy->BufLen = 0;
+ }
+ break;
+
+ case IG_WRITE_PHYSICAL:
+ phy = (PPHYSICAL) pig->data;
+ if (DmKdWritePhysicalMemory( phy->Address, phy->Buf, phy->BufLen, &len )) {
+ phy->BufLen = 0;
+ }
+ break;
+
+ case IG_DM_PARAMS:
+ ParseDmParams( (LPSTR)pig->data );
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+
+ case IG_KD_CONTEXT:
+ pi = (PPROCESSORINFO) pig->data;
+ pi->Processor = sc.Processor;
+ pi->NumberProcessors = (USHORT)sc.NumberProcessors;
+ break;
+
+ case IG_RELOAD:
+ AddQueue( QT_RELOAD_MODULES,
+ 0,
+ 0,
+ (DWORD)pig->data,
+ strlen((LPSTR)pig->data)+1 );
+ break;
+
+ case IG_PAGEIN:
+ if (DmKdPageIn( ((PULONG)pig->data)[0] ) == STATUS_SUCCESS) {
+ LpDmMsg->xosdRet = xosdNone;
+ } else {
+ LpDmMsg->xosdRet = xosdUnknown;
+ }
+ break;
+
+ case IG_CHANGE_PROC:
+ Processor = (USHORT)((PULONG)pig->data)[0];
+ break;
+
+ case IG_KSTACK_HELP:
+ KdHelp = (PKDHELP)pig->data;
+ KdHelp->Thread = SavedThread? SavedThread : (DWORD)sc.Thread;
+ SavedThread = 0;
+ KdHelp->KiCallUserMode = vs.KiCallUserMode;
+ KdHelp->ThCallbackStack = vs.ThCallbackStack;
+ KdHelp->NextCallback = vs.NextCallback;
+ KdHelp->FramePointer = vs.FramePointer;
+ KdHelp->KeUserCallbackDispatcher = vs.KeUserCallbackDispatcher;
+ break;
+
+ case IG_SET_THREAD:
+ memcpy(&SavedThread, pig->data, sizeof(ULONG));
+ break;
+
+ default:
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+ }
+
+ len = sizeof(IOCTLGENERIC) + pig->length;
+ memcpy( LpDmMsg->rgb, pig, len );
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(IOCTLGENERIC)+pig->length, LpDmMsg, lpdbb->hpid );
+}
+
+
+VOID
+ProcessIoctlCustomCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPIOL lpiol = (LPIOL)lpdbb->rgbVar;
+ LPSTR p = lpiol->rgbVar;
+
+
+ LpDmMsg->xosdRet = xosdUnsupported;
+
+ //
+ // parse the command
+ //
+ while (*p && !isspace(*p++));
+ if (*p) {
+ *(p-1) = '\0';
+ }
+
+ //
+ // process the command
+ //
+ if (_stricmp( lpiol->rgbVar, "resync" ) == 0) {
+ DMPrintShellMsg( "Host and target systems resynchronizing...\n" );
+ KdResync = TRUE;
+ LpDmMsg->xosdRet = xosdNone;
+ } else
+ if (_stricmp( lpiol->rgbVar, "cache" ) == 0) {
+ ProcessCacheCmd(p);
+ LpDmMsg->xosdRet = xosdNone;
+ } else
+ if (_stricmp( lpiol->rgbVar, "reboot" ) == 0) {
+ if (ApiIsAllowed) {
+ AddQueue( QT_REBOOT, 0, 0, 0, 0 );
+ LpDmMsg->xosdRet = xosdNone;
+ } else {
+ LpDmMsg->xosdRet = xosdUnknown;
+ }
+ } else
+ if (_stricmp( lpiol->rgbVar, "crash" ) == 0) {
+ if (ApiIsAllowed) {
+ AddQueue( QT_CRASH, 0, 0, CRASH_BUGCHECK_CODE, 0 );
+ LpDmMsg->xosdRet = xosdNone;
+ } else {
+ LpDmMsg->xosdRet = xosdUnknown;
+ }
+ } else
+ if ( !_stricmp(lpiol->rgbVar, "FastStep") ) {
+ fSmartRangeStep = TRUE;
+ LpDmMsg->xosdRet = xosdNone;
+ } else
+ if ( !_stricmp(lpiol->rgbVar, "SlowStep") ) {
+ fSmartRangeStep = FALSE;
+ LpDmMsg->xosdRet = xosdNone;
+ } else
+ if ( !_stricmp(lpiol->rgbVar, "trace") ) {
+ fPacketTrace = !fPacketTrace;
+ LpDmMsg->xosdRet = xosdNone;
+ }
+
+ //
+ // send back our response
+ //
+ Reply(0, LpDmMsg, lpdbb->hpid);
+}
+
diff --git a/private/windbg/newdm/kdwow.c b/private/windbg/newdm/kdwow.c
new file mode 100644
index 000000000..5a3d5b7fe
--- /dev/null
+++ b/private/windbg/newdm/kdwow.c
@@ -0,0 +1,238 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ WOW.C
+
+Abstract:
+
+ This file contains the code which is responsable for dealing with
+ the WOW debug structures and debug events.
+
+Author:
+
+ James L Schaad (jimsch) 05-11-92
+
+Environment:
+
+ User Mode WIN32
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+/************************* GLOBAL VARIABLES ******************************/
+
+extern char abEMReplyBuf[];
+extern DDVECTOR RgfnFuncEventDispatch[];
+extern DDVECTOR DebugDispatchTable[];
+extern char nameBuffer[];
+
+/************************** FUNCTIONS ************************************/
+
+
+void
+ProcessEntryPointEvent(
+ DEBUG_EVENT * pde,
+ HTHDX hthdx
+ )
+/*++
+
+Routine Description:
+
+ This handles task start events after the first one.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+}
+
+
+
+void
+ProcessSegmentLoadEvent(
+ DEBUG_EVENT * pde,
+ HTHDX hthdx
+ )
+
+/*++
+
+Routine Description:
+
+ This function takes care of dealing with segment load events from
+ the wow system. These come in as exceptions and are translated
+ to segment load events in ProcessDebugEvent.
+
+Arguments:
+
+ pde - Supplies a pointer to the modified debug event
+ hthdx - Supplies the handle to the thread of the debug event
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+} /* ProcessSegmentLoadEvent() */
+
+/*++
+
+Routine Description:
+
+ Callback for VDMEnumProcessWOW
+
+Arguments:
+
+ See PROCESSENUMPROC in vdmdbg.h
+
+Return Value:
+
+ TRUE
+
+--*/
+BOOL WINAPI EnumCallBack(
+ DWORD dwProcessId,
+ DWORD dwAttributes,
+ LPARAM lpUserDefined
+ )
+{
+ UNREFERENCED_PARAMETER( dwProcessId );
+ UNREFERENCED_PARAMETER( dwAttributes );
+ UNREFERENCED_PARAMETER( lpUserDefined );
+
+ return TRUE;
+}
+
+
+
+BOOL
+IsWOWPresent(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Determines if WOW is running
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if WOW is running, FALSE otherwise
+
+--*/
+
+{
+ return FALSE;
+}
+
+
+
+BOOL
+TranslateAddress(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR lpaddr,
+ BOOL f16ToFlat
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to preform address translations from the segmented
+ to the flat world and back again.
+
+Arguments:
+
+ hprc - Supplies the handle to the current process
+
+ hthd - Supplies the handle to the thread for the address
+
+ lpaddr - Supplies the address to be translated
+
+ f16ToFlat - Supplies the direction the translation is to be made
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+ return TRUE;
+} /* TranslateAddress() */
+
+
+BOOL
+WOWGetThreadContext(
+ HTHDX hthdx,
+ LPCONTEXT lpcxt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to g the context of a WOW thread. We have
+ a current assumption that we will only have one WOW event at a time.
+
+Arguments:
+
+ hthdx - supplies the handle to the thread to change the context of
+
+ lpcxt - supplies the new context.
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+ return FALSE;
+} /* WOWGetThreadContext() */
+
+
+
+BOOL
+WOWSetThreadContext(
+ HTHDX hthdx,
+ LPCONTEXT lpcxt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to set the context of a WOW thread. We have
+ a current assumption that we will only have one WOW event at a time.
+
+Arguments:
+
+ hthdx - supplies the handle to the thread to change the context of
+ lpcxt - supplies the new context.
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+ return FALSE;
+} /* WOWSetThreadContext() */
diff --git a/private/windbg/newdm/list.h b/private/windbg/newdm/list.h
new file mode 100644
index 000000000..380c5e846
--- /dev/null
+++ b/private/windbg/newdm/list.h
@@ -0,0 +1,133 @@
+
+//
+// Doubly-linked list manipulation routines. Implemented as macros
+// but logically these are procedures.
+//
+
+//
+// VOID
+// InitializeListHead(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define InitializeListHead(ListHead) (\
+ (ListHead)->Flink = (ListHead)->Blink = (ListHead))
+
+//
+// BOOLEAN
+// IsListEmpty(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define IsListEmpty(ListHead) \
+ ((ListHead)->Flink == (ListHead))
+
+//
+// PLIST_ENTRY
+// RemoveHeadList(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define RemoveHeadList(ListHead) \
+ (ListHead)->Flink;\
+ {RemoveEntryList((ListHead)->Flink)}
+
+//
+// PLIST_ENTRY
+// RemoveTailList(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define RemoveTailList(ListHead) \
+ (ListHead)->Blink;\
+ {RemoveEntryList((ListHead)->Blink)}
+
+//
+// VOID
+// RemoveEntryList(
+// PLIST_ENTRY Entry
+// );
+//
+
+#define RemoveEntryList(Entry) {\
+ PLIST_ENTRY _EX_Blink;\
+ PLIST_ENTRY _EX_Flink;\
+ _EX_Flink = (Entry)->Flink;\
+ _EX_Blink = (Entry)->Blink;\
+ _EX_Blink->Flink = _EX_Flink;\
+ _EX_Flink->Blink = _EX_Blink;\
+ }
+
+//
+// VOID
+// InsertTailList(
+// PLIST_ENTRY ListHead,
+// PLIST_ENTRY Entry
+// );
+//
+
+#define InsertTailList(ListHead,Entry) {\
+ PLIST_ENTRY _EX_Blink;\
+ PLIST_ENTRY _EX_ListHead;\
+ _EX_ListHead = (ListHead);\
+ _EX_Blink = _EX_ListHead->Blink;\
+ (Entry)->Flink = _EX_ListHead;\
+ (Entry)->Blink = _EX_Blink;\
+ _EX_Blink->Flink = (Entry);\
+ _EX_ListHead->Blink = (Entry);\
+ }
+
+//
+// VOID
+// InsertHeadList(
+// PLIST_ENTRY ListHead,
+// PLIST_ENTRY Entry
+// );
+//
+
+#define InsertHeadList(ListHead,Entry) {\
+ PLIST_ENTRY _EX_Flink;\
+ PLIST_ENTRY _EX_ListHead;\
+ _EX_ListHead = (ListHead);\
+ _EX_Flink = _EX_ListHead->Flink;\
+ (Entry)->Flink = _EX_Flink;\
+ (Entry)->Blink = _EX_ListHead;\
+ _EX_Flink->Blink = (Entry);\
+ _EX_ListHead->Flink = (Entry);\
+ }
+
+//
+//
+// PSINGLE_LIST_ENTRY
+// PopEntryList(
+// PSINGLE_LIST_ENTRY ListHead
+// );
+//
+
+#define PopEntryList(ListHead) \
+ (ListHead)->Next;\
+ {\
+ PSINGLE_LIST_ENTRY FirstEntry;\
+ FirstEntry = (ListHead)->Next;\
+ if (FirstEntry != NULL) { \
+ (ListHead)->Next = FirstEntry->Next;\
+ } \
+ }
+
+
+//
+// VOID
+// PushEntryList(
+// PSINGLE_LIST_ENTRY ListHead,
+// PSINGLE_LIST_ENTRY Entry
+// );
+//
+
+#define PushEntryList(ListHead,Entry) \
+ (Entry)->Next = (ListHead)->Next; \
+ (ListHead)->Next = (Entry)
+
diff --git a/private/windbg/newdm/mipsmach.c b/private/windbg/newdm/mipsmach.c
new file mode 100644
index 000000000..8afc3886a
--- /dev/null
+++ b/private/windbg/newdm/mipsmach.c
@@ -0,0 +1,883 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ mach.c
+
+Abstract:
+
+ This file contains the MIPS specific code for dealing with
+ machine dependent issues that invlove registers, instruction
+ disassembly, function calling and other interesting things.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+Notes:
+
+--*/
+
+#include "precomp.h"
+
+extern LPDM_MSG LpDmMsg;
+
+extern CRITICAL_SECTION csContinueQueue;
+
+typedef enum _MIPS_InstrType
+ {
+ mips_itype_Imm,
+ mips_itype_Jump,
+ mips_itype_Reg,
+ mips_itype_dont_care
+ }
+MIPS_InstrType;
+
+
+BOOL
+IsRet(
+ HTHDX hthd,
+ LPADDR addr
+ )
+{
+ DWORD instr;
+ DWORD cBytes;
+ if (!AddrReadMemory( hthd->hprc, hthd, addr, &instr, 4, &cBytes )) {
+ return FALSE;
+ }
+ return (instr == 0x03e00008); // JR r31
+}
+
+
+void
+IsCall (
+ HTHDX hthd,
+ LPADDR lpaddr,
+ LPINT lpf,
+ BOOL fStepOver
+ )
+
+/*++
+
+Routine Description:
+
+ IsCall
+
+Arguments:
+
+ hthd - Supplies the handle to the thread
+
+ lpaddr - Supplies the address to be check for a call instruction
+
+ lpf - Returns class of instruction:
+ CALL
+ BREAKPOINT_INSTRUCTION
+ SOFTWARE_INTERRUPT
+ FALSE
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG opcode;
+ ADDR firaddr = *lpaddr;
+ DWORD length;
+ ULONGLONG *regArray = &hthd->context.XIntZero;
+ INSTR disinstr;
+ BOOL r;
+
+
+
+ if (hthd->fIsCallDone) {
+ *lpaddr = hthd->addrIsCall;
+ *lpf = hthd->iInstrIsCall;
+ return;
+ }
+
+ /*
+ * Assume that this is not a call instruction
+ */
+
+ *lpf = FALSE;
+
+ /*
+ * Read in the dword which contains the instruction under
+ * inspection.
+ */
+
+ r = AddrReadMemory(hthd->hprc,
+ hthd,
+ &firaddr,
+ &disinstr.instruction,
+ sizeof(DWORD),
+ &length );
+ if (!r || length != sizeof(DWORD)) {
+ goto done;
+ }
+
+ /*
+ * Assume that this is a jump instruction and get the opcode.
+ * This is the top 6 bits of the instruction dword.
+ */
+
+ opcode = disinstr.jump_instr.Opcode;
+
+ /*
+ * The first thing to check for is the SPECIAL instruction.
+ *
+ * BREAK and JALR
+ */
+
+ if (opcode == 0x00L) {
+ /*
+ * There are one opcode in the SPECIAL range which need to
+ * be treaded specially.
+ *
+ * BREAK:
+ * If the value is 0x16 then this was a "breakpoint" set
+ * by the debugger. Other values represent different
+ * exceptions which were programmed in by the code writer.
+ */
+
+ if (disinstr.break_instr.Function == 0x0D) {
+ if (disinstr.break_instr.Code == 0x16) {
+ *lpf = INSTR_BREAKPOINT;
+ } else {
+ *lpf = INSTR_SOFT_INTERRUPT;
+ }
+ } else if (disinstr.special_instr.Funct == 0x09L) {
+ *lpf = INSTR_IS_CALL;
+ }
+ }
+
+ /*
+ * Next item is REGIMM
+ *
+ * BLTZAL, BGEZAL, BLTZALL, BGEZALL
+ */
+
+ else if (opcode == 0x01L) {
+ if (((disinstr.immed_instr.RT & ~0x3) == 0x10) &&
+
+ ((((LONGLONG)regArray[disinstr.immed_instr.RS]) >= 0) ==
+ (BOOL)(disinstr.immed_instr.RT & 0x01))) {
+
+ *lpf = INSTR_IS_CALL;
+ }
+ }
+
+ /*
+ * Next item is JAL
+ */
+
+ else if (opcode == 0x03) {
+ *lpf = INSTR_IS_CALL;
+ }
+
+ DPRINT(1, ("(IsCall?) FIR=%08x Type=%s\n", GetAddrOff(firaddr),
+ (*lpf==INSTR_IS_CALL? "CALL":
+ (*lpf==INSTR_BREAKPOINT? "BREAKPOINT":
+ (*lpf==INSTR_SOFT_INTERRUPT? "INTERRUPT":
+ "NORMAL"))) ) );
+
+done:
+ if (*lpf==INSTR_IS_CALL) {
+ lpaddr->addr.off += BP_SIZE + DELAYED_BRANCH_SLOT_SIZE;
+ hthd->addrIsCall = *lpaddr;
+ } else if ( *lpf==INSTR_SOFT_INTERRUPT ) {
+ lpaddr->addr.off += BP_SIZE;
+ }
+ hthd->iInstrIsCall = *lpf;
+
+ return;
+} /* IsCall() */
+
+
+
+ULONG
+GetNextOffset (
+ HTHDX hthd,
+ BOOL fStep
+ )
+
+/*++
+
+Routine Description:
+
+ From a limited disassembly of the instruction pointed
+ by the FIR register, compute the offset of the next
+ instruction for either a trace or step operation.
+
+Arguments:
+
+ hthd - Supplies the handle to the thread to get the next offset for
+
+ fStep - Supplies TRUE for STEP offset and FALSE for trace offset
+
+Return Value:
+
+ Offset to place breakpoint at for doing a STEP or TRACE
+
+--*/
+
+{
+ ULONG returnvalue;
+ ULONG opcode;
+ ADDR firaddr;
+ DWORD length;
+ ULONGLONG *regArray = &hthd->context.XIntZero;
+ INSTR disinstr;
+ BOOL r;
+
+ AddrFromHthdx(&firaddr, hthd);
+ r = AddrReadMemory(hthd->hprc,
+ hthd,
+ &firaddr,
+ &disinstr.instruction,
+ sizeof(DWORD),
+ &length);
+ if (!r || length != sizeof(DWORD)) {
+ DPRINT(1, ("GetNextOffset: AddrReadMemory failed %x\n", GetAddrOff(firaddr)) );
+ assert(FALSE);
+ return 4;
+ }
+ opcode = disinstr.jump_instr.Opcode;
+ returnvalue = firaddr.addr.off + sizeof(ULONG) * 2; /* assume delay slot */
+
+ if (disinstr.instruction == 0x0000000c) {
+ // stepping over a syscall instruction must set the breakpoint
+ // at the caller's return address, not the inst after the syscall
+ returnvalue = (DWORD)hthd->context.XIntRa;
+ }
+ else
+ if (opcode == 0x00L /* SPECIAL */
+ && (disinstr.special_instr.Funct & ~0x01L) == 0x08L) {
+ /* jr/jalr only */
+ if (disinstr.special_instr.Funct == 0x08L || !fStep) /* jr or trace */
+ returnvalue = (DWORD)regArray[disinstr.special_instr.RS];
+ }
+ else if (opcode == 0x01L) {
+
+ /*
+ * For BCOND opcode, RT values 0x00 - 0x03, 0x10 - 0x13
+ * are defined as conditional jumps. A 16-bit relative
+ * offset is taken if:
+ *
+ * (RT is even and (RS) < 0 (0x00 = BLTZ, 0x02 = BLTZL,
+ * 0x10 = BLTZAL, 0x12 = BLTZALL)
+ * OR
+ * RT is odd and (RS) >= 0 (0x01 = BGEZ, 0x03 = BGEZL
+ * 0x11 = BGEZAL, 0x13 = BGEZALL))
+ * AND
+ * (RT is 0x00 to 0x03 (BLTZ BGEZ BLTZL BGEZL non-linking)
+ * OR
+ * fStep is FALSE (linking and not stepping over))
+ */
+
+ if (((disinstr.immed_instr.RT & ~0x13) == 0x00) &&
+ (((LONGLONG)regArray[disinstr.immed_instr.RS] >= 0) ==
+ (BOOL)(disinstr.immed_instr.RT & 0x01)) &&
+ (((disinstr.immed_instr.RT & 0x10) == 0x00) || !fStep))
+ returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2)
+ + firaddr.addr.off + sizeof(ULONG);
+ }
+
+ else if ((opcode & ~0x01L) == 0x02) {
+ /*
+ * J and JAL opcodes (0x02 and 0x03). Target is
+ * 26-bit absolute offset using high four bits of the
+ * instruction location. Return target if J opcode or
+ * not stepping over JAL.
+ */
+
+ if (opcode == 0x02 || !fStep)
+ returnvalue = (disinstr.jump_instr.Target << 2)
+ + (firaddr.addr.off & 0xf0000000);
+ }
+
+ else if ((opcode & ~0x11L) == 0x04) {
+ /* BEQ, BNE, BEQL, BNEL opcodes (0x04, 0x05, 0x14, 0x15).
+ * Target is 16-bit relative offset to next instruction.
+ * Return target if (BEQ or BEQL) and (RS) == (RT),
+ * or (BNE or BNEL) and (RS) != (RT).
+ */
+
+ if ((BOOL)(opcode & 0x01) ==
+ (BOOL)(regArray[disinstr.immed_instr.RS] !=
+ regArray[disinstr.immed_instr.RT]))
+ returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2)
+ + firaddr.addr.off + sizeof(ULONG);
+ }
+ else if ((opcode & ~0x11L) == 0x06) {
+ /* BLEZ, BGTZ, BLEZL, BGTZL opcodes (0x06, 0x07, 0x16, 0x17).
+ * Target is 16-bit relative offset to next instruction.
+ * Return target if (BLEZ or BLEZL) and (RS) <= 0,
+ * or (BGTZ or BGTZL) and (RS) > 0.
+ */
+ if ((BOOL)(opcode & 0x01) ==
+ (BOOL)((LONGLONG)regArray[disinstr.immed_instr.RS] > 0))
+ returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2)
+ + firaddr.addr.off + sizeof(ULONG);
+ }
+ else if (opcode == 0x11L
+ && (disinstr.immed_instr.RS & ~0x04L) == 0x08L
+ && (disinstr.immed_instr.RT & ~0x03L) == 0x00L) {
+
+ /* COP1 opcode (0x11) with (RS) == 0x08 or (RS) == 0x0c and
+ * (RT) == 0x00 to 0x03, producing BC1F, BC1T, BC1FL, BC1TL
+ * instructions. Return target if (BC1F or BC1FL) and floating
+ * point condition is FALSE or if (BC1T or BC1TL) and condition TRUE.
+ *
+ * NOTENOTE - JLS -- I don't know that this is correct. rs = 0x3
+ * will also use CP3
+ */
+
+// if ((disinstr.immed_instr.RT & 0x01) == GetRegFlagValue(FLAGFPC))
+ if ((disinstr.immed_instr.RT & 0x01) == ((hthd->context.XFsr>>23)&1)) {
+ returnvalue = ((LONG)(SHORT)disinstr.immed_instr.Value << 2)
+ + firaddr.addr.off + sizeof(ULONG);
+ }
+ }
+ else {
+ returnvalue -= sizeof(ULONG); /* remove delay slot */
+ }
+
+ return returnvalue;
+} /* GetNextOffset() */
+
+
+
+XOSD
+SetupFunctionCall(
+ LPEXECUTE_OBJECT_DM lpeo,
+ LPEXECUTE_STRUCT lpes
+)
+{
+ /*
+ * Can only execute functions on the current stopped thread. Therefore
+ * assert that the current thread is stopped.
+ */
+
+ assert(lpeo->hthd->tstate & ts_stopped);
+ if (!(lpeo->hthd->tstate & ts_stopped)) {
+#ifdef OSDEBUG4
+ return xosdBadThread;
+#else
+ return xosdInvalidThread;
+#endif
+ }
+
+ /*
+ * Now get the current stack offset.
+ */
+
+ lpeo->addrStack.addr.off = (DWORD)lpeo->hthd->context.XIntSp;
+
+ /*
+ * Now place the return address correctly
+ */
+
+ lpeo->hthd->context.XFir = (LONG)lpeo->addrStart.addr.off;
+ lpeo->hthd->context.XIntRa = (LONG)lpeo->addrStart.addr.off;
+
+ /*
+ * Set the instruction pointer to the starting addresses
+ * and write the context back out
+ */
+
+ lpeo->hthd->context.XFir = (LONG)lpeo->addrStart.addr.off;
+
+ lpeo->hthd->fContextDirty = TRUE;
+
+ return xosdNone;
+}
+
+
+
+BOOL
+CompareStacks(
+ LPEXECUTE_OBJECT_DM lpeo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to determine if the stack pointers are currect
+ for terminating function evaluation.
+
+Arguments:
+
+ lpeo - Supplies the pointer to the DM Execute Object description
+
+Return Value:
+
+ TRUE if the evaluation is to be terminated and FALSE otherwise
+
+--*/
+
+{
+
+ if (lpeo->addrStack.addr.off <= (DWORD)lpeo->hthd->context.XIntSp) {
+ return TRUE;
+ }
+
+ return FALSE;
+} /* CompareStacks() */
+
+
+
+
+#ifndef KERNEL
+VOID
+MakeThreadSuspendItselfHelper(
+ HTHDX hthd,
+ FARPROC lpSuspendThread
+ )
+{
+ //
+ // set up the args to SuspendThread
+ //
+
+ // GetCurrentThread always returns a magic cookie, safe for any thread.
+ hthd->context.XIntA0 = (DWORD)GetCurrentThread();
+ hthd->context.XIntRa = (LONG)PC(hthd);
+ PC(hthd) = (DWORD)lpSuspendThread;
+ hthd->fContextDirty = TRUE;
+}
+#endif
+
+BOOL
+ProcessFrameStackWalkNextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ PCONTEXT context,
+ LPVOID pctxPtrs
+ )
+
+{
+ return FALSE;
+}
+
+
+
+DWORD
+BranchUnassemble(
+ void *Memory,
+ ADDR *Addr,
+ BOOL *IsBranch,
+ BOOL *TargetKnown,
+ BOOL *IsCall,
+ BOOL *IsTable,
+ ADDR *Target
+ )
+{
+ ULONG OpCode;
+ INSTR *Instr;
+ UOFF32 Offset;
+ UOFF32 TargetOffset;
+
+ MIPS_InstrType itype = mips_itype_dont_care;
+
+ assert( Memory );
+ assert( IsBranch );
+ assert( TargetKnown );
+ assert( IsCall );
+ assert( Target );
+
+ Offset = GetAddrOff( *Addr );
+ TargetOffset = 0;
+ *IsBranch = FALSE;
+ *IsTable = FALSE;
+
+ Instr = (INSTR *)Memory;
+ OpCode = Instr->jump_instr.Opcode;
+
+ switch ( OpCode ) {
+
+ case 0x00L:
+ //
+ // Special
+ //
+ switch ( Instr->special_instr.Funct ) {
+
+ case 0x09L:
+ //
+ // JALR
+ //
+ *IsBranch = TRUE;
+ *IsCall = TRUE;
+ *TargetKnown = FALSE;
+ itype = mips_itype_dont_care;
+ break;
+
+ case 0x08L:
+ //
+ // JR
+ //
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = FALSE;
+ itype = mips_itype_dont_care;
+ break;
+ }
+ break;
+
+ case 0x03:
+ //
+ // JAL
+ //
+ *IsBranch = TRUE;
+ *IsCall = TRUE;
+ *TargetKnown = TRUE;
+ itype = mips_itype_Jump;
+ break;
+
+ case 0x02:
+ //
+ // J
+ //
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = TRUE;
+ itype = mips_itype_Jump;
+ break;
+
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ //
+ // BCz
+ //
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = TRUE;
+ itype = mips_itype_Imm;
+ break;
+
+ case 0x04: // BEQ
+ case 0x14: // BEQL
+ case 0x05: // BNE
+ case 0x15: // BNEL
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = TRUE;
+ itype = mips_itype_Imm;
+ break;
+
+ case 0x01:
+ //
+ // REGIMM
+ //
+ itype = mips_itype_Imm;
+
+ switch ( Instr->immed_instr.RT ) {
+
+ case 0x00: // BLTZ
+ case 0x01: // BGEZ
+ case 0x02: // BLTZL
+ case 0x03: // BGEZL
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = TRUE;
+ break;
+
+ case 0x10: // BLTZAL
+ case 0x11: // BGEZAL
+ case 0x12: // BLTZALL
+ case 0x13: // BGEZALL
+ *IsBranch = TRUE;
+ *IsCall = TRUE;
+ *TargetKnown = TRUE;
+ break;
+
+ }
+ break;
+
+ case 0x07: // BGTZ ?
+ case 0x17: // BGTZL ?
+ case 0x06: // BLEZ ?
+ case 0x16: // BLEZL ?
+ if ( Instr->immed_instr.RT == 0x00 ) {
+ *IsBranch = TRUE;
+ *IsCall = FALSE;
+ *TargetKnown = TRUE;
+ itype = mips_itype_Imm;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (*TargetKnown)
+ {
+ switch (itype)
+ {
+ default:
+ case (mips_itype_Reg):
+ case (mips_itype_dont_care):
+ break;
+
+ case (mips_itype_Imm):
+ TargetOffset
+ = (UOFF32)(LONG)((SHORT)Instr->immed_instr.Value << 2 )
+ +
+ (Offset + sizeof(DWORD));
+ break;
+
+ case (mips_itype_Jump):
+ TargetOffset = (UOFF32)(Instr->jump_instr.Target << 2 )
+ |
+ ((Offset + sizeof(DWORD)) & 0xF0000000);
+ break;
+ }
+ }
+
+ AddrInit( Target, 0, 0, TargetOffset, TRUE, TRUE, FALSE, FALSE );
+
+ return sizeof( DWORD );
+}
+/********************************************************
+
+note: "z" refers to a co-processor, with value = 0, 1, 2, or 3
+
+ instr opcode rs/rt/imm (Imm)
+ mnemonic op type mnemonic rs/rt/rd/sa/fn (Reg)
+ -------- -- ---- -------- --/--/--/--/---
+ ADD 00 Reg SPECIAL xx/xx/xx/00/20
+ ADDI 08 Imm ADDI xx/xx/xxxx
+ ADDIU 09 Imm ADDIU xx/xx/xxxx
+ ADDU 00 Reg SPECIAL xx/xx/xx/00/21
+ AND 00 Reg SPECIAL xx/xx/xx/00/24
+ ANDI 0a Imm ANDI xx/xx/xxxx
+ * BCzF 1z Imm COPz 08/00/xxxx
+ * BCzFL 1z Imm COPz 08/02/xxxx
+ * BCzT 1z Imm COPz 08/01/xxxx
+ * BCzTL 1z Imm COPz 08/03/xxxx
+ * BEQ 04 Imm BEQ xx/xx/xxxx
+ * BEQL 14 Imm BEQL xx/xx/xxxx
+ * BGEZ 01 Imm REGIMM xx/01/xxxx
+ * BGEZAL 01 Imm REGIMM xx/11/xxxx
+ * BGEZALL 01 Imm REGIMM xx/13/xxxx
+ * BGEZL 01 Imm REGIMM xx/03/xxxx
+ * BGTZ 07 Imm BGTZ xx/00/xxxx
+ * BGTZL 17 Imm BGTZL xx/00/xxxx
+ * BLEZ 06 Imm BLEZ xx/00/xxxx
+ * BLEZL 16 Imm BLEZL xx/00/xxxx
+ * BLTZ 01 Imm REGIMM xx/00/xxxx
+ * BLTZAL 01 Imm REGIMM xx/10/xxxx
+ * BLTZALL 01 Imm REGIMM xx/12/xxxx
+ * BLTZL 01 Imm REGIMM xx/02/xxxx
+ * BNE 05 Imm BNE xx/xx/xxxx
+ * BNEL 15 Imm BNEL xx/xx/xxxx
+ BREAK 00 ? SPECIAL xx/xx/xx/xx/0c
+ CACHE 2f Imm CACHE xx/xx/xxxx
+ CFCz 1z ? COPz 02/xx/xx/xx/00
+ ? COPz 1z ? COPz 1x/xx/xxxx
+ CTCz 1z Imm COPz 06/xx/xx/??/00
+ DADD 00 Reg SPECIAL xx/xx/xx/00/2c
+ DADDI 18 Imm DADDI xx/xx/xxxx
+ DADDIU 19 Imm DADDIU xx/xx/xxxx
+ DADDU 00 Reg SPECIAL xx/xx/xx/00/2d
+ DDIV 00 Reg SPECIAL xx/xx/00/00/1e
+ DDIVU 00 Reg SPECIAL xx/xx/00/00/1f
+ DIV 00 Reg SPECIAL xx/xx/00/00/1a
+ DIVU 00 Imm SPECIAL xx/xx/00/00/1b
+ DMFC0 10 Reg COP0 01/xx/xx/00/00
+ DMFC0 10 Reg COP0 05/xx/xx/00/00
+ DMULT 00 Reg SPECIAL xx/xx/00/00/1c
+ DMULTU 00 Reg SPECIAL xx/xx/00/00/1d
+ DSLL 00 Reg SPECIAL 00/xx/xx/xx/38
+ DSLLV 00 Reg SPECIAL 00/xx/xx/xx/14
+ DSLL32 00 Reg SPECIAL 00/xx/xx/xx/3c
+ DSRA 00 Reg SPECIAL 00/xx/xx/xx/3b
+ DSRAV 00 Reg SPECIAL 00/xx/xx/xx/17
+ DSRA32 00 Reg SPECIAL 00/xx/xx/xx/3f
+ DSRL 00 Reg SPECIAL 00/xx/xx/xx/3a
+ DSRLV 00 Reg SPECIAL 00/xx/xx/xx/16
+ DSRL32 00 Reg SPECIAL 00/xx/xx/xx/3e
+ DSUB 00 Reg SPECIAL xx/xx/xx/00/2e
+ DSUBU 00 Reg SPECIAL xx/xx/xx/00/2f
+ ERET 10 Reg COP0 10/00/00/00/28
+ * J 02 Jump J xxxxxxx
+ * JAL 03 Jump JAL xxxxxxx
+ * JALR 00 Reg SPECIAL xx/00/xx/00/09
+ * JR 00 Reg SPECIAL xx/00/00/00/08
+ LB 30 Imm LB xx/xx/xxxx
+ LBU 34 Imm LBU xx/xx/xxxx
+ LD 37 Imm LD xx/xx/xxxx
+ LDCz 3? Imm LDCz xx/xx/xxxx
+ LDL 1a Imm LDL xx/xx/xxxx
+ LDR 1b Imm LDR xx/xx/xxxx
+ LH 21 Imm LH xx/xx/xxxx
+ LHU 25 Imm LHU xx/xx/xxxx
+ LL 30 Imm LL xx/xx/xxxx
+ LLD 34 Imm LLD xx/xx/xxxx
+ LUI 1f Imm LUI 00/xx/xxxx
+ LW 23 Imm LW xx/xx/xxxx
+ LWCz 3z Imm LWCz xx/xx/xxxx
+ LWL 22 Imm LWL xx/xx/xxxx
+ LWR 25 Imm LWR xx/xx/xxxx
+ LWU 2f Imm LWU xx/xx/xxxx
+ MFC0 10 Reg COP0 00/xx/xx/00/00
+ MFCz 1z Reg COPz 00/xx/xx/00/00
+ MFHI 00 Reg SPECIAL 00/00/xx/00/10
+ MFLO 00 Reg SPECIAL 00/00/xx/00/12
+ MTC0 10 Reg COP0 04/xx/xx/00/00
+ MTCz 1z Reg COPz 04/xx/xx/00/00
+ MTHI 00 Reg SPECIAL xx/00/00/00/11
+ MTLO 00 Reg SPECIAL xx/00/00/00/13
+ MULT 00 Reg SPECIAL xx/xx/00/00/18
+ MULTU 00 Reg SPECIAL xx/xx/00/00/19
+ NOR 00 Reg SPECIAL xx/xx/xx/00/37
+ OR 00 Reg SPECIAL xx/xx/xx/00/35
+ ORI 0d Imm ORI xx/xx/xxxx
+ SB 28 Imm SB xx/xx/xxxx
+ SC 38 Imm SC xx/xx/xxxx
+ SCD 3c Imm SCD xx/xx/xxxx
+ SCDz 3? Imm SCDz xx/xx/xxxx
+ SDL 2c Imm SDL xx/xx/xxxx
+ SDR 2d Imm SDR xx/xx/xxxx
+ SH 29 Imm SH xx/xx/xxxx
+ SLL 00 Reg SPECIAL xx/xx/xx/xx/00
+ SLLV 00 Reg SPECIAL xx/xx/xx/xx/04
+ SLT 00 Reg SPECIAL xx/xx/xx/xx/2a
+ SLTI 0a Imm SLTI xx/xx/xxxx
+ SLTIU 0b Imm SLTIU xx/xx/xxxx
+ SLTU 00 Reg SPECIAL xx/xx/xx/xx/2b
+ SRA 00 Reg SPECIAL 00/xx/xx/xx/03
+ SRAV 00 Reg SPECIAL xx/xx/xx/00/07
+ SRL 00 Reg SPECIAL 00/xx/xx/xx/02
+ SRLV 00 Reg SPECIAL xx/xx/xx/00/06
+ SUB 00 Reg SPECIAL xx/xx/xx/00/22
+ SUBU 00 Reg SPECIAL xx/xx/xx/00/23
+ SW 2b Imm SW xx/xx/xxxx
+ SWCz 3? Imm SWCz xx/xx/xxxx
+ SWL 2a Reg SWL xx/xx/xxxx
+ SWR 2d Reg SWR xx/xx/xxxx
+ SYNC 00 Reg SPECIAL 00/00/00/00/0f
+ SYSCALL 00 Reg SPECIAL xx/xx/xx/xx/0c
+ TEQ 00 Reg SPECIAL xx/xx/xx/xx/36
+ TEQI 01 Imm REGIMM xx/0c/xxxx
+ TGE 00 Reg SPECIAL xx/xx/xx/xx/30
+ TGEI 01 Reg REGIMM xx/08/xxxx
+ TGEIU 01 Imm REGIMM xx/09/xxxx
+ TGEU 00 Reg SPECIAL xx/xx/xx/xx/31
+ TLBP 10 Reg COP0 10/00/00/00/08
+ TLBR 10 Reg COP0 10/00/00/00/01
+ TLBWI 10 Reg COP0 10/00/00/00/02
+ TLBWR 10 Reg COP0 10/00/00/00/06
+ TLT 00 Reg SPECIAL xx/xx/xx/xx/32
+ TLTI 01 Imm REGIMM xx/0a/xxxx
+ TLTIU 01 Imm REGIMM xx/0b/xxxx
+ TLTU 00 Reg SPECIAL xx/xx/xx/xx/33
+ TNE 00 Reg SPECIAL xx/xx/xx/xx/3c
+ TNEI 01 Imm REGIMM xx/0e/xxxx
+ XOR 00 Reg SPECIAL xx/xx/xx/00/26
+ XORI 0c Imm XORI xx/xx/xxxx
+
+
+
+********************************************************/
+
+BOOL
+DecodeSingleStepEvent(
+ HTHDX hthd,
+ DEBUG_EVENT *de,
+ PDWORD eventCode,
+ PDWORD subClass
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hthd - Supplies thread that has a single step exception pending
+
+ de - Supplies the DEBUG_EVENT structure for the exception
+
+ eventCode - Returns the remapped debug event id
+
+ subClass - Returns the remapped subClass id
+
+
+Return Value:
+
+ TRUE if event was a real single step or was successfully mapped
+ to a breakpoint. FALSE if a register breakpoint occurred which was
+ not expected.
+
+--*/
+{
+ return FALSE;
+}
+
+BOOL
+CoerceContext64To32(
+ PCONTEXT pContext
+ )
+{
+ PULONGLONG Src;
+ PULONG Dst;
+ ULONG Index;
+
+ //
+ // If the target system is running a kernel with 64-bit addressing
+ // enabled in user mode, then coerce the 64-bit context to 32-bits.
+ //
+
+ DPRINT(1, ("ConvertContext64To32: ContextFlags == %08x\n", pContext->ContextFlags));
+ if ((pContext->ContextFlags & CONTEXT_EXTENDED_INTEGER) == CONTEXT_EXTENDED_INTEGER) {
+ DPRINT(1, ("ConvertContext64To32: Ra == %016Lx\n", pContext->XIntRa));
+ Src = &pContext->XIntZero;
+ Dst = &pContext->IntZero;
+ for (Index = 0; Index < 32; Index += 1) {
+ *Dst++ = (ULONG)*Src++;
+ }
+ pContext->ContextFlags &= ~CONTEXT_EXTENDED_INTEGER;
+ pContext->ContextFlags |= CONTEXT_INTEGER;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL
+CoerceContext32To64 (
+ PCONTEXT pContext
+ )
+{
+ PULONG Src;
+ PULONGLONG Dst;
+ ULONG Index;
+
+ //
+ // If the target system is running a kernel with 64-bit addressing
+ // enabled in user mode, then coerce the 32-bit context to 64-bits.
+ //
+
+ DPRINT(1, ("ConvertContext32To64: ContextFlags == %08x\n", pContext->ContextFlags));
+ if ((pContext->ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
+ DPRINT(1, ("ConvertContext32To64: Ra == %08x\n", pContext->IntRa));
+ Dst = &pContext->XIntZero;
+ Src = &pContext->IntZero;
+ for (Index = 0; Index < 32; Index += 1) {
+ *Dst++ = (LONG)*Src++;
+ }
+ pContext->ContextFlags |= CONTEXT_EXTENDED_INTEGER;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/private/windbg/newdm/p_alpha/dmkd.rc b/private/windbg/newdm/p_alpha/dmkd.rc
new file mode 100644
index 000000000..50b4de5e3
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/dmkd.rc
@@ -0,0 +1,3 @@
+#include "..\dmkd.rc"
+
+ \ No newline at end of file
diff --git a/private/windbg/newdm/p_alpha/dmkdalp.def b/private/windbg/newdm/p_alpha/dmkdalp.def
new file mode 100644
index 000000000..adc5bc1cb
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/dmkdalp.def
@@ -0,0 +1,8 @@
+LIBRARY dmkdalp
+
+EXPORTS
+ DmDllInit PRIVATE
+ DMInit PRIVATE
+ DMFunc PRIVATE
+ DBGVersionCheck PRIVATE
+
diff --git a/private/windbg/newdm/p_alpha/makefile b/private/windbg/newdm/p_alpha/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/newdm/p_alpha/makefile.inc b/private/windbg/newdm/p_alpha/makefile.inc
new file mode 100644
index 000000000..291018e08
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/makefile.inc
@@ -0,0 +1,27 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Wesley Witt (wesw) 10-Aug-1993
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
+
+OBJECTS = $(OBJECTS) $(BASEDIR)\private\ntos\rtl\user\obj\$(TARGET_DIRECTORY)\splay.obj
diff --git a/private/windbg/newdm/p_alpha/ntdis.h b/private/windbg/newdm/p_alpha/ntdis.h
new file mode 100644
index 000000000..c2dc0ded1
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/ntdis.h
@@ -0,0 +1,190 @@
+
+#ifndef _NTDIS_
+#define _NTDIS_
+
+//
+// Bit manipulations for Alpha instructions
+//
+
+#define SHFT_OPCODE 26
+#define SHFT_RA 21
+#define SHFT_RB 16
+#define SHFT_JMP_FNC 14
+#define SHFT_OP_FNC 5
+#define SHFT_RBV_TYPE 12
+#define SHFT_LIT 13
+#define SHFT_FP_FNC 5
+
+#define WIDTH_OPCODE 6
+#define WIDTH_REG 5
+#define WIDTH_MEM_DISP 16
+#define WIDTH_HINT 14
+#define WIDTH_JMP_FNC 2
+#define WIDTH_BR_DISP 21
+#define WIDTH_OP_FNC 7
+#define WIDTH_LIT 8
+#define WIDTH_FP_FNC 11
+#define WIDTH_PAL_FNC 26
+
+#define BITS_OPCODE ~(-1 << WIDTH_OPCODE)
+#define BITS_REG ~(-1 << WIDTH_REG)
+#define BITS_MEM_DISP ~(-1 << WIDTH_MEM_DISP)
+#define BITS_HINT ~(-1 << WIDTH_HINT)
+#define BITS_JMP_FNC ~(-1 << WIDTH_JMP_FNC)
+#define BITS_BR_DISP ~(-1 << WIDTH_BR_DISP)
+#define BITS_OP_FNC ~(-1 << WIDTH_OP_FNC)
+#define BITS_LIT ~(-1 << WIDTH_LIT)
+#define BITS_FP_FNC ~(-1 << WIDTH_FP_FNC)
+#define BITS_PAL_FNC ~(-1 << WIDTH_PAL_FNC)
+
+#define OPCODE(a) ((BITS_OPCODE & (a)) << SHFT_OPCODE)
+#define REG_A(a) ((BITS_REG & (a)) << SHFT_RA)
+#define REG_B(a) ((BITS_REG & (a)) << SHFT_RB)
+#define REG_C(a) (BITS_REG & (a))
+#define MEM_DISP(a) (BITS_MEM_DISP & (a))
+#define HINT(a) (BITS_HINT & (a))
+#define JMP_FNC(a) ((BITS_JMP_FNC & (a)) << SHFT_JMP_FNC)
+#define BR_DISP(a) (BITS_BR_DISP & (a))
+#define OP_FNC(a) ((BITS_OP_FNC & (a)) << SHFT_OP_FNC)
+#define RBV_TYPE(a) ((1 & (a)) << SHFT_RBV_TYPE)
+#define LIT(a) ((BITS_LIT & (a)) << SHFT_LIT)
+#define FP_FNC(a) ((BITS_FP_FNC & (a)) << SHFT_FP_FNC)
+#define PAL_FNC(a) (BITS_PAL_FNC & (a))
+
+#define MSK_OPCODE OPCODE(BITS_OPCODE)
+#define MSK_RA GET_RA(BITS_REG)
+#define MSK_RB REG_B(BITS_REG)
+#define MSK_RC REG_C(BITS_REG)
+#define MSK_MEM_DISP DISP(BITS_MEM_DISP)
+#define MSK_HINT HINT(BITS_HINT)
+#define MSK_JMP_FNC JMP_FNC(BITS_JMP_FNC)
+#define MSK_BR_DISP BR_DISP(BITS_BR_DISP)
+#define MSK_RBV_TYPE RBV_TYPE(1)
+#define MSK_LIT LIT(BITS_LIT)
+#define MSK_FP_FNC FP_FNC(BITS_FP_FNC)
+#define MSK_PAL_FNC PAL_FNC(BITS_PAL_FNC)
+
+#define EXTR_OPCODE(a) (((a) & MSK_OPCODE) >> SHFT_OPCODE)
+#define EXTR_RA(a) (((a) & MSK_RA) >> SHFT_RA)
+#define EXTR_RB(a) (((a) & MSK_RB) >> SHFT_RA)
+#define EXTR_RC(a) ((a) & MSK_RC)
+#define EXTR_MEM_DISP(a) ((a) & MSK_MEM_DISP)
+#define EXTR_HINT(a) ((a) & MSK_HINT)
+#define EXTR_JMP_FNC(a) (((a) & MSK_JMP_FNC) >> SHFT_JMP_FNC)
+#define EXTR_BR_DISP(a) ((a) & MSK_BR_DISP)
+#define EXTR_RBV_TYPE(a) (((a) & MSK_RBV_TYPE) >> SHFT_RBV_TYPE)
+#define EXTR_LIT(a) (((a) & MSK_LIT) >> SHFT_LIT)
+#define EXTR_FP_FNC(a) (((a) & MSK_FP_FNC) >> SHFT_FP_FNC)
+#define EXTR_PAL_FNC(a) ((a) & MSK_PAL_FNC)
+
+
+
+//
+// Bit manipulations for EV4 PAL mode instructions
+//
+
+#define SHFT_EV4_IBOX 5
+#define SHFT_EV4_ABOX 6
+#define SHFT_EV4_PALTEMP 7
+#define SHFT_EV4_QWORD 12
+#define SHFT_EV4_RWCHECK 13
+#define SHFT_EV4_ALT 14
+#define SHFT_EV4_PHYSICAL 15
+
+#define WIDTH_EV4_INDEX 5
+#define WIDTH_EV4_IBOX 1
+#define WIDTH_EV4_ABOX 1
+#define WIDTH_EV4_PALTEMP 1
+#define WIDTH_EV4_DISP 12
+#define WIDTH_EV4_QWORD 1
+#define WIDTH_EV4_RWCHECK 1
+#define WIDTH_EV4_ALT 1
+#define WIDTH_EV4_PHYSICAL 1
+
+#define BITS_EV4_INDEX ~(-1 << WIDTH_EV4_INDEX)
+#define BITS_EV4_IBOX ~(-1 << WIDTH_EV4_IBOX)
+#define BITS_EV4_ABOX ~(-1 << WIDTH_EV4_ABOX)
+#define BITS_EV4_PALTEMP ~(-1 << WIDTH_EV4_PALTEMP)
+#define BITS_EV4_DISP ~(-1 << WIDTH_EV4_DISP)
+#define BITS_EV4_QWORD ~(-1 << WIDTH_EV4_QWORD)
+#define BITS_EV4_RWCHECK ~(-1 << WIDTH_EV4_RWCHECK)
+#define BITS_EV4_ALT ~(-1 << WIDTH_EV4_ALT)
+#define BITS_EV4_PHYSICAL ~(-1 << WIDTH_EV4_PHYSICAL)
+
+#define EV4_INDEX(a) (BITS_EV4_INDEX & (a))
+#define EV4_IBOX(a) ((BITS_EV4_IBOX & (a)) << SHFT_EV4_IBOX)
+#define EV4_ABOX(a) ((BITS_EV4_ABOX & (a)) << SHFT_EV4_ABOX)
+#define EV4_PALTEMP(a) ((BITS_EV4_PALTEMP & (a)) << SHFT_EV4_PALTEMP)
+#define EV4_DISP(a) (BITS_EV4_DISP & (a))
+#define EV4_QWORD(a) ((BITS_EV4_QWORD & (a)) << SHFT_EV4_QWORD)
+#define EV4_RWCHECK(a) ((BITS_EV4_RWCHECK & (a)) << SHFT_EV4_RWCHECK)
+#define EV4_ALT(a) ((BITS_EV4_ALT & (a)) << SHFT_EV4_ALT)
+#define EV4_PHYSICAL(a) ((BITS_EV4_PHYSICAL & (a)) << SHFT_EV4_PHYSICAL)
+
+#define MSK_EV4_INDEX EV4_INDEX(BITS_EV4_INDEX)
+#define MSK_EV4_IBOX EV4_IBOX(BITS_EV4_IBOX)
+#define MSK_EV4_ABOX EV4_ABOX(BITS_EV4_ABOX)
+#define MSK_EV4_PALTEMP EV4_PALTEMP(BITS_EV4_PALTEMP)
+#define MSK_EV4_PR (MSK_EV4_INDEX | MSK_EV4_IBOX | MSK_EV4_ABOX | MSK_EV4_PALTEMP)
+#define MSK_EV4_DISP EV4_DISP(BITS_EV4_DISP)
+#define MSK_EV4_QWORD EV4_QWORD(BITS_EV4_QWORD)
+#define MSK_EV4_RWCHECK EV4_RWCHECK(BITS_EV4_RWCHECK)
+#define MSK_EV4_ALT EV4_ALT(BITS_EV4_ALT)
+#define MSK_EV4_PHYSICAL EV4_PHYSICAL(BITS_EV4_PHYSICAL)
+
+#define EXTR_EV4_INDEX(a) (MSK_EV4_INDEX & (a))
+#define EXTR_EV4_IBOX(a) ((MSK_EV4_IBOX & (a)) >> SHFT_EV4_IBOX)
+#define EXTR_EV4_ABOX(a) ((MSK_EV4_ABOX & (a)) >> SHFT_EV4_ABOX)
+#define EXTR_EV4_PALTEMP(a) ((MSK_EV4_PALTEMP & (a)) >> SHFT_EV4_PALTEMP)
+#define EXTR_EV4_DISP(a) (MSK_EV4_DISP & (a))
+#define EXTR_EV4_QWORD(a) ((MSK_EV4_QWORD & (a)) >> SHFT_EV4_QWORD)
+#define EXTR_EV4_RWCHECK(a) ((MSK_EV4_RWCHECK & (a)) >> SHFT_EV4_RWCHECK)
+#define EXTR_EV4_ALT(a) ((MSK_EV4_ALT & (a)) >> SHFT_EV4_ALT)
+#define EXTR_EV4_PHYSICAL(a) ((MSK_EV4_PHYSICAL & (a)) >> SHFT_EV4_PHYSICAL)
+
+#define EV4_TB_TAG (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(0))
+#define EV4_ITB_PTE (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(1))
+#define EV4_ICCSR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(2))
+#define EV4_ITM_PTE_TEMP (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(3))
+#define EV4_EXC_ADDR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(4))
+#define EV4_SL_RCV (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(5))
+#define EV4_ITBZAP (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(6))
+#define EV4_ITBASM (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(7))
+#define EV4_ITBIS (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(8))
+#define EV4_PS (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(9))
+#define EV4_EXC_SUM (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(10))
+#define EV4_PAL_BASE (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(11))
+#define EV4_HIRR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(12))
+#define EV4_SIRR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(13))
+#define EV4_ASTRR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(14))
+#define EV4_HIER (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(16))
+#define EV4_SIER (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(17))
+#define EV4_ASTER (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(18))
+#define EV4_SL_CLR (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(19))
+#define EV4_SL_XMIT (EV4_PALTEMP(0) | EV4_ABOX(0) | EV4_IBOX(1) | EV4_INDEX(22))
+#define EV4_DTB_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(0))
+#define EV4_DTB_PTE (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(2))
+#define EV4_DTB_PTE_TEMP (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(3))
+#define EV4_MMCSR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(4))
+#define EV4_VA (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(5))
+#define EV4_DTBZAP (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(6))
+#define EV4_DTASM (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(7))
+#define EV4_DTBIS (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(8))
+#define EV4_BIU_ADDR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(9))
+#define EV4_BIU_STAT (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(10))
+#define EV4_DC_ADDR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(11))
+#define EV4_DC_STAT (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(12))
+#define EV4_FILL_ADDR (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(13))
+#define EV4_ABOX_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(14))
+#define EV4_ALT_MODE (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(15))
+#define EV4_CC (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(16))
+#define EV4_CC_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(17))
+#define EV4_BIU_CTL (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(18))
+#define EV4_FILL_SYNDROME (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(19))
+#define EV4_BC_TAG (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(20))
+#define EV4_FLUSH_IC (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(21))
+#define EV4_FLUSH_IC_ASM (EV4_PALTEMP(0) | EV4_ABOX(1) | EV4_IBOX(0) | EV4_INDEX(23))
+#define EV4_PAL_TEMP(x) (EV4_PALTEMP(1) | EV4_ABOX(0) | EV4_IBOX(0) | EV4_INDEX(x))
+
+#endif // _NTDIS_
+
diff --git a/private/windbg/newdm/p_alpha/precomp.h b/private/windbg/newdm/p_alpha/precomp.h
new file mode 100644
index 000000000..2b764ee4a
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/precomp.h
@@ -0,0 +1,55 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+// an astonishingly stupid warning
+#pragma warning(disable:4124)
+
+#include "biavst.h"
+#include <stdio.h>
+#include <memory.h>
+#include <malloc.h>
+#include <process.h>
+#include <stdlib.h>
+#include <string.h>
+#include <crt\io.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <imagehlp.h>
+#include "types.h"
+#include "cvtypes.hxx"
+#include "defs.h"
+#include "ll.h"
+#include "shapi.hxx"
+#include "od.h"
+#include "tl.h"
+#include "emdm.h"
+#include "debug.h"
+#include "dm.h"
+#include "bp.h"
+#include "funccall.h"
+#include "dbgver.h"
+#include "lbhpt.h"
+#include "mm.h"
+#include <windef.h>
+#define NOEXTAPI
+#include <wdbgexts.h>
+#include "kd.h"
diff --git a/private/windbg/newdm/p_alpha/sources b/private/windbg/newdm/p_alpha/sources
new file mode 100644
index 000000000..9495cf5fd
--- /dev/null
+++ b/private/windbg/newdm/p_alpha/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=dmkd
+
+TARGETNAME=dmkdalp
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+DLLENTRY=DllInit
+
+SOURCES=\
+ ..\kdapi.c \
+ ..\bp.c \
+ ..\cache.c \
+ ..\com.c \
+ ..\dmx32.c \
+ ..\event.c \
+ ..\funccall.c \
+ ..\packet.c \
+ ..\procem.c \
+ ..\support.c \
+ ..\step.c \
+ ..\util.c \
+ ..\walk.c \
+ ..\kdwow.c \
+ ..\alpmach.c \
+ ..\dmkd.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include; \
+ ..\..\osdebug; \
+ ..; \
+ $(BASEDIR)\private\ntos\inc;\
+ $(BASEDIR)\private\ntos\io
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_ALPHA -DKERNEL -DDWORDLONG=ULONGLONG
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\crashlib.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\vdmdbg.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib \
+ ..\..\em\p_alpha\obj\*\emalp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/newdm/p_i386/dmkd.rc b/private/windbg/newdm/p_i386/dmkd.rc
new file mode 100644
index 000000000..50b4de5e3
--- /dev/null
+++ b/private/windbg/newdm/p_i386/dmkd.rc
@@ -0,0 +1,3 @@
+#include "..\dmkd.rc"
+
+ \ No newline at end of file
diff --git a/private/windbg/newdm/p_i386/dmkdx86.def b/private/windbg/newdm/p_i386/dmkdx86.def
new file mode 100644
index 000000000..b3eecb7c6
--- /dev/null
+++ b/private/windbg/newdm/p_i386/dmkdx86.def
@@ -0,0 +1,8 @@
+LIBRARY dmkdx86
+
+EXPORTS
+ DmDllInit PRIVATE
+ DMInit PRIVATE
+ DMFunc PRIVATE
+ DBGVersionCheck PRIVATE
+
diff --git a/private/windbg/newdm/p_i386/makefile b/private/windbg/newdm/p_i386/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/newdm/p_i386/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/newdm/p_i386/makefile.inc b/private/windbg/newdm/p_i386/makefile.inc
new file mode 100644
index 000000000..08bf0b0b2
--- /dev/null
+++ b/private/windbg/newdm/p_i386/makefile.inc
@@ -0,0 +1,29 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
+
+OBJECTS = $(OBJECTS) $(BASEDIR)\private\ntos\rtl\user\obj\$(TARGET_DIRECTORY)\splay.obj
+
+obj\i386\d3dm.obj: ..\..\em\p_i386\d3.c
diff --git a/private/windbg/newdm/p_i386/precomp.h b/private/windbg/newdm/p_i386/precomp.h
new file mode 100644
index 000000000..685d95665
--- /dev/null
+++ b/private/windbg/newdm/p_i386/precomp.h
@@ -0,0 +1,62 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+// an astonishingly stupid warning
+#pragma warning(disable:4124)
+
+#include "biavst.h"
+#define _CTXPTRS_H_
+
+#include <windef.h>
+#include <stdio.h>
+#include <memory.h>
+#include <malloc.h>
+#include <process.h>
+#include <stdlib.h>
+#include <string.h>
+#include <crt\io.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <imagehlp.h>
+
+#define NOEXTAPI
+#include <wdbgexts.h>
+
+#include "types.h"
+#include "cvtypes.hxx"
+#include "defs.h"
+#include "od.h"
+#include "ll.h"
+#include "tl.h"
+#include "mm.h"
+#include "lbhpt.h"
+#include "shapi.hxx"
+
+#include "dbgver.h"
+#include "emdm.h"
+
+#include "dm.h"
+#include "bp.h"
+#include "kd.h"
+#include "debug.h"
+#include "funccall.h"
+
diff --git a/private/windbg/newdm/p_i386/sources b/private/windbg/newdm/p_i386/sources
new file mode 100644
index 000000000..ece1e43d8
--- /dev/null
+++ b/private/windbg/newdm/p_i386/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=dmkd
+
+TARGETNAME=dmkdx86
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+DLLENTRY=DllInit
+
+SOURCES=\
+ ..\kdapi.c \
+ ..\bp.c \
+ ..\cache.c \
+ ..\com.c \
+ ..\dmx32.c \
+ ..\event.c \
+ ..\funccall.c \
+ ..\packet.c \
+ ..\procem.c \
+ ..\support.c \
+ ..\step.c \
+ ..\util.c \
+ ..\walk.c \
+ ..\kdwow.c \
+ ..\i386mach.c \
+ ..\i386d3dm.c \
+ ..\dmkd.rc
+
+UMTYPE=windows
+
+INCLUDES=\
+ ..\..\osdebug\include; \
+ ..\..\osdebug; \
+ ..; \
+ $(BASEDIR)\private\ntos\inc;\
+ $(BASEDIR)\private\ntos\io
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_i386 -DKERNEL -DDWORDLONG=ULONGLONG
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\crashlib.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\vdmdbg.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/newdm/p_mips/dmkd.rc b/private/windbg/newdm/p_mips/dmkd.rc
new file mode 100644
index 000000000..50b4de5e3
--- /dev/null
+++ b/private/windbg/newdm/p_mips/dmkd.rc
@@ -0,0 +1,3 @@
+#include "..\dmkd.rc"
+
+ \ No newline at end of file
diff --git a/private/windbg/newdm/p_mips/dmkdmip.def b/private/windbg/newdm/p_mips/dmkdmip.def
new file mode 100644
index 000000000..c3a166603
--- /dev/null
+++ b/private/windbg/newdm/p_mips/dmkdmip.def
@@ -0,0 +1,8 @@
+LIBRARY dmkdmip
+
+EXPORTS
+ DmDllInit PRIVATE
+ DMInit PRIVATE
+ DMFunc PRIVATE
+ DBGVersionCheck PRIVATE
+
diff --git a/private/windbg/newdm/p_mips/makefile b/private/windbg/newdm/p_mips/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/newdm/p_mips/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/newdm/p_mips/makefile.inc b/private/windbg/newdm/p_mips/makefile.inc
new file mode 100644
index 000000000..291018e08
--- /dev/null
+++ b/private/windbg/newdm/p_mips/makefile.inc
@@ -0,0 +1,27 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Wesley Witt (wesw) 10-Aug-1993
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
+
+OBJECTS = $(OBJECTS) $(BASEDIR)\private\ntos\rtl\user\obj\$(TARGET_DIRECTORY)\splay.obj
diff --git a/private/windbg/newdm/p_mips/precomp.h b/private/windbg/newdm/p_mips/precomp.h
new file mode 100644
index 000000000..76609762e
--- /dev/null
+++ b/private/windbg/newdm/p_mips/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+// an astonishingly stupid warning
+#pragma warning(disable:4124)
+
+#include "biavst.h"
+#define _CTXPTRS_H_
+#include <stdio.h>
+#include <memory.h>
+#include <malloc.h>
+#include <process.h>
+#include <stdlib.h>
+#include <string.h>
+#include <crt\io.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <imagehlp.h>
+#include "types.h"
+#include "cvtypes.hxx"
+#include "defs.h"
+#include "ll.h"
+#include "shapi.hxx"
+#include "od.h"
+#include "tl.h"
+#include "emdm.h"
+#include "debug.h"
+#include "dm.h"
+#include "bp.h"
+#include "funccall.h"
+#include "dbgver.h"
+#include "lbhpt.h"
+#include "mm.h"
+#include <windef.h>
+#define NOEXTAPI
+#include <wdbgexts.h>
+#include "kd.h"
diff --git a/private/windbg/newdm/p_mips/sources b/private/windbg/newdm/p_mips/sources
new file mode 100644
index 000000000..ddaaa5227
--- /dev/null
+++ b/private/windbg/newdm/p_mips/sources
@@ -0,0 +1,75 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=dmkd
+
+TARGETNAME=dmkdmip
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+DLLENTRY=DllInit
+
+SOURCES=\
+ ..\kdapi.c \
+ ..\bp.c \
+ ..\cache.c \
+ ..\com.c \
+ ..\dmx32.c \
+ ..\event.c \
+ ..\funccall.c \
+ ..\packet.c \
+ ..\procem.c \
+ ..\support.c \
+ ..\step.c \
+ ..\util.c \
+ ..\walk.c \
+ ..\kdwow.c \
+ ..\mipsmach.c \
+ ..\dmkd.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include; \
+ ..\..\osdebug; \
+ ..; \
+ $(BASEDIR)\private\ntos\inc;\
+ $(BASEDIR)\private\ntos\io
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_MIPS -DKERNEL -DDWORDLONG=ULONGLONG
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\crashlib.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\vdmdbg.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/newdm/p_ppc/dmkd.rc b/private/windbg/newdm/p_ppc/dmkd.rc
new file mode 100644
index 000000000..50b4de5e3
--- /dev/null
+++ b/private/windbg/newdm/p_ppc/dmkd.rc
@@ -0,0 +1,3 @@
+#include "..\dmkd.rc"
+
+ \ No newline at end of file
diff --git a/private/windbg/newdm/p_ppc/dmkdppc.def b/private/windbg/newdm/p_ppc/dmkdppc.def
new file mode 100644
index 000000000..5a7544477
--- /dev/null
+++ b/private/windbg/newdm/p_ppc/dmkdppc.def
@@ -0,0 +1,8 @@
+LIBRARY dmkdppc
+
+EXPORTS
+ DmDllInit PRIVATE
+ DMInit PRIVATE
+ DMFunc PRIVATE
+ DBGVersionCheck PRIVATE
+
diff --git a/private/windbg/newdm/p_ppc/makefile b/private/windbg/newdm/p_ppc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/newdm/p_ppc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/newdm/p_ppc/makefile.inc b/private/windbg/newdm/p_ppc/makefile.inc
new file mode 100644
index 000000000..13e4146d1
--- /dev/null
+++ b/private/windbg/newdm/p_ppc/makefile.inc
@@ -0,0 +1,28 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Wesley Witt (wesw) 10-Aug-1993
+
+
+!ENDIF
+
+SRCDIR=..
+
+!INCLUDE $(SRCDIR)\common.inc
+
+OBJECTS = $(OBJECTS) $(BASEDIR)\private\ntos\rtl\user\obj\$(TARGET_DIRECTORY)\splay.obj
+ \ No newline at end of file
diff --git a/private/windbg/newdm/p_ppc/precomp.h b/private/windbg/newdm/p_ppc/precomp.h
new file mode 100644
index 000000000..76609762e
--- /dev/null
+++ b/private/windbg/newdm/p_ppc/precomp.h
@@ -0,0 +1,56 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+// an astonishingly stupid warning
+#pragma warning(disable:4124)
+
+#include "biavst.h"
+#define _CTXPTRS_H_
+#include <stdio.h>
+#include <memory.h>
+#include <malloc.h>
+#include <process.h>
+#include <stdlib.h>
+#include <string.h>
+#include <crt\io.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <imagehlp.h>
+#include "types.h"
+#include "cvtypes.hxx"
+#include "defs.h"
+#include "ll.h"
+#include "shapi.hxx"
+#include "od.h"
+#include "tl.h"
+#include "emdm.h"
+#include "debug.h"
+#include "dm.h"
+#include "bp.h"
+#include "funccall.h"
+#include "dbgver.h"
+#include "lbhpt.h"
+#include "mm.h"
+#include <windef.h>
+#define NOEXTAPI
+#include <wdbgexts.h>
+#include "kd.h"
diff --git a/private/windbg/newdm/p_ppc/sources b/private/windbg/newdm/p_ppc/sources
new file mode 100644
index 000000000..a2387234b
--- /dev/null
+++ b/private/windbg/newdm/p_ppc/sources
@@ -0,0 +1,75 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=dmkd
+
+TARGETNAME=dmkdppc
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+DLLENTRY=DllInit
+
+SOURCES= \
+ ..\kdapi.c \
+ ..\bp.c \
+ ..\cache.c \
+ ..\com.c \
+ ..\dmx32.c \
+ ..\event.c \
+ ..\funccall.c \
+ ..\packet.c \
+ ..\procem.c \
+ ..\support.c \
+ ..\step.c \
+ ..\util.c \
+ ..\walk.c \
+ ..\kdwow.c \
+ ..\ppcmach.c \
+ ..\dmkd.rc
+
+UMTYPE=windows
+
+INCLUDES= \
+ ..\..\osdebug\include; \
+ ..\..\osdebug; \
+ ..; \
+ $(BASEDIR)\private\ntos\inc;\
+ $(BASEDIR)\private\ntos\io
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DTARGET_PPC -DKERNEL -DDWORDLONG=ULONGLONG
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\crashlib.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\vdmdbg.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/newdm/packet.c b/private/windbg/newdm/packet.c
new file mode 100644
index 000000000..521437c5e
--- /dev/null
+++ b/private/windbg/newdm/packet.c
@@ -0,0 +1,1129 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ packet.c
+
+Abstract:
+
+ This module implements the packet io APIs
+
+Author:
+
+ Wesley Witt (wesw) 8-Mar-1992
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+VOID
+TRACE_PRINT(
+ PCHAR szFormat,
+ ...
+ );
+
+jmp_buf JumpBuffer;
+BOOL DmKdBreakIn = FALSE;
+BOOL KdResync = FALSE;
+BOOL InitialBreak = FALSE;
+ULONG MaxRetries = 5;
+
+ULONG DmKdPacketExpected = INITIAL_PACKET_ID;
+ULONG DmKdNextPacketToSend = INITIAL_PACKET_ID;
+BOOL ValidUnaccessedPacket = FALSE;
+UCHAR DmKdPacket[PACKET_MAX_SIZE];
+KD_PACKET PacketHeader;
+UCHAR DmKdBreakinPacket[1] = { BREAKIN_PACKET_BYTE };
+UCHAR DmKdPacketTrailingByte[1] = { PACKET_TRAILING_BYTE };
+UCHAR StringBuffer[512];
+
+extern HANDLE DmKdComPort;
+extern BOOL ApiIsAllowed;
+extern DWORD PollThreadId;
+extern CRITICAL_SECTION csPacket;
+extern BOOL fPacketTrace;
+
+
+VOID
+DmKdHandlePromptString(
+ PDBGKD_DEBUG_IO IoMessage
+ )
+{
+ DEBUG_EVENT de;
+ ULONG len = min( sizeof(StringBuffer)-1,
+ IoMessage->u.GetString.LengthOfPromptString );
+ memcpy( StringBuffer,
+ (PUCHAR)(IoMessage+1),
+ len );
+ StringBuffer[len]='\0';
+
+ de.dwDebugEventCode = INPUT_DEBUG_STRING_EVENT;
+ de.dwProcessId = 1;
+ de.dwThreadId = 1;
+ de.u.DebugString.nDebugStringLength = (WORD)len;
+ de.u.DebugString.fUnicode = FALSE;
+ de.u.DebugString.lpDebugStringData = StringBuffer;
+
+ ApiIsAllowed = TRUE;
+
+ if (GetCurrentThreadId() != PollThreadId) {
+ StringBuffer[0] = 'i';
+ IoMessage->u.GetString.LengthOfStringRead = 1;
+ } else {
+ NotifyEM( &de, HTHDXFromPIDTID(1, 1), 0, NULL );
+ IoMessage->u.GetString.LengthOfStringRead = de.u.DebugString.nDebugStringLength;
+ }
+
+ DmKdWritePacket(IoMessage,
+ sizeof(*IoMessage),
+ PACKET_TYPE_KD_DEBUG_IO,
+ StringBuffer,
+ (USHORT)IoMessage->u.GetString.LengthOfStringRead);
+
+ ApiIsAllowed = FALSE;
+}
+
+VOID
+DmKdWriteControlPacket(
+ IN USHORT PacketType,
+ IN ULONG PacketId OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes a control packet to target machine.
+
+ N.B. a CONTROL Packet header is sent with the following information:
+ PacketLeader - indicates it's a control packet
+ PacketType - indicates the type of the control packet
+ ByteCount - aways zero to indicate no data following the header
+ PacketId - Valid ONLY for PACKET_TYPE_KD_ACKNOWLEDGE to indicate
+ which packet is acknowledged.
+
+Arguments:
+
+ PacketType - Supplies the type of the control packet.
+
+ PacketId - Supplies the PacketId. Used by Acknowledge packet only.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ DWORD BytesWritten;
+ BOOL rc;
+ KD_PACKET Packet;
+
+ assert( PacketType < PACKET_TYPE_MAX );
+
+ Packet.PacketLeader = CONTROL_PACKET_LEADER;
+ Packet.ByteCount = 0;
+ Packet.PacketType = PacketType;
+ if ( ARGUMENT_PRESENT(PacketId) ) {
+ Packet.PacketId = PacketId;
+ }
+
+ do {
+
+ //
+ // Write the control packet header
+ //
+
+ rc = DmKdWriteComPort((PUCHAR)&Packet, sizeof(Packet), &BytesWritten);
+
+ } while ( (!rc) || BytesWritten != sizeof(Packet) );
+}
+
+ULONG
+DmKdComputeChecksum (
+ IN PUCHAR Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the checksum for the string passed in.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the string.
+
+ Length - Supplies the length of the string.
+
+Return Value:
+
+ A ULONG is return as the checksum for the input string.
+
+--*/
+
+{
+
+ ULONG Checksum = 0;
+
+ while (Length > 0) {
+ Checksum = Checksum + (ULONG)*Buffer++;
+ Length--;
+ }
+ return Checksum;
+}
+
+BOOL
+DmKdSynchronizeTarget ( VOID )
+
+/*++
+
+Routine Description:
+
+ This routine keeps on sending reset packet to target until reset packet
+ is acknowledged by a reset packet from target.
+
+ N.B. This routine is intended to be used by kernel debugger at startup
+ time (ONLY) to get packet control variables on both target and host
+ back in synchronization. Also, reset request will cause kernel to
+ reset its control variables AND resend us its previous packet (with
+ the new packet id).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ USHORT Index;
+ UCHAR DataByte, PreviousDataByte;
+ USHORT PacketType = 0;
+ ULONG TimeoutCount = 0;
+ COMMTIMEOUTS CommTimeouts;
+ COMMTIMEOUTS OldTimeouts;
+ DWORD BytesRead;
+ BOOL rc;
+
+ TRACE_PRINT( "Synchronizing with the target machine...\n" );
+
+ //
+ // Get the old time out values and hold them.
+ // We then set a new total timeout value of
+ // five seconds on the read. (In millisecond intervals.
+ //
+
+ GetCommTimeouts( DmKdComPort, &OldTimeouts );
+
+ CommTimeouts = OldTimeouts;
+ CommTimeouts.ReadIntervalTimeout = 0;
+ CommTimeouts.ReadTotalTimeoutMultiplier = 0;
+ CommTimeouts.ReadTotalTimeoutConstant = 500;
+
+ SetCommTimeouts( DmKdComPort, &CommTimeouts );
+
+ while (TRUE) {
+Timeout:
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESET, 0L);
+
+ //
+ // Read packet leader
+ //
+
+ Index = 0;
+ do {
+
+ if (MaxRetries == 1) {
+// SetCommTimeouts( DmKdComPort,&OldTimeouts );
+ return FALSE;
+ }
+
+ //
+ // Check user input for control_c. If user types control_c,
+ // we will send a breakin packet to the target. Hopefully,
+ // target will send us a StateChange packet and
+ //
+
+
+ //
+ // if we don't get response from kernel in 3 seconds we
+ // will resend the reset packet if user does not type ctrl_c.
+ // Otherwise, we send breakin character and wait for data again.
+ //
+
+ rc = DmKdReadComPort(&DataByte, 1, &BytesRead);
+
+ if ((!rc) || (BytesRead != 1)) {
+
+ if (DmKdBreakIn) {
+ DmKdSendBreakin();
+ TimeoutCount = 0;
+ continue;
+ }
+
+ TimeoutCount++;
+
+ //
+ // if we have been waiting for 3 seconds, resend RESYNC packet
+ //
+
+ if (TimeoutCount != 6) {
+ continue;
+ }
+ TimeoutCount = 0;
+ TRACE_PRINT("SYNCTARGET: Timeout.\n");
+ goto Timeout;
+ }
+
+ if (rc && BytesRead == 1 &&
+ ( DataByte == PACKET_LEADER_BYTE ||
+ DataByte == CONTROL_PACKET_LEADER_BYTE)
+ ) {
+ if ( Index == 0 ) {
+ PreviousDataByte = DataByte;
+ Index++;
+ } else if ( DataByte == PreviousDataByte ) {
+ Index++;
+ } else {
+ PreviousDataByte = DataByte;
+ Index = 1;
+ }
+ } else {
+ Index = 0;
+ }
+ } while ( Index < 4 );
+
+ if (DataByte == CONTROL_PACKET_LEADER_BYTE) {
+
+ //
+ // Read 2 byte Packet type
+ //
+
+ rc = DmKdReadComPort((PUCHAR)&PacketType,sizeof(PacketType),&BytesRead);
+
+ if (rc && BytesRead == sizeof(PacketType) &&
+ PacketType == PACKET_TYPE_KD_RESET ) {
+ DmKdPacketExpected = INITIAL_PACKET_ID;
+ DmKdNextPacketToSend = INITIAL_PACKET_ID;
+ SetCommTimeouts( DmKdComPort,&OldTimeouts );
+ return TRUE;
+ }
+ }
+
+ //
+ // If we receive Data Packet leader, it means target has not
+ // receive our reset packet. So we loop back and send it again.
+ // N.B. We need to wait until target finishes sending the packet.
+ // Otherwise, we may be sending the reset packet while the target
+ // is sending the packet. This might cause target loss the reset
+ // packet.
+ //
+
+ while (DataByte != PACKET_TRAILING_BYTE) {
+ DmKdReadComPort(&DataByte, 1, &BytesRead);
+ if (BytesRead != 1) {
+ break;
+ }
+ }
+ }
+// SetCommTimeouts( DmKdComPort,&OldTimeouts );
+ return TRUE;
+}
+
+VOID
+DmKdSendBreakin( VOID )
+
+/*++
+
+ Routine Description:
+
+ Send a breakin packet to the target, unless some other packet
+ is already being transmitted, in which case do nothing.
+
+--*/
+
+{
+ DWORD BytesWritten;
+ BOOL rc;
+
+ TRACE_PRINT("Send Break in ...\n");
+
+ do {
+ rc = DmKdWriteComPort(
+ &DmKdBreakinPacket[0],
+ sizeof(DmKdBreakinPacket),
+ &BytesWritten
+ );
+ } while ((!rc) || (BytesWritten != sizeof(DmKdBreakinPacket)));
+ DmKdBreakIn = FALSE;
+}
+
+BOOL
+DmKdWritePacket(
+ IN PVOID PacketData,
+ IN USHORT PacketDataLength,
+ IN USHORT PacketType,
+ IN PVOID MorePacketData OPTIONAL,
+ IN USHORT MorePacketDataLength OPTIONAL
+ )
+{
+ DWORD BytesWritten;
+ BOOL rc;
+ KD_PACKET Packet;
+ USHORT TotalBytesToWrite;
+ BOOLEAN Received;
+ DWORD retries = 0;
+
+ assert( PacketType < PACKET_TYPE_MAX );
+ DEBUG_PRINT_3( "WRITE: Write type %x, packet id=%lx, ml=%hu\n",
+ PacketType,
+ DmKdNextPacketToSend,
+ MorePacketDataLength
+ );
+ if ( ARGUMENT_PRESENT(MorePacketData) ) {
+ TotalBytesToWrite = PacketDataLength + MorePacketDataLength;
+ Packet.Checksum = DmKdComputeChecksum(
+ MorePacketData,
+ MorePacketDataLength
+ );
+ }
+ else {
+ TotalBytesToWrite = PacketDataLength;
+ Packet.Checksum = 0;
+ }
+ Packet.Checksum += DmKdComputeChecksum(
+ PacketData,
+ PacketDataLength
+ );
+ Packet.PacketLeader = PACKET_LEADER;
+ Packet.ByteCount = TotalBytesToWrite;
+ Packet.PacketType = PacketType;
+ResendPacket:
+ Packet.PacketId = DmKdNextPacketToSend;
+
+ //
+ // Write the packet header
+ //
+
+ rc = DmKdWriteComPort((PUCHAR)&Packet, sizeof(Packet), &BytesWritten);
+
+ if ( (!rc) || BytesWritten != sizeof(Packet) ){
+
+ //
+ // an error occured writing the header, so write it again
+ //
+
+ TRACE_PRINT("WRITE: Packet header error.\n");
+ retries++;
+ if (retries == MaxRetries) {
+ return FALSE;
+ }
+ goto ResendPacket;
+ }
+
+ //
+ // Write the primary packet data
+ //
+
+ rc = DmKdWriteComPort(PacketData, PacketDataLength, &BytesWritten);
+
+ if ( (!rc) || BytesWritten != PacketDataLength ){
+
+ //
+ // an error occured writing the primary packet data,
+ // so write it again
+ //
+
+ TRACE_PRINT("WRITE: Message header error.\n");
+ retries++;
+ if (retries == MaxRetries) {
+ return FALSE;
+ }
+ goto ResendPacket;
+ }
+
+ //
+ // If secondary packet data was specified (WriteMemory, SetContext...)
+ // then write it as well.
+ //
+
+ if ( ARGUMENT_PRESENT(MorePacketData) ) {
+
+ rc = DmKdWriteComPort(
+ MorePacketData,
+ MorePacketDataLength,
+ &BytesWritten
+ );
+
+ if ( (!rc) || BytesWritten != MorePacketDataLength ){
+
+ //
+ // an error occured writing the secondary packet data,
+ // so write it again
+ //
+
+ TRACE_PRINT("WRITE: Message data error.\n");
+ retries++;
+ if (retries == MaxRetries) {
+ return FALSE;
+ }
+ goto ResendPacket;
+ }
+ }
+
+ //
+ // Output a packet trailing byte
+ //
+
+ do {
+ rc = DmKdWriteComPort(
+ &DmKdPacketTrailingByte[0],
+ sizeof(DmKdPacketTrailingByte),
+ &BytesWritten
+ );
+
+ } while ((!rc) || (BytesWritten != sizeof(DmKdPacketTrailingByte)));
+
+ //
+ // Wait for ACK
+ //
+
+ Received = DmKdWaitForPacket(
+ PACKET_TYPE_KD_ACKNOWLEDGE,
+ NULL
+ );
+
+ if ( Received == FALSE ) {
+ TRACE_PRINT("WRITE: Wait for ACK failed. Resend Packet.\n");
+ retries++;
+ if (retries == MaxRetries) {
+ return FALSE;
+ }
+ goto ResendPacket;
+ }
+ return TRUE;
+}
+
+BOOL
+DmKdReadPacketLeader(
+ IN ULONG PacketType,
+ OUT PULONG PacketLeader
+ )
+{
+ DWORD BytesRead;
+ BOOL rc;
+ USHORT Index;
+ UCHAR DataByte, PreviousDataByte;
+
+ Index = 0;
+ do {
+ if (DmKdBreakIn) {
+ if (PacketType == PACKET_TYPE_KD_STATE_CHANGE) {
+ DmKdSendBreakin( );
+ DmKdBreakIn = FALSE;
+ LeaveCriticalSection(&csPacket);
+ longjmp( JumpBuffer, 1 );
+ }
+ }
+ if (KdResync) {
+ KdResync = FALSE;
+ TRACE_PRINT(" Resync packet id ...\n");
+ DmKdSynchronizeTarget( );
+ TRACE_PRINT(" Done.\n");
+ LeaveCriticalSection(&csPacket);
+ longjmp( JumpBuffer, 1 );
+ }
+ rc = DmKdReadComPort(&DataByte, 1, &BytesRead);
+ if (rc && BytesRead == 1 &&
+ ( DataByte == PACKET_LEADER_BYTE ||
+ DataByte == CONTROL_PACKET_LEADER_BYTE)
+ ) {
+ if ( Index == 0 ) {
+ PreviousDataByte = DataByte;
+ Index++;
+ } else if ( DataByte == PreviousDataByte ) {
+ Index++;
+ } else {
+ PreviousDataByte = DataByte;
+ Index = 1;
+ }
+ } else {
+ Index = 0;
+ if (BytesRead == 0) {
+ TRACE_PRINT("READ: Timeout.\n");
+ if (InitialBreak) {
+ DmKdSendBreakin( );
+ InitialBreak = FALSE;
+ }
+ return(FALSE);
+ }
+ }
+ } while ( Index < 2 );
+
+ if ( DataByte != CONTROL_PACKET_LEADER_BYTE ) {
+ *PacketLeader = PACKET_LEADER;
+ } else {
+ *PacketLeader = CONTROL_PACKET_LEADER;
+ }
+ return TRUE;
+}
+
+BOOL
+DmKdWaitForPacket(
+ IN USHORT PacketType,
+ OUT PVOID Packet
+ )
+{
+ PDBGKD_DEBUG_IO IoMessage;
+ DWORD BytesRead;
+ BOOL rc;
+ UCHAR DataByte;
+ ULONG Checksum;
+ ULONG SyncBit;
+
+ if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
+ DEBUG_PRINT_1("READ: wait for ACK packet with id = %lx\n", DmKdNextPacketToSend);
+ }
+ else {
+ TRACE_PRINT("READ: Wait for type %x packet exp id = %lx\n",
+ PacketType, DmKdPacketExpected);
+ }
+
+ if (PacketType != PACKET_TYPE_KD_ACKNOWLEDGE) {
+ if (ValidUnaccessedPacket) {
+ DEBUG_PRINT("READ: Grab packet from buffer.\n");
+ goto ReadBuffered;
+ }
+ }
+
+ //
+ // First read a packet leader
+ //
+
+WaitForPacketLeader:
+
+ ValidUnaccessedPacket = FALSE;
+
+ if (!DmKdReadPacketLeader(PacketType, &PacketHeader.PacketLeader)) {
+ return FALSE;
+ }
+
+ if (InitialBreak) {
+ DmKdSendBreakin( );
+ InitialBreak = FALSE;
+ }
+
+ //
+ // Read packetLeader ONLY read two Packet Leader bytes. This do loop
+ // filters out the remaining leader byte.
+ //
+
+ do {
+ rc = DmKdReadComPort(&DataByte, 1, &BytesRead);
+ if ((rc) && BytesRead == 1) {
+ if (DataByte == PACKET_LEADER_BYTE ||
+ DataByte == CONTROL_PACKET_LEADER_BYTE) {
+ continue;
+ } else {
+ *(PUCHAR)&PacketHeader.PacketType = DataByte;
+ break;
+ }
+ } else {
+ goto WaitForPacketLeader;
+ }
+ }while (TRUE);
+
+ //
+ // Now we have valid packet leader. Read rest of the packet type.
+ //
+
+ rc = DmKdReadComPort(
+ ((PUCHAR)&PacketHeader.PacketType) + 1,
+ sizeof(PacketHeader.PacketType) - 1,
+ &BytesRead
+ );
+ if ((!rc) || BytesRead != sizeof(PacketHeader.PacketType) - 1) {
+ //
+ // If we cannot read the packet type and if the packet leader
+ // indicates this is a data packet, we need to ask for resend.
+ // Otherwise we simply ignore the incomplete packet.
+ //
+
+ if (PacketHeader.PacketLeader == PACKET_LEADER) {
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ TRACE_PRINT("READ: Data packet header Type error (short read).\n");
+ }
+ goto WaitForPacketLeader;
+ }
+
+ //
+ // Check the Packet type.
+ //
+
+ if (PacketHeader.PacketType >= PACKET_TYPE_MAX ) {
+ TRACE_PRINT("READ: Received INVALID packet type [%x]\n",PacketHeader.PacketType);
+ if (PacketHeader.PacketLeader == PACKET_LEADER) {
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ }
+ goto WaitForPacketLeader;
+ }
+
+ //
+ // Read ByteCount
+ //
+
+ rc = DmKdReadComPort(
+ (PUCHAR)&PacketHeader.ByteCount,
+ sizeof(PacketHeader.ByteCount),
+ &BytesRead
+ );
+
+ if ((!rc) || BytesRead != sizeof(PacketHeader.ByteCount)) {
+ //
+ // If we cannot read the packet type and if the packet leader
+ // indicates this is a data packet, we need to ask for resend.
+ // Otherwise we simply ignore the incomplete packet.
+ //
+
+ if (PacketHeader.PacketLeader == PACKET_LEADER) {
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ TRACE_PRINT("READ: Data packet header ByteCount error (short read).\n");
+ }
+ goto WaitForPacketLeader;
+ }
+
+ //
+ // Check ByteCount
+ //
+
+ if (PacketHeader.ByteCount > PACKET_MAX_SIZE ) {
+ if (PacketHeader.PacketLeader == PACKET_LEADER) {
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ TRACE_PRINT("READ: Data packet header ByteCount error (short read).\n");
+ }
+ goto WaitForPacketLeader;
+ }
+
+ //
+ // Read Packet Id
+ //
+
+ rc = DmKdReadComPort(
+ (PUCHAR)&PacketHeader.PacketId,
+ sizeof(PacketHeader.PacketId),
+ &BytesRead
+ );
+
+ if ((!rc) || BytesRead != sizeof(PacketHeader.PacketId)) {
+ //
+ // If we cannot read the packet Id and if the packet leader
+ // indicates this is a data packet, we need to ask for resend.
+ // Otherwise we simply ignore the incomplete packet.
+ //
+
+ if (PacketHeader.PacketLeader == PACKET_LEADER) {
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ DEBUG_PRINT("READ: Data packet header Id error (short read).\n");
+ }
+ goto WaitForPacketLeader;
+ }
+
+ if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER ) {
+ if (PacketHeader.PacketType == PACKET_TYPE_KD_ACKNOWLEDGE ) {
+
+ //
+ // If we received an expected ACK packet and we are not
+ // waiting for any new packet, update outgoing packet id
+ // and return. If we are NOT waiting for ACK packet
+ // we will keep on waiting. If the ACK packet
+ // is not for the packet we send, ignore it and keep on waiting.
+ //
+
+ if (PacketHeader.PacketId != DmKdNextPacketToSend) {
+ TRACE_PRINT("READ: Received unmatched packet id = %lx, Type = %x\n",
+ PacketHeader.PacketId, PacketHeader.PacketType);
+ goto WaitForPacketLeader;
+ } else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
+ DmKdNextPacketToSend ^= 1;
+ TRACE_PRINT("Received correct ACK packet.\n");
+ return TRUE;
+ } else {
+ goto WaitForPacketLeader;
+ }
+ } else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESET) {
+
+ //
+ // if we received Reset packet, reset the packet control variables
+ // and resend earlier packet.
+ //
+
+ DmKdNextPacketToSend = INITIAL_PACKET_ID;
+ DmKdPacketExpected = INITIAL_PACKET_ID;
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESET, 0L);
+ return FALSE;
+ } else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESEND) {
+ TRACE_PRINT("READ: Received RESEND packet\n");
+ return FALSE;
+ } else {
+
+ //
+ // Invalid packet header, ignore it.
+ //
+
+ TRACE_PRINT("READ: Received Control packet with UNKNOWN type\n");
+ goto WaitForPacketLeader;
+ }
+
+ //
+ // The packet header is for data packet (not control packet).
+ //
+
+ } else {
+
+ //
+ // Read Packet Checksum. (for Data Packet Only).
+ //
+
+ rc = DmKdReadComPort(
+ (PUCHAR)&PacketHeader.Checksum,
+ sizeof(PacketHeader.Checksum),
+ &BytesRead
+ );
+
+
+ if ((!rc) || BytesRead != sizeof(PacketHeader.Checksum)) {
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ TRACE_PRINT("READ: Data packet header checksum error (short read).\n");
+ goto WaitForPacketLeader;
+ }
+
+ if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
+
+ //
+ // if we are waiting for ACK packet ONLY
+ // and we receive a data packet header, check if the packet id
+ // is what we expected. If yes, assume the acknowledge is lost (but
+ // sent), ask sender to resend and return with PACKET_RECEIVED.
+ //
+
+ if (PacketHeader.PacketId == DmKdPacketExpected) {
+ DmKdNextPacketToSend ^= 1;
+ TRACE_PRINT("READ: Received VALID data packet while waiting for ACK.\n");
+ } else {
+ TRACE_PRINT("READ: Received Data packet with unmatched ID = %lx\n");
+ // ,PacketHeader.PacketId);
+ DmKdWriteControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
+ PacketHeader.PacketId
+ );
+ goto WaitForPacketLeader;
+ }
+ }
+ }
+
+ //
+ // we are waiting for data packet and we received the packet header
+ // for data packet. Perform the following checkings to make sure
+ // it is the packet we are waiting for.
+ //
+
+ if ((PacketHeader.PacketId & ~SYNC_PACKET_ID) != INITIAL_PACKET_ID &&
+ (PacketHeader.PacketId & ~SYNC_PACKET_ID) != (INITIAL_PACKET_ID ^ 1)) {
+ TRACE_PRINT("READ: Received INVALID packet Id.\n");
+ goto AskForResend;
+ }
+
+ rc = DmKdReadComPort(
+ DmKdPacket,
+ PacketHeader.ByteCount,
+ &BytesRead
+ );
+
+ if ( (!rc) || BytesRead != PacketHeader.ByteCount ) {
+ TRACE_PRINT("READ: Data packet error (short read).\n");
+ goto AskForResend;
+ }
+
+ //
+ // Make sure the next byte is packet trailing byte
+ //
+
+ rc = DmKdReadComPort(&DataByte, sizeof(DataByte), &BytesRead);
+
+ if ( (!rc) || BytesRead != sizeof(DataByte) ||
+ DataByte != PACKET_TRAILING_BYTE ) {
+ TRACE_PRINT("READ: Packet trailing byte timeout.\n");
+ goto AskForResend;
+ }
+
+ //
+ // Make sure the checksum is valid.
+ //
+
+ Checksum = DmKdComputeChecksum(DmKdPacket, PacketHeader.ByteCount);
+ if (Checksum != PacketHeader.Checksum) {
+ TRACE_PRINT("READ: Checksum error.\n");
+ goto AskForResend;
+ }
+
+ //
+ // We have a valid data packet. If the packetid is bad, we just
+ // ack the packet to the sender will step ahead. If packetid is bad
+ // but SYNC_PACKET_ID bit is set, we sync up. If packetid is good,
+ // or SYNC_PACKET_ID is set, we take the packet.
+ //
+
+ TRACE_PRINT("READ: Received Packet with id = %lx\n", PacketHeader.PacketId);
+
+ SyncBit = PacketHeader.PacketId & SYNC_PACKET_ID;
+ PacketHeader.PacketId = PacketHeader.PacketId & ~SYNC_PACKET_ID;
+
+ //
+ // Ack the packet. SYNC_PACKET_ID bit will ALWAYS be OFF.
+ //
+
+ DmKdWriteControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
+ PacketHeader.PacketId
+ );
+
+ //
+ // Check the incoming packet Id.
+ //
+
+ if ((PacketHeader.PacketId != DmKdPacketExpected) &&
+ (SyncBit != SYNC_PACKET_ID)) {
+ DEBUG_PRINT_1("READ: Unexpected Packet Id (Acked) (%lx)\n",
+ DmKdPacketExpected);
+ goto WaitForPacketLeader;
+ }
+ else {
+ if (SyncBit == SYNC_PACKET_ID) {
+
+ //
+ // We know SyncBit is set, so reset Expected Ids
+ //
+
+ TRACE_PRINT("READ: Got Sync Id, reset PacketId.\n");
+
+ DmKdPacketExpected = PacketHeader.PacketId;
+ DmKdNextPacketToSend = INITIAL_PACKET_ID;
+
+ }
+ DmKdPacketExpected ^= 1;
+ }
+
+ //
+ // If this is an internal packet. IO, or Resend, then
+ // handle it.
+ //
+
+ if (PacketHeader.PacketType == PACKET_TYPE_KD_DEBUG_IO) {
+ IoMessage = (PDBGKD_DEBUG_IO)DmKdPacket;
+
+ if (IoMessage->ApiNumber == DbgKdPrintStringApi) {
+ ULONG len = min( sizeof(StringBuffer)-1,
+ IoMessage->u.PrintString.LengthOfString );
+ memcpy( StringBuffer,
+ (PUCHAR)(IoMessage+1),
+ len );
+ StringBuffer[len]='\0';
+ //
+ // If we are in the poll thread, then we just print the message,
+ // otherwise we queue it so the poll thread will take care of
+ // the printing.
+ //
+ if ( GetCurrentThreadId() == PollThreadId ) {
+ DMPrintShellMsg( "%s", StringBuffer );
+ } else {
+ AddQueue( QT_DEBUGSTRING, 0, 0, (DWORD)StringBuffer, len+1 );
+ }
+ }
+ else if (IoMessage->ApiNumber == DbgKdGetStringApi) {
+ DmKdHandlePromptString(IoMessage);
+ }
+ if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
+ return TRUE;
+ }
+ goto WaitForPacketLeader;
+ }
+
+ if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
+ ValidUnaccessedPacket = TRUE;
+ TRACE_PRINT("READ: Packet Read ahead.\n");
+ return TRUE;
+ }
+ReadBuffered:
+
+ //
+ // Check PacketType is what we are waiting for.
+ //
+
+ if (PacketType != PacketHeader.PacketType) {
+ TRACE_PRINT("READ: Unexpected Packet type (Acked).\n");
+ goto WaitForPacketLeader;
+ }
+ *(PVOID *)Packet = &DmKdPacket;
+ ValidUnaccessedPacket = FALSE;
+ return TRUE;
+
+AskForResend:
+
+ DmKdWriteControlPacket(PACKET_TYPE_KD_RESEND, 0L);
+ if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
+ return TRUE;
+ }
+ TRACE_PRINT("READ: Ask for resend.\n");
+ goto WaitForPacketLeader;
+}
+
+DWORD
+DmKdWaitStateChange(
+ OUT PDBGKD_WAIT_STATE_CHANGE StateChange,
+ OUT PVOID Buffer,
+ IN ULONG BufferLength
+ )
+
+/*++
+
+Routine Description:
+
+ This function causes the calling user interface to wait for a state
+ change to occur in the system being debugged. Once a state change
+ occurs, the user interface can either continue the system using
+ DmKdContinue, or it can manipulate system state using anyone of the
+ DmKd state manipulation APIs.
+
+Arguments:
+
+ StateChange - Supplies the address of state change record that
+ will contain the state change information.
+
+ Buffer - Supplies the address of a buffer that returns additional
+ information.
+
+ BufferLength - Supplies the length of Buffer.
+
+Return Value:
+
+ STATUS_SUCCESS - A state change occured. Valid state change information
+ was returned.
+
+--*/
+
+{
+ BOOLEAN rc;
+ PDBGKD_WAIT_STATE_CHANGE LocalStateChange;
+ DWORD st;
+ UCHAR *pt;
+ DWORD i;
+
+ DEBUG_PRINT( "Waiting for a state change\n" );
+
+ EnterCriticalSection(&csPacket);
+
+ st = (DWORD)STATUS_UNSUCCESSFUL;
+ while ( st != STATUS_SUCCESS ) {
+
+ //
+ // Waiting for a state change message. Copy the message to the callers
+ // buffer, and then free the packet entry.
+ //
+
+ do {
+ rc = DmKdWaitForPacket(
+ PACKET_TYPE_KD_STATE_CHANGE,
+ &LocalStateChange
+ );
+ if (!rc && MaxRetries==1) {
+ LeaveCriticalSection(&csPacket);
+ return STATUS_TIMEOUT;
+ }
+ } while ( rc == FALSE);
+
+ LocalStateChange = (PDBGKD_WAIT_STATE_CHANGE)DmKdPacket;
+ st = STATUS_SUCCESS;
+ *StateChange = *LocalStateChange;
+
+ switch ( (USHORT) StateChange->NewState ) {
+ case DbgKdExceptionStateChange:
+ pt = (UCHAR *)LocalStateChange + sizeof(DBGKD_WAIT_STATE_CHANGE);
+ if (PacketHeader.ByteCount < sizeof(DBGKD_WAIT_STATE_CHANGE)) {
+ i = PacketHeader.ByteCount;
+ }
+ else {
+ i = PacketHeader.ByteCount - sizeof(DBGKD_WAIT_STATE_CHANGE);
+ }
+ memcpy( Buffer, pt, i );
+ break;
+ case DbgKdLoadSymbolsStateChange:
+ if ( BufferLength < LocalStateChange->u.LoadSymbols.PathNameLength ) {
+ st = (DWORD)STATUS_BUFFER_OVERFLOW;
+ } else {
+ pt = ((UCHAR *) LocalStateChange) + PacketHeader.ByteCount -
+ (int)LocalStateChange->u.LoadSymbols.PathNameLength;
+ memcpy(Buffer, pt,
+ (int)LocalStateChange->u.LoadSymbols.PathNameLength);
+ }
+ break;
+ default:
+ assert(FALSE);
+ }
+ DEBUG_PRINT_1( "state change = %x\n", StateChange->NewState );
+ LeaveCriticalSection(&csPacket);
+ return st;
+ }
+}
+
+VOID
+TRACE_PRINT(
+ PCHAR szFormat,
+ ...
+ )
+{
+ va_list marker;
+ char buf[500];
+ int n;
+#if DBG
+ if (!fPacketTrace && FVerbose < 5)
+#else
+ if (!fPacketTrace)
+#endif
+ {
+ return;
+
+ }
+
+ va_start( marker, szFormat );
+ n = _vsnprintf(buf, sizeof(buf), szFormat, marker );
+ va_end( marker);
+
+ if (n == -1) {
+ buf[sizeof(buf)-1] = '\0';
+ }
+
+
+#if DBG
+ if (FVerbose >= 5) {
+ OutputDebugString( buf );
+ }
+#endif
+ if (fPacketTrace) {
+ DMPrintShellMsg( buf );
+ }
+ return;
+}
+
diff --git a/private/windbg/newdm/ppcmach.c b/private/windbg/newdm/ppcmach.c
new file mode 100644
index 000000000..d2180c2c3
--- /dev/null
+++ b/private/windbg/newdm/ppcmach.c
@@ -0,0 +1,913 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ mach.c
+
+Abstract:
+
+ This file contains the PPC601 specific code for dealing with
+ the process of stepping a single instruction. This includes
+ determination of the next offset to be stopped at and if the
+ instruction is all call type instruction.
+
+Author:
+
+ Kent Forschmiedt (kentf)
+ Farooq Butt (fmbutt@engage.sps.mot.com)
+
+Environment:
+
+ Win32 - User
+
+Notes:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+ //setup a couple of macros
+
+ // The below macro is used to do subscripting operations
+ // len_item is the length of the embedded word that we are
+ // interested in subscripting
+
+#define NTH_BIT(word,n,len_item) \
+ ( ((word) >> ((len_item) - (n) - 1)) & 0x01)
+
+
+
+//
+// Stuff for debug registers
+//
+// The debug register architecture is represented to NT as
+// nearly identical to the x86.
+// As of this writing, there is one debug register, and it only
+// supports a data length of 8.
+//
+
+
+typedef struct _DR7 *PDR7;
+typedef struct _DR7 {
+ DWORD L0 : 1;
+ DWORD G0 : 1;
+ DWORD L1 : 1;
+ DWORD G1 : 1;
+ DWORD L2 : 1;
+ DWORD G2 : 1;
+ DWORD L3 : 1;
+ DWORD G3 : 1;
+ DWORD LE : 1;
+ DWORD GE : 1;
+ DWORD Pad1 : 3;
+ DWORD GD : 1;
+ DWORD Pad2 : 1;
+ DWORD Pad3 : 1;
+ DWORD Rwe0 : 2;
+ DWORD Len0 : 2;
+ DWORD Rwe1 : 2;
+ DWORD Len1 : 2;
+ DWORD Rwe2 : 2;
+ DWORD Len2 : 2;
+ DWORD Rwe3 : 2;
+ DWORD Len3 : 2;
+} DR7;
+
+
+#define RWE_EXEC 0x00
+#define RWE_WRITE 0x01
+#define RWE_RESERVED 0x02
+#define RWE_READWRITE 0x03
+
+
+DWORD LenMask[ MAX_DEBUG_REG_DATA_SIZE + 1 ] = DEBUG_REG_LENGTH_MASKS;
+
+
+extern LPDM_MSG LpDmMsg;
+
+BOOL
+IsRet(
+ HTHDX hthd,
+ LPADDR addr
+ )
+{
+ DWORD instr;
+ DWORD cBytes;
+ if (!AddrReadMemory( hthd->hprc, hthd, addr, &instr, 4, &cBytes )) {
+ return FALSE;
+ }
+ return (instr == 0x4e800020); // bclr branch always
+}
+
+
+void
+IsCall (
+ HTHDX hthd,
+ LPADDR lpaddr,
+ LPINT lpf,
+ BOOL fStepOver
+ )
+
+/*++
+
+Routine Description:
+
+ IsCall
+
+Arguments:
+
+ hthd - Supplies the handle to the thread
+
+ lpaddr - Supplies the address to be check for a call instruction
+
+ lpf - Returns class of instruction:
+ CALL
+ BREAKPOINT_INSTRUCTION
+ SOFTWARE_INTERRUPT
+ FALSE
+
+ fStepOver
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG opcode;
+ ADDR iaraddr = *lpaddr;
+ DWORD length;
+ PPC_INSTRUCTION disinstr;
+ BOOL r;
+
+
+
+ if (hthd->fIsCallDone) {
+ *lpaddr = hthd->addrIsCall;
+ *lpf = hthd->iInstrIsCall;
+ return;
+ }
+
+ /*
+ * Assume that this is not a call instruction
+ */
+
+ *lpf = FALSE;
+
+ /*
+ * Read in the dword which contains the instruction under
+ * inspection.
+ */
+
+ r = AddrReadMemory(hthd->hprc,
+ hthd,
+ &iaraddr,
+ &disinstr.Long,
+ sizeof(DWORD),
+ &length);
+ if (!r || length != sizeof(DWORD)) {
+ goto done;
+ }
+
+
+ opcode = disinstr.Primary_Op;
+
+ /* Do we have a branch or is this a breakpoint ? If it is a
+ breakpoint, is it set by the user or was it set by the
+ debugger ? If all else fails return FALSE */
+
+ switch (opcode)
+ {
+ default:
+ DPRINT(5,("IsCall opcode == DEFAULT"));
+ break; // leaving *lpf = FALSE
+
+
+ case BC_OP:
+ DPRINT(5,("IsCall opcode == BC_OP"));
+ // branch conditional NEVER a call
+ break; // leaving *lpf == FALSE
+
+ case B_OP:
+ DPRINT(5,("IsCall opcode == B_OP"));
+ // unconditional branch, could be a call
+ // THIS is the real call operation if LK == 1
+
+ if ((disinstr.Long & 1) == 1)
+ {
+ // LK is on, we have a call
+ *lpf = INSTR_IS_CALL;
+ }
+
+ break; // leaving *lpf = FALSE if not call...
+
+
+ case X19_OP:
+ DPRINT(5,("IsCall opcode == X19_OP"));
+ // branch conditional on register (various extended opcodes)
+ // This could be a function call if it is a
+ // BCCTRL
+
+ if ((disinstr.XLform_XO == BCCTR_OP) &&
+ ((disinstr.Long & 1) == 1))
+ *lpf = INSTR_IS_CALL;
+
+ if (disinstr.XLform_XO == BCLR_OP) {
+ *lpf = INSTR_IS_CALL;
+ }
+
+ break; // leaving *lpf = FALSE if not BCCTRL
+
+ case TWI_OP:
+ DPRINT(5,("IsCall opcode == TWI_OP"));
+
+ // Is this TWI instruction installed by the debugger or
+ // was it a user installed one ?
+
+ // First make sure this is a BREAK
+ if (disinstr.Dform_TO == 0x1f) // All 1's in the TO field
+ {
+ switch(disinstr.Dform_SI)
+ {
+
+ case DEBUG_PRINT_BREAKPOINT:
+ case DEBUG_PROMPT_BREAKPOINT:
+ case DEBUG_STOP_BREAKPOINT:
+ case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
+ case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
+
+ *lpf = INSTR_BREAKPOINT;
+ DPRINT(5,("IsCall opcode was an INSTR_BREAKPOINT"));
+ break;
+
+ default:
+ *lpf = INSTR_SOFT_INTERRUPT;
+ DPRINT(5,("IsCall opcode was a INSTR_SOFT_INTERRUPT"));
+ break;
+ }
+ }
+
+ }
+
+
+ DPRINT(1, ("(IsCall?) FIR=%08x Type=%s\n", iaraddr.addr.off,
+ *lpf==INSTR_IS_CALL ?"CALL":
+ (*lpf==INSTR_BREAKPOINT?"BREAKPOINT":
+ (*lpf==INSTR_SOFT_INTERRUPT ?"INTERRUPT":
+ "NORMAL"))));
+
+done:
+ if (*lpf==INSTR_IS_CALL) {
+ lpaddr->addr.off += BP_SIZE;
+ hthd->addrIsCall = *lpaddr;
+ } else if ( *lpf==INSTR_SOFT_INTERRUPT ) {
+ lpaddr->addr.off += BP_SIZE;
+ }
+ hthd->iInstrIsCall = *lpf;
+
+ return;
+} /* IsCall() */
+
+
+
+#ifndef KERNEL
+void
+ProcessGetDRegsCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPDWORD lpdw = (LPDWORD)LpDmMsg->rgb;
+ CONTEXT cxt;
+ int rs = 0;
+
+ DEBUG_PRINT( "ProcessGetDRegsCmd :\n");
+
+
+ if (hthd == 0) {
+ rs = 0;
+ } else {
+ cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (!GetThreadContext(hthd->rwHand, &cxt)) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ rs = 0;
+ } else {
+ lpdw[0] = hthd->context.Dr0;
+ lpdw[1] = hthd->context.Dr1;
+ lpdw[2] = hthd->context.Dr2;
+ lpdw[3] = hthd->context.Dr3;
+ lpdw[4] = hthd->context.Dr6;
+ lpdw[5] = hthd->context.Dr7;
+ LpDmMsg->xosdRet = xosdNone;
+ rs = sizeof(CONTEXT);
+ }
+ }
+
+ Reply( rs, LpDmMsg, lpdbb->hpid );
+ return;
+} /* ProcessGetDRegsCmd() */
+
+
+void
+ProcessSetDRegsCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPDWORD lpdw = (LPDWORD)(lpdbb->rgbVar);
+ XOSD_ xosd = xosdNone;
+
+ Unreferenced(hprc);
+
+ DPRINT(5, ("ProcessSetDRegsCmd : "));
+
+ hthd->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
+ hthd->context.Dr0 = lpdw[0];
+ hthd->context.Dr1 = lpdw[1];
+ hthd->context.Dr2 = lpdw[2];
+ hthd->context.Dr3 = lpdw[3];
+ hthd->context.Dr6 = lpdw[4];
+ hthd->context.Dr7 = lpdw[5];
+
+
+ if (hthd->fWowEvent) {
+ WOWSetThreadContext(hthd, &hthd->context);
+ } else {
+ SetThreadContext(hthd->rwHand, &hthd->context);
+ }
+
+ Reply(0, &xosd, lpdbb->hpid);
+
+ return;
+} /* ProcessSetDRegsCmd() */
+
+VOID
+MakeThreadSuspendItselfHelper(
+ HTHDX hthd,
+ FARPROC lpSuspendThread
+ )
+{
+ //
+ // set up the args to SuspendThread
+ //
+
+ // GetCurrentThread always returns a magic cookie, safe for any thread.
+
+ hthd->context.Gpr3 = (DWORD)GetCurrentThread();
+ hthd->context.Lr = PC(hthd);
+ PC(hthd) = (DWORD)lpSuspendThread;
+ hthd->fContextDirty = TRUE;
+}
+#endif // !KERNEL
+
+
+
+ULONG
+GetNextOffset (
+ HTHDX hthd,
+ BOOL fStep
+ )
+
+/*++
+
+Routine Description:
+
+ From a limited disassembly of the instruction pointed
+ by the IAR register, compute the offset of the next
+ instruction for either a trace or step operation.
+
+Arguments:
+
+ hthd - Supplies the handle to the thread to get the next offset for
+
+ fStep - Supplies TRUE for STEP offset and FALSE for trace offset
+
+Return Value:
+
+ Offset to place breakpoint at for doing a STEP or TRACE
+
+--*/
+
+{
+ ULONG returnvalue;
+ ULONG opcode;
+ ADDR iaraddr;
+ DWORD length;
+ ULONG *regArray = &hthd->context.Gpr0;
+ PPC_INSTRUCTION disinstr;
+ ULONG absolute;
+ ULONG cr,ctr,lr,cond_ok=0,ctr_ok=0;
+ BOOL r;
+
+ AddrFromHthdx(&iaraddr, hthd);
+
+ r = AddrReadMemory(hthd->hprc,
+ hthd,
+ &iaraddr,
+ &disinstr.Long,
+ sizeof(DWORD),
+ &length);
+
+ opcode = disinstr.Primary_Op;
+
+ DPRINT(5,("Entered GetNextOffset routine, the address we start with is "
+ "0x%x\n\tThe instruction is 0x%x",iaraddr.addr.off,
+ disinstr.Long));
+
+ // setup default return value
+ returnvalue = iaraddr.addr.off + sizeof(ULONG);
+
+
+ // setup the absolute flag in case of a branch
+ absolute = (int) ((disinstr.Long >> 1) & 1);
+
+ // Before going into the switch, let us do some up front
+ // calculations
+
+ /* Let us use the algorithm described in pp 10-22 of
+ the MPC/601 users manual */
+
+ ctr = hthd->context.Ctr;
+ cr = hthd->context.Cr;
+
+ /* First find out whether the CTR has to be decremented */
+
+ if (NTH_BIT(disinstr.Bform_BO,2,5) == 0)
+ // i.e if ~B0[2] then ctr = ctr - 1
+ ctr = ctr - 1;
+
+ // next we do the following operation:
+ // ctr_ok = BO[2] OR ((ctr NEQ 0) XOR BO[3]))
+
+ ctr_ok = (NTH_BIT(disinstr.Bform_BO,2,5) ||
+ ((ctr != 0) ^ (NTH_BIT(disinstr.Bform_BO,3,5))));
+
+ // now for
+ // cond_ok= BO[0] OR ( (CR[BI] LEQIV BO[1]))
+
+ cond_ok = ((NTH_BIT(disinstr.Bform_BO,0,5)) ||
+ ((NTH_BIT(cr,(disinstr.Bform_BI),32)) ==
+ (NTH_BIT(disinstr.Bform_BO,1,5))));
+
+
+ switch (opcode)
+ {
+
+ case SC_OP:
+ DPRINT(5,("We have an SC_OP"));
+ // stepping over a syscall instruction must set the breakpoint
+ // at the inst after the syscall (default)
+ break;
+
+ case B_OP:
+ DPRINT(5,("We have an B_OP"));
+ // unconditional branch found
+ // no need to chase down branch targets unless you are
+ // tracing (i.e. NOT stepping over functions).
+ // Of course the whole test about stepping etc. only
+ // makes sense if you are stepping over a FUNCTION CALL
+ // i.e. a branch and link operation
+
+
+ if (!fStep) {
+ if (absolute) {
+ /* LI can only address words not bytes so << 2 */
+ returnvalue = disinstr.Iform_LI << 2;
+ } else {
+ returnvalue = (disinstr.Iform_LI << 2) + iaraddr.addr.off;
+ }
+ }
+
+ break;
+
+ case BC_OP:
+ DPRINT(5,("We have a BC_OP"));
+ /* We got a branch conditional, if it evaluates to true,
+ let us set return to the target. Otherwise
+ let us leave the default returnvalue in place */
+
+
+ /* << 2 bits since we address words */
+
+ if (ctr_ok && cond_ok) {
+ if (absolute) {
+ returnvalue = disinstr.Bform_BD << 2;
+ } else {
+ returnvalue = (disinstr.Bform_BD << 2)+iaraddr.addr.off;
+ }
+ }
+ break;
+
+ case X19_OP:
+ DPRINT(5,("We have an X19_OP"));
+ if (disinstr.XLform_XO == BCLR_OP) {
+ lr = hthd->context.Lr;
+
+ if (ctr_ok && cond_ok) {
+ returnvalue = lr & ~3; // remember, we address words
+ // not bytes thus ~3
+
+ }
+ } else if (disinstr.XLform_XO == BCCTR_OP) {
+ if (cond_ok) {
+ returnvalue = ctr & ~3;
+ }
+ }
+
+ break;
+
+ default:
+ DPRINT(5,("We have an unhandled DEFAULT op"));
+ break;
+
+ }
+
+ return returnvalue;
+} /* GetNextOffset() */
+
+
+
+XOSD
+SetupFunctionCall(
+ LPEXECUTE_OBJECT_DM lpeo,
+ LPEXECUTE_STRUCT lpes
+ )
+{
+ /*
+ * Can only execute functions on the current stopped thread. Therefore
+ * assert that the current thread is stopped.
+ */
+
+ assert(lpeo->hthd->tstate & ts_stopped);
+ if (!(lpeo->hthd->tstate & ts_stopped)) {
+ return xosdInvalidThread;
+ }
+
+ /*
+ * Now get the current stack offset.
+ */
+
+ lpeo->addrStack.addr.off = lpeo->hthd->context.Gpr1;
+
+ /*
+ * Now place the return address correctly
+ */
+
+ lpeo->hthd->context.Iar = lpeo->hthd->context.Lr =
+ lpeo->addrStart.addr.off;
+
+ /*
+ * Set the instruction pointer to the starting addresses
+ * and write the context back out
+ */
+
+ lpeo->hthd->context.Iar = lpeo->addrStart.addr.off;
+
+ lpeo->hthd->fContextDirty = TRUE;
+
+ return xosdNone;
+}
+
+
+
+BOOL
+CompareStacks(
+ LPEXECUTE_OBJECT_DM lpeo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to determine if the stack pointers are currect
+ for terminating function evaluation.
+
+Arguments:
+
+ lpeo - Supplies the pointer to the DM Execute Object description
+
+Return Value:
+
+ TRUE if the evaluation is to be terminated and FALSE otherwise
+
+--*/
+
+{
+
+ if (lpeo->addrStack.addr.off <= lpeo->hthd->context.Gpr1) {
+ return TRUE;
+ }
+
+ return FALSE;
+} /* CompareStacks() */
+
+BOOL
+ProcessFrameStackWalkNextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ PCONTEXT context,
+ LPVOID pctxPtrs
+ )
+
+{
+ return FALSE;
+}
+
+
+DWORD
+BranchUnassemble(
+ void *Memory,
+ ADDR *Addr,
+ BOOL *IsBranch,
+ BOOL *TargetKnown,
+ BOOL *IsCall,
+ BOOL *IsTable,
+ ADDR *Target
+ )
+
+{
+
+ ULONG opcode, absolute=FALSE, linkbit_on=FALSE;
+ PPC_INSTRUCTION disinstr;
+ UOFF32 Offset;
+ UOFF32 TargetOffset;
+
+
+ assert( Memory );
+ assert( IsBranch );
+ assert( TargetKnown );
+ assert( IsCall );
+ assert( Target );
+
+ Offset = GetAddrOff(*Addr);
+ TargetOffset = 0;
+ *IsBranch = FALSE;
+ *IsTable = FALSE;
+ disinstr.Long = * (PULONG ) Memory;
+
+ // Is the absolute bit on ?
+ absolute = (int) ((disinstr.Long >> 1) & 1);
+
+ // Is the link bit on ?
+ linkbit_on = (int) ((disinstr.Long & 1));
+
+ opcode = disinstr.Primary_Op;
+
+ switch (opcode)
+ {
+ default:
+ break;
+
+ case BC_OP:
+ *IsCall= linkbit_on;
+ *IsBranch = TRUE;
+ *TargetKnown = TRUE;
+ if (absolute)
+ TargetOffset = disinstr.Bform_BD << 2;
+ else
+ TargetOffset = (disinstr.Bform_BD << 2)+ Offset;
+ break;
+
+ case B_OP:
+ *IsCall= linkbit_on;
+ *IsBranch = TRUE;
+ *TargetKnown = TRUE;
+ if (absolute)
+ TargetOffset = disinstr.Iform_LI << 2;
+ else
+ TargetOffset = (disinstr.Iform_LI << 2) + Offset;
+ break;
+
+
+ case X19_OP:
+ // branch conditional on register (various extended opcodes)
+ *IsCall = linkbit_on;
+ *IsBranch = TRUE;
+ *TargetKnown = FALSE;
+ TargetOffset = 0;
+ break;
+
+ }
+
+ AddrInit(Target, 0, 0, TargetOffset, TRUE, TRUE, FALSE, FALSE);
+
+ return(sizeof(DWORD));
+
+}
+
+
+BOOL
+SetupDebugRegister(
+ HTHDX hthd,
+ int Register,
+ int DataSize,
+ DWORD DataAddr,
+ DWORD BpType
+ )
+{
+ DWORD Len;
+ DWORD rwMask;
+
+#ifdef KERNEL
+ KSPECIAL_REGISTERS ksr;
+ PDWORD Dr0 = &ksr.KernelDr0;
+ PDWORD Dr1 = &ksr.KernelDr1;
+ PDWORD Dr2 = &ksr.KernelDr2;
+ PDWORD Dr3 = &ksr.KernelDr3;
+ PDR7 Dr7 = (PDR7)&(ksr.KernelDr7);
+#else
+ CONTEXT Context;
+ PDWORD Dr0 = &Context.Dr0;
+ PDWORD Dr1 = &Context.Dr1;
+ PDWORD Dr2 = &Context.Dr2;
+ PDWORD Dr3 = &Context.Dr3;
+ PDR7 Dr7 = (PDR7)&(Context.Dr7);
+#endif
+
+ // ppc currently only supports 1
+ assert(Register == 1);
+
+#ifdef KERNEL
+ if (!GetExtendedContext(hthd, &ksr))
+#else
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (!GetThreadContext(hthd->rwHand, &Context))
+#endif
+ {
+ return FALSE;
+ }
+
+
+ Len = LenMask[ DataSize ];
+
+ switch ( BpType ) {
+ case bptpDataR:
+ rwMask = RWE_READWRITE;
+ break;
+
+ case bptpDataW:
+ case bptpDataC:
+ rwMask = RWE_WRITE;
+ break;
+
+ case bptpDataExec:
+ rwMask = RWE_EXEC;
+ //
+ // length must be 0 for exec bp
+ //
+ Len = 0;
+ break;
+
+ default:
+ assert(!"Invalid BpType!!");
+ break;
+ }
+
+
+ switch( Register ) {
+ case 0:
+ *Dr0 = DataAddr;
+ Dr7->Len0 = Len;
+ Dr7->Rwe0 = rwMask;
+ Dr7->L0 = 0x01;
+ break;
+ case 1:
+ *Dr1 = DataAddr;
+ Dr7->Len1 = Len;
+ Dr7->Rwe1 = rwMask;
+ Dr7->L1 = 0x01;
+ break;
+ case 2:
+ *Dr2 = DataAddr;
+ Dr7->Len2 = Len;
+ Dr7->Rwe2 = rwMask;
+ Dr7->L2 = 0x01;
+ break;
+ case 3:
+ *Dr3 = DataAddr;
+ Dr7->Len3 = Len;
+ Dr7->Rwe3 = rwMask;
+ Dr7->L3 = 0x01;
+ break;
+ }
+
+#ifdef KERNEL
+ ksr.KernelDr6 = 0;
+ return SetExtendedContext(hthd, &ksr);
+#else
+ return SetThreadContext(hthd->rwHand, &Context);
+#endif
+
+}
+
+VOID
+ClearDebugRegister(
+ HTHDX hthd,
+ int Register
+ )
+{
+#ifdef KERNEL
+ KSPECIAL_REGISTERS ksr;
+ PDWORD Dr0 = &ksr.KernelDr0;
+ PDWORD Dr1 = &ksr.KernelDr1;
+ PDWORD Dr2 = &ksr.KernelDr2;
+ PDWORD Dr3 = &ksr.KernelDr3;
+ PDR7 Dr7 = (PDR7)&(ksr.KernelDr7);
+#else
+ CONTEXT Context;
+ PDWORD Dr0 = &Context.Dr0;
+ PDWORD Dr1 = &Context.Dr1;
+ PDWORD Dr2 = &Context.Dr2;
+ PDWORD Dr3 = &Context.Dr3;
+ PDR7 Dr7 = (PDR7)&(Context.Dr7);
+#endif
+
+ // ppc currently only supports 1
+ assert(Register == 1);
+
+
+#ifdef KERNEL
+ if (GetExtendedContext(hthd, &ksr))
+#else
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ if (GetThreadContext(hthd->rwHand, &Context))
+#endif
+ {
+
+ switch( Register ) {
+ case 0:
+ *Dr0 = 0;
+ Dr7->Len0 = 0;
+ Dr7->Rwe0 = 0;
+ Dr7->L0 = 0;
+ break;
+ case 1:
+ *Dr1 = 0;
+ Dr7->Len1 = 0;
+ Dr7->Rwe1 = 0;
+ Dr7->L1 = 0;
+ break;
+ case 2:
+ *Dr2 = 0;
+ Dr7->Len2 = 0;
+ Dr7->Rwe2 = 0;
+ Dr7->L2 = 0;
+ break;
+ case 3:
+ *Dr3 = 0;
+ Dr7->Len3 = 0;
+ Dr7->Rwe3 = 0;
+ Dr7->L3 = 0;
+ break;
+ }
+
+#ifdef KERNEL
+ ksr.KernelDr6 = 0;
+ SetExtendedContext(hthd, &ksr);
+#else
+ SetThreadContext( hthd->rwHand, &Context );
+#endif
+ }
+}
+
+
+BOOL
+DecodeSingleStepEvent(
+ HTHDX hthd,
+ DEBUG_EVENT *de,
+ PDWORD eventCode,
+ PDWORD subClass
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hthd - Supplies thread that has a single step exception pending
+
+ de - Supplies the DEBUG_EVENT structure for the exception
+
+ eventCode - Returns the remapped debug event id
+
+ subClass - Returns the remapped subClass id
+
+
+Return Value:
+
+ TRUE if event was a real single step or was successfully mapped
+ to a breakpoint. FALSE if a register breakpoint occurred which was
+ not expected.
+
+--*/
+{
+ return FALSE;
+}
diff --git a/private/windbg/newdm/procem.c b/private/windbg/newdm/procem.c
new file mode 100644
index 000000000..65657e5cd
--- /dev/null
+++ b/private/windbg/newdm/procem.c
@@ -0,0 +1,2490 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ procem.c
+
+Abstract:
+
+
+Author:
+
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifndef KERNEL
+#include <crash.h>
+extern BOOL CrashDump;
+#endif
+
+SetFile()
+
+#ifdef WIN32S
+// set true while in exception dbg evt
+extern BOOL fCanGetThreadContext;
+#endif
+
+
+#ifndef WIN32S
+extern DEBUG_ACTIVE_STRUCT DebugActiveStruct;
+extern PKILLSTRUCT KillQueue;
+extern CRITICAL_SECTION csKillQueue;
+#endif
+
+extern WT_STRUCT WtStruct;
+
+extern EXPECTED_EVENT masterEE, *eeList;
+
+extern HTHDX thdList;
+extern HPRCX prcList;
+extern CRITICAL_SECTION csThreadProcList;
+
+extern DEBUG_EVENT falseSSEvent;
+extern METHOD EMNotifyMethod;
+
+extern CRITICAL_SECTION csProcessDebugEvent;
+extern HANDLE hEventCreateProcess;
+extern HANDLE hEventNoDebuggee;
+extern HANDLE hDmPollThread;
+extern HANDLE hEventRemoteQuit;
+extern HANDLE hEventContinue;
+
+extern LPDM_MSG LpDmMsg;
+
+extern HPID hpidRoot;
+extern BOOL fUseRoot;
+extern BOOL fDisconnected;
+
+extern DMTLFUNCTYPE DmTlFunc;
+
+extern char nameBuffer[];
+VOID
+MethodContinueSS(
+ DEBUG_EVENT*,
+ HTHDX,
+ DWORD,
+ METHOD*
+ );
+
+BOOL
+MakeThreadSuspendItself(
+ HTHDX
+ );
+
+VOID
+ProcessIoctlGenericCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ );
+
+VOID
+ProcessIoctlCustomCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ );
+
+#ifdef KERNEL
+extern BOOL DmKdBreakIn;
+#endif
+
+#if defined(KERNEL)
+BOOL fSmartRangeStep = TRUE;
+#else
+BOOL fSmartRangeStep = FALSE;
+#endif
+
+
+void
+ActionRemoveBP(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD unused,
+ BREAKPOINT* bp
+ )
+{
+ Unreferenced( de );
+ Unreferenced( hthd );
+
+ RemoveBP(bp);
+}
+
+
+
+
+VOID
+ProcessCreateProcessCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ Create a process requested by the EM.
+
+Arguments:
+
+ hprc -
+
+ hthd -
+
+ lpdbb -
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XOSD xosd = xosdNone;
+
+ Unreferenced( hprc );
+ Unreferenced( hthd );
+
+ DEBUG_PRINT_2(
+ "ProcessCreateProcessCmd called with HPID=%d, (sizeof(HPID)=%d)",
+ lpdbb->hpid, sizeof(HPID));
+
+ hpidRoot = lpdbb->hpid;
+ fUseRoot = TRUE;
+
+ Reply(0, &xosd, lpdbb->hpid);
+
+ return;
+} /* ProcessCreateProcessCmd() */
+
+DWORD
+ProcessProcStatCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPPST lppst = (LPPST)LpDmMsg->rgb;
+
+ Unreferenced( lpdbb );
+
+ DEBUG_PRINT("ProcessProcStatCmd\n");
+
+ lppst->dwProcessID = hprc->pid;
+ sprintf(lppst->rgchProcessID, "%5d", hprc->pid);
+
+ /*
+ * Check if any of this process's threads are running
+ */
+
+ if (hprc->pstate & ps_exited) {
+ lppst->dwProcessState = pstExited;
+ strcpy(lppst->rgchProcessState, "Exited");
+ } else if (hprc->pstate & ps_dead) {
+ lppst->dwProcessState = pstDead;
+ strcpy(lppst->rgchProcessState, "Dead");
+ } else {
+ lppst->dwProcessState = pstRunning;
+ strcpy(lppst->rgchProcessState, "Running");
+
+ EnterCriticalSection(&csThreadProcList);
+ for (hthd = (HTHDX)hprc->hthdChild;hthd;hthd=hthd->nextSibling) {
+ if (hthd->tstate & ts_stopped) {
+ lppst->dwProcessState = pstStopped;
+ strcpy(lppst->rgchProcessState, "Stopped");
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ }
+
+ return sizeof(PST);
+}
+
+
+DWORD
+ProcessThreadStatCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPTST lptst = (LPTST) LpDmMsg->rgb;
+ XOSD xosd = xosdNone;
+
+#ifndef KERNEL
+ typedef NTSTATUS (* QTHREAD)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
+
+ NTSTATUS Status;
+ THREAD_BASIC_INFORMATION ThreadBasicInfo;
+ QTHREAD Qthread;
+ DWORD dw;
+#endif // KERNEL
+
+
+ Unreferenced( hprc );
+ DEBUG_PRINT("ProcessThreadStatCmd : ");
+
+#ifdef KERNEL
+
+ assert(hthd != 0);
+
+#else // KERNEL
+
+ if (!hthd) {
+ WaitForSingleObject(hprc->hEventCreateThread, INFINITE);
+ hthd = HTHDXFromHPIDHTID(lpdbb->hpid, lpdbb->htid);
+ assert(hthd != 0);
+ if (!hthd) {
+ LpDmMsg->xosdRet = xosdInvalidThread;
+ return sizeof(TST);
+ }
+ }
+
+#endif // KERNEL
+
+
+ ZeroMemory(lptst, sizeof(TST));
+
+#ifdef KERNEL
+
+ lptst->dwThreadID = hthd->tid;
+ sprintf(lptst->rgchThreadID, "%5d", lptst->dwThreadID);
+
+ lptst->dwSuspendCount = 0;
+ lptst->dwSuspendCountMax = 0;
+ lptst->dwPriority = 1;
+ lptst->dwPriorityMax = 1;
+ sprintf(lptst->rgchPriority, "%2d", lptst->dwPriority);
+
+#else // !KERNEL
+
+ if (CrashDump) {
+ lptst->dwThreadID = hthd->CrashThread.ThreadId;
+ } else {
+ lptst->dwThreadID = hthd->tid;
+ }
+
+ sprintf(lptst->rgchThreadID, "%5d", lptst->dwThreadID);
+
+ if (CrashDump) {
+ lptst->dwSuspendCount = hthd->CrashThread.SuspendCount;
+ } else {
+ dw = SuspendThread(hthd->rwHand);
+ if (dw != 0xffffffff) {
+ lptst->dwSuspendCount = dw;
+ ResumeThread(hthd->rwHand);
+ } else {
+ switch (GetLastError()) {
+ case (DWORD)STATUS_SUSPEND_COUNT_EXCEEDED:
+ lptst->dwSuspendCount = MAXIMUM_SUSPEND_COUNT;
+ break;
+
+ case (DWORD)STATUS_THREAD_IS_TERMINATING:
+ lptst->dwSuspendCount = 0;
+ break;
+
+ default:
+ lptst->dwSuspendCount = 0;
+ xosd = xosdInvalidThread;
+ }
+ }
+ }
+ lptst->dwSuspendCountMax = MAXIMUM_SUSPEND_COUNT;
+
+ if (CrashDump) {
+ dw = hthd->CrashThread.PriorityClass;
+ } else {
+ dw = GetPriorityClass(hprc->rwHand);
+ }
+
+ if (!dw) {
+
+ xosd = xosdInvalidThread;
+
+ } else {
+
+ switch (dw) {
+
+ case IDLE_PRIORITY_CLASS:
+ lptst->dwPriority = 4;
+ lptst->dwPriorityMax = 15;
+ break;
+
+ case NORMAL_PRIORITY_CLASS:
+ lptst->dwPriority = 9;
+ lptst->dwPriorityMax = 15;
+ break;
+
+ case HIGH_PRIORITY_CLASS:
+ lptst->dwPriority = 13;
+ lptst->dwPriorityMax = 15;
+ break;
+
+ case REALTIME_PRIORITY_CLASS:
+ lptst->dwPriority = 4;
+ lptst->dwPriorityMax = 31;
+ break;
+ }
+
+ if (CrashDump) {
+ dw = hthd->CrashThread.Priority;
+ } else {
+ dw = GetThreadPriority(hthd->rwHand);
+ }
+ if (dw == THREAD_PRIORITY_ERROR_RETURN) {
+ xosd = xosdInvalidThread;
+ } else {
+ lptst->dwPriority += dw;
+ if ((long)lptst->dwPriority > (long)lptst->dwPriorityMax) {
+ lptst->dwPriority = lptst->dwPriorityMax;
+ } else if ((long)lptst->dwPriority < (long)(lptst->dwPriorityMax - 15)) {
+ lptst->dwPriority = lptst->dwPriorityMax - 15;
+ }
+ sprintf(lptst->rgchPriority, "%2d", lptst->dwPriority);
+ }
+ }
+
+#endif // !KERNEL
+
+ if (hthd->tstate & ts_running) {
+ lptst->dwState = tstRunning;
+ strcpy(lptst->rgchState, "Running");
+ } else if (hthd->tstate & ts_stopped) {
+ lptst->dwState = tstStopped;
+ if (hthd->tstate & ts_frozen) {
+ lptst->dwSuspendCount = 1;
+ }
+ strcpy(lptst->rgchState, "Stopped");
+ } else if (hthd->tstate & ts_dead) {
+ lptst->dwState = tstExiting;
+ strcpy(lptst->rgchState, "Exiting");
+ } else if (hthd->tstate & ts_destroyed) {
+ lptst->dwState = tstDead;
+ strcpy(lptst->rgchState, "Dead");
+ } else {
+ lptst->dwState = tstRunnable;
+ strcpy(lptst->rgchState, "Pre-run");
+ }
+
+
+ if (hthd->tstate & ts_rip ) {
+ lptst->dwState |= tstRip;
+ strcat(lptst->rgchState, ", RIPped");
+ } else if (hthd->tstate & ts_first) {
+ lptst->dwState |= tstExcept1st;
+ strcat(lptst->rgchState, ", 1st chance");
+ } else if (hthd->tstate & ts_second) {
+ lptst->dwState |= tstExcept2nd;
+ strcat(lptst->rgchState, ", 2nd chance");
+ }
+
+
+ if (hthd->tstate & ts_frozen) {
+ lptst->dwState |= tstFrozen;
+ strcat(lptst->rgchState, ", suspended");
+ }
+
+ lptst->dwTeb = 0;
+#ifndef KERNEL
+ if (CrashDump) {
+ lptst->dwTeb = hthd->CrashThread.Teb;
+ } else {
+ Qthread = (QTHREAD)GetProcAddress( GetModuleHandle( "ntdll.dll" ),
+ "NtQueryInformationThread" );
+ if (Qthread) {
+ Status = Qthread( hthd->rwHand,
+ ThreadBasicInformation,
+ &ThreadBasicInfo,
+ sizeof(ThreadBasicInfo),
+ NULL
+ );
+ if (NT_SUCCESS(Status)) {
+ lptst->dwTeb = (DWORD)ThreadBasicInfo.TebBaseAddress;
+ }
+ }
+ }
+#endif // !KERNEL
+
+ LpDmMsg->xosdRet = xosd;
+ return sizeof(TST);
+}
+
+
+/*** ProcessLoadCmd
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Process a load command from the debugger
+*/
+
+void
+ProcessLoadCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+#ifdef KERNEL
+
+ LPPRL lpprl = (LPPRL)(lpdbb->rgbVar);
+ LPSTR p;
+ char progname[MAX_PATH];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+
+ ValidateHeap();
+ if (fDisconnected) {
+ DmKdBreakIn = TRUE;
+ SetEvent( hEventRemoteQuit );
+ LpDmMsg->xosdRet = xosdNone;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+ }
+
+ // The debugger will pass us a quoted string version of the name. Parse out the quotes.
+
+ for (p=lpprl->lszCmdLine+1; p && *p && *p !='"'; p++) ;
+ if (*p=='"') {
+ *p = '\0';
+ }
+ _splitpath( lpprl->lszCmdLine+1, NULL, NULL, fname, ext );
+ if (_stricmp(ext,"exe") != 0) {
+ strcpy(ext, "exe" );
+ }
+ _makepath( progname, NULL, NULL, fname, ext );
+
+ if ((_stricmp(progname,KERNEL_IMAGE_NAME)==0) ||
+ (_stricmp(progname,OSLOADER_IMAGE_NAME)==0)) {
+
+ ValidateHeap();
+ if (!DmKdConnectAndInitialize( progname )) {
+ LpDmMsg->xosdRet = xosdFileNotFound;
+ } else {
+ LpDmMsg->xosdRet = xosdNone;
+ }
+
+ } else {
+ LpDmMsg->xosdRet = xosdFileNotFound;
+ }
+
+ ValidateHeap();
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ ValidateHeap();
+ return;
+
+#else // !KERNEL
+
+ char * szApplicationName;
+ char * szCommandLine=NULL;
+ char ** szEnvironment=NULL;
+ char * szCurrentDirectory=NULL;
+ DWORD creationFlags;
+ STARTUPINFO si;
+ XOSD xosd;
+ LPPRL lpprl = (LPPRL)(lpdbb->rgbVar);
+ HPRCX hprc1;
+ HPRCX hprcT;
+
+
+ fDisconnected = FALSE;
+
+ /*
+ * For various strange reasons the list of processes may not have
+ * been completely cleared. If not do so now
+ */
+
+ for (hprc1 = prcList; hprc1 != hprcxNull; hprc1 = hprcT) {
+ hprcT = hprc1->next;
+
+ if (hprc1->pstate & ps_dead) {
+ FreeProcess( hprc1, FALSE );
+ }
+ }
+
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+
+ si.dwFlags = STARTF_USESHOWWINDOW;
+
+#ifdef OSDEBUG4
+ switch ( lpprl->dwChildFlags & (ulfMinimizeApp | ulfNoActivate) )
+#else
+ switch ( lpprl->ulChildFlags & (ulfMinimizeApp | ulfNoActivate) )
+#endif
+ {
+ case 0:
+ si.wShowWindow = SW_SHOWNORMAL;
+ break;
+ case ulfMinimizeApp:
+ si.wShowWindow = SW_SHOWMINIMIZED;
+ break;
+ case ulfNoActivate:
+ si.wShowWindow = SW_SHOWNOACTIVATE;
+ break;
+ case (ulfMinimizeApp | ulfNoActivate):
+ si.wShowWindow = SW_SHOWMINNOACTIVE;
+ break;
+ }
+
+#ifdef OSDEBUG4
+ creationFlags = (lpprl->dwChildFlags & ulfMultiProcess)?
+#else
+ creationFlags = (lpprl->ulChildFlags & ulfMultiProcess)?
+#endif
+ DEBUG_PROCESS :
+ DEBUG_ONLY_THIS_PROCESS;
+
+#ifdef OSDEBUG4
+ if (lpprl->dwChildFlags & ulfWowVdm) {
+#else
+ if (lpprl->ulChildFlags & ulfWowVdm) {
+#endif
+ creationFlags |= CREATE_SEPARATE_WOW_VDM;
+ }
+
+ szApplicationName = lpprl->lszCmdLine;
+
+ DEBUG_PRINT_2("Load Program: \"%s\" HPRC=0x%x\n",
+ szApplicationName, (DWORD) hprc);
+ // M00BUG -- Reply on load failure needs to be done here
+
+ xosd = Load(hprc,
+ szApplicationName,
+ szCommandLine,
+ (LPVOID)0, // &lc->processAttributes,
+ (LPVOID)0, // &lc->threadAttributes,
+ creationFlags,
+#ifdef OSDEBUG4
+ (lpprl->dwChildFlags & ulfInheritHandles) != 0,
+#else
+ (lpprl->ulChildFlags & ulfInheritHandles) != 0,
+#endif
+ szEnvironment,
+ szCurrentDirectory,
+ &si );
+
+ /*
+ ** If the load failed then we need to reply right now. Otherwise
+ ** we will delay the reply until we get the All Dlls loaded exception.
+ */
+
+ if (!fUseRoot || xosd != xosdNone) {
+ Reply(0, &xosd, lpdbb->hpid);
+ }
+
+ return;
+#endif // !KERNEL
+}
+
+
+DWORD
+ProcessUnloadCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ DEBUG_EVENT devent, *pde=&devent;
+ HTHDXSTRUCT tHthdS;
+ HTHDX hthdT;
+
+ Unreferenced( lpdbb );
+
+ DEBUG_PRINT("ProcessUnloadCmd called.\n");
+
+ /*
+ * Verify we got a valid HPRCX
+ */
+
+ if (!hprc) {
+ return FALSE;
+ }
+
+ if (hprc->pstate != (ps_root | ps_destroyed)) {
+
+ if (hprc->hthdChild != 0) {
+ tHthdS = *((HTHDX)(hprc->hthdChild));
+ } else {
+ memset( &tHthdS, 0, sizeof( HTHDXSTRUCT ) );
+ tHthdS.hprc = hprc;
+ tHthdS.rwHand = (HANDLE)-1;
+ }
+
+ /*
+ * Pump back destruction notifications
+ */
+ pde->dwDebugEventCode = DESTROY_THREAD_DEBUG_EVENT;
+ pde->dwProcessId = hprc->pid;
+
+ for(hthd=hprc->hthdChild; hthd; hthd = hthdT){
+
+ hthdT = hthd->nextSibling;
+
+ if (hthd->rwHand != (HANDLE)INVALID) {
+ pde->dwThreadId = hthd->tid;
+ NotifyEM(pde, hthd, 0, hprc);
+ //
+ // The session manager "owns" this handle...
+ //
+ //CloseHandle(hthd->rwHand);
+ }
+ FreeHthdx(hthd);
+ }
+
+ hprc->hthdChild = NULL;
+
+#ifndef KERNEL
+ if (hprc->rwHand != (HANDLE)INVALID && hprc->CloseProcessHandle) {
+ CloseHandle(hprc->rwHand);
+ hprc->rwHand = (HANDLE)INVALID;
+ }
+#endif // KERNEL
+
+ pde->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
+ pde->u.ExitProcess.dwExitCode = hprc->dwExitCode;
+ NotifyEM(pde, &tHthdS, 0, hprc);
+
+ pde->dwDebugEventCode = DESTROY_PROCESS_DEBUG_EVENT;
+ NotifyEM(pde, &tHthdS, 0, hprc);
+ }
+
+ return (DWORD) TRUE;
+} /* ProcessUnloadCmd() */
+
+
+XOSD
+FreeProcess(
+ HPRCX hprc,
+ BOOL fKillRoot
+ )
+{
+ HPRCX chp;
+ HPRCX * pphp;
+ PBREAKPOINT pbp;
+ PBREAKPOINT pbpT;
+ int iDll;
+
+ EnterCriticalSection(&csThreadProcList);
+
+ pphp = &prcList->next;
+ chp = *pphp;
+
+ while (chp) {
+ if (chp != hprc) {
+ pphp = &chp->next;
+ } else {
+#ifndef KERNEL
+ if (chp->rwHand != (HANDLE)INVALID && chp->CloseProcessHandle) {
+ CloseHandle(chp->rwHand);
+ chp->rwHand = (HANDLE)INVALID;
+ }
+#endif
+ RemoveExceptionList(chp);
+
+ for (pbp = BPNextHprcPbp(hprc, NULL); pbp; pbp = pbpT) {
+ pbpT = BPNextHprcPbp(hprc, pbp);
+ RemoveBP(pbp);
+ }
+
+ for (iDll = 0; iDll < chp->cDllList; iDll++) {
+ DestroyDllLoadItem(&chp->rgDllList[iDll]);
+ }
+ free(chp->rgDllList);
+
+ if (!fKillRoot && (chp->pstate & ps_root)) {
+ chp->pid = (PID)-1;
+ chp->pstate = ps_root | ps_destroyed;
+ ResetEvent(chp->hExitEvent);
+ pphp = &chp->next;
+ } else {
+ CloseHandle(chp->hExitEvent);
+ *pphp = chp->next;
+ free(chp);
+ }
+ }
+ chp = *pphp;
+ }
+
+ /*
+ * special case:
+ * if everything has been deleted except for the "sticky"
+ * root process, delete it now, and set fUseRoot.
+ * The hpid remains the same. If that changes, the EM needs
+ * to send a DestroyPid/CreatePid to change it here.
+ */
+ if (prcList->next
+ && prcList->next->next == NULL
+ && prcList->next->pstate == (ps_root | ps_destroyed)) {
+
+ CloseHandle(prcList->next->hExitEvent);
+ free(prcList->next);
+ prcList->next = NULL;
+ fUseRoot = TRUE;
+ }
+
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ return xosdNone;
+} /* FreeProcess() */
+
+
+XOSD
+HandleWatchpoints(
+ HPRCX hprcx,
+ BOOL fSet,
+ LPBPIS lpbpis,
+ LPDWORD lpdwNotification
+ )
+{
+ BOOL fRet;
+ ADDR addr = {0};
+ HTHDX hthdx;
+ XOSD xosd = xosdNone;
+ PBREAKPOINT pbp;
+ HANDLE hWalk;
+
+ hthdx = !lpbpis->fOneThd ? 0:
+ HTHDXFromHPIDHTID(hprcx->hpid, lpbpis->htid);
+
+ switch ( lpbpis->bptp ) {
+
+ case bptpDataR:
+ case bptpDataW:
+ case bptpDataC:
+ case bptpDataExec:
+
+ if (lpbpis->data.cb != 0) {
+
+ addr = lpbpis->data.addr;
+ fRet = ADDR_IS_FLAT(addr) ||
+ TranslateAddress(hprcx, hthdx, &addr, TRUE);
+ assert(fRet);
+ if (!fRet) {
+ xosd = xosdBadAddress;
+ break;
+ }
+ }
+
+ if (fSet) {
+ hWalk = SetWalk(hprcx,
+ hthdx,
+ GetAddrOff(addr),
+ lpbpis->data.cb,
+ lpbpis->bptp );
+ if (!hWalk) {
+ xosd = xosdUnknown;
+ } else {
+ pbp = GetNewBp(hprcx,
+ hthdx,
+ lpbpis->bptp,
+ lpbpis->bpns,
+ NULL,
+ NULL,
+ NULL);
+ assert(pbp);
+ pbp->hWalk = hWalk;
+ AddBpToList(pbp);
+ *lpdwNotification = (DWORD)pbp;
+ }
+ } else {
+ assert((LPVOID)*lpdwNotification);
+ pbp = (PBREAKPOINT)(*lpdwNotification);
+ assert(pbp->hWalk);
+ if (RemoveWalk(pbp->hWalk)) {
+ RemoveBP((PBREAKPOINT)*lpdwNotification);
+ } else {
+ xosd = xosdUnknown;
+ }
+ }
+
+ break;
+
+
+ case bptpRange:
+#if 0
+ addr = lpbpis->rng.addr;
+ fRet = ADDR_IS_FLAT(addr) ||
+ TranslateAddress(hprcx, hthdx, &addr, TRUE);
+ assert(fRet);
+ if (!fRet) {
+ xosd = xosdBadAddress;
+ } else {
+ if (fSet) {
+ if (!SetWalkRange( hprcx, hthdx, GetAddrOff(addr),
+ GetAddrOff(addr)+lpbpis->rng.cb)) {
+ xosd = xosdUnknown;
+ }
+ } else {
+ if ( !RemoveWalkRange( hprcx, hthdx, GetAddrOff(addr),
+ GetAddrOff(addr)+lpbpis->rng.cb)) {
+ xosd = xosdUnknown;
+ }
+ }
+ }
+ break;
+#endif
+
+ case bptpRegC:
+ case bptpRegR:
+ case bptpRegW:
+
+ default:
+
+ xosd = xosdUnsupported;
+ break;
+ }
+
+ return xosd;
+}
+
+
+XOSD
+HandleBreakpoints(
+ HPRCX hprcx,
+ BOOL fSet,
+ LPBPIS lpbpis,
+ LPDWORD lpdwNotification
+ )
+{
+ LPADDR lpaddr;
+ HTHDX hthdx;
+ BREAKPOINT *bp;
+ XOSD xosd = xosdNone;
+
+ switch (lpbpis->bptp) {
+ case bptpExec:
+ lpaddr = &lpbpis->exec.addr;
+ break;
+
+ case bptpMessage:
+ lpaddr = &lpbpis->msg.addr;
+ break;
+
+ case bptpMClass:
+ lpaddr = &lpbpis->mcls.addr;
+ break;
+ }
+
+ if (fSet) {
+ DPRINT(5, ("Set a breakpoint: %d @%08x:%04x:%08x",
+ ADDR_IS_FLAT(*lpaddr), lpaddr->emi,
+ lpaddr->addr.seg, lpaddr->addr.off));
+
+ hthdx = lpbpis->fOneThd? 0 :
+ HTHDXFromHPIDHTID(hprcx->hpid, lpbpis->htid);
+
+ bp = SetBP(hprcx, hthdx, lpbpis->bptp, lpbpis->bpns, lpaddr, 0);
+
+ if (bp == NULL) {
+ xosd = xosdUnknown;
+ } else {
+ *lpdwNotification = (DWORD)bp;
+ }
+
+ } else {
+
+ DEBUG_PRINT("Clear a breakpoint");
+
+ hthdx = lpbpis->fOneThd? 0 :
+ HTHDXFromHPIDHTID(hprcx->hpid, lpbpis->htid);
+
+ bp = FindBP(hprcx, hthdx, lpbpis->bptp, lpbpis->bpns, lpaddr, TRUE);
+
+ if (bp != NULL) {
+ assert((DWORD)bp == *lpdwNotification);
+ RemoveBP(bp);
+ } else if ( (hprcx->pstate & (ps_destroyed | ps_killed)) == 0) {
+ // Don't fail if this process is already trashed.
+ xosd = xosdUnknown;
+ }
+ }
+
+ return xosd;
+}
+
+
+VOID
+ProcessBreakpointCmd(
+ HPRCX hprcx,
+ HTHDX hthdx,
+ LPDBB lpdbb
+ )
+{
+ XOSD xosd;
+ XOSD * lpxosd;
+ LPDWORD lpdwMessage;
+ LPDWORD lpdwNotification;
+ LPBPS lpbps = (LPBPS)lpdbb->rgbVar;
+ LPBPIS lpbpis;
+ UINT i;
+ DWORD SizeofBps = SizeofBPS(lpbps);
+
+ if (!lpbps->cbpis) {
+ // enable or disable all extant bps.
+ // is this used?
+ assert(0 && "clear/set all BPs not implemented in DM");
+ xosd = xosdUnsupported;
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+
+#ifdef KERNEL
+ if (!ApiIsAllowed) {
+ xosd = xosdUnknown;
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+#endif
+
+ lpdwMessage = DwMessage(lpbps);
+ lpxosd = RgXosd(lpbps);
+ lpdwNotification = DwNotification(lpbps);
+ lpbpis = RgBpis(lpbps);
+
+ // walk the list of breakpoint commands
+
+ for (i = 0; i < lpbps->cbpis; i++) {
+ switch( lpbpis[i].bptp ) {
+ case bptpDataC:
+ case bptpDataR:
+ case bptpDataW:
+ case bptpDataExec:
+ case bptpRegC:
+ case bptpRegR:
+ case bptpRegW:
+
+ //
+ // dispatch to watchpoint handler
+ //
+ lpxosd[i] = HandleWatchpoints(hprcx, lpbps->fSet, &lpbpis[i],
+ &lpdwNotification[i]);
+ break;
+
+ case bptpMessage:
+ case bptpMClass:
+
+ //
+ // handle as address BP - let debugger handle the details
+ //
+
+ case bptpExec:
+ lpxosd[i] = HandleBreakpoints(hprcx, lpbps->fSet, &lpbpis[i],
+ &lpdwNotification[i]);
+ break;
+
+ case bptpInt:
+ case bptpRange:
+ // ???
+ assert(0 && "don't know what these are supposed to do");
+ break;
+ }
+ }
+
+ // send whole structure back to EM
+
+ LpDmMsg->xosdRet = xosdNone;
+ memcpy(LpDmMsg->rgb, lpbps, SizeofBps);
+ Reply(SizeofBps, LpDmMsg, lpdbb->hpid);
+}
+
+
+
+VOID
+ProcessReadMemoryCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to a request from the EM to read
+ the debuggees memory. It will take care of any address translations
+ which need to be done and request the read operation from the OS.
+
+Arguments:
+
+ hprc - Supplies the handle to the process descriptor
+
+ hthd - Supplies the handle to the thread descriptor
+
+ lpdbb - Supplies the request packet.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPRWP lprwp = (LPRWP) lpdbb->rgbVar;
+ DWORD cb = (DWORD) lprwp->cb;
+ LPDM_MSG lpm = (LPDM_MSG)malloc( cb + sizeof(DWORD) + FIELD_OFFSET(DM_MSG, rgb));
+ char * buffer = lpm->rgb + sizeof(DWORD);
+ DWORD length;
+
+ DPRINT(5, ("ProcessReadMemoryCmd : %x %d:%04x:%08x %d\n", hprc,
+ lprwp->addr.emi, lprwp->addr.addr.seg,
+ lprwp->addr.addr.off, cb));
+
+
+ if (AddrReadMemory(hprc, hthd, &(lprwp->addr), buffer, cb, &length) == 0) {
+ lpm->xosdRet = xosdUnknown;
+ Reply(0, lpm, lpdbb->hpid);
+ } else {
+ lpm->xosdRet = xosdNone;
+ *((DWORD *) (lpm->rgb)) = length;
+ Reply( length + sizeof(DWORD), lpm, lpdbb->hpid);
+ }
+ free(lpm);
+ return;
+} /* ProcessReadMemoryCmd() */
+
+
+
+VOID
+ProcessWriteMemoryCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ this routine is called to case a write into a debuggess memory.
+
+Arguments:
+
+ hprc - Supplies a handle to the process to write memory in
+
+ hthd - Supplies a handle to a thread
+
+ lpdbb - points to data for the command
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ LPRWP lprwp = (LPRWP)lpdbb->rgbVar;
+ DWORD cb = lprwp->cb;
+ char * buffer = lprwp->rgb;
+
+ HANDLE rwHand;
+ DWORD length;
+ DWORD offset;
+ XOSD xosd = xosdUnknown;
+ BP_UNIT instr;
+ BREAKPOINT *bp;
+
+ DEBUG_PRINT("ProcessWriteMemoryCmd called\n");
+
+ /*
+ * Sanitize the memory block before writing it into memory :
+ * ie: replace any breakpoints that might be in the block
+ */
+
+ for(bp=bpList->next; bp; bp=bp->next) {
+ if (BPInRange(hprc, hthd, bp, &lprwp->addr, cb, &offset, &instr)) {
+ bp->instr1 = *((BP_UNIT *) (buffer + offset));
+ *((BP_UNIT *) (buffer + offset)) = BP_OPCODE;
+ }
+ }
+
+ rwHand = hprc->rwHand;
+
+ if (AddrWriteMemory(hprc, hthd, &lprwp->addr, buffer, cb, &length)) {
+ xosd = xosdNone;
+ }
+
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+} /* ProcessWriteMemoryCmd() */
+
+#ifndef OSDEBUG4
+
+VOID
+ProcessGetFrameContextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called in response to a request to get the full
+ context of a thread.
+
+Arguments:
+
+ hprc - Supplies the handle of process for the thread
+
+ hthd - Supplies the handle of the thread
+
+ lpdbb - Supplies pointer to argument area for request
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKNONVOLATILE_CONTEXT_POINTERS lpctxptrs;
+ LPCONTEXT lpregs;
+ UINT frame = *(UINT *)lpdbb->rgbVar;
+
+
+ Unreferenced(hprc);
+
+ DEBUG_PRINT( "ProcessGetFrameContextCmd :\n");
+
+ //
+ // zero out the context pointers
+ //
+ lpregs = &( (PFRAME_INFO)LpDmMsg->rgb )->frameRegs;
+ lpctxptrs = &( (PFRAME_INFO)LpDmMsg->rgb )->frameRegPtrs;
+ ClearContextPointers(lpctxptrs);
+
+ if (hthd == 0
+#ifdef WIN32S
+ // Can't yet get thread context within
+ // a non-exception event.
+ || ! fCanGetThreadContext
+#endif
+ )
+ {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ return;
+ }
+
+ lpregs->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+
+
+ if (!DbgGetThreadContext(hthd,lpregs)) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid);
+ return;
+ }
+
+ //
+ // For each frame before the target, we do a walk-back
+ //
+
+ //
+ // ----> this MUST be fixed for user mode... for now it is broken
+ // ----> when i get time i'll fix it
+ // ----> this needs to call imagehlp just like the em, but it can't
+ // ----> so it has to call the em or this whole thing needs to be
+ // ----> moved to the em
+ //
+#ifdef KERNEL
+ while (frame != 0) {
+
+ frame--;
+ if (!ProcessFrameStackWalkNextCmd(hprc,
+ hthd,
+ lpregs,
+ lpctxptrs)) {
+ LpDmMsg->xosdRet = xosdEndOfStack;
+ Reply( 0, LpDmMsg, lpdbb->hpid);
+ }
+
+ }
+#endif
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(FRAME_INFO), LpDmMsg, lpdbb->hpid );
+
+ return;
+} /* ProcessGetFrameContextCmd() */
+#endif
+
+
+
+VOID
+ProcessGetContextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called in response to a request to get the full
+ context of a thread for a particular frame.
+ The current frame is 0. They count back positively; caller is 1.
+
+Arguments:
+
+ hprc - Supplies the handle of process for the thread
+
+ hthd - Supplies the handle of the thread
+
+ lpdbb - Supplies pointer to argument area for request
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPCONTEXT lpreg = (LPCONTEXT)LpDmMsg->rgb;
+ BOOL rval;
+
+
+ Unreferenced(hprc);
+
+ DEBUG_PRINT( "ProcessGetContextCmd\n");
+
+ if (hthd == 0
+#ifdef WIN32S
+ // Can't yet get thread context within
+ // a non-exception event.
+ || ! fCanGetThreadContext
+#endif
+ )
+ {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ return;
+ }
+
+ lpreg->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+
+ if ((hthd->tstate & ts_frozen) && hthd->pss) {
+ memcpy(lpreg, &hthd->pss->context, sizeof(CONTEXT));
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(CONTEXT), LpDmMsg, lpdbb->hpid );
+ } else if ((hthd->tstate & ts_stopped)
+#ifdef KERNEL
+ &&(!hthd->fContextStale)
+#endif
+ ) {
+ memcpy(lpreg, &hthd->context, sizeof(CONTEXT));
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(CONTEXT), LpDmMsg, lpdbb->hpid );
+ } else if (DbgGetThreadContext(hthd,lpreg)) {
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(CONTEXT), LpDmMsg, lpdbb->hpid );
+ } else {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ }
+ return;
+} /* ProcessGetContextCmd() */
+
+
+VOID
+ProcessSetContextCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This function is used to update the register set for a thread
+
+Arguments:
+
+ hprc - Supplies a handle to a process
+
+ hthd - Supplies the handle to the thread to be updated
+
+ lpdbb - Supplies the set of context information
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPCONTEXT lpcxt = (LPCONTEXT)(lpdbb->rgbVar);
+ XOSD xosd = xosdNone;
+ ADDR addr;
+
+ Unreferenced(hprc);
+
+ DPRINT(5, ("ProcessSetContextCmd : "));
+
+ lpcxt->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+
+ if ((hthd->tstate & ts_frozen) && hthd->pss) {
+
+ memcpy(&hthd->pss->context, lpcxt, sizeof(CONTEXT));
+
+ } else {
+ memcpy(&hthd->context, lpcxt, sizeof(CONTEXT));
+
+ if (hthd->tstate & ts_stopped) {
+ hthd->fContextDirty = TRUE;
+ /*
+ * If we change the program counter then we may be pointing
+ * at a different breakpoint. If so then setup to point
+ * to the new breakpoint
+ */
+
+ AddrFromHthdx(&addr, hthd);
+ SetBPFlag(hthd, FindBP(hthd->hprc, hthd, bptpExec, (BPNS)-1, &addr, FALSE));
+#ifndef KERNEL
+ } else if (hthd->fWowEvent) {
+ WOWSetThreadContext(hthd, lpcxt);
+#endif
+ } else {
+ DbgSetThreadContext(hthd, lpcxt);
+ }
+ }
+
+ Reply(0, &xosd, lpdbb->hpid);
+
+ return;
+} /* ProcessSetContextCmd() */
+
+
+
+
+#if defined(DOLPHIN)
+void
+PushRunningThread(
+ HTHDX hthd,
+ HTHDX hthdFocus
+ )
+/*++
+
+Routine Description:
+
+ Someone's trying to step a thread that didn't stop. We must push
+ the stopped thread otherwise it will hit the same BP it's currently at.
+
+Arguments:
+
+ hthd - the stopped thread
+
+ hthdFocus - the thread we want to step/go
+
+Return Value:
+
+ none
+
+--*/
+{
+ BREAKPOINT* bp;
+ if (bp = AtBP(hthd)) {
+ if (bp != EMBEDDED_BP && bp->isStep) {
+ // Hit SS again
+ } else {
+ /*
+ * We are recovering from a breakpoint, so restore the
+ * original instruction, single step and then finally go.
+ */
+
+ METHOD *ContinueSSMethod;
+
+ DEBUG_PRINT("***Recovering from a breakpoint");
+
+ ClearBPFlag(hthd);
+ if (bp == EMBEDDED_BP) {
+
+ IncrementIP(hthd);
+
+ } else {
+
+ ContinueSSMethod = (METHOD*)malloc(sizeof(METHOD));
+ ContinueSSMethod->notifyFunction = (ACVECTOR)MethodContinueSS;
+ ContinueSSMethod->lparam = ContinueSSMethod;
+ ContinueSSMethod->lparam2 = bp;
+
+ RestoreInstrBP(hthd, bp);
+ SingleStepEx(hthd, ContinueSSMethod, FALSE, FALSE, FALSE);
+
+ }
+ }
+ }
+
+ /* Also ensure that the focus thread has accurate context */
+ if (hthdFocus != NULL) {
+ hthdFocus->context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
+ DmpGetThreadContext( hthdFocus, &hthdFocus->context );
+ }
+}
+#endif // DOLPHIN
+
+
+VOID
+ProcessSingleStepCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This command is called to do a single step of the processor. If
+ calls are made then it will step into the command.
+
+Arguments:
+
+ hprc - Supplies process handle
+
+ hthd - Supplies thread handle
+
+ lpdbb - Supplies information on command
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPEXOP lpexop = (LPEXOP)lpdbb->rgbVar;
+ XOSD xosd = xosdNone;
+
+ Unreferenced( hprc );
+
+ DEBUG_PRINT("ProcessSingleStepCmd called\n");
+
+
+ if (hprc->pstate & ps_dead) {
+ hprc->pstate |= ps_dead;
+ /*
+ * The process has exited, and we have
+ * announced the death of all its threads (but one).
+ * All that remains is to clean up the remains.
+ */
+
+ ProcessUnloadCmd(hprc, hthd, lpdbb);
+ Reply(0, &xosd, lpdbb->hpid);
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ return;
+ }
+
+#ifndef KERNEL
+ if (lpexop->fSetFocus) {
+ DmSetFocus(hprc);
+ }
+
+#if defined(DOLPHIN)
+ if (!(hthd->tstate & ts_stopped)) {
+ HTHDX lastHthd = HTHDXFromPIDTID(hprc->pid, hprc->lastTidDebugEvent);
+ PushRunningThread(lastHthd, hthd);
+ }
+ /* Catch any exception that changes flow of control */
+ RegisterExpectedEvent(hthd->hprc, (HTHDX)0,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ DONT_NOTIFY,
+ ActionExceptionDuringStep,
+ FALSE,
+ NULL);
+#endif // DOLPHIN
+#endif // !KERNEL
+
+
+ if (hthd->tstate & ts_stepping) {
+ xosd = xosdUnknown;
+ } else if (lpexop->fStepOver) {
+ StepOver(hthd, &EMNotifyMethod, FALSE, FALSE);
+ } else {
+ SingleStep(hthd, &EMNotifyMethod, FALSE, FALSE);
+ }
+
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+} /* ProcessSingleStepCmd() */
+
+
+
+VOID
+ProcessRangeStepCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to start a range step. This will continue
+ to do steps as long as the current PC is between the starting
+ and ending addresses
+
+Arguments:
+
+ hprc - Supplies the process handle to be stepped
+
+ hthd - Supples the thread handle to be stepped
+
+ lpdbb - Supples the information about the command
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPRST lprst = (LPRST)lpdbb->rgbVar;
+ XOSD xosd = xosdNone;
+
+ DEBUG_PRINT_2("RangeStep [%08x - %08x]\n", lprst->offStart, lprst->offEnd);
+
+ if (hprc->pstate & ps_dead) {
+
+ hprc->pstate |= ps_dead;
+ /*
+ * The process has exited, and we have
+ * announced the death of all its threads (but one).
+ * All that remains is to clean up the remains.
+ */
+
+ ProcessUnloadCmd(hprc, hthd, lpdbb);
+ Reply(0, &xosd, lpdbb->hpid);
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ return;
+ }
+
+ assert(hthd);
+
+
+#if !defined(KERNEL)
+#if defined(DOLPHIN)
+ if (!(hthd->tstate & ts_stopped)) {
+ HTHDX lastHthd = HTHDXFromPIDTID(hprc->pid, hprc->lastTidDebugEvent);
+ PushRunningThread(lastHthd, hthd);
+ }
+ /* Catch any exception that changes flow of control */
+ RegisterExpectedEvent(hthd->hprc, (HTHDX)0,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ DONT_NOTIFY,
+ ActionExceptionDuringStep,
+ FALSE,
+ NULL);
+#endif // DOLPHIN
+#endif // !KERNEL
+
+ RangeStep(hthd,
+ lprst->offStart,
+ lprst->offEnd,
+ !lprst->fInitialBP,
+ lprst->fStepOver
+ );
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+} /* ProcessRangeStepCmd() */
+
+#if 0
+
+VOID
+ProcessReturnStepCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ hprc - Supplies the process handle to be stepped
+ hthd - Supples the thread handle to be stepped
+ lpdbb - Supples the information about the command
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPRTRNSTP lprtrnstp = (LPRTRNSTP)lpdbb->rgbVar;
+ XOSD xosd = xosdNone;
+
+ Unreferenced( hprc );
+
+ if (hprc->pstate & ps_dead) {
+
+ hprc->pstate |= ps_dead;
+ /*
+ * The process has exited, and we have
+ * announced the death of all its threads (but one).
+ * All that remains is to clean up the remains.
+ */
+
+ ProcessUnloadCmd(hprc, hthd, lpdbb);
+ Reply(0, &xosd, lpdbb->hpid);
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ return;
+ }
+
+ if (lprtrnstp->exop.fSetFocus) {
+ DmSetFocus(hprc);
+ }
+
+#if defined(DOLPHIN)
+ if (!(hthd->tstate & ts_stopped)) {
+ HTHDX lastHthd = HTHDXFromPIDTID(hprc->pid, hprc->lastTidDebugEvent);
+ PushRunningThread(lastHthd, hthd);
+ }
+ /* Catch any exception that changes flow of control */
+ RegisterExpectedEvent(hthd->hprc, (HTHDX)0,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ DONT_NOTIFY,
+ ActionExceptionDuringStep,
+ FALSE,
+ NULL);
+#endif // DOLPHIN
+ ReturnStep(hthd, &EMNotifyMethod, FALSE, FALSE, &(lprtrnstp->addrRA), &(lprtrnstp->addrBase));
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+
+} /* ProcessReturnStepCmd() */
+#endif
+
+
+
+VOID
+ProcessContinueCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This function is used to cause a process to be executed.
+ It is called in response to a GO command.
+
+Arguments:
+
+ hprc - Supplies handle to process to execute
+
+ hthdd - Supplies handle to thread
+
+ lpdbb - Command buffer
+
+Return Value:
+
+ xosd Error code
+
+TODO:
+ Are there any times where we do not want to allow a GO command
+ to be executed.
+
+ Two other possible problems here that need to be deal with are:
+
+ 1. Single thread go commands
+
+ 2. The current thread not being the thread where the last debug
+ event occured. In this case the DoContinueDebugEvent
+ command SHOULD NOT WORK.
+
+--*/
+
+{
+ LPEXOP lpexop = (LPEXOP)lpdbb->rgbVar;
+ BREAKPOINT *bp;
+ XOSD xosd = xosdNone;
+ DEBUG_EVENT de;
+ HTHDXSTRUCT hthdS;
+ DWORD cs;
+
+ DPRINT(5, ("ProcessContinueCmd : pid=%08lx, tid=%08lx, hthd=%08lx",
+ hprc->pid, hthd ? hthd->tid : -1, hthd));
+
+#ifndef KERNEL
+ if (lpexop->fSetFocus) {
+ DmSetFocus(hprc);
+ }
+#endif
+
+ if (hprc->pstate & ps_connect) {
+ Reply(0, &xosd, lpdbb->hpid);
+ SetEvent( hEventContinue );
+ return;
+ }
+
+ //
+ // Don't enter during event processing, because we
+ // might be here before the DM has finished with the
+ // event we are responding to.
+ //
+ // Don't worry about new events during our processing,
+ // since they won't apply to this process.
+ //
+
+ EnterCriticalSection(&csProcessDebugEvent);
+ LeaveCriticalSection(&csProcessDebugEvent);
+
+ if (!hthd) {
+ WaitForSingleObject(hprc->hEventCreateThread, INFINITE);
+ hthd = HTHDXFromHPIDHTID(lpdbb->hpid, lpdbb->htid);
+ assert(hthd != 0);
+ if (!hthd) {
+#ifdef OSDEBUG4
+ xosd = xosdBadThread;
+#else
+ xosd = xosdInvalidThread;
+#endif
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+ }
+
+
+ if (hprc->pstate & ps_dead) {
+
+ hprc->pstate |= ps_dead;
+ //
+ // The process has exited, and we have announced
+ // the death of all its threads (but one).
+ // All that remains is to clean up the remains.
+ //
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ ProcessUnloadCmd(hprc, hthd, lpdbb);
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+
+
+ if (hthd->tstate & ts_dead) {
+
+ //
+ // Note that if a terminated thread is frozen
+ // then we do not send a destroy on it yet:
+ // ProcessAsyncGoCmd() deals with those cases.
+ //
+
+ hthdS = *hthd; // keep some info
+
+ //
+ // If it isn't frozen, destroy it.
+ //
+
+ if ( !(hthd->tstate & ts_frozen)) {
+ de.dwDebugEventCode = DESTROY_THREAD_DEBUG_EVENT;
+ NotifyEM(&de, hthd, 0, NULL);
+ FreeHthdx(hthd);
+ hprc->pstate &= ~ps_deadThread;
+ }
+
+ //
+ // if there are other dead threads (how??)
+ // put the deadThread bit back.
+ //
+
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ if (hthd->tstate & ts_dead) {
+ hprc->pstate |= ps_deadThread;
+ }
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdS.hprc->pid,
+ hthdS.tid,
+ DBG_CONTINUE,
+ 0);
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+
+
+#if !defined(KERNEL) && !defined(WIN32S)
+ if (hthd->tstate & ts_frozen) {
+ //
+ // this thread is not really suspended. We need to
+ // continue it and cause it to be suspended before
+ // allowing it to actually execute the user's code.
+ //
+ if (!MakeThreadSuspendItself(hthd)) {
+ hthd->tstate &= ~ts_frozen;
+ }
+ }
+#endif
+
+ //
+ // If the current thread is sitting a breakpoint then it is necessary
+ // to do a step over it and then try and do a go. Steps are necessary
+ // to ensure that the breakpoint will be restored.
+ //
+ // If the breakpoint is embedded in the code path and not one we
+ // set then just advance the IP past the breakpoint.
+ //
+ // NOTENOTE - jimsch - it is necessary to do a single thread step
+ // to insure that no other threads of execution would have
+ // hit the breakpoint we are disabling while the step on
+ // the current thead is being executed.
+ //
+ // NOTENOTE - jimsch - INTEL - two byte int 3 is not deal with
+ // correctly if it is embedded.
+ //
+
+ if (bp = AtBP(hthd)) {
+ //
+ // We are recovering from a breakpoint, so restore the
+ // original instruction, single step and then finally go.
+ //
+
+ METHOD *ContinueSSMethod;
+
+ DEBUG_PRINT("Recovering from a breakpoint\n");
+
+ if (bp == EMBEDDED_BP) {
+
+ //
+ // "step" past the bp and continue.
+ //
+ if (!hthd->fDontStepOff) {
+ ClearBPFlag(hthd);
+ hthd->fIsCallDone = FALSE;
+ IncrementIP(hthd);
+ }
+
+ } else {
+
+ ContinueSSMethod = (METHOD*)malloc(sizeof(METHOD));
+ ContinueSSMethod->notifyFunction = (ACVECTOR)MethodContinueSS;
+ ContinueSSMethod->lparam = ContinueSSMethod;
+ ContinueSSMethod->lparam2 = bp;
+
+ SingleStep(hthd, ContinueSSMethod, FALSE, FALSE);
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+ }
+
+ //
+ // Have the Expression BP manager know that we are continuing
+ //
+ ExprBPContinue( hprc, hthd );
+
+
+ //
+ // Do a continue debug event and continue execution
+ //
+
+ assert ( (hprc->pstate & ps_destroyed) == 0 );
+
+ //
+ // fExceptionHandled may also have been set by function eval code.
+ //
+ hthd->fExceptionHandled = hthd->fExceptionHandled ||
+ !lpexop->fPassException;
+
+ if ((hthd->tstate & (ts_first | ts_second)) && !hthd->fExceptionHandled) {
+ cs = (DWORD)DBG_EXCEPTION_NOT_HANDLED;
+
+ } else {
+ cs = (DWORD)DBG_CONTINUE;
+ }
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ hthd->fExceptionHandled = FALSE;
+
+ Reply(0, &xosd, lpdbb->hpid);
+
+#ifndef KERNEL
+ //
+ // In user mode crashdumps, this is how we emulate the
+ // continuation of the loader breakpoint.
+ //
+ if (CrashDump) {
+ SetEvent( hEventContinue );
+ } else
+#endif
+ {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ (DWORD)cs,
+ 0);
+ }
+
+ return;
+} /* ProcessContinueCmd() */
+
+void
+MethodContinueSS(
+ DEBUG_EVENT *pde,
+ HTHDX hthd,
+ DWORD unused,
+ METHOD *method
+ )
+{
+ PBREAKPOINT bp = (BREAKPOINT*) method->lparam2;
+
+ Unreferenced( pde );
+
+ if (bp != EMBEDDED_BP && !bp->hWalk) {
+ WriteBreakPoint( bp );
+ }
+
+ free(method->lparam);
+
+ //
+ // Have the Expression BP manager know that we are continuing
+ //
+ ExprBPContinue( hthd->hprc, hthd );
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+
+ return;
+}
+
+
+
+DWORD
+ProcessFreezeThreadCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+
+#ifdef KERNEL
+
+ XOSD xosd = xosdNone;
+ hthd->tstate |= ts_frozen;
+ Reply(0, &xosd, lpdbb->hpid);
+ return( xosd );
+
+#else // KERNEL
+
+ XOSD xosd = xosdNone;
+
+ Unreferenced( hprc );
+
+ DEBUG_PRINT("ProcessFreezeThreadCmd called.\n\r");
+
+#ifdef WIN32S
+ xosd = xosdUnsupported; // can't freeze thread in win32s
+#else // !WIN32S
+
+ if (!(hthd->tstate & ts_frozen)) {
+
+ if (hthd->tstate & ts_stopped) {
+ //
+ // If the thread is at a debug event, don't suspend it -
+ // let it suspend itself later when we continue it.
+ //
+ hthd->tstate |= ts_frozen;
+ } else if (SuspendThread(hthd->rwHand) != -1L) {
+ hthd->tstate |= ts_frozen;
+ } else {
+#ifdef OSDEBUG4
+ xosd = xosdBadThread;
+#else
+ xosd = xosdInvalidThread;
+#endif // OSDEBUG4
+ }
+ }
+#endif // WIN32S
+
+ Reply(0, &xosd, lpdbb->hpid);
+ return( xosd );
+
+#endif // KERNEL
+}
+
+
+#ifdef WIN32S // {
+#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION
+#define EXCEPTION_DATATYPE_MISALIGNMENT STATUS_DATATYPE_MISALIGNMENT
+#define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT
+#define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP
+#define EXCEPTION_ARRAY_BOUNDS_EXCEEDED STATUS_ARRAY_BOUNDS_EXCEEDED
+#define EXCEPTION_FLT_DENORMAL_OPERAND STATUS_FLOAT_DENORMAL_OPERAND
+#define EXCEPTION_FLT_DIVIDE_BY_ZERO STATUS_FLOAT_DIVIDE_BY_ZERO
+#define EXCEPTION_FLT_INEXACT_RESULT STATUS_FLOAT_INEXACT_RESULT
+#define EXCEPTION_FLT_INVALID_OPERATION STATUS_FLOAT_INVALID_OPERATION
+#define EXCEPTION_FLT_OVERFLOW STATUS_FLOAT_OVERFLOW
+#define EXCEPTION_FLT_STACK_CHECK STATUS_FLOAT_STACK_CHECK
+#define EXCEPTION_FLT_UNDERFLOW STATUS_FLOAT_UNDERFLOW
+#define EXCEPTION_INT_DIVIDE_BY_ZERO STATUS_INTEGER_DIVIDE_BY_ZERO
+#define EXCEPTION_INT_OVERFLOW STATUS_INTEGER_OVERFLOW
+#define EXCEPTION_PRIV_INSTRUCTION STATUS_PRIVILEGED_INSTRUCTION
+#define EXCEPTION_IN_PAGE_ERROR STATUS_IN_PAGE_ERROR
+#endif // }
+
+#define efdDefault efdStop
+
+EXCEPTION_DESCRIPTION ExceptionList[] = {
+#ifndef WIN32S // WIN32S can't get these
+ // DBG_CONTROL_C and DBG_CONTROL_BREAK are *only*
+ // raised if the app is being debugged. The system
+ // remotely creates a thread in the debuggee and then
+ // raises one of these exceptions; the debugger must
+ // respond to the first-chance exception if it wants
+ // to trap it at all, because it will never see a
+ // last-chance notification.
+ {(DWORD)DBG_CONTROL_C, efdStop, "Control-C"},
+ {(DWORD)DBG_CONTROL_BREAK, efdStop, "Control-Break"},
+#endif
+ {(DWORD)EXCEPTION_DATATYPE_MISALIGNMENT, efdDefault, "Datatype Misalignment"},
+ {(DWORD)EXCEPTION_ACCESS_VIOLATION, efdDefault, "Access Violation"},
+ {(DWORD)EXCEPTION_IN_PAGE_ERROR, efdDefault, "In Page Error"},
+ {(DWORD)STATUS_ILLEGAL_INSTRUCTION, efdDefault, "Illegal Instruction"},
+ {(DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED, efdDefault, "Array Bounds Exceeded"},
+ // Floating point exceptions will only be raised if
+ // the user calls _controlfp() to turn them on.
+ {(DWORD)EXCEPTION_FLT_DENORMAL_OPERAND, efdDefault, "Float Denormal Operand"},
+ {(DWORD)EXCEPTION_FLT_DIVIDE_BY_ZERO, efdDefault, "Float Divide by Zero"},
+ {(DWORD)EXCEPTION_FLT_INEXACT_RESULT, efdDefault, "Float Inexact Result"},
+ {(DWORD)EXCEPTION_FLT_INVALID_OPERATION, efdDefault, "Float Invalid Operation"},
+ {(DWORD)EXCEPTION_FLT_OVERFLOW, efdDefault, "Float Overflow"},
+ {(DWORD)EXCEPTION_FLT_STACK_CHECK, efdDefault, "Float Stack Check"},
+ {(DWORD)EXCEPTION_FLT_UNDERFLOW, efdDefault, "Float Underflow"},
+ // STATUS_NO_MEMORY can be raised by HeapAlloc and
+ // HeapRealloc.
+ {(DWORD)STATUS_NO_MEMORY, efdDefault, "No Memory"},
+ // STATUS_NONCONTINUABLE_EXCEPTION is raised if a
+ // noncontinuable exception happens and an exception
+ // filter return -1, meaning to resume execution.
+ {(DWORD)STATUS_NONCONTINUABLE_EXCEPTION, efdDefault, "Noncontinuable Exception"},
+ // STATUS_INVALID_DISPOSITION means an NT exception
+ // filter (which is slightly different from an MS C
+ // exception filter) returned some value other than
+ // 0 or 1 to the system.
+ {(DWORD)STATUS_INVALID_DISPOSITION, efdDefault, "Invalid Disposition"},
+ {(DWORD)EXCEPTION_INT_DIVIDE_BY_ZERO, efdDefault, "Integer Divide by Zero"},
+ {(DWORD)EXCEPTION_INT_OVERFLOW, efdDefault, "Integer Overflow"},
+ {(DWORD)EXCEPTION_PRIV_INSTRUCTION, efdDefault, "Privileged Instruction"},
+ {(DWORD)STATUS_STACK_OVERFLOW, efdDefault, "Stack Overflow"},
+ {(DWORD)STATUS_DLL_NOT_FOUND, efdDefault, "DLL Not Found"},
+ {(DWORD)STATUS_DLL_INIT_FAILED, efdDefault, "DLL Initialization Failed"},
+ {(DWORD)(0xE0000000 | 'msc'), efdNotify, "Microsoft C++ Exception"},
+ {(DWORD)RPC_S_SERVER_UNAVAILABLE, efdNotify, "RPC Server Unavailable"},
+ {(DWORD)RPC_S_SERVER_TOO_BUSY, efdNotify, "RPC Server Busy"},
+ {(DWORD)RPC_S_OUT_OF_RESOURCES, efdNotify, "RPC Out Of Resources"},
+};
+
+#define SIZEOFELIST ( sizeof(ExceptionList) / sizeof(ExceptionList[0]) )
+
+void
+ProcessGetExceptionState(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This function is used to query the dm about exception handling.
+
+Arguments:
+
+ hprc - Supplies process handle
+ hthd - Supplies thread handle
+ lpdbb - Supplies info about the command
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPEXCMD lpexcmd = (LPEXCMD)lpdbb->rgbVar;
+ LPEXCEPTION_DESCRIPTION lpexdesc = (LPEXCEPTION_DESCRIPTION)LpDmMsg->rgb;
+ EXCEPTION_LIST *eList;
+ XOSD xosd = xosdNone;
+ int i = 0;
+ DWORD val = 1;
+
+ Unreferenced (hthd);
+
+ DEBUG_PRINT("ProcessGetExceptionStateCmd");
+
+ if (!hprc) {
+ xosd = xosdUnknown;
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+
+ switch( lpexcmd->exc ) {
+
+ case exfFirst:
+
+ if (!hprc || !hprc->exceptionList) {
+ *lpexdesc = ExceptionList[0];
+ } else {
+ *lpexdesc = hprc->exceptionList->excp;
+ }
+ break;
+
+ case exfNext:
+
+ xosd = xosdEndOfStack;
+ if (hprc && hprc->exceptionList) {
+ for (eList=hprc->exceptionList; eList; eList=eList->next) {
+ if (eList->excp.dwExceptionCode ==
+ lpexdesc->dwExceptionCode) {
+ eList = eList->next;
+ if (eList) {
+ *lpexdesc = eList->excp;
+ xosd = xosdNone;
+ } else {
+ lpexdesc->dwExceptionCode = 0;
+ }
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < SIZEOFELIST; i++) {
+ if (ExceptionList[i].dwExceptionCode ==
+ lpexdesc->dwExceptionCode) {
+ if (i+1 < SIZEOFELIST) {
+ *lpexdesc = ExceptionList[i+1];
+ xosd = xosdNone;
+ } else {
+ lpexdesc->dwExceptionCode = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case exfSpecified:
+
+ xosd = xosdEndOfStack;
+ if (hprc && hprc->exceptionList) {
+ for (eList = hprc->exceptionList; eList; eList = eList->next) {
+ if (eList->excp.dwExceptionCode ==
+ lpexdesc->dwExceptionCode) {
+ *lpexdesc = eList->excp;
+ xosd = xosdNone;
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < SIZEOFELIST; i++) {
+ if (ExceptionList[i].dwExceptionCode ==
+ lpexdesc->dwExceptionCode) {
+ *lpexdesc = ExceptionList[i+1];
+ xosd = xosdNone;
+ break;
+ }
+ }
+ }
+
+ break;
+
+ default:
+ assert(!"Invalid exf to ProcessGetExceptionState");
+ xosd = xosdUnknown;
+ break;
+ }
+
+ LpDmMsg->xosdRet = xosd;
+ Reply(sizeof(EXCEPTION_DESCRIPTION), LpDmMsg, lpdbb->hpid);
+ return;
+}
+
+
+VOID
+ProcessSetExceptionState(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This function is used to change how the debugger will handle exceptions.
+
+Arguments:
+
+ hprc - Supplies process handle
+ hthd - Supplies thread handle
+ lpdbb - Supplies info about the command
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPEXCEPTION_DESCRIPTION lpexdesc = (LPEXCEPTION_DESCRIPTION)lpdbb->rgbVar;
+ EXCEPTION_LIST *eList;
+ XOSD xosd = xosdNone;
+
+ Unreferenced (hthd);
+
+ DEBUG_PRINT("ProcessSetExceptionStateCmd");
+
+ if (!hprc) {
+ WaitForSingleObject(hEventCreateProcess, INFINITE);
+ hprc = HPRCFromHPID(lpdbb->hpid);
+ if (!hprc) {
+ xosd = xosdUnknown;
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+ }
+
+ for (eList=hprc->exceptionList; eList; eList=eList->next) {
+ if (eList->excp.dwExceptionCode==lpexdesc->dwExceptionCode) {
+ break;
+ }
+ }
+
+ if (eList) {
+ // update it:
+ eList->excp = *lpexdesc;
+ } else {
+ // add it:
+ InsertException(&(hprc->exceptionList), lpexdesc);
+ }
+
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+}
+
+
+EXCEPTION_FILTER_DEFAULT
+ExceptionAction(
+ HPRCX hprc,
+ DWORD dwExceptionCode
+ )
+{
+ EXCEPTION_LIST *eList;
+
+ for (eList=hprc->exceptionList; eList; eList=eList->next) {
+ if (eList->excp.dwExceptionCode==dwExceptionCode ) {
+ break;
+ }
+ }
+
+ if (eList != NULL) {
+ return eList->excp.efd;
+ } else {
+ return efdDefault;
+ }
+}
+
+
+void
+RemoveExceptionList(
+ HPRCX hprc
+ )
+{
+ EXCEPTION_LIST *el, *elt;
+ for(el = hprc->exceptionList; el; el = elt) {
+ elt = el->next;
+ free(el);
+ }
+ hprc->exceptionList = NULL;
+}
+
+
+EXCEPTION_LIST *
+InsertException(
+ EXCEPTION_LIST ** ppeList,
+ LPEXCEPTION_DESCRIPTION lpexc
+ )
+{
+ LPEXCEPTION_LIST pnew;
+ while ((*ppeList) &&
+ (*ppeList)->excp.dwExceptionCode < lpexc->dwExceptionCode) {
+ ppeList = &((*ppeList)->next);
+ }
+ pnew = (LPEXCEPTION_LIST)malloc(sizeof(EXCEPTION_LIST));
+ pnew->next = *ppeList;
+ *ppeList = pnew;
+ pnew->excp = *lpexc;
+ return pnew;
+}
+
+
+void
+InitExceptionList(
+ HPRCX hprc
+ )
+{
+ int i;
+ for (i = 0; i < SIZEOFELIST; i++) {
+ InsertException(&(hprc->exceptionList), ExceptionList + i);
+ }
+}
+
+
+
+VOID
+ProcessIoctlCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to an ioctl command from the
+ shell. It is used as a catch all to get and set strange information
+ which is not covered else where. The set of ioctls is OS and
+ implemenation dependent.
+
+Arguments:
+
+ hprc - Supplies a process handle
+
+ hthd - Supplies a thread handle
+
+ lpdbb - Supplies the command information packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPIOL lpiol = (LPIOL)lpdbb->rgbVar;
+
+ switch( lpiol->wFunction ) {
+ case ioctlGetProcessHandle:
+ LpDmMsg->xosdRet = xosdNone;
+ *((HANDLE *)LpDmMsg->rgb) = hprc->rwHand;
+ Reply( sizeof(HANDLE), LpDmMsg, lpdbb->hpid );
+ return;
+
+ case ioctlGetThreadHandle:
+ LpDmMsg->xosdRet = xosdNone;
+ *((HANDLE *)LpDmMsg->rgb) = hthd->rwHand;
+ Reply( sizeof(HANDLE), LpDmMsg, lpdbb->hpid );
+ return;
+
+ case ioctlGeneric:
+ ProcessIoctlGenericCmd( hprc, hthd, lpdbb );
+ return;
+
+ case ioctlCustomCommand:
+ ProcessIoctlCustomCmd( hprc, hthd, lpdbb );
+ return;
+
+ default:
+ LpDmMsg->xosdRet = xosdUnsupported;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+ }
+
+ return;
+} /* ProcessIoctlCmd() */
+
+
+
+VOID
+ProcessSetPathCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path;
+
+Arguments:
+
+ hprc -
+ hthd -
+ lpdbb -
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SETPTH *SetPath = (SETPTH *)lpdbb->rgbVar;
+
+ if ( SetPath->Set ) {
+
+ SearchPathSet = TRUE;
+
+ if ( SetPath->Path[0] ) {
+ strcpy(SearchPathString, SetPath->Path );
+ } else {
+ SearchPathString[0] = '\0';
+ }
+ } else {
+ SearchPathSet = FALSE;
+ SearchPathString[0] = '\0';
+ }
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+}
+
+
diff --git a/private/windbg/newdm/step.c b/private/windbg/newdm/step.c
new file mode 100644
index 000000000..e0e7da729
--- /dev/null
+++ b/private/windbg/newdm/step.c
@@ -0,0 +1,2968 @@
+#include "precomp.h"
+#pragma hdrstop
+
+extern DMTLFUNCTYPE DmTlFunc;
+
+extern DEBUG_EVENT falseSSEvent;
+
+extern BYTE abEMReplyBuf[];
+
+VOID
+DestroyRangeStruct(
+ RANGESTRUCT* RangeStruct
+ );
+
+static void SSActionRBAndContinue(DEBUG_EVENT*, HTHDX, DWORD, BREAKPOINT* );
+//#define Execute(pid,tid)
+
+
+
+void
+SingleStep(
+ HTHDX hthd,
+ METHOD* notify,
+ BOOL stopOnBP,
+ BOOL fInFuncEval
+ )
+/*++
+
+Routine Description:
+
+ This function is used to do a single step operation on the sepcified
+ thread.
+
+Arguments:
+
+ hthd - Supplies the thread handle to be stepped.
+
+ notify -
+
+ stopOnBp - Supplies TRUE if a bp at current PC should cause a stop
+
+ fInFuncEval - Supplies TRUE if called by the fucntion evaluation code
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ADDR currAddr;
+ WORD opcode = 0;
+ ACVECTOR action = NO_ACTION;
+ int lpf = 0;
+ BREAKPOINT* bp;
+ LPCONTEXT lpContext = &(hthd->context);
+ HANDLE rwHand = (hthd->hprc)->rwHand;
+
+
+ /*
+ * Get the current IP of the thread
+ */
+
+ AddrFromHthdx(&currAddr, hthd);
+
+#ifdef WIN32S
+ // DON'T ALLOW trace into Win32s system dlls! It will hang windows.
+ // WARNWARN: X86 specific code:
+
+ switch (IsWin32sSystemThunk(hthd->hprc, hthd, currAddr.addr.off,
+ lpContext->Esp)) { // x86 specific
+ case WIN32S_THUNK_CALL:
+ StepOver(hthd, notify, stopOnBP, fInFuncEval);
+ return;
+ case WIN32S_THUNK_JUMP:
+ DEBUG_PRINT("Found a jump to win32s system code. Just GO.\r\n");
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ QueueContinueDebugEvent(hthd->hprc->pid, hthd->tid,
+ DBG_CONTINUE);
+ return;
+ default: // not about to enter a system dll. Go on and do the step.
+ break;
+ }
+#endif
+
+ bp = AtBP(hthd);
+
+ if (!stopOnBP && !bp) {
+ bp = FindBP(hthd->hprc, hthd, bptpExec, (BPNS)-1, &currAddr, FALSE);
+ SetBPFlag(hthd, bp);
+ }
+
+ /*
+ * Check if we are on a BP
+ */
+ if (bp == EMBEDDED_BP) {
+
+ DPRINT(3, ("-- At embedded BP, skipping it.\n"));
+
+ //
+ // If it isn't a BP we set then just increment past it
+ // & pretend that a single step actually took place
+ //
+
+
+ ClearBPFlag(hthd);
+ IncrementIP(hthd);
+ hthd->fIsCallDone = FALSE;
+ NotifyEM(&falseSSEvent, hthd, 0, (LPVOID)0);
+
+ } else if (bp) {
+
+ RestoreInstrBP(hthd, bp);
+ ClearBPFlag(hthd);
+
+ //
+ // Place this on our list of expected events
+ //
+
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)EXCEPTION_SINGLE_STEP,
+ notify,
+ SSActionReplaceByte,
+ FALSE,
+ bp);
+
+ //
+ // Issue the single step command
+ //
+
+ SetupSingleStep(hthd, TRUE);
+
+ } else { // bp == NULL
+
+ //
+ // Determine if the current instruction is a breakpoint
+ // instruction. If it is then based on the stopOnBP
+ // flag we either execute to hit the breakpoint or
+ // skip over it and create a single step event
+ //
+
+ IsCall(hthd, &currAddr, &lpf, FALSE);
+
+ if (lpf == INSTR_BREAKPOINT) {
+
+ if (stopOnBP) {
+ /*
+ * We were instructed to stop on breakpoints
+ * Just issue an execute command and execute
+ * the breakpoint.
+ */
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ } else {
+ /*
+ * else just increment past it
+ * & pretend that a single step actually took place
+ */
+
+ DPRINT(3, (" At an embedded bp -- ignoring\n\r"));
+
+ IncrementIP(hthd);
+
+ hthd->fIsCallDone = FALSE;
+ ClearBPFlag(hthd);
+ if (notify) {
+ (notify->notifyFunction)(&falseSSEvent,
+ hthd,
+ 0,
+ notify->lparam);
+ } else {
+ NotifyEM(&falseSSEvent, hthd, 0, (LPVOID)0);
+ }
+ }
+
+ } else {
+
+ if (lpf == INSTR_CANNOT_TRACE) {
+
+ bp = SetBP( hthd->hprc,
+ hthd,
+ bptpExec,
+ bpnsStop,
+ &currAddr,
+ (HPID) INVALID);
+ bp->isStep = TRUE;
+
+ }
+
+
+
+ //
+ // Place this on our list of expected events
+ //
+
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)EXCEPTION_SINGLE_STEP,
+ notify,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ //
+ // Issue the single step command
+ //
+
+ SetupSingleStep(hthd, TRUE);
+
+ }
+ }
+
+ return;
+} /* SingleStep() */
+
+
+
+void
+IncrementIP(HTHDX hthd)
+{
+ PC(hthd) += BP_SIZE;
+ assert(hthd->tstate & ts_stopped);
+ hthd->fContextDirty = TRUE;
+
+ return;
+} /* IncrementIP() */
+
+
+
+
+void
+DecrementIP(HTHDX hthd)
+{
+ // M00BUG -- two byte version of int 3
+
+ PC(hthd) -= BP_SIZE;
+ assert(hthd->tstate & ts_stopped);
+ hthd->fContextDirty = TRUE;
+
+ return;
+} /* DecrementIP() */
+
+
+
+
+void
+StepOver(
+ HTHDX hthd,
+ METHOD* notify,
+ BOOL stopOnBP,
+ BOOL fInFuncEval
+ )
+/*++
+
+Routine Desription:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ ADDR currAddr;
+ WORD opcode = 0;
+ int lpf = 0;
+ BREAKPOINT *bp, *atbp;
+ LPCONTEXT lpContext = &hthd->context;
+ HPRCX hprc=hthd->hprc;
+ HANDLE rwHand = hprc->rwHand;
+ METHOD *method;
+
+ DPRINT(3, ("** SINGLE STEP OVER "));
+
+ //
+ // Get the current IP of the thread
+ //
+
+ AddrFromHthdx(&currAddr, hthd);
+
+ //
+ // Determine what type of instruction we are presently on
+ //
+
+ IsCall(hthd, &currAddr, &lpf, TRUE);
+
+ //
+ // If the instruction is not a call or an intrpt then do a SS
+ //
+
+ if (lpf == INSTR_TRACE_BIT) {
+ SingleStep(hthd, notify, stopOnBP, fInFuncEval);
+ return;
+ }
+
+ //
+ // If the instruction is a BP then "uncover" it
+ //
+
+ if (lpf == INSTR_BREAKPOINT) {
+
+ DPRINT(5, (" We have hit a breakpoint instruction\n\r"));
+
+ if (stopOnBP) {
+ /*
+ ** We were instructed to stop on breakpoints
+ ** Just issue an execute command and execute
+ ** the breakpoint.
+ */
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+ } else {
+
+ IncrementIP(hthd);
+ hthd->fIsCallDone = FALSE;
+ ClearBPFlag(hthd);
+ if (notify) {
+ (notify->notifyFunction)(&falseSSEvent, hthd, 0, notify->lparam);
+ } else {
+ NotifyEM(&falseSSEvent, hthd, 0, (LPVOID)0);
+ }
+ }
+
+ } else {
+
+ if (lpf == INSTR_CANNOT_TRACE) {
+
+ bp = SetBP( hthd->hprc, hthd, bptpExec, bpnsStop, &currAddr, (HPID) INVALID);
+ bp->isStep = TRUE;
+
+ }
+
+ /*
+ ** If control gets to this point, then the instruction
+ ** that we are at is either a call or an interrupt.
+ */
+
+ atbp = bp = AtBP(hthd);
+ if (!stopOnBP && !atbp) {
+ atbp = bp = FindBP(hthd->hprc, hthd, bptpExec, (BPNS)-1, &currAddr, FALSE);
+ SetBPFlag(hthd, bp);
+ }
+
+ if (atbp) {
+ /*
+ ** Put the single step on our list of expected
+ ** events and set the action to "Replace Byte and Continue"
+ ** without notifying the EM
+ */
+
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)EXCEPTION_SINGLE_STEP,
+ DONT_NOTIFY,
+ (ACVECTOR) SSActionRBAndContinue,
+ FALSE,
+ bp);
+
+ RestoreInstrBP(hthd, bp);
+
+ /*
+ ** Issue the single step
+ */
+
+ if (lpf != INSTR_CANNOT_TRACE) {
+ SetupSingleStep(hthd, FALSE);
+ }
+ }
+
+ if (lpf == INSTR_IS_CALL) {
+
+ DPRINT(3, (" Placing a Breakpoint @ %08x ", currAddr));
+
+ /*
+ ** Set a BP after this call instruction
+ */
+
+ bp = SetBP(hprc, hthd, bptpExec, bpnsStop, &currAddr, (HPID)INVALID);
+
+ /*
+ ** Make a copy of the notification method
+ */
+
+ method = (METHOD*)malloc(sizeof(METHOD));
+ *method = *notify;
+
+ /*
+ ** Store the breakpoint with this notification method
+ */
+
+ method->lparam2 = (LPVOID)bp;
+
+ /*
+ ** Place this on our list of expected events
+ ** (Let the action function do the notification, other-
+ ** wise the EM will receive a breakpoint notification,
+ ** rather than a single step notification).NOTE:
+ ** This is the reason why we make a copy of the notif-
+ ** ication method -- because the action function must
+ ** know which notification method to use, in addition
+ ** to the breakpoint that was created.
+ */
+
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)bp,
+ DONT_NOTIFY,
+ (ACVECTOR) SSActionRemoveBP,
+ FALSE,
+ method);
+
+ DPRINT(7, ("PID= %lx TID= %lx\n", hprc->pid, hthd->tid));
+
+ }
+
+ /*
+ ** Issue the execute command
+ */
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+ //
+ // If we hit a DIFFERENT BP while we are in the called routine we
+ // must clear this (and ALL other consumable events) from the
+ // expected event queue.
+ //
+ }
+
+ return;
+} /* StepOver() */
+
+
+
+void
+SSActionRemoveBP(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD unused,
+ METHOD* method
+ )
+/*++
+
+Routine Description:
+
+ This action function is called upon the receipt of a breakpoint
+ event in order to remove the breakpoint and fake a single step event.
+ Note that the lparam to this action function must be a METHOD* and
+ the BREAKPOINT* to remove must be stored in the lparam2 field of the
+ method.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ BREAKPOINT* bp = (BREAKPOINT*)method->lparam2;
+
+ Unreferenced( de );
+
+ DEBUG_PRINT("** SS Action Remove BP called\n");
+
+ // Remove the temporary breakpoint
+ RemoveBP(bp);
+
+ // Notify whoever is concerned, that a SS event has occured
+ (method->notifyFunction)(&falseSSEvent, hthd, 0, method->lparam);
+
+ // Free the temporary notification method.
+ free(method);
+}
+
+
+
+
+void
+SSActionReplaceByte(
+ DEBUG_EVENT *de,
+ HTHDX hthd,
+ DWORD unused,
+ BREAKPOINT *bp
+ )
+/*++
+
+Routine Description:
+
+ This action function is called upon the receipt of a single step
+ event in order to replace the breakpoint instruction (INT 3, 0xCC)
+ that was written over.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+#ifdef KERNEL
+ Unreferenced( de );
+ Unreferenced( unused );
+
+
+ if (bp->hWalk) {
+ ExprBPResetBP(hthd, bp);
+ } else {
+ WriteBreakPoint( bp );
+ }
+
+#else
+ HANDLE rwHandle = (hthd->hprc)->rwHand;
+ BP_UNIT opcode = BP_OPCODE;
+ DWORD i;
+ ADDR addr = bp->addr;
+
+ Unreferenced( de );
+ Unreferenced( unused );
+
+ if (bp->hWalk) {
+ //
+ // It was really a hardware BP, let the walk handler fix it up.
+ //
+ DPRINT(5, ("** SS Action Replace Byte is really a hardware BP\n"));
+ ExprBPResetBP(hthd, bp);
+ } else {
+ DPRINT(5, ("** SS Action Replace Byte at %d:%04x:%08x with %x\n",
+ ADDR_IS_FLAT(addr), addr.addr.seg, addr.addr.off, opcode));
+
+ AddrWriteMemory(hthd->hprc,
+ hthd,
+ &addr,
+ (LPBYTE)&opcode,
+ BP_SIZE,
+ &i);
+ }
+#endif
+
+ return;
+}
+
+
+
+void
+SSActionRBAndContinue(
+ DEBUG_EVENT *de,
+ HTHDX hthd,
+ DWORD unused,
+ BREAKPOINT *bp
+ )
+/*++
+
+Routine Description:
+
+ This action function is called upon the receipt of a single step
+ event in order to replace the breakpoint instruction (INT 3, 0xCC)
+ that was written over, and then continuing execution.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ HANDLE rwHandle = (hthd->hprc)->rwHand;
+
+
+ ADDR addr = bp->addr;
+ BP_UNIT opcode = BP_OPCODE;
+ DWORD i;
+
+ Unreferenced( de );
+
+ if (bp->hWalk) {
+ //
+ // Really a hardware BP, let walk manager fix it.
+ //
+ DPRINT(5, ("** SS Action RB and continue is really a hardware BP\n"));
+ ExprBPResetBP(hthd, bp);
+ } else {
+ DPRINT(5, ("** SS Action RB and Continue: Replace byte @ %d:%04x:%08x with %x\n",
+ ADDR_IS_FLAT(addr), addr.addr.seg, addr.addr.off, opcode));
+
+ RestoreBreakPoint( bp );
+ }
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+
+ return;
+}
+
+
+BOOL InsideRange( HTHDX, ADDR*, ADDR*, ADDR* );
+BRANCH_LIST * GetBranchList ( HTHDX, ADDR*, ADDR* );
+RANGESTRUCT * SetupRange ( HTHDX, ADDR*, ADDR*, BRANCH_LIST *, BOOL, BOOL, METHOD* );
+VOID AddRangeBp( RANGESTRUCT*, ADDR*, BOOL );
+BOOL SetRangeBp( RANGESTRUCT* );
+VOID RemoveRangeBp( RANGESTRUCT* );
+BOOL GetThunkTarget( RANGESTRUCT*, ADDR*, ADDR* );
+
+VOID RecoverFromSingleStep( ADDR*, RANGESTRUCT*);
+BOOL ContinueFromInsideRange( ADDR*, RANGESTRUCT*);
+BOOL ContinueFromOutsideRange( ADDR*, RANGESTRUCT*);
+
+
+
+BOOL
+SmartRangeStep(
+ HTHDX hthd,
+ UOFF32 offStart,
+ UOFF32 offEnd,
+ BOOL fStopOnBP,
+ BOOL fStepOver
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to implement range stepping the the DM. Range
+ stepping is used to cause all instructions between a pair of addresses
+ to be executed.
+
+ The segment is implied to be the current segment. This is validated
+ in the EM.
+
+Arguments:
+
+ hthd - Supplies the thread to be stepped.
+
+ offStart - Supplies the initial offset in the range
+
+ offEnd - Supplies the final offset in the range
+
+ fStopOnBP - Supplies TRUE if stop on an initial breakpoint
+
+ fStepOver - Supplies TRUE if to step over call type instructions
+
+Return Value:
+
+ TRUE if successful. If the disassembler fails, a breakpoint cannot
+ be set or other problems, FALSE will be returned, and the caller will
+ fall back to the slow range step method.
+
+--*/
+
+{
+ BRANCH_LIST *BranchList;
+ METHOD *Method;
+ RANGESTRUCT *RangeStruct;
+ ADDR AddrStart;
+ ADDR AddrEnd;
+
+ //
+ // Initialize start and end addresses
+ //
+
+ AddrInit(&AddrStart, 0, PcSegOfHthdx(hthd), offStart,
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE, hthd->fAddrIsReal);
+
+ AddrInit(&AddrEnd, 0, PcSegOfHthdx(hthd), offEnd,
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE, hthd->fAddrIsReal);
+
+
+
+ //
+ // Locate all the branch instructions inside the range (and their
+ // targets if available) and obtain a branch list.
+ //
+ BranchList = GetBranchList( hthd, &AddrStart, &AddrEnd );
+
+ if (!BranchList) {
+ return FALSE;
+ }
+
+ //
+ // Setup range step method
+ //
+ Method = (METHOD*)malloc(sizeof(METHOD));
+ assert( Method );
+
+ Method->notifyFunction = (ACVECTOR)MethodSmartRangeStep;
+
+ //
+ // Set up the range structure (this will set all safety breakpoints).
+ //
+ RangeStruct = SetupRange( hthd, &AddrStart, &AddrEnd, BranchList,
+ fStopOnBP, fStepOver, Method );
+ if (!RangeStruct) {
+ return FALSE;
+ }
+
+ //
+ // Now let the thread run.
+ //
+ AddQueue( RangeStruct->fSingleStep ?
+ QT_TRACE_DEBUG_EVENT : QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+#ifdef KERNEL
+ hthd->tstate |= ts_stepping;
+#endif
+
+ return TRUE;
+}
+
+
+
+BOOL
+InsideRange(
+ HTHDX hthd,
+ ADDR *AddrStart,
+ ADDR *AddrEnd,
+ ADDR *Addr
+ )
+{
+ ADDR AddrS;
+ ADDR AddrE;
+ ADDR AddrC;
+
+ assert( AddrStart );
+ assert( AddrEnd );
+ assert( Addr );
+
+ if ( ADDR_IS_LI(*Addr) ) {
+ return FALSE;
+ }
+
+ AddrS = *AddrStart;
+ AddrE = *AddrEnd;
+ AddrC = *Addr;
+
+ if (!ADDR_IS_FLAT(AddrS)) {
+ if ( !TranslateAddress(hthd->hprc, hthd, &AddrS, TRUE) ) {
+ return FALSE;
+ }
+ }
+
+ if (!ADDR_IS_FLAT(AddrE)) {
+ if ( !TranslateAddress(hthd->hprc, hthd, &AddrE, TRUE) ) {
+ return FALSE;
+ }
+ }
+
+ if (!ADDR_IS_FLAT(AddrC)) {
+ if ( !TranslateAddress(hthd->hprc, hthd, &AddrC, TRUE) ) {
+ return FALSE;
+ }
+ }
+
+ if ( GetAddrOff( AddrC ) >= GetAddrOff( AddrS ) &&
+ GetAddrOff( AddrC ) <= GetAddrOff( AddrE ) ) {
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+BRANCH_LIST *
+GetBranchList (
+ HTHDX hthd,
+ ADDR *AddrStart,
+ ADDR *AddrEnd
+ )
+/*++
+
+Routine Description:
+
+ Locates all the branch instructions within a range and builds a
+ branch list.
+
+Arguments:
+
+ hthd - Supplies thread
+
+ AddrStart - Supplies start of range
+
+ AddrEnd - Supplies end of range
+
+Return Value:
+
+ BRANCH_LIST * - Pointer to branch list.
+
+--*/
+{
+ void *Memory;
+ BRANCH_LIST *BranchList = NULL;
+ BRANCH_LIST *BranchListTmp;
+ DWORD RangeSize;
+ LONG Length;
+ BYTE *Instr;
+ DWORD ListSize;
+ DWORD i;
+ ADDR Addr;
+
+ assert( AddrStart );
+ assert( AddrEnd );
+
+ RangeSize = GetAddrOff(*AddrEnd) - GetAddrOff(*AddrStart) + 1;
+
+ //
+ // Read the code.
+ //
+ Memory = malloc( RangeSize );
+ assert( Memory );
+
+ if (!Memory) {
+ return NULL;
+ }
+
+ //
+ // Allocate and initialize the branch list structure
+ //
+ ListSize = sizeof( BRANCH_LIST );
+ BranchList = (BRANCH_LIST *)malloc( ListSize );
+
+ assert( BranchList );
+
+ if (!BranchList) {
+ free(Memory);
+ return NULL;
+ }
+
+ BranchList->AddrStart = *AddrStart;
+ BranchList->AddrEnd = *AddrEnd;
+ BranchList->Count = 0;
+
+
+ Addr = *AddrStart;
+
+ AddrReadMemory(hthd->hprc, hthd, &Addr, Memory, RangeSize, &Length );
+#ifndef KERNEL
+ assert(Length==(LONG)RangeSize);
+#endif
+ //
+ // If the code crosses a page boundary and the second
+ // page is not present, the read will be short.
+ // Fail, and we will fall back to the slow step code.
+ //
+
+ if (Length != (LONG)RangeSize) {
+ free(BranchList);
+ free(Memory);
+ return NULL;
+ }
+
+
+ //
+ // Unassemble the code and determine where all branches are.
+ //
+ Instr = (BYTE *)Memory;
+
+ while ( Length > 0 ) {
+
+ BOOL IsBranch;
+ BOOL TargetKnown;
+ BOOL IsCall;
+ BOOL IsTable;
+ ADDR Target;
+ DWORD Consumed;
+
+ //
+ // Unassemble one instruction
+ //
+ Consumed = BranchUnassemble( (void *)Instr,
+ &Addr,
+ &IsBranch,
+ &TargetKnown,
+ &IsCall,
+ &IsTable,
+ &Target );
+
+ assert( Consumed > 0 );
+ if ( Consumed == 0 ) {
+
+ //
+ // Could not unassemble the instruction, give up.
+ //
+
+ free(BranchList);
+ BranchList = NULL;
+ Length = 0;
+
+ } else {
+
+ if (IsBranch && IsTable &&
+ InsideRange(hthd, AddrStart, AddrEnd, &Target)) {
+
+ //
+ // this is a vectored jump with the table included
+ // in the source range. Rather than try to figure
+ // out what we can and cannot disassemble, punt
+ // here and let the slow step code catch it.
+ //
+
+ free(BranchList);
+ BranchList = NULL;
+ Length = 0;
+
+ } else if ( IsBranch ) {
+
+ //
+ // If instruction is a branch, and the branch falls outside
+ // of the range, add a branch node to the list.
+ //
+
+ BOOLEAN fAdded = FALSE;
+
+ if ( TargetKnown ) {
+ if ( ADDR_IS_FLAT(Target) ) {
+ if ( GetAddrOff(Target) != 0 ) {
+ GetAddrSeg(Target) = PcSegOfHthdx(hthd);
+ }
+ } else {
+ ADDR_IS_REAL(Target) = hthd->fAddrIsReal;
+ }
+ }
+
+ if ( !InsideRange( hthd, AddrStart, AddrEnd, &Target ) ||
+ !TargetKnown ) {
+
+ //
+ // this loop is to ensure that we don't get duplicate
+ // breapoints set
+ //
+ for (i=0; i<BranchList->Count; i++) {
+
+ if ( TargetKnown &&
+ AreAddrsEqual( hthd->hprc,
+ hthd,
+ &BranchList->BranchNode[i].Target,
+ &Target ) ) {
+ break;
+ }
+ }
+
+ if (i == BranchList->Count) {
+ ListSize += sizeof( BRANCH_NODE );
+ BranchListTmp = (BRANCH_LIST *)realloc( BranchList,
+ ListSize );
+ assert( BranchListTmp );
+ BranchList = BranchListTmp;
+
+ BranchList->BranchNode[ BranchList->Count ].TargetKnown=
+ TargetKnown;
+ BranchList->BranchNode[ BranchList->Count ].IsCall =
+ IsCall;
+ BranchList->BranchNode[ BranchList->Count ].Addr =
+ Addr;
+ BranchList->BranchNode[ BranchList->Count ].Target =
+ Target;
+
+ BranchList->Count++;
+
+ fAdded = TRUE;
+ }
+ }
+
+#if defined(TARGET_MIPS)
+ //
+ // If the delay slot falls outside the range, add
+ // the branch to the list no matter what the target.
+ //
+ if ( !fAdded && GetAddrOff(Addr) + 4 > GetAddrOff(*AddrEnd) ) {
+ ListSize += sizeof( BRANCH_NODE );
+ BranchListTmp = (BRANCH_LIST *)realloc( BranchList,
+ ListSize );
+ assert( BranchListTmp );
+ BranchList = BranchListTmp;
+
+ BranchList->BranchNode[ BranchList->Count ].TargetKnown =
+ TargetKnown;
+ BranchList->BranchNode[ BranchList->Count ].IsCall =
+ IsCall;
+ BranchList->BranchNode[ BranchList->Count ].Addr =
+ Addr;
+ BranchList->BranchNode[ BranchList->Count ].Target =
+ Target;
+
+ BranchList->Count++;
+ }
+#endif
+ }
+
+ Instr += Consumed;
+ GetAddrOff(Addr) += Consumed;
+ Length -= Consumed;
+ }
+ }
+
+ free( Memory );
+
+ return BranchList;
+}
+
+
+
+RANGESTRUCT *
+SetupRange (
+ HTHDX hthd,
+ ADDR *AddrStart,
+ ADDR *AddrEnd,
+ BRANCH_LIST *BranchList,
+ BOOL fStopOnBP,
+ BOOL fStepOver,
+ METHOD *Method
+ )
+/*++
+
+Routine Description:
+
+ Helper function for RangeStep.
+
+Arguments:
+
+ hthd - Supplies thread
+
+ AddrStart - Supplies start of range
+
+ AddrEnd - Supplies end of range
+
+ BranchList - Supplies branch list
+
+ fStopOnBP - Supplies fStopOnBP flag
+
+ fStepOver - Supplies fStepOver flag
+
+Return Value:
+
+ RANGESTRUCT * - Pointer to range structure
+
+ N.B. if this fails, it will free(BranchList).
+
+--*/
+{
+ RANGESTRUCT *RangeStruct;
+ BREAKPOINT *Bp;
+ DWORD i;
+ BOOLEAN fAddedAtEndOfRange = FALSE;
+ char rgch[sizeof(RTP) + sizeof(ADDR)];
+ HPID hpid;
+ LPRTP lprtp;
+ LPADDR paddr;
+ ADDR Addr;
+ CANSTEP *CanStep;
+
+ assert( AddrStart );
+ assert( AddrEnd );
+ assert( BranchList );
+ assert( Method );
+
+ //
+ // Allocate and initialize the range structure
+ //
+ RangeStruct = (RANGESTRUCT *)malloc( sizeof(RANGESTRUCT) );
+ assert( RangeStruct );
+
+ RangeStruct->hthd = hthd;
+ RangeStruct->BranchList = BranchList;
+ RangeStruct->fStepOver = fStepOver;
+ RangeStruct->fStopOnBP = fStopOnBP;
+ RangeStruct->BpCount = 0;
+ RangeStruct->BpAddrs = NULL;
+ RangeStruct->BpList = NULL;
+ RangeStruct->fSingleStep = FALSE;
+ RangeStruct->fInCall = FALSE;
+ RangeStruct->fFromThunk = FALSE;
+ RangeStruct->Method = Method;
+
+ Method->lparam = RangeStruct;
+
+
+ //
+ // If the given range has branches, set branch breakpoints according to
+ // the fStepOver flag.
+ //
+ if ( BranchList->Count > 0 ) {
+
+ if ( fStepOver ) {
+
+ //
+ // Ignore calls (We're stepping over them), set BPs in all
+ // known target (if outside of range) and all branch instructions
+ // with unknown targets.
+ //
+ for ( i=0; i < BranchList->Count; i++ ) {
+
+#if defined(TARGET_MIPS)
+ //
+ // If delay slot is outside range, set breakpoint at next
+ // instruction after delay slot (i.e. the return address)
+ //
+ if ( GetAddrOff(BranchList->BranchNode[i].Addr) + 4 > GetAddrOff(*AddrEnd) ) {
+ ADDR Addr = BranchList->BranchNode[i].Addr;
+ GetAddrOff(Addr) += 8;
+ AddRangeBp( RangeStruct, &Addr, FALSE );
+ fAddedAtEndOfRange = TRUE;
+ }
+#endif
+ if ( !BranchList->BranchNode[i].IsCall ) {
+ if ( !BranchList->BranchNode[i].TargetKnown ) {
+
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Addr, FALSE );
+
+ } else if ( !InsideRange( hthd, AddrStart, AddrEnd, &BranchList->BranchNode[i].Target ) ) {
+
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Target, FALSE );
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // Set BPs in all branches/calls with unknown targets, all
+ // branch targets (if outside of range) and all call targets
+ // for which we have source.
+ //
+ for ( i=0; i < BranchList->Count; i++ ) {
+
+#if defined(TARGET_MIPS)
+ //
+ // If delay slot is outside range, set breakpoint at next
+ // instruction after delay slot (i.e. the return address)
+ //
+ if ( GetAddrOff(BranchList->BranchNode[i].Addr) + 4 > GetAddrOff(*AddrEnd) ) {
+ ADDR Addr = BranchList->BranchNode[i].Addr;
+ GetAddrOff(Addr) += 8;
+ AddRangeBp( RangeStruct, &Addr, FALSE );
+ fAddedAtEndOfRange = TRUE;
+ }
+#endif
+ if ( !BranchList->BranchNode[i].TargetKnown ) {
+
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Addr, FALSE );
+
+ } else if ( !InsideRange( hthd, AddrStart, AddrEnd, &BranchList->BranchNode[i].Target ) ) {
+
+ if ( !BranchList->BranchNode[i].IsCall ) {
+
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Target, FALSE );
+
+ } else {
+
+ //
+ // BUGBUG - If debugging WOW, we don't set a
+ // breakpoint in a function prolog, instead we set the
+ // breakpoint in the call instruction and single step
+ // to the function.
+ //
+ if (!ADDR_IS_FLAT(BranchList->BranchNode[i].Addr) ) {
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Addr, FALSE );
+ } else {
+
+ hpid = hthd->hprc->hpid;
+ lprtp = (LPRTP) &rgch;
+ paddr = (LPADDR) &rgch[sizeof(RTP)];
+ lprtp->dbc = dbcCanStep;
+ lprtp->hpid = hpid;
+ lprtp->htid = hthd->htid;
+ lprtp->cb = sizeof(ADDR);
+
+ *paddr = BranchList->BranchNode[i].Target;
+ DmTlFunc(tlfRequest, hpid, sizeof(rgch), (LONG)&rgch);
+ CanStep = (CANSTEP *)abEMReplyBuf;
+ switch ( CanStep->Flags ) {
+
+ case CANSTEP_YES:
+ GetAddrOff(BranchList->BranchNode[i].Target) += CanStep->PrologOffset;
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Target, FALSE );
+ break;
+
+ case CANSTEP_THUNK:
+ //
+ // Get the thunk target and see if we can step into it.
+ //
+ if ( GetThunkTarget( RangeStruct, &BranchList->BranchNode[i].Target, &Addr ) ) {
+
+ if ( AreAddrsEqual( hthd->hprc,
+ hthd,
+ &BranchList->BranchNode[i].Target,
+ &Addr )) {
+
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Target, FALSE );
+
+ } else {
+
+ *paddr = Addr;
+ DmTlFunc(tlfRequest, hpid, sizeof(rgch), (LONG)&rgch);
+ CanStep = (CANSTEP *)abEMReplyBuf;
+
+ switch ( CanStep->Flags ) {
+ case CANSTEP_YES:
+ GetAddrOff(Addr) += CanStep->PrologOffset;
+ BranchList->BranchNode[i].Target = Addr;
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Target, FALSE );
+ break;
+
+ case CANSTEP_THUNK:
+ AddRangeBp( RangeStruct, &Addr, FALSE );
+ break;
+
+ default:
+ break;
+
+ }
+ }
+ } else {
+
+ AddRangeBp( RangeStruct, &BranchList->BranchNode[i].Target, FALSE );
+ }
+
+ break;
+
+ case CANSTEP_NO:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( !fAddedAtEndOfRange ) {
+ //
+ // We always set a safety breakpoint at the instruction past the end
+ // of the range.
+ //
+ ADDR Addr = *AddrEnd;
+ GetAddrOff(Addr) += 1;
+ AddRangeBp( RangeStruct, &Addr, FALSE );
+ }
+
+ //
+ // If we currently are at a BP and the address is not already in the
+ // list, then we must setup a single step for the instruction.
+ //
+ Bp = AtBP(hthd);
+
+ if ( Bp == EMBEDDED_BP ) {
+
+ //
+ // we must step off the harcoded bp
+ //
+
+ ClearBPFlag( hthd );
+ IncrementIP( hthd );
+ hthd->fIsCallDone = FALSE;
+
+ } else if ( Bp ) {
+
+ //
+ // Make sure that the BP is not in the list
+ //
+ for ( i=0; i<RangeStruct->BpCount; i++ ) {
+ if ( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ &RangeStruct->BpAddrs[i],
+ &Bp->addr )) {
+ break;
+ }
+ }
+
+ if ( i >= RangeStruct->BpCount ) {
+ //
+ // We have to single step the breakpoint.
+ //
+ ClearBPFlag( hthd );
+ RestoreInstrBP( RangeStruct->hthd, Bp );
+ RangeStruct->PrevAddr = Bp->addr;
+ RangeStruct->fSingleStep = TRUE;
+
+ //
+ // Set the fInCall flag so that the stepping method knows whether
+ // or not it should stop stepping in case we get out of the range.
+ //
+ for ( i=0; i < RangeStruct->BranchList->Count; i++ ) {
+ if ( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ &Bp->addr,
+ &RangeStruct->BranchList->BranchNode[i].Addr ) ) {
+ RangeStruct->fInCall =
+ RangeStruct->BranchList->BranchNode[i].IsCall;
+ break;
+ }
+ }
+
+#ifdef TARGET_i386
+
+#ifndef KERNEL
+ RangeStruct->hthd->context.EFlags |= TF_BIT_MASK;
+ RangeStruct->hthd->fContextDirty = TRUE;
+#endif
+
+#else // i386
+ {
+ ADDR Addr;
+ UOFF32 NextOffset;
+
+ NextOffset = GetNextOffset( hthd, RangeStruct->fStepOver );
+
+#ifndef KERNEL
+ if ( NextOffset != 0x00000000 ) {
+ AddrInit( &Addr, 0, 0, NextOffset, TRUE, TRUE, FALSE, FALSE );
+ RangeStruct->TmpAddr = Addr;
+ RangeStruct->TmpBp = SetBP( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ bptpExec,
+ bpnsStop,
+ &Addr,
+ (HPID) INVALID);
+ }
+ assert( RangeStruct->TmpBp );
+
+#else // KERNEL
+
+
+
+ hpid = hthd->hprc->hpid;
+ lprtp = (LPRTP) &rgch;
+ paddr = (LPADDR) &rgch[sizeof(RTP)];
+ lprtp->dbc = dbcCanStep;
+ lprtp->hpid = hpid;
+ lprtp->htid = hthd->htid;
+ lprtp->cb = sizeof(ADDR);
+
+ AddrInit( &Addr, 0, 0, NextOffset, TRUE, TRUE, FALSE, FALSE );
+ *paddr = Addr;
+ DmTlFunc(tlfRequest, hpid, sizeof(rgch), (LONG)&rgch);
+ CanStep = (CANSTEP *)abEMReplyBuf;
+ if (CanStep->Flags == CANSTEP_YES) {
+ GetAddrOff(Addr) += CanStep->PrologOffset;
+ }
+
+
+ RangeStruct->TmpAddr = Addr;
+ RangeStruct->TmpBp = SetBP( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ bptpExec,
+ bpnsStop,
+ &Addr,
+ (HPID) INVALID);
+ assert( RangeStruct->TmpBp );
+#endif // KERNEL
+
+ }
+#endif // i386
+ }
+ }
+
+ if (!SetRangeBp( RangeStruct )) {
+ DestroyRangeStruct(RangeStruct);
+ RangeStruct = NULL;
+ }
+
+ return RangeStruct;
+}
+
+VOID
+AddRangeBp(
+ RANGESTRUCT *RangeStruct,
+ ADDR *Addr,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Sets a breakpoint at a particular address and adds it to the breakpoint
+ list in a RANGESTRUCT
+
+Arguments:
+
+ RangeStruct - Supplies pointer to range structure
+
+ Offset - Supplies flat address of breakpoint
+
+ fSet - Supplies flag which if true causes the BP to be set
+
+Return Value:
+
+ None
+
+--*/
+{
+ BREAKPOINT **BpList;
+ ADDR *BpAddrs;
+ DWORD i;
+
+ assert( RangeStruct );
+ assert( Addr );
+
+ //
+ // Add the breakpoint to the list in the range structure
+ //
+ if ( RangeStruct->BpList ) {
+ assert( RangeStruct->BpCount > 0 );
+ assert( RangeStruct->BpAddrs );
+
+ //
+ // Do not add duplicates
+ //
+ for ( i=0; i<RangeStruct->BpCount; i++ ) {
+ if ( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ &RangeStruct->BpAddrs[i],
+ Addr ) ) {
+ return;
+ }
+ }
+
+ BpList = ( BREAKPOINT** )realloc( RangeStruct->BpList, sizeof( BREAKPOINT *) * (RangeStruct->BpCount + 1) );
+ BpAddrs = ( ADDR* )realloc( RangeStruct->BpAddrs, sizeof( ADDR ) * (RangeStruct->BpCount + 1) );
+ } else {
+ assert( RangeStruct->BpCount == 0 );
+ assert( RangeStruct->BpAddrs == NULL );
+ BpList = ( BREAKPOINT** )malloc( sizeof( BREAKPOINT * ) );
+ BpAddrs = ( ADDR* )malloc( sizeof( ADDR ) );
+ }
+
+ assert( BpList );
+ assert( BpAddrs );
+
+ BpList[RangeStruct->BpCount] = NULL;
+ BpAddrs[ RangeStruct->BpCount] = *Addr;
+
+ if ( fSet ) {
+
+ BpList[ RangeStruct->BpCount ] =
+ SetBP( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ bptpExec,
+ bpnsStop,
+ Addr,
+ (HPID) INVALID
+ );
+
+ assert( BpList[ RangeStruct->BpCount ] );
+ }
+
+ RangeStruct->BpCount++;
+ RangeStruct->BpList = BpList;
+ RangeStruct->BpAddrs = BpAddrs;
+}
+
+
+BOOL
+SetRangeBp(
+ RANGESTRUCT *RangeStruct
+ )
+/*++
+
+Routine Description:
+
+ Sets the breakpoints in the range
+
+Arguments:
+
+ RangeStruct - Supplies pointer to range structure
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ BOOL BpSet;
+ DWORD Class;
+ DWORD SubClass;
+
+ assert( RangeStruct );
+
+ if ( RangeStruct->fSingleStep ) {
+#ifdef TARGET_i386
+ Class = EXCEPTION_DEBUG_EVENT;
+ SubClass = (DWORD)STATUS_SINGLE_STEP;
+#else
+ Class = BREAKPOINT_DEBUG_EVENT;
+ SubClass = (DWORD)NO_SUBCLASS;
+#endif
+ } else {
+ Class = BREAKPOINT_DEBUG_EVENT;
+ SubClass = (DWORD)NO_SUBCLASS;
+ }
+
+ //
+ // Register the expected breakpoint event.
+ //
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ Class,
+ SubClass,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ if ( RangeStruct->BpCount ) {
+
+ assert( RangeStruct->BpList );
+ assert( RangeStruct->BpAddrs );
+
+ //
+ // Set all the breakpoints at once
+ //
+ BpSet = SetBPEx( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ (HPID) INVALID,
+ RangeStruct->BpCount,
+ RangeStruct->BpAddrs,
+ RangeStruct->BpList,
+ 0
+ //DBG_CONTINUE
+ );
+
+ assert( BpSet );
+ }
+ return BpSet;
+}
+
+VOID
+RemoveRangeBp(
+ RANGESTRUCT *RangeStruct
+ )
+/*++
+
+Routine Description:
+
+ Clear the breakpoints in the range
+
+Arguments:
+
+ RangeStruct - Supplies pointer to range structure
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ BOOL BpRemoved;
+
+ assert( RangeStruct );
+
+ if ( RangeStruct->BpCount ) {
+
+ assert( RangeStruct->BpList );
+ assert( RangeStruct->BpAddrs );
+
+ //
+ // Reset all the breakpoints at once
+ //
+ BpRemoved = RemoveBPEx( RangeStruct->BpCount,
+ RangeStruct->BpList
+ );
+ }
+}
+
+
+BOOL
+GetThunkTarget(
+ RANGESTRUCT *RangeStruct,
+ ADDR *AddrThunk,
+ ADDR *AddrTarget
+ )
+{
+ BOOL fGotTarget = FALSE;
+ BYTE *Buffer;
+ DWORD BufferSize;
+ LONG Length;
+ BYTE *Instr;
+ ADDR Addr;
+
+ assert( RangeStruct );
+ assert( AddrThunk );
+ assert( AddrTarget );
+
+#define PADDINGSIZE 4
+
+ BufferSize = 16;
+ Buffer = (BYTE *)malloc( BufferSize + PADDINGSIZE );
+ assert( Buffer );
+ memset( Buffer + BufferSize, 0, PADDINGSIZE);
+
+ //
+ // Disassemble instructions until a branch is found.
+ //
+ if ( Buffer ) {
+
+ Addr = *AddrThunk;
+
+ while ( TRUE ) {
+
+ AddrReadMemory(RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ &Addr,
+ Buffer,
+ BufferSize,
+ &Length );
+ assert(Length==(LONG)BufferSize);
+
+ //
+ // Unassemble the code and determine where all branches are.
+ //
+ Instr = (BYTE *)Buffer;
+
+ while ( Length > 0 ) {
+
+ BOOL IsBranch;
+ BOOL TargetKnown;
+ BOOL IsCall;
+ BOOL IsTable;
+ ADDR Target;
+ DWORD Consumed;
+
+ //
+ // Unassemble one instruction
+ //
+ Consumed = BranchUnassemble( (void *)Instr,
+ &Addr,
+ &IsBranch,
+ &TargetKnown,
+ &IsCall,
+ &IsTable,
+ &Target );
+
+ if ( Consumed == 0 ) {
+ //
+ // Could not unassemble the instruction.
+ //
+ Length = 0;
+
+ } else {
+
+ //
+ // If instruction is a branch, this is our guy.
+ //
+ if ( IsBranch ) {
+
+ if ( ADDR_IS_FLAT(Target) ) {
+ if ( GetAddrOff(Target) != 0 ) {
+ GetAddrSeg(Target) = PcSegOfHthdx(RangeStruct->hthd);
+ }
+ } else {
+ ADDR_IS_REAL(Target) = RangeStruct->hthd->fAddrIsReal;
+ }
+
+ if ( TargetKnown ) {
+
+ *AddrTarget = Target;
+
+ } else {
+
+ if ( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ AddrThunk,
+ &Addr ) ) {
+
+ UOFF32 NextOffset;
+
+#ifdef TARGET_i386
+ UNREFERENCED_PARAMETER( NextOffset );
+
+ //
+ // Don't have the target but we are at
+ // the jump/call instruction. Will set the
+ // target to the current address and let
+ // the caller decide what to do.
+ //
+
+#else
+ //
+ // We are at the branch instruction, so the
+ // target can be determined.
+ //
+ NextOffset = GetNextOffset( RangeStruct->hthd, RangeStruct->fStepOver );
+
+ GetAddrOff( Addr ) = NextOffset;
+#endif
+
+ *AddrTarget = Addr;
+
+ } else {
+
+ *AddrTarget = Addr;
+ }
+
+ }
+
+ fGotTarget = TRUE;
+ goto GetOut;
+ }
+
+ Instr += Consumed;
+ GetAddrOff(Addr) += Consumed;
+ Length -= Consumed;
+ }
+ }
+ }
+
+ GetOut:
+ free( Buffer );
+ }
+
+ return fGotTarget;
+}
+
+
+
+
+
+
+void
+MethodSmartRangeStep(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD unused,
+ RANGESTRUCT* RangeStruct
+ )
+{
+ ADDR AddrCurrent;
+ BOOL fSingleStep = FALSE;
+
+ assert( de );
+ assert( RangeStruct );
+
+ //
+ // Get the current address
+ //
+ AddrFromHthdx( &AddrCurrent, hthd );
+
+ if ( RangeStruct->fSingleStep ) {
+ //
+ // Recover from single step
+ //
+ RecoverFromSingleStep( &AddrCurrent, RangeStruct );
+ fSingleStep = TRUE;
+ }
+
+ //
+ // See what we must do now.
+ //
+ if ( InsideRange( hthd,
+ &RangeStruct->BranchList->AddrStart,
+ &RangeStruct->BranchList->AddrEnd,
+ &AddrCurrent ) ) {
+
+
+ //
+ // Still inside the range.
+ //
+ if ( ContinueFromInsideRange( &AddrCurrent, RangeStruct ) ) {
+ return;
+ }
+
+ } else {
+
+ //
+ // Outside the range
+ //
+ if ( fSingleStep && RangeStruct->fStepOver && RangeStruct->fInCall ) {
+ //
+ // Recovering from a single step, continue.
+ //
+ RangeStruct->fInCall = FALSE;
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ AddQueue( RangeStruct->fSingleStep ? QT_TRACE_DEBUG_EVENT : QT_CONTINUE_DEBUG_EVENT,
+ RangeStruct->hthd->hprc->pid,
+ RangeStruct->hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ RangeStruct->hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ RangeStruct->hthd->tstate |= ts_running;
+
+ return;
+ }
+ if ( ContinueFromOutsideRange( &AddrCurrent, RangeStruct ) ) {
+ return;
+ }
+ }
+
+ //
+ // If we get here then we must clean up all the allocated resources
+ // and notify the EM.
+ //
+
+ DestroyRangeStruct( RangeStruct );
+
+ //
+ // Notify the EM that this thread has stopped.
+ //
+#ifdef KERNEL
+ hthd->tstate &= ~ts_stepping;
+#endif
+ hthd->tstate &= ~ts_running;
+ hthd->tstate |= ts_stopped;
+ NotifyEM(&falseSSEvent, hthd, 0, (LPVOID)0);
+}
+
+
+VOID
+DestroyRangeStruct(
+ RANGESTRUCT* RangeStruct
+ )
+{
+ if (RangeStruct) {
+
+ if ( RangeStruct->BpCount > 0 ) {
+
+ //assert( RangeStruct->BpList );
+ //assert( RangeStruct->BpAddrs );
+
+ RemoveRangeBp( RangeStruct );
+
+ free( RangeStruct->BpList );
+ free( RangeStruct->BpAddrs );
+ }
+
+ //assert( RangeStruct->BranchList );
+ if (RangeStruct->BranchList) {
+ free( RangeStruct->BranchList );
+ }
+
+ //assert( RangeStruct->Method );
+ if (RangeStruct->Method) {
+ free( RangeStruct->Method );
+ }
+
+ free( RangeStruct );
+ }
+}
+
+
+VOID
+RecoverFromSingleStep(
+ ADDR *AddrCurrent,
+ RANGESTRUCT* RangeStruct
+ )
+{
+ BREAKPOINT *Bp;
+ DWORD i;
+ BP_UNIT opcode = BP_OPCODE;
+
+ assert( AddrCurrent );
+ assert( RangeStruct );
+ assert( RangeStruct->fSingleStep );
+
+
+
+ //
+ // Recovering from a single step.
+ // Reset previous BP
+ //
+
+ Bp = FindBP( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ bptpExec,
+ (BPNS)-1,
+ &RangeStruct->PrevAddr,
+ FALSE );
+
+ assert( Bp );
+
+ if ( Bp ) {
+ WriteBreakPoint( Bp );
+ }
+
+
+
+#ifdef TARGET_i386
+
+#ifndef KERNEL
+ //
+ // Clear trace flag
+ //
+ //
+ RangeStruct->hthd->context.EFlags &= ~(TF_BIT_MASK);
+ RangeStruct->hthd->fContextDirty = TRUE;
+
+#endif // KERNEL
+
+
+#else
+
+ //
+ // Remove temporary breakpoint
+ //
+ assert( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ &RangeStruct->TmpBp->addr,
+ AddrCurrent ) );
+
+ assert( RangeStruct->TmpBp );
+ RemoveBP( RangeStruct->TmpBp );
+ RangeStruct->TmpBp = NULL;
+
+#endif
+
+ RangeStruct->fSingleStep = FALSE;
+}
+
+
+BOOL
+ContinueFromInsideRange(
+ ADDR *AddrCurrent,
+ RANGESTRUCT *RangeStruct
+ )
+{
+
+ DWORD i;
+ BREAKPOINT *Bp;
+ UOFF32 NextOffset;
+ ADDR NextAddr;
+ BOOL fContinue = FALSE;
+
+ assert( AddrCurrent );
+ assert( RangeStruct );
+
+ Bp = AtBP(RangeStruct->hthd);
+
+ if ( RangeStruct->BranchList->Count > 0 && Bp ) {
+
+ if ( Bp != EMBEDDED_BP ) {
+
+ //
+ // Look for the branch node corresponding to this address.
+ // When found, determine the target address and set a
+ // safety breakpoint there if necessary. Then let the
+ // thread continue.
+ //
+ for ( i=0; i < RangeStruct->BranchList->Count; i++ ) {
+
+ if ( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ &RangeStruct->BranchList->BranchNode[i].Addr,
+ AddrCurrent ) ) {
+
+ //
+ // This is our guy.
+ //
+
+ //
+ // Determine the next address
+ //
+ RangeStruct->fInCall = RangeStruct->BranchList->BranchNode[i].IsCall;
+#ifdef TARGET_i386
+ UNREFERENCED_PARAMETER( NextOffset );
+ UNREFERENCED_PARAMETER( NextAddr );
+#else
+ NextOffset = GetNextOffset( RangeStruct->hthd, RangeStruct->fStepOver );
+ AddrInit(&NextAddr, 0, 0, NextOffset, TRUE, TRUE, FALSE, FALSE );
+#endif
+
+ //
+ // We have to single step the current instruction.
+ // We set a temporary breakpoint at the next offset,
+ // recover the current breakpoint and set the flags to
+ // reset the breakpoint when we hit the temporary
+ // breakpoint.
+ //
+ ClearBPFlag( RangeStruct->hthd );
+ RestoreInstrBP( RangeStruct->hthd, Bp );
+ RangeStruct->PrevAddr = *AddrCurrent;
+
+ RangeStruct->fSingleStep = TRUE;
+#ifdef TARGET_i386
+#ifndef KERNEL
+ RangeStruct->hthd->context.EFlags |= TF_BIT_MASK;
+ RangeStruct->hthd->fContextDirty = TRUE;
+#endif // KERNEL
+#else
+ RangeStruct->TmpAddr = NextAddr;
+ RangeStruct->TmpBp = SetBP( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ bptpExec,
+ bpnsStop,
+ &NextAddr,
+ (HPID) INVALID);
+ assert( RangeStruct->TmpBp );
+#endif
+
+ //
+ // Register the expected event.
+ //
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+#ifdef TARGET_i386
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)STATUS_SINGLE_STEP,
+#else
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+#endif
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ AddQueue( RangeStruct->fSingleStep ? QT_TRACE_DEBUG_EVENT : QT_CONTINUE_DEBUG_EVENT,
+ RangeStruct->hthd->hprc->pid, RangeStruct->hthd->tid, DBG_CONTINUE, 0 );
+
+ RangeStruct->hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ RangeStruct->hthd->tstate |= ts_running;
+
+ fContinue = TRUE;
+ break;
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // We might end up here if continuing from a single step.
+ //
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ AddQueue( RangeStruct->fSingleStep ? QT_TRACE_DEBUG_EVENT : QT_CONTINUE_DEBUG_EVENT,
+ RangeStruct->hthd->hprc->pid,
+ RangeStruct->hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ RangeStruct->hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ RangeStruct->hthd->tstate |= ts_running;
+
+ fContinue = TRUE;
+ }
+
+ return fContinue;
+}
+
+
+BOOL
+ContinueFromOutsideRange(
+ ADDR *AddrCurrent,
+ RANGESTRUCT *RangeStruct
+ )
+{
+
+ BOOL fContinue = FALSE;
+ char rgch[sizeof(RTP) + sizeof(ADDR)];
+ HPID hpid = RangeStruct->hthd->hprc->hpid;
+ LPRTP lprtp = (LPRTP) &rgch;
+ LPADDR paddr = (LPADDR) &rgch[sizeof(RTP)];
+ ADDR Addr;
+ BREAKPOINT *Bp;
+
+ assert( AddrCurrent );
+ assert( RangeStruct );
+
+ Bp = AtBP(RangeStruct->hthd);
+
+ if ( RangeStruct->fFromThunk ) {
+
+
+
+ // } else if ( (!Bp || (Bp && Bp != EMBEDDED_BP)) && RangeStruct->fInCall) {
+ } else if ( !Bp || (Bp && Bp != EMBEDDED_BP) ) {
+
+ CANSTEP *CanStep;
+
+ lprtp->dbc = dbcCanStep;
+ lprtp->hpid = hpid;
+ lprtp->htid = RangeStruct->hthd->htid;
+ lprtp->cb = sizeof(ADDR);
+
+ *paddr = *AddrCurrent;
+ DmTlFunc(tlfRequest, hpid, sizeof(rgch), (LONG)&rgch);
+ CanStep = (CANSTEP *)abEMReplyBuf;
+
+ if ( !RangeStruct->fInCall && CanStep->Flags == CANSTEP_NO ) {
+ //
+ // If did not get here thru a call, then we must step
+ // into this no matter what the shell says.
+ //
+ CanStep->Flags = CANSTEP_YES;
+ CanStep->PrologOffset = 0;
+ }
+ switch ( CanStep->Flags ) {
+
+ case CANSTEP_YES:
+ if ( CanStep->PrologOffset > 0 ) {
+
+ Addr = *AddrCurrent;
+ GetAddrOff(Addr) += CanStep->PrologOffset;
+ AddRangeBp( RangeStruct, &Addr, TRUE );
+
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ ClearBPFlag( RangeStruct->hthd );
+ if ( Bp ) {
+ RestoreInstrBP( RangeStruct->hthd, Bp );
+ }
+
+ AddQueue(QT_CONTINUE_DEBUG_EVENT,
+ RangeStruct->hthd->hprc->pid,
+ RangeStruct->hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+
+ RangeStruct->hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ RangeStruct->hthd->tstate |= ts_running;
+
+ fContinue = TRUE;
+
+ }
+ break;
+
+ case CANSTEP_THUNK:
+
+ if ( GetThunkTarget( RangeStruct, AddrCurrent, &Addr ) ) {
+
+ DWORD Class;
+ DWORD SubClass;
+
+ if ( AreAddrsEqual( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ AddrCurrent,
+ &Addr ) ) {
+
+ //
+ // Could not determine target address. Set a single
+ // step and continue.
+ //
+
+ RangeStruct->PrevAddr = *AddrCurrent;
+
+#ifdef TARGET_i386
+#ifndef KERNEL
+ RangeStruct->hthd->context.EFlags |= TF_BIT_MASK;
+ RangeStruct->hthd->fContextDirty = TRUE;
+#endif // KERNEL
+ Class = EXCEPTION_DEBUG_EVENT;
+ SubClass = (DWORD)STATUS_SINGLE_STEP;
+
+#else
+ {
+ ADDR Addr;
+ UOFF32 NextOffset;
+ NextOffset = GetNextOffset( RangeStruct->hthd,
+ RangeStruct->fStepOver );
+ if ( NextOffset != 0x00000000 ) {
+ AddrInit( &Addr, 0, 0, NextOffset, TRUE, TRUE, FALSE, FALSE );
+ RangeStruct->TmpAddr = Addr;
+ RangeStruct->TmpBp = SetBP( RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ bptpExec,
+ bpnsStop,
+ &Addr,
+ (HPID) INVALID);
+ assert( RangeStruct->TmpBp );
+ }
+ Class = BREAKPOINT_DEBUG_EVENT;
+ SubClass = (DWORD)NO_SUBCLASS;
+ }
+#endif
+
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ Class,
+ SubClass,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ } else {
+
+ //
+ // Set breakpoint at target address and continue
+ //
+ AddRangeBp( RangeStruct, &Addr, TRUE );
+
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+ }
+
+ //
+ // Remove current breakpoint
+ //
+ ClearBPFlag( RangeStruct->hthd );
+ if ( Bp ) {
+ RestoreInstrBP( RangeStruct->hthd, Bp );
+ }
+
+ AddQueue( RangeStruct->fSingleStep ? QT_TRACE_DEBUG_EVENT : QT_CONTINUE_DEBUG_EVENT,
+ RangeStruct->hthd->hprc->pid,
+ RangeStruct->hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ RangeStruct->hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ RangeStruct->hthd->tstate |= ts_running;
+
+ fContinue = TRUE;
+ }
+
+ break;
+
+ case CANSTEP_NO:
+ //
+ // Register the expected event.
+ //
+ RegisterExpectedEvent(
+ RangeStruct->hthd->hprc,
+ RangeStruct->hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)NO_SUBCLASS,
+ RangeStruct->Method,
+ NO_ACTION,
+ FALSE,
+ NULL);
+
+ ClearBPFlag( RangeStruct->hthd );
+ if ( Bp ) {
+ RestoreInstrBP( RangeStruct->hthd, Bp );
+ }
+
+ AddQueue( RangeStruct->fSingleStep ?
+ QT_TRACE_DEBUG_EVENT : QT_CONTINUE_DEBUG_EVENT,
+ RangeStruct->hthd->hprc->pid,
+ RangeStruct->hthd->tid,
+ DBG_CONTINUE,
+ 0 );
+ RangeStruct->hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ RangeStruct->hthd->tstate |= ts_running;
+
+ fContinue = TRUE;
+ break;
+ }
+ }
+
+ return fContinue;
+}
+
+
+
+
+void
+RangeStep(
+ HTHDX hthd,
+ UOFF32 offStart,
+ UOFF32 offEnd,
+ BOOL fStopOnBP,
+ BOOL fstepOver
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to implement range stepping the the DM. Range
+ stepping is used to cause all instructions between a pair of addresses
+ to be executed.
+
+ The segment is implied to be the current segment. This is validated
+ in the EM.
+
+ Range stepping is done by registering an expected debug event at the
+ end of a step and seeing if the current program counter is still in
+ the correct range. If it is not then the range step is over, if it
+ is then a new event is register and we loop.
+
+Arguments:
+
+ hthd - Supplies the thread to be stepped.
+ offStart - Supplies the initial offset in the range
+ offEnd - Supplies the final offset in the range
+ fStopOnBP - Supplies TRUE if stop on an initial breakpoint
+ fStepOver - Supplies TRUE if to step over call type instructions
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ RANGESTEP * rs;
+ METHOD * method;
+ HPRCX hprc = hthd->hprc;
+ int lpf = 0;
+ ADDR addr;
+
+ //
+ // Create and fill a range step structure
+ //
+
+ rs = (RANGESTEP*) malloc(sizeof(RANGESTEP));
+ rs->hprc = hprc;
+ rs->hthd = hthd;
+ rs->addrStart = offStart;
+ rs->addrEnd = offEnd;
+ rs->segCur = PcSegOfHthdx(hthd);
+
+
+ //
+ // Create a notification method for this range step
+ //
+
+ method = (METHOD*) malloc(sizeof(METHOD));
+ method->notifyFunction = (ACVECTOR)MethodRangeStep;
+ method->lparam = rs;
+ rs->method = method;
+ rs->safetyBP = NULL;
+
+ if ( fstepOver ) {
+ rs->stepFunction = StepOver;
+ } else {
+ rs->stepFunction = SingleStep;
+
+ /*
+ * Check to see if we are currently at a call instruction. If we
+ * are then we need to set a breakpoint at the end of the call
+ * instruction as the "safty" breakpoint.
+ *
+ * This will allow use to reccover back to the current level
+ * if the call we are just about to step into does not have
+ * any source information (in which case the range step
+ * is defined to continue).
+ */
+
+ AddrInit(&addr, 0, rs->segCur, offStart,
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE, hthd->fAddrIsReal);
+ IsCall( hthd, &addr, &lpf, FALSE);
+ if ( lpf== INSTR_IS_CALL ) {
+ rs->safetyBP = SetBP(hprc, hthd, bptpExec, bpnsStop, &addr, (HPID)INVALID);
+ }
+ }
+
+ //
+ // Call the step over function to send notifications
+ // to the RangeStepper (NOT THE EM!)
+ //
+ (rs->stepFunction)(hthd, method, fStopOnBP, FALSE);
+
+ return;
+} /* RangeStep() */
+
+
+
+
+/*** MethodRangeStep
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** This method is called upon the receipt of a single step event
+** while inside of a range step. It checks if the IP is still in the
+** specified range, if it isn't then the EM is notified that the
+** process has stopped outside the range, and all the RS structs and
+** notification method are freed.
+*/
+
+void
+MethodRangeStep(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD unused,
+ RANGESTEP* rs
+ )
+{
+ LPCONTEXT lpContext = &hthd->context;
+ DWORD eip = (DWORD)cPC(lpContext);
+ DWORD currAddr = eip;
+ int lpf = 0;
+ HPRCX hprc = hthd->hprc;
+ HANDLE rwHand = hprc->rwHand;
+ METHOD * method;
+ ADDR addr;
+
+ Unreferenced( de );
+
+ DEBUG_PRINT_3("** MethodRangeStep called: %08x-%08x EIP=%08x",
+ rs->addrStart, rs->addrEnd, eip);
+
+ //
+ // Check if we are in unknown territory
+ //
+ if (rs->safetyBP) {
+ HPID hpid = hprc->hpid;
+ char rgch[sizeof(RTP) + sizeof(ADDR)];
+ LPRTP lprtp = (LPRTP) &rgch;
+ LPADDR paddr = (LPADDR) &rgch[sizeof(RTP)];
+ CANSTEP *CanStep;
+
+ //
+ // The safety BP was on, indicating we don't know if
+ // source is available for this range. Must check now
+ // if source exists.
+ //
+
+ //
+ // Form the request packet
+ //
+ lprtp->dbc = dbcCanStep;
+ lprtp->hpid = hpid;
+ lprtp->htid = hthd->htid;
+ lprtp->cb = sizeof(ADDR);
+ AddrFromHthdx(paddr, hthd);
+
+ //
+ // Ask the debugger if we can step into this function
+ //
+ DmTlFunc(tlfRequest, hpid, sizeof(rgch), (LONG)&rgch);
+ CanStep = (CANSTEP *)abEMReplyBuf;
+ switch ( CanStep->Flags ) {
+
+ case CANSTEP_THUNK:
+ (rs->stepFunction)(hthd, rs->method, TRUE, FALSE);
+ return;
+ break;
+
+
+ case CANSTEP_NO:
+
+ method = (METHOD*)malloc(sizeof(METHOD));
+
+ //
+ // We are not allowed to step into here. We
+ // must now continue to our safety breakpoint.
+ //
+ *method = *rs->method;
+ method->lparam2 = (LPVOID)rs->safetyBP;
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)rs->safetyBP,
+ DONT_NOTIFY,
+ (ACVECTOR) SSActionRemoveBP,
+ FALSE,
+ method);
+ //
+ // Since we are not expecting the safty we don't need to have
+ // it set any more
+ //
+ rs->safetyBP = NULL;
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ return;
+ break;
+
+ case CANSTEP_YES:
+ //
+ // We are allowed to step in here, so remove
+ // our safety BP, and fall through
+ //
+ RemoveBP(rs->safetyBP);
+ rs->safetyBP = NULL;
+ break;
+ }
+ }
+
+ //
+ // Check if we are still within the range
+ //
+ if ((rs->addrStart <= eip) &&
+ (eip <= rs->addrEnd) &&
+ (PcSegOfHthdx(hthd) == rs->segCur)) {
+
+ //
+ // We still are in the range, continue stepping
+ //
+ if (rs->stepFunction!=(STEPPER)StepOver){
+
+ //
+ // If we a doing a "Step Into" must check for "CALL"
+ //
+ AddrFromHthdx(&addr, hthd);
+ IsCall(hthd, &addr, &lpf, FALSE);
+ if (lpf== INSTR_IS_CALL) {
+
+ //
+ // Before we step into this function, let's
+ // put a "safety-net" breakpoint on the instruction
+ // after this call. This way if we don't have
+ // source for this function, we can always continue
+ // and break at this safety-net breakpoint.
+ //
+ rs->safetyBP = SetBP(hprc, hthd, bptpExec, bpnsStop, &addr, (HPID)INVALID);
+ }
+ }
+ (rs->stepFunction)(hthd, rs->method, TRUE, FALSE);
+ return;
+ }
+
+ DEBUG_PRINT(" Out\n");
+
+ //
+ // We are no longer in the range, free all consummable
+ // events on the queue for this thread
+ //
+ ConsumeAllThreadEvents(hthd, FALSE);
+
+ //
+ // Free the structures created for range-stepping
+ //
+ free(rs->method);
+ free(rs);
+
+ //
+ // Notify the EM that this thread has stopped on a SS
+ //
+ hthd->tstate &= ~ts_running;
+ hthd->tstate |= ts_stopped;
+ NotifyEM(&falseSSEvent, hthd, 0, (LPVOID)0);
+
+ return;
+}
+
+void
+WtPrintCallNode(
+ LPWTNODE wt
+ )
+{
+ DWORD i;
+ static CHAR margin[] =
+" ";
+ i = wt->lex*3;
+ if (i > 60) {
+ i = 60;
+ }
+ DMPrintShellMsg( "%4d %4d %*.*s%s\r\n",
+ wt->icnt,
+ wt->scnt,
+ i, i, margin,
+ wt->fname );
+}
+
+void
+WtGetSymbolName(
+ HTHDX hthd,
+ LPADDR lpaddr,
+ LPSTR *lpFname,
+ LPDWORD lpdwSymAddress,
+ LPDWORD lpdwReturnAddress
+ )
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ LPRTP rtp;
+ LPDMSYM lpds = (LPDMSYM)abEMReplyBuf;
+
+
+ __try {
+
+ rtp = (LPRTP)malloc(sizeof(RTP)+sizeof(ADDR));
+
+ rtp->hpid = hthd->hprc->hpid;
+ rtp->htid = hthd->htid;
+ rtp->dbc = dbceGetSymbolFromOffset;
+ rtp->cb = sizeof(ADDR);
+
+ memcpy( rtp->rgbVar, lpaddr, rtp->cb );
+
+ DmTlFunc( tlfRequest, rtp->hpid, sizeof(RTP)+rtp->cb, (LONG)rtp );
+
+ free( rtp );
+
+ *lpFname = _strdup( lpds->fname );
+ *lpdwSymAddress = GetAddrOff(lpds->AddrSym);
+ *lpdwReturnAddress = lpds->Ra;
+
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ *lpFname = NULL;
+ *lpdwReturnAddress = 0;
+ *lpdwSymAddress = 0;
+
+ }
+}
+
+
+/*** WtMethodRangeStep
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** This method is called upon the receipt of a single step event
+** while inside of a range step. It checks if the IP is still in the
+** specified range, if it isn't then the EM is notified that the
+** process has stopped outside the range, and all the RS structs and
+** notification method are freed.
+*/
+
+void
+WtMethodRangeStep(
+ DEBUG_EVENT *de,
+ HTHDX hthd,
+ DWORD unused,
+ RANGESTEP *rs
+ )
+{
+ DWORD currAddr = (DWORD)PC(hthd);
+ HPRCX hprc = hthd->hprc;
+ ADDR addr;
+ LPWTNODE wt;
+ LPWTNODE wt1;
+ DWORD ra;
+ DWORD symaddr;
+
+
+ AddrInit( &addr, 0, PcSegOfHthdx(hthd), currAddr,
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE, hthd->fAddrIsReal );
+
+ hthd->wtcurr->icnt++;
+
+ if (rs->fIsRet) {
+ rs->fIsRet = FALSE;
+ WtPrintCallNode( hthd->wtcurr );
+ if (hthd->wtcurr->caller) {
+ wt1 = hthd->wtcurr;
+ wt = wt1->caller;
+ wt->scnt += wt1->icnt + wt1->scnt;
+ wt->callee = NULL;
+ hthd->wtcurr = wt;
+ free(wt1);
+ }
+ }
+
+
+ if (rs->addrEnd == 0 || currAddr == rs->addrEnd || hthd->wtmode == 2) {
+
+ //
+ // unwind the stack, print totals
+ //
+
+ wt = hthd->wtcurr;
+ while (wt) {
+ WtPrintCallNode( wt );
+ if (wt1 = wt->caller ) {
+ wt1->scnt += wt->icnt + wt->scnt;
+ free(wt);
+ }
+ wt = wt1;
+ }
+
+ finished:
+ hthd->wtmode = 0;
+ ConsumeAllThreadEvents(hthd, FALSE);
+ free(rs->method);
+ free(rs);
+ hthd->tstate &= ~ts_running;
+ hthd->tstate |= ts_stopped;
+ NotifyEM(&falseSSEvent, hthd, 0, (LPVOID)0);
+ return;
+ }
+
+ if (rs->fIsCall) {
+ LPSTR p;
+ //
+ // we just completed a call instruction
+ // the pc is the first instruction of a new function
+ //
+ wt = malloc( sizeof(WTNODE) );
+ ZeroMemory( wt, sizeof(WTNODE) );
+
+ hthd->wtcurr->callee = wt;
+ wt->caller = hthd->wtcurr;
+ wt->lex = hthd->wtcurr->lex + 1;
+ wt->offset = currAddr;
+ wt->sp = (DWORD)STACK_POINTER(hthd);
+
+ WtGetSymbolName( hthd, &addr, &p, &symaddr, &ra );
+
+ if (!p) {
+ p = malloc( 16 );
+ sprintf( p, "0x%08x", currAddr );
+ } else if (symaddr != currAddr) {
+ DWORD l = strlen(p);
+ p = realloc(p, l + 12);
+ sprintf(p + l, "+0x%x", currAddr - symaddr);
+ }
+ wt->fname = p;
+
+ //
+ // put new node at head of chain.
+ //
+
+ hthd->wtcurr = wt;
+ }
+
+ if (STACK_POINTER(hthd) > hthd->wtcurr->sp) {
+
+ //
+ // attempt to compensate for unwinds and longjumps.
+ // also catches cases that miss the target address.
+ //
+
+ //
+ // unwind the stack, print totals
+ //
+
+ wt = hthd->wtcurr;
+ while (wt && STACK_POINTER(hthd) > wt->sp) {
+ WtPrintCallNode( wt );
+ if (wt1 = wt->caller ) {
+ wt1->scnt += wt->icnt + wt->scnt;
+ free(wt);
+ }
+ wt = wt1;
+ }
+ if (wt) {
+ hthd->wtcurr = wt;
+ } else {
+ hthd->wtcurr = &hthd->wthead;
+ goto finished;
+ }
+
+ }
+
+ rs->fIsCall = FALSE;
+
+ rs->fIsRet = IsRet(hthd, &addr);
+
+ if (!rs->fIsRet) {
+ int CallFlag;
+ IsCall( hthd, &addr, &CallFlag, FALSE );
+ if (CallFlag == INSTR_IS_CALL) {
+ //
+ // we are about to trace a call instruction
+ //
+ rs->fIsCall = TRUE;
+ WtPrintCallNode( hthd->wtcurr );
+ }
+ }
+
+ SingleStep( hthd, rs->method, TRUE, FALSE );
+
+ return;
+} /* WtMethodRangeStep() */
+
+
+
+void
+WtRangeStep(
+ HTHDX hthd
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to implement the watch trace feature in the DM. Range
+ stepping is used to cause all instructions between a pair of addresses
+ to be executed.
+
+ The segment is implied to be the current segment. This is validated
+ in the EM.
+
+ Range stepping is done by registering an expected debug event at the
+ end of a step and seeing if the current program counter is still in
+ the correct range. If it is not then the range step is over, if it
+ is then a new event is register and we loop.
+
+Arguments:
+
+ hthd - Supplies the thread to be stepped.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ RANGESTEP *rs;
+ METHOD *method;
+ HPRCX hprc = hthd->hprc;
+ int CallFlag = 0;
+ ADDR addr;
+ LPSTR fname;
+ DWORD ra;
+ DWORD symaddr;
+ DWORD instrOff;
+
+
+ if (hthd->wtmode != 0) {
+ DMPrintShellMsg( "wt command already running for this thread\r\n" );
+ return;
+ }
+
+ AddrInit( &addr, 0, PcSegOfHthdx(hthd), (DWORD)PC(hthd),
+ hthd->fAddrIsFlat, hthd->fAddrOff32, FALSE, hthd->fAddrIsReal );
+ WtGetSymbolName( hthd, &addr, &fname, &symaddr, &ra );
+
+
+ //
+ // Create and fill a range step structure
+ //
+ rs = (RANGESTEP*) malloc(sizeof(RANGESTEP));
+ ZeroMemory( rs, sizeof(RANGESTEP) );
+
+ //
+ // Create a notification method for this range step
+ //
+ method = (METHOD*) malloc(sizeof(METHOD));
+ method->notifyFunction = (ACVECTOR)WtMethodRangeStep;
+ method->lparam = rs;
+
+ rs->hprc = hprc;
+ rs->hthd = hthd;
+ rs->segCur = PcSegOfHthdx(hthd);
+ rs->method = method;
+ rs->safetyBP = NULL;
+ rs->stepFunction = NULL;
+ rs->addrStart = (DWORD)PC(hthd);
+
+ //
+ // always tell the watch stepper that the first instruction
+ // was a call. that way, it makes a frame for the place that
+ // we are returning to.
+ //
+ rs->fIsCall = TRUE;
+
+ hthd->wtcurr = &hthd->wthead;
+ ZeroMemory( hthd->wtcurr, sizeof(WTNODE) );
+ hthd->wtcurr->offset = (DWORD)PC(hthd);
+ hthd->wtcurr->sp = (DWORD)STACK_POINTER(hthd);
+ hthd->wtcurr->fname = fname;
+ hthd->wtmode = 1;
+
+
+ IsCall( hthd, &addr, &CallFlag, FALSE);
+ if (CallFlag == INSTR_IS_CALL) {
+ ra = GetAddrOff(addr);
+ }
+
+ rs->addrEnd = ra;
+ DMPrintShellMsg( "Tracing %s to return address %08x\r\n", fname, ra );
+
+ if (CallFlag == INSTR_IS_CALL) {
+
+ //
+ // This is a call instruction. Assume that we
+ // want to trace the function that is about to
+ // be called. The call instruction will be the
+ // only instruction counted in the current frame.
+ //
+
+ //
+ // Call the step over function to send notifications
+ // to the RangeStepper (NOT THE EM!)
+ //
+
+ SingleStep(hthd, method, TRUE, FALSE);
+
+ } else {
+
+ //
+ // tracing to return address.
+ //
+ // tell it that we just did a call so that a new
+ // frame will be pushed, leaving the current frame
+ // to contain this function's caller.
+ //
+
+ hthd->wtcurr->icnt = -1;
+ WtMethodRangeStep(&falseSSEvent, hthd, 0, rs);
+ }
+
+ return;
+} /* WtRangeStep() */
diff --git a/private/windbg/newdm/support.c b/private/windbg/newdm/support.c
new file mode 100644
index 000000000..88a0dab68
--- /dev/null
+++ b/private/windbg/newdm/support.c
@@ -0,0 +1,2396 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ api.c
+
+Abstract:
+
+ This module implements the all apis that simulate their
+ WIN32 counterparts.
+
+Author:
+
+ Wesley Witt (wesw) 8-Mar-1992
+
+Environment:
+
+ NT 3.1
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+extern CRITICAL_SECTION csPacket;
+
+//#define dp(s) OutputDebugString(s)
+#define dp(s)
+
+
+
+DWORD
+DmKdReadPhysicalMemory(
+ IN PHYSICAL_ADDRESS TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the specified data from the physical memory of
+ the system being debugged.
+
+Arguments:
+
+ TargetBaseAddress - Supplies the physical address of the memory to read
+ from the system being debugged.
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that data read is to be placed.
+
+ TransferCount - Specifies the number of bytes to read.
+
+ ActualBytesRead - An optional parameter that if supplied, returns
+ the number of bytes actually read.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is too large was specified.
+
+ STATUS_ACCESS_VIOLATION - TBD // Can you even HAVE an access
+ // violation with a physical
+ // memory access??
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
+ DWORD st, cb, cb2;
+ BOOLEAN rc;
+
+ dp("DmKdReadPhysicalMemory\n");
+
+ EnterCriticalSection(&csPacket);
+
+ if (TransferCount > PACKET_MAX_SIZE) {
+ // Read the partial the first time.
+ cb = TransferCount % PACKET_MAX_SIZE;
+ } else {
+ cb = TransferCount;
+ }
+
+ cb2 = 0;
+
+ if (ARGUMENT_PRESENT(ActualBytesRead)) {
+ *ActualBytesRead = 0;
+ }
+
+ while (TransferCount != 0) {
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdReadPhysicalMemoryApi;
+ m.ReturnStatus = STATUS_PENDING;
+ //
+ // BUGBUG TargetBaseAddress should be >32 bits
+ //
+ a->TargetBaseAddress = (PVOID)(TargetBaseAddress.LowPart+cb2);
+ a->TransferCount = cb;
+ a->ActualBytesRead = 0L;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a ReadMemory response then protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdReadPhysicalMemoryApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadMemory;
+ assert(a->ActualBytesRead <= cb);
+
+ //
+ // Return actual bytes read, and then transfer the bytes
+ //
+
+ if (ARGUMENT_PRESENT(ActualBytesRead)) {
+ *ActualBytesRead += a->ActualBytesRead;
+ }
+ st = Reply->ReturnStatus;
+
+ //
+ // Since read response data follows message, Reply+1 should point
+ // at the data
+ //
+
+ memcpy((PCHAR)((DWORD) UserInterfaceBuffer+cb2), Reply+1, (int)a->ActualBytesRead);
+
+ if (st != STATUS_SUCCESS) {
+ TransferCount = 0;
+ } else {
+ TransferCount -= cb;
+ cb2 += cb;
+ cb = PACKET_MAX_SIZE;
+ }
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdWritePhysicalMemory(
+ IN PHYSICAL_ADDRESS TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesWritten OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the specified data to the physical memory of the
+ system being debugged.
+
+Arguments:
+
+ TargetBaseAddress - Supplies the physical address of the memory to write
+ to the system being debugged.
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that contains the data to be written.
+
+ TransferCount - Specifies the number of bytes to write.
+
+ ActualBytesWritten - An optional parameter that if supplied, returns
+ the number of bytes actually written.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
+
+ STATUS_ACCESS_VIOLATION - TBD // Can you even HAVE an access
+ // violation with a physical
+ // memory access??
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
+ DWORD st;
+ BOOLEAN rc;
+ ULONG cb, cb2;
+
+
+ dp("DmKdWritePhysicalMemory\n");
+
+ EnterCriticalSection(&csPacket);
+
+ if (TransferCount > PACKET_MAX_SIZE) {
+ // Read the partial the first time.
+ cb = TransferCount % PACKET_MAX_SIZE;
+ } else {
+ cb = TransferCount;
+ }
+
+ cb2 = 0;
+
+ if (ARGUMENT_PRESENT(ActualBytesWritten)) {
+ *ActualBytesWritten = 0;
+ }
+
+ while (TransferCount != 0) {
+ //
+ // Format state manipulate message
+ //
+
+
+ m.ApiNumber = DbgKdWritePhysicalMemoryApi;
+ m.ReturnStatus = STATUS_PENDING;
+ //
+ // BUGBUG TargetBaseAddress should be >32 bits
+ //
+ a->TargetBaseAddress = (PVOID)(TargetBaseAddress.LowPart+cb2);
+ a->TransferCount = cb;
+ a->ActualBytesWritten = 0L;
+
+ //
+ // Send the message and data to write and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ (PVOID)((DWORD)UserInterfaceBuffer+cb2),
+ (USHORT)cb
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a WriteMemory response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdWritePhysicalMemoryApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.WriteMemory;
+ assert(a->ActualBytesWritten <= cb);
+
+ //
+ // Return actual bytes written
+ //
+
+ if (ARGUMENT_PRESENT(ActualBytesWritten)) {
+ *ActualBytesWritten += a->ActualBytesWritten;
+ }
+ st = Reply->ReturnStatus;
+
+ if (st != STATUS_SUCCESS) {
+ TransferCount = 0;
+ } else {
+ TransferCount -= cb;
+ cb2 += cb;
+ cb = PACKET_MAX_SIZE;
+ }
+ }
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdReboot( VOID )
+
+/*++
+
+Routine Description:
+
+ This function reboots being debugged.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdRebootApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ //
+ // Send the message.
+ //
+
+ if (!DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0)) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return STATUS_SUCCESS;
+}
+
+DWORD
+DmKdGetContext(
+ IN USHORT Processor,
+ IN OUT PCONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the context from the system being debugged.
+ The ContextFlags field determines how much context is read.
+
+Arguments:
+
+ Processor - Supplies a processor number to get context from.
+
+ Context - On input, the ContextFlags field controls what portions of
+ the context record the caller as interested in reading. On
+ output, the context record returns the current context for the
+ processor that reported the last state change.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified get context occured.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_GET_CONTEXT a = &m.u.GetContext;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdGetContext\n");
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdGetContextApi;
+ m.ReturnStatus = STATUS_PENDING;
+ m.Processor = Processor;
+ a->ContextFlags = Context->ContextFlags;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a GetContext response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdGetContextApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.GetContext;
+ st = Reply->ReturnStatus;
+
+ //
+ // Since get context response data follows message, Reply+1 should point
+ // at the data
+ //
+
+ memcpy(Context, Reply+1, sizeof(*Context));
+
+ //
+ // Check if current command has been canceled. If yes, go back to
+ // kd prompt. BUGBUG Do we really need to check for this call?
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdSetContext(
+ IN USHORT Processor,
+ IN CONST CONTEXT *Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the specified context to the system being debugged.
+
+Arguments:
+
+ Processor - Supplies a processor number to set the context to.
+
+ Context - Supplies a context record used to set the context for the
+ processor that reported the last state change. Only the
+ portions of the context indicated by the ContextFlags field are
+ actually written.
+
+
+Return Value:
+
+ STATUS_SUCCESS - The specified set context occured.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_SET_CONTEXT a = &m.u.SetContext;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdSetContext\n");
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdSetContextApi;
+ m.ReturnStatus = STATUS_PENDING;
+ m.Processor = Processor;
+ a->ContextFlags = Context->ContextFlags;
+
+ //
+ // Send the message and context and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ (PVOID)Context,
+ sizeof(*Context)
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a SetContext response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdSetContextApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.SetContext;
+ st = Reply->ReturnStatus;
+
+ //
+ // Check if the current command has been canceled.
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdWriteBreakPoint(
+ IN PVOID BreakPointAddress,
+ OUT PULONG BreakPointHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to write a breakpoint at the address specified.
+
+
+Arguments:
+
+ BreakPointAddress - Supplies the address that a breakpoint
+ instruction is to be written. This address is interpreted using
+ the current mapping on the processor reporting the previous
+ state change. If the address refers to a page that is not
+ valid, the the breakpoint is remembered by the system. As each
+ page is made valid, the system will check for pending
+ breakpoints and install breakpoints as necessary.
+
+ BreakPointHandle - Returns a handle to a breakpoint. This handle
+ may be used in a subsequent call to DmKdRestoreBreakPoint.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified breakpoint write occured.
+
+ !NT_SUCCESS() - TBD
+
+
+--*/
+
+{
+
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_WRITE_BREAKPOINT a = &m.u.WriteBreakPoint;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdWriteBreakPoint\n");
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdWriteBreakPointApi;
+ m.ReturnStatus = STATUS_PENDING;
+ a->BreakPointAddress = BreakPointAddress;
+
+ //
+ // Send the message and context and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ NULL,
+ 0
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a WriteBreakPoint response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdWriteBreakPointApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.WriteBreakPoint;
+ st = Reply->ReturnStatus;
+ *BreakPointHandle = a->BreakPointHandle;
+
+ //
+ // Check should we return to caller or to kd prompt.
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdRestoreBreakPoint(
+ IN ULONG BreakPointHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to restore a breakpoint to its original
+ value.
+
+Arguments:
+
+ BreakPointHandle - Supplies a handle returned by
+ DmKdWriteBreakPoint. This handle must refer to a valid
+ address. The contents of the address must also be a breakpoint
+ instruction. If both of these are true, then the original value
+ at the breakpoint address is restored.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified breakpoint restore occured.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_RESTORE_BREAKPOINT a = &m.u.RestoreBreakPoint;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdRestoreBreakPoint\n");
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdRestoreBreakPointApi;
+ m.ReturnStatus = STATUS_PENDING;
+ a->BreakPointHandle = BreakPointHandle;
+
+ //
+ // Send the message and context and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ NULL,
+ 0
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a RestoreBreakPoint response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdRestoreBreakPointApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.RestoreBreakPoint;
+ st = Reply->ReturnStatus;
+
+ //
+ // free the packet
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdReadIoSpace(
+ IN PVOID IoAddress,
+ OUT PVOID ReturnedData,
+ IN ULONG DataSize
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used read a byte, short, or long (1,2,4 bytes) from
+ the specified I/O address.
+
+Arguments:
+
+ IoAddress - Supplies the Io address to read from.
+
+ ReturnedData - Supplies the value read from the I/O address.
+
+ DataSize - Supplies the size in bytes to read. Values of 1, 2, or
+ 4 are accepted.
+
+Return Value:
+
+ STATUS_SUCCESS - Data was successfully read from the I/O
+ address.
+
+ STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
+ specified.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdReadIoSpace\n");
+
+ EnterCriticalSection(&csPacket);
+
+ switch ( DataSize ) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdReadIoSpaceApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ a->DataSize = DataSize;
+ a->IoAddress = IoAddress;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ NULL,
+ 0
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a ReadIo response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdReadIoSpaceApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadWriteIo;
+ st = Reply->ReturnStatus;
+
+ switch ( DataSize ) {
+ case 1:
+ *(PUCHAR)ReturnedData = (UCHAR)a->DataValue;
+ break;
+ case 2:
+ *(PUSHORT)ReturnedData = (USHORT)a->DataValue;
+ break;
+ case 4:
+ *(PULONG)ReturnedData = a->DataValue;
+ break;
+ }
+
+ //
+ // Check if current command has been canceled. If yes, go back to
+ // kd prompt. BUGBUG Do we really need to check for this call?
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+
+DWORD
+DmKdWriteIoSpace(
+ IN PVOID IoAddress,
+ IN ULONG DataValue,
+ IN ULONG DataSize
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used write a byte, short, or long (1,2,4 bytes) to
+ the specified I/O address.
+
+Arguments:
+
+ IoAddress - Supplies the Io address to write to.
+
+ DataValue - Supplies the value to write to the I/O address.
+
+ DataSize - Supplies the size in bytes to write. Values of 1, 2, or
+ 4 are accepted.
+
+Return Value:
+
+ STATUS_SUCCESS - Data was successfully written to the I/O
+ address.
+
+ STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
+ specified.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdWriteIoSpace\n");
+
+ EnterCriticalSection(&csPacket);
+
+ switch ( DataSize ) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdWriteIoSpaceApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ a->DataSize = DataSize;
+ a->IoAddress = IoAddress;
+ a->DataValue = DataValue;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ NULL,
+ 0
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a WriteIo response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdWriteIoSpaceApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadWriteIo;
+ st = Reply->ReturnStatus;
+
+ //
+ // free the packet
+ //
+
+ //
+ // Check should we return to caller or to kd prompt.
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdReadIoSpaceEx(
+ IN PVOID IoAddress,
+ OUT PVOID ReturnedData,
+ IN ULONG DataSize,
+ IN ULONG InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG AddressSpace
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used read a byte, short, or long (1,2,4 bytes) from
+ the specified I/O address.
+
+Arguments:
+
+ IoAddress - Supplies the Io address to read from.
+
+ ReturnedData - Supplies the value read from the I/O address.
+
+ DataSize - Supplies the size in bytes to read. Values of 1, 2, or
+ 4 are accepted.
+
+Return Value:
+
+ STATUS_SUCCESS - Data was successfully read from the I/O
+ address.
+
+ STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
+ specified.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_WRITE_IO_EXTENDED a = &m.u.ReadWriteIoExtended;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdReadIoSpaceEx\n");
+
+ EnterCriticalSection(&csPacket);
+
+ switch ( DataSize ) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdReadIoSpaceExtendedApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ a->DataSize = DataSize;
+ a->IoAddress = IoAddress;
+ a->InterfaceType = InterfaceType;
+ a->BusNumber = BusNumber;
+ a->AddressSpace = AddressSpace;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ NULL,
+ 0
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a ReadIo response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdReadIoSpaceExtendedApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadWriteIoExtended;
+ st = Reply->ReturnStatus;
+
+ switch ( DataSize ) {
+ case 1:
+ *(PUCHAR)ReturnedData = (UCHAR)a->DataValue;
+ break;
+ case 2:
+ *(PUSHORT)ReturnedData = (USHORT)a->DataValue;
+ break;
+ case 4:
+ *(PULONG)ReturnedData = a->DataValue;
+ break;
+ }
+
+ //
+ // Check if current command has been canceled. If yes, go back to
+ // kd prompt. BUGBUG Do we really need to check for this call?
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+DWORD
+DmKdWriteIoSpaceEx(
+ IN PVOID IoAddress,
+ IN ULONG DataValue,
+ IN ULONG DataSize,
+ IN ULONG InterfaceType,
+ IN ULONG BusNumber,
+ IN ULONG AddressSpace
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used write a byte, short, or long (1,2,4 bytes) to
+ the specified I/O address.
+
+Arguments:
+
+ IoAddress - Supplies the Io address to write to.
+
+ DataValue - Supplies the value to write to the I/O address.
+
+ DataSize - Supplies the size in bytes to write. Values of 1, 2, or
+ 4 are accepted.
+
+Return Value:
+
+ STATUS_SUCCESS - Data was successfully written to the I/O
+ address.
+
+ STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
+ specified.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_WRITE_IO_EXTENDED a = &m.u.ReadWriteIoExtended;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdWriteIoSpaceEx\n");
+
+ EnterCriticalSection(&csPacket);
+
+ switch ( DataSize ) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdWriteIoSpaceExtendedApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ a->DataSize = DataSize;
+ a->IoAddress = IoAddress;
+ a->DataValue = DataValue;
+ a->InterfaceType = InterfaceType;
+ a->BusNumber = BusNumber;
+ a->AddressSpace = AddressSpace;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ NULL,
+ 0
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a WriteIo response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdWriteIoSpaceExtendedApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadWriteIoExtended;
+ st = Reply->ReturnStatus;
+
+ //
+ // free the packet
+ //
+
+ //
+ // Check should we return to caller or to kd prompt.
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdReadVirtualMemory(
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Interface to read VirtualMemory from target machine.
+ Goes through cached memory addresses, then through serial port.
+
+Arguments:
+
+ TargetBaseAddress - Supplies the base address of the memory to read
+ from the system being debugged. The virtual address is in terms
+ of the current mapping for the processor that reported the last
+ state change. Until we figure out how to do this differently,
+ the virtual address must refer to a valid page (although it does
+ not necesserily have to be in the TB).
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that data read is to be placed.
+
+ TransferCount - Specifies the number of bytes to read.
+
+ ActualBytesRead - An optional parameter that if supplied, returns
+ the number of bytes actually read.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
+
+ STATUS_ACCESS_VIOLATION - The TargetBaseAddress/TransferCount
+ parameters refers to invalid virtual memory.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ ULONG BytesRead=0;
+ ULONG BytesRequested=0;
+ DWORD rc=0;
+
+
+ dp("DmKdReadVirtualMemory\n");
+
+ EnterCriticalSection(&csPacket);
+
+ rc = DmKdReadCachedVirtualMemory (
+ (ULONG) TargetBaseAddress,
+ (ULONG) BytesRequested,
+ (PUCHAR) UserInterfaceBuffer,
+ (PULONG) &BytesRead,
+ FALSE );
+
+ if (BytesRead > TransferCount) {
+ BytesRead = TransferCount;
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return rc;
+}
+
+DWORD
+DmKdReadVirtualMemoryNow(
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the specified data from the system being debugged
+ using the current mapping of the processor.
+
+Arguments:
+
+ TargetBaseAddress - Supplies the base address of the memory to read
+ from the system being debugged. The virtual address is in terms
+ of the current mapping for the processor that reported the last
+ state change. Until we figure out how to do this differently,
+ the virtual address must refer to a valid page (although it does
+ not necesserily have to be in the TB).
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that data read is to be placed.
+
+ TransferCount - Specifies the number of bytes to read.
+
+ ActualBytesRead - An optional parameter that if supplied, returns
+ the number of bytes actually read.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
+
+ STATUS_ACCESS_VIOLATION - The TargetBaseAddress/TransferCount
+ parameters refers to invalid virtual memory.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
+ DWORD st;
+ BOOLEAN rc;
+ DWORD cb, cb2;
+
+ dp("DmKdReadVirtualMemoryNow\n");
+
+ EnterCriticalSection(&csPacket);
+
+ if (TransferCount > PACKET_MAX_SIZE) {
+ // Read the partial the first time.
+ cb = TransferCount % PACKET_MAX_SIZE;
+ } else {
+ cb = TransferCount;
+ }
+
+ cb2 = 0;
+
+ if (ARGUMENT_PRESENT(ActualBytesRead)) {
+ *ActualBytesRead = 0;
+ }
+
+ while (TransferCount != 0) {
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdReadVirtualMemoryApi;
+ m.ReturnStatus = STATUS_PENDING;
+ a->TargetBaseAddress = (PVOID) ((DWORD)TargetBaseAddress+cb2);
+ a->TransferCount = cb;
+ a->ActualBytesRead = 0L;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
+ &Reply
+ );
+ } while (rc == FALSE);
+
+ //
+ // If this is not a ReadMemory response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdReadVirtualMemoryApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadMemory;
+ assert(a->ActualBytesRead <= cb);
+
+ //
+ // Return actual bytes read, and then transfer the bytes
+ //
+
+ if (ARGUMENT_PRESENT(ActualBytesRead)) {
+ *ActualBytesRead += a->ActualBytesRead;
+ }
+
+ //
+ // Since read response data follows message, Reply+1 should point
+ // at the data
+ //
+
+ memcpy((PVOID)((DWORD)UserInterfaceBuffer+cb2), Reply+1, (int)a->ActualBytesRead);
+
+ st = Reply->ReturnStatus;
+
+ if (st != STATUS_SUCCESS) {
+ TransferCount = 0;
+ } else {
+ TransferCount -= cb;
+ cb2 += cb;
+ cb = PACKET_MAX_SIZE;
+ }
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdWriteVirtualMemory(
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesWritten OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the specified data to the system being debugged
+ using the current mapping of the processor.
+
+Arguments:
+
+ TargetBaseAddress - Supplies the base address of the memory to be written
+ into the system being debugged. The virtual address is in terms
+ of the current mapping for the processor that reported the last
+ state change. Until we figure out how to do this differently,
+ the virtual address must refer to a valid page (although it does
+ not necesserily have to be in the TB).
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that contains the data to be written.
+
+ TransferCount - Specifies the number of bytes to write.
+
+ ActualBytesWritten - An optional parameter that if supplied, returns
+ the number of bytes actually written.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
+
+ STATUS_ACCESS_VIOLATION - The TargetBaseAddress/TransferCount
+ parameters refers to invalid virtual memory.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
+ DWORD st, cb, cb2;
+ BOOLEAN rc;
+
+ dp("DmKdWriteVirtualMemory\n");
+
+ EnterCriticalSection(&csPacket);
+
+ DmKdWriteCachedVirtualMemory (
+ (ULONG) TargetBaseAddress,
+ (ULONG) TransferCount,
+ (PUCHAR) UserInterfaceBuffer
+ );
+
+ if (TransferCount > PACKET_MAX_SIZE) {
+ // Read the partial the first time.
+ cb = TransferCount % PACKET_MAX_SIZE;
+ } else {
+ cb = TransferCount;
+ }
+
+ cb2 = 0;
+
+ if (ARGUMENT_PRESENT(ActualBytesWritten)) {
+ *ActualBytesWritten = 0;
+ }
+
+ while (TransferCount != 0) {
+ //
+ // Format state manipulate message
+ //
+
+ m.ApiNumber = DbgKdWriteVirtualMemoryApi;
+ m.ReturnStatus = STATUS_PENDING;
+ a->TargetBaseAddress = (PVOID)((DWORD)TargetBaseAddress + cb2);
+ a->TransferCount = cb;
+ a->ActualBytesWritten = 0L;
+
+ //
+ // Send the message and data to write and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ (PVOID)((DWORD)UserInterfaceBuffer + cb2),
+ (USHORT)cb
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
+ &Reply
+ );
+ } while (rc == FALSE);
+
+ //
+ // If this is not a WriteMemory response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ assert(Reply->ApiNumber == DbgKdWriteVirtualMemoryApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.WriteMemory;
+ assert(a->ActualBytesWritten <= cb);
+
+ //
+ // Return actual bytes written
+ //
+
+ if (ARGUMENT_PRESENT(ActualBytesWritten)) {
+ *ActualBytesWritten += a->ActualBytesWritten;
+ }
+ st = Reply->ReturnStatus;
+
+ if (st != STATUS_SUCCESS) {
+ TransferCount = 0;
+ } else {
+ TransferCount -= cb;
+ cb2 += cb;
+ cb = PACKET_MAX_SIZE;
+ }
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdReadControlSpace(
+ IN USHORT Processor,
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesRead OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the specified data from the control space of
+ the system being debugged.
+
+ Control space is processor dependent. TargetBaseAddress is mapped
+ to control space in a processor/implementation defined manner.
+
+Arguments:
+
+ Processor - Supplies the processor whoes control space is desired.
+
+ TargetBaseAddress - Supplies the base address in control space to
+ read. This address is interpreted in an implementation defined
+ manner.
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that data read is to be placed.
+
+ TransferCount - Specifies the number of bytes to read.
+
+ ActualBytesRead - An optional parameter that if supplied, returns
+ the number of bytes actually read.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
+ DWORD st;
+ BOOLEAN rc;
+
+ dp("DmKdReadControlSpace\n");
+
+ if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
+ return (DWORD)STATUS_BUFFER_OVERFLOW;
+ }
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdReadControlSpaceApi;
+ m.ReturnStatus = STATUS_PENDING;
+ m.Processor = Processor;
+ a->TargetBaseAddress = TargetBaseAddress;
+ a->TransferCount = TransferCount;
+ a->ActualBytesRead = 0L;
+
+ //
+ // Send the message and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket( &m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+
+ } while (rc == FALSE);
+
+ //
+ // If this is not a ReadControl response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdReadControlSpaceApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.ReadMemory;
+ assert(a->ActualBytesRead <= TransferCount);
+
+ //
+ // Return actual bytes read, and then transfer the bytes
+ //
+
+ if (ARGUMENT_PRESENT(ActualBytesRead)) {
+ *ActualBytesRead = a->ActualBytesRead;
+ }
+ st = Reply->ReturnStatus;
+
+ //
+ // Since read response data follows message, Reply+1 should point
+ // at the data
+ //
+
+ memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
+
+ //
+ // Check if current command has been canceled. If yes, go back to
+ // kd prompt. BUGBUG Do we really need to check for this call?
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+
+
+DWORD
+DmKdWriteControlSpace(
+ IN USHORT Processor,
+ IN PVOID TargetBaseAddress,
+ OUT PVOID UserInterfaceBuffer,
+ IN ULONG TransferCount,
+ OUT PULONG ActualBytesWritten OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the specified data to control space on the system
+ being debugged.
+
+ Control space is processor dependent. TargetBaseAddress is mapped
+ to control space in a processor/implementation defined manner.
+
+Arguments:
+
+ Processor - Supplies the processor whoes control space is desired.
+
+ TargetBaseAddress - Supplies the base address in control space to be
+ written.
+
+ UserInterfaceBuffer - Supplies the address of the buffer in the user
+ interface that contains the data to be written.
+
+ TransferCount - Specifies the number of bytes to write.
+
+ ActualBytesWritten - An optional parameter that if supplied, returns
+ the number of bytes actually written.
+
+Return Value:
+
+ STATUS_SUCCESS - The specified read occured.
+
+ STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
+
+ !NT_SUCCESS() - TBD
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdWriteControlSpace\n");
+
+ if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
+ return (DWORD)STATUS_BUFFER_OVERFLOW;
+ }
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdWriteControlSpaceApi;
+ m.ReturnStatus = STATUS_PENDING;
+ m.Processor = Processor;
+ a->TargetBaseAddress = TargetBaseAddress;
+ a->TransferCount = TransferCount;
+ a->ActualBytesWritten = 0L;
+
+ //
+ // Send the message and data to write and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ UserInterfaceBuffer,
+ (USHORT)TransferCount
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a WriteControl response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdWriteControlSpaceApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.WriteMemory;
+ assert(a->ActualBytesWritten <= TransferCount);
+
+ //
+ // Return actual bytes written
+ //
+
+ *ActualBytesWritten = a->ActualBytesWritten;
+ st = Reply->ReturnStatus;
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdContinue (
+ IN DWORD ContinueStatus
+ )
+
+/*++
+
+Routine Description:
+
+ Continuing a system that previously reported a state change causes
+ the system to continue executiontion using the context in effect at
+ the time the state change was reported (of course this context could
+ have been modified using the DmKd state manipulation APIs).
+
+Arguments:
+
+ ContinueStatus - Supplies the continuation status to the thread
+ being continued. Valid values for this are
+ DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
+ or DBG_CONTINUE.
+
+Return Value:
+
+ STATUS_SUCCESS - Successful call to DbgUiContinue
+
+ STATUS_INVALID_PARAMETER - An invalid continue status or was
+ specified.
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_CONTINUE a = &m.u.Continue;
+ DWORD st;
+
+
+ dp("DmKdContinue\n");
+ EnterCriticalSection(&csPacket);
+
+ if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
+ ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
+ ContinueStatus == DBG_CONTINUE ) {
+
+ m.ApiNumber = DbgKdContinueApi;
+ m.ReturnStatus = ContinueStatus;
+
+ a->ContinueStatus = ContinueStatus;
+ if (!DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0)) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ st = STATUS_SUCCESS;
+ DmKdPurgeCachedVirtualMemory( FALSE );
+ }
+ else {
+ st = (DWORD)STATUS_INVALID_PARAMETER;
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+
+DWORD
+DmKdContinue2 (
+ IN DWORD ContinueStatus,
+ IN PDBGKD_CONTROL_SET ControlSet
+ )
+
+/*++
+
+Routine Description:
+
+ Continuing a system that previously reported a state change causes
+ the system to continue executiontion using the context in effect at
+ the time the state change was reported, modified by the values set
+ in the ControlSet structure. (And, of course, the context could have
+ been modified by used the DmKd state manipulation APIs.)
+
+Arguments:
+
+ ContinueStatus - Supplies the continuation status to the thread
+ being continued. Valid values for this are
+ DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
+ or DBG_CONTINUE.
+
+ ControlSet - Supplies a pointer to a structure containing the machine
+ specific control data to set. For the x86 this is the TraceFlag
+ and Dr7.
+
+Return Value:
+
+ STATUS_SUCCESS - Successful call to DbgUiContinue
+
+ STATUS_INVALID_PARAMETER - An invalid continue status or was
+ specified.
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ DWORD st;
+
+
+ dp("DmKdContinue2\n");
+ EnterCriticalSection(&csPacket);
+
+ if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
+ ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
+ ContinueStatus == DBG_CONTINUE ) {
+
+ m.ApiNumber = DbgKdContinueApi2;
+ m.ReturnStatus = ContinueStatus;
+
+ m.u.Continue2.ContinueStatus = ContinueStatus;
+ m.u.Continue2.ControlSet = *ControlSet;
+
+ if (!DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0)) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ st = STATUS_SUCCESS;
+ DmKdPurgeCachedVirtualMemory( FALSE );
+ }
+ else {
+ st = (DWORD)STATUS_INVALID_PARAMETER;
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdSetSpecialCalls (
+ IN ULONG NumSpecialCalls,
+ IN PULONG Calls
+ )
+
+/*++
+
+Routine Description:
+
+ Inform the debugged kernel that calls to these addresses
+ are "special" calls, and they should result in callbacks
+ to the kernel debugger rather than continued local stepping.
+ The new values *replace* any old ones that may have previously
+ set (not that you're likely to want to change this).
+
+Arguments:
+
+ NumSpecialCalls - how many special calls there are
+
+ Calls - pointer to an array of calls.
+
+Return Value:
+
+ STATUS_SUCCESS - Successful call to DbgUiContinue
+
+ STATUS_INVALID_PARAMETER - The number of special calls
+ wasn't between 0 and MAX_SPECIAL_CALLS.
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ ULONG i;
+
+
+ dp("DmKdSetSpecialCalls\n");
+
+ EnterCriticalSection(&csPacket);
+
+#if 0
+ ClearTraceDataSyms();
+#endif
+
+ m.ApiNumber = DbgKdClearSpecialCallsApi;
+ m.ReturnStatus = STATUS_PENDING;
+ if (!DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0)) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ DmKdPurgeCachedVirtualMemory( FALSE );
+
+ for (i = 0; i < NumSpecialCalls; i++) {
+
+ m.ApiNumber = DbgKdSetSpecialCallApi;
+ m.ReturnStatus = STATUS_PENDING;
+ m.u.SetSpecialCall.SpecialCall = Calls[i];
+ if (!DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0)) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ }
+
+ LeaveCriticalSection(&csPacket);
+
+ return STATUS_SUCCESS;
+}
+
+DWORD
+DmKdSetInternalBp (
+ ULONG addr,
+ ULONG flags
+ )
+
+/*++
+
+Routine Description:
+
+ Inform the debugged kernel that a breakpoint at this address
+ is to be internally counted, and not result in a callback to the
+ remote debugger (us). This function DOES NOT cause the kernel to
+ set the breakpoint; the debugger must do that independently.
+
+Arguments:
+
+ Addr - address of the breakpoint
+
+ Flags - the breakpoint flags to set (note: if the invalid bit
+ is set, this CLEARS a breakpoint).
+
+Return Value:
+
+ STATUS_SUCCESS - Successful call to DbgUiContinue
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ DWORD st;
+
+
+ dp("DmKdSetInternalBp\n");
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdSetInternalBreakPointApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ m.u.SetInternalBreakpoint.BreakpointAddress = addr;
+ m.u.SetInternalBreakpoint.Flags = flags;
+
+ if (!DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0)) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+
+ st = STATUS_SUCCESS;
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdGetInternalBp (
+ ULONG addr,
+ PULONG flags,
+ PULONG calls,
+ PULONG minInstr,
+ PULONG maxInstr,
+ PULONG totInstr,
+ PULONG maxCPS
+ )
+
+/*++
+
+Routine Description:
+
+ Query the status of an internal breakpoint from the debugged
+ kernel and return the data to the caller.
+
+Arguments:
+
+ Addr - address of the breakpoint
+
+ flags, calls, minInstr, maxInstr, totInstr - values returned
+ describing the particular breakpoint. flags will contain
+ the invalid bit if the breakpoint is bogus.
+
+Return Value:
+
+ STATUS_SUCCESS - Successful call to DbgUiContinue
+
+--*/
+
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ DWORD st;
+ ULONG rc;
+
+
+ dp("DmKdGetInternalBp\n");
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdGetInternalBreakPointApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ m.u.GetInternalBreakpoint.BreakpointAddress = addr;
+
+ do {
+ rc = DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket( PACKET_TYPE_KD_STATE_MANIPULATE,
+ &Reply
+ );
+ } while (rc == FALSE);
+
+ *flags = Reply->u.GetInternalBreakpoint.Flags;
+ *calls = Reply->u.GetInternalBreakpoint.Calls;
+ *maxCPS = Reply->u.GetInternalBreakpoint.MaxCallsPerPeriod;
+ *maxInstr = Reply->u.GetInternalBreakpoint.MaxInstructions;
+ *minInstr = Reply->u.GetInternalBreakpoint.MinInstructions;
+ *totInstr = Reply->u.GetInternalBreakpoint.TotalInstructions;
+
+ st = STATUS_SUCCESS;
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdGetVersion (
+ PDBGKD_GET_VERSION GetVersion
+ )
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_GET_VERSION a = &m.u.GetVersion;
+ DWORD st;
+ ULONG rc;
+
+
+ dp("DmKdGetVersion\n");
+
+ m.ApiNumber = DbgKdGetVersionApi;
+ m.ReturnStatus = STATUS_PENDING;
+ a->ProtocolVersion = 1; // request context records on state changes
+
+ do {
+ rc = DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket( PACKET_TYPE_KD_STATE_MANIPULATE,
+ &Reply
+ );
+ } while (rc == FALSE);
+
+ *GetVersion = Reply->u.GetVersion;
+
+ st = Reply->ReturnStatus;
+
+ return st;
+}
+
+DWORD
+DmKdPageIn(
+ ULONG Address
+ )
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ NTSTATUS rc;
+
+
+ ZeroMemory( &m, sizeof(m) );
+ m.ApiNumber = DbgKdPageInApi;
+ m.ReturnStatus = STATUS_PENDING;
+ m.u.PageIn.Address = Address;
+ m.u.PageIn.ContinueStatus = DBG_CONTINUE;
+
+ do {
+ DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+ rc = DmKdWaitForPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &Reply );
+ } while (rc == FALSE);
+
+ return Reply->ReturnStatus;
+}
+
+DWORD
+DmKdCrash(
+ DWORD BugCheckCode
+ )
+{
+ DBGKD_MANIPULATE_STATE m;
+
+
+ dp("DmKdCrash\n");
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdCauseBugCheckApi;
+ m.ReturnStatus = STATUS_PENDING;
+ *(PULONG)&m.u = BugCheckCode;
+
+ //
+ // Send the message.
+ //
+
+ DmKdWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
+
+ LeaveCriticalSection(&csPacket);
+
+ return STATUS_SUCCESS;
+}
+
+DWORD
+DmKdWriteBreakPointEx(
+ IN ULONG BreakPointCount,
+ IN OUT PDBGKD_WRITE_BREAKPOINT BreakPoints,
+ IN DWORD ContinueStatus
+ )
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_BREAKPOINTEX a = &m.u.BreakPointEx;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdWriteBreakPointEx\n");
+
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdWriteBreakPointExApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ a->BreakPointCount = BreakPointCount;
+ a->ContinueStatus = (NTSTATUS)ContinueStatus;
+
+ //
+ // Send the message and context and then wait for reply
+ //
+
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ (PVOID)BreakPoints,
+ (USHORT)(sizeof(*BreakPoints) * BreakPointCount)
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a SetContext response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdWriteBreakPointExApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.BreakPointEx;
+ st = Reply->ReturnStatus;
+
+ memcpy(BreakPoints, Reply+1, sizeof(*BreakPoints) * BreakPointCount );
+ BreakPointCount = a->BreakPointCount;
+
+ //
+ // Check if the current command has been canceled.
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
+
+DWORD
+DmKdRestoreBreakPointEx(
+ IN ULONG BreakPointCount,
+ IN PDBGKD_RESTORE_BREAKPOINT BreakPointHandles
+ )
+{
+ DBGKD_MANIPULATE_STATE m;
+ PDBGKD_MANIPULATE_STATE Reply;
+ PDBGKD_BREAKPOINTEX a = &m.u.BreakPointEx;
+ DWORD st;
+ BOOLEAN rc;
+
+
+ dp("DmKdRestoreBreakPointEx\n");
+ //
+ // Format state manipulate message
+ //
+
+ EnterCriticalSection(&csPacket);
+
+ m.ApiNumber = DbgKdRestoreBreakPointExApi;
+ m.ReturnStatus = STATUS_PENDING;
+
+ a->BreakPointCount = BreakPointCount;
+
+ //
+ // Send the message and context and then wait for reply
+ //
+
+ do {
+ rc = DmKdWritePacket(
+ &m,
+ sizeof(m),
+ PACKET_TYPE_KD_STATE_MANIPULATE,
+ (PVOID)BreakPointHandles,
+ (USHORT)(sizeof(*BreakPointHandles) * BreakPointCount)
+ );
+ if (!rc) {
+ LeaveCriticalSection(&csPacket);
+ return (DWORD)STATUS_DATA_ERROR;
+ }
+ rc = DmKdWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
+ } while (rc == FALSE);
+
+ //
+ // If this is not a SetContext response than protocol is screwed up.
+ // assert that protocol is ok.
+ //
+
+ st = Reply->ReturnStatus;
+ assert(Reply->ApiNumber == DbgKdRestoreBreakPointExApi);
+
+ //
+ // Reset message address to reply.
+ //
+
+ a = &Reply->u.BreakPointEx;
+ st = Reply->ReturnStatus;
+
+ memcpy(BreakPointHandles, Reply+1, sizeof(*BreakPointHandles) * BreakPointCount );
+
+ //
+ // Check if the current command has been canceled.
+ //
+
+ LeaveCriticalSection(&csPacket);
+
+ return st;
+}
diff --git a/private/windbg/newdm/user/dm.def b/private/windbg/newdm/user/dm.def
new file mode 100644
index 000000000..a46fad329
--- /dev/null
+++ b/private/windbg/newdm/user/dm.def
@@ -0,0 +1,7 @@
+LIBRARY dm
+
+EXPORTS
+ DmDllInit PRIVATE
+ DMInit PRIVATE
+ DMFunc PRIVATE
+ DBGVersionCheck PRIVATE
diff --git a/private/windbg/newdm/user/dm.rc b/private/windbg/newdm/user/dm.rc
new file mode 100644
index 000000000..8e2f96f6a
--- /dev/null
+++ b/private/windbg/newdm/user/dm.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Debuggee Module for WinDbg"
+#define VER_INTERNALNAME_STR "dm.dll\0"
+#define VER_ORIGINALFILENAME_STR "dm.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/newdm/user/makefile b/private/windbg/newdm/user/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/newdm/user/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/newdm/user/makefile.inc b/private/windbg/newdm/user/makefile.inc
new file mode 100644
index 000000000..e2cfd4e35
--- /dev/null
+++ b/private/windbg/newdm/user/makefile.inc
@@ -0,0 +1,23 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile.inc
+
+Abstract:
+
+ This file tells nmake the correct dependency relationships
+ for objects created from c files in this directory which are
+ wrappers for c files in another directory.
+
+
+Author:
+
+ Kent Forschmiedt
+
+
+!ENDIF
+
+obj\i386\d3dm.obj: ..\..\em\p_i386\d3.c
diff --git a/private/windbg/newdm/user/precomp.h b/private/windbg/newdm/user/precomp.h
new file mode 100644
index 000000000..7fc930840
--- /dev/null
+++ b/private/windbg/newdm/user/precomp.h
@@ -0,0 +1,81 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <process.h>
+#include <string.h>
+#include <malloc.h>
+
+#if defined(TARGET_i386) && !defined(WIN32S)
+#include <vdmdbg.h>
+#endif
+
+#if defined(TARGET_ALPHA)
+#include <alphaops.h>
+#include "ctxptrs.h"
+#endif
+
+#if defined(TARGET_MIPS)
+#include <mipsinst.h>
+#endif
+
+#if defined(TARGET_PPC)
+#include <ppcinst.h>
+#endif
+
+#ifdef OSDEBUG4
+
+#include "od.h"
+#include "odp.h"
+#include "emdm.h"
+#include "win32dm.h"
+
+#else // OSDEBUG4
+
+#include "defs.h"
+#include "types.h"
+#include "cvtypes.hxx"
+#include "od.h"
+#include "emdm.h"
+#include "ll.h"
+#include "tl.h"
+#include "shapi.hxx"
+
+#endif // OSDEBUG4
+
+#include "heap.h"
+
+#include "dm.h"
+#include "list.h"
+#include "bp.h"
+#include "funccall.h"
+#include "debug.h"
+#include "dbgver.h"
+
diff --git a/private/windbg/newdm/user/process.c b/private/windbg/newdm/user/process.c
new file mode 100644
index 000000000..9c010eee9
--- /dev/null
+++ b/private/windbg/newdm/user/process.c
@@ -0,0 +1,335 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ process.c
+
+Abstract:
+
+ This code provides access to the task list.
+
+Author:
+
+ Wesley Witt (wesw) 16-June-1993
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#ifndef WIN32S
+
+#include <winperf.h>
+
+
+
+//
+// defines
+//
+#define INITIAL_SIZE 51200
+#define EXTEND_SIZE 25600
+#define REGKEY_PERF "software\\microsoft\\windows nt\\currentversion\\perflib"
+#define REGSUBKEY_COUNTERS "Counters"
+#define PROCESS_COUNTER "process"
+#define PROCESSID_COUNTER "id process"
+#define UNKNOWN_TASK "unknown"
+
+
+
+VOID
+GetTaskList(
+ PTASK_LIST pTask,
+ DWORD dwNumTasks
+ )
+
+/*++
+
+Routine Description:
+
+ Provides an API for getting a list of tasks running at the time of the
+ API call. This function uses the registry performance data to get the
+ task list and is therefor straight WIN32 calls that anyone can call.
+
+Arguments:
+
+ ldwNumTasks - pointer to a dword that will be set to the
+ number of tasks returned.
+
+Return Value:
+
+ PTASK_LIST - pointer to an array of TASK_LIST records.
+
+--*/
+
+{
+ DWORD rc;
+ HKEY hKeyNames = NULL;
+ DWORD dwType;
+ DWORD dwSize;
+ LPBYTE buf = NULL;
+ CHAR szSubKey[1024];
+ LANGID lid;
+ LPSTR p;
+ LPSTR p2;
+ PPERF_DATA_BLOCK pPerf;
+ PPERF_OBJECT_TYPE pObj;
+ PPERF_INSTANCE_DEFINITION pInst;
+ PPERF_COUNTER_BLOCK pCounter;
+ PPERF_COUNTER_DEFINITION pCounterDef;
+ DWORD i;
+ DWORD dwProcessIdTitle;
+ DWORD dwProcessIdCounter;
+ CHAR szProcessName[MAX_PATH];
+ DWORD dwLimit = dwNumTasks - 1;
+ DWORD ThisPid = GetCurrentProcessId();
+
+
+
+ //
+ // Look for the list of counters. Always use the neutral
+ // English version, regardless of the local language. We
+ // are looking for some particular keys, and we are always
+ // going to do our looking in English. We are not going
+ // to show the user the counter names, so there is no need
+ // to go find the corresponding name in the local language.
+ //
+ lid = MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL );
+ sprintf( szSubKey, "%s\\%03x", REGKEY_PERF, lid );
+ rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ szSubKey,
+ 0,
+ KEY_READ,
+ &hKeyNames
+ );
+ if (rc != ERROR_SUCCESS) {
+ goto exit;
+ }
+
+ //
+ // get the buffer size for the counter names
+ //
+ rc = RegQueryValueEx( hKeyNames,
+ REGSUBKEY_COUNTERS,
+ NULL,
+ &dwType,
+ NULL,
+ &dwSize
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ goto exit;
+ }
+
+ //
+ // allocate the counter names buffer
+ //
+ buf = (LPBYTE) malloc( dwSize );
+ if (buf == NULL) {
+ goto exit;
+ }
+ memset( buf, 0, dwSize );
+
+ //
+ // read the counter names from the registry
+ //
+ rc = RegQueryValueEx( hKeyNames,
+ REGSUBKEY_COUNTERS,
+ NULL,
+ &dwType,
+ buf,
+ &dwSize
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ goto exit;
+ }
+
+ //
+ // now loop thru the counter names looking for the following counters:
+ //
+ // 1. "Process" process name
+ // 2. "ID Process" process id
+ //
+ // the buffer contains multiple null terminated strings and then
+ // finally null terminated at the end. the strings are in pairs of
+ // counter number and counter name.
+ //
+
+ p = buf;
+ while (*p) {
+ if (_stricmp(p, PROCESS_COUNTER) == 0) {
+ //
+ // look backwards for the counter number
+ //
+ for( p2=p-2; isdigit(*p2); p2--) ;
+ strcpy( szSubKey, p2+1 );
+ }
+ else
+ if (_stricmp(p, PROCESSID_COUNTER) == 0) {
+ //
+ // look backwards for the counter number
+ //
+ for( p2=p-2; isdigit(*p2); p2--) ;
+ dwProcessIdTitle = atol( p2+1 );
+ }
+ //
+ // next string
+ //
+ p += (strlen(p) + 1);
+ }
+
+ //
+ // free the counter names buffer
+ //
+ free( buf );
+
+
+ //
+ // allocate the initial buffer for the performance data
+ //
+ dwSize = INITIAL_SIZE;
+ buf = malloc( dwSize );
+ if (buf == NULL) {
+ goto exit;
+ }
+ memset( buf, 0, dwSize );
+
+
+ while (TRUE) {
+
+ rc = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
+ szSubKey,
+ NULL,
+ &dwType,
+ buf,
+ &dwSize
+ );
+
+ pPerf = (PPERF_DATA_BLOCK) buf;
+
+ //
+ // check for success and valid perf data block signature
+ //
+ if ((rc == ERROR_SUCCESS) &&
+ (dwSize > 0) &&
+ (pPerf)->Signature[0] == (WCHAR)'P' &&
+ (pPerf)->Signature[1] == (WCHAR)'E' &&
+ (pPerf)->Signature[2] == (WCHAR)'R' &&
+ (pPerf)->Signature[3] == (WCHAR)'F' ) {
+ break;
+ }
+
+ //
+ // if buffer is not big enough, reallocate and try again
+ //
+ if (rc == ERROR_MORE_DATA) {
+ dwSize += EXTEND_SIZE;
+ buf = realloc( buf, dwSize );
+ memset( buf, 0, dwSize );
+ }
+ else {
+ goto exit;
+ }
+ }
+
+ //
+ // set the perf_object_type pointer
+ //
+ pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);
+
+ //
+ // loop thru the performance counter definition records looking
+ // for the process id counter and then save its offset
+ //
+ pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
+ for (i=0; i<(DWORD)pObj->NumCounters; i++) {
+ if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {
+ dwProcessIdCounter = pCounterDef->CounterOffset;
+ break;
+ }
+ pCounterDef++;
+ }
+
+ dwNumTasks = min( dwLimit, (DWORD)pObj->NumInstances );
+
+ pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);
+
+ //
+ // loop thru the performance instance data extracting each process name
+ // and process id
+ //
+ for (i=0; i<dwNumTasks; i++) {
+ //
+ // pointer to the process name
+ //
+ p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);
+
+ //
+ // convert it to ascii
+ //
+ rc = WideCharToMultiByte( CP_ACP,
+ 0,
+ (LPCWSTR)p,
+ -1,
+ szProcessName,
+ sizeof(szProcessName),
+ NULL,
+ NULL
+ );
+
+ if (!rc) {
+ //
+ // if we cant convert the string then use a bogus value
+ //
+ strcpy( pTask->ProcessName, UNKNOWN_TASK );
+ }
+
+ if (strlen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {
+ strcpy( pTask->ProcessName, szProcessName );
+ strcat( pTask->ProcessName, ".exe" );
+ }
+
+ //
+ // get the process id
+ //
+ pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
+ pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
+ if (pTask->dwProcessId == 0) {
+ pTask->dwProcessId = (DWORD)-2;
+ }
+ if (_stricmp(szProcessName,"csrss")==0) {
+ pTask->dwProcessId = (DWORD)-1;
+ }
+
+ //
+ // next process
+ //
+ if (pTask->dwProcessId == ThisPid) {
+ ZeroMemory( pTask, sizeof(*pTask) );
+ } else {
+ pTask++;
+ }
+ pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);
+ }
+
+exit:
+ if (buf) {
+ free( buf );
+ }
+
+ if (hKeyNames) {
+ RegCloseKey( hKeyNames );
+ RegCloseKey( HKEY_PERFORMANCE_DATA );
+ }
+
+ return;
+}
+
+#endif
diff --git a/private/windbg/newdm/user/sources b/private/windbg/newdm/user/sources
new file mode 100644
index 000000000..d3634544f
--- /dev/null
+++ b/private/windbg/newdm/user/sources
@@ -0,0 +1,89 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=dm
+
+TARGETNAME=dm
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+DLLENTRY=DllInit
+
+SOURCES= \
+ ..\bp.c \
+ ..\dmx32.c \
+ ..\event.c \
+ ..\funccall.c \
+ ..\procem.c \
+ ..\step.c \
+ ..\util.c \
+ ..\walk.c \
+ process.c \
+ userapi.c \
+ wow.c \
+ dm.rc
+
+i386_SOURCES= \
+ ..\i386mach.c \
+ ..\i386d3dm.c
+
+mips_SOURCES= \
+ ..\mipsmach.c
+
+ppc_SOURCES= \
+ ..\ppcmach.c
+
+alpha_SOURCES= \
+ ..\alpmach.c
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+MIPS_FLAGS=-DNO_TRACE_BIT -DTARGET_MIPS
+386_FLAGS=-DWOW -DTARGET_i386
+ALPHA_FLAGS=-DNO_TRACE_BIT -DTARGET_ALPHA
+PPC_FLAGS=-DNO_TRACE_BIT -DTARGET_PPC
+
+C_DEFINES = $(C_DEFINES) -DDWORDLONG=ULONGLONG
+
+INCLUDES=..;..\..\osdebug\include;..\..\osdebug
+
+CONDITIONAL_INCLUDES=odp.h win32dm.h
+
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\vdmdbg.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\crashlib.lib \
+!IF $(ALPHA)
+ ..\..\em\p_alpha\obj\*\emalp.lib \
+!ENDIF
+ $(MORE_LIBS)
+
+NTTARGETFILES=
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/newdm/user/userapi.c b/private/windbg/newdm/user/userapi.c
new file mode 100644
index 000000000..da84896e6
--- /dev/null
+++ b/private/windbg/newdm/user/userapi.c
@@ -0,0 +1,2041 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef WIN32S
+extern BOOL fProcessingDebugEvent;
+extern BOOL fWaitForDebugEvent;
+extern DWORD tidExit;
+extern BOOL fExitProcessDebugEvent; // set true when the last debug event
+#endif
+
+HANDLE hEventContinue;
+extern LPDM_MSG LpDmMsg;
+extern SYSTEM_INFO SystemInfo;
+extern WT_STRUCT WtStruct; // .. for wt
+extern DEBUG_ACTIVE_STRUCT DebugActiveStruct; // ... for DebugActiveProcess()
+
+extern PKILLSTRUCT KillQueue;
+extern CRITICAL_SECTION csKillQueue;
+
+extern HTHDX thdList;
+extern HPRCX prcList;
+extern CRITICAL_SECTION csThreadProcList;
+
+extern BOOL fSmartRangeStep;
+extern HANDLE hEventNoDebuggee;
+extern HANDLE hEventRemoteQuit;
+extern BOOL fDisconnected;
+extern BOOL fUseRoot;
+extern char nameBuffer[];
+
+#if defined(TARGET_MIPS)
+MIPSCONTEXTSIZE MipsContextSize;
+#endif
+
+
+
+BOOL
+DbgWriteMemory(
+ HPRCX hprc,
+ LPVOID lpOffset,
+ LPBYTE lpb,
+ DWORD cb,
+ LPDWORD pcbWritten
+ )
+/*++
+
+Routine Description:
+
+ Write to a flat address in a process.
+
+Arguments:
+
+ hprc - Supplies the handle to the process
+
+ lpOffset - Supplies address of data in process
+
+ lpb - Supplies a pointer to the bytes to be written
+
+ cb - Supplies the count of bytes to be written
+
+ pcbWritten - Returns the number of bytes actually written
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise
+
+--*/
+
+{
+ BOOL fRet;
+
+ assert(hprc->rwHand != (HANDLE)-1);
+
+ if (hprc->rwHand == (HANDLE)-1) {
+ return FALSE;
+ }
+
+ fRet = WriteProcessMemory(hprc->rwHand, lpOffset, lpb, cb, pcbWritten);
+
+#if defined(JLS_RWBP) && DBG
+ {
+ DWORD cbT;
+ LPBYTE lpbT = malloc(cb);
+
+ assert( fRet );
+ assert( *pcbWritten == cb );
+ fRet = ReadProcessMemory(hprc->rwHand, lpOffset, lpbT, cb, &cbT);
+ assert(fRet);
+ assert( cb == cbT);
+ assert(memcmp(lpbT, lpb) == 0);
+ free lpbT;
+ }
+#endif
+
+ return fRet;
+}
+
+
+BOOL
+DbgReadMemory(
+ HPRCX hprc,
+ LPVOID lpOffset,
+ LPVOID lpb,
+ DWORD cb,
+ LPDWORD lpRead
+ )
+/*++
+
+Routine Description:
+
+ Read from a flat address in a process.
+
+Arguments:
+
+ hprc - Supplies the handle to the process
+
+ lpOffset - Supplies address of data in process
+
+ lpb - Supplies a pointer to the local buffer
+
+ cb - Supplies the count of bytes to read
+
+ lpRead - Returns the number of bytes actually read
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise
+
+--*/
+
+{
+#ifndef WIN32S
+ DWORD cbr;
+ if (CrashDump) {
+ cbr = DmpReadMemory( (PVOID)lpOffset, lpb, cb );
+ if (lpRead) {
+ *lpRead = cbr;
+ }
+ return (cbr > 0) || (cbr == cb);
+ }
+#endif
+
+ assert(hprc->rwHand != (HANDLE)-1);
+
+ if (hprc->rwHand == (HANDLE)-1) {
+ return FALSE;
+ }
+
+ if (ReadProcessMemory(hprc->rwHand, lpOffset, lpb, cb, lpRead)) {
+
+ return TRUE;
+
+ } else {
+
+#if DBG
+ int e = GetLastError();
+#endif
+ //
+ // Reads across page boundaries will not work if the
+ // second page is not accessible.
+ //
+#define PAGE_SIZE (SystemInfo.dwPageSize)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+ DWORD firstsize;
+ DWORD dwRead;
+
+ firstsize = (((DWORD)lpOffset + PAGE_SIZE) & PAGE_MASK) - (DWORD)lpOffset;
+ if (cb < firstsize) {
+ firstsize = cb;
+ }
+
+ //
+ // read from the first page. If the first read fails,
+ // fail the whole thing.
+ //
+
+ if (!ReadProcessMemory(hprc->rwHand, lpOffset, lpb, firstsize,
+ lpRead)) {
+ return FALSE;
+ }
+
+ //
+ // read intermediate complete pages.
+ // if any of these reads fail, succeed with a short read.
+ //
+
+ assert(*lpRead == firstsize);
+ cb -= firstsize;
+ lpb = (LPVOID)((LPBYTE)lpb + firstsize);
+ lpOffset = (LPVOID)((LPBYTE)lpOffset + firstsize);
+
+ while (cb >= PAGE_SIZE) {
+
+ if (!ReadProcessMemory(hprc->rwHand, lpOffset, lpb, PAGE_SIZE,
+ &dwRead)) {
+ return TRUE;
+ } else {
+ assert(dwRead == PAGE_SIZE);
+ lpb = (LPVOID)((LPBYTE)lpb + PAGE_SIZE);
+ lpOffset = (LPVOID)((LPBYTE)lpOffset + PAGE_SIZE);
+ *lpRead += dwRead;
+ cb -= PAGE_SIZE;
+ }
+ }
+
+ if (cb > 0) {
+ if (ReadProcessMemory(hprc->rwHand, lpOffset, lpb, cb, &dwRead)) {
+ assert(dwRead == cb);
+ *lpRead += dwRead;
+ }
+ }
+
+ return TRUE;
+ }
+
+}
+
+BOOL
+DbgGetThreadContext(
+ HTHDX hthd,
+ PCONTEXT lpcontext
+ )
+{
+#ifndef WIN32S
+ if (CrashDump) {
+ return DmpGetContext(hthd->tid-1, lpcontext);
+ } else if (hthd->fWowEvent) {
+ return WOWGetThreadContext(hthd, lpcontext);
+ } else
+#endif
+ {
+#ifndef TARGET_MIPS
+ return GetThreadContext(hthd->rwHand, lpcontext);
+#else
+ BOOL rc;
+ DWORD Flags = lpcontext->ContextFlags;
+
+ if (MipsContextSize == Ctx32Bit) {
+ lpcontext->ContextFlags = ((lpcontext->ContextFlags & ~CONTEXT_EXTENDED_INTEGER) | CONTEXT_INTEGER);
+ }
+ rc = GetThreadContext(hthd->rwHand, lpcontext);
+ if (rc) {
+ if ((Flags & CONTEXT_EXTENDED_INTEGER) == CONTEXT_EXTENDED_INTEGER) {
+ CoerceContext32To64(lpcontext);
+ } else if ((Flags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
+ CoerceContext64To32(lpcontext);
+ }
+ }
+ return rc;
+#endif
+ }
+}
+
+BOOL
+DbgSetThreadContext(
+ HTHDX hthd,
+ PCONTEXT lpcontext
+ )
+{
+ assert(!CrashDump);
+
+#ifndef WIN32S
+ if (CrashDump) {
+ return FALSE;
+ } else if (hthd->fWowEvent) {
+ return WOWSetThreadContext(hthd, lpcontext);
+ } else
+#endif
+ {
+#ifdef TARGET_MIPS
+ CONTEXT ctx = *lpcontext;
+ lpcontext = &ctx;
+ if (MipsContextSize == Ctx32Bit) {
+ CoerceContext64To32(lpcontext);
+ } else {
+ CoerceContext32To64(lpcontext);
+ }
+#endif
+ return SetThreadContext(hthd->rwHand, lpcontext);
+ }
+}
+
+BOOL
+WriteBreakPoint(
+ IN PBREAKPOINT Breakpoint
+ )
+{
+ DWORD cb;
+ BP_UNIT opcode = BP_OPCODE;
+ BOOL r = AddrWriteMemory(Breakpoint->hprc,
+ Breakpoint->hthd,
+ &Breakpoint->addr,
+ &opcode,
+ BP_SIZE,
+ &cb);
+ return (r && (cb == BP_SIZE));
+}
+
+BOOL
+RestoreBreakPoint(
+ IN PBREAKPOINT Breakpoint
+ )
+{
+ DWORD cb;
+ BOOL r;
+
+ assert(Breakpoint->bpType == bptpExec);
+
+ r = AddrWriteMemory(Breakpoint->hprc,
+ Breakpoint->hthd,
+ &Breakpoint->addr,
+ &Breakpoint->instr1,
+ BP_SIZE,
+ &cb);
+ return (r && (cb == BP_SIZE));
+}
+
+
+
+/****************************************************************************/
+/****************************************************************************/
+#ifndef PROCESSOR_MIPS_R10000
+#define PROCESSOR_MIPS_R10000 10000
+#endif
+
+
+VOID
+GetMachineType(
+ LPPROCESSOR p
+ )
+{
+ // Look Ma, no ifdefs!!
+
+ SYSTEM_INFO SystemInfo;
+
+ GetSystemInfo(&SystemInfo);
+ switch (SystemInfo.wProcessorArchitecture) {
+
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ p->Level = SystemInfo.wProcessorLevel;
+ p->Type = mptix86;
+ p->Endian = endLittle;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_MIPS:
+ p->Level = SystemInfo.wProcessorLevel * 1000;
+ p->Type = mptmips;
+ p->Endian = endLittle;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_ALPHA:
+ p->Level = SystemInfo.wProcessorLevel;
+ p->Type = mptdaxp;
+ p->Endian = endLittle;
+ p->Level = 21064; // BUGBUG - why?
+ break;
+
+ case PROCESSOR_ARCHITECTURE_PPC:
+ p->Level = SystemInfo.wProcessorLevel + 600; // BUGBUG - 603+
+ p->Type = mptmppc;
+ p->Endian = endLittle;
+ break;
+
+ default:
+ assert(!"Unknown target machine");
+ break;
+ }
+}
+
+
+
+HWND
+HwndFromPid (
+ PID pid
+ )
+{
+
+ HWND hwnd = GetForegroundWindow();
+ HWND hwndNext;
+
+ DPRINT(4, ( "*HwndFromPid, pid = 0x%lx\n", pid ) );
+
+ for (hwndNext = GetWindow ( hwnd, GW_HWNDFIRST );
+ hwndNext;
+ hwndNext = GetWindow ( hwndNext, GW_HWNDNEXT )) {
+
+ // what we want is windows *without* an owner, hence !GetWindow...
+ if ( !GetWindow ( hwndNext, GW_OWNER ) &&
+ IsWindowVisible ( hwndNext ) ) {
+ PID pidT;
+
+ GetWindowThreadProcessId ( hwndNext, &pidT );
+ DPRINT(4, ("\thwnd 0x%08lx owned by process 0x%lx, ",
+ hwndNext, pidT ) );
+#if DBG
+ {
+ char szWindowText[256];
+ if ( GetWindowText(hwndNext, szWindowText,
+ sizeof(szWindowText)) ) {
+ DPRINT(4, ("title = \"%s\"\n", szWindowText) );
+ } else {
+ DPRINT(4, ("title = \"<none>\"\n") );
+ }
+ }
+#endif
+ if ( pid == pidT ) {
+ // found a match, return the hwnd
+ break;
+ }
+ } // if ( !GetWindow...
+ hwndNext = GetWindow ( hwndNext, GW_HWNDNEXT );
+ } // while ( hwndNext )
+
+ return hwndNext;
+}
+
+VOID
+DmSetFocus (
+ HPRCX phprc
+ )
+{
+ PID pidGer; // debugger pid
+ PID pidCurFore; // owner of foreground window
+ HWND hwndCurFore; // current foreground window
+ HWND phprc_hwndProcess;
+ HWND hwndT;
+
+
+ // decide if we are the foreground app currently
+ pidGer = GetCurrentProcessId(); // debugger pid
+ hwndCurFore = GetForegroundWindow();
+ if ( hwndCurFore &&
+ GetWindowThreadProcessId ( hwndCurFore, &pidCurFore ) ) {
+ if ( pidCurFore != pidGer ) {
+ // foreground is not debugger, bail out
+ return;
+ }
+ }
+
+ phprc_hwndProcess = HwndFromPid ( phprc->pid );
+ if ( !phprc_hwndProcess ) {
+ // no window attached to pid; bail out
+ return;
+ }
+
+ // continuing with valid hwnd's and we have foreground window
+ assert ( phprc_hwndProcess );
+
+ // now, get the last active window in that group!
+ hwndT = GetLastActivePopup ( phprc_hwndProcess );
+
+ // NOTE: taskman has a check at this point for state disabled...
+ // don't know if I should do it either...
+ SetForegroundWindow ( hwndT );
+}
+
+
+
+/****************************************************************************/
+//
+// ContinueDebugEvent() queue.
+// We can only have one debug event pending per process, but there may be
+// one event pending for each process we are debugging.
+//
+// There are 200 entries in a static sized queue. If there are ever more
+// than 200 debug events pending, AND windbg actually handles them all in
+// less than 1/5 second, we will be in trouble. Until then, sleep soundly.
+//
+/****************************************************************************/
+typedef struct tagCQUEUE {
+ struct tagCQUEUE *next;
+ DWORD pid;
+ DWORD tid;
+ DWORD dwContinueStatus;
+} CQUEUE, *LPCQUEUE;
+
+static LPCQUEUE lpcqFirst;
+static LPCQUEUE lpcqLast;
+static LPCQUEUE lpcqFree;
+static CQUEUE cqueue[200];
+static CRITICAL_SECTION csContinueQueue;
+
+static BOOL DequeueContinueDebugEvents( void );
+
+
+/***************************************************************************/
+/***************************************************************************/
+
+
+
+VOID
+QueueContinueDebugEvent(
+ DWORD dwProcessId,
+ DWORD dwThreadId,
+ DWORD dwContinueStatus
+ )
+
+/*++
+
+Routine Description:
+
+ Queue a debug event continue for later execution.
+
+Arguments:
+
+ dwProcessId = pid to continue
+
+ dwThreadId = tid to continue
+
+ dwContinueStatus - Supplies the continue status code
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef WIN32S
+
+ HTHDX hthd;
+
+ if (dwContinueStatus != DBG_TERMINATE_PROCESS) {
+ hthd = HTHDXFromPIDTID(dwProcessId, dwThreadId);
+ if (hthd) {
+ if (hthd->fContextDirty) {
+ /*
+ * Set the child's context
+ */
+ DPRINT(1, ("Context is dirty\n"));
+
+ DbgSetThreadContext(hthd, &hthd->context);
+
+ hthd->fContextDirty = FALSE;
+ }
+ }
+ }
+
+ DPRINT(1, ("ContinueDebugEvent(PID:%x, TID:%x, Stat:%u)\r\n",
+ dwProcessId, dwThreadId, dwContinueStatus));
+
+ ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus);
+ fProcessingDebugEvent = FALSE;
+ fWaitForDebugEvent = FALSE;
+
+#else
+
+ LPCQUEUE lpcq;
+
+ EnterCriticalSection(&csContinueQueue);
+
+ lpcq = lpcqFree;
+ assert(lpcq);
+
+ lpcqFree = lpcq->next;
+
+ lpcq->next = NULL;
+ if (lpcqLast) {
+ lpcqLast->next = lpcq;
+ }
+ lpcqLast = lpcq;
+
+ if (!lpcqFirst) {
+ lpcqFirst = lpcq;
+ }
+
+ lpcq->pid = dwProcessId;
+ lpcq->tid = dwThreadId;
+ lpcq->dwContinueStatus = dwContinueStatus;
+
+ LeaveCriticalSection(&csContinueQueue);
+
+#endif
+
+ return;
+} /* QueueContinueDebugEvent() */
+
+
+#ifndef WIN32S
+BOOL
+DequeueContinueDebugEvents(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Remove any pending continues from the queue and execute them.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE if one or more events were continued.
+ FALSE if none were continued.
+
+--*/
+{
+ LPCQUEUE lpcq;
+ BOOL fDid = FALSE;
+ HTHDX hthd;
+
+ EnterCriticalSection(&csContinueQueue);
+
+ while ( lpcq=lpcqFirst ) {
+
+ hthd = HTHDXFromPIDTID(lpcq->pid, lpcq->tid);
+ if (hthd) {
+ if (hthd->fContextDirty) {
+ /*
+ * Set the child's context
+ */
+
+ DbgSetThreadContext(hthd, &hthd->context);
+
+ hthd->fContextDirty = FALSE;
+ }
+ hthd->fWowEvent = FALSE;
+ }
+
+ ContinueDebugEvent(lpcq->pid, lpcq->tid, lpcq->dwContinueStatus);
+
+ lpcqFirst = lpcq->next;
+ if (lpcqFirst == NULL) {
+ lpcqLast = NULL;
+ }
+
+ lpcq->next = lpcqFree;
+ lpcqFree = lpcq;
+
+ fDid = TRUE;
+ }
+
+ LeaveCriticalSection(&csContinueQueue);
+ return fDid;
+} /* DequeueContinueDebugEvents() */
+#endif // !WIN32S
+
+
+VOID
+AddQueue(
+ DWORD dwType,
+ DWORD dwProcessId,
+ DWORD dwThreadId,
+ DWORD dwData,
+ DWORD dwLen
+ )
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ dwType
+
+ dwProcessId
+
+ dwThreadId
+
+ dwData
+
+ dwLen
+
+Return Value:
+
+ none
+
+--*/
+
+{
+ switch (dwType) {
+ case QT_CONTINUE_DEBUG_EVENT:
+ case QT_TRACE_DEBUG_EVENT:
+ if (CrashDump) {
+ break;
+ }
+
+ QueueContinueDebugEvent(dwProcessId, dwThreadId, dwData);
+ break;
+
+
+ case QT_RELOAD_MODULES:
+ case QT_REBOOT:
+ case QT_CRASH:
+ case QT_RESYNC:
+ assert(!"Unsupported usermode QType in AddQueue.");
+ break;
+
+ case QT_DEBUGSTRING:
+ assert(!"Is this a bad idea?");
+ DMPrintShellMsg( "%s", (LPSTR)dwData );
+ free((LPSTR)dwData);
+ break;
+
+ }
+
+ if (dwType == QT_CONTINUE_DEBUG_EVENT) {
+ SetEvent( hEventContinue );
+ }
+
+ return;
+}
+
+BOOL
+DequeueAllEvents(
+ BOOL fForce, // force a dequeue even if the dm isn't initialized
+ BOOL fConsume // delete all events from the queue with no action
+ )
+{
+#ifdef WIN32S
+ return TRUE;
+#else
+ return DequeueContinueDebugEvents();
+#endif
+}
+
+VOID
+InitEventQueue(
+ VOID
+ )
+{
+ int n;
+ int i;
+
+ InitializeCriticalSection(&csContinueQueue);
+
+ n = sizeof(cqueue) / sizeof(CQUEUE);
+ for (i = 0; i < n-1; i++) {
+ cqueue[i].next = &cqueue[i+1];
+ }
+ cqueue[n-1].next = NULL;
+ lpcqFree = &cqueue[0];
+ lpcqFirst = NULL;
+ lpcqLast = NULL;
+}
+
+
+VOID
+ProcessQueryTlsBaseCmd(
+ HPRCX hprcx,
+ HTHDX hthdx,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to an EM request to get the base
+ of the thread local storage for a given thread and DLL.
+
+Arguments:
+
+ hprcx - Supplies a process handle
+ hthdx - Supplies a thread handle
+ lpdbb - Supplies the command information packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+ OFFSET offRgTls;
+ DWORD iTls;
+ LPADDR lpaddr = (LPADDR) LpDmMsg->rgb;
+ OFFSET offResult;
+ DWORD cb;
+ int iDll;
+ OFFSET offDll = * (OFFSET *) lpdbb->rgbVar;
+
+ /*
+ * Read number 1. Get the pointer to the Thread Local Storage array.
+ */
+
+
+ if ((DbgReadMemory(hprcx, (char *) hthdx->offTeb+0x2c,
+ &offRgTls, sizeof(OFFSET), &cb) == 0) ||
+ (cb != sizeof(OFFSET))) {
+ err:
+ xosd = xosdUnknown;
+ Reply(0, &xosd, lpdbb->hpid);
+ return;
+ }
+
+ /*
+ * Read number 2. Get the TLS index for this dll
+ */
+
+ for (iDll=0; iDll<hprcx->cDllList; iDll+=1 ) {
+ if (hprcx->rgDllList[iDll].fValidDll &&
+ (hprcx->rgDllList[iDll].offBaseOfImage == offDll)) {
+ break;
+ }
+ }
+
+ if (iDll == hprcx->cDllList) {
+ goto err;
+ }
+
+ if (!DbgReadMemory(hprcx,
+ (char *) hprcx->rgDllList[iDll].offTlsIndex,
+ &iTls,
+ sizeof(iTls),
+ &cb) ||
+ (cb != sizeof(iTls))) {
+ goto err;
+ }
+
+
+ /*
+ * Read number 3. Get the actual TLS base pointer
+ */
+
+ if ((DbgReadMemory(hprcx, (char *)offRgTls+iTls*sizeof(OFFSET),
+ &offResult, sizeof(OFFSET), &cb) == 0) ||
+ (cb != sizeof(OFFSET))) {
+ goto err;
+ }
+
+ memset(lpaddr, 0, sizeof(ADDR));
+
+ lpaddr->addr.off = offResult;
+#ifdef TARGET_i386
+ lpaddr->addr.seg = (SEGMENT) hthdx->context.SegDs;
+#else
+ lpaddr->addr.seg = 0;
+#endif
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(ADDR), LpDmMsg, lpdbb->hpid );
+ return;
+} /* ProcessQueryTlsBaseCmd() */
+
+
+VOID
+ProcessQuerySelectorCmd(
+ HPRCX hprcx,
+ HTHDX hthdx,
+ LPDBB lpdbb
+ )
+/*++
+
+Routine Description:
+
+ This command is sent from the EM to fill in an LDT_ENTRY structure
+ for a given selector.
+
+Arguments:
+
+ hprcx - Supplies the handle to the process
+
+ hthdx - Supplies the handle to the thread and is optional
+
+ lpdbb - Supplies the pointer to the full query packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XOSD xosd;
+
+#if defined( TARGET_i386 )
+ SEGMENT seg;
+
+ seg = *((SEGMENT *) lpdbb->rgbVar);
+
+ if (hthdx == hthdxNull) {
+ hthdx = hprcx->hthdChild;
+ }
+
+ if ((hthdx != NULL) &&
+ (GetThreadSelectorEntry(hthdx->rwHand, seg, (LDT_ENTRY *) LpDmMsg->rgb))) {
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(LDT_ENTRY), LpDmMsg, lpdbb->hpid);
+ return;
+ }
+#endif
+
+#ifdef OSDEBUG4
+ xosd = xosdInvalidParameter;
+#else
+ xosd = xosdInvalidSelector;
+#endif
+
+ Reply( sizeof(xosd), &xosd, lpdbb->hpid);
+
+ return;
+} /* ProcessQuerySelectorCmd */
+
+
+VOID
+ProcessVirtualQueryCmd(
+ HPRCX hprc,
+ LPDBB lpdbb
+ )
+{
+ XOSD xosd = xosdNone;
+ ADDR addr;
+ BOOL fRet;
+ DWORD dwSize;
+
+ if (!hprc->rwHand || hprc->rwHand == (HANDLE)(-1)) {
+#ifdef OSDEBUG4
+ xosd = xosdBadProcess;
+#else
+ xosd = xosdInvalidProc;
+#endif
+ }
+
+ addr = *(LPADDR)(lpdbb->rgbVar);
+
+ if (!ADDR_IS_FLAT(addr)) {
+ fRet = TranslateAddress(hprc, 0, &addr, TRUE);
+ assert(fRet);
+ if (!fRet) {
+ xosd = xosdBadAddress;
+ goto reply;
+ }
+ }
+
+ dwSize = VirtualQueryEx(hprc->rwHand,
+ (LPCVOID)addr.addr.off,
+ (PMEMORY_BASIC_INFORMATION)LpDmMsg->rgb,
+ sizeof(MEMORY_BASIC_INFORMATION));
+
+ if (dwSize != sizeof(MEMORY_BASIC_INFORMATION)) {
+ xosd = xosdUnknown;
+ goto reply;
+ }
+
+ reply:
+
+ LpDmMsg->xosdRet = xosd;
+ Reply( sizeof(MEMORY_BASIC_INFORMATION), LpDmMsg, lpdbb->hpid );
+
+ return;
+} /* ProcessVirtualQueryCmd */
+
+VOID
+ProcessGetDmInfoCmd(
+ HPRCX hprc,
+ LPDBB lpdbb,
+ DWORD cb
+ )
+{
+ LPDMINFO lpi = (LPDMINFO)LpDmMsg->rgb;
+
+ LpDmMsg->xosdRet = xosdNone;
+
+ lpi->fAsync = 1;
+#ifdef WIN32S
+ lpi->fHasThreads = 0;
+#else
+ lpi->fHasThreads = 1;
+#endif
+ lpi->fReturnStep = 0;
+ //lpi->fRemote = ???
+ lpi->fAsyncStop = 1;
+ lpi->fAlwaysFlat = 0;
+ lpi->fHasReload = 0;
+
+ lpi->cbSpecialRegs = 0;
+ lpi->MajorVersion = 0;
+ lpi->MinorVersion = 0;
+
+ lpi->Breakpoints = bptsExec |
+ bptsDataC |
+ bptsDataW |
+ bptsDataR |
+ bptsDataExec;
+
+ GetMachineType(&lpi->Processor);
+
+ //
+ // hack so that TL can call tlfGetVersion before
+ // reply buffer is initialized.
+ //
+ if ( cb >= (sizeof(DBB) + sizeof(DMINFO)) ) {
+ memcpy(lpdbb->rgbVar, lpi, sizeof(DMINFO));
+ }
+
+ Reply( sizeof(DMINFO), LpDmMsg, lpdbb->hpid );
+} /* ProcessGetDMInfoCmd */
+
+
+
+ActionResumeThread(
+ DEBUG_EVENT * pde,
+ HTHDX hthd,
+ DWORD unused,
+ PSUSPENDSTRUCT pss
+ )
+{
+ //
+ // This thread just hit a breakpoint after falling out of
+ // SuspendThread. Clear the BP, put the original context
+ // back and continue.
+ //
+
+ RemoveBP( pss->pbp );
+
+ hthd->context = pss->context;
+ hthd->fContextDirty = TRUE;
+ hthd->pss = NULL;
+
+ free(pss);
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ return 0;
+}
+
+
+BOOL
+MakeThreadSuspendItself(
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Set up the thread to call SuspendThread. This relies on kernel32
+ being present in the debuggee, and the current implementation gives
+ up if the thread is in a 16 bit context.
+
+ The cpu dependent part of this is MakeThreadSuspendItselfHelper,
+ in mach.c.
+
+Arguments:
+
+ hthd - Supplies thread
+
+Return Value:
+
+ TRUE if the thread will be suspended, FALSE if not.
+
+--*/
+{
+ PSUSPENDSTRUCT pss;
+ ADDR addr;
+ HANDLE hdll;
+ FARPROC lpSuspendThread;
+
+ //
+ // the only time this should fail is when the debuggee
+ // does not use kernel32, which is rare.
+ //
+
+ if (!hthd->hprc->dwKernel32Base) {
+ DPRINT(1, ("can't suspend thread %x: Kernel32 not loaded\n",
+ (DWORD)hthd));
+ DMPrintShellMsg("*** Unable to suspend thread.\n");
+ return 0;
+ }
+
+ //
+ // Oh, yeah... don't try to do this with a 16 bit thread, either.
+ // maybe someday...
+ //
+
+ if (hthd->fWowEvent) {
+ DMPrintShellMsg("*** Can't leave 16 bit thread suspended.\n");
+ return 0;
+ }
+
+ //
+ // find the address of SuspendThread
+ //
+
+ hdll = GetModuleHandle("KERNEL32");
+ assert(hdll || !"kernel32 not found in DM!!!");
+ if (!hdll) {
+ return 0;
+ }
+
+ lpSuspendThread = GetProcAddress(hdll, "SuspendThread");
+ assert(lpSuspendThread || !"SuspendThread not found in kernel32!!!");
+ if (!lpSuspendThread) {
+ return 0;
+ }
+
+ //
+ // this is probably unneccessary, because I think kernel32
+ // may not be relocated.
+ //
+ lpSuspendThread = (FARPROC)((DWORD)lpSuspendThread - (DWORD)hdll
+ + hthd->hprc->dwKernel32Base);
+
+ pss = malloc(sizeof(*pss));
+ assert(pss || !"malloc failed in MakeThreadSuspendItself");
+ if (!pss) {
+ return 0;
+ }
+
+ //
+ // Remember the current context
+ //
+ hthd->pss = pss;
+ pss->context = hthd->context;
+
+ //
+ // set a BP on the current PC, and register a persistent
+ // expected event to catch it later.
+ //
+
+ AddrInit(&addr, 0, 0, (DWORD) PC(hthd), TRUE, TRUE, FALSE, FALSE);
+ pss->pbp = SetBP( hthd->hprc, hthd, bptpExec, bpnsStop, &addr, (HPID) INVALID);
+
+ //
+ // don't try to step off of BP.
+ //
+ pss->atBP = hthd->atBP;
+ hthd->atBP = NULL;
+
+ RegisterExpectedEvent(
+ hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)pss->pbp,
+ NULL,
+ (ACVECTOR)ActionResumeThread,
+ TRUE,
+ pss);
+
+ //
+ // do machine dependent part
+ //
+ MakeThreadSuspendItselfHelper(hthd, lpSuspendThread);
+
+ return TRUE;
+}
+
+
+
+VOID
+ProcessIoctlGenericCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPIOL lpiol = (LPIOL)lpdbb->rgbVar;
+ PIOCTLGENERIC pig = (PIOCTLGENERIC)lpiol->rgbVar;
+ DWORD len;
+ ADDR addr;
+
+
+ switch( pig->ioctlSubType ) {
+ case IG_TRANSLATE_ADDRESS:
+ memcpy( &addr, pig->data, sizeof(addr) );
+ if (TranslateAddress( hprc, hthd, &addr, TRUE )) {
+ memcpy( pig->data, &addr, sizeof(addr) );
+ len = sizeof(IOCTLGENERIC) + pig->length;
+ memcpy( LpDmMsg->rgb, pig, len );
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(IOCTLGENERIC)+pig->length, LpDmMsg, lpdbb->hpid );
+ } else {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ }
+ break;
+
+ case IG_WATCH_TIME:
+ WtRangeStep( hthd );
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case IG_WATCH_TIME_STOP:
+ WtStruct.fWt = TRUE;
+ WtStruct.dwType = pig->ioctlSubType;
+ WtStruct.hthd = hthd;
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case IG_WATCH_TIME_RECALL:
+ WtStruct.fWt = TRUE;
+ WtStruct.dwType = pig->ioctlSubType;
+ WtStruct.hthd = hthd;
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case IG_WATCH_TIME_PROCS:
+ WtStruct.fWt = TRUE;
+ WtStruct.dwType = pig->ioctlSubType;
+ WtStruct.hthd = hthd;
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+
+ case IG_THREAD_INFO:
+#ifdef WIN32S
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+#else
+ {
+ typedef NTSTATUS (* QTHREAD)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
+
+ NTSTATUS Status;
+ THREAD_BASIC_INFORMATION ThreadBasicInfo;
+ QTHREAD Qthread;
+
+ Qthread = (QTHREAD)GetProcAddress( GetModuleHandle( "ntdll.dll" ), "NtQueryInformationThread" );
+ if (!Qthread) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+ }
+
+ Status = Qthread( hthd->rwHand,
+ ThreadBasicInformation,
+ &ThreadBasicInfo,
+ sizeof(ThreadBasicInfo),
+ NULL
+ );
+ if (!NT_SUCCESS(Status)) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ }
+
+ *(LPDWORD)pig->data = (DWORD)ThreadBasicInfo.TebBaseAddress;
+
+ len = sizeof(IOCTLGENERIC) + pig->length;
+ memcpy( LpDmMsg->rgb, pig, len );
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( len, LpDmMsg, lpdbb->hpid );
+ }
+#endif // WIN32S
+ break;
+
+ case IG_TASK_LIST:
+#ifdef WIN32S
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+#else
+ {
+ PTASK_LIST pTaskList = (PTASK_LIST)pig->data;
+ GetTaskList( pTaskList, pTaskList->dwProcessId );
+ len = sizeof(IOCTLGENERIC) + pig->length;
+ memcpy( LpDmMsg->rgb, pig, len );
+ LpDmMsg->xosdRet = xosdNone;
+ Reply( sizeof(IOCTLGENERIC)+pig->length, LpDmMsg, lpdbb->hpid );
+ }
+#endif
+ break;
+
+ default:
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply( 0, LpDmMsg, lpdbb->hpid );
+ break;
+ }
+
+ return;
+}
+
+
+VOID
+ProcessIoctlCustomCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ LPIOL lpiol = (LPIOL)lpdbb->rgbVar;
+ LPSTR p = lpiol->rgbVar;
+
+
+ LpDmMsg->xosdRet = xosdUnsupported;
+
+ //
+ // parse the command
+ //
+ while (*p && !isspace(*p++));
+ if (*p) {
+ *(p-1) = '\0';
+ }
+
+ //
+ // we don't have any custom dot command here yet
+ // when we do this is what the code should look like:
+ //
+ // at this point the 'p' variable points to any arguments
+ // to the dot command
+ //
+ // if (_stricmp( lpiol->rgbVar, "dot-command" ) == 0) {
+ // -----> do your thing <------
+ // LpDmMsg->xosdRet = xosdNone;
+ // }
+ //
+#if 0
+ if ( !_stricmp(lpiol->rgbVar, "FastStep") ) {
+ fSmartRangeStep = TRUE;
+ LpDmMsg->xosdRet = xosdNone;
+ } else if ( !_stricmp(lpiol->rgbVar, "SlowStep") ) {
+ fSmartRangeStep = FALSE;
+ LpDmMsg->xosdRet = xosdNone;
+ }
+#else
+ LpDmMsg->xosdRet = xosdNone;
+#endif
+
+ //
+ // send back our response
+ //
+ Reply(0, LpDmMsg, lpdbb->hpid);
+} /* ProcessIoctlCustomCmd() */
+
+
+#ifndef WIN32S
+
+DWORD WINAPI
+DoTerminate(
+ LPVOID lpv
+ )
+{
+ HPRCX hprcx = (HPRCX)lpv;
+
+ if (CrashDump) {
+ ProcessUnloadCmd(hprcx, NULL, NULL);
+ return 0;
+ }
+ TerminateProcess(hprcx->rwHand, 1);
+
+ //
+ // now that TerminateThread has completed, put priority
+ // back before calling out of DM
+ //
+
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+
+ WaitForSingleObject(hprcx->hExitEvent, INFINITE);
+
+ ProcessUnloadCmd(hprcx, NULL, NULL);
+
+ return 0;
+}
+
+VOID
+CompleteTerminateProcessCmd(
+ VOID
+ )
+{
+ DEBUG_EVENT devent, *de=&devent;
+ HANDLE hThread;
+ DWORD dwTid;
+ BREAKPOINT *pbpT;
+ BREAKPOINT *pbp;
+ PKILLSTRUCT pk;
+ HPRCX hprc;
+ HTHDX hthd;
+
+ DEBUG_PRINT("CompleteTerminateProcessCmd");
+
+ EnterCriticalSection(&csKillQueue);
+
+ pk = KillQueue;
+ if (pk) {
+ KillQueue = pk->next;
+ }
+
+ LeaveCriticalSection(&csKillQueue);
+
+ assert(pk);
+ if (!pk) {
+ return;
+ }
+
+ hprc = pk->hprc;
+ free(pk);
+
+ ConsumeAllProcessEvents(hprc, TRUE);
+
+ /*
+ * see if process is already dead
+ */
+
+ if ((hprc->pstate & ps_dead) || (hprc->rwHand == (HANDLE)INVALID)) {
+
+ //
+ // Queue a continue if any thread is stopped
+ //
+
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ if (hthd->tstate & ts_stopped) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~ts_stopped;
+ hthd->tstate |= ts_running;
+ }
+ }
+
+ ProcessUnloadCmd(hprc, NULL, NULL);
+
+ } else {
+
+ for (pbp = BPNextHprcPbp(hprc, NULL); pbp; pbp = pbpT) {
+ pbpT = BPNextHprcPbp(hprc, pbp);
+ RemoveBP(pbp);
+ }
+
+ //
+ // Start another thread to kill the thing. This thread needs to
+ // continue any threads which are stopped. The new thread will then
+ // wait until this one (the poll thread) has handled all of the
+ // events, and then send destruction notifications to the shell.
+ //
+
+ hThread = CreateThread(NULL,
+ 4096,
+ DoTerminate,
+ (LPVOID)hprc,
+ 0,
+ &dwTid);
+ assert(hThread);
+ if ( !hThread ) {
+ return;
+ }
+
+ //
+ // Yield so DoTerminate can do its thing before we start posting
+ // ContinueDebugEvents, so we minimize the time that the app
+ // runs before it is terminated.
+ //
+
+ hprc->pstate |= ps_killed;
+ SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
+ Sleep(0);
+
+ CloseHandle(hThread);
+
+ //
+ // Queue a continue if any thread is stopped
+ //
+
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ if (hthd->tstate & ts_stopped) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~ts_stopped;
+ hthd->tstate |= ts_running;
+ }
+ }
+
+ }
+
+}
+
+
+DWORD
+ProcessTerminateProcessCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ PKILLSTRUCT pk;
+
+ if (!hprc) {
+ return FALSE;
+ }
+
+ Unreferenced( lpdbb );
+
+ pk = (PKILLSTRUCT)malloc(sizeof(KILLSTRUCT));
+ pk->hprc = hprc;
+
+ EnterCriticalSection(&csKillQueue);
+
+ pk->next = KillQueue;
+ KillQueue = pk;
+
+ LeaveCriticalSection(&csKillQueue);
+
+ return TRUE;
+}
+#endif
+
+#ifdef WIN32S
+
+DWORD
+ProcessTerminateProcessCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ DWORD rval;
+
+ if (!hprc) {
+ return FALSE;
+ }
+
+ Unreferenced( lpdbb );
+
+ DEBUG_PRINT_2("ProcessTerminateProcessCmd called hprc=0x%x, hthd=0x%x.\n\r",
+ hprc, hthd);
+
+ // Win32s doesn't support TerminateProcess(), but does give us a special
+ // ContinueDebugEvent flag. If we are stopped at a debug event, we can
+ // Continue with this flag to terminate the child app.
+
+ DEBUG_PRINT("ConsumeAllProcessEvents\r\n");
+
+ ConsumeAllProcessEvents(hprc, TRUE);
+
+ DEBUG_PRINT("Check process state\r\n");
+
+ if ((hprc->pstate & ps_dead) || hprc->rwHand == (HANDLE)INVALID) {
+ DEBUG_PRINT("Process already dead\r\n");
+ if (fExitProcessDebugEvent) {
+ // we saved tidExit when we got the EXIT_PROCESS_DEBUG_EVENT
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hprc->pid,
+ tidExit,
+ DBG_CONTINUE,
+ 0);
+ }
+ rval = FALSE; // already dead
+ }
+
+ if (fProcessingDebugEvent) {
+ DEBUG_PRINT_1("Continue with %s\r\n",
+ (fExitProcessDebugEvent ? "DBG_CONTINUE" : "DBG_TERMINATE_PROCESS"));
+
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ if (hthd->tstate & ts_stopped) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ fExitProcessDebugEvent?
+ DBG_CONTINUE : DBG_TERMINATE_PROCESS,
+ 0);
+ hthd->tstate &= ~ts_stopped;
+ hthd->tstate |= ts_running;
+ }
+ }
+
+ // mark this process as killed
+ DEBUG_PRINT("Mark process as killed\r\n");
+ hprc->pstate |= ps_killed;
+ rval = TRUE; // killed it.
+ } else {
+ DEBUG_PRINT("Can't terminate process right now\r\n");
+ // can't continue debug event right now, so can't terminate.
+ rval = FALSE;
+ }
+
+ return rval;
+}
+#endif
+
+
+VOID
+ProcessAllProgFreeCmd(
+ HPRCX hprcXX,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ HPRCX hprc;
+
+ Unreferenced(hprcXX);
+ Unreferenced(hthd);
+
+ for (;;) {
+
+ EnterCriticalSection(&csThreadProcList);
+ for (hprc = prcList; hprc; hprc = hprc->next) {
+ if (hprc->pstate != (ps_root | ps_destroyed)) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+
+ if (hprc) {
+ ProcessTerminateProcessCmd(hprc, hthd, lpdbb);
+ ProcessUnloadCmd(hprc, hthd, lpdbb);
+ } else {
+ break;
+ }
+
+ }
+
+ WaitForSingleObject(hEventNoDebuggee, INFINITE);
+}
+
+
+DWORD
+ProcessAsyncGoCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+ XOSD xosd = xosdNone;
+#ifndef WIN32S
+ DEBUG_EVENT de;
+#endif
+
+ DEBUG_PRINT("ProcessAsyncGoCmd called.\n\r");
+
+#ifdef WIN32S
+ xosd = xosdUnsupported; // can't resume thread in win32s
+#else
+
+#ifdef WIN32
+ if ((hthd->tstate & ts_frozen)) {
+ if (hthd->tstate & ts_stopped) {
+ //
+ // if at a debug event, it won't really be suspended,
+ // so just clear the flag.
+ //
+ hthd->tstate &= ~ts_frozen;
+
+ } else if (ResumeThread(hthd->rwHand) == -1L ) {
+
+#ifdef OSDEBUG4
+ xosd = xosdBadThread;
+#else
+ xosd = xosdInvalidThread;
+#endif
+
+ } else {
+
+ hthd->tstate &= ~ts_frozen;
+
+ /*
+ * deal with dead, frozen, continued thread:
+ */
+ if ((hthd->tstate & ts_dead) && !(hthd->tstate & ts_stopped)) {
+
+ de.dwDebugEventCode = DESTROY_THREAD_DEBUG_EVENT;
+ de.dwProcessId = hprc->pid;
+ de.dwThreadId = hthd->tid;
+ NotifyEM(&de, hthd, 0, NULL);
+ FreeHthdx(hthd);
+
+ hprc->pstate &= ~ps_deadThread;
+ for (hthd = hprc->hthdChild; hthd; hthd = hthd->nextSibling) {
+ if (hthd->tstate & ts_dead) {
+ hprc->pstate |= ps_deadThread;
+ }
+ }
+
+ }
+ }
+ }
+#endif // WIN32
+#endif // !WIN32S
+
+ Reply(0, &xosd, lpdbb->hpid);
+ return(xosd);
+}
+
+
+void
+ActionAsyncStop(
+ DEBUG_EVENT * pde,
+ HTHDX hthd,
+ DWORD unused,
+ BREAKPOINT * pbp
+ )
+/*++
+
+Routine Description:
+
+ This routine is called if a breakpoint is hit which is part of a
+ Async Stop request. When hit is needs to do the following: clean
+ out any expected events on the current thread, clean out all breakpoints
+ which are setup for doing the current async stop.
+
+Arguments:
+
+ pde - Supplies a pointer to the debug event which just occured
+
+ hthd - Supplies a pointer to the thread for the debug event
+
+ pbp - Supplies a pointer to the breakpoint for the ASYNC stop
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ union {
+ RTP rtp;
+ char rgb[sizeof(RTP) + sizeof(BPR)];
+ } rtpbuf;
+ RTP * prtp = &rtpbuf.rtp;
+ BPR * pbpr = (BPR *) prtp->rgbVar;
+ HPRCX hprc = hthd->hprc;
+ BREAKPOINT * pbpT;
+
+ /*
+ * We no longer need to have this breakpoint set.
+ */
+
+ RemoveBP( pbp );
+
+ /*
+ * Remove any other breakpoints in this process which are for
+ * async stop commands
+ */
+
+ for (pbp = BPNextHprcPbp(hprc, NULL); pbp != NULL; pbp = pbpT) {
+
+ pbpT = BPNextHprcPbp(hprc, pbp);
+
+ if (pbp->id == (HPID)ASYNC_STOP_BP) {
+ RemoveBP( pbp );
+ }
+ }
+
+ /*
+ * Setup a return packet which says we hit an async stop breakpoint
+ */
+
+ prtp->hpid = hprc->hpid;
+ prtp->htid = hthd->htid;
+ prtp->dbc = dbcAsyncStop;
+ prtp->cb = sizeof(BPR);
+
+#ifdef TARGET_i386
+ pbpr->segCS = (SEGMENT) hthd->context.SegCs;
+ pbpr->segSS = (SEGMENT) hthd->context.SegSs;
+ pbpr->offEBP = (UOFFSET) hthd->context.Ebp;
+#endif
+
+ pbpr->offEIP = (DWORD) PC(hthd);
+
+ DmTlFunc(tlfDebugPacket, prtp->hpid, sizeof(rtpbuf), (LONG)&rtpbuf);
+
+ return;
+} /* ActionAsyncStop() */
+
+
+
+VOID
+ProcessAsyncStopCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to a asynchronous stop request.
+ In order to do this we will set breakpoints the current PC for
+ every thread in the system and wait for the fireworks to start.
+
+Arguments:
+
+ hprc - Supplies a process handle
+
+ hthd - Supplies a thread handle
+
+ lpdbb - Supplies the command information packet
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#ifdef WIN32S
+
+ /*
+ * Win32s doesn't support async stop this way. The user should
+ * press the debugger hot key at the debuggee console to generate
+ * an async stop. This may change if BoazF gives us a private API
+ * to generate the async stop exception.
+ */
+ DEBUG_PRINT("\r\nProcessAsyncStopCmd\r\n");
+
+ LpDmMsg->xosdRet = xosdUnsupported;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+
+#else
+ CONTEXT regs;
+ BREAKPOINT * pbp;
+ ADDR addr;
+ BOOL fSetFocus = * ( BOOL *) lpdbb->rgbVar;
+
+ regs.ContextFlags = CONTEXT_CONTROL;
+
+
+ /*
+ * Step 1. Enumerate through the threads and freeze them all.
+ */
+
+ for (hthd = hprc->hthdChild; hthd != NULL; hthd = hthd->nextSibling) {
+ if (SuspendThread(hthd->rwHand) == -1L) {
+ ; // Internal error;
+ }
+ }
+
+ /*
+ * Step 2. Place a breakpoint on every PC address
+ */
+
+ for (hthd = hprc->hthdChild; hthd != NULL; hthd = hthd->nextSibling) {
+#ifndef WIN32S
+ if (CrashDump) {
+ DmpGetContext( hthd->tid-1, &regs );
+ } else
+#endif
+ {
+ GetThreadContext( hthd->rwHand, &regs );
+ }
+
+ AddrInit(&addr, 0, 0, (DWORD)cPC(&regs), TRUE, TRUE, FALSE, FALSE);
+ pbp = SetBP(hprc, hthd, bptpExec, bpnsStop, &addr, (HPID) ASYNC_STOP_BP);
+
+ RegisterExpectedEvent(hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)pbp,
+ DONT_NOTIFY,
+ (ACVECTOR)ActionAsyncStop,
+ FALSE,
+ pbp);
+ }
+
+ /*
+ * Step 3. Unfreeze all threads
+ */
+
+ if (fSetFocus) {
+ DmSetFocus(hprc);
+ }
+ for (hthd = hprc->hthdChild; hthd != NULL; hthd = hthd->nextSibling) {
+ if (ResumeThread(hthd->rwHand) == -1) {
+ ; // Internal error
+ }
+ }
+
+ LpDmMsg->xosdRet = xosdNone;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ return;
+#endif
+} /* ProcessAsyncStopCmd() */
+
+
+VOID
+ProcessDebugActiveCmd(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPDBB lpdbb
+ )
+{
+#ifdef WIN32S
+
+ Unreferenced(hprc);
+ Unreferenced(hthd);
+
+ LpDmMsg->xosdRet = xosdUnsupported; // can't attatch in win32s
+ *((DWORD *)LpDmMsg->rgb) = ERROR_NOT_SUPPORTED;
+ Reply(sizeof(DWORD), LpDmMsg, lpdbb->hpid);
+
+#else
+
+#ifdef OSDEBUG4
+
+ LPDAP lpdap = ((LPDAP)(lpdbb->rgbVar));
+
+ Unreferenced(hprc);
+ Unreferenced(hthd);
+
+ if (fDisconnected) {
+
+ SetEvent( hEventRemoteQuit );
+
+ } else if (!StartDmPollThread()) {
+
+ //
+ // CreateThread() failed; fail and send a dbcError.
+ //
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+
+ } else if (WaitForSingleObject(DebugActiveStruct.hEventReady, INFINITE)
+ != 0) {
+ //
+ // the wait failed. why? are there cases where we
+ // should restart the wait?
+ //
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+
+ } else {
+
+ ResetEvent(DebugActiveStruct.hEventReady);
+ ResetEvent(DebugActiveStruct.hEventApiDone);
+
+ DebugActiveStruct.dwProcessId = lpdap->dwProcessId;
+ DebugActiveStruct.hEventGo = lpdap->hEventGo;
+ DebugActiveStruct.fAttach = TRUE;
+
+ *nameBuffer = 0;
+
+ // wait for it...
+
+ if (WaitForSingleObject(DebugActiveStruct.hEventApiDone, INFINITE) == 0
+ && DebugActiveStruct.fReturn != 0) {
+
+ LpDmMsg->xosdRet = xosdNone;
+ //
+ // the poll thread will reply when creating the "root" process.
+ //
+ if (!fUseRoot) {
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ }
+
+ } else {
+ LpDmMsg->xosdRet = xosdUnknown;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ }
+
+ }
+
+
+#else // OSDEBUG4
+
+ LPDBG_ACTIVE_STRUCT lpdba = ((LPDBG_ACTIVE_STRUCT)(lpdbb->rgbVar));
+
+ Unreferenced(hprc);
+ Unreferenced(hthd);
+
+ if (fDisconnected) {
+ SetEvent( hEventRemoteQuit );
+ } else if (!StartDmPollThread()) {
+
+ LpDmMsg->xosdRet = xosdUnknown;
+ // Last error is from CreateThread();
+ *((DWORD *)LpDmMsg->rgb) = GetLastError();
+ Reply(0, LpDmMsg, lpdbb->hpid);
+
+ // wait for attach struct to be available
+ } else if (WaitForSingleObject(DebugActiveStruct.hEventReady, INFINITE)
+ != 0) {
+ LpDmMsg->xosdRet = xosdUnknown;
+ *((DWORD *)LpDmMsg->rgb) = GetLastError();
+ Reply(0, LpDmMsg, lpdbb->hpid);
+
+ } else {
+
+ ResetEvent(DebugActiveStruct.hEventReady);
+ ResetEvent(DebugActiveStruct.hEventApiDone);
+
+ DebugActiveStruct.dwProcessId = lpdba->dwProcessId;
+ DebugActiveStruct.hEventGo = lpdba->hEventGo;
+ DebugActiveStruct.fAttach = TRUE;
+
+ *nameBuffer = 0;
+
+ // wait for it...
+
+ if (WaitForSingleObject(DebugActiveStruct.hEventApiDone, INFINITE) == 0
+ && DebugActiveStruct.fReturn != 0) {
+
+ LpDmMsg->xosdRet = xosdNone;
+ //
+ // the poll thread will reply when creating the "root" process.
+ //
+ if (!fUseRoot) {
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ }
+
+ } else {
+
+ DebugActiveStruct.dwProcessId = 0;
+ DebugActiveStruct.hEventGo = NULL;
+ LpDmMsg->xosdRet = xosdUnknown;
+ *((DWORD *)LpDmMsg->rgb) = DebugActiveStruct.dwError;
+ Reply(0, LpDmMsg, lpdbb->hpid);
+ }
+ }
+
+#endif // OSDEBUG4
+
+ SetEvent(DebugActiveStruct.hEventReady);
+
+#endif // WIN32S
+}
+
+
+VOID
+ProcessRemoteQuit(
+ VOID
+ )
+{
+ HPRCX hprc;
+ BREAKPOINT *pbp;
+ BREAKPOINT *pbpT;
+
+
+ EnterCriticalSection(&csThreadProcList);
+
+ for(hprc=prcList->next; hprc; hprc=hprc->next) {
+ for (pbp = BPNextHprcPbp(hprc, NULL); pbp; pbp = pbpT) {
+ pbpT = BPNextHprcPbp(hprc, pbp);
+ RemoveBP(pbp);
+ }
+ }
+
+ LeaveCriticalSection(&csThreadProcList);
+
+ fDisconnected = TRUE;
+ ResetEvent( hEventRemoteQuit );
+}
diff --git a/private/windbg/newdm/user/wow.c b/private/windbg/newdm/user/wow.c
new file mode 100644
index 000000000..e536bc792
--- /dev/null
+++ b/private/windbg/newdm/user/wow.c
@@ -0,0 +1,1175 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ WOW.C
+
+Abstract:
+
+ This file contains the code which is responsable for dealing with
+ the WOW debug structures and debug events.
+
+Author:
+
+ James L Schaad (jimsch) 05-11-92
+
+Environment:
+
+ User Mode WIN32
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+/************************* GLOBAL VARIABLES ******************************/
+
+extern char abEMReplyBuf[];
+extern DDVECTOR RgfnFuncEventDispatch[];
+extern DDVECTOR DebugDispatchTable[];
+extern char nameBuffer[];
+
+/********************** Local Prototypes *********************************/
+
+int LookupDllName(HPRCX hprcx, char * sz);
+int InsertDllName(HPRCX hprcx, char * sz);
+void RemoveDllName(HPRCX hprcx, int idx);
+
+static DEBUG_EVENT DeWow;
+
+
+/************************** FUNCTIONS ************************************/
+
+
+void
+ProcessEntryPointEvent(
+ DEBUG_EVENT * pde,
+ HTHDX hthdx
+ )
+/*++
+
+Routine Description:
+
+ This handles task start events after the first one.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+#if defined(i386) && !defined(WIN32S)
+ IMAGE_NOTE in;
+ LPBYTE lpb;
+ DWORD cbRead;
+ int b;
+ char szName0[_MAX_FNAME + _MAX_EXT];
+ char szName1[_MAX_FNAME + _MAX_EXT];
+ char szExt [_MAX_EXT];
+
+
+ lpb = (LPBYTE)pde->
+ u.Exception.ExceptionRecord.ExceptionInformation[2];
+ b = DbgReadMemory(hthdx->hprc,
+ lpb,
+ &in,
+ sizeof(in),
+ &cbRead);
+
+ if ((b == 0) || (cbRead != sizeof(in))) {
+ b = GetLastError();
+ } else {
+ _splitpath(in.FileName, NULL, NULL, szName0, szExt);
+ strcat(szName0, szExt);
+ _splitpath(nameBuffer, NULL, NULL, szName1, szExt);
+ strcat(szName1, szExt);
+
+ if (_strcmpi(szName0, szName1) == 0) {
+ *nameBuffer = 0;
+ hthdx->hprc->pstate &= ~ps_preEntry;
+ hthdx->tstate |= ts_stopped;
+ NotifyEM(pde, hthdx, 0, (LPVOID)ENTRY_BP);
+ return;
+ }
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+#endif
+}
+
+
+
+void
+ProcessSegmentLoadEvent(
+ DEBUG_EVENT * pde,
+ HTHDX hthdx
+ )
+
+/*++
+
+Routine Description:
+
+ This function takes care of dealing with segment load events from
+ the wow system. These come in as exceptions and are translated
+ to segment load events in ProcessDebugEvent.
+
+Arguments:
+
+ pde - Supplies a pointer to the modified debug event
+ hthdx - Supplies the handle to the thread of the debug event
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#if defined(i386) && !defined(WIN32S)
+
+ LPDWORD lpdw = &pde->u.Exception.ExceptionRecord.ExceptionInformation[0];
+ int mode = LOWORD( lpdw[0] );
+ int cb;
+ int cbRead;
+ int b;
+ char rgch[512];
+ char * lpb;
+ LPMODULELOAD lpmdl;
+ RTP rtp;
+ LPRTP lprtp;
+ WORD packetType = tlfDebugPacket;
+ HEMI hemi;
+ HPRCX hprcx = hthdx->hprc;
+ int idx;
+ SEGMENT_NOTE sn;
+ ADDR addr;
+ EXPECTED_EVENT * pee;
+ DWORD eventCode;
+ DWORD subClass;
+ LDT_ENTRY ldt;
+ BREAKPOINT *bp;
+
+
+#ifdef i386
+ DeWow = *pde;
+
+ rtp.hpid = hprcx->hpid;
+ rtp.htid = hthdx->htid;
+
+ hthdx->fWowEvent = TRUE;
+
+ VDMProcessException(pde);
+
+ switch ( mode ) {
+ /*
+ * SEG LOAD:
+ *
+ * LOWORD(lpdw[0]) --- DBG_SEGLOAD
+ * HIWORD(lpdw[0]) --- Unused
+ * LOWORD(lpdw[1]) --- Unused
+ * HIWORD(lpdw[1]) --- Unused
+ * lpdw[2] --- pointer to SEGMENT_NOTE structure
+ * lpdw[3] --- Reserved
+ */
+
+ case DBG_SEGLOAD:
+ lpb = (char *) lpdw[2];
+ b = DbgReadMemory(hprcx, lpb, &sn, sizeof(sn), &cbRead);
+
+ if ((b == 0) || (cbRead != sizeof(sn))) {
+ b = GetLastError();
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+
+ if (sn.FileName[0] == 0) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+ cb = strlen(sn.FileName)+1;
+
+ idx = LookupDllName(hprcx, sn.FileName);
+
+ if ( idx != -1 ) {
+ if (hprcx->rgDllList[idx].fReal) {
+ //
+ // Changing from real to protected mode. We don't
+ // support this, so we'll throw away what we have
+ // and start from scratch.
+ //
+ lprtp = (LPRTP) rgch;
+ *lprtp = rtp;
+ lprtp->dbc = dbceModFree16;
+ lprtp->cb = sizeof(WORD);
+ *((WORD *)(&lprtp->rgbVar[0])) = idx;
+
+ DmTlFunc(tlfDebugPacket, rtp.hpid, lprtp->cb + sizeof(RTP),
+ (LONG)(LPV) lprtp);
+
+ RemoveDllName( hprcx, idx );
+ idx = -1;
+ }
+ }
+
+ if (idx == -1) {
+
+ cb = cb + sizeof(MODULELOAD) + (sn.Segment+1)*sizeof(OBJD);
+ lprtp = (LPRTP) malloc(cb + sizeof(RTP));
+ memset(lprtp, 0, cb + sizeof(RTP));
+
+ *lprtp = rtp;
+ lprtp->dbc = dbcModLoad;
+ lprtp->cb = cb;
+
+ lpmdl = (LPMODULELOAD) &(lprtp->rgbVar[0]);
+ lpmdl->cobj = sn.Segment+1;
+
+ lpmdl->rgobjd[sn.Segment].wSel = sn.Selector1;
+ lpmdl->rgobjd[sn.Segment].cb = (DWORD) -1;
+ lpmdl->rgobjd[sn.Segment].wPad = 1;
+
+ lpmdl->mte = InsertDllName(hprcx, sn.FileName);
+ strcpy((char *) &lpmdl->rgobjd[lpmdl->cobj], sn.FileName);
+
+ lpmdl->fRealMode = FALSE;
+ lpmdl->fFlatMode = FALSE;
+ lpmdl->fOffset32 = FALSE;
+
+ DmTlFunc(tlfRequest, rtp.hpid, lprtp->cb + sizeof(RTP),
+ (LONG)(LPV) lprtp);
+
+ hemi = *((HEMI *) abEMReplyBuf);
+
+ free(lprtp);
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+
+ } else {
+ LPSLI lpsli;
+
+ lprtp = (LPRTP) malloc( sizeof(RTP) + sizeof(SLI));
+ *lprtp = rtp;
+ lprtp->dbc = dbceSegLoad;
+ lprtp->cb = sizeof(SLI);
+ lpsli = (LPSLI) &lprtp->rgbVar[0];
+ lpsli->wSelector = sn.Selector1;
+ lpsli->wSegNo = sn.Segment;
+ lpsli->mte = idx;
+
+ DmTlFunc(tlfDebugPacket, rtp.hpid, lprtp->cb + sizeof(RTP),
+ (LONG)(LPV) lprtp);
+
+ free( lprtp );
+ }
+
+ break;
+
+ /*
+ * SEGMOVE:
+ *
+ * This event will be triggered if a selector number
+ * is to be changed.
+ *
+ * LOWORD( lpdw[0] ) - SEGMOVE
+ * LOWORD( lpdw[1] ) - old selector number
+ * HIWORD( lpdw[1] ) - new selector number
+ */
+
+ case DBG_SEGMOVE:
+
+ lpb = (char *) lpdw[2];
+ b = DbgReadMemory(hprcx, lpb, &sn, sizeof(sn), &cbRead);
+
+ if ((b == 0) || (cbRead != sizeof(sn))) {
+ b = GetLastError();
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+
+ if (sn.FileName[0] == 0) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+ cb = strlen(sn.FileName)+1;
+
+ idx = LookupDllName(hprcx, sn.FileName);
+
+ if ( idx != -1 ) {
+ LPSLI lpsli;
+
+ lprtp = (LPRTP) malloc( sizeof(RTP) + sizeof(SLI));
+ *lprtp = rtp;
+ lprtp->dbc = dbceSegMove;
+ lprtp->cb = sizeof(SLI);
+ lpsli = (LPSLI) &lprtp->rgbVar[0];
+ assert( sn.Selector1 == 0 );
+ lpsli->wSelector = sn.Selector2;
+ lpsli->wSegNo = sn.Segment;
+ lpsli->mte = idx;
+
+ DmTlFunc(tlfDebugPacket, rtp.hpid, lprtp->cb + sizeof(RTP),
+ (LONG)(LPV) lprtp);
+
+ free( lprtp );
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+
+ break;
+
+ /*
+ * SEGFREE:
+ *
+ * This event is triggered if a selector is freed
+ *
+ * LOWORD( lpdw[0] ) - SEGFREE
+ * HIWORD( lpdw[0] ) - fBPRelease
+ * LOWORD( lpdw[1] ) - selector to be freed
+ */
+
+ case DBG_SEGFREE:
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+
+ break;
+
+ /*
+ * MODLOAD:
+ *
+ * This event is triggered when a new DLL is loaded
+ *
+ * LOWORD( lpdw[0] ) - MODLOAD
+ * HIWORD( lpdw[0] ) - length of module name
+ * HIWORD( lpdw[1] ) - selector
+ * lpdw[2] - address of module name
+ * lpdw[3] - image length
+ *
+ */
+
+ case DBG_MODLOAD:
+
+ lpb = (char *) lpdw[2];
+ b = DbgReadMemory(hprcx, lpb, &sn, sizeof(sn), &cbRead);
+
+ if ((b == 0) || (cbRead != sizeof(sn))) {
+ b = GetLastError();
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+
+ if (sn.FileName[0] == 0) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+
+ cb = strlen(sn.FileName)+1;
+ idx = LookupDllName(hprcx, sn.FileName);
+
+ if (idx == -1) {
+ cb = cb + sizeof(MODULELOAD);
+ lprtp = (LPRTP) malloc(cb + sizeof(RTP));
+ memset(lprtp, 0, cb + sizeof(RTP));
+
+ *lprtp = rtp;
+ lprtp->dbc = dbcModLoad;
+ lprtp->cb = cb;
+
+ lpmdl = (LPMODULELOAD) &(lprtp->rgbVar[0]);
+ lpmdl->cobj = 0;
+
+ lpmdl->mte = InsertDllName(hprcx, sn.FileName);
+
+ idx = LookupDllName(hprcx, sn.FileName);
+
+ if ( idx != -1 ) {
+ hprcx->rgDllList[idx].fReal = TRUE;
+ }
+
+ strcpy((char *) &lpmdl->rgobjd[lpmdl->cobj], sn.FileName);
+
+ lpmdl->StartingSegment = sn.Segment;
+
+ lpmdl->fRealMode = TRUE;
+ lpmdl->fFlatMode = FALSE;
+ lpmdl->fOffset32 = FALSE;
+
+ DmTlFunc(tlfRequest, rtp.hpid, lprtp->cb + sizeof(RTP),
+ (LONG)(LPV) lprtp);
+
+ hemi = *((HEMI *) abEMReplyBuf);
+
+ free(lprtp);
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+
+ break;
+
+ /*
+ * MODFREE:
+ *
+ * This event is triggered when a DLL is unloaded
+ *
+ * LOWORD( lpdw[0] ) - MODFREE
+ */
+
+ case DBG_MODFREE:
+ lpb = (char *) lpdw[2];
+ b = DbgReadMemory(hprcx, lpb, &sn, sizeof(sn), &cbRead);
+
+ if ((b == 0) || (cbRead != sizeof(sn))) {
+ b = GetLastError();
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+
+ if (sn.FileName[0] == 0) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ return;
+ }
+ cb = strlen(sn.FileName)+1;
+
+ idx = LookupDllName(hprcx, sn.FileName);
+
+ if (idx != -1) {
+ lprtp = (LPRTP) rgch;
+ *lprtp = rtp;
+ lprtp->dbc = dbceModFree16;
+ lprtp->cb = sizeof(WORD);
+ *((WORD *)(&lprtp->rgbVar[0])) = idx;
+
+ DmTlFunc(tlfDebugPacket, rtp.hpid, lprtp->cb + sizeof(RTP),
+ (LONG)(LPV) lprtp);
+
+ RemoveDllName( hprcx, idx );
+ }
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+
+ break;
+
+ /*
+ * Int 01h break;
+ */
+
+ case DBG_SINGLESTEP:
+ hthdx->context.ContextFlags = VDMCONTEXT_FULL;
+ VDMGetThreadContext(pde, &hthdx->context);
+
+ eventCode = EXCEPTION_DEBUG_EVENT;
+ pde->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+ pde->u.Exception.ExceptionRecord.ExceptionCode = subClass =
+ (DWORD)EXCEPTION_SINGLE_STEP;
+
+ /*
+ * They are not clearing the trace bit
+ */
+
+ hthdx->context.EFlags &= ~TF_BIT_MASK;
+ hthdx->fContextDirty = TRUE;
+
+ AddrInit(&addr, 0, (SEGMENT) hthdx->context.SegCs, hthdx->context.Eip,
+ FALSE, FALSE, FALSE, FALSE);
+
+ bp = FindBP(hthdx->hprc, hthdx, bptpExec, (BPNS)-1, &addr, FALSE);
+
+ if ( bp ) {
+ SetBPFlag( hthdx, bp );
+ }
+
+ goto dispatch;
+
+ case DBG_TASKSTART:
+ hthdx->context.ContextFlags = VDMCONTEXT_FULL;
+ VDMGetThreadContext(pde, &hthdx->context);
+
+ eventCode =
+ pde->dwDebugEventCode = ENTRYPOINT_DEBUG_EVENT;
+
+ goto dispatch;
+
+ case DBG_TASKSTOP:
+ case DBG_DLLSTART:
+ case DBG_DLLSTOP:
+ case DBG_ATTACH:
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ break;
+
+
+ /*
+ * Int 03h break
+ *
+ * LOWORD(lpdw[0]) --- BREAKPOINT
+ * HIWORD(lpdw[0]) --- Protect Mode
+ */
+
+ case DBG_BREAK:
+ hthdx->context.ContextFlags = VDMCONTEXT_FULL;
+ VDMGetThreadContext(pde, &hthdx->context);
+
+ PC(hthdx) -= 1;
+ hthdx->fContextDirty = TRUE;
+
+ eventCode = pde->dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;
+
+ // NOTENOTE --- jimsch -- assuming only 0xcc not 0xcd 0x3 breakpoints
+
+ AddrInit(&addr, 0, (SEGMENT) hthdx->context.SegCs, hthdx->context.Eip,
+ FALSE, FALSE, FALSE, FALSE);
+
+ bp = FindBP(hthdx->hprc, hthdx, bptpExec, (BPNS)-1, &addr, FALSE);
+
+ if ( bp && bp->isStep ) {
+
+ eventCode = EXCEPTION_DEBUG_EVENT;
+ pde->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+
+ pde->u.Exception.ExceptionRecord.ExceptionCode =
+ subClass = (DWORD)EXCEPTION_SINGLE_STEP;
+ RemoveBP(bp);
+
+ } else {
+
+ if ( bp ) {
+ SetBPFlag( hthdx, bp );
+ }
+
+ pde->u.Exception.ExceptionRecord.ExceptionCode =
+ subClass = (DWORD)bp;
+ }
+
+ pde->u.Exception.ExceptionRecord.ExceptionAddress = (LPVOID) PC(hthdx);
+
+ dispatch:
+ hthdx->fAddrIsReal = FALSE;
+ hthdx->fAddrIsFlat = FALSE;
+
+ if (VDMGetThreadSelectorEntry(pde,
+ hthdx->rwHand,
+ (WORD) hthdx->context.SegCs,
+ &ldt)) {
+ if (ldt.HighWord.Bits.Default_Big) {
+ hthdx->fAddrOff32 = TRUE;
+ } else {
+ hthdx->fAddrOff32 = FALSE;
+ }
+ } else {
+ hthdx->fAddrOff32 = FALSE;
+ }
+
+ /*
+ * Check if this debug event was expected
+ */
+
+ pee = PeeIsEventExpected(hthdx, eventCode, subClass);
+
+ /*
+ * If it wasn't, run the standard handler with
+ * notifications going to the execution model
+ */
+
+ assert((0 < eventCode) && (eventCode < MAX_EVENT_CODE));
+
+ if (pee == NULL) {
+ if ((hthdx != NULL) && (hthdx->tstate & ts_funceval)) {
+ RgfnFuncEventDispatch[eventCode-EXCEPTION_DEBUG_EVENT](pde, hthdx);
+ } else {
+ DebugDispatchTable[eventCode-EXCEPTION_DEBUG_EVENT](pde,hthdx);
+ }
+ return;
+ }
+
+
+ /*
+ * If it was expected then call the action
+ * function if one was specified
+ */
+
+ if (pee->action) {
+ (pee->action)(pde, hthdx, 0, pee->lparam);
+ }
+
+ /*
+ * And call the notifier if one was specified
+ */
+
+ if (pee->notifier) {
+ METHOD *nm = pee->notifier;
+ (nm->notifyFunction)(pde, hthdx, 0, nm->lparam);
+ }
+
+ free(pee);
+ break;
+
+#if 0 // why is this here??
+ case DBG_DIVOVERFLOW:
+ pde->dwDebugEventCode = 3;
+ goto fault_occured;
+
+ case DBG_INSTRFAULT:
+ pde->dwDebugEventCode = 1;
+ goto fault_occured;
+#endif
+
+ case DBG_DIVOVERFLOW:
+ case DBG_INSTRFAULT:
+ case DBG_GPFAULT:
+ pde->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+
+#if 0 // why is this here??
+ fault_occured:
+#endif
+
+ hthdx->context.ContextFlags = VDMCONTEXT_FULL;
+ VDMGetThreadContext(pde, &hthdx->context);
+ pde->u.Exception.ExceptionRecord.ExceptionCode = 13;
+
+ hthdx->fAddrIsReal = FALSE;
+ hthdx->fAddrIsFlat = FALSE;
+
+ if (VDMGetThreadSelectorEntry(pde, hthdx->rwHand,
+ (WORD) hthdx->context.SegCs, &ldt)) {
+ if (ldt.HighWord.Bits.Default_Big) {
+ hthdx->fAddrOff32 = TRUE;
+ } else {
+ hthdx->fAddrOff32 = FALSE;
+ }
+ } else {
+ hthdx->fAddrOff32 = FALSE;
+ }
+
+ ProcessExceptionEvent(pde, hthdx);
+ break;
+
+ default:
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthdx->hprc->pid,
+ hthdx->tid,
+ DBG_CONTINUE,
+ 0);
+ hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthdx->tstate |= ts_running;
+ break;
+ }
+#endif // i386
+#endif // i386 && !Win32S
+ return;
+} /* ProcessSegmentLoadEvent() */
+
+
+#if defined(i386) && !defined(WIN32S)
+
+int
+LookupDllName(
+ HPRCX hprcx,
+ char * sz
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will snoop through the structures of an exe and determine
+ if we have previously seen this dll name for this process.
+
+Arguments:
+
+ hprcx - Supplies a handle to a process
+ sz - Supplies a pointer to a DLL file name
+ .
+
+Return Value:
+
+ The index in the array if present. Else -1
+
+--*/
+
+{
+ int i;
+
+ /*
+ * If there is no list then the item is not on the list
+ */
+
+ if (hprcx->rgDllList == NULL) {
+ return -1;
+ }
+
+ /*
+ * Check each item in the list
+ */
+
+ for (i=0; i<hprcx->cDllList; i++) {
+ if ((hprcx->rgDllList[i].fValidDll) &&
+ (hprcx->rgDllList[i].szDllName != NULL) &&
+ (strcmp(hprcx->rgDllList[i].szDllName, sz) == 0)) {
+ return i;
+ }
+ }
+ return -1;
+} /* LookupDllName() */
+
+
+int
+InsertDllName(
+ HPRCX hprcx,
+ char * sz
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will take a dll name and an mte and put then into the
+ list of dlls for the current process.
+
+Arguments:
+
+ hprcx - Supplies a handle to a process
+ sz - Supplies a pointer to a DLL file name
+
+Return Value:
+
+ The index in the array where it was placed.
+
+--*/
+
+{
+ int i;
+ int cb;
+ int cItem;
+
+ /*
+ * If there is no list then make a list
+ */
+
+ if (hprcx->rgDllList == NULL) {
+ hprcx->rgDllList = (PDLLLOAD_ITEM) malloc(sizeof(DLLLOAD_ITEM) * 10);
+ memset(hprcx->rgDllList, 0, sizeof(DLLLOAD_ITEM)*10);
+ }
+
+ /*
+ * Check each item in the list
+ */
+
+ for (i=0; i<hprcx->cDllList; i++) {
+ if ((hprcx->rgDllList[i].fValidDll == FALSE) &&
+ (hprcx->rgDllList[i].szDllName == NULL)) {
+ hprcx->rgDllList[i].szDllName = _strdup(sz);
+ hprcx->rgDllList[i].fValidDll = TRUE;
+ hprcx->rgDllList[i].fWow = TRUE;
+ return i;
+ }
+ }
+
+ cItem = hprcx->cDllList;
+ if (i == cItem) {
+ cb = i * sizeof(DLLLOAD_ITEM);
+ cItem += 10;
+ hprcx->rgDllList = (PDLLLOAD_ITEM) realloc(hprcx->rgDllList, cItem*sizeof(DLLLOAD_ITEM));
+ memset(cb + (char *) hprcx->rgDllList, 0, 10*sizeof(DLLLOAD_ITEM));
+ }
+
+
+ hprcx->rgDllList[i].szDllName = _strdup(sz);
+ hprcx->rgDllList[i].fValidDll = TRUE;
+ hprcx->rgDllList[i].fWow = TRUE;
+ hprcx->cDllList += 10;
+
+ return i;
+} /* InsertDllName() */
+
+
+
+void
+RemoveDllName(
+ HPRCX hprcx,
+ int idx
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will remove a dll from the internal list of known dlls.
+
+Arguments:
+
+ hprcx - Supplies the handle to the current process
+ idx - supplies the index of the dll to be removed
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ assert( hprcx->rgDllList != NULL );
+
+ free(hprcx->rgDllList[idx].szDllName);
+ hprcx->rgDllList[idx].szDllName = NULL;
+ hprcx->rgDllList[idx].fValidDll = FALSE;
+ hprcx->rgDllList[idx].fReal = FALSE;
+ hprcx->rgDllList[idx].fWow = FALSE;
+
+ return;
+} /* RemoveDllName() */
+
+
+#endif // i386 && !WIN32S
+
+/*++
+
+Routine Description:
+
+ Callback for VDMEnumProcessWOW
+
+Arguments:
+
+ See PROCESSENUMPROC in vdmdbg.h
+
+Return Value:
+
+ TRUE
+
+--*/
+BOOL WINAPI EnumCallBack(
+ DWORD dwProcessId,
+ DWORD dwAttributes,
+ LPARAM lpUserDefined
+ )
+{
+ UNREFERENCED_PARAMETER( dwProcessId );
+ UNREFERENCED_PARAMETER( dwAttributes );
+ UNREFERENCED_PARAMETER( lpUserDefined );
+
+ return TRUE;
+}
+
+
+
+BOOL
+IsWOWPresent(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Determines if WOW is running
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if WOW is running, FALSE otherwise
+
+--*/
+
+{
+#if defined(i386) && !defined(WIN32S)
+ return VDMEnumProcessWOW( (PROCESSENUMPROC)EnumCallBack, 0 );
+#else
+ return FALSE;
+#endif
+}
+
+
+
+BOOL
+TranslateAddress(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR lpaddr,
+ BOOL f16ToFlat
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to preform address translations from the segmented
+ to the flat world and back again.
+
+Arguments:
+
+ hprc - Supplies the handle to the current process
+ hthd - Supplies the handle to the thread for the address
+ lpaddr - Supplies the address to be translated
+ f16ToFlat - Supplies the direction the translation is to be made
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+#if defined(i386)
+ LDT_ENTRY ldt;
+ ULONG ul;
+
+#ifdef WIN32S
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ ADDR_IS_REAL(*lpaddr) = FALSE;
+ return TRUE;
+#endif
+
+ /*
+ * Step 0. If the address has already been mapped flat then return
+ */
+
+ if (ADDR_IS_FLAT(*lpaddr)) {
+ return TRUE;
+ }
+
+ /*
+ * Step 1. Is to find a stopped thread. This is mainly for WOW support
+ * where the lack of a stopped thread is a serious thing,
+ * we can not do anything smartly with wow if this is the
+ * case. We will currently only search for a single
+ * stopped thread cause the blasted operating system won't
+ * let us have more than one.
+ */
+
+ if (hthd == 0) {
+ for (hthd = hprc->hthdChild; hthd != hthdxNull; hthd = hthd->next) {
+ if (hthd->tstate & ts_stopped) {
+ break;
+ }
+ }
+
+ if (hthd == 0) {
+ hthd = hprc->hthdChild;
+ }
+ }
+
+ /*
+ * Must have a thread
+ */
+
+ if (hthd == NULL) {
+ return FALSE;
+ }
+
+ /*
+ * Step 2. Depending on if the last event was WOW we need to
+ * either go in with a WOW remap or do the standard
+ * non-wow remap
+ */
+
+ if (hthd->fAddrIsFlat) {
+ if (ADDR_IS_REAL( *lpaddr )) {
+ ul = GetAddrSeg(*lpaddr) * 16 + GetAddrOff(*lpaddr);
+ lpaddr->addr.off = ul;
+ } else if (GetThreadSelectorEntry(hthd->rwHand, GetAddrSeg(*lpaddr),
+ &ldt)) {
+ ul = (ldt.HighWord.Bytes.BaseHi << 24) |
+ (ldt.HighWord.Bytes.BaseMid << 16) |
+ (ldt.BaseLow);
+ lpaddr->addr.off += ul;
+ } else {
+ /*
+ * Unrecognized selector
+ */
+ return FALSE;
+ }
+ } else {
+#if defined(i386) && !defined(WIN32S)
+ lpaddr->addr.off = VDMGetPointer(hprc->rwHand, hthd->rwHand,
+ GetAddrSeg(*lpaddr),
+ GetAddrOff(*lpaddr),
+ !lpaddr->mode.fReal);
+#else // defined(i386) && !defined(WIN32S)
+ assert(FALSE);
+ return FALSE;
+#endif // defined(i386) && !defined(WIN32S)
+ }
+#endif
+ ADDR_IS_FLAT(*lpaddr) = TRUE;
+ ADDR_IS_REAL(*lpaddr) = FALSE;
+ return TRUE;
+} /* TranslateAddress() */
+
+
+BOOL
+WOWGetThreadContext(
+ HTHDX hthdx,
+ LPCONTEXT lpcxt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to g the context of a WOW thread. We have
+ a current assumption that we will only have one WOW event at a time.
+
+Arguments:
+
+ hthdx - supplies the handle to the thread to change the context of
+ lpcxt - supplies the new context.
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+#if defined(i386) && !defined(WIN32S)
+ assert(hthdx->fWowEvent);
+
+ if (hthdx->tid != DeWow.dwThreadId) {
+ assert(FALSE);
+ return FALSE;
+ }
+
+ return VDMGetThreadContext(&DeWow, lpcxt);
+#else
+ return FALSE;
+#endif
+} /* WOWGetThreadContext() */
+
+
+
+BOOL
+WOWSetThreadContext(
+ HTHDX hthdx,
+ LPCONTEXT lpcxt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to set the context of a WOW thread. We have
+ a current assumption that we will only have one WOW event at a time.
+
+Arguments:
+
+ hthdx - supplies the handle to the thread to change the context of
+ lpcxt - supplies the new context.
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+#if defined(i386) && !defined(WIN32S)
+ assert(hthdx->fWowEvent);
+
+ if (hthdx->tid != DeWow.dwThreadId) {
+ assert(FALSE);
+ return FALSE;
+ }
+
+ return VDMSetThreadContext(&DeWow, lpcxt);
+#else
+ return FALSE;
+#endif
+} /* WOWSetThreadContext() */
diff --git a/private/windbg/newdm/util.c b/private/windbg/newdm/util.c
new file mode 100644
index 000000000..8d4af0817
--- /dev/null
+++ b/private/windbg/newdm/util.c
@@ -0,0 +1,658 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ util.c
+
+Abstract:
+
+ This file contains a set of general utility routines for the
+ Debug Monitor module
+
+Author:
+
+ Jim Schaad (jimsch) 9-12-92
+
+Environment:
+
+ Win32 user mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+extern EXPECTED_EVENT masterEE, *eeList;
+
+extern HTHDX thdList;
+extern HPRCX prcList;
+extern CRITICAL_SECTION csThreadProcList;
+
+
+static HPRCX HprcRead;
+static HANDLE HFileRead = 0; // Read File handle
+static LPB LpbMemory = 0; // Read File Address
+static ULONG CbOffset = 0; // Offset of read address
+
+
+
+BOOL
+AddrWriteMemory(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR paddr,
+ LPVOID lpv,
+ DWORD cb,
+ LPDWORD pcbWritten
+ )
+/*++
+
+Routine Description:
+
+ This function is used to do a verified write to memory. Most of the
+ time it will just do a simple call to WriteMemory but some times
+ it will do validations of writes.
+
+Arguments:
+
+ hprc - Supplies the handle to the process
+
+ paddr - Supplies the address to be written at
+
+ lpv - Supplies a pointer to the bytes to be written
+
+ cb - Supplies the count of bytes to be written
+
+ pcbWritten - Returns the number of bytes actually written
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise
+
+--*/
+
+{
+ BOOL fRet;
+ ADDR addr;
+
+ /*
+ * Can't resolve linker indices from here.
+ */
+
+ assert(!(ADDR_IS_LI(*paddr)));
+ if (ADDR_IS_LI(*paddr)) {
+ return FALSE;
+ }
+
+ /*
+ * Make a local copy to mess with
+ */
+
+ addr = *paddr;
+ if (!ADDR_IS_FLAT(addr)) {
+ fRet = TranslateAddress(hprc, hthd, &addr, TRUE);
+ assert(fRet);
+ if (!fRet) {
+ return fRet;
+ }
+ }
+
+ return DbgWriteMemory(hprc, (LPVOID) GetAddrOff(addr),
+ lpv, cb, pcbWritten);
+
+} /* AddrWriteMemory() */
+
+
+BOOL
+AddrReadMemory(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR paddr,
+ LPVOID lpv,
+ DWORD cb,
+ LPDWORD lpRead
+ )
+/*++
+
+Routine Description:
+
+ Read data from a process, using a full ADDR packet.
+
+Arguments:
+
+ hprc - Supplies the process structure
+
+ hthd - Supplies the thread structure. This must be valid if the
+ address is not flat; otherwise the thread is not used.
+
+ paddr - Supplies the address to read from
+
+ lpv - Supplies a pointer to the local buffer
+
+ cb - supplies the count of bytes to read
+
+ lpRead - Returns the number of bytes actually read
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise
+
+--*/
+
+{
+ BOOL fRet;
+ ADDR addr;
+#ifndef KERNEL
+ PBREAKPOINT bp;
+ DWORD offset;
+ BP_UNIT instr;
+#endif
+
+ /*
+ * We can't resolve linker indices from here.
+ */
+
+ assert(!(ADDR_IS_LI(*paddr)));
+ if (ADDR_IS_LI(*paddr)) {
+ return FALSE;
+ }
+
+ /*
+ * Make a local copy to mess with
+ */
+
+ addr = *paddr;
+ if (!ADDR_IS_FLAT(addr)) {
+ fRet = TranslateAddress(hprc, hthd, &addr, TRUE);
+ assert(fRet);
+ if (!fRet) {
+ return fRet;
+ }
+ }
+
+ if (!DbgReadMemory(hprc, (LPVOID) GetAddrOff(addr), lpv, cb, lpRead)) {
+ return FALSE;
+ }
+
+#ifndef KERNEL
+ /* The memory has been read into the buffer now sanitize it : */
+ /* (go through the entire list of breakpoints and see if any */
+ /* are in the range. If a breakpoint is in the range then an */
+ /* offset relative to the start address and the original inst */
+ /* ruction is returned and put into the return buffer) */
+
+ for (bp=bpList->next; bp; bp=bp->next) {
+ if (BPInRange(hprc, hthd, bp, &addr, *lpRead, &offset, &instr)) {
+ if (offset < 0) {
+ memcpy(lpv, ((char *) &instr) - offset,
+ sizeof(BP_UNIT) + offset);
+ } else if (offset + sizeof(BP_UNIT) > *lpRead) {
+ memcpy(((char *)lpv)+offset, &instr, *lpRead - offset);
+ } else {
+ *((BP_UNIT UNALIGNED *)((char *)lpv+offset)) = instr;
+ }
+ }
+ }
+#endif // !KERNEL
+
+ return TRUE;
+} /* AddrReadMemory() */
+
+
+#if 0
+BOOL
+SanitizedMemoryRead(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR paddr,
+ LPVOID lpb,
+ DWORD cb,
+ LPDWORD lpcb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is provided to do the actual read of memory. This allows
+ multiple routines in the DM to do the read through a single common
+ interface. This routine will correct the read memory for any breakpoints
+ currently set in memory.
+
+Arguments:
+
+ hprc - Supplies the process handle for the read
+
+ hthd - Supplies the thread handle for the read
+
+ paddr - Supplies the address to read memory from
+
+ lpb - Supplies the buffer to do the read into
+
+ cb - Supplies the number of bytes to be read
+
+ lpcb - Returns the number of bytes actually read
+
+Return Value:
+
+ TRUE on success and FALSE on failure
+
+--*/
+
+{
+ DWORD offset;
+ BP_UNIT instr;
+ BREAKPOINT *bp;
+
+ if (!AddrReadMemory(hprc, hthd, paddr, lpb, cb, lpcb)) {
+ return FALSE;
+ }
+
+#ifndef KERNEL
+ /* The memory has been read into the buffer now sanitize it : */
+ /* (go through the entire list of breakpoints and see if any */
+ /* are in the range. If a breakpoint is in the range then an */
+ /* offset relative to the start address and the original inst */
+ /* ruction is returned and put into the return buffer) */
+
+ for (bp=bpList->next; bp; bp=bp->next) {
+ if (BPInRange(hprc, hthd, bp, paddr, *lpcb, &offset, &instr)) {
+ if (offset < 0) {
+ memcpy(lpb, ((char *) &instr) - offset,
+ sizeof(BP_UNIT) + offset);
+ } else if (offset + sizeof(BP_UNIT) > *lpcb) {
+ memcpy(((char *)lpb)+offset, &instr, *lpcb - offset);
+ } else {
+ *((BP_UNIT UNALIGNED *)((char *)lpb+offset)) = instr;
+ }
+ }
+ }
+#endif // !KERNEL
+
+ return TRUE;
+}
+
+#endif
+
+
+ULONG
+SetReadPointer(
+ ULONG cbOffset,
+ int iFrom
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to deal with changing the location of where
+ the next read should occur. This will take effect on the current
+ file pointer or debuggee memory pointer address.
+
+Arguments:
+
+ cbOffset - Supplies the offset to set the file pointer at
+
+ iFrom - Supplies the type of set to be preformed.
+
+Return Value:
+
+ The new file offset
+
+--*/
+
+{
+ if (LpbMemory == NULL) {
+ CbOffset = SetFilePointer(HFileRead, cbOffset, NULL, iFrom);
+ } else {
+ switch( iFrom ) {
+ case FILE_BEGIN:
+ CbOffset = cbOffset;
+ break;
+
+ case FILE_CURRENT:
+ CbOffset += cbOffset;
+ break;
+
+ default:
+ assert(FALSE);
+ break;
+ }
+ }
+
+ return CbOffset;
+} /* SetReadPointer() */
+
+
+VOID
+SetPointerToFile(
+ HANDLE hFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to specify which file handle should be used for
+ doing reads from
+
+Arguments:
+
+ hFile - Supplies the file handle to do future reads from
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HFileRead = hFile;
+ HprcRead = NULL;
+ LpbMemory = NULL;
+
+ return;
+} /* SetPointerToFile() */
+
+
+
+VOID
+SetPointerToMemory(
+ HPRCX hprc,
+ LPVOID lpv
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to specify where in debuggee memory reads should
+ be done from.
+
+Arguments:
+
+ hProc - Supplies the handle to the process to read memory from
+
+ lpv - Supplies the base address of the dll to read memory at.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HprcRead = hprc;
+ LpbMemory = lpv;
+ HFileRead = NULL;
+
+ return;
+} /* SetPointerToMemory() */
+
+
+BOOL
+DoRead(
+ LPVOID lpv,
+ DWORD cb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to preform the actual read operation from either
+ a file handle or from the dlls memory.
+
+Arguments:
+
+ lpv - Supplies the pointer to read memory into
+
+ cb - Supplies the count of bytes to be read
+
+Return Value:
+
+ TRUE If read was fully successful and FALSE otherwise
+
+--*/
+
+{
+ DWORD cbRead;
+
+ if (LpbMemory) {
+ if ( !DbgReadMemory( HprcRead, LpbMemory+CbOffset, lpv, cb, &cbRead ) ||
+ (cb != cbRead) ) {
+ return FALSE;
+ }
+ CbOffset += cb;
+ } else if ((ReadFile(HFileRead, lpv, cb, &cbRead, NULL) == 0) ||
+ (cb != cbRead)) {
+ return FALSE;
+ }
+ return TRUE;
+} /* DoRead() */
+
+
+
+BOOL
+AreAddrsEqual(
+ HPRCX hprc,
+ HTHDX hthd,
+ LPADDR paddr1,
+ LPADDR paddr2
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to compare to addresses for equality
+
+Arguments:
+
+ hprc - Supplies process for address context
+
+ hthd - Supplies thread for address context
+
+ paddr1 - Supplies a pointer to an ADDR structure
+
+ paddr2 - Supplies a pointer to an ADDR structure
+
+Return Value:
+
+ TRUE if the addresses are equivalent
+
+--*/
+
+{
+ ADDR addr1;
+ ADDR addr2;
+
+ /*
+ * Step 1. Addresses are equal if
+ * - Both addresses are flat
+ * - The two offsets are the same
+ */
+
+ if ((ADDR_IS_FLAT(*paddr1) == TRUE) &&
+ (ADDR_IS_FLAT(*paddr1) == ADDR_IS_FLAT(*paddr2)) &&
+ (paddr1->addr.off == paddr2->addr.off)) {
+ return TRUE;
+ }
+
+ /*
+ * Step 2. Address are equal if the linear address are the same
+ */
+
+ addr1 = *paddr1;
+ addr2 = *paddr2;
+
+ if (addr1.addr.off == addr2.addr.off) {
+ return TRUE;
+ }
+
+ return FALSE;
+} /* AreAddrsEqual() */
+
+
+
+
+HTHDX
+HTHDXFromPIDTID(
+ PID pid,
+ TID tid
+ )
+{
+ HTHDX hthd;
+
+ EnterCriticalSection(&csThreadProcList);
+ for ( hthd = thdList->next; hthd; hthd = hthd->next ) {
+ if (hthd->tid == tid && hthd->hprc->pid == pid ) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ return hthd;
+}
+
+
+
+HTHDX
+HTHDXFromHPIDHTID(
+ HPID hpid,
+ HTID htid
+ )
+{
+ HTHDX hthd;
+
+ EnterCriticalSection(&csThreadProcList);
+ for(hthd = thdList->next; hthd; hthd = hthd->next) {
+ if (hthd->htid == htid && hthd->hprc->hpid == hpid ) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ return hthd;
+}
+
+
+
+
+HPRCX
+HPRCFromPID(
+ PID pid
+ )
+{
+ HPRCX hprc;
+
+ EnterCriticalSection(&csThreadProcList);
+ for( hprc = prcList->next; hprc; hprc = hprc->next) {
+ if (hprc->pid == pid) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ return hprc;
+}
+
+
+
+HPRCX
+HPRCFromHPID(
+ HPID hpid
+ )
+{
+ HPRCX hprc;
+
+ EnterCriticalSection(&csThreadProcList);
+ for ( hprc = prcList->next; hprc; hprc = hprc->next ) {
+ if (hprc->hpid == hpid) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ return hprc;
+}
+
+
+
+HPRCX
+HPRCFromRwhand(
+ HANDLE rwHand
+ )
+{
+ HPRCX hprc;
+
+ EnterCriticalSection(&csThreadProcList);
+ for ( hprc=prcList->next; hprc; hprc=hprc->next ) {
+ if (hprc->rwHand==rwHand) {
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ return hprc;
+}
+
+
+void
+FreeHthdx(
+ HTHDX hthd
+ )
+{
+ HTHDX * ppht;
+ BREAKPOINT * pbp;
+ BREAKPOINT * pbpT;
+
+ EnterCriticalSection(&csThreadProcList);
+
+ /*
+ * Free all breakpoints unique to thread
+ */
+
+ for (pbp = BPNextHthdPbp(hthd, NULL); pbp; pbp = pbpT) {
+ pbpT = BPNextHthdPbp(hthd, pbp);
+ RemoveBP(pbp);
+ }
+
+
+ for (ppht = &(hthd->hprc->hthdChild); *ppht; ppht = & ( (*ppht)->nextSibling ) ) {
+ if (*ppht == hthd) {
+ *ppht = (*ppht)->nextSibling;
+ break;
+ }
+ }
+
+ for (ppht = &(thdList->next); *ppht; ppht = & ( (*ppht)->next ) ) {
+ if (*ppht == hthd) {
+ *ppht = (*ppht)->next;
+ break;
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+
+ free(hthd);
+}
+
+
+VOID
+ClearContextPointers(
+ PKNONVOLATILE_CONTEXT_POINTERS ctxptrs
+ )
+/*++
+
+ Routine - Clear Context Pointers
+
+ Purpose - clears the context pointer structure.
+
+ Argument - lpvoid - pointer to context pointers structure;
+ void on on architectures that don't have such.
+
+--*/
+
+{
+ memset(ctxptrs, 0, sizeof (KNONVOLATILE_CONTEXT_POINTERS));
+}
+
diff --git a/private/windbg/newdm/walk.c b/private/windbg/newdm/walk.c
new file mode 100644
index 000000000..67d81d99f
--- /dev/null
+++ b/private/windbg/newdm/walk.c
@@ -0,0 +1,2073 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Walk.c
+
+Abstract:
+
+ This module contains the support for "Walking".
+
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 13-August-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+//
+// Externals
+//
+
+extern DMTLFUNCTYPE DmTlFunc;
+extern char abEMReplyBuf[];
+extern DEBUG_EVENT falseBPEvent;
+
+
+extern CRITICAL_SECTION csWalk;
+extern CRITICAL_SECTION csThreadProcList;
+
+typedef struct _WALK_LIST *PWALK_LIST;
+typedef struct _WALK *PWALK;
+
+
+#ifdef HAS_DEBUG_REGS
+
+typedef struct _REG_WALK *PREG_WALK;
+typedef struct _REG_WALK {
+ DWORD Register; // Register No.
+ DWORD ReferenceCount; // Reference count
+ DWORD DataAddr; // Data Address
+ DWORD DataSize; // Data Size
+ HPRCX hprc; // Process handle
+ BOOL InUse; // In use
+ DWORD BpType; // code, read, write, or change
+} REG_WALK;
+
+
+//
+// Initializer defined in dm.h
+//
+DWORD DebugRegDataSizes[] = DEBUG_REG_DATA_SIZES;
+#define NDEBUG_REG_DATA_SIZES (sizeof(DebugRegDataSizes) / sizeof(*DebugRegDataSizes))
+
+#endif
+
+
+//
+// Walk Structure.
+//
+// Contains information to perform a walk on a thread.
+//
+typedef struct _WALK {
+ PWALK Next; // Next in walk list
+ PWALK Previous; // Previous in walk list
+ PWALK_LIST WalkList; // Walk List
+ HTHDX hthd; // thread
+ DWORD GlobalCount; // Global count
+ DWORD LocalCount; // Local count;
+ DWORD AddrStart; // Range Begin
+ DWORD AddrEnd; // Range End
+ DWORD DataAddr; // Data Address
+ DWORD DataSize; // Data Size
+ BOOL Active; // Active flag
+ BOOL HasAddrEnd;
+ BREAKPOINT *SafetyBP; // Safety breakpoint
+ METHOD Method; // Walk method
+#ifdef HAS_DEBUG_REGS
+ PREG_WALK RegWalk; // Register-assisted walk
+ BOOL SingleStep; // In single-step mode
+#endif
+} WALK;
+
+
+//
+// Walk list. There is one of these for each thread that is
+// being walked.
+//
+typedef struct _WALK_LIST {
+ PWALK_LIST Next; // Next in chain
+ PWALK_LIST Previous; // Previous in chain
+ HPRCX hprc; // Process handle
+ HTHDX hthd; // Thread handle
+ PWALK FirstWalk; // First Walk in list
+#ifdef HAS_DEBUG_REGS
+ REG_WALK RegWalk[ NUMBER_OF_DEBUG_REGISTERS ];
+#endif
+} WALK_LIST;
+
+
+
+
+
+//
+// Walk group. This binds together the individual (per-thread) walks
+// associated with a particular SetWalk call.
+//
+typedef struct _WALK_GROUP_ENTRY {
+ LIST_ENTRY GroupList;
+ BOOL Global; // unfortunate kludge
+ PWALK Walk;
+} WALK_GROUP_ENTRY;
+typedef WALK_GROUP_ENTRY *PWALK_GROUP_ENTRY;
+
+
+
+//
+// Local variables
+//
+PWALK_LIST WalkListHead = NULL; // Head of walk list chain
+DWORD AnyGlobalCount = 0; // Global count
+
+
+
+PWALK
+SetWalkThread (
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD Addr,
+ DWORD Size,
+ BOOL Global,
+ DWORD BpType
+ );
+
+BOOL
+RemoveWalkByHandle(
+ PWALK Walk,
+ BOOL Global
+ );
+
+BOOL
+StartWalk(
+ PWALK pWalk,
+ BOOL Continuing
+ );
+
+
+PWALK_LIST
+AllocateWalkList(
+ HPRCX,
+ HTHDX
+ );
+
+BOOL
+DeallocateWalkList(
+ PWALK_LIST
+ );
+
+PWALK_LIST
+FindWalkList (
+ HPRCX,
+ HTHDX
+ );
+
+PWALK
+AllocateWalk(
+ PWALK_LIST,
+ DWORD,
+ DWORD
+ );
+
+BOOL
+DeallocateWalk(
+ PWALK
+ );
+
+PWALK
+FindWalk (
+ PWALK_LIST,
+ DWORD,
+ DWORD
+ );
+
+PWALK
+FindWalkInGroup(
+ HANDLE hWalk,
+ HTHDX hthd
+ );
+
+int
+MethodWalk(
+ DEBUG_EVENT*,
+ HTHDX,
+ DWORD,
+ PWALK
+ );
+
+#if 0
+int
+MethodDebugReg(
+ DEBUG_EVENT*,
+ HTHDX,
+ DWORD,
+ PWALK
+ );
+#endif
+
+DWORD
+CanStep (
+ HPRCX,
+ HTHDX,
+ DWORD
+ );
+
+DWORD
+GetEndOfRange (
+ HPRCX,
+ HTHDX,
+ DWORD
+ );
+
+
+
+
+
+//*******************************************************************
+//
+// Exported Functions
+//
+//******************************************************************
+
+
+
+VOID
+ExprBPCreateThread(
+ HPRCX hprc,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ If global walking, adds walk to new thread. Called when a
+ new thread is created.
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+Return Value:
+
+ None
+--*/
+
+{
+ PWALK Walk;
+ PWALK_LIST WalkList;
+ //
+ // If there are global walks, set them in this thread
+ //
+ if ( AnyGlobalCount > 0 ) {
+
+ EnterCriticalSection(&csWalk);
+
+ assert( WalkListHead && WalkListHead->FirstWalk );
+
+ //
+ // Get any walk list for this process and traverse it,
+ // setting all global walks in this thread. Note that we
+ // can use any walk list because global walks are common
+ // to all lists.
+ //
+
+ WalkList = FindWalkList(hprc, NULL);
+
+ if (WalkList) {
+ for (Walk = WalkList->FirstWalk; Walk; Walk = Walk->Next) {
+
+ if ( Walk->GlobalCount > 0 ) {
+ SetWalkThread( hprc,
+ hthd,
+ Walk->DataAddr,
+ Walk->DataSize,
+ TRUE,
+#ifdef HAS_DEBUG_REGS
+ Walk->RegWalk ?
+ Walk->RegWalk->BpType :
+#endif
+ bptpExec
+ );
+ }
+ }
+ }
+
+ LeaveCriticalSection(&csWalk);
+ }
+}
+
+
+VOID
+ExprBPExitThread (
+ HPRCX hprc,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Removes walk in a thread, called when the thread is gone.
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ BOOL Ok = TRUE;
+ PWALK_LIST WalkList;
+ PWALK Walk;
+ PWALK NextWalk;
+ DWORD GlobalCount;
+ DWORD LocalCount;
+
+ EnterCriticalSection(&csWalk);
+
+ if ( WalkList = FindWalkList( hprc, hthd ) ) {
+
+ Walk = WalkList->FirstWalk;
+
+ while ( Walk ) {
+
+ NextWalk = Walk->Next;
+ GlobalCount = Walk->GlobalCount;
+ LocalCount = Walk->LocalCount;
+ while ( GlobalCount-- ) {
+ RemoveWalkByHandle( Walk, TRUE );
+ }
+ while ( LocalCount-- ) {
+ RemoveWalkByHandle( Walk, FALSE );
+ }
+ Walk = NextWalk;
+ }
+ }
+
+ LeaveCriticalSection(&csWalk);
+}
+
+
+VOID
+ExprBPContinue (
+ HPRCX hprc,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Continues walking. Called as a result of a continue command.
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PWALK_LIST WalkList;
+ PWALK Walk;
+
+ /*
+ * NOTENOTE ramonsa - we don't yet support continue on all threads
+ */
+
+ if ( !hthd ) {
+ return;
+ }
+
+ assert(hthd->tstate & ts_stopped);
+
+ /*
+ * See if we have a walk on the thread
+ */
+
+ EnterCriticalSection(&csWalk);
+
+ if ( WalkList = FindWalkList( hprc, hthd ) ) {
+ for (Walk = WalkList->FirstWalk; Walk != NULL; Walk = Walk->Next ) {
+#ifdef HAS_DEBUG_REGS
+ if ( Walk->RegWalk && !Walk->SingleStep ) {
+
+ StartWalk( Walk, TRUE );
+
+ } else
+#endif
+ if ( !Walk->Active ) {
+ /*
+ * Get the current address for the thread.
+ */
+ Walk->AddrStart = (DWORD)PC( hthd );
+
+ /*
+ * Get the end of the range
+ */
+
+ Walk->AddrEnd = Walk->AddrStart;
+ Walk->HasAddrEnd = FALSE;
+
+ /*
+ * Start walking
+ */
+
+ StartWalk( Walk, TRUE );
+
+ }
+
+
+ }
+ }
+ LeaveCriticalSection(&csWalk);
+} /* ExprBPContinue() */
+
+
+VOID
+ExprBPResetBP(
+ HTHDX hthd,
+ BREAKPOINT *bp
+ )
+/*++
+
+Routine Description:
+
+ After stepping off of a hardware BP, reset debug register(s)
+ before continuing.
+
+Arguments:
+
+ hthd - Supplies the thread which has been stepped.
+
+Return Value:
+
+ none
+
+--*/
+{
+#ifndef HAS_DEBUG_REGS
+ Unreferenced(hthd);
+#else
+ PWALK pWalk;
+
+ assert(bp);
+
+ assert(bp->hWalk);
+
+ pWalk = FindWalkInGroup(bp->hWalk, hthd);
+
+ assert(pWalk->RegWalk && pWalk->RegWalk->InUse);
+
+ SetupDebugRegister(
+ hthd,
+ pWalk->RegWalk->Register,
+ pWalk->RegWalk->DataSize,
+ pWalk->RegWalk->DataAddr,
+ pWalk->RegWalk->BpType
+ );
+
+#endif // HAS_DEBUG_REGS
+}
+
+
+
+VOID
+ExprBPClearBPForStep(
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Turn off a hardware breakpoint to allow a single step to occur.
+
+Arguments:
+
+ hthd - Supplies the thread which is going to be stepped.
+
+Return Value:
+
+ none
+
+--*/
+{
+#ifndef HAS_DEBUG_REGS
+ Unreferenced(hthd);
+#else
+ BREAKPOINT *bp;
+ PWALK pWalk;
+
+ bp = AtBP(hthd);
+ assert(bp);
+
+ assert(bp->hWalk);
+
+ pWalk = FindWalkInGroup(bp->hWalk, hthd);
+
+ assert(pWalk && pWalk->RegWalk && pWalk->RegWalk->InUse);
+
+ ClearDebugRegister(hthd, pWalk->RegWalk->Register);
+#endif
+}
+
+
+void
+ExprBPRestoreDebugRegs(
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Restore the CPU debug registers to the state that we last put
+ them in. This routine is needed because the system trashes
+ the debug registers after initializing the DLLs and before the
+ app entry point is executed.
+
+Arguments:
+
+ hthd - Supplies descriptor for thread whose registers need fixing.
+
+Return Value:
+
+ None
+
+--*/
+{
+#ifndef HAS_DEBUG_REGS
+ Unreferenced(hthd);
+#else
+ PWALK_LIST WalkList;
+ PWALK Walk;
+
+ if ( WalkList = FindWalkList(hthd->hprc, hthd) ) {
+
+ EnterCriticalSection(&csWalk);
+
+ for (Walk = WalkList->FirstWalk; Walk; Walk = Walk->Next) {
+
+ if ( Walk->Active && Walk->RegWalk && Walk->RegWalk->InUse) {
+
+ SetupDebugRegister(
+ Walk->WalkList->hthd,
+ Walk->RegWalk->Register,
+ Walk->RegWalk->DataSize,
+ Walk->RegWalk->DataAddr,
+ Walk->RegWalk->BpType
+ );
+
+ }
+ }
+
+ LeaveCriticalSection(&csWalk);
+ }
+#endif
+}
+
+
+
+
+//*******************************************************************
+//
+// Local Functions
+//
+//******************************************************************
+
+HANDLE
+SetWalk (
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD Addr,
+ DWORD Size,
+ DWORD BpType
+ )
+/*++
+
+Routine Description:
+
+ Sets up a walk. Returns a handle which may be used to associate this
+ walk with a breakpoint structure.
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+ Addr - Supplies address
+
+ Size - Supplies size of memory to watch
+
+ BpType - Supplies type of breakpoint
+
+Return Value:
+
+ BOOL - TRUE if Walk set
+
+--*/
+
+{
+ BOOL Ok = FALSE;
+ PWALK Walk;
+ PLIST_ENTRY GroupList = NULL;
+ PWALK_GROUP_ENTRY GroupEntry;
+
+ if ( hprc ) {
+
+ //
+ // If a thread is specified, we use that specific thread,
+ // otherwise we must set the walk in all existing threads,
+ // plus we must set things up so that we walk all future
+ // threads too (while this walk is active).
+ //
+ if ( hthd ) {
+
+ Walk = SetWalkThread( hprc, hthd, Addr, Size, FALSE, BpType );
+ if (Walk) {
+ GroupList = malloc(sizeof(LIST_ENTRY));
+ InitializeListHead(GroupList);
+ GroupEntry = malloc(sizeof(WALK_GROUP_ENTRY));
+ GroupEntry->Walk = Walk;
+ GroupEntry->Global = FALSE;
+ InsertTailList(GroupList, &GroupEntry->GroupList);
+ }
+
+ } else {
+
+ Ok = TRUE;
+ AnyGlobalCount++;
+ EnterCriticalSection(&csThreadProcList);
+ GroupList = malloc(sizeof(LIST_ENTRY));
+ InitializeListHead(GroupList);
+ for ( hthd = (HTHDX)hprc->hthdChild;
+ hthd;
+ hthd = hthd->nextSibling ) {
+
+ Walk = SetWalkThread( hprc, hthd, Addr, Size, TRUE, BpType );
+ if (Walk) {
+ GroupEntry = malloc(sizeof(WALK_GROUP_ENTRY));
+ GroupEntry->Walk = Walk;
+ GroupEntry->Global = TRUE;
+ InsertTailList(GroupList, &GroupEntry->GroupList);
+ }
+ }
+ LeaveCriticalSection(&csThreadProcList);
+ }
+ }
+
+ return (HANDLE)GroupList;
+}
+
+
+
+BOOL
+RemoveWalk (
+ HANDLE hWalk
+ )
+/*++
+
+Routine Description:
+
+ Removes a walk.
+
+Arguments:
+
+ hWalk - Supplies a walk group list
+
+Return Value:
+
+ BOOL - TRUE if Walk removed
+
+--*/
+
+{
+ PLIST_ENTRY GroupList = (PLIST_ENTRY)hWalk;
+ PLIST_ENTRY ListItem;
+ PWALK_GROUP_ENTRY WalkGroupEntry;
+ BOOL IsGlobal = FALSE;
+
+ if (!GroupList) {
+ return FALSE;
+ }
+
+ ListItem = GroupList->Flink;
+ while (ListItem != GroupList) {
+ WalkGroupEntry = CONTAINING_RECORD(ListItem, WALK_GROUP_ENTRY, GroupList);
+ ListItem = ListItem->Flink;
+ IsGlobal = IsGlobal || WalkGroupEntry->Global;
+ RemoveWalkByHandle(WalkGroupEntry->Walk, WalkGroupEntry->Global);
+ free(WalkGroupEntry);
+ }
+ free(GroupList);
+ if (IsGlobal) {
+ AnyGlobalCount--;
+ }
+ return TRUE;
+}
+
+
+
+PWALK
+SetWalkThread (
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD Addr,
+ DWORD Size,
+ BOOL Global,
+ DWORD BpType
+ )
+/*++
+
+Routine Description:
+
+ Sets up a walk in a specific thread
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+ Addr - Supplies address
+
+ Size - Supplies Size
+
+ Global - Supplies global flag
+
+ BpType - Supplies type (read, read/write, change)
+
+Return Value:
+
+ BOOL - TRUE if Walk set
+
+--*/
+
+{
+ PWALK_LIST WalkList;
+ PWALK Walk;
+ BOOL AllocatedList = FALSE;
+ BOOL AllocatedWalk = FALSE;
+ BOOL Ok = FALSE;
+ BOOL Froze = FALSE;
+
+ // BUGBUG kentf doesn't find the right BpType here
+ if ( (WalkList = FindWalkList( hprc, hthd )) &&
+ (Walk = FindWalk( WalkList, Addr, Size )) ) {
+
+ //
+ // If the walk is already active, just increment the
+ // reference count and we're done.
+ //
+ if ( Walk->Active ) {
+ Global ? Walk->GlobalCount++ : Walk->LocalCount++;
+ Ok = TRUE;
+ goto Done;
+ }
+
+ } else {
+
+ //
+ // Allocate a walk for this thread.
+ //
+ if ( !(WalkList = FindWalkList( hprc, hthd )) ) {
+ if ( WalkList = AllocateWalkList( hprc, hthd ) ) {
+ AllocatedList = TRUE;
+ } else {
+ goto Done;
+ }
+ }
+
+ if ( Walk = AllocateWalk( WalkList, Addr, Size ) ) {
+ AllocatedWalk = TRUE;
+ } else {
+ goto Done;
+ }
+ }
+ //
+ // We have to freeze the specified thread in order to get
+ // the current address.
+ //
+ if ( !(hthd->tstate & ts_running) || (hthd->tstate & ts_frozen)) {
+ Ok = TRUE;
+ } else if ( SuspendThread( hthd->rwHand ) != -1L) {
+ Froze = TRUE;
+ Ok = TRUE;
+ }
+
+ if ( Ok ) {
+
+ //
+ // Increment reference count
+ //
+ Global ? Walk->GlobalCount++ : Walk->LocalCount++;
+
+ //
+ // Get the current address for the thread.
+ //
+
+#ifdef KERNEL
+ if (hthd) {
+ Walk->AddrStart = (DWORD)PC( hthd );
+ } else {
+ Walk->AddrStart = 0x80000000;
+ }
+#else
+ if (!hthd->tstate & ts_stopped) {
+ hthd->context.ContextFlags = CONTEXT_CONTROL;
+ DbgGetThreadContext( hthd, &hthd->context );
+ }
+ Walk->AddrStart = (DWORD)PC( hthd );
+#endif
+
+ //
+ // Get the end of the range
+ //
+ Walk->AddrEnd = Walk->AddrStart;
+ Walk->HasAddrEnd = FALSE;
+#ifdef HAS_DEBUG_REGS
+ if (Walk->RegWalk) {
+ Walk->RegWalk->BpType = BpType;
+ }
+#endif
+
+ Ok = StartWalk( Walk, FALSE );
+
+#ifndef KERNEL
+ //
+ // Resume the thread if we froze it.
+ //
+ if ( Froze ) {
+ if (!ResumeThread(hthd->rwHand)) {
+ assert(!"ResumeThread failed in SetWalkThread");
+ hthd->tstate |= ts_frozen;
+ }
+ }
+#endif
+ }
+
+Done:
+ //
+ // Clean up
+ //
+ if ( !Ok ) {
+ if ( Walk && AllocatedWalk ) {
+ DeallocateWalk( Walk );
+ }
+ if ( WalkList && AllocatedList ) {
+ DeallocateWalkList( WalkList );
+ }
+ }
+
+ return Ok?Walk:NULL;
+}
+
+
+
+
+BOOL
+RemoveWalkByHandle(
+ PWALK Walk,
+ BOOL Global
+ )
+/*++
+
+Routine Description:
+
+ Removes a walk structure. Walk is dereferenced; when refcount is 0,
+ structure is deleted.
+
+Arguments:
+
+ Walk - supplies walk struct
+
+ Global - supplies global flag
+
+Return Value:
+
+ BOOL - TRUE if Walk removed
+
+--*/
+
+{
+
+ BOOL Froze = FALSE;
+ HTHDX hthd = Walk->hthd;
+
+#ifndef KERNEL
+ //
+ // freeze the thread
+ //
+ if (hthd->tstate & ts_running) {
+ if (SuspendThread( hthd->rwHand ) != -1L) {
+ return FALSE;
+ }
+ hthd->tstate |= ts_frozen;
+ Froze = TRUE;
+ }
+
+#endif
+ //
+ // Remove the walk
+ //
+ Global ? Walk->GlobalCount-- : Walk->LocalCount--;
+
+ if ( Walk->GlobalCount == 0 &&
+ Walk->LocalCount == 0 ) {
+
+#ifdef HAS_DEBUG_REGS
+ if ( Walk->RegWalk ) {
+ Walk->Active = FALSE;
+ DeallocateWalk( Walk );
+
+ } else
+#endif
+ {
+ //
+ // The Walk has to go away. The walk is deallocated
+ // by the method when it sees that the reference
+ // counts are zero.
+ // If the walk is active, the method will eventually
+ // be called. Otherwise we must call the method
+ // ourselves.
+ //
+ if ( !Walk->Active ) {
+ MethodWalk( NULL, hthd, 0, Walk );
+ }
+ }
+
+#ifndef KERNEL
+ //
+ // Resume the thread if we froze it.
+ //
+ if ( Froze ) {
+ if (ResumeThread(hthd->rwHand) != -1L ) {
+ hthd->tstate &= ~ts_frozen;
+ }
+ }
+#endif
+
+ }
+
+ return TRUE;
+}
+
+
+
+
+BOOL
+StartWalk(
+ PWALK Walk,
+ BOOL Continuing
+ )
+/*++
+
+Routine Description:
+
+ Starts walking.
+
+Arguments:
+
+ Walk - Supplies the walk sructure
+
+ Continuing - Supplies a flag saying that the thread is being continued
+
+Return Value:
+
+ BOOL - TRUE if done
+
+--*/
+
+{
+ BREAKPOINT* bp;
+ ACVECTOR action = NO_ACTION;
+ HTHDX hthd = Walk->WalkList->hthd;
+
+#ifdef HAS_DEBUG_REGS
+
+ if ( Walk->RegWalk ) {
+
+ if ( !Walk->RegWalk->InUse ) {
+
+ if (!SetupDebugRegister(
+ hthd,
+ Walk->RegWalk->Register,
+ Walk->RegWalk->DataSize,
+ Walk->RegWalk->DataAddr,
+ Walk->RegWalk->BpType)
+ ) {
+ return FALSE;
+ }
+
+ Walk->Active = TRUE;
+ Walk->SingleStep = FALSE;
+ Walk->RegWalk->InUse = TRUE;
+
+#if 0
+ if (!(hthd->tstate & ts_stopped) || Continuing) {
+
+ //
+ // Place a single step on our list of expected events.
+ //
+
+ Walk->Method.notifyFunction = MethodDebugReg;
+ RegisterExpectedEvent(
+ hthd->hprc,
+ hthd,
+
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)Walk,
+
+ // EXCEPTION_DEBUG_EVENT,
+ // (DWORD)STATUS_SINGLE_STEP,
+
+ &(Walk->Method),
+ NO_ACTION,
+ FALSE,
+ NULL);
+ }
+#endif
+ }
+
+ } else
+#endif // HAS_DEBUG_REGS
+ {
+ bp = AtBP( hthd );
+
+ if ( !bp &&
+ (!(hthd->tstate & ts_stopped) || Continuing)) {
+
+ //
+ // Setup a single step
+ //
+ if (!SetupSingleStep(hthd, FALSE )) {
+ return FALSE;
+ }
+
+ Walk->Active = TRUE;
+
+ //
+ // Place a single step on our list of expected events.
+ //
+ RegisterExpectedEvent(
+ hthd->hprc,
+ hthd,
+ EXCEPTION_DEBUG_EVENT,
+ (DWORD)EXCEPTION_SINGLE_STEP,
+ &(Walk->Method),
+ action,
+ FALSE,
+ NULL);
+ }
+ }
+
+ return TRUE;
+} /* StartWalk() */
+
+
+
+//*******************************************************************
+//
+// WALK_LIST Stuff
+//
+//******************************************************************
+
+
+PWALK_LIST
+AllocateWalkList (
+ HPRCX hprc,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Allocates new walk list
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+Return Value:
+
+ PWALK_LIST - Allocated Walk list
+
+--*/
+
+{
+
+ PWALK_LIST WalkList;
+#ifdef HAS_DEBUG_REGS
+ DWORD i;
+#endif
+
+ if ( WalkList = (PWALK_LIST)malloc( sizeof( WALK_LIST ) ) ) {
+
+ EnterCriticalSection(&csWalk);
+
+ WalkList->hprc = hprc;
+ WalkList->hthd = hthd;
+ WalkList->FirstWalk = NULL;
+ WalkList->Next = WalkListHead;
+ WalkList->Previous = NULL;
+
+#ifdef HAS_DEBUG_REGS
+ for ( i=0; i<NUMBER_OF_DEBUG_REGISTERS; i++ ) {
+ WalkList->RegWalk[i].ReferenceCount = 0;
+ }
+#endif
+
+ if ( WalkListHead ) {
+ WalkListHead->Previous = WalkList;
+ }
+
+ WalkListHead = WalkList;
+
+ LeaveCriticalSection(&csWalk);
+ }
+
+ return WalkList;
+
+}
+
+
+
+
+BOOL
+DeallocateWalkList (
+ PWALK_LIST WalkList
+ )
+/*++
+
+Routine Description:
+
+ Deallocates walk list
+
+Arguments:
+
+ WalkList - Supplies Walk List
+
+Return Value:
+
+ BOOL - TRUE if deallocated
+
+--*/
+
+{
+
+ BOOL Ok = TRUE;
+
+ EnterCriticalSection(&csWalk);
+
+ while ( Ok && WalkList->FirstWalk ) {
+ Ok = DeallocateWalk( WalkList->FirstWalk );
+ }
+
+ if ( Ok ) {
+ if ( WalkList->Previous ) {
+ (WalkList->Previous)->Next = WalkList->Next;
+ }
+
+ if ( WalkList->Next ) {
+ (WalkList->Next)->Previous = WalkList->Previous;
+ }
+
+ if ( WalkListHead == WalkList ) {
+ WalkListHead = WalkList->Next;
+ }
+
+ free( WalkList );
+ }
+
+ LeaveCriticalSection(&csWalk);
+
+ return Ok;
+}
+
+
+
+
+PWALK_LIST
+FindWalkList (
+ HPRCX hprc,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+ Finds a walk list
+
+Arguments:
+
+ hprc - Supplies process
+ hthd - Supplies thread
+
+Return Value:
+
+ PWALK_LIST - Found Walk list
+
+--*/
+
+{
+ PWALK_LIST WalkList;
+
+ EnterCriticalSection(&csWalk);
+
+ WalkList = WalkListHead;
+
+ while ( WalkList ) {
+ if ( WalkList->hprc == hprc &&
+ (hthd == NULL || WalkList->hthd == hthd) ) {
+
+ break;
+ }
+
+ WalkList = WalkList->Next;
+ }
+
+ LeaveCriticalSection(&csWalk);
+
+ return WalkList;
+}
+
+
+
+
+
+PWALK
+AllocateWalk (
+ PWALK_LIST WalkList,
+ DWORD Addr,
+ DWORD Size
+ )
+/*++
+
+Routine Description:
+
+ Allocates new Walk structure and adds it to the list
+
+Arguments:
+
+ WalkList - Supplies Walk List
+
+ Addr - Supplies address
+
+ Size - Supplies Size
+
+
+Return Value:
+
+ PWALK - Walk created
+
+--*/
+{
+ PWALK Walk;
+ DWORD i;
+
+ EnterCriticalSection(&csWalk);
+
+ if ( Walk = (PWALK)malloc( sizeof( WALK ) ) ) {
+
+ Walk->WalkList = WalkList;
+ Walk->hthd = WalkList->hthd;
+ Walk->GlobalCount = 0;
+ Walk->LocalCount = 0;
+ Walk->Active = FALSE;
+ Walk->SafetyBP = NULL;
+ Walk->DataAddr = 0;
+ Walk->DataSize = 0;
+ Walk->HasAddrEnd = FALSE;
+
+
+ Walk->Method.notifyFunction = (ACVECTOR)MethodWalk;
+ Walk->Method.lparam = Walk;
+
+ Walk->Next = WalkList->FirstWalk;
+ Walk->Previous = NULL;
+
+ if ( WalkList->FirstWalk ) {
+ WalkList->FirstWalk->Previous = Walk;
+ }
+
+ WalkList->FirstWalk = Walk;
+
+
+#ifdef HAS_DEBUG_REGS
+
+ //
+ // If we can use (or re-use) a REG_WALK structure, do so.
+ //
+ if ( Addr == 0) {
+
+ Walk->RegWalk = NULL;
+
+ } else {
+
+ for (i = 0; i < NDEBUG_REG_DATA_SIZES; i++) {
+ if (Size == DebugRegDataSizes[i]) {
+ break;
+ }
+ }
+
+ if (i == NDEBUG_REG_DATA_SIZES) {
+
+ Walk->RegWalk = NULL;
+
+ } else {
+
+ PREG_WALK TmpRegWalk = NULL;
+
+ for ( i=0; i < NUMBER_OF_DEBUG_REGISTERS; i++ ) {
+ if ( WalkList->RegWalk[i].ReferenceCount == 0 ) {
+ TmpRegWalk = &(WalkList->RegWalk[i]);
+ TmpRegWalk->Register = i;
+ TmpRegWalk->InUse = FALSE;
+ } else if ( (WalkList->RegWalk[i].hprc == WalkList->hprc) &&
+ (WalkList->RegWalk[i].DataAddr == Addr) &&
+ (WalkList->RegWalk[i].DataSize >= Size) ) {
+ TmpRegWalk = &(WalkList->RegWalk[i]);
+ break;
+ }
+ }
+
+ if ( Walk->RegWalk = TmpRegWalk ) {
+
+ if ( TmpRegWalk->ReferenceCount == 0 ) {
+
+ TmpRegWalk->hprc = WalkList->hprc;
+ Walk->RegWalk->DataAddr = Addr;
+ Walk->RegWalk->DataSize = Size;
+ Walk->RegWalk->InUse = FALSE;
+ }
+
+ TmpRegWalk->ReferenceCount++;
+
+ Walk->DataAddr = Addr;
+ Walk->DataSize = Size;
+
+ }
+
+ }
+ }
+#endif
+
+ }
+
+ LeaveCriticalSection(&csWalk);
+
+ return Walk;
+}
+
+
+
+
+BOOL
+DeallocateWalk (
+ PWALK Walk
+ )
+/*++
+
+Routine Description:
+
+ Takes a walk out of the list and frees its memory.
+
+Arguments:
+
+ Walk - Supplies Walk to deallocate
+
+Return Value:
+
+
+ BOOLEAN - TRUE if deallocated
+
+--*/
+{
+ BOOLEAN Ok = TRUE;
+ PWALK_LIST WalkList;
+
+ EnterCriticalSection(&csWalk);
+
+ WalkList = Walk->WalkList;
+
+ if ( Walk->Previous ) {
+ (Walk->Previous)->Next = Walk->Next;
+ }
+
+ if ( Walk->Next ) {
+ (Walk->Next)->Previous = Walk->Previous;
+ }
+
+ if ( WalkList->FirstWalk == Walk ) {
+ WalkList->FirstWalk = Walk->Next;
+ }
+
+
+#ifdef HAS_DEBUG_REGS
+ if ( Walk->RegWalk ) {
+ Walk->RegWalk->ReferenceCount--;
+ if ( Walk->RegWalk->ReferenceCount == 0 ) {
+
+ Walk->RegWalk->InUse = FALSE;
+ ClearDebugRegister(Walk->WalkList->hthd, Walk->RegWalk->Register);
+
+ }
+ }
+#endif
+
+ free( Walk );
+
+ if ( !WalkList->FirstWalk ) {
+ DeallocateWalkList( WalkList );
+ }
+
+ LeaveCriticalSection(&csWalk);
+
+
+ return Ok;
+}
+
+
+
+
+PWALK
+FindWalk (
+ PWALK_LIST WalkList,
+ DWORD Addr,
+ DWORD Size
+ )
+/*++
+
+Routine Description:
+
+ Finds a walk
+
+Arguments:
+
+ WalkList - Supplies walk list
+
+ Addr - Supplies Address
+
+ Size - Supplies Size
+
+Return Value:
+
+ PWALK - Found Walk
+
+--*/
+
+{
+ PWALK Walk;
+ PWALK FoundWalk = NULL;
+
+ EnterCriticalSection(&csWalk);
+
+ Walk = WalkList->FirstWalk;
+ while ( Walk ) {
+
+ if ( (Walk->DataAddr == 0) || (Walk->DataAddr == Addr) ) {
+
+#ifdef HAS_DEBUG_REGS
+ if ( !Walk->RegWalk ) {
+
+ FoundWalk = Walk;
+
+ } else if ( Size <= Walk->RegWalk->DataSize )
+#endif
+ {
+
+ FoundWalk = Walk;
+ break;
+ }
+
+ }
+
+ Walk = Walk->Next;
+ }
+
+ LeaveCriticalSection(&csWalk);
+
+ return FoundWalk;
+}
+
+
+PWALK
+FindWalkInGroup(
+ HANDLE hWalk,
+ HTHDX hthd
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PLIST_ENTRY GroupList = (PLIST_ENTRY)hWalk;
+ PLIST_ENTRY ListItem;
+ PWALK_GROUP_ENTRY WalkGroupEntry;
+
+ ListItem = GroupList->Flink;
+ while (ListItem != GroupList) {
+ WalkGroupEntry = CONTAINING_RECORD(ListItem, WALK_GROUP_ENTRY, GroupList);
+ if (WalkGroupEntry->Walk->hthd == hthd) {
+ return WalkGroupEntry->Walk;
+ }
+ ListItem = ListItem->Flink;
+ }
+ return FALSE;
+
+
+}
+
+
+
+
+//*******************************************************************
+//
+// WALK Stuff
+//
+//******************************************************************
+
+CheckBpt(
+ HTHDX hthd,
+ BREAKPOINT *pbp
+ )
+{
+ DEBUG_EVENT de;
+
+ de.dwDebugEventCode = CHECK_BREAKPOINT_DEBUG_EVENT;
+ de.dwProcessId = hthd->hprc->pid;
+ de.dwThreadId = hthd->tid;
+ de.u.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
+
+ NotifyEM(&de, hthd, 0, pbp);
+
+ return *(DWORD *)abEMReplyBuf;
+}
+
+
+MethodWalk(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD unused,
+ PWALK Walk
+ )
+/*++
+
+Routine Description:
+
+ Walk method.
+
+Arguments:
+
+ de - Supplies debug event
+
+ hthd - Supplies thread
+
+ Walk - Supplies Walk
+
+Return Value:
+
+ Nothing meaningful.
+
+--*/
+{
+ LPCONTEXT lpContext = &hthd->context;
+ DWORD eip = (DWORD)cPC(lpContext);
+ ADDR currAddr;
+ int lpf = 0;
+ HPRCX hprc = hthd->hprc;
+ HANDLE rwHand = hprc->rwHand;
+ METHOD *method;
+ BOOL WalkGone;
+ BOOL Active;
+
+ Unreferenced( de );
+
+ AddrFromHthdx(&currAddr, hthd);
+
+ WalkGone = ( Walk->GlobalCount == 0 &&
+ Walk->LocalCount == 0 );
+
+ if ( WalkGone ) {
+ if (Walk->SafetyBP) {
+ RemoveBP( Walk->SafetyBP );
+ Walk->SafetyBP = NULL;
+ }
+
+ } else {
+
+ if ( !Walk->HasAddrEnd ) {
+
+ Walk->AddrEnd = GetEndOfRange( hprc, hthd, Walk->AddrStart );
+ Walk->HasAddrEnd = TRUE;
+ }
+
+ //
+ // See if we are in unknown territory
+ //
+ if (Walk->SafetyBP) {
+
+ //
+ // The safety BP was ON, indicating we don't know if
+ // source is available for this range. Must check
+ // now if the source exists.
+ //
+ switch ( CanStep( hprc, hthd, eip ) ) {
+
+ case CANSTEP_THUNK:
+ StepOver(hthd, &(Walk->Method), TRUE, FALSE);
+ return TRUE;
+
+ case CANSTEP_NO:
+ {
+
+ //
+ // No source.
+ //
+ method = (METHOD*)malloc(sizeof(METHOD));
+
+ //
+ // We are not allowed to step into here. We
+ // must now continue to our safety breakpoint.
+ //
+ *method = Walk->Method;
+ method->lparam2 = (LPVOID)Walk->SafetyBP;
+ RegisterExpectedEvent(
+ hthd->hprc,
+ hthd,
+ BREAKPOINT_DEBUG_EVENT,
+ (DWORD)Walk->SafetyBP,
+ DONT_NOTIFY,
+ (ACVECTOR)SSActionRemoveBP,
+ FALSE,
+ method
+ );
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ return TRUE;
+ }
+ break;
+
+ case CANSTEP_YES:
+ //
+ // We are allowed to step in here, so remove
+ // our safety BP and fall through.
+ //
+ RemoveBP( Walk->SafetyBP );
+ Walk->SafetyBP = NULL;
+ break;
+ }
+ }
+
+
+ //
+ // Check if we are still within the range.
+ //
+ if ( !WalkGone && eip >= Walk->AddrStart && eip <= Walk->AddrEnd ) {
+
+ //
+ // We still are in the range, continue stepping.
+ //
+ if ( Walk->AddrEnd ) {
+
+ //
+ // If we are doing a "Step Into" must check for "CALL"
+ //
+ IsCall(hthd, &currAddr, &lpf, FALSE);
+
+ if (lpf == INSTR_IS_CALL) {
+
+ //
+ // Before we step into this function, let's
+ // put a "safety-net" breakpoint on the instruction
+ // after this call. This way if we don't have
+ // source for this function, we can always continue
+ // and break at this safety-net breakpoint.
+ //
+ Walk->SafetyBP = SetBP(hprc, hthd, bptpExec, bpnsStop, &currAddr,(HPID)INVALID);
+ }
+
+ SingleStep(hthd, &(Walk->Method), TRUE, FALSE);
+
+ } else {
+
+ StepOver(hthd, &(Walk->Method), TRUE, FALSE);
+ }
+
+ return TRUE;
+ }
+ }
+
+ //
+ // We are no longer in the range, free all consummable
+ // events on the queue for this thread
+ //
+ // why?? --KENTF
+ //
+ //ConsumeAllThreadEvents(hthd, FALSE);
+
+
+ if ( WalkGone ) {
+
+ Active = Walk->Active;
+ DeallocateWalk( Walk );
+ if ( Active ) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ }
+
+ } else {
+
+ Walk->Active = FALSE;
+#ifdef HAS_DEBUG_REGS
+// BUGBUG kentf should this be ifndef NO_TRACE_FLAG?
+ Walk->SingleStep = FALSE;
+#endif
+
+ Walk->HasAddrEnd = FALSE;
+ Walk->AddrStart = eip;
+ Walk->AddrEnd = eip;
+
+ //
+ // ask the EM if this thread should remain stopped
+ //
+ if (CheckBpt(hthd, FindBpForWalk(Walk))) {
+ ConsumeAllThreadEvents(hthd, FALSE);
+ } else {
+ //
+ // Have the Expression BP manager know that we are continuing
+ //
+ ExprBPContinue( hprc, hthd );
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+IsWalkInGroup(
+ HANDLE hWalk,
+ PVOID pWalk
+ )
+{
+ PLIST_ENTRY GroupList = (PLIST_ENTRY)hWalk;
+ PLIST_ENTRY ListItem;
+ PWALK Walk = (PWALK)pWalk;
+ PWALK_GROUP_ENTRY WalkGroupEntry;
+
+ if (GroupList) {
+ ListItem = GroupList->Flink;
+ while (ListItem != GroupList) {
+ WalkGroupEntry = CONTAINING_RECORD(ListItem, WALK_GROUP_ENTRY, GroupList);
+ if (WalkGroupEntry->Walk == Walk) {
+ return TRUE;
+ }
+ ListItem = ListItem->Flink;
+ }
+ }
+ return FALSE;
+}
+
+
+
+#if 0
+
+MethodDebugReg(
+ DEBUG_EVENT* de,
+ HTHDX hthd,
+ DWORD unused,
+ PWALK Walk
+ )
+/*++
+
+Routine Description:
+
+ Method for handling debug registers
+
+Arguments:
+
+ de - Supplies debug event
+
+ hthd - Supplies thread
+
+ Walk - Supplies Walk
+
+Return Value:
+
+ Nothing meaningful.
+
+--*/
+{
+ LPCONTEXT lpContext = &hthd->context;
+ DWORD eip = (DWORD)cPC(lpContext);
+ DWORD currAddr = eip;
+ int lpf = 0;
+ HPRCX hprc = hthd->hprc;
+ HANDLE rwHand = hprc->rwHand;
+ ACVECTOR action = NO_ACTION;
+ BOOLEAN Active;
+#ifdef KERNEL
+ KSPECIAL_REGISTERS ksr;
+#else
+ CONTEXT Context;
+ BOOLEAN Ok;
+#endif
+
+ if ( Walk->GlobalCount == 0 &&
+ Walk->LocalCount == 0 ) {
+ Active = Walk->Active;
+ DeallocateWalk( Walk );
+ if ( Active ) {
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ }
+ return TRUE;
+ }
+
+#ifdef KERNEL
+ GetExtendedContext( hthd, &ksr);
+#else
+ Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ Ok = DbgGetThreadContext( Walk->WalkList->hthd, &Context);
+ assert(Ok)
+#endif
+
+ //
+ // See if this is really for us
+ //
+#ifdef KERNEL
+ if ( ksr.KernelDr6 & 0x0000000F )
+#else
+ if ( Context.Dr6 & 0x0000000F )
+#endif
+ {
+ ConsumeAllThreadEvents(hthd, FALSE);
+#ifdef KERNEL
+ ksr.KernelDr6 &= ~0x0000000f;
+ SetExtendedContext(hthd, &ksr);
+#endif
+
+ Walk->Active = FALSE;
+
+ SetBPFlag(hthd, FindBpForWalk(Walk));
+ //
+ // Notify the EM that this thread has stopped on a BP
+ //
+ NotifyEM( &falseBPEvent, hthd, 0, FindBpForWalk(Walk) );
+
+ } else {
+
+ AddQueue( QT_CONTINUE_DEBUG_EVENT,
+ hthd->hprc->pid,
+ hthd->tid,
+ DBG_CONTINUE,
+ 0);
+ hthd->tstate &= ~(ts_stopped|ts_first|ts_second);
+ hthd->tstate |= ts_running;
+ //
+ // This breakpoint is not for us.
+ //
+ //ProcessBreakpointEvent( de, hthd );
+ }
+
+ return TRUE;
+}
+
+#endif
+
+
+
+
+DWORD
+GetEndOfRange (
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD Addr
+ )
+/*++
+
+Routine Description:
+
+ Given an address, gets the end of the range for that address.
+
+Arguments:
+
+ hprc - Supplies process
+
+ hthd - Supplies thread
+
+ Addr - Supplies the address
+
+Return Value:
+
+ DWORD - End of range
+
+--*/
+
+{
+ char rgb[sizeof(RTP) + sizeof(ADDR) ];
+ LPRTP lprtp = (LPRTP) rgb;
+ LPADDR paddr = (LPADDR) &rgb[sizeof(RTP)];
+ HPID hpid = hprc->hpid;
+ LPCONTEXT lpContext = &hthd->context;
+
+
+ lprtp->dbc = dbcLastAddr;
+ lprtp->hpid = hpid;
+ lprtp->htid = hthd->htid;
+ lprtp->cb = sizeof(ADDR);
+ AddrFromHthdx(paddr, hthd);
+ SetAddrOff( paddr, Addr );
+
+ DmTlFunc(tlfRequest, hpid, sizeof(rgb), (LONG)&rgb);
+
+ Addr = (*(DWORD *)abEMReplyBuf);
+ // NOTENOTE : jimsch --- Is this correct?
+ return (DWORD) Addr;
+}
+
+
+
+
+DWORD
+CanStep (
+ HPRCX hprc,
+ HTHDX hthd,
+ DWORD Addr
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hprc - Supplies process
+ hthd - Supplies thread
+ Addr - Supplies Address
+
+Return Value:
+
+ BOOL - TRUE if can step
+
+--*/
+
+{
+ char rgb[sizeof(RTP)+sizeof(ADDR)];
+ LPRTP lprtp = (LPRTP) &rgb;
+ LPADDR paddr = (LPADDR) &rgb[sizeof(RTP)];
+ HPID hpid = hprc->hpid;
+ LPCONTEXT lpContext = &hthd->context;
+ CANSTEP *CanStep;
+
+
+ lprtp->dbc = dbcCanStep;
+ lprtp->hpid = hpid;
+ lprtp->htid = hthd->htid;
+ lprtp->cb = sizeof(ADDR);
+ AddrFromHthdx(paddr, hthd);
+
+ DmTlFunc(tlfRequest, hpid, sizeof(rgb), (LONG)&rgb);
+ CanStep = (CANSTEP *)abEMReplyBuf;
+
+ return CanStep->Flags;
+}
+
+#ifdef HAS_DEBUG_REGS
+PBREAKPOINT
+GetWalkBPFromBits(
+ HTHDX hthd,
+ DWORD bits
+ )
+{
+ PWALK_LIST WalkList;
+ PWALK Walk;
+ PBREAKPOINT bp;
+
+ WalkList = FindWalkList(hthd->hprc, hthd);
+
+ if (!WalkList) {
+ return FALSE;
+ }
+
+ bp = NULL;
+
+ EnterCriticalSection(&csWalk);
+
+ //
+ // This only finds the first match. If more than one BP was
+ // matched by the CPU, we won't notice.
+ //
+
+ for ( Walk = WalkList->FirstWalk; Walk; Walk = Walk->Next ) {
+ if ( Walk->RegWalk && Walk->RegWalk->InUse ) {
+ if (bits & (1 << Walk->RegWalk->Register)) {
+ // hit!
+ bp = FindBpForWalk(Walk);
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&csWalk);
+
+ return bp;
+}
+#endif // HAS_DEBUG_REGS
+
diff --git a/private/windbg/osdebug/bsexcpt.h b/private/windbg/osdebug/bsexcpt.h
new file mode 100644
index 000000000..dd609ce37
--- /dev/null
+++ b/private/windbg/osdebug/bsexcpt.h
@@ -0,0 +1,376 @@
+/* SCCSID = @(#)except32.h 13.10 90/09/28 */
+
+/*************************** START OF SPECIFICATION *****************
+ *
+ * Source File Name: bsexcpt.h
+ *
+ * Descriptive Name: Thread Exception Constants and Structure Definitions.
+ *
+ * Copyright: Microsoft Corp. 1989
+ * Copyright: IBM Corp. 1989
+ *
+ * Function: This file provides constants and data structure
+ * definitions required by application programs to use 32 bit
+ * thread exceptions management facility.
+ *
+ * Notes: None.
+ *
+ *************************** END OF SPECIFICATION *******************/
+
+/*
+ * User Exception Handler Return Codes:
+ */
+
+#define XCPT_CONTINUE_SEARCH 0x00000000 /* exception not handled */
+#define XCPT_CONTINUE_EXECUTION 0xFFFFFFFF /* exception handled */
+#define XCPT_CONTINUE_STOP 0x00716668 /* exception handled by */
+ /* debugger (VIA DosDebug) */
+
+/*
+ * fHandlerFlags values (see ExceptionStructure):
+ *
+ * The user may only set (but not clear) the EH_NONCONTINUABLE flag.
+ * All other flags are set by the system.
+ *
+ */
+
+#define EH_NONCONTINUABLE 0x1 /* Noncontinuable exception */
+#define EH_UNWINDING 0x2 /* Unwind is in progress */
+#define EH_EXIT_UNWIND 0x4 /* Exit unwind is in progress */
+#define EH_STACK_INVALID 0x8 /* Stack out of limits or unaligned */
+#define EH_NESTED_CALL 0x10 /* Nested exception handler call */
+
+
+/*
+ * Unwind all exception handlers (see DosUnwindException API)
+ */
+
+#define UNWIND_ALL 0
+
+/*
+ * Exception values are 32 bit values layed out as follows:
+ *
+ * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---+-+-------------------------+-------------------------------+
+ * |Sev|C| Facility | Code |
+ * +---+-+-------------------------+-------------------------------+
+ *
+ * where
+ *
+ * Sev - is the severity code
+ * 00 - Success
+ * 01 - Informational
+ * 10 - Warning
+ * 11 - Error
+ *
+ * C - is the Customer code flag
+ *
+ * Facility - is the facility code
+ *
+ * Code - is the facility's status code
+ *
+ * Exceptions specific to Cruiser (e.g. XCPT_SIGNAL) will be marked
+ * with a facility code of 1.
+ *
+ * System defined exceptions have a facility code of zero.
+ *
+ * Each exception may also have several pieces of additional information.
+ * These are stored in the ExceptionInformation fields of the
+ * ExceptionReportRecord. They are documented here with the exceptions
+ * only for ease of reference.
+ */
+
+#define XCPT_FATAL_EXCEPTION 0xC0000000
+#define XCPT_SEVERITY_CODE 0xC0000000
+#define XCPT_CUSTOMER_CODE 0x20000000
+#define XCPT_FACILITY_CODE 0x1FFF0000
+#define XCPT_EXCEPTION_CODE 0x0000FFFF
+
+/*
+ * Violation flags in ExceptionInformation
+ */
+#define XCPT_UNKNOWN_ACCESS 0x00000000 /* Unknown access */
+#define XCPT_READ_ACCESS 0x00000001 /* Read access */
+#define XCPT_WRITE_ACCESS 0x00000002 /* Write access */
+#define XCPT_EXECUTE_ACCESS 0x00000004 /* Execute access */
+#define XCPT_SPACE_ACCESS 0x00000008 /* Address space access */
+#define XCPT_LIMIT_ACCESS 0x00000010 /* Address space limit violation */
+
+#define XCPT_DATA_UNKNOWN 0xFFFFFFFF
+
+/*
+ * Signal subtypes for XCPT_SIGNAL
+ */
+#define XCPT_SIGNAL_INTR 1
+#define XCPT_SIGNAL_KILLPROC 3
+#define XCPT_SIGNAL_BREAK 4
+
+/*
+ * Portable non-fatal software generated exceptions
+ */
+
+#define XCPT_GUARD_PAGE_VIOLATION 0x80000001
+ /* ExceptionInformation[ 0 ] - Access Code: XCPT_READ_ACCESS
+ XCPT_WRITE_ACCESS */
+ /* ExceptionInformation[ 1 ] - FaultAddr */
+
+#define XCPT_UNABLE_TO_GROW_STACK 0x80010001
+
+/*
+ * Portable fatal hardware generated exceptions
+ */
+
+#define XCPT_DATATYPE_MISALIGNMENT 0xC000009E
+ /* ExceptionInformation[ 0 ] - Access Code: XCPT_READ_ACCESS
+ XCPT_WRITE_ACCESS */
+ /* ExceptionInformation[ 1 ] - Alignment */
+ /* ExceptionInformation[ 2 ] - FaultAddr */
+
+#define XCPT_BREAKPOINT 0xC000009F
+
+#define XCPT_SINGLE_STEP 0xC00000A0
+
+#define XCPT_ACCESS_VIOLATION 0xC0000005
+ /* ExceptionInformation[ 0 ] - Access Code: XCPT_READ_ACCESS
+ XCPT_WRITE_ACCESS
+ XCPT_SPACE_ACCESS
+ XCPT_LIMIT_ACCESS
+ XCPT_UNKNOWN_ACCESS */
+ /* ExceptionInformation[ 1 ] - FaultAddr (XCPT_READ_ACCESS/XCPT_WRITE_ACCESS)
+ Selector (XCPT_SPACE_ACCESS)
+ -1 (XCPT_LIMIT_ACCESS) */
+
+#define XCPT_ILLEGAL_INSTRUCTION 0xC000001C
+#define XCPT_FLOAT_DENORMAL_OPERAND 0xC0000094
+#define XCPT_FLOAT_DIVIDE_BY_ZERO 0xC0000095
+#define XCPT_FLOAT_INEXACT_RESULT 0xC0000096
+#define XCPT_FLOAT_INVALID_OPERATION 0xC0000097
+#define XCPT_FLOAT_OVERFLOW 0xC0000098
+#define XCPT_FLOAT_STACK_CHECK 0xC0000099
+#define XCPT_FLOAT_UNDERFLOW 0xC000009A
+
+#define XCPT_INTEGER_DIVIDE_BY_ZERO 0xC000009B
+#define XCPT_INTEGER_OVERFLOW 0xC000009C
+#define XCPT_PRIVILEGED_INSTRUCTION 0xC000009D
+
+/*
+ * Portable fatal software generated exceptions
+ */
+
+#define XCPT_IN_PAGE_ERROR 0xC0000006
+ /* ExceptionInformation[ 0 ] - FaultAddr */
+
+#define XCPT_PROCESS_TERMINATE 0xC0010001
+#define XCPT_ASYNC_PROCESS_TERMINATE 0xC0010002
+ /* ExceptionInfo[0] - TID of 'terminator' thread */
+
+#define XCPT_NONCONTINUABLE_EXCEPTION 0xC0000024
+#define XCPT_INVALID_DISPOSITION 0xC0000025
+
+/*
+ * Non-portable fatal exceptions
+ */
+
+#define XCPT_INVALID_LOCK_SEQUENCE 0xC000001D
+#define XCPT_ARRAY_BOUNDS_EXCEEDED 0xC0000093
+#define XCPT_B1NPX_ERRATA_02 0xC0010004
+
+/*
+ * Misc exceptions
+ */
+
+#define XCPT_UNWIND 0xC0000026
+#define XCPT_BAD_STACK 0xC0000027
+#define XCPT_INVALID_UNWIND_TARGET 0xC0000028
+
+/*
+ * Signal Exceptions
+ */
+
+#define XCPT_SIGNAL 0xC0010003
+ /* ExceptionInfo[0] - signal number */
+
+/*
+ * Exception Context.
+ *
+ * This is the machine specific register contents for the thread
+ * at the time of the exception. Note that only the register sets
+ * specified by ContextFlags contain valid data. Conversely, only
+ * registers specified in ContextFlags will be restored if an exception
+ * is handled.
+ */
+
+/*
+ * The following flags control the contents of the CONTEXT structure.
+ */
+
+#define CONTEXT_CONTROL 0x00000001L /* SS:ESP, CS:EIP, EFLAGS, */
+ /* EBP */
+#define CONTEXT_INTEGER 0x00000002L /* EAX, EBX, ECX, EDX, ESI, */
+ /* EDI */
+#define CONTEXT_SEGMENTS 0x00000004L /* DS, ES, FS, GS */
+#define CONTEXT_FLOATING_POINT 0x00000008L /* 387 state */
+
+#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | \
+ CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT)
+
+/* XLATOFF */
+#pragma pack(1)
+/* XLATON */
+
+struct _fpreg { /* coprocessor stack register element */
+ ULONG losig;
+ ULONG hisig;
+ USHORT signexp;
+};
+typedef struct _fpreg FPREG;
+
+/* XLATOFF */
+#pragma pack()
+/* XLATON */
+
+
+struct _CONTEXT { /* Ex */
+
+ /*
+ * The flags values within this flag control the contents of
+ * a CONTEXT record.
+ *
+ * If the context record is used as an input parameter, then
+ * for each portion of the context record controlled by a flag
+ * whose value is set, it is assumed that that portion of the
+ * context record contains valid context. If the context record
+ * is being used to modify a thread's context, then only that
+ * portion of the thread's context will be modified.
+ *
+ * If the context record is used as an Input/Output parameter to
+ * capture the context of a thread, then only those portions of the
+ * thread's context corresponding to set flags will be returned.
+ */
+
+ ULONG ContextFlags;
+
+ /*
+ * This section is specified/returned if the
+ * ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
+ */
+
+ ULONG ctx_env[7];
+ struct _fpreg ctx_stack[8];
+
+ /*
+ * This section is specified/returned if the
+ * ContextFlags word contains the flag CONTEXT_SEGMENTS.
+ */
+
+ ULONG ctx_SegGs;
+ ULONG ctx_SegFs;
+ ULONG ctx_SegEs;
+ ULONG ctx_SegDs;
+
+ /*
+ * This section is specified/returned if the
+ * ContextFlags word contains the flag CONTEXT_INTEGER.
+ */
+
+ ULONG ctx_RegEdi;
+ ULONG ctx_RegEsi;
+ ULONG ctx_RegEax;
+ ULONG ctx_RegEbx;
+ ULONG ctx_RegEcx;
+ ULONG ctx_RegEdx;
+
+ /*
+ * This section is specified/returned if the
+ * ContextFlags word contains the flag CONTEXT_CONTROL.
+ */
+
+ ULONG ctx_RegEbp;
+ ULONG ctx_RegEip;
+ ULONG ctx_SegCs;
+ ULONG ctx_EFlags;
+ ULONG ctx_RegEsp;
+ ULONG ctx_SegSs;
+
+};
+typedef struct _CONTEXT CONTEXTRECORD;
+typedef struct _CONTEXT *PCONTEXTRECORD;
+
+
+/*
+ * ExceptionReportRecord
+ *
+ * This structure contains machine independant information about an
+ * exception/unwind. No system exception will ever have more than
+ * EXCEPTION_MAXIMUM_PARAMETERS parameters. User exceptions are not
+ * bound to this limit.
+ */
+
+
+#define EXCEPTION_MAXIMUM_PARAMETERS 4 /* Enough for all system exceptions. */
+
+struct _EXCEPTIONREPORTRECORD {
+ ULONG ExceptionNum; /* exception number */
+ ULONG fHandlerFlags;
+ struct _EXCEPTIONREPORTRECORD *NestedExceptionReportRecord;
+ PVOID ExceptionAddress;
+ ULONG cParameters; /* Size of Exception Specific Info */
+ ULONG ExceptionInfo[EXCEPTION_MAXIMUM_PARAMETERS];
+ /* Exception Specfic Info */
+};
+typedef struct _EXCEPTIONREPORTRECORD EXCEPTIONREPORTRECORD;
+typedef struct _EXCEPTIONREPORTRECORD *PEXCEPTIONREPORTRECORD;
+
+/*
+ * ExceptionRegistrationRecord
+ *
+ * These are linked together to form a chain of exception handlers that
+ * will be dispatched to upon receipt of an exception.
+ *
+ * NOTE: Exception handlers should *NOT* be Registered directly from a
+ * high level language, such as 'C'. This is the responsibility of
+ * the language runtime.
+ */
+
+/* XLATOFF */
+struct _EXCEPTIONREGISTRATIONRECORD {
+ struct _EXCEPTIONREGISTRATIONRECORD *prev_structure;
+ ULONG (_cdecl * ExceptionHandler)(PEXCEPTIONREPORTRECORD,
+ struct _EXCEPTIONREGISTRATIONRECORD *,
+ PCONTEXTRECORD,
+ PVOID);
+};
+typedef struct _EXCEPTIONREGISTRATIONRECORD EXCEPTIONREGISTRATIONRECORD;
+typedef struct _EXCEPTIONREGISTRATIONRECORD *PEXCEPTIONREGISTRATIONRECORD;
+/* XLATON */
+
+/* ASM
+
+_EXCEPTIONREGISTRATIONRECORD STRUC
+prev_structure DD ?
+ExceptionHandler DD ?
+_EXCEPTIONREGISTRATIONRECORD ENDS
+
+EXCEPTIONREGISTRATIONRECORD struc
+ db size _EXCEPTIONREGISTRATIONRECORD dup(?)
+EXCEPTIONREGISTRATIONRECORD ends
+
+PEXCEPTIONREGISTRATIONRECORD struc
+ dd ?
+PEXCEPTIONREGISTRATIONRECORD ends
+
+*/
+
+/*
+ * End of exception chain marker.
+ */
+
+/* XLATOFF */
+#define END_OF_CHAIN ((PEXCEPTIONREGISTRATIONRECORD) -1)
+/* XLATON */
+
+/* ASM
+END_OF_CHAIN EQU -1
+*/
+
diff --git a/private/windbg/osdebug/cc.h b/private/windbg/osdebug/cc.h
new file mode 100644
index 000000000..8002b75a0
--- /dev/null
+++ b/private/windbg/osdebug/cc.h
@@ -0,0 +1,23 @@
+#define CCInfoAvail(hpid) (*rgpids[hpid].cc.lpfnInfoAvail )
+#define CCInfoReq(hpid) (*rgpids[hpid].cc.lpfnInfoReq )
+#define CCModStart(hpid) (*rgpids[hpid].cc.lpfnModStart )
+#define CCSignal(hpid) (*rgpids[hpid].cc.lpfnSignal )
+#define CCBpt(hpid) (*rgpids[hpid].cc.lpfnBpt )
+#define CCProcTerm(hpid) (*rgpids[hpid].cc.lpfnProcTerm )
+#define CCException(hpid) (*rgpids[hpid].cc.lpfnException )
+#define CCModLoad(hpid) (*rgpids[hpid].cc.lpfnModLoad )
+#define CCCoProcErr(hpid) (*rgpids[hpid].cc.lpfnCoProcErr )
+#define CCThreadTerm(hpid) (*rgpids[hpid].cc.lpfnThreadTerm )
+#define CCAsyncStop(hpid) (*rgpids[hpid].cc.lpfnAsyncStop )
+#define CCNewProc(hpid) (*rgpids[hpid].cc.lpfnNewProc )
+#define CCAliasFree(hpid) (*rgpids[hpid].cc.lpfnAliasFree )
+#define CCWatchPoint(hpid) (*rgpids[hpid].cc.lpfnWatchPoint )
+#define CCModFree(hpid) (*rgpids[hpid].cc.lpfnModFree )
+#define CCCreateThread(hpid)(*rgpids[hpid].cc.lpfnCreateThread)
+#define CCRangeStep(hpid) (*rgpids[hpid].cc.lpfnRangeStep )
+#define CCPageLoad(hpid) (*rgpids[hpid].cc.lpfnPageLoad )
+#define CCPageMove(hpid) (*rgpids[hpid].cc.lpfnPageMove )
+#define CCPageUnload(hpid) (*rgpids[hpid].cc.lpfnPageUnload )
+#define CCEmChange(hpid) (*rgpids[hpid].cc.lpfnEmChange )
+#define CCSuccess(hpid) (*rgpids[hpid].cc.lpfnSuccess )
+#define CCError(hpid) (*rgpids[hpid].cc.lpfnError )
diff --git a/private/windbg/osdebug/cchpt.h b/private/windbg/osdebug/cchpt.h
new file mode 100644
index 000000000..add1efb7e
--- /dev/null
+++ b/private/windbg/osdebug/cchpt.h
@@ -0,0 +1,25 @@
+
+
+#define CCInfoAvail(hpid) (*rgpids[hpid].cc.lpfnInfoAvail )
+#define CCInfoReq(hpid) (*rgpids[hpid].cc.lpfnInfoReq )
+#define CCModStart(hpid) (*rgpids[hpid].cc.lpfnModStart )
+#define CCSignal(hpid) (*rgpids[hpid].cc.lpfnSignal )
+#define CCBpt(hpid) (*rgpids[hpid].cc.lpfnBpt )
+#define CCProcTerm(hpid) (*rgpids[hpid].cc.lpfnProcTerm )
+#define CCException(hpid) (*rgpids[hpid].cc.lpfnException )
+#define CCModLoad(hpid) (*rgpids[hpid].cc.lpfnModLoad )
+#define CCCoProcErr(hpid) (*rgpids[hpid].cc.lpfnCoProcErr )
+#define CCThreadTerm(hpid) (*rgpids[hpid].cc.lpfnThreadTerm )
+#define CCAsyncStop(hpid) (*rgpids[hpid].cc.lpfnAsyncStop )
+#define CCNewProc(hpid) (*rgpids[hpid].cc.lpfnNewProc )
+#define CCAliasFree(hpid) (*rgpids[hpid].cc.lpfnAliasFree )
+#define CCWatchPoint(hpid) (*rgpids[hpid].cc.lpfnWatchPoint )
+#define CCModFree(hpid) (*rgpids[hpid].cc.lpfnModFree )
+#define CCCreateThread(hpid)(*rgpids[hpid].cc.lpfnCreateThread)
+#define CCRangeStep(hpid) (*rgpids[hpid].cc.lpfnRangeStep )
+#define CCPageLoad(hpid) (*rgpids[hpid].cc.lpfnPageLoad )
+#define CCPageMove(hpid) (*rgpids[hpid].cc.lpfnPageMove )
+#define CCPageUnload(hpid) (*rgpids[hpid].cc.lpfnPageUnload )
+#define CCEmChange(hpid) (*rgpids[hpid].cc.lpfnEmChange )
+#define CCSuccess(hpid) (*rgpids[hpid].cc.lpfnSuccess )
+#define CCError(hpid) (*rgpids[hpid].cc.lpfnError )
diff --git a/private/windbg/osdebug/defs.h b/private/windbg/osdebug/defs.h
new file mode 100644
index 000000000..0826cd33c
--- /dev/null
+++ b/private/windbg/osdebug/defs.h
@@ -0,0 +1,47 @@
+#ifndef ADDR_MIXED
+#define ADDR_MIXED
+#endif
+
+#include "types.h"
+#include "cvinfo.h"
+#include "cvtypes.hxx"
+#include "shapi.hxx" // for convenience, since almost everyone will
+ // be including od.h, which needs this
+
+#include <stdio.h>
+
+#ifdef DOS32DM // DOS32DM = compiles under cl386
+#undef ENUM
+#define ENUM short enum
+#endif
+
+#ifdef TARGET32
+#ifdef CRUISER
+#define SETADDRMODE(a) ( ADDR_IS_FLAT(a) = (unsigned char ) (FIsBigSeg ( (a).addr.seg ) != 0))
+#else
+#define SETADDRMODE(a) ( ADDR_IS_FLAT(a) = TRUE)
+#endif
+#else
+#define SETADDRMODE(a) ( ADDR_IS_FLAT(a) = FALSE)
+#endif
+
+#define segAddr(a) GetAddrSeg(a)
+#define offAddr(a) GetAddrOff(a)
+
+#ifdef TARGET32
+typedef ULONG TID;
+typedef ULONG PID;
+#else
+typedef USHORT TID;
+typedef USHORT PID;
+#endif
+
+enum { cmpLess = -1, cmpEqual = 0, cmpGreater = 1 } ;
+
+typedef short CMP;
+
+#ifndef EXPENTRY
+#define EXPENTRY PASCAL FAR LOADDS
+#endif
+
+typedef char FAR * LPSZ;
diff --git a/private/windbg/osdebug/include/bpprotos.h b/private/windbg/osdebug/include/bpprotos.h
new file mode 100644
index 000000000..532d6c97f
--- /dev/null
+++ b/private/windbg/osdebug/include/bpprotos.h
@@ -0,0 +1,91 @@
+/***
+ *
+ * Breakpoint Handler API
+ *
+ */
+
+extern BPSTATUS PASCAL BPInit( void );
+extern BPSTATUS PASCAL BPTerm( void );
+
+extern BPSTATUS PASCAL BPParse(HBPT FAR * pHbpt, char FAR * szBpt, char FAR * szMod, char FAR * szFile, HPID hPid);
+extern BPSTATUS PASCAL BPBindHbpt( HBPT, CXF * );
+
+extern BPSTATUS PASCAL BPAddToList( HBPT, int );
+extern BPSTATUS PASCAL BPChange( HBPT, int );
+extern BPSTATUS PASCAL BPDelete( HBPT );
+extern BPSTATUS PASCAL BPDeleteAll( VOID );
+
+extern BPSTATUS PASCAL BPGetFinalHbpt( HBPT, HBPT FAR *);
+extern BPSTATUS PASCAL BPNextHbpt( HBPT FAR *, UINT);
+extern BPSTATUS PASCAL BPFormatHbpt( HBPT, char FAR *, UINT, UINT);
+
+extern BPSTATUS PASCAL BPCommit(void);
+extern BPSTATUS PASCAL BPUnCommit(void);
+
+extern BPSTATUS PASCAL BPHighlightSourceFile( char *fname );
+
+extern BPSTATUS PASCAL BPSetHpid(HBPT, HPID);
+extern BPSTATUS PASCAL BPGetHpid(HBPT, HPID *);
+extern BPSTATUS PASCAL BPGetIpid(HBPT, UINT *);
+extern BPSTATUS PASCAL BPGetHtid(HBPT, HTID *);
+
+extern BPSTATUS PASCAL BPSetTmp(LPADDR, HPID, HTID, HBPT FAR *);
+extern BPSTATUS PASCAL BPClearAllTmp(HPID, HTID);
+
+extern BPSTATUS PASCAL BPDisable(HBPT);
+extern BPSTATUS PASCAL BPEnable(HBPT);
+
+extern BPSTATUS PASCAL BPHbptFromI(HBPT FAR *, UINT);
+
+extern BPSTATUS PASCAL BPHbptFromFileLine(char FAR *, UINT, HBPT FAR *);
+extern BPSTATUS PASCAL BPHbptFromAddr(ADDR FAR *, HBPT FAR *);
+
+extern BPSTATUS PASCAL BPAddrFromHbpt(HBPT, ADDR FAR *);
+extern BPSTATUS PASCAL BPIFromHbpt(UINT FAR *, HBPT);
+extern BPSTATUS PASCAL BPFreeHbpt(HBPT);
+
+extern BPSTATUS PASCAL BPCheckHbpt(CXF, LPFNBPCALLBACK, HPID, HTID, DWORD);
+
+extern BPSTATUS PASCAL BPQueryBPTypeOfHbpt(HBPT, int FAR *);
+extern BPSTATUS PASCAL BPQueryCmdOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryLocationOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryExprOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryMemoryOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryMemorySizeOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryPassCntOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryPassLeftOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryProcessOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryThreadOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPQueryMessageOfHbpt(HBPT, char FAR *, UINT);
+extern BPSTATUS PASCAL BPUpdateMemory( ULONG );
+extern BPSTATUS PASCAL BPQueryHighlightLineOfHbpt( HBPT, UINT *);
+
+extern EESTATUS PASCAL BPADDRFromTM (PHTM, unsigned short FAR *, PADDR);
+
+extern LPSTR PASCAL BPShortenContext(LPSTR lpSrc, LPSTR lpDest);
+
+extern HMOD PASCAL BPFileNameToMod( char * FileName );
+
+/*
+** THe following are the set of callback routines used by the
+** breakpoint engine
+*/
+
+#if 0
+extern BOOL PASCAL BPQuerySrcWinFls(FLS *);
+#endif
+
+extern BOOL PASCAL BPCBBindHbpt( HBPT );
+extern BOOL PASCAL BPCBSetHighlight(char FAR *, UINT, BOOL, BOOL, WORD);
+extern BOOL PASCAL BPCBSetUHighlight(char FAR *, UINT, BOOL, BOOL);
+extern BOOL PASCAL BPCBGetSourceFromAddr(PADDR, char FAR *, int, int FAR *);
+
+extern BOOL PASCAL BPIsMarkedForDeletion( HBPT );
+extern BOOL PASCAL BPIsDisabled( HBPT );
+extern BOOL PASCAL BPIsInstantiated( HBPT );
+extern BOOL PASCAL BPUninstantiate( HBPT );
+extern BOOL PASCAL BPIsQuiet( HBPT );
+extern VOID PASCAL BPSetQuiet( HBPT );
+extern VOID PASCAL BPSegLoad( ULONG );
+extern BOOL PASCAL BPSymbolLoading( BOOL );
+extern BOOL PASCAL BPSymbolsMayBeAvailable( HBPT );
diff --git a/private/windbg/osdebug/include/bptypes.h b/private/windbg/osdebug/include/bptypes.h
new file mode 100644
index 000000000..57f1fbd89
--- /dev/null
+++ b/private/windbg/osdebug/include/bptypes.h
@@ -0,0 +1,316 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Bptypes.h
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _BPTYPES_ )
+#define _BPTYPES_
+
+#include "eeapi.h"
+
+// Just to hide things
+#define HBPI HLLE
+#define hbpiNull hlleNull
+
+#define HBPT HLLE
+#define hbptNull hlleNull
+
+typedef struct cpb FAR * _LPCBP;
+
+#ifdef LATER
+// Types of breakpoints
+#define BPCONTINUE 0
+#define BPBREAKPT 1
+#define BPTMP 2
+#define BPINTERNAL 3
+#define BPSKIPCALL 4
+#define BPDEADCHILD 5
+#define BPABORT 6
+#define BPUSERINT3 7
+#define BPDEADTHREAD 8
+#define BPNMI 9
+
+
+#define BRKPTOPCODE 0xCC
+#define DPLBITS ((unsigned int) 0x3)
+
+#if DOS5
+#define SKIPBPUIFLAGS 7
+#else
+#define SKIPBPUIFLAGS 3
+#endif // dos5
+
+#endif // LATER
+
+#if 0
+typedef union bpf {
+ UINT flags;
+ struct {
+ UINT fBpCode : 1; // Is there a Code bp
+ UINT fBpData : 1; // Is there a watch/trace point
+ UINT fActive : 1; // Breakpoint is active
+ UINT fBPLoaded : 1; // is BRKPTOPCODE in the code
+ UINT fVirtual : 1; // This is a virtual bp
+ UINT fAmbig : 1; // This BP came from an ambiguous expression
+ UINT fPass : 1; // if a passcount was specified
+ UINT fUser : 1; // for use WITHIN a proc, up to you how to use
+ UINT fDlgActive : 1; // Dialog hold are for orignal fActive state
+ UINT fDlgMarkDel : 1; // This breakpoint has been marked for deletion
+ UINT fDlgMarkAdd : 1; // This breakpoint has been marked for addition
+ UINT BpType : 3; // The type of breakpoint
+#if defined(WINDOWS3) || defined(DOS5)
+ UINT BpSubType : 2;
+#endif
+ } f;
+} BPF;
+
+#endif
+
+typedef union dpf {
+ UINT flags;
+ struct {
+ UINT fEmulate : 1; // If emulation is required
+ UINT fFuncBpSet : 1; // if a function breakpoint is set
+ UINT fTpFuncHit : 1; // When we hit a breakpoint set by tracepoint
+ UINT fFuncLoad : 1; // We must load the breakpoint value on function entry
+ UINT fEvalExpr : 1; // Is the expr not an lvalue
+ UINT fDataRange : 1; // if a datarange was specifed
+ UINT fBpRel : 1; // if a code range was specified
+ UINT fContext : 1; // if context checking is required
+ UINT fReg : 1; // if it is in a register
+ UINT fHighReg : 1; // if in the highbyte of reg
+ UINT fUser : 1; // for use WITHIN a proc, up to you how to use
+ UINT fHdwBrk : 1; // Is this a hardware bp
+ UINT HdwReg : 2; // The hardware reg used
+ } f;
+} DPF;
+typedef DPF FAR * PDPF;
+#ifdef LATER
+
+#if defined(WINDOWS3) || defined(DOS5)
+struct cbp; // for forward reference
+#endif
+#endif // LATER
+
+typedef struct dpi {
+ union {
+ struct {
+ ADDR DataAddr; // Data address to watch
+ } d;
+ struct {
+ ADDR BlkAddr; // the start address of the block
+ UOFFSET oEnd; // The end offset of the function
+ short oBp; // ofset from the bp
+ FRAME Frame; // the frame
+ } bp;
+ } u;
+ char * pValue; // pointer to the initial value
+ short iReg; // if in register, the reg index
+ USHORT cData; // Number of data items to watch
+ USHORT cbData; // Number of bytes in data item
+ HTM hTM; // a TM handle for the data breakpoint
+} DPI;
+typedef DPI * PDPI;
+
+
+#if 0
+
+typedef struct bpi {
+ BPF bpf; // flags
+ DPF dpf; // the data bp flags
+ int fLang; // the language type
+ unsigned char OpCode; // The orignal opcode
+ ADDR CodeAddr; // Code address of breakpoint
+ DPI * pdpi; // pointer to the DataBreakpoint
+/*
+ * This defines a function callback mechanism which can be used to
+ * generalize the breakpoint facility.
+ * The messages and responses are defined earlier in this file.
+ */
+ int (FAR *lpfnEval)(_LPCBP);// A breakpoint callback function
+ long lData; // User data
+ USHORT cPass; // Initial Pass count
+ USHORT cPassCur; // Current Pass count
+ char * pCmd; // Offset of the command to Execute
+ USHORT hprc; // The process this bp is associated with
+ USHORT hthd; // The tread to break at
+ // NULL breaks on all threads
+// struct bpi * pbpiNext;
+// struct bpi * pbpiBack;
+} BPI;
+typedef BPI * PBPI;
+typedef BPI FAR * LPBPI;
+
+#endif // 0
+
+#ifdef LATER
+
+#if defined(WINDOWS3) || defined(DOS5)
+/*
+ * This defines a function callback mechanism which can be used to
+ * generalize the breakpoint facility.
+ * The messages and responses are defined earlier in this file.
+ */
+typedef struct cbp {
+ unsigned wMsg; // A message giving the reason for the call
+ unsigned wInstance; // BPBrkExec call count
+ char FAR * lpch; // A buffer for return info
+ HBPI hbpi; // Points to the parent bpi
+ } cbp;
+#endif
+
+#endif // LATER
+
+typedef struct PBPD {
+ USHORT hthd;
+ USHORT BPType;
+ PCXF pCXF;
+ USHORT BPSegType;
+ char FAR * szCmd;
+ unsigned int fAmbig;
+ union {
+ ADDR Addr;
+ struct {
+ unsigned int cBPMax;
+ TML TMLT;
+ } u;
+ } u;
+ PDPI pDPI;
+ DPF DPF;
+ USHORT cPass;
+ char FAR * szOptCmd;
+ int iErr;
+ char SubType;
+ int (FAR *lpfnEval)(_LPCBP);// A possible callback function
+ long lData; // User data
+} PBP;
+typedef PBP FAR * PPBP;
+
+#ifdef LATER
+typedef struct sfi {
+ int fLang;
+ ushort fEnable;
+ ushort hthd;
+} sfi;
+
+// user global variable YUK! this should not be visable to the world!
+// extern PBPI pbpiFirst;
+extern int G_BPfEmulate;
+
+extern HLLI llbpi;
+#endif // LATER
+
+extern UINT radix;
+extern char fCaseSensitive;
+
+
+#define BPCODEADDR 1001
+#define BPDATAADDR 1002
+#define BPLENGTH 1003
+#define BPPASSCNT 1004
+#define BADBKPTCMD 1005
+#define WMSGALL 1006
+#define WMSGTYPE 1007
+#define WMSGCLASS 1008
+#define WMSGBPCLASS 1009
+#define WMSGBPTYPE 1010
+#define WMSGDPCLASS 1011
+#define WMSGDPTYPE 1012
+#define WMSGBPALL 1013
+#define WMSGDPALL 1014
+#define BPSTCALLBACK 1015
+#define NOCODE 1019
+#define NOTLVALUE 1020
+
+
+/**********************************************************************/
+
+#define MHOmfUnLock(a)
+
+
+#define bptNext 1
+#define bptPrevious 2
+#define bptFirst 3
+#define bptLast 4
+
+typedef enum {
+ BPNOERROR = 0, // No Error
+ BPBadDataSize = 1,
+ BPBadPassCount = 2,
+ BPBadCmdString = 3,
+ BPBadOption = 4,
+ BPBadAddrExpr = 5,
+ BPBadContextOp = 6,
+ BPOOMemory = 7,
+ BPError = 8,
+ BPBadBPHandle = 9,
+ BPNoMatch = 10,
+ BPAmbigous = 11,
+ BPNoBreakpoint = 12,
+ BPTmpBreakpoint = 13,
+ BPPassBreakpoint = 14,
+ BPBadExpression = 15,
+ BPOutOfSpace = 16,
+ BPBadThread = 17,
+ BPBadProcess = 18,
+ BPCancel = 19
+} BPSTATUS;
+
+
+#define BPLOC 0
+#define BPLOCEXPRTRUE 1
+#define BPLOCEXPRCHGD 2
+#define BPEXPRTRUE 3
+#define BPEXPRCHGD 4
+#define BPWNDPROC 5
+#define BPWNDPROCEXPRTRUE 6
+#define BPWNDPROCEXPRCHGD 7
+#define BPWNDPROCMSGRCVD 8
+
+
+/*
+** Define the states that a breakpoint can have.
+*/
+
+typedef enum {
+ bpstateNotSet = 1, /* Breakpoint is parsed */
+ bpstateVirtual = 2, /* Breakpoint is parsed & Addr-ed */
+ bpstateSet = 4, /* Breakpoint is parsed, Addr-ed & Set */
+ bpstateSets = 7, /* */
+ bpstateDisabled = 0, /* Breakpoint is Disabled */
+ bpstateEnabled = 16, /* Breakpoint is Enabled */
+ bpstateDeleted = 32 /* Breakpoint has been deleted */
+} BPSTATE;
+
+
+/*
+** BreakPoint Format Control Flags
+*/
+
+#define BPFCF_ITEM_COUNT 0x01
+#define BPFCF_ADD_DELETE 0x02
+#define BPFCF_WNDPROC 0x04
+#define BPFCF_WRKSPACE 0x08
+
+/*
+**
+*/
+
+typedef VOID (LOADDS PASCAL FAR * LPFNBPCALLBACK)(HBPT, BPSTATUS);
+
+#endif // _BPTYPES_
diff --git a/private/windbg/osdebug/include/cp.h b/private/windbg/osdebug/include/cp.h
new file mode 100644
index 000000000..e02b056f6
--- /dev/null
+++ b/private/windbg/osdebug/include/cp.h
@@ -0,0 +1,51 @@
+
+#define BADTYPECAST 101
+#define NOROOM 102
+#define GEXPRERR 105
+
+
+extern int FAR PASCAL CPCopyToken(LPSTR *lplps, LPSTR lpt);
+extern int FAR PASCAL CPCopyString(LPSTR *lplps, LPSTR lpT, char chEscape, BOOL fQuote);
+extern LPSTR FAR PASCAL CPAdvance(char FAR *, char FAR *);
+extern LPSTR FAR PASCAL CPszToken(char FAR *, char FAR *);
+extern LPSTR FAR PASCAL CPTrim(char FAR *, char);
+extern int FAR PASCAL CPQueryChar(char FAR *, char FAR *);
+extern int FAR PASCAL CPQueryQuoteIndex ( char FAR * szSrc );
+extern int FAR PASCAL CPGetCastNbr(char FAR *, USHORT, int, int, PCXF, char FAR *, char FAR *);
+extern long FAR PASCAL CPGetNbr(char FAR *, int, int, PCXF, char FAR *, int FAR *);
+extern long FAR PASCAL CPGetInt(char FAR *, int FAR *, int FAR *);
+extern int FAR PASCAL CPGetAddress(char FAR *, int FAR *, ADDR FAR *, EERADIX, CXF FAR *, BOOL, BOOL);
+extern LPSTR FAR PASCAL CPSkipWhitespace(char FAR *);
+
+extern int FAR PASCAL
+CPGetFPNbr(
+ LPSTR lpExpr,
+ int cBits,
+ int nRadix,
+ int fCase,
+ PCXF pCxf,
+ LPSTR lpBuf,
+ LPSTR lpErr);
+
+extern int FAR PASCAL
+CPGetRange(
+ LPSTR lpszExpr,
+ int FAR *lpcch,
+ LPADDR lpAddr1,
+ LPADDR lpAddr2,
+ EERADIX radix,
+ int cbDefault,
+ int cbSize,
+ CXF FAR *pcxf,
+ BOOL fCase,
+ BOOL fSpecial);
+
+typedef enum {
+ CPNOERROR,
+ CPNOARGS,
+ CPISOPENQUOTE,
+ CPISCLOSEQUOTE,
+ CPISOPENANDCLOSEQUOTE,
+ CPISDELIM,
+ CPNOTINQUOTETABLE
+} CPRETURNS;
diff --git a/private/windbg/osdebug/include/ctxptrs.h b/private/windbg/osdebug/include/ctxptrs.h
new file mode 100644
index 000000000..1e1bb2dda
--- /dev/null
+++ b/private/windbg/osdebug/include/ctxptrs.h
@@ -0,0 +1,97 @@
+#if defined( _NTMIPS_ ) || defined( _NTALPHA_ ) || defined( _NTPPC_ )
+#define _CTXPTRS_H_
+#endif
+
+#ifndef _CTXPTRS_H_
+#define _CTXPTRS_H_
+
+#if !defined( _ALPHA_ ) && !defined (TARGET_ALPHA)
+
+typedef ULONG KNONVOLATILE_CONTEXT_POINTERS;
+typedef PULONG PKNONVOLATILE_CONTEXT_POINTERS;
+
+#else
+
+//
+// modified from ntalpha.h June 7, 1993.
+//
+
+//
+// Nonvolatile context pointer record.
+//
+
+typedef struct _KNONVOLATILE_CONTEXT_POINTERS {
+
+ PLARGE_INTEGER FloatingContext[1];
+ PLARGE_INTEGER FltF1;
+ // Nonvolatile floating point registers start here.
+ PLARGE_INTEGER FltF2;
+ PLARGE_INTEGER FltF3;
+ PLARGE_INTEGER FltF4;
+ PLARGE_INTEGER FltF5;
+ PLARGE_INTEGER FltF6;
+ PLARGE_INTEGER FltF7;
+ PLARGE_INTEGER FltF8;
+ PLARGE_INTEGER FltF9;
+ PLARGE_INTEGER FltF10;
+ PLARGE_INTEGER FltF11;
+ PLARGE_INTEGER FltF12;
+ PLARGE_INTEGER FltF13;
+ PLARGE_INTEGER FltF14;
+ PLARGE_INTEGER FltF15;
+ PLARGE_INTEGER FltF16;
+ PLARGE_INTEGER FltF17;
+ PLARGE_INTEGER FltF18;
+ PLARGE_INTEGER FltF19;
+ PLARGE_INTEGER FltF20;
+ PLARGE_INTEGER FltF21;
+ PLARGE_INTEGER FltF22;
+ PLARGE_INTEGER FltF23;
+ PLARGE_INTEGER FltF24;
+ PLARGE_INTEGER FltF25;
+ PLARGE_INTEGER FltF26;
+ PLARGE_INTEGER FltF27;
+ PLARGE_INTEGER FltF28;
+ PLARGE_INTEGER FltF29;
+ PLARGE_INTEGER FltF30;
+ PLARGE_INTEGER FltF31;
+
+ PLARGE_INTEGER IntegerContext[1];
+ PLARGE_INTEGER IntT0;
+ PLARGE_INTEGER IntT1;
+ PLARGE_INTEGER IntT2;
+ PLARGE_INTEGER IntT3;
+ PLARGE_INTEGER IntT4;
+ PLARGE_INTEGER IntT5;
+ PLARGE_INTEGER IntT6;
+ PLARGE_INTEGER IntT7;
+ // Nonvolatile integer registers start here.
+ PLARGE_INTEGER IntS0;
+ PLARGE_INTEGER IntS1;
+ PLARGE_INTEGER IntS2;
+ PLARGE_INTEGER IntS3;
+ PLARGE_INTEGER IntS4;
+ PLARGE_INTEGER IntS5;
+ PLARGE_INTEGER IntFp;
+ PLARGE_INTEGER IntA0;
+ PLARGE_INTEGER IntA1;
+ PLARGE_INTEGER IntA2;
+ PLARGE_INTEGER IntA3;
+ PLARGE_INTEGER IntA4;
+ PLARGE_INTEGER IntA5;
+ PLARGE_INTEGER IntT8;
+ PLARGE_INTEGER IntT9;
+ PLARGE_INTEGER IntT10;
+ PLARGE_INTEGER IntT11;
+ PLARGE_INTEGER IntRa;
+ PLARGE_INTEGER IntT12;
+ PLARGE_INTEGER IntAt;
+ PLARGE_INTEGER IntGp;
+ PLARGE_INTEGER IntSp;
+ PLARGE_INTEGER IntZero;
+
+} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS;
+
+#endif // !_ALPHA_ && !TARGET_ALPHA
+
+#endif // _CTXPTRS_H_
diff --git a/private/windbg/osdebug/include/cvexefmt.h b/private/windbg/osdebug/include/cvexefmt.h
new file mode 100644
index 000000000..0b3286c18
--- /dev/null
+++ b/private/windbg/osdebug/include/cvexefmt.h
@@ -0,0 +1,364 @@
+/*** cvexefmt.h - format of CodeView information in exe
+ *
+ * Structures, constants, etc. for reading CodeView information
+ * from the executable.
+ *
+ */
+
+
+/*** The master copy of this file resides in the CodeView project.
+ * All Microsoft projects are required to use the master copy without
+ * modification. Modification of the master version or a copy
+ * without consultation with all parties concerned is extremely
+ * risky.
+ *
+ */
+
+
+
+
+// The following structures and constants describe the format of the
+// CodeView Debug OMF for that will be accepted by CodeView 4.0 and
+// later. These are executables with signatures of NB05, NB06 and NB07.
+// There is some confusion about the signatures NB03 and NB04 so none
+// of the utilites will accept executables with these signatures.
+
+// All of the structures described below must start on a long word boundary
+// to maintain natural alignment. Pad space can be inserted during the
+// write operation and the addresses adjusted without affecting the contents
+// of the structures.
+
+
+// Type of subsection entry.
+
+#define sstModule 0x120
+#define sstTypes 0x121
+#define sstPublic 0x122
+#define sstPublicSym 0x123 // publics as symbol (waiting for link)
+#define sstSymbols 0x124
+#define sstAlignSym 0x125
+#define sstSrcLnSeg 0x126 // because link doesn't emit SrcModule
+#define sstSrcModule 0x127
+#define sstLibraries 0x128
+#define sstGlobalSym 0x129
+#define sstGlobalPub 0x12a
+#define sstGlobalTypes 0x12b
+#define sstMPC 0x12c
+#define sstSegMap 0x12d
+#define sstSegName 0x12e
+#define sstPreComp 0x12f // precompiled types
+#define sstPreCompMap 0x130 // map precompiled types in global types
+#define sstOffsetMap16 0x131
+#define sstOffsetMap32 0x132
+#define sstFileIndex 0x133
+#define sstStaticSym 0x134
+
+
+
+typedef enum OMFHash {
+ OMFHASH_NONE, // no hashing
+ OMFHASH_SUMUC16, // upper case sum of chars in 16 bit table
+ OMFHASH_SUMUC32, // upper case sum of chars in 32 bit table
+ OMFHASH_ADDR16, // sorted by increasing address in 16 bit table
+ OMFHASH_ADDR32 // sorted by increasing address in 32 bit table
+} OMFHASH;
+
+// CodeView Debug OMF signature. The signature at the end of the file is
+// a negative offset from the end of the file to another signature. At
+// the negative offset (base address) is another signature whose filepos
+// field points to the first OMFDirHeader in a chain of directories.
+// The NB05 signature is used by the link utility to indicated a completely
+// unpacked file. The NB06 signature is used by ilink to indicate that the
+// executable has had CodeView information from an incremental link appended
+// to the executable. The NB07 signature is used by cvpack to indicate that
+// the CodeView Debug OMF has been packed. CodeView will only process
+// executables with the NB07 signature.
+
+
+typedef struct OMFSignature {
+ char Signature[4]; // "NB05", "NB06" or "NB07"
+ long filepos; // offset in file
+} OMFSignature;
+
+
+
+// directory information structure
+// This structure contains the information describing the directory.
+// It is pointed to by the signature at the base address or the directory
+// link field of a preceeding directory. The directory entries immediately
+// follow this structure.
+
+
+typedef struct OMFDirHeader {
+ unsigned short cbDirHeader; // length of this structure
+ unsigned short cbDirEntry; // number of bytes in each directory entry
+ unsigned long cDir; // number of directorie entries
+ long lfoNextDir; // offset from base of next directory
+ unsigned long flags; // status flags
+} OMFDirHeader;
+
+
+
+
+// directory structure
+// The data in this structure is used to reference the data for each
+// subsection of the CodeView Debug OMF information. Tables that are
+// not associated with a specific module will have a module index of
+// oxffff. These tables are the global types table, the global symbol
+// table, the global public table and the library table.
+
+
+typedef struct OMFDirEntry {
+ unsigned short SubSection; // subsection type (sst...)
+ unsigned short iMod; // module index
+ long lfo; // large file offset of subsection
+ unsigned long cb; // number of bytes in subsection
+} OMFDirEntry;
+
+
+
+// information decribing each segment in a module
+
+typedef struct OMFSegDesc {
+ unsigned short Seg; // segment index
+ unsigned short pad; // pad to maintain alignment
+ unsigned long Off; // offset of code in segment
+ unsigned long cbSeg; // number of bytes in segment
+} OMFSegDesc;
+
+
+
+
+// per module information
+// There is one of these subsection entries for each module
+// in the executable. The entry is generated by link/ilink.
+// This table will probably require padding because of the
+// variable length module name.
+
+typedef struct OMFModule {
+ unsigned short ovlNumber; // overlay number
+ unsigned short iLib; // library that the module was linked from
+ unsigned short cSeg; // count of number of segments in module
+ char Style[2]; // debugging style "CV"
+ OMFSegDesc SegInfo[1]; // describes segments in module
+ char Name[]; // length prefixed module name padded to
+ // long word boundary
+} OMFModule;
+
+
+
+// Symbol hash table format
+// This structure immediately preceeds the global publics table
+// and global symbol tables.
+
+typedef struct OMFSymHash {
+ unsigned short symhash; // symbol hash function index
+ unsigned short addrhash; // address hash function index
+ unsigned long cbSymbol; // length of symbol information
+ unsigned long cbHSym; // length of symbol hash data
+ unsigned long cbHAddr; // length of address hashdata
+} OMFSymHash;
+
+
+
+// Global types subsection format
+// This structure immediately preceeds the global types table.
+// The offsets in the typeOffset array are relative to the address
+// of ctypes. Each type entry following the typeOffset array must
+// begin on a long word boundary.
+
+typedef struct OMFTypeFlags {
+ unsigned long sig :8;
+ unsigned long unused :24;
+} OMFTypeFlags;
+
+
+typedef struct OMFGlobalTypes {
+ OMFTypeFlags flags;
+ unsigned long cTypes; // number of types
+ unsigned long typeOffset[]; // array of offsets to types
+} OMFGlobalTypes;
+
+
+
+
+// Precompiled types mapping table
+// This table should be ignored by all consumers except the incremental
+// packer.
+
+
+typedef struct OMFPreCompMap {
+ unsigned short FirstType; // first precompiled type index
+ unsigned short cTypes; // number of precompiled types
+ unsigned long signature; // precompiled types signature
+ unsigned short pad;
+ CV_typ_t map[]; // mapping of precompiled types
+} OMFPreCompMap;
+
+
+
+
+// Source line to address mapping table.
+// This table is generated by the link/ilink utility from line number
+// information contained in the object file OMF data. This table contains
+// only the code contribution for one segment from one source file.
+
+
+typedef struct OMFSourceLine {
+ unsigned short Seg; // linker segment index
+ unsigned short cLnOff; // count of line/offset pairs
+ unsigned long offset[1]; // array of offsets in segment
+ unsigned short lineNbr[1]; // array of line lumber in source
+} OMFSourceLine;
+
+typedef OMFSourceLine FAR * LPSL;
+
+
+// Source file description
+// This table is generated by the linker
+
+
+typedef struct OMFSourceFile {
+ unsigned short cSeg; // number of segments from source file
+ unsigned short reserved; // reserved
+ unsigned long baseSrcLn[1]; // base of OMFSourceLine tables
+ // this array is followed by array
+ // of segment start/end pairs followed by
+ // an array of linker indices
+ // for each segment in the file
+ unsigned short cFName; // length of source file name
+ char Name; // name of file padded to long boundary
+} OMFSourceFile;
+
+typedef OMFSourceFile FAR * LPSF;
+
+
+// Source line to address mapping header structure
+// This structure describes the number and location of the
+// OMFAddrLine tables for a module. The offSrcLine entries are
+// relative to the beginning of this structure.
+
+
+typedef struct OMFSourceModule {
+ unsigned short cFile; // number of OMFSourceTables
+ unsigned short cSeg; // number of segments in module
+ unsigned long baseSrcFile[1]; // base of OMFSourceFile table
+ // this array is followed by array
+ // of segment start/end pairs followed
+ // by an array of linker indices
+ // for each segment in the module
+} OMFSourceModule;
+
+typedef OMFSourceModule FAR * LPSM;
+
+// sstLibraries
+
+typedef struct OMFLibrary {
+ unsigned char cbLibs; // count of library names
+ char Libs[1]; // array of length prefixed lib names (first entry zero length)
+} OMFLibrary;
+
+
+// Pcode support. This subsection contains debug information generated
+// by the MPC utility used to process Pcode executables. Currently
+// it contains a mapping table from segment index (zero based) to
+// frame paragraph. MPC converts segmented exe's to non-segmented
+// exe's for DOS support. To avoid backpatching all CV info, this
+// table is provided for the mapping. Additional info may be provided
+// in the future for profiler support.
+
+typedef struct OMFMpcDebugInfo {
+ unsigned short cSeg; // number of segments in module
+ unsigned short mpSegFrame[1]; // map seg (zero based) to frame
+} OMFMpcDebugInfo;
+
+// The following structures and constants describe the format of the
+// CodeView Debug OMF for linkers that emit executables with the NB02
+// signature. Current utilities with the exception of cvpack and cvdump
+// will not accept or emit executables with the NB02 signature. Cvdump
+// will dump an unpacked executable with the NB02 signature. Cvpack will
+// read an executable with the NB02 signature but the packed executable
+// will be written with the table format, contents and signature of NB07.
+
+
+
+
+
+// subsection type constants
+
+#define SSTMODULE 0x101 // Basic info. about object module
+#define SSTPUBLIC 0x102 // Public symbols
+#define SSTTYPES 0x103 // Type information
+#define SSTSYMBOLS 0x104 // Symbol Data
+#define SSTSRCLINES 0x105 // Source line information
+#define SSTLIBRARIES 0x106 // Names of all library files used
+#define SSTIMPORTS 0x107 // Symbols for DLL fixups
+#define SSTCOMPACTED 0x108 // Compacted types section
+#define SSTSRCLNSEG 0x109 // Same as source lines, contains segment
+
+
+typedef struct DirEntry{
+ unsigned short SubSectionType;
+ unsigned short ModuleIndex;
+ long lfoStart;
+ unsigned short Size;
+} DirEntry;
+
+
+// information decribing each segment in a module
+
+typedef struct oldnsg {
+ unsigned short Seg; // segment index
+ unsigned short Off; // offset of code in segment
+ unsigned short cbSeg; // number of bytes in segment
+} oldnsg;
+
+
+// old subsection module information
+
+typedef struct oldsmd {
+ oldnsg SegInfo; // describes first segment in module
+ unsigned short ovlNbr; // overlay number
+ unsigned short iLib;
+ unsigned char cSeg; // Number of segments in module
+ char reserved;
+ unsigned char cbName[1]; // length prefixed name of module
+ oldnsg arnsg[]; // cSeg-1 structures exist for alloc text or comdat code
+} oldsmd;
+
+typedef struct{
+ unsigned short Seg;
+ unsigned long Off;
+ unsigned long cbSeg;
+} oldnsg32;
+
+typedef struct {
+ oldnsg32 SegInfo; // describes first segment in module
+ unsigned short ovlNbr; // overlay number
+ unsigned short iLib;
+ unsigned char cSeg; // Number of segments in module
+ char reserved;
+ unsigned char cbName[1]; // length prefixed name of module
+ oldnsg32 arnsg[]; // cSeg-1 structures exist for alloc text or comdat code
+} oldsmd32;
+
+// OMFSegMap - This table contains the mapping between the logical segment indices
+// used in the symbol table and the physical segments where the program is loaded
+
+typedef struct OMFSegMapDesc {
+ unsigned short flags; // descriptor flags bit field.
+ unsigned short ovl; // the logical overlay number
+ unsigned short group; // group index into the descriptor array
+ unsigned short frame; // logical segment index - interpreted via flags
+ unsigned short iSegName; // segment or group name - index into sstSegName
+ unsigned short iClassName; // class name - index into sstSegName
+ unsigned long offset; // byte offset of the logical within the physical segment
+ unsigned long cbSeg; // byte count of the logical segment or group
+} OMFSegMapDesc;
+
+typedef struct OMFSegMap {
+ unsigned short cSeg; // total number of segment descriptors
+ unsigned short cSegLog; // number of logical segment descriptors
+ OMFSegMapDesc rgDesc[0]; // array of segment descriptors
+} OMFSegMap;
+
diff --git a/private/windbg/osdebug/include/cvinfo.h b/private/windbg/osdebug/include/cvinfo.h
new file mode 100644
index 000000000..7f7dc138a
--- /dev/null
+++ b/private/windbg/osdebug/include/cvinfo.h
@@ -0,0 +1,3221 @@
+/*** cvinfo.h - Generic CodeView information definitions
+ *
+ * Structures, constants, etc. for accessing and interpreting
+ * CodeView information.
+ *
+ */
+
+
+/*** The master copy of this file resides in the langapi project.
+ * All Microsoft projects are required to use the master copy without
+ * modification. Modification of the master version or a copy
+ * without consultation with all parties concerned is extremely
+ * risky.
+ *
+ * When this file is modified, the corresponding documentation file
+ * omfdeb.doc in the langapi project must be updated.
+ */
+
+#ifndef _VC_VER_INC
+#include "..\include\vcver.h"
+#endif
+
+#ifndef _CV_INFO_INCLUDED
+#define _CV_INFO_INCLUDED
+
+#ifdef __cplusplus
+#pragma warning ( disable: 4200 )
+#endif
+
+#ifndef __INLINE
+#ifdef __cplusplus
+#define __INLINE inline
+#else
+#define __INLINE __inline
+#endif
+#endif
+
+#pragma pack ( push, 1 )
+typedef unsigned long CV_uoff32_t;
+typedef long CV_off32_t;
+typedef unsigned short CV_uoff16_t;
+typedef short CV_off16_t;
+typedef unsigned short CV_typ_t;
+
+#if !defined (CV_ZEROLEN)
+#define CV_ZEROLEN
+#endif
+
+#if !defined (FLOAT10)
+#if defined(_M_I86) // 16 bit x86 supporting long double
+typedef long double FLOAT10;
+#else // 32 bit w/o long double support
+typedef struct FLOAT10
+{
+ char b[10];
+} FLOAT10;
+#endif
+#endif
+
+
+#define CV_SIGNATURE_C6 0L // Actual signature is >64K
+#define CV_SIGNATURE_C7 1L // First explicit signature
+#define CV_SIGNATURE_RESERVED 2L // All signatures from 2 to 64K are reserved
+
+#define CV_MAXOFFSET 0xffffffff
+
+/** CodeView Symbol and Type OMF type information is broken up into two
+ * ranges. Type indices less than 0x1000 describe type information
+ * that is frequently used. Type indices above 0x1000 are used to
+ * describe more complex features such as functions, arrays and
+ * structures.
+ */
+
+
+
+
+/** Primitive types have predefined meaning that is encoded in the
+ * values of the various bit fields in the value.
+ *
+ * A CodeView primitive type is defined as:
+ *
+ * 1 1
+ * 1 089 7654 3 210
+ * r mode type r sub
+ *
+ * Where
+ * mode is the pointer mode
+ * type is a type indicator
+ * sub is a subtype enumeration
+ * r is a reserved field
+ *
+ * See Microsoft Symbol and Type OMF (Version 4.0) for more
+ * information.
+ */
+
+
+#define CV_MMASK 0x700 // mode mask
+#define CV_TMASK 0x0f0 // type mask
+
+// can we use the reserved bit ??
+#define CV_SMASK 0x00f // subtype mask
+
+#define CV_MSHIFT 8 // primitive mode right shift count
+#define CV_TSHIFT 4 // primitive type right shift count
+#define CV_SSHIFT 0 // primitive subtype right shift count
+
+// macros to extract primitive mode, type and size
+
+#define CV_MODE(typ) (((typ) & CV_MMASK) >> CV_MSHIFT)
+#define CV_TYPE(typ) (((typ) & CV_TMASK) >> CV_TSHIFT)
+#define CV_SUBT(typ) (((typ) & CV_SMASK) >> CV_SSHIFT)
+
+// macros to insert new primitive mode, type and size
+
+#define CV_NEWMODE(typ, nm) ((CV_typ_t)(((typ) & ~CV_MMASK) | ((nm) << CV_MSHIFT)))
+#define CV_NEWTYPE(typ, nt) (((typ) & ~CV_TMASK) | ((nt) << CV_TSHIFT))
+#define CV_NEWSUBT(typ, ns) (((typ) & ~CV_SMASK) | ((ns) << CV_SSHIFT))
+
+
+
+// pointer mode enumeration values
+
+typedef enum CV_prmode_e {
+ CV_TM_DIRECT = 0, // mode is not a pointer
+ CV_TM_NPTR = 1, // mode is a near pointer
+ CV_TM_FPTR = 2, // mode is a far pointer
+ CV_TM_HPTR = 3, // mode is a huge pointer
+ CV_TM_NPTR32 = 4, // mode is a 32 bit near pointer
+ CV_TM_FPTR32 = 5, // mode is a 32 bit far pointer
+ CV_TM_NPTR64 = 6, // mode is a 64 bit near pointer
+ CV_TM_NPTR128 = 7 // mode is a 128 bit near pointer
+} CV_prmode_e;
+
+
+
+
+// type enumeration values
+
+
+typedef enum CV_type_e {
+ CV_SPECIAL = 0x00, // special type size values
+ CV_SIGNED = 0x01, // signed integral size values
+ CV_UNSIGNED = 0x02, // unsigned integral size values
+ CV_BOOLEAN = 0x03, // Boolean size values
+ CV_REAL = 0x04, // real number size values
+ CV_COMPLEX = 0x05, // complex number size values
+ CV_SPECIAL2 = 0x06, // second set of special types
+ CV_INT = 0x07, // integral (int) values
+ CV_CVRESERVED = 0x0f
+} CV_type_e;
+
+
+
+
+// subtype enumeration values for CV_SPECIAL
+
+
+typedef enum CV_special_e {
+ CV_SP_NOTYPE = 0x00,
+ CV_SP_ABS = 0x01,
+ CV_SP_SEGMENT = 0x02,
+ CV_SP_VOID = 0x03,
+ CV_SP_CURRENCY = 0x04,
+ CV_SP_NBASICSTR = 0x05,
+ CV_SP_FBASICSTR = 0x06,
+ CV_SP_NOTTRANS = 0x07
+} CV_special_e;
+
+
+
+
+// subtype enumeration values for CV_SPECIAL2
+
+
+typedef enum CV_special2_e {
+ CV_S2_BIT = 0x00,
+ CV_S2_PASCHAR = 0x01 // Pascal CHAR
+} CV_special2_e;
+
+
+
+
+
+// subtype enumeration values for CV_SIGNED, CV_UNSIGNED and CV_BOOLEAN
+
+
+typedef enum CV_integral_e {
+ CV_IN_1BYTE = 0x00,
+ CV_IN_2BYTE = 0x01,
+ CV_IN_4BYTE = 0x02,
+ CV_IN_8BYTE = 0x03,
+ CV_IN_16BYTE = 0x04
+} CV_integral_e;
+
+
+
+
+
+// subtype enumeration values for CV_REAL and CV_COMPLEX
+
+
+typedef enum CV_real_e {
+ CV_RC_REAL32 = 0x00,
+ CV_RC_REAL64 = 0x01,
+ CV_RC_REAL80 = 0x02,
+ CV_RC_REAL128 = 0x03,
+ CV_RC_REAL48 = 0x04
+} CV_real_e;
+
+
+
+
+// subtype enumeration values for CV_INT (really int)
+
+
+typedef enum CV_int_e {
+ CV_RI_CHAR = 0x00,
+ CV_RI_INT1 = 0x00,
+ CV_RI_WCHAR = 0x01,
+ CV_RI_UINT1 = 0x01,
+ CV_RI_INT2 = 0x02,
+ CV_RI_UINT2 = 0x03,
+ CV_RI_INT4 = 0x04,
+ CV_RI_UINT4 = 0x05,
+ CV_RI_INT8 = 0x06,
+ CV_RI_UINT8 = 0x07,
+ CV_RI_INT16 = 0x08,
+ CV_RI_UINT16 = 0x09
+} CV_int_e;
+
+
+
+
+// macros to check the type of a primitive
+
+#define CV_TYP_IS_DIRECT(typ) (CV_MODE(typ) == CV_TM_DIRECT)
+#define CV_TYP_IS_PTR(typ) (CV_MODE(typ) != CV_TM_DIRECT)
+#define CV_TYP_IS_NPTR(typ) (CV_MODE(typ) == CV_TM_NPTR)
+#define CV_TYP_IS_FPTR(typ) (CV_MODE(typ) == CV_TM_FPTR)
+#define CV_TYP_IS_HPTR(typ) (CV_MODE(typ) == CV_TM_HPTR)
+#define CV_TYP_IS_NPTR32(typ) (CV_MODE(typ) == CV_TM_NPTR32)
+#define CV_TYP_IS_FPTR32(typ) (CV_MODE(typ) == CV_TM_FPTR32)
+
+#define CV_TYP_IS_SIGNED(typ) (((CV_TYPE(typ) == CV_SIGNED) && CV_TYP_IS_DIRECT(typ)) || \
+ (typ == T_INT1) || \
+ (typ == T_INT2) || \
+ (typ == T_INT4) || \
+ (typ == T_INT8) || \
+ (typ == T_INT16) || \
+ (typ == T_RCHAR))
+
+#define CV_TYP_IS_UNSIGNED(typ) (((CV_TYPE(typ) == CV_UNSIGNED) && CV_TYP_IS_DIRECT(typ)) || \
+ (typ == T_UINT1) || \
+ (typ == T_UINT2) || \
+ (typ == T_UINT4) || \
+ (typ == T_UINT8) || \
+ (typ == T_UINT16))
+
+#define CV_TYP_IS_REAL(typ) ((CV_TYPE(typ) == CV_REAL) && CV_TYP_IS_DIRECT(typ))
+
+#define CV_FIRST_NONPRIM 0x1000
+#define CV_IS_PRIMITIVE(typ) ((typ) < CV_FIRST_NONPRIM)
+#define CV_TYP_IS_COMPLEX(typ) ((CV_TYPE(typ) == CV_COMPLEX) && CV_TYP_IS_DIRECT(typ))
+
+
+
+
+// selected values for type_index - for a more complete definition, see
+// Microsoft Symbol and Type OMF document
+
+
+
+
+// Special Types
+
+
+#define T_NOTYPE 0x0000 // uncharacterized type (no type)
+#define T_ABS 0x0001 // absolute symbol
+#define T_SEGMENT 0x0002 // segment type
+#define T_VOID 0x0003 // void
+#define T_PVOID 0x0103 // near pointer to void
+#define T_PFVOID 0x0203 // far pointer to void
+#define T_PHVOID 0x0303 // huge pointer to void
+#define T_32PVOID 0x0403 // 16:32 near pointer to void
+#define T_32PFVOID 0x0503 // 16:32 far pointer to void
+#define T_CURRENCY 0x0004 // BASIC 8 byte currency value
+#define T_NBASICSTR 0x0005 // Near BASIC string
+#define T_FBASICSTR 0x0006 // Far BASIC string
+#define T_NOTTRANS 0x0007 // type not translated by cvpack
+#define T_BIT 0x0060 // bit
+#define T_PASCHAR 0x0061 // Pascal CHAR
+
+
+
+// Character types
+
+
+#define T_CHAR 0x0010 // 8 bit signed
+#define T_UCHAR 0x0020 // 8 bit unsigned
+#define T_PCHAR 0x0110 // near pointer to 8 bit signed
+#define T_PUCHAR 0x0120 // near pointer to 8 bit unsigned
+#define T_PFCHAR 0x0210 // far pointer to 8 bit signed
+#define T_PFUCHAR 0x0220 // far pointer to 8 bit unsigned
+#define T_PHCHAR 0x0310 // huge pointer to 8 bit signed
+#define T_PHUCHAR 0x0320 // huge pointer to 8 bit unsigned
+#define T_32PCHAR 0x0410 // 16:32 near pointer to 8 bit signed
+#define T_32PUCHAR 0x0420 // 16:32 near pointer to 8 bit unsigned
+#define T_32PFCHAR 0x0510 // 16:32 far pointer to 8 bit signed
+#define T_32PFUCHAR 0x0520 // 16:32 far pointer to 8 bit unsigned
+
+
+
+
+// really a character types
+
+#define T_RCHAR 0x0070 // really a char
+#define T_PRCHAR 0x0170 // 16:16 near pointer to a real char
+#define T_PFRCHAR 0x0270 // 16:16 far pointer to a real char
+#define T_PHRCHAR 0x0370 // 16:16 huge pointer to a real char
+#define T_32PRCHAR 0x0470 // 16:32 near pointer to a real char
+#define T_32PFRCHAR 0x0570 // 16:32 far pointer to a real char
+
+
+
+
+// really a wide character types
+
+#define T_WCHAR 0x0071 // wide char
+#define T_PWCHAR 0x0171 // 16:16 near pointer to a wide char
+#define T_PFWCHAR 0x0271 // 16:16 far pointer to a wide char
+#define T_PHWCHAR 0x0371 // 16:16 huge pointer to a wide char
+#define T_32PWCHAR 0x0471 // 16:32 near pointer to a wide char
+#define T_32PFWCHAR 0x0571 // 16:32 far pointer to a wide char
+
+
+// 8 bit int types
+
+
+#define T_INT1 0x0068 // 8 bit signed int
+#define T_UINT1 0x0069 // 8 bit unsigned int
+#define T_PINT1 0x0168 // near pointer to 8 bit signed int
+#define T_PUINT1 0x0169 // near pointer to 8 bit unsigned int
+#define T_PFINT1 0x0268 // far pointer to 8 bit signed int
+#define T_PFUINT1 0x0269 // far pointer to 8 bit unsigned int
+#define T_PHINT1 0x0368 // huge pointer to 8 bit signed int
+#define T_PHUINT1 0x0369 // huge pointer to 8 bit unsigned int
+
+#define T_32PINT1 0x0468 // 16:32 near pointer to 8 bit signed int
+#define T_32PUINT1 0x0469 // 16:32 near pointer to 8 bit unsigned int
+#define T_32PFINT1 0x0568 // 16:32 far pointer to 8 bit signed int
+#define T_32PFUINT1 0x0569 // 16:32 far pointer to 8 bit unsigned int
+
+
+// 16 bit short types
+
+
+#define T_SHORT 0x0011 // 16 bit signed
+#define T_USHORT 0x0021 // 16 bit unsigned
+#define T_PSHORT 0x0111 // near pointer to 16 bit signed
+#define T_PUSHORT 0x0121 // near pointer to 16 bit unsigned
+#define T_PFSHORT 0x0211 // far pointer to 16 bit signed
+#define T_PFUSHORT 0x0221 // far pointer to 16 bit unsigned
+#define T_PHSHORT 0x0311 // huge pointer to 16 bit signed
+#define T_PHUSHORT 0x0321 // huge pointer to 16 bit unsigned
+
+#define T_32PSHORT 0x0411 // 16:32 near pointer to 16 bit signed
+#define T_32PUSHORT 0x0421 // 16:32 near pointer to 16 bit unsigned
+#define T_32PFSHORT 0x0511 // 16:32 far pointer to 16 bit signed
+#define T_32PFUSHORT 0x0521 // 16:32 far pointer to 16 bit unsigned
+
+
+
+
+// 16 bit int types
+
+
+#define T_INT2 0x0072 // 16 bit signed int
+#define T_UINT2 0x0073 // 16 bit unsigned int
+#define T_PINT2 0x0172 // near pointer to 16 bit signed int
+#define T_PUINT2 0x0173 // near pointer to 16 bit unsigned int
+#define T_PFINT2 0x0272 // far pointer to 16 bit signed int
+#define T_PFUINT2 0x0273 // far pointer to 16 bit unsigned int
+#define T_PHINT2 0x0372 // huge pointer to 16 bit signed int
+#define T_PHUINT2 0x0373 // huge pointer to 16 bit unsigned int
+
+#define T_32PINT2 0x0472 // 16:32 near pointer to 16 bit signed int
+#define T_32PUINT2 0x0473 // 16:32 near pointer to 16 bit unsigned int
+#define T_32PFINT2 0x0572 // 16:32 far pointer to 16 bit signed int
+#define T_32PFUINT2 0x0573 // 16:32 far pointer to 16 bit unsigned int
+
+
+
+
+// 32 bit long types
+
+
+#define T_LONG 0x0012 // 32 bit signed
+#define T_ULONG 0x0022 // 32 bit unsigned
+#define T_PLONG 0x0112 // near pointer to 32 bit signed
+#define T_PULONG 0x0122 // near pointer to 32 bit unsigned
+#define T_PFLONG 0x0212 // far pointer to 32 bit signed
+#define T_PFULONG 0x0222 // far pointer to 32 bit unsigned
+#define T_PHLONG 0x0312 // huge pointer to 32 bit signed
+#define T_PHULONG 0x0322 // huge pointer to 32 bit unsigned
+
+#define T_32PLONG 0x0412 // 16:32 near pointer to 32 bit signed
+#define T_32PULONG 0x0422 // 16:32 near pointer to 32 bit unsigned
+#define T_32PFLONG 0x0512 // 16:32 far pointer to 32 bit signed
+#define T_32PFULONG 0x0522 // 16:32 far pointer to 32 bit unsigned
+
+
+
+
+// 32 bit int types
+
+
+#define T_INT4 0x0074 // 32 bit signed int
+#define T_UINT4 0x0075 // 32 bit unsigned int
+#define T_PINT4 0x0174 // near pointer to 32 bit signed int
+#define T_PUINT4 0x0175 // near pointer to 32 bit unsigned int
+#define T_PFINT4 0x0274 // far pointer to 32 bit signed int
+#define T_PFUINT4 0x0275 // far pointer to 32 bit unsigned int
+#define T_PHINT4 0x0374 // huge pointer to 32 bit signed int
+#define T_PHUINT4 0x0375 // huge pointer to 32 bit unsigned int
+
+#define T_32PINT4 0x0474 // 16:32 near pointer to 32 bit signed int
+#define T_32PUINT4 0x0475 // 16:32 near pointer to 32 bit unsigned int
+#define T_32PFINT4 0x0574 // 16:32 far pointer to 32 bit signed int
+#define T_32PFUINT4 0x0575 // 16:32 far pointer to 32 bit unsigned int
+
+
+
+
+// 64 bit quad types
+
+
+#define T_QUAD 0x0013 // 64 bit signed
+#define T_UQUAD 0x0023 // 64 bit unsigned
+#define T_PQUAD 0x0113 // near pointer to 64 bit signed
+#define T_PUQUAD 0x0123 // near pointer to 64 bit unsigned
+#define T_PFQUAD 0x0213 // far pointer to 64 bit signed
+#define T_PFUQUAD 0x0223 // far pointer to 64 bit unsigned
+#define T_PHQUAD 0x0313 // huge pointer to 64 bit signed
+#define T_PHUQUAD 0x0323 // huge pointer to 64 bit unsigned
+#define T_32PQUAD 0x0413 // 16:32 near pointer to 64 bit signed
+#define T_32PUQUAD 0x0423 // 16:32 near pointer to 64 bit unsigned
+#define T_32PFQUAD 0x0513 // 16:32 far pointer to 64 bit signed
+#define T_32PFUQUAD 0x0523 // 16:32 far pointer to 64 bit unsigned
+
+
+
+// 64 bit int types
+
+
+#define T_INT8 0x0076 // 64 bit signed int
+#define T_UINT8 0x0077 // 64 bit unsigned int
+#define T_PINT8 0x0176 // near pointer to 64 bit signed int
+#define T_PUINT8 0x0177 // near pointer to 64 bit unsigned int
+#define T_PFINT8 0x0276 // far pointer to 64 bit signed int
+#define T_PFUINT8 0x0277 // far pointer to 64 bit unsigned int
+#define T_PHINT8 0x0376 // huge pointer to 64 bit signed int
+#define T_PHUINT8 0x0377 // huge pointer to 64 bit unsigned int
+
+#define T_32PINT8 0x0476 // 16:32 near pointer to 64 bit signed int
+#define T_32PUINT8 0x0477 // 16:32 near pointer to 64 bit unsigned int
+#define T_32PFINT8 0x0576 // 16:32 far pointer to 64 bit signed int
+#define T_32PFUINT8 0x0577 // 16:32 far pointer to 64 bit unsigned int
+
+
+// 128 bit octet types
+
+
+#define T_OCT 0x0014 // 128 bit signed
+#define T_UOCT 0x0024 // 128 bit unsigned
+#define T_POCT 0x0114 // near pointer to 128 bit signed
+#define T_PUOCT 0x0124 // near pointer to 128 bit unsigned
+#define T_PFOCT 0x0214 // far pointer to 128 bit signed
+#define T_PFUOCT 0x0224 // far pointer to 128 bit unsigned
+#define T_PHOCT 0x0314 // huge pointer to 128 bit signed
+#define T_PHUOCT 0x0324 // huge pointer to 128 bit unsigned
+
+#define T_32POCT 0x0414 // 16:32 near pointer to 128 bit signed
+#define T_32PUOCT 0x0424 // 16:32 near pointer to 128 bit unsigned
+#define T_32PFOCT 0x0514 // 16:32 far pointer to 128 bit signed
+#define T_32PFUOCT 0x0524 // 16:32 far pointer to 128 bit unsigned
+
+// 128 bit int types
+
+
+#define T_INT16 0x0078 // 128 bit signed int
+#define T_UINT16 0x0079 // 128 bit unsigned int
+#define T_PINT16 0x0178 // near pointer to 128 bit signed int
+#define T_PUINT16 0x0179 // near pointer to 128 bit unsigned int
+#define T_PFINT16 0x0278 // far pointer to 128 bit signed int
+#define T_PFUINT16 0x0279 // far pointer to 128 bit unsigned int
+#define T_PHINT16 0x0378 // huge pointer to 128 bit signed int
+#define T_PHUINT16 0x0379 // huge pointer to 128 bit unsigned int
+
+#define T_32PINT16 0x0478 // 16:32 near pointer to 128 bit signed int
+#define T_32PUINT16 0x0479 // 16:32 near pointer to 128 bit unsigned int
+#define T_32PFINT16 0x0578 // 16:32 far pointer to 128 bit signed int
+#define T_32PFUINT16 0x0579 // 16:32 far pointer to 128 bit unsigned int
+
+
+
+
+
+// 32 bit real types
+
+
+#define T_REAL32 0x0040 // 32 bit real
+#define T_PREAL32 0x0140 // near pointer to 32 bit real
+#define T_PFREAL32 0x0240 // far pointer to 32 bit real
+#define T_PHREAL32 0x0340 // huge pointer to 32 bit real
+#define T_32PREAL32 0x0440 // 16:32 near pointer to 32 bit real
+#define T_32PFREAL32 0x0540 // 16:32 far pointer to 32 bit real
+
+
+
+// 48 bit real types
+
+
+#define T_REAL48 0x0044 // 48 bit real
+#define T_PREAL48 0x0144 // near pointer to 48 bit real
+#define T_PFREAL48 0x0244 // far pointer to 48 bit real
+#define T_PHREAL48 0x0344 // huge pointer to 48 bit real
+#define T_32PREAL48 0x0444 // 16:32 near pointer to 48 bit real
+#define T_32PFREAL48 0x0544 // 16:32 far pointer to 48 bit real
+
+
+
+
+// 64 bit real types
+
+
+#define T_REAL64 0x0041 // 64 bit real
+#define T_PREAL64 0x0141 // near pointer to 64 bit real
+#define T_PFREAL64 0x0241 // far pointer to 64 bit real
+#define T_PHREAL64 0x0341 // huge pointer to 64 bit real
+#define T_32PREAL64 0x0441 // 16:32 near pointer to 64 bit real
+#define T_32PFREAL64 0x0541 // 16:32 far pointer to 64 bit real
+
+
+
+
+// 80 bit real types
+
+
+#define T_REAL80 0x0042 // 80 bit real
+#define T_PREAL80 0x0142 // near pointer to 80 bit real
+#define T_PFREAL80 0x0242 // far pointer to 80 bit real
+#define T_PHREAL80 0x0342 // huge pointer to 80 bit real
+#define T_32PREAL80 0x0442 // 16:32 near pointer to 80 bit real
+#define T_32PFREAL80 0x0542 // 16:32 far pointer to 80 bit real
+
+
+
+
+// 128 bit real types
+
+
+#define T_REAL128 0x0043 // 128 bit real
+#define T_PREAL128 0x0143 // near pointer to 128 bit real
+#define T_PFREAL128 0x0243 // far pointer to 128 bit real
+#define T_PHREAL128 0x0343 // huge pointer to 128 bit real
+#define T_32PREAL128 0x0443 // 16:32 near pointer to 128 bit real
+#define T_32PFREAL128 0x0543 // 16:32 far pointer to 128 bit real
+
+
+
+
+// 32 bit complex types
+
+
+#define T_CPLX32 0x0050 // 32 bit complex
+#define T_PCPLX32 0x0150 // near pointer to 32 bit complex
+#define T_PFCPLX32 0x0250 // far pointer to 32 bit complex
+#define T_PHCPLX32 0x0350 // huge pointer to 32 bit complex
+#define T_32PCPLX32 0x0450 // 16:32 near pointer to 32 bit complex
+#define T_32PFCPLX32 0x0550 // 16:32 far pointer to 32 bit complex
+
+
+
+
+// 64 bit complex types
+
+
+#define T_CPLX64 0x0051 // 64 bit complex
+#define T_PCPLX64 0x0151 // near pointer to 64 bit complex
+#define T_PFCPLX64 0x0251 // far pointer to 64 bit complex
+#define T_PHCPLX64 0x0351 // huge pointer to 64 bit complex
+#define T_32PCPLX64 0x0451 // 16:32 near pointer to 64 bit complex
+#define T_32PFCPLX64 0x0551 // 16:32 far pointer to 64 bit complex
+
+
+
+
+// 80 bit complex types
+
+
+#define T_CPLX80 0x0052 // 80 bit complex
+#define T_PCPLX80 0x0152 // near pointer to 80 bit complex
+#define T_PFCPLX80 0x0252 // far pointer to 80 bit complex
+#define T_PHCPLX80 0x0352 // huge pointer to 80 bit complex
+#define T_32PCPLX80 0x0452 // 16:32 near pointer to 80 bit complex
+#define T_32PFCPLX80 0x0552 // 16:32 far pointer to 80 bit complex
+
+
+
+
+// 128 bit complex types
+
+
+#define T_CPLX128 0x0053 // 128 bit complex
+#define T_PCPLX128 0x0153 // near pointer to 128 bit complex
+#define T_PFCPLX128 0x0253 // far pointer to 128 bit complex
+#define T_PHCPLX128 0x0353 // huge pointer to 128 bit real
+#define T_32PCPLX128 0x0453 // 16:32 near pointer to 128 bit complex
+#define T_32PFCPLX128 0x0553 // 16:32 far pointer to 128 bit complex
+
+
+
+
+// boolean types
+
+
+#define T_BOOL08 0x0030 // 8 bit boolean
+#define T_BOOL16 0x0031 // 16 bit boolean
+#define T_BOOL32 0x0032 // 32 bit boolean
+#define T_BOOL64 0x0033 // 64 bit boolean
+#define T_PBOOL08 0x0130 // near pointer to 8 bit boolean
+#define T_PBOOL16 0x0131 // near pointer to 16 bit boolean
+#define T_PBOOL32 0x0132 // near pointer to 32 bit boolean
+#define T_PBOOL64 0x0133 // near pointer to 64 bit boolean
+#define T_PFBOOL08 0x0230 // far pointer to 8 bit boolean
+#define T_PFBOOL16 0x0231 // far pointer to 16 bit boolean
+#define T_PFBOOL32 0x0232 // far pointer to 32 bit boolean
+#define T_PFBOOL64 0x0233 // far pointer to 64 bit boolean
+#define T_PHBOOL08 0x0330 // huge pointer to 8 bit boolean
+#define T_PHBOOL16 0x0331 // huge pointer to 16 bit boolean
+#define T_PHBOOL32 0x0332 // huge pointer to 32 bit boolean
+#define T_PHBOOL64 0x0333 // huge pointer to 64 bit boolean
+
+#define T_32PBOOL08 0x0430 // 16:32 near pointer to 8 bit boolean
+#define T_32PFBOOL08 0x0530 // 16:32 far pointer to 8 bit boolean
+#define T_32PBOOL16 0x0431 // 16:32 near pointer to 18 bit boolean
+#define T_32PFBOOL16 0x0531 // 16:32 far pointer to 16 bit boolean
+#define T_32PBOOL32 0x0432 // 16:32 near pointer to 32 bit boolean
+#define T_32PFBOOL32 0x0532 // 16:32 far pointer to 32 bit boolean
+#define T_32PBOOL64 0x0433 // 16:32 near pointer to 64 bit boolean
+#define T_32PFBOOL64 0x0533 // 16:32 far pointer to 64 bit boolean
+
+
+#define T_NCVPTR 0x01f0 // CV Internal type for created near pointers
+#define T_FCVPTR 0x02f0 // CV Internal type for created far pointers
+#define T_HCVPTR 0x03f0 // CV Internal type for created huge pointers
+#define T_32NCVPTR 0x04f0 // CV Internal type for created near 32-bit pointers
+#define T_32FCVPTR 0x05f0 // CV Internal type for created far 32-bit pointers
+#define T_64NCVPTR 0x06f0 // CV Internal type for created near 64-bit pointers
+
+#define CV_IS_INTERNAL_PTR(typ) (CV_IS_PRIMITIVE(typ) && \
+ CV_TYPE(typ) == CV_CVRESERVED && \
+ CV_TYP_IS_PTR(typ))
+
+
+/** No leaf index can have a value of 0x0000. The leaf indices are
+ * separated into ranges depending upon the use of the type record.
+ * The second range is for the type records that are directly referenced
+ * in symbols. The first range is for type records that are not
+ * referenced by symbols but instead are referenced by other type
+ * records. All type records must have a starting leaf index in these
+ * first two ranges. The third range of leaf indices are used to build
+ * up complex lists such as the field list of a class type record. No
+ * type record can begin with one of the leaf indices. The fourth ranges
+ * of type indices are used to represent numeric data in a symbol or
+ * type record. These leaf indices are greater than 0x8000. At the
+ * point that type or symbol processor is expecting a numeric field, the
+ * next two bytes in the type record are examined. If the value is less
+ * than 0x8000, then the two bytes contain the numeric value. If the
+ * value is greater than 0x8000, then the data follows the leaf index in
+ * a format specified by the leaf index. The final range of leaf indices
+ * are used to force alignment of subfields within a complex type record..
+ */
+
+
+
+ // leaf indices starting records but referenced from symbol records
+
+#define LF_MODIFIER 0x0001
+#define LF_POINTER 0x0002
+#define LF_ARRAY 0x0003
+#define LF_CLASS 0x0004
+#define LF_STRUCTURE 0x0005
+#define LF_UNION 0x0006
+#define LF_ENUM 0x0007
+#define LF_PROCEDURE 0x0008
+#define LF_MFUNCTION 0x0009
+#define LF_VTSHAPE 0x000a
+#define LF_COBOL0 0x000b
+#define LF_COBOL1 0x000c
+#define LF_BARRAY 0x000d
+#define LF_LABEL 0x000e
+#define LF_NULL 0x000f
+#define LF_NOTTRAN 0x0010
+#define LF_DIMARRAY 0x0011
+#define LF_VFTPATH 0x0012
+#define LF_PRECOMP 0x0013 // not referenced from symbol
+#define LF_ENDPRECOMP 0x0014 // not referenced from symbol
+#define LF_OEM 0x0015 // oem definable type string
+#define LF_TYPESERVER 0x0016 // not referenced from symbol
+
+ // leaf indices starting records but referenced only from type records
+
+#define LF_SKIP 0x0200
+#define LF_ARGLIST 0x0201
+#define LF_DEFARG 0x0202
+#define LF_LIST 0x0203
+#define LF_FIELDLIST 0x0204
+#define LF_DERIVED 0x0205
+#define LF_BITFIELD 0x0206
+#define LF_METHODLIST 0x0207
+#define LF_DIMCONU 0x0208
+#define LF_DIMCONLU 0x0209
+#define LF_DIMVARU 0x020a
+#define LF_DIMVARLU 0x020b
+#define LF_REFSYM 0x020c
+
+#define LF_BCLASS 0x0400
+#define LF_VBCLASS 0x0401
+#define LF_IVBCLASS 0x0402
+#define LF_ENUMERATE 0x0403
+#define LF_FRIENDFCN 0x0404
+#define LF_INDEX 0x0405
+#define LF_MEMBER 0x0406
+#define LF_STMEMBER 0x0407
+#define LF_METHOD 0x0408
+#define LF_NESTTYPE 0x0409
+#define LF_VFUNCTAB 0x040a
+#define LF_FRIENDCLS 0x040b
+#define LF_ONEMETHOD 0x040c
+#define LF_VFUNCOFF 0x040d
+#define LF_NESTTYPEEX 0x040e
+#define LF_MEMBERMODIFY 0x040f
+
+#define LF_NUMERIC 0x8000
+#define LF_CHAR 0x8000
+#define LF_SHORT 0x8001
+#define LF_USHORT 0x8002
+#define LF_LONG 0x8003
+#define LF_ULONG 0x8004
+#define LF_REAL32 0x8005
+#define LF_REAL64 0x8006
+#define LF_REAL80 0x8007
+#define LF_REAL128 0x8008
+#define LF_QUADWORD 0x8009
+#define LF_UQUADWORD 0x800a
+#define LF_REAL48 0x800b
+#define LF_COMPLEX32 0x800c
+#define LF_COMPLEX64 0x800d
+#define LF_COMPLEX80 0x800e
+#define LF_COMPLEX128 0x800f
+#define LF_VARSTRING 0x8010
+
+#define LF_OCTWORD 0x8017
+#define LF_UOCTWORD 0x8018
+
+#define LF_PAD0 0xf0
+#define LF_PAD1 0xf1
+#define LF_PAD2 0xf2
+#define LF_PAD3 0xf3
+#define LF_PAD4 0xf4
+#define LF_PAD5 0xf5
+#define LF_PAD6 0xf6
+#define LF_PAD7 0xf7
+#define LF_PAD8 0xf8
+#define LF_PAD9 0xf9
+#define LF_PAD10 0xfa
+#define LF_PAD11 0xfb
+#define LF_PAD12 0xfc
+#define LF_PAD13 0xfd
+#define LF_PAD14 0xfe
+#define LF_PAD15 0xff
+
+// end of leaf indices
+
+
+
+
+// Type enum for pointer records
+// Pointers can be one of the following types
+
+
+typedef enum CV_ptrtype_e {
+ CV_PTR_NEAR = 0x00, // near pointer
+ CV_PTR_FAR = 0x01, // far pointer
+ CV_PTR_HUGE = 0x02, // huge pointer
+ CV_PTR_BASE_SEG = 0x03, // based on segment
+ CV_PTR_BASE_VAL = 0x04, // based on value of base
+ CV_PTR_BASE_SEGVAL = 0x05, // based on segment value of base
+ CV_PTR_BASE_ADDR = 0x06, // based on address of base
+ CV_PTR_BASE_SEGADDR = 0x07, // based on segment address of base
+ CV_PTR_BASE_TYPE = 0x08, // based on type
+ CV_PTR_BASE_SELF = 0x09, // based on self
+ CV_PTR_NEAR32 = 0x0a, // 16:32 near pointer
+ CV_PTR_FAR32 = 0x0b, // 16:32 far pointer
+ CV_PTR_UNUSEDPTR = 0x0c // first unused pointer type
+} CV_ptrtype_e;
+
+
+
+
+
+// Mode enum for pointers
+// Pointers can have one of the following modes
+
+
+typedef enum CV_ptrmode_e {
+ CV_PTR_MODE_PTR = 0x00, // "normal" pointer
+ CV_PTR_MODE_REF = 0x01, // reference
+ CV_PTR_MODE_PMEM = 0x02, // pointer to data member
+ CV_PTR_MODE_PMFUNC = 0x03, // pointer to member function
+ CV_PTR_MODE_RESERVED= 0x04 // first unused pointer mode
+} CV_ptrmode_e;
+
+
+
+
+// Enumeration for function call type
+
+
+typedef enum CV_call_e {
+ CV_CALL_NEAR_C = 0x00, // near right to left push, caller pops stack
+ CV_CALL_FAR_C = 0x01, // far right to left push, caller pops stack
+ CV_CALL_NEAR_PASCAL = 0x02, // near left to right push, callee pops stack
+ CV_CALL_FAR_PASCAL = 0x03, // far left to right push, callee pops stack
+ CV_CALL_NEAR_FAST = 0x04, // near left to right push with regs, callee pops stack
+ CV_CALL_FAR_FAST = 0x05, // far left to right push with regs, callee pops stack
+ CV_CALL_SKIPPED = 0x06, // skipped (unused) call index
+ CV_CALL_NEAR_STD = 0x07, // near standard call
+ CV_CALL_FAR_STD = 0x08, // far standard call
+ CV_CALL_NEAR_SYS = 0x09, // near sys call
+ CV_CALL_FAR_SYS = 0x0a, // far sys call
+ CV_CALL_THISCALL = 0x0b, // this call (this passed in register)
+ CV_CALL_MIPSCALL = 0x0c, // Mips call
+ CV_CALL_GENERIC = 0x0d, // Generic call sequence
+ CV_CALL_ALPHACALL = 0x0e, // Alpha call
+ CV_CALL_PPCCALL = 0x0f, // PPC call
+ CV_CALL_RESERVED = 0x10 // first unused call enumeration
+} CV_call_e;
+
+
+
+
+// Values for the access protection of class attributes
+
+
+typedef enum CV_access_e {
+ CV_private = 1,
+ CV_protected = 2,
+ CV_public = 3
+} CV_access_e;
+
+
+
+// enumeration for method properties
+
+typedef enum CV_methodprop_e {
+ CV_MTvanilla = 0x00,
+ CV_MTvirtual = 0x01,
+ CV_MTstatic = 0x02,
+ CV_MTfriend = 0x03,
+ CV_MTintro = 0x04,
+ CV_MTpurevirt = 0x05,
+ CV_MTpureintro = 0x06
+} CV_methodprop_e;
+
+
+
+
+// enumeration for virtual shape table entries
+
+typedef enum CV_VTS_desc_e {
+ CV_VTS_near = 0x00,
+ CV_VTS_far = 0x01,
+ CV_VTS_thin = 0x02,
+ CV_VTS_outer = 0x03,
+ CV_VTS_meta = 0x04,
+ CV_VTS_near32 = 0x05,
+ CV_VTS_far32 = 0x06,
+ CV_VTS_unused = 0x07
+} CV_VTS_desc_e;
+
+
+
+
+// enumeration for LF_LABEL address modes
+
+typedef enum CV_LABEL_TYPE_e {
+ CV_LABEL_NEAR = 0, // near return
+ CV_LABEL_FAR = 4 // far return
+} CV_LABEL_TYPE_e;
+
+
+
+// enumeration for LF_MODIFIER values
+
+
+typedef struct CV_modifier_t {
+ unsigned short MOD_const :1;
+ unsigned short MOD_volatile :1;
+ unsigned short MOD_unaligned :1;
+ unsigned short MOD_unused :13;
+} CV_modifier_t;
+
+
+// bit field structure describing class/struct/union/enum properties
+
+typedef struct CV_prop_t {
+ unsigned short packed :1; // true if structure is packed
+ unsigned short ctor :1; // true if constructors or destructors present
+ unsigned short ovlops :1; // true if overloaded operators present
+ unsigned short isnested :1; // true if this is a nested class
+ unsigned short cnested :1; // true if this class contains nested types
+ unsigned short opassign :1; // true if overloaded assignment (=)
+ unsigned short opcast :1; // true if casting methods
+ unsigned short fwdref :1; // true if forward reference (incomplete defn)
+ unsigned short scoped :1; // scoped definition
+ unsigned short reserved :7;
+} CV_prop_t;
+
+
+
+
+// class field attribute
+
+typedef struct CV_fldattr_t {
+ unsigned short access :2; // access protection CV_access_t
+ unsigned short mprop :3; // method properties CV_methodprop_t
+ unsigned short pseudo :1; // compiler generated fcn and does not exist
+ unsigned short noinherit :1; // true if class cannot be inherited
+ unsigned short noconstruct :1; // true if class cannot be constructed
+ unsigned short compgenx :1; // compiler generated fcn and does exist
+ unsigned short unused :7; // unused
+} CV_fldattr_t;
+
+
+
+// Structures to access to the type records
+
+
+typedef struct TYPTYPE {
+ unsigned short len;
+ unsigned short leaf;
+ unsigned char data[CV_ZEROLEN];
+} TYPTYPE; // general types record
+
+
+__INLINE char *NextType (char * pType) {
+ return (pType + ((TYPTYPE *)pType)->len + sizeof(unsigned short));
+}
+
+typedef enum CV_PMEMBER {
+ CV_PDM16_NONVIRT = 0x00, // 16:16 data no virtual fcn or base
+ CV_PDM16_VFCN = 0x01, // 16:16 data with virtual functions
+ CV_PDM16_VBASE = 0x02, // 16:16 data with virtual bases
+ CV_PDM32_NVVFCN = 0x03, // 16:32 data w/wo virtual functions
+ CV_PDM32_VBASE = 0x04, // 16:32 data with virtual bases
+
+ CV_PMF16_NEARNVSA = 0x05, // 16:16 near method nonvirtual single address point
+ CV_PMF16_NEARNVMA = 0x06, // 16:16 near method nonvirtual multiple address points
+ CV_PMF16_NEARVBASE = 0x07, // 16:16 near method virtual bases
+ CV_PMF16_FARNVSA = 0x08, // 16:16 far method nonvirtual single address point
+ CV_PMF16_FARNVMA = 0x09, // 16:16 far method nonvirtual multiple address points
+ CV_PMF16_FARVBASE = 0x0a, // 16:16 far method virtual bases
+
+ CV_PMF32_NVSA = 0x0b, // 16:32 method nonvirtual single address point
+ CV_PMF32_NVMA = 0x0c, // 16:32 method nonvirtual multiple address point
+ CV_PMF32_VBASE = 0x0d // 16:32 method virtual bases
+} CV_PMEMBER;
+
+
+
+// memory representation of pointer to member. These representations are
+// indexed by the enumeration above in the LF_POINTER record
+
+
+
+
+// representation of a 16:16 pointer to data for a class with no
+// virtual functions or virtual bases
+
+
+struct CV_PDMR16_NONVIRT {
+ CV_off16_t mdisp; // displacement to data (NULL = -1)
+};
+
+
+
+
+// representation of a 16:16 pointer to data for a class with virtual
+// functions
+
+
+struct CV_PMDR16_VFCN {
+ CV_off16_t mdisp; // displacement to data ( NULL = 0)
+};
+
+
+
+
+// representation of a 16:16 pointer to data for a class with
+// virtual bases
+
+
+struct CV_PDMR16_VBASE {
+ CV_off16_t mdisp; // displacement to data
+ CV_off16_t pdisp; // this pointer displacement to vbptr
+ CV_off16_t vdisp; // displacement within vbase table
+ // NULL = (,,0xffff)
+};
+
+
+
+
+// representation of a 16:32 near pointer to data for a class with
+// or without virtual functions and no virtual bases
+
+
+struct CV_PDMR32_NVVFCN {
+ CV_off32_t mdisp; // displacement to data (NULL = 0x80000000)
+};
+
+
+
+
+// representation of a 16:32 near pointer to data for a class
+// with virtual bases
+
+
+struct CV_PDMR32_VBASE {
+ CV_off32_t mdisp; // displacement to data
+ CV_off32_t pdisp; // this pointer displacement
+ CV_off32_t vdisp; // vbase table displacement
+ // NULL = (,,0xffffffff)
+};
+
+
+
+
+// representation of a 16:16 pointer to near member function for a
+// class with no virtual functions or bases and a single address point
+
+
+struct CV_PMFR16_NEARNVSA {
+ CV_uoff16_t off; // near address of function (NULL = 0)
+};
+
+
+
+// representation of a 16:16 near pointer to member functions of a
+// class with no virtual bases and multiple address points
+
+
+struct CV_PMFR16_NEARNVMA {
+ CV_uoff16_t off; // offset of function (NULL = 0,x)
+ signed short disp;
+};
+
+
+
+
+// representation of a 16:16 near pointer to member function of a
+// class with virtual bases
+
+
+struct CV_PMFR16_NEARVBASE {
+ CV_uoff16_t off; // offset of function (NULL = 0,x,x,x)
+ CV_off16_t mdisp; // displacement to data
+ CV_off16_t pdisp; // this pointer displacement
+ CV_off16_t vdisp; // vbase table displacement
+};
+
+
+
+
+// representation of a 16:16 pointer to far member function for a
+// class with no virtual bases and a single address point
+
+
+struct CV_PMFR16_FARNVSA {
+ CV_uoff16_t off; // offset of function (NULL = 0:0)
+ unsigned short seg; // segment of function
+};
+
+
+
+
+// representation of a 16:16 far pointer to member functions of a
+// class with no virtual bases and multiple address points
+
+
+struct CV_PMFR16_FARNVMA {
+ CV_uoff16_t off; // offset of function (NULL = 0:0,x)
+ unsigned short seg;
+ signed short disp;
+};
+
+
+
+
+// representation of a 16:16 far pointer to member function of a
+// class with virtual bases
+
+
+struct CV_PMFR16_FARVBASE {
+ CV_uoff16_t off; // offset of function (NULL = 0:0,x,x,x)
+ unsigned short seg;
+ CV_off16_t mdisp; // displacement to data
+ CV_off16_t pdisp; // this pointer displacement
+ CV_off16_t vdisp; // vbase table displacement
+
+};
+
+
+
+
+// representation of a 16:32 near pointer to member function for a
+// class with no virtual bases and a single address point
+
+
+struct CV_PMFR32_NVSA {
+ CV_uoff32_t off; // near address of function (NULL = 0L)
+};
+
+
+
+
+// representation of a 16:32 near pointer to member function for a
+// class with no virtual bases and multiple address points
+
+
+struct CV_PMFR32_NVMA {
+ CV_uoff32_t off; // near address of function (NULL = 0L,x)
+ CV_off32_t disp;
+};
+
+
+
+
+// representation of a 16:32 near pointer to member function for a
+// class with virtual bases
+
+
+struct CV_PMFR32_VBASE {
+ CV_uoff32_t off; // near address of function (NULL = 0L,x,x,x)
+ CV_off32_t mdisp; // displacement to data
+ CV_off32_t pdisp; // this pointer displacement
+ CV_off32_t vdisp; // vbase table displacement
+};
+
+
+
+
+
+// Easy leaf - used for generic casting to reference leaf field
+// of a subfield of a complex list
+
+typedef struct lfEasy {
+ unsigned short leaf; // LF_...
+} lfEasy;
+
+
+/** The following type records are basically variant records of the
+ * above structure. The "unsigned short leaf" of the above structure and
+ * the "unsigned short leaf" of the following type definitions are the same
+ * symbol. When the OMF record is locked via the MHOMFLock API
+ * call, the address of the "unsigned short leaf" is returned
+ */
+
+
+// Type record for LF_MODIFIER
+
+
+typedef struct lfModifier {
+ unsigned short leaf; // LF_MODIFIER
+ CV_modifier_t attr; // modifier attribute modifier_t
+ CV_typ_t type; // modified type
+} lfModifier;
+
+
+
+
+// type record for LF_POINTER
+
+#ifndef __cplusplus
+typedef struct lfPointer {
+#endif
+ struct lfPointerBody {
+ unsigned short leaf; // LF_POINTER
+ struct lfPointerAttr {
+ unsigned char ptrtype :5; // ordinal specifying pointer type (ptrtype-t)
+ unsigned char ptrmode :3; // ordinal specifying pointer mode (ptrmode_t)
+ unsigned char isflat32 :1; // true if 0:32 pointer
+ unsigned char isvolatile :1; // TRUE if volatile pointer
+ unsigned char isconst :1; // TRUE if const pointer
+ unsigned char isunaligned :1; // TRUE if unaligned pointer
+ unsigned char unused :4;
+ } attr;
+ CV_typ_t utype; // type index of the underlying type
+#if (defined(__cplusplus) || defined(_MSC_VER)) // for C++ and MS compilers that support unnamed unions
+ };
+#else
+ } u;
+#endif
+#ifdef __cplusplus
+typedef struct lfPointer : public lfPointerBody {
+#endif
+ union {
+ struct {
+ CV_typ_t pmclass; // index of containing class for pointer to member
+ unsigned short pmenum; // enumeration specifying pm format
+ } pm;
+ unsigned short bseg; // base segment if PTR_BASE_SEG
+ unsigned char Sym[1]; // copy of base symbol record (including length)
+ struct {
+ CV_typ_t index; // type index if CV_PTR_BASE_TYPE
+ unsigned char name[1]; // name of base type
+ } btype;
+ } pbase;
+} lfPointer;
+
+
+
+
+// type record for LF_ARRAY
+
+
+typedef struct lfArray {
+ unsigned short leaf; // LF_ARRAY
+ CV_typ_t elemtype; // type index of element type
+ CV_typ_t idxtype; // type index of indexing type
+ unsigned char data[CV_ZEROLEN]; // variable length data specifying
+ // size in bytes and name
+} lfArray;
+
+
+
+
+// type record for LF_CLASS, LF_STRUCTURE
+
+
+typedef struct lfClass {
+ unsigned short leaf; // LF_CLASS, LF_STRUCT
+ unsigned short count; // count of number of elements in class
+ CV_typ_t field; // type index of LF_FIELD descriptor list
+ CV_prop_t property; // property attribute field (prop_t)
+ CV_typ_t derived; // type index of derived from list if not zero
+ CV_typ_t vshape; // type index of vshape table for this class
+ unsigned char data[CV_ZEROLEN]; // data describing length of structure in
+ // bytes and name
+} lfClass;
+typedef lfClass lfStructure;
+
+
+
+
+// type record for LF_UNION
+
+
+typedef struct lfUnion {
+ unsigned short leaf; // LF_UNION
+ unsigned short count; // count of number of elements in class
+ CV_typ_t field; // type index of LF_FIELD descriptor list
+ CV_prop_t property; // property attribute field
+ unsigned char data[CV_ZEROLEN]; // variable length data describing length of
+ // structure and name
+} lfUnion;
+
+
+
+
+// type record for LF_ENUM
+
+
+typedef struct lfEnum {
+ unsigned short leaf; // LF_ENUM
+ unsigned short count; // count of number of elements in class
+ CV_typ_t utype; // underlying type of the enum
+ CV_typ_t field; // type index of LF_FIELD descriptor list
+ CV_prop_t property; // property attribute field
+ unsigned char Name[1]; // length prefixed name of enum
+} lfEnum;
+
+
+
+
+// Type record for LF_PROCEDURE
+
+
+typedef struct lfProc {
+ unsigned short leaf; // LF_PROCEDURE
+ CV_typ_t rvtype; // type index of return value
+ unsigned char calltype; // calling convention (CV_call_t)
+ unsigned char reserved; // reserved for future use
+ unsigned short parmcount; // number of parameters
+ CV_typ_t arglist; // type index of argument list
+} lfProc;
+
+
+
+// Type record for member function
+
+
+typedef struct lfMFunc {
+ unsigned short leaf; // LF_MFUNCTION
+ CV_typ_t rvtype; // type index of return value
+ CV_typ_t classtype; // type index of containing class
+ CV_typ_t thistype; // type index of this pointer (model specific)
+ unsigned char calltype; // calling convention (call_t)
+ unsigned char reserved; // reserved for future use
+ unsigned short parmcount; // number of parameters
+ CV_typ_t arglist; // type index of argument list
+ long thisadjust; // this adjuster (long because pad required anyway)
+} lfMFunc;
+
+
+
+
+// type record for virtual function table shape
+
+
+typedef struct lfVTShape {
+ unsigned short leaf; // LF_VTSHAPE
+ unsigned short count; // number of entries in vfunctable
+ unsigned char desc[CV_ZEROLEN]; // 4 bit (CV_VTS_desc) descriptors
+} lfVTShape;
+
+
+
+
+// type record for cobol0
+
+
+typedef struct lfCobol0 {
+ unsigned short leaf; // LF_COBOL0
+ CV_typ_t type; // parent type record index
+ unsigned char data[CV_ZEROLEN];
+} lfCobol0;
+
+
+
+
+// type record for cobol1
+
+
+typedef struct lfCobol1 {
+ unsigned short leaf; // LF_COBOL1
+ unsigned char data[CV_ZEROLEN];
+} lfCobol1;
+
+
+
+
+// type record for basic array
+
+
+typedef struct lfBArray {
+ unsigned short leaf; // LF_BARRAY
+ CV_typ_t utype; // type index of underlying type
+} lfBArray;
+
+// type record for assembler labels
+
+
+typedef struct lfLabel {
+ unsigned short leaf; // LF_LABEL
+ unsigned short mode; // addressing mode of label
+} lfLabel;
+
+
+
+// type record for dimensioned arrays
+
+
+typedef struct lfDimArray {
+ unsigned short leaf; // LF_DIMARRAY
+ CV_typ_t utype; // underlying type of the array
+ CV_typ_t diminfo; // dimension information
+ unsigned char name[1]; // length prefixed name
+} lfDimArray;
+
+
+
+// type record describing path to virtual function table
+
+
+typedef struct lfVFTPath {
+ unsigned short leaf; // LF_VFTPATH
+ unsigned short count; // count of number of bases in path
+ CV_typ_t base[1]; // bases from root to leaf
+} lfVFTPath;
+
+
+// type record describing inclusion of precompiled types
+
+
+typedef struct lfPreComp {
+ unsigned short leaf; // LF_PRECOMP
+ unsigned short start; // starting type index included
+ unsigned short count; // number of types in inclusion
+ unsigned long signature; // signature
+ unsigned char name[CV_ZEROLEN]; // length prefixed name of included type file
+} lfPreComp;
+
+
+// type record describing end of precompiled types that can be
+// included by another file
+
+
+typedef struct lfEndPreComp {
+ unsigned short leaf; // LF_ENDPRECOMP
+ unsigned long signature; // signature
+} lfEndPreComp;
+
+
+
+
+
+// type record for OEM definable type strings
+
+
+typedef struct lfOEM {
+ unsigned short leaf; // LF_OEM
+ unsigned short cvOEM; // MS assigned OEM identified
+ unsigned short recOEM; // OEM assigned type identifier
+ unsigned short count; // count of type indices to follow
+ CV_typ_t index[CV_ZEROLEN]; // array of type indices followed
+ // by OEM defined data
+} lfOEM;
+
+#define OEM_MS_FORTRAN90 0xF090
+#define OEM_ODI 0x0010
+#define OEM_THOMSON_SOFTWARE 0x5453
+#define OEM_ODI_REC_BASELIST 0x0000
+
+
+// type record describing using of a type server
+
+typedef struct lfTypeServer {
+ unsigned short leaf; // LF_TYPESERVER
+ unsigned long signature; // signature
+ unsigned long age; // age of database used by this module
+ unsigned char name[CV_ZEROLEN]; // length prefixed name of PDB
+} lfTypeServer;
+
+// description of type records that can be referenced from
+// type records referenced by symbols
+
+
+
+// type record for skip record
+
+
+typedef struct lfSkip {
+ unsigned short leaf; // LF_SKIP
+ CV_typ_t type; // next valid index
+ unsigned char data[CV_ZEROLEN]; // pad data
+} lfSkip;
+
+
+
+// argument list leaf
+
+
+typedef struct lfArgList {
+ unsigned short leaf; // LF_ARGLIST
+ unsigned short count; // number of arguments
+ CV_typ_t arg[CV_ZEROLEN]; // number of arguments
+} lfArgList;
+
+
+
+
+// derived class list leaf
+
+
+typedef struct lfDerived {
+ unsigned short leaf; // LF_DERIVED
+ unsigned short count; // number of arguments
+ CV_typ_t drvdcls[CV_ZEROLEN]; // type indices of derived classes
+} lfDerived;
+
+
+
+
+// leaf for default arguments
+
+
+typedef struct lfDefArg {
+ unsigned short leaf; // LF_DEFARG
+ CV_typ_t type; // type of resulting expression
+ unsigned char expr[CV_ZEROLEN]; // length prefixed expression string
+} lfDefArg;
+
+
+
+// list leaf
+// This list should no longer be used because the utilities cannot
+// verify the contents of the list without knowing what type of list
+// it is. New specific leaf indices should be used instead.
+
+
+typedef struct lfList {
+ unsigned short leaf; // LF_LIST
+ char data[CV_ZEROLEN]; // data format specified by indexing type
+} lfList;
+
+
+
+
+// field list leaf
+// This is the header leaf for a complex list of class and structure
+// subfields.
+
+
+typedef struct lfFieldList {
+ unsigned short leaf; // LF_FIELDLIST
+ char data[CV_ZEROLEN]; // field list sub lists
+} lfFieldList;
+
+
+
+
+
+
+
+// type record for non-static methods and friends in overloaded method list
+
+typedef struct mlMethod {
+ CV_fldattr_t attr; // method attribute
+ CV_typ_t index; // index to type record for procedure
+ unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if intro virtual
+} mlMethod;
+
+
+typedef struct lfMethodList {
+ unsigned short leaf;
+ unsigned char mList[CV_ZEROLEN]; // really a mlMethod type
+} lfMethodList;
+
+
+
+
+
+// type record for LF_BITFIELD
+
+
+typedef struct lfBitfield {
+ unsigned short leaf; // LF_BITFIELD
+ unsigned char length;
+ unsigned char position;
+ CV_typ_t type; // type of bitfield
+
+} lfBitfield;
+
+
+
+
+// type record for dimensioned array with constant bounds
+
+
+typedef struct lfDimCon {
+ unsigned short leaf; // LF_DIMCONU or LF_DIMCONLU
+ unsigned short rank; // number of dimensions
+ CV_typ_t typ; // type of index
+ unsigned char dim[CV_ZEROLEN]; // array of dimension information with
+ // either upper bounds or lower/upper bound
+} lfDimCon;
+
+
+
+
+// type record for dimensioned array with variable bounds
+
+
+typedef struct lfDimVar {
+ unsigned short leaf; // LF_DIMVARU or LF_DIMVARLU
+ unsigned short rank; // number of dimensions
+ CV_typ_t typ; // type of index
+ unsigned char dim[CV_ZEROLEN]; // array of type indices for either
+ // variable upper bound or variable
+ // lower/upper bound. The referenced
+ // types must be LF_REFSYM or T_VOID
+} lfDimVar;
+
+
+
+
+// type record for referenced symbol
+
+
+typedef struct lfRefSym {
+ unsigned short leaf; // LF_REFSYM
+ unsigned char Sym[1]; // copy of referenced symbol record
+ // (including length)
+} lfRefSym;
+
+
+
+
+
+/** the following are numeric leaves. They are used to indicate the
+ * size of the following variable length data. When the numeric
+ * data is a single byte less than 0x8000, then the data is output
+ * directly. If the data is more the 0x8000 or is a negative value,
+ * then the data is preceeded by the proper index.
+ */
+
+
+
+// signed character leaf
+
+typedef struct lfChar {
+ unsigned short leaf; // LF_CHAR
+ signed char val; // signed 8-bit value
+} lfChar;
+
+
+
+
+// signed short leaf
+
+typedef struct lfShort {
+ unsigned short leaf; // LF_SHORT
+ short val; // signed 16-bit value
+} lfShort;
+
+
+
+
+// unsigned short leaf
+
+typedef struct lfUShort {
+ unsigned short leaf; // LF_unsigned short
+ unsigned short val; // unsigned 16-bit value
+} lfUShort;
+
+
+
+
+// signed long leaf
+
+typedef struct lfLong {
+ unsigned short leaf; // LF_LONG
+ long val; // signed 32-bit value
+} lfLong;
+
+
+
+
+// unsigned long leaf
+
+typedef struct lfULong {
+ unsigned short leaf; // LF_ULONG
+ unsigned long val; // unsigned 32-bit value
+} lfULong;
+
+
+
+
+// signed quad leaf
+
+typedef struct lfQuad {
+ unsigned short leaf; // LF_QUAD
+ unsigned char val[8]; // signed 64-bit value
+} lfQuad;
+
+
+
+
+// unsigned quad leaf
+
+typedef struct lfUQuad {
+ unsigned short leaf; // LF_UQUAD
+ unsigned char val[8]; // unsigned 64-bit value
+} lfUQuad;
+
+
+// signed int128 leaf
+
+typedef struct lfOct {
+ unsigned short leaf; // LF_OCT
+ unsigned char val[16]; // signed 128-bit value
+} lfOct;
+
+// unsigned int128 leaf
+
+typedef struct lfUOct {
+ unsigned short leaf; // LF_UOCT
+ unsigned char val[16]; // unsigned 128-bit value
+} lfUOct;
+
+
+
+
+// real 32-bit leaf
+
+typedef struct lfReal32 {
+ unsigned short leaf; // LF_REAL32
+ float val; // 32-bit real value
+} lfReal32;
+
+
+
+
+// real 48-bit leaf
+
+typedef struct lfReal48 {
+ unsigned short leaf; // LF_REAL48
+ unsigned char val[6]; // 48-bit real value
+} lfReal48;
+
+
+
+
+// real 64-bit leaf
+
+typedef struct lfReal64 {
+ unsigned short leaf; // LF_REAL64
+ double val; // 64-bit real value
+} lfReal64;
+
+
+
+
+// real 80-bit leaf
+
+typedef struct lfReal80 {
+ unsigned short leaf; // LF_REAL80
+ FLOAT10 val; // real 80-bit value
+} lfReal80;
+
+
+
+
+// real 128-bit leaf
+
+typedef struct lfReal128 {
+ unsigned short leaf; // LF_REAL128
+ char val[16]; // real 128-bit value
+} lfReal128;
+
+
+
+
+// complex 32-bit leaf
+
+typedef struct lfCmplx32 {
+ unsigned short leaf; // LF_COMPLEX32
+ float val_real; // real component
+ float val_imag; // imaginary component
+} lfCmplx32;
+
+
+
+
+// complex 64-bit leaf
+
+typedef struct lfCmplx64 {
+ unsigned short leaf; // LF_COMPLEX64
+ double val_real; // real component
+ double val_imag; // imaginary component
+} flCmplx64;
+
+
+
+
+// complex 80-bit leaf
+
+typedef struct lfCmplx80 {
+ unsigned short leaf; // LF_COMPLEX80
+ FLOAT10 val_real; // real component
+ FLOAT10 val_imag; // imaginary component
+} lfCmplx80;
+
+
+
+
+// complex 128-bit leaf
+
+typedef struct lfCmplx128 {
+ unsigned short leaf; // LF_COMPLEX128
+ char val_real[16]; // real component
+ char val_imag[16]; // imaginary component
+} lfCmplx128;
+
+
+
+// variable length numeric field
+
+typedef struct lfVarString {
+ unsigned short leaf; // LF_VARSTRING
+ unsigned short len; // length of value in bytes
+ unsigned char value[CV_ZEROLEN]; // value
+} lfVarString;
+
+//***********************************************************************
+
+
+// index leaf - contains type index of another leaf
+// a major use of this leaf is to allow the compilers to emit a
+// long complex list (LF_FIELD) in smaller pieces.
+
+typedef struct lfIndex {
+ unsigned short leaf; // LF_INDEX
+ CV_typ_t index; // type index of referenced leaf
+} lfIndex;
+
+
+// subfield record for base class field
+
+typedef struct lfBClass {
+ unsigned short leaf; // LF_BCLASS
+ CV_typ_t index; // type index of base class
+ CV_fldattr_t attr; // attribute
+ unsigned char offset[CV_ZEROLEN]; // variable length offset of base within class
+} lfBClass;
+
+
+
+
+
+// subfield record for direct and indirect virtual base class field
+
+typedef struct lfVBClass {
+ unsigned short leaf; // LF_VBCLASS | LV_IVBCLASS
+ CV_typ_t index; // type index of direct virtual base class
+ CV_typ_t vbptr; // type index of virtual base pointer
+ CV_fldattr_t attr; // attribute
+ unsigned char vbpoff[CV_ZEROLEN]; // virtual base pointer offset from address point
+ // followed by virtual base offset from vbtable
+} lfVBClass;
+
+
+
+
+
+// subfield record for friend class
+
+
+typedef struct lfFriendCls {
+ unsigned short leaf; // LF_FRIENDCLS
+ CV_typ_t index; // index to type record of friend class
+} lfFriendCls;
+
+
+
+
+
+// subfield record for friend function
+
+
+typedef struct lfFriendFcn {
+ unsigned short leaf; // LF_FRIENDFCN
+ CV_typ_t index; // index to type record of friend function
+ unsigned char Name[1]; // name of friend function
+} lfFriendFcn;
+
+
+
+// subfield record for non-static data members
+
+typedef struct lfMember {
+ unsigned short leaf; // LF_MEMBER
+ CV_typ_t index; // index of type record for field
+ CV_fldattr_t attr; // attribute mask
+ unsigned char offset[CV_ZEROLEN]; // variable length offset of field followed
+ // by length prefixed name of field
+} lfMember;
+
+
+
+// type record for static data members
+
+typedef struct lfSTMember {
+ unsigned short leaf; // LF_STMEMBER
+ CV_typ_t index; // index of type record for field
+ CV_fldattr_t attr; // attribute mask
+ unsigned char Name[1]; // length prefixed name of field
+} lfSTMember;
+
+
+
+// subfield record for virtual function table pointer
+
+typedef struct lfVFuncTab {
+ unsigned short leaf; // LF_VFUNCTAB
+ CV_typ_t type; // type index of pointer
+} lfVFuncTab;
+
+
+
+// subfield record for virtual function table pointer with offset
+
+typedef struct lfVFuncOff {
+ unsigned short leaf; // LF_VFUNCTAB
+ CV_typ_t type; // type index of pointer
+ CV_off32_t offset; // offset of virtual function table pointer
+} lfVFuncOff;
+
+
+
+// subfield record for overloaded method list
+
+
+typedef struct lfMethod {
+ unsigned short leaf; // LF_METHOD
+ unsigned short count; // number of occurances of function
+ CV_typ_t mList; // index to LF_METHODLIST record
+ unsigned char Name[1]; // length prefixed name of method
+} lfMethod;
+
+
+
+// subfield record for nonoverloaded method
+
+
+typedef struct lfOneMethod {
+ unsigned short leaf; // LF_ONEMETHOD
+ CV_fldattr_t attr; // method attribute
+ CV_typ_t index; // index to type record for procedure
+ unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if
+ // intro virtual followed by
+ // length prefixed name of method
+} lfOneMethod;
+
+
+// subfield record for enumerate
+
+typedef struct lfEnumerate {
+ unsigned short leaf; // LF_ENUMERATE
+ CV_fldattr_t attr; // access
+ unsigned char value[CV_ZEROLEN]; // variable length value field followed
+ // by length prefixed name
+} lfEnumerate;
+
+
+// type record for nested (scoped) type definition
+
+typedef struct lfNestType {
+ unsigned short leaf; // LF_NESTTYPE
+ CV_typ_t index; // index of nested type definition
+ unsigned char Name[1]; // length prefixed type name
+} lfNestType;
+
+// type record for nested (scoped) type definition, with attributes
+
+typedef struct lfNestTypeEx {
+ unsigned short leaf; // LF_NESTTYPEEX
+ CV_typ_t index; // index of nested type definition
+ CV_fldattr_t attr; // member access
+ unsigned char Name[1]; // length prefixed type name
+} lfNestTypeEx;
+
+// type record for modifications to members
+
+typedef struct lfMemberModify {
+ unsigned short leaf; // LF_MEMBERMODIFY
+ CV_typ_t index; // index of base class type definition
+ CV_fldattr_t attr; // the new attributes
+ unsigned char Name[1]; // length prefixed member name
+} lfMemberModify;
+
+// type record for pad leaf
+
+typedef struct lfPad {
+ unsigned char leaf;
+} SYM_PAD;
+
+
+
+// Symbol definitions
+
+typedef enum SYM_ENUM_e {
+ S_COMPILE = 0x0001, // Compile flags symbol
+ S_REGISTER = 0x0002, // Register variable
+ S_CONSTANT = 0x0003, // constant symbol
+ S_UDT = 0x0004, // User defined type
+ S_SSEARCH = 0x0005, // Start Search
+ S_END = 0x0006, // Block, procedure, "with" or thunk end
+ S_SKIP = 0x0007, // Reserve symbol space in $$Symbols table
+ S_CVRESERVE = 0x0008, // Reserved symbol for CV internal use
+ S_OBJNAME = 0x0009, // path to object file name
+ S_ENDARG = 0x000a, // end of argument/return list
+ S_COBOLUDT = 0x000b, // special UDT for cobol that does not symbol pack
+ S_MANYREG = 0x000c, // multiple register variable
+ S_RETURN = 0x000d, // return description symbol
+ S_ENTRYTHIS = 0x000e, // description of this pointer on entry
+
+ S_BPREL16 = 0x0100, // BP-relative
+ S_LDATA16 = 0x0101, // Module-local symbol
+ S_GDATA16 = 0x0102, // Global data symbol
+ S_PUB16 = 0x0103, // a public symbol
+ S_LPROC16 = 0x0104, // Local procedure start
+ S_GPROC16 = 0x0105, // Global procedure start
+ S_THUNK16 = 0x0106, // Thunk Start
+ S_BLOCK16 = 0x0107, // block start
+ S_WITH16 = 0x0108, // with start
+ S_LABEL16 = 0x0109, // code label
+ S_CEXMODEL16 = 0x010a, // change execution model
+ S_VFTABLE16 = 0x010b, // address of virtual function table
+ S_REGREL16 = 0x010c, // register relative address
+
+ S_BPREL32 = 0x0200, // BP-relative
+ S_LDATA32 = 0x0201, // Module-local symbol
+ S_GDATA32 = 0x0202, // Global data symbol
+ S_PUB32 = 0x0203, // a public symbol (CV internal reserved)
+ S_LPROC32 = 0x0204, // Local procedure start
+ S_GPROC32 = 0x0205, // Global procedure start
+ S_THUNK32 = 0x0206, // Thunk Start
+ S_BLOCK32 = 0x0207, // block start
+ S_WITH32 = 0x0208, // with start
+ S_LABEL32 = 0x0209, // code label
+ S_CEXMODEL32 = 0x020a, // change execution model
+ S_VFTABLE32 = 0x020b, // address of virtual function table
+ S_REGREL32 = 0x020c, // register relative address
+ S_LTHREAD32 = 0x020d, // local thread storage
+ S_GTHREAD32 = 0x020e, // global thread storage
+ S_SLINK32 = 0x020f, // static link for MIPS EH implementation
+
+ S_LPROCMIPS = 0x0300, // Local procedure start
+ S_GPROCMIPS = 0x0301, // Global procedure start
+
+ S_PROCREF = 0x0400, // Reference to a procedure
+ S_DATAREF = 0x0401, // Reference to data
+ S_ALIGN = 0x0402, // Used for page alignment of symbols
+ S_LPROCREF = 0x0403 // Local Reference to a procedure
+} SYM_ENUM_e;
+
+
+
+
+// enum describing the compile flag source language
+
+
+typedef enum CV_CFL_LANG {
+ CV_CFL_C = 0x00,
+ CV_CFL_CXX = 0x01,
+ CV_CFL_FORTRAN = 0x02,
+ CV_CFL_MASM = 0x03,
+ CV_CFL_PASCAL = 0x04,
+ CV_CFL_BASIC = 0x05,
+ CV_CFL_COBOL = 0x06,
+ CV_CFL_LINK = 0x07,
+ CV_CFL_CVTRES = 0x08,
+} CV_CFL_LANG;
+
+
+
+// enum describing target processor
+
+
+typedef enum CV_CPU_TYPE_e {
+ CV_CFL_8080 = 0x00,
+ CV_CFL_8086 = 0x01,
+ CV_CFL_80286 = 0x02,
+ CV_CFL_80386 = 0x03,
+ CV_CFL_80486 = 0x04,
+ CV_CFL_PENTIUM = 0x05,
+ CV_CFL_MIPSR4000 = 0x10,
+ CV_CFL_M68000 = 0x20,
+ CV_CFL_M68010 = 0x21,
+ CV_CFL_M68020 = 0x22,
+ CV_CFL_M68030 = 0x23,
+ CV_CFL_M68040 = 0x24,
+ CV_CFL_ALPHA = 0x30,
+ CV_CFL_PPC601 = 0x40,
+ CV_CFL_PPC603 = 0x41,
+ CV_CFL_PPC604 = 0x42,
+ CV_CFL_PPC620 = 0x43
+
+} CV_CPU_TYPE_e;
+
+
+
+
+// enum describing compile flag ambiant data model
+
+
+typedef enum CV_CFL_DATA {
+ CV_CFL_DNEAR = 0x00,
+ CV_CFL_DFAR = 0x01,
+ CV_CFL_DHUGE = 0x02
+} CV_CFL_DATA;
+
+
+
+
+// enum describing compile flag ambiant code model
+
+
+typedef enum CV_CFL_CODE_e {
+ CV_CFL_CNEAR = 0x00,
+ CV_CFL_CFAR = 0x01,
+ CV_CFL_CHUGE = 0x02
+} CV_CFL_CODE_e;
+
+
+
+
+// enum describing compile flag target floating point package
+
+typedef enum CV_CFL_FPKG_e {
+ CV_CFL_NDP = 0x00,
+ CV_CFL_EMU = 0x01,
+ CV_CFL_ALT = 0x02
+} CV_CFL_FPKG_e;
+
+
+// enum describing function return method
+
+
+typedef struct CV_PROCFLAGS {
+ union {
+ unsigned char bAll;
+ struct {
+ unsigned char CV_PFLAG_NOFPO:1; // frame pointer present
+ unsigned char CV_PFLAG_INT :1; // interrupt return
+ unsigned char CV_PFLAG_FAR :1; // far return
+ unsigned char CV_PFLAG_NEVER:1; // function does not return
+ unsigned char unused :4; //
+ };
+ };
+} CV_PROCFLAGS;
+
+
+// enum describing function data return method
+
+typedef enum CV_GENERIC_STYLE_e {
+ CV_GENERIC_VOID = 0x00, // void return type
+ CV_GENERIC_REG = 0x01, // return data is in registers
+ CV_GENERIC_ICAN = 0x02, // indirect caller allocated near
+ CV_GENERIC_ICAF = 0x03, // indirect caller allocated far
+ CV_GENERIC_IRAN = 0x04, // indirect returnee allocated near
+ CV_GENERIC_IRAF = 0x05, // indirect returnee allocated far
+ CV_GENERIC_UNUSED = 0x06 // first unused
+} CV_GENERIC_STYLE_e;
+
+
+typedef struct CV_GENERIC_FLAG {
+ unsigned short cstyle :1; // true push varargs right to left
+ unsigned short rsclean :1; // true if returnee stack cleanup
+ unsigned short unused :14; // unused
+} CV_GENERIC_FLAG;
+
+
+
+
+
+typedef struct SYMTYPE {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // Record type
+ char data[CV_ZEROLEN];
+} SYMTYPE;
+
+__INLINE SYMTYPE *NextSym (SYMTYPE * pSym) {
+ return (SYMTYPE *) ((char *)pSym + pSym->reclen + sizeof(unsigned short));
+}
+
+// non-model specific symbol types
+
+
+
+typedef struct REGSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_REGISTER
+ CV_typ_t typind; // Type index
+ unsigned short reg; // register enumerate
+ unsigned char name[1]; // Length-prefixed name
+} REGSYM;
+
+
+
+typedef struct MANYREGSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_MANYREG
+ CV_typ_t typind; // Type index
+ unsigned char count; // count of number of registers
+ unsigned char reg[1]; // count register enumerates followed by
+ // length-prefixed name. Registers are
+ // most significant first.
+} MANYREGSYM;
+
+
+
+typedef struct CONSTSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_CONSTANT
+ CV_typ_t typind; // Type index (containing enum if enumerate)
+ unsigned short value; // numeric leaf containing value
+ unsigned char name[CV_ZEROLEN]; // Length-prefixed name
+} CONSTSYM;
+
+typedef struct UDTSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_UDT | S_COBOLUDT
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} UDTSYM;
+
+typedef struct SEARCHSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_SSEARCH
+ unsigned long startsym; // offset of the procedure
+ unsigned short seg; // segment of symbol
+} SEARCHSYM;
+
+typedef struct CFLAGSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_COMPILE
+ unsigned char machine; // target processor
+ struct {
+ unsigned char language :8; // language index
+ unsigned char pcode :1; // true if pcode present
+ unsigned char floatprec :2; // floating precision
+ unsigned char floatpkg :2; // float package
+ unsigned char ambdata :3; // ambiant data model
+ unsigned char ambcode :3; // ambiant code model
+ unsigned char mode32 :1; // true if compiled 32 bit mode
+ unsigned char pad :4; // reserved
+ } flags;
+ unsigned char ver[1]; // Length-prefixed compiler version string
+} CFLAGSYM;
+
+
+
+
+
+typedef struct OBJNAMESYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_OBJNAME
+ unsigned long signature; // signature
+ unsigned char name[1]; // Length-prefixed name
+} OBJNAMESYM;
+
+
+
+
+typedef struct ENDARGSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_ENDARG
+} ENDARGSYM;
+
+
+typedef struct RETURNSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_RETURN
+ CV_GENERIC_FLAG flags; // flags
+ CV_GENERIC_STYLE_e style; // return style
+ // followed by return method data
+} RETURNSYM;
+
+
+typedef struct ENTRYTHISSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_ENTRYTHIS
+ unsigned char thissym; // symbol describing this pointer on entry
+} ENTRYTHISSYM;
+
+
+// symbol types for 16:16 memory model
+
+
+typedef struct BPRELSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_BPREL16
+ CV_off16_t off; // BP-relative offset
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} BPRELSYM16;
+
+
+
+typedef struct DATASYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_LDATA or S_GDATA
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} DATASYM16;
+typedef DATASYM16 PUBSYM16;
+
+
+typedef struct PROCSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_GPROC16 or S_LPROC16
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+ unsigned short len; // Proc length
+ unsigned short DbgStart; // Debug start offset
+ unsigned short DbgEnd; // Debug end offset
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ CV_typ_t typind; // Type index
+ CV_PROCFLAGS flags; // Proc flags
+ unsigned char name[1]; // Length-prefixed name
+} PROCSYM16;
+
+
+
+
+typedef struct THUNKSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_THUNK
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ unsigned short len; // length of thunk
+ unsigned char ord; // ordinal specifying type of thunk
+ unsigned char name[1]; // name of thunk
+ unsigned char variant[CV_ZEROLEN]; // variant portion of thunk
+} THUNKSYM16;
+
+typedef enum {
+ THUNK_ORDINAL_NOTYPE,
+ THUNK_ORDINAL_ADJUSTOR,
+ THUNK_ORDINAL_VCALL,
+ THUNK_ORDINAL_PCODE
+} THUNK_ORDINAL;
+
+typedef struct LABELSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_LABEL16
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ CV_PROCFLAGS flags; // flags
+ unsigned char name[1]; // Length-prefixed name
+} LABELSYM16;
+
+typedef struct BLOCKSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_BLOCK16
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned short len; // Block length
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ unsigned char name[1]; // Length-prefixed name
+} BLOCKSYM16;
+
+typedef struct WITHSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_WITH16
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned short len; // Block length
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ unsigned char expr[1]; // Length-prefixed expression
+} WITHSYM16;
+
+
+
+
+typedef enum CEXM_MODEL_e {
+ CEXM_MDL_table = 0x00, // not executable
+ CEXM_MDL_jumptable = 0x01, // Compiler generated jump table
+ CEXM_MDL_datapad = 0x02, // Data padding for alignment
+ CEXM_MDL_native = 0x20, // native (actually not-pcode)
+ CEXM_MDL_cobol = 0x21, // cobol
+ CEXM_MDL_codepad = 0x22, // Code padding for alignment
+ CEXM_MDL_code = 0x23, // code
+ CEXM_MDL_pcode = 0x40, // pcode
+ CEXM_MDL_pcode32Mac = 0x41, // macintosh 32 bit pcode
+ CEXM_MDL_pcode32MacNep = 0x42 // macintosh 32 bit pcode native entry point
+} CEXM_MODEL_e;
+
+typedef enum CV_COBOL_e {
+ CV_COBOL_dontstop,
+ CV_COBOL_pfm,
+ CV_COBOL_false,
+ CV_COBOL_extcall
+} CV_COBOL_e;
+
+typedef struct CEXMSYM16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_CEXMODEL16
+ CV_uoff16_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ unsigned short model; // execution model
+ union var16 {
+ struct {
+ CV_uoff16_t pcdtable; // offset to pcode function table
+ CV_uoff16_t pcdspi; // offset to segment pcode information
+ } pcode;
+ struct {
+ unsigned short subtype; // see CV_COBOL_e above
+ unsigned short flag;
+ } cobol;
+ };
+} CEXMSYM16;
+
+
+
+
+typedef struct VPATHSYM16 {
+ unsigned short reclen; // record length
+ unsigned short rectyp; // S_VFTPATH16
+ CV_uoff16_t off; // offset of virtual function table
+ unsigned short seg; // segment of virtual function table
+ CV_typ_t root; // type index of the root of path
+ CV_typ_t path; // type index of the path record
+} VPATHSYM16;
+
+
+
+
+typedef struct REGREL16 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_REGREL16
+ CV_uoff16_t off; // offset of symbol
+ unsigned short reg; // register index
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} REGREL16;
+
+
+
+
+
+typedef struct BPRELSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_BPREL32
+ CV_off32_t off; // BP-relative offset
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} BPRELSYM32;
+
+typedef struct DATASYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_LDATA32, S_GDATA32 or S_PUB32
+ CV_uoff32_t off;
+ unsigned short seg;
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} DATASYM32;
+typedef DATASYM32 PUBSYM32;
+
+
+
+typedef struct PROCSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_GPROC32 or S_LPROC32
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+ unsigned long len; // Proc length
+ unsigned long DbgStart; // Debug start offset
+ unsigned long DbgEnd; // Debug end offset
+ CV_uoff32_t off;
+ unsigned short seg;
+ CV_typ_t typind; // Type index
+ CV_PROCFLAGS flags; // Proc flags
+ unsigned char name[1]; // Length-prefixed name
+} PROCSYM32;
+
+
+
+
+typedef struct THUNKSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_THUNK32
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+ CV_uoff32_t off;
+ unsigned short seg;
+ unsigned short len; // length of thunk
+ unsigned char ord; // ordinal specifying type of thunk
+ unsigned char name[1]; // Length-prefixed name
+ unsigned char variant[CV_ZEROLEN]; // variant portion of thunk
+} THUNKSYM32;
+
+
+
+
+typedef struct LABELSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_LABEL32
+ CV_uoff32_t off;
+ unsigned short seg;
+ CV_PROCFLAGS flags; // flags
+ unsigned char name[1]; // Length-prefixed name
+} LABELSYM32;
+
+
+typedef struct BLOCKSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_BLOCK32
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long len; // Block length
+ CV_uoff32_t off; // Offset in code segment
+ unsigned short seg; // segment of label
+ unsigned char name[1]; // Length-prefixed name
+} BLOCKSYM32;
+
+
+typedef struct WITHSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_WITH32
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long len; // Block length
+ CV_uoff32_t off; // Offset in code segment
+ unsigned short seg; // segment of label
+ unsigned char expr[1]; // Length-prefixed expression string
+} WITHSYM32;
+
+
+
+typedef struct CEXMSYM32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_CEXMODEL32
+ CV_uoff32_t off; // offset of symbol
+ unsigned short seg; // segment of symbol
+ unsigned short model; // execution model
+ union var32 {
+ struct {
+ CV_uoff32_t pcdtable; // offset to pcode function table
+ CV_uoff32_t pcdspi; // offset to segment pcode information
+ } pcode;
+ struct {
+ unsigned short subtype; // see CV_COBOL_e above
+ unsigned short flag;
+ } cobol;
+ struct {
+ CV_uoff32_t calltableOff; // offset to function table
+ unsigned short calltableSeg; // segment of function table
+ } pcode32Mac;
+ };
+} CEXMSYM32;
+
+
+
+typedef struct VPATHSYM32 {
+ unsigned short reclen; // record length
+ unsigned short rectyp; // S_VFTPATH32
+ CV_uoff32_t off; // offset of virtual function table
+ unsigned short seg; // segment of virtual function table
+ CV_typ_t root; // type index of the root of path
+ CV_typ_t path; // type index of the path record
+} VPATHSYM32;
+
+
+
+
+
+typedef struct REGREL32 {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_REGREL32
+ CV_uoff32_t off; // offset of symbol
+ unsigned short reg; // register index for symbol
+ CV_typ_t typind; // Type index
+ unsigned char name[1]; // Length-prefixed name
+} REGREL32, *LPREGREL32;
+
+
+
+typedef struct THREADSYM32 {
+ unsigned short reclen; // record length
+ unsigned short rectyp; // S_LTHREAD32 | S_GTHREAD32
+ CV_uoff32_t off; // offset into thread storage
+ unsigned short seg; // segment of thread storage
+ CV_typ_t typind; // type index
+ unsigned char name[1]; // length prefixed name
+} THREADSYM32;
+
+typedef struct SLINK32 {
+ unsigned short reclen; // record length
+ unsigned short rectyp; // S_SLINK32
+ unsigned long framesize; // frame size of parent procedure
+ CV_off32_t off; // signed offset where the static link was saved relative to the value of reg
+ unsigned short reg;
+} SLINK32;
+
+typedef struct PROCSYMMIPS {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_GPROCMIPS or S_LPROCMIPS
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+ unsigned long len; // Proc length
+ unsigned long DbgStart; // Debug start offset
+ unsigned long DbgEnd; // Debug end offset
+ unsigned long regSave; // int register save mask
+ unsigned long fpSave; // fp register save mask
+ CV_uoff32_t intOff; // int register save offset
+ CV_uoff32_t fpOff; // fp register save offset
+ CV_uoff32_t off; // Symbol offset
+ unsigned short seg; // Symbol segment
+ CV_typ_t typind; // Type index
+ unsigned char retReg; // Register return value is in
+ unsigned char frameReg; // Frame pointer register
+ unsigned char name[1]; // Length-prefixed name
+} PROCSYMMIPS, *PROCPTRMIPS;
+
+
+typedef struct REFSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_PROCREF or S_DATAREF
+ unsigned long sumName; // SUC of the name
+ unsigned long ibSym; // Offset of actual symbol in $$Symbols
+ unsigned short imod; // Module containing the actual symbol
+ unsigned short usFill; // align this record
+} REFSYM;
+
+typedef struct ALIGNSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_PROCREF or S_DATAREF
+} ALIGNSYM;
+
+// generic block definition symbols
+// these are similar to the equivalent 16:16 or 16:32 symbols but
+// only define the length, type and linkage fields
+
+typedef struct PROCSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_GPROC16 or S_LPROC16
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+} PROCSYM;
+
+
+typedef struct THUNKSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_THUNK
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+ unsigned long pNext; // pointer to next symbol
+} THUNKSYM;
+
+typedef struct BLOCKSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_BLOCK16
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+} BLOCKSYM;
+
+
+typedef struct WITHSYM {
+ unsigned short reclen; // Record length
+ unsigned short rectyp; // S_WITH16
+ unsigned long pParent; // pointer to the parent
+ unsigned long pEnd; // pointer to this blocks end
+} WITHSYM;
+
+
+typedef enum CV_HREG_e {
+ // Register set for the Intel 80x86 and ix86 processor series
+ // (plus PCODE registers)
+
+ CV_REG_NONE = 0,
+ CV_REG_AL = 1,
+ CV_REG_CL = 2,
+ CV_REG_DL = 3,
+ CV_REG_BL = 4,
+ CV_REG_AH = 5,
+ CV_REG_CH = 6,
+ CV_REG_DH = 7,
+ CV_REG_BH = 8,
+ CV_REG_AX = 9,
+ CV_REG_CX = 10,
+ CV_REG_DX = 11,
+ CV_REG_BX = 12,
+ CV_REG_SP = 13,
+ CV_REG_BP = 14,
+ CV_REG_SI = 15,
+ CV_REG_DI = 16,
+ CV_REG_EAX = 17,
+ CV_REG_ECX = 18,
+ CV_REG_EDX = 19,
+ CV_REG_EBX = 20,
+ CV_REG_ESP = 21,
+ CV_REG_EBP = 22,
+ CV_REG_ESI = 23,
+ CV_REG_EDI = 24,
+ CV_REG_ES = 25,
+ CV_REG_CS = 26,
+ CV_REG_SS = 27,
+ CV_REG_DS = 28,
+ CV_REG_FS = 29,
+ CV_REG_GS = 30,
+ CV_REG_IP = 31,
+ CV_REG_FLAGS = 32,
+ CV_REG_EIP = 33,
+ CV_REG_EFLAGS = 34,
+ CV_REG_TEMP = 40, // PCODE Temp
+ CV_REG_TEMPH = 41, // PCODE TempH
+ CV_REG_QUOTE = 42, // PCODE Quote
+ CV_REG_PCDR3 = 43, // PCODE reserved
+ CV_REG_PCDR4 = 44, // PCODE reserved
+ CV_REG_PCDR5 = 45, // PCODE reserved
+ CV_REG_PCDR6 = 46, // PCODE reserved
+ CV_REG_PCDR7 = 47, // PCODE reserved
+ CV_REG_CR0 = 80, // CR0 -- control registers
+ CV_REG_CR1 = 81,
+ CV_REG_CR2 = 82,
+ CV_REG_CR3 = 83,
+ CV_REG_CR4 = 84, // Pentium
+ CV_REG_DR0 = 90, // Debug register
+ CV_REG_DR1 = 91,
+ CV_REG_DR2 = 92,
+ CV_REG_DR3 = 93,
+ CV_REG_DR4 = 94,
+ CV_REG_DR5 = 95,
+ CV_REG_DR6 = 96,
+ CV_REG_DR7 = 97,
+ CV_REG_GDTR = 110,
+ CV_REG_GDTL = 111,
+ CV_REG_IDTR = 112,
+ CV_REG_IDTL = 113,
+ CV_REG_LDTR = 114,
+ CV_REG_TR = 115,
+
+ CV_REG_PSEUDO1 = 116,
+ CV_REG_PSEUDO2 = 117,
+ CV_REG_PSEUDO3 = 118,
+ CV_REG_PSEUDO4 = 119,
+ CV_REG_PSEUDO5 = 120,
+ CV_REG_PSEUDO6 = 121,
+ CV_REG_PSEUDO7 = 122,
+ CV_REG_PSEUDO8 = 123,
+ CV_REG_PSEUDO9 = 124,
+
+ CV_REG_ST0 = 128,
+ CV_REG_ST1 = 129,
+ CV_REG_ST2 = 130,
+ CV_REG_ST3 = 131,
+ CV_REG_ST4 = 132,
+ CV_REG_ST5 = 133,
+ CV_REG_ST6 = 134,
+ CV_REG_ST7 = 135,
+ CV_REG_CTRL = 136,
+ CV_REG_STAT = 137,
+ CV_REG_TAG = 138,
+ CV_REG_FPIP = 139,
+ CV_REG_FPCS = 140,
+ CV_REG_FPDO = 141,
+ CV_REG_FPDS = 142,
+ CV_REG_ISEM = 143,
+ CV_REG_FPEIP = 144,
+ CV_REG_FPEDO = 145,
+
+ // registers for the 68K processors
+
+ CV_R68_D0 = 0,
+ CV_R68_D1 = 1,
+ CV_R68_D2 = 2,
+ CV_R68_D3 = 3,
+ CV_R68_D4 = 4,
+ CV_R68_D5 = 5,
+ CV_R68_D6 = 6,
+ CV_R68_D7 = 7,
+ CV_R68_A0 = 8,
+ CV_R68_A1 = 9,
+ CV_R68_A2 = 10,
+ CV_R68_A3 = 11,
+ CV_R68_A4 = 12,
+ CV_R68_A5 = 13,
+ CV_R68_A6 = 14,
+ CV_R68_A7 = 15,
+ CV_R68_CCR = 16,
+ CV_R68_SR = 17,
+ CV_R68_USP = 18,
+ CV_R68_MSP = 19,
+ CV_R68_SFC = 20,
+ CV_R68_DFC = 21,
+ CV_R68_CACR = 22,
+ CV_R68_VBR = 23,
+ CV_R68_CAAR = 24,
+ CV_R68_ISP = 25,
+ CV_R68_PC = 26,
+ //reserved 27
+ CV_R68_FPCR = 28,
+ CV_R68_FPSR = 29,
+ CV_R68_FPIAR = 30,
+ //reserved 31
+ CV_R68_FP0 = 32,
+ CV_R68_FP1 = 33,
+ CV_R68_FP2 = 34,
+ CV_R68_FP3 = 35,
+ CV_R68_FP4 = 36,
+ CV_R68_FP5 = 37,
+ CV_R68_FP6 = 38,
+ CV_R68_FP7 = 39,
+ //reserved 40
+ CV_R68_MMUSR030 = 41,
+ CV_R68_MMUSR = 42,
+ CV_R68_URP = 43,
+ CV_R68_DTT0 = 44,
+ CV_R68_DTT1 = 45,
+ CV_R68_ITT0 = 46,
+ CV_R68_ITT1 = 47,
+ //reserved 50
+ CV_R68_PSR = 51,
+ CV_R68_PCSR = 52,
+ CV_R68_VAL = 53,
+ CV_R68_CRP = 54,
+ CV_R68_SRP = 55,
+ CV_R68_DRP = 56,
+ CV_R68_TC = 57,
+ CV_R68_AC = 58,
+ CV_R68_SCC = 59,
+ CV_R68_CAL = 60,
+ CV_R68_TT0 = 61,
+ CV_R68_TT1 = 62,
+ //reserved 63
+ CV_R68_BAD0 = 64,
+ CV_R68_BAD1 = 65,
+ CV_R68_BAD2 = 66,
+ CV_R68_BAD3 = 67,
+ CV_R68_BAD4 = 68,
+ CV_R68_BAD5 = 69,
+ CV_R68_BAD6 = 70,
+ CV_R68_BAD7 = 71,
+ CV_R68_BAC0 = 72,
+ CV_R68_BAC1 = 73,
+ CV_R68_BAC2 = 74,
+ CV_R68_BAC3 = 75,
+ CV_R68_BAC4 = 76,
+ CV_R68_BAC5 = 77,
+ CV_R68_BAC6 = 78,
+ CV_R68_BAC7 = 79,
+
+ // Register set for the MIPS 4000
+
+ CV_M4_NOREG = CV_REG_NONE,
+
+ CV_M4_IntZERO = 10, /* CPU REGISTER */
+ CV_M4_IntAT = 11,
+ CV_M4_IntV0 = 12,
+ CV_M4_IntV1 = 13,
+ CV_M4_IntA0 = 14,
+ CV_M4_IntA1 = 15,
+ CV_M4_IntA2 = 16,
+ CV_M4_IntA3 = 17,
+ CV_M4_IntT0 = 18,
+ CV_M4_IntT1 = 19,
+ CV_M4_IntT2 = 20,
+ CV_M4_IntT3 = 21,
+ CV_M4_IntT4 = 22,
+ CV_M4_IntT5 = 23,
+ CV_M4_IntT6 = 24,
+ CV_M4_IntT7 = 25,
+ CV_M4_IntS0 = 26,
+ CV_M4_IntS1 = 27,
+ CV_M4_IntS2 = 28,
+ CV_M4_IntS3 = 29,
+ CV_M4_IntS4 = 30,
+ CV_M4_IntS5 = 31,
+ CV_M4_IntS6 = 32,
+ CV_M4_IntS7 = 33,
+ CV_M4_IntT8 = 34,
+ CV_M4_IntT9 = 35,
+ CV_M4_IntKT0 = 36,
+ CV_M4_IntKT1 = 37,
+ CV_M4_IntGP = 38,
+ CV_M4_IntSP = 39,
+ CV_M4_IntS8 = 40,
+ CV_M4_IntRA = 41,
+ CV_M4_IntLO = 42,
+ CV_M4_IntHI = 43,
+
+ CV_M4_Fir = 50,
+ CV_M4_Psr = 51,
+
+ CV_M4_FltF0 = 60, /* Floating point registers */
+ CV_M4_FltF1 = 61,
+ CV_M4_FltF2 = 62,
+ CV_M4_FltF3 = 63,
+ CV_M4_FltF4 = 64,
+ CV_M4_FltF5 = 65,
+ CV_M4_FltF6 = 66,
+ CV_M4_FltF7 = 67,
+ CV_M4_FltF8 = 68,
+ CV_M4_FltF9 = 69,
+ CV_M4_FltF10 = 70,
+ CV_M4_FltF11 = 71,
+ CV_M4_FltF12 = 72,
+ CV_M4_FltF13 = 73,
+ CV_M4_FltF14 = 74,
+ CV_M4_FltF15 = 75,
+ CV_M4_FltF16 = 76,
+ CV_M4_FltF17 = 77,
+ CV_M4_FltF18 = 78,
+ CV_M4_FltF19 = 79,
+ CV_M4_FltF20 = 80,
+ CV_M4_FltF21 = 81,
+ CV_M4_FltF22 = 82,
+ CV_M4_FltF23 = 83,
+ CV_M4_FltF24 = 84,
+ CV_M4_FltF25 = 85,
+ CV_M4_FltF26 = 86,
+ CV_M4_FltF27 = 87,
+ CV_M4_FltF28 = 88,
+ CV_M4_FltF29 = 89,
+ CV_M4_FltF30 = 90,
+ CV_M4_FltF31 = 91,
+ CV_M4_FltFsr = 92,
+
+
+ // Register set for the ALPHA AXP
+
+ CV_ALPHA_NOREG = CV_REG_NONE,
+
+ CV_ALPHA_FltF0 = 10, // Floating point registers
+ CV_ALPHA_FltF1 = 11,
+ CV_ALPHA_FltF2 = 12,
+ CV_ALPHA_FltF3 = 13,
+ CV_ALPHA_FltF4 = 14,
+ CV_ALPHA_FltF5 = 15,
+ CV_ALPHA_FltF6 = 16,
+ CV_ALPHA_FltF7 = 17,
+ CV_ALPHA_FltF8 = 18,
+ CV_ALPHA_FltF9 = 19,
+ CV_ALPHA_FltF10 = 20,
+ CV_ALPHA_FltF11 = 21,
+ CV_ALPHA_FltF12 = 22,
+ CV_ALPHA_FltF13 = 23,
+ CV_ALPHA_FltF14 = 24,
+ CV_ALPHA_FltF15 = 25,
+ CV_ALPHA_FltF16 = 26,
+ CV_ALPHA_FltF17 = 27,
+ CV_ALPHA_FltF18 = 28,
+ CV_ALPHA_FltF19 = 29,
+ CV_ALPHA_FltF20 = 30,
+ CV_ALPHA_FltF21 = 31,
+ CV_ALPHA_FltF22 = 32,
+ CV_ALPHA_FltF23 = 33,
+ CV_ALPHA_FltF24 = 34,
+ CV_ALPHA_FltF25 = 35,
+ CV_ALPHA_FltF26 = 36,
+ CV_ALPHA_FltF27 = 37,
+ CV_ALPHA_FltF28 = 38,
+ CV_ALPHA_FltF29 = 39,
+ CV_ALPHA_FltF30 = 40,
+ CV_ALPHA_FltF31 = 41,
+
+ CV_ALPHA_IntV0 = 42, // Integer registers
+ CV_ALPHA_IntT0 = 43,
+ CV_ALPHA_IntT1 = 44,
+ CV_ALPHA_IntT2 = 45,
+ CV_ALPHA_IntT3 = 46,
+ CV_ALPHA_IntT4 = 47,
+ CV_ALPHA_IntT5 = 48,
+ CV_ALPHA_IntT6 = 49,
+ CV_ALPHA_IntT7 = 50,
+ CV_ALPHA_IntS0 = 51,
+ CV_ALPHA_IntS1 = 52,
+ CV_ALPHA_IntS2 = 53,
+ CV_ALPHA_IntS3 = 54,
+ CV_ALPHA_IntS4 = 55,
+ CV_ALPHA_IntS5 = 56,
+ CV_ALPHA_IntFP = 57,
+ CV_ALPHA_IntA0 = 58,
+ CV_ALPHA_IntA1 = 59,
+ CV_ALPHA_IntA2 = 60,
+ CV_ALPHA_IntA3 = 61,
+ CV_ALPHA_IntA4 = 62,
+ CV_ALPHA_IntA5 = 63,
+ CV_ALPHA_IntT8 = 64,
+ CV_ALPHA_IntT9 = 65,
+ CV_ALPHA_IntT10 = 66,
+ CV_ALPHA_IntT11 = 67,
+ CV_ALPHA_IntRA = 68,
+ CV_ALPHA_IntT12 = 69,
+ CV_ALPHA_IntAT = 70,
+ CV_ALPHA_IntGP = 71,
+ CV_ALPHA_IntSP = 72,
+ CV_ALPHA_IntZERO = 73,
+
+
+ CV_ALPHA_Fpcr = 74, // Control registers
+ CV_ALPHA_Fir = 75,
+ CV_ALPHA_Psr = 76,
+ CV_ALPHA_FltFsr = 77,
+ CV_ALPHA_SoftFpcr = 78,
+
+ // Register Set for Motorola/IBM PowerPC
+
+ /*
+ ** PowerPC General Registers ( User Level )
+ */
+ CV_PPC_GPR0 = 1,
+ CV_PPC_GPR1 = 2,
+ CV_PPC_GPR2 = 3,
+ CV_PPC_GPR3 = 4,
+ CV_PPC_GPR4 = 5,
+ CV_PPC_GPR5 = 6,
+ CV_PPC_GPR6 = 7,
+ CV_PPC_GPR7 = 8,
+ CV_PPC_GPR8 = 9,
+ CV_PPC_GPR9 = 10,
+ CV_PPC_GPR10 = 11,
+ CV_PPC_GPR11 = 12,
+ CV_PPC_GPR12 = 13,
+ CV_PPC_GPR13 = 14,
+ CV_PPC_GPR14 = 15,
+ CV_PPC_GPR15 = 16,
+ CV_PPC_GPR16 = 17,
+ CV_PPC_GPR17 = 18,
+ CV_PPC_GPR18 = 19,
+ CV_PPC_GPR19 = 20,
+ CV_PPC_GPR20 = 21,
+ CV_PPC_GPR21 = 22,
+ CV_PPC_GPR22 = 23,
+ CV_PPC_GPR23 = 24,
+ CV_PPC_GPR24 = 25,
+ CV_PPC_GPR25 = 26,
+ CV_PPC_GPR26 = 27,
+ CV_PPC_GPR27 = 28,
+ CV_PPC_GPR28 = 29,
+ CV_PPC_GPR29 = 30,
+ CV_PPC_GPR30 = 31,
+ CV_PPC_GPR31 = 32,
+
+ /*
+ ** PowerPC Condition Register ( User Level )
+ */
+ CV_PPC_CR = 33,
+ CV_PPC_CR0 = 34,
+ CV_PPC_CR1 = 35,
+ CV_PPC_CR2 = 36,
+ CV_PPC_CR3 = 37,
+ CV_PPC_CR4 = 38,
+ CV_PPC_CR5 = 39,
+ CV_PPC_CR6 = 40,
+ CV_PPC_CR7 = 41,
+
+ /*
+ ** PowerPC Floating Point Registers ( User Level )
+ */
+ CV_PPC_FPR0 = 42,
+ CV_PPC_FPR1 = 43,
+ CV_PPC_FPR2 = 44,
+ CV_PPC_FPR3 = 45,
+ CV_PPC_FPR4 = 46,
+ CV_PPC_FPR5 = 47,
+ CV_PPC_FPR6 = 48,
+ CV_PPC_FPR7 = 49,
+ CV_PPC_FPR8 = 50,
+ CV_PPC_FPR9 = 51,
+ CV_PPC_FPR10 = 52,
+ CV_PPC_FPR11 = 53,
+ CV_PPC_FPR12 = 54,
+ CV_PPC_FPR13 = 55,
+ CV_PPC_FPR14 = 56,
+ CV_PPC_FPR15 = 57,
+ CV_PPC_FPR16 = 58,
+ CV_PPC_FPR17 = 59,
+ CV_PPC_FPR18 = 60,
+ CV_PPC_FPR19 = 61,
+ CV_PPC_FPR20 = 62,
+ CV_PPC_FPR21 = 63,
+ CV_PPC_FPR22 = 64,
+ CV_PPC_FPR23 = 65,
+ CV_PPC_FPR24 = 66,
+ CV_PPC_FPR25 = 67,
+ CV_PPC_FPR26 = 68,
+ CV_PPC_FPR27 = 69,
+ CV_PPC_FPR28 = 70,
+ CV_PPC_FPR29 = 71,
+ CV_PPC_FPR30 = 72,
+ CV_PPC_FPR31 = 73,
+
+ /*
+ ** PowerPC Floating Point Status and Control Register ( User Level )
+ */
+ CV_PPC_FPSCR = 74,
+
+ /*
+ ** PowerPC Machine State Register ( Supervisor Level )
+ */
+ CV_PPC_MSR = 75,
+
+ /*
+ ** PowerPC Segment Registers ( Supervisor Level )
+ */
+ CV_PPC_SR0 = 76,
+ CV_PPC_SR1 = 77,
+ CV_PPC_SR2 = 78,
+ CV_PPC_SR3 = 79,
+ CV_PPC_SR4 = 80,
+ CV_PPC_SR5 = 81,
+ CV_PPC_SR6 = 82,
+ CV_PPC_SR7 = 83,
+ CV_PPC_SR8 = 84,
+ CV_PPC_SR9 = 85,
+ CV_PPC_SR10 = 86,
+ CV_PPC_SR11 = 87,
+ CV_PPC_SR12 = 88,
+ CV_PPC_SR13 = 89,
+ CV_PPC_SR14 = 90,
+ CV_PPC_SR15 = 91,
+
+ /*
+ ** For all of the special purpose registers add 100 to the SPR# that the
+ ** Motorola/IBM documentation gives with the exception of any imaginary
+ ** registers.
+ */
+
+ /*
+ ** PowerPC Special Purpose Registers ( User Level )
+ */
+ CV_PPC_PC = 99, // PC (imaginary register)
+
+ CV_PPC_MQ = 100, // MPC601
+ CV_PPC_XER = 101,
+ CV_PPC_RTCU = 104, // MPC601
+ CV_PPC_RTCL = 105, // MPC601
+ CV_PPC_LR = 108,
+ CV_PPC_CTR = 109,
+
+ CV_PPC_COMPARE = 110, // part of XER (internal to the debugger only)
+ CV_PPC_COUNT = 111, // part of XER (internal to the debugger only)
+
+ /*
+ ** PowerPC Special Purpose Registers ( Supervisor Level )
+ */
+ CV_PPC_DSISR = 118,
+ CV_PPC_DAR = 119,
+ CV_PPC_DEC = 122,
+ CV_PPC_SDR1 = 125,
+ CV_PPC_SRR0 = 126,
+ CV_PPC_SRR1 = 127,
+ CV_PPC_SPRG0 = 372,
+ CV_PPC_SPRG1 = 373,
+ CV_PPC_SPRG2 = 374,
+ CV_PPC_SPRG3 = 375,
+ CV_PPC_ASR = 280, // 64-bit implementations only
+ CV_PPC_EAR = 382,
+ CV_PPC_PVR = 287,
+ CV_PPC_BAT0U = 628,
+ CV_PPC_BAT0L = 629,
+ CV_PPC_BAT1U = 630,
+ CV_PPC_BAT1L = 631,
+ CV_PPC_BAT2U = 632,
+ CV_PPC_BAT2L = 633,
+ CV_PPC_BAT3U = 634,
+ CV_PPC_BAT3L = 635,
+ CV_PPC_DBAT0U = 636,
+ CV_PPC_DBAT0L = 637,
+ CV_PPC_DBAT1U = 638,
+ CV_PPC_DBAT1L = 639,
+ CV_PPC_DBAT2U = 640,
+ CV_PPC_DBAT2L = 641,
+ CV_PPC_DBAT3U = 642,
+ CV_PPC_DBAT3L = 643,
+
+ /*
+ ** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor Level )
+ */
+
+ /*
+ ** Doesn't appear that IBM/Motorola has finished defining these.
+ */
+
+ CV_PPC_PMR0 = 1044, // MPC620,
+ CV_PPC_PMR1 = 1045, // MPC620,
+ CV_PPC_PMR2 = 1046, // MPC620,
+ CV_PPC_PMR3 = 1047, // MPC620,
+ CV_PPC_PMR4 = 1048, // MPC620,
+ CV_PPC_PMR5 = 1049, // MPC620,
+ CV_PPC_PMR6 = 1050, // MPC620,
+ CV_PPC_PMR7 = 1051, // MPC620,
+ CV_PPC_PMR8 = 1052, // MPC620,
+ CV_PPC_PMR9 = 1053, // MPC620,
+ CV_PPC_PMR10 = 1054, // MPC620,
+ CV_PPC_PMR11 = 1055, // MPC620,
+ CV_PPC_PMR12 = 1056, // MPC620,
+ CV_PPC_PMR13 = 1057, // MPC620,
+ CV_PPC_PMR14 = 1058, // MPC620,
+ CV_PPC_PMR15 = 1059, // MPC620,
+
+ CV_PPC_DMISS = 1076, // MPC603
+ CV_PPC_DCMP = 1077, // MPC603
+ CV_PPC_HASH1 = 1078, // MPC603
+ CV_PPC_HASH2 = 1079, // MPC603
+ CV_PPC_IMISS = 1080, // MPC603
+ CV_PPC_ICMP = 1081, // MPC603
+ CV_PPC_RPA = 1082, // MPC603
+
+ CV_PPC_HID0 = 1108, // MPC601, MPC603, MPC620
+ CV_PPC_HID1 = 1109, // MPC601
+ CV_PPC_HID2 = 1110, // MPC601, MPC603, MPC620 ( IABR )
+ CV_PPC_HID3 = 1111, // Not Defined
+ CV_PPC_HID4 = 1112, // Not Defined
+ CV_PPC_HID5 = 1113, // MPC601, MPC604, MPC620 ( DABR )
+ CV_PPC_HID6 = 1114, // Not Defined
+ CV_PPC_HID7 = 1115, // Not Defined
+ CV_PPC_HID8 = 1116, // MPC620 ( BUSCSR )
+ CV_PPC_HID9 = 1117, // MPC620 ( L2CSR )
+ CV_PPC_HID10 = 1118, // Not Defined
+ CV_PPC_HID11 = 1119, // Not Defined
+ CV_PPC_HID12 = 1120, // Not Defined
+ CV_PPC_HID13 = 1121, // MPC604 ( HCR )
+ CV_PPC_HID14 = 1122, // Not Defined
+ CV_PPC_HID15 = 1123 // MPC601, MPC604, MPC620 ( PIR )
+
+
+} CV_HREG_e;
+
+#pragma pack ( pop )
+
+#endif /* CV_INFO_INCLUDED */
diff --git a/private/windbg/osdebug/include/cvtypes.h b/private/windbg/osdebug/include/cvtypes.h
new file mode 100644
index 000000000..6f181db49
--- /dev/null
+++ b/private/windbg/osdebug/include/cvtypes.h
@@ -0,0 +1,295 @@
+#error Don't include cvtypes.h... Use cvtypes.hxx instead.
+
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cvtypes.h
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 05-Apr-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined _CVTYPES_
+#define _CVTYPES_
+
+#include "types.h"
+
+/*
+** HDEP is a machine dependent size and passes as a general handle.
+** HIND is a machine independent sized handle and is used for things
+** which are passed between machines
+**
+*/
+
+#ifdef STRICT
+ DECLARE_HANDLE(HDEP);
+ DECLARE_HANDLE(HIND);
+#else
+ typedef HANDLE HDEP;
+ typedef HANDLE HIND;
+#endif
+
+
+typedef HDEP FAR * LPHDEP;
+typedef HIND FAR * LPHIND;
+
+
+/* HMEM should be avoided (HDEP should be used instead), but for now we'll
+** define it for backwards compatibility.
+*/
+
+typedef HDEP HMEM;
+typedef HMEM FAR * LPHMEM;
+
+/* These values are used in the SegType field of the Expression Evaluator's
+** TI structure, and as the third parameter to the Symbol Handler's
+** SHGetNearestHsym function.
+*/
+#define EECODE 0x01
+#define EEDATA 0x02
+#define EEANYSEG 0xFFFF
+
+/*
+** HPID
+** HTID
+**
+*/
+
+#ifdef STRICT
+DECLARE_HANDLE(HPID);
+DECLARE_HANDLE(HTID);
+#else
+typedef HIND HPID;
+typedef HIND HTID;
+#endif
+
+typedef USHORT SEGMENT; // 32-bit compiler doesn't like "_segment"
+typedef ULONG UOFF32;
+typedef USHORT UOFF16;
+typedef LONG OFF32;
+typedef SHORT OFF16;
+#if defined (ADDR_16)
+ // we are operating as a 16:16 evaluator only
+ // the address packet will be defined as an offset and a 16 bit filler
+ typedef OFF16 SOFFSET;
+ typedef UOFF16 UOFFSET;
+ typedef UOFF16 OFFSET;
+#else
+ typedef OFF32 SOFFSET;
+ typedef UOFF32 UOFFSET;
+ typedef UOFF32 OFFSET;
+#endif
+
+// address definitions
+// the address packet is always a 16:32 address.
+
+typedef struct {
+ UOFF32 off;
+ SEGMENT seg;
+} address_t;
+
+#define SegAddrT(a) ((a).seg)
+#define OffAddrT(a) ((a).off)
+
+#define AddrTInit(paddrT,segSet,offSet) \
+ { \
+ SegAddrT(*(paddrT)) = segSet; \
+ OffAddrT(*(paddrT)) = offSet; \
+ }
+
+typedef struct {
+ BYTE fFlat :1; // true if address is flat
+ BYTE fOff32 :1; // true if offset is 32 bits
+ BYTE fIsLI :1; // true if segment is linker index
+ BYTE fReal :1; // x86: is segment a real mode address
+ BYTE unused :4; // unused
+} memmode_t;
+
+#define MODE_IS_FLAT(m) ((m).fFlat)
+#define MODE_IS_OFF32(m) ((m).fOff32)
+#define MODE_IS_LI(m) ((m).fIsLI)
+#define MODE_IS_REAL(m) ((m).fReal)
+
+#define ModeInit(pmode,fFlat,fOff32,fLi,fRealSet) \
+ { \
+ MODE_IS_FLAT(*(pmode)) = fFlat; \
+ MODE_IS_OFF32(*(pmode)) = fOff32; \
+ MODE_IS_LI(*(pmode)) = fLi; \
+ MODE_IS_REAL(*(pmode)) = fRealSet; \
+ }
+
+#ifdef STRICT
+DECLARE_HANDLE(HEMI);
+#else
+typedef HIND HEMI; // Executable Module Index
+#endif
+
+typedef struct ADDR {
+ address_t addr;
+ HEMI emi;
+ memmode_t mode;
+} ADDR; //* An address specifier
+typedef ADDR FAR * PADDR; //* REVIEW: BUG: shouldn't be explicitly far
+typedef ADDR FAR * LPADDR;
+
+#define addrAddr(a) ((a).addr)
+#define emiAddr(a) ((a).emi)
+#define modeAddr(a) ((a).mode)
+
+#define AddrInit(paddr,emiSet,segSet,offSet,fFlat,fOff32,fLi,fRealSet) \
+ { \
+ AddrTInit( &(addrAddr(*(paddr))), segSet, offSet ); \
+ emiAddr(*(paddr)) = emiSet; \
+ ModeInit( &(modeAddr(*(paddr))),fFlat,fOff32,fLi,fRealSet); \
+ }
+
+#define ADDR_IS_FLAT(a) (MODE_IS_FLAT(modeAddr(a)))
+#define ADDR_IS_OFF32(a) (MODE_IS_OFF32(modeAddr(a)))
+#define ADDR_IS_LI(a) (MODE_IS_LI(modeAddr(a)))
+#define ADDR_IS_REAL(a) (MODE_IS_REAL(modeAddr(a)))
+
+#define ADDRSEG16(a) { ADDR_IS_FLAT(a) = FALSE; ADDR_IS_OFF32(a) = FALSE; }
+#define ADDRSEG32(a) { ADDR_IS_FLAT(a) = FALSE; ADDR_IS_OFF32(a) = TRUE; }
+#define ADDRLIN32(a) { ADDR_IS_FLAT(a) = TRUE; ADDR_IS_OFF32(a) = TRUE; }
+
+#define GetAddrSeg(a) (SegAddrT(addrAddr(a)))
+#define GetAddrOff(a) (OffAddrT(addrAddr(a)))
+#define SetAddrSeg(a,s) (SegAddrT(addrAddr(*(a)))=s)
+#define SetAddrOff(a,o) (OffAddrT(addrAddr(*(a)))=o)
+
+// Because an ADDR has some filler areas (in the mode and the address_t),
+// it's bad to use memcmp two ADDRs to see if they're equal. Use this
+// macro instead. (I deliberately left out the test for fAddr32(), because
+// I think it's probably not necessary when comparing.)
+#define FAddrsEq(a1, a2) \
+ ( \
+ GetAddrOff(a1) == GetAddrOff(a2) && \
+ GetAddrSeg(a1) == GetAddrSeg(a2) && \
+ ADDR_IS_LI(a1) == ADDR_IS_LI(a2) && \
+ emiAddr(a1) == emiAddr(a2) \
+ )
+
+// address definitions
+// the address packet is always a 16:32 address.
+
+typedef struct FRAME {
+ SEGMENT SS;
+ address_t BP;
+ SEGMENT DS;
+ memmode_t mode;
+ HPID PID;
+ HTID TID;
+} FRAME;
+typedef FRAME FAR *PFRAME; //* REVIEW: BUG: shouldn't be explicitly far
+
+#define addrFrameSS(a) ((a).SS)
+#define addrFrameBP(a) ((a).BP)
+#define GetFrameBPOff(a) ((a).BP.off)
+#define GetFrameBPSeg(a) ((a).BP.seg)
+#define SetFrameBPOff(a,o) ((a).BP.off = o)
+#define SetFrameBPSeg(a,s) ((a).BP.seg = s)
+#define FRAMEMODE(a) ((a).mode)
+#define FRAMEPID(a) ((a).PID)
+#define FRAMETID(a) ((a).TID)
+
+#define FrameFlat(a) MODE_IS_FLAT((a).mode)
+#define FrameOff32(a) MODE_IS_OFF32((a).mode)
+#define FrameReal(a) MODE_IS_REAL((a).mode)
+
+
+/*
+** A few public types related to the linked list manager
+*/
+
+typedef HDEP HLLI; //* A handle to a linked list
+typedef HIND HLLE; //* A handle to a linked list entry
+
+typedef void (FAR PASCAL * LPFNKILLNODE)( LPV );
+typedef int (FAR PASCAL * LPFNFCMPNODE)( LPV, LPV, LONG );
+
+typedef USHORT LLF; //* Linked List Flags
+#define llfNull (LLF)0x0
+#define llfAscending (LLF)0x1
+#define llfDescending (LLF)0x2
+
+
+/*
+ *
+ */
+
+typedef struct {
+ char b[10];
+} REAL10;
+
+typedef REAL10 FLOAT10;
+
+//
+// copied from winnt.h:
+//
+#ifndef PAGE_NOACCESS
+
+#define PAGE_NOACCESS 0x01
+#define PAGE_READONLY 0x02
+#define PAGE_READWRITE 0x04
+#define PAGE_WRITECOPY 0x08
+#define PAGE_EXECUTE 0x10
+#define PAGE_EXECUTE_READ 0x20
+#define PAGE_EXECUTE_READWRITE 0x40
+#define PAGE_EXECUTE_WRITECOPY 0x80
+#define PAGE_GUARD 0x100
+#define PAGE_NOCACHE 0x200
+
+#define MEM_COMMIT 0x1000
+#define MEM_RESERVE 0x2000
+#define MEM_FREE 0x10000
+
+#define MEM_PRIVATE 0x20000
+#define MEM_MAPPED 0x40000
+//#define SEC_IMAGE 0x1000000
+//#define MEM_IMAGE SEC_IMAGE
+#define MEM_IMAGE 0x1000000
+
+#endif
+
+typedef struct _MEMINFO {
+ ADDR addr;
+ ADDR addrAllocBase;
+ UOFF32 uRegionSize;
+ DWORD dwProtect;
+ DWORD dwState;
+ DWORD dwType;
+} MEMINFO;
+typedef MEMINFO FAR * LPMEMINFO;
+
+/*
+** Return values for mtrcEndian -- big or little endian -- which
+** byte is [0] most or least significat byte
+*/
+enum _END {
+ endBig,
+ endLittle
+};
+typedef DWORD END;
+
+enum _MPT {
+ mptix86,
+ mptm68k,
+ mptdaxp,
+ mptmips,
+ mptmppc,
+ mptUnknown
+};
+typedef DWORD MPT;
+
+#endif // _CVTYPES_
diff --git a/private/windbg/osdebug/include/cvtypes.hxx b/private/windbg/osdebug/include/cvtypes.hxx
new file mode 100644
index 000000000..018ebf694
--- /dev/null
+++ b/private/windbg/osdebug/include/cvtypes.hxx
@@ -0,0 +1,264 @@
+// CVTYPES.H
+//
+// This file contains a common set of base type declarations
+// between multiple CodeView projects. If you touch this in one
+// project be sure to copy it to all other projects as well.
+
+#ifndef _VC_VER_INC
+#include "..\include\vcver.h"
+#endif
+
+#ifndef CV_PROJECT_BASE_TYPES
+#define CV_PROJECT_BASE_TYPES
+
+#include "dbapiver.h"
+#include "types.h"
+
+// HDEP is a machine dependent size and passes as a general handle.
+// HIND is a machine independent sized handle and is used for things
+// which are passed between machines
+
+#ifdef STRICT
+DECLARE_HANDLE(HDEP);
+DECLARE_HANDLE(HIND);
+#else
+typedef HANDLE HDEP;
+typedef HANDLE HIND;
+#endif
+
+typedef HDEP * LPHDEP;
+typedef HIND * LPHIND;
+
+// HMEM should be avoided (HDEP should be used instead), but for now we'll
+// define it for backwards compatibility.
+
+typedef HDEP HMEM;
+typedef HMEM * LPHMEM;
+
+// These values are used in the SegType field of the Expression Evaluator's
+// TI structure, and as the third parameter to the Symbol Handler's
+// SHGetNearestHsym function.
+
+#define EECODE 0x01
+#define EEDATA 0x02
+#define EEANYSEG 0xFFFF
+
+#ifdef STRICT
+DECLARE_HANDLE(HPID);
+DECLARE_HANDLE(HTID);
+#else
+typedef HIND HPID;
+typedef HIND HTID;
+#endif
+
+typedef USHORT SEGMENT; // 32-bit compiler doesn't like "_segment"
+typedef ULONG UOFF32;
+typedef USHORT UOFF16;
+typedef LONG OFF32;
+typedef SHORT OFF16;
+
+typedef OFF32 SOFFSET;
+typedef UOFF32 UOFFSET;
+typedef UOFF32 OFFSET;
+typedef UOFFSET *LPUOFFSET;
+
+// address definitions
+// the address packet is always a 16:32 address.
+
+typedef struct {
+ UOFF32 off;
+ SEGMENT seg;
+} address_t;
+
+#define SegAddrT(a) ((a).seg)
+#define OffAddrT(a) ((a).off)
+
+#define AddrTInit(paddrT,segSet,offSet) \
+ { \
+ SegAddrT(*(paddrT)) = segSet; \
+ OffAddrT(*(paddrT)) = offSet; \
+ }
+
+typedef struct {
+ BYTE fFlat :1; // true if address is flat
+ BYTE fOff32 :1; // true if offset is 32 bits
+ BYTE fIsLI :1; // true if segment is linker index
+ BYTE fReal :1; // x86: is segment a real mode address
+ BYTE unused :4; // unused
+} memmode_t;
+
+#define MODE_IS_FLAT(m) ((m).fFlat)
+#define MODE_IS_OFF32(m) ((m).fOff32)
+#define MODE_IS_LI(m) ((m).fIsLI)
+#define MODE_IS_REAL(m) ((m).fReal)
+
+#define ModeInit(pmode,fFlat,fOff32,fLi,fRealSet) \
+ { \
+ MODE_IS_FLAT(*(pmode)) = fFlat; \
+ MODE_IS_OFF32(*(pmode)) = fOff32; \
+ MODE_IS_LI(*(pmode)) = fLi; \
+ MODE_IS_REAL(*(pmode)) = fRealSet; \
+ }
+
+#ifdef STRICT
+DECLARE_HANDLE(HEMI);
+#else
+typedef HIND HEMI; // Executable Module Index
+#endif
+
+typedef struct ADDR {
+ address_t addr;
+ HEMI emi;
+ memmode_t mode;
+} ADDR; // An address specifier
+typedef ADDR * PADDR;
+typedef ADDR * LPADDR;
+
+#define addrAddr(a) ((a).addr)
+#define emiAddr(a) ((a).emi)
+#define modeAddr(a) ((a).mode)
+
+#define AddrInit(paddr,emiSet,segSet,offSet,fFlat,fOff32,fLi,fRealSet) \
+ { \
+ AddrTInit( &(addrAddr(*(paddr))), segSet, offSet ); \
+ emiAddr(*(paddr)) = emiSet; \
+ ModeInit( &(modeAddr(*(paddr))),fFlat,fOff32,fLi,fRealSet); \
+ }
+
+#define ADDR_IS_FLAT(a) (MODE_IS_FLAT(modeAddr(a)))
+#define ADDR_IS_OFF32(a) (MODE_IS_OFF32(modeAddr(a)))
+#define ADDR_IS_LI(a) (MODE_IS_LI(modeAddr(a)))
+#define ADDR_IS_REAL(a) (MODE_IS_REAL(modeAddr(a)))
+
+#define ADDRSEG16(a) {ADDR_IS_FLAT(a) = FALSE; ADDR_IS_OFF32(a) = FALSE;}
+#define ADDRSEG32(a) {ADDR_IS_FLAT(a) = FALSE; ADDR_IS_OFF32(a) = TRUE;}
+#define ADDRLIN32(a) {ADDR_IS_FLAT(a) = TRUE; ADDR_IS_OFF32(a) = TRUE;}
+
+#define GetAddrSeg(a) ((a).addr.seg)
+#define GetAddrOff(a) ((a).addr.off)
+#define SetAddrSeg(a,s) ((a)->addr.seg=s)
+#define SetAddrOff(a,o) ((a)->addr.off=o)
+
+// Because an ADDR has some filler areas (in the mode and the address_t),
+// it's bad to use memcmp two ADDRs to see if they're equal. Use this
+// macro instead. (I deliberately left out the test for fAddr32(), because
+// I think it's probably not necessary when comparing.)
+#define FAddrsEq(a1, a2) \
+ ( \
+ GetAddrOff(a1) == GetAddrOff(a2) && \
+ GetAddrSeg(a1) == GetAddrSeg(a2) && \
+ ADDR_IS_LI(a1) == ADDR_IS_LI(a2) && \
+ emiAddr(a1) == emiAddr(a2) \
+ )
+
+// address definitions
+// the address packet is always a 16:32 address.
+
+typedef struct FRAME {
+ SEGMENT SS;
+ address_t BP;
+ SEGMENT DS;
+ memmode_t mode;
+ HPID PID;
+ HTID TID;
+ address_t SLP; // Static link pointer
+} FRAME;
+typedef FRAME *PFRAME;
+
+#define addrFrameSS(a) ((a).SS)
+#define addrFrameBP(a) ((a).BP)
+#define GetFrameBPOff(a) ((a).BP.off)
+#define GetFrameBPSeg(a) ((a).BP.seg)
+#define SetFrameBPOff(a,o) ((a).BP.off = o)
+#define SetFrameBPSeg(a,s) ((a).BP.seg = s)
+#define GetFrameSLPOff(a) ((a).SLP.off)
+#define GetFrameSLPSeg(a) ((a).SLP.seg)
+#define SetFrameSLPOff(a,o) ((a).SLP.off = o)
+#define SetFrameSLPSeg(a,s) ((a).SLP.seg = s)
+#define FRAMEMODE(a) ((a).mode)
+#define FRAMEPID(a) ((a).PID)
+#define FRAMETID(a) ((a).TID)
+
+#define FrameFlat(a) MODE_IS_FLAT((a).mode)
+#define FrameOff32(a) MODE_IS_OFF32((a).mode)
+#define FrameReal(a) MODE_IS_REAL((a).mode)
+
+// A few public types related to the linked list manager
+
+typedef HDEP HLLI; // A handle to a linked list
+// typedef HDEP HLLE; // A handle to a linked list entry
+typedef HIND HLLE; // A handle to a linked list entry
+
+typedef void (* LPFNKILLNODE)(PVOID);
+typedef int (* LPFNFCMPNODE)(PVOID, PVOID, LONG );
+
+typedef USHORT LLF; // Linked List Flags
+#define llfNull (LLF)0x0
+#define llfAscending (LLF)0x1
+#define llfDescending (LLF)0x2
+
+// EXPCALL indicates that a function should use whatever calling
+// convention is preferable for exported functions.
+
+#define EXPCALL __stdcall
+
+// copied from winnt.h:
+
+#ifndef PAGE_NOACCESS
+
+#define PAGE_NOACCESS 0x01
+#define PAGE_READONLY 0x02
+#define PAGE_READWRITE 0x04
+#define PAGE_WRITECOPY 0x08
+#define PAGE_EXECUTE 0x10
+#define PAGE_EXECUTE_READ 0x20
+#define PAGE_EXECUTE_READWRITE 0x40
+#define PAGE_EXECUTE_WRITECOPY 0x80
+#define PAGE_GUARD 0x100
+#define PAGE_NOCACHE 0x200
+
+#define MEM_COMMIT 0x1000
+#define MEM_RESERVE 0x2000
+#define MEM_FREE 0x10000
+
+#define MEM_PRIVATE 0x20000
+#define MEM_MAPPED 0x40000
+#define MEM_IMAGE 0x1000000
+
+#endif
+
+typedef struct _MEMINFO {
+ ADDR addr;
+ ADDR addrAllocBase;
+ UOFF32 uRegionSize;
+ DWORD dwProtect;
+ DWORD dwState;
+ DWORD dwType;
+} MEMINFO;
+typedef MEMINFO * LPMEMINFO;
+
+// Return values for mtrcEndian -- big or little endian -- which
+// byte is [0] most or least significat byte
+
+enum _END {
+ endBig,
+ endLittle
+};
+typedef DWORD END;
+
+// Return values for mtrcProcessorType
+
+enum _MPT {
+ mptix86 = 1, // Intel X86
+ mptm68k = 2, // Mac 68K
+ mptdaxp = 3, // Alpha AXP
+ mptmips = 4, // MIPS
+ mptmppc = 5, // Mac PPC
+ mptntppc = 6, // NT PPC
+ mptUnknown
+};
+typedef DWORD MPT;
+
+#include <dbgver.h> // For AVS definition and support functions
+
+#endif // CV_PROJECT_BASE_TYPES
diff --git a/private/windbg/osdebug/include/dbapiver.h b/private/windbg/osdebug/include/dbapiver.h
new file mode 100644
index 000000000..b80ffe313
--- /dev/null
+++ b/private/windbg/osdebug/include/dbapiver.h
@@ -0,0 +1,6 @@
+#ifndef _VC_VER_INC
+#include "..\include\vcver.h"
+#endif
+
+#define DBG_API_VERSION 6
+#define DBG_API_SUBVERSION 3
diff --git a/private/windbg/osdebug/include/dbgver.h b/private/windbg/osdebug/include/dbgver.h
new file mode 100644
index 000000000..f26b94cf3
--- /dev/null
+++ b/private/windbg/osdebug/include/dbgver.h
@@ -0,0 +1,135 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dbgver.h
+
+Abstract:
+
+Author:
+
+ Kent D. Forschmiedt (kentf) 25-Jan-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined _DBGVER_
+#define _DBGVER_
+
+/*
+** DBG_API_VERSION is the major version number used to specify the
+** api version of the debugger or debug dll. For release versions
+** dlls will export this and debuggers will check against this
+** version to verify that it can use the dll.
+**
+** For beta and debug versions, this number will be used in
+** conjunction with minor and revision numbers (probably derived
+** from SLM rmm & rup) to verify compatibility.
+**
+** Until the API has stabilized, we will most likely have to
+** rev this version number for every major product release.
+**
+*/
+
+#include <dbapiver.h>
+
+/* AVS - Api Version Structure:
+**
+** All debug dlls should be prepared to return a pointer to this
+** structure conaining its vital statistics. The debugger should
+** check first two characters of the dll's name against rgchType
+** and the version numbers as described in the DBG_API_VERSION
+** and show the user an error if any of these tests fail.
+**
+*/
+
+typedef enum {
+ rlvtRelease,
+ rlvtBeta,
+ rlvtDebug
+} RLVT; // ReLease Version Type
+
+typedef struct _AVS {
+ CHAR rgchType [ 2 ]; // Component name (EE,EM,TL,SH,DM)
+ WORD rlvt; // ReLease Version Type
+ BYTE iApiVer; // DBG_API_VERSION
+ BYTE iApiSubVer; // DBG_API_SUBVERSION
+ WORD iRup; // Revision number
+ WORD chBuild; // Build of revision # (a,b,c,d)
+ LSZ lszTitle; // User readable text describing the DLL
+ MPT mpt; // CPU binary is running on
+ WORD iRmj; // Major version number
+ WORD iRmm; // Minor version number
+} AVS; // Api Version Structure
+typedef AVS *LPAVS;
+
+
+/* DBGVersionCheck:
+**
+** All debug dlls should provide this API and support the return
+** of a pointer to the structure described above even before
+** initialization takes place.
+*/
+
+#if defined(_M_IX86)
+#define __dbgver_cpu__ mptix86
+#elif defined(_M_MRX000)
+#define __dbgver_cpu__ mptmips
+#elif defined(_M_ALPHA)
+#define __dbgver_cpu__ mptdaxp
+#elif defined(_M_PPC)
+#define __dbgver_cpu__ mptntppc
+#else
+#error( "unknown host machine" );
+#endif
+
+#define DEBUG_VERSION(C1,C2,TITLE) \
+AVS Avs = { \
+ { C1, C2 }, \
+ rlvtDebug, \
+ DBG_API_VERSION, \
+ DBG_API_SUBVERSION, \
+ 0, \
+ '\0', \
+ TITLE, \
+ __dbgver_cpu__, \
+ 0, \
+ 0, \
+ };
+
+#define RELEASE_VERSION(C1,C2,TITLE) \
+AVS Avs = { \
+ { C1, C2 }, \
+ rlvtRelease, \
+ DBG_API_VERSION, \
+ DBG_API_SUBVERSION, \
+ 0, \
+ '\0', \
+ TITLE, \
+ __dbgver_cpu__, \
+ 0, \
+ 0, \
+};
+
+#undef MINOR
+#undef MAJOR
+
+#define DBGVERSIONPROCNAME "DBGVersionCheck"
+
+typedef LPAVS (*DBGVERSIONPROC)(VOID);
+LPAVS WINDBGVersionCheck(VOID);
+LPAVS DBGVersionCheck(VOID);
+
+
+#define DBGVERSIONFUNCTION() \
+ LPAVS WINDBGVersionCheck( void ) { return &Avs; } \
+ LPAVS DBGVersionCheck( void ) { return &Avs; }
+
+#define DBGVERSIONCHECK() DBGVERSIONFUNCTION()
+
+#endif // _DBGVER_
diff --git a/private/windbg/osdebug/include/eeapi.h b/private/windbg/osdebug/include/eeapi.h
new file mode 100644
index 000000000..cb19423de
--- /dev/null
+++ b/private/windbg/osdebug/include/eeapi.h
@@ -0,0 +1,395 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Eeapi.h
+
+Abstract:
+
+ This file contains all types and APIs that are defined by the
+ Expression Evaluator and are publicly accessible by other components.
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+Notes:
+
+ The master copy of this file resides in the CodeView project. All
+ Microsoft projects are required to use the master copy without
+ modification. Modification of the master version or a copy without
+ consultation with all parties concerned is extremely risky.
+
+ The projects known to use this version (1.00.00) are:
+
+ Codeview
+ Sequoia
+ C/C++ expression evaluator
+ Cobol expression evaluator
+ QC/Windows
+ Pascal 2.0 expression evaluator
+
+--*/
+
+#if ! defined( _EEAPI_ )
+#define _EEAPI_
+
+
+// **********************************************************************
+// * *
+// * Initialization Structures *
+// * *
+// **********************************************************************
+
+typedef struct {
+void FAR * (LOADDS PASCAL *pMHlpvAlloc)( size_t );
+void (LOADDS PASCAL *pMHFreeLpv)(void FAR *);
+HEXE (LOADDS PASCAL *pSHGetNextExe)(HEXE);
+HEXE (LOADDS PASCAL *pSHHexeFromHmod)(HMOD);
+HMOD (LOADDS PASCAL *pSHGetNextMod)(HEXE, HMOD);
+PCXT (LOADDS PASCAL *pSHGetCxtFromHmod)(HMOD, PCXT);
+PCXT (LOADDS PASCAL *pSHGetCxtFromHexe)(HEXE, PCXT);
+PCXT (LOADDS PASCAL *pSHSetCxt)(LPADDR, PCXT);
+PCXT (LOADDS PASCAL *pSHSetCxtMod)(LPADDR, PCXT);
+HSYM (LOADDS PASCAL *pSHFindNameInGlobal)(HSYM, PCXT, LPSSTR, SHFLAG, PFNCMP, PCXT);
+HSYM (LOADDS PASCAL *pSHFindNameInContext)(HSYM, PCXT, LPSSTR, SHFLAG, PFNCMP, PCXT);
+HSYM (LOADDS PASCAL *pSHGoToParent)(PCXT, PCXT);
+HSYM (LOADDS PASCAL *pSHHsymFromPcxt)(PCXT);
+HSYM (LOADDS PASCAL *pSHNextHsym)(HMOD, HSYM);
+PCXF (LOADDS PASCAL *pSHGetFuncCxf)(LPADDR, PCXF);
+char FAR * (LOADDS PASCAL *pSHGetModName)(HMOD);
+char FAR * (LOADDS PASCAL *pSHGetExeName)(HEXE);
+char FAR * (LOADDS PASCAL *pSHGetModNameFromHexe)(HEXE);
+char FAR * (LOADDS PASCAL *pSHGetSymFName)(HEXE);
+HEXE (LOADDS PASCAL *pSHGethExeFromName)(char FAR *);
+HEXE (LOADDS PASCAL *pSHGethExeFromModuleName)(char FAR *);
+UOFF32 (LOADDS PASCAL *pSHGetNearestHsym)(LPADDR, HMOD, int, PHSYM);
+SHFLAG (LOADDS PASCAL *pSHIsInProlog)(PCXT);
+SHFLAG (LOADDS PASCAL *pSHIsAddrInCxt)(PCXT, LPADDR);
+UINT (LOADDS PASCAL *pSHModelFromAddr)(PADDR,LPW,LPB,UOFFSET FAR *);
+
+
+BOOL (LOADDS PASCAL *pSLLineFromAddr) ( LPADDR, unsigned short FAR *, SHOFF FAR *, SHOFF FAR * );
+BOOL (LOADDS PASCAL *pSLFLineToAddr) ( HSF, WORD, LPADDR, SHOFF FAR *, WORD FAR * );
+char FAR * (LOADDS PASCAL *pSLNameFromHsf) ( HSF );
+HMOD (LOADDS PASCAL *pSLHmodFromHsf) ( HEXE, HSF );
+HSF (LOADDS PASCAL *pSLHsfFromPcxt) ( PCXT );
+HSF (LOADDS PASCAL *pSLHsfFromFile) ( HMOD, char FAR * );
+
+UOFF32 (LOADDS PASCAL *pPHGetNearestHsym)(LPADDR, HEXE, PHSYM);
+HSYM (LOADDS PASCAL *pPHFindNameInPublics)(HSYM, HEXE, LPSSTR, SHFLAG, PFNCMP);
+HTYPE (LOADDS PASCAL *pTHGetTypeFromIndex)(HMOD, THIDX);
+HTYPE (LOADDS PASCAL *pTHGetNextType)(HMOD, HTYPE);
+HDEP (LOADDS PASCAL *pMHMemAllocate)(UINT);
+HDEP (LOADDS PASCAL *pMHMemReAlloc)(HDEP, UINT);
+void (LOADDS PASCAL *pMHMemFree)(HDEP);
+LPV (LOADDS PASCAL *pMHMemLock)(HDEP);
+void (LOADDS PASCAL *pMHMemUnLock)(HDEP);
+SHFLAG (LOADDS PASCAL *pMHIsMemLocked)(HDEP);
+UINT (LOADDS PASCAL *pDHGetDebuggeeBytes)(ADDR, UINT, void FAR *);
+UINT (LOADDS PASCAL *pDHPutDebuggeeBytes)(ADDR, UINT, void FAR *);
+PSHREG (LOADDS PASCAL *pDHGetReg)(PSHREG, PCXT);
+PSHREG (LOADDS PASCAL *pDHSetReg)(PSHREG, PCXT);
+UINT (LOADDS PASCAL *pDHSetupExecute)(LPHDEP);
+UINT (LOADDS PASCAL *pDHCleanUpExecute)(HDEP);
+UINT (LOADDS PASCAL *pDHStartExecute)(HDEP, LPADDR, BOOL, SHCALL);
+char FAR *pin386mode;
+char FAR *pis_assign;
+void (LOADDS PASCAL *passert)(LPCH,LPCH,UINT);
+void (LOADDS PASCAL *pquit)(UINT);
+ushort FAR *pArrayDefault;
+SHFLAG (LOADDS PASCAL *pSHCompareRE)(char FAR *, char FAR *, BOOL);
+SHFLAG (LOADDS PASCAL *pSHFixupAddr)(LPADDR);
+SHFLAG (LOADDS PASCAL *pSHUnFixupAddr)(LPADDR);
+SHFLAG (LOADDS PASCAL *pCVfnCmp)(HVOID, HVOID, char FAR *, SHFLAG);
+SHFLAG (LOADDS PASCAL *pCVtdCmp)(HVOID, HVOID, char FAR *, SHFLAG);
+SHFLAG (LOADDS PASCAL *pCVcsCmp)(HVOID, HVOID, char FAR *, SHFLAG);
+BOOL (LOADDS PASCAL *pSYGetAddr)(PADDR, int);
+DWORD (LOADDS PASCAL *pSYGetMemInfo)(LPMEMINFO);
+BOOL (LOADDS PASCAL *pSHWantSymbols)(HEXE);
+} CVF; // CodeView kernel Functions exported to the Expression Evaluator
+typedef CVF FAR * PCVF;
+
+typedef struct {
+ short (CDECL *pintLoadDS)();
+ char NEAR * (CDECL *pultoa)(ulong, char NEAR *, int);
+ char NEAR * (CDECL *pitoa)(int, char NEAR *, int);
+ char NEAR * (CDECL *pltoa)(long, char NEAR *, int);
+ int (CDECL *peprintf)(const char FAR *, char FAR *, char FAR *, int);
+ int (CDECL *psprintf)(char NEAR *, const char FAR *, ...);
+} CRF; // C Runtime functions exported to the Expression Evaluator
+typedef CRF FAR * PCRF;
+
+typedef struct CI {
+ char cbCI;
+ char Version;
+ CVF FAR * pStructCVAPI;
+ CRF FAR * pStructCRuntime;
+} CI;
+typedef CI FAR * PCI;
+
+
+typedef struct HDR_TYPE {
+ ushort offname;
+ ushort lenname;
+ ushort offtrail;
+} HDR_TYPE;
+typedef HDR_TYPE FAR *PHDR_TYPE;
+
+// **********************************************************************
+// * *
+// * the expr evaluator stuff *
+// * *
+// **********************************************************************
+
+typedef HDEP HSYML; //* An hsym list
+typedef HSYML FAR * PHSYML; //* A pointer to a hsym list
+typedef uint EERADIX;
+typedef EERADIX FAR * PEERADIX;
+typedef uchar FAR * PEEFORMAT;
+typedef ushort EESTATUS;
+typedef HDEP EEHSTR;
+typedef EEHSTR FAR * PEEHSTR;
+typedef HDEP HTM;
+typedef HTM FAR * PHTM;
+typedef HDEP HTI;
+typedef HTI FAR * PHTI;
+
+
+typedef enum {
+ fmtAscii = 0,
+ fmtInt = 1,
+ fmtUInt = 2,
+ fmtFloat = 3,
+ fmtAddress = 4,
+ fmtUnicode = 5,
+ fmtBasis = 0x0f,
+
+ fmtOverRide = 0x2000, // override logic to force radix
+ fmtZeroPad = 0x4000
+} FMTTYPE;
+
+
+// Error return values
+#define EENOERROR 0
+#define EENOMEMORY 1
+#define EEGENERAL 2
+#define EEBADADDR 3
+#define EEBADFORMAT 4
+#define EEOVERRUN 5
+#define EEOPTIONAL 6 // expression valid for optional form
+#define EEDEFAULT 7 // argument was missing; default value was used
+#define EECATASTROPHIC 0XFF
+
+typedef enum {
+ EEHORIZONTAL,
+ EEVERTICAL,
+ EEBPADDRESS
+} EEDSP; // Display format specifier
+
+typedef enum {
+ EENOTEXP,
+ EEAGGREGATE,
+ EETYPE,
+ EEPOINTER,
+ EETYPENOTEXP
+} EEPDTYP;
+typedef EEPDTYP FAR *PEEPDTYP;
+
+typedef enum {
+ EEFMT_32 = 0x01, /* Display a 32-bit offset */
+ EEFMT_SEG = 0x02, /* Display a segment */
+ EEFMT_LOWER = 0x04, /* Use lowercase letters */
+ EEFMT_REAL = 0x08 /* Real mode address */
+} EEFMTFLGS;
+
+typedef struct TML {
+ unsigned cTMListMax;
+ unsigned cTMListAct;
+ unsigned iTMError;
+ HDEP hTMList;
+} TML;
+typedef TML FAR *PTML;
+
+#define TMLISTCNT 20 // number of entries in TM list
+
+
+typedef struct RI {
+ ushort fSegType :1;
+ ushort fAddr :1;
+ ushort fValue :1;
+ ushort fSzBits :1;
+ ushort fSzBytes :1;
+ ushort fLvalue :1;
+ ushort Type;
+} RI;
+typedef RI FAR * PRI;
+
+typedef struct TI {
+ RI fResponse;
+ struct {
+ ushort SegType :4;
+ ushort fLvalue :1;
+ ushort fAddrInReg :1;
+ ushort fBPRel :1;
+ ushort fFunction :1;
+ ushort fLData :1; // True if expression references local data
+ ushort fGData :1; // True if expression references global data
+ ushort fFmtStr :1;
+ } u;
+ union {
+ ADDR AI;
+ ushort hReg; // This is really a CV_HREG_e
+ } u2;
+ ulong cbValue;
+#ifdef i386
+ char Value[0];
+#else
+ char Value[1];
+#endif
+} TI;
+typedef TI FAR * PTI;
+
+typedef struct {
+ HSYM hSym;
+ CXT CXT;
+} HCS;
+
+typedef struct {
+ CXT CXT;
+ ushort cHCS;
+#ifdef i386
+ HCS rgHCS[0];
+#else
+ HCS rgHCS[1];
+#endif
+} CXTL;
+
+typedef HDEP HCXTL;
+typedef HCXTL FAR * PHCXTL;
+typedef CXTL FAR * PCXTL;
+
+// Structures for Get/Free HSYMList
+
+// Search request / response flags for Get/Free HSYMList
+
+#define HSYMR_lexical 0x0001 // lexical out to function scope
+#define HSYMR_function 0x0002 // function scope
+#define HSYMR_class 0x0004 // class scope
+#define HSYMR_module 0x0008 // module scope
+#define HSYMR_global 0x0010 // global symbol table scope
+#define HSYMR_exe 0x0020 // all other module scope
+#define HSYMR_public 0x0040 // public symbols
+#define HSYMR_nocase 0x8000 // case insensitive
+#define HSYMR_allscopes \
+ HSYMR_lexical | \
+ HSYMR_function | \
+ HSYMR_class | \
+ HSYMR_module | \
+ HSYMR_global | \
+ HSYMR_exe | \
+ HSYMR_public
+
+// structure describing HSYM list for a context
+
+typedef struct HSL_LIST {
+ ushort request; // context that this block statisfies
+ struct {
+ ushort isused :1; // block contains data if true
+ ushort hascxt :1; // context packet has been stored
+ ushort complete :1; // block is complete if true
+ ushort isclass :1; // context is class if true
+ } status;
+ HSYM hThis; // handle of this pointer if class scope
+ ushort symbolcnt; // number of symbol handles in this block
+ CXT Cxt; // context for this block of symbols
+ HSYM hSym[]; // list of symbol handles
+} HSL_LIST;
+typedef HSL_LIST FAR *PHSL_LIST;
+
+
+typedef struct HSL_HEAD {
+ ushort size; // number of bytes in buffer
+ ushort remaining; // remaining space in buffer
+ PHSL_LIST pHSLList; // pointer to current context list (EE internal)
+ struct {
+ ushort endsearch :1; // end of search reached if true
+ ushort fatal :1; // fatal error if true
+ } status;
+ ushort blockcnt; // number of CXT blocks in buffer
+ ushort symbolcnt; // number of symbol handles in buffer
+ HDEP restart; // handle of search restart information
+} HSL_HEAD;
+typedef HSL_HEAD FAR *PHSL_HEAD;
+
+typedef struct {
+void (LOADDS PASCAL *pEEFreeStr)(EEHSTR);
+EESTATUS (LOADDS PASCAL *pEEGetError)(PHTM, EESTATUS, PEEHSTR);
+EESTATUS (LOADDS PASCAL *pEEParse)(char FAR *, EERADIX, SHFLAG, PHTM, uint FAR *);
+EESTATUS (LOADDS PASCAL *pEEBindTM)(PHTM, PCXT, SHFLAG, SHFLAG,BOOL);
+EESTATUS (LOADDS PASCAL *pEEvaluateTM)(PHTM, PFRAME, EEDSP);
+EESTATUS (LOADDS PASCAL *pEEGetExprFromTM)(PHTM, PEERADIX, PEEHSTR, ushort FAR *);
+EESTATUS (LOADDS PASCAL *pEEGetValueFromTM)(PHTM, EERADIX, PEEFORMAT, PEEHSTR);
+EESTATUS (LOADDS PASCAL *pEEGetNameFromTM)(PHTM, PEEHSTR);
+EESTATUS (LOADDS PASCAL *pEEGetTypeFromTM)(PHTM, EEHSTR, PEEHSTR, ulong);
+EESTATUS (LOADDS PASCAL *pEEFormatCXTFromPCXT)(PCXT, PEEHSTR, BOOL);
+void (LOADDS PASCAL *pEEFreeTM)(PHTM);
+EESTATUS (LOADDS PASCAL *pEEParseBP)(char FAR *, EERADIX, SHFLAG, PCXF, PTML, ulong, uint FAR *, SHFLAG);
+void (LOADDS PASCAL *pEEFreeTML)(PTML);
+EESTATUS (LOADDS PASCAL *pEEInfoFromTM)(PHTM, PRI, PHTI);
+void (LOADDS PASCAL *pEEFreeTI)(PHTI);
+EESTATUS (LOADDS PASCAL *pEEGetCXTLFromTM)(PHTM, PHCXTL);
+void (LOADDS PASCAL *pEEFreeCXTL)(PHCXTL);
+EESTATUS (LOADDS PASCAL *pEEAssignTMToTM)(PHTM, PHTM);
+EEPDTYP (LOADDS PASCAL *pEEIsExpandable)(PHTM);
+SHFLAG (LOADDS PASCAL *pEEAreTypesEqual)(PHTM, PHTM);
+EESTATUS (LOADDS PASCAL *pEEcChildrenTM)(PHTM, long FAR *, PSHFLAG);
+EESTATUS (LOADDS PASCAL *pEEGetChildTM)(PHTM, long, PHTM, uint FAR *, SHFLAG, uint);
+EESTATUS (LOADDS PASCAL *pEEDereferenceTM)(PHTM, PHTM, uint FAR *, SHFLAG);
+EESTATUS (LOADDS PASCAL *pEEcParamTM)(PHTM, ushort FAR *, PSHFLAG);
+EESTATUS (LOADDS PASCAL *pEEGetParmTM)(PHTM, uint, PHTM, uint FAR *, SHFLAG, uint);
+EESTATUS (LOADDS PASCAL *pEEGetTMFromHSYM)(HSYM, PCXT, PHTM, uint FAR *, SHFLAG);
+EESTATUS (LOADDS PASCAL *pEEFormatAddress)(SHSEG, SHOFF, char FAR *, uint, uint);
+EESTATUS (LOADDS PASCAL *pEEGetHSYMList)(PHSYML, PCXT, ushort, uchar FAR *, SHFLAG);
+void (LOADDS PASCAL *pEEFreeHSYMList)(PHSYML);
+EESTATUS (LOADDS PASCAL *pEEFormatAddr)(LPADDR, char FAR *, uint, uint);
+EESTATUS (LOADDS PASCAL *pEEUnFormatAddr)(LPADDR, char FAR *);
+SHFLAG (LOADDS PASCAL *pfnCmp)(HVOID, HVOID, char FAR *, SHFLAG);
+SHFLAG (LOADDS PASCAL *ptdCmp)(HVOID, HVOID, char FAR *, SHFLAG);
+SHFLAG (LOADDS PASCAL *pcsCmp)(HVOID, HVOID, char FAR *, SHFLAG);
+EESTATUS (LOADDS PASCAL *pEEFormatMemory)(char FAR *, uint, char FAR *, uint, FMTTYPE, uint);
+EESTATUS (LOADDS PASCAL *pEEUnformatMemory)(uchar FAR *, char FAR *, uint, FMTTYPE, uint);
+EESTATUS (LOADDS PASCAL *pEEFormatEnumerate)(uint, uint FAR *, uint FAR *, uint FAR *,
+ uint FAR *, uint FAR *, LPCH FAR *);
+HTYPE (LOADDS PASCAL *pEEGetHtypeFromTM)(PHTM);
+void (LOADDS PASCAL *pEESetSuffix)(char);
+
+} EXF;
+typedef EXF FAR * PEXF;
+
+typedef struct EI {
+ char cbEI;
+ char Version;
+ PEXF pStructExprAPI;
+ char Language;
+ char FAR *IdCharacters;
+ char FAR *EETitle;
+ char FAR *EESuffixes;
+ char FAR *Assign; // length prefixed assignment operator
+} EI;
+typedef EI FAR * PEI;
+
+// FNEEINIT is the prototype for the EEInitializeExpr function
+typedef VOID LOADDS PASCAL FAR FNEEINIT(PCI, PEI);
+typedef VOID (PASCAL LOADDS FAR * LPFNEEINIT)(PCI, PEI);
+
+// This is the only EE function that's actually exported from the DLL
+//FNEEINIT EEInitializeExpr;
+
+#endif // _EEAPI_
diff --git a/private/windbg/osdebug/include/emdm.h b/private/windbg/osdebug/include/emdm.h
new file mode 100644
index 000000000..a58f712b3
--- /dev/null
+++ b/private/windbg/osdebug/include/emdm.h
@@ -0,0 +1,432 @@
+/**** EMDM.HMD - Common structures for Win32/NT EM and DM ****
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: November 17, 1990 by David W. Gray *
+ * *
+ * Purpose: *
+ * *
+ * This file defines the types, enums, and constants that are common *
+ * for all execution models, both debugger and debuggee end. *
+ * *
+ ***************************************************************************/
+
+#ifndef _EMDM
+#define _EMDM
+
+//#if !defined(DOS32) || (defined(DOS32) && defined(DOS32DM))
+#include "cvinfo.h"
+//#endif
+
+// Shared message structs for od/em/dm
+#include "odmsg.h"
+
+//
+// This is included to define a NONVOLATILE_CONTEXT_POINTERS structure
+// of the appropriate size. The goal is to keep any machine-specific
+// reference out of emdp.c here, but we need to know how much data to
+// transfer to the thread context on the different architectures.
+//
+
+#include "ctxptrs.h"
+
+#define MAXCACHE 16
+#define CACHESIZE 0x100
+
+
+typedef unsigned MTE;
+
+#ifdef TARGET32
+#define MAXBIGSEGS 3
+#endif
+
+
+typedef enum {
+ dmfRemoteDied = -1, /* debugger quit */
+ dmfCommError = -2, /* transport layer error */
+
+ dmfNull = 0,
+
+ dmfBreakpoint,
+ dmfGetExceptionState,
+ dmfSetExceptionState,
+
+
+ dmfReadMem,
+ dmfReadReg,
+ dmfReadFrameReg,
+ dmfWriteMem,
+ dmfWriteReg,
+ dmfWriteFrameReg,
+ dmfGetFP,
+ dmfSetFP,
+
+ dmfThreadStatus,
+ dmfProcessStatus,
+
+ dmfGo,
+ dmfTerm,
+ dmfStop,
+ dmfFreeze,
+ dmfResume,
+ dmfSingleStep,
+ dmfRangeStep,
+ //dmfReturnStep,
+ dmfSelect,
+ dmfConnect,
+ dmfInit,
+ dmfUnInit,
+ dmfProgLoad,
+ dmfProgFree,
+ dmfInit32SegValues,
+ dmfCreatePid,
+ dmfDestroyPid,
+ dmfSelLim,
+ dmfSetMulti,
+ dmfClearMulti,
+ dmfDebugger,
+ dmfSync,
+ dmfIOCTL,
+ dmfSendChar,
+ //dmfGoToReturn,
+ dmfSetupExecute,
+ dmfStartExecute,
+ dmfCleanUpExecute,
+ dmfDebugActive,
+ dmfSetPath,
+ dmfQueryTlsBase,
+ dmfPollForDebugEvents, // WIN32S only
+ dmfPollMessageLoop, // WIN32S only
+ dmfGetPrompt,
+ dmfQuerySelector,
+ dmfVirtualQuery,
+ dmfOmapCheck, // Lego
+ dmfOmapToSrc, // Lego
+ dmfOmapFromSrc, // Lego
+ dmfReadRegEx,
+ dmfWriteRegEx,
+ dmfGetDmInfo,
+ dmfRemoteQuit,
+ dmfGetSections,
+ dmfLast
+} _DMF;
+
+typedef LONG DMF;
+
+
+typedef struct _DM_MSG {
+ union {
+ XOSD_ xosdRet;
+ DWORDLONG Alignment;
+ };
+ char rgb[1];
+} DM_MSG, *LPDM_MSG;
+
+#define iflgMax 12
+
+
+#pragma pack(4)
+
+typedef struct _RST {
+ BOOL fStepOver;
+ BOOL fAllThreads;
+ BOOL fInitialBP;
+#ifdef TARGET32
+ CV_uoff32_t offStart;
+ CV_uoff32_t offEnd;
+ CV_uoff32_t offPC;
+#else
+ ADDR addrStart;
+ ADDR addrEnd;
+ ADDR addrCSIP;
+#endif
+} RST; // Range STep Packet
+
+typedef struct _SETPTH {
+ BOOL Set;
+ char Path[1];
+} SETPTH;
+
+#pragma pack()
+
+//
+// DM Misc info structure.
+//
+// Some of these correspond to the debug metrics exposed by OSDebug.
+// These cover the differences between user and kernel mode, Win32,
+// Win32s and Win32c, maybe Cairo, whatever other DMs might be handled
+// by the Win32 EM.
+//
+
+typedef struct _PROCESSOR {
+ MPT Type;
+ DWORD Level;
+ END Endian;
+} PROCESSOR, FAR * LPPROCESSOR;
+
+typedef struct _DMINFO {
+ DWORD fAsync:1; // read/write mem and regs while running?
+ DWORD fHasThreads:1; //
+ DWORD fReturnStep:1; // step out of function?
+ DWORD fRemote:1; // target is not on debugger host
+ DWORD fAsyncStop:1; // OSDAsyncStop supported
+ DWORD fAlwaysFlat:1; // Addresses are always flat
+ DWORD fHasReload:1; // !reload support
+
+ DWORD cbSpecialRegs; // size of private regs struct for dmfGetRegsEx
+ WORD MajorVersion; //
+ WORD MinorVersion; //
+ BPTS Breakpoints; // OSDebug breakpoints supported
+ PROCESSOR Processor;
+} DMINFO;
+typedef DMINFO FAR * LPDMINFO;
+
+
+typedef RST *PRST;
+typedef RST FAR *LPRST;
+
+typedef struct _GOP {
+ USHORT fBpt;
+ USHORT fAllThreads;
+ ADDR addr;
+} GOP; // Go until this address
+
+typedef GOP *PGOP;
+typedef GOP FAR *LPGOP;
+
+// DO NOT TAKE THIS OUT - *#&*@(#@*(& !!!!!!!!!!!!!!!
+
+#ifdef TARGET32
+
+#define BP_INSTR 0
+
+typedef struct _SBP {
+ HPID id;
+ BOOL fAddr;
+ ADDR addr;
+ DWORD Size;
+ DWORD BpType;
+} SBP;
+
+typedef SBP FAR* LPSBP;
+
+#endif
+
+typedef struct _WPR {
+ BPR bpr;
+ SEGMENT segWP;
+ UOFFSET offWP;
+ WORD ireg;
+} WPR; // WatchPoint Return
+typedef WPR FAR *LPWPR;
+
+typedef struct _EHP {
+ DWORD iException;
+ BOOL fHandle;
+} EHP; // Exception Handled Packet
+typedef EHP FAR *LPEHP;
+
+typedef struct _TTR {
+ BPR bpr;
+ ULONG ulExitCode;
+} TTR; // Thread (or Process) Term Return;
+typedef TTR FAR *LPTTR;
+
+typedef struct _RSR {
+ WORD segCS;
+ UOFFSET offIP;
+ WORD segSS;
+ UOFFSET offBP;
+ WORD segCSNext;
+ UOFFSET offIPNext;
+} RSR; // Range Step Return
+typedef RSR FAR *LPRSR;
+
+
+typedef struct _OBJD {
+ DWORD offset;
+ DWORD cb;
+ WORD wSel;
+ WORD wPad;
+} OBJD, FAR * LPOBJD;
+
+typedef struct _MODULELOAD {
+ WORD mte;
+ WORD pad0;
+ LPVOID lpBaseOfDll;
+ DWORD dwSizeOfDll;
+ SEGMENT StartingSegment;
+ BOOL fRealMode;
+ BOOL fFlatMode;
+ BOOL fOffset32;
+ SEGMENT CSSel;
+ SEGMENT DSSel;
+ LONG cobj;
+ OBJD rgobjd[];
+} MODULELOAD;
+typedef MODULELOAD FAR *LPMODULELOAD;
+
+typedef struct _RWP {
+ DWORD cb;
+ ADDR addr;
+ BYTE rgb[];
+} RWP; // Read Write Packet
+typedef RWP *PRWP;
+typedef RWP FAR *LPRWP;
+
+
+typedef struct _NPP {
+ PID pid;
+ BOOL fReallyNew;
+} NPP; // New Process Packet, used with dbcNewProc. See od.h for description
+ // of fReallyNew
+typedef NPP FAR * LPNPP;
+
+typedef struct _WPP {
+ ADDR addr;
+ WORD cb;
+} WPP; // Watch Point Packet
+typedef WPP FAR *LPWPP;
+
+typedef struct _SLI {
+ WORD wSelector;
+ WORD wSegNo;
+ WORD mte;
+} SLI, FAR * LPSLI;
+
+// Exception command packet
+typedef struct _EXCMD {
+ EXCEPTION_CONTROL exc;
+ EXCEPTION_DESCRIPTION exd;
+} EXCMD;
+typedef EXCMD FAR * LPEXCMD;
+
+
+// The DBCEs always come back in an RTP structure, which has additional
+// info. The comments on the DBCEs below refer to the other fields of
+// the RTP structure.
+enum {
+ dbceAssignPID = dbcMax, // Tell the EM what PID is associated with
+ // a given HPID. At offset 0 of rtp.rgbVar[]
+ // is the PID.
+ dbceLoadBigSegTbl, // ??
+ dbceCheckBpt, // Find out if EM wants us to single-step
+ // over a specified breakpoint. Upon return,
+ // rgbVar[0] is fStop to stop at this
+ // breakpoint; if fStop is FALSE, then
+ // rgbVar[1] is the byte with which to
+ // overwrite the INT 3.
+ dbceFinishedLoad, // Tell the EM we're done with a dmfProgLoad.
+ // rgbVar is empty.
+ dbceInstructionLen, // Ask the em how long the instruction is.
+ // rgbVar contains the cs:ip
+ dbceSegLoad, // WOW just loaded a segment
+ dbceSegMove, // Moved a segment
+ dbceModFree16, // Unload of a 16-bit DLL
+ dbceModFree32, // Unload of a 32-bit DLL
+ dbceGetOffsetFromSymbol, // - Call the expression evaluator
+ // wParam = nothing
+ // lParam = pointer to the expression
+ dbceGetSymbolFromOffset, // - Call the expression evaluator
+ // wParam = nothing
+ // lParam = pointer to the expression
+ dbceEnableCache, // - Enable/Disable the em's cache
+ // wParam = nothing
+ // lParam = TRUE/FALSE
+ dbceMax
+} _DBCE;
+typedef LONG DBCE;
+
+#pragma pack(1)
+
+// it is important that the rgbVar fields be aligned on a DWORD boundary
+
+typedef struct _DBB {
+ union {
+ DMF dmf;
+ DWORD dw0;
+ };
+ HPID hpid;
+ HTID htid;
+ BYTE rgbVar[ ];
+} DBB;
+
+
+typedef DBB *PDBB;
+typedef DBB FAR *LPDBB;
+
+typedef struct _RTP {
+ union {
+ DBC dbc; // a DBC or a DBCE
+ DWORD dw0;
+ };
+ HPID hpid;
+ HTID htid;
+ union {
+ WORD cb; // the length of rgbVar
+ DWORD dw1;
+ };
+ BYTE rgbVar[ ]; // additional information - see the
+ // definitions of the DBCE and DBC codes
+} RTP;
+
+#pragma pack()
+
+typedef RTP *PRTP;
+typedef RTP FAR *LPRTP;
+
+typedef struct _RTRNSTP {
+ EXOP exop;
+ ADDR addrRA; // Address to return to
+ ADDR addrBase; // Address of what SP should be when returning
+} RTRNSTP; // ReTuRN STeP packet
+typedef RTRNSTP FAR *LPRTRNSTP;
+
+
+
+
+
+
+
+
+#define lpregDbb(dbb) ( (LPREG) &dbb )
+#define lpfprDbb(dbb) ( (LPFPR) &dbb )
+#define lszDbb(dbb) ( (LSZ) &dbb )
+
+#define addrDbb(dbb) (*( (LPADDR) &dbb ))
+#define stpDbb(dbb) (*( (LPSTP) &dbb ))
+#define rstDbb(dbb) (*( (LPRST) &dbb ))
+#define gopDbb(dbb) (*( (LPGOP) &dbb ))
+#define tstDbb(dbb) (*( (LPTST) &dbb ))
+#define pstDbb(dbb) (*( (LPF) &dbb ))
+#define rwpDbb(dbb) (*( (LPRWP) &dbb ))
+#define fDbb(dbb) (*( (LPF) &dbb ))
+
+
+
+/****************************************************************************
+ * *
+ * Packets returned from the debuggee execution model to the debugger *
+ * execution model. *
+ * *
+ ****************************************************************************/
+
+#ifdef DOS32DM
+#undef BOOL
+#endif
+
+typedef struct _FRAME_INFO {
+ CONTEXT frameRegs;
+ KNONVOLATILE_CONTEXT_POINTERS frameRegPtrs;
+} FRAME_INFO, * PFRAME_INFO;
+
+
+#ifdef SMARTALIAS
+
+#define GetInvalid(w,i) ((w>>i)&1)
+#define SetInvalid(w,i) w=((1<<i)|w)
+
+#endif
+
+#endif // _EMDM
diff --git a/private/windbg/osdebug/include/heap.h b/private/windbg/osdebug/include/heap.h
new file mode 100644
index 000000000..2052e0877
--- /dev/null
+++ b/private/windbg/osdebug/include/heap.h
@@ -0,0 +1,16 @@
+
+#if USE_HEAP_CHECKING
+
+void
+ValidateTheHeap(
+ char *fName,
+ unsigned long dwLine
+ );
+
+#define ValidateHeap() ValidateTheHeap( __FILE__, __LINE__ )
+
+#else
+
+#define ValidateHeap()
+
+#endif
diff --git a/private/windbg/osdebug/include/ll.h b/private/windbg/osdebug/include/ll.h
new file mode 100644
index 000000000..f971f906c
--- /dev/null
+++ b/private/windbg/osdebug/include/ll.h
@@ -0,0 +1,9 @@
+/*
+** This file can be used as a single include file to get all of
+** the list manager types and prototypes. The files can also be
+** included independently
+**
+*/
+
+#include "lltypes.h"
+#include "llproto.h"
diff --git a/private/windbg/osdebug/include/llproto.h b/private/windbg/osdebug/include/llproto.h
new file mode 100644
index 000000000..c1f54960b
--- /dev/null
+++ b/private/windbg/osdebug/include/llproto.h
@@ -0,0 +1,70 @@
+/*
+** This file contains the set of prototypes and defines which pass
+** as functions for the list manager subsystem.
+**
+*/
+
+#ifndef LL_PROTO_INCLUDED
+#define LL_PROTO_INCLUDED 1
+
+
+/*
+** Prototypes for the list manager system
+*/
+
+extern HLLI PASCAL LOADDS LLHlliInit( UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE );
+extern HLLE PASCAL LOADDS LLHlleCreate( HLLI );
+extern void PASCAL LOADDS LLAddHlleToLl( HLLI, HLLE );
+extern void PASCAL LOADDS LLInsertHlleInLl( HLLI, HLLE, DWORD );
+extern BOOL PASCAL LLFDeleteHlleIndexed( HLLI, DWORD );
+extern BOOL PASCAL LLFDeleteLpvFromLl( HLLI, HLLE, LPV, DWORD );
+extern BOOL PASCAL LOADDS LLFDeleteHlleFromLl( HLLI, HLLE );
+extern HLLE PASCAL LOADDS LLHlleFindNext( HLLI, HLLE );
+extern LONG PASCAL LOADDS LLChlleDestroyLl( HLLI );
+extern HLLE PASCAL LOADDS LLHlleFindLpv( HLLI, HLLE, LPV, DWORD );
+extern DWORD PASCAL LOADDS LLChlleInLl( HLLI );
+extern LPV PASCAL LOADDS LLLpvFromHlle( HLLE );
+extern VOID PASCAL LOADDS LLUnlockHlle( HLLE );
+extern HLLE PASCAL LOADDS LLHlleGetLast( HLLI );
+extern void PASCAL LOADDS LLHlleAddToHeadOfLI( HLLI, HLLE );
+extern BOOL PASCAL LOADDS LLFRemoveHlleFromLl( HLLI, HLLE );
+
+
+#ifdef DBLLINK
+extern HLLE PASCAL LOADDS LLHlleFindPrev( HLLI, HLLE );
+#endif // DBLLINK
+
+//
+// FCheckHlli is for debug versions ONLY as an integrety check
+//
+
+#ifdef DEBUGVER
+extern BOOL PASCAL LLFCheckHlli( HLLI );
+#else // DEBUGVER
+#define LLFCheckHlli(hlli) TRUE
+#endif // DEBUGVER
+
+//
+// Map memory manager to our source versions
+//
+
+#define AllocHmem(cb) MMhAllocMb(MMDLLHEAP,CVMALLOCED,cb) // _fmalloc(cb)
+#define FreeHmem(h) MMDeallocMb(h) // _ffree(h)
+#define LockHmem(h) MMlpvLockMb(h) // (h)
+#define UnlockHmem(h) MMbUnlockMb(h) //
+
+//
+// This helps the codes appearance!
+//
+
+#define UnlockHlle(hlle) UnlockHmem((HDEP) hlle)
+#define UnlockHlli(hlli) UnlockHmem(hlli)
+
+
+/*
+** More help on code appearance
+*/
+
+#define LLHlleDestroy(hlle) MMDeallocateMb(h)
+
+#endif /* LL_PROTO_INCLUDED */
diff --git a/private/windbg/osdebug/include/lltypes.h b/private/windbg/osdebug/include/lltypes.h
new file mode 100644
index 000000000..4083933f3
--- /dev/null
+++ b/private/windbg/osdebug/include/lltypes.h
@@ -0,0 +1,22 @@
+/*
+** This file contains the basic types used by the list manager.
+**
+** It is assumed that these will not be passed across a transport
+** layer from an EM to a DM or from a DM to an EM. These types are
+** therefore defined in a machine dependent manner.
+*/
+
+#ifndef LL_TYPES_INCLUDED
+#define LL_TYPES_INCLUDED 1
+
+//
+// Return values from lpfnCmpNode functions
+//
+
+#define fCmpLT -1
+#define fCmpEQ 0
+#define fCmpGT 1
+
+#define hlleNull (HLLE)NULL
+
+#endif /* LL_TYPES_INCLUDED */
diff --git a/private/windbg/osdebug/include/od.h b/private/windbg/osdebug/include/od.h
new file mode 100644
index 000000000..619504f01
--- /dev/null
+++ b/private/windbg/osdebug/include/od.h
@@ -0,0 +1,1160 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Od.h
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 05-Apr-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined _OD_
+#define _OD_
+
+#include "shapi.hxx"
+#include "odmsg.h"
+
+typedef enum {
+ xosdContinue = 1,
+ xosdNone = 0,
+ xosdQueueEmpty = -1,
+ xosdModLoad = -2,
+ xosdFindProc = -3,
+ xosdOSStruct = -4,
+ xosdSyntax = -5,
+ xosdInvalidProc = -6,
+ xosdInvalidThread = -7,
+ xosdInvalidTL = -8,
+ xosdInvalidEM = -9,
+ xosdNoProc = -10,
+ xosdProcRunning = -11,
+ xosdCreateDBGThread = -12,
+ xosdOutOfMemory = -13,
+ xosdInvalidBreakPoint = -14,
+ xosdBadAddress = -15,
+ xosdNoWatchPoints = -16,
+ xosdInvalidPID = -17,
+ xosdInvalidTID = -18,
+ xosdOutOfThreads = -19,
+ xosdOutOfProcs = -20,
+ xosdPtrace = -21,
+ xosdLoadChild = -22,
+ xosdRead = -23,
+ xosdWrite = -24,
+ xosdBadQueue = -25,
+ xosdEMInUse = -26,
+ xosd27 = -27,
+ xosdTLInUse = -28,
+ xosd29 = -29,
+ xosdFatal = -30,
+ xosdUnknown = -31,
+ xosdInvalidMTE = -32,
+ xosdInvalidSelector = -33,
+ xosdInvalidRegister = -34,
+
+ xosdInvalidParameter = -35,
+ xosdOutOfStructures = -36,
+ xosdPathNotFound = -37,
+ xosdLineBusy = -38,
+ xosdBadLine = -39,
+ xosdBrokenLine = -40,
+ xosdInterrupt = -41,
+ xosdInvalidFunction = -42,
+ xosdLineNotConnected = -43,
+ xosdAccessDenied = -44,
+ xosdCannotMake = -45,
+ xosdFileNotFound = -46,
+ xosdInvalidAccess = -47,
+ xosdOpenFailed = -48,
+ xosdSharingBufferExeeded= -49,
+ xosdSharingViolation = -50,
+ xosdLine = -51,
+ xosdEndOfStack = -52,
+ xosdFPNotLoaded = -53,
+
+ xosdQuit = -54,
+ xosdTooManyObjects = -55,
+ xosdGetModNameFail = -56,
+ xosdCannotConnect = -57,
+ xosdPunt = -58,
+ xosdNotFound = -59,
+ xosdIDError = -60,
+ xosdOverrun = -61,
+ xosdBadFormat = -62,
+
+ xosdAsmTooFew = -63,
+ xosdAsmTooMany = -64,
+ xosdAsmSize = -65,
+ xosdAsmBadRange = -66,
+ xosdAsmOverFlow = -67,
+ xosdAsmSyntax = -68,
+ xosdAsmBadOpcode = -69,
+ xosdAsmExtraChars = -70,
+ xosdAsmOperand = -71,
+ xosdAsmBadSeg = -72,
+ xosdAsmBadReg = -73,
+ xosdAsmDivide = -74,
+ xosdAsmSymbol = -75,
+ xosdErrorMoreInfo = -76,
+ xosdUnsupported = -77,
+ xosdCannotDebug = -78,
+ xosdVDMRunning = -79,
+ xosdBadRemoteVersion = -80,
+ xosdBadVersion = -81,
+ xosdCantOpenComPort = -82,
+ xosdBadComParameters = -83,
+ xosdBadPipeServer = -84,
+ xosdBadPipeName = -85,
+ xosdNotRemote = -86,
+ xosdAttachDeadlock = -87
+} XOSD;
+
+typedef LONG XOSD_;
+
+typedef XOSD FAR *LPXOSD;
+
+
+typedef struct _INF {
+ BOOL fReply; // Reply desired
+ DWORD fUniCode; // Unicode flag
+ BYTE buffer[]; // the string
+} INF; // InfoAvail return
+typedef INF * LPINF;
+
+typedef enum {
+ fctNone,
+ fctNear,
+ fctFar
+} FCT; // Function Call Type for OSDGetCaller
+
+typedef enum {
+ emNative,
+ emNonNative
+} EMTYPE;
+
+typedef enum {
+ stoNone = 0,
+ stoOneThread = 1, // Execute a single thread
+ stoInitialBP = 2, // Skip on initial breakpoint
+ stoQueryStep = 4 // Query before stepping into
+} STO; // STep Options
+
+typedef enum {
+ dopNone = 0x00000000,
+ dopAddr = 0x00000001, // put address (w/ seg) in front of disassm
+ dopFlatAddr = 0x00000002, // put flat address (no seg)
+ dopOpcode = 0x00000004, // dump the Opcode
+ dopOperands = 0x00000008, // dump the Operands
+ dopRaw = 0x00000010, // dump the raw code bytes
+ dopEA = 0x00000020, // calculate the effective address
+ dopSym = 0x00000040, // output symbols
+ dopUpper = 0x00000080, // force upper case for all chars except syms
+ dopDemand = 0x00000100 // disasm window open only on user demand
+} DOP; // Disassembly OPtions
+
+
+typedef struct _SDI {
+ DOP dop; // Disassembly OPtions (see above)
+ ADDR addr; // The address to disassemble
+ BOOL fAssocNext; // This instruction is associated w/ the next one
+ BOOL fIsBranch;
+ BOOL fIsCall;
+ BOOL fJumpTable;
+ ADDR addrEA0; // First effective address
+ ADDR addrEA1; // Second effective address
+ ADDR addrEA2; // Third effective address
+ int cbEA0; // First effective address size
+ int cbEA1; // Second effective address size
+ int cbEA2; // Third effective address size
+ int ichAddr;
+ int ichBytes;
+ int ichOpcode;
+ int ichOperands;
+ int ichComment;
+ int ichEA0;
+ int ichEA1;
+ int ichEA2;
+ LPCH lpch;
+} SDI; // Structured DiSsassembly
+typedef SDI FAR *LPSDI;
+
+typedef HIND HTL; // handle to a transport layer
+typedef HIND HEM; // handle to an execution model
+
+typedef HPID FAR *LPHPID;
+typedef HTID FAR *LPHTID;
+typedef HTL FAR *LPHTL;
+typedef HEM FAR *LPHEM;
+
+typedef struct GIS {
+ BOOL fCanSetup;
+ CHAR rgchInfo [ 80 ];
+} GIS; // Get Info Struct for OSDTLGetInfo
+
+typedef GIS FAR * LPGIS;
+
+
+/*
+** Thread state structure
+*/
+
+typedef enum {
+ tstRunnable = 0, // Thread is not running but has been stopped due
+ // to a debug event on another thread in the
+ // current process, or hasn't run yet.
+ tstStopped = 1, // Thread is at a debug event (other than exception)
+ tstRunning = 2, // Thread is current in the scheduler queue
+ tstExiting = 3, // Thread is in the process of exiting
+ tstDead = 4, // Thread is no longer schedulable (may not exists for
+ tstRunMask = 0xf,
+ // all Ems
+ tstExcept1st = 0x10, // Thread is at first chance exception
+ tstExcept2nd = 0x20, // Thread is at second change exception
+ tstRip = 0x30, // Thread is in a RIP state
+ tstExceptionMask = 0xf0,
+
+ tstFrozen = 0x100, // Thread has been frozen by Debugger
+ tstSuspended = 0x200, // Thread has been frozen by Other
+ tstBlocked = 0x300, // Thread is blocked on something (i.e. a semaphore)
+ tstSuspendMask= 0xf00,
+
+ tstCritSec = 0x1000, // Thread is currently in a critical section
+ tstOtherMask = 0xf000
+} TSTATE;
+
+
+// Process state bits
+typedef enum {
+ pstRunning = 0,
+ pstStopped = 1,
+ pstExited = 2,
+ pstDead = 3
+} PSTATE;
+
+
+#define IDSTRINGSIZE 10
+#define STATESTRINGSIZE 60
+typedef struct _PST {
+ DWORD dwProcessID;
+ DWORD dwProcessState;
+ char rgchProcessID[IDSTRINGSIZE];
+ char rgchProcessState[STATESTRINGSIZE];
+} PST;
+typedef PST FAR * LPPST;
+
+typedef struct _TST {
+ DWORD dwThreadID;
+ DWORD dwSuspendCount;
+ DWORD dwSuspendCountMax;
+ DWORD dwPriority;
+ DWORD dwPriorityMax;
+ DWORD dwState;
+ DWORD dwTeb;
+ char rgchThreadID[IDSTRINGSIZE];
+ char rgchState[STATESTRINGSIZE];
+ char rgchPriority[STATESTRINGSIZE];
+} TST;
+typedef TST FAR * LPTST;
+
+XOSD PASCAL
+OSDGetThreadStatus(
+ HPID hpid,
+ HTID htid,
+ LPTST lptst
+ );
+
+XOSD PASCAL
+OSDGetProcessStatus(
+ HPID hpid,
+ LPPST lppst
+ );
+
+/*
+**
+*/
+
+typedef enum {
+ osdGoXXX, // 00 - Run the debuggee
+ // wParam = nothing
+ // lParam = nothing
+ osdSingleStepXXX, // 01 - Single-step
+ // wParam = sto
+ // stoOneThread = Step only this thread
+ // stoInitialBP = Step over init break
+ // stoQueryStep = Query before stepinto
+ // lParam = nothing
+ osdStepOverXXX, // 02 - Single-step, step over calls and ints
+ // wParam = sto
+ // stoOneThread = Step only this thread
+ // stoInitialBP = Step over init break
+ // lParam = nothing
+ osdStopXXX, // 03 - Do an asynchronous stop of the process
+ // wParam = nothing
+ // lParam = nothing
+ osdFreeze, // 04 - Freeze thread indicated by HTID
+ // wParam = nothing
+ // lParam = nothing
+ osdThaw, // 05 - Thaw thread indicated by HTID
+ // wParam = nothing
+ // lParam = nothing
+ osdIOCTL, // 06 - Special debuggee controls
+ // wParam = command- and DM-dependent
+ // lParam = command- and DM-dependent
+ osdProcStatusXXX, // 07 - Query process status
+ // wParam = nothing
+ // lParam = LPBOOL, filled with fProcRunning
+ osdThreadStatusXXX, // 08 - Query thread status
+ // wParam = nothing
+ // lParam = LPTST (see emp.hmd)
+ osdReadBuf, // 09 - Read memory from address set on last
+ // OSDSetAddr(adrCurrent) call
+ // wParam = number of bytes to read
+ // lParam = pointer to buffer
+ osdWriteBuf, // 0A - Write memory to address set on last
+ // OSDSetAddr(adrCurrent) call
+ // wParam = number of bytes to write
+ // lParam = pointer to buffer
+ osdSetWatchPointXXX, // 0B - Set watchpoint at address set on last
+ // OSDSetAddr(adrCurrent) call (positive
+ // return value is a watchpoint number)
+ // wParam = length of watchpoint
+ // lParam = type and scope [specify]
+ osdRemoveWatchPointXXX, // 0C - Remove a watchpoint
+ // wParam = watchpoint number
+ // lParam = nothing
+ osdSetBreakPointXXX, // 0D - Set a breakpoint.
+ // wParam = fOneThread
+ // lParam = ptr to ADDR
+ osdRemoveBreakPointXXX, // 0E - Remove a breakpoint.
+ // wParam = fOneThread
+ // lParam = ptr to ADDR
+ osdRangeStepXXX, // 0F - Perform osdSingleStep until IP is outside
+ // range from starting IP to ADDR pointed to
+ // by lParam
+ // wParam = sto
+ // stoOneThread = Step only this thread
+ // stoInitialBP = Step over init break
+ // stoQueryStep = Query before stepinto
+ // lParam = ptr to ending ADDR
+ osdRangeOverXXX, // 10 - Perform osdStepOver until IP is outside
+ // range from starting IP to ADDR pointed to
+ // by lParam
+ // wParam = sto
+ // stoOneThread = Step only this thread
+ // stoInitialBP = Step over init break
+ // lParam = ptr to ending ADDR
+ osdHandleExceptionXXX, // 11 - Clear current exception on target and
+ // prepare debuggee for execution
+ // wParam = nothing
+ // lParam = nothing
+ osdGetLibNameXXX, // 12 - Query the name of a module (REVIEW: gone)
+ // wParam = ??
+ // lParam = ??
+ osdShowDebuggee, // 13 - Show debugger's or debuggee's screen
+ // wParam = TRUE for gee's, FALSE for ger's
+ // lParam = nothing
+ osdFixupAddr, // 14 - Map ADDR from un-fixed up to fixed up
+ // wParam = nothing
+ // lParam = ptr to ADDR
+ osdUnFixupAddr, // 15 - Map ADDR from fixed up to un-fixed up
+ // wParam = nothing
+ // lParam = ptr to ADDR
+ osdSetEmi, // 16 - Set EMI field of an ADDR
+ // wParam = nothing
+ // lParam = ptr to ADDR
+ osdEMSvcReqXXX, // 17 - [talk to Jon]
+ // wParam = ??
+ // lParam = ??
+ osdSendChar, // 18 - Send a character to the target OS
+ // wParam = ??
+ // lParam = ??
+ osdFreezeState, // 19 - Freeze or thaw the state of a process.
+ // wParam = TRUE - Freeze, FALSE - Thaw
+ // lParam = nothing
+ osdIsOverlayLoaded, // 1A - Check to see if overlay is loaded
+ // wParam = ??
+ // lParam = point to addr to check
+ osdCompareAddrs, // 1B - Compare addresses
+ //
+ // lParam far pointer to rglpaddr[2];
+ //
+ osdIgnoreExceptionXXX, // 1C - Ignore exception
+ // wParam = nothing
+ // lParam = nothing
+ osdMax // 1D
+} OSD; // OSDebug commands for OSDPtrace
+
+enum _MTRC {
+ mtrcProcessorType,
+ mtrcProcessorLevel,
+ mtrcEndian,
+ mtrcThreads,
+ mtrcCRegs,
+ mtrcCFlags,
+ mtrcExtRegs,
+ mtrcExtFP,
+ mtrcExtMMU,
+ mtrcPidSize,
+ mtrcTidSize,
+ mtrcExceptionHandling,
+ mtrcAssembler,
+ mtrcAsync,
+ mtrcAsyncStop,
+ mtrcBreakPoints,
+ mtrcReturnStep,
+ mtrcShowDebuggee,
+ mtrcHardSoftMode,
+ mtrcRemote,
+ mtrcOleRpc, // Supports OLE Remote Procedure Call debugging?
+ mtrcNativeDebugger, // Supports low-level debugging (eg MacsBug)
+ mtrcOSVersion,
+ mtrcMultInstances
+};
+typedef DWORD MTRC;
+
+enum {
+ adrCurrent = 1, // scratch address, e.g. for reading/writing memory
+ adrPC = 2, // program counter (e.g. CS:EIP)
+ adrBase = 3, // base pointer (e.g. SS:EBP)
+ adrStack = 4, // stack pointer (e.g. SS:ESP)
+ adrData = 5, // pointer to beginning of data (e.g. DS:0)
+// adrBaseProlog = 6, // base pointer while PC is in prolog of a function(?)
+ adrTlsBase = 7 // Thread Local Storage base address
+};
+typedef short ADR; // address passed to OSDGetAddr/OSDSetAddr
+
+/*
+** Register types --- flags describing recommendations on
+** register display
+*/
+
+enum {
+ rtProcessMask = 0x0f, // Mask for processor type bits
+ rtCPU = 0x01, // Central Processing Unit
+ rtFPU = 0x02, // Floating Point Unit
+ rtMMU = 0x03, // Memory Manager Unit
+
+ rtGroupMask = 0xf0, // Which group register falls into
+ rtInvisible = 0x10, // Recommend no display
+ rtRegular = 0x20, // Recommend regular display
+ rtExtended = 0x40, // Recommend extended display
+ rtSpecial = 0x80, // Special registers...
+
+ rtFmtTypeMask = 0xf00, // Mask of display formats
+ rtInteger = 0x100, // Unsigned integer format
+ rtFloat = 0x200, // Floating point format
+ rtAddress = 0x300, // Address format
+
+ rtMiscMask = 0xf000, // misc info
+ rtPC = 0x1000, // this is the PC
+ rtFrame = 0x2000, // this reg affects the stack frame
+ rtNewLine = 0x4000 // print newline when listing
+};
+typedef short RT; // Register Types
+
+#define rtFmtTypeShift 8
+
+
+/*
+** Flag types -- flags describing recommendations on flag display
+*/
+
+enum {
+ ftInvisible = 0x01,
+ ftRegular = 0x02,
+ ftRegularExt= 0x04,
+ ftFP = 0x08,
+ ftFPExt = 0x10,
+ ftMMU = 0x20,
+ ftMMUExt = 0x40
+};
+typedef short FT; // Flag Types
+
+/*
+** Register description: This structure contains the description for
+** a register on the machine. Note that hReg must be used to get
+** the value for this register but a different index is used to get
+** this description structure.
+*/
+
+typedef struct {
+ char FAR * lpsz; /* Pointer into EM for registers name */
+ RT rt; /* Register Type flags */
+ UINT cbits; /* Number of bits in the register */
+ USHORT hReg; /* Value to use with Read/Write Register*/
+} RD; // Register Description
+
+/*
+** Flag Data description: This structure contains the description for
+** a flag on the machine. Note that the hReg field contains the
+** value to be used with Read/Write register to get the register which
+** contains this flag.
+*/
+
+typedef struct {
+ char FAR * lpsz; /* Pointer into EM for flag name */
+ RT ft; /* Flag Type flags */
+ UINT cbits; /* Number of bits in the flag */
+ USHORT hReg; /* register containning this flag */
+} FD; // Flag Data description
+typedef XOSD (PASCAL LOADDS *LPFNSVC) ( DBC, HPID, HTID, DWORD, LONG );
+typedef XOSD (PASCAL LOADDS *TLFUNC) ( TLF, HPID, DWORD, LONG );
+typedef XOSD (PASCAL LOADDS *EMFUNC) ( EMF, HPID, HTID, DWORD, LONG );
+
+typedef void (FAR CDECL LOADDS * LPFNCLDS)( void );
+
+typedef struct {
+ void FAR * (PASCAL LOADDS * lpfnMHAlloc) ( UINT );
+ void FAR * (PASCAL LOADDS * lpfnMHRealloc) ( void FAR *, UINT );
+ void (PASCAL LOADDS * lpfnMHFree) ( void FAR * );
+
+ HDEP (PASCAL LOADDS * lpfnMMAllocHmem) ( UINT );
+ void (PASCAL LOADDS * lpfnMMFreeHmem) ( HDEP );
+ void FAR * (PASCAL LOADDS * lpfnMMLock) ( HDEP );
+ VOID (PASCAL LOADDS * lpfnMMUnlock) ( HDEP );
+
+ HLLI (PASCAL LOADDS * LLInit) ( UINT,
+ LLF,
+ LPFNKILLNODE,
+ LPFNFCMPNODE );
+ HLLE (PASCAL LOADDS * LLCreate) ( HLLI );
+ void (PASCAL LOADDS * LLAdd) ( HLLI, HLLE );
+ void (PASCAL LOADDS * LLInsert) ( HLLI, HLLE, DWORD );
+ BOOL (PASCAL LOADDS * LLDelete) ( HLLI, HLLE );
+ HLLE (PASCAL LOADDS * LLNext) ( HLLI, HLLE );
+ LONG (PASCAL LOADDS * LLDestroy) ( HLLI );
+ HLLE (PASCAL LOADDS * LLFind) ( HLLI,
+ HLLE,
+ VOID FAR *,
+ DWORD );
+ LONG (PASCAL LOADDS * LLSize) ( HLLI );
+ VOID FAR * (PASCAL LOADDS * LLLock) ( HLLE );
+ VOID (PASCAL LOADDS * LLUnlock) ( HLLE );
+ HLLE (PASCAL LOADDS * LLLast) ( HLLI );
+ VOID (PASCAL LOADDS * LLAddHead) ( HLLI, HLLE );
+ BOOL (PASCAL LOADDS * LLRemove) ( HLLI, HLLE );
+
+ int (PASCAL LOADDS * lpfnSHModelFromAddr)( PADDR,
+ WORD FAR *,
+ LPB,
+ UOFFSET FAR * );
+
+ int (PASCAL LOADDS * lpfnSHPublicNameToAddr)(PADDR, PADDR, char FAR *);
+
+ LPSTR (PASCAL LOADDS * lpfnSHAddrToPublicName)(LPADDR, LPADDR);
+
+ BOOL (PASCAL LOADDS * lpfnSHWantSymbols)(HEXE);
+
+ LSZ (PASCAL LOADDS * lpfnSHGetSymbol) ( PADDR,
+ PADDR,
+ SOP,
+ LPODR
+ );
+ BOOL (PASCAL LOADDS * lpfnSHGetPublicAddr)( PADDR, LSZ );
+ VOID FAR * (PASCAL LOADDS * lpfnSHLpGSNGetTable)( HEXE );
+ LPDEBUGDATA (PASCAL LOADDS * lpfnSHGetDebugData) ( HEXE );
+ BOOL (PASCAL LOADDS * lpfnSHFindSymbol) ( LSZ, PADDR, LPASR );
+
+ // DWORD (PASCAL LOADDS * lpfnSHLocateSymbolFile)( LSZ, DWORD );
+
+ int (PASCAL LOADDS * lpfnLBPrintf) ( LPCH, LPCH, UINT );
+ int (PASCAL LOADDS * lpfnLBQuit) ( UINT );
+
+ LPFNCLDS (CDECL LOADDS * lpfnSignal) ( int, LPFNCLDS );
+ VOID (CDECL LOADDS * lpfnAbort) ( VOID );
+ int (CDECL LOADDS * lpfnSpawnL) ( LPV FAR *,
+ int,
+ LSZ,
+ LSZ, ... );
+ BOOL (PASCAL LOADDS * lpfnDHGetNumber) ( char FAR *,
+ int FAR *);
+ int FAR * lpPsp;
+ char FAR * lpchOsMajor;
+
+} DBF; // DeBugger callback Functions
+typedef DBF FAR *LPDBF;
+
+
+//
+// Mesage mask values
+//
+#define MSG_TYPE_MOUSE 0x0001
+#define MSG_TYPE_WINDOW 0x0002
+#define MSG_TYPE_INPUT 0x0004
+#define MSG_TYPE_SYSTEM 0x0008
+#define MSG_TYPE_INIT 0x0010
+#define MSG_TYPE_CLIPBOARD 0x0020
+#define MSG_TYPE_DDE 0x0040
+#define MSG_TYPE_NONCLIENT 0x0080
+#define MSG_TYPE_OTHER 0x0100
+
+typedef struct _FUNCTION_INFO {
+ ADDR AddrStart;
+ ADDR AddrEnd;
+ ADDR AddrPrologEnd;
+} FUNCTION_INFO, *PFUNCTION_INFO;
+
+XOSD PASCAL OSDInit ( LPDBF );
+XOSD PASCAL OSDTerm ( VOID );
+XOSD PASCAL OSDCreatePID ( LPFNSVC, HEM, HTL, LPHPID );
+XOSD PASCAL OSDDestroyPID ( HPID );
+XOSD PASCAL OSDDestroyTID ( HTID );
+XOSD PASCAL OSDDisconnect ( HPID, HTID );
+XOSD PASCAL OSDPtrace ( OSD, UINT, VOID FAR *, HPID, HTID );
+XOSD PASCAL OSDProgramLoad ( HPID, LSZ, LSZ, ULONG );
+XOSD PASCAL OSDProgramFree ( HPID );
+XOSD PASCAL OSDAddEM ( EMFUNC, LPDBF, LPHEM, EMTYPE );
+XOSD PASCAL OSDDeleteEM ( HEM );
+XOSD PASCAL OSDAddTL ( TLFUNC, LPHTL, LPCH );
+XOSD PASCAL OSDDeleteTL ( HTL );
+XOSD PASCAL OSDDeinitTL ( TLFUNC );
+XOSD PASCAL OSDInitTL ( TLFUNC, LPDBF );
+XOSD PASCAL OSDTLGetInfo ( TLFUNC, LPGIS, UINT );
+XOSD PASCAL OSDTLSetup ( TLFUNC, LSZ, UINT, LPV );
+XOSD PASCAL OSDGetAddr ( HPID, HTID, ADR, PADDR );
+XOSD PASCAL OSDSetAddr ( HPID, HTID, ADR, PADDR );
+XOSD PASCAL OSDReadReg ( HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDWriteReg ( HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDReadFlag ( HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDWriteFlag ( HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDSetFrameContext(HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDFrameReadReg ( HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDFrameWriteReg ( HPID, HTID, UINT, VOID FAR * );
+XOSD PASCAL OSDGetRegDesc ( HPID, HTID, UINT, RD FAR * );
+XOSD PASCAL OSDGetFlagDesc ( HPID, HTID, UINT, FD FAR * );
+XOSD PASCAL OSDGetCurrentEM ( HPID, HTID, LPHEM );
+XOSD PASCAL OSDNativeOnly ( HPID, HTID, BOOL );
+XOSD PASCAL OSDUseEM ( HPID, HTID );
+XOSD PASCAL OSDDiscardEM ( HPID, HTID );
+XOSD PASCAL OSDGetDebugMetric( HPID, HTID, MTRC, LPV );
+XOSD PASCAL OSDUnassemble ( HPID, HTID, LPSDI );
+XOSD PASCAL OSDGetPrevInst ( HPID, HTID, PADDR );
+XOSD PASCAL OSDAssemble ( HPID, HTID, PADDR, LSZ );
+XOSD PASCAL OSDGetObjLength ( HPID, HTID, LPL, LPL, PADDR );
+XOSD PASCAL OSDGetFrame ( HPID, HTID, PADDR );
+XOSD PASCAL OSDGetCaller ( HPID, HTID, FCT, PADDR, PADDR );
+XOSD PASCAL OSDSaveRegs ( HPID, HTID, LPHIND );
+XOSD PASCAL OSDRestoreRegs ( HPID, HTID, HIND );
+XOSD PASCAL OSDIoctl ( HPID, HTID, UINT, UINT, LPV );
+XOSD PASCAL OSDRegisterEmi ( HPID, HTID, HEMI, LSZ );
+#ifdef KBDMON
+XOSD PASCAL OSDKbdRecord ( HPID, HTID, BOOL );
+XOSD PASCAL OSDKbdPlay ( HPID, HTID, LSZ );
+#endif
+XOSD PASCAL OSDIsStackSetup ( HPID, HTID, LPADDR );
+// XOSD PASCAL OSDTranslateMsg ( HPID, HTID, LPW, LPW, LSZ, LPW );
+XOSD PASCAL OSDGetMsgMap ( HPID, HTID, LPMSGMAP* );
+XOSD PASCAL OSDGetError ( HPID, HTID, LPW, LSZ, LSZ );
+XOSD PASCAL OSDSetupExecute ( HPID, HTID, LPHDEP );
+XOSD PASCAL OSDStartExecute ( HPID, HDEP, LPADDR, BOOL, BOOL);
+XOSD PASCAL OSDCleanUpExecute ( HPID, HDEP );
+XOSD PASCAL OSDLoadDllAck ( HPID );
+XOSD PASCAL OSDUnLoadDllAck ( HPID, HEXE, BOOL );
+XOSD PASCAL OSDDebugActive ( HPID, DWORD, HANDLE, LPDWORD );
+XOSD PASCAL OSDStackWalkSetup ( HPID, HTID, BOOL, LPSTKSTR );
+XOSD PASCAL OSDStackWalkNext ( HPID, HTID, LPSTKSTR );
+XOSD PASCAL OSDStackWalkCleanup ( HPID, HTID, LPSTKSTR );
+XOSD PASCAL OSDSetFrame ( HPID, HTID, PFRAME );
+XOSD PASCAL OSDSetPath ( HPID, BOOL, LSZ );
+//XOSD PASCAL OSDSetBreakpoint ( HPID, HTID, WORD, LPBPARGS );
+//XOSD PASCAL OSDRemoveBreakpoint ( HPID, HTID, WORD, LPBPARGS );
+//XOSD PASCAL OSDBPAccept ( HPID, HTID, BOOL );
+XOSD PASCAL OSDGetPrompt ( HPID, LPPROMPTMSG );
+XOSD PASCAL OSDGetModuleList ( HPID, HTID, BOOL, LSZ, LPMODULE_LIST* );
+XOSD PASCAL OSDSendReply ( HPID, UINT, LPVOID );
+XOSD PASCAL OSDGetFunctionInfo ( HPID, PADDR, PFUNCTION_INFO );
+
+enum {
+ ioctlNull = 0,
+ ioctlDumpLocalHeap,
+ ioctlDumpGlobalHeap,
+ ioctlDumpModuleList,
+ ioctlCrackLocalHmem,
+ ioctlCrackGlobalHmem,
+ ioctlKillApplication,
+ ioctlGetThreadHandle, // get the low level thread handle (NT)
+ ioctlGetProcessHandle, // Get the low level process handle (NT)
+ ioctlGetThreadContext, // get os+machine specific context structure
+ ioctlSetThreadContext, // set os+machine specific context structure
+ ioctlCustomCommand, // random user command for EM
+ ioctlGeneric // generic dm specific
+};
+
+typedef enum {
+ dbcCommError = -1, // -1 - Error occurred in transport layer
+ //
+ dbcInfoAvail = 0x100, // 100 - Display info the the user.
+ // wParam = nothing
+ // lParam = string to be dumped
+ dbcInfoReq, // 101 - DM needs a character.
+ // wParam = nothing
+ // lParam = nothing
+ dbcSuccess, // 102 - A command completed successfully.
+ // (REVIEW: remove?)
+ // wParam = ??
+ // lParam = ??
+ dbcError, // 103 - A command resulted in an error.
+ // wParam = nothing
+ // lParam = zero-terminated string to display
+ dbcSignal, // 104 - A signal has been received.
+ // wParam = nothing(??)
+ // lParam = nothing(??)
+ dbcException, // 105 - An exception occurred.
+ // wParam = exception code (REVIEW: UNDONE)
+ // lParam = nothing
+ dbcBpt, // 106 - A breakpoint was hit.
+ // wParam = nothing
+ // lParam = nothing
+ dbcWatchPoint, // 107 - A watchpoint was hit.
+ // wParam = watchpoint number that was hit
+ // lParam = nothing
+ dbcSingleStepXXX, // 108 - A single-step finished.
+ // wParam = nothing
+ // lParam = nothing
+ dbcRangeStepXXX, // 109 - A range-step finished.
+ // wParam = nothing
+ // lParam = nothing
+ dbcCoProcErr, // 10A - A coprocessor error occurred.
+ // wParam = nothing
+ // lParam = nothing
+ dbcAsyncStop, // 10B - An asynchronous stop occurred.
+ // wParam = nothing
+ // lParam = nothing
+ dbcNewProc, // 10C - A new process was created.
+ // wParam = new process's HPID
+ // lParam = fReallyNew: true if this process
+ // was just created false if it existed
+ // before but this is the first time the
+ // debugger has been told about it (e.g. in
+ // CVW if a bp is hit in a random process)
+ dbcCreateThread, // 10D - A thread was created.
+ // wParam = nothing
+ // lParam = nothing
+ dbcProcTerm, // 10E - A process terminated. May be followed by
+ // dbcDeleteProc if the HPID was created by
+ // OSDebug rather than by the debugger. The
+ // HPID is still valid until dbcDeleteProc
+ // is received.
+ // wParam = nothing
+ // lParam = process termination code (REVIEW:
+ // UNDONE)
+ dbcThreadTerm, // 10F - A thread terminated. Will be followed by
+ // dbcDeleteThread. The HTID is still valid
+ // until dbcDeleteThread is received.
+ // wParam = nothing
+ // lParam = nothing
+ dbcDeleteProc, // 110 - An HPID is no longer valid. Normally
+ // preceded by dbcProcTerm.
+ // wParam = nothing(??)
+ // lParam = nothing(??)
+ dbcDeleteThread, // 111 - An HTID is no longer valid. Normally
+ // preceded by dbcThreadTerm.
+ // wParam = nothing(??)
+ // lParam = nothing(??)
+ dbcModLoad, // 112 - A module was loaded.
+ // wParam = Module Table Entry (MTE)
+ // lParam = ptr to name of module
+ dbcModFree, // 113 - A module was freed.
+ // wParam = ??
+ // lParam = ??
+ dbcPageLoad, // 114 - A page load occurred.
+ // wParam = ??
+ // lParam = ??
+ dbcPageMove, // 115 - A page move occurred.
+ // wParam = ??
+ // lParam = ??
+ dbcPageUnload, // 116 - A page unload occurred.
+ // wParam = ??
+ // lParam = ??
+ dbcAliasFree, // 117 - ??
+ // wParam = ??
+ // lParam = ??
+ dbcEmChange, // 118 - ??
+ // wParam = ??
+ // lParam = ??
+ dbcCanStep, // 119 - ??
+ // wParam = ??
+ // lParam = ??
+ dbcFlipScreen, // 11A - The debugger should return control of the
+ // user screen to the system.
+ // wParam = nothing
+ // lParam = nothing
+ dbcMOVEOverlay, // 11B - DOS M.O.V.E. overlay [un]load notification
+ // wParam = fLoad
+ // lParam = nothing
+ dbcThreadBlocked, // 11C - Single thread execution blocked
+ // wParam = nothing
+ // lParam = nothing
+ dbcKbdRecord, // 11D - recording keyboard message
+ // wParam = handle to pid of keyboard
+ // lParam = nothing
+ dbcSetSession, // 11E - set session index of process in hpid
+ // wParam = index of session (nonzero)
+ // lParam = nothing
+ dbcIoctlDone, // 11F - set session index of process in hpid
+ // wParam = index of session (nonzero)
+ // lParam = nothing
+ dbcThreadDestroy, // 120 - Destory the thread
+ dbcNtRip, // 121 - A RIP occurred
+ // wParam = sizeof(NT_RIP)
+ // lParam = pointer to NT_RIP
+ dbcExecuteDone, // 122 - Execute function call is done
+ // wParam = nothing
+ // lparam = handle of save area
+ dbcLastAddr, // 123 - Get last address in line
+ // wParam = nothing
+ // lparam = pointer to address
+ dbcChangedMemory, // 124 - Changed memory contents
+ // wParam = 0
+ // lparam = size of memory block
+ //
+ dbcSegLoad, // 125 - Loaded selector
+ // wParam = 0
+ // lparam = selector
+ //
+ dbcSegFree, // 126 - Freed selector
+ // wParam = 0
+ // lparam = selector
+ //
+ dbcEntryPoint, // 127 - Program is stopped at entry point
+ // wParam = nothing
+ // lParam = nothing
+ dbcLoadComplete, // 128 - Static DLL loads are complete
+ // wParam =
+ // lParam =
+ dbcRemoteQuit, // 129 - The remote monitor has terminated
+ // wParam = nothing
+ // lParam = nothing
+ dbcCheckBpt,
+
+ dbcStep,
+
+ dbcMax // 12A
+} _DBC; // DeBug Callback
+typedef LONG DBC;
+
+
+//
+// Return values from dbcCanStep
+//
+typedef struct _CANSTEP {
+ DWORD Flags;
+ UOFF32 PrologOffset;
+} CANSTEP;
+
+typedef CANSTEP FAR *LPCANSTEP;
+
+#define CANSTEP_NO 0x00000000
+#define CANSTEP_YES 0x00000001
+#define CANSTEP_THUNK 0x00000002
+
+
+typedef struct _CBP {
+ WORD wMessage;
+ HPID hpid;
+ HTID htid;
+ WORD wParam;
+ LONG lParam;
+} CBP; // CallBack Parameters. Not used by OSDebug itself,
+ // but possibly handy for the debugger.
+typedef CBP FAR *LPCBP;
+
+
+#define hmemNull 0
+#define hpidNull 0
+#define htidNull 0
+#define htlNull 0
+#define hemNull 0
+
+#define wNull 0
+#define lNull 0L
+
+//
+// the kernel debugger reserves the first 255 subtypes
+//
+// the subtypes that are defined here are applicable to all
+// dms that exist today.
+//
+#define IG_TRANSLATE_ADDRESS 256
+#define IG_WATCH_TIME 257
+#define IG_WATCH_TIME_STOP 258
+#define IG_WATCH_TIME_RECALL 259
+#define IG_WATCH_TIME_PROCS 260
+#define IG_DM_PARAMS 261
+#define IG_THREAD_INFO 262
+#define IG_TASK_LIST 263
+#define IG_RELOAD 264
+#define IG_PAGEIN 265
+#define IG_CHANGE_PROC 266
+
+
+typedef struct _IOCTLGENERIC {
+ DWORD ioctlSubType;
+ DWORD length;
+ char data[0];
+} IOCTLGENERIC, *PIOCTLGENERIC;
+
+typedef struct _TASK_LIST {
+ DWORD dwProcessId;
+ char ProcessName[16];
+} TASK_LIST, *PTASK_LIST;
+
+
+XOSD FAR PASCAL
+OSDGetMemInfo(HPID hpid, LPMEMINFO lpMemInfo);
+
+
+
+
+//
+// Breakpoints
+//
+
+enum {
+ bptpExec,
+ bptpDataExec,
+ bptpDataC,
+ bptpDataW,
+ bptpDataR,
+ bptpRegC,
+ bptpRegW,
+ bptpRegR,
+ bptpMessage,
+ bptpMClass,
+ bptpInt,
+ bptpRange
+};
+typedef DWORD BPTP;
+
+enum {
+ bpnsStop,
+ bpnsContinue,
+ bpnsCheck
+};
+typedef DWORD BPNS;
+
+enum _BPTS {
+ bptsExec = 0x0001,
+ bptsDataC = 0x0002,
+ bptsDataW = 0x0004,
+ bptsDataR = 0x0008,
+ bptsRegC = 0x0010,
+ bptsRegW = 0x0020,
+ bptsRegR = 0x0040,
+ bptsMessage = 0x0080,
+ bptsMClass = 0x0100,
+ bptsRange = 0x0200,
+ bptsDataExec = 0x0400
+};
+typedef DWORD BPTS;
+
+
+typedef struct _BPIS {
+ BPTP bptp;
+ BPNS bpns;
+ DWORD fOneThd;
+ HTID htid;
+ union {
+ struct {
+ ADDR addr;
+ } exec;
+ struct {
+ ADDR addr;
+ DWORD cb;
+ } data;
+ struct {
+ DWORD dwId;
+ } reg;
+ struct {
+ ADDR addr;
+ DWORD imsg;
+ DWORD cmsg;
+ } msg;
+ struct {
+ ADDR addr;
+ DWORD dwmask;
+ } mcls;
+ struct {
+ DWORD ipt;
+ } ipt;
+ struct {
+ ADDR addr;
+ DWORD cb;
+ } rng;
+ };
+} BPIS;
+typedef BPIS FAR * LPBPIS;
+
+typedef struct _BPS {
+ DWORD cbpis;
+ DWORD cmsg;
+ DWORD fSet;
+ // BPIS rgbpis[];
+ // DWORD rgdwMessage[];
+ // XOSD rgxosd[];
+ // DWORD rgdwNotification[];
+} BPS;
+typedef BPS FAR * LPBPS;
+
+#define RgBpis(B) ((LPBPIS)(((LPBPS)(B)) + 1))
+#define DwMessage(B) ((LPDWORD)(RgBpis((B)) + ((LPBPS)(B))->cbpis))
+#define RgXosd(B) ((LPXOSD)(DwMessage((B)) + ((LPBPS)(B))->cmsg))
+#define DwNotification(B) ((LPDWORD)(RgXosd((B)) + ((LPBPS)(B))->cbpis))
+#define SizeofBPS(B) ( sizeof(BPS) + \
+ (((LPBPS)(B))->cbpis * \
+ (sizeof(BPIS) + sizeof(XOSD) + sizeof(DWORD))) + \
+ (((LPBPS)(B))->cmsg * sizeof(DWORD)) )
+
+XOSD PASCAL
+OSDBreakpoint(
+ HPID hpid,
+ LPBPS lpbps
+ );
+
+
+
+
+
+
+//
+// Exception handling
+//
+
+//
+// These are the actions which the debugger may take
+// in response to an exception raised in the debuggee.
+//
+typedef enum _EXCEPTION_FILTER_DEFAULT {
+ efdIgnore,
+ efdNotify,
+ efdCommand,
+ efdStop
+} EXCEPTION_FILTER_DEFAULT;
+typedef EXCEPTION_FILTER_DEFAULT FAR * LPEXCEPTION_FILTER_DEFAULT;
+
+//
+// commands understood by OSDGetExceptionState
+//
+
+typedef enum _EXCEPTION_CONTROL {
+ exfFirst,
+ exfNext,
+ exfSpecified
+} EXCEPTION_CONTROL;
+typedef EXCEPTION_CONTROL FAR * LPEXCEPTION_CONTROL;
+
+//
+// Exception information packet
+//
+#define EXCEPTION_STRING_SIZE 60
+typedef struct _EXCEPTION_DESCRIPTION {
+ DWORD dwExceptionCode;
+ EXCEPTION_FILTER_DEFAULT efd;
+ char rgchDescription[EXCEPTION_STRING_SIZE];
+} EXCEPTION_DESCRIPTION;
+typedef EXCEPTION_DESCRIPTION FAR * LPEXCEPTION_DESCRIPTION;
+
+XOSD PASCAL
+OSDGetExceptionState(
+ HPID hpid,
+ HTID htid,
+ LPEXCEPTION_DESCRIPTION lpExd,
+ EXCEPTION_CONTROL exf
+ );
+
+XOSD PASCAL
+OSDSetExceptionState (
+ HPID hpid,
+ HTID htid,
+ LPEXCEPTION_DESCRIPTION lpExd
+ );
+
+
+
+//
+// Target execution control
+//
+
+typedef struct _EXOP {
+ BYTE fSingleThread;
+ BYTE fStepOver;
+ BYTE fQueryStep;
+ BYTE fInitialBP;
+ BYTE fPassException;
+ BYTE fSetFocus;
+} EXOP;
+typedef EXOP FAR * LPEXOP;
+
+
+//
+// Range Step Struct
+//
+typedef struct _RSS {
+ LPADDR lpaddrMin;
+ LPADDR lpaddrMax;
+ LPEXOP lpExop;
+} RSS;
+typedef RSS FAR * LPRSS;
+
+
+XOSD PASCAL
+OSDGo(
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpexop
+ );
+
+XOSD PASCAL
+OSDSingleStep(
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpexop
+ );
+
+XOSD PASCAL
+OSDRangeStep(
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddrMin,
+ LPADDR lpaddrMax,
+ LPEXOP lpexop
+ );
+
+XOSD PASCAL
+OSDReturnStep(
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpexop
+ );
+
+XOSD PASCAL
+OSDAsyncStop(
+ HPID hpid,
+ DWORD fSetFocus
+ );
+
+
+
+
+
+
+
+typedef XOSD (FAR PASCAL LOADDS *TLFUNCTYPE) ( TLF, HPID, DWORD, LPARAM );
+typedef XOSD (FAR PASCAL LOADDS *DMTLFUNCTYPE) ( TLF, HPID, DWORD, LPARAM );
+typedef XOSD (FAR PASCAL LOADDS *TLCALLBACKTYPE) (HPID, DWORD, LPARAM );
+typedef XOSD (FAR PASCAL LOADDS *LPDMINIT) ( DMTLFUNCTYPE, LPVOID );
+typedef XOSD (FAR PASCAL LOADDS *LPDMFUNC) ( DWORD, LPBYTE );
+typedef DWORD (FAR PASCAL LOADDS *LPDMDLLINIT) ( LPDBF );
+typedef XOSD (FAR PASCAL LOADDS *LPUISERVERCB) ( TLCB, HPID, HTID, DWORD, LONG);
+
+#endif // _OD_
diff --git a/private/windbg/osdebug/include/odmsg.h b/private/windbg/osdebug/include/odmsg.h
new file mode 100644
index 000000000..3d6105c29
--- /dev/null
+++ b/private/windbg/osdebug/include/odmsg.h
@@ -0,0 +1,244 @@
+#ifndef _ODMSG
+#define _ODMSG
+
+//
+// MSG Map structure
+//
+typedef struct _MSGINFO *LPMSGINFO;
+typedef struct _MSGINFO {
+ UINT Msg; // Message number
+ LPSTR MsgText; // Message Text
+ DWORD MsgMask; // Message mask
+} MSGINFO;
+
+//
+// MSG Map structure
+//
+typedef struct _MSGMAP *LPMSGMAP;
+typedef struct _MSGMAP {
+ DWORD Count; // Number of elements
+ LPMSGINFO MsgInfo; // Pointer to array
+} MSGMAP;
+
+
+//
+// =============== Support for OSDGetModuleList ===========
+//
+
+//
+// Module list
+//
+typedef struct _MODULE_LIST *LPMODULE_LIST;
+typedef struct _MODULE_LIST {
+ DWORD Count;
+} MODULE_LIST;
+
+
+//
+// Module entry
+//
+typedef struct _MODULE_ENTRY *LPMODULE_ENTRY;
+typedef struct _MODULE_ENTRY {
+ BOOL Flat;
+ BOOL Real;
+ DWORD Segment;
+ DWORD Selector;
+ DWORD Base;
+ DWORD Limit;
+ DWORD Type;
+ DWORD SectionCount;
+ HEXE hexe;
+} MODULE_ENTRY;
+
+
+#define FreeModuleList(m) free(m)
+#define ModuleListCount(m) ((m)->Count)
+#define FirstModuleEntry(m) ((LPMODULE_ENTRY)((m)+1))
+#define NextModuleEntry(e) ((e)+1)
+#define NthModuleEntry(m,n) (FirstModuleEntry(m)+(n))
+
+#define ModuleEntryFlat(e) ((e)->Flat)
+#define ModuleEntryReal(e) ((e)->Real)
+#define ModuleEntrySegment(e) ((e)->Segment)
+#define ModuleEntrySelector(e) ((e)->Selector)
+#define ModuleEntryBase(e) ((e)->Base)
+#define ModuleEntryLimit(e) ((e)->Limit)
+#define ModuleEntryType(e) ((e)->Type)
+#define ModuleEntrySectionCount(e) ((e)->SectionCount)
+#define ModuleEntryHexe(e) ((e)->hexe)
+
+
+
+//
+// Module list request
+//
+typedef struct _MODULE_LIST_REQUEST *LPMODULE_LIST_REQUEST;
+typedef struct _MODULE_LIST_REQUEST {
+ BOOL Flat;
+ LSZ Name;
+ LPMODULE_LIST *List;
+} MODULE_LIST_REQUEST;
+
+
+//
+// ========================================================
+//
+
+
+typedef struct _GOL {
+ LPL lplBase;
+ LPL lplLen;
+ LPADDR lpaddr;
+} GOL; // Get Object Length Structure
+typedef GOL FAR *LPGOL;
+
+typedef struct _GET {
+ LPW lpwErrNum;
+ LSZ lszErr;
+ LSZ lszErrText;
+} GET; // get error text
+typedef GET FAR *LPGET;
+
+typedef struct _GTM {
+ LPW lpwMsg;
+ LPW lpwType;
+ LSZ lszMsg;
+ LPW lpwMask;
+} GTM; // get translated message
+typedef GTM FAR *LPGTM;
+
+typedef struct _IOL {
+ UINT wFunction;
+ BYTE rgbVar[];
+} IOL; // Ioctl Structure
+typedef IOL FAR *LPIOL;
+
+// packet used by OSDProgramLoad
+typedef struct _PRL {
+ ULONG ulChildFlags;
+ WORD cbCmdLine;
+ WORD cbPad;
+ CHAR lszCmdLine[];
+} PRL; // PRogram Load structure
+typedef PRL FAR * LPPRL;
+
+// Bit flags for ulChildFlags
+#define ulfMultiProcess 0x00000001L // OS2, NT, and ?MAC?
+#define ulfDebugRegisters 0x00000002L // Win and DOS (?MAC?)
+#define ulfDisableNMI 0x00000004L // DOS (CV /N0)
+#define ulfForceNMI 0x00000008L // DOS (CV /N1)
+#define ulfDisableIBM 0x00000010L // DOS (CV /I0)
+#define ulfForceIBM 0x00000020L // DOS (CV /I1)
+#define ulfMinimizeApp 0x00000040L // Win32
+#define ulfNoActivate 0x00000080L // Win32
+#define ulfInheritHandles 0x00000100L // Win32
+#define ulfWowVdm 0x00000200L // Win32
+
+/*
+ * This structure is used in commuicating a stop event to the EM. It
+ * contains the most basic of information about the stopped thread.
+ * A "frame" pointer, a program counter and bits describing the type
+ * of segment stopped in.
+ */
+
+typedef struct _BPR {
+ DWORD dwNotify; /* tag to identify BP # */
+ UOFFSET offEIP; /* Program Counter offset */
+ UOFFSET offEBP; /* Frame pointer offset */
+ UOFFSET offESP; /* Stack pointer offset */
+ SEGMENT segCS; /* Program counter seletor */
+ SEGMENT segSS; /* Frame & Stack pointer offset */
+ BOOL fFlat:1;
+ BOOL fOff32:1;
+ BOOL fReal:1;
+} BPR; // BreakPoint Return
+
+typedef BPR FAR *LPBPR;
+
+#ifdef WIN32
+typedef struct _EPR {
+ BPR bpr;
+ DWORD dwFirstChance;
+ DWORD ExceptionCode;
+ DWORD ExceptionFlags;
+ DWORD NumberParameters;
+ DWORD ExceptionInformation[];
+} EPR; // Exception Return
+#else
+typedef struct _EPR {
+ BPR;
+ WORD wException;
+} EPR; // Exception Return
+#endif
+typedef EPR FAR *LPEPR;
+
+/*
+ * RIP reporting structure
+ */
+
+typedef struct _NT_RIP {
+ BPR bpr;
+ ULONG ulErrorCode;
+ ULONG ulErrorLevel;
+} NT_RIP; // RIP Return
+typedef NT_RIP FAR *LPNT_RIP;
+
+/*
+ * Stack walking structure
+ *
+ */
+
+typedef struct _STKSTR {
+ ADDR addrPC; // Program counter address
+ ADDR addrRetAddr; // Return Address
+ ADDR addrFrame; // Frame pointer address
+ ULONG ulParams[4]; // first 4 words off the stack
+ ULONG ul; // Space for EM/DM to use
+ PVOID pFpoData; // pointer to fpo data or null (PFPO_DATA)
+ BOOL fFar; // Far call
+} STKSTR, * LPSTKSTR;
+
+
+/*
+ * The following structure is used by the emfSetupExecute message
+ */
+typedef struct _EXECUTE_STRUCT {
+ ADDR addr; /* Starting address for function */
+ HDEP lphdep; /* Handle of save area */
+ BOOL fIgnoreEvents:1; /* Ignore events coming back? */
+ BOOL fFar:1; /* Is the function a _far routine */
+ HIND hindDm; /* This is the DMs handle */
+} EXECUTE_STRUCT;
+typedef EXECUTE_STRUCT FAR * LPEXECUTE_STRUCT;
+
+/*
+ * this is used to debug an active process
+ */
+typedef struct _DBG_ACTIVE_STRUCT {
+ DWORD dwProcessId;
+ HANDLE hEventGo;
+ DWORD dwStatus;
+} DBG_ACTIVE_STRUCT;
+typedef DBG_ACTIVE_STRUCT FAR *LPDBG_ACTIVE_STRUCT;
+
+typedef struct _PROCESSLIST {
+ DWORD pid;
+ BYTE pname[];
+} PROCESSLIST; // ProcessList return
+typedef PROCESSLIST * LPPROCESSLIST;
+
+typedef struct _PROMPTMSG {
+ DWORD len;
+ BYTE szPrompt[];
+} PROMPTMSG; // GetPrompt return
+typedef PROMPTMSG * LPPROMPTMSG;
+
+typedef struct _DMSYM {
+ ADDR AddrSym;
+ DWORD Ra;
+ char fname[];
+} DMSYM;
+typedef DMSYM *PDMSYM, *LPDMSYM;
+
+
+#endif // _ODMS
diff --git a/private/windbg/osdebug/include/osdem.h b/private/windbg/osdebug/include/osdem.h
new file mode 100644
index 000000000..123959da4
--- /dev/null
+++ b/private/windbg/osdebug/include/osdem.h
@@ -0,0 +1,190 @@
+/**** OSDEM.H - Execution model api ****
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 15, 1990 by David W. Gray *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+#ifndef _OSDEM
+#define _OSDEM
+
+typedef enum {
+ emfFreeze = osdFreeze,
+ emfThaw = osdThaw,
+ emfIOCTL = osdIOCTL,
+ emfReadBuf = osdReadBuf,
+ emfWriteBuf = osdWriteBuf,
+ emfShowDebuggee = osdShowDebuggee,
+ emfFixupAddr = osdFixupAddr,
+ emfUnFixupAddr = osdUnFixupAddr,
+ emfSetEmi = osdSetEmi,
+ emfSendChar = osdSendChar,
+ emfFreezeState = osdFreezeState,
+ emfIsOverlayLoaded = osdIsOverlayLoaded,
+ emfCompareAddrs = osdCompareAddrs,
+
+
+ emfDUMMY = 0x30,
+
+
+////////// OSDEBUG4 emfs, more or less ///////////////
+
+ emfDebugPacket,
+
+ emfRegisterDBF,
+ emfInit,
+ emfGetModel,
+ emfUnInit,
+// emfAttach,
+// emfDetach,
+ emfConnect,
+ emfDisconnect,
+
+ emfCreatePid,
+ emfDestroyPid,
+ emfDestroyTid,
+
+ emfSetMulti,
+ emfDebugger,
+
+ emfProgramLoad,
+ emfDebugActive,
+ emfSetPath,
+ emfProgramFree,
+
+ emfThreadStatus,
+ emfProcessStatus,
+// emfFreezeThread,
+// emfSetThreadPriority,
+
+ emfGetExceptionState,
+ emfSetExceptionState,
+
+ emfGetModuleList,
+
+ emfGo,
+ emfSingleStep,
+ emfRangeStep,
+ emfReturnStep,
+ emfStop,
+
+ emfBreakPoint,
+
+ emfSetupExecute,
+ emfStartExecute,
+ emfCleanUpExecute,
+
+ emfGetAddr,
+ emfSetAddr,
+// emfFixupAddr,
+// emfUnFixupAddr,
+// emfSetEmi,
+ emfRegisterEmi,
+// emfUnRegisterEmi,
+// emfCompareAddrs,
+// emfGetObjLength,
+// emfGetMemoryInfo,
+
+// emfReadMemory,
+// emfWriteMemory,
+
+ emfGetRegStruct,
+ emfGetFlagStruct,
+ emfGetReg,
+ emfSetReg,
+ emfGetFlag,
+ emfSetFlag,
+// emfSaveRegs,
+// emfRestoreRegs,
+
+ emfUnassemble,
+// emfGetPrevInst,
+ emfAssemble,
+
+// emfGetFrame,
+
+ emfMetric,
+
+ emfGetMsgMap,
+// emfGetMessageMaskMap,
+
+// emfInfoReply,
+// emfContinue,
+
+// emfReadFile,
+// emfWriteFile,
+
+// emfShowDebuggee,
+ emfGetProcessList,
+// emfSystemService,
+// emfSetDebugMode,
+
+
+/////////////////////////////////////////////////
+
+ emfIsStackSetup,
+ emfStackWalkSetup,
+ emfStackWalkNext,
+ emfStackWalkCleanup,
+ emfLoadDllAck,
+ emfUnLoadDllAck,
+ emfSetFrame,
+ emfGetPrompt,
+ emfSetFrameContext,
+ emfFrameRegValue,
+ emfFrameSetReg,
+ emfMiscReply,
+ emfGetMemInfo,
+ emfGetFunctionInfo,
+ emfMax
+} _EMF;
+
+typedef DWORD EMF;
+
+typedef enum {
+ dbcoCreateThread = dbcMax,
+ dbcoNewProc,
+ dbcoMax
+} _DBCO; // Debug CallBacks Osdebug specific
+typedef LONG DBCO;
+
+typedef struct _EMCB {
+ XOSD (PASCAL LOADDS *lpfnCallBackDB) ( DBC, HPID, HTID, DWORD, DWORD, VOID FAR * );
+ XOSD (PASCAL LOADDS *lpfnCallBackTL) ( TLF, HPID, DWORD, VOID FAR * );
+ XOSD (PASCAL LOADDS *lpfnCallBackNT) ( EMF, HPID, HTID, DWORD, VOID FAR * );
+ XOSD (PASCAL LOADDS *lpfnCallBackEM) ( EMF, HPID, HTID, DWORD, DWORD, VOID FAR * );
+} EMCB; // Execution Model CallBacks
+typedef EMCB FAR *LPEMCB;
+
+typedef struct _REMI {
+ HEMI hemi;
+ LSZ lsz;
+} REMI; // Register EMI structure
+typedef REMI FAR * LPREMI;
+
+// M.O.V.E. notification types/defs
+
+#define fOvlLoad ((BYTE)0x06)
+#define fOvlUnload ((BYTE)0x07)
+
+#pragma pack(1)
+typedef struct _OVL7 {
+ BYTE bVersion;
+ BYTE cbOvl7;
+ BYTE fOvlOp;
+ unsigned short iovl;
+ WORD dbFrameBase;
+} OVL7;
+#pragma pack()
+typedef OVL7 FAR *LPOVL7;
+
+
+// get od/em/dm message structures
+#include "odmsg.h"
+
+#endif // _OSDEM
diff --git a/private/windbg/osdebug/include/shapi.h b/private/windbg/osdebug/include/shapi.h
new file mode 100644
index 000000000..2414c361c
--- /dev/null
+++ b/private/windbg/osdebug/include/shapi.h
@@ -0,0 +1,386 @@
+#error Don't include shapi.h... Use shapi.hxx instead.
+
+/** shapi.h - Public API to the Symbol Handler
+ *
+ * This file contains all types and APIs that are defined by
+ * the Symbol Handler and are publicly accessible by other
+ * components.
+ *
+ * Before including this file, you must include cvtypes.h.
+ */
+
+
+/*** The master copy of this file resides in the CodeView project.
+ * All Microsoft projects are required to use the master copy without
+ * modification. Modification of the master version or a copy
+ * without consultation with all parties concerned is extremely
+ * risky.
+ *
+ * The projects known to use this version (1.00.00) are:
+ *
+ * Codeview
+ * Sequoia
+ * C/C++ expression evaluator
+ * Cobol expression evaluator
+ * QC/Windows
+ * Pascal 2.0 expression evaluator
+ * Symbol Handler
+ * Stump (OSDebug)
+ */
+
+#ifndef SH_API
+#define SH_API
+
+#ifndef RC_INVOKED
+#pragma pack (1)
+
+typedef enum { // Error returns from some SH functions
+ sheNone = 0,
+ sheNoSymbols = 1, // No CV info
+ sheFutureSymbols = 2, // NB08 to NB99
+ sheMustRelink = 3, // NB00 to NB04
+ sheNotPacked = 4, // NB05 to NB06
+ sheOutOfMemory = 5,
+ sheCorruptOmf = 6,
+ sheFileOpen = 7, // Couldn't open file
+ sheSuppressSyms = 8, // Symbol loading was suppressed
+ sheDeferSyms = 9, // Symbol loading was defered
+ sheSymbolsConverted = 10,
+ sheBadTimeStamp = 11,
+ sheBadCheckSum = 12,
+ sheLastError // Must be last -- used by SHLszGetErrorText as limit
+} SHE;
+
+enum {
+ sopNone = 0,
+ sopData = 1,
+ sopStack = 2
+};
+typedef short SOP; // Symbol OPtions
+
+typedef enum {
+ fcdNone,
+ fcdData,
+ fcdNear,
+ fcdFar
+} FCD; // Function Call Distance (near/far/unknown)
+
+typedef enum {
+ astNone,
+ astAddress,
+ astRegister,
+ astBaseOff
+} AST; // Assembler symbol return Types
+
+typedef struct _ASR {
+ AST ast;
+ union {
+ struct {
+ FCD fcd;
+ ADDR addr;
+ } u;
+ WORD ireg;
+ OFFSET off;
+ } u;
+} ASR; // Assembler Symbol Return structure
+typedef ASR FAR *LPASR;
+
+typedef HEMI SHEMI;
+typedef unsigned int SHFLAG; //* A TRUE/FALSE flag var
+typedef SHFLAG FAR * PSHFLAG;
+typedef SEGMENT SHSEG; //* A segment/selector value
+typedef UOFFSET SHOFF; //* An offset value
+
+typedef HDEP HTYPE; //* A handle to a type
+typedef HDEP HSYM; //* A handle to a symbol
+typedef HDEP HPROC; //* A handle to a procedure
+typedef HDEP HBLK; //* A handle to a block.
+typedef HDEP HSF; //* A handle to source file table
+
+#if defined (WIN32) && defined(STRICT)
+DECLARE_HANDLE( HVOID );
+DECLARE_HANDLE( HMOD );
+DECLARE_HANDLE( HGRP );
+DECLARE_HANDLE( HEXE );
+DECLARE_HANDLE( HPDS );
+#else
+typedef HIND HVOID; //* Generic handle type
+typedef HIND HMOD; //* A module handle
+typedef HIND HGRP; //* A group handle (sub group of module
+ //* currently either a seg or filename)
+typedef HIND HEXE; //* An Executable file handle
+typedef HIND HPDS; //* A handle to a process
+#endif
+
+typedef HSYM FAR * PHSYM;
+
+typedef unsigned short THIDX;
+
+typedef struct CXT {
+ ADDR addr;
+ HMOD hMod;
+ HGRP hGrp;
+ HPROC hProc;
+ HBLK hBlk;
+ } CXT; //* General Symbol context pkt
+typedef CXT FAR *PCXT;
+
+typedef struct CXF {
+ CXT cxt;
+ FRAME Frame;
+ } CXF; //* Symbol context pkt locked to a frame ptr
+typedef CXF FAR *PCXF;
+
+typedef enum {
+ SHFar,
+ SHNear
+ } SHCALL;
+
+typedef struct SHREG {
+ unsigned short hReg;
+ union {
+ unsigned char Byte1;
+ struct {
+ unsigned short Byte2;
+ unsigned short Byte2High;
+ } a;
+ struct {
+ unsigned long Byte4;
+ unsigned long Byte4High;
+ } b;
+ double Byte8;
+ REAL10 Byte10;
+ } u;
+ } SHREG;
+typedef SHREG FAR *PSHREG;
+
+
+
+// structure defining parameters of symbol to be searched for. The address
+// of this structure is passed on the the EE's symbol compare routine. Any
+// additional data required by the EE's routine must follow this structure.
+
+typedef struct _SSTR { // string with length byte and pointer to data
+ LPB lpName; // pointer to the string itself
+ unsigned char cb; // length byte
+ unsigned char searchmask; // mask to control symbol searching
+ unsigned short symtype; // symbol types to be checked
+ unsigned char FAR *pRE; // pointer to regular expression
+} SSTR;
+typedef SSTR FAR *LPSSTR;
+
+#define SSTR_proc 0x0001 // compare only procs with correct type
+#define SSTR_data 0x0002 // compare only global data with correct type
+#define SSTR_RE 0x0004 // compare using regular expression
+#define SSTR_NoHash 0x0008 // do a linear search of the table
+#define SSTR_symboltype 0x0010 // pass only symbols of symtype to the
+ // comparison function.
+
+#define SHpCXTFrompCXF(a) (&((a)->cxt))
+#define SHpFrameFrompCXF(a) (&(a)->Frame)
+#define SHHMODFrompCXT(a) ((a)->hMod)
+#define SHHPROCFrompCXT(a) ((a)->hProc)
+#define SHHBLKFrompCXT(a) ((a)->hBlk)
+#define SHpADDRFrompCXT(a) (&((a)->addr))
+#define SHPAddrFromPCxf(a) (SHpADDRFrompCXT(SHpCXTFrompCXF(a)))
+
+#define SHIsCXTMod(a) ((a)->hMod && !(a)->hProc && !(a)->hBlk)
+#define SHIsCXTProc(a) ((a)->hMod && (a)->hProc && !(a)->hBlk)
+#define SHIsCXTBlk(a) ((a)->hMod && (a)->hProc && (a)->hBlk)
+
+#define SHHGRPFrompCXT(a) ((a)->hGrp)
+
+typedef SHFLAG (PASCAL FAR *PFNCMP)(LPSSTR, LPV, LSZ, SHFLAG);
+ //* comparison prototype
+typedef BOOL (PASCAL FAR *PFNVALIDATEEXE)(UINT, LPV, LPSTR);
+
+#define LPFNSYM PASCAL LOADDS FAR *
+#define LPFNSYMC CDECL LOADDS FAR *
+
+typedef struct omap_tag {
+ DWORD rva;
+ DWORD rvaTo;
+} OMAP, *LPOMAP;
+
+typedef struct {
+ DWORD Offset;
+ DWORD Size;
+ DWORD Flags;
+} SECSTART, *LPSECSTART;
+
+typedef struct _tagDEBUGDATA {
+ LPVOID lpRtf; // Runtime function table - fpo or pdata
+ DWORD cRtf; // Count of rtf entries
+ LPOMAP lpOmapFrom; // Omap table - From Source
+ DWORD cOmapFrom; // Count of omap entries - From Source
+ LPOMAP lpOmapTo; // Omap table - To Source
+ DWORD cOmapTo; // Count of omap entries - To Source
+ LPSECSTART lpSecStart; // Original section table (pre-Lego)
+ SHE she;
+} DEBUGDATA, *LPDEBUGDATA;
+
+typedef struct _KNF {
+ int cb;
+
+ LPV (LPFNSYM lpfnMHAlloc) ( UINT );
+ LPV (LPFNSYM lpfnMHRealloc) ( LPV, UINT );
+ VOID (LPFNSYM lpfnMHFree) ( LPV );
+ VOID _HUGE_ * (LPFNSYM lpfnMHAllocHuge) ( LONG, UINT );
+ VOID (LPFNSYM lpfnMHFreeHuge) ( LPV );
+
+ HDEP (LPFNSYM lpfnMMAllocHmem) ( UINT );
+ VOID (LPFNSYM lpfnMMFreeHmem) ( HDEP );
+ LPV (LPFNSYM lpfnMMLock) ( HDEP );
+ VOID (LPFNSYM lpfnMMUnlock) ( HDEP );
+
+ HLLI (LPFNSYM lpfnLLInit) ( UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE );
+ HLLE (LPFNSYM lpfnLLCreate) ( HLLI );
+ VOID (LPFNSYM lpfnLLAdd) ( HLLI, HLLE );
+ VOID (LPFNSYM lpfnLLAddHead) ( HLLI, HLLE );
+ VOID (LPFNSYM lpfnLLInsert) ( HLLI, HLLE, ULONG );
+ BOOL (LPFNSYM lpfnLLDelete) ( HLLI, HLLE );
+ BOOL (LPFNSYM lpfnLLRemove) ( HLLI, HLLE );
+ LONG (LPFNSYM lpfnLLDestroy) ( HLLI );
+ HLLE (LPFNSYM lpfnLLNext) ( HLLI, HLLE );
+ HLLE (LPFNSYM lpfnLLFind) ( HLLI, HLLE, LPV, ULONG );
+ HLLE (LPFNSYM lpfnLLLast) ( HLLI );
+ LONG (LPFNSYM lpfnLLSize) ( HLLI );
+ LPV (LPFNSYM lpfnLLLock) ( HLLE );
+ VOID (LPFNSYM lpfnLLUnlock) ( HLLE );
+
+ int (LPFNSYM lpfnLBPrintf) ( LPCH, LPCH, UINT );
+ UINT (LPFNSYM lpfnLBQuit) ( UINT );
+
+ UINT (LPFNSYM lpfnSYOpen) ( LSZ );
+ VOID (LPFNSYM lpfnSYClose) ( UINT );
+ UINT (LPFNSYM lpfnSYReadFar) ( UINT, LPB, UINT );
+ LONG (LPFNSYM lpfnSYSeek) ( UINT, LONG, UINT );
+ UINT (LPFNSYM lpfnSYFixupAddr) ( PADDR );
+ UINT (LPFNSYM lpfnSYUnFixupAddr)(PADDR );
+ UINT (LPFNSYM lpfnSYProcessor) ( VOID );
+ UINT (LPFNSYM lpfnSYFIsOverlayLoaded)( PADDR );
+
+ VOID (LPFNSYM lpfn_searchenv)( LSZ, LSZ, LSZ );
+ UINT (LPFNSYMC lpfnsprintf)( LSZ, LSZ, ... );
+ VOID (LPFNSYM lpfn_splitpath)( LSZ, LSZ, LSZ, LSZ, LSZ );
+ LSZ (LPFNSYM lpfn_fullpath)( LSZ, LSZ, UINT );
+ VOID (LPFNSYM lpfn_makepath)( LSZ, LSZ, LSZ, LSZ, LSZ );
+ UINT (LPFNSYM lpfnstat)( LSZ, LPCH );
+ VOID (LPFNSYM lpfnLBLog) ( LSZ);
+ LONG (LPFNSYM lpfnSYTell) ( UINT);
+ UINT (LPFNSYM lpfnSYFindExeFile) ( LSZ, LSZ, UINT, LPV, PFNVALIDATEEXE );
+ VOID (LPFNSYM lpfnLoadedSymbols) ( SHE, HPID, LSZ );
+ BOOL (LPFNSYM lpfnSYGetDefaultShe) ( LSZ, SHE * );
+
+
+} KNF; // codeview KeRnel Functions exported to the Symbol Handler
+typedef KNF FAR *LPKNF;
+
+typedef struct _SHF {
+ int cb;
+ HPDS (LPFNSYM pSHCreateProcess) ( VOID );
+ VOID (LPFNSYM pSHSetHpid) ( HPID );
+ BOOL (LPFNSYM pSHDeleteProcess) ( HPDS );
+ HPDS (LPFNSYM pSHChangeProcess) ( HPDS, BOOL );
+ SHE (LPFNSYM pSHAddDll) ( LSZ, BOOL );
+ SHE (LPFNSYM pSHAddDllsToProcess) ( VOID );
+ SHE (LPFNSYM pSHLoadDll) ( LSZ, BOOL );
+ VOID (LPFNSYM pSHUnloadDll) ( HEXE );
+ UOFFSET (LPFNSYM pSHGetDebugStart) ( HSYM );
+ LSZ (LPFNSYM pSHGetSymName) ( HSYM, LSZ );
+ BOOL (LPFNSYM pSHAddrFromHsym) ( PADDR, HSYM );
+ HMOD (LPFNSYM pSHHModGetNextGlobal) ( HEXE FAR *, HMOD );
+ int (LPFNSYM pSHModelFromAddr) ( PADDR, LPW, LPB, UOFFSET FAR * );
+ int (LPFNSYM pSHPublicNameToAddr) ( PADDR, PADDR, LSZ );
+ LSZ (LPFNSYM pSHGetSymbol) ( PADDR, SOP, PADDR, LSZ, LPL );
+ LSZ (LPFNSYM pSHGetModule) ( PADDR, LSZ );
+ BOOL (LPFNSYM pSHGetPublicAddr) ( PADDR, LSZ );
+ BOOL (LPFNSYM pSHIsLabel) ( HSYM );
+
+ VOID (LPFNSYM pSHSetDebuggeeDir) ( LSZ );
+ VOID (LPFNSYM pSHSetUserDir) ( LSZ );
+ BOOL (LPFNSYM pSHAddrToLabel) ( PADDR, LSZ );
+
+ int (LPFNSYM pSHGetSymLoc) ( HSYM, LSZ, UINT, PCXT );
+ BOOL (LPFNSYM pSHFIsAddrNonVirtual) ( PADDR );
+ BOOL (LPFNSYM pSHIsFarProc) ( HSYM );
+
+ HEXE (LPFNSYM pSHGetNextExe) ( HEXE );
+ HEXE (LPFNSYM pSHHexeFromHmod) ( HMOD );
+ HMOD (LPFNSYM pSHGetNextMod) ( HEXE, HMOD );
+ PCXT (LPFNSYM pSHGetCxtFromHmod) ( HMOD, PCXT );
+ PCXT (LPFNSYM pSHGetCxtFromHexe) ( HEXE, PCXT );
+ PCXT (LPFNSYM pSHSetCxt) ( PADDR, PCXT );
+ PCXT (LPFNSYM pSHSetCxtMod) ( PADDR, PCXT );
+ HSYM (LPFNSYM pSHFindNameInGlobal) ( HSYM,
+ PCXT,
+ LPSSTR,
+ SHFLAG,
+ PFNCMP,
+ SHFLAG,
+ PCXT
+ );
+ HSYM (LPFNSYM pSHFindNameInContext) ( HSYM,
+ PCXT,
+ LPSSTR,
+ SHFLAG,
+ PFNCMP,
+ SHFLAG,
+ PCXT
+ );
+ HSYM (LPFNSYM pSHGoToParent) ( PCXT, PCXT );
+ HSYM (LPFNSYM pSHHsymFromPcxt) ( PCXT );
+ HSYM (LPFNSYM pSHNextHsym) ( HMOD, HSYM );
+ PCXF (LPFNSYM pSHGetFuncCXF) ( PADDR, PCXF );
+ LPCH (LPFNSYM pSHGetModName) ( HMOD );
+ LPCH (LPFNSYM pSHGetExeName) ( HEXE );
+ LPCH (LPFNSYM pSHGetModNameFromHexe) ( HEXE );
+ LPCH (LPFNSYM pSHGetSymFName) ( HEXE );
+ HEXE (LPFNSYM pSHGethExeFromName) ( LPCH );
+ HEXE (LPFNSYM pSHGethExeFromModuleName) ( LPCH );
+ UOFF32 (LPFNSYM pSHGetNearestHsym) ( PADDR, HMOD, int, PHSYM );
+ SHFLAG (LPFNSYM pSHIsInProlog) ( PCXT );
+ SHFLAG (LPFNSYM pSHIsAddrInCxt) ( PCXT, PADDR );
+ SHFLAG (LPFNSYM pSHCompareRE) ( LPCH, LPCH, BOOL );
+ BOOL (LPFNSYM pSHFindSymbol) ( LSZ, PADDR, LPASR );
+ UOFF32 (LPFNSYM pPHGetNearestHsym) ( PADDR, HEXE, PHSYM );
+ HSYM (LPFNSYM pPHFindNameInPublics) ( HSYM,
+ HEXE,
+ LPSSTR,
+ SHFLAG,
+ PFNCMP
+ );
+ HTYPE (LPFNSYM pTHGetTypeFromIndex) ( HMOD, THIDX );
+ HTYPE (LPFNSYM pTHGetNextType) ( HMOD, HTYPE );
+ LPV (LPFNSYM pSHLpGSNGetTable) ( HEXE );
+ LPDEBUGDATA (LPFNSYM pSHGetDebugData) ( HEXE );
+ BOOL (LPFNSYM pSHCanDisplay) ( HSYM );
+
+ // Source Line handler API Exports
+
+ BOOL (LPFNSYM pSLLineFromAddr) ( LPADDR, LPW, SHOFF FAR *, SHOFF FAR * );
+ BOOL (LPFNSYM pSLFLineToAddr) ( HSF, WORD, LPADDR, SHOFF FAR * ,WORD FAR * );
+ LPCH (LPFNSYM pSLNameFromHsf) ( HSF );
+ LPCH (LPFNSYM pSLNameFromHmod) ( HMOD, WORD );
+ BOOL (LPFNSYM pSLFQueryModSrc) ( HMOD );
+ HMOD (LPFNSYM pSLHmodFromHsf) ( HEXE, HSF );
+ HSF (LPFNSYM pSLHsfFromPcxt) ( PCXT );
+ HSF (LPFNSYM pSLHsfFromFile) ( HMOD, LSZ );
+
+ LPV (LPFNSYM pMHOmfLock) ( HDEP );
+ VOID (LPFNSYM pMHOmfUnLock) ( HDEP );
+ LSZ (LPFNSYM pSHLszGetErrorText) ( SHE );
+ BOOL (LPFNSYM pSHIsThunk) ( HSYM );
+ BOOL (LPFNSYM pSHWantSymbols) ( HEXE );
+} SHF; // Symbol Handler Functions
+typedef SHF FAR *LPSHF;
+
+typedef BOOL (*LPFNSHINIT)(LPSHF*,LPKNF);
+typedef BOOL (*LPFNSHUNINIT)(VOID);
+typedef BOOL (*LPFNSHSTARTBACKGROUND)(VOID);
+typedef BOOL (*LPFNSHSTOPBACKGROUND)(VOID);
+
+#pragma pack ()
+
+#endif //RC_INVOKED
+#endif // SH_API
diff --git a/private/windbg/osdebug/include/shapi.hxx b/private/windbg/osdebug/include/shapi.hxx
new file mode 100644
index 000000000..5c40e4159
--- /dev/null
+++ b/private/windbg/osdebug/include/shapi.hxx
@@ -0,0 +1,411 @@
+// shapi.h - Public API to the Symbol Handler
+//
+// This file contains all types and APIs that are defined by
+// the Symbol Handler and are publicly accessible by other
+// components.
+//
+// Before including this file, you must include cvtypes.h.
+
+
+// The master copy of this file resides in the CVINC project.
+// All Microsoft projects are required to use the master copy without
+// modification. Modification of the master version or a copy
+// without consultation with all parties concerned is extremely
+// risky.
+
+#ifndef _VC_VER_INC
+#include "..\include\vcver.h"
+#endif
+
+#if !defined(SH_API) && !defined(RC_INVOKED)
+#define SH_API
+
+typedef enum { // Error returns from some SH functions
+ sheNone = 0,
+ sheNoSymbols = 1, // No CV info
+ sheFutureSymbols = 2, // NB08 to NB99
+ sheMustRelink = 3, // NB00 to NB04
+ sheNotPacked = 4, // NB05 to NB06
+ sheOutOfMemory = 5,
+ sheCorruptOmf = 6,
+ sheFileOpen = 7, // Couldn't open file
+ sheSuppressSyms = 8, // Symbol loading was suppressed
+ sheDeferSyms = 9, // Symbol loading was defered
+ sheSymbolsConverted = 10,
+ sheBadTimeStamp = 11,
+ sheBadCheckSum = 12,
+ shePdbNotFound = 13, // Can't find/open pdb file
+ shePdbBadSig = 14, // internal pdb signature doesn't match sym handler
+ shePdbInvalidAge = 15, // pdb info doesn't match exe/dll
+ shePdbOldFormat = 16, // pdb format is obsolete
+ sheMax // marker for count of she's
+} SHE;
+
+enum {
+ sopNone = 0,
+ sopData = 1,
+ sopStack = 2,
+ sopReg = 4,
+ sopLab = 8,
+ sopFcn = 16,
+ sopExact = 32
+};
+typedef short SOP; // Symbol OPtions
+
+typedef enum {
+ fstNone,
+ fstSymbol,
+ fstPublic
+} FST; // Function Symbol Type
+
+typedef enum {
+ fcdUnknown,
+ fcdNear,
+ fcdFar,
+ fcdData
+} FCD; // Function Call Distance (near/far/unknown)
+
+typedef enum {
+ fptUnknown,
+ fptPresent,
+ fptOmitted
+} FPT; // Frame Pointer Type
+
+typedef struct _ODR {
+ FST fst;
+ FCD fcd;
+ FPT fpt;
+ WORD cbProlog;
+ DWORD dwDeltaOff;
+ LSZ lszName;
+} ODR; // OSDebug Return type
+typedef ODR *LPODR;
+
+
+typedef enum {
+ astNone,
+ astAddress,
+ astRegister,
+ astBaseOff
+} AST; // Assembler symbol return Types
+
+typedef struct _ASR {
+ AST ast;
+ union {
+ struct {
+ FCD fcd;
+ ADDR addr;
+ };
+ WORD ireg;
+ OFFSET off;
+ };
+} ASR; // Assembler Symbol Return structure
+typedef ASR *LPASR;
+
+typedef HEMI SHEMI;
+typedef unsigned int SHFLAG; // A TRUE/FALSE flag var
+typedef SHFLAG * PSHFLAG;
+typedef SEGMENT SHSEG; // A segment/selector value
+typedef UOFFSET SHOFF; // An offset value
+
+typedef void * HVOID; // Generic handle type
+typedef HIND HMOD; // A module handle
+typedef HIND HGRP; // A group handle (sub group of module
+ // currently either a seg or filename)
+typedef HVOID HPROC; // A handle to a procedure
+typedef HVOID HBLK; // A handle to a block.
+typedef HVOID HSF; // A handle to source file table
+typedef HIND HEXE; // An Executable file handle
+typedef HVOID HTYPE; // A handle to a type
+typedef HVOID HSYM; // A handle to a symbol
+typedef HIND HPDS; // A handle to a process
+
+typedef HSYM * PHSYM;
+
+typedef unsigned short THIDX;
+
+typedef struct CXT {
+ ADDR addr;
+ HMOD hMod;
+ HGRP hGrp;
+ HPROC hProc;
+ HBLK hBlk;
+} CXT; // General Symbol context pkt
+typedef CXT *PCXT;
+
+typedef struct CXF {
+ CXT cxt;
+ FRAME Frame;
+} CXF; // Symbol context pkt locked to a frame ptr
+typedef CXF *PCXF;
+
+typedef enum {
+ SHFar,
+ SHNear
+} SHCALL;
+
+typedef struct SHREG {
+ unsigned short hReg;
+ union {
+ unsigned char Byte1;
+ struct {
+ unsigned short Byte2;
+ unsigned short Byte2High;
+ };
+ struct {
+ unsigned long Byte4;
+ unsigned long Byte4High;
+ };
+ double Byte8;
+ FLOAT10 Byte10;
+ };
+} SHREG;
+typedef SHREG *PSHREG;
+
+typedef struct _SLP {
+ ADDR addr;
+ SHOFF cb;
+} SLP; // Source Line Pair (used by SLCAddrFromLine)
+typedef SLP * LPSLP;
+
+// structure defining parameters of symbol to be searched for. The address
+// of this structure is passed on the the EE's symbol compare routine. Any
+// additional data required by the EE's routine must follow this structure.
+
+typedef struct _SSTR { // string with length byte and pointer to data
+ LPB lpName; // pointer to the string itself
+ unsigned char cb; // length byte
+ unsigned char searchmask; // mask to control symbol searching
+ unsigned short symtype; // symbol types to be checked
+ unsigned char * pRE; // pointer to regular expression
+} SSTR;
+typedef SSTR *LPSSTR;
+
+#define SSTR_proc 0x0001 // compare only procs with correct type
+#define SSTR_data 0x0002 // compare only global data with correct type
+#define SSTR_RE 0x0004 // compare using regular expression
+#define SSTR_NoHash 0x0008 // do a linear search of the table
+#define SSTR_symboltype 0x0010 // pass only symbols of symtype to the
+ // comparison function.
+
+#define SHpCXTFrompCXF(a) (&((a)->cxt))
+#define SHpFrameFrompCXF(a) (&(a)->Frame)
+#define SHHMODFrompCXT(a) ((a)->hMod)
+#define SHHPROCFrompCXT(a) ((a)->hProc)
+#define SHHBLKFrompCXT(a) ((a)->hBlk)
+#define SHpADDRFrompCXT(a) (&((a)->addr))
+#define SHPAddrFromPCxf(a) (SHpADDRFrompCXT(SHpCXTFrompCXF(a)))
+
+#define SHIsCXTMod(a) ((a)->hMod && !(a)->hProc && !(a)->hBlk)
+#define SHIsCXTProc(a) ((a)->hMod && (a)->hProc && !(a)->hBlk)
+#define SHIsCXTBlk(a) ((a)->hMod && (a)->hProc && (a)->hBlk)
+
+#define SHHGRPFrompCXT(a) ((a)->hGrp)
+
+// comparison prototype
+typedef SHFLAG (*PFNCMP) (HVOID, HVOID, LSZ, SHFLAG);
+typedef BOOL (*PFNVALIDATEEXE) (UINT, PVOID, LPSTR);
+
+#define LPFNSYM *
+#define LPFNSYMC CDECL *
+
+typedef struct omap_tag {
+ DWORD rva;
+ DWORD rvaTo;
+} OMAP, *LPOMAP;
+
+typedef struct {
+ DWORD Offset;
+ DWORD Size;
+ DWORD Flags;
+} SECSTART, *LPSECSTART;
+
+typedef struct _tagDEBUGDATA {
+ union {
+ PIMAGE_RUNTIME_FUNCTION_ENTRY lpRtf; // Runtime function table - fpo or pdata
+ PFPO_DATA lpFpo;
+ };
+ DWORD cRtf; // Count of rtf entries
+ LPOMAP lpOmapFrom; // Omap table - From Source
+ DWORD cOmapFrom; // Count of omap entries - From Source
+ LPOMAP lpOmapTo; // Omap table - To Source
+ DWORD cOmapTo; // Count of omap entries - To Source
+ LPSECSTART lpSecStart; // Original section table (pre-Lego)
+ SHE she;
+} DEBUGDATA, *LPDEBUGDATA;
+
+typedef struct _KNF {
+ int cb;
+
+ PVOID (LPFNSYM lpfnMHAlloc) (UINT);
+ PVOID (LPFNSYM lpfnMHRealloc) (PVOID, UINT);
+ VOID (LPFNSYM lpfnMHFree) (PVOID);
+ PVOID (LPFNSYM lpfnMHAllocHuge) (LONG, UINT);
+ VOID (LPFNSYM lpfnMHFreeHuge) (PVOID);
+
+ HDEP (LPFNSYM lpfnMMAllocHmem) (UINT);
+ VOID (LPFNSYM lpfnMMFreeHmem) (HDEP);
+ PVOID (LPFNSYM lpfnMMLock) (HDEP);
+ VOID (LPFNSYM lpfnMMUnlock) (HDEP);
+
+ HLLI (LPFNSYM lpfnLLInit) (UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE);
+ HLLE (LPFNSYM lpfnLLCreate) (HLLI);
+ VOID (LPFNSYM lpfnLLAdd) (HLLI, HLLE);
+ VOID (LPFNSYM lpfnLLAddHead) (HLLI, HLLE);
+ VOID (LPFNSYM lpfnLLInsert) (HLLI, HLLE, DWORD);
+ BOOL (LPFNSYM lpfnLLDelete) (HLLI, HLLE);
+ BOOL (LPFNSYM lpfnLLRemove) (HLLI, HLLE);
+ DWORD (LPFNSYM lpfnLLDestroy) (HLLI);
+ HLLE (LPFNSYM lpfnLLNext) (HLLI, HLLE);
+ HLLE (LPFNSYM lpfnLLFind) (HLLI, HLLE, PVOID, DWORD);
+ HLLE (LPFNSYM lpfnLLLast) (HLLI);
+ DWORD (LPFNSYM lpfnLLSize) (HLLI);
+ PVOID (LPFNSYM lpfnLLLock) (HLLE);
+ VOID (LPFNSYM lpfnLLUnlock) (HLLE);
+
+ BOOL (LPFNSYM lpfnLBPrintf) (LPCH, LPCH, UINT);
+ BOOL (LPFNSYM lpfnLBQuit) (UINT);
+
+ UINT (LPFNSYM lpfnSYOpen) (LSZ);
+ VOID (LPFNSYM lpfnSYClose) (UINT);
+ UINT (LPFNSYM lpfnSYReadFar) (UINT, LPB, UINT);
+ LONG (LPFNSYM lpfnSYSeek) (UINT, LONG, UINT);
+ BOOL (LPFNSYM lpfnSYFixupAddr) (PADDR);
+ BOOL (LPFNSYM lpfnSYUnFixupAddr)(PADDR);
+ UINT (LPFNSYM lpfnSYProcessor) (DWORD);
+
+// Added/Changed for NT merge.
+
+// VOID (LPFNSYM lpfn_searchenv) (LSZ, LSZ, LSZ);
+// UINT (LPFNSYMC lpfnsprintf) (LSZ, LSZ, ...);
+// VOID (LPFNSYM lpfn_splitpath) (LSZ, LSZ, LSZ, LSZ, LSZ);
+// LSZ (LPFNSYM lpfn_fullpath) (LSZ, LSZ, UINT);
+// VOID (LPFNSYM lpfn_makepath) (LSZ, LSZ, LSZ, LSZ, LSZ);
+// UINT (LPFNSYM lpfnstat) (LSZ, LPCH);
+
+ LONG (LPFNSYM lpfnSYTell) (UINT);
+ UINT (LPFNSYM lpfnSYFindExeFile) (LSZ, LSZ, UINT, PVOID, PFNVALIDATEEXE);
+ VOID (LPFNSYM lpfnLoadedSymbols) (SHE, HPID, LSZ);
+ BOOL (LPFNSYM lpfnSYGetDefaultShe) (LSZ, SHE *);
+
+} KNF; // KerNel Functions exported to the Symbol Handler
+typedef KNF *LPKNF;
+
+typedef struct _SHF {
+ int cb;
+ HPDS (LPFNSYM pSHCreateProcess) (VOID);
+ VOID (LPFNSYM pSHSetHpid) (HPID);
+ BOOL (LPFNSYM pSHDeleteProcess) (HPDS);
+ HPDS (LPFNSYM pSHChangeProcess) (HPDS);
+ SHE (LPFNSYM pSHAddDll) (LSZ, BOOL); // Changed for NT
+ SHE (LPFNSYM pSHAddDllsToProcess) (VOID);
+ SHE (LPFNSYM pSHLoadDll) (LSZ, BOOL);
+ VOID (LPFNSYM pSHUnloadDll) (HEXE);
+ UOFFSET (LPFNSYM pSHGetDebugStart) (HSYM);
+ LSZ (LPFNSYM pSHGetSymName) (HSYM, LSZ);
+ BOOL (LPFNSYM pSHAddrFromHsym) (PADDR, HSYM); // Changed for NT
+ HMOD (LPFNSYM pSHHModGetNextGlobal) (HEXE *, HMOD);
+ int (LPFNSYM pSHModelFromAddr) (PADDR, LPW, LPB, UOFFSET *);
+ int (LPFNSYM pSHPublicNameToAddr) (PADDR, PADDR, LSZ);
+ LSZ (LPFNSYM pSHGetSymbol) (LPADDR, LPADDR, SOP, LPODR);
+ BOOL (LPFNSYM pSHGetPublicAddr) (PADDR, LSZ);
+ BOOL (LPFNSYM pSHIsLabel) (HSYM);
+
+ VOID (LPFNSYM pSHSetDebuggeeDir) (LSZ);
+// VOID (LPFNSYM pSHSetUserDir) (LSZ); // Deleted for NT
+ BOOL (LPFNSYM pSHAddrToLabel) (PADDR, LSZ);
+
+ int (LPFNSYM pSHGetSymLoc) (HSYM, LSZ, UINT, PCXT);
+ BOOL (LPFNSYM pSHFIsAddrNonVirtual) (PADDR);
+ BOOL (LPFNSYM pSHIsFarProc) (HSYM);
+
+ HEXE (LPFNSYM pSHGetNextExe) (HEXE);
+ HEXE (LPFNSYM pSHHexeFromHmod) (HMOD);
+ HMOD (LPFNSYM pSHGetNextMod) (HEXE, HMOD);
+ PCXT (LPFNSYM pSHGetCxtFromHmod) (HMOD, PCXT);
+ PCXT (LPFNSYM pSHSetCxt) (PADDR, PCXT);
+ PCXT (LPFNSYM pSHSetCxtMod) (PADDR, PCXT);
+ HSYM (LPFNSYM pSHFindNameInGlobal) (HSYM,
+ PCXT,
+ LPSSTR,
+ SHFLAG,
+ PFNCMP,
+ PCXT
+ );
+ HSYM (LPFNSYM pSHFindNameInContext) (HSYM,
+ PCXT,
+ LPSSTR,
+ SHFLAG,
+ PFNCMP,
+ PCXT
+ );
+ HSYM (LPFNSYM pSHGoToParent) (PCXT, PCXT);
+ HSYM (LPFNSYM pSHHsymFromPcxt) (PCXT);
+ HSYM (LPFNSYM pSHNextHsym) (HMOD, HSYM);
+ PCXF (LPFNSYM pSHGetFuncCXF) (PADDR, PCXF);
+ LPCH (LPFNSYM pSHGetModName) (HMOD);
+ LPCH (LPFNSYM pSHGetExeName) (HEXE);
+ HEXE (LPFNSYM pSHGethExeFromName) (LPCH);
+ UOFF32 (LPFNSYM pSHGetNearestHsym) (PADDR, HMOD, int, PHSYM);
+ SHFLAG (LPFNSYM pSHIsInProlog) (PCXT);
+ SHFLAG (LPFNSYM pSHIsAddrInCxt) (PCXT, PADDR);
+ SHFLAG (LPFNSYM pSHCompareRE) (LPCH, LPCH, BOOL);
+ BOOL (LPFNSYM pSHFindSymbol) (LSZ, PADDR, LPASR);
+ UOFF32 (LPFNSYM pPHGetNearestHsym) (PADDR, HEXE, PHSYM);
+ HSYM (LPFNSYM pPHFindNameInPublics) (HSYM, HEXE, LPSSTR, SHFLAG, PFNCMP);
+ HTYPE (LPFNSYM pTHGetTypeFromIndex) (HMOD, THIDX);
+ HTYPE (LPFNSYM pTHGetNextType) (HMOD, HTYPE);
+ PVOID (LPFNSYM pSHLpGSNGetTable) (HEXE);
+ BOOL (LPFNSYM pSHCanDisplay) (HSYM);
+
+ // Source Line handler API Exports
+
+ BOOL (LPFNSYM pSLLineFromAddr) (LPADDR, LPW, SHOFF *, SHOFF *);
+ BOOL (LPFNSYM pSLFLineToAddr) (HSF, WORD, LPADDR, SHOFF *, WORD *);
+ LPCH (LPFNSYM pSLNameFromHsf) (HSF);
+ LPCH (LPFNSYM pSLNameFromHmod) (HMOD, WORD);
+ BOOL (LPFNSYM pSLFQueryModSrc) (HMOD);
+ HMOD (LPFNSYM pSLHmodFromHsf) (HEXE, HSF);
+ HSF (LPFNSYM pSLHsfFromPcxt) (PCXT);
+ HSF (LPFNSYM pSLHsfFromFile) (HMOD, LSZ);
+
+ int (LPFNSYM pSLCAddrFromLine) (HEXE, HMOD, LSZ, WORD, LPSLP *);
+ VOID (LPFNSYM pSHFree) (PVOID);
+ VOID (LPFNSYM pSHUnloadSymbolHandler)(BOOL);
+// REVIEW: piersh
+ SHE (LPFNSYM pSHGetExeTimeStamp) (LPSTR, ULONG *);
+ VOID (LPFNSYM pSHPdbNameFromExe) (LSZ, LSZ, UINT);
+ LPDEBUGDATA (LPFNSYM pSHGetDebugData) (HEXE);
+ BOOL (LPFNSYM pSHIsThunk) (HSYM);
+ HSYM (LPFNSYM pSHFindSymInExe) (HEXE, LPSSTR, BOOL);
+ HSYM (LPFNSYM pSHFindSLink32) (PCXT);
+ BOOL (LPFNSYM pSHIsDllLoaded) (HEXE);
+
+// Entries added for NT work.
+
+ LSZ (LPFNSYM pSHGetModule) (PADDR, LSZ);
+ PCXT (LPFNSYM pSHGetCxtFromHexe) (HEXE, PCXT);
+ LPCH (LPFNSYM pSHGetModNameFromHexe) (HEXE);
+ LPCH (LPFNSYM pSHGetSymFName) (HEXE);
+ HEXE (LPFNSYM pSHGethExeFromModuleName) (LPCH);
+ LSZ (LPFNSYM pSHLszGetErrorText) (SHE);
+ BOOL (LPFNSYM pSHWantSymbols) (HEXE);
+ HSYM (LPFNSYM pSHFindNameInTypes) ( PCXT, LPSSTR, SHFLAG, PFNCMP, PCXT );
+} SHF; // Symbol Handler Functions
+typedef SHF *LPSHF;
+
+// FNSHINIT is the prototype for the SHInit function
+
+typedef BOOL FNSHINIT(LPSHF *, LPKNF);
+
+typedef FNSHINIT * LPFNSHINIT;
+typedef FNSHINIT * PFNSHINIT;
+
+typedef BOOL (* LPFNSHUNINIT)(VOID);
+typedef BOOL (* LPFNSHSTARTBACKGROUND)(VOID);
+typedef BOOL (* LPFNSHSTOPBACKGROUND)(VOID);
+
+// This is the only SH function that's actually exported from the DLL
+FNSHINIT SHInit;
+
+#endif // SH_API
diff --git a/private/windbg/osdebug/include/types.h b/private/windbg/osdebug/include/types.h
new file mode 100644
index 000000000..c8b589a91
--- /dev/null
+++ b/private/windbg/osdebug/include/types.h
@@ -0,0 +1,257 @@
+/** types.h - Generic types
+ *
+ * This file contains generic types such as USHORT, ushort,
+ * WORD, etc., which are not directly related to CodeView.
+ * Every attempt is made to define them in such a way as they
+ * will not conflict with the standard header files such as
+ * windows.h and os2.h.
+ */
+
+
+/*** The master copy of this file resides in the CodeView project.
+ * All Microsoft projects are required to use the master copy without
+ * modification. Modification of the master version or a copy
+ * without consultation with all parties concerned is extremely
+ * risky.
+ *
+ * The projects known to use this file are:
+ *
+ * CodeView
+ * C/C++ expression evaluator
+ * Symbol Handler
+ * Stump (OSDebug)
+ */
+
+#ifndef _TYPES_H_DEFINED
+#define _TYPES_H_DEFINED
+
+
+#ifdef HOST32
+#define _export
+
+#ifndef LOADDS
+#define LOADDS
+#endif
+
+#ifndef PASCAL
+#define PASCAL
+#endif
+
+#ifndef CDECL
+#define CDECL
+#endif
+
+#ifndef FASTCALL
+#define FASTCALL
+#endif
+
+#ifndef FAR
+#define FAR
+#endif
+
+#ifndef NEAR
+#define NEAR
+#endif
+
+#ifndef _HUGE
+#define _HUGE
+#endif
+
+#ifndef _HUGE_
+#define _HUGE_
+#endif
+
+/*
+** This set of functions need to be expanded to deal with
+** unicode and other problems.
+*/
+
+#define _fmemcmp memcmp
+#define _fmemcpy memcpy
+#define _fmemmove memmove
+#define _fmemset memset
+#define _fstrcat strcat
+#define _fstrchr strchr
+#define _fstrcpy strcpy
+#define _fstricmp stricmp
+#define _fstrlen strlen
+#define _fstrncat strncat
+#define _fstrncmp strncmp
+#define _fstrncpy strncpy
+#define _fstrnicmp strnicmp
+#define _fstrstr strstr
+#define _fstrupr strupr
+
+#else // !HOST32
+
+#ifndef LOADDS
+#define LOADDS _loadds
+#endif
+
+#ifndef PASCAL
+#define PASCAL _pascal
+#endif
+
+#ifndef CDECL
+#define CDECL _cdecl
+#endif
+
+#ifndef FASTCALL
+#define FASTCALL _fastcall
+#endif
+
+#ifndef FAR
+#define FAR _far
+#endif
+
+#ifndef NEAR
+#define NEAR _near
+#endif
+
+#ifndef _HUGE
+#define _HUGE _huge
+#endif
+
+#ifndef _HUGE_
+#define _HUGE_ _huge
+#endif
+#endif // HOST32
+
+#ifndef INTERRUPT
+#define INTERRUPT _interrupt
+#endif
+
+#ifndef LOCAL
+#define LOCAL static
+#endif
+
+#ifndef GLOBAL
+#define GLOBAL
+#endif
+
+//
+// Things that come from either windows.h or os2.h
+//
+
+#if !defined(LOWORD) && !defined(OS2_INCLUDED)
+
+#define VOID void
+
+ typedef unsigned char BYTE;
+
+ typedef int BOOL;
+
+#define LONG long
+
+#endif
+
+//
+// Things that come from windows.h
+//
+
+#if !defined(LOWORD)
+
+ typedef unsigned int HANDLE;
+
+ typedef char FAR * LPSTR;
+
+ typedef unsigned short WORD;
+ typedef unsigned long DWORD;
+
+#endif
+
+//
+// Things that come from os2.h
+//
+
+#if !defined(OS2_INCLUDED)
+
+#define CHAR char
+
+#ifndef _WINDOWS_
+ typedef unsigned char UCHAR;
+#endif
+#define SHORT short
+#define INT int
+#ifndef _WINDOWS_
+ typedef unsigned short USHORT;
+ typedef unsigned int UINT;
+ typedef unsigned long ULONG;
+ typedef char * PCH;
+#endif
+#endif
+
+#if !defined(LOWORD)
+
+#define LOWORD(l) ((WORD)(l))
+#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
+
+#endif
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#ifndef HNULL
+#define HNULL 0
+#endif
+
+#if !defined(TRUE) || !defined(FALSE)
+#undef TRUE
+#undef FALSE
+
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#if !defined(fTrue) || !defined(fFalse)
+#undef fTrue
+#undef fFalse
+
+#define fFalse 0
+#define fTrue 1
+#endif
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef Unreferenced
+#define Unreferenced(a) ((void)a)
+#endif
+
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+typedef void * PV;
+typedef void FAR * LPV;
+
+typedef char * SZ;
+typedef char FAR * LSZ;
+#ifndef _WINDOWS_
+typedef char FAR * LPCH;
+#endif
+
+typedef BOOL FAR * LPF;
+typedef BYTE FAR * LPB;
+typedef WORD FAR * LPW;
+typedef LONG FAR * LPL;
+typedef ULONG FAR * LPUL;
+typedef USHORT FAR *LPUS;
+
+typedef short SWORD;
+
+#ifdef HOST32
+typedef ULONG IWORD;
+#else
+typedef UINT IWORD;
+#define WNDPROC FARPROC
+#endif
+
+#endif // _TYPES_H_DEFINED
diff --git a/private/windbg/osdebug/include/vcver.h b/private/windbg/osdebug/include/vcver.h
new file mode 100644
index 000000000..bd3ee5124
--- /dev/null
+++ b/private/windbg/osdebug/include/vcver.h
@@ -0,0 +1,6 @@
+#ifndef _VC_VER_INC
+#define _VC_VER_INC
+#ifndef _VC_VER
+#define _VC_VER 300
+#endif
+#endif
diff --git a/private/windbg/osdebug/include/version.h b/private/windbg/osdebug/include/version.h
new file mode 100644
index 000000000..9b824fa6e
--- /dev/null
+++ b/private/windbg/osdebug/include/version.h
@@ -0,0 +1,5 @@
+#define rmj 2
+#define rmm 0
+#define rup 4193
+#define szVerName "NT - Windbg"
+#define szVerUser "KENTF2"
diff --git a/private/windbg/osdebug/lb.h b/private/windbg/osdebug/lb.h
new file mode 100644
index 000000000..5a56a2b62
--- /dev/null
+++ b/private/windbg/osdebug/lb.h
@@ -0,0 +1,17 @@
+/**** ****
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 31, 1990 by David W. Gray *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+int PASCAL LOADDS LBPrintf ( char FAR *, char FAR *, int );
+int PASCAL LOADDS LBQuit ( int i );
+
+
+BOOL PASCAL LOADDS DHGetNumber ( char FAR *, int FAR * );
diff --git a/private/windbg/osdebug/lbhpt.h b/private/windbg/osdebug/lbhpt.h
new file mode 100644
index 000000000..c9aba0634
--- /dev/null
+++ b/private/windbg/osdebug/lbhpt.h
@@ -0,0 +1,12 @@
+#define LBPrintf (*lpdbf->lpfnLBPrintf)
+#define LBQuit (*lpdbf->lpfnLBQuit)
+#define SHGetSymbol (*lpdbf->lpfnSHGetSymbol)
+#define SHGetPublicAddr (*lpdbf->lpfnSHGetPublicAddr)
+#define SHModelFromAddr (*lpdbf->lpfnSHModelFromAddr)
+#define SHPublicNameToAddr (*lpdbf->lpfnSHPublicNameToAddr)
+#define SHAddrToPublicName (*lpdbf->lpfnSHAddrToPublicName)
+#define SHWantSymbols (*lpdbf->lpfnSHWantSymbols)
+#define SHLpGSNGetTable (*lpdbf->lpfnSHLpGSNGetTable)
+#define SHGetDebugData (*lpdbf->lpfnSHGetDebugData)
+#define SHFindSymbol (*lpdbf->lpfnSHFindSymbol)
+#define DHGetNumber (*lpdbf->lpfnDHGetNumber)
diff --git a/private/windbg/osdebug/llhpt.h b/private/windbg/osdebug/llhpt.h
new file mode 100644
index 000000000..34ef02867
--- /dev/null
+++ b/private/windbg/osdebug/llhpt.h
@@ -0,0 +1,14 @@
+#define LLInit (*lpdbf->LLInit)
+#define LLCreate (*lpdbf->LLCreate)
+#define LLAdd (*lpdbf->LLAdd)
+#define LLInsert (*lpdbf->LLInsert)
+#define LLDelete (*lpdbf->LLDelete)
+#define LLNext (*lpdbf->LLNext)
+#define LLDestroy (*lpdbf->LLDestroy)
+#define LLFind (*lpdbf->LLFind)
+#define LLSize (*lpdbf->LLSize)
+#define LLLock (*lpdbf->LLLock)
+#define LLUnlock (*lpdbf->LLUnlock)
+#define LLLast (*lpdbf->LLLast)
+#define LLAddHead (*lpdbf->LLAddHead)
+#define LLRemove (*lpdbf->LLRemove)
diff --git a/private/windbg/osdebug/makefile b/private/windbg/osdebug/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/osdebug/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/osdebug/mh.h b/private/windbg/osdebug/mh.h
new file mode 100644
index 000000000..c9ddcb747
--- /dev/null
+++ b/private/windbg/osdebug/mh.h
@@ -0,0 +1,15 @@
+/**** ****
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 31, 1990 by David W. Gray *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+void FAR * PASCAL LOADDS MHAlloc ( size_t );
+void FAR * PASCAL LOADDS MHRealloc ( void FAR *, size_t );
+void PASCAL LOADDS MHFree ( void FAR * );
diff --git a/private/windbg/osdebug/mhhpt.h b/private/windbg/osdebug/mhhpt.h
new file mode 100644
index 000000000..99781ce59
--- /dev/null
+++ b/private/windbg/osdebug/mhhpt.h
@@ -0,0 +1,8 @@
+#define MHAlloc (*lpdbf->lpfnMHAlloc)
+#define MHRealloc (*lpdbf->lpfnMHRealloc)
+#define MHFree (*lpdbf->lpfnMHFree)
+
+#define MMAllocHmem (*lpdbf->lpfnMMAllocHmem)
+#define MMFreeHmem (*lpdbf->lpfnMMFreeHmem)
+#define MMLockHmem (*lpdbf->lpfnMMLock)
+#define MMUnlockHmem (*lpdbf->lpfnMMUnlock)
diff --git a/private/windbg/osdebug/mm.h b/private/windbg/osdebug/mm.h
new file mode 100644
index 000000000..998e63bb8
--- /dev/null
+++ b/private/windbg/osdebug/mm.h
@@ -0,0 +1,55 @@
+/*** mm.h - Memory Manager public data and routines
+*
+* Copyright <C> 1989, Microsoft Corporation
+*
+* Purpose: handle the near and far memory requests of cw and help systems.
+*
+*
+*************************************************************************/
+//
+// MB (Memory Block) memory management structures
+//
+
+#pragma pack(1) // pack on byte boundary
+
+typedef struct _MBHI { // memory block handle information
+ unsigned char index;
+ unsigned char flags : 4;
+ unsigned char mbNum : 4;
+ } MBHI;
+
+typedef union _MBH { // memory block handle
+ HDEP hmem;
+ MBHI mbhi;
+ } MBH;
+
+typedef struct _MB { // memory blocks
+ unsigned char flags;
+ short swLocked;
+ unsigned short cb;
+ void FAR * lpvBlock;
+ } MB;
+
+
+typedef MB FAR * PMB;
+
+//
+// Based Heap Memory manager data structures and defines.
+//
+enum HEAPPRIORITY {
+ MMEMERGENCYHEAP,
+ MMCOWHEAP,
+ MMDLLHEAP,
+ MMHELPHEAP
+};
+
+enum _HANDLEFLAGS {
+ MALLOCED = 0x1, // memory was allocated with near malloc
+ FMALLOCED = 0x2, // memory was allocated with far malloc
+ CVMALLOCED = 0x4 // memory was allocated from cv far memory pool
+ };
+
+
+#define MBUNDEFINED (0) // undefined handle value.
+
+#pragma pack() // packing off
diff --git a/private/windbg/osdebug/newexe.h b/private/windbg/osdebug/newexe.h
new file mode 100644
index 000000000..69c81a5b8
--- /dev/null
+++ b/private/windbg/osdebug/newexe.h
@@ -0,0 +1,105 @@
+/* SCCSID = @(#)newexe.h 4.6 86/09/10 */
+/*
+ * Title
+ *
+ * newexe.h
+ * Pete Stewart
+ * (C) Copyright Microsoft Corp 1984-1987
+ * 17 August 1984
+ *
+ * Description
+ *
+ * Data structure definitions for the DOS 4.0/Windows 2.0
+ * executable file format.
+ *
+ * Modification History
+ *
+ * 84/08/17 Pete Stewart Initial version
+ * 84/10/17 Pete Stewart Changed some constants to match OMF
+ * 84/10/23 Pete Stewart Updates to match .EXE format revision
+ * 84/11/20 Pete Stewart Substantial .EXE format revision
+ * 85/01/09 Pete Stewart Added constants ENEWEXE and ENEWHDR
+ * 85/01/10 Steve Wood Added resource definitions
+ * 85/03/04 Vic Heller Reconciled Windows and DOS 4.0 versions
+ * 85/03/07 Pete Stewart Added movable entry count
+ * 85/04/01 Pete Stewart Segment alignment field, error bit
+ * 85/10/03 Reuben Borman Removed segment discard priority
+ * 85/10/11 Vic Heller Added PIF header fields
+ * 86/03/10 Reuben Borman Changes for DOS 5.0
+ * 86/09/02 Reuben Borman NSPURE ==> NSSHARED
+ * 87/05/04 Reuben Borman Added ne_cres and NSCONFORM
+ * 87/07/08 Reuben Borman Added NEAPPTYPE definitions
+ * 87/10/28 Wieslaw Kalkus Added ne_exetyp
+ * 89/03/23 Wieslaw Kalkus Added ne_flagsothers for OS/2 1.2
+ */
+
+
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | DOS3 .EXE FILE HEADER DEFINITION |
+ | |
+ |_________________________________________________________________|
+ * */
+
+
+#define EMAGIC 0x5A4D /* Old magic number */
+#define ENEWEXE sizeof(struct exe_hdr)
+ /* Value of E_LFARLC for new .EXEs */
+#define ENEWHDR 0x003C /* Offset in old hdr. of ptr. to new */
+#define ERESWDS 0x000d /* No. of reserved words (OLD) */
+#define ERES2WDS 0x000A /* No. of reserved words in e_res2 */
+#define ECP 0x0004 /* Offset in struct of E_CP */
+#define ECBLP 0x0002 /* Offset in struct of E_CBLP */
+#define EMINALLOC 0x000A /* Offset in struct of E_MINALLOC */
+#define EKNOWEAS 0x0001 /* e_flags - program understands EAs */
+#define EDOSEXTENDED 0x0002 /* e_flags - program runs under DOS extender */
+
+struct exe_hdr /* DOS 1, 2, 3 .EXE header */
+ {
+ unsigned short e_magic; /* Magic number */
+ unsigned short e_cblp; /* Bytes on last page of file */
+ unsigned short e_cp; /* Pages in file */
+ unsigned short e_crlc; /* Relocations */
+ unsigned short e_cparhdr; /* Size of header in paragraphs */
+ unsigned short e_minalloc; /* Minimum extra paragraphs needed */
+ unsigned short e_maxalloc; /* Maximum extra paragraphs needed */
+ unsigned short e_ss; /* Initial (relative) SS value */
+ unsigned short e_sp; /* Initial SP value */
+ unsigned short e_csum; /* Checksum */
+ unsigned short e_ip; /* Initial IP value */
+ unsigned short e_cs; /* Initial (relative) CS value */
+ unsigned short e_lfarlc; /* File address of relocation table */
+ unsigned short e_ovno; /* Overlay number */
+ unsigned long e_sym_tab; /* offset of symbol table file */
+ unsigned short e_flags; /* old exe header flags */
+ unsigned short e_res; /* Reserved words */
+ unsigned short e_oemid; /* OEM identifier (for e_oeminfo) */
+ unsigned short e_oeminfo; /* OEM information; e_oemid specific */
+ unsigned short e_res2[ERES2WDS];/* Reserved words */
+ long e_lfanew; /* File address of new exe header */
+ };
+
+#define E_MAGIC(x) (x).e_magic
+#define E_CBLP(x) (x).e_cblp
+#define E_CP(x) (x).e_cp
+#define E_CRLC(x) (x).e_crlc
+#define E_CPARHDR(x) (x).e_cparhdr
+#define E_MINALLOC(x) (x).e_minalloc
+#define E_MAXALLOC(x) (x).e_maxalloc
+#define E_SS(x) (x).e_ss
+#define E_SP(x) (x).e_sp
+#define E_CSUM(x) (x).e_csum
+#define E_IP(x) (x).e_ip
+#define E_CS(x) (x).e_cs
+#define E_LFARLC(x) (x).e_lfarlc
+#define E_OVNO(x) (x).e_ovno
+#define E_SYM_TAB(x) (x).e_sym_tab
+#define E_FLAGS(x) (x).e_flags
+#define E_RES(x) (x).e_res
+#define E_OEMID(x) (x).e_oemid
+#define E_OEMINFO(x) (x).e_oeminfo
+#define E_RES2(x) (x).e_res2
+#define E_LFANEW(x) (x).e_lfanew
+
diff --git a/private/windbg/osdebug/od.c b/private/windbg/osdebug/od.c
new file mode 100644
index 000000000..d4d1d38f4
--- /dev/null
+++ b/private/windbg/osdebug/od.c
@@ -0,0 +1,4293 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ Osdebug.c
+
+Abstract:
+
+ This module implements the OSDebug API used by WinDBG.
+
+Author:
+
+ Kent D. Forschmiedt (kentf) 06-Jul-1993
+ James L. Schaad (jimsch)
+ David W. Gray (davidgra) 15-Oct-1990
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "windows.h"
+#include "memory.h"
+#include "defs.h"
+
+#include "mm.h"
+#include "ll.h"
+#include "lb.h"
+
+#include "tl.h"
+#include "od.h"
+#include "od2.h"
+#include "osdem.h"
+
+#include "mhhpt.h"
+#include "cchpt.h"
+#include "lbhpt.h"
+#include "llhpt.h"
+
+#include "osassert.h"
+#include <string.h>
+#include "dbgver.h"
+
+
+extern AVS Avs;
+static LPDBF lpdbf;
+
+static HLLI llpid;
+static HLLI llem;
+static HLLI lltl = 0;
+
+#define CEXM_MDL_native 0x20
+
+XOSD OSDDoCallBack ( UINT, HPID, HTID, UINT, UINT, LONG );
+XOSD OSDDoCallBackToEM ( EMF, HPID, HTID, UINT, LONG );
+XOSD CreateProc ( LPFNSVC, HEM, HTL, LPHPID );
+XOSD CreateThd ( HPID, HTID, LPHTID );
+
+XOSD CallEM ( EMF, HPID, HTID, DWORD, LPV );
+XOSD CallTL ( TLF, HPID, DWORD, LPV );
+
+XOSD PASCAL LOADDS EMCallBackDB ( DBC, HPID, HTID, DWORD, DWORD, LPV );
+XOSD PASCAL LOADDS EMCallBackTL ( TLF, HPID, DWORD, LPV );
+XOSD PASCAL LOADDS EMCallBackNT ( EMF, HPID, HTID, DWORD, LPV );
+XOSD PASCAL LOADDS EMCallBackEM ( EMF, HPID, HTID, DWORD, DWORD, LPV );
+
+XOSD PASCAL LOADDS TLCallBack ( HPID, UINT, LPV );
+
+static EMCB emcb = {
+ EMCallBackDB,
+ EMCallBackTL,
+ EMCallBackNT,
+ EMCallBackEM
+};
+
+static CRITICAL_SECTION CallbackCriticalSection;
+
+
+
+
+XOSD PASCAL
+OSDInit (
+ LPDBF lpdbfT
+ )
+/*++
+
+Routine Description:
+
+ Initialize the internal structures for osdebug.
+ Register the debugger services callback vector.
+
+ Use list manager to create the three global lists used by osdebug.
+ These are the list of processes ( llpid ), the list of transport
+ layers ( lltl ), and the list of execution models ( llem ).
+
+ Registering the debugger services with osdebug is just an
+ assignment of a pointer to the function structure.
+
+ If this function fails, it is catastrophic. No cleanup of
+ partially allocated data is attempted.
+
+Arguments:
+
+ lpdbfT - Supplies the debugger services structure
+
+Return Value:
+
+ xosdNone - Function succeeded
+
+ xosdOutOfMemory - List manager was unable to allocate room
+ for its root structures.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+
+ assert ( lpdbfT != NULL );
+
+ InitializeCriticalSection( &CallbackCriticalSection );
+
+ lpdbf = lpdbfT;
+
+ llpid = LLInit (sizeof ( PIDS ), llfNull, ODPDKill, (LPFNFCMPNODE) NULL );
+ lltl = LLInit ( sizeof ( TLS ), llfNull, TLKill, (LPFNFCMPNODE) NULL );
+ llem = LLInit ( sizeof ( EMS ), llfNull, EMKill, (LPFNFCMPNODE) NULL );
+
+ if ( llpid == 0 || lltl == 0 || llem == 0 ) {
+ xosd = xosdOutOfMemory;
+ }
+
+ return xosd;
+}
+
+
+
+XOSD PASCAL
+OSDTerm(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Deallocate resources used by OSD. At present, this only destroys
+ critical sections used by osdebug.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ xosd - always xosdNone
+
+--*/
+{
+ DeleteCriticalSection( &CallbackCriticalSection );
+ return xosdNone;
+}
+
+
+
+XOSD PASCAL
+OSDCreatePID (
+ LPFNSVC lpfnsvc,
+ HEM hem,
+ HTL htl,
+ LPHPID lphpid
+ )
+/*++
+
+Routine Description:
+
+ Create the structures associated with a process
+
+ Create the osdebug pid structure and add it to the list of processes
+ ( llpid ). Notify the native execution model ( hem ) and the
+ transport layer ( htl ) of the new process.
+
+ When connecting to a remote transport layer, check the version
+ signature to verify that the components are compatible.
+
+Arguments:
+
+ lpfnsvc - Supplies a pointer to the debugger callback function.
+
+ hem - Supplies a handle to the native execution model.
+
+ htl - Supplies a handle to the transport layer.
+
+ lszEMData - Supplies a string that specifies init data for the
+ process required by the execution model.
+
+ lszTLData - Supplies a string that specifies init data for the
+ process required by the transport layer.
+
+ lphpid - Returns the handle to the pid that is generated.
+
+Return Value:
+
+ xosdOutOfMemory - The List manager was unable to allocate
+ memory for the structures to be created.
+
+ Any error values that may be generated by the transport
+ layer or execution model initialization of a process.
+
+--*/
+{
+ /* *
+ * Use the list manager to create a process structure and add it to *
+ * the process list ( llpid ). *
+ * *
+ * Initialize the fields of the process structure. *
+ * *
+ * Call the execution model service function for the native execution *
+ * model with the emfCreatePid command and the initialization string *
+ * ( lszEMData ). *
+ * *
+ * Call the transport layer service function for the process's *
+ * transport layer with the tlfCreatePid command and the *
+ * initialization string ( lszTLData ). */
+
+ HEM hodem;
+ HPID oldhpid;
+
+ HPID hpid;
+ LPEM lpem;
+ LPTL lptl;
+ XOSD xosd = xosdNone;
+
+ assert ( lpfnsvc != NULL );
+ assert ( hem != hemNull );
+ assert ( htl != htlNull );
+ assert ( lphpid != NULL );
+ assert ( llpid != 0 );
+
+ // Create and initialize the process structure and add to llpid
+
+ xosd = CreateProc ( lpfnsvc, hem, htl, &hpid );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ // Notify the transport layer of the new process
+
+ lptl = LLLock ( htl );
+ xosd = CallTL ( tlfConnect, hpid, 0, NULL );
+ LLUnlock ( htl );
+
+ if (xosd != xosdNone) {
+ // remove hpid from the lists of hpids in llem
+ for (hodem = LLNext((HLLI) llem, (HLLE)hmemNull ); hodem; hodem = LLNext( (HLLI)llem, (HLLE)hodem )) {
+
+ lpem = LLLock ( hodem );
+ if ( oldhpid = (HPID)LLFind ( lpem->llhpid, 0, &hpid, 0L ) ) {
+ LLDelete ( lpem->llhpid, (HLLE)oldhpid );
+ }
+ LLUnlock ( hodem );
+ }
+ LLUnlock ( hodem );
+ LLDelete ( llpid, (HLLE)hpid );
+ return xosd;
+ }
+
+ // Notify the native execution model of the new process
+
+ lpem = LLLock ( hem );
+ xosd = lpem->emfunc( emfConnect, hpid, htidNull, 0, 0);
+
+ if (xosd != xosdNone) {
+ goto err;
+ }
+
+ xosd = lpem->emfunc (emfCreatePid, hpid, htidNull, 0, (LONG) NULL);
+
+ err:
+ LLUnlock ( hem );
+
+ if (xosd != xosdNone) {
+ CallTL(tlfDisconnect, hpid, 0, NULL);
+ LLDelete ( llpid, (HLLE)hpid );
+ return xosd;
+ }
+
+ *lphpid = hpid;
+
+ return xosd;
+}
+
+
+XOSD PASCAL
+OSDDisconnect(
+ HPID hpid,
+ HTID htid
+ )
+{
+ if (!hpid) {
+ return xosdUnknown;
+ }
+
+ return CallTL( tlfDisconnect, hpid, (DWORD)htid, NULL );
+}
+
+
+XOSD PASCAL
+OSDDestroyPID (
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+ Destroy the structures associated with a process
+
+ Delete the osdebug pid structure from the list of processes
+ ( llpid ). Notify the native execution model ( hem ) and the
+ transport layer ( htl ) that it's been deleted.
+
+Arguments:
+
+ hpid - Supplies the process to destroy.
+
+Return Value:
+
+ xosdInvalidProc - The hpid given was invalid.
+
+ Any error values that may be generated by the transport
+ layer or execution model during destruction of a process.
+
+--*/
+{
+
+/***************************************************************************
+ * *
+ * Call the execution model service functions to let them know that *
+ * this hpid is being destroyed. *
+ * *
+ * Use the list manager to delete the process structure from the *
+ * process list ( llpid ). *
+ * *
+ ***************************************************************************/
+
+ XOSD xosd;
+ HEM hodem;
+ LPEM lpem;
+ HPID oldhpid;
+ LPPID lppid;
+ HTL htl, htlT;
+
+ xosd = CallEM ( emfDestroyPid, hpid, htidNull, 0, 0 );
+
+ if (xosd == xosdNone) {
+
+ lppid = LLLock((HLLE)hpid);
+ htl = lppid->htl;
+ LLUnlock((HLLE)hpid);
+
+ oldhpid = NULL;
+ while (oldhpid = (HPID)LLNext((HLLI)llpid, (HLLE)oldhpid) ) {
+ if (oldhpid != hpid) {
+ lppid = LLLock((HLLE)oldhpid);
+ htlT = lppid->htl;
+ LLUnlock((HLLE)oldhpid);
+ if (htlT == htl) {
+ htl = 0;
+ break;
+ }
+ }
+ }
+
+ if (htl) {
+ // if nobody else is using it, tell TL to disconnect
+ xosd = CallEM ( emfDisconnect, hpid, 0, 0, 0 );
+ xosd = CallTL ( tlfDisconnect, hpid, 0, NULL );
+ }
+
+ // remove hpid from the lists of hpids in llem
+ for (hodem = LLNext( (HLLI)llem, (HLLE)hmemNull ); hodem; hodem = LLNext( (HLLI)llem, (HLLE)hodem )) {
+
+ lpem = LLLock ( (HLLE)hodem );
+ if ( oldhpid = (HPID)LLFind ( lpem->llhpid, 0, &hpid, 0L ) ) {
+ LLDelete ( lpem->llhpid, (HLLE)oldhpid );
+ }
+ LLUnlock ( (HLLE)hodem );
+ }
+
+ LLDelete ( llpid, (HLLE)hpid );
+ }
+
+ return xosd;
+
+}
+
+
+
+XOSD PASCAL
+OSDDestroyTID(
+ HTID htid
+ )
+/*++
+
+Routine Description:
+
+ Companion for OSDDestroyPID(); unhooks and deletes an htid.
+ There is less to this than destroying a PID: the EM has to be
+ notified, but the TL does not.
+
+Arguments:
+
+ htid - osdebug htid
+
+Return Value:
+
+ xosdNone, xosdInvalidProc, xosdInvalidThread
+
+--*/
+{
+ LPTID lptid;
+ HPID hpid;
+ LPPID lppid;
+ XOSD xosd;
+
+ lptid = LLLock((HLLE) htid );
+ if (!lptid) {
+ return xosdInvalidThread;
+ }
+ hpid = lptid->hpid;
+ LLUnlock((HLLE) htid );
+
+ xosd = CallEM ( emfDestroyTid, hpid, htid, 0, 0 );
+
+ lppid = LLLock ( (HLLE)hpid );
+ if (!lppid) {
+ return xosdInvalidProc;
+ }
+ LLDelete ( lppid->lltid, (HLLE)htid );
+ LLUnlock ( (HLLE)hpid );
+
+ return xosdNone;
+}
+
+
+XOSD PASCAL
+OSDPtrace (
+ OSD osd,
+ UINT wValue,
+ LPV lpData,
+ HPID hpid,
+ HTID htid
+ )
+/*++
+
+Routine Description:
+
+ Provide ptrace-type functionality. This just passes the parameters
+ to the EM service function.
+
+Arguments:
+
+ osd - Supplies OSD index of requested service
+
+ wValue - Supplies function-dependent data
+
+ lpData - Supplies and/or Returns function dependent data
+
+ hpid - Supplies handle to process structure
+
+ htid - Supplies handle to thread structure
+
+Return Value:
+
+ xosd value as returned by the EM service function.
+
+--*/
+{
+ return CallEM ( (EMF) osd, hpid, htid, wValue, lpData );
+}
+
+
+
+XOSD PASCAL
+OSDIoctl (
+ HPID hpid,
+ HTID htid,
+ UINT wFunction,
+ UINT cbData,
+ LPV lpData
+ )
+/*++
+
+Routine Description:
+
+ Provide OS specific functionality. Calls the EM service function,
+ requesting the emfIOCTL service.
+
+Arguments:
+
+ hpid - Supplies handle to the process to perform the operation
+ on. Some IOCTLs may not apply to a process, but the hpid
+ is required to provide the hook to the EM and TL.
+
+ htid - Supplies optional thread structure
+
+ wFunction - Supplies the IOCTL function index
+
+ cbData - Supplies the number of bytes in the data packet
+
+ lpData - Supplies and returns data. Use of this field depends on
+ the IOCTL.
+
+Return Value:
+
+ xosd return value is supplied by the IOCTL function.
+
+--*/
+{
+
+ XOSD xosd = xosdNone;
+ LPIOL lpiol = MHAlloc ( sizeof ( IOL ) + cbData );
+
+ if ( lpiol == NULL ) return xosdOutOfMemory;
+
+ lpiol->wFunction = wFunction;
+ _fmemcpy ( lpiol->rgbVar, lpData, cbData );
+
+ xosd = CallEM ((EMF) emfIOCTL, hpid, htid, sizeof ( IOL ) + cbData, (LPV) lpiol );
+
+ _fmemcpy ( lpData, lpiol->rgbVar, cbData );
+
+ MHFree ( lpiol );
+
+ return xosd;
+
+}
+
+
+XOSD PASCAL
+OSDProgramLoad (
+ HPID hpid,
+ LSZ lszCmdLine,
+ LSZ lszDebugger,
+ ULONG ulFlags
+ )
+/*++
+
+Routine Description:
+
+ Send a program load request to the EM. If the process is created,
+ the shell will be notified of a new process creation.
+
+Arguments:
+
+ hpid - Supplies the process the process handle that binds to the
+ EM and TL. This is not neccessarily the hpid that will
+ correspond to the new process.
+
+ lszCmdLine - Supplies the command line that specifies the child program
+ and its arguments.
+
+ lszDebugger - Supplies the name of the debugger to the EM. This is
+ provided mainly so that the DM can print the debugger's
+ name in error messages.
+
+ ulFlags - Supplies flags that are passed to the EM. The following
+ flags are defined; any or none may be supported by any
+ EM/DM pair:
+
+ ulfMultiProcess - children of the new process will
+ be debugged.
+
+ ulfMinimizeApp - New process will be iconic
+
+ ulfNoActivate - New process will not receive focus
+
+ ulfInheritHandles - New app will inherit handles
+ from debugger. This is useful
+ when debugging an app which inherits
+ handles from its parent.
+
+ ulfDebugRegisters
+
+ ulfDisableNMI
+
+ ulfForceNMI
+
+ ulfDisableIBM
+
+ ulfForceIBM
+
+Return Value:
+
+ If OSDProgramLoad cannot allocate a buffer to copy the arguements
+ into, it will return xosdOutOfMemory. Other xosd failure codes may be
+ returned from the EM, such as xosdFileNotFound, xosdAccessDenied.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ LPPRL lpprl;
+ UINT cchCmd;
+
+ assert ( hpid != NULL );
+ assert ( lszCmdLine != NULL );
+
+ (void)CallEM ( emfSetMulti,
+ hpid,
+ htidNull,
+ ( ulFlags & ulfMultiProcess ) != 0,
+ NULL
+ );
+
+ (void)CallEM ( emfDebugger,
+ hpid,
+ htidNull,
+ _fstrlen ( lszDebugger ) + 1,
+ lszDebugger
+ );
+
+
+ cchCmd = _fstrlen( lszCmdLine ) + 1;
+ lpprl = (LPPRL)MHAlloc ( sizeof ( PRL ) + cchCmd );
+ if ( lpprl == NULL ) {
+
+ xosd = xosdOutOfMemory;
+
+ } else {
+
+ lpprl->cbCmdLine = cchCmd;
+ lpprl->ulChildFlags = ulFlags;
+ _fmemcpy( lpprl->lszCmdLine, lszCmdLine, cchCmd );
+
+ xosd = CallEM ( emfProgramLoad,
+ hpid,
+ htidNull,
+ sizeof( PRL ) + cchCmd,
+ lpprl
+ );
+
+ MHFree ( lpprl );
+ }
+
+ return xosd;
+}
+
+
+XOSD PASCAL
+OSDAddEM (
+ EMFUNC emfunc,
+ LPDBF lpdbf,
+ LPHEM lphem,
+ EMTYPE emtype
+ )
+/*++
+
+Routine Description:
+
+ Create and initialize an execution model associated with the
+ service function EMFunc and add it to the list of osdebug's
+ available execution models ( llem ).
+
+Arguments:
+
+ emfunc - Supplies a pointer to the execution model service function
+ to be associated with the execution model that is being
+ created.
+
+ lpdbf - Supplies a pointer to the debugger services structure that
+ will be registered with the execution model being created.
+
+ lphem - Returns the execution model handle.
+
+ emtype - Supplies the type of EM; emNative or emNonNative.
+
+Return Value:
+
+ xosdNone - Success.
+
+ xosdOutOfMemory - List manager was unable to allocate em or
+ add it to the execution model list ( llem ).
+
+ Other xosd failure codes may be returned from the new EM while
+ it is being initialized.
+
+--*/
+{
+/***************************************************************************
+ * IMPLEMENTATION: *
+ * *
+ * Use list manager to create an execution model handle and add it *
+ * to the execution model list ( llem ). *
+ * *
+ * Call the execution model service function ( lpfnsvcEM ) to *
+ * initialize the execution model and to register the debugger *
+ * service functions ( lpdbf ). *
+ * *
+ * *
+ ***************************************************************************/
+
+ HEM hem;
+ HEM hemm = 0;
+ LPEM lpem;
+ LPEM lpemm;
+ XOSD xosd = xosdNone;
+ UINT wModel;
+
+ assert ( emfunc != NULL );
+ assert ( lpdbf != NULL );
+ assert ( lphem != NULL );
+
+ hem = LLCreate ( llem );
+ if ( hem == hemNull ) {
+ return xosdOutOfMemory;
+ }
+
+ if ( emtype == emNative ) {
+
+ // native inserted at the tail of the list
+ LLAdd ( llem, hem );
+ }
+ else {
+
+ // non-native inserted at head of list
+ LLAddHead ( llem, hem );
+ }
+
+ lpem = LLLock ( hem );
+ lpem->emfunc = emfunc;
+ lpem->emtype = emtype;
+ lpem->llhpid = LLInit ( sizeof ( HPID ), llfNull, NULL, EMHpidCmp );
+ if ( lpem->llhpid == 0 ) {
+ xosd = xosdOutOfMemory;
+ }
+
+ xosd = emfunc ( emfRegisterDBF, NULL, htidNull, 0, (LONG) lpdbf );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ xosd = emfunc ( emfInit, NULL, htidNull, 0, (LONG) (LPV) &emcb );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ xosd = emfunc ( emfGetModel, NULL, htidNull, 0, (LONG) (LPV) &wModel );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ while ( hemm = LLNext ( llem, hemm ) ) {
+ lpemm = LLLock ( hemm );
+ if ( lpemm->model == wModel ) {
+
+ // this is an error, cannot add the same model twice
+ LLUnlock ( hemm );
+ LLUnlock ( hem );
+ return xosdInvalidEM;
+ }
+ LLUnlock ( hemm );
+ }
+
+ lpem->model = wModel;
+
+ LLUnlock ( hem );
+
+ *lphem = hem;
+
+ return xosd;
+}
+
+
+XOSD PASCAL
+OSDDeleteEM (
+ HEM hem
+ )
+/*++
+
+Routine Description:
+
+ Remove the execution model (hem) from os debug's list of available
+ execution models ( llem ).
+
+Arguments:
+
+ hem - Supplies handle to EM which is being removed
+
+Return Value:
+
+ xosdNone - Success.
+
+ xosdInvalidEM - The execution model handle ( hem ) is invalid.
+
+ xosdEMInUse - The execution model is still being used by some pid.
+ OSDDiscardEM must be called on all of the pids using
+ this particular em before OSDDeleteEM can be called
+ without error.
+
+--*/
+{
+/***************************************************************************
+ * IMPLEMENTATION: *
+ * *
+ * Check the list of pids using this execution model. If it is zero *
+ * indicating that no pids are using it, then call the list manager *
+ * to delete it from the list of available execution models ( llem ). *
+ * *
+ ***************************************************************************/
+ XOSD xosd = xosdNone;
+ LPEM lpem;
+
+ assert ( hem != hemNull );
+
+ lpem = LLLock ( hem );
+
+ if ( LLSize ( lpem->llhpid ) != 0 ) {
+
+ LLUnlock ( hem );
+ xosd = xosdEMInUse;
+
+ } else {
+
+ // Tell the EM and DM that they're about to be discarded
+ (lpem->emfunc) ( emfUnInit, NULL, htidNull, 0, 0 );
+
+ LLUnlock ( hem );
+
+ if ( !LLDelete ( llem, (HLLE)hem ) ) {
+ xosd = xosdInvalidEM;
+ }
+ }
+
+ return xosd;
+}
+
+
+XOSD PASCAL
+OSDDeinitTL(
+ TLFUNC tlfunc
+ )
+/*++
+
+Routine Description:
+
+ Tell the transport to clean up. This should be called if the
+ OSDInitTL succeeds, but the OSDAddTL fails. This sends a
+ tlfGlobalDestroy message to the transport layer.
+
+Arguments:
+
+ tlfunc - Supplies the TL service function
+
+Return Value:
+
+ xosd status returned by the TL.
+
+--*/
+{
+ XOSD xosd;
+
+ xosd = tlfunc(tlfGlobalDestroy, NULL, 0, (LONG)0);
+ return(xosd);
+}
+
+
+XOSD PASCAL
+OSDInitTL(
+ TLFUNC tlfunc,
+ LPDBF lpdbf
+ )
+/*++
+
+Routine Description:
+
+ Initialize a transport layer. Send a pointer to a table of
+ debugger service functions to the TL, then tell it to initialize.
+
+Arguments:
+
+ tlfunc - Supplies the address of the TL service function
+
+ lpdbf - Supplies the table of debugger service functions
+
+Return Value:
+
+ Return status is supplied by the TL.
+ xosdNone if initialization succeeds, an xosd failure code if not.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+
+ xosd = tlfunc ( tlfRegisterDBF, NULL, 0, (LONG) lpdbf );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ xosd = tlfunc ( tlfGlobalInit, NULL, 0, (LONG) TLCallBack );
+ return xosd;
+}
+
+
+
+#if 0
+XOSD PASCAL OSDTLGetInfo( TLFUNC tlfunc, LPGIS lpgis, UINT wLen) {
+ XOSD xosd = xosdNone;
+
+ xosd = tlfunc ( tlfGetInfo, NULL, wLen, (LONG) lpgis );
+ return xosd;
+}
+
+XOSD PASCAL OSDTLSetup( TLFUNC tlfunc, LSZ lszInit, UINT wLen, LPV lpv) {
+ XOSD xosd = xosdNone;
+
+ xosd = tlfunc ( tlfSetUIStruct, NULL, 0, (LONG) lpv );
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+
+ xosd = tlfunc ( tlfSetup, NULL, wLen, (LONG) lszInit );
+ return xosd;
+}
+
+
+#endif // 0
+
+XOSD PASCAL
+OSDAddTL (
+ TLFUNC tlfunc,
+ LPHTL lphtl,
+ LPCH lpchInit
+ )
+/*++
+
+Routine Description:
+
+ Create and initialize a transport layer associated with the
+ service function lpfnsvcTL and add it to the list of osdebug's
+ available transport layers ( lltl ).
+
+Arguments:
+
+ tlfunc - Supplies pointer to the transport layer service function
+ to be associated with the transport layer that is being
+ created.
+
+ lpdbf - Supplies pointer to the debugger services structure that
+ will be registered with the transport layer being created.
+
+ lphtl - Returns the transport layer handle.
+
+Return Value:
+
+ xosdNone - Success.
+
+ xosdOutOfMemory - List manager was unable to allocate TL
+ or add it to the transport layer list ( lltl ).
+
+ Other xosd failure codes may be returned by the transport layer
+ if its initialization fails.
+
+--*/
+{
+/***************************************************************************
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Use list manager to create a transport layer handle and add it *
+ * to the transport layer list ( lltl ). *
+ * *
+ * Call the transport layer service function ( lpfnsvcTL ) to *
+ * initialize the transport layer and to register the debugger *
+ * service functions ( lpdbf ). *
+ * *
+ ***************************************************************************/
+ HTL htl;
+ LPTL lptl;
+ XOSD xosd = xosdNone;
+ AVS RemoteAvs;
+
+ assert ( tlfunc != NULL );
+ assert ( lpdbf != NULL );
+ assert ( lphtl != NULL );
+
+ htl = LLCreate ( lltl );
+ if ( htl == htlNull ) {
+
+ xosd = xosdOutOfMemory;
+
+ } else {
+
+ LLAdd ( lltl, htl );
+
+ lptl = LLLock ( htl );
+
+ lptl->tlfunc = tlfunc;
+ lptl->llpid = LLInit ( sizeof ( HPID ), llfNull, NULL, NULL );
+ if ( lptl->llpid == 0 ) {
+ xosd = xosdOutOfMemory;
+ }
+
+ if (xosd == xosdNone) {
+ xosd = tlfunc ( tlfInit, NULL, 0, (LONG) lpchInit );
+ }
+
+ if (xosd == xosdNone) {
+ xosd = tlfunc ( tlfConnect, NULL, 0, 0 );
+ }
+
+ if (xosd == xosdNone) {
+ xosd = tlfunc(tlfGetVersion, NULL, sizeof(Avs), (LONG)&RemoteAvs);
+ switch (xosd) {
+ case xosdNone:
+ // got version info for remote side of transport...
+ // verify it.
+ if (Avs.rlvt != RemoteAvs.rlvt ||
+ Avs.iApiVer != RemoteAvs.iApiVer) {
+ xosd = xosdBadRemoteVersion; // bogus version
+ }
+ *(MPT *)lpchInit = RemoteAvs.mpt;
+ break;
+
+ case xosdNotRemote:
+ // local transport, don't need to check ver
+ *(MPT *)lpchInit = RemoteAvs.mpt;
+ xosd = xosdNone;
+ break;
+
+ case xosdBadRemoteVersion:
+ default:
+ break; // pass error back after cleaning up
+ }
+
+ if (xosd != xosdNone) {
+ // version check failed, disconnect tl
+ // hpid cleanup is handled below
+ tlfunc( tlfDisconnect, NULL, 0, 0 );
+ }
+ }
+
+ LLUnlock ( htl );
+
+ if (xosd == xosdNone) {
+ *lphtl = htl;
+ } else {
+ LLDelete(lltl, (HLLE)htl);
+ }
+
+ }
+ return xosd;
+}
+
+
+
+XOSD PASCAL
+OSDDeleteTL (
+ HTL htl
+ )
+/*++
+
+Routine Description:
+
+ Remove the transport layer (htl) from os debug's list of available
+ transport layers ( lltl ).
+
+Arguments:
+
+ htl - A transport layer that has previously been returned by
+ OSDAddTL.
+
+Return Value:
+
+ xosdNone - Success.
+
+ xosdTLInUse - The transport layer is still being used by
+ some pid. OSDDiscardTL must be called on all of the
+ pids using this particular em before OSDDeleteTL can
+ be called without error.
+
+ xosdInvalidTL - The transport layer handle ( htl ) is invalid.
+
+--*/
+{
+/***************************************************************************
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Check the list of pids using this transport layer. If it is zero *
+ * indicating that no pids are using it, then call the list manager *
+ * to delete it from the list of available transport layers ( lltl ). *
+ * *
+ ***************************************************************************/
+ XOSD xosd = xosdNone;
+ LPTL lptl;
+
+ assert ( htl != htlNull );
+
+ lptl = LLLock ( htl );
+ if ( LLSize ( lptl->llpid ) != 0 ) {
+
+ LLUnlock ( htl );
+ xosd = xosdTLInUse;
+
+ } else {
+
+ (*lptl->tlfunc)(tlfDestroy, NULL, 0, 0);
+ (*lptl->tlfunc)(tlfGlobalDestroy, NULL, 0, 0);
+
+ LLUnlock ( htl );
+
+ if ( !LLDelete ( lltl, (HLLE)htl ) ) {
+ xosd = xosdInvalidTL;
+ }
+ }
+
+ return xosd;
+}
+
+
+XOSD PASCAL
+OSDGetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+/*++
+
+Routine Description:
+
+ To get one of the special addresses in a process/thread which
+ the EM can supply.
+
+Arguments:
+
+ hpid - The process
+
+ htid - The thread
+
+ adr - The address to get. One of the following.
+
+ adrCurrent - The the current address for the thread.
+ This is used to specify breakpoint
+ addresses, etc.
+
+ adrPC - The program counter of the thread.
+
+ adrBase - The frame base address of the thread.
+
+ adrStack - The current stack pointer of the thread.
+
+ adrData - The data area for the thread/process
+
+ adrBaseProlog - The frame base address will be fixed up as
+ if the prolog code of the existing function
+ were already executed. This requires that
+ the address passed in be the start of the
+ function.
+
+ adrTlsBase - The base of the thread local storage area.
+
+ lpaddr - Returns the requested address.
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that may be generated by the emfGetAddr function
+ of the execution model associated with hpid:htid.
+
+--*/
+{
+ assert ( lpaddr != NULL );
+
+ if ( htid == htidNull && adr != adrCurrent ) {
+ _fmemset ( lpaddr, 0, sizeof ( ADDR ) );
+ return xosdNone;
+ }
+ else {
+ return CallEM ( emfGetAddr, hpid, htid, adr, lpaddr );
+ }
+
+}
+
+
+XOSD PASCAL
+OSDIsStackSetup (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr
+ )
+/*++
+
+Routine Description:
+
+ Find out if the thread's stack is set up for the function
+ at the address supplied. Returns FALSE if the thread's PC
+ is in the function prolog.
+
+ The address must point to a function prolog, and the thread's
+ PC must be in that function, or this API's behaviour is undefined.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lpaddr - Supplies address of the beginning of a function.
+
+Return Value:
+
+ xosdNone - Stack isn't setup
+
+ xosdContinue - The Stack is setup
+
+--*/
+{
+ assert ( lpaddr != NULL )
+
+ if ( htid == htidNull ) {
+ _fmemset ( lpaddr, 0, sizeof ( ADDR ) );
+ return xosdNone;
+ }
+ else {
+ return CallEM ( emfIsStackSetup, hpid, htid, 0, lpaddr );
+ }
+}
+
+
+XOSD PASCAL
+OSDSetAddr (
+ HPID hpid,
+ HTID htid,
+ ADR adr,
+ LPADDR lpaddr
+ )
+/*++
+
+Routine Description:
+
+ Sets one of the addresses associated with a thread.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ adr - Supplies id of the address to set, and may be
+ one of the following:
+
+ adrCurrent - The current address for the thread.
+ This is used to specify breakpoint
+ addresses, etc.
+
+ adrPC - The program counter of the thread.
+
+ adrBase - The frame base address of the thread.
+
+ adrStack - The current stack pointer of the thread.
+
+ adrData - The data area for the thread/process
+
+ adrBaseProlog - N/A ( can't be set )
+
+ adrTlsBase - N/A ( can't be set )
+
+ lpaddr - Supplies the address to set the hpid:htid with
+
+Return Value:
+
+ xosdNone - Success.
+
+ Any error that may be generated by the emfSetAddr function
+ of the execution model associated with hpid:htid.
+
+--*/
+{
+ assert ( lpaddr != NULL );
+
+ if ( htid == htidNull && adr != adrCurrent ) {
+ return xosdInvalidThread;
+ }
+ else {
+ return CallEM ( emfSetAddr, hpid, htid, adr, lpaddr );
+ }
+}
+
+
+
+XOSD PASCAL
+OSDReadReg (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Read a register in a debuggee thread
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wIndex - Supplies register index
+
+ lpv - Returns register value
+
+Return Value:
+
+ xosdNone - Success
+
+ The EM may return an xosd failure status if wIndex is invalid
+ or for other reasons.
+
+--*/
+{
+ assert ( lpv != NULL );
+ return CallEM ( emfGetReg, hpid, htid, wIndex, lpv );
+}
+
+
+XOSD PASCAL
+OSDWriteReg (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Write a register in a debuggee thread
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wIndex - Supplies register index
+
+ lpv - Supplies register value
+
+Return Value:
+
+ xosdNone - Success
+
+ The EM may return an xosd failure status if wIndex is invalid
+ or for other reasons.
+
+--*/
+{
+ return CallEM ( emfSetReg, hpid, htid, wIndex, lpv );
+}
+
+
+XOSD PASCAL
+OSDSetFrameContext (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Specify which frame to use to get context information in the EM
+
+Arguments:
+
+ hpid - The process
+
+ htid - The thread
+
+ wIndex - The frame number; Current is 0; caller is 1, etc.
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that may be generated by the emfSetFrameContext
+ of the execution model associated with hpid:htid.
+
+--*/
+{
+ return CallEM ( emfSetFrameContext, hpid, htid, wIndex, lpv );
+}
+
+
+
+XOSD PASCAL
+OSDFrameReadReg (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Read the register specified by wIndex in the register set
+ specified by hpid:htid, and the frame which was set by a prior
+ call to OSDSetFrameContext.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wIndex - Supplies register index
+
+ lpv - Returns register value
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that may be generated by the emfFrameRegValue
+ function of the execution model associated with hpid:htid.
+
+--*/
+{
+ assert ( lpv != NULL );
+ return CallEM ( emfFrameRegValue, hpid, htid, wIndex, lpv );
+}
+
+
+XOSD PASCAL
+OSDFrameWriteReg (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Write the register specified by wIndex in the register set
+ specified by hpid:htid, and the frame which was set by a prior
+ call to OSDSetFrameContext.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wIndex - Supplies register index
+
+ lpv - Supplies register value
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that may be generated by the emfFrameSetReg function
+ of the execution model associated with hpid:htid.
+
+--*/
+{
+ return CallEM ( emfFrameSetReg, hpid, htid, wIndex, lpv );
+}
+
+
+
+XOSD PASCAL
+OSDReadFlag (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Read the flag specified by wIndex in the processor flag set
+ for hpid:htid pair.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wIndex - Supplies register index
+
+ lpv - Returns value
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that may be generated by the emfGetFlag function
+ of the execution model associated with hpid:htid.
+
+--*/
+{
+ assert ( lpv != NULL );
+ return CallEM ( emfGetFlag, hpid, htid, wIndex, lpv );
+}
+
+
+XOSD PASCAL
+OSDWriteFlag (
+ HPID hpid,
+ HTID htid,
+ UINT wIndex,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Write the flag specified by wIndex in the processor flag set
+ for hpid:htid pair.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wIndex - Supplies register index
+
+ lpv - Supplies new value
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that may be generated by the emfSetFlag function
+ of the execution model associated with hpid:htid.
+
+--*/
+{
+ return CallEM ( emfSetFlag, hpid, htid, wIndex, lpv );
+}
+
+
+
+XOSD PASCAL
+OSDProgramFree (
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+ Terminate and unload the program being debugged in process hpid.
+ This does not guarantee termination of child processes.
+
+Arguments:
+
+ hpid - Supplies the process to kill
+
+Return Value:
+
+ xosdNone - Success
+
+ Any error that can be generated by emfProgramFree
+
+--*/
+{
+ assert ( hpid != NULL);
+ return CallEM ( emfProgramFree, hpid, htidNull, 0, NULL );
+}
+
+#if 0
+
+/**** OSDGETCURRENTEM - Get the execution model for hpid:htid ****
+ * *
+ * PURPOSE: *
+ * *
+ * To get the handle for the current execution model associated *
+ * with hpid:htid. *
+ * *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - The process *
+ * htid - The thread *
+ * lphem - A far pointer to the location to stuff the handle to *
+ * the execution model. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success *
+ * xosdInvalidEM - No valid execution model for this hpid:htid *
+ * *
+ * *lphem - A handle to the current execution model for hpid:htid. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Look up the execution model field in the structure reference by *
+ * htid and stuff it into *lphem. *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDGetCurrentEM ( HPID hpid, HTID htid, LPHEM lphem ) {
+ LPPID lppid;
+ HIND hodem = hmemNull;
+ LPEMP lpemp;
+ LPEM lpem;
+
+ Unreferenced( htid );
+
+ assert ( lphem != NULL );
+
+ lppid = LLLock ( hpid );
+ if ( lppid == NULL ) {
+ return xosdInvalidEM;
+ }
+ if ( lppid->lastmodel == CEXM_MDL_native ) {
+ lpemp = LLLock ( lppid->hempNative );
+ *lphem = lpemp->hem;
+ LLUnlock ( lppid->hempNative );
+ }
+ else {
+ while ( hodem = LLNext ( llem, hodem ) ) {
+ lpem = LLLock ( hodem );
+ if ( lpem->model == lppid->lastmodel ) {
+ *lphem = hodem;
+ }
+ LLUnlock ( hodem );
+ }
+ }
+ LLUnlock ( hpid );
+ return xosdNone;
+}
+
+
+/**** OSDNATIVEONLY - Force the use of only the native em for hpid:htid ****
+ * *
+ * PURPOSE: *
+ * *
+ * To allow the debugger to force the use of the native em even where *
+ * there is non-native code (ie pcode) *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - The process *
+ * htid - The thread *
+ * fNat - true to set native only, false to return to normal mode *
+ * of handling multiple em's *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDNativeOnly ( HPID hpid, HTID htid, BOOL fNat ) {
+ HEMP hemp;
+ HEMP hempTmp = hemNull;
+ XOSD xosd = xosdNone;
+ LPEMP lpemp;
+ LPPID lppid;
+
+ assert ( hpid != NULL );
+
+ lppid = LLLock ( hpid );
+
+ if ( lppid->fNative == fNat ) {
+ LLUnlock((HLLE)hpid);
+ return xosd;
+ }
+ else if ( fNat ) {
+
+ // get the native em
+ hemp = lppid->hempNative;
+
+ // tell all of the non-native models to disconnect, cleanup or whatever
+ // they need to do
+ while ( ( hempTmp = LLNext ( lppid->llemp, hempTmp ) ) && hempTmp != hemp ) {
+ lpemp = LLLock ( hempTmp );
+ xosd = (lpemp->emfunc) ( emfDetach, hpid, htid, 0, (LONG) 0 );
+ LLUnlock ( hempTmp );
+ }
+
+ // we then move the native em to the head of the list, forcing it to be called
+ // first, until fNative is reset
+ LLRemove ( lppid->llemp, hemp );
+ LLAddHead ( lppid->llemp, hemp );
+
+ // if current model used to be non-native, send notification
+ if ( lppid->lastmodel != CEXM_MDL_native ) {
+ OSDDoCallBack ( dbcEmChange, hpid, htid, lppid->lastmodel, CEXM_MDL_native, (LONG) 0 );
+ lppid->lastmodel = CEXM_MDL_native;
+ }
+
+ // finally, set our global flag to true
+ lppid->fNative = fNat;
+ }
+ else {
+
+ // put the native em back at the end of the list
+ hemp = lppid->hempNative;
+ LLRemove ( lppid->llemp, hemp );
+ LLAdd ( lppid->llemp, hemp );
+
+ // tell all of the non-native models that they can re-connect
+ xosd = xosdPunt;
+ while ( ( hempTmp = LLNext ( lppid->llemp, hempTmp ) ) && hempTmp != hemp &&
+ xosd == xosdPunt) {
+
+ WORD wModel;
+
+ lpemp = LLLock ( hempTmp );
+ xosd = (lpemp->emfunc) ( emfAttach, hpid, htid, 0, (LONG) (LPV) &wModel );
+ if ( xosd == xosdNone ) {
+
+ // send a dbcEmChange notification
+ OSDDoCallBack ( dbcEmChange, hpid, htid, lppid->lastmodel, wModel, (LONG) 0 );
+ lppid->lastmodel = wModel;
+ }
+ LLUnlock ( hempTmp );
+ }
+ if ( xosd == xosdPunt ) xosd = xosdNone;
+
+ // reset our global flag to false
+ lppid->fNative = fNat;
+ }
+
+ LLUnlock ( hpid );
+ return xosd;
+}
+
+
+/**** OSDUSEEM - Add the execution model to the process' list of ems ****
+ * *
+ * PURPOSE: *
+ * *
+ * To tell osdebug that it should pass commands and callbacks for the *
+ * process hpid through the execution model whose handle is hem. *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - The process *
+ * hem - A handle to the execution model *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success *
+ * xosdOutOfMemory - Not enough memory to create the reference *
+ * to the execution model in the process structure. *
+ * xosdInvalidEM - tried to add a native em when one was already *
+ * present *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDUseEM ( HPID hpid, HEM hem ) {
+ LPPID lppid;
+ HEMP hemp = hemNull;
+ LPEM lpem;
+ LPEMP lpemp;
+ HPID hpidem;
+ LPHPID lphpid;
+
+ assert ( hem != hemNull );
+ assert ( hpid != NULL );
+
+ // Add hem to pid's hem list
+
+ lppid = LLLock ( hpid );
+
+ while ( hemp = LLNext ( lppid->llemp, hemp ) ) {
+ lpemp = LLLock ( hemp );
+ if ( lpemp->hem == hem ) {
+
+ // this is an error, cannot add the same model twice
+ LLUnlock ( hemp );
+ LLUnlock ( hpid );
+ return xosdInvalidEM;
+ }
+ LLUnlock ( hemp );
+ }
+
+ hemp = LLCreate ( lppid->llemp );
+ if ( hemp == hmemNull ) {
+ LLUnlock ( hpid );
+ return xosdOutOfMemory;
+ }
+
+ lpem = LLLock ( hem );
+ if ( lpem->emtype ) {
+ LLAddHead ( lppid->llemp, hemp );
+ }
+ else {
+ // new native em
+ LLAdd ( lppid->llemp, hemp );
+ lppid->hempNative = hemp;
+ }
+ LLUnlock ( hpid );
+
+ // add hpid to hem in llem
+
+ hpidem = LLCreate ( lpem->llhpid );
+ if ( hpidem == hemNull ) {
+ return xosdOutOfMemory;
+ }
+ lphpid = LLLock ( hpidem );
+
+ // puts hpid in node
+ *lphpid = hpid;
+
+ LLUnlock ( hpidem );
+ LLUnlock ( hem );
+ LLAdd ( lpem->llhpid, hpidem );
+
+ return xosdNone;
+}
+
+
+
+/**** OSDDISCARDEM - Remove the execution model from the proc's list ****
+ * *
+ * PURPOSE: *
+ * *
+ * To remove the execution model whose handle is hem from the *
+ * process hpid's list of available execution models. *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process *
+ * hem - A handle to the execution model. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success *
+ * xosdInvalidEM - There is no execution model associated *
+ * with hem. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDDiscardEM ( HPID hpid, HEM hem ) {
+ LPPID lppid;
+ HEM hemdis;
+ LPEM lpem;
+ HEMP hemp = hemNull;
+ HEMP hempdis;
+ LPEMP lpemp;
+ HPID hpiddis;
+ XOSD xosd = xosdNone;
+
+ assert ( hpid != NULL );
+
+ // find the hem in the lppid's list
+ lppid = LLLock ( hpid );
+
+ lpemp = LLLock ( lppid->hempNative );
+ if ( lpemp->hem == hem ) {
+
+ // trying to remove the native em
+ lppid->hempNative = 0;
+ }
+ LLUnlock ( lppid->hempNative );
+
+ while (hemp = LLNext ( lppid->llemp, hemp ) ) {
+ lpemp = LLLock ( hemp );
+ if ( lpemp->hem == hem ) {
+ hemdis = hem;
+ hempdis = hemp;
+ }
+ LLUnlock ( hemp );
+ }
+ if ( ! hemdis ) {
+
+ // no em found, return error
+ xosd = xosdInvalidEM;
+ }
+ else {
+
+ // delete the em from the hpid, then remove hpid from em in llem
+ LLDelete ( lppid->llemp, (HLLE)hempdis );
+
+ lpem = LLLock ( hemdis );
+ if ( hpiddis = LLFind ( lpem->llhpid, 0, &hpid, 0L ) ) {
+ LLDelete ( lpem->llhpid, (HLLE)hpiddis );
+ }
+ else {
+
+ // hpid not found: internal cosistancy error
+ assert ( FALSE );
+ }
+ LLUnlock ( hemdis );
+ }
+ LLUnlock ( hpid );
+ return xosd;
+}
+#endif // 0
+
+
+XOSD PASCAL
+OSDUnassemble (
+ HPID hpid,
+ HTID htid,
+ LPSDI lpsdi
+ )
+/*++
+
+Routine Description:
+
+ Disassemble one machine instruction. The address of the
+ instruction to disassemble is in the SDI structure pointed
+ to by lpsdi.
+
+Arguments:
+
+ hpid - Supplies process to get data from
+
+ htid - Supplies thread
+
+ lpsdi - Supplies and Returns disassembly info
+
+Return Value:
+
+ xosdNone for success, other xosd codes describe the reason
+ for failure.
+
+ When the call succeeds, lpsdi->lsz will point to a static
+ string containing the disassembled instruction. The SDI
+ structure contains ADDR fields which will contain effective
+ addresses computed for the instruction, and int fields which
+ describe the length of each of the parts of the disassembly
+ text, to facilitate formatting the text for display.
+
+ The addr field will be updated to point to the next instruction
+ in the stream.
+
+--*/
+{
+ assert ( lpsdi != NULL );
+ return CallEM ( emfUnassemble, hpid, htid, 0, lpsdi );
+}
+
+
+
+XOSD PASCAL
+OSDAssemble (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr,
+ LSZ lsz
+ )
+/*++
+
+Routine Description:
+
+ Assemble an instruction into the debuggee.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (optional?)
+
+ lpaddr - Supplies address to assemble to
+
+ lsz - Supplies instruction text
+
+Return Value:
+
+ xosdNone for success, other xosd codes describe cause of failure.
+
+--*/
+{
+ XOSD xosd = xosdNone; // [00]
+ // [00]
+ (void)CallEM ( emfSetAddr, hpid, htid, adrCurrent, lpaddr ); // [00]
+ // [00]
+ xosd = CallEM ( emfAssemble, hpid, htid, 0, lsz ); // [00]
+ if (xosd != xosdNone) {
+ return xosd;
+ }
+ // [00]
+ (void)CallEM ( emfGetAddr, hpid, htid, adrCurrent, lpaddr ); // [00]
+ // [00]
+ return xosd; // [00]
+}
+
+#if 0
+
+XOSD PASCAL OSDGetPrevInst (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr
+) {
+ return CallEM ( emfGetPrevInst, hpid, htid, 0, lpaddr );
+}
+
+#endif
+
+XOSD PASCAL
+OSDGetDebugMetric (
+ HPID hpid,
+ HTID htid,
+ MTRC mtrc,
+ LPVOID lpv
+ )
+/*++
+
+Routine Description:
+
+ This is a facility for getting various information about
+ the execution model associated with a process.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (optional for some metrics)
+
+ mtrc - Supplies metric to query, see od.h
+
+ lpv - Returns requested info
+
+Return Value:
+
+ xosdNone for success, other xosd codes describe the cause of failure.
+ lpv must point to a buffer of sufficient size to receive the info.
+
+--*/
+{
+ return CallEM ( emfMetric, hpid, htid, mtrc, lpv );
+}
+
+#if 0
+
+
+/**** OSDGETOBJLENGTH - Get the length of the object containing *lpaddr ****
+ * *
+ * PURPOSE: Get the lenth of a given linear exe object *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * lplBase - A pointer to a long in which to place the base address *
+ * lplLen - A pointer to a long in which to place the length *
+ * *lpaddr - An address within the object in question. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * Any value that can be returned by the Get object length *
+ * of the execution model called. *
+ * *
+ * *
+ * *lplBase - The base address of the object. ( In a segmented *
+ * environment this will always be 0 ). *
+ * *lplLen - The length of the object. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Package the information in a gol ( Get Object Length ) package *
+ * and pass it to the most specific execution model associated *
+ * with the hpid:htid pair. *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDGetObjLength (
+ HPID hpid,
+ HTID htid,
+ LPL lplBase,
+ LPL lplLen,
+ LPADDR lpaddr ) {
+
+ GOL gol;
+
+ gol.lplBase = lplBase;
+ gol.lplLen = lplLen;
+ gol.lpaddr = lpaddr;
+
+ assert ( lpaddr != NULL );
+
+ return CallEM ( emfGetObjLength, hpid, htid, 0, &gol );
+}
+
+#endif // 0
+
+
+XOSD PASCAL
+OSDGetMsgMap (
+ HPID hpid,
+ HTID htid,
+ LPMSGMAP* MsgMap
+ )
+/*++
+
+Routine Description:
+
+ Get a pointer to MSGMAP structure for the EM associated with
+ hpid. This is a structure describing the window messages
+ supported by the EM. Not implemented for OS's without messages.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (not used)
+
+ MsgMap - Returns pointer to MSGMAP structure
+
+Return Value:
+
+ xosdNone for success, other xosd codes describe the cause of
+ failure. If a Win32 EM is associated with hpid, this always succeeds.
+
+--*/
+{
+ return CallEM ( emfGetMsgMap, hpid, htid, 0, MsgMap );
+}
+
+
+XOSD PASCAL
+OSDGetModuleList (
+ HPID hpid,
+ HTID htid,
+ BOOL Flat,
+ LSZ ModuleName,
+ LPMODULE_LIST * ModuleList
+ )
+/*++
+
+Routine Description:
+
+ Get the list of modules loaded in a process, or look up one
+ module. The returned module list contains one entry per
+ segment per module.
+
+ N.B. The function will look up flat or segmented modules,
+ but not both at the same time. This is not neccessarily
+ desirable behaviour.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (not used)
+
+ Flat - Supplies TRUE to get flat modues, FALSE to
+ get segmented ones.
+
+ ModuleName - Supplies optional name of module to look for.
+ If this arg is NULL, all modules will be found.
+
+ ModuleList - Returns list of modules
+
+Return Value:
+
+ xosdNone if successful. Other xosd codes indicate the
+ cause of failure.
+
+--*/
+{
+ MODULE_LIST_REQUEST Request;
+
+ Request.Flat = Flat;
+ Request.Name = ModuleName;
+ Request.List = ModuleList;
+
+ return CallEM ( emfGetModuleList, hpid, htid, 0, &Request );
+}
+
+#if 0
+
+
+/**** OSDGetError - Get the Text of an error msg for a particular hpid/htid
+ *
+ * PURPOSE: Get the OS specific error msg for a pid and tid from the em.
+ * The debugger is responsible for providing a 12 byte buffer
+ * for lszErr, and a 256 byte buffer for lszErrText
+ *
+ * INPUTS:
+ *
+ * hpid - A handle to the process.
+ * htid - A handle to the thread.
+ * lpwErrNum - the error #
+ * lszErr - error # text string (ex. "DMOS001" )
+ * lszErrText - human readable text string (ex. "Tried to load OS2 app under Windows")
+ *
+ * OUTPUTS:
+ *
+ * Return Value -
+ *
+ * xosdNone - if msg was available
+ * xosdSyntax - if no msg available
+ *
+ * IMPLEMENTATION:
+ *
+ ***************************************************************************/
+
+XOSD PASCAL OSDGetError ( HPID hpid,
+ HTID htid,
+ LPW lpwErrNum,
+ LSZ lszErr,
+ LSZ lszErrText ) {
+ GET get;
+
+ get.lpwErrNum = lpwErrNum;
+ get.lszErr = lszErr;
+ get.lszErrText = lszErrText;
+
+ return CallEM ( emfGetError, hpid, htid, 0, &get );
+}
+
+
+/**** OSDGETFRAME - Get the the frame previous to the frame *lpaddr ****
+ * *
+ * PURPOSE: *
+ * *
+ * Put the frame on the stack previous to the frame specified by *
+ * *lpaddr into *lpaddr. *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * *lpaddr - The current frame. *
+ * lpaddr - A pointer to the return frame address. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * Any value that can be returned by the Get Frame Function *
+ * of the execution model called. *
+ * *
+ * *lpaddr - The previous frame address. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Send the Get Frame command to the execution model. *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDGetFrame ( HPID hpid, HTID htid, LPADDR lpaddr ) {
+
+ return CallEM ( emfGetFrame, hpid, htid, 0, lpaddr );
+}
+
+
+/**** OSDGETRETURN - Get the return address for the frame *lpaddrFrame ****
+ * *
+ * PURPOSE: *
+ * *
+ * Put the return addres of the frame into *lpaddrPC. *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * *lpaddrFrame - The current frame. *
+ * *lpaddrPC - The code addres of the current frame. *
+ * lpaddrPC - A pointer to the return address. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * Any value that can be returned by the Get Return Function *
+ * of the execution model called. *
+ * *
+ * *lpaddr - The previous frame address. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Send the current addres of the htid to the frame. Send the *
+ * lpaddrPC into the execution model with the get return command. *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDGetCaller (
+ HPID hpid,
+ HTID htid,
+ FCT fct,
+ LPADDR lpaddrFrame,
+ LPADDR lpaddrPC ) {
+
+ (void)CallEM ( emfSetAddr, hpid, htid, adrCurrent, lpaddrFrame );
+
+ return CallEM ( emfGetCaller, hpid, htid, fct, lpaddrPC );
+}
+
+
+/**** OSDSAVEREGS - Save the register set of the thread ****
+ * *
+ * PURPOSE: *
+ * *
+ * Save the register set of the thread htid in an allocated handle *
+ * that is returned in *lphmem. *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * lphmem - A pointer in which to return the register buffer. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * Any value that can be returned by the Save Register Function *
+ * of the execution model called. *
+ * *
+ * *lphmem - The buffer in which the registers are saved. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Call the execution model to save the registers. *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDSaveRegs ( HPID hpid, HTID htid, LPHIND lphmem ) {
+
+ return CallEM ( emfSaveRegs, hpid, htid, 0, lphmem );
+}
+
+
+/**** OSDRESTORREGS - Restore the registers of the thread from hmem ****
+ * *
+ * PURPOSE: *
+ * *
+ * Restore the register set(s) of the thread htid with the values *
+ * save by OSDSaveRegs in hmem. *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * hmem - A handle to a valid register set for the thread. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * Any value that can be returned by the Restore Register Function*
+ * of the execution model called. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Call the execution model to restore the registers. *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDRestoreRegs ( HPID hpid, HTID htid, HIND hmem ) {
+
+ return CallEM ( emfRestoreRegs, hpid, htid, 0, (LPV) hmem );
+}
+
+
+#ifdef KBDMON
+/**** OSDKBDRECORD - turn keyboard recording on or off ****
+ * *
+ * PURPOSE: *
+ * *
+ * Call the EM to set or clear the keyboard recording flag *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * fOn - new value for the flag *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Call the execution model to set or clear the flag *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDKbdRecord ( HPID hpid, HTID htid, BOOL fOn ) {
+
+ return CallEM ( emfKbdRecord, hpid, htid, fOn, NULL );
+}
+
+
+/**** OSDKBDPLAY - play back keyboard information ****
+ * *
+ * PURPOSE: *
+ * *
+ * Call the EM to play back keyboard string *
+ * *
+ * INPUTS: *
+ * *
+ * hpid - A handle to the process. *
+ * htid - A handle to the thread. *
+ * pszPlay - string to process *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - *
+ * *
+ * xosdNone - Success. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Call the execution model to play the string *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL OSDKbdPlay ( HPID hpid, HTID htid, LSZ lszPlay ) {
+
+ return CallEM ( emfKbdPlay, hpid, htid, 0, (LPV)lszPlay );
+}
+#endif // KBDMON
+
+#endif // 0
+
+XOSD PASCAL
+OSDGetRegDesc (
+ HPID hpid,
+ HTID htid,
+ UINT iReg,
+ RD FAR * lprd
+ )
+/*++
+
+Routine Description:
+
+ Get the internal description of what a specific register looks
+ like. This is provided for general UI interfaces. See the
+ RD structure for more info.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (optional?)
+
+ iReg - Supplies index of register
+
+ lprd - Returns requested info in an RD structure
+
+Return Value:
+
+ xosdNone. Results are undefined if iReg is out of range.
+
+--*/
+{
+ return CallEM ( emfGetRegStruct, hpid, htid, iReg, lprd );
+}
+
+
+XOSD PASCAL
+OSDGetFlagDesc (
+ HPID hpid,
+ HTID htid,
+ UINT iFlag,
+ FD FAR * lpfd
+ )
+/*++
+
+Routine Description:
+
+ Get the internal description of what a specific flag looks
+ like. This is provided for general UI interfaces.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (unused?)
+
+ iReg - Supplies index of requested flag
+
+ lprd - Returns FD structure describing flag
+
+Return Value:
+
+ xosdNone. If iReg is out of range, behaviour is undefined.
+
+--*/
+{
+ return CallEM ( emfGetFlagStruct, hpid, htid, iFlag, lpfd );
+}
+
+
+XOSD PASCAL
+OSDRegisterEmi (
+ HPID hpid,
+ HTID htid,
+ HEMI hemi,
+ LSZ lsz
+ )
+/*++
+
+Routine Description:
+
+ Register an EMI and filename with the EM. This hooks up the
+ symbol table info for a module to the EM's representation of
+ the module in the process.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread (unused)
+
+ hemi - Supplies handle from SH to symbolic info
+
+ lsz - Supplies the name of the module
+
+Return Value:
+
+ xosdNone on success. Current implementation never reports failure.
+
+--*/
+{
+ REMI remi;
+
+ remi.hemi = hemi;
+ remi.lsz = lsz;
+
+ return CallEM ( emfRegisterEmi, hpid, htid, 0, &remi );
+}
+
+
+/***************************************************************************
+ * *
+ * Services provided for execution model and transport layer *
+ * *
+ ***************************************************************************/
+
+XOSD PASCAL LOADDS
+EMCallBackDB (
+ DBC dbc,
+ HPID hpid,
+ HTID htid,
+ DWORD wModel,
+ DWORD cb,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Send callback messages from an execution model to the debugger.
+ The messages get passed through all intervening higher-level
+ execution models.
+
+ If dbc is a dbco value, it creates the appropriate thread or
+ process and returns the hpid or htid in *lpv.
+
+ Otherwise, it calls OSDCallbackToEM to query all of the higher
+ level EM's associated with the process. If none of them
+ handled the callback, it then calls the debugger's callback
+ function via OSDDoCallback.
+
+Arguments:
+
+ dbc - Supplies the callback message
+
+ hpid - Supplies handle to the process
+
+ htid - Supplies handle to the thread
+
+ wModel - Supplies index of EM initiating the callback
+
+ cb - Supplies the number of bytes pointed to by lpv
+
+ lpv - Supplies data associated with the callback,
+ Returns data for dbco callbacks.
+
+Return Value:
+
+ xosdNone - Success
+
+ Any value that can be returned by the debugger or higher
+ level execution models.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+
+ //
+ // Several threads can execute this, so we protect it with a critical
+ // section.
+ //
+ EnterCriticalSection( &CallbackCriticalSection );
+
+ switch ( dbc ) {
+
+ case dbcoCreateThread:
+
+ xosd = CreateThd ( hpid, htid, &htid );
+ *( (LPHTID) lpv) = htid;
+ goto Return;
+ //return xosd;
+
+ case dbcoNewProc: {
+ LPPID lppid = LLLock ( (HLLE)hpid );
+ HPID hpidT = hpid;
+ LPEMP lpemp = LLLock ( (HLLE)(lppid->hempNative) );
+
+ xosd = CreateProc (
+ lppid->lpfnsvcCC,
+ lpemp->hem,
+ lppid->htl,
+ &hpid
+ );
+
+ *( (LPHPID) lpv) = hpid;
+ LLUnlock ( (HLLE)(lppid->hempNative) );
+ LLUnlock ( (HLLE)hpidT );
+ }
+ goto Return;
+ //return xosd;
+ }
+
+ // hit all of the EMs with the DoCallback, a la CallEM,
+ // hitting the debugger last
+ xosd = OSDDoCallBackToEM ( dbc, hpid, htid, cb, (LONG) lpv );
+
+ // if xosd is xosdPunt then all non-native EMs punted on the notification
+ if ( xosd == xosdPunt ) {
+ xosd = OSDDoCallBack ( dbc, hpid, htid, wModel, cb, (LONG) lpv );
+ }
+
+Return:
+
+ LeaveCriticalSection( &CallbackCriticalSection );
+
+ return xosd;
+}
+
+
+XOSD PASCAL LOADDS
+EMCallBackTL (
+ TLF wCmd,
+ HPID hpid,
+ DWORD cb,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Send messages from the execution model (native) to the transport layer.
+
+Arguments:
+
+ wCmd - Supplies the message
+ hpid - Supplies process
+ cb - Supplies the size of the buffer at lpv, in bytes
+ lpv - Supplies or Returns data specific to the command
+
+Return Value:
+
+ xosdNone for success, TL may return other xosd codes to
+ describe failure.
+
+--*/
+{
+ return CallTL ( wCmd, hpid, cb, lpv );
+}
+
+
+
+XOSD PASCAL LOADDS
+EMCallBackNT (
+ EMF emf,
+ HPID hpid,
+ HTID htid,
+ DWORD cb,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Provides native em services to higher level EMs. Sends messages
+ from the execution model (non-native) to the native execution model
+ for the process hpid.
+
+Arguments:
+
+ emf - Supplies the execution model function number
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ cb - Supplies size of buffer at lpv in bytes
+
+ lpv - Supplies and Returns data for EM service
+
+Return Value:
+
+ xosdNone - Success
+
+ xosdInvalidPID - hpid is not a handle to a process.
+
+ Any value that can be returned by the native execution model.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ LPPID lppid;
+ HEMP hemp;
+ LPEMP lpemp;
+
+ lppid = LLLock ( (HLLE)hpid );
+ if ( lppid == NULL ) {
+ return xosdInvalidPID;
+ }
+
+ hemp = lppid->hempNative;
+ LLUnlock ( (HLLE)hpid );
+
+ lpemp = LLLock ( (HLLE)hemp );
+ xosd = (lpemp->emfunc) ( emf, hpid, htid, cb, (LONG) lpv );
+ LLUnlock ( (HLLE)hemp );
+
+ return xosd;
+}
+
+
+XOSD PASCAL LOADDS
+EMCallBackEM (
+ EMF emf,
+ HPID hpid,
+ HTID htid,
+ DWORD wModel,
+ DWORD cb,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Provides EM services to other EMs. Sends messages from one
+ non-native EM to the next EM in the chain for the process hpid.
+
+Arguments:
+
+ emf - Supplies EM function number
+
+ hpid - Supplies handle to the process
+
+ htid - Supplies handle to the thread
+
+ wModel - Supplies EM # of calling EM
+
+ cb - Supplies size in bytes of buffer at lpv.
+
+ lpv - Supplies and Returns data for EM service
+
+Return Value:
+
+ xosd code returned by the EM that handles the service request.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ LPPID lppid;
+ HEMP hemp = 0;
+ HEMP hempnext = 0;
+ LPEMP lpemp;
+
+ assert ( hpid != NULL );
+
+ //native ems can never make this callback!
+ assert ( wModel != CEXM_MDL_native );
+
+ lppid = LLLock ( (HLLE)hpid );
+
+ if ( lppid == NULL ) {
+ return xosdInvalidPID;
+ }
+
+ while ( hemp = LLNext ( (HLLI)(lppid->llemp), (HLLE)hemp ) ) {
+ lpemp = LLLock ( (HLLE)hemp );
+ if ( lpemp->model == wModel ) {
+ hempnext = LLNext ( (HLLI)(lppid->llemp), (HLLE)hemp );
+ break;
+ }
+ LLUnlock ( (HLLE)hemp );
+ }
+
+ assert ( hempnext != 0 );
+
+ lpemp = LLLock ( (HLLE)hempnext );
+ xosd = (lpemp->emfunc) ( emf, hpid, htid, cb, (LONG) lpv );
+ LLUnlock ( (HLLE)hempnext );
+
+ LLUnlock ( (HLLE)hpid );
+
+ return xosd;
+}
+
+
+XOSD PASCAL LOADDS
+TLCallBack (
+ HPID hpid,
+ UINT cb,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Call the native execution model for the process hpid with the
+ package sent from the transport layer. This is how the DM
+ sends things to its native EM.
+
+Arguments:
+
+ hpid - Supplies handle to the process
+
+ cb - Supplies size in bytes of the packet
+
+ lpv - Supplies the packet
+
+Return Value:
+
+ xosdNone - Success
+
+ Any return value that can be generated by a native execution model.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ LPEMP lpemp;
+ LPPID lppid;
+ EMFUNC emfunc;
+
+ assert ( hpid != NULL );
+
+//NOTENOTE a-kentf this probably doesn't have to Unlock before calling
+ lppid = LLLock ( (HLLE)hpid );
+ lpemp = LLLock ( (HLLE)(lppid->hempNative) );
+ emfunc = lpemp->emfunc;
+ LLUnlock ( (HLLE)(lppid->hempNative) );
+ LLUnlock ( (HLLE)hpid );
+
+ xosd = (*emfunc)( emfDebugPacket, hpid, htidNull, cb, (LONG) lpv );
+
+ return xosd;
+}
+
+
+/***************************************************************************
+ * *
+ * Internal Support functions *
+ * *
+ ***************************************************************************/
+
+
+
+/**** CallEM - Call the execution model for hpid:htid ****
+ * *
+ * PURPOSE: *
+ * *
+ * This function multiplexes on the hpid and htid values to call *
+ * the most specific execution model possible. *
+ * *
+ * INPUTS: *
+ * *
+ * emf, wValue, lValue, lpxosd: These are all just passed through *
+ * to the actual execution model service function. *
+ * *
+ * hpid - This is the process that the execution model service *
+ * function is to handle. If it is null, the first execution *
+ * model that was registered with osdebug is called. *
+ * Hpid must not be invalid. *
+ * *
+ * htid - This is the thread that the execution model service *
+ * function is to handle. If it is null, the native execution *
+ * model for the pid is called. Htid must not be invalid. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - This will return whatever the execution model *
+ * service function that it calls returns. *
+ * *
+ * *lpxosd - The errors returned here are those defined by the *
+ * execution model service function that was called. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Find the most specific em available. This is the current em *
+ * for the pid:tid if both pid & tid are non-Null, the native *
+ * execution model for the pid if the tid is null but the pid is *
+ * non-Null, or the first em installed if both pid & tid are null. *
+ * *
+ * *
+ ***************************************************************************/
+
+
+XOSD
+CallEM(
+ EMF emf,
+ HPID hpid,
+ HTID htid,
+ DWORD wValue,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+
+ XOSD xosd = xosdNone;
+ HEMP hemp;
+ LPPID lppid;
+ LPEMP lpemp;
+ HLLI llemx;
+
+ if ( hpid == NULL ) {
+
+ // get oldest native EM.
+ if (llem != NULL) {
+ hemp = (HEMP)LLLast ( llemx = llem );
+ } else {
+ return xosdUnknown;
+ }
+ if (hemp == NULL) {
+ return xosdUnknown;
+ }
+ } else {
+
+ lppid = LLLock ( (HLLE)hpid );
+ assert ( lppid != NULL );
+ hemp = (HEMP)LLNext ( (llemx = lppid->llemp), NULL );
+ LLUnlock ( (HLLE)hpid );
+
+ }
+
+ lpemp = LLLock ( (HLLE)hemp );
+ if (lpemp->emfunc != NULL) {
+ xosd = (lpemp->emfunc)( emf, hpid, htid, wValue, (LONG) lpv );
+ } else {
+ xosd = xosdUnknown;
+ }
+ LLUnlock ( (HLLE)hemp );
+
+ if (xosd == xosdPunt) {
+
+ hemp = (HEMP)LLNext ( llemx, (HLLE)hemp );
+
+ do {
+ lpemp = LLLock ( (HLLE)hemp );
+ xosd = (lpemp->emfunc) ( emf, hpid, htid, wValue, (LONG) lpv );
+ LLUnlock ( (HLLE)hemp );
+ } while (xosd == xosdPunt &&
+ (hemp = (HEMP)LLNext ( llemx, (HLLE)hemp )) );
+
+ if (xosd == xosdPunt) {
+ xosd = xosdUnsupported;
+ }
+ }
+
+ return xosd;
+}
+
+
+/**** CallTL - Call the transport layer for hpid ****
+ * *
+ * PURPOSE: *
+ * *
+ * *
+ * INPUTS: *
+ * *
+ * tlf, htid, wValue, lpv - These are all just passed *
+ * through to the actual transport layer service function. *
+ * *
+ * hpid - This is the process that the transport layer service *
+ * function is to handle. If it is null, the first transport *
+ * layer that was registered with osdebug is called. *
+ * Hpid must not be invalid. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Return Value - This will return whatever the transport layer *
+ * service function that it calls returns. *
+ * *
+ * *lpxosd - The errors returned here are those defined by the *
+ * transport layer service function that was called. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Find the most specific tl available. This is the transport *
+ * layer associated with the pid if the pid is non-Null, otherwise *
+ * it is the first transport layer registered with osdebug. *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD
+CallTL (
+ TLF tlf,
+ HPID hpid,
+ DWORD wValue,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Call the transport layer associated with hpid, and send it a
+ message and packet.
+
+Arguments:
+
+ tlf - Supplies transport layer function number.
+
+ hpid - Supplies process.
+
+ wValue - Supplies function dependent data.
+
+ lpv - Supplies and Returns data depending on function.
+
+Return Value:
+
+ xosd status code, as returned by the TL.
+
+--*/
+{
+ XOSD xosd = xosdNone;
+ HTL htl;
+ LPTL lptl;
+
+ if ( hpid == NULL ) {
+ htl = LLNext ( lltl, htlNull );
+ }
+ else {
+ LPPID lppid = LLLock ( (HLLE)hpid );
+ htl = lppid->htl;
+ LLUnlock ( (HLLE)hpid );
+ }
+
+ lptl = LLLock ( (HLLE)htl );
+ xosd = lptl->tlfunc ( tlf, hpid, wValue, (LONG) lpv );
+ LLUnlock ( (HLLE)htl );
+
+ return xosd;
+}
+
+
+
+/**** OSDDOCALLBACK - Call the debug client with a notification message ****
+ * *
+ * PURPOSE: *
+ * *
+ * INPUTS: *
+ * *
+ * OUTPUTS: *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+XOSD
+OSDDoCallBack (
+ UINT wCommand,
+ HPID hpid,
+ HTID htid,
+ UINT wModel,
+ UINT wValue,
+ LONG lValue
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+
+ XOSD xosd = xosdNone;
+ LPPID lppid;
+
+ assert ( hpid != NULL );
+
+ lppid = LLLock ( (HLLE)hpid );
+ switch ( wCommand ) {
+ case dbcBpt:
+ case dbcStep:
+ case dbcCheckBpt:
+ case dbcProcTerm:
+ case dbcThreadTerm:
+ case dbcException:
+ case dbcWatchPoint:
+ case dbcEntryPoint:
+
+ if ( lppid->lastmodel != wModel ) {
+
+ // model has changed, issue dbcEmChange notification
+ xosd = lppid->lpfnsvcCC ( dbcEmChange, hpid, htid, wModel, (LONG) 0 );
+ lppid->lastmodel = wModel;
+ }
+ break;
+
+ default:
+
+ // same model as before, do nothing
+ break;
+ }
+
+ xosd = lppid->lpfnsvcCC (( USHORT ) wCommand, hpid, htid, wValue, lValue );
+
+ LLUnlock ( (HLLE)hpid );
+
+ switch ( wCommand ) {
+ case dbcThreadDestroy:
+ // The shell will call OSDDestroyTID(), instead of
+ // us doing it here.
+ break;
+
+ case dbcProcTerm:
+ // same here; the shell calls OSDDestroyPID() when it
+ // is finished using the structures.
+ break;
+ }
+
+ return xosd;
+}
+
+
+XOSD
+OSDDoCallBackToEM (
+ EMF wCommand,
+ HPID hpid,
+ HTID htid,
+ UINT wValue,
+ LONG lValue
+ )
+/*++
+
+Routine Description:
+
+ Call all of the non-native EMs with a notification message.
+
+Arguments:
+
+ wCommand - Supplies the message
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ wValue - Supplies message dependent data
+
+ lValue - Supplies message dependent data
+
+Return Value:
+
+ An xosd status code. xosdPunt means it was not handled by any EM.
+ If an EM handles it, xosdNone or a failure status will be returned.
+
+--*/
+{
+
+ XOSD xosd = xosdPunt;
+ HEM hemp;
+ LPEMP lpemp;
+ LPPID lppid;
+
+ assert ( hpid != NULL );
+
+ // get handle to the native EM
+ lppid = LLLock ( (HLLE)hpid );
+ if ( lppid->fNative ) {
+ LLUnlock((HLLE) hpid );
+ // native only mode, return
+ return xosd;
+ }
+ LLUnlock ( (HLLE)hpid );
+
+ // M00BUG - this is not correct. we should be hitting the ems
+ // in the reverse order that they are in the list.
+ // This will bite us when we move to multiple nms
+
+ hemp = hemNull;
+ while ( xosd == xosdPunt ) {
+ if ( ! ( hemp = LLNext ( (HLLI)(lppid->llemp), (HLLE)hemp ) ) ) {
+ return xosd;
+ }
+
+ lpemp = LLLock ( (HLLE)hemp );
+
+ if ( lpemp->emtype == emNative ) {
+ LLUnlock ( (HLLE)hemp );
+ return xosd;
+ }
+
+ xosd = (lpemp->emfunc) ( wCommand, hpid, htid, wValue, lValue );
+ LLUnlock ( (HLLE)hemp );
+ }
+ return xosd;
+}
+
+
+/**** CREATEPROC - Create a process data struct and add to proc list ****
+ * *
+ * PURPOSE: *
+ * *
+ * INPUTS: *
+ * *
+ * OUTPUTS: *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+
+XOSD
+CreateProc (
+ LPFNSVC lpfnsvc,
+ HEM hem,
+ HTL htl,
+ LPHPID lphpid
+ )
+{
+
+ XOSD xosd = xosdNone;
+ HPID hpid;
+ LPPID lppid;
+ HEMP hemp;
+ LPEMP lpemp;
+ HEM hodem = hmemNull;
+ LPEM lpem;
+ HPID hpidem = hmemNull;
+ LPHPID lphpidt;
+
+ hpid = (HPID)LLCreate ((HLLI) llpid );
+ if ( hpid == NULL ) {
+ return xosdOutOfMemory;
+ }
+
+ LLAdd ( (HLLI)llpid, (HLLE)hpid );
+
+ lppid = LLLock ( (HLLE)hpid );
+ lppid->htl = htl;
+ lppid->fNative = FALSE;
+ lppid->lastmodel = CEXM_MDL_native;
+ lppid->lpfnsvcCC = lpfnsvc;
+
+ lppid->lltid = LLInit ( sizeof ( TIDS ), llfNull, NULL, NULL );
+ lppid->llemp = LLInit ( sizeof ( EMPS ), llfNull, EMPKill, NULL );
+
+ if ( lppid->llemp == 0 || lppid->lltid == 0 ) {
+ xosd == xosdOutOfMemory;
+ }
+
+ // create llem in lppid
+
+ while ( hodem = LLNext ( (HLLI)llem, (HLLE)hodem ) ) {
+ hemp = LLCreate ( (HLLI)(lppid->llemp) );
+ if ( hemp == hemNull ) {
+ return xosdOutOfMemory;
+ }
+ lpem = LLLock ( (HLLE)hodem );
+ lpemp = LLLock ( (HLLE)hemp );
+
+ // copy relevant info to hpid's emp
+ lpemp->hem = hodem;
+ lpemp->emfunc = lpem->emfunc;
+ lpemp->emtype = lpem->emtype;
+ if ( ! lpem->emtype && hodem == hem ) {
+ lppid->hempNative = hemp;
+ }
+ lpemp->model = lpem->model;
+
+ LLUnlock ( (HLLE)hemp );
+ LLUnlock ( (HLLE)hodem );
+ LLAdd ( (HLLI)(lppid->llemp), (HLLE)hemp );
+ }
+
+ // add the hpid to all em's list of hpids
+
+ hemp = hodem = hmemNull;
+ while ( hodem = LLNext ( (HLLI)llem, (HLLE)hodem ) ) {
+
+ lpem = LLLock ( (HLLE)hodem );
+ hpidem = (HPID)LLCreate ( (HLLI)(lpem->llhpid) );
+ if ( hpidem == hemNull ) {
+ LLUnlock((HLLE)hpid);
+ return xosdOutOfMemory;
+ }
+ lphpidt = LLLock ( (HLLE)hpidem );
+
+ // puts hpid in node
+ *lphpidt = hpid;
+
+ LLUnlock ( (HLLE)hpidem );
+ LLUnlock ( (HLLE)hodem );
+ LLAdd ( (HLLI)(lpem->llhpid), (HLLE)hpidem );
+ }
+
+ // clean up
+
+ LLUnlock ( (HLLE)hpid );
+
+ if (xosd == xosdNone) {
+ *lphpid = hpid;
+ }
+
+ return xosd;
+}
+
+
+/**** CREATETHD - Create a thread data struct & add to process ****
+ * *
+ * PURPOSE: *
+ * *
+ * INPUTS: *
+ * *
+ * OUTPUTS: *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * *
+ ***************************************************************************/
+
+
+XOSD
+CreateThd (
+ HPID hpid,
+ HTID htid,
+ LPHTID lphtid
+ )
+{
+ HTID htidT;
+ LPTID lptidT;
+ LPPID lppid;
+
+ Unreferenced( htid );
+
+ lppid = LLLock ( (HLLE)hpid );
+
+ htidT = (HTID)LLCreate ( (HLLI)(lppid->lltid) );
+ if ( htidT == htidNull ) {
+ LLUnlock ( (HLLE)hpid );
+ return xosdOutOfMemory;
+ }
+
+ LLAdd((HLLI)(lppid->lltid), (HLLE)htidT);
+
+ lptidT = LLLock ( (HLLE)htidT );
+ lptidT->hpid = hpid;
+
+ LLUnlock ( (HLLE)htidT );
+ LLUnlock ( (HLLE)hpid );
+
+ *lphtid = htidT;
+ return xosdNone;
+}
+
+/****************************************************************************
+ * *
+ * Kill and compare functions for the various lists used by osdebug *
+ * *
+ ****************************************************************************/
+
+
+void PASCAL LOADDS
+ODPDKill (
+ LPV lpv
+ )
+{
+ LPPID lppid = (LPPID) lpv;
+
+ LLDestroy ( lppid->llemp );
+ LLDestroy ( lppid->lltid );
+}
+
+
+void PASCAL LOADDS
+EMKill (
+ LPV lpv
+ )
+{
+ LPEM lpem = (LPEM) lpv;
+
+ LLDestroy ( lpem->llhpid );
+}
+
+
+void PASCAL LOADDS
+EMPKill (
+ LPV lpv
+ )
+{
+ Unreferenced( lpv );
+ return;
+}
+
+void PASCAL LOADDS
+TLKill (
+ LPV lpv
+ )
+{
+ LPTL lptl = (LPTL) lpv;
+ LLDestroy ( lptl->llpid );
+}
+
+int FAR PASCAL LOADDS
+EMHpidCmp (
+ LPV lpv1,
+ LPV lpv2,
+ LONG lParam
+ )
+{
+ Unreferenced( lParam );
+
+ if ( *( (LPHPID) lpv1) == *( (LPHPID) lpv2 ) ) {
+ return fCmpEQ;
+ } else {
+ return fCmpLT;
+ }
+}
+
+
+/************************************************************************/
+
+/* Exception Handling */
+
+/************************************************************************/
+
+
+XOSD PASCAL
+OSDGetExceptionState(
+ HPID hpid,
+ HTID htid,
+ LPEXCEPTION_DESCRIPTION lpExd,
+ EXCEPTION_CONTROL exf
+ )
+/*++
+
+Routine Description:
+
+ Given an address of an EXCEPTION_DESC filled in with the exception
+ code look up the code in the table and return a pointer to the
+ real exception info structure for that exception.
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lpExd - A pointer to an exception structure to be filled in.
+ The dwExceptionCode member of this structure must be set
+ in order to use the exfSpecified or exfNext parmeter
+
+ exf - one of:
+ exfFirst
+ exfNext
+ exfSpecified
+
+Return Value:
+
+ xosdNone - Success
+
+--*/
+{
+ if (hpid || !htid) {
+ return CallEM ( emfGetExceptionState, hpid, htid, exf, lpExd );
+ } else {
+ return (*(EMFUNC)htid)(emfGetExceptionState, NULL, NULL, exf, lpExd);
+ }
+}
+
+
+XOSD PASCAL
+OSDSetExceptionState (
+ HPID hpid,
+ HTID htid,
+ LPEXCEPTION_DESCRIPTION lpExd
+ )
+/*++
+
+Routine Description:
+
+ Set the exception state for the given hpid/htid.
+
+ First implementation of this API should ignore the HTID parameter
+ as it is intended that it will only be able to Get/Set thread
+ exception states on a per process basis rather than on a per thread
+ basis. Should we choose in the future that there is a need to
+ Get/Set exception states on a per thread basis we can make use of
+ the HTID parameter at that time. At that time an htid of NULL would
+ indicate all threads.
+
+Parameters:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lpExd - Supplies an exception structure to be Set. Should this
+ exception not be found in the current list of exceptions for
+ the given process/thread it will be added.
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ return CallEM( emfSetExceptionState, hpid, htid, 0, lpExd );
+}
+
+
+
+
+XOSD PASCAL
+OSDSetupExecute(
+ HPID hpid,
+ HTID htid,
+ LPHDEP lphdep
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to set up a thread for doing a function
+ evaluation. This is passed on the the EM for processing.
+
+Arguments:
+
+ hpid - Supplies the handle to the process
+
+ htid - Supplies the handle to the thread
+
+ lphdep - Supplies a pointer to save the SAVEINFO handle at
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ XOSD xosd;
+ xosd = CallEM( emfSetupExecute, hpid, htid, 0, lphdep);
+
+ return xosd;
+} /* OSDSetupExecute() */
+
+
+XOSD PASCAL
+OSDStartExecute(
+ HPID hpid,
+ HDEP hdep,
+ LPADDR lpaddr,
+ BOOL fIgnoreEvents,
+ BOOL fFar
+ )
+
+/*++
+
+Routine Description:
+
+ Execute function evaluation.
+
+Arguments:
+
+ hpid - Supplies the handle to the process
+
+ hdep - Supplies the exeute object handle
+
+ lpaddr - Supplies the address to start evaluation at
+
+ fIgnoreEvents - Supplies TRUE if sub-events are to be ignored
+
+ fFar - Supplies TRUE if this is an _far function
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ EXECUTE_STRUCT es;
+
+ es.addr = *lpaddr;
+ es.fIgnoreEvents = fIgnoreEvents;
+ es.fFar = fFar;
+
+ return CallEM( emfStartExecute, hpid, 0, (DWORD)hdep, &es);
+} /* OSDStartExecute() */
+
+
+XOSD PASCAL
+OSDCleanUpExecute (
+ HPID hpid,
+ HDEP hdep
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to clean up a current pending function
+ evaluation.
+
+Arguments:
+
+ hdep Supplies the handle to the execute object
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ return CallEM( emfCleanUpExecute, hpid, htidNull, (DWORD)hdep, 0);
+} /* OSDCleanUpExecute() */
+
+
+
+XOSD PASCAL
+OSDLoadDllAck(
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+ This routine is called in response to a modLoad message to inform
+ the DM that processing may now continue.
+
+Arguments:
+
+ hpid - Supplies the handle to the process for the modLoad message
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ return CallEM( emfLoadDllAck, hpid, 0, 0, 0);
+} /* OSDDllLoadAck */
+
+
+
+XOSD PASCAL
+OSDUnLoadDllAck(
+ HPID hpid,
+ HEXE emi,
+ BOOL fTellDM
+ )
+/*++
+
+Routine Description:
+
+ This routine is called in response to a modLoad message to inform
+ the DM that processing may now continue.
+
+Arguments:
+
+ hpid - Supplies the handle to the process for the modLoad message
+
+ emi - Supplies emi of module being unloaded.
+
+Return Value:
+
+ xosd error code
+
+--*/
+
+{
+ return CallEM( emfUnLoadDllAck, hpid, 0, fTellDM, (LPV)emi);
+}
+
+
+XOSD
+OSDDebugActive(
+ HPID hpid,
+ DWORD dwProcessId,
+ HANDLE hEventGo,
+ LPDWORD lpdwStatus
+ )
+/*++
+
+Routine Description:
+
+ Tell the EM to debug a process which is already running and not
+ being debugged. If this succeeds, the debugger will be notified
+ of a new process, very similar to the creation of a child of
+ a process already being debugged.
+
+Arguments:
+
+ hpid - Supplies process to bind to the EM. If no process is
+ already being debugged, this will be the "root" process,
+ and will not yet have a real debuggee attached to it.
+ Otherwise, this may be any process which is bound to the
+ right native EM.
+
+ dwProcessId - Supplies the OS supplied process ID for the process to debug.
+
+ hEventGo - Supplies an optional event handle which the DM will signal
+ when the DM is ready to catch an exception in the process.
+ This is used when attaching to a crashed process in Win32.
+
+ lpdwStatus - Returns the error status from the DebugActiveProcess API.
+
+Return Value:
+
+ xosdNone if the DebugActiveProcess succeeds. If it fails, the value
+ returned in the DWORD at lpdwStatus may be examined to learn the
+ cause of the failure.
+
+--*/
+{
+ DBG_ACTIVE_STRUCT dba;
+ XOSD xosd;
+ dba.dwProcessId = dwProcessId;
+ dba.hEventGo = hEventGo;
+ xosd = CallEM( emfDebugActive, hpid, htidNull, 0, &dba);
+ *lpdwStatus = dba.dwStatus;
+ return xosd;
+}
+
+
+XOSD
+OSDStackWalkSetup(
+ HPID hpid,
+ HTID htid,
+ BOOL fInProlog,
+ LPSTKSTR lpstkstr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to setup the stkstr structure which is used
+ to do a stack walk operation. After this function has been called
+ the current Program Counter and Frame Pointer will be set in the
+ stkstr as well as any flags needed for it.
+
+Arguments:
+
+ hpid - Supplies the process handle to use
+
+ htid - Supplies the thread handle to use
+
+ fInProlog- Supplies TRUE if current address is in prolog
+
+ lpstkstr - Supplies a pointer to the Stack Walk Structure to fill-in
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ return CallEM( emfStackWalkSetup, hpid, htid, fInProlog, lpstkstr);
+
+} /* OSDStackWalkSetup() */
+
+
+XOSD
+OSDStackWalkNext(
+ HPID hpid,
+ HTID htid,
+ LPSTKSTR lpstkstr
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hpid - Supplies the process handle to use
+
+ htid - Supplies the thread handle to use
+
+ lpstkstr - Supplies a pointer to the Stack Walk Structure to fill-in
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ return CallEM( emfStackWalkNext, hpid, htid, 0, lpstkstr);
+} /* OSDStackWalkNext() */
+
+
+XOSD
+OSDStackWalkCleanup(
+ HPID hpid,
+ HTID htid,
+ LPSTKSTR lpstkstr
+ )
+
+/*++
+
+Routine Description:
+
+ Tell the EM to clean up data structures used for walking stack
+
+Arguments:
+
+ hpid - Supplies the process handle to use
+
+ htid - Supplies the thread handle to use
+
+ lpstkstr - Supplies a pointer to the Stack Walk Structure
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ return CallEM( emfStackWalkCleanup, hpid, htid, 0, lpstkstr);
+} /* OSDStackWalkCleanup() */
+
+
+XOSD
+OSDSetFrame(
+ HPID hpid,
+ HTID htid,
+ PFRAME pframe
+ )
+/*++
+
+Routine Description:
+
+ Get a structure describing the current stack frame for a thread.
+
+Arguments:
+
+ hpid - Supplies the process handle to use
+
+ htid - Supplies the thread handle to use
+
+ pframe - Returns FRAME structure
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ return CallEM( emfSetFrame, hpid, htid, 0, pframe );
+} /* OSDSetFrame() */
+
+
+XOSD
+OSDSetPath(
+ HPID hpid,
+ BOOL Set,
+ LSZ Path
+ )
+/*++
+
+Routine Description:
+
+ Sets the search path in the DM
+
+Arguments:
+
+ hpid - Supplies process to bind EM
+
+ Set - Supplies TRUE to set new path, FALSE to turn
+ off path searching.
+
+ Path - Supplies search path string
+
+Return Value:
+
+ XOSD error code
+
+--*/
+{
+ return CallEM( emfSetPath, hpid, 0, Set, Path );
+}
+
+
+/************************************************************************/
+
+/* Breakpoints */
+
+/************************************************************************/
+
+
+XOSD PASCAL
+OSDBreakpoint (
+ HPID hpid,
+ LPBPS lpbps
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ return CallEM ( emfBreakPoint, hpid, NULL, SizeofBPS(lpbps), lpbps);
+}
+
+
+XOSD
+OSDGetPrompt(
+ HPID hpid,
+ LPPROMPTMSG lppm
+ )
+/*++
+
+Routine Description:
+
+ Get a prompt string for command window. This provides a way
+ for the EM/DM pair to identify itself to the user.
+
+Arguments:
+
+ hpid - Supplies process
+
+ lppm - Returns PROMPTMSG struct
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ return CallEM( emfGetPrompt, hpid, 0, 0, lppm );
+}
+
+
+XOSD
+OSDSendReply(
+ HPID hpid,
+ UINT cb,
+ LPVOID lpv
+ )
+{
+ return CallEM( emfMiscReply, hpid, 0, cb, lpv );
+}
+
+
+XOSD PASCAL
+OSDGetMemInfo(
+ HPID hpid,
+ LPMEMINFO lpMemInfo
+ )
+{
+ return CallEM( emfGetMemInfo, hpid, 0, sizeof(MEMINFO), lpMemInfo );
+}
+
+
+
+
+XOSD
+OSDGetFunctionInfo(
+ HPID hpid,
+ PADDR Addr,
+ PFUNCTION_INFO FunctionInfo
+ )
+{
+ return CallEM( emfGetFunctionInfo, hpid, 0, (DWORD)Addr, FunctionInfo );
+}
+XOSD PASCAL
+OSDGetProcessStatus (
+ HPID hpid,
+ LPPST lppst
+ )
+/*++
+
+Routine Description:
+
+ Returns a structure describing the process status for the given hpid.
+
+ uses emfProcessStatus
+
+Arguments:
+
+ hpid - Supplies process
+
+ lppst - Returns process state structure
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ return CallEM( emfProcessStatus, hpid, NULL, 0, lppst );
+}
+
+XOSD PASCAL
+OSDGetThreadStatus (
+ HPID hpid,
+ HTID htid,
+ LPTST lptst
+ )
+/*++
+
+Routine Description:
+
+ Returns a structure describing the thread status for the given htid.
+
+ uses emfThreadStatus
+
+Arguments:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lptst - Returns thread state structure
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ return CallEM( emfThreadStatus, hpid, htid, 0, lptst );
+}
+
+/************************************************************************/
+
+/* Target execution */
+
+/************************************************************************/
+
+
+XOSD PASCAL
+OSDGo (
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpExop
+ )
+/*++
+
+Routine Description:
+
+ Run the target program for the process hpid [thread htid].
+
+ uses emfGo.
+
+ Note: This is an asynchronous API.
+
+Parameters:
+
+ hpid - Supplies process to run
+
+ htid - Supplies the thread to run
+
+ lpExop - Supplies options to control execution
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ return CallEM( emfGo, hpid, htid, 0, lpExop );
+}
+
+
+
+
+XOSD PASCAL
+OSDSingleStep (
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpExop
+ )
+/*++
+
+Routine Description:
+
+ Execute a single processor instruction of the process hpid
+ and thread htid.
+
+ uses emfSingleStep
+
+ Note: This is an asynchronous API.
+
+Parameters:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lpExop - Supplies options to control execution
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ return CallEM( emfSingleStep, hpid, htid, 0, lpExop );
+}
+
+
+XOSD PASCAL
+OSDRangeStep (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddrMin,
+ LPADDR lpaddrMax,
+ LPEXOP lpExop
+ )
+/*++
+
+Routine Description:
+
+ Execute single processor instructions for hpid/htid while *lpaddrMin
+ <= adrPC <= *lpaddrMax.
+
+ Both of the boundary addresses are inclusive of the range.
+
+ uses emfRangeStep.
+
+ Note: This is an asynchronous API.
+
+Parameters:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lpaddrMin - Supplies the lower boundary address
+
+ lpaddrMax - Supplies the upper boundary address
+
+ lpExop - Supplies options to control execution
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ RSS rss;
+ rss.lpaddrMin = lpaddrMin;
+ rss.lpaddrMax = lpaddrMax;
+ rss.lpExop = lpExop;
+ return CallEM( emfRangeStep, hpid, htid, 0 , &rss );
+}
+
+
+XOSD PASCAL
+OSDReturnStep (
+ HPID hpid,
+ HTID htid,
+ LPEXOP lpExop
+ )
+/*++
+
+Routine Description:
+
+ Execute the thread until it has returned to the caller.
+
+ uses emfReturnStep
+
+ Note: This is an asynchronous API.
+
+Parameters:
+
+ hpid - Supplies process
+
+ htid - Supplies thread
+
+ lpExop - Supplies options to control execution
+
+Return Value:
+
+ xosdNone: Success
+
+--*/
+{
+ return CallEM( emfReturnStep, hpid, htid, 0, lpExop );
+}
+
+
+XOSD PASCAL
+OSDAsyncStop (
+ HPID hpid,
+ DWORD fSetFocus
+)
+/*++
+
+Description:
+
+ Halt the execution of the target process hpid.
+
+ uses emfStop.
+
+ Note: This is an asynchronous API.
+
+Parameters:
+
+ hpid - Supplies process
+
+ fSetFocus - Supplies option of changing focus to debuggee to avoid
+ user having to nudge debuggee into stop
+
+
+Return Value:
+
+--*/
+{
+ return CallEM( emfStop, hpid, NULL, fSetFocus, 0 );
+}
+
+
+
diff --git a/private/windbg/osdebug/od2.h b/private/windbg/osdebug/od2.h
new file mode 100644
index 000000000..23e3edcc0
--- /dev/null
+++ b/private/windbg/osdebug/od2.h
@@ -0,0 +1,49 @@
+typedef HIND HEMP;
+
+typedef struct tid_struct {
+ HPID hpid;
+} TIDS;
+typedef TIDS FAR *LPTID; // Thread information
+
+typedef struct pid_struct {
+ HTL htl;
+ HEMP hempNative;
+ HLLI llemp;
+ BOOL fNative;
+ UINT lastmodel;
+ LPFNSVC lpfnsvcCC;
+ HLLI lltid;
+} PIDS;
+typedef PIDS FAR *LPPID; // Process information
+
+typedef struct _EMS {
+ EMFUNC emfunc;
+ EMTYPE emtype;
+ HLLI llhpid;
+ UINT model;
+} EMS; // Execution Model Structure
+typedef EMS FAR *LPEM;
+
+typedef struct _EMPS {
+ HEM hem;
+ EMFUNC emfunc;
+ EMTYPE emtype;
+ UINT model;
+} EMPS; // Execution Model Structure
+typedef EMPS FAR *LPEMP;
+
+typedef struct _TLS {
+ TLFUNC tlfunc;
+ HLLI llpid;
+} TLS; // Transport Layer Structure
+typedef TLS FAR *LPTL;
+
+
+void PASCAL LOADDS NullKill ( LPV );
+void PASCAL LOADDS ODPDKill ( LPV );
+void PASCAL LOADDS EMKill ( LPV );
+int PASCAL LOADDS EMHpidCmp ( LPV, LPV, LONG );
+void PASCAL LOADDS EMPKill ( LPV );
+void PASCAL LOADDS TLKill ( LPV );
+
+int PASCAL LOADDS NullComp ( LPV, LPV, LONG );
diff --git a/private/windbg/osdebug/osassert.h b/private/windbg/osdebug/osassert.h
new file mode 100644
index 000000000..f5b624d29
--- /dev/null
+++ b/private/windbg/osdebug/osassert.h
@@ -0,0 +1,34 @@
+/***
+*assert.h - define the assert macro
+*
+* Copyright (c) 1985-1987, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the assert(exp) macro.
+* [ANSI/System V]
+*
+*Modified:
+* Allent 3/14/88 - call Quit instead of abort
+*******************************************************************************/
+#ifndef _ASSERT_DEFINED
+
+#if DBG
+
+
+
+#define assert(exp) { \
+ if (!(exp)) { \
+ LBPrintf( #exp, __FILE__, __LINE__); \
+ LBQuit(2); \
+ } \
+}
+
+#else
+
+#define assert(exp)
+
+#endif /* NDEBUG */
+
+#define _ASSERT_DEFINED
+
+#endif /* _ASSERT_DEFINED */
diff --git a/private/windbg/osdebug/sources b/private/windbg/osdebug/sources
new file mode 100644
index 000000000..0d1f3b9fb
--- /dev/null
+++ b/private/windbg/osdebug/sources
@@ -0,0 +1,44 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=osdebug
+
+TARGETNAME=osdebug
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES= od.c
+
+UMTYPE=windows
+
+MIPS_FLAGS=-DWIN32 -DTARGET32 -DHOST32 -DADDR_MIXED
+386_FLAGS=-DWIN32 -DTARGET32 -DHOST32 -DADDR_MIXED
+ALPHA_FLAGS=-DWIN32 -DTARGET32 -DHOST32 -DADDR_MIXED
+PPC_FLAGS=-DWIN32 -DTARGET32 -DHOST32 -DADDR_MIXED
+
+MS_MIPS=1
+
+LINKER_FLAGS=-ignore:505
+386_WARNING_LEVEL=/WX /W3
+
+INCLUDES=include
diff --git a/private/windbg/osdebug/tl.h b/private/windbg/osdebug/tl.h
new file mode 100644
index 000000000..9ed81576d
--- /dev/null
+++ b/private/windbg/osdebug/tl.h
@@ -0,0 +1,60 @@
+/**** TL.H - Transport layer api ****
+ * *
+ * *
+ * Copyright <C> 1990, Microsoft Corp *
+ * *
+ * Created: October 15, 1990 by David W. Gray *
+ * *
+ * Purpose: *
+ * *
+ * *
+ ***************************************************************************/
+
+//
+// tlfGetInfo parameter block
+//
+
+#define CTLDESCRIPTION 64 /* max bytes in a TL description */
+#define CTLSETUP 128 /* max bytes in setup string */
+
+#define DM_SIDE_L_INIT_SWITCH "DMSide"
+
+typedef struct
+{
+ CHAR szDesc[CTLDESCRIPTION];
+ USHORT fSetupNeeded;
+} TLINFO;
+
+// the set of transport layer commands process by TLFunc and DMTLFunc
+
+typedef enum {
+ tlfGlobalInit, // initialize "mondo" TL and set TLCallBack
+ tlfGlobalDestroy, // uninitialize "mondo" TL
+ tlfRegisterDBF, // register the debugger helper functions
+ tlfSetUIStruct, // set user interface structure
+ tlfInit, // initialize/create a (specific) transport layer
+ tlfDestroy, // vaporize any tl structs created
+ tlfConnect, // connect to the companion transport layer
+ tlfDisconnect, // disconnected from the companion transport layer
+ tlfSetBuffer, // set the data buffer to be used for incoming packets
+ tlfDebugPacket, // send the debug packet to the debug monitor
+ tlfRequest, // request data from the companion transport layer
+ tlfReply, // reply to a data request message
+ tlfGetInfo, // return an id string and other data
+ tlfSetup, // set up the transport layer
+ tlfGetProc, // return the true TLFUNC proc for the htl
+ tlfLoadDM, // load the DM module (remote transport does this)
+ tlfSetErrorCB, // Set the address of the error callback function
+ tlfPoll, // WIN32S: enter polling loop
+ tlfSendVersion, // Send the version packet to the remote side
+ tlfGetVersion, // Request the version packet from the remote side
+ tlfRemoteQuit, // Remote quit
+ tlfMax
+} _TLF;
+typedef LONG TLF;
+
+typedef enum {
+ tlcbDisconnect, // Transport layer was disconnected normally
+ tlcbMax
+} _TLCB;
+typedef DWORD TLCB;
diff --git a/private/windbg/remote/dirs b/private/windbg/remote/dirs
new file mode 100644
index 000000000..992812494
--- /dev/null
+++ b/private/windbg/remote/dirs
@@ -0,0 +1,19 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= xport \
+ pipe \
+ serial \
+ shell
diff --git a/private/windbg/remote/pipe/control.c b/private/windbg/remote/pipe/control.c
new file mode 100644
index 000000000..a56d693ca
--- /dev/null
+++ b/private/windbg/remote/pipe/control.c
@@ -0,0 +1,751 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ tlpipe.c
+
+Abstract:
+
+ This module contains the code for the named pipe transport layer
+ which explicitly deals with the machanics of doing named pipes.
+
+Author:
+
+ Wesley Witt (wesw) 25-Nov-93
+
+Environment:
+
+ Win32 User
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef OSDEBUG4
+
+#include "od.h"
+
+#else
+
+#include "defs.h"
+#include "od.h"
+
+#endif
+
+#include "xport.h"
+#include "tlpipe.h"
+
+#undef MessageBox
+
+//
+// there can only be 2 control pipes open at once because
+// the connect thread can only service one client at a time
+//
+#define MAX_PIPES 2
+#define BREAKIN_TIMEOUT 20 // in seconds
+
+#define ControlClient(f) ci[CiClient].f
+#define ControlConnect(f) ci[CiConnect].f
+
+typedef struct _tagCONTROL_PIPE_INFO {
+ HANDLE hPipe;
+ OVERLAPPED olConnect;
+ OVERLAPPED olRead;
+ OVERLAPPED olWrite;
+ BOOL fConnected;
+ CHAR szName[MAX_PATH];
+ CHAR szClientId[MAX_PATH];
+} CONTROL_PIPE_INFO, *LPCONTROL_PIPE_INFO;
+
+CONTROL_PIPE_INFO ci[MAX_PIPES];
+CHAR ClientId[MAX_PATH];
+
+DWORD CiClient = 0;
+DWORD CiConnect = 0;
+
+extern BOOL FConnected;
+
+
+
+
+
+//*********************************************************************************************
+// Message Box Utiluties
+//*********************************************************************************************
+
+typedef struct _tagMESSAGEBOX_INFO {
+ HWND hWnd;
+ LPSTR lpText;
+ LPSTR lpCaption;
+ UINT uType;
+ DWORD dwResponse;
+} MESSAGEBOX_INFO, *LPMESSAGEBOX_INFO;
+
+
+DWORD
+MessageBoxThread(
+ LPMESSAGEBOX_INFO lpMbi
+ )
+{
+ lpMbi->dwResponse = MessageBoxA( lpMbi->hWnd, lpMbi->lpText, lpMbi->lpCaption, lpMbi->uType );
+ return 0;
+}
+
+
+int
+WINAPI
+MessageBox(
+ HWND hWnd ,
+ LPSTR lpText,
+ LPSTR lpCaption ,
+ UINT uType,
+ DWORD dwTimeout
+ )
+{
+ MESSAGEBOX_INFO mbi;
+ HANDLE hThread;
+ DWORD id;
+
+ mbi.hWnd = hWnd;
+ mbi.lpText = lpText;
+ mbi.lpCaption = lpCaption;
+ mbi.uType = uType;
+
+ hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)MessageBoxThread, &mbi, 0, &id);
+ if (!hThread) {
+ return 0;
+ }
+
+ if (WaitForSingleObject( hThread, dwTimeout ) == WAIT_TIMEOUT) {
+ TerminateThread( hThread, 0 );
+ return STATUS_TIMEOUT;
+ }
+
+ return mbi.dwResponse;
+}
+
+
+VOID
+TlControlInitialization(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes all control pipe structures
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD i;
+
+
+ ZeroMemory( ci, sizeof(ci) );
+
+ for (i=0; i<MAX_PIPES; i++) {
+ ci[i].hPipe = INVALID_HANDLE_VALUE;
+ ci[i].olConnect.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ ci[i].olRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ ci[i].olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ }
+
+ return;
+}
+
+
+XOSD
+TlCreateControlPipe(
+ LPSTR szName
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates the pipe which will be connected to windbgrm (server).
+
+Arguments:
+
+ szName - Supplies the name of the pipe to create
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ SECURITY_DESCRIPTOR securityDescriptor;
+ SECURITY_ATTRIBUTES lsa;
+ DWORD ec;
+ DWORD i;
+
+
+ for (i=0; i<MAX_PIPES; i++) {
+ ci[i].fConnected = FALSE;
+
+ //
+ // Set a security descriptor
+ //
+ InitializeSecurityDescriptor( &securityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION );
+ SetSecurityDescriptorDacl( &securityDescriptor, TRUE, NULL, FALSE );
+ lsa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ lsa.lpSecurityDescriptor = &securityDescriptor;
+ lsa.bInheritHandle = TRUE;
+
+ sprintf( ci[i].szName, "\\\\.\\pipe\\%scontrol", szName );
+
+ ci[i].hPipe =
+ CreateNamedPipe( ci[i].szName,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES,
+ PIPE_BUFFER_SIZE,
+ PIPE_BUFFER_SIZE,
+ 1000,
+ &lsa
+ );
+
+ if (ci[i].hPipe == INVALID_HANDLE_VALUE) {
+ ec = GetLastError();
+ DEBUG_OUT1("TLCreateControlPipe: failed ec=%u\n", ec);
+ return xosdBadPipeName;
+ }
+ }
+
+ return xosdNone;
+}
+
+
+XOSD
+TlCreateClientControlPipe(
+ LPSTR lpHostName,
+ LPSTR lpPipeName
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates the pipe which will be connected to windbgrm (server).
+
+Arguments:
+
+ lpHostName - Supplies name of remote debuggee host
+
+ lpPipeName - Supplies remote pipe name
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ SECURITY_DESCRIPTOR securityDescriptor;
+ SECURITY_ATTRIBUTES lsa;
+ DWORD timeOut;
+ DWORD mode;
+ BYTE buf[256];
+ LPCONTROLPACKET cp = (LPCONTROLPACKET) &buf[0];
+
+
+
+ ControlClient(fConnected) = FALSE;
+
+ //
+ // Set a security descriptor
+ //
+ InitializeSecurityDescriptor( &securityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION );
+ SetSecurityDescriptorDacl( &securityDescriptor, TRUE, NULL, FALSE );
+ lsa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ lsa.lpSecurityDescriptor = &securityDescriptor;
+ lsa.bInheritHandle = TRUE;
+
+ if (!lpHostName || !*lpHostName) {
+ lpHostName = DEFAULT_SERVER;
+ }
+ if (!lpPipeName || !*lpPipeName) {
+ lpPipeName = DEFAULT_PIPE;
+ }
+ sprintf( ControlClient(szName), "\\\\%s\\pipe\\%scontrol",
+ lpHostName, lpPipeName);
+
+ mode = sizeof(ControlClient(szClientId));
+ GetComputerName( ControlClient(szClientId), &mode );
+ strcpy( cp->ClientId, ControlClient(szClientId) );
+
+ ControlClient(hPipe) = INVALID_HANDLE_VALUE;
+ timeOut = TlUtilTime() + 10;
+
+ while ((ControlClient(hPipe) == INVALID_HANDLE_VALUE) && (TlUtilTime() < timeOut)) {
+ //
+ // wait for the server to make a pipe available...
+ //
+ WaitNamedPipe( ControlClient(szName), 10000 );
+
+ //
+ // create the client pipe
+ //
+ ControlClient(hPipe) = CreateFile( ControlClient(szName),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL );
+
+ if (ControlClient(hPipe) == INVALID_HANDLE_VALUE &&
+ GetLastError() == ERROR_BAD_NETPATH) {
+ return xosdBadPipeServer;
+ }
+ }
+
+ if (ControlClient(hPipe) == INVALID_HANDLE_VALUE) {
+ return xosdCannotConnect;
+ }
+
+ mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+
+ if ( !SetNamedPipeHandleState( ControlClient(hPipe), &mode, NULL, NULL ) ) {
+ DEBUG_OUT1("SetNamedPipeHandleState failed, ec=%u\n", GetLastError());
+ CloseHandle( ControlClient(hPipe) );
+ return xosdBadPipeName;
+ }
+
+ ControlClient(fConnected) = TRUE;
+ cp->Length = sizeof(CONTROLPACKET);
+ cp->Type = CP_REQUEST_CONNECTION;
+ cp->Response = 0;
+ TlWriteControl( CiClient, (PUCHAR)cp, cp->Length );
+ TlReadControl( CiClient, (PUCHAR)cp, sizeof(buf) );
+
+ if (cp->Response) {
+
+ //
+ // we have permission to open a control pipe
+ // try to open a client debuggeer pipe
+ //
+ return xosdNone;
+
+ } else {
+
+ //
+ // the server did not give us permission to
+ // open a debugger connection
+ //
+ ControlClient(fConnected) = FALSE;
+ CloseHandle( ControlClient(hPipe) );
+ return xosdCannotConnect;
+
+ }
+
+ return xosdNone;
+}
+
+
+XOSD
+TlConnectControlPipe(
+ VOID
+ )
+{
+ DWORD ec;
+ DWORD status;
+ LPSTR NewClientId;
+ BYTE buf[256];
+ LPCONTROLPACKET cp = (LPCONTROLPACKET) &buf[0];
+
+
+ assert( ControlConnect(fConnected) == FALSE );
+
+ ControlConnect(fConnected) =
+ ConnectNamedPipe( ControlConnect(hPipe), &ControlConnect(olConnect) );
+
+ if (!ControlConnect(fConnected)) {
+ ec = GetLastError();
+ switch( ec ) {
+ case ERROR_PIPE_CONNECTED:
+ goto connected;
+
+ case ERROR_IO_PENDING:
+ break;
+
+ default:
+ DEBUG_OUT1("PLPIPE: ConnectNamedPipe failed, Error %u\n", ec);
+ //DebugPrint("ConnectNamedPipe failed, Error=%u\n", ec);
+ return xosdCannotConnect;
+ }
+
+ status = WaitForSingleObject( ControlConnect(olConnect.hEvent),
+ MAX_CONNECT_WAIT * 1000 );
+ switch ( status ) {
+ case WAIT_OBJECT_0:
+ goto connected;
+
+ case WAIT_TIMEOUT:
+ //DebugPrint("ConnectNamedPipe timed out\n");
+ return xosdCannotConnect;
+
+ default:
+ ec = GetLastError();
+ DEBUG_OUT2("PLPIPE: ConnectNamedPipe failed, Status %u, ec=%u\n", status, ec);
+ //DebugPrint("ConnectNamedPipe failed, Error=%u\n", ec);
+ return xosdCannotConnect;
+ }
+ }
+
+connected:
+ ControlConnect(fConnected) = TRUE;
+ //DebugPrint("controlpipe connected\n");
+
+ //
+ // the control pipe is now connected so we
+ // must now negotiate a 'real' connection
+ //
+
+ if (!TlReadControl( CiConnect, (PUCHAR)cp, sizeof(buf) )) {
+ //DebugPrint("read #1 failed\n");
+ TlDisconnectControl( CiConnect );
+ return xosdCannotConnect;
+ }
+
+ //DebugPrint("read #1 completed\n");
+
+ if (cp->Type == CP_REQUEST_CONNECTION) {
+
+ NewClientId = _strdup( cp->ClientId );
+
+ if (FConnected) {
+ //
+ // in this case there is already a valid debugger connection.
+ // the connection must be disconnected and a new connection
+ // established with the new client.
+ //
+
+ //
+ // forward the request to the currently connected client
+ // the current client has the right to decline the new connection
+ //
+ cp->Type = CP_BREAKIN_CONNECTION;
+ if (!TlWriteControl( CiClient, (PUCHAR)cp, cp->Length )) {
+ //DebugPrint("write failed\n");
+ TlDisconnectControl( CiConnect );
+ return xosdCannotConnect;
+ }
+ if (!TlReadControl( CiClient, (PUCHAR)cp, sizeof(buf) )) {
+ //DebugPrint("read failed\n");
+ TlDisconnectControl( CiConnect );
+ return xosdCannotConnect;
+ }
+ if (cp->Response) {
+ TlPipeFailure();
+ FConnected = FALSE;
+ TlDisconnectTransport();
+ } else {
+ TlDisconnectControl( CiConnect );
+ return xosdCannotConnect;
+ }
+ }
+
+ //
+ // save the client id
+ //
+ strcpy( ClientId, NewClientId );
+ free( NewClientId );
+
+ //
+ // tell the new client that the connection request is granted
+ //
+ cp->Response = 1;
+ if (!TlWriteControl( CiConnect, (PUCHAR)cp, cp->Length )) {
+ //DebugPrint("write #2 failed\n");
+ TlDisconnectControl( CiConnect );
+ return xosdCannotConnect;
+ }
+
+ //DebugPrint("write #2 completed\n");
+
+ if (CiConnect == 0) {
+ CiClient = CiConnect;
+ CiConnect = 1;
+ } else {
+ CiClient = CiConnect;
+ CiConnect = 0;
+ }
+ }
+
+ //DebugPrint("connection established\n");
+
+ return xosdNone;
+}
+
+BOOL
+TlWriteControl(
+ DWORD ciIdx,
+ PUCHAR pch,
+ DWORD cch
+ )
+{
+ DWORD dwBytesWritten;
+ static DWORD cblast;
+ DWORD error;
+
+ if ( !ci[ciIdx].fConnected ) {
+ return FALSE;
+ }
+
+ DEBUG_OUT1("PLPIPE: Writing... (Count %u)\n",cch);
+
+ if (WriteFile(ci[ciIdx].hPipe, pch, cch, &dwBytesWritten,
+ &ci[ciIdx].olWrite )) {
+ //
+ // Write was successful and finished
+ //
+ FlushFileBuffers( ci[ciIdx].hPipe );
+
+ if ( dwBytesWritten != cch ) {
+ DEBUG_OUT2("PLPIPE: Wrote %u but asked for %u\n", dwBytesWritten, cch);
+ return FALSE;
+ }
+
+ DEBUG_OUT1( "PLPIPE: Wrote (%u)\n", dwBytesWritten);
+
+ cblast = cch;
+ return TRUE;
+ }
+
+ //
+ // We got a failure case -- there are now two possiblities.
+ // 1. -- we have overlapped I/O or
+ // 2. -- we are messed up
+ //
+ error = GetLastError();
+ switch ( error ) {
+ case ERROR_PIPE_NOT_CONNECTED:
+ case ERROR_BROKEN_PIPE:
+ case ERROR_NO_DATA:
+ DEBUG_OUT1("PLPIPE: Pipe is gone (1), error %u\n", error);
+ break;
+
+ case ERROR_IO_PENDING:
+ dwBytesWritten = 0;
+ goto WaitWrite;
+
+ default:
+ DEBUG_OUT1("PLPIPE: WriteFile failed, error %u\n", error);
+ break;
+ }
+
+ return FALSE;
+
+ WaitWrite:
+ if (GetOverlappedResult(ci[ciIdx].hPipe, &ci[ciIdx].olWrite, &dwBytesWritten, TRUE)) {
+ //
+ // Read has successfully completed
+ //
+ FlushFileBuffers( ci[ciIdx].hPipe );
+
+ if ( dwBytesWritten != cch ) {
+ DEBUG_OUT2("PLPIPE: Wrote %u but asked for %u\n", dwBytesWritten, cch);
+ return FALSE;
+ }
+
+ DEBUG_OUT1("PLPIPE: Wrote (%u)\n", dwBytesWritten);
+
+ cblast = cch;
+ return TRUE;
+ }
+
+ error = GetLastError();
+ switch ( error ) {
+ case ERROR_PIPE_NOT_CONNECTED:
+ case ERROR_BROKEN_PIPE:
+ case ERROR_NO_DATA:
+ DEBUG_OUT1("PLPIPE: Pipe is gone (3), error %u\n", error);
+ break;
+
+ default:
+ DEBUG_OUT1("PLPIPE: Get Read result failed, error %u\n", error);
+ break;
+ }
+
+ return FALSE;
+}
+
+DWORD
+TlReadControl(
+ DWORD ciIdx,
+ PUCHAR pch,
+ DWORD cch
+ )
+{
+ DWORD dwBytesRead;
+ DWORD error;
+
+ if ( !ci[ciIdx].fConnected ) {
+ return (DWORD) -1;
+ }
+
+ ResetEvent( ci[ciIdx].olRead.hEvent );
+
+ if (ReadFile(ci[ciIdx].hPipe, pch, cch, &dwBytesRead, &ci[ciIdx].olRead)) {
+ //
+ // Read was successful and finished return packet size and exit.
+ //
+ return dwBytesRead;
+ }
+
+ //
+ // We got a failure case -- there are now two possibities.
+ // 1. -- we have overlapped I/O, or
+ // 2. -- we are messed up.
+ //
+
+ error = GetLastError();
+ switch ( error ) {
+ case ERROR_MORE_DATA:
+ DEBUG_OUT(("Message is too long\n"));
+ assert( "Message is too long" && FALSE );
+ break;
+
+ case ERROR_IO_PENDING:
+ DEBUG_OUT1("PLPIPE: Read pending (%u bytes)...\n", cch);
+ dwBytesRead = 0;
+ goto WaitRead;
+
+ case ERROR_PIPE_NOT_CONNECTED:
+ case ERROR_BROKEN_PIPE:
+ case ERROR_NO_DATA:
+ DEBUG_OUT1("PLPIPE: Pipe is gone (2), error %u\n", error);
+ return (DWORD) -1;
+
+ default:
+ DEBUG_OUT1("PLPIPE: ReadFile failed, error %u\n", error);
+ break;
+ }
+
+ return 0;
+
+ WaitRead:
+ if (GetOverlappedResult(ci[ciIdx].hPipe, &ci[ciIdx].olRead, &dwBytesRead, TRUE)) {
+ //
+ // Read has successfully completed
+ //
+ return dwBytesRead;
+ }
+
+ error = GetLastError();
+ DEBUG_OUT1("PLPIPE: Pipe is gone (3), error %u\n", error);
+ return (DWORD) -1;
+}
+
+VOID
+ControlPipeFailure(
+ VOID
+ )
+{
+ TlDisconnectControl( CiClient );
+}
+
+BOOL
+TlDisconnectControl(
+ DWORD ciIdx
+ )
+{
+ BOOL Ok = TRUE;
+ DWORD Error;
+
+ DEBUG_OUT("PipeDisconnect\n");
+
+ Ok = DisconnectNamedPipe( ci[ciIdx].hPipe );
+
+ if ( !Ok ) {
+
+ Error = GetLastError();
+
+ switch( Error ) {
+
+ case ERROR_PIPE_NOT_CONNECTED:
+ Ok = TRUE;
+ break;
+
+ default:
+ DEBUG_OUT1("DisconnectNamedPipe failed, Error %u\n", Error);
+ break;
+ }
+ }
+
+ if ( Ok ) {
+ DEBUG_OUT(( "PLPIPE: Disconnected\n" ));
+ ci[ciIdx].fConnected = FALSE;
+ }
+
+ return Ok;
+}
+
+
+DWORD
+ControlReaderThread(
+ LPVOID lpv
+ )
+{
+ int cb;
+ int response;
+ BYTE buf[512];
+ LPCONTROLPACKET cp = (LPCONTROLPACKET) &buf[0];
+ CHAR szMsg[256];
+
+
+ while (TRUE) {
+ //
+ // Read the next packet item from the network
+ //
+ cb = TlReadControl( CiClient, (PUCHAR)cp, sizeof(buf) );
+
+ if (cb > 0) {
+ assert( cp->Length == (DWORD)cb );
+ if (cp->Type == CP_BREAKIN_CONNECTION) {
+ //
+ // some hosehead wants to break in and use this
+ // client's debug pipe
+ //
+ sprintf( szMsg,
+ "%s is requesting permission to interrupt your debug session.\n\nYou have %d seconds to respond or permission will be granted\n\nWould you like to grant permission?",
+ cp->ClientId,
+ BREAKIN_TIMEOUT
+ );
+ response = MessageBox( NULL,
+ szMsg,
+ "Windbg Remote Debugger",
+ MB_ICONQUESTION | MB_OKCANCEL | MB_SETFOREGROUND,
+ 1000 * BREAKIN_TIMEOUT
+ );
+
+ if (response == STATUS_TIMEOUT || response == IDOK) {
+ cp->Response = TRUE;
+ } else {
+ cp->Response = FALSE;
+ }
+ TlWriteControl( CiClient, (PUCHAR)cp, sizeof(*cp) );
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/private/windbg/remote/pipe/makefile b/private/windbg/remote/pipe/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/remote/pipe/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/remote/pipe/sources b/private/windbg/remote/pipe/sources
new file mode 100644
index 000000000..6c0b87259
--- /dev/null
+++ b/private/windbg/remote/pipe/sources
@@ -0,0 +1,47 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=tlpipe
+
+TARGETNAME=tlpipe
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+SOURCES= \
+ control.c \
+ tlpipe.c \
+ tlpipe.rc
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+INCLUDES=..\..\osdebug;..\..\osdebug\include;..\xport
+
+LINKLIBS=..\xport\obj\*\xport.lib
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
diff --git a/private/windbg/remote/pipe/tlpipe.c b/private/windbg/remote/pipe/tlpipe.c
new file mode 100644
index 000000000..9ea808476
--- /dev/null
+++ b/private/windbg/remote/pipe/tlpipe.c
@@ -0,0 +1,1280 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ tlpipe.c
+
+Abstract:
+
+ This module contains the code for the named pipe transport layer
+ which explicitly deals with the machanics of doing named pipes.
+
+Author:
+
+ Jim Schaad (jimsch) 11-Jun-93
+ Wesley Witt (wesw) 25-Nov-93
+
+Environment:
+
+ Win32 User
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef OSDEBUG4
+#include "defs.h"
+#endif
+
+
+#include "od.h"
+#include "dbgver.h"
+
+#include "xport.h"
+#include "tlpipe.h"
+
+#ifdef OSDEBUG4
+TLIS Tlis = {
+ TRUE, // fCanSetup
+ 0xffffffff, // dwMaxPacket
+ 0xffffffff, // dwOptPacket
+ TLISINFOSIZE, // dwInfoSize ?? what is this for ??
+ TRUE, // fRemote
+#if defined(_M_IX86)
+ mptix86, // mpt
+ mptix86, // mptRemote
+#elif defined(_M_MRX000)
+ mptmips, // mpt
+ mptmips, // mptRemote
+#elif defined(_M_ALPHA)
+ mptdaxp, // mpt
+ mptdaxp, // mptRemote
+#else
+#error( "unknown target machine" );
+#endif
+ { "Named Pipe Transport Layer (PIPE:)" } // rgchInfo
+};
+
+LPTLIS
+TlGetInfo(
+ VOID
+ )
+{
+ return &Tlis;
+}
+#endif
+
+#ifdef DEBUGVER
+DEBUG_VERSION('T','L',"Named Pipe Transport Layer (Debug)")
+#else
+RELEASE_VERSION('T','L',"Named Pipe Transport Layer")
+#endif
+
+DBGVERSIONCHECK()
+
+
+extern CRITICAL_SECTION csExpecting;
+
+BOOL FVerbose = FALSE;
+BOOL FPipeConnected = FALSE;
+HANDLE HandleNamedPipe = INVALID_HANDLE_VALUE;
+HANDLE HReadThread;
+HANDLE HControlReadThread;
+OVERLAPPED OverlappedPipe;
+OVERLAPPED OverlappedRead;
+OVERLAPPED OverlappedWrite;
+CRITICAL_SECTION CsWritePipe;
+CHAR RgchPipeName[MAX_PATH];
+BOOL FDMSide = FALSE;
+struct {
+ char * lpb;
+ int cb;
+} RgQueue[SIZE_OF_QUEUE];
+int IQueueFront = 0;
+int IQueueBack = 0;
+CRITICAL_SECTION CsQueue = {0};
+HANDLE HQueueEvent;
+HANDLE HCallbackThread;
+CHAR SzRemoteHostName[MAX_PATH];
+CHAR SzRemotePipeName[MAX_PATH];
+
+REPLY RgReplys[SIZE_OF_REPLYS];
+CRITICAL_SECTION CsReplys;
+int IReplys;
+
+char * RgSzTypes[] = {"FirstAsync", "Async", "FirstReply", "Reply",
+ "Disconnect", "VersionRequest", "VersionReply"};
+char * SzTypes(unsigned int i)
+{
+ static char rgch[20];
+ if (i > sizeof(RgSzTypes)/sizeof(RgSzTypes[0])) {
+ sprintf(rgch, "Type %x", i);
+ return rgch;
+ } else {
+ return RgSzTypes[i];
+ }
+}
+
+
+//#define TL_ERROR_LOGGING 1
+
+
+#ifdef TL_ERROR_LOGGING
+
+typedef struct {
+ DWORD ty;
+ DWORD ec;
+ DWORD cb;
+ DWORD ln;
+ DWORD td;
+ LPDWORD ob;
+ LPDWORD p;
+} ERRLOG;
+
+#define LOGIT(x,y,z,q) {el[ei].ty=x;el[ei].ec=y;el[ei].cb=z;el[ei].ln=__LINE__; \
+ el[ei].td=GetCurrentThreadId(); \
+ el[ei].ob=(LPDWORD)q; \
+ el[ei].p=(LPDWORD)malloc(z);memcpy(el[ei].p,q,z); \
+ printel2(ei); \
+ ei++; \
+ if (ei==99) ei=0;}
+#define LGREAD 1
+#define LGWRITE 2
+ERRLOG el[100];
+DWORD ei=0;
+
+void printel( void )
+{
+ DWORD i;
+
+ for (i=0; i<ei; i++) {
+ DebugPrint( "%d\t%d\t%x\t%d\t%08x\t%08x\t%x\n",
+ el[i].ty,
+ el[i].ec,
+ el[i].cb,
+ el[i].ln,
+ el[i].p,
+ el[i].ob,
+ el[i].td
+ );
+ }
+}
+
+void printel2( int i )
+{
+ DebugPrint( "%d\t%d\t%x\t%d\t%08x\t%08x\t%x\n",
+ el[i].ty,
+ el[i].ec,
+ el[i].cb,
+ el[i].ln,
+ el[i].p,
+ el[i].ob,
+ el[i].td
+ );
+}
+
+#else
+
+#define LOGIT(x,y,z,q)
+#define LGREAD 1
+#define LGWRITE 2
+
+#endif
+
+XOSD PipeConnect(HANDLE,DWORD);
+BOOL PipeClose(void);
+DWORD ReadFromPipe(PUCHAR,DWORD);
+DWORD ReaderThread(LPVOID arg);
+DWORD ControlReaderThread(LPVOID arg);
+DWORD CallbackThread(LPVOID lpvArg);
+
+int FAR PASCAL
+CopyString(
+ LPSTR * lplps,
+ LPSTR lpT,
+ char chEscape,
+ BOOL fQuote
+ );
+
+BOOL
+CreateStuff(
+ VOID
+ )
+{
+ int i = 0;
+
+ if (FDMSide && HReadThread) {
+ return TRUE;
+ }
+
+#ifdef TL_ERROR_LOGGING
+ if (i=1) printel();
+#endif
+
+ TlControlInitialization();
+
+ //
+ // Create random data strutures needed internally
+ //
+
+ OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (OverlappedRead.hEvent == NULL) {
+ return FALSE;
+ }
+
+ OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (OverlappedWrite.hEvent == NULL) {
+ return FALSE;
+ }
+
+ InitializeCriticalSection( &CsQueue );
+ HQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ InitializeCriticalSection( &CsReplys );
+ for (i=0; i<SIZE_OF_REPLYS; i++) {
+ RgReplys[i].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ }
+
+ InitializeCriticalSection(&CsWritePipe);
+
+#if DBG
+ InitializeCriticalSection(&csExpecting);
+#endif
+
+ return TRUE;
+}
+
+
+BOOL
+StartWorkerThreads(
+ BOOL fStartControlReader
+ )
+{
+ DWORD id;
+
+
+
+ //
+ // start the debugger pipe reader thread
+ //
+ HReadThread = CreateThread(NULL, 0, ReaderThread, 0, 0, &id);
+ if (!HReadThread) {
+ return FALSE;
+ }
+ SetThreadPriority( HReadThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ if (fStartControlReader) {
+ //
+ // start the control pipe reader thread, << ONLY FOR CLIENTS >>
+ //
+ HControlReadThread = CreateThread(NULL, 0, ControlReaderThread, 0, 0, &id);
+ if (!HControlReadThread) {
+ TerminateThread( HReadThread, 0 );
+ return FALSE;
+ }
+ SetThreadPriority( HControlReadThread, THREAD_PRIORITY_ABOVE_NORMAL );
+ }
+
+ //
+ // start the callback thread
+ //
+ HCallbackThread = CreateThread(NULL, 0, CallbackThread, 0, 0, &id);
+ if (!HCallbackThread) {
+ TerminateThread( HControlReadThread, 0 );
+ TerminateThread( HReadThread, 0 );
+ return FALSE;
+ }
+ SetThreadPriority( HCallbackThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ return TRUE;
+}
+
+
+VOID
+DestroyStuff(
+ VOID
+ )
+{
+ int i;
+
+ //
+ // If there is a reader thread -- then wait for it to be termianted
+ // and close the handle
+ //
+ if (HReadThread) {
+ TerminateThread( HReadThread, 0 );
+ WaitForSingleObject(HReadThread, INFINITE);
+ CloseHandle(HReadThread);
+ HReadThread = NULL;
+ }
+
+ //
+ // If there is a control thread -- then wait for it to be termianted
+ // and close the handle
+ //
+ if (HControlReadThread) {
+ TerminateThread( HControlReadThread, 0 );
+ WaitForSingleObject(HControlReadThread, INFINITE);
+ CloseHandle(HControlReadThread);
+ HControlReadThread = NULL;
+ }
+
+ if (HCallbackThread) {
+ TerminateThread( HCallbackThread, 0 );
+ WaitForSingleObject(HCallbackThread, INFINITE);
+ CloseHandle(HCallbackThread);
+ HCallbackThread = NULL;
+ }
+
+ //
+ // Now delete all of the objects
+ //
+ CloseHandle(HQueueEvent);
+ CloseHandle(OverlappedRead.hEvent);
+ CloseHandle(OverlappedWrite.hEvent);
+ DeleteCriticalSection(&CsQueue);
+ DeleteCriticalSection(&CsReplys);
+ DeleteCriticalSection(&CsWritePipe);
+ for (i=0; i<SIZE_OF_REPLYS; i++) {
+ CloseHandle(RgReplys[i].hEvent);
+ }
+
+#if DBG
+ DeleteCriticalSection(&csExpecting);
+#endif
+
+ return;
+}
+
+
+VOID
+TlPipeFailure(
+ VOID
+ )
+{
+ int i;
+ static int f = FALSE;
+
+ if (f) {
+ return;
+ }
+ f = TRUE;
+ EnterCriticalSection(&CsReplys);
+ for (i=0; i<IReplys; i++) {
+ SetEvent(RgReplys[i].hEvent);
+ }
+ LeaveCriticalSection(&CsReplys);
+ ControlPipeFailure();
+ f = FALSE;
+ return;
+}
+
+
+XOSD
+TlCreateTransport(
+ LPSTR szName
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates the pipe which will be connected to windbgrm (server).
+
+Arguments:
+
+ szName - Supplies the name of the pipe to create
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ SECURITY_DESCRIPTOR securityDescriptor;
+ SECURITY_ATTRIBUTES lsa;
+ DWORD error;
+
+
+ if (!CreateStuff()) {
+ return xosdUnknown;
+ }
+
+ if (TlCreateControlPipe( szName ) != xosdNone) {
+ return xosdBadPipeName;
+ }
+
+ DEBUG_OUT(("TlCreateTransport: Create ServerPipe\n"));
+
+ //
+ // create the event used for overlapped io
+ //
+ OverlappedPipe.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (OverlappedPipe.hEvent == NULL) {
+ return xosdUnknown;
+ }
+
+ //
+ // Set a security descriptor
+ //
+ InitializeSecurityDescriptor( &securityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION );
+ SetSecurityDescriptorDacl( &securityDescriptor, TRUE, NULL, FALSE );
+ lsa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ lsa.lpSecurityDescriptor = &securityDescriptor;
+ lsa.bInheritHandle = TRUE;
+
+ _snprintf(RgchPipeName, sizeof(RgchPipeName), PIPE_NAME_FORMAT,
+ ".", szName ? szName : DEFAULT_PIPE);
+
+ HandleNamedPipe = CreateNamedPipe( RgchPipeName,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE |
+ PIPE_WAIT,
+ 1,
+ PIPE_BUFFER_SIZE,
+ PIPE_BUFFER_SIZE,
+ 1000,
+ &lsa
+ );
+
+ if (HandleNamedPipe == INVALID_HANDLE_VALUE) {
+ error = GetLastError();
+ DEBUG_OUT1("TLCreateTransport: failed Error %u\n", error);
+ return xosdBadPipeName;
+ }
+
+ FPipeConnected = FALSE;
+
+ StartWorkerThreads( FALSE );
+
+ return xosdNone;
+}
+
+
+XOSD
+TlConnectTransport(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function attempts to connect the server pipe to a client.
+
+Arguments:
+
+ szName - Supplies the name of the pipe to create
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ DWORD ec;
+ DWORD status;
+
+
+ if (TlConnectControlPipe() != xosdNone) {
+ return xosdCannotConnect;
+ }
+
+ if (FPipeConnected) {
+ return xosdNone;
+ }
+
+ FPipeConnected = ConnectNamedPipe( HandleNamedPipe, &OverlappedPipe);
+
+ if (!FPipeConnected) {
+ ec = GetLastError();
+ switch( ec ) {
+ case ERROR_PIPE_CONNECTED:
+ goto connected;
+
+ case ERROR_IO_PENDING:
+ break;
+
+ default:
+ DEBUG_OUT1("PLPIPE: ConnectNamedPipe failed, Error %u\n", ec);
+ //DebugPrint("ConnectNamedPipe failed, Error=%u\n", ec);
+ return xosdCannotConnect;
+ }
+
+ status = WaitForSingleObject( OverlappedPipe.hEvent,
+ MAX_CONNECT_WAIT * 1000 );
+ switch ( status ) {
+ case WAIT_OBJECT_0:
+ goto connected;
+
+ case WAIT_TIMEOUT:
+ //DebugPrint("ConnectNamedPipe timed out\n");
+ return xosdCannotConnect;
+ break;
+
+ default:
+ ec = GetLastError();
+ DEBUG_OUT2(
+ "PLPIPE: ConnectNamedPipe failed, Status %u, ec=%u\n",
+ status, ec);
+ //DebugPrint("ConnectNamedPipe failed, Error=%u\n", ec);
+ return xosdCannotConnect;
+ }
+ }
+
+connected:
+ FPipeConnected = TRUE;
+
+ return xosdNone;
+}
+
+XOSD
+TlCreateClient(
+ LPSTR szName
+ )
+{
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ DWORD timeOut;
+ DWORD mode;
+ XOSD xosd = xosdNone;
+ DWORD error;
+ char * lpsz;
+
+
+ if (!CreateStuff()) {
+ return xosdUnknown;
+ }
+
+ if (szName) {
+ lpsz = szName;
+ while (*lpsz && isspace(*lpsz)) {
+ lpsz++;
+ }
+
+ *SzRemoteHostName = 0;
+ *SzRemotePipeName = 0;
+
+ if (CopyString(&lpsz, SzRemoteHostName, '\\', *lpsz == '"') > 0) {
+ while (*lpsz && isspace(*lpsz)) {
+ lpsz++;
+ }
+ CopyString(&lpsz, SzRemotePipeName, '\\', *lpsz == '"');
+ }
+
+ if ((xosd = TlCreateClientControlPipe(SzRemoteHostName,
+ SzRemotePipeName)) != xosdNone) {
+ return xosd;
+ }
+
+ if (HandleNamedPipe != INVALID_HANDLE_VALUE) {
+ DEBUG_OUT(("Named pipe is already open\n"));
+ return xosdNone;
+ }
+
+ DEBUG_OUT(("PLPIPE: OpenClientPipe\n"));
+ }
+
+ if ( (szName == NULL) || (*SzRemoteHostName == 0) ) {
+ _snprintf( RgchPipeName, sizeof(RgchPipeName), PIPE_NAME_FORMAT,
+ DEFAULT_SERVER, DEFAULT_PIPE );
+ } else {
+ _snprintf(RgchPipeName, sizeof(RgchPipeName), PIPE_NAME_FORMAT,
+ SzRemoteHostName, SzRemotePipeName);
+ }
+
+ timeOut = TlUtilTime() + 10;
+ while ((handle == INVALID_HANDLE_VALUE) && (TlUtilTime() < timeOut)) {
+
+ WaitNamedPipe( RgchPipeName, 10000 );
+
+ handle = CreateFile( RgchPipeName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL );
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ //
+ // server doesn't exist, don't wait around.
+ //
+
+ if (GetLastError() == ERROR_BAD_NETPATH) {
+ break;
+ }
+ Sleep(500);
+ }
+ }
+
+ if ( handle == INVALID_HANDLE_VALUE ) {
+
+ error = GetLastError();
+ DEBUG_OUT1("PLPIPE: CreateFile failed Error %u\n", error);
+ switch (error) {
+ case ERROR_BAD_NETPATH:
+ xosd = xosdBadPipeServer;
+ break;
+
+ case ERROR_FILE_NOT_FOUND:
+ xosd = xosdBadPipeName;
+ break;
+
+ default:
+ xosd = xosdBadPipeServer;
+ break;
+ }
+
+ } else {
+
+ mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+
+ if ( !SetNamedPipeHandleState( handle, &mode, NULL, NULL ) ) {
+ DEBUG_OUT1("PLPIPE: SetNamedPipeHandleState failed, Error %u\n",
+ GetLastError());
+ xosd = xosdBadPipeName;
+ }
+
+ DEBUG_OUT(( "PLPIPE: Opened client side of pipe\n" ));
+ DEBUG_OUT(( "PLPIPE: Connected\n" ));
+
+ HandleNamedPipe = handle;
+ FPipeConnected = TRUE;
+
+ StartWorkerThreads( TRUE );
+ }
+
+ return(xosd);
+}
+
+
+XOSD
+TlDestroyTransport(
+ VOID
+ )
+{
+ if (FPipeConnected) {
+ FPipeConnected = FALSE;
+ if (!FDMSide) {
+ DestroyStuff();
+ }
+ TlDisconnectTransport();
+ if (!FDMSide) {
+ PipeClose();
+ CloseHandle(OverlappedPipe.hEvent);
+ }
+ }
+ return xosdNone;
+}
+
+
+BOOL
+TlDisconnectTransport(
+ VOID
+ )
+{
+ BOOL Ok = TRUE;
+ DWORD Error;
+
+ DEBUG_OUT("PipeDisconnect\n");
+
+ Ok = DisconnectNamedPipe( HandleNamedPipe );
+
+ if ( !Ok ) {
+
+ Error = GetLastError();
+
+ switch( Error ) {
+
+ case ERROR_PIPE_NOT_CONNECTED:
+ Ok = TRUE;
+ break;
+
+ default:
+ DEBUG_OUT1("DisconnectNamedPipe failed, Error %u\n", Error);
+ break;
+ }
+ }
+
+ if ( Ok ) {
+ DEBUG_OUT(( "PLPIPE: Disconnected\n" ));
+ FPipeConnected = FALSE;
+ }
+
+ return Ok;
+}
+
+
+BOOL
+PipeClose(
+ void
+ )
+{
+ BOOL Ok = TRUE;
+
+ DEBUG_OUT(("PLPIPE: PipeClose\n"));
+
+ if ( HandleNamedPipe != INVALID_HANDLE_VALUE ) {
+
+ if ( FDMSide && FPipeConnected ) {
+
+ DEBUG_OUT( ("PLPIPE: Pipe being closed without disconnecting\n") );
+ Ok = FALSE;
+
+ } else {
+
+ CloseHandle( HandleNamedPipe );
+ HandleNamedPipe = INVALID_HANDLE_VALUE;
+ FPipeConnected = FALSE;
+ DEBUG_OUT( ("PLPIPE: Named Pipe now closed\n") );
+ }
+ }
+
+ return Ok;
+}
+
+
+DWORD
+TlUtilTime(VOID)
+{
+ DWORD time;
+ static DWORD lTickCount = 0;
+
+ time = GetCurrentTime();
+
+ time = time / 1000; // Convert from millisecs to secs
+
+ if (time < lTickCount) // Take care of day wrap
+ time += (24L * 3600);
+
+ lTickCount = time;
+
+ return(time);
+}
+
+
+BOOL
+TlWriteTransport(
+ PUCHAR pch,
+ DWORD cch
+ )
+{
+ DWORD dwBytesWritten;
+ DWORD ec;
+
+ if ( !FPipeConnected ) {
+ return FALSE;
+ }
+
+ DEBUG_OUT1("PLPIPE: Writing... (Count %u)\n",cch);
+
+ EnterCriticalSection(&CsWritePipe);
+ if (WriteFile(HandleNamedPipe, pch, cch, &dwBytesWritten, &OverlappedWrite )) {
+ //
+ // Write was successful and finished
+ //
+ LeaveCriticalSection(&CsWritePipe);
+
+ if ( dwBytesWritten != cch ) {
+ DEBUG_OUT2("PLPIPE: Wrote %u but asked for %u\n", dwBytesWritten, cch);
+ LOGIT(LGWRITE,cch,dwBytesWritten,pch);
+ goto errorWrite;
+ }
+
+ DEBUG_OUT1( "PLPIPE: Wrote (%u)\n", dwBytesWritten);
+
+ LOGIT(LGWRITE,0,dwBytesWritten,pch);
+ return TRUE;
+ }
+
+ ec = GetLastError();
+ if (ec != ERROR_IO_PENDING) {
+ LeaveCriticalSection(&CsWritePipe);
+ goto errorWrite;
+ }
+
+ if (GetOverlappedResult(HandleNamedPipe, &OverlappedWrite, &dwBytesWritten, TRUE)) {
+ //
+ // Write was successful and finished
+ //
+ LeaveCriticalSection(&CsWritePipe);
+
+ if ( dwBytesWritten != cch ) {
+ DEBUG_OUT2("PLPIPE: Wrote %u but asked for %u\n", dwBytesWritten, cch);
+ LOGIT(LGWRITE,cch,dwBytesWritten,pch);
+ goto errorWrite;
+ }
+
+ DEBUG_OUT1("PLPIPE: Wrote (%u)\n", dwBytesWritten);
+
+ LOGIT(LGWRITE,0,dwBytesWritten,pch);
+ return TRUE;
+ }
+
+ LeaveCriticalSection(&CsWritePipe);
+
+errorWrite:
+ ec = GetLastError();
+ LOGIT(LGWRITE,ec,dwBytesRead,pch);
+ TlPipeFailure();
+
+ return FALSE;
+}
+
+
+BOOL
+TlFlushTransport(
+ VOID
+ )
+{
+ return FlushFileBuffers( HandleNamedPipe );
+}
+
+
+DWORD
+ReadFromPipe(
+ PUCHAR pch,
+ DWORD cch
+ )
+{
+ DWORD dwBytesRead;
+ DWORD ec;
+ PNLBLK pnlblk = (PNLBLK)pch;
+
+ if (!FPipeConnected) {
+ return (DWORD) -1;
+ }
+
+ ResetEvent( OverlappedRead.hEvent );
+
+ if (ReadFile(HandleNamedPipe, pch, cch, &dwBytesRead, &OverlappedRead)) {
+ //
+ // Read has successfully completed
+ //
+ LOGIT(LGREAD,pnlblk->cchMessage,dwBytesRead,pch);
+ return dwBytesRead;
+ }
+
+ ec = GetLastError();
+ if (ec != ERROR_IO_PENDING) {
+ goto errorRead;
+ }
+
+ if (GetOverlappedResult(HandleNamedPipe, &OverlappedRead, &dwBytesRead, TRUE)) {
+ //
+ // Read has successfully completed
+ //
+ LOGIT(LGREAD,pnlblk->cchMessage,dwBytesRead,pch);
+ return dwBytesRead;
+ }
+
+errorRead:
+ ec = GetLastError();
+ LOGIT(LGREAD,ec,dwBytesRead,pch);
+ TlPipeFailure();
+
+ return (DWORD) -1;
+}
+
+
+DWORD
+ReaderThread(
+ LPVOID lpvArg
+ )
+/*++
+
+Routine Description:
+
+ This is the main function for the reader thread in this transport layer.
+ Its sole purpose is to pull things from the named pipe queue as fast
+ as possible and place them into an internal queue. This will prevent
+ us from getting piled up in the network queue to fast.
+
+Arguments:
+
+ lpvArg - Supplies the starting parameter -- which is ignored
+
+Return Value:
+
+ 0 on a normal exit and -1 otherwise
+
+--*/
+
+{
+ DWORD bufSize;
+ PNLBLK pnlblk;
+ PNLBLK pnlblk2;
+ int cb = 0;
+ int cb2;
+ int i;
+ LPSTR lpb;
+ MPACKET * pMpacket;
+
+
+
+ bufSize = MAX_INTERNAL_PACKET + sizeof(NLBLK) + sizeof(MPACKET);
+ pnlblk = (PNLBLK) malloc( bufSize );
+
+ while(HandleNamedPipe == INVALID_HANDLE_VALUE || (!FPipeConnected)) {
+ Sleep( 500 );
+ }
+
+ while (TRUE) {
+ //
+ // Read the next packet item from the network
+ //
+ cb2 = cb;
+ cb = ReadFromPipe((PUCHAR)pnlblk, bufSize);
+
+ assert( cb != 0 );
+
+ //
+ // Did the read routine decide that the pipe has completely
+ // failed and caused a shut down of it to occur? if so
+ // then go ahead and exit this thread from the system.
+ //
+
+ if (cb == -1) {
+ //
+ // Make sure that there is space to put the entry into the
+ // queue -- if no then wait until we can get enough space
+ //
+
+ EnterCriticalSection(&CsQueue);
+ while ((IQueueFront + 1) % SIZE_OF_QUEUE == IQueueBack) {
+ LeaveCriticalSection(&CsQueue);
+ Sleep(100);
+ EnterCriticalSection(&CsQueue);
+ }
+ DEBUG_OUT("READER: Add killer\n");
+
+ //
+ // Allocate space for the killer message
+ //
+
+ lpb = malloc(sizeof(NLBLK));
+ pnlblk2 = (PNLBLK) lpb;
+ pnlblk2->mtypeBlk = mtypeTransportIsDead;
+ pnlblk2->cchMessage = 0;
+
+ //
+ // Put the message in the queue
+ //
+
+ RgQueue[IQueueFront].lpb = lpb;
+ RgQueue[IQueueFront].cb = sizeof(NLBLK);
+ IQueueFront = (IQueueFront + 1) % SIZE_OF_QUEUE;
+
+ //
+ // Wake up the other guy and terminate this thread
+ //
+
+ SetEvent(HQueueEvent);
+ LeaveCriticalSection(&CsQueue);
+
+ if (FDMSide) {
+
+ TlDestroyTransport();
+ while(HandleNamedPipe == INVALID_HANDLE_VALUE || (!FPipeConnected)) {
+ Sleep( 500 );
+ }
+
+ EnterCriticalSection(&CsQueue);
+ IQueueFront = 0;
+ IQueueBack = 0;
+ LeaveCriticalSection(&CsQueue);
+ ZeroMemory(pnlblk, bufSize);
+
+ } else {
+
+ return 0;
+
+ }
+ }
+
+ //
+ // If the readed item had some length -- then we need to process
+ // the message packet just recieved
+ //
+ else if ( cb > 0) {
+
+ //
+ // Print a message about this packet type.
+ //
+
+ //DEBUG_OUT2("READER: %s %d\n", SzTypes(pnlblk->mtypeBlk), cb);
+ DEBUG_OUT2("READER: %x %x\n", pnlblk->mtypeBlk, cb )
+
+ //
+ // For a reply or a version reply message. Place the reply
+ // into the buffer which was supplied for that purpose.
+ //
+
+ if ((pnlblk->mtypeBlk == mtypeVersionReply) ||
+ (pnlblk->mtypeBlk == mtypeReply)) {
+ EnterCriticalSection(&CsReplys);
+ i = IReplys - 1;
+ assert(i != -1);
+ if (i != -1) {
+ assert( WaitForSingleObject( RgReplys[i].hEvent, 0 ) != WAIT_OBJECT_0 );
+ cb = min(pnlblk->cchMessage, RgReplys[i].cbBuffer);
+ memcpy(RgReplys[i].lpb, pnlblk->rgchData, cb);
+ RgReplys[i].cbRet = cb;
+ SetEvent(RgReplys[i].hEvent);
+ }
+ LeaveCriticalSection(&CsReplys);
+ } else if (pnlblk->mtypeBlk == mtypeReplyMulti) {
+ EnterCriticalSection(&CsReplys);
+ i = IReplys - 1;
+ if (i != -1) {
+ pMpacket = (MPACKET *) pnlblk->rgchData;
+ cb2 = pMpacket->packetNum * MAX_INTERNAL_PACKET;
+ cb = pnlblk->cchMessage - sizeof(MPACKET);
+ cb = min(cb + cb2, RgReplys[i].cbBuffer);
+ if (cb > cb2) {
+ memcpy(RgReplys[i].lpb + cb2, pMpacket->rgchData,
+ cb - cb2);
+ RgReplys[i].cbRet = cb;
+ }
+ if (pMpacket->packetNum + 1 == pMpacket->packetCount) {
+ SetEvent(RgReplys[i].hEvent);
+ }
+ }
+ LeaveCriticalSection(&CsReplys);
+ } else {
+
+ assert( cb == (int) (pnlblk->cchMessage + sizeof(NLBLK)) );
+
+ lpb = malloc(cb);
+ memcpy(lpb, pnlblk, cb);
+
+ EnterCriticalSection( &CsQueue );
+ while ((IQueueFront + 1) % SIZE_OF_QUEUE == IQueueBack) {
+ LeaveCriticalSection( &CsQueue );
+ Sleep(100);
+ EnterCriticalSection( &CsQueue );
+ }
+ DEBUG_OUT2("READER: Add queue Front=%d End=%d\n", IQueueFront, IQueueBack);
+ RgQueue[IQueueFront].lpb = lpb;
+ RgQueue[IQueueFront].cb = cb;
+ IQueueFront = (IQueueFront + 1) % SIZE_OF_QUEUE;
+ SetEvent(HQueueEvent);
+ LeaveCriticalSection( &CsQueue );
+ }
+ }
+ }
+
+ return (DWORD) -1;
+}
+
+
+DWORD
+CallbackThread(
+ LPVOID lpvArg
+ )
+{
+ LPSTR lpb;
+ int cb;
+
+ while (TRUE) {
+ EnterCriticalSection( &CsQueue );
+ if (IQueueFront == IQueueBack) {
+ ResetEvent( HQueueEvent);
+ LeaveCriticalSection( &CsQueue );
+ WaitForSingleObject( HQueueEvent, INFINITE );
+ EnterCriticalSection( &CsQueue );
+ }
+
+ lpb = RgQueue[IQueueBack].lpb;
+ DEBUG_OUT3("CALLBACK: %x Back=%d Front=%d\n",((PNLBLK)lpb)->mtypeBlk,IQueueBack,IQueueFront);
+ cb = RgQueue[IQueueBack].cb;
+ RgQueue[IQueueBack].lpb = NULL;
+ RgQueue[IQueueBack].cb = 0;
+ IQueueBack = (IQueueBack + 1) % SIZE_OF_QUEUE;
+ LeaveCriticalSection( &CsQueue );
+
+ if (!CallBack((PNLBLK) lpb, cb)) {
+
+ if (!FDMSide) {
+ return 0;
+ }
+
+ }
+
+ free(lpb);
+
+ }
+ return (DWORD) -1;
+}
+
+
+int FAR PASCAL
+CopyString(
+ LPSTR * lplps,
+ LPSTR lpT,
+ char chEscape,
+ BOOL fQuote
+ )
+/*++
+
+Routine Description:
+
+ Scan and copy an optionally quoted C-style string. If the first
+ character is a quote, a matching quote will terminate the string,
+ otherwise the scanning will stop at the first whitespace encountered.
+ The target string will be null terminated if any characters are copied.
+
+Arguments:
+
+ lplps - Supplies a pointer to a pointer to the source string
+
+ lpt - Supplies a pointer to the target string
+
+ chEscape - Supplies the escape character (typically '\\')
+
+ fQuote - Supplies a flag indicating whether the first character is a quote
+
+Return Value:
+
+ The number of characters copied into lpt[]. If an error occurs, -1 is
+ returned.
+
+--*/
+{
+ LPSTR lps = *lplps;
+ LPSTR lpt = lpT;
+ int i;
+ int n;
+ int err = 0;
+ char cQuote;
+#ifdef DBCS
+ BOOL fDBCS = FALSE;
+#endif
+
+ if (fQuote) {
+ if (*lps) cQuote = *lps++;
+ }
+
+ while (!err) {
+
+ if (*lps == 0)
+ {
+ if (fQuote) err = 1;
+ else *lpt = '\0';
+ break;
+ }
+#ifdef DBCS
+ else if (fQuote && *lps == cQuote && !fDBCS)
+#else
+ else if (fQuote && *lps == cQuote)
+#endif
+ {
+ *lpt = '\0';
+ // eat the quote
+ lps++;
+ break;
+ }
+#ifdef DBCS
+ else if (!fQuote && !fDBCS &&
+ (!*lps ||
+ *lps == ' ' ||
+ *lps == '\t' ||
+ *lps == '\r' ||
+ *lps == '\n'))
+#else
+ else if (!fQuote &&
+ (!*lps ||
+ *lps == ' ' ||
+ *lps == '\t' ||
+ *lps == '\r' ||
+ *lps == '\n'))
+#endif
+ {
+ *lpt = '\0';
+ break;
+ }
+
+#ifdef DBCS
+ else if (IsDBCSLeadByte((BYTE)*lps) && !fDBCS) {
+ *lpt++ = *lps++;
+ fDBCS = TRUE;
+ }
+#endif
+ else if (*lps != chEscape)
+ {
+ *lpt++ = *lps++;
+#ifdef DBCS
+ fDBCS = FALSE;
+#endif
+ }
+ else
+ {
+ switch (*++lps) {
+ case 0:
+ err = 1;
+ --lps;
+ break;
+
+ default: // any char - usually escape or quote
+ *lpt++ = *lps;
+ break;
+
+ case 'b': // backspace
+ *lpt++ = '\b';
+ break;
+
+ case 'f': // formfeed
+ *lpt++ = '\f';
+ break;
+
+ case 'n': // newline
+ *lpt++ = '\n';
+ break;
+
+ case 'r': // return
+ *lpt++ = '\r';
+ break;
+
+ case 's': // space
+ *lpt++ = ' ';
+ break;
+
+ case 't': // tab
+ *lpt++ = '\t';
+ break;
+
+ case '0': // octal escape
+ for (n = 0, i = 0; i < 3; i++) {
+ ++lps;
+ if (*lps < '0' || *lps > '7') {
+ --lps;
+ break;
+ }
+ n = (n<<3) + *lps - '0';
+ }
+ *lpt++ = (UCHAR)(n & 0xff);
+ break;
+ }
+ lps++; // skip char from switch
+#ifdef DBCS
+ fDBCS = FALSE;
+#endif
+ }
+
+ } // while
+
+ if (err) {
+ return -1;
+ } else {
+ *lplps = lps;
+ return lpt - lpT;
+ }
+}
+
diff --git a/private/windbg/remote/pipe/tlpipe.def b/private/windbg/remote/pipe/tlpipe.def
new file mode 100644
index 000000000..3f6731dfa
--- /dev/null
+++ b/private/windbg/remote/pipe/tlpipe.def
@@ -0,0 +1,5 @@
+LIBRARY tlpipe
+
+EXPORTS
+ DBGVersionCheck PRIVATE
+ TLFunc PRIVATE
diff --git a/private/windbg/remote/pipe/tlpipe.h b/private/windbg/remote/pipe/tlpipe.h
new file mode 100644
index 000000000..331f18c2f
--- /dev/null
+++ b/private/windbg/remote/pipe/tlpipe.h
@@ -0,0 +1,80 @@
+
+#define DEFAULT_PIPE "windbg"
+#define DEFAULT_SERVER "."
+#define PIPE_NAME_FORMAT "\\\\%s\\pipe\\%s"
+
+#define PIPE_BUFFER_SIZE (1024 * 5)
+#define MAX_CONNECT_WAIT 30 // in seconds
+#define SIZE_OF_QUEUE 100
+
+
+DWORD TlUtilTime(void);
+
+
+//
+// packet types for the control pipe
+//
+
+#define CP_REQUEST_CONNECTION 1
+#define CP_BREAKIN_CONNECTION 2
+
+
+typedef struct _tagCONTROLPACKET {
+ DWORD Length; // this includes the packet overhead
+ DWORD Type;
+ CHAR ClientId[16];
+ DWORD Response;
+ BYTE Data[];
+} CONTROLPACKET, *LPCONTROLPACKET;
+
+
+
+DWORD
+TlReadControl(
+ DWORD ciIdx,
+ PUCHAR pch,
+ DWORD cch
+ );
+
+BOOL
+TlWriteControl(
+ DWORD ciIdx,
+ PUCHAR pch,
+ DWORD cch
+ );
+
+XOSD
+TlConnectControlPipe(
+ VOID
+ );
+
+VOID
+TlPipeFailure(
+ VOID
+ );
+
+XOSD
+TlCreateControlPipe(
+ LPSTR szName
+ );
+
+XOSD
+TlCreateClientControlPipe(
+ LPSTR lpHostName,
+ LPSTR lpPipeName
+ );
+
+VOID
+ControlPipeFailure(
+ VOID
+ );
+
+BOOL
+TlDisconnectControl(
+ DWORD ciIdx
+ );
+
+VOID
+TlControlInitialization(
+ VOID
+ );
diff --git a/private/windbg/remote/pipe/tlpipe.rc b/private/windbg/remote/pipe/tlpipe.rc
new file mode 100644
index 000000000..47de011ef
--- /dev/null
+++ b/private/windbg/remote/pipe/tlpipe.rc
@@ -0,0 +1,9 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Named Pipe transport layer for WinDbg"
+#define VER_INTERNALNAME_STR "TLPIPE.DLL"
+
+#include <common.ver>
diff --git a/private/windbg/remote/serial/makefile b/private/windbg/remote/serial/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/remote/serial/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/remote/serial/sources b/private/windbg/remote/serial/sources
new file mode 100644
index 000000000..10f9ca286
--- /dev/null
+++ b/private/windbg/remote/serial/sources
@@ -0,0 +1,45 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=tlser
+
+TARGETNAME=tlser
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+SOURCES= \
+ tlser.c \
+ tlser.rc
+
+UMTYPE=windows
+
+!include ..\..\common.src
+
+INCLUDES=..\..\osdebug;..\..\osdebug\include;..\xport
+
+LINKLIBS=..\xport\obj\*\xport.lib
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
diff --git a/private/windbg/remote/serial/tlser.c b/private/windbg/remote/serial/tlser.c
new file mode 100644
index 000000000..a43f85532
--- /dev/null
+++ b/private/windbg/remote/serial/tlser.c
@@ -0,0 +1,758 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ tlser.c
+
+Abstract:
+
+ This module contains the code for the serial transport layer.
+
+Author:
+
+ Wesley Witt (wesw) 25-Nov-93
+
+Environment:
+
+ Win32 User
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "defs.h"
+#include "od.h"
+#include "dbgver.h"
+#include "xport.h"
+#include "tlser.h"
+
+#define SIZE_OF_QUEUE 100
+
+extern CRITICAL_SECTION csExpecting;
+
+BOOL FVerbose = FALSE;
+HANDLE HReadThread;
+BOOL FDMSide = FALSE;
+BOOL fConnected;
+
+static OVERLAPPED OverlappedRead;
+static OVERLAPPED OverlappedWrite;
+
+struct {
+ char * lpb;
+ int cb;
+} RgQueue[SIZE_OF_QUEUE];
+
+int IQueueFront = 0;
+int IQueueBack = 0;
+CRITICAL_SECTION CsQueue = {0};
+CRITICAL_SECTION CsSerial = {0};
+HANDLE HQueueEvent;
+HANDLE HCallbackThread;
+HANDLE TlComPort;
+DWORD TlBaudRate;
+CHAR ClientId[MAX_PATH];
+
+REPLY RgReplys[SIZE_OF_REPLYS];
+CRITICAL_SECTION CsReplys;
+static CRITICAL_SECTION CsNull;
+int IReplys;
+
+static VOID DestroyCriticalSection(CRITICAL_SECTION *);
+
+char * SzTypes(unsigned int i)
+{
+ static char rgch[30];
+
+ switch (i) {
+ case mtypeAsync:
+ sprintf(rgch, "mtypeAsync");
+ break;
+
+ case mtypeAsyncMulti:
+ sprintf(rgch, "mtypeAsyncMulti");
+ break;
+
+ case mtypeSync:
+ sprintf(rgch, "mtypeSync");
+ break;
+
+ case mtypeSyncMulti:
+ sprintf(rgch, "mtypeSyncMulti");
+ break;
+
+ case mtypeReply:
+ sprintf(rgch, "mtypeReply");
+ break;
+
+ case mtypeReplyMulti:
+ sprintf(rgch, "mtypeReplyMulti");
+ break;
+
+ case mtypeDisconnect:
+ sprintf(rgch, "mtypeDisconnect");
+ break;
+
+ case mtypeVersionRequest:
+ sprintf(rgch, "mtypeVersionRequest");
+ break;
+
+ case mtypeVersionReply:
+ sprintf(rgch, "mtypeVersionReply");
+ break;
+
+ case mtypeTransportIsDead:
+ sprintf(rgch, "mtypeTransportIsDead");
+ break;
+
+ default:
+ sprintf(rgch, "Type %x", i);
+ break;
+ }
+ return rgch;
+}
+
+
+#define TL_ERROR_LOGGING 1
+
+
+#ifdef TL_ERROR_LOGGING
+
+typedef struct {
+ DWORD ty;
+ DWORD ec;
+ DWORD cb;
+ DWORD ln;
+ DWORD td;
+ LPDWORD ob;
+ LPDWORD p;
+} ERRLOG;
+
+#define LOGIT(x,y,z,q) {el[ei].ty=x;el[ei].ec=y;el[ei].cb=z;el[ei].ln=__LINE__; \
+ el[ei].td=GetCurrentThreadId(); \
+ el[ei].ob=(LPDWORD)q; \
+ el[ei].p=(LPDWORD)malloc(z);memcpy(el[ei].p,q,z);ei++; \
+ if (ei==99) ei=0;}
+#define LGREAD 1
+#define LGWRITE 2
+ERRLOG el[100];
+DWORD ei=0;
+
+#if DBG
+void printel( void )
+{
+ DWORD i;
+
+ for (i=0; i<ei; i++) {
+ DebugPrint( "%d\t%d\t%x\t%d\t%08x\t%08x\t%x\n",
+ el[i].ty,
+ el[i].ec,
+ el[i].cb,
+ el[i].ln,
+ el[i].p,
+ el[i].ob,
+ el[i].td
+ );
+ }
+}
+#endif
+
+#else
+
+#define LOGIT(x,y,z,q)
+#define LGREAD 1
+#define LGWRITE 2
+
+#endif
+
+DWORD ReaderThread(LPVOID arg);
+DWORD CallbackThread(LPVOID lpvArg);
+
+#ifdef DEBUGVER
+DEBUG_VERSION('T','L',"Serial Transport Layer (Debug)")
+#else
+RELEASE_VERSION('T','L',"Serial Transport Layer")
+#endif
+
+DBGVERSIONCHECK()
+
+
+
+BOOL
+CreateStuff(
+ VOID
+ )
+{
+ int i;
+
+ if (FDMSide && HReadThread) {
+ return TRUE;
+ }
+
+ //
+ // Create random data strutures needed internally
+ //
+
+ InitializeCriticalSection( &CsQueue );
+ InitializeCriticalSection( &CsSerial );
+
+ OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (OverlappedRead.hEvent == NULL)
+ return FALSE;
+
+ OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (OverlappedWrite.hEvent == NULL)
+ return FALSE;
+
+ HQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (HQueueEvent == NULL)
+ return FALSE;
+
+ InitializeCriticalSection( &CsReplys );
+ for (i=0; i<SIZE_OF_REPLYS; i++) {
+ RgReplys[i].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (RgReplys[i].hEvent == NULL)
+ return FALSE;
+ }
+
+#if DBG
+ InitializeCriticalSection(&csExpecting);
+#endif
+
+ return TRUE;
+}
+
+
+BOOL
+StartWorkerThreads(
+ VOID
+ )
+{
+ DWORD id;
+
+ //
+ // start the debugger reader thread
+ //
+ HReadThread = CreateThread(NULL, 0, ReaderThread, 0, 0, &id);
+ if (!HReadThread) {
+ return FALSE;
+ }
+ SetThreadPriority( HReadThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ //
+ // start the callback thread
+ //
+ HCallbackThread = CreateThread(NULL, 0, CallbackThread, 0, 0, &id);
+ if (!HCallbackThread) {
+ TerminateThread( HReadThread, 0 );
+ return FALSE;
+ }
+ SetThreadPriority( HCallbackThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ return TRUE;
+}
+
+
+VOID
+DestroyStuff(
+ VOID
+ )
+{
+ int i;
+
+ //
+ // If there is a reader thread -- then wait for it to be termianted
+ // and close the handle
+ //
+ if (HReadThread) {
+ TerminateThread( HReadThread, 0 );
+ WaitForSingleObject(HReadThread, INFINITE);
+ CloseHandle(HReadThread);
+ HReadThread = NULL;
+ }
+
+ if (HCallbackThread) {
+ TerminateThread( HCallbackThread, 0 );
+ WaitForSingleObject(HCallbackThread, INFINITE);
+ CloseHandle(HCallbackThread);
+ HCallbackThread = NULL;
+ }
+
+ //
+ // Now delete all of the objects
+ //
+ if (OverlappedRead.hEvent) {
+ CloseHandle(OverlappedRead.hEvent);
+ OverlappedRead.hEvent = NULL;
+ }
+ if (OverlappedWrite.hEvent) {
+ CloseHandle(OverlappedWrite.hEvent);
+ OverlappedWrite.hEvent = NULL;
+ }
+ if (HQueueEvent == NULL) {
+ CloseHandle(HQueueEvent);
+ HQueueEvent = NULL;
+ }
+
+ DestroyCriticalSection(&CsSerial);
+ DestroyCriticalSection(&CsQueue);
+ DestroyCriticalSection(&CsReplys);
+
+ for (i=0; i<SIZE_OF_REPLYS; i++) {
+ if (RgReplys[i].hEvent) {
+ CloseHandle(RgReplys[i].hEvent);
+ RgReplys[i].hEvent = NULL;
+ }
+ }
+
+#if DBG
+ DestroyCriticalSection(&csExpecting);
+#endif
+
+ return;
+}
+
+
+XOSD
+TlCreateTransport(
+ LPSTR szParams
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates the connection to windbgrm (server).
+
+Arguments:
+
+ szParams - Supplies the parameters
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ DCB LocalDcb;
+ COMMTIMEOUTS To;
+ LPSTR p;
+ CHAR buf[16];
+
+
+ p = strtok(szParams, ":");
+ sprintf( buf, "%s:", p );
+ p = strtok(NULL, ":" );
+ TlBaudRate = strtoul(p, NULL, 0);
+
+ TlComPort = CreateFile( buf,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_FLAG_OVERLAPPED,
+ NULL
+ );
+
+ if (TlComPort == INVALID_HANDLE_VALUE || TlComPort == NULL) {
+ return xosdUnknown;
+ }
+
+ SetupComm( TlComPort, 4096, 4096 );
+
+
+ if (!GetCommState( TlComPort, &LocalDcb )) {
+ CloseHandle( TlComPort );
+ return xosdUnknown;
+ }
+
+ LocalDcb.BaudRate = TlBaudRate;
+ LocalDcb.fBinary = TRUE;
+ LocalDcb.fParity = FALSE;
+ LocalDcb.fOutxCtsFlow = FALSE;
+ LocalDcb.fOutxDsrFlow = FALSE;
+ LocalDcb.fDtrControl = DTR_CONTROL_ENABLE;
+ LocalDcb.fDsrSensitivity = FALSE;
+
+ LocalDcb.fOutX = FALSE;
+ LocalDcb.fInX = FALSE;
+
+ LocalDcb.fNull = FALSE;
+ LocalDcb.fRtsControl = RTS_CONTROL_ENABLE;
+ LocalDcb.fAbortOnError = FALSE;
+
+ LocalDcb.ByteSize = 8;
+ LocalDcb.Parity = NOPARITY;
+ LocalDcb.StopBits = ONESTOPBIT;
+
+ if (!SetCommState( TlComPort, &LocalDcb )) {
+ CloseHandle( TlComPort );
+ return xosdUnknown;
+ }
+
+ //
+ // Set the normal read and write timeout time.
+ //
+ To.ReadIntervalTimeout = 0;
+ To.ReadTotalTimeoutMultiplier = 0;
+ To.ReadTotalTimeoutConstant = 20 * 1000;
+ To.WriteTotalTimeoutMultiplier = 0;
+ To.WriteTotalTimeoutConstant = 20 * 1000;
+
+ if (!SetCommTimeouts( TlComPort, &To )) {
+ CloseHandle( TlComPort );
+ return xosdUnknown;
+ }
+
+ if (!CreateStuff()) {
+ CloseHandle( TlComPort );
+ return xosdUnknown;
+ }
+
+ StartWorkerThreads();
+
+ return xosdNone;
+}
+
+
+XOSD
+TlConnectTransport(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function attempts to connect the server to a client.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ XOSD error code.
+
+--*/
+
+{
+ if (TlComPort) {
+ if (fConnected) {
+ Sleep( 1000 * 10 );
+ return xosdCannotConnect;
+ } else {
+ fConnected = TRUE;
+ return xosdNone;
+ }
+ }
+
+ Sleep( 1000 * 10 );
+ return xosdCannotConnect;
+}
+
+XOSD
+TlCreateClient(
+ LPSTR szName
+ )
+{
+ return TlCreateTransport( szName );
+
+}
+
+
+XOSD
+TlDestroyTransport(
+ VOID
+ )
+{
+ DestroyStuff();
+ CloseHandle( TlComPort );
+
+ return xosdNone;
+}
+
+
+BOOL
+TlDisconnectTransport(
+ VOID
+ )
+{
+ return TRUE;
+}
+
+
+BOOL
+TlWriteTransport(
+ PUCHAR Buffer,
+ DWORD SizeOfBuffer
+ )
+{
+ BOOLEAN rc;
+ DWORD TrashErr;
+ COMSTAT TrashStat;
+ DWORD BytesWritten;
+
+#if DBG
+ DebugPrint("Transmitting %d bytes\n", SizeOfBuffer);
+#endif
+ EnterCriticalSection(&CsSerial);
+ rc = WriteFile( TlComPort, Buffer, SizeOfBuffer, &BytesWritten, &OverlappedWrite );
+ if (!rc && GetLastError() != ERROR_IO_PENDING) {
+ //
+ // Device could be locked up. Clear it just in case.
+ //
+ ClearCommError( TlComPort, &TrashErr, &TrashStat );
+#if DBG
+ DebugPrint( "COMERR: %d %x\n", GetLastError(), TrashErr );
+#endif
+ LeaveCriticalSection(&CsSerial);
+ return rc;
+ }
+ rc = GetOverlappedResult(TlComPort, &OverlappedWrite, &BytesWritten, TRUE);
+ if (!rc) {
+ ClearCommError( TlComPort, &TrashErr, &TrashStat );
+#if DBG
+ DebugPrint( "COMERR: %d %x\n", GetLastError(), TrashErr );
+#endif
+ }
+ LeaveCriticalSection(&CsSerial);
+ return rc;
+}
+
+
+DWORD
+TlReadTransport(
+ PUCHAR Buffer,
+ DWORD SizeOfBuffer
+ )
+{
+ DWORD BytesRead = 0;
+ BOOLEAN rc;
+ DWORD TrashErr;
+ COMSTAT TrashStat;
+
+ ResetEvent(OverlappedRead.hEvent);
+ rc = ReadFile( TlComPort, (LPVOID)Buffer, SizeOfBuffer, &BytesRead, &OverlappedRead);
+ if (!rc && GetLastError() != ERROR_IO_PENDING) {
+ ClearCommError( TlComPort, &TrashErr, &TrashStat );
+#if DBG
+ DebugPrint( "COMERR: %d %x\n", GetLastError(), TrashErr );
+ DebugBreak();
+#endif
+ return (DWORD)-1;
+ }
+ if (!GetOverlappedResult(TlComPort, &OverlappedRead, &BytesRead, TRUE)) {
+ ClearCommError( TlComPort, &TrashErr, &TrashStat );
+#if DBG
+ DebugPrint( "COMERR: %d %x\n", GetLastError(), TrashErr );
+ DebugBreak();
+#endif
+ return (DWORD)-1;
+ }
+ return (BytesRead);
+}
+
+BOOL
+TlFlushTransport(
+ VOID
+ )
+{
+ return FlushFileBuffers( TlComPort );
+}
+
+DWORD
+ReaderThread(
+ LPVOID lpvArg
+ )
+/*++
+
+Routine Description:
+
+ This is the main function for the reader thread in this transport layer.
+ Its sole purpose is to pull things from the transport queue as fast
+ as possible and place them into an internal queue. This will prevent
+ us from getting piled up in the network queue to fast.
+
+Arguments:
+
+ lpvArg - Supplies the starting parameter -- which is ignored
+
+Return Value:
+
+ 0 on a normal exit and -1 otherwise
+
+--*/
+
+{
+ DWORD bufSize;
+ PNLBLK pnlblk;
+ DWORD cb = 0;
+ DWORD cb2;
+ DWORD i;
+ LPSTR lpb;
+ MPACKET * pMpacket;
+ BOOLEAN rc;
+ DWORD BytesRead;
+
+
+
+ bufSize = MAX_INTERNAL_PACKET + sizeof(NLBLK) + sizeof(MPACKET);
+ pnlblk = (PNLBLK) malloc( bufSize );
+ pMpacket = (MPACKET *) pnlblk->rgchData;
+
+ while (TRUE) {
+ //
+ // Read the next packet item from the network
+ //
+ ZeroMemory( (LPVOID)pnlblk, bufSize );
+
+
+ //
+ // read the block header
+ //
+ BytesRead = TlReadTransport((LPVOID)pnlblk, sizeof(NLBLK));
+ if (BytesRead <= 0) {
+ Sleep( 50 );
+ continue;
+ }
+
+ if (BytesRead != sizeof(NLBLK)) {
+ assert(FALSE);
+ Sleep( 50 );
+ continue;
+ }
+
+ if (pnlblk->cchMessage) {
+ //
+ // read the data
+ //
+ BytesRead = TlReadTransport((LPVOID)pnlblk->rgchData, pnlblk->cchMessage);
+ if (BytesRead <= 0) {
+ Sleep( 50 );
+ continue;
+ }
+
+ if ( BytesRead != (DWORD)pnlblk->cchMessage ) {
+ assert(FALSE);
+ Sleep ( 50 );
+ continue;
+ }
+ cb = pnlblk->cchMessage + sizeof(NLBLK);
+ } else {
+ cb = sizeof(NLBLK);
+ }
+
+ //
+ // Print a message about this packet type.
+ //
+ DEBUG_OUT2("READER: %s %d\n", SzTypes(pnlblk->mtypeBlk), cb);
+#if DBG
+ //DebugPrint( "PACKET: %02x, %d %ld\n", pnlblk->mtypeBlk, pnlblk->cchMessage, BytesRead );
+#endif
+ if ((pnlblk->mtypeBlk == mtypeVersionReply) ||
+ (pnlblk->mtypeBlk == mtypeReply)) {
+ EnterCriticalSection(&CsReplys);
+ i = IReplys - 1;
+ if (i != -1) {
+ cb = min(pnlblk->cchMessage, RgReplys[i].cbBuffer);
+ memcpy(RgReplys[i].lpb, pnlblk->rgchData, cb);
+ RgReplys[i].cbRet = cb;
+ SetEvent(RgReplys[i].hEvent);
+ }
+ LeaveCriticalSection(&CsReplys);
+ continue;
+ }
+
+ if (pnlblk->mtypeBlk == mtypeReplyMulti) {
+ EnterCriticalSection( &CsReplys );
+ i = IReplys - 1;
+ if (i != -1) {
+ cb2 = pMpacket->packetNum * MAX_INTERNAL_PACKET;
+ cb = pnlblk->cchMessage - sizeof(MPACKET);
+ cb = min( cb + cb2, (DWORD)RgReplys[i].cbBuffer );
+ if (cb > cb2) {
+ memcpy( RgReplys[i].lpb + cb2, pMpacket->rgchData, cb - cb2 );
+ RgReplys[i].cbRet = cb;
+ }
+ if (pMpacket->packetNum + 1 == pMpacket->packetCount) {
+ SetEvent( RgReplys[i].hEvent );
+ }
+ }
+ LeaveCriticalSection( &CsReplys );
+ continue;
+ }
+
+ lpb = malloc( cb );
+ memcpy( lpb, pnlblk, cb );
+ EnterCriticalSection( &CsQueue );
+ while ((IQueueFront + 1) % SIZE_OF_QUEUE == IQueueBack) {
+ LeaveCriticalSection( &CsQueue );
+ Sleep(100);
+ EnterCriticalSection( &CsQueue );
+ }
+ RgQueue[IQueueFront].lpb = lpb;
+ RgQueue[IQueueFront].cb = cb;
+ IQueueFront = (IQueueFront + 1) % SIZE_OF_QUEUE;
+ SetEvent(HQueueEvent);
+ LeaveCriticalSection( &CsQueue );
+ }
+
+ return 0;
+}
+
+
+DWORD
+CallbackThread(
+ LPVOID lpvArg
+ )
+{
+ LPSTR lpb;
+ int cb;
+
+ while (TRUE) {
+ EnterCriticalSection( &CsQueue );
+ if (IQueueFront == IQueueBack) {
+ ResetEvent( HQueueEvent);
+ LeaveCriticalSection( &CsQueue );
+ WaitForSingleObject( HQueueEvent, INFINITE );
+ EnterCriticalSection( &CsQueue );
+ }
+
+ lpb = RgQueue[IQueueBack].lpb;
+ cb = RgQueue[IQueueBack].cb;
+ RgQueue[IQueueBack].lpb = NULL;
+ RgQueue[IQueueBack].cb = 0;
+ IQueueBack = (IQueueBack + 1) % SIZE_OF_QUEUE;
+ LeaveCriticalSection( &CsQueue );
+
+ if (!CallBack((PNLBLK) lpb, cb)) {
+
+ if (!FDMSide) {
+ return 0;
+ }
+
+ }
+
+ free(lpb);
+
+ }
+ return (DWORD) -1;
+}
+
+static
+VOID
+DestroyCriticalSection(
+ CRITICAL_SECTION *csItem
+)
+{
+ if (csItem && memcmp(csItem, &CsNull, sizeof(CsNull))) {
+ DeleteCriticalSection(csItem);
+ *csItem = CsNull;
+ }
+}
diff --git a/private/windbg/remote/serial/tlser.def b/private/windbg/remote/serial/tlser.def
new file mode 100644
index 000000000..5e1f2a695
--- /dev/null
+++ b/private/windbg/remote/serial/tlser.def
@@ -0,0 +1,5 @@
+LIBRARY tlser
+
+EXPORTS
+ DBGVersionCheck PRIVATE
+ TLFunc PRIVATE
diff --git a/private/windbg/remote/serial/tlser.h b/private/windbg/remote/serial/tlser.h
new file mode 100644
index 000000000..849ec26e8
--- /dev/null
+++ b/private/windbg/remote/serial/tlser.h
@@ -0,0 +1,73 @@
+
+#define PIPE_BUFFER_SIZE (1024 * 5)
+#define DEFAULT_PIPE "WinDbg_Pipe"
+#define MAX_CONNECT_WAIT 30
+
+DWORD TlUtilTime(void);
+
+
+//
+// packet types for the control pipe
+//
+
+#define CP_REQUEST_CONNECTION 1
+#define CP_BREAKIN_CONNECTION 1
+
+
+typedef struct _tagCONTROLPACKET {
+ DWORD Length; // this includes the packet overhead
+ DWORD Type;
+ CHAR ClientId[16];
+ DWORD Response;
+ BYTE Data[];
+} CONTROLPACKET, *LPCONTROLPACKET;
+
+
+
+DWORD
+TlReadControl(
+ DWORD ciIdx,
+ PUCHAR pch,
+ DWORD cch
+ );
+
+BOOL
+TlWriteControl(
+ DWORD ciIdx,
+ PUCHAR pch,
+ DWORD cch
+ );
+
+TlConnectControlPipe(
+ VOID
+ );
+
+VOID
+TlPipeFailure(
+ VOID
+ );
+
+XOSD
+TlCreateControlPipe(
+ LPSTR szName
+ );
+
+XOSD
+TlCreateClientControlPipe(
+ LPSTR szParams
+ );
+
+VOID
+ControlPipeFailure(
+ VOID
+ );
+
+BOOL
+TlDisconnectControl(
+ DWORD ciIdx
+ );
+
+VOID
+TlControlInitialization(
+ VOID
+ );
diff --git a/private/windbg/remote/serial/tlser.rc b/private/windbg/remote/serial/tlser.rc
new file mode 100644
index 000000000..2785d7ce8
--- /dev/null
+++ b/private/windbg/remote/serial/tlser.rc
@@ -0,0 +1,9 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Serial transport layer for WinDbg"
+#define VER_INTERNALNAME_STR "TLSER.DLL"
+
+#include <common.ver>
diff --git a/private/windbg/remote/shell/connect.ico b/private/windbg/remote/shell/connect.ico
new file mode 100644
index 000000000..9696ad7e2
--- /dev/null
+++ b/private/windbg/remote/shell/connect.ico
Binary files differ
diff --git a/private/windbg/remote/shell/dbgdll.c b/private/windbg/remote/shell/dbgdll.c
new file mode 100644
index 000000000..7373fcc01
--- /dev/null
+++ b/private/windbg/remote/shell/dbgdll.c
@@ -0,0 +1,675 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dbgdll.c
+
+Abstract:
+
+ This file contains the source code for the dialog to select the
+ various different transport layers
+
+Author:
+
+ Wesley Witt (wesw) 1-Nov-1993
+
+Environment:
+
+ User mode WIN32
+
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "emdm.h"
+#include "tl.h"
+#include "dbgver.h"
+#include "resource.h"
+#include "windbgrm.h"
+
+
+BOOL FTLChanged;
+int ITransportLayer;
+LPTRANSPORT_LAYER RgDbt;
+DWORD CDbt;
+
+BOOL
+DlgKernelDbg(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ );
+
+extern CHAR szHelpFileName[];
+
+/*
+ * SetHorizontalScrollExtent
+ *
+ * INPUTS hDlg = hwnd of dialog box
+ * rgch = string to check extent of
+ * pMaxStringExtent -> points to MaxStringExtent value (static)
+ * TabStop = current tab stop for the list box
+ * OUTPUTS none
+ *
+ * SUMMARY If the text extent of the string in the dialog box is greater
+ * than the current max, set the horizontal extent for the list box.
+ */
+VOID
+SetHorizontalScrollExtent(
+ HWND hDlg,
+ PUCHAR rgch,
+ PINT pMaxStringExtent,
+ INT TabStop
+ )
+{
+ HDC hDC;
+ INT Extent;
+
+
+ hDC = GetDC(hDlg);
+ // Keep track of the longest extent string we have in the
+ // list box
+ Extent = GetTabbedTextExtent(hDC, rgch, strlen(rgch), 1, &TabStop);
+ ReleaseDC(hDlg, hDC);
+
+ if (LOWORD(Extent) > *pMaxStringExtent) {
+ *pMaxStringExtent = LOWORD(Extent);
+ SendDlgItemMessage( hDlg,
+ ID_KNOWN_DLLS,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)*pMaxStringExtent,
+ 0
+ );
+ }
+}
+
+
+/*
+ * SetHorizontalScrollExtent
+ *
+ * INPUTS hDlg = hwnd of dialog box
+ * rgDbt = transport list
+ * cDbt = number of entries in transport list
+ * pMaxStringExtent -> points to MaxStringExtent value (static)
+ * TabStop = current tab stop for the list box
+ * OUTPUTS none
+ *
+ * SUMMARY Starts from scratch and recomputes the horizontal scroll extents
+ * for the listbox and sets the extent appropriately.
+ *
+ */
+VOID
+ScanSetHorizontalScrollExtent(
+ HWND hDlg,
+ LPTRANSPORT_LAYER rgDbt,
+ DWORD cDbt,
+ PINT pMaxStringExtent,
+ INT TabStop
+ )
+{
+ DWORD i;
+ UCHAR rgch[MAX_LIST_BOX_STRING];
+
+ *pMaxStringExtent = 0;
+
+ for (i=0; i<cDbt; i++) {
+ sprintf(rgch, "%s\t%s", rgDbt[i].szShortName, rgDbt[i].szLongName);
+ SetHorizontalScrollExtent(hDlg, rgch, pMaxStringExtent, TabStop);
+ }
+}
+
+
+/*
+ * SetDefaultButton
+ *
+ * INPUTS hDlg dialog box hwnd
+ * idButton button id
+ *
+ * OUTPUTS none
+ *
+ * SUMMARY Sets the default pushbutton and sets it's button style to default.
+ * Resets all other pushbuttons to non-default.
+ */
+VOID
+SetDefaultButton(
+ HWND hDlg,
+ int idButton
+ )
+{
+ HWND hwndButton;
+ HWND hwndPrevious;
+
+
+ hwndButton = GetDlgItem( hDlg, idButton );
+
+ if (hwndPrevious = SetFocus( hwndButton )) {
+ switch(GetDlgCtrlID( hwndPrevious )) { // if previous id was a known
+ case IDOK: // button, unhilight
+ case IDCANCEL:
+ case ID_HELP:
+ case ID_ADD:
+ case ID_DELETE:
+ SendDlgItemMessage( hDlg,
+ GetDlgCtrlID(hwndPrevious),
+ BM_SETSTYLE,
+ (WPARAM)BS_PUSHBUTTON,
+ MAKELPARAM(TRUE, 0)
+ );
+ break;
+ default:
+ break;
+ }
+ }
+
+ SendDlgItemMessage( hDlg,
+ idButton,
+ BM_SETSTYLE,
+ (WPARAM)BS_DEFPUSHBUTTON,
+ MAKELPARAM(TRUE, 0)
+ );
+}
+
+
+/*
+ * AddItem
+ *
+ * INPUTS hDlg dialog box hwnd
+ * prgDbt Points to current Debug Transport structure
+ * (contents may be changed)
+ * pcDbt points to number of entries in rgDbt (may be changed)
+ * piCurrent points to index of currently selected item in listbox
+ * pMaxStringExtent Points to currently known maximum string
+ * extent in listbox. (may be changed)
+ * TabStop Current listbox tabstop in dialog box units
+ *
+ * OUTPUTS Returns LIST_CHANGED if there were changes detected
+ * NO_CHANGE if no changes
+ * and LIST_ERROR if there was a consistency error
+ *
+ * SUMMARY Adds an item to the Debug Transport list and updates the list box.
+ * Does error checking on the ShortName.
+ */
+DWORD
+AddItem(
+ HWND hDlg,
+ LPTRANSPORT_LAYER *prgDbt,
+ PDWORD pcDbt,
+ PDWORD piCurrent,
+ PINT pMaxStringExtent,
+ INT TabStop
+ )
+{
+ int i;
+ int i2;
+ UCHAR rgch[MAX_LIST_BOX_STRING];
+
+
+ GetDlgItemText(hDlg, ID_SHORT_NAME, rgch, sizeof(rgch));
+
+ if (strlen(rgch) == 0) {
+ MessageBox(hDlg, "Must provide a Short Name", NULL, MB_OK);
+ return LIST_ERROR;
+ }
+
+ for (i=0; i<(signed int)*pcDbt; i++) {
+ i2 = lstrcmpi(rgch, (*prgDbt)[i].szShortName);
+ if (i2 == 0) {
+ MessageBox( hDlg, "Short Names must be unique", NULL, MB_OK);
+ return LIST_ERROR;
+ }
+
+ if (i2 < 0) {
+ break; // found insertion point
+ }
+ }
+
+ *prgDbt = (LPTRANSPORT_LAYER) realloc(*prgDbt, sizeof(TRANSPORT_LAYER)*(*pcDbt+1));
+
+ for (i2=(signed int)*pcDbt; i2 > i; i2--) {
+ (*prgDbt)[i2] = (*prgDbt)[i2-1];
+ }
+ *pcDbt += 1;
+
+ *piCurrent = (DWORD)i;
+
+ (*prgDbt)[*piCurrent].szShortName = _strdup(rgch);
+
+ GetDlgItemText(hDlg, ID_DESCRIPTION, rgch, sizeof(rgch));
+ (*prgDbt)[*piCurrent].szLongName = _strdup(rgch);
+
+ GetDlgItemText(hDlg, ID_PATH, rgch, sizeof(rgch));
+ (*prgDbt)[*piCurrent].szDllName = _strdup(rgch);
+
+ GetDlgItemText(hDlg, ID_PARAMETERS, rgch, sizeof(rgch));
+ (*prgDbt)[*piCurrent].szParam = _strdup(rgch);
+
+ (*prgDbt)[*piCurrent].fDefault = IsDlgButtonChecked(hDlg, ID_DEFAULT);
+
+ sprintf(rgch, "%s\t%s", (*prgDbt)[*piCurrent].szShortName,
+ (*prgDbt)[*piCurrent].szLongName);
+ *piCurrent = SendDlgItemMessage(hDlg, ID_KNOWN_DLLS, LB_ADDSTRING, 0,
+ (LPARAM)rgch);
+ SendDlgItemMessage(hDlg, ID_KNOWN_DLLS, LB_SETCURSEL, *piCurrent, 0);
+
+ SetHorizontalScrollExtent(hDlg, rgch, pMaxStringExtent, TabStop);
+ return LIST_CHANGED;
+}
+
+
+/*
+ * CheckChangeItem
+ *
+ * INPUTS hDlg dialog box hwnd
+ * prgDbt Points to current Debug Transport structure
+ * (contents may be changed)
+ * pcDbt points to number of entries in rgDbt (may be changed)
+ * piCurrent points to index of currently selected item in listbox
+ * pMaxStringExtent Points to currently known maximum string
+ * extent in listbox. (may be changed)
+ * TabStop Current listbox tabstop in dialog box units
+ * fDeleted TRUE if the last operation performed was a Delete.
+ * (If TRUE, we should not re-add the item)
+ *
+ * OUTPUTS Returns LIST_CHANGED if there were changes detected
+ * NO_CHANGE if no changes
+ * and LIST_ERROR if there was a consistency error
+ *
+ * SUMMARY Checks if the values in the details fields match those in the
+ * current listbox item. If so, return FALSE, otherwise... if the
+ * short name matches the current item, change the fields in the
+ * current item, else add a new item.
+ */
+
+DWORD
+CheckChangeItem(
+ HWND hDlg,
+ LPTRANSPORT_LAYER * prgDbt,
+ PDWORD pcDbt,
+ PDWORD piCurrent,
+ PINT pMaxStringExtent,
+ INT TabStop,
+ BOOL fDeleted
+ )
+{
+ BOOL fChange = FALSE, fChangeDescription = FALSE;
+ UCHAR rgch[MAX_LIST_BOX_STRING];
+ DWORD i;
+
+
+ // get the short name field
+ // if short name field is different from the curretly selected item
+ // if it matches any OTHER item
+ // bring up a message box and return.
+ // else
+ // add new item
+ // else (short name is same as current)
+ // if any other fields are different
+ // get the changes
+ // if current item is marked default, remove default mark from
+ // all others.
+
+ // get the short name field
+
+ if ((*piCurrent == LB_ERR) ||
+ GetDlgItemText(hDlg, ID_SHORT_NAME, rgch, sizeof(rgch)) == 0 ||
+ strlen(rgch) == 0) {
+ return(NO_CHANGE);
+ }
+
+ // if short name field is different from the curretly selected item
+ if (lstrcmpi(rgch, (*prgDbt)[*piCurrent].szShortName) != 0) {
+ for (i=0; i<*pcDbt; i++) {
+ if (i != *piCurrent) {
+ if (lstrcmpi(rgch, (*prgDbt)[i].szShortName) == 0) {
+ MessageBox( hDlg, "Short Names must be unique", NULL, MB_OK);
+ return(LIST_ERROR);
+ }
+ }
+ }
+ // else add the new item
+
+ // if we just deleted this item, don't add it again just because we
+ // moved the cursor. Otherwise, the user must have made changes, add
+ // the new item.
+ if (! fDeleted) {
+ return AddItem(hDlg,
+ prgDbt,
+ pcDbt,
+ piCurrent,
+ pMaxStringExtent,
+ TabStop);
+ } else {
+ return(NO_CHANGE);
+ }
+
+ } else {
+ // else (short name is same as current)
+ // if any other fields are different, get the changes
+
+ GetDlgItemText(hDlg, ID_DESCRIPTION, rgch, sizeof(rgch));
+ if (lstrcmpi(rgch, (*prgDbt)[*piCurrent].szLongName)) {
+ free((*prgDbt)[*piCurrent].szLongName);
+ (*prgDbt)[*piCurrent].szLongName = _strdup(rgch);
+ fChange = TRUE;
+ fChangeDescription = TRUE;
+ }
+
+ GetDlgItemText(hDlg, ID_PATH, rgch, sizeof(rgch));
+ if (lstrcmpi(rgch, (*prgDbt)[*piCurrent].szDllName)) {
+ free((*prgDbt)[*piCurrent].szDllName);
+ (*prgDbt)[*piCurrent].szDllName = _strdup(rgch);
+ fChange = TRUE;
+ }
+
+ GetDlgItemText(hDlg, ID_PARAMETERS, rgch, sizeof(rgch));
+ if (lstrcmpi(rgch, (*prgDbt)[*piCurrent].szParam)) {
+ free((*prgDbt)[*piCurrent].szParam);
+ (*prgDbt)[*piCurrent].szParam = _strdup(rgch);
+ fChange = TRUE;
+ }
+
+ if (IsDlgButtonChecked(hDlg, ID_DEFAULT)) {
+ if (! (*prgDbt)[*piCurrent].fDefault) {
+ fChange = TRUE;
+ }
+ for (i=0; i<*pcDbt; i++) {
+ (*prgDbt)[i].fDefault = FALSE;
+ }
+ (*prgDbt)[*piCurrent].fDefault = TRUE;
+ } else {
+ if ((*prgDbt)[*piCurrent].fDefault) {
+ fChange = TRUE;
+ }
+ (*prgDbt)[*piCurrent].fDefault = FALSE;
+ }
+ if (fChange) {
+ // update list box display
+ SendDlgItemMessage( hDlg, ID_KNOWN_DLLS, LB_DELETESTRING,
+ *piCurrent, 0);
+
+ sprintf(rgch, "%s\t%s", (*prgDbt)[*piCurrent].szShortName,
+ (*prgDbt)[*piCurrent].szLongName);
+
+ if (fChangeDescription) { // user could have shortened the
+ // longest list box string
+ ScanSetHorizontalScrollExtent(hDlg, *prgDbt, *pcDbt,
+ pMaxStringExtent, TabStop);
+ } else {
+ SetHorizontalScrollExtent(hDlg, rgch, pMaxStringExtent,
+ TabStop);
+ }
+
+ *piCurrent = SendDlgItemMessage( hDlg, ID_KNOWN_DLLS, LB_ADDSTRING,
+ 0, (LPARAM) rgch);
+ }
+ }
+ return(fChange ? LIST_CHANGED : NO_CHANGE);
+}
+
+
+LONG APIENTRY
+DebugDllDlgProc(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routine contains the window procedure for transport dll selection
+ dialog
+
+Arguments:
+
+ hDlg - Supplies the handle to the dialog window
+ msg - Supplies the message to be processed
+ wParam - Supplies information about the message
+ lParam - Supplies information about the message
+
+Return Value:
+
+ return-value - Description of conditions needed to return value.
+
+--*/
+
+{
+ int i;
+ char rgch[MAX_LIST_BOX_STRING];
+ static LPTRANSPORT_LAYER rgDbt;
+ static int cDbt;
+ static int idx;
+ static INT MaxStringExtent;
+ static INT TabStop;
+ static BOOL fDeleted;
+
+
+ switch( msg ) {
+ /*
+ * This section sets up the dialog and initializes the fields.
+ */
+
+ case WM_INITDIALOG:
+
+ // Don't accept more characters in the edit boxes than they can hold
+ SendDlgItemMessage(hDlg, ID_SHORT_NAME, EM_LIMITTEXT,
+ (WPARAM)MAX_SHORT_NAME, 0);
+ SendDlgItemMessage(hDlg, ID_DESCRIPTION, EM_LIMITTEXT,
+ (WPARAM)MAX_LONG_NAME, 0);
+ SendDlgItemMessage(hDlg, ID_PATH, EM_LIMITTEXT,
+ (WPARAM)MAX_LONG_NAME, 0);
+ SendDlgItemMessage(hDlg, ID_PARAMETERS, EM_LIMITTEXT,
+ (WPARAM)MAX_LONG_NAME, 0);
+
+ TabStop = 13 * 4; // 13 chars * 4 dlg box units/char: A magic number
+ // that approximates the width of 7 (our maximum
+ // ShortName length) of the widest characters (W in
+ // the default system proportional font).
+
+ SendDlgItemMessage(hDlg, ID_KNOWN_DLLS, LB_SETTABSTOPS, (WPARAM)1,
+ (LPARAM)&TabStop);
+
+ idx = LB_ERR;
+ if (CDbt == 0) {
+ RgDbt = RegGetTransportLayers( &CDbt );
+ }
+
+ cDbt = CDbt;
+ rgDbt = (LPTRANSPORT_LAYER) malloc(sizeof(TRANSPORT_LAYER)*cDbt);
+ fDeleted = FALSE;
+
+ memcpy(rgDbt, RgDbt, sizeof(TRANSPORT_LAYER)*cDbt);
+
+ for (i=0; i<cDbt; i++) {
+ sprintf(rgch, "%s\t%s", RgDbt[i].szShortName, RgDbt[i].szLongName);
+ SendDlgItemMessage(hDlg, ID_KNOWN_DLLS, LB_ADDSTRING, 0,
+ (LPARAM) rgch);
+ }
+ for (i=0; i<cDbt; i++) {
+ long idx;
+
+ sprintf(rgch, "%s\t", RgDbt[i].szShortName);
+ idx = SendDlgItemMessage(hDlg, ID_KNOWN_DLLS, LB_FINDSTRING, 0,
+ (LPARAM) rgch);
+ rgDbt[idx].szShortName = _strdup(RgDbt[i].szShortName);
+ rgDbt[idx].szLongName = _strdup(RgDbt[i].szLongName);
+ rgDbt[idx].szDllName = _strdup(RgDbt[i].szDllName);
+ rgDbt[idx].szParam = _strdup(RgDbt[i].szParam);
+ rgDbt[idx].fDefault = RgDbt[i].fDefault;
+ if (RgDbt[i].fDefault) {
+ ITransportLayer = idx;
+ }
+ }
+
+ // if there are entries, but there is no default specified, make the
+ // first entry the default.
+ if (cDbt && (ITransportLayer == NO_TRANSPORT_LAYER_SELECTED)) {
+ ITransportLayer = 0;
+ }
+
+ ScanSetHorizontalScrollExtent(hDlg, rgDbt, cDbt, &MaxStringExtent,
+ TabStop);
+ SendDlgItemMessage(hDlg, ID_KNOWN_DLLS, LB_SETCURSEL, ITransportLayer, 0);
+ PostMessage(hDlg, WM_COMMAND, (LBN_SELCHANGE << 16) | ID_KNOWN_DLLS, 0);
+
+ idx = ITransportLayer;
+ return(TRUE); // tell Windows to set focus to 1st control
+ break;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam )) {
+
+ case ID_KNOWN_DLLS:
+ switch( HIWORD( wParam )) {
+ case LBN_SELCHANGE: /* User clicks on selection */
+
+ // check if the values have been changed
+ //
+ switch (CheckChangeItem(hDlg, &rgDbt, &cDbt, &idx,
+ &MaxStringExtent, TabStop, fDeleted)) {
+ case NO_CHANGE:
+ case LIST_CHANGED:
+ fDeleted = FALSE;
+ break;
+ case LIST_ERROR:
+ fDeleted = FALSE;
+ return(TRUE);
+ }
+
+ idx = SendDlgItemMessage( hDlg, ID_KNOWN_DLLS, LB_GETCURSEL, 0, 0);
+
+ if (idx == LB_ERR) {
+ SetDlgItemText( hDlg, ID_SHORT_NAME, "");
+ SetDlgItemText( hDlg, ID_DESCRIPTION, "");
+ SetDlgItemText( hDlg, ID_PATH, "");
+ SetDlgItemText( hDlg, ID_PARAMETERS, "");
+ CheckDlgButton( hDlg, ID_DEFAULT, FALSE);
+ } else {
+ SetDlgItemText( hDlg, ID_SHORT_NAME, rgDbt[idx].szShortName);
+ SetDlgItemText( hDlg, ID_DESCRIPTION, rgDbt[idx].szLongName);
+ SetDlgItemText( hDlg, ID_PATH, rgDbt[idx].szDllName);
+ SetDlgItemText( hDlg, ID_PARAMETERS, rgDbt[idx].szParam);
+ CheckDlgButton( hDlg, ID_DEFAULT, rgDbt[idx].fDefault);
+ }
+ }
+ break;
+
+ case ID_DELETE:
+ if (idx == LB_ERR) {
+ MessageBeep(0);
+ } else {
+ fDeleted = TRUE;
+ // free string memory for deleted item
+ free(rgDbt[idx].szShortName);
+ free(rgDbt[idx].szLongName);
+ free(rgDbt[idx].szDllName);
+ free(rgDbt[idx].szParam);
+
+ for (i=idx; i<cDbt-1; i++) {
+ rgDbt[i] = rgDbt[i+1];
+ }
+ cDbt -= 1;
+
+ SendDlgItemMessage( hDlg, ID_KNOWN_DLLS, LB_DELETESTRING, idx, 0);
+
+ // recompute the list box's horizontal extent because we could
+ // have removed the longest string.
+ ScanSetHorizontalScrollExtent(hDlg, rgDbt, cDbt,
+ &MaxStringExtent, TabStop);
+ idx = LB_ERR;
+ }
+ SetDefaultButton(hDlg, IDOK);
+ break;
+
+ case ID_ADD:
+ fDeleted = FALSE;
+ AddItem(hDlg, &rgDbt, &cDbt, &idx, &MaxStringExtent, TabStop);
+ SetDefaultButton(hDlg, IDOK);
+ return(TRUE);
+
+ case ID_ADVANCED:
+ DialogBoxParam( GetModuleHandle( NULL ),
+ MAKEINTRESOURCE(DLG_KERNELDBG),
+ hDlg,
+ DlgKernelDbg,
+ (LPARAM) &rgDbt[idx].KdParams
+ );
+ SetDefaultButton(hDlg, IDOK);
+ return(TRUE);
+
+ case IDOK:
+ // IF ShortName is new, add the item.
+ // ELSE IF any other field has changed, CHANGE the current item.
+
+ //
+ // check if the values have been changed
+ //
+ fDeleted = FALSE;
+ switch (CheckChangeItem(hDlg, &rgDbt, &cDbt, &idx,
+ &MaxStringExtent, TabStop, fDeleted)) {
+ case NO_CHANGE:
+ case LIST_CHANGED:
+ break;
+ case LIST_ERROR: // get user to fix it before OK
+ return(TRUE);
+ }
+
+ for (i=0; i<(int)CDbt; i++) {
+ free(RgDbt[i].szShortName);
+ free(RgDbt[i].szLongName);
+ free(RgDbt[i].szDllName);
+ free(RgDbt[i].szParam);
+ }
+ free(RgDbt);
+
+ RgDbt = rgDbt;
+
+ CDbt = cDbt;
+
+ if (idx < 0 || idx >= (int)CDbt) {
+ ITransportLayer = NO_TRANSPORT_LAYER_SELECTED;
+ } else {
+ ITransportLayer = idx;
+ }
+
+ FTLChanged = TRUE;
+
+ RegSaveTransportLayers( RgDbt, CDbt );
+
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ case IDCANCEL:
+ for (i=0; i<cDbt; i++) {
+ free(rgDbt[i].szShortName);
+ free(rgDbt[i].szLongName);
+ free(rgDbt[i].szDllName);
+ free(rgDbt[i].szParam);
+ }
+ free(rgDbt);
+
+ EndDialog(hDlg, FALSE); // FALSE says "Discard the Changes"
+ return TRUE;
+
+ case ID_HELP:
+ WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_TRANSPORT_HELP);
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/private/windbg/remote/shell/debugger.c b/private/windbg/remote/shell/debugger.c
new file mode 100644
index 000000000..3cf2645be
--- /dev/null
+++ b/private/windbg/remote/shell/debugger.c
@@ -0,0 +1,384 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ debugger.c
+
+Abstract:
+
+ This file implements the debugger.
+
+Author:
+
+ Wesley Witt (wesw) 1-Nov-1993
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "emdm.h"
+#include "tl.h"
+#include "dbgver.h"
+#include "resource.h"
+#include "windbgrm.h"
+
+
+
+UINT CbSendBuf;
+LPBYTE LpSendBuf;
+BYTE DmMsg[4096];
+DWORD nextHtid;
+HTID htidBpt;
+HANDLE hEventAttach;
+HANDLE hEventEntryPoint;
+LPDBF lpdbf;
+GOP gop = {0};
+
+
+
+
+/**** SENDREQUEST - Send a request to the DM ****
+ * *
+ * PURPOSE: *
+ * Send a DMF request to the DM. *
+ * *
+ * INPUTS: *
+ * dmf - the request to send *
+ * hpid - the process *
+ * htid - the thread *
+ * *
+ * OUTPUTS: *
+ * xosd - error code indicating if request was sent successfully *
+ * LpDmMsg - global buffer filled in with returned data *
+ * *
+ * IMPLEMENTATION: *
+ * Unlike SendCommand, this function will wait for data to be *
+ * returned from the DM before returning to the caller. *
+ * *
+ ***************************************************************************/
+XOSD
+SendRequest(
+ DMF dmf,
+ HPID hpid,
+ HTID htid
+ )
+{
+ DBB dbb;
+ XOSD xosd;
+
+ dbb.dmf = dmf;
+ dbb.hpid = hpid;
+ dbb.htid = htid;
+
+ xosd = TLFunc( tlfRequest, hpid, sizeof ( DBB ), &dbb );
+
+ return xosd;
+}
+
+/**** SENDREQUESTX - Send a request with parameters to the DM ****
+ * *
+ * PURPOSE: *
+ * Send a DMF request and its parameter info to the DM. *
+ * *
+ * INPUTS: *
+ * dmf - the request to send *
+ * hpid - the process *
+ * htid - the thread *
+ * wLen - number of bytes in lpv *
+ * lpv - pointer to additional info needed by the DM; contents are *
+ * dependent on the DMF *
+ * *
+ * OUTPUTS: *
+ * xosd - error code indicating if request was sent successfully *
+ * *
+ * IMPLEMENTATION: *
+ * Unlike SendCommand, this function will wait for data to be *
+ * returned from the DM before returning to the caller. *
+ * *
+ ***************************************************************************/
+XOSD
+SendRequestX(
+ DMF dmf,
+ HPID hpid,
+ HTID htid,
+ UINT wLen,
+ LPV lpv
+ )
+{
+ PDBB pdbb;
+ XOSD xosd;
+
+ if (wLen + sizeof(DBB) > CbSendBuf) {
+ if (LpSendBuf) {
+ free(LpSendBuf);
+ }
+ CbSendBuf = sizeof(DBB) + wLen;
+ LpSendBuf = malloc(CbSendBuf);
+ }
+
+ if (!LpSendBuf) {
+ return xosdOutOfMemory;
+ }
+
+ pdbb = (PDBB)LpSendBuf;
+
+ pdbb->dmf = dmf;
+ pdbb->hpid = hpid;
+ pdbb->htid = htid;
+ _fmemcpy ( pdbb->rgbVar, lpv, wLen );
+
+ xosd = TLFunc( tlfRequest, hpid, sizeof ( DBB ) + wLen, (LPV)pdbb );
+
+ return xosd;
+}
+
+XOSD PASCAL LOADDS
+TLCallBack (
+ HPID hpid,
+ UINT cb,
+ LPV lpv
+ )
+/*++
+
+Routine Description:
+
+ Call the native execution model for the process hpid with the
+ package sent from the transport layer. This is how the DM
+ sends things to its native EM.
+
+Arguments:
+
+ hpid - Supplies handle to the process
+
+ cb - Supplies size in bytes of the packet
+
+ lpv - Supplies the packet
+
+Return Value:
+
+ xosdNone - Success
+
+ Any return value that can be generated by a native execution model.
+
+--*/
+{
+ LPRTP lprtp = (LPRTP) lpv;
+ BYTE b;
+ XOSD xosd;
+ HTID htid;
+
+
+ DEBUG_OUT3( "tlcallback %x [hpid=(%d) htid=(%d)]\n", lprtp->dbc, hpid, lprtp->htid );
+
+ switch(lprtp->dbc) {
+ case dbcModLoad:
+ b = 1;
+ TLFunc( tlfReply, hpid, 1, &b );
+ break;
+
+ case dbcCreateThread:
+ htid = (HTID) ++nextHtid;
+ TLFunc( tlfReply, hpid, sizeof(htid), (LPV)&htid );
+ xosd = SendRequestX( dmfGo, hpid, htid, sizeof(gop), &gop );
+ break;
+
+ case dbcBpt:
+ htidBpt = lprtp->htid;
+ SetEvent( hEventAttach );
+ break;
+
+ case dbcLoadComplete:
+ htidBpt = lprtp->htid;
+ SetEvent( hEventAttach );
+ break;
+
+ case dbcEntryPoint:
+ htidBpt = lprtp->htid;
+ SetEvent( hEventEntryPoint );
+ break;
+
+ default:
+ break;
+ }
+
+ return xosdNone;
+}
+
+BOOL
+ConnectDebugger(
+ VOID
+ )
+{
+ extern AVS Avs;
+ DBGVERSIONPROC pVerProc;
+ LPAVS pavs;
+ CHAR buf[256];
+ DWORD cb;
+ LPTRANSPORT_LAYER lpTl;
+
+
+ lpTl = RegGetDefaultTransportLayer( szTlName );
+ if (!lpTl) {
+ return FALSE;
+ }
+
+ if ((hTransportDll = LoadLibrary( lpTl->szDllName )) == NULL) {
+ return FALSE;
+ }
+
+ pVerProc = (DBGVERSIONPROC)GetProcAddress(hTransportDll, DBGVERSIONPROCNAME);
+ if (!pVerProc) {
+ return FALSE;
+ }
+
+ pavs = (*pVerProc)();
+
+ if (pavs->rgchType[0] != 'T' || pavs->rgchType[1] != 'L') {
+ return FALSE;
+ }
+
+ if (Avs.rlvt != pavs->rlvt) {
+ return FALSE;
+ }
+
+ if (Avs.iRmj != pavs->iRmj) {
+ return FALSE;
+ }
+
+ if ((TLFunc = (TLFUNC)GetProcAddress(hTransportDll, "TLFunc")) == NULL) {
+ return FALSE;
+ }
+
+ if (TLFunc( tlfRegisterDBF, hpidNull, wNull, (LONG) lpdbf ) != xosdNone) {
+ return FALSE;
+ }
+
+ if (TLFunc( tlfGlobalInit, hpidNull, wNull, (LONG) TLCallBack ) != xosdNone) {
+ return FALSE;
+ }
+
+ cb = sizeof(buf);
+ GetComputerName( buf, &cb );
+ strcat( buf, " " );
+ strcat( buf, lpTl->szParam );
+
+ if (TLFunc( tlfInit, hpidNull, NULL, (LONG) buf ) != xosdNone) {
+ return FALSE;
+ }
+
+ if (TLFunc( tlfSetBuffer, hpidNull, sizeof(DmMsg), &DmMsg ) != xosdNone) {
+ return FALSE;
+ }
+
+ if (TLFunc( tlfConnect, hpidNull, 0, NULL ) != xosdNone) {
+ return FALSE;
+ }
+
+ if (SendRequest( dmfInit, hpidNull, htidNull ) != xosdNone) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+DisConnectDebugger(
+ HPID hpid
+ )
+{
+ if (TLFunc( tlfDisconnect, hpid, NULL, htidBpt ) != xosdNone) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+AttachProcess(
+ HPID hpid,
+ DBG_ACTIVE_STRUCT *das
+ )
+{
+ hEventAttach = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+ if (SendRequest( dmfCreatePid, hpid, htidNull ) != xosdNone) {
+ return FALSE;
+ }
+
+ if (SendRequestX(dmfDebugActive, hpid, htidNull, sizeof(*das), das) != xosdNone) {
+ return FALSE;
+ }
+
+ WaitForSingleObject( hEventAttach, INFINITE );
+
+ CloseHandle( hEventAttach );
+
+ return TRUE;
+}
+
+
+BOOL
+ProgramLoad(
+ HPID hpid,
+ LPSTR lpProgName
+ )
+{
+ BYTE buf[512];
+ LPPRL lpprl = (LPPRL) &buf[0];
+ SETPTH *setpth = (SETPTH *)&buf[0];
+
+
+ hEventAttach = CreateEvent( NULL, TRUE, FALSE, NULL );
+ hEventEntryPoint = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+ if (SendRequest( dmfCreatePid, hpid, htidNull ) != xosdNone) {
+ return FALSE;
+ }
+
+ setpth->Set = TRUE;
+ setpth->Path[0] = '\0';
+ if (SendRequestX( dmfSetPath, hpid, htidNull, sizeof(SETPTH), setpth ) != xosdNone) {
+ return FALSE;
+ }
+
+ lpprl->ulChildFlags = ulfMultiProcess;
+ strcpy( lpprl->lszCmdLine, lpProgName );
+ lpprl->cbCmdLine = strlen( lpprl->lszCmdLine );
+ if (SendRequestX(dmfProgLoad, hpid, htidNull, sizeof(*lpprl)+lpprl->cbCmdLine, lpprl) != xosdNone) {
+ return FALSE;
+ }
+
+ //
+ // wait for the loader breakpoint
+ //
+ WaitForSingleObject( hEventAttach, INFINITE );
+ SendRequestX( dmfGo, hpid, htidBpt, sizeof(gop), &gop );
+
+ //
+ // wait for the entrypoint breakpoint
+ //
+ WaitForSingleObject( hEventEntryPoint, INFINITE );
+ SendRequestX( dmfGo, hpid, htidBpt, sizeof(gop), &gop );
+
+ //
+ // cleanup
+ //
+ CloseHandle( hEventAttach );
+ CloseHandle( hEventEntryPoint );
+
+ return TRUE;
+}
diff --git a/private/windbg/remote/shell/gui.c b/private/windbg/remote/shell/gui.c
new file mode 100644
index 000000000..44a3f43f2
--- /dev/null
+++ b/private/windbg/remote/shell/gui.c
@@ -0,0 +1,221 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ gui.c
+
+Abstract:
+
+ This file implements the ui.
+
+Author:
+
+ Wesley Witt (wesw) 1-Nov-1993
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <shellapi.h>
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "emdm.h"
+#include "tl.h"
+#include "dbgver.h"
+#include "resource.h"
+#include "windbgrm.h"
+
+
+#ifdef DEBUGVER
+DEBUG_VERSION('W', 'R', "WinDbg Remote Shell, DEBUG")
+#else
+RELEASE_VERSION('W', 'R', "WinDbg Remote Shell")
+#endif
+
+#define DEF_POS_X 0 // window position
+#define DEF_POS_Y 0
+#define DEF_SIZE_X 400 // window size
+#define DEF_SIZE_Y 200
+
+HANDLE hMessageThread;
+HANDLE HAccTable;
+HWND HWndFrame;
+HANDLE hInst;
+CHAR szAppName[MAX_PATH];
+CHAR szTransportLayers[4096];
+CHAR szHelpFileName[_MAX_PATH];
+
+extern CHAR ClientId[];
+extern BOOL fConnected;
+extern HANDLE hEventLoadTl;
+
+LONG APIENTRY
+DebugDllDlgProc(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+
+LONG APIENTRY
+MainWndProc(
+ HWND hWnd,
+ UINT message,
+ UINT wParam,
+ LONG lParam
+ )
+{
+ char s[MAX_PATH];
+
+ switch (message) {
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDM_OPTIONS_EXIT:
+ SendMessage( hWnd, WM_CLOSE, 0, 0 );
+ break;
+
+ case IDM_OPTIONS_DEBUG_DLLS:
+ DialogBox( hInst,
+ MAKEINTRESOURCE(DLG_TRANSPORTS),
+ hWnd,
+ DebugDllDlgProc
+ );
+ SetEvent( hEventLoadTl );
+ break;
+
+ case IDM_HELP_CONTENTS:
+ WinHelp(hWnd, szHelpFileName, HELP_CONTENTS, 0L);
+ break;
+
+ case IDM_HELP_ABOUT:
+ ShellAbout(hWnd, szAppName, "", LoadIcon(hInst, "WindbgRmIcon"));
+ break;
+
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ if (wParam == IDM_STATUS) {
+ if (fConnected) {
+ sprintf(s, "Connected to %s",ClientId);
+ } else {
+ sprintf(s, "Not Connected - Last Connection was to %s", ClientId);
+ }
+ MessageBox( hWnd,
+ s,
+ "WinDbgRm Connection Status",
+ MB_OK | MB_ICONINFORMATION
+ );
+ }
+ break;
+
+ case WM_DESTROY:
+ ExitProcess( 0 );
+ break;
+ }
+
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+
+DWORD
+MessagePumpThread(
+ LPVOID lpvArg
+ )
+{
+ MSG msg;
+ WNDCLASS WndClass;
+ HMENU hMenu;
+
+
+ hInst = GetModuleHandle( NULL );
+ LoadString( hInst, IDS_APPNAME, szAppName, sizeof(szAppName) );
+
+ WndClass.cbClsExtra = 0;
+ WndClass.cbWndExtra = 0;
+ WndClass.lpszClassName = szAppName;
+ WndClass.lpszMenuName = szAppName;
+ WndClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
+ WndClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+ WndClass.hInstance = hInst;
+ WndClass.lpfnWndProc = (WNDPROC)MainWndProc;
+ WndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ WndClass.hIcon = LoadIcon( hInst, "WindbgRmIcon" );
+
+ HAccTable = LoadAccelerators( hInst, szAppName );
+
+ RegisterClass( &WndClass );
+
+ HWndFrame = CreateWindow( szAppName,
+ szAppName,
+ WS_TILEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ DEF_SIZE_X,
+ DEF_SIZE_Y,
+ NULL,
+ NULL,
+ hInst,
+ NULL
+ );
+
+ if (!HWndFrame) {
+ return FALSE;
+ }
+
+ ShowWindow( HWndFrame, SW_SHOWMINNOACTIVE );
+
+ hMenu = GetSystemMenu( HWndFrame, FALSE );
+ AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
+ AppendMenu( hMenu, MF_STRING, IDM_STATUS, "Connection Status..." );
+
+ while (GetMessage( &msg, NULL, 0, 0 )) {
+ TranslateAccelerator( HWndFrame, HAccTable, &msg );
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+
+ return 0;
+}
+
+
+BOOL
+InitApplication(
+ VOID
+ )
+{
+ DWORD tid;
+ char szDrive[_MAX_DRIVE];
+ char szDir[_MAX_DIR];
+ char szFName[_MAX_FNAME];
+ char szExt[_MAX_EXT];
+
+ hMessageThread = CreateThread( NULL, 0, MessagePumpThread, 0, 0, &tid );
+ SetThreadPriority( hMessageThread, THREAD_PRIORITY_ABOVE_NORMAL );
+
+ //
+ // Build help file name from executable path
+ //
+
+ (void)GetModuleFileName(hInst, szHelpFileName, _MAX_PATH);
+ _splitpath(szHelpFileName, szDrive, szDir, szFName, szExt);
+ strcpy(szHelpFileName, szDrive);
+ strcat(szHelpFileName, szDir);
+ strcat(szHelpFileName, "windbg.hlp");
+
+ return TRUE;
+}
+
+
diff --git a/private/windbg/remote/shell/kdopt.c b/private/windbg/remote/shell/kdopt.c
new file mode 100644
index 000000000..ccc9bab36
--- /dev/null
+++ b/private/windbg/remote/shell/kdopt.c
@@ -0,0 +1,241 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ kdopt.c
+
+Abstract:
+
+
+Author:
+
+ Wesley Witt (wesw) 26-July-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "emdm.h"
+#include "tl.h"
+#include "dbgver.h"
+#include "resource.h"
+#include "windbgrm.h"
+
+
+LPSTR KdComPorts[] = { "COM1", "COM2", "COM3", "COM4" };
+LPSTR KdPlatforms[] = { "X86", "MIPS", "ALPHA", "PPC"};
+DWORD KdBaudRates[] = { 1200, 2400, 4800, 9600, 19200, 38400, 56000 };
+DWORD KdCacheSizes[] = { 102400, 512000, 1024000 };
+
+#define KdMaxComPorts (sizeof(KdComPorts)/sizeof(LPSTR))
+#define KdMaxPlatforms (sizeof(KdPlatforms)/sizeof(LPSTR))
+#define KdMaxBaudRates (sizeof(KdBaudRates)/sizeof(DWORD))
+#define KdMaxCacheSizes (sizeof(KdCacheSizes)/sizeof(DWORD))
+
+void EnableControls( HWND hDlg, BOOL fMode );
+
+LPKDPARAMS KdParams;
+
+
+BOOL
+DlgKernelDbg(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ char rgch[256];
+ BOOL b;
+ BOOL fChange = FALSE;
+ int i;
+ HWND hCtl;
+ DWORD tmp;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ KdParams = (LPKDPARAMS) lParam;
+
+ if (KdParams->fEnable) {
+ CheckDlgButton( hDlg, ID_KD_ENABLE, 1);
+ }
+
+ if (KdParams->fGoExit) {
+ CheckDlgButton( hDlg, ID_KD_GOEXIT, 1);
+ }
+
+ if (KdParams->fVerbose) {
+ CheckDlgButton( hDlg, ID_KD_VERBOSE, 1);
+ }
+
+ if (KdParams->fInitialBp) {
+ CheckDlgButton( hDlg, ID_KD_INITIALBP, 1);
+ }
+
+ if (KdParams->fDefer) {
+ CheckDlgButton( hDlg, ID_KD_DEFER, 1);
+ }
+
+ if (KdParams->fUseModem) {
+ CheckDlgButton( hDlg, ID_KD_MODEM, 1);
+ }
+
+ hCtl = GetDlgItem(hDlg,ID_KD_PORT);
+ sprintf( rgch, "COM%d", KdParams->dwPort );
+ for (i=0; i<KdMaxComPorts; i++) {
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)KdComPorts[i]);
+ if (strcmp( rgch, KdComPorts[i] ) == 0) {
+ SendMessage(hCtl, CB_SETCURSEL, i, 0);
+ }
+ }
+
+ hCtl = GetDlgItem(hDlg,ID_KD_BAUDRATE);
+ for (i=0; i<KdMaxBaudRates; i++) {
+ sprintf( rgch, "%d", KdBaudRates[i] );
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)rgch);
+ if (KdParams->dwBaudRate == KdBaudRates[i] ) {
+ SendMessage(hCtl, CB_SETCURSEL, i, 0);
+ }
+ }
+
+ hCtl = GetDlgItem(hDlg,ID_KD_CACHE);
+ for (i=0; i<KdMaxCacheSizes; i++) {
+ sprintf( rgch, "%d", KdCacheSizes[i] );
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)rgch);
+ if (KdParams->dwCache == KdCacheSizes[i] ) {
+ SendMessage(hCtl, CB_SETCURSEL, i, 0);
+ }
+ }
+
+ hCtl = GetDlgItem(hDlg,ID_KD_PLATFORM);
+ for (i=0; i<KdMaxPlatforms; i++) {
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)KdPlatforms[i]);
+ if (KdParams->dwPlatform == (DWORD)i) {
+ SendMessage(hCtl, CB_SETCURSEL, i, 0);
+ }
+ }
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK :
+
+ /*
+ * Transfer the options to global
+ *
+ * Now start looking at the rest and determine what needs to
+ * be updated
+ */
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_ENABLE) != 0);
+ if (b != KdParams->fEnable) {
+ KdParams->fEnable = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_GOEXIT) != 0);
+ if (b != KdParams->fGoExit) {
+ KdParams->fGoExit = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_VERBOSE) != 0);
+ if (b != KdParams->fVerbose) {
+ KdParams->fVerbose = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_INITIALBP) != 0);
+ if (b != KdParams->fInitialBp) {
+ KdParams->fInitialBp = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_DEFER) != 0);
+ if (b != KdParams->fDefer) {
+ KdParams->fDefer = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_MODEM) != 0);
+ if (b != KdParams->fUseModem) {
+ KdParams->fUseModem = b;
+ fChange = TRUE;
+ }
+
+ if (GetDlgItemText( hDlg, ID_KD_PORT, rgch, sizeof(rgch) )) {
+ for (i=0; i<KdMaxComPorts; i++) {
+ if (strcmp(KdComPorts[i],rgch)==0) {
+ KdParams->dwPort = i+1;
+ fChange = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (GetDlgItemText( hDlg, ID_KD_BAUDRATE, rgch, sizeof(rgch) )) {
+ tmp = atol( rgch );
+ for (i=0; i<KdMaxBaudRates; i++) {
+ if (KdBaudRates[i] == tmp) {
+ KdParams->dwBaudRate = tmp;
+ fChange = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (GetDlgItemText( hDlg, ID_KD_CACHE, rgch, sizeof(rgch) )) {
+ tmp = atol( rgch );
+ for (i=0; i<KdMaxCacheSizes; i++) {
+ if (KdCacheSizes[i] == tmp) {
+ KdParams->dwCache = tmp;
+ fChange = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (GetDlgItemText( hDlg, ID_KD_PLATFORM, rgch, sizeof(rgch) )) {
+ for (i=0; i<KdMaxPlatforms; i++) {
+ if (strcmp(KdPlatforms[i],rgch)==0) {
+ KdParams->dwPlatform = i;
+ fChange = TRUE;
+ break;
+ }
+ }
+ }
+
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDCANCEL:
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+#if 0
+ case IDWINDBGHELP: /* User Help */
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_DBUGOPT_HELP));
+ return (TRUE);
+#endif
+
+ default:
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/private/windbg/remote/shell/makefile b/private/windbg/remote/shell/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/remote/shell/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/remote/shell/registry.c b/private/windbg/remote/shell/registry.c
new file mode 100644
index 000000000..78c8b62d0
--- /dev/null
+++ b/private/windbg/remote/shell/registry.c
@@ -0,0 +1,607 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ gui.c
+
+Abstract:
+
+ This file implements all access to the registry for WinDbgRm
+
+Author:
+
+ Wesley Witt (wesw) 1-Nov-1993
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "emdm.h"
+#include "tl.h"
+#include "dbgver.h"
+#include "resource.h"
+#include "windbgrm.h"
+
+
+//
+// string constants for accessing the registry
+// there is a string constant here for each key and each value
+// that is accessed in the registry.
+//
+#define REGKEY_WINDBGRM "software\\microsoft\\WinDbgRm\\0010"
+#define REGKEY_KD_OPTIONS "Kernel Debugger Options"
+
+#define WS_STR_LONGNAME "Description"
+#define WS_STR_DLLNAME "Dll_Path"
+#define WS_STR_PARAMS "Parameters"
+#define WS_STR_DEFAULT "Default"
+
+#define WS_STR_KD_VERBOSE "Verbose"
+#define WS_STR_KD_INITIALBP "Initial Break Point"
+#define WS_STR_KD_DEFER "Defer Symbol Load"
+#define WS_STR_KD_MODEM "Use Modem Controls"
+#define WS_STR_KD_PORT "Port"
+#define WS_STR_KD_BAUDRATE "Baudrate"
+#define WS_STR_KD_CACHE "Cache Size"
+#define WS_STR_KD_PLATFORM "Platform"
+#define WS_STR_KD_ENABLE "Enable"
+#define WS_STR_KD_GOEXIT "Go On Exit"
+
+#define RegSetString(hKey,szSubKey,lpsz) \
+ RegSetValueEx( hKey, szSubKey, 0, REG_SZ, lpsz, strlen(lpsz)+1 )
+
+#define RegSetDword(hKey,szSubKey,dw) \
+ RegSetValueEx( hKey, szSubKey, 0, REG_DWORD, (LPBYTE)&dw, 4 )
+
+#define RegGetString(hKey,szSubKey,lpsz) \
+ { \
+ CHAR __buf[256]; \
+ DWORD __len = sizeof(__buf); \
+ DWORD __dwType = 0; \
+ RegQueryValueEx( hKey, szSubKey, 0, &__dwType, __buf, &__len ); \
+ lpsz = _strdup(__buf); \
+ }
+
+#define RegGetDword(hKey,szSubKey,dw) \
+ { \
+ DWORD __len = sizeof(DWORD); \
+ DWORD __dwType = 0; \
+ RegQueryValueEx( hKey, szSubKey, 0, &__dwType, (LPBYTE)&dw, &__len ); \
+ }
+
+
+#define NUM_DEFAULT_TLS 7
+
+TRANSPORT_LAYER DefaultTl[NUM_DEFAULT_TLS] = {
+ "Pipes", "Named pipe transport Layer - PIPE=windbg", "tlpipe.dll", "windbg", 1, 0, 0, 0, 1, 0, 0, 19200, 2, 102400, 0,
+ "PipesKd", "Named pipe transport Layer - PIPE=windbg", "tlpipe.dll", "windbg", 0, 1, 0, 0, 1, 0, 0, 19200, 2, 102400, 0,
+ "Ser300", "Serial Transport Layer on COM1 at 300 Baud", "tlser.dll", "COM1:300", 0, 0, 0, 0, 1, 0, 0, 19200, 2, 102400, 0,
+ "Ser1200", "Serial Transport Layer on COM1 at 1200 Baud", "tlser.dll", "COM1:1200", 0, 0, 0, 0, 1, 0, 0, 19200, 2, 102400, 0,
+ "Ser9600", "Serial Transport Layer on COM1 at 9600 Baud", "tlser.dll", "COM1:9600", 0, 0, 0, 0, 1, 0, 0, 19200, 2, 102400, 0,
+ "Ser192", "Serial Transport Layer on COM1 at 19200 Baud", "tlser.dll", "COM1:19200", 0, 0, 0, 0, 1, 0, 0, 19200, 2, 102400, 0,
+ "Ser5600", "Serial Transport Layer on COM1 at 56000 Baud", "tlser.dll", "COM1:56000", 0, 0, 0, 0, 1, 0, 0, 19200, 2, 102400, 0
+};
+
+
+
+
+HKEY
+RegGetAppKey(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets a handle to the WinDbgRm registry key.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Valid handle - handle opened ok
+ NULL - could not open the handle
+
+--*/
+
+{
+ DWORD rc;
+ HKEY hKeyWindbgRm;
+
+ rc = RegOpenKeyEx( HKEY_CURRENT_USER,
+ REGKEY_WINDBGRM,
+ 0,
+ KEY_QUERY_VALUE | KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
+ &hKeyWindbgRm
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ return NULL;
+ }
+
+ return hKeyWindbgRm;
+}
+
+
+HKEY
+RegGetSubKey(
+ HKEY hKeyWindbgRm,
+ LPSTR lpSubKeyName
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets a handle to the WINDBGRM registry key.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Valid handle - handle opened ok
+ NULL - could not open the handle
+
+--*/
+
+{
+ DWORD rc;
+ HKEY hSubKey;
+
+ rc = RegOpenKeyEx( hKeyWindbgRm,
+ lpSubKeyName,
+ 0,
+ KEY_QUERY_VALUE | KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
+ &hSubKey
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ return NULL;
+ }
+
+ return hSubKey;
+}
+
+
+HKEY
+RegCreateAppKey(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates the WINDBGRM registry key.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Valid handle - handle opened ok
+ NULL - could not open the handle
+
+--*/
+
+{
+ DWORD rc;
+ HKEY hKeyWindbgRm;
+ CHAR szClass[MAX_PATH+1];
+ DWORD dwDisposition;
+
+
+ szClass[0]='\0';
+ rc = RegCreateKeyEx( HKEY_CURRENT_USER,
+ REGKEY_WINDBGRM,
+ 0,
+ szClass,
+ REG_OPTION_NON_VOLATILE,
+ KEY_QUERY_VALUE | KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
+ NULL,
+ &hKeyWindbgRm,
+ &dwDisposition
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ return NULL;
+ }
+
+ return hKeyWindbgRm;
+}
+
+
+HKEY
+RegCreateSubKey(
+ HKEY hKeyWindbgRm,
+ LPSTR lpSubKeyName
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets a handle to the WINDBGRM registry key.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Valid handle - handle opened ok
+ NULL - could not open the handle
+
+--*/
+
+{
+ DWORD rc;
+ HKEY hSubKey;
+ CHAR szClass[MAX_PATH+1];
+ DWORD dwDisposition;
+
+ szClass[0]='\0';
+ rc = RegCreateKeyEx( hKeyWindbgRm,
+ lpSubKeyName,
+ 0,
+ szClass,
+ REG_OPTION_NON_VOLATILE,
+ KEY_QUERY_VALUE | KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
+ NULL,
+ &hSubKey ,
+ &dwDisposition
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ return NULL;
+ }
+
+ return hSubKey;
+}
+
+
+DWORD
+RegGetNumberOfSubKeys(
+ HKEY hKey
+ )
+{
+ CHAR buf[512];
+ LONG rc;
+ DWORD cbClass;
+ DWORD cSubKeys;
+ DWORD cbMaxSubKeyLen;
+ DWORD cbMaxClassLen;
+ DWORD cValues;
+ DWORD cbMaxValueNameLen;
+ DWORD cbMaxValueLen;
+ DWORD cbSecurityDescriptor;
+ FILETIME ftLastWriteTime;
+
+
+ cbClass = sizeof(buf);
+ rc = RegQueryInfoKey( hKey,
+ buf,
+ &cbClass,
+ NULL,
+ &cSubKeys,
+ &cbMaxSubKeyLen,
+ &cbMaxClassLen,
+ &cValues,
+ &cbMaxValueNameLen,
+ &cbMaxValueLen,
+ &cbSecurityDescriptor,
+ &ftLastWriteTime
+ );
+
+ if (rc != ERROR_SUCCESS) {
+ return 0;
+ }
+
+ return cSubKeys;
+}
+
+
+BOOL
+RegGetTransportData(
+ HKEY hKeyWindbgRm,
+ LPSTR lpTransportName,
+ LPTRANSPORT_LAYER lpTl
+ )
+{
+ HKEY hKeyTl;
+ HKEY hKeyKd;
+
+ //
+ // open the registry key for the tl
+ //
+ hKeyTl = RegGetSubKey( hKeyWindbgRm, lpTransportName );
+ if (!hKeyTl) {
+ return FALSE;
+ }
+
+ //
+ // retrieve the data from the registry
+ //
+ lpTl->szShortName = _strdup( lpTransportName );
+ RegGetString( hKeyTl, WS_STR_LONGNAME, lpTl->szLongName );
+ RegGetString( hKeyTl, WS_STR_DLLNAME, lpTl->szDllName );
+ RegGetString( hKeyTl, WS_STR_PARAMS, lpTl->szParam );
+ RegGetDword ( hKeyTl, WS_STR_DEFAULT, lpTl->fDefault );
+
+ //
+ // get the key to the kernel debugger options
+ //
+ hKeyKd = RegGetSubKey( hKeyTl, REGKEY_KD_OPTIONS );
+ if (hKeyKd) {
+ RegGetDword( hKeyKd, WS_STR_KD_VERBOSE, lpTl->KdParams.fVerbose );
+ RegGetDword( hKeyKd, WS_STR_KD_INITIALBP, lpTl->KdParams.fInitialBp );
+ RegGetDword( hKeyKd, WS_STR_KD_DEFER, lpTl->KdParams.fDefer );
+ RegGetDword( hKeyKd, WS_STR_KD_MODEM, lpTl->KdParams.fUseModem );
+ RegGetDword( hKeyKd, WS_STR_KD_PORT, lpTl->KdParams.dwPort );
+ RegGetDword( hKeyKd, WS_STR_KD_BAUDRATE, lpTl->KdParams.dwBaudRate );
+ RegGetDword( hKeyKd, WS_STR_KD_CACHE, lpTl->KdParams.dwCache );
+ RegGetDword( hKeyKd, WS_STR_KD_PLATFORM, lpTl->KdParams.dwPlatform );
+ RegGetDword( hKeyKd, WS_STR_KD_GOEXIT, lpTl->KdParams.fGoExit );
+ RegGetDword( hKeyKd, WS_STR_KD_ENABLE, lpTl->KdParams.fEnable );
+ RegCloseKey( hKeyKd );
+ } else {
+ lpTl->KdParams.fEnable = FALSE;
+ lpTl->KdParams.fVerbose = FALSE;
+ lpTl->KdParams.fInitialBp = FALSE;
+ lpTl->KdParams.fDefer = TRUE;
+ lpTl->KdParams.fUseModem = FALSE;
+ lpTl->KdParams.fGoExit = FALSE;
+ lpTl->KdParams.dwBaudRate = 19200;
+ lpTl->KdParams.dwPort = 2;
+ lpTl->KdParams.dwCache = 102400;
+ lpTl->KdParams.dwPlatform = 0;
+ }
+
+ RegCloseKey( hKeyTl );
+
+ return TRUE;
+}
+
+
+LPTRANSPORT_LAYER
+RegGetTransportLayers(
+ LPDWORD lpdwCount
+ )
+{
+ HKEY hKeyWindbgRm;
+ DWORD i;
+ CHAR buf[4096];
+ LONG rc;
+ DWORD NumTls;
+ LPTRANSPORT_LAYER lpTl;
+
+
+ *lpdwCount = 0;
+
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ RegSaveTransportLayers( DefaultTl, NUM_DEFAULT_TLS );
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ return NULL;
+ }
+ }
+
+ NumTls = RegGetNumberOfSubKeys( hKeyWindbgRm );
+
+ lpTl = (LPTRANSPORT_LAYER) malloc( sizeof(TRANSPORT_LAYER) * NumTls );
+ if (!lpTl) {
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+ }
+
+ for (i=0; i<NumTls; i++) {
+ //
+ // get the next transport layer name
+ //
+ rc = RegEnumKey( hKeyWindbgRm, i, buf, sizeof(buf) );
+ if (rc != ERROR_SUCCESS) {
+ free( lpTl );
+ return NULL;
+ }
+
+ if (!RegGetTransportData( hKeyWindbgRm, buf, &lpTl[i] )) {
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+ }
+ }
+
+ RegCloseKey( hKeyWindbgRm );
+
+ *lpdwCount = i;
+
+ return lpTl;
+}
+
+
+BOOL
+RegSaveTransportLayers(
+ LPTRANSPORT_LAYER lpTl,
+ DWORD dwCount
+ )
+{
+ HKEY hKeyWindbgRm;
+ HKEY hKeyTl;
+ HKEY hKeyKd;
+ DWORD i;
+
+
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ hKeyWindbgRm = RegCreateAppKey();
+ if (!hKeyWindbgRm) {
+ return FALSE;
+ }
+ }
+
+ for (i=0; i<dwCount; i++) {
+
+ hKeyTl = RegGetSubKey( hKeyWindbgRm, lpTl[i].szShortName );
+ if (!hKeyTl) {
+ hKeyTl = RegCreateSubKey( hKeyWindbgRm, lpTl[i].szShortName );
+ if (!hKeyTl) {
+ return FALSE;
+ }
+ }
+
+ RegSetString( hKeyTl, WS_STR_LONGNAME, lpTl[i].szLongName );
+ RegSetString( hKeyTl, WS_STR_DLLNAME, lpTl[i].szDllName );
+ RegSetString( hKeyTl, WS_STR_PARAMS, lpTl[i].szParam );
+ RegSetDword ( hKeyTl, WS_STR_DEFAULT, lpTl[i].fDefault );
+
+ //
+ // get the key to the kernel debugger options
+ //
+ hKeyKd = RegGetSubKey( hKeyTl, REGKEY_KD_OPTIONS );
+ if (!hKeyKd) {
+ hKeyKd = RegCreateSubKey( hKeyTl, REGKEY_KD_OPTIONS );
+ if (!hKeyKd) {
+ return FALSE;
+ }
+ }
+
+ RegSetDword( hKeyKd, WS_STR_KD_VERBOSE, lpTl[i].KdParams.fVerbose );
+ RegSetDword( hKeyKd, WS_STR_KD_INITIALBP, lpTl[i].KdParams.fInitialBp );
+ RegSetDword( hKeyKd, WS_STR_KD_DEFER, lpTl[i].KdParams.fDefer );
+ RegSetDword( hKeyKd, WS_STR_KD_MODEM, lpTl[i].KdParams.fUseModem );
+ RegSetDword( hKeyKd, WS_STR_KD_PORT, lpTl[i].KdParams.dwPort );
+ RegSetDword( hKeyKd, WS_STR_KD_BAUDRATE, lpTl[i].KdParams.dwBaudRate );
+ RegSetDword( hKeyKd, WS_STR_KD_CACHE, lpTl[i].KdParams.dwCache );
+ RegSetDword( hKeyKd, WS_STR_KD_PLATFORM, lpTl[i].KdParams.dwPlatform );
+ RegSetDword( hKeyKd, WS_STR_KD_GOEXIT, lpTl[i].KdParams.fGoExit );
+ RegSetDword( hKeyKd, WS_STR_KD_ENABLE, lpTl[i].KdParams.fEnable );
+
+ RegCloseKey( hKeyKd );
+
+ RegCloseKey( hKeyTl );
+ }
+
+ RegCloseKey( hKeyWindbgRm );
+
+ return TRUE;
+}
+
+
+LPTRANSPORT_LAYER
+RegGetTransportLayer(
+ LPSTR lpTransportName
+ )
+{
+ HKEY hKeyWindbgRm;
+ LPTRANSPORT_LAYER lpTl;
+
+
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ RegSaveTransportLayers( DefaultTl, NUM_DEFAULT_TLS );
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ return NULL;
+ }
+ }
+
+ //
+ // allocate the transport layer memory
+ //
+ lpTl = (LPTRANSPORT_LAYER) malloc( sizeof(TRANSPORT_LAYER) );
+ if (!lpTl) {
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+ }
+
+ if (!RegGetTransportData( hKeyWindbgRm, lpTransportName, lpTl )) {
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+ }
+
+ RegCloseKey( hKeyWindbgRm );
+ return lpTl;
+}
+
+
+LPTRANSPORT_LAYER
+RegGetDefaultTransportLayer(
+ LPSTR lpTlName
+ )
+{
+ HKEY hKeyWindbgRm;
+ DWORD i;
+ CHAR buf[4096];
+ LONG rc;
+ DWORD NumTls;
+ LPTRANSPORT_LAYER lpTl;
+
+
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ RegSaveTransportLayers( DefaultTl, NUM_DEFAULT_TLS );
+ hKeyWindbgRm = RegGetAppKey();
+ if (!hKeyWindbgRm) {
+ return NULL;
+ }
+ }
+
+ NumTls = RegGetNumberOfSubKeys( hKeyWindbgRm );
+
+ lpTl = (LPTRANSPORT_LAYER) malloc( sizeof(TRANSPORT_LAYER) );
+ if (!lpTl) {
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+ }
+
+ for (i=0; i<NumTls; i++) {
+ //
+ // get the next transport layer name
+ //
+ rc = RegEnumKey( hKeyWindbgRm, i, buf, sizeof(buf) );
+ if (rc != ERROR_SUCCESS) {
+ free( lpTl );
+ return NULL;
+ }
+
+ if (!RegGetTransportData( hKeyWindbgRm, buf, lpTl )) {
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+ }
+
+ if (lpTlName && *lpTlName) {
+ if (_stricmp( lpTlName, lpTl->szShortName ) == 0) {
+ RegCloseKey( hKeyWindbgRm );
+ return lpTl;
+ }
+ } else if (lpTl->fDefault) {
+ RegCloseKey( hKeyWindbgRm );
+ return lpTl;
+ }
+ }
+
+ RegCloseKey( hKeyWindbgRm );
+ return NULL;
+}
diff --git a/private/windbg/remote/shell/resource.h b/private/windbg/remote/shell/resource.h
new file mode 100644
index 000000000..a8a2248d8
--- /dev/null
+++ b/private/windbg/remote/shell/resource.h
@@ -0,0 +1,51 @@
+#define IDS_APPNAME 100
+#define IDS_USNAME 101
+#define IDS_Usage 102
+#define IDS_Version 103
+
+#define IDM_DO_CONNECT 200
+#define IDM_OPTIONS 201
+#define IDM_CONNECT 202
+#define IDM_DISCONNECT 203
+#define IDM_NOT_CONNECTING 204
+#define IDM_HELP 205
+#define IDM_STATUS 206
+#define IDM_OPTIONS_DEBUG_DLLS 207
+#define IDM_OPTIONS_EXIT 208
+#define IDM_HELP_CONTENTS 209
+#define IDM_HELP_ABOUT 210
+
+#define ID_KNOWN_DLLS 301
+#define ID_ADD 302
+#define ID_DELETE 303
+#define ID_DEFAULT 304
+#define ID_DESCRIPTION 305
+#define ID_PATH 306
+#define ID_PARAMETERS 307
+#define ID_HELP 308
+#define ID_ADVANCED 309
+#define ID_TRANSPORT_HELP 310 // this must match the one
+ // in win32s\shell\wdbg32s.h
+#define ID_SHORT_NAME 311
+#define ID_KD_DEBUGGERGROUP 312
+#define ID_KD_VERBOSE 313
+#define ID_KD_INITIALBP 314
+#define ID_KD_DEFER 315
+#define ID_KD_MODEM 316
+#define ID_KD_PORT_LABEL 317
+#define ID_KD_PORT 318
+#define ID_KD_BAUDRATE_LABEL 319
+#define ID_KD_BAUDRATE 320
+#define ID_KD_CACHE_LABEL 321
+#define ID_KD_CACHE 322
+#define ID_KD_PLATFORM_LABEL 323
+#define ID_KD_PLATFORM 324
+#define ID_KD_ENABLE 325
+#define ID_KD_GOEXIT 326
+
+#define DLG_TRANSPORTS 500
+#define DLG_CONNECTING 501
+#define DLG_KERNELDBG 502
+#define DISCONNECT_OK 503
+#define CONNECT_OK 504
+#define CONNECTING_ICON 505
diff --git a/private/windbg/remote/shell/sources b/private/windbg/remote/shell/sources
new file mode 100644
index 000000000..12d3bb507
--- /dev/null
+++ b/private/windbg/remote/shell/sources
@@ -0,0 +1,50 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=windbgrm
+
+TARGETNAME=windbgrm
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+SOURCES= \
+ windbgrm.rc \
+ windbgrm.c \
+ gui.c \
+ debugger.c \
+ registry.c \
+ dbgdll.c \
+ kdopt.c
+
+UMTYPE=windows
+
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\shell32.lib
+
+!include ..\..\common.src
+
+C_DEFINES = $(C_DEFINES) -DOSDEBUG
+
+INCLUDES=.\;..\..\osdebug;..\..\osdebug\include;..\..\windbg\include
+
+LINKLIBS=$(MORE_LIBS)
diff --git a/private/windbg/remote/shell/windbgrm.c b/private/windbg/remote/shell/windbgrm.c
new file mode 100644
index 000000000..853579b2b
--- /dev/null
+++ b/private/windbg/remote/shell/windbgrm.c
@@ -0,0 +1,704 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ windbgrm.c
+
+Abstract:
+
+ This file implements the WinDbg remote debugger that doesn't use any
+ USER32.DLL or csrss functionality one initialized.
+
+Author:
+
+ Wesley Witt (wesw) 1-Nov-1993
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "emdm.h"
+#include "tl.h"
+#include "dbgver.h"
+#include "resource.h"
+#include "windbgrm.h"
+
+
+
+
+//
+// globals
+//
+HANDLE hEventService;
+HANDLE hEventLoadTl;
+HANDLE hConnectThread;
+BOOL fConnected;
+BOOL fStartup;
+BOOL fDebugger;
+BOOL fGuiMode = TRUE;
+DWORD dwRequest;
+HPID hpidSvc;
+HANDLE hout;
+BOOL fGonOnDisconnect;
+CHAR szTlName[256];
+TLFUNC TLFunc;
+HANDLE hTransportDll;
+DBG_ACTIVE_STRUCT das;
+DWORD nextHpid;
+CHAR szCmdLine[512];
+CHAR ClientId[MAX_PATH];
+
+
+
+
+
+
+//
+// prototypes
+//
+DWORD
+ConnectThread(
+ LPVOID lpv
+ );
+
+VOID
+GetCommandLineArgs(
+ VOID
+ );
+
+BOOL
+LoadTransport(
+ LPTRANSPORT_LAYER lpTl
+ );
+
+BOOL
+UnLoadTransport(
+ LPTRANSPORT_LAYER lpTl
+ );
+
+XOSD
+TLCallbackFunc(
+ TLCB tlcb,
+ HPID hpid,
+ HTID htid,
+ UINT wParam,
+ LONG lParam
+ );
+
+void
+DebugPrint(
+ char * szFormat,
+ ...
+ );
+
+HANDLE
+StartupDebugger(
+ VOID
+ );
+
+BOOL
+ConnectDebugger(
+ VOID
+ );
+
+BOOL
+DisConnectDebugger(
+ HPID hpid
+ );
+
+BOOL
+AttachProcess(
+ HPID hpid,
+ DBG_ACTIVE_STRUCT *das
+ );
+
+BOOL
+ProgramLoad(
+ HPID hpid,
+ LPSTR lpProgName
+ );
+
+BOOL
+InitApplication(
+ VOID
+ );
+
+BOOLEAN
+DebuggerStateChanged(
+ VOID
+ );
+
+
+
+
+VOID _cdecl
+main(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This is the entry point for WINDBGRM
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ #define append(s,n) p=p+sprintf(p,s,n)
+ HANDLE hDebugger;
+ CHAR buf[256];
+ LPSTR p;
+ LPTRANSPORT_LAYER lpTl;
+
+
+
+// DEBUG_OUT( "WinDbgRm initializing\n" );
+
+ GetCommandLineArgs();
+
+ if (fGuiMode) {
+ InitApplication();
+ }
+
+ SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS );
+
+ hEventService = CreateEvent( NULL, TRUE, FALSE, NULL );
+ hEventLoadTl = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+ if (fDebugger) {
+ ConnectDebugger();
+ if (szCmdLine[0]) {
+ nextHpid++;
+ ProgramLoad( (HPID)nextHpid, szCmdLine );
+ }
+ if (das.dwProcessId) {
+ nextHpid++;
+ AttachProcess( (HPID)nextHpid, &das );
+ }
+ DisConnectDebugger( (HPID) nextHpid );
+ return;
+ }
+
+ while( TRUE ) {
+ //
+ // get the default transport layer
+ //
+ lpTl = RegGetDefaultTransportLayer( szTlName );
+ if (!lpTl) {
+ return;
+ }
+
+ if (!szTlName[0]) {
+ strcpy( szTlName, lpTl->szShortName );
+ }
+
+ //
+ // load the TL and DM
+ //
+ if (!LoadTransport( lpTl )) {
+ if (fGuiMode) {
+ WaitForSingleObject( hEventLoadTl, INFINITE );
+ ResetEvent( hEventLoadTl );
+ continue;
+ }
+ return;
+ }
+
+ //
+ // Initialize the Transport with init string and create the transports
+ //
+ sprintf( buf, "%s %s ", DM_SIDE_L_INIT_SWITCH, lpTl->szParam );
+
+ //
+ // add the kernel debugger options
+ //
+ if (lpTl->KdParams.fEnable) {
+ p = &buf[strlen(buf)];
+ append( "baudrate=%d ", lpTl->KdParams.dwBaudRate );
+ append( "port=%d ", lpTl->KdParams.dwPort );
+ append( "cache=%d ", lpTl->KdParams.dwCache );
+ append( "verbose=%d ", lpTl->KdParams.fVerbose );
+ append( "initialbp=%d ", lpTl->KdParams.fInitialBp );
+ append( "defer=%d ", lpTl->KdParams.fDefer );
+ append( "usemodem=%d ", lpTl->KdParams.fUseModem );
+ append( "goexit=%d ", lpTl->KdParams.fGoExit );
+ append( "symbolpath=%s ", "." );
+ }
+
+ fConnected = FALSE;
+ if (TLFunc( tlfInit, hpidNull, TRUE, (LONG)buf ) != xosdNone) {
+ //
+ // we couldn't create the necessary transport objects
+ //
+ if (fGuiMode) {
+ UnLoadTransport( lpTl );
+ WaitForSingleObject( hEventLoadTl, INFINITE );
+ ResetEvent( hEventLoadTl );
+ continue;
+ }
+ return;
+ } else {
+ break;
+ }
+ }
+
+ if (fStartup) {
+ hDebugger = StartupDebugger();
+ if (!hDebugger) {
+ return;
+ }
+ }
+
+ while ( TRUE ) {
+ if (TLFunc(tlfConnect, hpidNull, sizeof(ClientId), ClientId) == xosdNone) {
+
+ fConnected = TRUE;
+
+ } else {
+
+ Sleep( 2000 );
+
+ }
+ }
+
+ return;
+}
+
+XOSD
+TLCallbackFunc(
+ TLCB tlcb,
+ HPID hpid,
+ HTID htid,
+ UINT wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Provides a callback function for the TL. Currently
+ this callback is only to signal a disconnect.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if ((tlcb != tlcbDisconnect) || (!TLFunc) || (!fConnected)) {
+ return xosdNone;
+ }
+
+// DebugPrint("windbgrm disconnecting...\n");
+
+ fConnected = FALSE;
+ hpidSvc = hpid;
+ htidBpt = htid;
+ fGonOnDisconnect = wParam;
+ SetEvent( hEventService );
+
+ return xosdNone;
+}
+
+
+BOOL
+LoadTransport(
+ LPTRANSPORT_LAYER lpTl
+ )
+
+/*++
+
+Routine Description:
+
+ Loads the named pipes transport layer and does the necessary
+ initialization of the TL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ extern AVS Avs;
+ DBGVERSIONPROC pVerProc;
+ LPAVS pavs;
+ CHAR szDmName[16];
+
+
+ if ((hTransportDll = LoadLibrary(lpTl->szDllName)) == NULL) {
+ goto LoadTransportError;
+ }
+
+ pVerProc = (DBGVERSIONPROC)GetProcAddress(hTransportDll, DBGVERSIONPROCNAME);
+ if (!pVerProc) {
+ goto LoadTransportError;
+ }
+
+ pavs = (*pVerProc)();
+
+ if (pavs->rgchType[0] != 'T' || pavs->rgchType[1] != 'L') {
+ goto LoadTransportError;
+ }
+
+ if (Avs.rlvt != pavs->rlvt) {
+ goto LoadTransportError;
+ }
+
+ if (Avs.iRmj != pavs->iRmj) {
+ goto LoadTransportError;
+ }
+
+ if ((TLFunc = (TLFUNC)GetProcAddress(hTransportDll, "TLFunc")) == NULL) {
+ goto LoadTransportError;
+ }
+
+ //
+ // Ask the TL to load the DM.
+ //
+ if (lpTl->KdParams.fEnable) {
+ switch (lpTl->KdParams.dwPlatform) {
+ case 0:
+ strcpy( szDmName, "DMKDX86.DLL " );
+ break;
+
+ case 1:
+ strcpy( szDmName, "DMKDMIP.DLL " );
+ break;
+
+ case 2:
+ strcpy( szDmName, "DMKDALP.DLL " );
+ break;
+ }
+ } else {
+ strcpy( szDmName, "DM.DLL " );
+ }
+
+ if (TLFunc(tlfLoadDM, hpidNull, wNull, (LONG)szDmName) != xosdNone) {
+ goto LoadTransportError;
+ }
+
+ if (TLFunc(tlfRegisterDBF, hpidNull, wNull, 0) != xosdNone) {
+ goto LoadTransportError;
+ }
+
+ if (TLFunc(tlfSetErrorCB, hpidNull, wNull, (LONG) &TLCallbackFunc) != xosdNone) {
+ goto LoadTransportError;
+ }
+
+ //
+ // Initialize the Timer and Physical Layers of the Transport.
+ // Callback address should be NULL for now. The TL has already
+ // initialized this.
+ //
+ if (TLFunc(tlfGlobalInit, hpidNull, wNull, 0) != xosdNone) {
+ goto LoadTransportError;
+ }
+
+ return TRUE;
+
+LoadTransportError:
+ if (hTransportDll) {
+ FreeLibrary( hTransportDll );
+ hTransportDll = NULL;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+UnLoadTransport(
+ LPTRANSPORT_LAYER lpTl
+ )
+
+/*++
+
+Routine Description:
+
+ Unloads the transport layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ FreeLibrary( hTransportDll );
+ hTransportDll = NULL;
+ free( lpTl );
+
+ return TRUE;
+}
+
+
+HANDLE
+StartupDebugger(
+ VOID
+ )
+{
+ CHAR szCommandLine[MAX_PATH];
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+
+ sprintf( szCommandLine, "windbgrm -q -d -n %s ", szTlName );
+ if (das.dwProcessId) {
+ sprintf( &szCommandLine[strlen(szCommandLine)], "-p %d ", das.dwProcessId );
+ }
+ if (das.hEventGo) {
+ sprintf( &szCommandLine[strlen(szCommandLine)], "-e %d ", das.hEventGo );
+ }
+ if (szCmdLine[0]) {
+ strcat( szCommandLine, szCmdLine );
+ }
+
+ GetStartupInfo( &si );
+ si.hStdOutput = hout;
+
+ if (!CreateProcess( NULL, szCommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi )) {
+ return NULL;
+ }
+
+ return pi.hProcess;
+}
+
+
+VOID
+GetCommandLineArgs(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Simple command line parser.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ char *lpstrCmd = GetCommandLine();
+ UCHAR ch;
+ DWORD i = 0;
+
+ // skip over program name
+ do {
+ ch = *lpstrCmd++;
+ }
+ while (ch != ' ' && ch != '\t' && ch != '\0');
+
+ // skip over any following white space
+ while (ch == ' ' || ch == '\t') {
+ ch = *lpstrCmd++;
+ }
+
+ // process each switch character '-' as encountered
+
+ while (ch == '-' || ch == '/') {
+ ch = tolower(*lpstrCmd++);
+ // process multiple switch characters as needed
+ do {
+ switch (ch) {
+ case 'n':
+ do {
+ ch = *lpstrCmd++;
+ } while (ch == ' ' || ch == '\t');
+ i=0;
+ while (ch != ' ' && ch != '\0') {
+ szTlName[i++] = ch;
+ ch = *lpstrCmd++;
+ }
+ szTlName[i] = '\0';
+ break;
+
+ case '?':
+ //Usage();
+ ch = *lpstrCmd++;
+ break;
+
+ case 'p':
+ // skip whitespace
+ do {
+ ch = *lpstrCmd++;
+ } while (ch == ' ' || ch == '\t');
+
+ if ( ch == '-' ) {
+ ch = *lpstrCmd++;
+ if ( ch == '1' ) {
+ das.dwProcessId = 0xffffffff;
+ ch = *lpstrCmd++;
+ }
+ } else {
+ i=0;
+ while (ch >= '0' && ch <= '9') {
+ i = i * 10 + ch - '0';
+ ch = *lpstrCmd++;
+ }
+ das.dwProcessId = i;
+ }
+ fStartup = TRUE;
+ break;
+
+ case 'e':
+ // skip whitespace
+ do {
+ ch = *lpstrCmd++;
+ } while (ch == ' ' || ch == '\t');
+
+ i=0;
+ while (ch >= '0' && ch <= '9') {
+ i = i * 10 + ch - '0';
+ ch = *lpstrCmd++;
+ }
+ das.hEventGo = (HANDLE) i;
+ break;
+
+ case 'q':
+ fDebugger = TRUE;
+ ch = *lpstrCmd++;
+ break;
+
+ case 'g':
+ ch = *lpstrCmd++;
+ break;
+
+ case 'd':
+ fGuiMode = FALSE;
+ ch = *lpstrCmd++;
+ break;
+
+ default:
+ return;
+ }
+ } while (ch != ' ' && ch != '\t' && ch != '\0');
+
+ while (ch == ' ' || ch == '\t') {
+ ch = *lpstrCmd++;
+ }
+ }
+
+
+ //
+ // get the command line for a debuggee
+ //
+
+ while (ch == ' ' || ch == '\t') {
+ ch = *lpstrCmd++;
+ }
+ i=0;
+ while (ch) {
+ szCmdLine[i++] = ch;
+ ch = *lpstrCmd++;
+ }
+ szCmdLine[i] = '\0';
+ if (i) {
+ fStartup = TRUE;
+ }
+
+ return;
+}
+
+
+void
+DebugPrint(
+ char * szFormat,
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ Provides a printf style function for doing outputdebugstring.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ va_list marker;
+ int n;
+ char rgchDebug[4096];
+
+ va_start( marker, szFormat );
+ n = _vsnprintf(rgchDebug, sizeof(rgchDebug), szFormat, marker );
+ va_end( marker);
+
+ if (n == -1) {
+ rgchDebug[sizeof(rgchDebug)-1] = '\0';
+ }
+
+ OutputDebugString( rgchDebug );
+ return;
+}
+
+void
+ShowAssert(
+ LPSTR condition,
+ UINT line,
+ LPSTR file
+ )
+{
+ char text[4096];
+ int id;
+
+ sprintf(text, "Assertion failed - Line:%u, File:%Fs, Condition:%Fs", line, file, condition);
+ DebugPrint( "%s\r\n", text );
+ id = MessageBox( NULL, text, "WinDbgRm", MB_YESNO | MB_ICONHAND | MB_TASKMODAL | MB_SETFOREGROUND );
+ if (id != IDYES) {
+ DebugBreak();
+ }
+
+ return;
+}
diff --git a/private/windbg/remote/shell/windbgrm.dlg b/private/windbg/remote/shell/windbgrm.dlg
new file mode 100644
index 000000000..6e7c93f88
--- /dev/null
+++ b/private/windbg/remote/shell/windbgrm.dlg
@@ -0,0 +1,64 @@
+1 DLGINCLUDE "resource.h"
+
+DLG_TRANSPORTS DIALOG 117, 73, 272, 180
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Transport DLL"
+FONT 8, "MS Shell DLG"
+BEGIN
+ DEFPUSHBUTTON "OK", IDOK, 225, 6, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 225, 23, 40, 14
+ PUSHBUTTON "&Help", ID_HELP, 225, 40, 40, 14
+ PUSHBUTTON "&Add", ID_ADD, 225, 72, 40, 14
+ PUSHBUTTON "&Delete", ID_DELETE, 225, 89, 40, 14
+ //PUSHBUTTON "Ad&vanced", ID_ADVANCED, 225, 106, 40, 14
+ LTEXT "&Short Name:", 102, 7, 17, 42, 8
+ EDITTEXT ID_SHORT_NAME, 53, 15, 52, 12, ES_AUTOHSCROLL | WS_GROUP
+ LTEXT "D&escription:", 108, 7, 37, 41, 8
+ EDITTEXT ID_DESCRIPTION, 53, 35, 160, 12, ES_AUTOHSCROLL
+ LTEXT "&Path:", 109, 7, 57, 20, 8
+ EDITTEXT ID_PATH, 53, 55, 160, 12, ES_AUTOHSCROLL
+ LTEXT "Pa&rameters:", 111, 7, 77, 42, 8
+ EDITTEXT ID_PARAMETERS, 53, 75, 160, 12, ES_AUTOHSCROLL
+ AUTOCHECKBOX "Default &Transport Layer", ID_DEFAULT, 7, 95, 90, 10
+ LTEXT "&Known Transport Layers:", 115, 7, 115, 85, 8
+ LISTBOX ID_KNOWN_DLLS, 7, 125, 258, 48, LBS_SORT |
+ LBS_USETABSTOPS | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+END
+
+DLG_CONNECTING DIALOG 95, 193, 94, 37
+STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "WinDbgRm Connecting"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Connecting...", 102, 37, 15, 45, 8
+ ICON CONNECTING_ICON, 108, 6, 9, 18, 20
+END
+
+DLG_KERNELDBG DIALOG 24, 54, 254, 127
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Kernel Debugger Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ AUTOCHECKBOX "Verbose Output", ID_KD_VERBOSE, 14, 16, 103, 10
+ AUTOCHECKBOX "Stop at Initial Breakpoint", ID_KD_INITIALBP, 14, 28,
+ 103, 10
+ AUTOCHECKBOX "Defer Symbol Loading", ID_KD_DEFER, 14, 40, 103, 10
+ AUTOCHECKBOX "Use Modem Controls", ID_KD_MODEM, 14, 52, 103, 10
+ AUTOCHECKBOX "Enable Kernel Debugging", ID_KD_ENABLE, 14, 64, 103, 10
+ AUTOCHECKBOX "Go On Exit", ID_KD_GOEXIT, 14, 76, 103, 10
+ LTEXT "Port", ID_KD_PORT_LABEL, 139, 37, 20, 8
+ COMBOBOX ID_KD_PORT, 181, 35, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Baud Rate", ID_KD_BAUDRATE_LABEL, 139, 21, 41, 8
+ COMBOBOX ID_KD_BAUDRATE, 181, 19, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Cache Size", ID_KD_CACHE_LABEL, 139, 54, 41, 9
+ COMBOBOX ID_KD_CACHE, 181, 51, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Platform", ID_KD_PLATFORM_LABEL, 139, 71, 41, 9
+ COMBOBOX ID_KD_PLATFORM, 181, 68, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 18, 107, 62, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 96, 107, 62, 14
+ PUSHBUTTON "&Help", 100, 174, 107, 62, 14
+END
diff --git a/private/windbg/remote/shell/windbgrm.h b/private/windbg/remote/shell/windbgrm.h
new file mode 100644
index 000000000..16c7ff83f
--- /dev/null
+++ b/private/windbg/remote/shell/windbgrm.h
@@ -0,0 +1,107 @@
+
+
+
+
+#define NO_CHANGE 0
+#define LIST_CHANGED 1
+#define LIST_ERROR 2
+#define NO_TRANSPORT_LAYER_SELECTED -1
+
+#define MAX_SHORT_NAME 7 // maximum chars in short name
+#define MAX_LONG_NAME 255 // maximum for other fields in dialog
+// a short name + a tab char + a long name + a null
+#define MAX_LIST_BOX_STRING (MAX_SHORT_NAME + MAX_LONG_NAME + 2)
+
+//
+// kernel debugger options
+//
+typedef struct _KDPARAMS {
+ BOOL fEnable;
+ BOOL fVerbose;
+ BOOL fInitialBp;
+ BOOL fDefer;
+ BOOL fUseModem;
+ BOOL fGoExit;
+ DWORD dwBaudRate;
+ DWORD dwPort;
+ DWORD dwCache;
+ DWORD dwPlatform;
+} KDPARAMS, *LPKDPARAMS;
+
+//
+// transport layer
+//
+typedef struct _tagTRANSPORT_LAYER {
+ LPSTR szShortName;
+ LPSTR szLongName;
+ LPSTR szDllName;
+ LPSTR szParam;
+ BOOL fDefault;
+ KDPARAMS KdParams;
+} TRANSPORT_LAYER, *LPTRANSPORT_LAYER;
+
+
+#if DBG
+#define assert(exp) if (!(exp)) { ShowAssert(#exp,__LINE__,__FILE__); }
+#define DPRINT(args) DebugPrint args;
+#define DEBUG_OUT(str) DPRINT((str))
+#define DEBUG_OUT1(str, a1) DPRINT((str, a1))
+#define DEBUG_OUT2(str, a1, a2) DPRINT((str, a1, a2))
+#define DEBUG_OUT3(str, a1, a2, a3) DPRINT((str, a1, a2, a3))
+#else
+#define assert(exp)
+#define DPRINT(args)
+#define DEBUG_OUT(str)
+#define DEBUG_OUT1(str, a1)
+#define DEBUG_OUT2(str, a1, a2)
+#define DEBUG_OUT3(str, a1, a2, a3)
+#endif
+
+#define TRANSPORT_NAME "tlpipe.dll"
+#define RQ_CONNECT 1
+#define RQ_DISCONNECT 2
+
+extern CHAR szTlName[];
+extern TLFUNC TLFunc;
+extern HTID htidBpt;
+extern HANDLE hTransportDll;
+
+
+void
+DebugPrint(
+ char * szFormat,
+ ...
+ );
+
+void
+ShowAssert(
+ LPSTR condition,
+ UINT line,
+ LPSTR file
+ );
+
+//----------------------------------------------------------------------------------------------
+// registry functions
+//----------------------------------------------------------------------------------------------
+
+LPTRANSPORT_LAYER
+RegGetTransportLayers(
+ LPDWORD lpdwCount
+ );
+
+BOOL
+RegSaveTransportLayers(
+ LPTRANSPORT_LAYER lpTl,
+ DWORD dwCount
+ );
+
+LPTRANSPORT_LAYER
+RegGetTransportLayer(
+ LPSTR lpTransportName
+ );
+
+LPTRANSPORT_LAYER
+RegGetDefaultTransportLayer(
+ LPSTR lpTlName
+ );
+
diff --git a/private/windbg/remote/shell/windbgrm.ico b/private/windbg/remote/shell/windbgrm.ico
new file mode 100644
index 000000000..e7299ef82
--- /dev/null
+++ b/private/windbg/remote/shell/windbgrm.ico
Binary files differ
diff --git a/private/windbg/remote/shell/windbgrm.rc b/private/windbg/remote/shell/windbgrm.rc
new file mode 100644
index 000000000..3f65b550a
--- /dev/null
+++ b/private/windbg/remote/shell/windbgrm.rc
@@ -0,0 +1,44 @@
+#include "windows.h"
+#include "resource.h"
+#include <ntverp.h>
+
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Remote WinDbg Target Module"
+#define VER_INTERNALNAME_STR "WinDbgRm\0"
+
+#include "common.ver"
+
+
+WinDbgRm MENU PRELOAD DISCARDABLE
+BEGIN
+ POPUP "&Options"
+ {
+ MENUITEM "&Transport DLL...", IDM_OPTIONS_DEBUG_DLLS
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_OPTIONS_EXIT
+ }
+ POPUP "&Help"
+ {
+ MENUITEM "&Contents", IDM_HELP_CONTENTS
+ MENUITEM "&About WinDbgRm...", IDM_HELP_ABOUT
+ }
+END
+
+WinDbgRm ACCELERATORS
+BEGIN
+ VK_F1, IDM_HELP_CONTENTS, VIRTKEY
+END
+
+#include "windbgrm.dlg"
+
+WindbgRmIcon ICON PRELOAD DISCARDABLE "windbgrm.ico"
+CONNECTING_ICON ICON PRELOAD DISCARDABLE "connect.ico"
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ IDS_APPNAME, "WinDbgRm"
+ IDS_Usage, "windbgrm -c -p<proc num> -e<event num> -s<short name>\n"
+ IDS_Version, "0010"
+END
diff --git a/private/windbg/remote/xport/makefile b/private/windbg/remote/xport/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/remote/xport/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/remote/xport/sources b/private/windbg/remote/xport/sources
new file mode 100644
index 000000000..99c8028fe
--- /dev/null
+++ b/private/windbg/remote/xport/sources
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=xport
+
+TARGETNAME=xport
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES=xport.c
+
+UMTYPE=windows
+
+INCLUDES=..\..\osdebug;..\..\osdebug\include
+
+!include ..\..\common.src
diff --git a/private/windbg/remote/xport/xport.c b/private/windbg/remote/xport/xport.c
new file mode 100644
index 000000000..f297dcaac
--- /dev/null
+++ b/private/windbg/remote/xport/xport.c
@@ -0,0 +1,1143 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ xport.c
+
+Abstract:
+
+ This module contains the code for the named pipe transport layer
+ which explicitly deals with the machanics of doing named pipes.
+
+Author:
+
+ Jim Schaad (jimsch) 11-June-93
+ Wesley Witt (wesw) 25-Nov-93
+
+Environment:
+
+ Win32 User
+
+--*/
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <stdlib.h>
+#include <defs.h>
+#include <string.h>
+#include <memory.h>
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "tl.h"
+#include "llhpt.h"
+#include "mhhpt.h"
+#include "lbhpt.h"
+#include "emdm.h"
+#include "xport.h"
+#include "dbgver.h"
+
+
+#if DBG
+DWORD FExpectingReply = 0;
+DWORD FExpectingSeq = 0;
+CRITICAL_SECTION csExpecting;
+#endif
+
+extern AVS Avs;
+
+#ifdef WIN32
+LPDMINIT LpDmInit;
+LPDMFUNC LpDmFunc;
+LPDMDLLINIT LpDmDllInit;
+LPUISERVERCB LpUiServer;
+void EXPENTRY DMInit (DMTLFUNCTYPE, LPV);
+#else
+void EXPENTRY DMInit (DMTLFUNCTYPE);
+#endif
+
+LPDBF lpdbf = (LPDBF)0; // the debugger helper functions LOCAL
+TLCALLBACKTYPE TLCallBack; // central osdebug callback function
+
+//
+// these variables are static to prevent collisions with other TL's
+//
+
+BOOL FConnected = FALSE;
+static LPB lpbDM;
+static WORD ibMaxDM;
+static WORD ibDM;
+static HPID hpidRoot;
+LPSTR SzParams;
+LPSTR LpszDm;
+HANDLE HDm = NULL;
+static DWORD pkSeq;
+
+extern CHAR ClientId[];
+
+static char Rgb[MAX_INTERNAL_PACKET + sizeof(NLBLK) + sizeof(MPACKET)];
+#define Pnlblk ((PNLBLK) Rgb)
+#define PnlblkDm ((PNLBLK) Rgb)
+
+static char RgbReply[MAX_INTERNAL_PACKET + sizeof(NLBLK) + sizeof(MPACKET)];
+#define PnlblkRp ((PNLBLK) RgbReply)
+
+static char RgbRequest[MAX_INTERNAL_PACKET + sizeof(NLBLK) + sizeof(MPACKET)];
+#define PnlblkRq ((PNLBLK) RgbRequest)
+
+XOSD
+SendData(
+ LPV lpvOut,
+ int cbOut
+ );
+
+XOSD
+SendRequest(
+ int mtypeResponse,
+ LPV lpvOut,
+ int cbOut,
+ LPV lpvReply,
+ int * pcbReply,
+ DWORD dwTimeOut
+ );
+
+XOSD EXPENTRY
+DMTLFunc(
+ TLF wCommand,
+ HPID hpid,
+ DWORD wParam,
+ LONG lParam
+ );
+
+XOSD EXPENTRY
+TLFunc(
+ TLF wCommand,
+ HPID hpid,
+ DWORD wParam,
+ LONG lParam
+ );
+
+extern BOOL FDMSide;
+
+
+BOOL
+DllVersionMatch(
+ HANDLE hMod,
+ LPSTR pType
+ )
+{
+ DBGVERSIONPROC pVerProc;
+ LPAVS pavs;
+
+ pVerProc = (DBGVERSIONPROC)GetProcAddress(hMod, DBGVERSIONPROCNAME);
+ if (!pVerProc) {
+ return(FALSE); // no version entry point
+ } else {
+ pavs = (*pVerProc)();
+ if ((pType[0] != pavs->rgchType[0] || pType[1] != pavs->rgchType[1]) ||
+ (Avs.rlvt != pavs->rlvt) || (Avs.iRmj != pavs->iRmj)) {
+ return(FALSE);
+ }
+ }
+ return(TRUE);
+}
+
+
+XOSD EXPENTRY
+TLFunc(
+ TLF wCommand,
+ HPID hpid,
+ DWORD wParam,
+ LONG lParam
+ )
+/*++
+
+Routine Description:
+
+ This function contains the dispatch loop for commands comming into
+ the transport layer. The address of this procedure is exported to
+ users of the DLL.
+
+Arguments:
+
+ wCommand - Supplies the command to be executed.
+
+ hpid - Supplies the hpid for which the command is to be executed.
+
+ wParam - Supplies information about the command.
+
+ lParam - Supplies information about the command.
+
+Return Value:
+
+ XOSD error code. xosdNone means that no errors occured. Other
+ error codes are defined in osdebug\include\od.h.
+
+--*/
+
+{
+ LPGIS lpgis;
+ int cb;
+ LPSTR p;
+ MPACKET * pMpckt;
+ XOSD xosd = xosdNone;
+ LPDBB lpdbb;
+ AVS dmavs;
+
+
+ switch ( wCommand ) {
+ case tlfGlobalInit:
+ DEBUG_OUT("TlFunc: tlfGlobalInit\n");
+ TLCallBack = (TLCALLBACKTYPE) lParam;
+ break;
+
+ case tlfGlobalDestroy:
+ DEBUG_OUT("TlFunc: tlfGlobalDestroy\n");
+ break;
+
+ case tlfRegisterDBF:
+ DEBUG_OUT("TlFunc: tlfRegisterDBF\n");
+ lpdbf = (LPDBF) lParam;
+ break;
+
+ case tlfInit:
+ DEBUG_OUT("TlFunc: tlfInit\n");
+ p = (LPSTR)lParam;
+ if (strncmp(p, "DMSide", 6) == 0) {
+ FDMSide = TRUE;
+ p = strtok(p, " ");
+ p = strtok(NULL, " ");
+ SzParams = _strdup( p );
+ p += (strlen( p ) + 1);
+ if (LpDmInit != NULL) {
+ xosd = LpDmInit(DMTLFunc, (LPV)lParam);
+ } else {
+ xosd = xosdUnknown;
+ }
+ } else {
+ SzParams = _strdup( p );
+ }
+ break;
+
+ case tlfDestroy:
+ DEBUG_OUT("TlFunc: tlfDestroy\n");
+ if (LpDmInit != NULL) {
+ LpDmInit(NULL, NULL);
+ }
+ if (HDm != NULL) {
+ FreeLibrary(HDm);
+ HDm = NULL;
+ LpDmInit = NULL;
+
+ LpDmFunc = NULL;
+ }
+ if (LpUiServer) {
+ DEBUG_OUT(("NL: tlcbDisconnect\n"));
+ LpUiServer(tlcbDisconnect, 0, 0, 0, 0);
+ }
+
+ TlDestroyTransport();
+ FConnected = FALSE;
+
+ DEBUG_OUT(("NL: tlfDestroy exit\n"));
+ break;
+
+ case tlfSetUIStruct: // not used for local case
+ DEBUG_OUT("TlFunc: tlfSetUIStruct\n");
+ break;
+
+ case tlfGetProc:
+ DEBUG_OUT("TlFunc: tlfGetProc\n");
+ *((TLFUNCTYPE FAR *) lParam) = TLFunc;
+ break;
+
+ case tlfConnect:
+ DEBUG_OUT("TlFunc: tlfConnect\n");
+ if (hpid) {
+ hpidRoot = hpid;
+ } else {
+ if (lParam) {
+ if ((xosd = TlConnectTransport()) == xosdNone) {
+ FConnected = TRUE;
+ strncpy( (LPSTR)lParam, ClientId, wParam );
+ }
+ } else {
+ if (TlCreateClient(SzParams) != xosdNone) {
+ xosd = xosdCannotConnect;
+ } else {
+ FConnected = TRUE;
+ }
+ }
+ }
+ break;
+
+ case tlfDisconnect:
+ DEBUG_OUT("TlFunc: tlfDisconnect\n");
+ TlDestroyTransport();
+ FConnected = FALSE;
+ break;
+
+ case tlfRemoteQuit:
+ DEBUG_OUT("TlFunc: tlfRemoteQuit\n");
+
+ //
+ // tell the dm that it is disconnected from the debugger
+ //
+ lpdbb = (LPDBB)Rgb;
+ lpdbb->dmf = dmfRemoteQuit;
+ lpdbb->hpid = 0;
+ lpdbb->htid = 0;
+ LpDmFunc(sizeof(*lpdbb), (char *) lpdbb);
+
+ TlDestroyTransport();
+ break;
+
+ case tlfSetBuffer:
+ DEBUG_OUT("TlFunc: tlfSetBuffer\n");
+ lpbDM = (LPB) lParam;
+ ibMaxDM = (short)wParam;
+ break;
+
+ case tlfDebugPacket:
+ DEBUG_OUT("TlFunc: tlfDebugPacket\n");
+ if (FConnected) {
+ if (wParam > MAX_INTERNAL_PACKET) {
+ pMpckt = (MPACKET * ) Pnlblk->rgchData;
+ Pnlblk->mtypeBlk = mtypeAsyncMulti;
+ Pnlblk->hpid = hpid;
+ Pnlblk->cchMessage = MAX_INTERNAL_PACKET + sizeof(MPACKET);
+ Pnlblk->seq = ++pkSeq;
+ pMpckt->packetNum = 0;
+
+ pMpckt->packetCount = (((short)wParam + MAX_INTERNAL_PACKET - 1) /
+ MAX_INTERNAL_PACKET);
+ while (wParam > MAX_INTERNAL_PACKET) {
+ memcpy(pMpckt->rgchData, (LPB) lParam, MAX_INTERNAL_PACKET);
+ xosd = SendData(Pnlblk, sizeof(NLBLK) + sizeof(MPACKET) +
+ MAX_INTERNAL_PACKET);
+ if (xosd != xosdNone) {
+ return xosdUnknown;
+ }
+ wParam -= MAX_INTERNAL_PACKET;
+ lParam += MAX_INTERNAL_PACKET;
+
+ pMpckt->packetNum += 1;
+ }
+
+ memcpy(pMpckt->rgchData, (LPB) lParam, wParam);
+
+ Pnlblk->cchMessage = (short)(wParam + sizeof(MPACKET));
+
+ xosd = SendData(Pnlblk, sizeof(NLBLK) + sizeof(MPACKET) + wParam);
+ } else {
+ Pnlblk->mtypeBlk = mtypeAsync;
+
+ Pnlblk->hpid = hpid;
+ Pnlblk->cchMessage = (short)wParam;
+ Pnlblk->seq = ++pkSeq;
+
+ memcpy(Pnlblk->rgchData, (LPB) lParam, wParam);
+ xosd = SendData(Pnlblk, sizeof(NLBLK) + wParam);
+ }
+ } else {
+ xosd = xosdLineNotConnected;
+ }
+ break;
+
+
+ case tlfReply:
+ DEBUG_OUT("TlFunc: tlfReply\n");
+#if DBG
+ EnterCriticalSection(&csExpecting);
+ assert(FExpectingReply);
+ FExpectingReply = 0;
+ LeaveCriticalSection(&csExpecting);
+#endif
+ if (FConnected) {
+ if (wParam > MAX_INTERNAL_PACKET) {
+ pMpckt = (MPACKET * ) PnlblkRp->rgchData;
+ PnlblkRp->mtypeBlk = mtypeReplyMulti;
+ PnlblkRp->hpid = hpid;
+ PnlblkRp->cchMessage = MAX_INTERNAL_PACKET + sizeof(MPACKET);
+ PnlblkRp->seq = ++pkSeq;
+ pMpckt->packetNum = 0;
+
+ pMpckt->packetCount = (((short)wParam + MAX_INTERNAL_PACKET - 1) /
+ MAX_INTERNAL_PACKET);
+ while (wParam > MAX_INTERNAL_PACKET) {
+ memcpy(pMpckt->rgchData, (LPB) lParam, MAX_INTERNAL_PACKET);
+ xosd = SendData(PnlblkRp, sizeof(NLBLK) + sizeof(MPACKET) +
+ MAX_INTERNAL_PACKET);
+ if (xosd != xosdNone) {
+ return xosdUnknown;
+ }
+ wParam -= MAX_INTERNAL_PACKET;
+ lParam += MAX_INTERNAL_PACKET;
+
+ pMpckt->packetNum += 1;
+ }
+
+ memcpy(pMpckt->rgchData, (LPB) lParam, wParam);
+
+ PnlblkRp->cchMessage = (short)(wParam + sizeof(MPACKET));
+
+ xosd = SendData(PnlblkRp, sizeof(NLBLK) + sizeof(MPACKET) + wParam);
+ } else {
+ PnlblkRp->mtypeBlk = mtypeReply;
+
+ PnlblkRp->hpid = hpid;
+ PnlblkRp->cchMessage = (short)wParam;
+ PnlblkRp->seq = ++pkSeq;
+
+ memcpy(PnlblkRp->rgchData, (LPB) lParam, wParam);
+ xosd = SendData(PnlblkRp, sizeof(NLBLK) + wParam);
+ }
+ } else {
+ xosd = xosdLineNotConnected;
+ }
+ break;
+
+ case tlfRequest:
+ DEBUG_OUT("TlFunc: tlfRequest\n");
+ if ( !FConnected ) {
+ xosd = xosdLineNotConnected;
+ } else {
+ cb = ibMaxDM;
+ if (wParam > MAX_INTERNAL_PACKET) {
+ pMpckt = (MPACKET * ) PnlblkRq->rgchData;
+ PnlblkRq->mtypeBlk = mtypeSyncMulti;
+ PnlblkRq->hpid = hpid;
+ PnlblkRq->cchMessage = MAX_INTERNAL_PACKET + sizeof(MPACKET);
+ PnlblkRq->seq = ++pkSeq;
+ pMpckt->packetNum = 0;
+
+ pMpckt->packetCount = (((short)wParam + MAX_INTERNAL_PACKET - 1) /
+ MAX_INTERNAL_PACKET);
+ while (wParam > MAX_INTERNAL_PACKET) {
+ memcpy(pMpckt->rgchData, (LPB) lParam, MAX_INTERNAL_PACKET);
+ xosd = SendData(PnlblkRq, sizeof(NLBLK) + sizeof(MPACKET) +
+ MAX_INTERNAL_PACKET);
+ if (xosd != xosdNone) {
+ return xosdUnknown;
+ }
+ wParam -= MAX_INTERNAL_PACKET;
+ lParam += MAX_INTERNAL_PACKET;
+
+ pMpckt->packetNum += 1;
+ }
+
+ PnlblkRq->cchMessage = (short)(wParam + sizeof(MPACKET));
+
+ memcpy(pMpckt->rgchData, (LPB) lParam, wParam);
+ xosd = SendRequest(mtypeReply, PnlblkRq, sizeof(NLBLK) + sizeof(MPACKET) +
+ wParam, lpbDM, &cb, INFINITE);
+ } else {
+ PnlblkRq->mtypeBlk = mtypeSync;
+
+ PnlblkRq->cchMessage = (short)wParam;
+ PnlblkRq->hpid = hpid;
+ PnlblkRq->seq = ++pkSeq;
+
+ memcpy(PnlblkRq->rgchData, (char *) lParam, wParam);
+ xosd = SendRequest(mtypeReply, PnlblkRq, wParam + sizeof(NLBLK), lpbDM, &cb, INFINITE);
+ }
+ }
+ break;
+
+ case tlfGetVersion:
+ DEBUG_OUT("TlFunc: tlfGetVersion\n");
+ {
+ int cb = wParam;
+ //
+ // Get the version information from the remote side. If it doesn't
+ // return anything in 10 seconds, time out and return 0's.
+ //
+ // lParam = buffer to fill in
+ // wParam = size of buffer
+ //
+ // sets globals lpchVersionReply = lParam
+ // cchVersionReplyMax = wParam
+ //
+ //
+
+ DEBUG_OUT("NL: tlfGetVersion\n");
+ if (!FConnected) {
+ DEBUG_OUT(("NL: tlfGetVersion not on line\n"));
+ xosd = xosdLineNotConnected;
+ break;
+ }
+
+ //
+ // must be connected
+ // basically works like a tlfRequest with a timeout and a
+ // target in the transport rather than the DM/EM.
+ //
+
+ //
+ // Create the desired packet. The packet consists of:
+ // type = mtypeVersionRequest
+ // length = 0
+ // hpid = current pid
+ //
+
+ Pnlblk->mtypeBlk = mtypeVersionRequest;
+
+ Pnlblk->cchMessage = 0;
+ Pnlblk->hpid = hpid;
+ Pnlblk->seq = ++pkSeq;
+
+ //
+ // send the version request packet
+ //
+
+ xosd = SendRequest(mtypeVersionReply, Pnlblk,
+ sizeof(NLBLK), (void *) lParam, &cb, 5);
+ if (xosd == xosdNone) {
+ } else {
+ memset((LPCH) lParam, 0, wParam);
+ }
+ DEBUG_OUT("NL: tlfVersionCheck exit\n");
+ }
+ break;
+
+ case tlfSendVersion:
+ DEBUG_OUT("TlFunc: tlfSendVersion\n");
+ if (!FConnected) {
+ return xosdLineNotConnected;
+ } else {
+ // Send the version information to
+ // the other side. This is in response to a mtypeVersionRequest
+ // (tlfGetVersion)
+
+ // Create a packet with the appropriate data packet
+ // type = mtypeVersionReply cb = sizeof(Avs);
+ // hpid = hpid
+ // data = Version structure
+
+ if (HDm) {
+ DBGVERSIONPROC verproc =
+ (DBGVERSIONPROC)GetProcAddress(HDm, DBGVERSIONPROCNAME);
+ dmavs = *verproc();
+ } else {
+ dmavs = Avs;
+ }
+
+ Pnlblk->mtypeBlk = mtypeVersionReply;
+ Pnlblk->hpid = hpid;
+ Pnlblk->cchMessage = sizeof(AVS);
+ Pnlblk->seq = ++pkSeq;
+ memcpy(&Pnlblk->rgchData,(LPCH)&dmavs, sizeof(AVS));
+ SendData(Pnlblk, sizeof(NLBLK) + sizeof(AVS));
+
+ DEBUG_OUT(("Send Reply to version request packet\n"));
+ }
+ break;
+
+ case tlfGetInfo:
+ DEBUG_OUT("TlFunc: tlfGetInfo\n");
+ lpgis = (LPGIS) lParam;
+ _fstrcpy(lpgis->rgchInfo, "Local Transport Layer (LOCAL:)");
+ lpgis->fCanSetup = FALSE;
+ break;
+
+ case tlfSetup:
+ DEBUG_OUT("TlFunc: tlfSetup\n");
+ break;
+
+ case tlfLoadDM:
+ DEBUG_OUT("TlFunc: tlfLoadDM\n");
+ if (lParam) {
+ LpszDm = (char *) lParam;
+ } else {
+ LpszDm = "DM.DLL";
+ }
+ HDm = LoadLibrary(LpszDm);
+ if (HDm == NULL) {
+ xosd = xosdUnknown;
+ break;
+ }
+
+ // Do DM dll version check here
+ if (! DllVersionMatch(HDm, "DM")) {
+ xosd = xosdBadVersion;
+ FreeLibrary(HDm);
+ break;
+ }
+
+ if ((LpDmInit = (LPDMINIT) GetProcAddress(HDm, "DMInit")) == NULL) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ break;
+ }
+
+ if ((LpDmFunc = (LPDMFUNC) GetProcAddress(HDm, "DMFunc")) == NULL) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ LpDmInit = NULL;
+ break;
+ }
+
+ if ((LpDmDllInit = (LPDMDLLINIT) GetProcAddress(HDm, "DmDllInit")) ==
+ NULL) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+
+ LpDmFunc = NULL;
+ LpDmInit = NULL;
+ break;
+ }
+
+#ifdef WIN32
+ if (LpDmDllInit(lpdbf) == FALSE) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ break;
+ }
+#endif
+ break;
+
+ case tlfSetErrorCB:
+ DEBUG_OUT("TlFunc: tlfSetErrorCB\n");
+ LpUiServer = (LPUISERVERCB) lParam;
+ break;
+
+ default:
+ DEBUG_OUT("TlFunc: **** unknown tlf ****\n");
+ assert ( FALSE );
+ break;
+ }
+
+ return xosd;
+}
+
+
+XOSD EXPENTRY
+DMTLFunc(
+ TLF wCommand,
+ HPID hpid,
+ DWORD wParam,
+ LONG lParam
+ )
+{
+ XOSD xosd = xosdNone;
+ int cb;
+ MPACKET * pMpckt;
+
+ switch ( wCommand ) {
+ case tlfInit:
+ DEBUG_OUT( "DMTlFunc: tlfInit\n" );
+ break;
+
+ case tlfDestroy:
+ DEBUG_OUT( "DMTlFunc: tlfDestroy\n" );
+ break;
+
+ case tlfConnect:
+ DEBUG_OUT( "DMTlFunc: tlfConnect\n" );
+ if (TlCreateTransport(SzParams) != xosdNone) {
+ xosd = xosdCannotConnect;
+ }
+ break;
+
+ case tlfDisconnect:
+ DEBUG_OUT( "DMTlFunc: tlfDisconnect\n" );
+ TlDestroyTransport();
+ FConnected = FALSE;
+ break;
+
+ case tlfSetBuffer: lpbDM = (LPB) lParam;
+ DEBUG_OUT( "DMTlFunc: tlfSetBuffer\n" );
+ ibMaxDM = (short)wParam;
+ break;
+
+ case tlfDebugPacket:
+ DEBUG_OUT( "DMTlFunc: tlfDebugPacket\n" );
+ if (FConnected) {
+ if (wParam > MAX_INTERNAL_PACKET) {
+ pMpckt = (MPACKET * ) PnlblkDm->rgchData;
+ PnlblkDm->mtypeBlk = mtypeAsyncMulti;
+ PnlblkDm->hpid = hpid;
+ PnlblkDm->cchMessage = MAX_INTERNAL_PACKET + sizeof(MPACKET);
+ PnlblkDm->seq = ++pkSeq;
+ pMpckt->packetNum = 0;
+
+ pMpckt->packetCount = (((short)wParam + MAX_INTERNAL_PACKET - 1) /
+ MAX_INTERNAL_PACKET);
+ while (wParam > MAX_INTERNAL_PACKET) {
+ memcpy(pMpckt->rgchData, (LPB) lParam, MAX_INTERNAL_PACKET);
+ xosd = SendData(PnlblkDm, sizeof(NLBLK) + sizeof(MPACKET) +
+ MAX_INTERNAL_PACKET);
+ if (xosd != xosdNone) {
+ return xosdUnknown;
+ }
+ wParam -= MAX_INTERNAL_PACKET;
+ lParam += MAX_INTERNAL_PACKET;
+
+ pMpckt->packetNum += 1;
+ }
+
+ memcpy(pMpckt->rgchData, (LPB) lParam, wParam);
+
+ PnlblkDm->cchMessage = (short)(wParam + sizeof(MPACKET));
+
+ xosd = SendData(PnlblkDm, sizeof(NLBLK) + sizeof(MPACKET) + wParam);
+ } else {
+ PnlblkDm->mtypeBlk = mtypeAsync;
+
+ PnlblkDm->hpid = hpid;
+ PnlblkDm->cchMessage = (short)wParam;
+ PnlblkDm->seq = ++pkSeq;
+
+ memcpy(PnlblkDm->rgchData, (LPB) lParam, wParam);
+ xosd = SendData(PnlblkDm, sizeof(NLBLK) + wParam);
+ }
+ } else {
+ xosd = xosdIDError;
+ }
+ break;
+
+
+ case tlfReply:
+ DEBUG_OUT( "DMTlFunc: tlfReply\n" );
+#if DBG
+ EnterCriticalSection(&csExpecting);
+ assert(FExpectingReply);
+ FExpectingReply = 0;
+ LeaveCriticalSection(&csExpecting);
+#endif
+ if (FConnected) {
+ if (wParam > MAX_INTERNAL_PACKET) {
+ pMpckt = (MPACKET * ) PnlblkRp->rgchData;
+ PnlblkRp->mtypeBlk = mtypeReplyMulti;
+ PnlblkRp->hpid = hpid;
+ PnlblkRp->cchMessage = MAX_INTERNAL_PACKET + sizeof(MPACKET);
+ PnlblkRp->seq = ++pkSeq;
+ pMpckt->packetNum = 0;
+
+ pMpckt->packetCount = (((short)wParam + MAX_INTERNAL_PACKET - 1) /
+ MAX_INTERNAL_PACKET);
+ while (wParam > MAX_INTERNAL_PACKET) {
+ memcpy(pMpckt->rgchData, (LPB) lParam, MAX_INTERNAL_PACKET);
+ xosd = SendData(PnlblkRp, sizeof(NLBLK) + sizeof(MPACKET) +
+ MAX_INTERNAL_PACKET);
+ if (xosd != xosdNone) {
+ return xosdUnknown;
+ }
+ wParam -= MAX_INTERNAL_PACKET;
+ lParam += MAX_INTERNAL_PACKET;
+
+ pMpckt->packetNum += 1;
+ }
+
+ memcpy(pMpckt->rgchData, (LPB) lParam, wParam);
+
+ PnlblkRp->cchMessage = (short)(wParam + sizeof(MPACKET));
+
+ xosd = SendData(PnlblkRp, sizeof(NLBLK) + sizeof(MPACKET) + wParam);
+ } else {
+ PnlblkRp->mtypeBlk = mtypeReply;
+
+ PnlblkRp->hpid = hpid;
+ PnlblkRp->cchMessage = (short)wParam;
+ PnlblkRp->seq = ++pkSeq;
+
+ memcpy(PnlblkRp->rgchData, (LPB) lParam, wParam);
+ xosd = SendData(PnlblkRp, sizeof(NLBLK) + wParam);
+ }
+ } else {
+ xosd = xosdIDError;
+ }
+ break;
+
+
+ case tlfRequest:
+ DEBUG_OUT( "DMTlFunc: tlfRequest\n" );
+ if ( !FConnected ) {
+ xosd = xosdIDError;
+ } else {
+ cb = ibMaxDM;
+ if (wParam > MAX_INTERNAL_PACKET) {
+ pMpckt = (MPACKET * ) PnlblkRq->rgchData;
+ PnlblkRq->mtypeBlk = mtypeSyncMulti;
+ PnlblkRq->hpid = hpid;
+ PnlblkRq->cchMessage = MAX_INTERNAL_PACKET + sizeof(MPACKET);
+ PnlblkRq->seq = ++pkSeq;
+ pMpckt->packetNum = 0;
+
+ pMpckt->packetCount = (((short)wParam + MAX_INTERNAL_PACKET - 1) /
+ MAX_INTERNAL_PACKET);
+ while (wParam > MAX_INTERNAL_PACKET) {
+ memcpy(pMpckt->rgchData, (LPB) lParam, MAX_INTERNAL_PACKET);
+ xosd = SendData(PnlblkRq, sizeof(NLBLK) + sizeof(MPACKET) +
+ MAX_INTERNAL_PACKET);
+ if (xosd != xosdNone) {
+ return xosdUnknown;
+ }
+ wParam -= MAX_INTERNAL_PACKET;
+ lParam += MAX_INTERNAL_PACKET;
+
+ pMpckt->packetNum += 1;
+ }
+
+ PnlblkRq->cchMessage = (short)(wParam + sizeof(MPACKET));
+
+ memcpy(pMpckt->rgchData, (LPB) lParam, wParam);
+ xosd = SendRequest(mtypeReply, PnlblkRq, sizeof(NLBLK) +
+ sizeof(MPACKET) +
+ wParam, lpbDM, &cb, INFINITE);
+ } else {
+ PnlblkRq->mtypeBlk = mtypeSync;
+ PnlblkRq->cchMessage = (short)wParam;
+ PnlblkRq->hpid = hpid;
+ PnlblkRq->seq = ++pkSeq;
+ memcpy(PnlblkRq->rgchData, (char *) lParam, wParam);
+ xosd = SendRequest(mtypeReply, PnlblkRq, wParam + sizeof(NLBLK),
+ lpbDM, &cb, INFINITE);
+ }
+ }
+ break;
+
+ default:
+ DEBUG_OUT( "DMTlFunc: **** unknown tlf ****\n" );
+ assert ( FALSE );
+ break;
+ }
+ return xosd;
+}
+
+
+
+BOOL
+CallBack(
+ PNLBLK pnlblk,
+ int cb
+ )
+{
+ MPACKET * pMpacket;
+ DPACKET * pDpckt;
+ static int cbMulti = 0;
+ static char * pbMulti = NULL;
+
+
+ switch( pnlblk->mtypeBlk ) {
+ case mtypeVersionRequest:
+ DEBUG_OUT("CallBack: mtypeVersionRequest\n" );
+ TLFunc(tlfSendVersion, pnlblk->hpid, 0, 0);
+ break;
+
+
+ case mtypeSyncMulti:
+ case mtypeAsyncMulti:
+#if DBG
+ if (pnlblk->mtypeBlk == mtypeAsyncMulti) {
+ DEBUG_OUT("CallBack: mtypeAsyncMulti\n" );
+ EnterCriticalSection(&csExpecting);
+ FExpectingReply = 0;
+ LeaveCriticalSection(&csExpecting);
+ } else {
+ DEBUG_OUT("CallBack: mtypeSyncMulti\n" );
+ EnterCriticalSection(&csExpecting);
+ FExpectingReply = 1;
+ FExpectingSeq = pnlblk->seq;
+ LeaveCriticalSection(&csExpecting);
+ }
+#endif
+ assert( cb == (int) (pnlblk->cchMessage + sizeof(NLBLK)) );
+ if (FConnected) {
+ pMpacket = (MPACKET *) pnlblk->rgchData;
+ if (pMpacket->packetNum == 0) {
+ if (cbMulti < pMpacket->packetCount * MAX_INTERNAL_PACKET) {
+ pbMulti = realloc(pbMulti, pMpacket->packetCount *
+ MAX_INTERNAL_PACKET);
+ }
+ }
+ memcpy(pbMulti + pMpacket->packetNum * MAX_INTERNAL_PACKET,
+ pMpacket->rgchData, pnlblk->cchMessage - sizeof(MPACKET));
+ if (pMpacket->packetNum + 1 == pMpacket->packetCount) {
+ cb = pMpacket->packetNum * MAX_INTERNAL_PACKET +
+ pnlblk->cchMessage - sizeof(MPACKET);
+ if (TLCallBack != NULL) {
+ TLCallBack( pnlblk->hpid, (WORD) cb, (LONG) pbMulti);
+ } else if (LpDmFunc != NULL) {
+ LpDmFunc((WORD) cb, pbMulti);
+ }
+ }
+ }
+ break;
+
+ case mtypeAsync:
+ case mtypeSync:
+#if DBG
+ if (pnlblk->mtypeBlk == mtypeAsync) {
+ DEBUG_OUT("CallBack: mtypeAsync\n" );
+ EnterCriticalSection(&csExpecting);
+ FExpectingReply = 0;
+ LeaveCriticalSection(&csExpecting);
+ } else {
+ DEBUG_OUT("CallBack: mtypeSync\n" );
+ EnterCriticalSection(&csExpecting);
+ FExpectingReply = 1;
+ FExpectingSeq = pnlblk->seq;
+ LeaveCriticalSection(&csExpecting);
+ }
+#endif
+ assert( cb == (int) (pnlblk->cchMessage + sizeof(NLBLK)) );
+ if (FConnected) {
+ if (TLCallBack != NULL) {
+ TLCallBack( pnlblk->hpid, pnlblk->cchMessage,
+ (LONG) pnlblk->rgchData);
+ } else if (LpDmFunc != NULL) {
+ LpDmFunc(pnlblk->cchMessage, pnlblk->rgchData);
+ }
+ }
+ break;
+
+ case mtypeDisconnect:
+ DEBUG_OUT("CallBack: mtypeDisconnect\n" );
+ if (TLCallBack != NULL) {
+ RTP rtp = { dbcRemoteQuit, pnlblk->hpid, 0, 0 };
+ TLCallBack(pnlblk->hpid, sizeof(rtp), (LONG)&rtp);
+ }
+ if (LpUiServer) {
+ pDpckt = (DPACKET *) pnlblk->rgchData;
+ LpUiServer( tlcbDisconnect,
+ pDpckt->hpid,
+ pDpckt->htid,
+ pDpckt->fContinue,
+ 0
+ );
+ }
+ break;
+
+ case mtypeTransportIsDead:
+ DEBUG_OUT("CallBack: mtypeTransportIsDead\n" );
+ TransportFailure();
+ return FALSE;
+ break;
+
+ default:
+ assert(FALSE);
+ }
+
+ return TRUE;
+}
+
+
+
+VOID
+TransportFailure(
+ VOID
+ )
+{
+ DEBUG_OUT("*** TransportFailure()\n" );
+
+ if (LpUiServer) {
+
+ LpUiServer(tlcbDisconnect, 0, 0, 0, 0);
+ TLFunc( tlfRemoteQuit, 0, 0, 0 );
+
+ } else if (TLCallBack) {
+
+ RTP rtp = { dbcRemoteQuit, hpidRoot, 0, 0 };
+ TLCallBack( hpidRoot, sizeof(rtp), (LONG)&rtp );
+
+ }
+
+ FConnected = FALSE;
+
+ return;
+}
+
+
+XOSD
+SendData(
+ LPV lpvOut,
+ int cbOut
+ )
+{
+ if (!TlWriteTransport(lpvOut, cbOut)) {
+ return xosdWrite;
+ }
+
+ return xosdNone;
+}
+
+
+//
+// data structures for tlfreplys
+//
+// these structures exist in the physical layer of the
+// transport layer (pipe, serial, ...)
+//
+
+extern CRITICAL_SECTION CsReplys;
+extern int IReplys;
+extern REPLY RgReplys[];
+
+
+XOSD
+SendRequest(
+ int mtypeResponse,
+ LPV lpvOut,
+ int cbOut,
+ LPV lpvReply,
+ int * pcbReply,
+ DWORD dwTimeOut
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ mtypeResponse - Supplies the packet type to be used as a response
+
+ lpvOut - Supplies the request packet
+
+ cbOut - Supplies length of request packet
+
+ lpvIn - Returns the reply data
+
+ cbIn - Supplies length of return bugger
+
+ dwTimeOut - Supplies -1 or # of seconds to wait before timeout
+
+Return Value:
+
+ XOSD error code
+
+--*/
+
+{
+ int i;
+ XOSD xosd = xosdNone;
+
+ //
+ // Allow us to work with impunity
+ //
+
+ EnterCriticalSection(&CsReplys);
+
+ //
+ // Are we in trouble due to overflow?
+ //
+
+ if (IReplys == SIZE_OF_REPLYS) {
+ LeaveCriticalSection(&CsReplys);
+ return xosdUnknown;
+ }
+
+ assert( IReplys == 0 );
+
+ //
+ // Setup the reply location
+ //
+
+ RgReplys[IReplys].lpb = (char *) lpvReply;
+ RgReplys[IReplys].cbBuffer = *pcbReply;
+ RgReplys[IReplys].cbRet = 0;
+
+ i = IReplys;
+
+ IReplys += 1;
+
+ //
+ //
+ //
+ ResetEvent( RgReplys[i].hEvent );
+
+
+ LeaveCriticalSection(&CsReplys);
+
+ //
+ // No finally mail the request out
+ //
+
+ if (!TlWriteTransport(lpvOut, cbOut)) {
+ EnterCriticalSection(&CsReplys);
+ IReplys -= 1;
+ LeaveCriticalSection(&CsReplys);
+ return xosdWrite;
+ }
+
+ //
+ // Wait for the reply to come back
+ //
+
+ if (dwTimeOut != INFINITE) {
+ dwTimeOut *= 1000;
+ }
+
+ WaitForSingleObject(RgReplys[i].hEvent, dwTimeOut);
+
+ //
+ // Now get the message back
+ //
+
+ EnterCriticalSection(&CsReplys);
+
+ RgReplys[i].lpb = NULL;
+ *pcbReply = RgReplys[i].cbRet;
+ if (RgReplys[i].cbRet == 0) {
+ xosd = xosdUnknown;
+ }
+
+ assert( IReplys == i + 1 );
+
+ if (IReplys == i + 1) {
+ IReplys = i;
+ } else {
+ xosd = xosdUnknown;
+ }
+
+ LeaveCriticalSection(&CsReplys);
+ return xosd;
+}
+
+VOID
+DebugPrint(
+ LPSTR szFormat,
+ ...
+ )
+{
+ va_list marker;
+ int n;
+ char rgchDebug[4096];
+
+ va_start( marker, szFormat );
+ n = _vsnprintf(rgchDebug, sizeof(rgchDebug), szFormat, marker );
+ va_end( marker);
+
+ if (n == -1) {
+ rgchDebug[sizeof(rgchDebug)-1] = '\0';
+ }
+
+ OutputDebugString( rgchDebug );
+ return;
+}
+
+VOID
+ShowAssert(
+ LPSTR condition,
+ UINT line,
+ LPSTR file
+ )
+{
+ char text[4096];
+ int id;
+
+ _snprintf(text, sizeof(text), "Assertion failed - Line:%u, File:%Fs, Condition:%Fs", line, file, condition);
+ DebugPrint( "%s\r\n", text );
+ id = MessageBox( NULL, text, "Pipe Transport", MB_YESNO | MB_ICONHAND | MB_TASKMODAL | MB_SETFOREGROUND );
+ if (id != IDYES) {
+ DebugBreak();
+ }
+
+ return;
+}
diff --git a/private/windbg/remote/xport/xport.h b/private/windbg/remote/xport/xport.h
new file mode 100644
index 000000000..f5d7da04a
--- /dev/null
+++ b/private/windbg/remote/xport/xport.h
@@ -0,0 +1,136 @@
+//
+// values for MTYPE
+//
+
+enum {
+ mtypeAsync = 0x10, // single async packet
+ mtypeAsyncMulti = 0x11, // multliple packet types
+ mtypeSync = 0x12,
+ mtypeSyncMulti = 0x13,
+ mtypeReply = 0x20, // single reply packet
+ mtypeReplyMulti = 0x21, // multiple packet
+ mtypeDisconnect = 0x30, // disconnect packet
+ mtypeVersionRequest = 0x40, // version request packet (no data)
+ mtypeVersionReply = 0x41, // version reply packet (contains version data)
+ mtypeTransportIsDead = 0x42 // Internal message
+};
+typedef char MTYPE;
+
+
+//
+// structure for message packet
+//
+
+typedef struct {
+ MTYPE mtypeBlk;
+ char pad;
+ short cchMessage;
+ HPID hpid;
+ DWORD seq;
+ char rgchData[];
+} NLBLK, *PNLBLK;
+
+typedef struct {
+ HPID hpid;
+ HTID htid;
+ BOOL fContinue;
+} DPACKET, *PDPACKET;
+
+typedef struct {
+ short packetNum;
+ short packetCount;
+ char rgchData[];
+} MPACKET;
+
+#define MAX_INTERNAL_PACKET 4096
+
+#define SIZE_OF_REPLYS 1
+typedef struct _tagREPLY {
+ HANDLE hEvent;
+ char * lpb;
+ int cbBuffer;
+ int cbRet;
+} REPLY, *LPREPLY;
+
+
+//
+// these functions MUST exist in the physical layer (pipe, serial, ...)
+// and are called by the generic xport code
+//
+
+BOOL
+TlWriteTransport(
+ PUCHAR pch,
+ DWORD cch
+ );
+
+XOSD
+TlDestroyTransport(
+ VOID
+ );
+
+XOSD
+TlCreateTransport(
+ LPSTR szName
+ );
+
+XOSD
+TlConnectTransport(
+ VOID
+ );
+
+BOOL
+TlDisconnectTransport(
+ VOID
+ );
+
+BOOL
+TlFlushTransport(
+ VOID
+ );
+
+XOSD
+TlCreateClient(
+ LPSTR szName
+ );
+
+BOOL
+CallBack(
+ PNLBLK pnlblk,
+ int cb
+ );
+
+VOID
+TransportFailure(
+ VOID
+ );
+
+
+
+#if DBG
+
+extern BOOL FVerbose;
+extern void DebugPrint(char *, ...);
+extern void ShowAssert(LPSTR,UINT,LPSTR);
+
+#define assert(exp) if (!(exp)) { ShowAssert(#exp,__LINE__,__FILE__); }
+#define DPRINT(args) if (FVerbose) { DebugPrint args; }
+#define DEBUG_OUT(str) DPRINT((str))
+#define DEBUG_OUT1(str, a1) DPRINT((str, a1))
+#define DEBUG_OUT2(str, a1, a2) DPRINT((str, a1, a2))
+#define DEBUG_OUT3(str, a1, a2, a3) DPRINT((str, a1, a2, a3))
+#define DEBUG_OUT4(str, a1, a2, a3, a4) DPRINT((str, a1, a2, a3, a4))
+#define DEBUG_OUT5(str, a1, a2, a3, a4, a5) DPRINT((str, a1, a2, a3, a4, a5))
+
+#else
+
+#define assert(exp)
+#define DPRINT(args)
+#define DEBUG_OUT(str)
+#define DEBUG_OUT1(str, a1)
+#define DEBUG_OUT2(str, a1, a2)
+#define DEBUG_OUT3(str, a1, a2, a3)
+#define DEBUG_OUT4(str, a1, a2, a3, a4)
+#define DEBUG_OUT5(str, a1, a2, a3, a4, a5)
+
+#endif
diff --git a/private/windbg/symcvt/dirs b/private/windbg/symcvt/dirs
new file mode 100644
index 000000000..00030c171
--- /dev/null
+++ b/private/windbg/symcvt/dirs
@@ -0,0 +1,17 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS=symcvt \
+ symedit
diff --git a/private/windbg/symcvt/include/cofftocv.h b/private/windbg/symcvt/include/cofftocv.h
new file mode 100644
index 000000000..bc0d78269
--- /dev/null
+++ b/private/windbg/symcvt/include/cofftocv.h
@@ -0,0 +1,7 @@
+/*
+ * cofftocv.h -- This file contains prototypes, type definitions
+ * and other information relative to COFF to CODEVIEW converstions
+ */
+
+BOOL ConvertCoffToCv( PPOINTERS p );
+
diff --git a/private/windbg/symcvt/include/cv.h b/private/windbg/symcvt/include/cv.h
new file mode 100644
index 000000000..aca554fd5
--- /dev/null
+++ b/private/windbg/symcvt/include/cv.h
@@ -0,0 +1,69 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cv.h
+
+Abstract:
+
+ This file contains all of the type definitions for accessing
+ CODEVIEW data.
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+#include <cvtypes.hxx>
+#include <cvinfo.h>
+#include <cvexefmt.h>
+
+// Global Segment Info table
+typedef struct _sgf {
+ unsigned short fRead :1;
+ unsigned short fWrite :1;
+ unsigned short fExecute:1;
+ unsigned short f32Bit :1;
+ unsigned short res1 :4;
+ unsigned short fSel :1;
+ unsigned short fAbs :1;
+ unsigned short res2 :2;
+ unsigned short fGroup :1;
+ unsigned short res3 :3;
+} SGF;
+
+typedef struct _sgi {
+ SGF sgf; // Segment flags
+ unsigned short iovl; // Overlay number
+ unsigned short igr; // Group index
+ unsigned short isgPhy; // Physical segment index
+ unsigned short isegName; // Index to segment name
+ unsigned short iclassName; // Index to segment class name
+ unsigned long doffseg; // Starting offset inside physical segment
+ unsigned long cbSeg; // Logical segment size
+} SGI;
+
+typedef struct _sgm {
+ unsigned short cSeg; // number of segment descriptors
+ unsigned short cSegLog; // number of logical segment descriptors
+} SGM;
+
+#define FileAlign(x) ( ((x) + p->optrs.optHdr->FileAlignment - 1) & \
+ ~(p->optrs.optHdr->FileAlignment - 1) )
+#define SectionAlign(x) (((x) + p->optrs.optHdr->SectionAlignment - 1) & \
+ ~(p->optrs.optHdr->SectionAlignment - 1) )
+
+#define NextSym32(m) ((DATASYM32 *) \
+ (((DWORD)(m) + sizeof(DATASYM32) + \
+ ((DATASYM32*)(m))->name[0] + 3) & ~3))
+
+#define NextSym16(m) ((DATASYM16 *) \
+ (((DWORD)(m) + sizeof(DATASYM16) + \
+ ((DATASYM16*)(m))->name[0] + 1) & ~1))
diff --git a/private/windbg/symcvt/include/cvcommon.h b/private/windbg/symcvt/include/cvcommon.h
new file mode 100644
index 000000000..3be55aad5
--- /dev/null
+++ b/private/windbg/symcvt/include/cvcommon.h
@@ -0,0 +1,15 @@
+/*
+ * PROTOTYPES, TYPEDEFS and other items for cvcommon.c
+ */
+
+DWORD CreateSignature( PPOINTERS p );
+DWORD CreateDirectories( PPOINTERS p );
+DWORD CreateModuleDirectoryEntries( PPOINTERS p );
+DWORD CreateSegMapDirectoryEntries( PPOINTERS p );
+DWORD CreateSrcModulesDirectoryEntries( PPOINTERS p );
+DWORD CreatePublicDirectoryEntries( PPOINTERS p );
+DWORD CreateSymbolHashTable( PPOINTERS p );
+DWORD CreateAddressSortTable( PPOINTERS p );
+DWORD DWordXorLrl(char * szSym);
+OMFModule * NextMod(OMFModule * pMod);
+VOID UpdatePtrs( PPOINTERS p, PPTRINFO pi, LPVOID lpv, DWORD count );
diff --git a/private/windbg/symcvt/include/symcvt.h b/private/windbg/symcvt/include/symcvt.h
new file mode 100644
index 000000000..c2d6ade7b
--- /dev/null
+++ b/private/windbg/symcvt/include/symcvt.h
@@ -0,0 +1,91 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ symcvt.h
+
+Abstract:
+
+ This file contains all of the type definitions and prototypes
+ necessary to access the symcvt library.
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+typedef struct tagPTRINFO {
+ DWORD size;
+ DWORD count;
+ PUCHAR ptr;
+} PTRINFO, *PPTRINFO;
+
+typedef struct tagIMAGEPOINTERS {
+ char szName[MAX_PATH];
+ HANDLE hFile;
+ BOOL CloseFile; // TRUE if symcvt opened file
+ HANDLE hMap;
+ DWORD fsize;
+ PUCHAR fptr;
+ BOOLEAN fRomImage;
+ PIMAGE_DOS_HEADER dosHdr;
+ PIMAGE_NT_HEADERS ntHdr;
+ PIMAGE_ROM_HEADERS romHdr;
+ PIMAGE_FILE_HEADER fileHdr;
+ PIMAGE_OPTIONAL_HEADER optHdr;
+ PIMAGE_SEPARATE_DEBUG_HEADER sepHdr;
+ int cDebugDir;
+ PIMAGE_DEBUG_DIRECTORY * rgDebugDir;
+ PIMAGE_SECTION_HEADER sectionHdrs;
+ PIMAGE_SECTION_HEADER debugSection;
+ PIMAGE_SYMBOL AllSymbols;
+ PUCHAR stringTable;
+ int numberOfSymbols;
+ int numberOfSections;
+ PCHAR * rgpbDebugSave;
+} IMAGEPOINTERS, *PIMAGEPOINTERS;
+
+#define COFF_DIR(x) ((x)->rgDebugDir[IMAGE_DEBUG_TYPE_COFF])
+#define CV_DIR(x) ((x)->rgDebugDir[IMAGE_DEBUG_TYPE_CODEVIEW])
+
+typedef struct _MODULEINFO {
+ DWORD iMod;
+ DWORD cb;
+ DWORD SrcModule;
+ LPSTR name;
+} MODULEINFO, *LPMODULEINFO;
+
+typedef struct tagPOINTERS {
+ IMAGEPOINTERS iptrs; // input file pointers
+ IMAGEPOINTERS optrs; // output file pointers
+ PTRINFO pCvStart; // start of cv info
+ PUCHAR pCvCurr; // current cv pointer
+ PTRINFO pCvModules; // module information
+ PTRINFO pCvSrcModules; // source module information
+ PTRINFO pCvPublics; // publics information
+ PTRINFO pCvSegName; // segment names
+ PTRINFO pCvSegMap; // segment map
+ PTRINFO pCvSymHash; // symbol hash table
+ PTRINFO pCvAddrSort; // address sort table
+ LPMODULEINFO pMi;
+ DWORD modcnt;
+} POINTERS, *PPOINTERS;
+
+typedef char * (* CONVERTPROC) (HANDLE, char *);
+
+BOOL MapInputFile ( PPOINTERS p, HANDLE hFile, char *fname);
+BOOL UnMapInputFile ( PPOINTERS p );
+BOOL CalculateNtImagePointers( PIMAGEPOINTERS p );
+
+#define align(_n) ((4 - (( (DWORD)_n ) % 4 )) & 3)
+
+#include "heap.h"
diff --git a/private/windbg/symcvt/include/symtocv.h b/private/windbg/symcvt/include/symtocv.h
new file mode 100644
index 000000000..fdf5a12b4
--- /dev/null
+++ b/private/windbg/symcvt/include/symtocv.h
@@ -0,0 +1,7 @@
+/*
+ * symtocv.h -- This file contains prototypes, type definitions
+ * and other information relative to SYM FILES to CODEVIEW converstions
+ */
+
+BOOL ConvertSymToCv( PPOINTERS p );
+
diff --git a/private/windbg/symcvt/symcvt/cofftocv.c b/private/windbg/symcvt/symcvt/cofftocv.c
new file mode 100644
index 000000000..ca8c4dbca
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/cofftocv.c
@@ -0,0 +1,847 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cv.c
+
+Abstract:
+
+ This module handles the conversion activities requires for converting
+ COFF debug data to CODEVIEW debug data.
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <imagehlp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cv.h"
+#include "symcvt.h"
+#include "cvcommon.h"
+
+typedef struct tagOFFSETSORT {
+ DWORD dwOffset; // offset for the symbol
+ DWORD dwSection; // section number of the symbol
+ DATASYM32 *dataSym; // pointer to the symbol info
+} OFFSETSORT;
+
+
+#define n_name N.ShortName
+#define n_zeroes N.Name.Short
+#define n_nptr N.LongName[1]
+#define n_offset N.Name.Long
+
+static LPSTR GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s );
+DWORD CreateModulesFromCoff( PPOINTERS p );
+DWORD CreatePublicsFromCoff( PPOINTERS p );
+DWORD CreateSegMapFromCoff( PPOINTERS p );
+DWORD CreateSrcLinenumbers( PPOINTERS p );
+
+
+
+LONG
+GuardPageFilterFunction(
+ DWORD ec,
+ LPEXCEPTION_POINTERS lpep
+ )
+
+/*++
+
+Routine Description:
+
+ This function catches all exceptions from the convertcofftocv function
+ and all that it calls. The purpose of this function is allocate memory
+ when it is necessary. This happens because the cofftocv conversion cannot
+ estimate the memory requirements before the conversion takes place. To
+ handle this properly space in the virtual address space is reserved, the
+ reservation amount is 10 times the image size. The first page is commited
+ and then the conversion is started. When an access violation occurs and the
+ page that is trying to be access has a protection of noaccess then the
+ page is committed. Any other exception is not handled.
+
+Arguments:
+
+ ec - the ecxeption code (should be EXCEPTION_ACCESS_VIOLATION)
+ lpep - pointer to the exception record and context record
+
+
+Return Value:
+
+ EXCEPTION_CONTINUE_EXECUTION - access violation handled
+ EXCEPTION_EXECUTE_HANDLER - unknown exception and is not handled
+
+--*/
+
+{
+ LPVOID vaddr;
+ SYSTEM_INFO si;
+ MEMORY_BASIC_INFORMATION mbi;
+
+
+ if (ec == EXCEPTION_ACCESS_VIOLATION) {
+ vaddr = (LPVOID)lpep->ExceptionRecord->ExceptionInformation[1];
+ VirtualQuery( vaddr, &mbi, sizeof(mbi) );
+ if (mbi.AllocationProtect == PAGE_NOACCESS) {
+ GetSystemInfo( &si );
+ VirtualAlloc( vaddr, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+
+// return EXCEPTION_CONTINUE_SEARCH;
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+BOOL
+ConvertCoffToCv( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ This is the control function for the conversion of COFF to CODEVIEW
+ debug data. It calls individual functions for the conversion of
+ specific types of debug data.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ TRUE - conversion succeded
+ FALSE - conversion failed
+
+--*/
+
+{
+ SYSTEM_INFO si;
+ DWORD cbsize;
+ BOOL rval = TRUE;
+
+
+ ValidateHeap();
+
+ GetSystemInfo( &si );
+ cbsize = max( p->iptrs.fsize * 10, si.dwPageSize * 10 );
+
+ //
+ // reserve all necessary pages
+ //
+ p->pCvCurr = p->pCvStart.ptr = VirtualAlloc( NULL, cbsize, MEM_RESERVE, PAGE_NOACCESS );
+
+ //
+ // commit the first pages
+ //
+ VirtualAlloc( p->pCvCurr, min( cbsize, 5 * si.dwPageSize), MEM_COMMIT, PAGE_READWRITE );
+
+
+ __try {
+
+ ValidateHeap();
+ CreateSignature( p );
+ ValidateHeap();
+ CreateModulesFromCoff( p );
+ ValidateHeap();
+ CreatePublicsFromCoff( p );
+ ValidateHeap();
+ CreateSymbolHashTable( p );
+ ValidateHeap();
+ CreateAddressSortTable( p );
+ ValidateHeap();
+ CreateSegMapFromCoff( p );
+ ValidateHeap();
+// CreateSrcLinenumbers( p );
+ ValidateHeap();
+ CreateDirectories( p );
+ ValidateHeap();
+
+ } __except ( GuardPageFilterFunction( GetExceptionCode(), GetExceptionInformation() )) {
+
+ VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
+ p->pCvStart.ptr = NULL;
+ rval = FALSE;
+
+ }
+
+ ValidateHeap();
+ if (rval) {
+ p->pCvCurr = LocalAlloc( NONZEROLPTR, p->pCvStart.size );
+ CopyMemory( p->pCvCurr, p->pCvStart.ptr, p->pCvStart.size );
+ VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
+ p->pCvStart.ptr = p->pCvCurr;
+ }
+ ValidateHeap();
+
+ return rval;
+}
+
+
+DWORD
+CreateModulesFromCoff( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the individual CV module records. There is one CV module
+ record for each .FILE record in the COFF debug data. This is true
+ even if the COFF size is zero.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of modules that were created.
+
+--*/
+
+{
+ int i;
+ OMFModule *m = NULL;
+ char * pb;
+ PIMAGE_SECTION_HEADER sh;
+
+ p->pMi = (LPMODULEINFO) LocalAlloc( LPTR, sizeof(MODULEINFO) );
+
+ m = (OMFModule *) p->pCvCurr;
+ m->ovlNumber = 0;
+ m->iLib = 0;
+ m->Style[0] = 'C';
+ m->Style[1] = 'V';
+
+ sh = p->iptrs.sectionHdrs;
+
+ for (i=0; i < p->iptrs.numberOfSections; i++) {
+ m->SegInfo[i].Seg = i + 1;
+ m->SegInfo[i].cbSeg = sh->Misc.VirtualSize;
+ // Note: Off isn't the va where this section starts,
+ // it's where the symbolic in this section starts.
+ m->SegInfo[i].Off = 0;
+ sh++;
+ }
+
+ m->cSeg = i;
+
+ pb = (char *) &m->SegInfo[i];
+ *pb = strlen("foo.c");
+ memcpy(pb+1, "foo.c", *pb);
+
+ p->pMi[0].name = "foo.c";
+ p->pMi[0].iMod = 1;
+ p->pMi[0].cb = 0;
+ p->pMi[0].SrcModule = 0;
+
+ m = NextMod(m);
+ p->modcnt = 1;
+ UpdatePtrs( p, &p->pCvModules, (LPVOID)m, 1 );
+
+ return 1;
+}
+
+
+DWORD
+CreatePublicsFromCoff( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the individual CV public symbol records. There is one CV
+ public record created for each COFF symbol that is marked as EXTERNAL
+ and has a section number greater than zero. The resulting CV publics
+ are sorted by section and offset.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of publics created.
+
+--*/
+
+{
+ int i;
+ DWORD numaux;
+ DWORD numsyms = 0;
+ char szSymName[256];
+ PIMAGE_SYMBOL Symbol;
+ OMFSymHash *omfSymHash;
+ DATASYM32 *dataSym;
+ DATASYM32 *dataSym2;
+
+ omfSymHash = (OMFSymHash *) p->pCvCurr;
+ dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
+
+ for (i= 0, Symbol = p->iptrs.AllSymbols;
+ i < p->iptrs.numberOfSymbols;
+ i += numaux + 1, Symbol += numaux + 1) {
+
+ if ((Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) &&
+ (Symbol->SectionNumber > 0)) {
+
+ if (GetSymName( Symbol, p->iptrs.stringTable, szSymName )) {
+ dataSym->rectyp = S_PUB32;
+ dataSym->seg = Symbol->SectionNumber;
+ dataSym->off = Symbol->Value -
+ p->iptrs.sectionHdrs[Symbol->SectionNumber-1].VirtualAddress;
+ dataSym->typind = 0;
+ dataSym->name[0] = strlen( szSymName );
+ strcpy( &dataSym->name[1], szSymName );
+ dataSym2 = NextSym32( dataSym );
+ dataSym->reclen = (USHORT) ((DWORD)dataSym2 - (DWORD)dataSym) - 2;
+ dataSym = dataSym2;
+ numsyms += 1;
+ }
+ }
+ numaux = Symbol->NumberOfAuxSymbols;
+ }
+
+ UpdatePtrs( p, &p->pCvPublics, (LPVOID)dataSym, numsyms );
+
+ omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
+ omfSymHash->symhash = 0;
+ omfSymHash->addrhash = 0;
+ omfSymHash->cbHSym = 0;
+ omfSymHash->cbHAddr = 0;
+
+ return numsyms;
+} /* CreatePublisFromCoff() */
+
+
+DWORD
+CreateSrcLinenumbers(
+ PPOINTERS p
+ )
+
+/*++
+
+Routine Description:
+
+ Creates the individual CV soure line number records.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of publics created.
+
+--*/
+
+{
+ typedef struct _SEGINFO {
+ DWORD start;
+ DWORD end;
+ DWORD cbLines;
+ DWORD ptrLines;
+ DWORD va;
+ DWORD num;
+ BOOL used;
+ } SEGINFO, *LPSEGINFO;
+
+ typedef struct _SRCINFO {
+ LPSEGINFO seg;
+ DWORD numSeg;
+ DWORD cbSeg;
+ CHAR name[MAX_PATH+1];
+ } SRCINFO, *LPSRCINFO;
+
+ typedef struct _SECTINFO {
+ DWORD va;
+ DWORD size;
+ DWORD ptrLines;
+ DWORD numLines;
+ } SECTINFO, *LPSECTINFO;
+
+
+ DWORD i;
+ DWORD j;
+ DWORD k;
+ DWORD l;
+ DWORD actual;
+ DWORD sidx;
+ DWORD NumSrcFiles;
+ DWORD SrcFileCnt;
+ DWORD numaux;
+ PIMAGE_SYMBOL Symbol;
+ PIMAGE_AUX_SYMBOL AuxSymbol;
+ BOOL first = TRUE;
+ OMFSourceModule *SrcModule;
+ OMFSourceFile *SrcFile;
+ OMFSourceLine *SrcLine;
+ LPBYTE lpb;
+ LPDWORD lpdw;
+ PUSHORT lps;
+ PUCHAR lpc;
+ PIMAGE_LINENUMBER pil, pilSave;
+ LPSRCINFO si;
+ LPSECTINFO sections;
+
+
+ //
+ // setup the section info structure
+ //
+ sections = (LPSECTINFO) LocalAlloc( NONZEROLPTR, sizeof(SECTINFO) * p->iptrs.numberOfSections );
+ for (i=0; i<(DWORD)p->iptrs.numberOfSections; i++) {
+ sections[i].va = p->iptrs.sectionHdrs[i].VirtualAddress;
+ sections[i].size = p->iptrs.sectionHdrs[i].SizeOfRawData;
+ sections[i].ptrLines = p->iptrs.sectionHdrs[i].PointerToLinenumbers;
+ sections[i].numLines = p->iptrs.sectionHdrs[i].NumberOfLinenumbers;
+ }
+
+ //
+ // count the number of source files that contibute linenumbers
+ //
+ SrcFileCnt = 100;
+ si = (LPSRCINFO) LocalAlloc( LPTR, sizeof(SRCINFO) * SrcFileCnt );
+ for (i=0, j=0, Symbol=p->iptrs.AllSymbols, NumSrcFiles=0;
+ i<(DWORD)p->iptrs.numberOfSymbols;
+ i+=(numaux+1), Symbol+=(numaux + 1)) {
+
+ numaux = Symbol->NumberOfAuxSymbols;
+ AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
+
+ if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
+
+ if (!first) {
+ si[NumSrcFiles].cbSeg = j;
+ NumSrcFiles++;
+ if (NumSrcFiles == SrcFileCnt) {
+ SrcFileCnt += 100;
+ si = (LPSRCINFO) LocalReAlloc( si, sizeof(SRCINFO) * SrcFileCnt, LMEM_ZEROINIT );
+ }
+ }
+
+ memcpy(si[NumSrcFiles].name, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
+ si[NumSrcFiles].name[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
+ si[NumSrcFiles].numSeg = 100;
+ si[NumSrcFiles].seg = (LPSEGINFO) LocalAlloc( LPTR, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
+ first = FALSE;
+ j = 0;
+
+ }
+
+ //
+ // we do not want to look for segment information until we
+ // have found a valid source file
+ //
+ if (first) {
+ continue;
+ }
+
+ //
+ // check the symbol to see if it is a segment record
+ //
+ if (numaux && Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC &&
+ (*Symbol->n_name == '.' ||
+ ((Symbol->Type & 0xf) == IMAGE_SYM_TYPE_NULL && AuxSymbol->Section.Length)) &&
+ AuxSymbol->Section.NumberOfLinenumbers > 0) {
+
+ //
+ // find the section that this symbol belongs to
+ //
+ for (k=0; k<(DWORD)p->iptrs.numberOfSections; k++) {
+ if (Symbol->Value >= sections[k].va &&
+ Symbol->Value < sections[k].va + sections[k].size) {
+
+ sidx = k;
+ break;
+
+ }
+ }
+
+ if (k != (DWORD)p->iptrs.numberOfSections &&
+ p->iptrs.sectionHdrs[k].NumberOfLinenumbers) {
+
+ pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + sections[sidx].ptrLines);
+ k = 0;
+
+ while( k < AuxSymbol->Section.NumberOfLinenumbers ) {
+
+ //
+ // count the linenumbers in this section or sub-section
+ //
+ for ( pilSave=pil,l=0;
+ k<AuxSymbol->Section.NumberOfLinenumbers;
+ k++,pilSave++,l++ ) {
+
+ if ((k != (DWORD)AuxSymbol->Section.NumberOfLinenumbers-1) &&
+ (pilSave->Linenumber > (pilSave+1)->Linenumber)) {
+ pilSave++;
+ l++;
+ break;
+ }
+
+ }
+
+ //
+ // pil == beginning of the range
+ // pilSave == end of the range
+ //
+
+ si[NumSrcFiles].seg[j].start =
+ (pil->Type.VirtualAddress - sections[sidx].va);
+
+ if (sections[sidx].numLines == l) {
+ pilSave--;
+ si[NumSrcFiles].seg[j].end =
+ (pilSave->Type.VirtualAddress - sections[sidx].va) + 1;
+// (Symbol->Value - sections[sidx].va) + 1;
+ } else {
+ si[NumSrcFiles].seg[j].end =
+ (pilSave->Type.VirtualAddress - sections[sidx].va) - 1;
+// (Symbol->Value - sections[sidx].va) - 1;
+ }
+
+ si[NumSrcFiles].seg[j].ptrLines = sections[sidx].ptrLines;
+ si[NumSrcFiles].seg[j].cbLines = l;
+ si[NumSrcFiles].seg[j].va = sections[sidx].va;
+ si[NumSrcFiles].seg[j].num = sidx + 1;
+ si[NumSrcFiles].seg[j].used = FALSE;
+
+ sections[sidx].ptrLines += (l * sizeof(IMAGE_LINENUMBER));
+ sections[sidx].numLines -= l;
+
+ j++;
+ if (j == si[NumSrcFiles].numSeg) {
+ si[NumSrcFiles].numSeg += 100;
+ si[NumSrcFiles].seg = (LPSEGINFO) LocalReAlloc( si[NumSrcFiles].seg,
+ sizeof(SEGINFO) * si[NumSrcFiles].numSeg,
+ LMEM_ZEROINIT );
+ }
+ k++;
+ pil = pilSave;
+ }
+
+ }
+
+ }
+
+ }
+
+ lpb = (LPBYTE) p->pCvCurr;
+
+ //
+ // if there is nothing to do then bail out
+ //
+ if (!NumSrcFiles) {
+ UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, 0 );
+ return 0;
+ }
+
+ for (i=0,actual=0,l=0; i<NumSrcFiles; i++) {
+
+ if (si[i].cbSeg == 0) {
+ continue;
+ }
+
+ //
+ // create the source module header
+ //
+ SrcModule = (OMFSourceModule*) lpb;
+ SrcModule->cFile = 1;
+ SrcModule->cSeg = (USHORT)si[i].cbSeg;
+ SrcModule->baseSrcFile[0] = 0;
+
+ //
+ // write the start/end pairs
+ //
+ lpdw = (LPDWORD) ((LPBYTE)SrcModule + sizeof(OMFSourceModule));
+ for (k=0; k<si[i].cbSeg; k++) {
+ *lpdw++ = si[i].seg[k].start;
+ *lpdw++ = si[i].seg[k].end;
+ }
+
+ //
+ // write the segment numbers
+ //
+ lps = (PUSHORT) lpdw;
+ for (k=0; k<si[i].cbSeg; k++) {
+ *lps++ = (USHORT)si[i].seg[k].num;
+ }
+
+ //
+ // align to a dword boundry
+ //
+ lps = (PUSHORT) ((LPBYTE)lps + align(lps));
+
+ //
+ // update the base pointer
+ //
+ SrcModule->baseSrcFile[0] = (DWORD) ((LPBYTE)lps - (LPBYTE)SrcModule);
+
+ //
+ // write the source file record
+ //
+ SrcFile = (OMFSourceFile*) lps;
+ SrcFile->cSeg = (USHORT)si[i].cbSeg;
+ SrcFile->reserved = 0;
+
+ for (k=0; k<si[i].cbSeg; k++) {
+ SrcFile->baseSrcLn[k] = 0;
+ }
+
+ //
+ // write the start/end pairs
+ //
+ lpdw = (LPDWORD) ((LPBYTE)SrcFile + 4 + (4 * si[i].cbSeg));
+ for (k=0; k<si[i].cbSeg; k++) {
+ *lpdw++ = si[i].seg[k].start;
+ *lpdw++ = si[i].seg[k].end;
+ }
+
+ //
+ // write the source file name
+ //
+ lpc = (PUCHAR) lpdw;
+ k = strlen(si[i].name);
+ *lpc++ = (UCHAR) k;
+ strcpy( lpc, si[i].name );
+ lpb = lpc + k;
+
+ //
+ // find the module info struct
+ //
+ for (; l<p->modcnt; l++) {
+ if (_stricmp(p->pMi[l].name,si[i].name)==0) {
+ break;
+ }
+ }
+
+ p->pMi[l].SrcModule = (DWORD) SrcModule;
+
+ //
+ // align to a dword boundry
+ //
+ lpb = (LPBYTE) (lpb + align(lpb));
+
+ //
+ // create the line number pairs
+ //
+ for (k=0; k<si[i].cbSeg; k++) {
+
+ //
+ // find the first line number that applies to this segment
+ //
+ pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + si[i].seg[k].ptrLines);
+
+ //
+ // update the base pointer
+ //
+ SrcFile->baseSrcLn[k] = (DWORD) (lpb - (LPBYTE)SrcModule);
+
+ //
+ // write the line numbers
+ //
+ SrcLine = (OMFSourceLine*) lpb;
+ SrcLine->Seg = (USHORT)si[i].seg[k].num;
+ SrcLine->cLnOff = (USHORT) si[i].seg[k].cbLines;
+ pilSave = pil;
+ lpdw = (LPDWORD) (lpb + 4);
+ for (j=0; j<SrcLine->cLnOff; j++) {
+ *lpdw++ = pil->Type.VirtualAddress - si[i].seg[k].va;
+ pil++;
+ }
+ lps = (PUSHORT) lpdw;
+ pil = pilSave;
+ for (j=0; j<SrcLine->cLnOff; j++) {
+ *lps++ = pil->Linenumber;
+ pil++;
+ }
+
+ //
+ // align to a dword boundry
+ //
+ lps = (PUSHORT) ((LPBYTE)lps + align(lps));
+
+ lpb = (LPBYTE) lps;
+ }
+
+ p->pMi[l].cb = (DWORD)lpb - (DWORD)SrcModule;
+ actual++;
+
+ }
+
+ UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, actual );
+
+ //
+ // cleanup all allocated memory
+ //
+
+ LocalFree( sections );
+
+ for (i=0; i<SrcFileCnt; i++) {
+ if (si[i].seg) {
+ LocalFree( si[i].seg );
+ }
+ }
+
+ LocalFree( si );
+
+ return NumSrcFiles;
+} /* CreateSrcLinenumbers() */
+
+
+DWORD
+CreateSegMapFromCoff( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the CV segment map. The segment map is used by debuggers
+ to aid in address lookups. One segment is created for each COFF
+ section in the image.
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of segments in the map.
+
+--*/
+
+{
+ int i;
+ SGM *sgm;
+ SGI *sgi;
+ PIMAGE_SECTION_HEADER sh;
+ ULONG align;
+
+
+ sgm = (SGM *) p->pCvCurr;
+ sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
+
+ sgm->cSeg = p->iptrs.numberOfSections;
+ sgm->cSegLog = p->iptrs.numberOfSections;
+
+ sh = p->iptrs.sectionHdrs;
+
+ if (p->iptrs.optHdr) {
+ align = p->iptrs.optHdr->FileAlignment;
+ } else {
+ align = p->iptrs.sepHdr->SectionAlignment;
+ }
+
+ for (i=0; i<p->iptrs.numberOfSections; i++, sh++) {
+ sgi->sgf.fRead = (USHORT) ((sh->Characteristics & IMAGE_SCN_MEM_READ) == IMAGE_SCN_MEM_READ);
+ sgi->sgf.fWrite = (USHORT) ((sh->Characteristics & IMAGE_SCN_MEM_WRITE) == IMAGE_SCN_MEM_WRITE);
+ sgi->sgf.fExecute = (USHORT) ((sh->Characteristics & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE);
+ sgi->sgf.f32Bit = 1;
+ sgi->sgf.fSel = 0;
+ sgi->sgf.fAbs = 0;
+ sgi->sgf.fGroup = 1;
+ sgi->iovl = 0;
+ sgi->igr = 0;
+ sgi->isgPhy = (USHORT) i + 1;
+ sgi->isegName = 0;
+ sgi->iclassName = 0;
+ sgi->doffseg = 0;
+ sgi->cbSeg = ((sh->Misc.VirtualSize + (align-1)) & ~(align-1));
+ sgi++;
+ }
+
+ UpdatePtrs( p, &p->pCvSegMap, (LPVOID)sgi, i );
+
+ return i;
+}
+
+
+LPSTR
+GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s )
+
+/*++
+
+Routine Description:
+
+ Extracts the COFF symbol from the image symbol pointer and puts
+ the ascii text in the character pointer passed in.
+
+
+Arguments:
+
+ Symbol - COFF Symbol Record
+ StringTable - COFF string table
+ s - buffer for the symbol string
+
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ DWORD i;
+
+ if (Symbol->n_zeroes) {
+ for (i=0; i<8; i++) {
+ if ((Symbol->n_name[i]>0x1f) && (Symbol->n_name[i]<0x7f)) {
+ *s++ = Symbol->n_name[i];
+ }
+ }
+ *s = 0;
+ }
+ else {
+ if (StringTable[Symbol->n_offset] == '?') {
+ i = UnDecorateSymbolName( &StringTable[Symbol->n_offset],
+ s,
+ 255,
+ UNDNAME_COMPLETE |
+ UNDNAME_NO_LEADING_UNDERSCORES |
+ UNDNAME_NO_MS_KEYWORDS |
+ UNDNAME_NO_FUNCTION_RETURNS |
+ UNDNAME_NO_ALLOCATION_MODEL |
+ UNDNAME_NO_ALLOCATION_LANGUAGE |
+ UNDNAME_NO_MS_THISTYPE |
+ UNDNAME_NO_CV_THISTYPE |
+ UNDNAME_NO_THISTYPE |
+ UNDNAME_NO_ACCESS_SPECIFIERS |
+ UNDNAME_NO_THROW_SIGNATURES |
+ UNDNAME_NO_MEMBER_TYPE |
+ UNDNAME_NO_RETURN_UDT_MODEL |
+ UNDNAME_NO_ARGUMENTS |
+ UNDNAME_NO_SPECIAL_SYMS |
+ UNDNAME_NAME_ONLY
+ );
+ if (!i) {
+ return NULL;
+ }
+ } else {
+ strcpy( s, &StringTable[Symbol->n_offset] );
+ }
+ }
+
+ return s;
+}
diff --git a/private/windbg/symcvt/symcvt/cvcommon.c b/private/windbg/symcvt/symcvt/cvcommon.c
new file mode 100644
index 000000000..9591a58d9
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/cvcommon.c
@@ -0,0 +1,784 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cvcommon.c
+
+Abstract:
+
+ This file contians a set of common routines which are used in
+ doing symbol conversions from one type of symbols to CodeView
+ symbols.
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+ Jim Schaad (jimsch) 22 May 1993
+
+--*/
+
+#include <windows.h>
+#include <stdlib.h>
+#include "cv.h"
+#include "symcvt.h"
+#include "cvcommon.h"
+
+typedef struct tagSYMHASH {
+ DWORD dwHashVal; // hash value for the symbol
+ DWORD dwHashBucket; // hash bucket number
+ DATASYM16 * dataSym; // pointer to the symbol info
+} SYMHASH;
+
+typedef struct tagOFFSETSORT {
+ DWORD dwOffset; // offset for the symbol
+ DWORD dwSection; // section number of the symbol
+ DATASYM16 * dataSym; // pointer to the symbol info
+} OFFSETSORT;
+
+
+int _CRTAPI1 SymHashCompare( const void *arg1, const void *arg2 );
+int _CRTAPI1 OffsetSortCompare( const void *arg1, const void *arg2 );
+
+
+DWORD
+CreateSignature( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the CODEVIEW signature record. Currently this converter only
+ generates NB08 data (MS C/C++ 7.0).
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ number of records generates, this is always 1.
+
+--*/
+
+{
+ OMFSignature *omfSig;
+
+ omfSig = (OMFSignature *) p->pCvCurr;
+ strcpy( omfSig->Signature, "NB08" );
+ omfSig->filepos = 0;
+ p->pCvStart.size += sizeof(OMFSignature);
+ p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFSignature);
+ return 1;
+} /* CreateSignature() */
+
+
+DWORD
+CreateDirectories( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ This is the control function for the generation of the CV directories.
+ It calls individual functions for the generation of specific types of
+ debug directories.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ the number of directories created.
+
+--*/
+
+{
+ OMFDirHeader *omfDir = (OMFDirHeader *)p->pCvCurr;
+ OMFSignature *omfSig = (OMFSignature *)p->pCvStart.ptr;
+ OMFDirEntry *omfDirEntry = NULL;
+
+ omfSig->filepos = (DWORD)p->pCvCurr - (DWORD)p->pCvStart.ptr;
+
+ omfDir->cbDirHeader = sizeof(OMFDirHeader);
+ omfDir->cbDirEntry = sizeof(OMFDirEntry);
+ omfDir->cDir = 0;
+ omfDir->lfoNextDir = 0;
+ omfDir->flags = 0;
+
+ p->pCvStart.size += sizeof(OMFDirHeader);
+ p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirHeader);
+
+ omfDir->cDir += CreateModuleDirectoryEntries( p );
+ omfDir->cDir += CreatePublicDirectoryEntries( p );
+ omfDir->cDir += CreateSegMapDirectoryEntries( p );
+ omfDir->cDir += CreateSrcModulesDirectoryEntries( p );
+
+ strcpy(p->pCvCurr, "NB080000");
+ p->pCvStart.size += 8;
+ p->pCvCurr += 8;
+ *((DWORD *) (p->pCvCurr-4)) = p->pCvStart.size;
+
+ return omfDir->cDir;
+} /* CreateDirectories() */
+
+
+DWORD
+CreateModuleDirectoryEntries( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates directory entries for each module in the image.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ the number of directory entries created.
+
+--*/
+
+{
+ OMFDirEntry *omfDirEntry = NULL;
+ OMFModule *m = NULL;
+ OMFModule *mNext = NULL;
+ DWORD i = 0;
+ DWORD mSize = 0;
+ DWORD lfo = (DWORD)p->pCvModules.ptr - (DWORD)p->pCvStart.ptr;
+
+ m = (OMFModule *) p->pCvModules.ptr;
+ for (i=0; i<p->pCvModules.count; i++) {
+ mNext = NextMod(m);
+
+ omfDirEntry = (OMFDirEntry *) p->pCvCurr;
+
+ mSize = (DWORD)mNext - (DWORD)m;
+ omfDirEntry->SubSection = sstModule;
+ omfDirEntry->iMod = (USHORT) i + 1;
+ omfDirEntry->lfo = lfo;
+ omfDirEntry->cb = mSize;
+
+ lfo += mSize;
+
+ p->pCvStart.size += sizeof(OMFDirEntry);
+ p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
+
+ m = mNext;
+ }
+
+ return p->pCvModules.count;
+} /* CreateModuleDirectoryEntries() */
+
+
+DWORD
+CreatePublicDirectoryEntries( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the directory entry for the global publics.
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ the number of directory entries created, always 1.
+
+--*/
+
+{
+ OMFDirEntry *omfDirEntry = (OMFDirEntry *) p->pCvCurr;
+
+ omfDirEntry->SubSection = sstGlobalPub;
+ omfDirEntry->iMod = 0xffff;
+ omfDirEntry->lfo = (DWORD)p->pCvPublics.ptr - (DWORD)p->pCvStart.ptr;
+ omfDirEntry->cb = p->pCvPublics.size;
+
+ p->pCvStart.size += sizeof(OMFDirEntry);
+ p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
+
+ return 1;
+} /* CreatePublicDirectoryEntries() */
+
+
+DWORD
+CreateSegMapDirectoryEntries( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the directory entry for the segment map.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ the number of directory entries created, always 1.
+
+--*/
+
+{
+ OMFDirEntry *omfDirEntry = (OMFDirEntry *) p->pCvCurr;
+
+ omfDirEntry->SubSection = sstSegMap;
+ omfDirEntry->iMod = 0xffff;
+ omfDirEntry->lfo = (DWORD)p->pCvSegMap.ptr - (DWORD)p->pCvStart.ptr;
+ omfDirEntry->cb = p->pCvSegMap.size;
+
+ p->pCvStart.size += sizeof(OMFDirEntry);
+ p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
+
+ return 1;
+} /* CreateSegMapDirectoryEntries() */
+
+
+DWORD
+CreateSrcModulesDirectoryEntries( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates directory entries for each source module in the image.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ the number of directory entries created.
+
+--*/
+
+{
+ OMFDirEntry *omfDirEntry = NULL;
+ DWORD i;
+ DWORD lfo = (DWORD)p->pCvSrcModules.ptr - (DWORD)p->pCvStart.ptr;
+ DWORD j = lfo;
+ OMFSourceModule *m;
+
+
+ //
+ // if there were no linenumber conversions then bail out
+ //
+ if (!p->pCvSrcModules.count) {
+ return 0;
+ }
+
+ for (i=0; i<p->pCvSrcModules.count; i++) {
+
+ if (!p->pMi[i].SrcModule) {
+ continue;
+ }
+
+ omfDirEntry = (OMFDirEntry *) p->pCvCurr;
+
+ omfDirEntry->SubSection = sstSrcModule;
+ omfDirEntry->iMod = (USHORT) p->pMi[i].iMod;
+ omfDirEntry->lfo = lfo;
+ omfDirEntry->cb = p->pMi[i].cb;
+
+ m = (OMFSourceModule*) p->pMi[i].SrcModule;
+
+ lfo += omfDirEntry->cb;
+
+ p->pCvStart.size += sizeof(OMFDirEntry);
+ p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
+ }
+
+ LocalFree ( p->pMi );
+
+ return p->pCvSrcModules.count;
+} /* CreateSrcModulesDirectoryEntries() */
+
+
+DWORD
+DWordXorLrl( char *szSym )
+
+/*++
+
+Routine Description:
+
+ This function will take an ascii character string and generate
+ a hash for that string. The hash algorithm is the CV NB08 hash
+ algorithm.
+
+
+Arguments:
+
+ szSym - a character pointer, the first char is the string length
+
+
+Return Value:
+
+ The generated hash value.
+
+--*/
+
+{
+ char *pName = szSym+1;
+ int cb = *szSym;
+ char *pch;
+ char c;
+ DWORD hash = 0;
+ DWORD UNALIGNED *pul = (DWORD *) pName;
+ static rgMask[] = {0, 0xff, 0xffff, 0xffffff};
+
+ //
+ // We replace all "::" to "__"
+ //
+ c = *(pName+cb);
+ *(pName+cb) = '\0';
+ pch = strstr( pName, "::" );
+ if ( pch ) {
+ *pch++ = '_';
+ *pch = '_';
+ }
+ *(pName+cb) = c;
+
+ pch = pName + cb - 1;
+ while (isdigit(*pch)) {
+ pch--;
+ }
+
+ if (*pch == '@') {
+ cb = pch - pName;
+ }
+
+ for (; cb > 3; cb-=4, pul++) {
+ hash = _lrotl(hash, 4);
+ hash ^= (*pul & 0xdfdfdfdf);
+ }
+
+ if (cb > 0) {
+ hash = _lrotl(hash,4);
+ hash ^= ((*pul & rgMask[cb]) & 0xdfdfdfdf);
+ }
+
+ return hash;
+} /* DWordXorLrl() */
+
+
+
+OMFModule *
+NextMod(
+ OMFModule * pMod
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ return-value - Description of conditions needed to return value. - or -
+ None.
+
+--*/
+
+{
+ char * pb;
+
+ pb = (char *) &(pMod->SegInfo[pMod->cSeg]);
+ pb += *pb + 1;
+ pb = (char *) (((unsigned long) pb + 3) & ~3);
+
+ return (OMFModule *) pb;
+} /* NextMod() */
+
+
+
+int
+_CRTAPI1
+SymHashCompare(
+ const void * arg1,
+ const void * arg2
+ )
+/*++
+
+Routine Description:
+
+ Sort compare function for sorting SYMHASH records by hashed
+ bucket number.
+
+
+Arguments:
+
+ arg1 - record #1
+ arg2 - record #2
+
+
+Return Value:
+
+ -1 - record #1 is < record #2
+ 0 - records are equal
+ 1 - record #1 is > record #2
+
+--*/
+
+{
+ if (((SYMHASH*)arg1)->dwHashBucket < ((SYMHASH*)arg2)->dwHashBucket) {
+ return -1;
+ }
+ if (((SYMHASH*)arg1)->dwHashBucket > ((SYMHASH*)arg2)->dwHashBucket) {
+ return 1;
+ }
+ return 0;
+} /* SymHashCompare() */
+
+
+DWORD
+CreateSymbolHashTable(
+ PPOINTERS p
+ )
+/*++
+
+Routine Description:
+
+
+ Creates the CV symbol hash table. This hash table is used
+ primarily by debuggers to access symbols in a quick manner.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of buckets is the hash table.
+
+--*/
+
+{
+ DWORD i;
+ DWORD j;
+ int k;
+ DWORD numsyms;
+ DWORD numbuckets;
+ OMFSymHash *omfSymHash;
+ DATASYM16 *dataSymStart;
+ DATASYM16 *dataSym;
+ LPVOID pHashData;
+ USHORT *pCHash;
+ DWORD *pHashTable;
+ USHORT *pBucketCounts;
+ DWORD *pChainTable;
+ SYMHASH *symHashStart;
+ SYMHASH *symHash;
+ DWORD dwHashVal;
+ char * sz;
+
+ numsyms = p->pCvPublics.count;
+ numbuckets = (numsyms+9) / 10;
+ numbuckets = (1 + numbuckets) & ~1;
+
+ symHashStart =
+ symHash = (SYMHASH *) LocalAlloc( NONZEROLPTR, numsyms * sizeof(SYMHASH) );
+ if (symHashStart == NULL) {
+ return 0;
+ }
+
+ memset( symHashStart, 0, numsyms * sizeof(SYMHASH) );
+
+ pHashData = (LPVOID) p->pCvCurr;
+ pCHash = (USHORT *) pHashData;
+ pHashTable = (DWORD *) ((DWORD)pHashData + sizeof(DWORD));
+ pBucketCounts = (USHORT *) ((DWORD)pHashTable +
+ (sizeof(DWORD) * numbuckets));
+ pChainTable = (DWORD *) ((DWORD)pBucketCounts +
+ ((sizeof(USHORT) * numbuckets)));
+
+ omfSymHash = (OMFSymHash *) p->pCvPublics.ptr;
+ dataSymStart =
+ dataSym = (DATASYM16 *) ((DWORD)omfSymHash + sizeof(OMFSymHash));
+
+ *pCHash = (USHORT)numbuckets;
+
+ /*
+ * cruise thru the symbols and calculate the hash values
+ * and the hash bucket numbers; save the info away for later use
+ */
+ for (i=0; i<numsyms; i++, symHash++) {
+ switch( dataSym->rectyp ) {
+ case S_PUB16:
+ sz = dataSym->name;
+ break;
+
+ case S_PUB32:
+ sz = ((DATASYM32 *) dataSym)->name;
+ break;
+
+ default:
+ continue;
+ }
+
+ dwHashVal = DWordXorLrl( sz );
+ symHash->dwHashBucket = dwHashVal % numbuckets;
+ pBucketCounts[symHash->dwHashBucket] += 1;
+ symHash->dataSym = dataSym;
+ dataSym = ((DATASYM16 *) ((char *) dataSym + dataSym->reclen + 2));
+ }
+
+ qsort( (void*)symHashStart, numsyms, sizeof(SYMHASH), SymHashCompare );
+
+ j = (char *)pChainTable - (char *)pHashData;
+ for (i=0, k = 0; i<numbuckets;
+ k += pBucketCounts[i], i += 1, pHashTable++ ) {
+ *pHashTable = (DWORD) j + (k * 4);
+ }
+
+ dataSymStart = (DATASYM16 *) (PUCHAR)((DWORD)omfSymHash);
+ for (i=0,symHash=symHashStart; i<numsyms; i++,symHash++,pChainTable++) {
+ *pChainTable = (DWORD) (DWORD)symHash->dataSym - (DWORD)dataSymStart;
+ }
+
+ UpdatePtrs( p, &p->pCvSymHash, (LPVOID)pChainTable, numsyms );
+
+ omfSymHash->symhash = 6;
+ omfSymHash->cbHSym = p->pCvSymHash.size;
+
+ LocalFree( symHashStart );
+
+ return numbuckets;
+} /* CreateSymbolHashTable() */
+
+
+VOID
+UpdatePtrs( PPOINTERS p, PPTRINFO pi, LPVOID lpv, DWORD count )
+
+/*++
+
+Routine Description:
+
+ This function is called by ALL functions that put data into the
+ CV data area. After putting the data into the CV memory this function
+ must be called. It will adjust all of the necessary pointers so the
+ the next guy doesn't get hosed.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+ pi - the CV pointer that is to be updated
+ lpv - current pointer into the CV data
+ count - the number of items that were placed into the CV data
+
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ if (!count) {
+ return;
+ }
+
+ pi->ptr = p->pCvCurr;
+ pi->size = (DWORD) ((DWORD)lpv - (DWORD)p->pCvCurr);
+ pi->count = count;
+
+ p->pCvStart.size += pi->size;
+ p->pCvCurr = (PUCHAR) lpv;
+
+ return;
+} /* UpdatePtrs() */
+
+
+int
+_CRTAPI1
+OffsetSortCompare( const void *arg1, const void *arg2 )
+
+/*++
+
+Routine Description:
+
+ Sort compare function for sorting OFFETSORT records by section number.
+
+
+Arguments:
+
+ arg1 - record #1
+ arg2 - record #2
+
+
+Return Value:
+
+ -1 - record #1 is < record #2
+ 0 - records are equal
+ 1 - record #1 is > record #2
+
+--*/
+
+{
+ if (((OFFSETSORT*)arg1)->dwSection < ((OFFSETSORT*)arg2)->dwSection) {
+ return -1;
+ }
+ if (((OFFSETSORT*)arg1)->dwSection > ((OFFSETSORT*)arg2)->dwSection) {
+ return 1;
+ }
+ if (((OFFSETSORT*)arg1)->dwOffset < ((OFFSETSORT*)arg2)->dwOffset) {
+ return -1;
+ }
+ if (((OFFSETSORT*)arg1)->dwOffset > ((OFFSETSORT*)arg2)->dwOffset) {
+ return 1;
+ }
+ return 0;
+} /* OffsetSortCompare() */
+
+
+DWORD
+CreateAddressSortTable( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+
+ Creates the CV address sort table. This hash table is used
+ primarily by debuggers to access symbols in a quick manner when
+ all you have is an address.
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of sections in the table.
+
+--*/
+
+{
+ DWORD i;
+ DWORD j;
+ int k;
+ DWORD numsyms = p->pCvPublics.count;
+ DWORD numsections;
+ OMFSymHash *omfSymHash;
+ DATASYM16 *dataSymStart;
+ DATASYM16 *dataSym;
+ LPVOID pAddressData;
+ USHORT *pCSeg;
+ DWORD *pSegTable;
+ USHORT *pOffsetCounts;
+ DWORD *pOffsetTable;
+ OFFSETSORT *pOffsetSortStart;
+ OFFSETSORT *pOffsetSort;
+
+ extern int CSymSegs;
+
+ if (p->iptrs.fileHdr) {
+ numsections = p->iptrs.fileHdr->NumberOfSections;
+ } else if (p->iptrs.sepHdr) {
+ numsections = p->iptrs.sepHdr->NumberOfSections;
+ } else {
+ numsections = CSymSegs;
+ }
+
+ pOffsetSortStart =
+ pOffsetSort = (OFFSETSORT *) LocalAlloc( NONZEROLPTR, numsyms * sizeof(OFFSETSORT) );
+
+ if (pOffsetSort == NULL) {
+ return 0;
+ }
+
+ memset( pOffsetSortStart, 0, numsyms * sizeof(OFFSETSORT) );
+
+ pAddressData = (LPVOID) p->pCvCurr;
+ pCSeg = (USHORT *) pAddressData;
+ pSegTable = (DWORD *) ((DWORD)pAddressData + sizeof(DWORD));
+ pOffsetCounts = (USHORT *) ((DWORD)pSegTable +
+ (sizeof(DWORD) * numsections));
+ pOffsetTable = (DWORD *) ((DWORD)pOffsetCounts +
+ ((sizeof(USHORT) * numsections)));
+ if (numsections & 1) {
+ pOffsetTable = (DWORD *) ((DWORD)pOffsetTable + 2);
+ }
+
+ omfSymHash = (OMFSymHash *) p->pCvPublics.ptr;
+ dataSymStart =
+ dataSym = (DATASYM16 *) ((DWORD)omfSymHash + sizeof(OMFSymHash));
+
+ *pCSeg = (USHORT)numsections;
+
+ for (i=0;
+ i<numsyms;
+ i++, pOffsetSort++)
+ {
+ switch(dataSym->rectyp) {
+ case S_PUB16:
+ pOffsetSort->dwOffset = dataSym->off;
+ pOffsetSort->dwSection = dataSym->seg;
+ break;
+
+ case S_PUB32:
+ pOffsetSort->dwOffset = ((DATASYM32 *) dataSym)->off;
+ pOffsetSort->dwSection = ((DATASYM32 *) dataSym)->seg;
+ }
+
+ pOffsetSort->dataSym = dataSym;
+ pOffsetCounts[pOffsetSort->dwSection - 1] += 1;
+ dataSym = ((DATASYM16 *) ((char *) dataSym + dataSym->reclen + 2)); }
+
+//#if 0
+ qsort((void*)pOffsetSortStart, numsyms, sizeof(OFFSETSORT), OffsetSortCompare );
+//#endif
+
+ j = (DWORD) (DWORD)pOffsetTable - (DWORD)pAddressData;
+ for (i=0, k=0; i<numsections;
+ k += pOffsetCounts[i], i += 1, pSegTable++) {
+ *pSegTable = (DWORD) j + (k * 4);
+ }
+
+ dataSymStart = (DATASYM16 *) (PUCHAR)((DWORD)omfSymHash);
+ for (i=0, pOffsetSort=pOffsetSortStart;
+ i < numsyms;
+ i++, pOffsetSort++, pOffsetTable++) {
+ *pOffsetTable = (DWORD)pOffsetSort->dataSym - (DWORD)dataSymStart;
+ }
+
+ UpdatePtrs( p, &p->pCvAddrSort, (LPVOID)pOffsetTable, numsyms );
+
+ omfSymHash->addrhash = 5;
+ omfSymHash->cbHAddr = p->pCvAddrSort.size;
+
+ LocalFree( pOffsetSortStart );
+
+ return numsections;
+} /* CreateAddressSort() */
diff --git a/private/windbg/symcvt/symcvt/file.c b/private/windbg/symcvt/symcvt/file.c
new file mode 100644
index 000000000..eef14e85f
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/file.c
@@ -0,0 +1,467 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ file.c
+
+Abstract:
+
+ This module handles all file i/o for SYMCVT. This includes the
+ mapping of all files and establishing all file pointers for the
+ mapped file(s).
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "symcvt.h"
+
+
+static BOOL CalculateOutputFilePointers( PIMAGEPOINTERS pi, PIMAGEPOINTERS po );
+static BOOL CalculateInputFilePointers( PIMAGEPOINTERS p );
+
+
+
+BOOL
+MapInputFile (
+ PPOINTERS p,
+ HANDLE hFile,
+ char * fname
+ )
+/*++
+
+Routine Description:
+
+ Maps the input file specified by the fname argument and saves the
+ file handle & file pointer in the POINTERS structure.
+
+
+Arguments:
+
+ p - Supplies pointer to a POINTERS structure (see cofftocv.h)
+ hFile - OPTIONAL Supplies handle for file if already open
+ fname - Supplies ascii string for the file name
+
+Return Value:
+
+ TRUE - file mapped ok
+ FALSE - file could not be mapped
+
+--*/
+
+{
+ BOOL rVal = TRUE;
+
+ memset( p, 0, sizeof(POINTERS) );
+
+ strcpy( p->iptrs.szName, fname );
+
+ if (hFile != NULL) {
+
+ p->iptrs.hFile = hFile;
+ p->iptrs.CloseFile = FALSE;
+
+ } else {
+
+ p->iptrs.hFile = CreateFile( p->iptrs.szName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+ p->iptrs.CloseFile = TRUE;
+ }
+
+ if (p->iptrs.hFile == INVALID_HANDLE_VALUE) {
+
+ rVal = FALSE;
+
+ } else {
+
+ p->iptrs.fsize = GetFileSize( p->iptrs.hFile, NULL );
+ p->iptrs.hMap = CreateFileMapping( p->iptrs.hFile,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ 0,
+ NULL
+ );
+
+ if (p->iptrs.hMap == INVALID_HANDLE_VALUE) {
+
+ p->iptrs.hMap = NULL;
+ rVal = FALSE;
+
+ } else {
+
+ p->iptrs.fptr = MapViewOfFile( p->iptrs.hMap,
+ FILE_MAP_READ,
+ 0, 0, 0 );
+ if (p->iptrs.fptr == NULL) {
+ CloseHandle( p->iptrs.hMap );
+ p->iptrs.hMap = NULL;
+ rVal = FALSE;
+ }
+ }
+ }
+
+ if (!hFile && p->iptrs.hFile != INVALID_HANDLE_VALUE) {
+ CloseHandle(p->iptrs.hFile);
+ p->iptrs.hFile = NULL;
+ }
+
+ return rVal;
+} /* MapInputFile() */
+
+
+
+BOOL
+UnMapInputFile (
+ PPOINTERS p
+ )
+/*++
+
+Routine Description:
+
+ Unmaps the input file specified by the fname argument and then
+ closes the file.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+Return Value:
+
+ TRUE - file mapped ok
+ FALSE - file could not be mapped
+
+--*/
+
+{
+ if ( p->iptrs.fptr ) {
+ UnmapViewOfFile( p->iptrs.fptr );
+ p->iptrs.fptr = NULL;
+ }
+ if ( p->iptrs.hMap ) {
+ CloseHandle( p->iptrs.hMap );
+ p->iptrs.hMap = NULL;
+ }
+ if (p->iptrs.hFile != NULL) {
+ if (p->iptrs.CloseFile) {
+ CloseHandle( p->iptrs.hFile );
+ }
+ p->iptrs.hFile = NULL;
+ }
+ return TRUE;
+} /* UnMapInputFile() */
+
+
+BOOL
+FillInSeparateImagePointers(
+ PIMAGEPOINTERS p
+ )
+/*++
+
+Routine Description:
+
+ This routine will go through the exe file and fill in the
+ pointers needed relative to the separate debug information files
+
+Arguments:
+
+ p - Supplies the structure to fill in
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise.
+
+--*/
+
+{
+ int li;
+ int numDebugDirs;
+ PIMAGE_DEBUG_DIRECTORY pDebugDir;
+ PIMAGE_COFF_SYMBOLS_HEADER pCoffHdr;
+
+ p->sectionHdrs = (PIMAGE_SECTION_HEADER)
+ (p->fptr + sizeof(IMAGE_SEPARATE_DEBUG_HEADER));
+
+ numDebugDirs = p->sepHdr->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
+
+ if (numDebugDirs == 0) {
+ return FALSE;
+ }
+
+ /*
+ * For each debug directory, determine the debug directory type
+ * and cache any information about them.
+ */
+
+ pDebugDir = (PIMAGE_DEBUG_DIRECTORY)
+ (p->fptr + sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
+ p->sepHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
+ p->sepHdr->ExportedNamesSize);
+
+ for (li=0; li < numDebugDirs; li++, pDebugDir++) {
+ if (((int) pDebugDir->Type) > p->cDebugDir) {
+ p->cDebugDir += 10;
+ p->rgDebugDir = LocalReAlloc((char *) p->rgDebugDir,
+ p->cDebugDir * sizeof(p->rgDebugDir[0]),
+ LMEM_ZEROINIT);
+ }
+
+ p->rgDebugDir[pDebugDir->Type] = pDebugDir;
+ }
+
+ if (p->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) {
+ pCoffHdr = (PIMAGE_COFF_SYMBOLS_HEADER) (p->fptr +
+ p->rgDebugDir[IMAGE_DEBUG_TYPE_COFF]->PointerToRawData);
+ p->AllSymbols = (PIMAGE_SYMBOL)
+ ((char *) pCoffHdr + pCoffHdr->LvaToFirstSymbol);
+ p->stringTable = pCoffHdr->NumberOfSymbols * IMAGE_SIZEOF_SYMBOL +
+ (char *) p->AllSymbols;
+ p->numberOfSymbols = pCoffHdr->NumberOfSymbols;
+ }
+ p->numberOfSections = p->sepHdr->NumberOfSections;
+
+ return TRUE;
+} /* FillInSeparateImagePointers() */
+
+
+
+BOOL
+CalculateNtImagePointers(
+ PIMAGEPOINTERS p
+ )
+/*++
+
+Routine Description:
+
+ This function reads an NT image and its associated COFF headers
+ and file pointers and build a set of pointers into the mapped image.
+ The pointers are all relative to the image's mapped file pointer
+ and allow direct access to the necessary data.
+
+Arguments:
+
+ p - pointer to a IMAGEPOINTERS structure (see cofftocv.h)
+
+Return Value:
+
+ TRUE - pointers were created
+ FALSE - pointers could not be created
+
+--*/
+{
+ PIMAGE_DEBUG_DIRECTORY debugDir;
+ PIMAGE_SECTION_HEADER sh;
+ DWORD i, li, rva, numDebugDirs;
+ PIMAGE_FILE_HEADER pFileHdr;
+ PIMAGE_OPTIONAL_HEADER pOptHdr;
+ DWORD offDebugInfo;
+
+ __try {
+ /*
+ * Based on wheither or not we find the dos (MZ) header
+ * at the beginning of the file, attempt to get a pointer
+ * to where the PE header is suppose to be.
+ */
+
+ p->dosHdr = (PIMAGE_DOS_HEADER) p->fptr;
+ if (p->dosHdr->e_magic == IMAGE_DOS_SIGNATURE) {
+ p->ntHdr = (PIMAGE_NT_HEADERS)
+ ((DWORD)p->dosHdr->e_lfanew + p->fptr);
+ p->fRomImage = FALSE;
+ } else if (p->dosHdr->e_magic == IMAGE_SEPARATE_DEBUG_SIGNATURE) {
+ p->sepHdr = (PIMAGE_SEPARATE_DEBUG_HEADER) p->fptr;
+ p->dosHdr = NULL;
+ p->fRomImage = FALSE;
+ p->cDebugDir = 10;
+ p->rgDebugDir = LocalAlloc(LPTR, sizeof(IMAGE_DEBUG_DIRECTORY) * 10 );
+ return FillInSeparateImagePointers(p);
+ } else {
+ p->romHdr = (PIMAGE_ROM_HEADERS) p->fptr;
+ if (p->romHdr->FileHeader.SizeOfOptionalHeader ==
+ IMAGE_SIZEOF_ROM_OPTIONAL_HEADER &&
+ p->romHdr->OptionalHeader.Magic ==
+ IMAGE_ROM_OPTIONAL_HDR_MAGIC) {
+ //
+ // its a rom image
+ //
+ p->fRomImage = TRUE;
+ p->ntHdr = NULL;
+ p->dosHdr = NULL;
+ } else {
+ p->fRomImage = FALSE;
+ p->ntHdr = (PIMAGE_NT_HEADERS) p->fptr;
+ p->dosHdr = NULL;
+ p->romHdr = NULL;
+ }
+ }
+
+ /*
+ * What comes next must be a PE header. If not then pop out
+ */
+
+ if ( p->ntHdr ) {
+ if ( p->dosHdr && (DWORD)p->dosHdr->e_lfanew > (DWORD)p->fsize ) {
+ return FALSE;
+ }
+
+ if ( p->ntHdr->Signature != IMAGE_NT_SIGNATURE ) {
+ return FALSE;
+ }
+
+ /*
+ * We did find a PE header so start setting pointers to various
+ * structures in the exe file.
+ */
+
+ pFileHdr = p->fileHdr = &p->ntHdr->FileHeader;
+ pOptHdr = p->optHdr = &p->ntHdr->OptionalHeader;
+ } else if (p->romHdr) {
+ pFileHdr = p->fileHdr = &p->romHdr->FileHeader;
+ pOptHdr = (PIMAGE_OPTIONAL_HEADER) &p->romHdr->OptionalHeader;
+ p->optHdr = (PIMAGE_OPTIONAL_HEADER) &p->romHdr->OptionalHeader;
+ } else {
+ return FALSE;
+ }
+
+ if (!(pFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {
+ return FALSE;
+ }
+
+ if (pFileHdr->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
+ return(FALSE);
+ }
+
+ /*
+ * If they exists then get a pointer to the symbol table and
+ * the string table
+ */
+
+ if (pFileHdr->PointerToSymbolTable) {
+ p->AllSymbols = (PIMAGE_SYMBOL)
+ (pFileHdr->PointerToSymbolTable + p->fptr);
+ p->stringTable = (LPSTR)((ULONG)p->AllSymbols +
+ (IMAGE_SIZEOF_SYMBOL * pFileHdr->NumberOfSymbols));
+ p->numberOfSymbols = pFileHdr->NumberOfSymbols;
+ }
+
+ p->numberOfSections = pFileHdr->NumberOfSections;
+ p->cDebugDir = 10;
+ p->rgDebugDir = LocalAlloc(LPTR, sizeof(IMAGE_DEBUG_DIRECTORY) * 10 );
+
+ if (p->romHdr) {
+
+ sh = p->sectionHdrs = (PIMAGE_SECTION_HEADER) (p->romHdr+1);
+
+ debugDir = 0;
+
+ for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) {
+ if (!strcmp(sh->Name, ".rdata")) {
+ debugDir = (PIMAGE_DEBUG_DIRECTORY)(sh->PointerToRawData + p->fptr);
+ }
+
+ if (strncmp(sh->Name,".debug",8)==0) {
+ p->debugSection = sh;
+ }
+ }
+
+ if (debugDir) {
+ do {
+ if ((int)debugDir->Type > p->cDebugDir) {
+ p->cDebugDir += 10;
+ p->rgDebugDir = LocalReAlloc((char *) p->rgDebugDir, p->cDebugDir * sizeof(p->rgDebugDir[0]), LMEM_ZEROINIT);
+ }
+ p->rgDebugDir[debugDir->Type] = debugDir;
+ debugDir++;
+ } while (debugDir->Type != 0);
+ }
+ } else {
+
+ /*
+ * Locate the debug directory
+ */
+
+ rva =
+ pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+
+ numDebugDirs =
+ pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
+ sizeof(IMAGE_DEBUG_DIRECTORY);
+
+ if (numDebugDirs == 0) {
+ return FALSE;
+ }
+
+ sh = p->sectionHdrs = IMAGE_FIRST_SECTION( p->ntHdr );
+
+ /*
+ * Find the section the debug directory is in.
+ */
+
+ for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) {
+ if (rva >= sh->VirtualAddress &&
+ rva < sh->VirtualAddress+sh->SizeOfRawData) {
+ break;
+ }
+ }
+
+ /*
+ * For each debug directory, determine the debug directory
+ * type and cache any information about them.
+ */
+
+ debugDir = (PIMAGE_DEBUG_DIRECTORY) ( rva - sh->VirtualAddress +
+ sh->PointerToRawData +
+ p->fptr );
+
+ for (li=0; li<numDebugDirs; li++, debugDir++) {
+ if (((int) debugDir->Type) > p->cDebugDir) {
+ p->cDebugDir += 10;
+ p->rgDebugDir = LocalReAlloc((char *) p->rgDebugDir,
+ p->cDebugDir * sizeof(p->rgDebugDir[0]),
+ LMEM_ZEROINIT);
+ }
+ p->rgDebugDir[debugDir->Type] = debugDir;
+ offDebugInfo = debugDir->AddressOfRawData;
+ }
+
+ /*
+ * Check to see if the debug information is mapped and if
+ * there is a section called .debug
+ */
+
+ sh = p->sectionHdrs = IMAGE_FIRST_SECTION( p->ntHdr );
+
+ for (i=0; i<pFileHdr->NumberOfSections; i++, sh++) {
+ if ((offDebugInfo >= sh->VirtualAddress) &&
+ (offDebugInfo < sh->VirtualAddress+sh->SizeOfRawData)) {
+ p->debugSection = sh;
+ break;
+ }
+ }
+ }
+
+ return TRUE;
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ return FALSE;
+ }
+} /* CalcuateNtImagePointers() */
diff --git a/private/windbg/symcvt/symcvt/makefile b/private/windbg/symcvt/symcvt/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/symcvt/symcvt/sources b/private/windbg/symcvt/symcvt/sources
new file mode 100644
index 000000000..632a2ee07
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=symcvt
+
+TARGETNAME=symcvt
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+SOURCES= \
+ cofftocv.c \
+ cvcommon.c \
+ file.c \
+ symcvt.c \
+ symtocv.c \
+ symcvt.rc
+
+UMTYPE=windows
+
+DLLBASE=0x58400000
+
+!include ..\..\common.src
+
+INCLUDES=.\;..\include;..\..\osdebug\include
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
diff --git a/private/windbg/symcvt/symcvt/symcvt.c b/private/windbg/symcvt/symcvt/symcvt.c
new file mode 100644
index 000000000..12f702393
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/symcvt.c
@@ -0,0 +1,128 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ symcvt.c
+
+Abstract:
+
+ This module is the shell for the SYMCVT DLL. The DLL's purpose is
+ to convert the symbols for the specified image. The resulting
+ debug data must conform to the CODEVIEW spec.
+
+ Currently this DLL converts COFF symbols and C7/C8 MAPTOSYM SYM files.
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "symcvt.h"
+#include "cofftocv.h"
+#include "symtocv.h"
+
+
+
+PUCHAR
+ConvertSymbolsForImage(
+ HANDLE hFile,
+ char * fname
+ )
+/*++
+
+Routine Description:
+
+ Calls the appropriate conversion routine based on the file contents.
+
+
+Arguments:
+
+ hFile - file handle for the image (may be NULL)
+ fname - file name for the image (may not have correct path)
+
+
+Return Value:
+
+ NULL - could not convert the symbols
+ Valid Pointer - a pointer to malloc'ed memory that contains the
+ CODEVIEW symbols
+
+--*/
+{
+ POINTERS p;
+ char szDrive [_MAX_DRIVE];
+ char szDir [_MAX_DIR];
+ char szFname [_MAX_FNAME];
+ char szExt [_MAX_EXT];
+ char szSymName [MAX_PATH];
+ PUCHAR rVal;
+
+
+ if (!MapInputFile( &p, hFile, fname)) {
+
+ rVal = NULL;
+
+ } else if (CalculateNtImagePointers( &p.iptrs )) {
+
+ //
+ // we were able to compute the nt image pointers so this must be
+ // a nt PE image. now we must decide if there are coff symbols
+ // if there are then we do the cofftocv conversion.
+ //
+ // btw, this is where someone would convert some other type of
+ // symbols that are in a nt PE image. (party on garth..)
+ //
+
+// if (!COFF_DIR(&p.iptrs)) {
+ if (!p.iptrs.numberOfSymbols) {
+ rVal = NULL;
+ } else {
+ ConvertCoffToCv( &p );
+ rVal = p.pCvStart.ptr;
+ }
+ UnMapInputFile( &p );
+ if (p.iptrs.rgDebugDir) {
+ LocalFree(p.iptrs.rgDebugDir);
+ }
+
+ } else {
+
+ UnMapInputFile ( &p );
+
+ _splitpath( fname, szDrive, szDir, szFname, szExt );
+ _makepath( szSymName, szDrive, szDir, szFname, "sym" );
+
+ if (!MapInputFile( &p, NULL, szSymName)) {
+
+ rVal = NULL;
+
+ } else {
+
+ //
+ // must be a wow/dos app and there is a .sym file so lets to
+ // the symtocv conversion
+ //
+
+ ConvertSymToCv( &p );
+ UnMapInputFile( &p );
+
+ rVal = p.pCvStart.ptr;
+ }
+
+ }
+
+ return rVal;
+}
diff --git a/private/windbg/symcvt/symcvt/symcvt.def b/private/windbg/symcvt/symcvt/symcvt.def
new file mode 100644
index 000000000..a5c7296af
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/symcvt.def
@@ -0,0 +1,9 @@
+LIBRARY symcvt
+
+EXPORTS
+ ConvertSymbolsForImage
+ ConvertCoffToCv
+ ConvertSymToCv
+ MapInputFile
+ UnMapInputFile
+ CalculateNtImagePointers
diff --git a/private/windbg/symcvt/symcvt/symcvt.rc b/private/windbg/symcvt/symcvt/symcvt.rc
new file mode 100644
index 000000000..6fb2cd4c5
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/symcvt.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "CodeView Symbol Converter DLL"
+#define VER_INTERNALNAME_STR "symcvt.dll\0"
+#define VER_ORIGINALFILENAME_STR "symcvt.dll\0"
+
+#include "common.ver"
+ \ No newline at end of file
diff --git a/private/windbg/symcvt/symcvt/symtocv.c b/private/windbg/symcvt/symcvt/symtocv.c
new file mode 100644
index 000000000..8b1ce14f9
--- /dev/null
+++ b/private/windbg/symcvt/symcvt/symtocv.c
@@ -0,0 +1,482 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ symtocv.c
+
+Abstract:
+
+ This module handles the conversion activities requires for converting
+ C7/C8 SYM files to CODEVIEW debug data.
+
+Author:
+
+ Wesley A. Witt (wesw) 13-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cv.h"
+#include "symcvt.h"
+#include "cvcommon.h"
+
+typedef struct tagSYMNAME {
+ BYTE length;
+ char name[1];
+} SYMNAME, *PSYMNAME;
+
+typedef struct tagSYMSYMBOL {
+ WORD offset;
+ SYMNAME symName;
+} SYMSYMBOL, *PSYMSYMBOL;
+
+typedef struct tagSYMFILEHEADER {
+ DWORD fileSize;
+ WORD reserved1;
+ WORD numSyms;
+ DWORD reserved2;
+ WORD nextOffset;
+ BYTE reserved3;
+ SYMNAME symName;
+} SYMFILEHEADER, *PSYMFILEHEADER;
+
+typedef struct tagSYMHEADER {
+ WORD nextOffset;
+ WORD numSyms;
+ WORD reserved1;
+ WORD segment;
+ BYTE reserved2[12];
+ SYMNAME symName;
+} SYMHEADER, *PSYMHEADER;
+
+#define SIZEOFSYMFILEHEADER 16
+#define SIZEOFSYMHEADER 21
+#define SIZEOFSYMBOL 3
+
+#define SYM_SEGMENT_NAME 0
+#define SYM_SYMBOL_NAME 1
+#define SYM_SEGMENT_ABS 2
+#define SYM_SYMBOL_ABS 3
+
+typedef struct tagENUMINFO {
+ DATASYM16 *dataSym;
+ DATASYM16 *dataSym2;
+ DWORD numsyms;
+ SGI *sgi;
+} ENUMINFO, *PENUMINFO;
+
+typedef BOOL (CALLBACK* SYMBOLENUMPROC)(PSYMNAME pSymName, int symType,
+ SEGMENT segment, UOFF16 offset,
+ PENUMINFO pEnumInfo);
+
+
+static VOID GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable,
+ char * s );
+DWORD CreateModulesFromSyms( PPOINTERS p );
+DWORD CreatePublicsFromSyms( PPOINTERS p );
+DWORD CreateSegMapFromSyms( PPOINTERS p );
+static BOOL EnumSymbols( PPOINTERS p, SYMBOLENUMPROC lpEnumProc,
+ PENUMINFO pEnumInfo );
+
+int CSymSegs;
+
+BOOL CALLBACK
+SymbolCount(PSYMNAME pSymName, int symType, SEGMENT segment,
+ UOFF16 offset, PENUMINFO pEnumInfo )
+{
+ if ((symType == SYM_SEGMENT_NAME) && (segment > 0)) {
+ CSymSegs += 1;
+ }
+ pEnumInfo->numsyms++;
+ return TRUE;
+}
+
+BOOL
+ConvertSymToCv( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ This is the control function for the conversion of COFF to CODEVIEW
+ debug data. It calls individual functions for the conversion of
+ specific types of debug data.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ TRUE - conversion succeded
+ FALSE - conversion failed
+
+--*/
+
+{
+ ENUMINFO enumInfo;
+ DWORD dwSize;
+
+ CSymSegs = 0;
+ enumInfo.numsyms = 0;
+ EnumSymbols( p, SymbolCount, &enumInfo );
+ dwSize = (enumInfo.numsyms * (sizeof(DATASYM16) + 10)) + 256000;
+ p->pCvCurr = p->pCvStart.ptr = LocalAlloc( NONZEROLPTR, dwSize );
+ if (p->pCvStart.ptr == NULL) {
+ return FALSE;
+ }
+ memset( p->pCvStart.ptr, 0, dwSize );
+
+ __try {
+
+ CreateSignature( p );
+ CreatePublicsFromSyms( p );
+ CreateSymbolHashTable( p );
+ CreateAddressSortTable( p );
+ CreateSegMapFromSyms( p );
+ CreateModulesFromSyms( p );
+ CreateDirectories( p );
+ p->pCvStart.ptr = LocalReAlloc( p->pCvStart.ptr, p->pCvStart.size, 0 );
+ return TRUE;
+
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+
+ LocalFree( p->pCvStart.ptr );
+ p->pCvStart.ptr = NULL;
+ return FALSE;
+
+ }
+}
+
+
+DWORD
+CreateModulesFromSyms( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the individual CV module records. There is one CV module
+ record for each .FILE record in the COFF debug data. This is true
+ even if the COFF size is zero.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of modules that were created.
+
+--*/
+
+{
+ char szDrive [_MAX_DRIVE];
+ char szDir [_MAX_DIR];
+ char szFname [_MAX_FNAME];
+ char szExt [_MAX_EXT];
+ OMFModule *m;
+ int i;
+ char * pb;
+
+ _splitpath( p->iptrs.szName, szDrive, szDir, szFname, szExt );
+
+ m = (OMFModule *) p->pCvCurr;
+
+ m->ovlNumber = 0;
+ m->iLib = 0;
+ m->cSeg = CSymSegs;
+ m->Style[0] = 'C';
+ m->Style[1] = 'V';
+ for (i=0; i<CSymSegs; i++) {
+ m->SegInfo[i].Seg = i+1;
+ m->SegInfo[i].pad = 0;
+ m->SegInfo[i].Off = 0;
+ m->SegInfo[i].cbSeg = 0xffff;
+ }
+ pb = (char *) &m->SegInfo[CSymSegs];
+ sprintf( &pb[1], "%s.c", szFname );
+ pb[0] = strlen( &pb[1] );
+
+ pb = (char *) NextMod(m);
+
+ UpdatePtrs( p, &p->pCvModules, (LPVOID)pb, 1 );
+
+ return 1;
+}
+
+BOOL CALLBACK
+ConvertASymtoPublic(PSYMNAME pSymName, int symType, SEGMENT segment,
+ UOFF16 offset, PENUMINFO pEnumInfo )
+{
+ if (symType != SYM_SYMBOL_NAME) {
+ return TRUE;
+ }
+
+ pEnumInfo->dataSym->rectyp = S_PUB16;
+ pEnumInfo->dataSym->seg = segment;
+ pEnumInfo->dataSym->off = offset;
+ pEnumInfo->dataSym->typind = 0;
+ pEnumInfo->dataSym->name[0] = pSymName->length;
+ strncpy( &pEnumInfo->dataSym->name[1], pSymName->name, pSymName->length );
+ pEnumInfo->dataSym2 = NextSym16( pEnumInfo->dataSym );
+ pEnumInfo->dataSym->reclen = (USHORT) ((DWORD)pEnumInfo->dataSym2 -
+ (DWORD)pEnumInfo->dataSym) - 2;
+ pEnumInfo->dataSym = pEnumInfo->dataSym2;
+ pEnumInfo->numsyms++;
+
+ return TRUE;
+}
+
+DWORD
+CreatePublicsFromSyms( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the individual CV public symbol records. There is one CV
+ public record created for each COFF symbol that is marked as EXTERNAL
+ and has a section number greater than zero. The resulting CV publics
+ are sorted by section and offset.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of publics created.
+
+--*/
+
+{
+ OMFSymHash *omfSymHash;
+ ENUMINFO enumInfo;
+
+
+ enumInfo.dataSym = (DATASYM16 *)
+ (PUCHAR)((DWORD)p->pCvCurr + sizeof(OMFSymHash));
+ enumInfo.numsyms = 0;
+
+ EnumSymbols( p, ConvertASymtoPublic, &enumInfo );
+
+ omfSymHash = (OMFSymHash *) p->pCvCurr;
+ UpdatePtrs(p, &p->pCvPublics, (LPVOID)enumInfo.dataSym,
+ enumInfo.numsyms );
+
+ omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
+ omfSymHash->symhash = 0;
+ omfSymHash->addrhash = 0;
+ omfSymHash->cbHSym = 0;
+ omfSymHash->cbHAddr = 0;
+
+ return enumInfo.numsyms;
+}
+
+
+BOOL CALLBACK
+ConvertASegment( PSYMNAME pSymName, int symType, SEGMENT segment,
+ UOFF16 offset, PENUMINFO pEnumInfo )
+{
+ if (symType != SYM_SEGMENT_NAME) {
+ return TRUE;
+ }
+
+ if (segment == 0) {
+ return TRUE;
+ }
+
+ pEnumInfo->numsyms++;
+
+ pEnumInfo->sgi->sgf.fRead = TRUE;
+ pEnumInfo->sgi->sgf.fWrite = TRUE;
+ pEnumInfo->sgi->sgf.fExecute = TRUE;
+ pEnumInfo->sgi->sgf.f32Bit = 0;
+ pEnumInfo->sgi->sgf.fSel = 0;
+ pEnumInfo->sgi->sgf.fAbs = 0;
+ pEnumInfo->sgi->sgf.fGroup = 1;
+ pEnumInfo->sgi->iovl = 0;
+ pEnumInfo->sgi->igr = 0;
+ pEnumInfo->sgi->isgPhy = (USHORT) pEnumInfo->numsyms;
+ pEnumInfo->sgi->isegName = 0;
+ pEnumInfo->sgi->iclassName = 0;
+ pEnumInfo->sgi->doffseg = offset;
+ pEnumInfo->sgi->cbSeg = 0xFFFF;
+ pEnumInfo->sgi++;
+
+ return TRUE;
+}
+
+
+DWORD
+CreateSegMapFromSyms( PPOINTERS p )
+
+/*++
+
+Routine Description:
+
+ Creates the CV segment map. The segment map is used by debuggers
+ to aid in address lookups. One segment is created for each COFF
+ section in the image.
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ The number of segments in the map.
+
+--*/
+
+{
+ SGM *sgm;
+ ENUMINFO enumInfo;
+
+
+ sgm = (SGM *) p->pCvCurr;
+ enumInfo.sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
+ enumInfo.numsyms = 0;
+
+ EnumSymbols( p, ConvertASegment, &enumInfo );
+
+ sgm->cSeg = (USHORT)enumInfo.numsyms;
+ sgm->cSegLog = (USHORT)enumInfo.numsyms;
+
+ UpdatePtrs( p, &p->pCvSegMap, (LPVOID)enumInfo.sgi, enumInfo.numsyms );
+
+ return enumInfo.numsyms;
+}
+
+BOOL
+EnumSymbols( PPOINTERS p, SYMBOLENUMPROC lpEnumProc, PENUMINFO pEnumInfo )
+
+/*++
+
+Routine Description:
+
+ This function enumerates all symbols ine the mapped SYM file
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure
+ lpEnumProc - function to be called once for each function
+ pEnumInfo - data to be passed between the caller and the enum func
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+{
+ PSYMFILEHEADER pSymFileHead;
+ PSYMHEADER pSymHead;
+ PSYMHEADER pSymHead2;
+ PSYMSYMBOL pSymSymbol;
+ DWORD i;
+ DWORD startPosition;
+ DWORD position;
+ BOOL fV86Mode;
+ WORD Segment;
+ UOFF16 Offset;
+
+
+ pSymFileHead = (PSYMFILEHEADER) p->iptrs.fptr;
+ pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymFileHead + SIZEOFSYMFILEHEADER +
+ pSymFileHead->symName.length + 1);
+
+ if (!lpEnumProc(&pSymFileHead->symName, SYM_SEGMENT_ABS,
+ 0, 0, pEnumInfo )) {
+ return FALSE;
+ }
+
+ for (i=0; i<pSymFileHead->numSyms; i++) {
+ if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_ABS,
+ 0, pSymSymbol->offset, pEnumInfo )) {
+ return FALSE;
+ }
+ pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymSymbol + SIZEOFSYMBOL +
+ pSymSymbol->symName.length);
+ }
+
+ position = startPosition = ((LONG)pSymFileHead->nextOffset) << 4;
+
+ //
+ // Determine if this is a V86Mode sym file.
+ //
+ // We'll read the first two headers. If their segment numbers are
+ // not 1 and 2, then we assume V86Mode.
+ //
+ pSymHead = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
+ position = ((LONG)pSymHead->nextOffset) << 4;
+ if ( position != startPosition && position != 0 ) {
+ pSymHead2 = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
+ } else {
+ pSymHead2 = NULL;
+ }
+
+ if ( pSymHead->segment == 1 &&
+ (!pSymHead2 || pSymHead2->segment == 2)) {
+ fV86Mode = FALSE;
+ } else {
+ fV86Mode = TRUE;
+ Segment = 0;
+ }
+
+ position = startPosition;
+
+ do {
+ pSymHead = (PSYMHEADER) ((DWORD)p->iptrs.fptr + position);
+ pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymHead + SIZEOFSYMHEADER +
+ pSymHead->symName.length);
+
+ if ( fV86Mode ) {
+ Segment++;
+ Offset = pSymHead->segment;
+ } else {
+ Segment = pSymHead->segment;
+ Offset = 0;
+ }
+
+ position = ((LONG)pSymHead->nextOffset) << 4;
+
+ if (!lpEnumProc( &pSymHead->symName, SYM_SEGMENT_NAME,
+ Segment, Offset, pEnumInfo )) {
+ return FALSE;
+ }
+
+ for (i=0; i<pSymHead->numSyms; i++) {
+ if (!lpEnumProc(&pSymSymbol->symName, SYM_SYMBOL_NAME,
+ Segment, pSymSymbol->offset,
+ pEnumInfo )) {
+ return FALSE;
+ }
+ pSymSymbol = (PSYMSYMBOL) ((DWORD)pSymSymbol + SIZEOFSYMBOL +
+ pSymSymbol->symName.length);
+ }
+ } while ( position != startPosition && position != 0 );
+
+ return 0;
+}
diff --git a/private/windbg/symcvt/symedit/makefile b/private/windbg/symcvt/symedit/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/symcvt/symedit/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/symcvt/symedit/makefile.inc b/private/windbg/symcvt/symedit/makefile.inc
new file mode 100644
index 000000000..92bbabbec
--- /dev/null
+++ b/private/windbg/symcvt/symedit/makefile.inc
@@ -0,0 +1,4 @@
+obj\$(TARGET_DIRECTORY)\strings.i: strings.h
+ $(TARGET_CPP) -EP -DRESOURCES -Tc strings.h > $@
+
+obj\$(TARGET_DIRECTORY)\symedit.res: obj\$(TARGET_DIRECTORY)\strings.i
diff --git a/private/windbg/symcvt/symedit/sources b/private/windbg/symcvt/symedit/sources
new file mode 100644
index 000000000..97761bf3a
--- /dev/null
+++ b/private/windbg/symcvt/symedit/sources
@@ -0,0 +1,47 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Wesley Witt (wesw)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=symedit
+
+TARGETNAME=symedit
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+UMTYPE=console
+
+INCLUDES=.\;..\include;..\..\osdebug\include;obj\$(TARGET_DIRECTORY)
+
+SOURCES= \
+ symedit.rc \
+ symedit.c
+
+!include ..\..\common.src
+
+UMLIBS=..\symcvt\obj\*\symcvt.lib \
+ $(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib \
+ $(BASEDIR)\public\sdk\lib\*\setargv.obj \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+NTTARGETFILES=
diff --git a/private/windbg/symcvt/symedit/strings.c b/private/windbg/symcvt/symedit/strings.c
new file mode 100644
index 000000000..6dcc7e54b
--- /dev/null
+++ b/private/windbg/symcvt/symedit/strings.c
@@ -0,0 +1,2 @@
+#define LANG_USE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#include "strings.h"
diff --git a/private/windbg/symcvt/symedit/strings.h b/private/windbg/symcvt/symedit/strings.h
new file mode 100644
index 000000000..eb3796ae8
--- /dev/null
+++ b/private/windbg/symcvt/symedit/strings.h
@@ -0,0 +1,37 @@
+#if ! defined( _RES_STR_ )
+#define _RES_STR_
+
+#ifdef RESOURCES
+#define RES_STR(a, b, c) b, c
+STRINGTABLE
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+BEGIN
+#else
+
+enum _RESOURCEIDS {
+#define RES_STR(a, b, c) a = b,
+#endif
+
+
+RES_STR(ERR_OPEN_INPUT_FILE, 1, "The file '%s' could not be openned for reading")
+RES_STR(ERR_INVALID_PE, 2, "'%s' is not a valid PE exe file with debug info")
+RES_STR(ERR_NO_DEST, 3, "Need to specify a destination for the converted debug information")
+RES_STR(ERR_OPEN_WRITE_FILE, 4, "Cannot open the file '%s' for writing")
+RES_STR(ERR_EDIT_DBG_FILE, 5, "Cannot edit name file in DBG file")
+RES_STR(ERR_MAP_FILE, 6, "Cannot map the file '%s'")
+RES_STR(ERR_NO_COFF, 7, "No COFF debug information present to be converted")
+RES_STR(ERR_NOT_MAPPED, 8, "Cannot add CV info unless debug information is mapped")
+RES_STR(ERR_COFF_TO_CV, 9, "Cannot convert COFF debug information to CodeView debug information")
+RES_STR(ERR_OP_UNKNOWN, 10, "Operation '%s' is unknown")
+RES_STR(ERR_NO_MEMORY, 11, "Out of memory")
+RES_STR(ERR_FILE_PTRS, 12, "INTERNAL: cannot set file pointers")
+RES_STR(ERR_SET_EOF, 13, "INTERNAL: cannot set the end of file markder")
+RES_STR(ERR_CHECKSUM_CALC, 14, "INTERNAL: cannot compute the image checksum")
+
+#ifdef RESOURCES
+END
+#else
+};
+#endif
+
+#endif // _RES_STR_
diff --git a/private/windbg/symcvt/symedit/symedit.c b/private/windbg/symcvt/symedit/symedit.c
new file mode 100644
index 000000000..3625183b1
--- /dev/null
+++ b/private/windbg/symcvt/symedit/symedit.c
@@ -0,0 +1,1381 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ symedit.c
+
+Abstract:
+
+
+Author:
+
+ Wesley A. Witt (wesw) 19-April-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "symcvt.h"
+#include "cv.h"
+#include "cofftocv.h"
+#include "symtocv.h"
+#include "strings.h"
+
+#include <imagehlp.h>
+
+
+/*
+ * prototypes for this module
+ */
+
+BOOL CalculateOutputFilePointers( PIMAGEPOINTERS pi, PIMAGEPOINTERS po );
+void ProcessCommandLineArgs( int argc, char *argv[] );
+void PrintCopyright( void );
+void PrintUsage( void );
+void FatalError( int, ... );
+BOOL MapOutputFile ( PPOINTERS p, char *fname, int );
+void ComputeChecksum( char *szExeFile );
+void ReadDebugInfo( PPOINTERS p );
+void WriteDebugInfo( PPOINTERS p, BOOL, BOOL );
+void MungeDebugHeadersCoffToCv( PPOINTERS p, BOOL fAddCV );
+void MungeExeName( PPOINTERS p, char * szExeName );
+void DoCoffToCv(char *, char *, BOOL);
+void DoSymToCv(char *, char *, char *, char *);
+void DoNameChange(char *, char *, char *);
+void DoExtract(char *);
+
+IMAGE_DEBUG_DIRECTORY DbgDirSpare;
+IMAGE_DEBUG_DIRECTORY DbgDirCoff;
+
+#define AdjustPtr(ptr) (((ptr) != NULL) ? ((DWORD)ptr - (DWORD)pi->fptr + (DWORD)po->fptr) : ((DWORD)(ptr)))
+
+
+
+int _CRTAPI1
+main(
+ int argc,
+ char * argv[]
+ )
+/*++
+
+Routine Description:
+
+ Shell for this utility.
+
+Arguments:
+
+ argc - argument count
+ argv - argument pointers
+
+
+Return Value:
+
+ 0 - image was converted
+ >0 - image could not be converted
+
+--*/
+
+{
+ /*
+ * Scan the command line and check what operations we are doing
+ */
+
+ ProcessCommandLineArgs( argc, argv );
+ return 0;
+}
+
+void
+PrintCopyright( void )
+
+/*++
+
+Routine Description:
+
+ Prints the MS copyright message to stdout.
+
+Arguments:
+
+ void
+
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ puts( "\nMicrosoft(R) Windows NT SymEdit Version 3.51\n"
+ "(C) 1989-1995 Microsoft Corp. All rights reserved.\n");
+}
+
+void
+PrintUsage( void )
+
+/*++
+
+Routine Description:
+
+ Prints the command line help to stdout
+
+Arguments:
+
+ void
+
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ PrintCopyright();
+ puts("\nUsage: SYMEDIT <OPERATION> -q -o<file out> <file in>\n\n"
+ "\t<OPERATION> is:\n"
+ "\tA\tAdd debug information\n"
+ "\tC\tConvert symbol information\n"
+ "\tN\tEdit name field\n"
+ "\tX\tExtract debug information\n"
+ "\tS\tStrip all debug information\n\n"
+ "Options:\n"
+ "\t-a\t\tAdd CodeView debug info to file\n"
+ "\t-n<name>\tName to change to\n"
+ "\t-o<file>\tspecify output file\n"
+ "\t-q\t\tquiet mode\n"
+ "\t-s<file>\tSym file source");
+}
+
+void
+ProcessCommandLineArgs(
+ int argc,
+ char *argv[]
+ )
+
+/*++
+
+Routine Description:
+
+ Processes the command line arguments and sets global flags to
+ indicate the user's desired behavior.
+
+Arguments:
+
+ argc - argument count
+ argv - argument pointers
+
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ int i;
+ BOOL fQuiet = FALSE;
+ BOOL fSilent = FALSE;
+ char * szOutputFile = NULL;
+ char * szInputFile = NULL;
+ char * szExeName = NULL;
+ char * szDbgFile = NULL;
+ char * szSymFile = NULL;
+ int iOperation;
+ BOOLEAN fAddCV = FALSE;
+
+ /*
+ * Minimun number of of arguments is 2 -- program and operation
+ */
+
+ if (argc < 2) {
+ PrintUsage();
+ exit(1);
+ }
+
+ if ((strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "?") == 0)) {
+ PrintUsage();
+ exit(1);
+ }
+
+ /*
+ * All operations on 1 character wide
+ */
+
+ if (argv[1][1] != 0) {
+ FatalError(ERR_OP_UNKNOWN, argv[1]);
+ }
+
+ /*
+ * Validate the operation
+ */
+
+ switch( argv[1][0] ) {
+ case 'C':
+ case 'N':
+ case 'X':
+ case 'S':
+ iOperation = argv[1][0];
+ break;
+ default:
+ FatalError(ERR_OP_UNKNOWN, argv[1]);
+ }
+
+ /*
+ * Parse out any other switches on the command line
+ */
+
+ for (i=2; i<argc; i++) {
+ if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
+ switch (argv[i][1]) {
+ /*
+ * Add the CV debug information section rather than
+ * replace the COFF section with the CV info.
+ */
+ case 'a':
+ case 'A':
+ fAddCV = TRUE;
+ break;
+
+ /*
+ * Specify the output name for the DBG file
+ */
+
+ case 'd':
+ case 'D':
+ if (argv[i][2] == 0) {
+ i += 1;
+ szDbgFile = argv[i];
+ } else {
+ szDbgFile = &argv[i][2];
+ }
+ break;
+
+ /*
+ * Specify a new name to shove into the name of the
+ * debuggee field in the Misc. Debug info field
+ */
+
+ case 'N':
+ case 'n':
+ if (argv[i][2] == 0) {
+ i += 1;
+ szExeName = argv[i];
+ } else {
+ szExeName = &argv[i][2];
+ }
+ break;
+
+ /*
+ * Specify the name of the output file
+ */
+
+ case 'O':
+ case 'o':
+ if (argv[i][2] == 0) {
+ i += 1;
+ szOutputFile = argv[i];
+ } else {
+ szOutputFile = &argv[i][2];
+ }
+ break;
+
+ /*
+ * Be quite and don't put out the banner
+ */
+
+ case 'Q':
+ case 'q':
+ fQuiet = TRUE;
+ fSilent = TRUE;
+ break;
+
+ /*
+ * Replace COFF debug information with CODEVIEW debug information
+ */
+
+ case 'R':
+ case 'r':
+ break;
+
+ /*
+ * Convert a Symbol File to CV info
+ */
+
+ case 'S':
+ case 's':
+ if (argv[i][2] == 0) {
+ i += 1;
+ szSymFile = argv[i];
+ } else {
+ szSymFile = &argv[i][2];
+ }
+ break;
+
+ /*
+ * Print the command line options
+ */
+
+ case '?':
+ PrintUsage();
+ exit(1);
+ break;
+
+ /*
+ * Unrecognized option
+ */
+
+ default:
+ FatalError( ERR_OP_UNKNOWN, argv[i] );
+ break;
+ }
+ } else {
+ /*
+ * No leading switch character -- must be a file name
+ */
+
+ szInputFile = &argv[i][0];
+
+ /*
+ * Process the file(s)
+ */
+
+ if (!fQuiet) {
+ PrintCopyright();
+ fQuiet = TRUE;
+ }
+
+ if (!fSilent) {
+ printf("processing file: %s\n", szInputFile );
+ }
+
+ /*
+ * Do switch validation cheching and setup any missing global variables
+ */
+
+ switch ( iOperation ) {
+ /*
+ * Add debug information to an exe file
+ *
+ * Must specify in input file
+ * Optional outputfile
+ * Must specify a debug info file
+ */
+
+ case 'A':
+ break;
+
+ /*
+ * For conversions -- there are three types
+ *
+ * 1. Coff to CV -- add
+ * 2. Coff to CV -- replace
+ * 3. SYM to CV --- add
+ * 4. SYM to CV -- seperate file
+ *
+ * Optional input file (not needed for case 4)
+ * Optional output file
+ * Optional sym file (implys sym->CV)
+ * Optional DBG file
+ */
+
+ case 'C':
+ if (szSymFile == NULL) {
+ DoCoffToCv(szInputFile, szOutputFile, fAddCV);
+ } else {
+ DoSymToCv(szInputFile, szOutputFile, szDbgFile, szSymFile);
+ }
+ szInputFile = NULL;
+ szOutputFile = NULL;
+ szDbgFile = NULL;
+ szSymFile = NULL;
+ break;
+
+ /*
+ * For changing the name of the debuggee --
+ * Must specify input file
+ * Must specify new name
+ * Optional output file
+ */
+
+ case 'N':
+ DoNameChange(szInputFile, szOutputFile, szExeName);
+ szInputFile = NULL;
+ szOutputFile = NULL;
+ szExeName = NULL;
+ break;
+
+ /*
+ * For extraction of debug information
+ * Must specify input file
+ * Optional output file name
+ * Optional debug file name
+ */
+
+ case 'X':
+ case 'S':
+ DoExtract(szInputFile);
+ break;
+ }
+ }
+ }
+ return;
+} /* ProcessCommandLineArgs() */
+
+
+void
+ReadDebugInfo(
+ PPOINTERS p
+ )
+/*++
+
+Routine Description:
+
+ This function will go out and read in all of the debug information
+ into memory -- this is required because the input and output
+ files might be the same, if so then writing out informaiton may
+ destory data we need at a later time.
+
+Arguments:
+
+ p - Supplies a pointer to the structure describing the debug info file
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int i;
+ int cb;
+ char * pb;
+ PIMAGE_COFF_SYMBOLS_HEADER pCoffDbgInfo;
+
+
+ /*
+ * Allocate space to save pointers to debug info
+ */
+
+ p->iptrs.rgpbDebugSave = (PCHAR *) malloc(p->iptrs.cDebugDir * sizeof(PCHAR));
+ memset(p->iptrs.rgpbDebugSave, 0, p->iptrs.cDebugDir * sizeof(PCHAR));
+
+ /*
+ * Check each possible debug type record
+ */
+
+ for (i=0; i<p->iptrs.cDebugDir; i++) {
+ /*
+ * If there was debug information then copy over the
+ * description block and cache in the actual debug
+ * data.
+ */
+
+ if ((i != IMAGE_DEBUG_TYPE_COFF) && (p->iptrs.rgDebugDir[i] != NULL)) {
+ p->iptrs.rgpbDebugSave[i] =
+ malloc( p->iptrs.rgDebugDir[i]->SizeOfData );
+ if (p->iptrs.rgpbDebugSave[i] == NULL) {
+ FatalError(ERR_NO_MEMORY);
+ }
+ _try {
+ memcpy(p->iptrs.rgpbDebugSave[i],
+ p->iptrs.fptr +
+ p->iptrs.rgDebugDir[i]->PointerToRawData,
+ p->iptrs.rgDebugDir[i]->SizeOfData );
+ } _except(EXCEPTION_EXECUTE_HANDLER ) {
+ free(p->iptrs.rgpbDebugSave[i]);
+ p->iptrs.rgpbDebugSave[i] = NULL;
+ }
+ }
+ }
+
+ /*
+ * Treat COFF debug information seperately -- since the linker loves
+ * to mix it in with other things
+ */
+
+ if (p->iptrs.rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) {
+ DbgDirCoff = *COFF_DIR(&p->iptrs);
+
+ /*
+ * Allocate space to save the coff debug info
+ */
+
+ pb = p->iptrs.rgpbDebugSave[i] = malloc(DbgDirCoff.SizeOfData);
+
+ /*
+ * Copy over and point to the description for the
+ * debug info.
+ */
+
+ memcpy(pb, DbgDirCoff.PointerToRawData + p->iptrs.fptr,
+ sizeof(IMAGE_COFF_SYMBOLS_HEADER));
+ pCoffDbgInfo = (PIMAGE_COFF_SYMBOLS_HEADER) pb;
+
+ /*
+ * Now figure out how much space we really have -- only things
+ * after the first symbol are "good" -- everything else is
+ * suspect as part of something else.
+ */
+
+ cb = DbgDirCoff.SizeOfData - pCoffDbgInfo->LvaToFirstSymbol;
+
+ /*
+ * Now copy over the real symbol information and set up the
+ * new pointers in the header record
+ */
+
+ memcpy(pb+sizeof(IMAGE_COFF_SYMBOLS_HEADER),
+ p->iptrs.fptr + DbgDirCoff.PointerToRawData +
+ pCoffDbgInfo->LvaToFirstSymbol, cb);
+ pCoffDbgInfo->LvaToFirstSymbol = sizeof(IMAGE_COFF_SYMBOLS_HEADER);
+ DbgDirCoff.SizeOfData = cb + sizeof(IMAGE_COFF_SYMBOLS_HEADER);
+ pCoffDbgInfo->NumberOfLinenumbers = 0;
+ pCoffDbgInfo->LvaToFirstLinenumber = 0;
+ }
+ return;
+} /* ReadDebugInfo() */
+
+
+
+void
+WriteDebugInfo(
+ PPOINTERS p,
+ BOOL fAddCV,
+ BOOL fStrip
+ )
+/*++
+
+Routine Description:
+
+ This function will go out and read in all of the debug information
+ into memory -- this is required because the input and output
+ files might be the same, if so then writing out informaiton may
+ destory data we need at a later time.
+
+Arguments:
+
+ p - Supplies a pointer to the structure describing the debug info file
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PointerToDebugData = 0; /* Offset from the start of the file
+ * to the current location to write
+ * debug information out.
+ */
+ ULONG BaseOfDebugData = 0;
+ int i;
+ PIMAGE_DEBUG_DIRECTORY pDir;
+ int flen;
+ PIMAGE_DEBUG_DIRECTORY pDbgDir = NULL;
+
+
+ if (p->optrs.debugSection) {
+ BaseOfDebugData = PointerToDebugData =
+ p->optrs.debugSection->PointerToRawData;
+ } else if (p->optrs.sepHdr) {
+ BaseOfDebugData = PointerToDebugData =
+ sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
+ p->optrs.sepHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
+ p->optrs.sepHdr->ExportedNamesSize;
+ }
+
+
+ /*
+ * Step 2. If the debug information is mapped, we know this
+ * from the section headers, then we may need to write
+ * out a new debug director to point to the debug information
+ */
+
+ if (fAddCV) {
+ if (p->optrs.optHdr) {
+ p->optrs.optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].
+ VirtualAddress = p->optrs.debugSection->VirtualAddress;
+ p->optrs.optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size +=
+ sizeof(IMAGE_DEBUG_DIRECTORY);
+ } else if (p->optrs.sepHdr) {
+ p->optrs.sepHdr->DebugDirectorySize +=
+ sizeof(IMAGE_DEBUG_DIRECTORY);
+ } else {
+ exit(1);
+ }
+
+ if (p->optrs.sepHdr) {
+ pDbgDir = (PIMAGE_DEBUG_DIRECTORY) malloc(p->optrs.cDebugDir * sizeof(IMAGE_DEBUG_DIRECTORY));
+ for (i=0; i<p->optrs.cDebugDir; i++) {
+ if (p->optrs.rgDebugDir[i] != NULL) {
+ pDbgDir[i] = *(p->optrs.rgDebugDir[i]);
+ p->optrs.rgDebugDir[i] = &pDbgDir[i];
+ }
+ }
+ }
+ for (i=0; i<p->optrs.cDebugDir; i++) {
+ if (p->optrs.rgDebugDir[i]) {
+ pDir = (PIMAGE_DEBUG_DIRECTORY) (PointerToDebugData +
+ p->optrs.fptr);
+ *pDir = *(p->optrs.rgDebugDir[i]);
+ p->optrs.rgDebugDir[i] = pDir;
+ PointerToDebugData += sizeof(IMAGE_DEBUG_DIRECTORY);
+ }
+ }
+ }
+
+ /*
+ * For every debug info type, write out the debug information
+ * and update any header information required
+ */
+
+ for (i=0; i<p->optrs.cDebugDir; i++) {
+ if (p->optrs.rgDebugDir[i] != NULL) {
+ if (!fStrip ||
+ (i == IMAGE_DEBUG_TYPE_FPO) ||
+ (i == IMAGE_DEBUG_TYPE_MISC)) {
+ if (p->optrs.rgpbDebugSave[i] != NULL) {
+ p->optrs.rgDebugDir[i]->PointerToRawData =
+ PointerToDebugData;
+ if (p->optrs.debugSection) {
+ p->optrs.rgDebugDir[i]->AddressOfRawData =
+ p->optrs.debugSection->VirtualAddress +
+ PointerToDebugData - BaseOfDebugData;
+ }
+ memcpy(p->optrs.fptr + PointerToDebugData,
+ p->optrs.rgpbDebugSave[i],
+ p->optrs.rgDebugDir[i]->SizeOfData);
+
+ if ((i == IMAGE_DEBUG_TYPE_COFF) &&
+ (p->optrs.fileHdr != NULL)) {
+ p->optrs.fileHdr->PointerToSymbolTable =
+ PointerToDebugData + sizeof(IMAGE_COFF_SYMBOLS_HEADER);
+ }
+ }
+ PointerToDebugData += p->optrs.rgDebugDir[i]->SizeOfData;
+ }
+ }
+ }
+
+ if ((PointerToDebugData == BaseOfDebugData) && fStrip) {
+ p->optrs.fileHdr->NumberOfSections -= 1;
+ }
+
+ /*
+ * Step 4. Clean up any COFF structures if we are replacing
+ * the coff information with CV info.
+ */
+
+ if ((p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_COFF] == NULL) &&
+ (p->optrs.fileHdr != NULL)) {
+ /*
+ * Since there is no coff debug information -- clean out
+ * both fields pointing to the debug info
+ */
+
+ p->optrs.fileHdr->PointerToSymbolTable = 0;
+ p->optrs.fileHdr->NumberOfSymbols = 0;
+ }
+
+ /*
+ * Step 5. Correct the alignments if needed. If there is
+ * a real .debug section in the file (i.e. it is mapped)
+ * then update the description of the section.
+ */
+
+ if (p->optrs.debugSection) {
+ p->optrs.debugSection->SizeOfRawData =
+ FileAlign(PointerToDebugData - BaseOfDebugData);
+ /*
+ * update the optional header with the new image size
+ */
+
+ p->optrs.optHdr->SizeOfImage =
+ SectionAlign(p->optrs.debugSection->VirtualAddress +
+ p->optrs.debugSection->SizeOfRawData);
+ p->optrs.optHdr->SizeOfInitializedData +=
+ p->optrs.debugSection->SizeOfRawData;
+ }
+
+ /*
+ * calculate the new file size
+ */
+
+ if (p->optrs.optHdr != NULL) {
+ flen = FileAlign(PointerToDebugData);
+ } else {
+ flen = PointerToDebugData;
+ }
+
+ /*
+ * finally, update the eof pointer and close the file
+ */
+
+ UnmapViewOfFile( p->optrs.fptr );
+
+ if (!SetFilePointer( p->optrs.hFile, flen, 0, FILE_BEGIN )) {
+ FatalError( ERR_FILE_PTRS );
+ }
+
+ if (!SetEndOfFile( p->optrs.hFile )) {
+ FatalError( ERR_SET_EOF );
+ }
+
+ CloseHandle( p->optrs.hFile );
+
+ /*
+ * Exit -- we are done.
+ */
+
+ return;
+} /* WriteDebugInfo() */
+
+
+
+void
+MungeDebugHeadersCoffToCv(
+ PPOINTERS p,
+ BOOL fAddCV
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ if (!fAddCV) {
+ CV_DIR(&p->optrs) = COFF_DIR(&p->optrs);
+ COFF_DIR(&p->optrs) = 0;
+ } else {
+ CV_DIR(&p->optrs) = &DbgDirSpare;
+ *(COFF_DIR(&p->optrs)) = *(COFF_DIR(&p->iptrs));
+ };
+
+ *CV_DIR(&p->optrs) = *(COFF_DIR(&p->iptrs));
+ CV_DIR(&p->optrs)->Type = IMAGE_DEBUG_TYPE_CODEVIEW;
+ CV_DIR(&p->optrs)->SizeOfData = p->pCvStart.size;
+ p->optrs.rgpbDebugSave[IMAGE_DEBUG_TYPE_CODEVIEW] = p->pCvStart.ptr;
+
+ return;
+} /* MungeDebugHeadersCoffToCv() */
+
+
+
+BOOL
+MapOutputFile (
+ PPOINTERS p,
+ char *fname,
+ int cb
+ )
+
+/*++
+
+Routine Description:
+
+ Maps the output file specified by the fname argument and saves the
+ file handle & file pointer in the POINTERS structure.
+
+
+Arguments:
+
+ p - pointer to a POINTERS structure (see cofftocv.h)
+ fname - ascii string for the file name
+
+
+Return Value:
+
+ TRUE - file mapped ok
+ FALSE - file could not be mapped
+
+--*/
+
+{
+ BOOL rval;
+ HANDLE hMap = NULL;
+ DWORD oSize;
+
+ rval = FALSE;
+
+ p->optrs.hFile = CreateFile( fname,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ 0,
+ NULL );
+
+ if (p->optrs.hFile == INVALID_HANDLE_VALUE) {
+ goto exit;
+ }
+
+ oSize = p->iptrs.fsize;
+ if (p->pCvStart.ptr != NULL) {
+ oSize += p->pCvStart.size;
+ }
+ oSize += cb;
+ oSize += p->iptrs.cDebugDir * sizeof(IMAGE_DEBUG_DIRECTORY);
+
+ hMap = CreateFileMapping( p->optrs.hFile, NULL, PAGE_READWRITE,
+ 0, oSize, NULL );
+
+ if (hMap == NULL) {
+ goto exit;
+ }
+
+ p->optrs.fptr = MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 );
+
+ if (p->optrs.fptr == NULL) {
+ goto exit;
+ }
+ rval = TRUE;
+exit:
+ return rval;
+} /* MapOutputFile() */
+
+BOOL
+CalculateOutputFilePointers(
+ PIMAGEPOINTERS pi,
+ PIMAGEPOINTERS po
+ )
+
+/*++
+
+Routine Description:
+
+ This function calculates the output file pointers based on the
+ input file pointers. The same address is used but they are all
+ re-based off the output file's file pointer.
+
+Arguments:
+
+ p - pointer to a IMAGEPOINTERS structure (see cofftocv.h)
+
+
+Return Value:
+
+ TRUE - pointers were created
+ FALSE - pointers could not be created
+
+--*/
+{
+ int i;
+
+ // fixup the pointers relative the fptr for the output file
+ po->dosHdr = (PIMAGE_DOS_HEADER) AdjustPtr(pi->dosHdr);
+ po->ntHdr = (PIMAGE_NT_HEADERS) AdjustPtr(pi->ntHdr);
+ po->fileHdr = (PIMAGE_FILE_HEADER) AdjustPtr(pi->fileHdr);
+ po->optHdr = (PIMAGE_OPTIONAL_HEADER) AdjustPtr(pi->optHdr);
+ po->sectionHdrs = (PIMAGE_SECTION_HEADER) AdjustPtr(pi->sectionHdrs);
+ po->sepHdr = (PIMAGE_SEPARATE_DEBUG_HEADER) AdjustPtr(pi->sepHdr);
+ po->debugSection = (PIMAGE_SECTION_HEADER) AdjustPtr(pi->debugSection);
+ po->AllSymbols = (PIMAGE_SYMBOL) AdjustPtr(pi->AllSymbols);
+ po->stringTable = (PUCHAR) AdjustPtr(pi->stringTable);
+
+ // move the data from the input file to the output file
+ memcpy( po->fptr, pi->fptr, pi->fsize );
+
+ po->cDebugDir = pi->cDebugDir;
+ po->rgDebugDir = malloc(po->cDebugDir * sizeof(po->rgDebugDir[0]));
+ memset(po->rgDebugDir, 0, po->cDebugDir * sizeof(po->rgDebugDir[0]));
+
+ for (i=0; i<po->cDebugDir; i++) {
+ po->rgDebugDir[i] = (PIMAGE_DEBUG_DIRECTORY) AdjustPtr(pi->rgDebugDir[i]);
+ }
+ po->rgpbDebugSave = pi->rgpbDebugSave;
+
+ /*
+ * Point the input stream to the modified coff descriptor
+ */
+
+ if (pi->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) {
+ pi->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] = &DbgDirCoff;
+ }
+
+ return TRUE;
+}
+
+
+void
+FatalError(
+ int idMsg,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a message string to stderr and then exits.
+
+Arguments:
+
+ s - message string to be printed
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ va_list marker;
+ char rgchFormat[256];
+ char rgch[256];
+
+ LoadString(GetModuleHandle(NULL), idMsg, rgchFormat, sizeof(rgchFormat));
+
+ va_start(marker, idMsg);
+ vsprintf(rgch, rgchFormat, marker);
+ va_end(marker);
+
+ fprintf(stderr, "%s\n", rgch);
+
+ exit(1);
+} /* FatalError() */
+
+
+void
+ComputeChecksum(
+ char *szExeFile
+ )
+
+/*++
+
+Routine Description:
+
+ Computes a new checksum for the image by calling imagehlp.dll
+
+Arguments:
+
+ szExeFile - exe file name
+
+
+Return Value:
+
+ void
+
+--*/
+
+{
+ DWORD dwHeaderSum = 0;
+ DWORD dwCheckSum = 0;
+ HANDLE hFile;
+ DWORD cb;
+ IMAGE_DOS_HEADER dosHdr;
+ IMAGE_NT_HEADERS ntHdr;
+
+ if (MapFileAndCheckSum(szExeFile, &dwHeaderSum, &dwCheckSum) != CHECKSUM_SUCCESS) {
+ FatalError( ERR_CHECKSUM_CALC );
+ }
+
+ hFile = CreateFile( szExeFile,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ // seek to the beginning of the file
+ SetFilePointer( hFile, 0, 0, FILE_BEGIN );
+
+ // read in the dos header
+ if ((ReadFile(hFile, &dosHdr, sizeof(dosHdr), &cb, 0) == FALSE) || (cb != sizeof(dosHdr))) {
+ FatalError( ERR_CHECKSUM_CALC );
+ }
+
+ // read in the pe header
+ if ((dosHdr.e_magic != IMAGE_DOS_SIGNATURE) ||
+ (SetFilePointer(hFile, dosHdr.e_lfanew, 0, FILE_BEGIN) == -1L)) {
+ FatalError( ERR_CHECKSUM_CALC );
+ }
+
+ // read in the nt header
+ if ((!ReadFile(hFile, &ntHdr, sizeof(ntHdr), &cb, 0)) || (cb != sizeof(ntHdr))) {
+ FatalError( ERR_CHECKSUM_CALC );
+ }
+
+ if (SetFilePointer(hFile, dosHdr.e_lfanew, 0, FILE_BEGIN) == -1L) {
+ FatalError( ERR_CHECKSUM_CALC );
+ }
+
+ ntHdr.OptionalHeader.CheckSum = dwCheckSum;
+
+ if (!WriteFile(hFile, &ntHdr, sizeof(ntHdr), &cb, NULL)) {
+ FatalError( ERR_CHECKSUM_CALC );
+ }
+
+ CloseHandle(hFile);
+ return;
+}
+
+
+void
+MungeExeName(
+ PPOINTERS p,
+ char * szExeName
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argument-name - Supplies | Returns description of argument.
+ .
+ .
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIMAGE_DEBUG_MISC pMiscIn;
+ PIMAGE_DEBUG_MISC pMiscOut;
+ int cb;
+ int i;
+
+ for (i=0; i<p->iptrs.cDebugDir; i++) {
+ if (p->optrs.rgDebugDir[i] != 0) {
+ *(p->optrs.rgDebugDir[i]) = *(p->iptrs.rgDebugDir[i]);
+ }
+ }
+
+ pMiscIn = (PIMAGE_DEBUG_MISC)
+ p->iptrs.rgpbDebugSave[IMAGE_DEBUG_TYPE_MISC];
+
+ if (p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC] == NULL) {
+ p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC] = &DbgDirSpare;
+ memset(&DbgDirSpare, 0, sizeof(DbgDirSpare));
+ }
+
+ pMiscOut = (PIMAGE_DEBUG_MISC)
+ p->optrs.rgpbDebugSave[IMAGE_DEBUG_TYPE_MISC] =
+ malloc(p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC]->SizeOfData +
+ strlen(szExeName));
+ cb = p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC]->SizeOfData;
+
+ while ( cb > 0 ) {
+ if (pMiscIn->DataType == IMAGE_DEBUG_MISC_EXENAME) {
+ pMiscOut->DataType = IMAGE_DEBUG_MISC_EXENAME;
+ pMiscOut->Length = (sizeof(IMAGE_DEBUG_MISC) +
+ strlen(szExeName) + 3) & ~3;
+ pMiscOut->Unicode = FALSE;
+ strcpy(&pMiscOut->Data[0], szExeName);
+ szExeName = NULL;
+ } else {
+ memcpy(pMiscOut, pMiscIn, pMiscIn->Length);
+ }
+
+ p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC]->SizeOfData +=
+ (pMiscOut->Length - pMiscIn->Length);
+
+ cb -= pMiscIn->Length;
+ pMiscIn = (PIMAGE_DEBUG_MISC) (((char *) pMiscIn) + pMiscIn->Length);
+ pMiscOut = (PIMAGE_DEBUG_MISC) (((char *) pMiscOut) + pMiscOut->Length);
+ }
+
+ if (szExeName) {
+ pMiscOut->DataType = IMAGE_DEBUG_MISC_EXENAME;
+ pMiscOut->Length = (sizeof(IMAGE_DEBUG_MISC) +
+ strlen(szExeName) + 3) & ~3;
+ pMiscOut->Unicode = FALSE;
+ strcpy(&pMiscOut->Data[0], szExeName);
+ }
+
+ return;
+} /* MungeExeName() */
+
+
+/*** DoCoffToCv
+ *
+ *
+ */
+
+void
+DoCoffToCv(
+ char * szInput,
+ char * szOutput,
+ BOOL fAddCV
+ )
+{
+ POINTERS p;
+
+ /*
+ * Do default checking
+ */
+
+ if (szOutput == NULL) {
+ szOutput = szInput;
+ }
+
+ /*
+ * Open the input file name and setup the pointers into the file
+ */
+
+ if (!MapInputFile( &p, NULL, szInput )) {
+ FatalError( ERR_OPEN_INPUT_FILE, szInput );
+ }
+
+ /*
+ * Now, if we thing we are playing with PE exes then we need
+ * to setup the pointers into the map file
+ */
+
+ if (!CalculateNtImagePointers( &p.iptrs )) {
+ FatalError( ERR_INVALID_PE, szInput );
+ }
+
+ /*
+ * We are about to try and do the coff to cv symbol conversion.
+ *
+ * Verify that the operation is legal.
+ *
+ * 1. We need to have coff debug information to start with
+ * 2. If the debug info is not mapped then we must not
+ * be trying to add CodeView info.
+ */
+
+ if ((p.iptrs.AllSymbols == NULL) || (COFF_DIR(&p.iptrs) == NULL)) {
+ FatalError( ERR_NO_COFF );
+ }
+
+ if (fAddCV && (p.iptrs.debugSection == 0) && (p.iptrs.sepHdr == NULL)) {
+ FatalError( ERR_NOT_MAPPED );
+ }
+
+ /*
+ * Now go out an preform the acutal conversion.
+ */
+
+ if (!ConvertCoffToCv( &p )) {
+ FatalError( ERR_COFF_TO_CV );
+ }
+
+ /*
+ * Read in any additional debug information in the file
+ */
+
+ ReadDebugInfo(&p);
+
+ /*
+ * Open the output file and adjust the pointers so that
+ * we are ok.
+ */
+
+ if (!MapOutputFile( &p, szOutput, 0 )) {
+ FatalError( ERR_MAP_FILE, szOutput );
+ }
+
+ CalculateOutputFilePointers( &p.iptrs, &p.optrs );
+
+ /*
+ * Munge the various debug information structures
+ * to preform the correct operations
+ */
+
+ MungeDebugHeadersCoffToCv( &p, fAddCV );
+
+ /*
+ * Write out the debug information to the end of the exe
+ */
+
+ WriteDebugInfo( &p, fAddCV, FALSE );
+
+ /*
+ * and finally compute the checksum
+ */
+
+ if (p.iptrs.fileHdr != NULL) {
+ ComputeChecksum( szOutput );
+ }
+
+ return;
+} /* DoCoffToCv() */
+
+/*** DoSymToCv
+ *
+ */
+
+void
+DoSymToCv(
+ char * szInput,
+ char * szOutput,
+ char * szDbg,
+ char * szSym
+ )
+{
+ POINTERS p;
+ HANDLE hFile;
+ DWORD cb;
+ OFSTRUCT ofs;
+
+ /*
+ * Open the input file name and setup the pointers into the file
+ */
+
+ if (!MapInputFile( &p, NULL, szSym )) {
+ FatalError(ERR_OPEN_INPUT_FILE, szSym);
+ }
+
+ /*
+ * Now preform the desired operation
+ */
+
+ if ((szOutput == NULL) && (szDbg == NULL)) {
+ szOutput = szInput;
+ }
+
+ ConvertSymToCv( &p );
+
+ if (szOutput) {
+ if (szOutput != szInput) {
+ if (OpenFile(szInput, &ofs, OF_EXIST) == 0) {
+ FatalError(ERR_OPEN_INPUT_FILE, szInput);
+ }
+ if (CopyFile(szInput, szOutput, FALSE) == 0) {
+ FatalError(ERR_OPEN_WRITE_FILE, szOutput);
+ }
+ }
+ hFile = CreateFile(szOutput, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ FatalError(ERR_OPEN_WRITE_FILE, szOutput);
+ }
+ SetFilePointer(hFile, 0, 0, FILE_END);
+ } else if (szDbg) {
+ hFile = CreateFile(szDbg, GENERIC_WRITE, 0, NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ FatalError(ERR_OPEN_WRITE_FILE, szDbg);
+ }
+ }
+
+ WriteFile(hFile, p.pCvStart.ptr, p.pCvStart.size, &cb, NULL);
+ CloseHandle(hFile);
+
+ return;
+} /* DoSymToCv() */
+
+
+void
+DoNameChange(
+ char * szInput,
+ char * szOutput,
+ char * szNewName
+ )
+{
+ POINTERS p;
+
+ /*
+ * Open the input file name and setup the pointers into the file
+ */
+
+ if (!MapInputFile( &p, NULL, szInput )) {
+ FatalError(ERR_OPEN_INPUT_FILE, szInput);
+ }
+
+ /*
+ * Now, if we thing we are playing with PE exes then we need
+ * to setup the pointers into the map file
+ */
+
+ if (!CalculateNtImagePointers( &p.iptrs )) {
+ FatalError(ERR_INVALID_PE, szInput);
+ }
+
+ /*
+ * Now preform the desired operation
+ */
+
+ if (szOutput == NULL) {
+ szOutput = szInput;
+ }
+
+ if (szNewName == NULL) {
+ szNewName = szOutput;
+ }
+
+ if (p.iptrs.sepHdr != NULL) {
+ FatalError(ERR_EDIT_DBG_FILE);
+ }
+
+ /*
+ * Read in all of the debug information
+ */
+
+ ReadDebugInfo(&p);
+
+ /*
+ * Open the output file and adjust the pointers.
+ */
+
+ if (!MapOutputFile(&p, szOutput,
+ sizeof(szNewName) * 2 + sizeof(IMAGE_DEBUG_MISC))) {
+ FatalError(ERR_MAP_FILE, szOutput);
+ }
+
+ CalculateOutputFilePointers(&p.iptrs, &p.optrs);
+
+ /*
+ * Munge the name of the file
+ */
+
+ MungeExeName(&p, szNewName);
+
+ /*
+ * Write out the debug information to the end of the exe
+ */
+
+ WriteDebugInfo(&p, FALSE, FALSE);
+
+ /*
+ * and finally compute the checksum
+ */
+
+ if (p.iptrs.fileHdr != NULL) {
+ ComputeChecksum( szOutput );
+ }
+
+ return;
+} /* DoNameChange() */
+
+
+void
+DoExtract(
+ char * szInput
+ )
+{
+ char OutFile[_MAX_PATH];
+ // Just call SplitSymbols in imagehlp.dll
+
+ SplitSymbols(szInput, NULL, OutFile, SPLITSYM_EXTRACT_ALL);
+ printf("Symbols for \"%s\" extracted into \"%s\"\n", szInput, OutFile);
+}
diff --git a/private/windbg/symcvt/symedit/symedit.mak b/private/windbg/symcvt/symedit/symedit.mak
new file mode 100644
index 000000000..50862109b
--- /dev/null
+++ b/private/windbg/symcvt/symedit/symedit.mak
@@ -0,0 +1,16 @@
+!include "..\..\mfc\mfc\samples\ntsample.mak"
+
+OBJS = symedit.obj symedit.res
+
+all: symedit.exe
+
+symedit.exe: $(OBJS)
+ $(LINK) $CONFLAGS) -out:symedit.exe $(OBJS) $(CONLIBS)
+
+symedit.res: symedit.rc strings.i
+
+symedit.obj: symedit.c ..\include\symcvt.h ..\include\cv.h \
+ ..\include\cofftocv.h ..\include\symtocv.h strings.h
+
+strings.i:
+ $(CC) -E -DRESOURCES strings.c | findstr -v /C:"#" > strings.i
diff --git a/private/windbg/symcvt/symedit/symedit.rc b/private/windbg/symcvt/symedit/symedit.rc
new file mode 100644
index 000000000..d70842b40
--- /dev/null
+++ b/private/windbg/symcvt/symedit/symedit.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Symbol Editing Program\0"
+#define VER_INTERNALNAME_STR "symedit.exe\0"
+#define VER_ORIGINALFILENAME_STR "symedit.exe\0"
+
+#include "common.ver"
+#include "strings.i"
+ \ No newline at end of file
diff --git a/private/windbg/tlloc/makefile b/private/windbg/tlloc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/tlloc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/tlloc/sources b/private/windbg/tlloc/sources
new file mode 100644
index 000000000..15ca0e416
--- /dev/null
+++ b/private/windbg/tlloc/sources
@@ -0,0 +1,44 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=tlloc
+
+TARGETNAME=tlloc
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+SOURCES= \
+ tllp.c \
+ tlloc.rc
+
+UMTYPE=windows
+
+!include ..\common.src
+
+INCLUDES=..\osdebug;..\osdebug\include
+
+CONDITIONAL_INCLUDES=odp.h odtypes.h odassert.h
+
+TARGETLIBS=$(MORE_LIBS) \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
diff --git a/private/windbg/tlloc/tlloc.def b/private/windbg/tlloc/tlloc.def
new file mode 100644
index 000000000..5f5fbb485
--- /dev/null
+++ b/private/windbg/tlloc/tlloc.def
@@ -0,0 +1,5 @@
+LIBRARY tlloc
+
+EXPORTS
+ DBGVersionCheck PRIVATE
+ TLFunc PRIVATE
diff --git a/private/windbg/tlloc/tlloc.rc b/private/windbg/tlloc/tlloc.rc
new file mode 100644
index 000000000..e41f82121
--- /dev/null
+++ b/private/windbg/tlloc/tlloc.rc
@@ -0,0 +1,14 @@
+//
+// Adapted from OAK\BIN\VERRC.TPL
+//
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Transport Layer (Local) for WinDbg"
+#define VER_INTERNALNAME_STR "tlloc.dll\0"
+#define VER_ORIGINALFILENAME_STR "tlloc.dll\0"
+
+#include <common.ver>
+ \ No newline at end of file
diff --git a/private/windbg/tlloc/tllp.c b/private/windbg/tlloc/tllp.c
new file mode 100644
index 000000000..f41f25103
--- /dev/null
+++ b/private/windbg/tlloc/tllp.c
@@ -0,0 +1,571 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ tllp.c
+
+Abstract:
+
+ This implements the local transport layer for OSDebug versions
+ 2 and 4 on Win32.
+
+Author:
+
+ Jim Schaad (jimsch)
+ Kent Forschmiedt (kentf)
+
+
+--*/
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <stdlib.h>
+
+#include <string.h>
+#include <memory.h>
+
+#ifdef OSDEBUG4
+
+#include "odtypes.h"
+#include "od.h"
+#include "odp.h"
+#include "odassert.h"
+
+#else
+
+#include "defs.h"
+#include "mm.h"
+#include "ll.h"
+#include "od.h"
+#include "tl.h"
+#include "llhpt.h"
+#include "mhhpt.h"
+#include "lbhpt.h"
+#include "osassert.h"
+#include "emdm.h"
+
+#endif
+
+
+#include "dbgver.h"
+extern AVS Avs;
+
+#ifndef CVWS
+int _acrtused = 0;
+#endif
+
+int fReplyDM = FALSE;
+int fReplyEM = FALSE;
+
+
+// debug monitor function definitions.
+
+#ifdef WIN32
+LPDMINIT LpDmInit;
+LPDMFUNC LpDmFunc;
+LPDMDLLINIT LpDmDllInit;
+void FAR PASCAL LOADDS DMInit (DMTLFUNCTYPE, LPVOID);
+#else
+void FAR PASCAL LOADDS DMInit (DMTLFUNCTYPE);
+#endif
+
+LPDBF lpdbf = (LPDBF)0; // the debugger helper functions
+LOCAL TLCALLBACKTYPE TLCallBack; // central osdebug callback function
+
+XOSD FAR PASCAL LOADDS TLFunc ( TLF, HPID, DWORD, LONG);
+XOSD FAR PASCAL LOADDS DMTLFunc ( TLF, HPID, DWORD, LONG);
+
+// these variables are static to prevent collisions with other TL's
+
+static BOOL fConDM = FALSE;
+static BOOL fConEM = FALSE;
+static BOOL fConnected = FALSE;
+
+static LPBYTE lpbDM;
+static DWORD ibMaxDM;
+static DWORD ibDM;
+
+static LPBYTE lpbEM;
+static DWORD ibMaxEM;
+static DWORD ibEM;
+
+char * LpszDm = "DM.DLL";
+HANDLE HDm = NULL;
+
+
+
+
+/**** DBGVersionCheck ****
+ * *
+ * PURPOSE: *
+ * *
+ * To export our version information to the debugger. *
+ * *
+ * INPUTS: *
+ * *
+ * NONE. *
+ * *
+ * OUTPUTS: *
+ * *
+ * Returns - A pointer to the standard version information. *
+ * *
+ * IMPLEMENTATION: *
+ * *
+ * Just returns a pointer to a static structure. *
+ * *
+ ***************************************************************************/
+
+#ifdef DEBUGVER
+DEBUG_VERSION('T','L',"Local Transport Layer")
+#else
+RELEASE_VERSION('T','L',"Local Transport Layer")
+#endif
+
+DBGVERSIONCHECK()
+
+
+
+BOOL DllVersionMatch(HANDLE hMod, LPSTR pType) {
+ DBGVERSIONPROC pVerProc;
+ LPAVS pavs;
+
+ pVerProc = (DBGVERSIONPROC)GetProcAddress(hMod, DBGVERSIONPROCNAME);
+ if (!pVerProc) {
+ return(FALSE); // no version entry point
+ } else {
+ pavs = (*pVerProc)();
+
+ if ((pType[0] != pavs->rgchType[0] || pType[1] != pavs->rgchType[1]) ||
+ (Avs.rlvt != pavs->rlvt) ||
+ (Avs.iRmj != pavs->iRmj)) {
+ return(FALSE);
+ }
+ }
+
+ return(TRUE);
+}
+
+
+
+XOSD FAR PASCAL LOADDS
+TLFunc (
+ TLF wCommand,
+ HPID hpid,
+ DWORD wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This function contains the dispatch loop for commands comming into
+ the transport layer. The address of this procedure is exported to
+ users of the DLL.
+
+Arguments:
+
+ wCommand - Supplies the command to be executed.
+ hpid - Supplies the hpid for which the command is to be executed.
+ wParam - Supplies information about the command.
+ lParam - Supplies information about the command.
+
+Return Value:
+
+ XOSD error code. xosdNone means that no errors occured. Other error
+ codes are defined in osdebug\include\od.h.
+
+--*/
+
+{
+#ifndef OSDEBUG4
+ LPGIS lpgis;
+#endif
+ char * lpsz;
+
+ XOSD xosd = xosdNone;
+
+ Unreferenced( hpid );
+
+ switch ( wCommand ) {
+
+#ifndef OSDEBUG4
+ case tlfGlobalInit:
+ TLCallBack = (TLCALLBACKTYPE) lParam;
+ break;
+
+ case tlfGlobalDestroy:
+ break;
+
+ case tlfSetUIStruct: /* not used for local case */
+ break;
+#endif
+
+
+ case tlfRegisterDBF:
+ lpdbf = (LPDBF) lParam;
+ break;
+
+ case tlfInit:
+ /*
+ * (LPCH) lParam isn't interesting
+ * pass the Local DMTLFunc to the debug monitor
+ */
+
+ lpsz = (char *) lParam;
+ if ((lpsz[0] == 'D') && (lpsz[1] == 'M') &&
+ ((lpsz[2] == ':') || (lpsz[2] == '='))) {
+ lpsz = LpszDm = &lpsz[3];
+ while ((*lpsz != 0) && (*lpsz != ' ')) lpsz++;
+ if (*lpsz != 0) {
+ *lpsz = 0;
+ lpsz++;
+ }
+ }
+ HDm = LoadLibrary(LpszDm);
+ if (HDm == NULL) {
+ xosd = xosdUnknown;
+ break;
+ }
+
+
+ // Do DM dll version check here
+ if (! DllVersionMatch(HDm, "DM")) {
+ xosd = xosdBadVersion;
+ FreeLibrary(HDm);
+ break;
+ }
+
+ if ((LpDmInit = (LPDMINIT) GetProcAddress(HDm, "DMInit")) == NULL) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ break;
+ }
+
+ if ((LpDmFunc = (LPDMFUNC) GetProcAddress(HDm, "DMFunc")) == NULL) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ break;
+ }
+
+ if ((LpDmDllInit = (LPDMDLLINIT) GetProcAddress(HDm, "DmDllInit")) == NULL) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ break;
+ }
+
+#ifdef WIN32
+ if (LpDmDllInit(lpdbf) == FALSE) {
+ xosd = xosdUnknown;
+ FreeLibrary(HDm);
+ break;
+ }
+#endif
+ LpDmInit(DMTLFunc, (LPVOID) lpsz);
+
+
+ break;
+
+ case tlfDestroy:
+ FreeLibrary(HDm);
+ HDm = NULL;
+ break;
+
+ case tlfGetProc:
+ *((TLFUNCTYPE FAR *) lParam) = TLFunc;
+ break;
+
+ case tlfConnect:
+
+ fConEM = TRUE;
+ fConnected = fConDM;
+ break;
+
+ case tlfDisconnect:
+
+ fConDM = fConnected = FALSE;
+ break;
+
+ case tlfSetBuffer:
+
+ lpbDM = (LPBYTE) lParam;
+ ibMaxDM = wParam;
+ break;
+
+ case tlfReply:
+
+ if (!fConnected) {
+#ifdef OSDEBUG4
+ xosd = xosdLineNotConnected;
+#else
+ xosd = xosdIDError;
+#endif
+ } else {
+ if ( wParam <= ibMaxEM ) {
+ _fmemcpy ( lpbEM, (LPBYTE) lParam, wParam );
+ ibEM = wParam;
+ } else {
+ ibEM = 0;
+#ifdef OSDEBUG4
+ xosd = xosdInvalidParameter;
+#else
+ xosd = xosdOverrun;
+#endif
+ }
+ fReplyEM = TRUE;
+ }
+ break;
+
+
+ case tlfDebugPacket:
+
+ if ( !fConnected ) {
+#ifdef OSDEBUG4
+ xosd = xosdLineNotConnected;
+#else
+ xosd = xosdIDError;
+#endif
+ }
+ else {
+#if DBG
+ static LPBYTE lpb = NULL;
+ static DWORD cb = 0;
+
+ if (wParam > cb) {
+ if (lpb != NULL) {
+ free(lpb);
+ }
+ lpb = malloc(wParam);
+ cb = wParam;
+ }
+ memcpy(lpb, (char *) lParam, wParam);
+ LpDmFunc( wParam, lpb);
+#else // DBG
+ LpDmFunc ( wParam, (LPBYTE) lParam );
+#endif // DBG
+ }
+ break;
+
+ case tlfRequest:
+
+ if ( !fConnected ) {
+#ifdef OSDEBUG4
+ xosd = xosdLineNotConnected;
+#else
+ xosd = xosdIDError;
+#endif
+ } else {
+ ibDM = 0;
+ fReplyDM = FALSE;
+#if DBG
+ {
+ static LPBYTE lpb = NULL;
+ static DWORD cb = 0;
+
+ if (wParam > cb) {
+ if (lpb != NULL) {
+ free(lpb);
+ }
+ lpb = malloc(wParam);
+ cb = wParam;
+ }
+ memcpy(lpb, (char *) lParam, wParam);
+ LpDmFunc( wParam, lpb);
+ }
+#else // DBG
+ LpDmFunc ( wParam, (LPBYTE) lParam );
+#endif // DBG
+#ifdef WIN32
+ while (fReplyDM == FALSE) {
+ /*
+ MSG msg;
+ while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE ) )
+ DispatchMessage(&msg);
+ */
+ Sleep(100);
+ }
+#endif
+ fReplyDM = FALSE;
+ }
+ break;
+
+ case tlfGetVersion: // Get DM cpu
+ {
+ AVS *avs = (AVS*)lParam;
+ int size = sizeof(DBB) + sizeof(DMINFO);
+ LPDBB lpdbb = malloc(size);
+ LPDMINFO lpdmi = (LPDMINFO)(lpdbb->rgbVar);
+ lpdbb->dmf = dmfGetDmInfo;
+ lpdbb->hpid = 0;
+ lpdbb->htid = 0;
+ LpDmFunc(size, (LPVOID) lpdbb);
+ avs->mpt = avs->iRup = (USHORT)lpdmi->Processor.Type;
+ }
+ xosd = xosdNotRemote;
+ break;
+
+
+ case tlfGetInfo:
+#ifndef OSDEBUG4
+ lpgis = (LPGIS) lParam;
+ _fstrcpy(lpgis->rgchInfo, "Local Transport Layer (LOCAL:)");
+ lpgis->fCanSetup = FALSE;
+#endif
+ break;
+
+ case tlfSetup:
+ break;
+
+ default:
+
+ assert ( FALSE );
+ break;
+ }
+
+ return xosd;
+} /* TLFunc() */
+
+//
+// DMTLFunc is what the debug monitor will call when it has something
+// to do.
+//
+
+XOSD FAR PASCAL LOADDS
+DMTLFunc (
+ TLF wCommand,
+ HPID hpid,
+ DWORD wParam,
+ LONG lParam
+ )
+{
+ XOSD xosd = xosdNone;
+
+ switch ( wCommand ) {
+
+ case tlfInit:
+
+ break;
+
+ case tlfDestroy:
+
+ break;
+
+ case tlfConnect:
+
+ fConDM = TRUE;
+ fConnected = fConEM;
+ break;
+
+ case tlfDisconnect:
+
+ fConEM = fConnected = FALSE;
+ break;
+
+ case tlfSetBuffer:
+
+ lpbEM = (LPBYTE) lParam;
+ ibMaxEM = wParam;
+ break;
+
+ case tlfReply:
+ if (!fConnected) {
+#ifdef OSDEBUG4
+ xosd = xosdLineNotConnected;
+#else
+ xosd = xosdIDError;
+#endif
+ } else {
+ if ( wParam <= ibMaxDM ) {
+ ibDM = wParam;
+ _fmemcpy ( lpbDM, (LPBYTE) lParam, wParam );
+ fReplyDM = TRUE;
+ } else {
+ ibDM = 0;
+ }
+ fReplyDM = TRUE;
+ }
+ break;
+
+ case tlfDebugPacket:
+ if (!fConnected) {
+#ifdef OSDEBUG4
+ xosd = xosdLineNotConnected;
+#else
+ xosd = xosdIDError;
+#endif
+ } else {
+#if DBG
+ static LPBYTE lpb = NULL;
+ static DWORD cb = 0;
+
+ if (wParam > cb) {
+ if (lpb != NULL) {
+ free(lpb);
+ }
+ lpb = malloc(wParam);
+ cb = wParam;
+ }
+
+ memcpy(lpb, (char *) lParam, wParam);
+ TLCallBack( hpid, wParam, (LONG) lpb);
+#else // DBG
+ TLCallBack ( hpid, wParam, lParam );
+#endif // DBG
+ }
+ break;
+
+ case tlfRequest:
+ if (!fConnected) {
+#ifdef OSDEBUG4
+ xosd = xosdLineNotConnected;
+#else
+ xosd = xosdIDError;
+#endif
+ } else {
+#if DBG
+ static LPBYTE lpb = NULL;
+ static DWORD cb = 0;
+
+ if (wParam > cb) {
+ if (lpb != NULL) {
+ free(lpb);
+ }
+ lpb = malloc(wParam);
+ cb = wParam;
+ }
+ memcpy(lpb, (char *) lParam, wParam);
+ TLCallBack( hpid, wParam, (LONG) lpb);
+#else // DBG
+ TLCallBack ( hpid, wParam, lParam );
+#endif // DBG
+
+#ifdef WIN32
+ while (fReplyEM == FALSE) {
+ Sleep(100);
+ }
+#endif
+ fReplyEM = FALSE;
+
+ if ( ibEM == 0 ) {
+#ifdef OSDEBUG4
+ xosd = xosdInvalidParameter;
+#else
+ xosd = xosdOverrun;
+#endif
+ }
+ }
+ break;
+
+ default:
+
+ assert ( FALSE );
+ break;
+ }
+
+ return xosd;
+
+}
+
diff --git a/private/windbg/windbg/apisupp.c b/private/windbg/windbg/apisupp.c
new file mode 100644
index 000000000..81bbd509e
--- /dev/null
+++ b/private/windbg/windbg/apisupp.c
@@ -0,0 +1,1593 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ apisupp.c
+
+Abstract:
+
+ This file contains the set of routines which preform the interfacing
+ between the debugger dlls and the shell exe.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+/**************************** INCLUDES **********************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern ULONG ulPseudo[];
+
+extern BOOL SetAutoRunSuppress(BOOL);
+
+
+/**********************************************************************/
+
+extern char in386mode;
+extern LPSHF Lpshf;
+extern CXF CxfIp;
+
+char is_assign;
+LPTD LptdFuncEval = NULL;
+
+/**********************************************************************/
+
+BOOL DoCallBacksUntil(void);
+XOSD CheckCallBack(void);
+BOOL EstablishConnection(LPSTR);
+
+/**********************************************************************/
+
+char * t_itoa(int a, char * b, int c) {
+ return _itoa(a, b, c);
+}
+
+
+int __cdecl CDECL d_sprintf(char * a, const char * b, ...)
+{
+ char rgch[100];
+
+ int returnvalue;
+ va_list va_arg;
+ va_start(va_arg, b);
+
+ _fstrcpy(rgch, b);
+ returnvalue = vsprintf(a, (char *) rgch, va_arg) ;
+
+ va_end(va_arg);
+ return returnvalue;
+} /* d_sprintf() */
+
+int CDECL d_eprintf(const char * a, char * b, char * c, int d)
+{
+ char rgch1[100];
+ char rgch2[100];
+ char rgch3[100];
+ char rgch4[100];
+
+ _fstrcpy(rgch1, a);
+ _fstrcpy(rgch2, b);
+ _fstrcpy(rgch3, c);
+
+ sprintf(rgch4, rgch1, rgch2, rgch3, d);
+ DebugBreak();
+ return( strlen(rgch4) );
+} /* d_eprintf() */
+
+int
+LBQuit(UINT ui)
+{
+ return 0;
+} /* LBQuit() */
+
+int
+AssertOut(
+ LPCH lszMsg,
+ LPCH lszFile,
+ UINT iln)
+{
+ ShowAssert(lszMsg, iln, lszFile);
+ return TRUE;
+} /* AssertOut() */
+
+VOID
+DLoadedSymbols(
+ SHE she,
+ HPID hpid,
+ LSZ s
+ )
+{
+ HEXE emi;
+ LPSTR lpch;
+ LPSTR p;
+ LPSTR modname;
+ DWORD len;
+
+
+ emi = SHGethExeFromName((char *)s);
+ Assert(emi != 0);
+ OSDRegisterEmi( hpid, 0, (HEMI)emi, s);
+
+ ModListModLoad( SHGetExeName( emi ), she );
+ if (she != sheSuppressSyms && runDebugParams.fVerbose) {
+ lpch = SHLszGetErrorText(she);
+ if (she == sheNoSymbols) {
+ modname = SHGetExeName( emi );
+ } else {
+ modname = SHGetSymFName( emi );
+ }
+ len = 32;
+ if (lpch) {
+ len += strlen(lpch);
+ }
+ len += strlen(modname);
+ p = malloc( len );
+ sprintf( p, "Module Load: %s (%s)\r\n", modname, lpch ? lpch : "" );
+ PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, TRUE, (LPARAM)p );
+ }
+ return;
+}
+
+BOOL SYGetDefaultShe( LSZ Name, SHE *She)
+{
+ return ModListGetDefaultShe( Name, She );
+}
+
+void LBLog(LSZ lsz)
+{
+ OutputDebugString(lsz);
+ return;
+} /* LBLog() */
+
+/**********************************************************************/
+
+void * MHAlloc(size_t cb)
+{
+ return malloc(cb);
+} /* MHAlloc() */
+
+void _HUGE_ * MHAllocHuge( LONG l, UINT ui)
+{
+ return MHAlloc(l * ui );
+} /* MHAllocHuge() */
+
+void * MHRealloc(void * lpv, size_t cb)
+{
+ return realloc(lpv, cb);
+} /* MHRealloc() */
+
+void MHFree(void * lpv)
+{
+ free(lpv);
+ return;
+} /* MHFree() */
+
+/**********************************************************************/
+
+int
+DHGetNumber(
+ char * lpv,
+ int * result
+ )
+/*++
+
+Routine Description:
+
+ Evaluate an expression, returning a long.
+
+
+Arguments:
+
+ lpv - supplies pointer to the string to convert to a number.
+
+ result - returns the value of the expression as a long
+
+Returns:
+
+ the error code returned by CPGetCastNbr
+
+--*/
+{
+
+ return (int) CPGetCastNbr ( lpv,
+ T_LONG,
+ radix,
+ fCaseSensitive,
+ &CxfIp,
+ (char *) result,
+ NULL);
+
+}
+
+HDEP
+MMAllocHmem(
+ size_t cb
+ )
+{
+ return (HDEP) calloc(1, cb);
+} /* MMAllocHmem() */
+
+HDEP
+MMReallocHmem(
+ HDEP hmem,
+ size_t cb
+ )
+{
+ LPBYTE p = (LPBYTE)hmem;
+ size_t s = p ? _msize(p) : 0;
+
+ if (cb > s) {
+ p = realloc(p, cb);
+ if (p) {
+ ZeroMemory(p+s, cb-s);
+ }
+ }
+ return (HDEP)p;
+} /* MMReallocHmem() */
+
+VOID
+MMFreeHmem(
+ HDEP hmem
+ )
+{
+ free((LPVOID)hmem);
+} /* MMFreeHmem() */
+
+LPVOID
+MMLpvLockMb(
+ HDEP hmem
+ )
+{
+ return (LPVOID)hmem;
+} /* MMLpvLockMb() */
+
+void
+MMbUnlockMb(
+ HDEP hmem
+ )
+{
+ return;
+} /* MMbUnlockMb() */
+
+/**********************************************************************/
+
+UINT SYOpen(LSZ lsz)
+{
+ EstablishConnection(lsz);
+ return((UINT) CreateFile(lsz,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL));
+} /* SYOpen() */
+
+VOID SYClose(UINT hFile)
+{
+ CloseHandle((HANDLE) hFile);
+ return;
+} /* SYClose() */
+
+UINT SYRead(UINT hFile, LPB pch, UINT cb)
+{
+ DWORD dwBytesRead;
+ ReadFile((HANDLE) hFile, pch, cb, &dwBytesRead, NULL);
+ return(dwBytesRead);
+} /* SYRead() */
+
+long SYLseek(UINT hFile, LONG cbOff, UINT iOrigin)
+{
+ return SetFilePointer((HANDLE) hFile, cbOff, NULL, iOrigin);
+} /* SYLseek() */
+
+long SYTell(UINT hFile)
+{
+ return SetFilePointer((HANDLE) hFile, 0, NULL, FILE_CURRENT);
+} /* SYTell() */
+
+
+static LPSTR lpBaseDir = NULL;
+
+VOID
+SetFindExeBaseName(
+ LPSTR lpName
+ )
+{
+ LPSTR p;
+
+ if (lpBaseDir) {
+ free(lpBaseDir);
+ lpBaseDir = 0;
+ }
+
+ if (lpName) {
+ // search from tail for '\\'
+ if ( p = strrchr(lpName, '\\') ) {
+ if (p == lpName || (p == (lpName + 2) && lpName[1] == ':')) {
+#ifdef DBCS
+ if (!IsDBCSLeadByte(*lpName))
+#endif
+ p += 1;
+ }
+ } else if ( lpName[0] != '\0' && lpName[1] == ':' ) {
+#ifdef DBCS
+ if (!IsDBCSLeadByte(*lpName))
+#endif
+ p = lpName + 2;
+ }
+ if (p) {
+ lpBaseDir = malloc((p - lpName) + 1);
+ strncpy(lpBaseDir, lpName, p - lpName);
+ lpBaseDir[p-lpName] = '\0';
+ }
+ }
+}
+
+
+BOOL
+IsExistingConnection(
+ LPSTR RemoteName
+ )
+{
+ DWORD rc;
+ HANDLE hEnum;
+ DWORD Entries;
+ NETRESOURCE *nrr = NULL;
+ DWORD cb;
+ DWORD i;
+ DWORD ss;
+ BOOL rval = FALSE;
+
+
+ rc = WNetOpenEnum( RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL, &hEnum );
+ if (rc != NO_ERROR) {
+ return FALSE;
+ }
+
+ ss = 0;
+ cb = 64 * 1024;
+ nrr = malloc( cb );
+ ZeroMemory( nrr, cb );
+
+ while( TRUE ) {
+ Entries = (DWORD)-1;
+ rc = WNetEnumResource( hEnum, &Entries, nrr, &cb );
+ if (rc == ERROR_NO_MORE_ITEMS) {
+ break;
+ } else if (rc == ERROR_MORE_DATA) {
+ cb += 16;
+ nrr = realloc( nrr, cb );
+ ZeroMemory( nrr, cb );
+ continue;
+ } else if (rc != NO_ERROR) {
+ break;
+ }
+ for (i=0; i<Entries; i++) {
+ if (_stricmp( nrr[i].lpRemoteName, RemoteName ) == 0) {
+ rval = TRUE;
+ break;
+ }
+ }
+ }
+
+ free( nrr );
+ WNetCloseEnum( hEnum );
+
+ return rval;
+}
+
+
+BOOL
+EstablishConnection(
+ LPSTR FileName
+ )
+{
+ NETRESOURCE nr;
+ DWORD rc;
+ DWORD i;
+ LPSTR RemoteName;
+ LPSTR p;
+
+
+
+ if ((FileName[0] != '\\') && (FileName[1] != '\\')) {
+ return FALSE;
+ }
+ p = strchr( &FileName[2], '\\' );
+ if (!p) {
+ //
+ // malformed name
+ //
+ return FALSE;
+ }
+ p = strchr( p+1, '\\' );
+ if (!p) {
+ p = &FileName[strlen(FileName)];
+ }
+ i = p - FileName;
+ RemoteName = malloc( i + 4 );
+ strncpy( RemoteName, FileName, i );
+ RemoteName[i] = 0;
+
+ if (IsExistingConnection( RemoteName )) {
+ free( RemoteName );
+ return TRUE;
+ }
+
+ nr.dwScope = 0;
+ nr.dwType = RESOURCETYPE_DISK;
+ nr.dwDisplayType = 0;
+ nr.dwUsage = 0;
+ nr.lpLocalName = NULL;
+ nr.lpRemoteName = RemoteName;
+ nr.lpComment = NULL;
+ nr.lpProvider = NULL;
+
+ rc = WNetAddConnection2( &nr, NULL, NULL, 0 );
+ if (rc != NO_ERROR) {
+ free( RemoteName );
+ return FALSE;
+ }
+
+ free( RemoteName );
+ return TRUE;
+}
+
+
+UINT
+SYFindExeFile(
+ LSZ lpFile,
+ LSZ lpFound,
+ UINT cchFound,
+ LPVOID lpv,
+ PFNVALIDATEEXE pfn
+ )
+{
+ UINT hFile;
+ LPSTR lpSearchPath = NULL;
+ CHAR szFname[_MAX_FNAME];
+ CHAR szExt[_MAX_EXT];
+ CHAR szDrive[_MAX_DRIVE];
+ CHAR szDir[_MAX_DIR];
+ CHAR szFileName[MAX_PATH];
+ SHE she;
+ CHAR rgch[MAX_PATH];
+ CHAR szBuf[MAX_PATH];
+ LPSTR msgBuf;
+ DWORD len;
+ DWORD cSP;
+ UINT rVal;
+
+
+
+ if (!lpFile || !*lpFile) {
+ rVal = (UINT)-1;
+ goto done;
+ }
+
+ if (*lpFile == '#') {
+ lpFile += 3;
+ }
+
+ _splitpath( lpFile, szDrive, szDir, szFname, szExt);
+ sprintf( szFileName, "%s%s", szFname, szExt );
+
+ cSP = ModListGetSearchPath(NULL, 0) + strlen(szDrive) + strlen(szDir) + 2;
+ if (!cSP) {
+ lpSearchPath = _strdup("");
+ } else {
+ lpSearchPath = malloc(cSP);
+
+ sprintf( lpSearchPath, "%s%s", szDrive, szDir );
+ len = strlen(lpSearchPath);
+ if (len) {
+ lpSearchPath[len++] = ';';
+ lpSearchPath[len] = 0;
+ }
+ ModListGetSearchPath( &lpSearchPath[len], cSP-len );
+ len = strlen(lpSearchPath);
+ Assert(len < cSP);
+ if (*lpSearchPath && lpSearchPath[len-1] == ';') {
+ //
+ // Kill the trailing semi-colon
+ //
+ lpSearchPath[len-1] = 0;
+ }
+ }
+
+ while( TRUE ) {
+
+ EstablishConnection( lpSearchPath );
+
+ hFile = (UINT)FindExecutableImage( szFileName, lpSearchPath, rgch );
+ if (!hFile) {
+ sprintf( szFileName, "%s.dbg", szFname );
+ hFile = (UINT)FindExecutableImage( szFileName, lpSearchPath, rgch );
+ }
+ if (!hFile) {
+ sprintf( szFileName, "%s.%s", szFname, szExt);
+ hFile = (UINT)FindDebugInfoFile( szFileName, lpSearchPath, rgch );
+ }
+ if (hFile) {
+ strcpy( szFileName, rgch );
+ }
+
+ if ((!hFile) || (hFile == (UINT)INVALID_HANDLE_VALUE)) {
+ if (!ExeBrowseForFile( szFileName, sizeof(szFileName) )) {
+ rVal = (UINT) -1;
+ goto done;
+ } else {
+ _splitpath( szFileName, szDrive, szDir, szFname, szExt );
+ sprintf( ExeFileDirectory, "%s%s", szDrive, szDir );
+ continue;
+ }
+ }
+
+ she = pfn( hFile, lpv, rgch );
+ switch( she ) {
+ case sheBadCheckSum:
+ case sheBadTimeStamp:
+ strcpy( szBuf, szFileName );
+ if (!ExeBrowseBadSym( szBuf, sizeof(szBuf) )) {
+ rVal = (UINT) -1;
+ goto done;
+ } else if (strcmp(szBuf,szFileName)==0) {
+ msgBuf = malloc( strlen(rgch) + strlen(szBuf) + 32 );
+ sprintf( msgBuf, "%s for %s\n", rgch, szBuf );
+ PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, TRUE, (LPARAM)msgBuf );
+ strcpy( lpFound, szFileName );
+ rVal = (UINT) hFile;
+ goto done;
+ } else {
+ strcpy( szFileName, szBuf );
+ _splitpath( szFileName, szDrive, szDir, szFname, szExt );
+ sprintf( ExeFileDirectory, "%s%s", szDrive, szDir );
+ continue;
+ }
+ break;
+
+ case sheNoSymbols:
+ _splitpath( szFileName, NULL, NULL, szFname, szExt);
+ sprintf( szFileName, "%s.dbg", szFname );
+ SYClose( hFile );
+ continue;
+ break;
+
+ case sheNone:
+ strcpy( lpFound, szFileName );
+ rVal = (UINT) hFile;
+ goto done;
+
+ default:
+ rVal = (UINT) -1;
+ goto done;
+ }
+ }
+
+done:
+ if (lpSearchPath) {
+ free(lpSearchPath);
+ }
+ return rVal;
+}
+
+
+/**********************************************************************/
+
+XOSD
+SYUnFixupAddr(
+ LPADDR lpaddr
+ )
+{
+ if (LppdCur == NULL) {
+ return xosdNone;
+ }
+
+#ifdef OSDEBUG4
+ return OSDUnFixupAddr(LppdCur->hpid, NULL, lpaddr);
+#else
+ return OSDPtrace(osdUnFixupAddr, 0, lpaddr, LppdCur->hpid, htidNull);
+#endif
+
+}
+
+XOSD
+SYFixupAddr(
+ LPADDR paddr
+ )
+{
+ if (LppdCur == NULL) {
+ return xosdNone;
+ }
+
+#ifdef OSDEBUG4
+ return OSDFixupAddr(LppdCur->hpid, NULL, lpaddr);
+#else
+ return OSDPtrace(osdFixupAddr, 0, paddr, LppdCur->hpid, htidNull);
+#endif
+}
+
+XOSD
+SYSanitizeAddr(
+ LPADDR paddr
+ )
+{
+ XOSD xosd;
+ emiAddr(*paddr) = 0;
+ if ((xosd = SYUnFixupAddr(paddr)) != xosdNone) {
+ return xosd;
+ }
+ return SYFixupAddr(paddr);
+}
+
+UINT SYProcessor(VOID)
+{
+ long l = 0;
+
+ Assert(LppdCur);
+
+ OSDGetDebugMetric ( LppdCur->hpid, 0, mtrcProcessorType, &l );
+
+ return (int) l;
+} /* SYProcessor() */
+
+void
+SYSetEmi (
+ HPID hpid,
+ HTID htid,
+ LPADDR lpaddr
+ )
+{
+ Assert ( ! ADDR_IS_LI ( *lpaddr ) );
+
+#ifdef OSDEBUG4
+ OSDSetEmi(hpid, htid, lpaddr);
+#else
+ OSDPtrace ( osdSetEmi, wNull, lpaddr, hpid, htid );
+#endif
+
+ return;
+} /* SYSetEmi() */
+
+BOOL SYGetAddr(LPADDR lpaddr, int addrType)
+{
+ if ((LppdCur == NULL) || (LptdCur == NULL)) {
+ return FALSE;
+ }
+
+ return OSDGetAddr ( LppdCur->hpid, LptdCur->htid, (ADR) addrType, lpaddr) == xosdNone;
+} /* SYGetAddr() */
+
+/*** SYFIsOverlayLoaded
+ *
+ * Purpose: To fixup and address packet
+ *
+ * Input:
+ * pADDR - The address in question
+ *
+ * Output:
+ * Returns:
+ * TRUE if address loaded up, FALSE otherwise.
+ *
+ * Exceptions:
+ *
+ * Notes: OSDPtrace will return xosdContinue if the address is "loaded"
+ *
+ *
+ *************************************************************************/
+
+#ifndef OSDEBUG4
+SHFLAG
+SYFIsOverlayLoaded (
+ LPADDR paddr
+ )
+{
+ XOSD xosd;
+
+ xosd = OSDPtrace (
+ osdIsOverlayLoaded,
+ wNull,
+ paddr,
+ LppdCur->hpid,
+ LptdCur->htid
+ );
+
+ return ( xosd == xosdContinue );
+} /* SYFIsOverlayLoaded() */
+
+XOSD SYIsStackSetup( HPID hpid, HTID htid, LPADDR lpaddr )
+{
+ XOSD xosd;
+
+ SYFixupAddr( lpaddr );
+ xosd = OSDIsStackSetup( hpid, htid, lpaddr );
+ ADDR_IS_LI ( *lpaddr ) = FALSE;
+ if ( emiAddr ( *lpaddr ) ) {
+ SYUnFixupAddr ( lpaddr );
+ }
+ return xosd;
+}
+#endif
+
+XOSD
+SYGetMemInfo(
+ LPMEMINFO lpmi
+ )
+{
+ return OSDGetMemInfo(LppdCur->hpid, lpmi);
+}
+
+/**********************************************************************/
+
+DWORD
+DHGetDebuggeeBytes(
+ ADDR addr,
+ UINT cb,
+ void * lpb
+ )
+{
+ int terrno = errno;
+#ifdef OSDEBUG4
+ XOSD xosd;
+#endif
+ DWORD cbT;
+
+
+ if ((LppdCur == NULL) || (LptdCur == NULL)) { //Sanity check
+ return 0;
+ }
+
+#ifdef OSDEBUG4
+ if ( ADDR_IS_LI ( addr ) ) {
+ OSDFixupAddr (LppdCur->hpid, LptdCur->htid, &addr );
+ }
+ if (OSDReadMemory(LppdCur->hpid, LptdCur->htid, &addr, lpb, cb, &cbT)
+ != xosdNone) {
+ cbT = 0;
+ }
+#else
+ if ( ADDR_IS_LI ( addr ) ) {
+ OSDPtrace (osdFixupAddr, 0, &addr, LppdCur->hpid, NULL);
+ }
+ OSDSetAddr ( LppdCur->hpid, LptdCur->htid, adrCurrent, &addr );
+ cbT = (DWORD)OSDPtrace(osdReadBuf, cb, lpb, LppdCur->hpid, LptdCur->htid );
+#endif
+
+ errno = terrno;
+ return cbT;
+} /* DHGetDebuggeeBytes() */
+
+/*** DHSetDebuggeeBytes
+ **
+ ** Synopsis:
+ ** uint = DHSetDebuggeeBytes(addr, cb, lpb)
+ **
+ ** Entry:
+ ** addr - address to write the bytes at
+ ** cb - count of bytes to be written
+ ** lpb - pointer to buffer of bytes to be written
+ **
+ ** Returns:
+ ** count of bytes actually written if positive otherwise an
+ ** XOSD error code.
+ **
+ ** Description:
+ ** This function will write bytes into the debuggees memory space.
+ ** To do this it uses OSDebug functions
+ */
+
+
+DWORD
+DHSetDebuggeeBytes(
+ ADDR addr,
+ UINT cb,
+ void * lpb
+ )
+{
+ int terrno = errno;
+ DWORD cbT = 0;
+#ifdef OSDEBUG4
+ XOSD xosd;
+#endif
+
+ if ((LppdCur == NULL) || (LptdCur == NULL)) { //Sanity check
+ return cbT;
+ }
+
+
+ if ( ADDR_IS_LI ( addr ) ) {
+ SYFixupAddr ( &addr );
+ }
+
+#ifdef OSDEBUG4
+ xosd = OSDWriteMemory(LppdCur->hpid, LptdCur->htid, &addr, lpb, cb, &cbT);
+
+ errno = terrno;
+ if (xosd == xosdNone) {
+ return cbT;
+ } else {
+ return 0;
+ }
+#else
+ OSDSetAddr ( LppdCur->hpid, LptdCur->htid, adrCurrent, &addr );
+ cbT = (DWORD)OSDPtrace(osdWriteBuf, cb, (LPV) lpb, LppdCur->hpid, LptdCur->htid );
+ errno = terrno;
+ return (cbT == xosdNone) ? cb : 0;
+#endif
+
+} /* DHSetDebuggeeBytes() */
+
+/*** DHGetReg
+ **
+ ** Synopsis:
+ ** pshreg = DHGetReg(pshreg, pframe)
+ **
+ ** Entry:
+ ** pshreg The register structure. The member hReg must contain
+ ** the handle to the register to get.
+ ** pCxt The context packet to use.
+ **
+ ** Returns:
+ ** pshreg if successful, NULL if the call could not be completed.
+ **
+ ** Description:
+ **
+ ** Currently the 8087 registers are not implemented. In the future
+ ** only ST0 will be implemented.
+ **
+ */
+
+PSHREG DHGetReg(PSHREG pShreg, PCXT pCxt)
+{
+ if ( LppdCur && LptdCur ) {
+
+ if (pShreg->hReg >= CV_REG_PSEUDO1 && pShreg->hReg <= CV_REG_PSEUDO9) {
+
+ pShreg->Byte4 = ulPseudo[pShreg->hReg - CV_REG_PSEUDO1];
+
+ } else if ( fUseFrameContext == TRUE ) {
+
+ OSDFrameReadReg( LppdCur->hpid,
+ LptdCur->htid,
+ pShreg->hReg,
+ &pShreg->Byte1 );
+ } else {
+ //
+ // use the current frame
+ //
+ OSDReadReg( LppdCur->hpid,
+ LptdCur->htid,
+ pShreg->hReg,
+ &pShreg->Byte1 );
+ }
+ return ( pShreg );
+ } else {
+ return NULL;
+ }
+} /* DHGetReg() */
+
+/*** DHSetReg
+ **
+ ** Synopsis:
+ ** pshreg = DHSetReg( pReg, pCxt )
+ **
+ ** Entry:
+ ** pReg - Register description to be read
+ ** pCxt - context to use reading the register
+ **
+ ** Returns:
+ ** pointer to register description
+ **
+ ** Description:
+ **
+ */
+
+PSHREG DHSetReg ( PSHREG pReg, PCXT pCxt )
+{
+ Unreferenced( pCxt );
+
+ if ( LppdCur && LptdCur ) {
+
+ if (pReg->hReg >= CV_REG_PSEUDO1 && pReg->hReg <= CV_REG_PSEUDO9) {
+
+ ulPseudo[pReg->hReg - CV_REG_PSEUDO1] = pReg->Byte4;
+ return ( pReg );
+
+ }
+
+ if ( fUseFrameContext == TRUE ) {
+
+ if (OSDFrameWriteReg( LppdCur->hpid,
+ LptdCur->htid,
+ pReg->hReg,
+ (void *) &pReg->Byte1 ) == xosdNone) {
+ return ( pReg );
+ } else {
+ return NULL;
+ }
+ }
+
+ if (OSDWriteReg (LppdCur->hpid, LptdCur->htid, pReg->hReg,
+ (void *) &pReg->Byte1 ) == xosdNone) {
+ return ( pReg );
+ } else {
+ return NULL;
+ }
+
+ } else {
+ return NULL;
+ }
+} /* DHSetReg() */
+
+
+
+
+BOOL
+DHSetupExecute(
+ LPHDEP lphdep
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called from the expression evaluator to setup things
+ up for a function evaluation call. This request is passed on to the
+ execution model.
+
+Arguments:
+
+ lphdep - Supples a pointer to where a handle is returned
+
+Return Value:
+
+ TRUE if something fails
+
+--*/
+
+{
+ if (LptdCur == NULL) {
+ return xosdUnknown;
+ }
+
+ LptdCur->fInFuncEval = TRUE;
+ LptdFuncEval = LptdCur;
+ return OSDSetupExecute( LppdCur->hpid, LptdCur->htid, lphdep ) != xosdNone;
+} /* DHSetupExecute() */
+
+
+
+BOOL
+DHStartExecute(
+ HDEP hdep,
+ LPADDR lpaddr,
+ BOOL fIgnoreEvents,
+ SHCALL shcall
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when the expression evaluator starts
+ the debugging running a function evaluation. It must be preceded
+ by a call to DHSetupExecute.
+
+Arguments:
+
+ hdep - Supplies the handle to the Execute Function object
+ lpaddr - Supplies the address to start execution at
+ fIgnoreEvents - Supplies
+ fFarRet - Supplies TRUE if a return should be executed
+
+Return Value:
+
+ TRUE if something fails
+
+--*/
+
+{
+ XOSD xosd;
+ MSG msg;
+ BOOL fTmp;
+
+ if (!LptdFuncEval) {
+ return 1;
+ }
+
+ xosd = OSDStartExecute(LptdFuncEval->lppd->hpid, hdep, lpaddr,
+ fIgnoreEvents, shcall == SHFar);
+
+ if (xosd != xosdNone) {
+ return 1;
+ }
+
+ fTmp = SetAutoRunSuppress(TRUE);
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ if (!LptdFuncEval) {
+ xosd = 1;
+ break;
+ }
+ if ((msg.message == DBG_REFRESH) &&
+ (msg.wParam == dbcExecuteDone)) {
+ xosd = msg.lParam;
+ break;
+ }
+ }
+ SetAutoRunSuppress(fTmp);
+
+ return xosd != xosdNone;
+} /* DHStartExecute() */
+
+
+
+BOOL
+DHCleanUpExecute(
+ HDEP hdep
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to clean up after doing a function evalution.
+
+Arguments:
+
+ hdep - Supplies the handle to the function evaluation object
+
+Return Value:
+
+ TRUE if something fails
+
+--*/
+
+{
+ if (!LptdFuncEval) {
+ return TRUE;
+ }
+ LptdFuncEval->fInFuncEval = FALSE;
+ return (OSDCleanUpExecute( LptdFuncEval->lppd->hpid, hdep ) != xosdNone);
+} /* DHCleanUpExecute() */
+
+
+/**********************************************************************/
+
+LSZ
+FullPath(
+ LSZ lszBuf,
+ LSZ lszRel,
+ UINT cbBuf
+ )
+{
+ char szBuf[500];
+ char szRel[500];
+ char * szRet;
+
+ _fstrcpy( szRel, lszRel );
+ if ( szRet = _fullpath( (char *) szBuf, szRel, (size_t)cbBuf ) ) {
+ _fstrcpy( lszBuf, szBuf );
+ }
+ return (LSZ)szRet;
+}
+
+void MakePath( LSZ lszPath, LSZ lszDrive, LSZ lszDir,
+ LSZ lszFName, LSZ lszExt )
+{
+ char szPath[500];
+ char szDrive[256];
+ char szDir[256];
+ char szFName[256];
+ char szExt[256];
+
+ _fstrcpy( szDrive, lszDrive );
+ _fstrcpy( szDir, lszDir );
+ _fstrcpy( szFName, lszFName );
+ _fstrcpy( szExt, lszExt );
+
+ _makepath( szPath, szDrive, szDir, szFName, szExt );
+ _fstrcpy( lszPath, szPath );
+}
+
+int OurStat( LSZ lsz, LPCH lpstat )
+{
+ char sz[ 256 ];
+ struct _stat statT;
+ int wRet;
+
+ strcpy( sz, lsz );
+ wRet = _stat( sz, &statT );
+ *(struct _stat *)lpstat = statT;
+ return wRet;
+}
+
+UINT CDECL OurSprintf( LSZ lszBuf, LSZ lszFmt, ... ) {
+ va_list val;
+ WORD wRet;
+ char szBuf[256];
+ char szFmt[256];
+
+ _fstrcpy( szFmt, lszFmt );
+
+ va_start( val, lszFmt );
+ wRet = (WORD)vsprintf( szBuf, szFmt, val );
+ va_end( val );
+
+ _fstrcpy( lszBuf, szBuf );
+ return wRet;
+}
+
+void SearchEnv( LSZ lszFile, LSZ lszVar, LSZ lszPath )
+{
+ char szFile[ 256 ];
+ char szVar[ 256 ];
+ char szPath[ 256 ];
+
+ _fstrcpy( szFile, lszFile );
+ _fstrcpy( szVar, lszVar );
+ _searchenv( szFile, szVar, szPath );
+ _fstrcpy( lszPath, szPath );
+}
+
+
+void SplitPath( LSZ lsz1, LSZ lsz2, LSZ lsz3, LSZ lsz4, LSZ lsz5 ) {
+ char sz1[ _MAX_CVPATH ];
+ char sz2[ _MAX_CVDRIVE ];
+ char sz3[ _MAX_CVDIR ];
+ char sz4[ _MAX_CVFNAME];
+ char sz5[ _MAX_CVEXT];
+
+ _fstrcpy( sz1, lsz1 );
+ _splitpath( sz1, sz2, sz3, sz4, sz5 );
+ if (lsz2 != NULL) _fstrcpy( lsz2, sz2 );
+ if (lsz3 != NULL) _fstrcpy( lsz3, sz3 );
+ if (lsz4 != NULL) _fstrcpy( lsz4, sz4 );
+ if (lsz5 != NULL) _fstrcpy( lsz5, sz5 );
+
+ return;
+}
+
+LPSTR
+FormatSymbol(
+ HSYM hsym,
+ PCXT lpcxt
+ )
+{
+ HDEP hstr;
+ char szContext[512];
+ char szStr[512];
+ char szUndecStr[256];
+
+
+ EEFormatCXTFromPCXT( lpcxt, &hstr, runDebugParams.fShortContext );
+ if (runDebugParams.fShortContext) {
+ strcpy( szContext, (LPSTR)MMLpvLockMb(hstr) );
+ } else {
+ BPShortenContext( (LPSTR)MMLpvLockMb(hstr), szContext );
+ }
+ MMbUnlockMb(hstr);
+ EEFreeStr(hstr);
+
+ FormatHSym(hsym, lpcxt, szStr);
+ if (*szStr == '?') {
+ if (UnDecorateSymbolName( szStr,
+ szUndecStr,
+ sizeof(szUndecStr),
+ UNDNAME_COMPLETE |
+ UNDNAME_NO_LEADING_UNDERSCORES |
+ UNDNAME_NO_MS_KEYWORDS |
+ UNDNAME_NO_FUNCTION_RETURNS |
+ UNDNAME_NO_ALLOCATION_MODEL |
+ UNDNAME_NO_ALLOCATION_LANGUAGE |
+ UNDNAME_NO_MS_THISTYPE |
+ UNDNAME_NO_CV_THISTYPE |
+ UNDNAME_NO_THISTYPE |
+ UNDNAME_NO_ACCESS_SPECIFIERS |
+ UNDNAME_NO_THROW_SIGNATURES |
+ UNDNAME_NO_MEMBER_TYPE |
+ UNDNAME_NO_RETURN_UDT_MODEL |
+ UNDNAME_NO_ARGUMENTS |
+ UNDNAME_NO_SPECIAL_SYMS |
+ UNDNAME_NAME_ONLY
+ )) {
+ strcat(szContext,szUndecStr);
+ }
+ } else {
+ strcat(szContext,szStr);
+ }
+
+ return _strdup(szContext);
+}
+
+BOOL
+GetNearestSymbolInfo(
+ LPADDR addr,
+ LPNEARESTSYM lpnsym
+ )
+{
+ ADDR addr1;
+ HDEP hsyml;
+ PHSL_HEAD lphsymhead;
+ PHSL_LIST lphsyml;
+ UINT n;
+ DWORD dwOff;
+ DWORD dwOffP;
+ DWORD dwOffN;
+ DWORD dwAddrP;
+ DWORD dwAddrN;
+ EESTATUS eest;
+ HEXE hexe;
+
+
+ ZeroMemory(&lpnsym->cxt, sizeof(CXT));
+ SYUnFixupAddr(addr);
+ SHSetCxt(addr, &lpnsym->cxt);
+
+ hexe = (HEXE)emiAddr(*addr);
+ if ( hexe && (HPID)hexe != LppdCur->hpid ) {
+ SHWantSymbols(hexe);
+ }
+
+ hsyml = 0;
+ eest = EEGetHSYMList(&hsyml, &lpnsym->cxt, HSYMR_public, NULL, TRUE);
+ if (eest != EENOERROR) {
+ return FALSE;
+ }
+
+ lphsymhead = MMLpvLockMb ( hsyml );
+ lphsyml = (PHSL_LIST)(lphsymhead + 1);
+
+ dwOffP = 0xffffffff;
+ dwOffN = 0xffffffff;
+ dwAddrP = 0xffffffff;
+ dwAddrN = 0xffffffff;
+
+ SYFixupAddr(addr);
+ addr1 = *addr;
+ for ( n = 0; n < (UINT)lphsyml->symbolcnt; n++ ) {
+
+ if (SHAddrFromHsym(&addr1, lphsyml->hSym[n])) {
+ SYFixupAddr(&addr1);
+ if (GetAddrSeg(addr1) != GetAddrSeg(*addr)) {
+ continue;
+ }
+ if (GetAddrOff(addr1) <= GetAddrOff(*addr)) {
+ dwOff = GetAddrOff(*addr) - GetAddrOff(addr1);
+ if (dwOff < dwOffP) {
+ dwOffP = dwOff;
+ dwAddrP = GetAddrOff(addr1);
+ lpnsym->hsymP = lphsyml->hSym[n];
+ lpnsym->addrP = addr1;
+ }
+ } else {
+ dwOff = GetAddrOff(addr1) - GetAddrOff(*addr);
+ if (dwOff < dwOffN) {
+ dwOffN = dwOff;
+ dwAddrN = GetAddrOff(addr1);
+ lpnsym->hsymN = lphsyml->hSym[n];
+ lpnsym->addrN = addr1;
+ }
+ }
+ }
+
+ }
+
+ MMbUnlockMb(hsyml);
+ MMFreeHmem(hsyml);
+
+ return TRUE;
+}
+
+LPSTR
+GetNearestSymbolFromAddr(
+ LPADDR lpaddr,
+ LPADDR lpAddrRet
+ )
+{
+ NEARESTSYM nsym;
+
+
+ ZeroMemory( &nsym, sizeof(nsym) );
+
+ if (!GetNearestSymbolInfo( lpaddr, &nsym )) {
+ return NULL;
+ }
+
+ if (!nsym.hsymP) {
+ return NULL;
+ }
+
+ *lpAddrRet = nsym.addrP;
+ SYFixupAddr(lpAddrRet);
+
+ return FormatSymbol( nsym.hsymP, &nsym.cxt );
+}
+
+/**********************************************************************/
+
+/*
+ ** Set up the structures needed for OSDebug
+ **
+ ** dbf - This structure contains a set of callback routines
+ ** to be used by the OSDebug modules to get certian
+ ** services
+ */
+
+DBF Dbf = {
+ MHAlloc, /* MHAlloc */
+ MHRealloc, /* MHRealloc */
+ MHFree, /* MHFree */
+ MMAllocHmem, /* MMAllocHmem */
+ MMFreeHmem, /* MMFreeHmem */
+ MMLpvLockMb, /* MMLock */
+ MMbUnlockMb, /* MMUnlock */
+
+(HLLI (WINAPI *)( UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE ))
+ LLPlliInit, /* LLInit */
+(HLLE (WINAPI *)( HLLI ))
+ LLPlleCreate, /* LLCreate */
+(VOID (WINAPI *)( HLLI, HLLE ))
+ LLAddPlleToLl, /* LLAdd */
+(VOID (WINAPI *)( HLLI, HLLE, DWORD ))
+ LLInsertPlleInLl, /* LLInsert */
+(BOOL (WINAPI *)( HLLI, HLLE ))
+ LLFDeletePlleFromLl, /* LLDelete */
+(HLLE (WINAPI *)( HLLI, HLLE ))
+ LLPlleFindNext, /* LLNext */
+(LONG (WINAPI *)( HLLI ))
+ LLChlleDestroyLl, /* LLDestroy */
+(HLLE (WINAPI *)( HLLI, HLLE, LPV, DWORD ))
+ LLPlleFindLpv, /* LLFind */
+(DWORD (WINAPI *)( HLLI ))
+ LLChlleInLl, /* LLSize */
+(LPVOID (WINAPI *)( HLLE ))
+ LLLpvFromPlle, /* LLLock */
+(VOID (WINAPI *)( HLLE ))
+ LLUnlockPlle, /* LLUnlock */
+(HLLE (WINAPI *)( HLLI ))
+ LLPlleGetLast, /* LLLast */
+(VOID (WINAPI *)( HLLI, HLLE ))
+ LLPlleAddToHeadOfLI, /* LLAddHead */
+(BOOL (WINAPI *)( HLLI, HLLE ))
+ LLFRemovePlleFromLl, /* LLRemove */
+
+ NULL, /* SHModelFromADDR */
+ NULL, /* SHPublicNameTOADDR */
+ NULL, /* SHAddrToPublicName */
+ NULL, /* SHWantSymbols */
+ NULL, /* SHGetSymbol (1)*/
+ NULL, /* SHGetPublicAddr (1)*/
+ NULL, /* SHLpGSNGetTable (see FLoadEmTl)*/
+ NULL, /* SHGetDebugData */
+ NULL, /* SHFindSymbol */
+// NULL, /* SHLocateSymbolFile */
+
+ AssertOut, /* LBPrintf */
+ LBQuit, /* LBQuit */
+ NULL, /* Signal */
+ NULL, /* Abort */
+ NULL, /* SpawnL */
+ DHGetNumber, /* DHGetNumber */
+ NULL, /* PSP??? */
+ NULL /* OSMajor Version??? */
+ /* End of structure */
+};
+
+KNF Knf = {
+ sizeof(KNF),
+ MHAlloc, /* MHAlloc */
+ MHRealloc, /* MHRealloc */
+ MHFree, /* MHFree */
+#ifndef HOST32
+ LDShalloc, /* MHAllocHuge */
+ LDShfree, /* MHFreeHuge */
+#else
+ MHAllocHuge, /* MHAllocHuge */
+ MHFree, /* MHFreeHuge */
+#endif
+ MMAllocHmem, /* MMAllocHmem */
+ MMFreeHmem, /* MMFreeHmem */
+ MMLpvLockMb, /* MMLock */
+ MMbUnlockMb, /* MMUnlock */
+(HLLI (WINAPI *)( UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE ))
+ LLPlliInit, /* LLInit */
+(HLLE (WINAPI *)( HLLI ))
+ LLPlleCreate, /* LLCreate */
+(VOID (WINAPI *)( HLLI, HLLE ))
+ LLAddPlleToLl, /* LLAdd */
+(VOID (WINAPI *)( HLLI, HLLE ))
+ LLPlleAddToHeadOfLI, /* LLAddHead */
+(VOID (WINAPI *)( HLLI, HLLE, DWORD ))
+ LLInsertPlleInLl, /* LLInsert */
+(BOOL (WINAPI *)( HLLI, HLLE ))
+ LLFDeletePlleFromLl, /* LLDelete */
+(BOOL (WINAPI *)( HLLI, HLLE ))
+ LLFRemovePlleFromLl, /* LLRemove */
+(LONG (WINAPI *)( HLLI ))
+ LLChlleDestroyLl, /* LLDestroy */
+(HLLE (WINAPI *)( HLLI, HLLE ))
+ LLPlleFindNext, /* LLNext */
+(HLLE (WINAPI *)( HLLI, HLLE, LPV, DWORD ))
+ LLPlleFindLpv, /* LLFind */
+(HLLE (WINAPI *)( HLLI ))
+ LLPlleGetLast, /* LLLast */
+(DWORD (WINAPI *)( HLLI ))
+ LLChlleInLl, /* LLSize */
+(LPVOID (WINAPI *)( HLLE ))
+ LLLpvFromPlle, /* LLLock */
+(VOID (WINAPI *)( HLLE ))
+ LLUnlockPlle, /* LLUnlock */
+ AssertOut, /* LPPrintf */
+ LBQuit, /* LPQuit */
+ SYOpen, /* SYOpen */
+ SYClose, /* SYClose */
+ SYRead, /* SYRead */
+ SYLseek, /* SYSeek */
+ SYFixupAddr, /* SYFixupAddr */
+ SYUnFixupAddr, /* SYUnFixupAddr */
+
+ //SYProcessor, /* SYProcessor */
+ NULL,
+
+ // SYFIsOverlayLoaded, /* SYFIsOverlayLoaded */
+ // SearchEnv, /* searchenv */
+ // OurSprintf, /* sprintf */
+ // SplitPath, /* splitpath */
+ // FullPath, /* fullpath */
+ // MakePath, /* makepath */
+ // OurStat, /* stat */
+ // LBLog, /* LBLog */
+ SYTell, /* SYTell */
+ SYFindExeFile, /* SYFindExeFile */
+ DLoadedSymbols, /* LoadedSymbols */
+ SYGetDefaultShe /* SYGetDefaultShe */
+}; /* End of structure */
+
+CRF Crf = {
+ NULL, /* int */
+ NULL, /* ultoa */
+ t_itoa, /* _itoa */
+ NULL, /* ltoa */
+ d_eprintf, /* eprintf */
+ d_sprintf /* sprintf */
+}; /* End of structure */
+
+CVF Cvf = {
+ MHAlloc, /* MHlpvAlloc */
+ MHFree, /* MHFreeLpv */
+ NULL, /* SHGetNextExe (1) */
+ NULL, /* SHHEXEFromHMOD (1)*/
+ NULL, /* SHGetNextMod (1)*/
+ NULL, /* SHGetCXTFromHMOD (1)*/
+ NULL, /* SHGetCXTFromHEXE (1)*/
+ NULL, /* SHSetCXT (1)*/
+ NULL, /* SHSetCXTMod */
+ NULL, /* SHFindNameInGlobal (1)*/
+ NULL, /* SHFindNameInContext (1)*/
+ NULL, /* SHGoToParent (1)*/
+ NULL, /* SHHSYMFromCXT */
+ NULL, /* SHNextHsym (1)*/
+ CLGetFuncCXF, /* SHGetFuncCXF */
+ NULL, /* SHGetModName */
+ NULL, /* SHGetExeName */
+ NULL, /* SHGetModNameFromHexe */
+ NULL, /* SHGetSymFName */
+ NULL, /* SHGethExeFromName (1)*/
+ NULL, /* SHGethExeFromModuleName (1)*/
+ NULL, /* SHGetNearestHSYM (1)*/
+ NULL, /* SHIsInProlog (1)*/
+ NULL, /* SHModelFromAddr (1)*/
+ NULL, /* SHIsADDRInCXT */
+ NULL, /* SLLineFromAddr */
+ NULL, /* SLFLineToAddr (1)*/
+ NULL, /* SLNameFromHsf */
+ NULL, /* SLHmdsFromHsf */
+ NULL, /* SLHsfFromPcxt (1)*/
+ NULL, /* SLHsfFromFile (1)*/
+ NULL, /* PHGetNearestHSYM */
+ NULL, /* PHFindNameInPublics (1)*/
+ NULL, /* THGetTypeFromIndex (1)*/
+ NULL, /* THGetNextType */
+ MMAllocHmem, /* MHMemAllocate */
+ MMReallocHmem, /* MHMemReAlloc */
+ MMFreeHmem, /* MHMemFree */
+ MMLpvLockMb, /* MHMemLock */
+ MMbUnlockMb, /* MHMemUnLock */
+ NULL, /* MHIsMemLocked */
+ DHGetDebuggeeBytes, /* DHGetDebuggeeBytes */
+ DHSetDebuggeeBytes, /* DHPutDebuggeeBytes */
+ DHGetReg, /* DHGetReg */
+ DHSetReg, /* DHSetReg */
+ DHSetupExecute, /* DHSetupExecute */
+ DHCleanUpExecute, /* DHCleanUpExecute */
+ DHStartExecute, /* DHStartExecute */
+ &in386mode, /* in386mode */
+ &is_assign, /* is_assign */
+ AssertOut, /* assert */
+ LBQuit, /* quit */
+ NULL, /* ArrayDefault */
+ NULL, /* pSHCompareRE */
+ SYFixupAddr, /* SHFixupAddr */
+ SYUnFixupAddr, /* pSHUnFixupAddr */
+ NULL, /* pCVfnCmp */
+ NULL, /* pCVcsCmp */
+ NULL, /* pCVcsCmp */
+ SYGetAddr, /* pSYGetAddr */
+ SYGetMemInfo, /* pSYGetMemInfo */
+ NULL, /* SHWantSymbols */
+}; /* End of structure */
+
+LPSHF Lpshf;
+
+/*** CopyShToEe
+ **
+ ** Synopsis:
+ ** void = CopyShToEe()
+ **
+ ** Entry:
+ ** none
+ **
+ ** Returns:
+ ** Nothing
+ **
+ ** Description:
+ ** Copy function pointers from the Symbol handler API to the
+ ** Expression evaluator API
+ **
+ */
+
+void CopyShToEe()
+{
+ Cvf.pSHGetNextExe = Lpshf->pSHGetNextExe;
+ Cvf.pSHHexeFromHmod = Lpshf->pSHHexeFromHmod;
+ Cvf.pSHGetNextMod = Lpshf->pSHGetNextMod;
+ Cvf.pSHGetCxtFromHmod = Lpshf->pSHGetCxtFromHmod;
+ Cvf.pSHGetCxtFromHexe = Lpshf->pSHGetCxtFromHexe;
+ Cvf.pSHSetCxt = Lpshf->pSHSetCxt;
+ Cvf.pSHFindNameInGlobal = Lpshf->pSHFindNameInGlobal;
+ Cvf.pSHFindNameInContext = Lpshf->pSHFindNameInContext;
+ Cvf.pSHGoToParent = Lpshf->pSHGoToParent;
+ Cvf.pSHNextHsym = Lpshf->pSHNextHsym;
+ Cvf.pSHGethExeFromName = Lpshf->pSHGethExeFromName;
+ Cvf.pSHGethExeFromModuleName = Lpshf->pSHGethExeFromModuleName;
+ Cvf.pSHGetNearestHsym = Lpshf->pSHGetNearestHsym;
+ Cvf.pSHIsInProlog = Lpshf->pSHIsInProlog;
+ Cvf.pSHModelFromAddr = Lpshf->pSHModelFromAddr;
+ Cvf.pSLFLineToAddr = Lpshf->pSLFLineToAddr;
+ Cvf.pSLHsfFromPcxt = Lpshf->pSLHsfFromPcxt;
+ Cvf.pSLHsfFromFile = Lpshf->pSLHsfFromFile;
+ Cvf.pPHFindNameInPublics = Lpshf->pPHFindNameInPublics;
+ Cvf.pTHGetTypeFromIndex = Lpshf->pTHGetTypeFromIndex;
+ Cvf.pSHCompareRE = Lpshf->pSHCompareRE;
+ Cvf.pSHGetExeName = Lpshf->pSHGetExeName;
+ Cvf.pSHGetModNameFromHexe = Lpshf->pSHGetModNameFromHexe;
+ Cvf.pSHGetSymFName = Lpshf->pSHGetSymFName;
+ Cvf.pSLNameFromHsf = Lpshf->pSLNameFromHsf;
+ Cvf.pSHWantSymbols = Lpshf->pSHWantSymbols;
+
+ Dbf.lpfnSHPublicNameToAddr = Lpshf->pSHPublicNameToAddr;
+ Dbf.lpfnSHGetSymbol = Lpshf->pSHGetSymbol;
+ Dbf.lpfnSHGetPublicAddr = Lpshf->pSHGetPublicAddr;
+ Dbf.lpfnSHLpGSNGetTable = Lpshf->pSHLpGSNGetTable;
+ Dbf.lpfnSHGetDebugData = Lpshf->pSHGetDebugData;
+ Dbf.lpfnSHFindSymbol = Lpshf->pSHFindSymbol;
+ Dbf.lpfnSHAddrToPublicName = GetNearestSymbolFromAddr;
+ Dbf.lpfnSHWantSymbols = Lpshf->pSHWantSymbols;
+// Dbf.lpfnSHLocatSymbolFile = Lpshf->pSHLocateSymbolFile;
+
+ return;
+} /* CopyShToEe() */
diff --git a/private/windbg/windbg/arrange.c b/private/windbg/windbg/arrange.c
new file mode 100644
index 000000000..4b74002b0
--- /dev/null
+++ b/private/windbg/windbg/arrange.c
@@ -0,0 +1,602 @@
+/*++
+
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Arrange.c
+
+Abstract:
+
+ This module contains the default mdi tiling (arrange) code for CV format
+ windowing arrangement.
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 01-Aug-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern HWND GetCallsHWND(void);
+extern HWND GetLocalHWND(void);
+extern HWND GetFloatHWND(void);
+extern HWND GetWatchHWND(void);
+extern HWND GetCpuHWND(void);
+
+
+
+
+void PASCAL FAR arrange (void);
+
+
+
+void PASCAL FAR arrange ()
+{
+ UINT indx; // counters, indices...
+ int winType; // type of window (MEM,COMMAND,etc...)
+ NPDOCREC d;
+ int numdocs, nummems, nSide, nSplit, nVsplit, nHdelta, nVdelta;
+ BOOL fWatch, fLocal, fCpu, fFloat, fCalls;
+ BOOL fDoc, fDisasm, fCommand, fMem;
+ HWND hCpu, hFlt, hWtch, hLoc, hCalls;
+ RECT rc, rcc, rCm;
+ RECT rDoc, rDisasm, rComm, rMem;
+ BOOL fIcon = FALSE;
+
+
+
+ numdocs=nummems=nSide=nSplit=nVsplit=nHdelta=nVdelta = 0;
+ fWatch=fLocal=fCpu=fFloat=fCalls = FALSE;
+ fDoc=fDisasm=fCommand=fMem = FALSE; // initialize to non-existent
+
+
+ for (indx = 0; indx < MAX_VIEWS; indx++)
+ {
+ winType = Views[indx].Doc; //window type
+
+ if (winType == -1)
+ {
+ continue; // end of valid views or sparse array
+ }
+ else
+ if (winType < -1) // special case for WATCH,LOCALS,CPU,FLOAT win's
+ {
+ switch (-winType)
+ {
+ case WATCH_WIN:
+ if ((hWtch = GetWatchHWND()) != (HWND)NULL)
+ {
+ if(!IsIconic(hWtch))
+ {
+ fWatch = TRUE;
+ nSplit++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+ case LOCALS_WIN:
+ if ((hLoc = GetLocalHWND()) != (HWND)NULL)
+ {
+ if(!IsIconic(hLoc))
+ {
+ fLocal = TRUE;
+ nSplit++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+ case CPU_WIN:
+ if ((hCpu = GetCpuHWND()) != (HWND)NULL)
+ {
+ if (!IsIconic(hCpu))
+ {
+ fCpu = TRUE;
+ nSide++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+
+ case FLOAT_WIN:
+ if ((hFlt = GetFloatHWND()) != (HWND)NULL)
+ {
+ if(!IsIconic(hFlt))
+ {
+ fFloat = TRUE;
+ nSide++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+ case CALLS_WIN:
+ if ((hCalls = GetCallsHWND()) != (HWND)NULL)
+ {
+ if(!IsIconic(hCalls))
+ {
+ fCalls = TRUE;
+ nSplit++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+ default:
+ return;
+ }
+ }
+ else
+ {
+ d = &Docs[winType]; //Views[indx].Doc
+ winType = d->docType;
+
+
+ switch (winType)
+ {
+ case DOC_WIN:
+ if (Views[indx].hwndClient ) {
+ if ( !IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ fDoc = TRUE;
+ numdocs++;
+
+ if (numdocs == 1)
+ {
+ nVsplit++;
+ }
+
+ } else {
+ fIcon = TRUE;
+ }
+ }
+
+ break;
+
+ case DISASM_WIN:
+ if (Views[indx].hwndClient ) {
+ if ( !IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ fDisasm = TRUE;
+ nVsplit++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+ case COMMAND_WIN:
+ if (Views[indx].hwndClient ) {
+ if ( !IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ fCommand = TRUE;
+ nVsplit++;
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+ case MEMORY_WIN:
+ if (Views[indx].hwndClient ) {
+ if ( !IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ fMem = TRUE;
+ nummems++;
+
+ if (nummems == 1)
+ {
+ nVsplit++;
+ }
+ } else {
+ fIcon = TRUE;
+ }
+ }
+ break;
+
+
+ default:
+ return;
+ }
+
+ }
+
+ }
+
+
+ //Now we have a count of all multiple wins and an exist on special cases
+ //First get the Client extents
+
+
+ GetClientRect (hwndMDIClient, &rc);
+
+ //
+ // If icons present, don't cover them
+ //
+ if ( fIcon ) {
+ rc.bottom -= GetSystemMetrics( SM_CYICONSPACING );
+ }
+
+ CopyRect (&rCm,&rc); // make a copy for cumulatives
+
+
+ //special cases first
+
+
+ if (nSide > 0) {
+//
+// We will shrink the side windows (reg, float) to the minimum size
+// allowed and put them in the upper left corner of the MDIClient's
+// client area (have I got this 'client' usage right?). Next, we
+// expand them to fit the register set of the target machine, but we
+// presently allow only two choices: 32-bit and 64-bit. (Actually, we
+// allow only ALPHA and anything else as the two choices, eh?) Our scaling
+// factor is 1.5 for the smaller size, and something larger that gives
+// a good appearance for the other size. Caveat emptor et programmer!
+//
+
+ UINT processor;
+
+ float scaleFactor;
+
+ if (!LppdCur) {
+ processor = mptix86;
+ } else {
+ OSDGetDebugMetric(LppdCur->hpid, 0, mtrcProcessorType, &processor);
+ }
+
+ switch (processor) {
+ default:
+ case mptix86:
+ case mptmips:
+ case mptm68k:
+ case mptmppc:
+ scaleFactor = 1.5f;
+ break;
+
+ case mptdaxp:
+ scaleFactor = 3.0f;
+ break;
+ }
+
+ if (fCpu && ((hCpu = GetCpuHWND()) != (HWND)NULL)) {
+ if(!IsIconic(hCpu)) {
+ MoveWindow (hCpu,rc.left,rc.top,1,1,FALSE); //get minimum size, don't
+ //redraw yet
+ GetWindowRect (hCpu,&rcc);
+ ScreenToClient (hwndMDIClient,(LPPOINT)&rcc.left);
+ ScreenToClient (hwndMDIClient,(LPPOINT)&rcc.right);
+
+ rcc.right = ((LONG)((rcc.right - rcc.left) * scaleFactor)
+ + rcc.left);
+
+ SetWindowPos (hCpu,
+ (HWND)NULL,
+ (rc.right - (rcc.right - rcc.left)),
+ rc.top,(rcc.right - rcc.left),
+ (nSide == 2) ? ((rc.bottom - rc.top) / 2) : (rc.bottom - rc.top),
+ SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (hCpu,(LPRECT)NULL,TRUE);
+ PostMessage (hCpu,WM_PAINT,0,0L);
+
+ }
+ }
+
+
+ if (fFloat && ((hFlt = GetFloatHWND()) != (HWND)NULL))
+ {
+ if(!IsIconic(hFlt))
+ {
+ MoveWindow (hFlt,rc.left,rc.top,1,1,FALSE);
+
+ GetWindowRect (hFlt,&rcc);
+ ScreenToClient (hwndMDIClient,(LPPOINT)&rcc.left);
+ ScreenToClient (hwndMDIClient,(LPPOINT)&rcc.right);
+
+ rcc.right = ((LONG)((rcc.right - rcc.left) * scaleFactor)
+ + rcc.left);
+
+ SetWindowPos (hFlt,
+ (HWND)NULL,
+ (rc.right - (rcc.right - rcc.left)),
+ (nSide == 2)?(rc.top + ((rc.bottom - rc.top) / 2)):rc.top,
+ (rcc.right - rcc.left),
+ (nSide == 2) ? ((rc.bottom - rc.top) / 2) : (rc.bottom - rc.top),
+ SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (hFlt,(LPRECT)NULL,TRUE);
+ PostMessage (hFlt,WM_PAINT,0,0L);
+ }
+
+ }
+
+ rCm.right -= (rcc.right - rcc.left); // shrink horizontal cumulative
+ }
+
+
+
+ CopyRect (&rc,&rCm); // copy back for cumulatives
+
+
+ //Figure vertical delta
+
+ if ((fLocal == TRUE) || (fWatch == TRUE) || (fCalls == TRUE))
+ {
+ nVsplit++;
+ }
+
+ if (nVsplit > 0)
+ {
+ nVdelta = (rc.bottom - rc.top) / nVsplit;
+ }
+
+
+ if (nSplit > 0)
+ {
+ int currHorizPos = rc.left;
+
+ //Figure horizontal delta
+ nHdelta = (rc.right - rc.left) / nSplit;
+
+ if (fLocal && ((hLoc = GetLocalHWND()) != (HWND)NULL))
+ {
+ if(!IsIconic(hLoc))
+ {
+ SetWindowPos (hLoc,
+ (HWND)NULL,
+ currHorizPos,
+ rc.top,
+ nHdelta,
+ nVdelta,
+ SWP_NOZORDER|SWP_DRAWFRAME);
+ currHorizPos += nHdelta;
+ InvalidateRect (hLoc,(LPRECT)NULL,TRUE);
+ PostMessage (hLoc,WM_PAINT,0,0L);
+ }
+ }
+
+ if (fWatch && ((hWtch = GetWatchHWND()) != (HWND)NULL))
+ {
+ if(!IsIconic(hWtch))
+ {
+ SetWindowPos (hWtch,
+ (HWND)NULL,
+ currHorizPos,
+ rc.top,
+ nHdelta,
+ nVdelta,
+ SWP_NOZORDER|SWP_DRAWFRAME);
+ currHorizPos += nHdelta;
+ InvalidateRect (hWtch,(LPRECT)NULL,TRUE);
+ PostMessage (hWtch,WM_PAINT,0,0L);
+ }
+ }
+
+ if (fCalls && ((hCalls = GetCallsHWND()) != (HWND)NULL))
+ {
+ if(!IsIconic(hCalls))
+ {
+ SetWindowPos (hCalls,
+ (HWND)NULL,
+ currHorizPos,
+ rc.top,
+ nHdelta,
+ nVdelta,
+ SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (hCalls,(LPRECT)NULL,TRUE);
+ PostMessage (hCalls,WM_PAINT,0,0L);
+ }
+ }
+
+ rCm.top += nVdelta; // shrink vertical cumulative
+ }
+
+
+ if ((fLocal == TRUE) || (fWatch == TRUE) || (fCalls == TRUE))
+ {
+ nVsplit--;
+ }
+
+
+ CopyRect (&rc,&rCm); // copy back for cumulatives
+
+
+ if (nVsplit > 0) // do the main windows
+ {
+
+ CopyRect (&rDoc,&rc);
+ CopyRect (&rDisasm,&rc);
+ CopyRect (&rComm,&rc);
+ CopyRect (&rMem,&rc);
+
+
+ if (fDoc == TRUE) //Handle Document Windows
+ {
+ switch ((nVsplit))
+ {
+ case 1:
+ break;
+
+ case 2:
+ if (fCommand == FALSE) // can only be one other window
+ {
+ rDisasm.top = rc.top + ((rc.bottom - rc.top) / 2);
+ rMem.top = rc.top + ((rc.bottom - rc.top) / 2);
+ }
+ rDoc.bottom = rc.top + ((rc.bottom - rc.top) / 2);
+ break;
+
+ case 3:
+ if (fCommand == FALSE) // must be disasm amd mem
+ {
+ rDisasm.bottom = rc.top + ((rc.bottom - rc.top) / 3);
+ rMem.top = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ }
+ else // set disasm amd mem to middle
+ {
+ rDisasm.top = rc.top + ((rc.bottom - rc.top) / 3);
+ rDisasm.bottom = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ rMem.top = rc.top + ((rc.bottom - rc.top) / 3);
+ rMem.bottom = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ }
+ rDoc.bottom = rc.top + ((rc.bottom - rc.top) / 3);
+ break;
+
+ case 4:
+ rDisasm.top = rc.top + ((rc.bottom - rc.top) / 4);
+ rDisasm.bottom = rc.top + (((rc.bottom - rc.top) / 4) * 2);
+ rMem.top = rc.top + (((rc.bottom - rc.top) / 4) * 2);
+ rMem.bottom = rc.top + (((rc.bottom - rc.top) / 4) * 3);
+ rDoc.bottom = rc.top + ((rc.bottom - rc.top) / 4);
+ break;
+
+ default:
+ return;
+ }
+ }
+
+
+ if (fCommand == TRUE) // handle command window
+ {
+ switch ((nVsplit))
+ {
+ case 1:
+ break;
+
+ case 2:
+ if (fDoc == FALSE) // can only be one other window
+ {
+ rDisasm.bottom = rc.top + ((rc.bottom - rc.top) / 2);
+ rMem.bottom = rc.top + ((rc.bottom - rc.top) / 2);
+ }
+ rComm.top = rc.top + ((rc.bottom - rc.top) / 2);
+ break;
+
+ case 3:
+ if (fDoc == FALSE) // must be disasm amd mem
+ {
+ rDisasm.bottom = rc.top + ((rc.bottom - rc.top) / 3);
+ rMem.top = rc.top + ((rc.bottom - rc.top) / 3);
+ rMem.bottom = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ }
+ else // set disasm amd mem to middle
+ {
+ rDisasm.top = rc.top + ((rc.bottom - rc.top) / 3);
+ rDisasm.bottom = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ rMem.top = rc.top + ((rc.bottom - rc.top) / 3);
+ rMem.bottom = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ }
+
+ rComm.top = rc.top + (((rc.bottom - rc.top) / 3) * 2);
+ break;
+
+ case 4:
+ rDisasm.top = rc.top + ((rc.bottom - rc.top) / 4);
+ rDisasm.bottom = rc.top + (((rc.bottom - rc.top) / 4) * 2);
+ rMem.top = rc.top + (((rc.bottom - rc.top) / 4) * 2);
+ rMem.bottom = rc.top + (((rc.bottom - rc.top) / 4) * 3);
+ rComm.top = rc.top + (((rc.bottom - rc.top) / 4) * 3);
+ break;
+
+ default:
+ return;
+ }
+ }
+
+
+
+ if ((fDoc == FALSE) && (fCommand == FALSE))
+ {
+ if ((fDisasm == TRUE) && (fMem == TRUE))
+ {
+ rDisasm.bottom = rc.top + ((rc.bottom - rc.top) / 2);
+ rMem.top = rc.top + ((rc.bottom - rc.top) / 2);
+ }
+ }
+
+ nHdelta = (rc.right - rc.left); // refigure horizontal size
+
+ for (indx = 0; indx < MAX_VIEWS; indx++)
+ {
+ winType = Views[indx].Doc; //window type
+
+ if (winType <= -1) // only DOCS,DISASMS,COMMAND,MEMWINS
+ {
+ continue; // end of valid views or sparse array
+ }
+ else
+ {
+ d = &Docs[winType]; //Views[indx].Doc
+ winType = d->docType;
+
+ switch (winType)
+ {
+ case DOC_WIN:
+ if (!IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ SetWindowPos (GetParent(Views[indx].hwndClient),(HWND)NULL,rDoc.left,rDoc.top,(rDoc.right - rDoc.left),(rDoc.bottom - rDoc.top),SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (GetParent(Views[indx].hwndClient),(LPRECT)NULL,TRUE);
+ PostMessage (GetParent(Views[indx].hwndClient),WM_PAINT,0,0L);
+ }
+
+ break;
+
+ case DISASM_WIN:
+ if (!IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ SetWindowPos (GetParent(Views[indx].hwndClient),(HWND)NULL,rDisasm.left,rDisasm.top,(rDisasm.right - rDisasm.left),(rDisasm.bottom - rDisasm.top),SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (GetParent(Views[indx].hwndClient),(LPRECT)NULL,TRUE);
+ PostMessage (GetParent(Views[indx].hwndClient),WM_PAINT,0,0L);
+ }
+
+ break;
+
+ case COMMAND_WIN:
+ if (!IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ SetWindowPos (GetParent(Views[indx].hwndClient),(HWND)NULL,rComm.left,rComm.top,(rComm.right - rComm.left),(rComm.bottom - rComm.top),SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (GetParent(Views[indx].hwndClient),(LPRECT)NULL,TRUE);
+ PostMessage (GetParent(Views[indx].hwndClient),WM_PAINT,0,0L);
+ }
+ break;
+
+ case MEMORY_WIN:
+ if (!IsIconic(GetParent(Views[indx].hwndClient)))
+ {
+ SetWindowPos (GetParent(Views[indx].hwndClient),(HWND)NULL,rMem.left,rMem.top,(rMem.right - rMem.left),(rMem.bottom - rMem.top),SWP_NOZORDER|SWP_DRAWFRAME);
+ InvalidateRect (GetParent(Views[indx].hwndClient),(LPRECT)NULL,TRUE);
+ PostMessage (GetParent(Views[indx].hwndClient),WM_PAINT,0,0L);
+ }
+ break;
+ }
+
+ }
+
+ }
+
+ }
+
+ InvalidateRect (hwndMDIClient,(LPRECT)NULL,TRUE);
+ PostMessage (hwndMDIClient,WM_PAINT,0,0L);
+
+}
+
+
+/*==========================================================================*/
diff --git a/private/windbg/windbg/bitmaps/asm-da.bmp b/private/windbg/windbg/bitmaps/asm-da.bmp
new file mode 100644
index 000000000..830f1d686
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asm-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asm-dda.bmp b/private/windbg/windbg/bitmaps/asm-dda.bmp
new file mode 100644
index 000000000..67329f3ba
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asm-dda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asm-dn.bmp b/private/windbg/windbg/bitmaps/asm-dn.bmp
new file mode 100644
index 000000000..9bb17c88d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asm-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asm-up.bmp b/private/windbg/windbg/bitmaps/asm-up.bmp
new file mode 100644
index 000000000..8b36c39da
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asm-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asm.ico b/private/windbg/windbg/bitmaps/asm.ico
new file mode 100644
index 000000000..7dd7b6742
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asm.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asmda.bmp b/private/windbg/windbg/bitmaps/asmda.bmp
new file mode 100644
index 000000000..075a93d54
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asmda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asmdn.bmp b/private/windbg/windbg/bitmaps/asmdn.bmp
new file mode 100644
index 000000000..477533152
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asmdn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/asmup.bmp b/private/windbg/windbg/bitmaps/asmup.bmp
new file mode 100644
index 000000000..e52cf6b95
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/asmup.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosg.bcg b/private/windbg/windbg/bitmaps/atosg.bcg
new file mode 100644
index 000000000..704bb0aa6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosg.beg b/private/windbg/windbg/bitmaps/atosg.beg
new file mode 100644
index 000000000..a1aeaa2e4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosg.bvg b/private/windbg/windbg/bitmaps/atosg.bvg
new file mode 100644
index 000000000..51f4fe96a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosg.bvm b/private/windbg/windbg/bitmaps/atosg.bvm
new file mode 100644
index 000000000..80990b355
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosn.bcg b/private/windbg/windbg/bitmaps/atosn.bcg
new file mode 100644
index 000000000..704bb0aa6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosn.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosn.beg b/private/windbg/windbg/bitmaps/atosn.beg
new file mode 100644
index 000000000..a1aeaa2e4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosn.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosn.bvg b/private/windbg/windbg/bitmaps/atosn.bvg
new file mode 100644
index 000000000..8d442f26e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosn.bvm b/private/windbg/windbg/bitmaps/atosn.bvm
new file mode 100644
index 000000000..80990b355
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosn.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosp.bcg b/private/windbg/windbg/bitmaps/atosp.bcg
new file mode 100644
index 000000000..704bb0aa6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosp.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosp.beg b/private/windbg/windbg/bitmaps/atosp.beg
new file mode 100644
index 000000000..a1aeaa2e4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosp.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosp.bvg b/private/windbg/windbg/bitmaps/atosp.bvg
new file mode 100644
index 000000000..45959d7a2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/atosp.bvm b/private/windbg/windbg/bitmaps/atosp.bvm
new file mode 100644
index 000000000..80990b355
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/atosp.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/blank.bvg b/private/windbg/windbg/bitmaps/blank.bvg
new file mode 100644
index 000000000..0f0ba8a9c
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/blank.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakg.bcg b/private/windbg/windbg/bitmaps/breakg.bcg
new file mode 100644
index 000000000..d74dc9d1a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakg.beg b/private/windbg/windbg/bitmaps/breakg.beg
new file mode 100644
index 000000000..7149e1a8a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakg.bvg b/private/windbg/windbg/bitmaps/breakg.bvg
new file mode 100644
index 000000000..700f3661e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakg.bvm b/private/windbg/windbg/bitmaps/breakg.bvm
new file mode 100644
index 000000000..31d057fa6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakn.bcg b/private/windbg/windbg/bitmaps/breakn.bcg
new file mode 100644
index 000000000..d74dc9d1a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakn.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakn.beg b/private/windbg/windbg/bitmaps/breakn.beg
new file mode 100644
index 000000000..7149e1a8a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakn.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakn.bvg b/private/windbg/windbg/bitmaps/breakn.bvg
new file mode 100644
index 000000000..7bbbb6169
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakn.bvm b/private/windbg/windbg/bitmaps/breakn.bvm
new file mode 100644
index 000000000..31d057fa6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakn.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakp.bcg b/private/windbg/windbg/bitmaps/breakp.bcg
new file mode 100644
index 000000000..d74dc9d1a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakp.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakp.beg b/private/windbg/windbg/bitmaps/breakp.beg
new file mode 100644
index 000000000..7149e1a8a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakp.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakp.bvg b/private/windbg/windbg/bitmaps/breakp.bvg
new file mode 100644
index 000000000..2140ba299
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/breakp.bvm b/private/windbg/windbg/bitmaps/breakp.bvm
new file mode 100644
index 000000000..31d057fa6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/breakp.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/brkpt-da.bmp b/private/windbg/windbg/bitmaps/brkpt-da.bmp
new file mode 100644
index 000000000..b98f89bfd
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/brkpt-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/brkpt-dn.bmp b/private/windbg/windbg/bitmaps/brkpt-dn.bmp
new file mode 100644
index 000000000..749539db6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/brkpt-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/brkpt-up.bmp b/private/windbg/windbg/bitmaps/brkpt-up.bmp
new file mode 100644
index 000000000..d6f516f71
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/brkpt-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildg.bcg b/private/windbg/windbg/bitmaps/buildg.bcg
new file mode 100644
index 000000000..c3f62f0a0
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildg.beg b/private/windbg/windbg/bitmaps/buildg.beg
new file mode 100644
index 000000000..4dfd30b8b
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildg.bvg b/private/windbg/windbg/bitmaps/buildg.bvg
new file mode 100644
index 000000000..024021450
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildg.bvm b/private/windbg/windbg/bitmaps/buildg.bvm
new file mode 100644
index 000000000..e8210c5a5
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildn.bcg b/private/windbg/windbg/bitmaps/buildn.bcg
new file mode 100644
index 000000000..c3f62f0a0
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildn.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildn.beg b/private/windbg/windbg/bitmaps/buildn.beg
new file mode 100644
index 000000000..4dfd30b8b
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildn.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildn.bvg b/private/windbg/windbg/bitmaps/buildn.bvg
new file mode 100644
index 000000000..3ffa81bab
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildn.bvm b/private/windbg/windbg/bitmaps/buildn.bvm
new file mode 100644
index 000000000..e8210c5a5
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildn.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildp.bcg b/private/windbg/windbg/bitmaps/buildp.bcg
new file mode 100644
index 000000000..c3f62f0a0
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildp.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildp.beg b/private/windbg/windbg/bitmaps/buildp.beg
new file mode 100644
index 000000000..4dfd30b8b
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildp.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildp.bvg b/private/windbg/windbg/bitmaps/buildp.bvg
new file mode 100644
index 000000000..afba6e0be
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/buildp.bvm b/private/windbg/windbg/bitmaps/buildp.bvm
new file mode 100644
index 000000000..9727d2548
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/buildp.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/clflder.bmp b/private/windbg/windbg/bitmaps/clflder.bmp
new file mode 100644
index 000000000..9858c8702
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/clflder.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compg.bcg b/private/windbg/windbg/bitmaps/compg.bcg
new file mode 100644
index 000000000..964617420
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compg.beg b/private/windbg/windbg/bitmaps/compg.beg
new file mode 100644
index 000000000..7e427ac49
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compg.bvg b/private/windbg/windbg/bitmaps/compg.bvg
new file mode 100644
index 000000000..ca3f6dc68
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compg.bvm b/private/windbg/windbg/bitmaps/compg.bvm
new file mode 100644
index 000000000..22f92a137
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compn.bcg b/private/windbg/windbg/bitmaps/compn.bcg
new file mode 100644
index 000000000..964617420
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compn.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compn.beg b/private/windbg/windbg/bitmaps/compn.beg
new file mode 100644
index 000000000..7e427ac49
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compn.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compn.bvg b/private/windbg/windbg/bitmaps/compn.bvg
new file mode 100644
index 000000000..31bc19831
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compn.bvm b/private/windbg/windbg/bitmaps/compn.bvm
new file mode 100644
index 000000000..22f92a137
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compn.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compp.bcg b/private/windbg/windbg/bitmaps/compp.bcg
new file mode 100644
index 000000000..964617420
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compp.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compp.beg b/private/windbg/windbg/bitmaps/compp.beg
new file mode 100644
index 000000000..7e427ac49
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compp.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compp.bvg b/private/windbg/windbg/bitmaps/compp.bvg
new file mode 100644
index 000000000..246b4e9b2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/compp.bvm b/private/windbg/windbg/bitmaps/compp.bvm
new file mode 100644
index 000000000..22f92a137
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/compp.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/cpuwin.ico b/private/windbg/windbg/bitmaps/cpuwin.ico
new file mode 100644
index 000000000..df9b69761
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/cpuwin.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/cpuwin2.ico b/private/windbg/windbg/bitmaps/cpuwin2.ico
new file mode 100644
index 000000000..ddc13d454
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/cpuwin2.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/curflder.bmp b/private/windbg/windbg/bitmaps/curflder.bmp
new file mode 100644
index 000000000..dd0919bff
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/curflder.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/document.ico b/private/windbg/windbg/bitmaps/document.ico
new file mode 100644
index 000000000..50d76f25b
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/document.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/fmt.bvg b/private/windbg/windbg/bitmaps/fmt.bvg
new file mode 100644
index 000000000..ae4248edf
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/fmt.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/formatg.bvg b/private/windbg/windbg/bitmaps/formatg.bvg
new file mode 100644
index 000000000..da5cc357d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/formatg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/formatn.bvg b/private/windbg/windbg/bitmaps/formatn.bvg
new file mode 100644
index 000000000..ca4a57081
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/formatn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/formatp.bvg b/private/windbg/windbg/bitmaps/formatp.bvg
new file mode 100644
index 000000000..df13be186
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/formatp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/gog.bvg b/private/windbg/windbg/bitmaps/gog.bvg
new file mode 100644
index 000000000..3268de154
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/gog.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/gon.bvg b/private/windbg/windbg/bitmaps/gon.bvg
new file mode 100644
index 000000000..d2d4d460a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/gon.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/gop.bvg b/private/windbg/windbg/bitmaps/gop.bvg
new file mode 100644
index 000000000..e6b2db1c9
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/gop.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/help.cur b/private/windbg/windbg/bitmaps/help.cur
new file mode 100644
index 000000000..80b03e08f
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/help.cur
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/localwin.ico b/private/windbg/windbg/bitmaps/localwin.ico
new file mode 100644
index 000000000..5cd6d22bc
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/localwin.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/memory.ico b/private/windbg/windbg/bitmaps/memory.ico
new file mode 100644
index 000000000..ddc13d454
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/memory.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/minus.bmp b/private/windbg/windbg/bitmaps/minus.bmp
new file mode 100644
index 000000000..b94c9c8d8
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/minus.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/minus.bvg b/private/windbg/windbg/bitmaps/minus.bvg
new file mode 100644
index 000000000..9656852e6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/minus.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/opflder.bmp b/private/windbg/windbg/bitmaps/opflder.bmp
new file mode 100644
index 000000000..b1055488d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/opflder.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/opt-da.bmp b/private/windbg/windbg/bitmaps/opt-da.bmp
new file mode 100644
index 000000000..4f0c462bd
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/opt-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/opt-dn.bmp b/private/windbg/windbg/bitmaps/opt-dn.bmp
new file mode 100644
index 000000000..b1e9ea87c
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/opt-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/opt-up.bmp b/private/windbg/windbg/bitmaps/opt-up.bmp
new file mode 100644
index 000000000..c5df43eba
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/opt-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/optg.bvg b/private/windbg/windbg/bitmaps/optg.bvg
new file mode 100644
index 000000000..583b101e2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/optg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/optn.bvg b/private/windbg/windbg/bitmaps/optn.bvg
new file mode 100644
index 000000000..6b0e61080
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/optn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/optp.bvg b/private/windbg/windbg/bitmaps/optp.bvg
new file mode 100644
index 000000000..a08655cf7
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/optp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/plus.bmp b/private/windbg/windbg/bitmaps/plus.bmp
new file mode 100644
index 000000000..39d66095c
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/plus.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/plus.bvg b/private/windbg/windbg/bitmaps/plus.bvg
new file mode 100644
index 000000000..a1ccaa930
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/plus.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/plusmin.bmp b/private/windbg/windbg/bitmaps/plusmin.bmp
new file mode 100644
index 000000000..38b2ced02
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/plusmin.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcerr.ico b/private/windbg/windbg/bitmaps/qcerr.ico
new file mode 100644
index 000000000..ced8a4d3e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcerr.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcerror.ico b/private/windbg/windbg/bitmaps/qcerror.ico
new file mode 100644
index 000000000..22bbe635f
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcerror.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcfloat.ico b/private/windbg/windbg/bitmaps/qcfloat.ico
new file mode 100644
index 000000000..4a50c7351
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcfloat.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qclocal.ico b/private/windbg/windbg/bitmaps/qclocal.ico
new file mode 100644
index 000000000..fc81fbc74
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qclocal.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcmem.ico b/private/windbg/windbg/bitmaps/qcmem.ico
new file mode 100644
index 000000000..56a124702
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcmem.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcprod.ico b/private/windbg/windbg/bitmaps/qcprod.ico
new file mode 100644
index 000000000..3d3831bbe
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcprod.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp.ico b/private/windbg/windbg/bitmaps/qcqp.ico
new file mode 100644
index 000000000..020a7f67d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp1.ico b/private/windbg/windbg/bitmaps/qcqp1.ico
new file mode 100644
index 000000000..4f72caf68
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp1.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp2.ico b/private/windbg/windbg/bitmaps/qcqp2.ico
new file mode 100644
index 000000000..f7ac26915
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp2.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp3.ico b/private/windbg/windbg/bitmaps/qcqp3.ico
new file mode 100644
index 000000000..aa437bf9a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp3.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp4.ico b/private/windbg/windbg/bitmaps/qcqp4.ico
new file mode 100644
index 000000000..0fe74f3fb
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp4.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp5.ico b/private/windbg/windbg/bitmaps/qcqp5.ico
new file mode 100644
index 000000000..cf012e276
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp5.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp6.ico b/private/windbg/windbg/bitmaps/qcqp6.ico
new file mode 100644
index 000000000..e89f425f2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp6.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp7.ico b/private/windbg/windbg/bitmaps/qcqp7.ico
new file mode 100644
index 000000000..eb6865f98
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp7.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcqp8.ico b/private/windbg/windbg/bitmaps/qcqp8.ico
new file mode 100644
index 000000000..6e25c2b19
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcqp8.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcreg.ico b/private/windbg/windbg/bitmaps/qcreg.ico
new file mode 100644
index 000000000..cc526f805
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcreg.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcsource.ico b/private/windbg/windbg/bitmaps/qcsource.ico
new file mode 100644
index 000000000..562627b15
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcsource.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qcwatch.ico b/private/windbg/windbg/bitmaps/qcwatch.ico
new file mode 100644
index 000000000..b75c3b4fd
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qcwatch.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/quickc.ico b/private/windbg/windbg/bitmaps/quickc.ico
new file mode 100644
index 000000000..1bb367eed
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/quickc.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/quickc2.ico b/private/windbg/windbg/bitmaps/quickc2.ico
new file mode 100644
index 000000000..660a2abd1
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/quickc2.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchg.bcg b/private/windbg/windbg/bitmaps/qwatchg.bcg
new file mode 100644
index 000000000..eeb4056a6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchg.beg b/private/windbg/windbg/bitmaps/qwatchg.beg
new file mode 100644
index 000000000..b8fc3b28e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchg.bvg b/private/windbg/windbg/bitmaps/qwatchg.bvg
new file mode 100644
index 000000000..f3273f90d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchg.bvm b/private/windbg/windbg/bitmaps/qwatchg.bvm
new file mode 100644
index 000000000..34f5e4042
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchn.bcg b/private/windbg/windbg/bitmaps/qwatchn.bcg
new file mode 100644
index 000000000..eeb4056a6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchn.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchn.beg b/private/windbg/windbg/bitmaps/qwatchn.beg
new file mode 100644
index 000000000..b8fc3b28e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchn.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchn.bvg b/private/windbg/windbg/bitmaps/qwatchn.bvg
new file mode 100644
index 000000000..231145834
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchn.bvm b/private/windbg/windbg/bitmaps/qwatchn.bvm
new file mode 100644
index 000000000..34f5e4042
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchn.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchp.bcg b/private/windbg/windbg/bitmaps/qwatchp.bcg
new file mode 100644
index 000000000..eeb4056a6
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchp.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchp.beg b/private/windbg/windbg/bitmaps/qwatchp.beg
new file mode 100644
index 000000000..b8fc3b28e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchp.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchp.bvg b/private/windbg/windbg/bitmaps/qwatchp.bvg
new file mode 100644
index 000000000..5c62389f7
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/qwatchp.bvm b/private/windbg/windbg/bitmaps/qwatchp.bvm
new file mode 100644
index 000000000..34f5e4042
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/qwatchp.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/retrn-da.bmp b/private/windbg/windbg/bitmaps/retrn-da.bmp
new file mode 100644
index 000000000..df07b7289
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/retrn-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/retrn-dn.bmp b/private/windbg/windbg/bitmaps/retrn-dn.bmp
new file mode 100644
index 000000000..62a883eec
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/retrn-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/retrn-up.bmp b/private/windbg/windbg/bitmaps/retrn-up.bmp
new file mode 100644
index 000000000..b3fe68c21
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/retrn-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/run-da.bmp b/private/windbg/windbg/bitmaps/run-da.bmp
new file mode 100644
index 000000000..044307e62
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/run-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/run-dda.bmp b/private/windbg/windbg/bitmaps/run-dda.bmp
new file mode 100644
index 000000000..d23f5f494
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/run-dda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/run-dn.bmp b/private/windbg/windbg/bitmaps/run-dn.bmp
new file mode 100644
index 000000000..ae42b88fc
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/run-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/run-up.bmp b/private/windbg/windbg/bitmaps/run-up.bmp
new file mode 100644
index 000000000..4eddd3398
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/run-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/runda.bmp b/private/windbg/windbg/bitmaps/runda.bmp
new file mode 100644
index 000000000..67ca08f16
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/runda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/rundn.bmp b/private/windbg/windbg/bitmaps/rundn.bmp
new file mode 100644
index 000000000..b0937aab5
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/rundn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/runup.bmp b/private/windbg/windbg/bitmaps/runup.bmp
new file mode 100644
index 000000000..2702ce555
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/runup.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/source.ico b/private/windbg/windbg/bitmaps/source.ico
new file mode 100644
index 000000000..97cd9032b
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/source.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/src-da.bmp b/private/windbg/windbg/bitmaps/src-da.bmp
new file mode 100644
index 000000000..a3aa8b0a8
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/src-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/src-dda.bmp b/private/windbg/windbg/bitmaps/src-dda.bmp
new file mode 100644
index 000000000..6ed7754c0
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/src-dda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/src-dn.bmp b/private/windbg/windbg/bitmaps/src-dn.bmp
new file mode 100644
index 000000000..c0bff77fb
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/src-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/src-up.bmp b/private/windbg/windbg/bitmaps/src-up.bmp
new file mode 100644
index 000000000..ad960dcb5
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/src-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/step-da.bmp b/private/windbg/windbg/bitmaps/step-da.bmp
new file mode 100644
index 000000000..d5a02f57e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/step-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/step-dn.bmp b/private/windbg/windbg/bitmaps/step-dn.bmp
new file mode 100644
index 000000000..0bc03f319
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/step-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/step-up.bmp b/private/windbg/windbg/bitmaps/step-up.bmp
new file mode 100644
index 000000000..1716f9c6a
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/step-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepg.bcg b/private/windbg/windbg/bitmaps/stepg.bcg
new file mode 100644
index 000000000..f0f9727c3
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepg.beg b/private/windbg/windbg/bitmaps/stepg.beg
new file mode 100644
index 000000000..e3673dfa4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepg.bvg b/private/windbg/windbg/bitmaps/stepg.bvg
new file mode 100644
index 000000000..10990a5b2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepg.bvm b/private/windbg/windbg/bitmaps/stepg.bvm
new file mode 100644
index 000000000..f2f6376ee
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepn.bcg b/private/windbg/windbg/bitmaps/stepn.bcg
new file mode 100644
index 000000000..f0f9727c3
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepn.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepn.beg b/private/windbg/windbg/bitmaps/stepn.beg
new file mode 100644
index 000000000..e3673dfa4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepn.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepn.bvg b/private/windbg/windbg/bitmaps/stepn.bvg
new file mode 100644
index 000000000..c44a8dba9
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepn.bvm b/private/windbg/windbg/bitmaps/stepn.bvm
new file mode 100644
index 000000000..f2f6376ee
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepn.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepp.bcg b/private/windbg/windbg/bitmaps/stepp.bcg
new file mode 100644
index 000000000..f0f9727c3
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepp.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepp.beg b/private/windbg/windbg/bitmaps/stepp.beg
new file mode 100644
index 000000000..e3673dfa4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepp.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepp.bvg b/private/windbg/windbg/bitmaps/stepp.bvg
new file mode 100644
index 000000000..5e8f40238
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stepp.bvm b/private/windbg/windbg/bitmaps/stepp.bvm
new file mode 100644
index 000000000..f2f6376ee
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stepp.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stop-da.bmp b/private/windbg/windbg/bitmaps/stop-da.bmp
new file mode 100644
index 000000000..da9797e9d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stop-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stop-dda.bmp b/private/windbg/windbg/bitmaps/stop-dda.bmp
new file mode 100644
index 000000000..1fb090e4c
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stop-dda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stop-dn.bmp b/private/windbg/windbg/bitmaps/stop-dn.bmp
new file mode 100644
index 000000000..fc7286694
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stop-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stop-up.bmp b/private/windbg/windbg/bitmaps/stop-up.bmp
new file mode 100644
index 000000000..8c76322f3
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stop-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stopg.bvg b/private/windbg/windbg/bitmaps/stopg.bvg
new file mode 100644
index 000000000..72b711601
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stopg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stopn.bvg b/private/windbg/windbg/bitmaps/stopn.bvg
new file mode 100644
index 000000000..4751020fa
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stopn.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stopp.bvg b/private/windbg/windbg/bitmaps/stopp.bvg
new file mode 100644
index 000000000..6e2685ea2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stopp.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stpda.bmp b/private/windbg/windbg/bitmaps/stpda.bmp
new file mode 100644
index 000000000..215a42fee
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stpda.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stpdn.bmp b/private/windbg/windbg/bitmaps/stpdn.bmp
new file mode 100644
index 000000000..fd13820d3
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stpdn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/stpup.bmp b/private/windbg/windbg/bitmaps/stpup.bmp
new file mode 100644
index 000000000..3b5dcbdae
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/stpup.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/trace-da.bmp b/private/windbg/windbg/bitmaps/trace-da.bmp
new file mode 100644
index 000000000..f433714bd
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/trace-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/trace-dn.bmp b/private/windbg/windbg/bitmaps/trace-dn.bmp
new file mode 100644
index 000000000..4c7715213
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/trace-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/trace-up.bmp b/private/windbg/windbg/bitmaps/trace-up.bmp
new file mode 100644
index 000000000..6b3ad1704
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/trace-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/traceg.bcg b/private/windbg/windbg/bitmaps/traceg.bcg
new file mode 100644
index 000000000..b6368f9f2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/traceg.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/traceg.beg b/private/windbg/windbg/bitmaps/traceg.beg
new file mode 100644
index 000000000..f29927a21
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/traceg.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/traceg.bvg b/private/windbg/windbg/bitmaps/traceg.bvg
new file mode 100644
index 000000000..9f8707369
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/traceg.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/traceg.bvm b/private/windbg/windbg/bitmaps/traceg.bvm
new file mode 100644
index 000000000..347d5822d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/traceg.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracen.bcg b/private/windbg/windbg/bitmaps/tracen.bcg
new file mode 100644
index 000000000..b6368f9f2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracen.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracen.beg b/private/windbg/windbg/bitmaps/tracen.beg
new file mode 100644
index 000000000..f29927a21
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracen.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracen.bvg b/private/windbg/windbg/bitmaps/tracen.bvg
new file mode 100644
index 000000000..5d3d45ed5
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracen.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracen.bvm b/private/windbg/windbg/bitmaps/tracen.bvm
new file mode 100644
index 000000000..347d5822d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracen.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracep.bcg b/private/windbg/windbg/bitmaps/tracep.bcg
new file mode 100644
index 000000000..b6368f9f2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracep.bcg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracep.beg b/private/windbg/windbg/bitmaps/tracep.beg
new file mode 100644
index 000000000..f29927a21
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracep.beg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracep.bvg b/private/windbg/windbg/bitmaps/tracep.bvg
new file mode 100644
index 000000000..3108272f1
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracep.bvg
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/tracep.bvm b/private/windbg/windbg/bitmaps/tracep.bvm
new file mode 100644
index 000000000..347d5822d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/tracep.bvm
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/watchwin.ico b/private/windbg/windbg/bitmaps/watchwin.ico
new file mode 100644
index 000000000..abfb89093
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/watchwin.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wfapp.bmp b/private/windbg/windbg/bitmaps/wfapp.bmp
new file mode 100644
index 000000000..4c0cb889e
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wfapp.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wfcdrom.bmp b/private/windbg/windbg/bitmaps/wfcdrom.bmp
new file mode 100644
index 000000000..a05c77bc5
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wfcdrom.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wffile.bmp b/private/windbg/windbg/bitmaps/wffile.bmp
new file mode 100644
index 000000000..5c4c932b0
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wffile.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wffloppy.bmp b/private/windbg/windbg/bitmaps/wffloppy.bmp
new file mode 100644
index 000000000..317d7ab72
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wffloppy.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wfhard.bmp b/private/windbg/windbg/bitmaps/wfhard.bmp
new file mode 100644
index 000000000..1e7a8e72f
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wfhard.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wfnet.bmp b/private/windbg/windbg/bitmaps/wfnet.bmp
new file mode 100644
index 000000000..77e7d5ded
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wfnet.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wfram.bmp b/private/windbg/windbg/bitmaps/wfram.bmp
new file mode 100644
index 000000000..0d45b9ef2
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wfram.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/windbg.ico b/private/windbg/windbg/bitmaps/windbg.ico
new file mode 100644
index 000000000..a88361f08
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/windbg.ico
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wtch-da.bmp b/private/windbg/windbg/bitmaps/wtch-da.bmp
new file mode 100644
index 000000000..cc7db22a4
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wtch-da.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wtch-dn.bmp b/private/windbg/windbg/bitmaps/wtch-dn.bmp
new file mode 100644
index 000000000..160b8949f
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wtch-dn.bmp
Binary files differ
diff --git a/private/windbg/windbg/bitmaps/wtch-up.bmp b/private/windbg/windbg/bitmaps/wtch-up.bmp
new file mode 100644
index 000000000..5a854d03d
--- /dev/null
+++ b/private/windbg/windbg/bitmaps/wtch-up.bmp
Binary files differ
diff --git a/private/windbg/windbg/breakpts.c b/private/windbg/windbg/breakpts.c
new file mode 100644
index 000000000..691e05053
--- /dev/null
+++ b/private/windbg/windbg/breakpts.c
@@ -0,0 +1,834 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ breakpts.c
+
+Abstract:
+
+ This file contains the shell portion of the breakpoint handler (except
+ for the UI portion).
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+extern CXF CxfIp;
+extern EI Ei;
+extern LPSHF Lpshf;
+extern BOOL AutoTest;
+#define Lpei (&Ei)
+
+BOOL
+WINAPI
+DlgBpResolve(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL
+WINAPI
+DlgBpCanIUseThunk(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+LPSTR BpString;
+TML *TmlBpResolve;
+PCXF PcxfBpResolve;
+BPSTATUS RetBpResolve;
+BOOL BpDlgCalled;
+BOOL ResolvingBp;
+BOOL RetCanIUseThunk;
+
+/*** CheckExpression
+**
+** Synopsis:
+** bool = CheckExpression(Expr, Radix, Case)
+**
+** Entry:
+** Expr
+** Radix
+** Case
+**
+** Returns:
+** TRUE if expression parses successfully, FALSE otherwise.
+**
+** Description:
+** Takes an expression in string form and validates
+** it by running it through the EE.
+**
+*/
+
+BOOL
+CheckExpression(
+ LPSTR Expr,
+ int Radix,
+ int Case
+ )
+{
+ HTM hTM = (HTM)NULL;
+ USHORT status;
+ UINT end;
+
+ status = EEParse(Expr, Radix, Case, (PHTM)&hTM, &end);
+ if (hTM)
+ {
+ EEFreeTM (&hTM);
+ }
+
+ return (status == EENOERROR);
+} /* CheckExpression() */
+
+/*** DlgUnresolved
+**
+** Synopsis:
+** bool = DlgUnresolved( hDlg, msg, wParam, lParam)
+**
+** Entry:
+** hDlg - handle to the dialog box
+** msg - message to be processed
+** wParam - info about the message
+** lParam - info about the message
+**
+** Return:
+** TRUE if we handled the message and FALSE otherwise
+**
+** Description:
+** This is the dialog proc for the unresolved breakpoints dialog. It
+** is used to inform the user that the breakpoint was not set for
+** some reason and should have been.
+*/
+
+static HBPT HbptUnresolved;
+
+BOOL FAR PASCAL EXPORT
+DlgUnresolved(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ char rgchT[255];
+ int i;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+ Dbg( BPIFromHbpt(&i, HbptUnresolved) == BPNOERROR );
+ sprintf(rgchT, "Breakpoint #%d", i);
+ SendMessage(GetDlgItem(hDlg, ID_UNRESOLVED_HBPT), WM_SETTEXT, 0,
+ (DWORD)(LPSTR)rgchT);
+ Dbg(BPFormatHbpt(HbptUnresolved, rgchT, sizeof(rgchT), 0) == BPNOERROR);
+ SendMessage(GetDlgItem(hDlg, ID_UNRESOLVED_DESC), WM_SETTEXT, 0,
+ (DWORD)(LPSTR)rgchT);
+ SetFocus(GetDlgItem(hDlg, ID_UNRESOLVED_DEFER));
+ return FALSE;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam ) ) {
+ case ID_UNRESOLVED_DEFER:
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ case ID_UNRESOLVED_CLEAR:
+ Dbg( BPDelete( HbptUnresolved ) == BPNOERROR);
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ case ID_UNRESOLVED_QUIET:
+ BPSetQuiet( HbptUnresolved );
+ EndDialog(hDlg, TRUE);
+ break;
+
+ case ID_UNRESOLVED_DISABLE:
+ Dbg( BPDisable( HbptUnresolved ) == BPNOERROR);
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ case ID_UNRESOLVED_BREAKPOINTS:
+ StartDialog(DLG_BREAKPOINTS, DlgSetBreak);
+ BpDlgCalled = TRUE;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg,szHelpFileName,HELP_CONTEXT,ID_UNRESOLVED_HELP));
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+} /* DlgUnresolved() */
+
+
+
+VOID PASCAL
+BPTResolveAll(
+ HPID hpid,
+ BOOL fSearchAll
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ HBPT hBpt;
+ BPSTATUS bpstat;
+ UINT bpIpid;
+ UINT Ipid = 0;
+ CXF cxf = CxfIp;
+ LPPD lppd;
+ HEXE hexe;
+
+ if ( hpid && (lppd = LppdOfHpid(hpid))) {
+ Ipid = lppd->ipid;
+ }
+
+ BpDlgCalled = TRUE;
+
+ while ( BpDlgCalled ) {
+
+ BpDlgCalled = FALSE;
+
+ hBpt = 0;
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+
+ while (hBpt != NULL) {
+
+ //
+ // If unresolved breakpoint, try to resolve it
+ //
+ if ( !BPIsInstantiated( hBpt ) &&
+ !BPIsDisabled( hBpt ) ) {
+
+ BPGetIpid( hBpt, &bpIpid );
+
+ if ( bpIpid == Ipid ) {
+
+ if ( BPSymbolsMayBeAvailable( hBpt ) ) {
+
+ bpstat = BPBindHbpt( hBpt, &cxf );
+
+ if ( bpstat == BPCancel ) {
+ hBpt = NULL;
+ continue;
+ }
+
+ if (bpstat != BPNOERROR && fSearchAll) {
+ hexe = NULL;
+
+ while (bpstat != BPNOERROR &&
+ (hexe = SHGetNextExe(hexe))) {
+
+ SHWantSymbols( hexe );
+ memset(&cxf, 0, sizeof(cxf));
+ SHGetCxtFromHexe(hexe, &cxf.cxt);
+ bpstat = BPBindHbpt( hBpt, &cxf );
+ }
+ }
+
+ if ( (bpstat != BPNOERROR) &&
+ !BPIsQuiet( hBpt ) &&
+ !AutoTest ) {
+ HbptUnresolved = hBpt;
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+ EnsureFocusDebugger();
+ StartDialog(DLG_UNRESOLVED, DlgUnresolved);
+ if ( BpDlgCalled ) {
+ break;
+ }
+ continue;
+ }
+ }
+ }
+ }
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+ }
+ }
+ ChangeDebuggerState();
+ BPCommit();
+ return;
+} /* BPTResolveAll() */
+
+DWORD PASCAL
+BPTIsUnresolvedCount(
+ HPID hpid
+ )
+{
+ DWORD bpCount = 0;
+ HBPT hBpt;
+ UINT Ipid = 0;
+ CXF cxf = CxfIp;
+ LPPD lppd;
+ BOOL fGotInitialContext = FALSE;
+
+ if ( hpid && (lppd = LppdOfHpid(hpid))) {
+ Ipid = lppd->ipid;
+ }
+
+ BpDlgCalled = TRUE;
+
+ while ( BpDlgCalled ) {
+
+ BpDlgCalled = FALSE;
+
+ hBpt = 0;
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+
+ while (hBpt != NULL) {
+
+ if ( !BPIsInstantiated( hBpt ) &&
+ !BPIsDisabled( hBpt ) ) {
+
+ ++bpCount;
+ }
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+ }
+ }
+
+ return bpCount;
+}
+
+
+
+/*** BPTUnResolve
+**
+** Synopsis:
+** void = BPTUnResolve( hexe )
+**
+** Entry:
+** hexe - module whose breakpoints are beint unresolved
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+*/
+VOID
+BPTUnResolve(
+ HEXE hexe
+ )
+{
+ HBPT hBpt = 0;
+ ADDR Addr;
+
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+
+ //
+ // Unresolve all breakpoints in this module.
+ //
+ while (hBpt != NULL) {
+
+ if ( BPIsInstantiated( hBpt ) ) {
+
+ BPAddrFromHbpt( hBpt, &Addr );
+
+ if ( hexe == (HEXE)emiAddr( Addr ) ) {
+ BPUninstantiate( hBpt );
+ }
+ }
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+ }
+
+ return;
+}
+
+VOID
+BPTUnResolvePidTid(
+ HPID hpid,
+ HTID htid
+ )
+{
+ HBPT hBpt = 0;
+ HPID hPidB;
+ HTID hTidB;
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+
+ //
+ // Unresolve all breakpoints.
+ //
+ while (hBpt != NULL) {
+
+ BPGetHpid(hBpt, &hPidB);
+ BPGetHtid(hBpt, &hTidB);
+
+ if ( (hpid == hPidB) && (htid == hTidB) ) {
+ BPUninstantiate( hBpt );
+ }
+ Dbg(BPNextHbpt(&hBpt, bptNext) == BPNOERROR);
+ }
+
+ return;
+}
+
+
+/*** BPTUnResolveAll
+**
+** Synopsis:
+** void = BPTUnResolveAll(hpid)
+**
+** Entry:
+** hpid or NULL
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+*/
+VOID
+BPTUnResolveAll(
+ HPID hpid
+ )
+{
+ HBPT hBpt = 0;
+ HPID hPidB;
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+
+ //
+ // Unresolve all breakpoints.
+ //
+ while (hBpt != NULL) {
+
+ if (!hpid || (BPGetHpid(hBpt, &hPidB), hPidB) == hpid) {
+ BPUninstantiate( hBpt );
+ }
+ Dbg(BPNextHbpt(&hBpt, bptNext) == BPNOERROR);
+
+ }
+
+ return;
+}
+
+
+
+
+BOOL
+BPCBBindHbpt(
+ HBPT hbpt
+ )
+{
+ Unreferenced( hbpt);
+ DebugBreak();
+ return FALSE;
+} /* BPCBBindHbpt() */
+
+
+/*** BPCBCBSetHighlight
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL PASCAL
+BPCBSetHighlight(
+ char FAR * szFile,
+ UINT line,
+ BOOL fSet,
+ BOOL fAsmOnly,
+ WORD state
+ )
+{
+ int doc;
+ char rgch[255];
+ int GotNext;
+
+ if (disasmView != -1) {
+ ViewDisasm(NULL, disasmHighlight);
+ }
+
+ if ( !fAsmOnly ) {
+ Assert( sizeof(rgch)-1 > _fstrlen(szFile) );
+ _fstrcpy(rgch, szFile);
+ GotNext = SrcMapSourceFilename(rgch, sizeof(rgch), SRC_MAP_ONLY, NULL);
+
+ if ((GotNext == 1) && FindDoc( rgch, &doc, TRUE) ) {
+ LineStatus( doc, line, state,
+ fSet ? LINESTATUS_ON : LINESTATUS_OFF, FALSE, TRUE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+} /* BPCBSetHighlight() */
+
+
+int
+PASCAL
+BPTResolve(
+ LPSTR BpBuf,
+ PVOID tml,
+ PCXF pcxf,
+ BOOL fBp
+ )
+{
+ BpString = BpBuf;
+ TmlBpResolve = (TML *)tml;
+ PcxfBpResolve = pcxf;
+
+ ResolvingBp = fBp;
+
+ if ( AutoTest ) {
+ //
+ // In test mode we use everything.
+ //
+ RetBpResolve = BPNOERROR;
+
+ } else {
+
+ StartDialog( DLG_BPRESOLVE, DlgBpResolve );
+ }
+
+ return RetBpResolve;
+}
+
+
+BOOL
+WINAPI
+DlgBpResolve(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+
+ HDC hdc;
+ int i;
+ int j;
+ int Idx;
+ char * pch;
+ int LargestString = 0;
+ SIZE Size;
+ HWND hList;
+ PHTM pTmList;
+ BPSTATUS Ret;
+ ADDR Addr;
+ USHORT bpsegtype = EECODE;
+ CXT Cxt;
+ char rgch[512];
+ EEHSTR eehstr;
+ EEHSTR eehstr2;
+ USHORT cb;
+ int radix;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+
+ case WM_INITDIALOG:
+
+ if ( BpString ) {
+
+ char *Buffer = rgch;
+ char *p;
+ char c;
+
+ *Buffer = '\0';
+
+ if ( *BpString != '{' || !(p = strchr( BpString+1, '}' )) ) {
+ p = BpString;
+ } else {
+ c = *++p;
+ *p = '\0';
+ BPShortenContext( BpString, Buffer );
+ *p = c;
+ }
+
+ strcat(Buffer, p );
+
+ SendMessage(GetDlgItem(hDlg, ID_BPRESOLVE_STRING), WM_SETTEXT,
+ 0, (DWORD)(LPSTR)Buffer);
+ }
+
+ LoadString(
+ hInst,
+ ResolvingBp ? DLG_ResolveBpCaption: DLG_ResolveFuncCaption,
+ rgch,
+ sizeof(rgch) );
+
+ SetWindowText( hDlg, rgch );
+
+ hList = GetDlgItem(hDlg, ID_BPRESOLVE_LIST);
+
+ pTmList = (PHTM)MMLpvLockMb( TmlBpResolve->hTMList );
+
+ for (i = 0; i < (int)TmlBpResolve->cTMListAct; i++ ) {
+
+ Ret = EEvaluateTM(&pTmList[i],
+ SHpFrameFrompCXF(PcxfBpResolve),
+ EEBPADDRESS);
+
+ if (Ret == EENOERROR) {
+ Ret = BPADDRFromTM(&pTmList[i], &bpsegtype, &Addr );
+ }
+
+ if (Ret != EENOERROR) {
+ continue;
+ }
+
+ memset( &Cxt, 0, sizeof(Cxt ));
+ SHSetCxt( &Addr, &Cxt );
+
+ Dbg( EEFormatCXTFromPCXT(&Cxt, &eehstr2, FALSE) == EENOERROR);
+
+ *rgch = '\0';
+ if ( eehstr2 ) {
+ pch = MMLpvLockMb( eehstr2 );
+ if ( *pch ) {
+ BPShortenContext( pch, rgch );
+ }
+ MMbUnlockMb( eehstr2 );
+ EEFreeStr( eehstr2 );
+ }
+
+ eehstr = 0;
+ Dbg(EEGetExprFromTM( &pTmList[i], &radix, &eehstr, &cb) == EENOERROR);
+ if (eehstr) {
+ pch = MMLpvLockMb( eehstr );
+ if ( pch && strchr(pch,'{') ) {
+ char *p = strchr( pch, '}' );
+ if ( p ) {
+ if ( *rgch == '\0' ) {
+ char c;
+ c = *(p+1);
+ *(p+1) = '\0';
+ BPShortenContext( pch, rgch );
+ *(p+1) = 'c';
+ }
+
+ pch = p+1;
+ }
+ }
+ strcat(rgch, pch );
+
+ hdc = GetDC( hList );
+ GetTextExtentPoint(hdc, rgch, strlen(rgch), &Size );
+ ReleaseDC( hList, hdc );
+
+ if ( Size.cx > LargestString ) {
+
+ LargestString = Size.cx;
+
+ SendMessage(hList,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ SendMessage( hList, LB_ADDSTRING, 0, (LONG)rgch);
+
+ MMbUnlockMb( eehstr );
+ EEFreeStr( eehstr );
+ }
+
+ }
+
+ MMbUnlockMb( TmlBpResolve->hTMList );
+
+ SendMessage(hList, LB_SETSEL, 1, 0L);
+
+ return TRUE;
+
+
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+
+ case ID_BPRESOLVE_LIST:
+ switch (HIWORD(wParam)) {
+ case LBN_SELCHANGE:
+ if ( !ResolvingBp ) {
+ //
+ // We only allow one selection.
+ //
+ hList = GetDlgItem(hDlg, ID_BPRESOLVE_LIST);
+ j = SendMessage( hList, LB_GETCOUNT, 0, 0L );
+ Idx = SendMessage( hList, LB_GETCARETINDEX, 0, 0L );
+ for ( i=0; i < j; i++ ) {
+ if ( i != Idx && SendMessage( hList, LB_GETSEL, i, 0L ) ) {
+ SendMessage( hList, LB_SETSEL, FALSE, i );
+ }
+ }
+ if ( Idx != LB_ERR ) {
+ SendMessage( hList, LB_SETSEL, TRUE, Idx );
+ }
+ }
+ }
+ break;
+
+
+ case ID_BPRESOLVE_USE:
+
+ hList = GetDlgItem(hDlg, ID_BPRESOLVE_LIST);
+
+ pTmList = (PHTM)MMLpvLockMb( TmlBpResolve->hTMList );
+
+ //
+ // Get rid of all the entries which are not selected
+ //
+ for (i=0, j=0; i < (int)TmlBpResolve->cTMListAct; i++ ) {
+
+ if ( !SendMessage( hList, LB_GETSEL, i, 0L ) ) {
+
+ EEFreeTM( &(pTmList[i]) );
+ pTmList[i] = (HTM)NULL;
+
+ } else {
+
+ if ( i != j ) {
+ pTmList[j] = pTmList[i];
+ pTmList[i] = (HTM)NULL;
+ }
+ j++;
+ }
+ }
+
+ TmlBpResolve->cTMListAct = j;
+
+ MMbUnlockMb( TmlBpResolve->hTMList );
+
+ RetBpResolve = (j > 0) ? BPNOERROR : BPCancel;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+
+ case IDCANCEL:
+
+ RetBpResolve = BPCancel;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_BPRESOLVE_HELP) );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+BOOL
+BPTCanIUseThunk(
+ LPSTR BpBuf
+ )
+{
+ if ( AutoTest ) {
+ return FALSE;
+ }
+
+ BpString = BpBuf;
+ StartDialog( DLG_BPCANIUSETHUNK, DlgBpCanIUseThunk );
+ return RetCanIUseThunk;
+}
+
+
+BOOL
+WINAPI
+DlgBpCanIUseThunk(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ char Buffer[256];
+ char *p;
+ char c;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+
+ case WM_INITDIALOG:
+ if ( BpString ) {
+
+ *Buffer = '\0';
+
+ if ( *BpString == '{' ) {
+ if (p = strchr( BpString+1, '}' ) ) {
+ p++;
+ c = *p;
+ *p = '\0';
+ BPShortenContext( BpString, Buffer );
+ *p = c;
+ } else {
+ p = BpString;
+ }
+ } else {
+ p = BpString;
+ }
+
+ strcat(Buffer, p );
+
+ SendMessage(GetDlgItem(hDlg, ID_BPCANIUSETHUNK_STRING), WM_SETTEXT,
+ 0, (DWORD)(LPSTR)Buffer);
+ }
+
+ break;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+ case IDOK:
+ RetCanIUseThunk = TRUE;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ case IDCANCEL:
+ RetCanIUseThunk = FALSE;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/private/windbg/windbg/brkpt0.c b/private/windbg/windbg/brkpt0.c
new file mode 100644
index 000000000..9190e46a4
--- /dev/null
+++ b/private/windbg/windbg/brkpt0.c
@@ -0,0 +1,6614 @@
+/*** BRKPT0.c - breakpoint handlers *
+*
+* Copyright <C> 1989, Microsoft Corporation
+*
+* Purpose:
+*
+*
+*************************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define BRKPOINT_STATUS (WORD)((lpBpp->bpstate & bpstateNotSet) ? UBP_LINE : BRKPOINT_LINE)
+
+#include "bpitypes.h"
+
+#define atmNull (0)
+
+extern EI Ei;
+#define Lpei (&Ei)
+extern SHF FAR * Lpshf;
+extern CXF CxfIp;
+
+extern DOCREC Docs[];
+extern VIEWREC Views[];
+extern int curView;
+extern LPPD LppdCur;
+extern LPTD LptdCur;
+
+
+#define FP_OFF(fp) (*((unsigned FAR *)&(fp)))
+
+
+#define assert(a)
+
+extern int PASCAL SYSetEmi(HPID, HTID, LPADDR);
+extern void SYSetFrame(FRAME * pFrame);
+
+//
+// Breakpoint flags
+//
+//#define BP_ONETHREAD 0x0001
+//#define BP_CODE 0x0002
+#define BP_DATA_READ 0x0004
+#define BP_DATA_WRITE 0x0008
+#define BP_EXECUTE 0x0010
+#define BP_DATA_CHANGED 0x0020
+
+
+
+#ifdef dcvotxs
+#undef LOCAL
+#define LOCAL
+#endif // dcvotxs
+
+BPSTATUS PASCAL BPBindHbptAddr( HBPT hBpt, LPBPP lpBpp, BOOL fOnList, CXF *pCxf );
+BPSTATUS PASCAL BPBindHbptNoAddr( HBPT hBpt, LPBPP lpBpp, BOOL fOnList, CXF *pCxf );
+
+LOCAL BPSTATUS PASCAL BPParseLineNumber(char FAR *, LPBPP);
+LOCAL int PASCAL BPFCxtForWpTp( PDPI, PDPF, HCS FAR *, EESTATUS * );
+LOCAL EESTATUS PASCAL BPTracePoint (PDPI,PDPF, PTI, PCXTL, PCXF);
+LOCAL EESTATUS PASCAL BPWatchPoint (PDPI,PDPF, PTI, PCXTL, PCXF);
+LOCAL EESTATUS PASCAL BPMkDPI (char FAR *, PCXF, PDPI, PDPF);
+LOCAL int PASCAL BPLoadValue(HBPI);
+LOCAL BPSTATUS PASCAL BpGetHtm(LPBPP lpBpp, char FAR * szBpt, BOOL fExpr);
+LOCAL BPSTATUS PASCAL BPCheckExprLpBpp(LPBPP lpbpp, CXF cxf, BOOL * fStop);
+LOCAL BPSTATUS PASCAL BPCheckMemoryLpBpp(LPBPP lpbpp, CXF cxf, BOOL * fStop);
+
+//
+// BPS + 1 BPIS + 0 Msg + 1 XOSD + 1 Notification
+//
+BYTE _BpsBuffer[ sizeof(BPS) + sizeof(BPIS) + sizeof(XOSD) + sizeof(DWORD)];
+#define BpsBuffer ((LPBPS)_BpsBuffer)
+
+LOCAL VOID BPInitBps( LPBPP lpBpp, LPBPS Bps, BOOL Set );
+
+extern int PASCAL BPResolveDlg( PHTM , int );
+LOCAL EESTATUS PASCAL BPParseBind ( PHTM phtm, PCXT pcxt, int iRadix,
+ char fCase, char fForce, char FAR * sz);
+LOCAL EESTATUS PASCAL BPParseBindCxtl ( PHTM phtm, PCXT pcxt, int iRadix,
+ char fCase, char fForce, PHCXTL phcl, char FAR * sz);
+BOOLEAN BPIsThunk(LPBPP lpBpp, TML TMLT );
+
+BPSTATUS BPGetTmList( LPBPP lpBpp, PTML pTml, char *BpBuf, int BufSize );
+VOID SplitExpression( char *BpBuf, char **Source, char **Exe );
+BPSTATUS BPSearchContexts( LPBPP lpBpp, char * szAddrExpr, PTML pTml, BOOL ImplementationOnly, BOOL LoadSymbols );
+BPSTATUS BPBindFromTmList( LPBPP lpBpp, PTML pTml, BOOL fOnList, char *BpBuf );
+BPSTATUS PASCAL BPRemoveHighLight( LPBPP lpBpp );
+BPSTATUS PASCAL BPAddHighLight( LPBPP lpBpp );
+
+
+#define OPENCONTEXTOP '{'
+#define CLOSECONTEXTOP '}'
+#define DOUBLEQUOTE '\"'
+
+/************************* Local Variable Decls ***************************/
+PLLI PlliBpList;
+
+#ifdef DOS5
+HATOMTBL hAtmTable;
+#endif
+
+LPPD LppdOld;
+LPTD LptdOld;
+int MemoryBpCount = 0; // Keeps track of number of memory Breakpoints
+static BOOL SymbolLoadingEnabled = TRUE;
+
+/************************* Local Prototypes *******************************/
+
+static BOOL FParseableSz(char FAR * sz);
+static void BPBoundFixContext( LPBPP pBpp );
+
+BPSTATUS PASCAL BPBindTML(
+ PHTM pHtm,
+ LPBPP lpBpp,
+ BOOL fOnList
+ );
+
+BPSTATUS PASCAL BPSetPidTid (
+ LPBPP lpBpp
+ );
+
+BOOL
+ParseBpMsg(
+ LPBPP lpBpp,
+ LPMSGMAP MsgMap
+ );
+
+BOOL GetMsg(
+ LPBPP lpBpp,
+ CXF cxf,
+ UINT *Msg
+ );
+
+BOOL FindMsg(
+ LPBPP lpBpp,
+ LPMSGMAP MsgMap
+ );
+
+BOOL MatchMsgClass(
+ LPBPP lpBpp,
+ LPMSGMAP MsgMap,
+ UINT Msg
+ );
+
+int _CRTAPI1 MsgCmp (
+ const void *p1,
+ const void *p2
+ );
+
+VOID SaveDebuggerPdTd (
+ void
+ );
+
+VOID RestoreDebuggerPdTd (
+ void
+ );
+
+VOID SetDebuggerPdTd(
+ LPBPP lpBpp
+ );
+
+VOID BPReplace(
+ LPBPP lpBpp
+ );
+
+
+/********************** CODE ********************************************/
+
+/*** BPLLCmp
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+int FAR PASCAL BPLLCmp(LPV lpv1, LPV lpv2, LONG l)
+{
+ LPBPP a = (LPBPP) lpv1;
+ LPBPP b = (LPBPP) lpv2;
+
+// Assert(a->iBreakpointNum != -1);
+// Assert(b->iBreakpointNum != -1);
+
+ Unreferenced( l );
+
+ if (a->iBreakpointNum < b->iBreakpointNum)
+ return ( fCmpLT );
+ if (a->iBreakpointNum > b->iBreakpointNum)
+ return ( fCmpGT );
+ return( fCmpEQ );
+} /* BPLLCmp()*/
+
+
+/*** BPInit
+**
+** Synopsis:
+** bpstatus = BPInit()
+**
+** Entry:
+** None
+**
+** Returns:
+** BPNOERROR
+**
+** Description:
+** Setup initializations needed for the breakpoint engine.
+**
+*/
+
+BPSTATUS PASCAL BPInit()
+{
+#ifdef DOS5
+ hAtmTable = WinCreateAtomTable(100, 10);
+#endif
+#if defined(WIN32) || defined(WINDOWS3)
+ InitAtomTable(29);
+#endif
+
+ PlliBpList = LLPlliInit(sizeof(BPP), llfAscending, llfNull, BPLLCmp);
+ return BPNOERROR;
+} /* BPInit() */
+
+
+/*** BPTerm
+**
+** Synopsis:
+** bpstatus = BPTerm()
+**
+** Entry:
+** None
+**
+** Returns:
+** BPNOERROR
+**
+** Description:
+** This routine does all the clean-up required to run the
+** breakpoint handler interface
+**
+*/
+
+BPSTATUS PASCAL BPTerm()
+{
+ return BPNOERROR;
+} /* BPTerm() */
+
+
+/*** BPAddToList
+**
+** Synopsis:
+** bpstatus = BPAddToList( hBpt, iBp )
+**
+** Entry:
+** hBpt - Handle to break point to be added onto the list
+** iBp - index to assign to breakpoint
+**
+** Returns:
+** bpstatus error code
+**
+** Description:
+** This function is used to place a breakpoint onto the list of
+** breakpoints in the system. It will also assign a breakpoint
+** number to the breakpoint.
+*/
+
+BPSTATUS PASCAL BPAddToList( HBPT hBpt, int iBp)
+{
+ LPBPP lpBpp = LLLpvFromPlle(hBpt);
+ HBPT hBpt2;
+ LPBPP lpBpp2;
+ UINT micBreakpointNum = (UINT) -1;
+
+ if (iBp != -1) {
+ if (BPHbptFromI( &hBpt2, iBp ) != BPNoMatch) {
+ return BPAmbigous;
+ }
+ }
+
+ /*
+ ** Need to assign a breakpoint number to the item
+ */
+
+ Dbg( BPNextHbpt( &hBpt2, bptFirst ) == BPNOERROR);
+
+ if (iBp == -1) {
+ if (hBpt2 == NULL) {
+ lpBpp->iBreakpointNum = 0;
+ } else {
+ do {
+ lpBpp2 = LLLpvFromPlle( hBpt2 );
+ if ((lpBpp2->fMarkDelete) &&
+ (lpBpp2->iBreakpointNum > micBreakpointNum)) {
+ lpBpp->iBreakpointNum = lpBpp2->iBreakpointNum;
+ break;
+ }
+
+ if (micBreakpointNum + 1 < lpBpp2->iBreakpointNum) {
+ lpBpp->iBreakpointNum = micBreakpointNum+1;
+ break;
+ }
+ micBreakpointNum = lpBpp2->iBreakpointNum;
+ Dbg( BPNextHbpt(&hBpt2, bptNext) == BPNOERROR);
+ } while (hBpt2 != NULL);
+
+ if (hBpt2 == NULL) {
+ lpBpp->iBreakpointNum = micBreakpointNum + 1;
+ }
+ }
+ } else {
+ lpBpp->iBreakpointNum = iBp;
+ }
+
+ /*
+ ** Mark as "to be added"
+ */
+
+ lpBpp->fNewMark = TRUE;
+ lpBpp->fMarkAdd = TRUE;
+
+
+ LLInsertPlleInLl( PlliBpList, hBpt, 0);
+ return BPNOERROR;
+} /* BPAddToList() */
+
+
+/*** BPChange
+**
+** Synopsis:
+** bpstatus = BPChange( hBpt, iBp )
+**
+** Entry:
+** hBpt - Handle to new breakpoint
+** iBp - index of breakpoint to change
+**
+** Returns:
+** bpstatus error code
+**
+** Description:
+** This function is used to change a breakpoint
+*/
+
+BPSTATUS PASCAL BPChange( HBPT hBpt, int iBp)
+{
+ BPSTATUS BpStatus = BPNOERROR;
+ LPBPP lpBpp;
+ HBPT hBpt2;
+ LPBPP lpBpp2;
+
+ if ( BPHbptFromI( &hBpt2, iBp ) == BPNoMatch) {
+
+ BpStatus = BPNoMatch;
+
+ } else {
+
+ lpBpp2 = LLLpvFromPlle( hBpt2 );
+
+ if ( !lpBpp2 ) {
+
+ BpStatus = BPError;
+
+ } else {
+
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ if ( lpBpp ) {
+
+ //
+ // If BP is already changed, get rid of previous
+ // replacement.
+ //
+ if ( lpBpp2->fMarkChange ) {
+ LLFDeletePlleFromLl( PlliBpList, lpBpp2->ChangeHbpt );
+ }
+
+ lpBpp2->fMarkChange = TRUE;
+ lpBpp2->ChangeHbpt = hBpt;
+
+ lpBpp->fMarkAdd = TRUE;
+ lpBpp->fMarkEnable = lpBpp2->fMarkEnable;
+ lpBpp->fMarkDisable = lpBpp2->fMarkDisable;
+ lpBpp->iBreakpointNum = lpBpp2->iBreakpointNum;
+ lpBpp->fReplacement = TRUE;
+
+ } else {
+
+ BpStatus = BPError;
+ }
+
+ }
+ }
+
+ return BpStatus;
+}
+
+/*** BPGetFinalHbpt
+**
+** Synopsis:
+** bpstatus = BPGetFinalHbpt( hBpt, phBpt)
+**
+** Entry:
+** hBpt - breakpoint handle
+** phBpt - pointer to final handle
+**
+** Returns:
+** BPNOERROR if no error occurs and modifies *phBpt to point to
+** either the original breakpoint handle or to the replacement
+** breakpoint handle, if the given breakpoint is marked for
+** change.
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL BPGetFinalHbpt(HBPT hBpt, HBPT FAR * phBpt)
+{
+ LPBPP lpBpp = LLLpvFromPlle( hBpt );
+
+
+ if ( lpBpp->fMarkChange ) {
+ *phBpt = lpBpp->ChangeHbpt;
+ } else {
+ *phBpt = hBpt;
+ }
+
+ return BPNOERROR;
+}
+
+
+/*** BPNextHbpt
+**
+** Synopsis:
+** bpstatus = BPNextHbpt(phBpt, iFunc)
+**
+** Entry:
+** phBpt - pointer to breakpoint handle
+** iFunc - Function to be executed
+**
+** Returns:
+** BPNOERROR if no error occurs and modifies *phBpt to point to
+** new breakpoint handle
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL BPNextHbpt(HBPT FAR * phBpt, UINT iFunc)
+{
+ LPBPP lpBpp;
+ HBPT hBpt = *phBpt;
+ BOOL Replacement;
+
+ while ( TRUE ) {
+
+ switch ( iFunc ) {
+ case bptNext:
+ // M00TODO verify that *phBpt is in list
+ hBpt = LLPlleFindNext( PlliBpList, hBpt);
+ break;
+
+#ifdef DBLLINK
+ case bptPrevious:
+ // M00TODO verify that *phBpt is in list
+ hBpt = LLPlleFindPrev( PlliBpList, hBpt);
+ break;
+#endif
+
+ case bptFirst:
+ hBpt = LLPlleFindNext( PlliBpList, (HBPT) NULL);
+ break;
+
+#ifdef DBLLINK
+ case bptLast:
+ hBpt = LLPlleFindPrev( PlliBpList, NULL);
+ break;
+#endif
+ default:
+ return BPError;
+ }
+
+ //
+ // Skip replacement BPs
+ //
+ if ( hBpt == NULL ) {
+ break;
+ } else {
+
+ lpBpp = LLLpvFromPlle( hBpt );
+ Replacement = lpBpp->fReplacement;
+
+ if ( !Replacement ) {
+ break;
+ }
+ }
+ }
+
+ *phBpt = hBpt;
+
+ return BPNOERROR;
+} /* BPNextHbpt() */
+
+
+/*** BPDisable
+**
+** Synopsis:
+** bpstatus = BPDisable(hbpt)
+**
+** Entry:
+** hbpt - Handle to disable the breakpoint on
+**
+** Returns:
+** breakpoint error code
+**
+** Description:
+** This routine will mark a breakpoint for being disabled. The disabling
+** does not actually occur until the BPCommit is done.
+*/
+
+BPSTATUS PASCAL BPDisable( HBPT hbpt )
+{
+ LPBPP lpbpp;
+ LPBPP lpbpp2;
+
+ lpbpp = LLLpvFromPlle( hbpt );
+
+ if (lpbpp == NULL) {
+ return( BPBadBPHandle );
+ }
+
+ lpbpp->fNewMark = TRUE;
+
+ /*
+ ** If fMarkEnable is set then the current state of the breakpoint
+ ** is disable so just clear the "to be enabled" flag
+ */
+
+ if (lpbpp->fMarkEnable) {
+ lpbpp->fMarkEnable = FALSE;
+ } else {
+ if (lpbpp->bpstate & bpstateEnabled) {
+ lpbpp->fMarkDisable = TRUE;
+ }
+ }
+
+ if ( lpbpp->fMarkChange ) {
+ lpbpp2 = LLLpvFromPlle( lpbpp->ChangeHbpt );
+ if (lpbpp2->fMarkEnable) {
+ lpbpp2->fMarkEnable = FALSE;
+ }
+ lpbpp2->fMarkDisable = TRUE;
+
+ }
+
+ return( BPNOERROR );
+} /* BPDisable() */
+
+/*** BPEnable
+**
+** Synopsis:
+** bpstatus = BPEnable(hbpt)
+**
+** Entry:
+** hbpt - Handle to enable the breakpoint on
+**
+** Returns:
+** breakpoint error code
+**
+** Description:
+** This routine will mark a breakpoint for being enabled. The enabling
+** does not actually occur until the BPCommit is done.
+*/
+
+BPSTATUS PASCAL BPEnable( HBPT hbpt )
+{
+ LPBPP lpbpp;
+ LPBPP lpbpp2;
+ char rgch[256];
+ char rgch2[256];
+ int err;
+ BPSTATUS Ret = BPNOERROR;
+
+ lpbpp = LLLpvFromPlle( hbpt );
+
+ if (lpbpp == NULL) {
+ return( BPBadBPHandle );
+ }
+
+ lpbpp->fNewMark = TRUE;
+
+ if ( ((lpbpp->bpstate & bpstateEnabled) && lpbpp->fMarkDisable ) ||
+ !lpbpp->fMarkEnable ) {
+
+ //
+ // If the breakpoint is not instantiated, we try to instantiate it
+ //
+ if ( !(lpbpp->bpstate & bpstateSet) ) {
+ if ( DebuggeeActive() ) {
+ Ret = BPBindHbpt( hbpt, &CxfIp );
+ }
+ }
+
+ //
+ // If fMarkDisable is set then the current state of the breakpoint
+ // is enabled so just clear the "to be disabled" flag
+ //
+ if (lpbpp->fMarkDisable) {
+ lpbpp->fMarkDisable = FALSE;
+ } else {
+ if (!(lpbpp->bpstate & bpstateEnabled)) {
+ lpbpp->fMarkEnable = TRUE;
+ }
+ }
+
+ if ( lpbpp->fMarkChange ) {
+ lpbpp2 = LLLpvFromPlle( lpbpp->ChangeHbpt );
+ if (lpbpp2->fMarkDisable) {
+ lpbpp2->fMarkDisable = FALSE;
+ } else {
+ lpbpp2->fMarkEnable = TRUE;
+ }
+ }
+
+ //
+ // Reset count
+ //
+ if (lpbpp->atmPassCount != 0) {
+ GetAtomName(lpbpp->atmPassCount, rgch, sizeof(rgch)-1);
+ lpbpp->iPassCount = CPGetNbr(rgch, radix, fCaseSensitive, &(lpbpp->Cxf), rgch2, &err);
+ }
+ }
+
+ return( Ret );
+}
+
+
+
+/*** BPParse
+**
+** Purpose: To parse a breakpoint command.
+** This is used to validate that a breakpoint is syntaxactly correct.
+** This is used for the U,A,G,BP,and V commands.
+**
+** Input:
+** szBpt String defining the breakpoint
+** ppBpp Pointer to pointer to parse break point structure
+** szMod String defining the current module
+** szFile String defining the current file
+**
+** Output:
+** Error code for the parse operation
+** ppBpp will be filled in with a pointer to a BPP on success
+**
+** Exceptions:
+**
+** Notes:
+**
+*/
+
+BPSTATUS PASCAL
+BPParse(
+ HBPT FAR * phBpt,
+ char FAR * szBpt,
+ char FAR * szMod,
+ char FAR * szFile,
+ HPID hPid
+ )
+{
+ HBPT hBpt = LLPlleCreate(PlliBpList);
+ LPBPP pBpp;
+ BPSTATUS Ret = BPNOERROR;
+ char FAR * pNextTok;
+ char FAR * szInit = szBpt;
+ char rgch[256];
+ char rgch2[256];
+ BOOLEAN ParsedLineNumber = FALSE;
+ int err;
+
+ BOOLEAN ASwitch = FALSE;
+ BOOLEAN RSwitch = FALSE;
+ BOOLEAN PSwitch = FALSE;
+ BOOLEAN CSwitch = FALSE;
+ BOOLEAN MSwitch = FALSE;
+// BOOLEAN DSwitch = FALSE;
+ BOOLEAN QSwitch = FALSE;
+ BOOLEAN HSwitch = FALSE;
+ BOOLEAN TSwitch = FALSE;
+ BOOLEAN WSwitch = FALSE;
+
+ if (hBpt == NULL) {
+ return BPOOMemory;
+ }
+
+ pBpp = LLLpvFromPlle(hBpt);
+
+ //
+ // Initialize breakpoint structure
+ //
+ _fmemset(pBpp, 0, sizeof(*pBpp));
+
+ //
+ // By default all breakpoints are not set and enabled
+ //
+ pBpp->bpstate = bpstateNotSet | bpstateEnabled;
+ pBpp->hPid = hPid;
+ pBpp->iBreakpointNum = (USHORT) -1;
+ pBpp->iHighlightLine = (USHORT) -1;
+ pBpp->fTemporary = 0;
+ pBpp->BpType = 0;
+
+ //
+ // We are going to start parsing up the string.
+ // First skip over any leading whitespace and check to make sure that
+ // there was something specified. I.e. "bp " is not a
+ // legal breakpoint command
+ //
+ szBpt = CPSkipWhitespace(szBpt);
+ pNextTok = CPszToken(szBpt, "");
+ if ( *(szBpt) == '\0') {
+
+ //
+ // ERROR - empty string
+ //
+ Ret = BPCODEADDR;
+ goto error;
+ }
+
+ //
+ // Now start walking through the string looking for all of the pieces
+ // of a breakpoint command.
+ //
+ // For the most part we can tell what a piece is from its first character
+ //
+ // The portions of a breakpoint command are:
+ // expression Address expression
+ // =expression Watch point (data change)
+ // ?expression Trace point (expression change)
+ // /R /r Size of watch point
+ // /P /p Pass count
+ // /C /c Commands to execute
+ // /M /m Window message
+ // ! not used /D /d Don't stop if true (window msg only)
+ // /Q /q Quiet defer
+ // /T /t Thread
+ // /W /w WndProc breakpoint
+ // /A /a Data breakpoint types
+ //
+ // The following error checks must be done:
+ // 1. Watchpoint and Tracepoints are mutually exclusive
+ // 2. /R requires a Watchpoint command
+ //
+
+ while (*szBpt) {
+ switch (*szBpt++) {
+ case '=':
+ if (pBpp->atmExpr || pBpp->atmRangeSize) {
+ Ret = BPBadDataSize;
+ goto error;
+ }
+ if ((Ret = BpGetHtm(pBpp, szBpt, FALSE)) != BPNOERROR) {
+ goto error;
+ }
+ pBpp->BpType = BP_DATA_CHANGED;
+ break;
+
+ case '?':
+ if (pBpp->atmData) {
+ Ret = BPBadDataSize;
+ goto error;
+ }
+ if ((Ret = BpGetHtm(pBpp, szBpt, TRUE)) != BPNOERROR) {
+ goto error;
+ }
+ break;
+
+ case '/':
+ switch (*szBpt) {
+ /*
+ ** Get the size of the watch point to be used.
+ */
+
+ case 'R':
+ case 'r':
+ if (RSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ RSwitch = TRUE;
+ if (pBpp->atmExpr) {
+ Ret = BPBadDataSize;
+ goto error;
+ }
+ szBpt++;
+ if (!FParseableSz(szBpt)) {
+ Ret = BPBadDataSize;
+ goto error;
+ }
+ pBpp->atmRangeSize = AddAtom(szBpt);
+ break;
+
+ case 'P':
+ case 'p':
+ if (PSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ PSwitch = TRUE;
+ szBpt++;
+ if (!FParseableSz(szBpt)) {
+ Ret = BPBadPassCount;
+ goto error;
+ }
+ pBpp->atmPassCount = AddAtom(szBpt);
+ break;
+
+ case 'A':
+ case 'a':
+ if (ASwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ ASwitch = TRUE;
+ szBpt++;
+ switch( tolower(*szBpt) ) {
+ case 'e':
+ pBpp->BpType = BP_EXECUTE;
+ break;
+
+ case 'w':
+ pBpp->BpType = BP_DATA_WRITE;
+ break;
+
+ case 'r':
+ pBpp->BpType = BP_DATA_READ;
+ break;
+
+ case 'c':
+ pBpp->BpType = BP_DATA_CHANGED;
+ break;
+
+ default:
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ break;
+
+ case 'C':
+ case 'c':
+ if (CSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ CSwitch = TRUE;
+ szBpt++;
+ if (*szBpt != '\"') {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ if (szBpt[_fstrlen(szBpt)-1] == '\"')
+ szBpt[_fstrlen(szBpt)-1] = 0;
+ pBpp->szCmdLine = _strdup( szBpt+1);
+ break;
+
+ case 'M':
+ case 'm':
+ szBpt++;
+ if ( MSwitch ) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+
+ pBpp->atmMsg = AddAtom(szBpt);
+ pBpp->fWndProc = TRUE;
+ pBpp->fMsg = TRUE;
+ MSwitch = TRUE;
+ break;
+
+ //
+ // NOTENOTE ramonsa - not used - remove
+ // case 'D':
+ // case 'd':
+ // if (DSwitch) {
+ // Ret = BPBadCmdString;
+ // goto error;
+ // }
+ // DSwitch = TRUE;
+ // pBpp->fDontStop = TRUE;
+ // break;
+
+ case 'Q':
+ case 'q':
+ if (QSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ QSwitch = TRUE;
+ pBpp->fQuiet = TRUE;
+ break;
+
+
+ case 'H':
+ case 'h':
+ if (HSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ HSwitch = TRUE;
+ szBpt++;
+ if (!FParseableSz(szBpt)) {
+ Ret = BPBadPassCount;
+ goto error;
+ }
+ pBpp->iPid = CPGetNbr( szBpt, 10, fCaseSensitive, &CxfIp, rgch, &err);
+ if ( err != EENOERROR ) {
+ Ret = BPBadProcess;
+ goto error;
+ }
+ pBpp->fProcess = TRUE;
+ break;
+
+ case 'T':
+ case 't':
+ if (TSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ TSwitch = TRUE;
+ szBpt++;
+ if (!FParseableSz(szBpt)) {
+ Ret = BPBadPassCount;
+ goto error;
+ }
+ pBpp->iTid = CPGetNbr( szBpt, 10, fCaseSensitive, &CxfIp, rgch, &err);
+ if ( err != EENOERROR ) {
+ Ret = BPBadThread;
+ goto error;
+ }
+ pBpp->fThread = TRUE;
+ break;
+
+ case 'W':
+ case 'w':
+ if (WSwitch) {
+ Ret = BPBadCmdString;
+ goto error;
+ }
+ WSwitch = TRUE;
+ pBpp->fWndProc = TRUE;
+ szBpt++;
+ break;
+
+ default:
+ Ret = BPBadOption;
+ goto error;
+ }
+ break;
+
+ default:
+ szBpt--;
+ if ( ParsedLineNumber ) {
+ Ret = BPBadAddrExpr;
+ goto error;
+ } else if ((Ret = BPParseLineNumber(szBpt, pBpp)) != BPNOERROR) {
+ goto error;
+ }
+ ParsedLineNumber = TRUE;
+ break;
+ }
+
+ szBpt = pNextTok;
+ if ( !(*(pNextTok - 1))) *(pNextTok - 1) = ' ';
+ pNextTok = CPszToken( szBpt, "");
+
+ //
+ // NOTENOTE ramonsa - Is this trying to do something useful?
+ // remove it!
+ //
+ // if (szFile==(char FAR*)-1) {
+ // *szInit = (char)(szBpt - szInit);
+ // break;
+ // }
+ }
+
+ if ( !pBpp->fProcess ) {
+ if ( hPid == 0 ) {
+ pBpp->iPid = 0;
+ } else {
+ LPPD lppd = LppdOfHpid(hPid);
+ if (lppd) {
+ pBpp->iPid = lppd->ipid;
+ }
+ }
+ pBpp->fProcess = TRUE;
+ }
+
+ //
+ // Do additional error checking
+ //
+
+ if (pBpp->atmRangeSize ) {
+ if ( !pBpp->atmData) {
+ //
+ // A range requires a data address
+ //
+ Ret = BPBadDataSize;
+ goto error;
+ } else {
+ GetAtomName(pBpp->atmRangeSize, rgch, sizeof(rgch)-1);
+ pBpp->cbDataSize = CPGetNbr(rgch, radix, fCaseSensitive, &(pBpp->Cxf), rgch2, &err);
+ }
+ } else if ( pBpp->fMemory ) {
+
+ //
+ // For memory breakpoints, the size defaults to 4
+ //
+ pBpp->atmRangeSize = AddAtom( "4" );
+ pBpp->cbDataSize = 4;
+ }
+
+ if ( pBpp->fWndProc ) {
+
+ //
+ // No line numbers
+ //
+ if ( !pBpp->fCodeAddr ||
+ *(pBpp->szAddrExpr) == '@' ||
+ *(pBpp->szAddrExpr) == '.' ) {
+ Ret = BPBadAddrExpr;
+ goto error;
+ }
+
+ //
+ // Validate the message/message class if we can.
+ //
+ if ( pBpp->fMsg ) {
+
+ XOSD xosd;
+ LPMSGMAP MsgMap = NULL;
+ LPPD lppd;
+ LPTD lptd;
+
+ lppd = LppdOfIpid(pBpp->iPid);
+
+ if ( lppd ) {
+
+ //
+ // Get message list and parse the message.
+ //
+ lptd = lppd->lptdList;
+
+ xosd = OSDGetMsgMap( lppd->hpid, lptd->htid, &MsgMap );
+
+ if ( xosd == xosdNone ) {
+
+ if ( !ParseBpMsg( pBpp, MsgMap ) ) {
+ Ret = BPError;
+ goto error;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Make sure that we have an expression
+ //
+ if ( pBpp->fCodeAddr ) {
+ if ( !pBpp->atmAddrCxt &&
+ !pBpp->atmCxtDef &&
+ !pBpp->szAddrExpr ) {
+
+ Ret = BPError;
+ goto error;
+ }
+ }
+
+ //
+ // Get the default context set
+ //
+
+ if ((szMod != NULL) || (szFile != NULL && szFile !=(char FAR*)-1)) {
+ sprintf(rgch, "{%Fs,%Fs,}", szMod == NULL ? "" : szMod,
+ szFile == NULL ? "" : szFile);
+ pBpp->atmCxtDef = AddAtom(rgch);
+ if ((pBpp->atmHighlightFile == 0) && (szFile != NULL)) {
+ pBpp->atmHighlightFile = AddAtom(szFile);
+ }
+ }
+
+ //
+ // Return the pointer to the structure
+ //
+
+ *phBpt = hBpt;
+ return Ret;
+
+ //
+ // Come here in the event of an error to clean up the world
+ //
+error:
+ if (pBpp->atmPassCount) DeleteAtom(pBpp->atmPassCount);
+ if (pBpp->atmRangeSize) DeleteAtom(pBpp->atmRangeSize);
+ if (pBpp->szCmdLine) { free(pBpp->szCmdLine); pBpp->szCmdLine = NULL; }
+ if (pBpp->atmExpr) DeleteAtom(pBpp->atmExpr);
+ if (pBpp->szAddrExpr) { free(pBpp->szAddrExpr); pBpp->szAddrExpr = NULL; }
+ if (pBpp->atmAddrCxt) DeleteAtom(pBpp->atmAddrCxt);
+ if (pBpp->atmData) DeleteAtom(pBpp->atmData);
+ if (pBpp->hTm) EEFreeTM (&pBpp->hTm);
+ MMFreeHmem( (HDEP) hBpt );
+ return Ret;
+}
+
+/*** BPParseLineNumber
+*
+* Purpose:
+* Parse the address portion of a breakpoint command. Legal address
+* formats are:
+*
+* {CONTEXT}@line
+* {CONTEXT}.line
+* .line
+* @line
+* {CONTEXT}addr-expr
+* addr-expr
+*
+* Input:
+*
+* Output:
+*
+* Exceptions:
+*
+*************************************************************************/
+
+LOCAL BPSTATUS PASCAL
+BPParseLineNumber(
+ char FAR * sz,
+ LPBPP pBpp
+ )
+{
+ char szCxt[255] = {0};
+ char FAR * lpch;
+ char FAR * lpchAddr;
+ LPSTR lp0;
+ LPSTR lp1;
+ LPSTR lpBp;
+ char sfile[255];
+ UINT iLine;
+ BOOL fNeedContext = FALSE;
+
+ /*
+ ** Step 1 is to look and see if a context operator is being given
+ ** in the breakpoint command itself. If so then we want to strip
+ ** it off to look at the rest of the expression separately
+ */
+
+ if (*sz == OPENCONTEXTOP) { /* check for a context operator here */
+
+ lpBp = strchr(sz, CLOSECONTEXTOP);
+ if (!lpBp) {
+ return BPBadContextOp;
+ }
+ lpBp++;
+
+ lp0 = strchr(sz, ',');
+
+ if (!lp0 || lp0 >= lpBp) {
+
+ // don't look past the end of the context op
+ lp0 = sz + 1;
+
+ } else {
+
+ // skip function; if there is another comma, it
+ // delimits a source file
+ lp0++;
+
+ lp1 = strchr(lp0, ',');
+
+ if (lp1 && lp1 < lpBp) {
+
+ if (lp1 > lp0) {
+ memset(sfile, 0, sizeof(sfile));
+ strncpy(sfile, lp0, lp1-lp0);
+ pBpp->atmHighlightFile = AddAtom(sfile);
+ }
+ lp0 = lp1+1;
+ }
+
+ // refuse extra commas
+ lp1 = strchr(lp0, ',');
+ if (lp1 && lp1 < lpBp) {
+ return BPBadContextOp;
+ }
+ }
+
+ _fstrncpy(szCxt, sz, lpBp-sz);
+ szCxt[lpBp - sz] = 0;
+
+ /*
+ ** Skip over the context operator and any whitespace following it
+ */
+
+ sz = CPSkipWhitespace( lpBp );
+
+ /*
+ ** Check for only a context operator
+ */
+
+ if (*sz == 0) {
+ return BPBadContextOp;
+ }
+ } else if ( (lp0 = strchr( sz, '!' )) ) {
+
+ *lp0 = 0;
+ strcpy( szCxt, "{,," );
+ strcat( szCxt, sz );
+ strcat( szCxt, "}" );
+ sz = CPSkipWhitespace( lp0+1 );
+ }
+
+ pBpp->fHighlight = TRUE;
+
+ lpchAddr = sz;
+
+ /*
+ ** Two possibilities now -- either its a line number construct or
+ ** its an address.
+ */
+
+ if (*sz == '.') {
+ *sz = '@';
+ sz++; // Skip over the '.' character
+ sz = CPSkipWhitespace( sz );// Skip over any whitespace
+ if (*sz == 0) {
+ return BPBadAddrExpr;
+ }
+
+ /*
+ ** What is left should be a parsable expression
+ */
+
+ if (!FParseableSz(sz)) {
+ return BPBadAddrExpr;
+ }
+
+ fNeedContext = TRUE;
+ } else {
+ if (!FParseableSz(sz)) {
+ return BPBadAddrExpr;
+ }
+
+ fNeedContext = (strcspn(sz, "@") != _fstrlen(sz));
+ }
+
+ /*
+ ** Check for a line number expression -- defined as starting with
+ ** an @ character
+ */
+
+ if (*lpchAddr == '@') {
+ iLine = 0;
+ for (lpch = lpchAddr+1; ('0' <= *lpch) && (*lpch <= '9'); lpch++) {
+ iLine = iLine*10 + *lpch - '0';
+ }
+ if ( *lpch && *lpch != ' ' && *lpch != '\t' ) {
+ return BPBadAddrExpr;
+ }
+
+ pBpp->iHighlightLine = iLine;
+ }
+
+ /*
+ ** Now rebuild the expression to be evaluated
+ */
+
+ if (szCxt[0] != 0) {
+ pBpp->atmAddrCxt = AddAtom(szCxt);
+ }
+ pBpp->szAddrExpr = _strdup(lpchAddr);
+ pBpp->fCodeAddr = TRUE;
+
+ return BPNOERROR;
+} /* BPParseLineNumber() */
+
+
+/*** BPADDRFromTM
+*
+* Purpose: To get the address of an item represented by a TM
+*
+* Input:
+* phTM - A pointer to a handle to a TM that represents
+* the item to get the address of
+*
+* pwSegType - This indicates that the TM must be a member of this
+* segment type (Code, Data, Const).
+*
+* pAddr - The place to put the address when found
+*
+* Output:
+* Returns An Expr Eval Error, or EECATASTROPHIC if nothing was found
+*
+* Modify pwSegType to reflect InfoFromTM response.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+EESTATUS PASCAL
+BPADDRFromTM(
+ PHTM phTM,
+ unsigned short FAR * pwSegType,
+ LPADDR paddr
+ )
+{
+ EESTATUS Err = EENOERROR;
+ RI RIT = {0};
+ HTI hTI;
+ PTI pTI;
+
+ _fmemset(paddr, 0, sizeof(ADDR));
+ RIT.fAddr = TRUE;
+ RIT.fSegType = TRUE;
+ RIT.fValue = TRUE;
+ RIT.fSzBytes = TRUE;
+
+ // get the information
+ if( !(Err = EEInfoFromTM(phTM, &RIT, &hTI)) ) {
+
+ // get the TI
+ assert(hTI != (HTI)NULL);
+ pTI = MMLpvLockMb (hTI);
+
+ // if an address was given.
+ if ( pTI->fResponse.fAddr ) {
+ *paddr = pTI->u2.AI;
+ SYUnFixupAddr( paddr );
+ }
+ //if( pTI->fResponse.fAddr && (pTI->u.SegType & *pwSegType) ) {
+ // *paddr = pTI->u2.AI;
+ // SYUnFixupAddr ( paddr );
+ // *pwSegType = pTI->u.SegType;
+ //}
+ else if(!pTI->fResponse.fAddr &&
+ pTI->fResponse.fValue &&
+ pTI->fResponse.fSzBytes &&
+ pTI->cbValue >= sizeof(WORD) ) {
+
+ // if a value was given
+ // save the offset
+ switch ( pTI->cbValue ) {
+
+ case sizeof(BYTE):
+
+ SetAddrOff ( paddr , *((CHAR FAR *) pTI->Value) );
+ break;
+
+ default:
+ case sizeof(WORD):
+
+ SetAddrOff ( paddr , *((WORD FAR *) pTI->Value) );
+ break;
+
+ case sizeof(DWORD):
+
+ // sizeof(SHOFF) == sizeof(DWORD) if ADDR_MIXED is defined
+ SetAddrOff ( paddr , *((SHOFF FAR *) pTI->Value) );
+ break;
+ }
+
+ // set the segment
+ if( (*pwSegType & EEDATA) == EEDATA ) {
+ ADDR addrData = {0};
+
+ OSDGetAddr ( LppdCur->hpid, LptdCur->htid, (ADR)adrData, &addrData );
+ SetAddrSeg ( paddr, (SHSEG) GetAddrSeg ( addrData ) );
+ SYUnFixupAddr ( paddr );
+ *pwSegType &= EEDATA;
+ }
+
+ else if( (*pwSegType & EECODE) == EECODE ) {
+ ADDR addrPC = {0};
+
+ OSDGetAddr ( LppdCur->hpid, LptdCur->htid, (ADR)adrPC, &addrPC );
+ SetAddrSeg ( paddr, (SHSEG) GetAddrSeg ( addrPC ) );
+ SYUnFixupAddr ( paddr );
+ *pwSegType &= EECODE;
+ }
+
+ // assume bad address expression
+ else {
+ Err = EEBADADDR;
+ }
+ }
+ else {
+ Err = EEBADADDR;
+ }
+
+ // remove the TI
+ MMbUnlockMb (hTI);
+ EEFreeTI(&hTI);
+ }
+
+ // thou shalt never return a physical address from this function!
+#ifdef DEBUGVER
+ if ( !Err ) {
+ assert ( ADDR_IS_LI ( *paddr ) );
+ }
+#endif
+ return(Err);
+}
+
+/*** BPDelete
+**
+** Synopsis:
+** bpstatus = BPDelete( hBpt )
+**
+** Entry:
+** hBpt - handle of breakpoint to be deleted
+**
+** Returns:
+** breakpoint status code
+**
+** Description:
+** This routine will take and delete the requested breakpoint handle.
+**
+*/
+
+BPSTATUS PASCAL BPDelete( HBPT hBpt )
+{
+ LPBPP lpBpp;
+ LPBPP lpBpp2;
+
+ lpBpp = LLLpvFromPlle(hBpt);
+
+ if (lpBpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ lpBpp->fNewMark = TRUE;
+
+ if (lpBpp->fMarkAdd) {
+
+ if ( lpBpp->fMarkChange ) {
+ LLFDeletePlleFromLl( PlliBpList, lpBpp->ChangeHbpt );
+ lpBpp->ChangeHbpt = NULL;
+ lpBpp->fMarkChange = FALSE;
+ }
+
+ lpBpp->bpstate |= bpstateDeleted;
+ BPRemoveHighLight( lpBpp );
+ LLFDeletePlleFromLl( PlliBpList, hBpt );
+ }
+ else {
+ lpBpp->fMarkDelete = TRUE;
+
+ if ( lpBpp->fMarkChange ) {
+ lpBpp2 = LLLpvFromPlle( lpBpp->ChangeHbpt );
+ lpBpp2->fMarkDelete = TRUE;
+ lpBpp2->fMarkAdd = FALSE;
+ }
+
+ }
+
+ return BPNOERROR;
+
+} /* BPDelete() */
+
+
+/*** BPDeleteAll
+**
+** Synopsis:
+** bpstatus = BPDeleteAll( )
+**
+** Entry:
+** None
+**
+** Returns:
+** breakpoint status code
+**
+** Description:
+** This routine will take and delete all breakpoints in the world
+**
+*/
+
+BPSTATUS PASCAL
+BPDeleteAll(
+ VOID
+ )
+{
+ HBPT hBpt1;
+ HBPT hBpt2;
+
+ Dbg( BPNextHbpt( &hBpt1, bptFirst) == BPNOERROR );
+
+ while ( hBpt1 != NULL ) {
+ /*
+ ** Save the previous breakpoint
+ */
+
+ hBpt2 = hBpt1;
+
+ /*
+ ** Get the next one on the list incase this one disappears
+ */
+
+ Dbg( BPNextHbpt( &hBpt1, bptNext ) == BPNOERROR );
+
+ /*
+ ** Now delete the current one
+ */
+
+ Dbg( BPDelete( hBpt2 ) == BPNOERROR );
+ }
+
+ return BPNOERROR;
+} /* BPDeleteAll() */
+
+
+
+
+/*** BPParseBindCxtl
+*
+* Purpose: To parse, bind, and get Context list for an expression
+* returning tm and error value
+*
+* Input:
+* PHTM phtm handle to expression.
+* PCXT pcxt context to start symbol search if {} not supplied by users.
+* int iRadix radix to use.
+* char fCase case sensitivity.
+* char fForce force bind to new context.
+* PHCXTL phcl pointer to context list handle - modified by this function.
+* char far * sz pointer to expression.
+*
+* Output:
+*
+*
+* Returns
+*
+* EESTATUS eest EENOERROR / 0 if successfull
+* !0 Failuer CVExprErr has static buffer message.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+LOCAL EESTATUS PASCAL
+BPParseBindCxtl(
+ PHTM phtm,
+ PCXT pcxt,
+ int iRadix,
+ char fCase,
+ char fForce,
+ PHCXTL phcl,
+ char FAR * sz
+ )
+{
+
+ EESTATUS eest = EENOERROR;
+ UINT strIndex;
+
+ eest = EEParse(sz, iRadix, fCase, phtm, &strIndex);
+ if ( !eest ) {
+ eest = EEBindTM(phtm, pcxt, fForce, FALSE, FALSE);
+ if ( !eest ) {
+ eest = EEGetCXTLFromTM (phtm, phcl);
+ }
+ }
+ return eest;
+} /* BPParseBindCxtl */
+
+
+
+
+
+/*** BPBindHbpt
+**
+** Synopsis:
+** bpstatus = BPBindHbpt( hBpt )
+**
+** Entry:
+** hBpt - handle to breakpoint to be bound in
+**
+** Returns:
+** status of the action
+**
+** Description:
+**
+*/
+BPSTATUS PASCAL
+BPBindHbpt(
+ HBPT hBpt,
+ CXF *pCxf
+ )
+{
+ HBPT hBpt2;
+ BOOL fOnList = FALSE;
+ LPBPP lpBpp;
+ BPSTATUS Ret;
+
+ //
+ // Check to see if this breakpoint is on the list of breakpoints
+ //
+ Dbg( BPNextHbpt( &hBpt2, bptFirst) == BPNOERROR);
+ while (hBpt2 != NULL) {
+ if (hBpt2 == hBpt) {
+ fOnList = TRUE;
+ break;
+ }
+ Dbg( BPNextHbpt( &hBpt2, bptNext ) == BPNOERROR );
+ }
+
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ if ( lpBpp->fCodeAddr ) {
+ Ret = BPBindHbptAddr( hBpt, lpBpp, fOnList, pCxf );
+ } else {
+ Ret = BPBindHbptNoAddr( hBpt, lpBpp, fOnList, pCxf );
+ }
+
+
+ return Ret;
+} /* BPBindHbpt */
+
+
+
+BPSTATUS PASCAL
+BPBindHbptNoAddr(
+ HBPT hBpt,
+ LPBPP lpBpp,
+ BOOL fOnList,
+ CXF *pCxf
+ )
+{
+ char rgch[256];
+ char rgch2[256];
+ BPSTATUS Ret = BPNOERROR;
+ int err;
+ XOSD Xosd;
+ int cch;
+ BOOLEAN Ok;
+
+ Ret = BPSetPidTid( lpBpp );
+ if ( pCxf ) {
+ lpBpp->Cxf = *pCxf;
+ }
+
+ if ( Ret == BPNOERROR ) {
+
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateVirtual;
+
+ //
+ // If a memory breakpoint, try to bind the memory address expression
+ //
+ if ( !lpBpp->fMemory ) {
+
+ Ok = TRUE;
+
+ } else {
+
+ GetAtomName(lpBpp->atmData, rgch, sizeof(rgch)-1);
+
+ Ok = (CPGetAddress( rgch, &cch, &(lpBpp->AddrMem), radix,
+ &(lpBpp->Cxf), FALSE, FALSE) == EENOERROR);
+
+ if ( Ok ) {
+
+ if (lpBpp->cbDataSize == 0) {
+ lpBpp->cbDataSize = 1;
+ }
+
+#if 0
+ //
+ // Verify that the memory is readable.
+ //
+ lpBpp->Mem = (PBYTE)malloc( lpBpp->cbDataSize );
+
+ if ( !lpBpp->Mem ) {
+ Ok = FALSE;
+ } else {
+
+ SYFixupAddr( &(lpBpp->AddrMem) );
+ Ok = ( OSDSetAddr( lpBpp->hPid,
+ lpBpp->hTid,
+ (ADR)adrCurrent,
+ &(lpBpp->AddrMem))
+ == xosdNone);
+
+ if ( Ok ) {
+ SYUnFixupAddr( &(lpBpp->AddrMem) );
+ Ok = (OSDPtrace( osdReadBuf,
+ lpBpp->cbDataSize,
+ lpBpp->Mem,
+ lpBpp->hPid,
+ lpBpp->hTid)
+ == (XOSD)lpBpp->cbDataSize);
+ }
+ }
+#endif
+ }
+ }
+
+ if ( !Ok ) {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateNotSet;
+
+ Ret = BPError;
+ }
+
+
+ if ( Ok && fOnList && !lpBpp->fMarkAdd &&
+ (lpBpp->bpstate & bpstateEnabled)) {
+
+ BPInitBps( lpBpp, BpsBuffer, TRUE );
+ Xosd = OSDBreakpoint( lpBpp->hPid, BpsBuffer );
+
+ if ( Xosd == xosdNone ) {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateSet;
+ lpBpp->dwNotify = DwNotification(BpsBuffer)[0];
+
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount++;
+ }
+
+ } else {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateNotSet;
+
+ Ret = BPError;
+ }
+ }
+
+ if (lpBpp->atmPassCount != 0) {
+
+ GetAtomName(lpBpp->atmPassCount, rgch, sizeof(rgch)-1);
+ lpBpp->iPassCount = CPGetNbr(rgch, radix, fCaseSensitive,
+ &(lpBpp->Cxf), rgch2, &err);
+ }
+ }
+
+ return Ret;
+} /* BPBindHbptNoAddr */
+
+
+
+BPSTATUS PASCAL
+BPBindHbptAddr(
+ HBPT hBpt,
+ LPBPP lpBpp,
+ BOOL fOnList,
+ CXF *pCxf
+ )
+{
+ BPSTATUS Ret;
+ TML Tml;
+ LPMSGMAP MsgMap;
+ char BpBuf[256];
+
+ //
+ // Set Context fields in BP structure
+ //
+ Ret = BPSetPidTid( lpBpp );
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // If a CXF was provided, use it.
+ //
+ if ( pCxf ) {
+ lpBpp->Cxf = *pCxf;
+ }
+
+ //
+ // If this is a message BP and has not been parsed, load the message
+ // map and do the parsing now.
+ //
+ if ( lpBpp->fMsg && !lpBpp->fMsgParsed ) {
+ if ( (OSDGetMsgMap( lpBpp->hPid, lpBpp->hTid, &MsgMap ) != xosdNone) ||
+ !ParseBpMsg( lpBpp, MsgMap ) ) {
+ Ret = BPError;
+ }
+ }
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // Get the list of TMs in which the breakpoint can bind.
+ //
+ SaveDebuggerPdTd();
+ SetDebuggerPdTd( lpBpp );
+ Ret = BPGetTmList( lpBpp, &Tml, BpBuf, sizeof( BpBuf ) );
+ RestoreDebuggerPdTd();
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // Pick the TMs to use and bind the breakpoint(s).
+ //
+ Ret = BPBindFromTmList( lpBpp, &Tml, fOnList, BpBuf );
+ }
+
+ if ( Ret == BPCancel ) {
+ LLFDeletePlleFromLl( PlliBpList, hBpt );
+ }
+ }
+ }
+
+ return Ret;
+} /* BPBindHbptAddr */
+
+
+
+BPSTATUS
+BPGetTmList(
+ LPBPP lpBpp,
+ PTML pTml,
+ char *BpBuf,
+ int BufSize
+ )
+{
+ BPSTATUS Ret = BPNOERROR;
+ EESTATUS ERet;
+ char *szAddrExpr;
+ UINT stringindex;
+ TML Tml;
+ TML Tml2;
+ char *Source;
+ char *Exe;
+
+
+ //
+ // Get expression to parse.
+ //
+ if ( lpBpp->atmAddrCxt ) {
+
+ GetAtomName( lpBpp->atmAddrCxt, BpBuf, BufSize-1 );
+ szAddrExpr = &BpBuf[strlen(BpBuf)];
+ strcpy( szAddrExpr, lpBpp->szAddrExpr );
+
+ } else if ( lpBpp->atmCxtDef ) {
+
+ GetAtomName( lpBpp->atmCxtDef, BpBuf, BufSize-1 );
+ szAddrExpr = &BpBuf[strlen(BpBuf)];
+ strcpy( szAddrExpr, lpBpp->szAddrExpr );
+
+ } else if ( lpBpp->szAddrExpr ) {
+
+ strcpy( BpBuf, lpBpp->szAddrExpr );
+ szAddrExpr = BpBuf;
+
+ } else {
+ //
+ // No breakpoint expression!
+ //
+ Ret = BPError;
+ }
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // Try to parse the expression
+ //
+ ERet = EEParseBP( BpBuf, radix, fCaseSensitive, &(lpBpp->Cxf), &Tml, 0L, &stringindex, FALSE );
+ Ret = (ERet == EENOERROR ) ? BPNOERROR : BPError;
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // If There is a line number and there is a source file, but no
+ // module was specified, then look for any ambiguities (i.e. look
+ // for any modules that have the same source).
+ //
+ SplitExpression( BpBuf, &Source, &Exe );
+
+ if ( *szAddrExpr == '@' && Source && !Exe ) {
+
+ Ret = BPSearchContexts( lpBpp, szAddrExpr, &Tml, FALSE,
+ SymbolLoadingEnabled );
+
+ } else if ( lpBpp->atmAddrCxt == 0 &&
+ *szAddrExpr != '@' ) {
+
+ //
+ // If what we got is a thunk, then look for the implementation and try to
+ // set the BP there instead.
+ //
+ if ( BPIsThunk( lpBpp, Tml ) ) {
+
+ Tml2 = Tml;
+ Ret = BPSearchContexts( lpBpp, szAddrExpr, &Tml, TRUE, TRUE );
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // Found implementation. Discard TM for thunk and use the
+ // one for the implementation.
+ //
+ EEFreeTML( &Tml2 );
+
+ } else {
+
+ //
+ // Implementation not found, ask the user if she wants
+ // to set the breakpoint in the thunk.
+ //
+ if ( BPTCanIUseThunk( BpBuf ) ) {
+
+ Tml = Tml2;
+ Ret = BPNOERROR;
+
+ } else {
+
+ EEFreeTML( &Tml2 );
+ Ret = BPCancel;
+ }
+ }
+ }
+ }
+
+ } else if ( Ret == BPError ) {
+
+ //
+ // If no context was specified and this is not a line
+ // number BP, then search all contexts.
+ //
+ if ( ( lpBpp->atmAddrCxt == 0 && *szAddrExpr != '@' ) ||
+ lpBpp->atmCxtDef != 0 ||
+ lpBpp->atmAddrCxt != 0
+ ) {
+
+ Ret = BPSearchContexts( lpBpp,
+ szAddrExpr,
+ &Tml,
+ TRUE,
+ SymbolLoadingEnabled );
+ }
+ }
+ }
+
+ if ( Ret == BPNOERROR ) {
+ *pTml = Tml;
+ }
+
+ return Ret;
+} /* BPGetTmList */
+
+
+VOID
+SplitExpression(
+ char *BpBuf,
+ char **Source,
+ char **Exe
+ )
+{
+ char *p;
+ char *q;
+
+ *Source = NULL;
+ *Exe = NULL;
+
+ if ( p = strchr( BpBuf, OPENCONTEXTOP ) ) {
+
+ if ( p = strchr( p+1, ',' ) ) {
+
+ p++;
+ p += strspn( p, " \t" );
+ q = p + strcspn( p, /* { */ ",} " );
+
+ if ( q > p ) {
+ *Source = p;
+ }
+
+ q += strspn( q, " \t" );
+
+ if ( *q == ',' ) {
+
+ p = q+1;
+ p += strspn( p, " \t" );
+ q = p + strcspn( p, /* { */ "} " );
+
+ if ( q > p ) {
+ *Exe = p;
+ }
+ }
+ }
+ }
+} /* SplitExpression */
+
+VOID
+SearchContexts(
+ LPBPP lpBpp,
+ char *rgch,
+ char *szAddrExpr,
+ TML *pTml,
+ PHTM *ppTmList,
+ BOOL ImplementationOnly,
+ BOOL fLoad
+ )
+{
+
+ TML Tml = *pTml;
+ PHTM pTmList = *ppTmList;
+ TML Tml2;
+ PHTM pTmList2;
+ HEXE hexe = (HEXE) NULL;
+ char *p;
+ BOOLEAN fUse;
+ int ichExe;
+ EESTATUS ERet;
+ BPSTATUS Ret;
+ UINT stringindex;
+ int i;
+ LSZ ExeName;
+ SHE She;
+ LPDEBUGDATA DebugData;
+
+ p = rgch + strlen(rgch);
+
+ while ((( hexe = SHGetNextExe( hexe ) ) != 0) ) {
+
+ //
+ // We try a module only if its symbols are loaded. If the
+ // symbols are defered and the caller wants to load them,
+ // we load them.
+ //
+ fUse = FALSE;
+ DebugData = SHGetDebugData( hexe );
+ if ( DebugData ) {
+ switch ( DebugData->she ) {
+ case sheDeferSyms:
+ if ( fLoad ) {
+ SHWantSymbols( hexe );
+ DebugData = SHGetDebugData( hexe );
+ She = DebugData->she;
+ if ( She == sheNone ||
+ She == sheSymbolsConverted ) {
+ fUse = TRUE;
+ }
+ }
+ break;
+
+ case sheNone:
+ case sheSymbolsConverted:
+ fUse = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ( fUse ) {
+
+ *p = '\0';
+ ExeName = SHGetExeName( hexe );
+
+ strcat( rgch, ExeName );
+ ichExe = strlen(rgch);
+ rgch[ichExe] = CLOSECONTEXTOP;
+ rgch[ichExe+1] = 0;
+
+ _fstrncat( &rgch[ ichExe+1 ], szAddrExpr, strlen(szAddrExpr) );
+
+ ERet = EEParseBP( rgch, radix, fCaseSensitive, &(lpBpp->Cxf), &Tml2, 0L,
+ &stringindex, FALSE);
+ Ret = (ERet == EENOERROR ) ? BPNOERROR : BPError;
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // If interested in implementation, ignore thunks.
+ //
+ if ( !ImplementationOnly || !BPIsThunk( lpBpp, Tml2 ) ) {
+
+ if ( !pTmList ) {
+
+ Tml = Tml2;
+ pTmList = (HTM FAR *)MMLpvLockMb ( Tml.hTMList );
+
+ } else {
+
+ pTmList2 = (HTM FAR *)MMLpvLockMb ( Tml2.hTMList );
+
+ for (i=0; i < (int)Tml2.cTMListAct; i++ ) {
+ assert( Tml2.cTMListAct < Tml.cTMListMax );
+ pTmList[ Tml.cTMListAct++ ] = pTmList2[ i ];
+ pTmList2[i] = (HDEP) NULL;
+ }
+
+ MMbUnlockMb( Tml2.hTMList );
+
+ Tml2.cTMListAct = 0;
+ EEFreeTML( &Tml2 );
+ }
+ }
+
+ if ( fLoad ) {
+ break;
+ }
+ }
+ }
+ }
+
+ *pTml = Tml;
+ *ppTmList = pTmList;
+}
+
+BPSTATUS
+BPSearchContexts(
+ LPBPP lpBpp,
+ char * szAddrExpr,
+ PTML pTml,
+ BOOL ImplementationOnly,
+ BOOL LoadSymbols
+ )
+{
+ BPSTATUS Ret;
+ char rgch[256];
+ BOOL Ok;
+ char *p;
+ TML Tml;
+ PHTM pTmList;
+
+ //
+ // Initialize our context buffer
+ //
+ if ( lpBpp->atmCxtDef != 0 || lpBpp->atmAddrCxt != 0 ) {
+
+ if ( lpBpp->atmAddrCxt != 0 ) {
+ GetAtomName( lpBpp->atmAddrCxt, rgch, sizeof(rgch)-1 );
+ } else {
+ GetAtomName( lpBpp->atmCxtDef, rgch, sizeof(rgch)-1 );
+ }
+
+ //
+ // If the context does not have a module, try binding
+ // in all known modules.
+ //
+ Ok = FALSE;
+ if ( p = strchr( rgch, ',' ) ) {
+ if ( p = strpbrk( p+1, ",}" ) ) {
+ if ( *p == CLOSECONTEXTOP ) {
+ *p = ',';
+ *(p+1) = '\0';
+ Ok = TRUE;
+ } else {
+ p++;
+ p += strspn( p, " \t" );
+
+ if ( *p == CLOSECONTEXTOP ) {
+ *p = '\0';
+ Ok = TRUE;
+ }
+ }
+ }
+ }
+
+ if ( !Ok ) {
+ //
+ // Bogus context, get out
+ //
+ return BPError;
+ }
+
+ } else {
+
+ strcpy( rgch, "{,," );
+ }
+
+ //
+ // Get all the exes in which this breakpoint can bind.
+ //
+ Tml.hTMList = (HDEP) NULL;
+ pTmList = NULL;
+
+ SearchContexts( lpBpp,
+ rgch,
+ szAddrExpr,
+ &Tml,
+ &pTmList,
+ ImplementationOnly,
+ FALSE );
+ if ( !pTmList && LoadSymbols ) {
+ SearchContexts( lpBpp,
+ rgch,
+ szAddrExpr,
+ &Tml,
+ &pTmList,
+ ImplementationOnly,
+ TRUE );
+ }
+
+ if ( pTmList ) {
+
+ MMbUnlockMb( Tml.hTMList );
+ *pTml = Tml;
+ Ret = BPNOERROR;
+
+ } else {
+
+ Ret = BPError;
+ }
+
+ return Ret;
+}
+
+BPSTATUS
+BPBindFromTmList(
+ LPBPP lpBpp,
+ PTML pTml,
+ BOOL fOnList,
+ char *BpBuf
+ )
+{
+ BPSTATUS Ret;
+ PHTM pTmList;
+ LPBPP lpBpp2;
+ HBPT hBpt2;
+ BOOL fOnList2;
+ char rgch[256];
+ int i;
+ EEHSTR eehstr;
+ USHORT cb;
+ char * pch;
+
+
+ pTmList = (PHTM)MMLpvLockMb ( pTml->hTMList );
+
+ if (pTml->cTMListAct <= 1) {
+
+ Ret = BPBindTML( &pTmList[0], lpBpp, fOnList );
+
+ } else {
+
+ //
+ // The BP could bind to more than 1 exe. Let the
+ // user pick the exe(s) to use.
+ //
+ Ret = (BPSTATUS)BPTResolve( BpBuf, (PVOID)pTml, &(lpBpp->Cxf), TRUE );
+
+ if ( Ret == BPNOERROR ) {
+
+ for (i=0; i < (int)pTml->cTMListAct; i++ ) {
+
+ if ( i == (int)pTml->cTMListAct-1 ) {
+
+ lpBpp2 = lpBpp;
+ fOnList2 = fOnList;
+
+ } else {
+
+ hBpt2 = LLPlleCreate(PlliBpList);
+
+ if ( hBpt2 == NULL ) {
+ Ret == BPError;
+ break;
+ }
+
+ lpBpp2 = LLLpvFromPlle( hBpt2 );
+
+ memcpy( lpBpp2, lpBpp, sizeof( BPP ) );
+
+ if ( lpBpp->atmAddrCxt ) {
+ GetAtomName(lpBpp->atmAddrCxt, rgch, sizeof(rgch)-1);
+ lpBpp2->atmAddrCxt = AddAtom(rgch);
+ }
+
+ if ( lpBpp->szAddrExpr ) {
+ lpBpp2->szAddrExpr = _strdup( lpBpp->szAddrExpr );
+ }
+
+ if ( lpBpp->atmCxtDef ) {
+ GetAtomName(lpBpp->atmCxtDef, rgch, sizeof(rgch)-1);
+ lpBpp2->atmCxtDef = AddAtom(rgch);
+ }
+
+ if ( lpBpp->atmPassCount ) {
+ GetAtomName(lpBpp->atmPassCount, rgch, sizeof(rgch)-1);
+ lpBpp2->atmPassCount = AddAtom(rgch);
+ }
+
+ if ( lpBpp->szCmdLine ) {
+ lpBpp2->szCmdLine = _strdup( lpBpp->szCmdLine );
+ }
+
+ if ( lpBpp->atmExpr ) {
+ GetAtomName(lpBpp->atmExpr, rgch, sizeof(rgch)-1);
+ lpBpp2->atmExpr = AddAtom(rgch);
+ }
+
+ if ( lpBpp->atmData ) {
+ GetAtomName(lpBpp->atmData, rgch, sizeof(rgch)-1);
+ lpBpp2->atmData = AddAtom(rgch);
+ }
+
+ if ( lpBpp->atmRangeSize ) {
+ GetAtomName(lpBpp->atmRangeSize, rgch, sizeof(rgch)-1);
+ lpBpp2->atmRangeSize = AddAtom(rgch);
+ }
+
+ if ( lpBpp->atmHighlightFile ) {
+ GetAtomName(lpBpp->atmHighlightFile, rgch, sizeof(rgch)-1);
+ lpBpp2->atmHighlightFile = AddAtom(rgch);
+ }
+
+ Ret = BPAddToList( hBpt2, -1 );
+
+ if ( Ret != BPNOERROR ) {
+ break;
+ }
+
+ fOnList2 = TRUE;
+ }
+
+ //
+ // Replace the original address expression with the
+ // expression returned from the EE, which will be
+ // unambiguous.
+ //
+ Dbg(EEGetExprFromTM( &pTmList[i], &radix, &eehstr, &cb) == EENOERROR);
+ if (eehstr) {
+ if ( pch = MMLpvLockMb( eehstr ) ) {
+ if ( lpBpp2->szAddrExpr ) {
+ free(lpBpp2->szAddrExpr);
+ }
+ lpBpp2->szAddrExpr = _strdup(pch);
+ }
+ MMbUnlockMb( eehstr );
+ EEFreeStr( eehstr );
+ }
+
+ Ret = BPBindTML( &pTmList[i], lpBpp2, fOnList2 );
+
+ if ( Ret != BPNOERROR ) {
+ break;
+ }
+ }
+ }
+ }
+
+ MMbUnlockMb( pTml->hTMList );
+ EEFreeTML( pTml );
+
+ return Ret;
+}
+
+BOOLEAN BPIsThunk(
+ LPBPP lpBpp,
+ TML TMLT
+ )
+{
+
+ PHTM TMList;
+ PHTM pHtm;
+ USHORT bpsegtype = EECODE;
+ CXF Cxf;
+ UOFF32 Offset;
+ HSYM hSym;
+ BOOLEAN IsThunk = FALSE;
+
+ TMList = (PHTM)MMLpvLockMb ( TMLT.hTMList );
+
+ if (TMLT.cTMListAct == 1) {
+
+ pHtm = &TMList[0];
+
+ //
+ // Evaluate the address for the breakpoint.
+ //
+ SHSetCxtMod( &lpBpp->addr, SHpCXTFrompCXF(&(lpBpp->Cxf)));
+
+ if ( !EEvaluateTM(pHtm, SHpFrameFrompCXF(&(lpBpp->Cxf)), EEBPADDRESS) &&
+ !BPADDRFromTM(pHtm, &bpsegtype, &(lpBpp->addr))) {
+
+ memset( &Cxf, 0, sizeof(CXF) );
+ if ( SHSetCxt( (LPADDR)(&(lpBpp->addr)), (PCXT)(&Cxf) ) ) {
+
+ if (!ADDR_IS_LI (*SHpADDRFrompCXT (SHpCXTFrompCXF (&Cxf)))) {
+ SYUnFixupAddr (SHpADDRFrompCXT (SHpCXTFrompCXF (&Cxf)));
+ }
+
+ //
+ // Get the symbol at the given address.
+ //
+ Offset = SHGetNearestHSYM( SHpADDRFrompCXT(SHpCXTFrompCXF(&Cxf)),
+ SHHMODFrompCXT(SHpCXTFrompCXF(&Cxf)),
+ EECODE,
+ &hSym );
+
+ if ( Offset == 0 ) {
+ if ( SHIsThunk( hSym ) ) {
+ IsThunk = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ MMbUnlockMb( TMLT.hTMList );
+
+ return IsThunk;
+}
+
+
+
+
+BPSTATUS PASCAL BPBindTML(
+ PHTM pHtm,
+ LPBPP lpBpp,
+ BOOL fOnList
+ )
+
+{
+ extern STATUS status;
+ USHORT bpsegtype = EECODE;
+ char rgch[256];
+ char rgch2[256];
+ BPSTATUS Ret = BPNOERROR;
+ EESTATUS ERet;
+ int err;
+ XOSD Xosd;
+ BOOLEAN Ok;
+ int cch;
+ ADDR Addr;
+ CXT cxt;
+ FUNCTION_INFO FunctionInfo;
+
+ SHSetCxtMod( &lpBpp->addr, SHpCXTFrompCXF(&(lpBpp->Cxf)));
+
+ if ((ERet=EEvaluateTM(pHtm,SHpFrameFrompCXF(&(lpBpp->Cxf)),EEBPADDRESS)) ||
+ (ERet = BPADDRFromTM(pHtm, &bpsegtype, &(lpBpp->addr)))) {
+
+ Ret = (ERet == EENOERROR ) ? BPNOERROR : BPError;
+
+ } else {
+
+ //
+ // If a message breakpoint, we must set the breakpoint after
+ // the function prolog so we will be able to find the
+ // message value.
+ //
+ if ( lpBpp->fMsg ) {
+
+ WORD wLn;
+ SHOFF cbLn;
+ SHOFF dbLn;
+ CXF Cxf;
+ UOFF32 Offset;
+ HSYM hSym;
+
+ //
+ // Make sure that the address specified is a procedure.
+ //
+ Offset = 0;
+ memset( &Cxf, 0, sizeof(CXF) );
+ if ( SHSetCxt( (LPADDR)(&(lpBpp->addr)), (PCXT)&Cxf ) ) {
+
+ if (!ADDR_IS_LI (*SHpADDRFrompCXT (SHpCXTFrompCXF (&Cxf)))) {
+ SYUnFixupAddr (SHpADDRFrompCXT (SHpCXTFrompCXF (&Cxf)));
+ }
+
+ Offset = SHGetNearestHSYM( SHpADDRFrompCXT(SHpCXTFrompCXF(&Cxf)),
+ SHHMODFrompCXT(SHpCXTFrompCXF(&Cxf)),
+ EECODE,
+ &hSym );
+ }
+
+ if ( Offset != 0 ) {
+ Ret = BPBadExpression;
+ } else if (!SLLineFromAddr( &(lpBpp->addr), &wLn, &cbLn, &dbLn ) ) {
+ Ret = BPBadExpression;
+ } else {
+ lpBpp->addr.addr.off += cbLn - dbLn + 1;
+ if (!SLLineFromAddr( &(lpBpp->addr), &wLn, &cbLn, &dbLn)) {
+ Ret = BPBadExpression;
+ } else {
+ lpBpp->iHighlightLine = wLn;
+ }
+ }
+
+ }
+
+ if ( Ret == BPNOERROR ) {
+
+ SaveDebuggerPdTd();
+ SetDebuggerPdTd( lpBpp );
+
+ memset ( &cxt, 0, sizeof ( CXT ) );
+ if (!SHSetCxt ( &lpBpp->addr, &cxt )) {
+
+ Ret = BPBadExpression;
+
+ } else {
+
+ //
+ // make sure that we don't set a bp on the first
+ // instruction of the function. we must skip the prolog
+ //
+ Addr = lpBpp->addr;
+ SYFixupAddr( &Addr );
+
+ if ( OSDGetFunctionInfo( lpBpp->hPid, &Addr, &FunctionInfo ) ==
+ xosdNone ) {
+
+ if ( GetAddrOff(FunctionInfo.AddrPrologEnd) >
+ GetAddrOff( Addr ) ) {
+ GetAddrOff( Addr ) =
+ GetAddrOff(FunctionInfo.AddrPrologEnd);
+ SYUnFixupAddr( &Addr );
+ lpBpp->addr = Addr;
+ }
+
+ } else {
+
+ if ( !status.fSrcMode ) {
+ while( SHIsInProlog( &cxt ) ) {
+ cxt.addr.addr.off++;
+ }
+ }
+
+ lpBpp->addr = cxt.addr;
+ }
+
+ Addr = lpBpp->addr;
+
+ if ( SYFixupAddr( &Addr ) != xosdNone ) {
+ Ret = BPBadExpression;
+ }
+
+ }
+
+ RestoreDebuggerPdTd();
+
+ if ( Ret == BPNOERROR ) {
+
+ //
+ // We have now successfully computed an address for the
+ // breakpoint. Now if it is to be added -- do that and
+ // mark the breakpoint as having been added.
+ //
+
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateVirtual;
+
+ //
+ // If a memory breakpoint, try to bind the memory
+ // address expression
+ //
+ if ( !lpBpp->fMemory ) {
+
+ Ok = TRUE;
+
+ } else {
+
+ //
+ // Make sure there is some size to the memory breakpoint
+ //
+
+ if (lpBpp->cbDataSize == 0) {
+ lpBpp->cbDataSize = 1;
+ }
+
+#if 1
+
+ GetAtomName(lpBpp->atmData, rgch, sizeof(rgch)-1);
+ CPGetAddress( rgch,
+ &cch,
+ &(lpBpp->AddrMem),
+ radix,
+ &(lpBpp->Cxf),
+ FALSE,
+ FALSE);
+ Ok = TRUE;
+#else
+
+ if ( LppdCur && (LppdCur->pstate == psPreRunning) ) {
+ //
+ // At this point we most probably won't be able to
+ // read memory (or evaluate addresses) so defer it
+ // until we hit the address.
+ //
+ Ok = TRUE;
+
+ } else {
+
+ GetAtomName(lpBpp->atmData, rgch, sizeof(rgch)-1);
+ Ok = (CPGetAddress( rgch,
+ &cch,
+ &(lpBpp->AddrMem),
+ radix,
+ &(lpBpp->Cxf),
+ FALSE,
+ FALSE) == EENOERROR);
+
+ if ( !Ok ) {
+
+ //
+ // Could not get the memory address. This might
+ // be normal (e.g. trying to get the address
+ // of a local variable in another function), so
+ // we'll just defer it until we hit the address.
+ //
+ Ok = TRUE;
+ } else {
+
+ //
+ // Verify that the memory is readable.
+ //
+ lpBpp->Mem = (PBYTE)malloc( lpBpp->cbDataSize );
+ if ( !lpBpp->Mem ) {
+
+ Ok = FALSE;
+
+ } else {
+
+ SYFixupAddr( &(lpBpp->AddrMem) );
+ Ok = ( OSDSetAddr( lpBpp->hPid,
+ lpBpp->hTid,
+ (ADR)adrCurrent,
+ &(lpBpp->AddrMem)) ==
+ xosdNone);
+ if ( Ok ) {
+ SYUnFixupAddr( &(lpBpp->AddrMem) );
+ Ok = (OSDPtrace( osdReadBuf,
+ lpBpp->cbDataSize,
+ lpBpp->Mem,
+ lpBpp->hPid,
+ lpBpp->hTid) ==
+ (XOSD)lpBpp->cbDataSize);
+ }
+
+ if ( !Ok ) {
+ free( lpBpp->Mem );
+ lpBpp->Mem = NULL;
+ }
+
+ }
+
+ }
+
+ if ( !Ok ) {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateNotSet;
+
+ Ret = BPError;
+ }
+ }
+#endif
+
+ }
+
+
+ if ( Ok &&
+ fOnList &&
+ !lpBpp->fMarkAdd &&
+ (lpBpp->bpstate & bpstateEnabled)) {
+
+ // M00TODO -- deal with single thread breakpoints
+
+ BPInitBps( lpBpp, BpsBuffer, TRUE );
+ Xosd = OSDBreakpoint( lpBpp->hPid, BpsBuffer );
+
+ if ( Xosd == xosdNone ) {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateSet;
+ lpBpp->dwNotify = DwNotification(BpsBuffer)[0];
+
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount++;
+ }
+
+ } else {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateNotSet;
+ // lpBpp->fMarkAdd = TRUE;
+
+ Ret = BPError;
+ }
+ }
+
+ if (Ret == BPNOERROR ) {
+
+ BPBoundFixContext( lpBpp );
+
+ if (lpBpp->atmPassCount != 0) {
+
+ GetAtomName(lpBpp->atmPassCount, rgch, sizeof(rgch)-1);
+ lpBpp->iPassCount = CPGetNbr(rgch,
+ radix,
+ fCaseSensitive,
+ &(lpBpp->Cxf),
+ rgch2,
+ &err);
+ }
+ }
+ }
+ }
+ }
+
+ return Ret;
+}
+
+
+
+BPSTATUS PASCAL
+BPSetPidTid (
+ LPBPP lpBpp
+ )
+{
+ BPSTATUS Ret = BPNOERROR;
+ LPTD lptd = NULL;
+ LPPD lppd;
+ ADDR Addr;
+ HTID hTid;
+
+ //
+ // Make sure that the process number is valid. Set the
+ // breakpoint process id.
+ //
+ if ( lpBpp->fProcess ) {
+
+ //
+ // Get the process ID for the process
+ //
+ lppd = LppdOfIpid(lpBpp->iPid);
+
+ if ( lppd == NULL ) {
+ Ret = BPBadProcess;
+ } else {
+ lpBpp->hPid = lppd->hpid;
+ if ( lppd == LppdCur && !lpBpp->fThread ) {
+ lptd = LptdCur;
+ } else {
+ lptd = lppd->lptdList;
+ }
+ }
+
+ } else if ( LppdCur ) {
+
+ lpBpp->hPid = LppdCur->hpid;
+
+ } else {
+
+ Ret = BPBadProcess;
+ }
+
+ //
+ // Make sure that the thread number is valid. Set the
+ // breakpoint thread id.
+ //
+ if ( lpBpp->fThread ) {
+
+ //
+ // Get the thread ID for the thread
+ //
+ if ( !lptd ) {
+ lptd = LppdCur->lptdList;
+ }
+
+ for (; lptd != NULL; lptd = lptd->lptdNext) {
+ if (lptd->itid == lpBpp->iTid) {
+ lpBpp->hTid = lptd->htid;
+ hTid = lptd->htid;
+ break;
+ }
+ }
+
+ if ( lptd == NULL ) {
+ Ret = BPBadThread;
+ }
+
+ } else {
+
+ if ( !lptd ) {
+ lptd = LptdCur;
+ }
+
+ if ( lptd ) {
+
+ lpBpp->hTid = 0;
+ hTid = lptd->htid;
+
+ } else {
+
+ Ret = BPBadThread;
+ }
+ }
+
+ //
+ // Obtain a context based on the process & thread
+ //
+ if ( Ret == BPNOERROR ) {
+ OSDGetAddr( lpBpp->hPid, hTid, adrPC, &Addr );
+ if ( (Addr.addr.off == 0) && (Addr.addr.seg == 0) ) {
+ OSDGetAddr( lpBpp->hPid, hTid, adrPC, &Addr );
+ }
+ if ( ! ADDR_IS_LI ( Addr ) ) {
+ SYUnFixupAddr ( &Addr );
+ }
+ SHSetCxt( &Addr, SHpCxtFrompCxf( &(lpBpp->Cxf) ) );
+ OSDSetFrame( lpBpp->hPid, hTid, SHpFrameFrompCxf ( &lpBpp->Cxf ) );
+ }
+
+ return Ret;
+}
+
+
+
+/*** BPFormatHbpt
+**
+** Synopsis:
+** bpstatus = BPFormatHbpt(hBpt, lpb, cb, flags)
+**
+** Entry:
+** hBpt - Handle to breakpoint to be formated
+** lpb - pointer to buffer to place string in
+** cb - size of buffer in bytes
+** flags - flags controling the formatting of the breakpoint
+**
+** Returns:
+** Error code if needed and string in buffer pointed by lpb
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL
+BPFormatHbpt(
+ HBPT hBpt,
+ char FAR * lpb,
+ UINT cb,
+ UINT flags)
+{
+ char rgch[256];
+ char rgch2[256];
+ LPBPP lpBpp;
+ BOOL fSpace = FALSE;
+
+
+ // M00BUG -- verify hBpt is in list of breakpoints
+
+ lpBpp = LLLpvFromPlle(hBpt);
+
+ /*
+ ** Initialize to a null string
+ */
+
+ *lpb = 0;
+
+ /*
+ ** Check to see if item counts are to be included
+ */
+
+ if (flags & BPFCF_ITEM_COUNT) {
+ sprintf(rgch, "%d ", lpBpp->iBreakpointNum);
+ _fstrcat(lpb, rgch);
+ }
+
+ /*
+ ** If we are doing dialog box interfacing --- add 'a' and 'd' to mark
+ ** items as to be added or to be deleted
+ */
+
+ if (flags & BPFCF_ADD_DELETE) {
+
+ if ( lpBpp->fReplacement ) {
+ _fstrcat(lpb, "c");
+ } else {
+ _fstrcat(lpb, " ");
+ }
+
+ if (lpBpp->fMarkAdd && !lpBpp->fReplacement) {
+ _fstrcat(lpb, "a");
+ } else {
+ _fstrcat(lpb, " ");
+ }
+
+ if (lpBpp->fMarkDelete) {
+ _fstrcat(lpb, "d");
+ } else {
+ _fstrcat(lpb, " ");
+ }
+
+ _fstrcat(lpb, " ");
+ }
+
+ /*
+ **
+ */
+
+ if (lpBpp->bpstate & bpstateEnabled) {
+ if (lpBpp->fMarkDisable)
+ _fstrcat(lpb, "D");
+ else
+ _fstrcat(lpb, "E");
+ } else {
+ if (lpBpp->fMarkEnable)
+ _fstrcat(lpb, "E");
+ else
+ _fstrcat(lpb, "D");
+ }
+
+ switch ( lpBpp->bpstate & bpstateSets ) {
+ case bpstateNotSet:
+ _fstrcat(lpb, "U ");
+ break;
+
+ case bpstateVirtual:
+ if (lpBpp->bpstate & bpstateEnabled) {
+ _fstrcat(lpb, "V ");
+ } else {
+ _fstrcat(lpb, " ");
+ }
+ break;
+
+ case bpstateSet:
+ _fstrcat(lpb, " ");
+ break;
+
+ default:
+ assert(FALSE);
+ break;
+ }
+
+ /*
+ ** Now check each field and append as appropriate
+ */
+
+ if (lpBpp->atmAddrCxt != 0) {
+ assert(lpBpp->szAddrExpr != NULL);
+
+ GetAtomName(lpBpp->atmAddrCxt, rgch, sizeof(rgch));
+ BPShortenContext( rgch, rgch2 );
+ if (strlen(rgch2) > cb) {
+ return BPError;
+ }
+ _fstrcat(lpb, rgch2);
+ cb -= strlen(rgch2);
+
+ } else if (lpBpp->atmCxtDef != 0) {
+
+ GetAtomName(lpBpp->atmCxtDef, rgch, sizeof(rgch));
+ BPShortenContext( rgch, rgch2 );
+ if (strlen(rgch2) > cb) {
+ return BPError;
+ }
+ _fstrcat(lpb, rgch2);
+ cb -= strlen(rgch2);
+ }
+
+ if (lpBpp->szAddrExpr != 0) {
+ strcpy( rgch, lpBpp->szAddrExpr );
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+ fSpace = TRUE;
+ }
+
+
+ /*
+ ** Put out the expression if it exists
+ */
+
+ if (lpBpp->atmExpr != 0) {
+ BPQueryExprOfHbpt( hBpt, rgch, sizeof(rgch));
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat(lpb, " ?\"");
+ cb -= 4;
+ } else {
+ _fstrcat(lpb, "?\"");
+ cb -= 3;
+ }
+
+ _fstrcat(lpb, rgch);
+ _fstrcat(lpb, "\"");
+ cb -= strlen(rgch);
+ fSpace = TRUE;
+ }
+
+ /*
+ ** Put out the address expression if it exists
+ */
+
+ if (lpBpp->atmData != 0) {
+ GetAtomName(lpBpp->atmData, rgch, sizeof(rgch));
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat(lpb, " =\"");
+ cb -= 4;
+ } else {
+ _fstrcat(lpb, "=\"");
+ cb -= 3;
+ }
+
+ _fstrcat(lpb, rgch);
+ _fstrcat(lpb, "\"");
+ cb -= strlen(rgch);
+ fSpace = TRUE;
+
+ }
+
+ /*
+ ** Put out the range if it exists
+ */
+
+ if (lpBpp->atmRangeSize != 0) {
+ BPQueryMemorySizeOfHbpt( hBpt, rgch, sizeof(rgch));
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat(lpb, " /R");
+ cb -= 3;
+ } else {
+ _fstrcat(lpb, "/R");
+ cb -= 2;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+ fSpace = TRUE;
+ }
+
+ /*
+ **
+ */
+
+ if (!lpBpp->fCodeAddr && (lpBpp->BpType &
+ (BP_DATA_READ | BP_DATA_WRITE | BP_EXECUTE)) ) {
+ if (fSpace) {
+ _fstrcat(lpb, " /A");
+ cb -= 3;
+ } else {
+ _fstrcat(lpb, "/A");
+ cb -= 2;
+ }
+
+ if (lpBpp->BpType & BP_DATA_READ) {
+ _fstrcat(lpb, "r");
+ cb--;
+ }
+
+ if (lpBpp->BpType & BP_DATA_WRITE) {
+ _fstrcat(lpb, "w");
+ cb--;
+ }
+
+ if (lpBpp->BpType & BP_EXECUTE) {
+ _fstrcat(lpb, "e");
+ cb--;
+ }
+
+ fSpace = TRUE;
+ }
+
+ //
+ // Add message if it exists
+ //
+ if ( lpBpp->fMsg && lpBpp->atmMsg ) {
+ GetAtomName(lpBpp->atmMsg, rgch, sizeof(rgch));
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat(lpb, " /M");
+ cb -= 3;
+ } else {
+ _fstrcat(lpb, "/M");
+ cb -= 2;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+ fSpace = TRUE;
+ }
+
+ /*
+ ** Add the command set if one exists
+ */
+
+ if (lpBpp->szCmdLine ) {
+ strcpy(rgch, lpBpp->szCmdLine);
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat( lpb, " /C\"");
+ cb -= 5;
+ } else {
+ _fstrcat( lpb, "/C\"");
+ cb -= 4;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+
+ _fstrcat(lpb, "\"");
+ fSpace = TRUE;
+ }
+
+ /*
+ ** Add pass count if exists
+ */
+
+ BPQueryPassCntOfHbpt( hBpt, rgch, sizeof(rgch)-1);
+ if (rgch[0] != 0) {
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat( lpb, " /P");
+ cb -= 3;
+ } else {
+ _fstrcat( lpb, "/P");
+ cb -= 2;
+ }
+ _fstrcat( lpb, rgch );
+ cb -= strlen(rgch);
+
+
+ if ( !(flags & BPFCF_WRKSPACE) ) {
+ BPQueryPassLeftOfHbpt( hBpt, rgch, sizeof(rgch)-1);
+ if (rgch[0] != 0) {
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ _fstrcat( lpb, "(");
+ _fstrcat( lpb, rgch );
+ _fstrcat( lpb, ")" );
+ cb -= (strlen(rgch) + 2);
+ }
+ }
+ fSpace = TRUE;
+ }
+
+ if ( BPQueryProcessOfHbpt( hBpt, rgch, sizeof(rgch) ) == BPNOERROR ) {
+ if ( *rgch != '\0' ) {
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat( lpb, " /H");
+ cb -= 3;
+ } else {
+ _fstrcat( lpb, "/H");
+ cb -= 2;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+
+ fSpace = TRUE;
+ }
+ }
+
+ //
+ // Add the thread if specified
+ //
+ if (lpBpp->fThread ) {
+
+ sprintf( rgch, "%d", lpBpp->iTid );
+ if (strlen(rgch)+5 > cb) {
+ return BPError;
+ }
+
+ if (fSpace) {
+ _fstrcat( lpb, " /T");
+ cb -= 3;
+ } else {
+ _fstrcat( lpb, "/T");
+ cb -= 2;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+
+ fSpace = TRUE;
+ }
+
+ //
+ // Add the quiet defer switch if set
+ //
+ if (lpBpp->fQuiet) {
+
+ if ( fSpace ) {
+ _fstrcat(lpb, " /Q");
+ cb -= 3;
+ } else {
+ _fstrcat(lpb, "/Q");
+ cb -= 2;
+ }
+
+ fSpace = TRUE;
+ }
+
+
+ //
+ // Add the WndProc switch if set and caller wants it
+ //
+ if ( flags & BPFCF_WNDPROC ) {
+ if (lpBpp->fWndProc) {
+ if ( fSpace ) {
+ _fstrcat(lpb, " /W");
+ cb -= 3;
+ } else {
+ _fstrcat(lpb, "/W");
+ cb -= 2;
+ }
+
+ fSpace = TRUE;
+ }
+ }
+
+ return BPNOERROR;
+}
+
+
+/*** FParseableSz
+**
+** Synopsis:
+** bool = FParseableSz(sz)
+**
+** Entry:
+** sz - string to be tested
+**
+** Returns:
+** TRUE if it is a parsable expression else FALSE
+**
+** Description:
+** This function will check to see if the expression evaluator can
+** actually parse the requested expression. The expression is parsed
+** and then the resultant TM is freed
+**
+** M00TODO -- did we use all of it.
+*/
+
+static BOOL FParseableSz(char FAR * sz)
+{
+ HTM hTM;
+ unsigned int ich;
+
+ if (EEParse(sz, radix, fCaseSensitive, &hTM, &ich) != EENOERROR) {
+ return(FALSE);
+ }
+ EEFreeTM(&hTM);
+
+ return TRUE;
+} /* FParseableSz() */
+
+BPSTATUS PASCAL
+BPAddHighLight( LPBPP lpBpp )
+{
+ char rgchSource[256];
+ BOOLEAN fRemoveHighLight = TRUE;
+ BOOLEAN fRemoveAsmHighLight = TRUE;
+ INT line = 0;
+ ATOM atm = 0;
+
+
+ if (!(lpBpp->bpstate & bpstateNotSet)) {
+ if (!BPCBGetSourceFromAddr( &(lpBpp->addr),
+ rgchSource,
+ sizeof(rgchSource),
+ &line ) ) {
+ if (lpBpp->fHighlight) {
+ GetAtomName(lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ BPCBSetHighlight((char far *)rgchSource, (UINT)(lpBpp->iHighlightLine), TRUE, FALSE, (WORD)BRKPOINT_STATUS);
+ lpBpp->fHighlight = FALSE;
+ DeleteAtom(lpBpp->atmHighlightFile);
+ lpBpp->atmHighlightFile = atmNull;
+ lpBpp->iHighlightLine = (USHORT) -1;
+ }
+ return 0;
+ }
+ atm = AddAtom( rgchSource );
+ }
+ else {
+ atm = lpBpp->atmHighlightFile;
+ line = lpBpp->iHighlightLine;
+ GetAtomName(lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ }
+
+ if (lpBpp->fHighlight) {
+ if ( !lpBpp->fMarkDisable ) {
+ //
+ // Should highlight line now
+ //
+ if (( atm != lpBpp->atmHighlightFile ) || ((UINT)line != lpBpp->iHighlightLine)) {
+ if (atm != lpBpp->atmHighlightFile) {
+ GetAtomName(lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ BPCBSetHighlight((char far *)rgchSource, (UINT)(lpBpp->iHighlightLine), FALSE, FALSE, (WORD)BRKPOINT_STATUS );
+ DeleteAtom(lpBpp->atmHighlightFile);
+ }
+ else {
+ BPCBSetHighlight((char far *)rgchSource, (UINT)(lpBpp->iHighlightLine), FALSE, FALSE, (WORD)BRKPOINT_STATUS);
+ }
+ BPCBSetHighlight((char far *)rgchSource, (UINT)line, TRUE, FALSE, (WORD)BRKPOINT_STATUS);
+ lpBpp->atmHighlightFile = atm;
+ lpBpp->iHighlightLine = line;
+ }
+ else {
+ BPCBSetHighlight((char far *)rgchSource, (UINT)line, TRUE, FALSE, (WORD)BRKPOINT_STATUS);
+ }
+ }
+ else {
+ //
+ // Don't highlight now, but remember what must
+ // be hilighted.
+ //
+ lpBpp->atmHighlightFile = atm;
+ lpBpp->iHighlightLine = line;
+ }
+ }
+ else {
+ BPCBSetHighlight((char far *)rgchSource, (UINT)line, TRUE, FALSE, (WORD)BRKPOINT_STATUS );
+ lpBpp->fHighlight = TRUE;
+ lpBpp->atmHighlightFile = atm;
+ lpBpp->iHighlightLine = line;
+ }
+
+ return 0;
+}
+
+BPSTATUS PASCAL
+BPRemoveHighLight( LPBPP lpBpp )
+{
+ HBPT hBpt1;
+ LPBPP lpBpp1;
+ char rgchSource[256];
+ char rgchSource1[256];
+ BOOLEAN fRemoveHighLight = TRUE;
+ BOOLEAN fRemoveAsmHighLight = TRUE;
+ INT line;
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+
+ line = lpBpp->iHighlightLine;
+ GetAtomName( lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ _splitpath( rgchSource, drive, dir, fname, ext );
+ wsprintf( rgchSource, "%s%s", fname, ext );
+
+ //
+ // We should only remove the highlight if
+ // no other breakpoint is set on the same
+ // line.
+
+ //
+ // Traverse the breakpoint list looking for someone with the
+ // same highlight.
+ //
+ hBpt1 = LLPlleFindNext( PlliBpList, (HBPT) NULL);
+ while (hBpt1 != NULL) {
+ lpBpp1 = LLLpvFromPlle( hBpt1 );
+
+ if ( lpBpp1->iHighlightLine == (UINT)line &&
+ !(lpBpp1->bpstate & bpstateDeleted)) {
+
+ //
+ // If there is another breakpoint in same
+ // source, we don't remove source hilight
+ //
+ if ( fRemoveHighLight ) {
+ GetAtomName( lpBpp1->atmHighlightFile, rgchSource1, sizeof(rgchSource1));
+ _splitpath( rgchSource1, drive, dir, fname, ext );
+ wsprintf( rgchSource1, "%s%s", fname, ext );
+ if (_stricmp( rgchSource, rgchSource1 ) == 0) {
+ fRemoveHighLight = FALSE;
+ }
+ }
+
+ //
+ // If there is another breakpoint in same
+ // address, we don't remove the asm hilight
+ //
+ if ( FAddrsEq( lpBpp->addr, lpBpp1->addr ) ) {
+ fRemoveAsmHighLight = FALSE;
+ }
+ }
+
+ hBpt1 = LLPlleFindNext( PlliBpList, hBpt1 );
+ }
+
+ //
+ // Remove the highlight if we're supposed to.
+ //
+ if ( fRemoveHighLight ) {
+ BPCBSetHighlight(rgchSource, line, FALSE, FALSE, BRKPOINT_STATUS );
+ }
+
+ if ( fRemoveAsmHighLight ) {
+ BPCBSetHighlight(rgchSource, line, FALSE, FALSE, UBP_LINE );
+ }
+
+ return BPNOERROR;
+
+}
+
+BPSTATUS PASCAL
+BPHighlightSourceFile( char *sname )
+{
+ HBPT hBpt;
+ LPBPP lpBpp;
+ char rgchSource[256];
+ char rgch[256];
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+
+ _splitpath( sname, drive, dir, fname, ext );
+ wsprintf( rgch, "%s%s", fname, ext );
+ hBpt = LLPlleFindNext( PlliBpList, (HBPT) NULL);
+ SaveDebuggerPdTd();
+ while (hBpt != NULL) {
+ lpBpp = LLLpvFromPlle( hBpt );
+ GetAtomName( lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ _splitpath( rgchSource, drive, dir, fname, ext );
+ wsprintf( rgchSource, "%s%s", fname, ext );
+ if (_stricmp(rgch,rgchSource)==0) {
+ BPAddHighLight( lpBpp );
+ }
+ hBpt = LLPlleFindNext( PlliBpList, hBpt );
+ }
+ RestoreDebuggerPdTd();
+ return BPNOERROR;
+}
+
+/*** BPCommit
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL BPCommit()
+{
+ HBPT hBpt;
+ HBPT hBpt2;
+ LPBPP lpBpp;
+ char rgchSource[256];
+ INT line;
+ BOOLEAN fHighLight;
+ XOSD Xosd;
+ ADDR AddrHbpt;
+
+ /*
+ ** Get the first item and walk the list of all breakpoints
+ ** looking for those marked for change
+ */
+
+ hBpt = LLPlleFindNext( PlliBpList, (HBPT) NULL);
+
+ SaveDebuggerPdTd();
+
+ while (hBpt != NULL) {
+
+ lpBpp = LLLpvFromPlle( hBpt );
+
+
+ //
+ // If Marked for change, replace it
+ //
+ if ( lpBpp->fMarkChange && !lpBpp->fMarkDelete ) {
+ BPReplace( lpBpp );
+ }
+
+ lpBpp->fNewMark = FALSE;
+
+ if ( lpBpp->fMarkAdd || lpBpp->fMarkDelete ||
+ lpBpp->fMarkEnable || lpBpp->fMarkDisable ) {
+
+ SetDebuggerPdTd( lpBpp );
+ }
+
+ if (lpBpp->fMarkAdd) {
+
+ assert( lpBpp->fMarkDelete == FALSE );
+
+ /*
+ ** Set it at the low level if the state is correct
+ **
+ ** Correct state requires:
+ ** 1. That bpstateEnable be set
+ ** 2. The state is virutal (i.e. we have an address)
+ */
+
+ if (lpBpp->bpstate == (bpstateVirtual | bpstateEnabled)) {
+
+ if ( lpBpp->fMarkDisable ) {
+ Xosd = xosdNone;
+ lpBpp->bpstate = bpstateVirtual;
+ } else {
+ BPInitBps( lpBpp, BpsBuffer, TRUE );
+ Xosd = OSDBreakpoint( lpBpp->hPid, BpsBuffer );
+ if ( Xosd == xosdNone ) {
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateSet;
+ lpBpp->dwNotify = DwNotification(BpsBuffer)[0];
+
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount++;
+ }
+ }
+ }
+
+ if ( Xosd == xosdNone ) {
+ RestoreDebuggerPdTd();
+ BPAddHighLight( lpBpp ); //*
+ }
+
+ /*
+ ** Clear the notation that it was marked as added
+ */
+
+ lpBpp->fMarkAdd = FALSE;
+ lpBpp->fMarkDisable = FALSE;
+
+ } else if (lpBpp->bpstate == (bpstateNotSet | bpstateEnabled)) {
+ if (lpBpp->iHighlightLine != (USHORT) -1) {
+ GetAtomName( lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ RestoreDebuggerPdTd();
+
+ BPCBSetHighlight(rgchSource, lpBpp->iHighlightLine, TRUE, FALSE, UBP_LINE );
+ lpBpp->fHighlight = TRUE;
+ }
+ }
+
+
+
+ } else if (lpBpp->fMarkDelete) {
+
+ if ( lpBpp->fMarkChange ) {
+ LLFDeletePlleFromLl( PlliBpList, lpBpp->ChangeHbpt );
+ lpBpp->fMarkChange = FALSE;
+ lpBpp->ChangeHbpt = NULL;
+ }
+
+ hBpt2 = hBpt;
+
+ if (lpBpp->bpstate == (bpstateSet | bpstateEnabled)) {
+
+ BPInitBps( lpBpp, BpsBuffer, FALSE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone );
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount--;
+ }
+ }
+ /**
+ ** M00TODO -- other states
+ */
+
+ if ( lpBpp->fHighlight ) {
+
+ //
+ // Remember our source, line & address. We'll need these after
+ // deleting the breakpoint, to see if someone has a
+ // brekpoint on the same source/line.
+ //
+ GetAtomName( lpBpp->atmHighlightFile, rgchSource, sizeof(rgchSource));
+ line = (int)(lpBpp->iHighlightLine);
+ memcpy( &AddrHbpt, &(lpBpp->addr), sizeof( ADDR ) );
+ lpBpp->fHighlight = FALSE;
+ fHighLight = TRUE;
+
+ } else {
+ fHighLight = FALSE;
+ }
+
+#if 0
+ if (lpBpp->Mem != NULL ) {
+ free( lpBpp->Mem );
+ lpBpp->Mem = NULL;
+ }
+#endif
+
+ hBpt = LLPlleFindNext( PlliBpList, hBpt);
+ RestoreDebuggerPdTd();
+ lpBpp->bpstate |= bpstateDeleted;
+ BPRemoveHighLight( lpBpp ); //*
+ LLFDeletePlleFromLl( PlliBpList, hBpt2 );
+ continue;
+
+ /*
+ ** The breakpoint is marked as we are to make it disabled.
+ ** The following steps must therefore be taken:
+ **
+ ** 1. If the breakpoint is currently set then it must be
+ ** unset.
+ ** 2. The internal state of the breakpoint must be re-marked
+ **
+ */
+
+ } else if (lpBpp->fMarkDisable) {
+ assert( lpBpp->fMarkEnable == FALSE);
+
+ if ( lpBpp->bpstate == (bpstateSet | bpstateEnabled) ) {
+
+ BPInitBps( lpBpp, BpsBuffer, FALSE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone);
+
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateVirtual;
+
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount--;
+ }
+
+ RestoreDebuggerPdTd();
+ if (BPCBGetSourceFromAddr( &(lpBpp->addr), rgchSource, sizeof(rgchSource), &line )) {
+ BPCBSetHighlight((char far *)rgchSource, (UINT)line, FALSE, FALSE, (WORD)BRKPOINT_STATUS);
+ }
+ }
+
+ lpBpp->bpstate &= ~bpstateEnabled;
+ lpBpp->fMarkDisable = FALSE;
+
+ /*
+ ** The breakpoint is marked to be enabled. The following
+ ** steps need to be taken. Only enable if there is a live
+ ** debuggee
+ **
+ ** 1. If the breakpoint does not have an address then
+ ** we need to try and get one (???)
+ ** 2. If we have an address then we need to set the breakpoint
+ ** 3. The internal state of the breakpoint must be reset
+ */
+ } else if (lpBpp->fMarkEnable) {
+ if (DebuggeeAlive()) {
+ assert ((lpBpp->bpstate & bpstateEnabled) == FALSE );
+
+ if ( lpBpp->bpstate == bpstateNotSet ) {
+ BPBindHbpt( hBpt, NULL );
+ }
+
+ if ( lpBpp->bpstate == bpstateVirtual) {
+
+ BPInitBps( lpBpp, BpsBuffer, TRUE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone);
+
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateSet;
+ lpBpp->dwNotify = DwNotification(BpsBuffer)[0];
+
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount++;
+ }
+ }
+ RestoreDebuggerPdTd();
+ if (BPCBGetSourceFromAddr( &(lpBpp->addr), rgchSource,
+ sizeof(rgchSource), &line )) {
+ BPCBSetHighlight((char far *)rgchSource,
+ (UINT)line,
+ TRUE,
+ FALSE,
+ (WORD)BRKPOINT_STATUS);
+ }
+ }
+ lpBpp->bpstate |= bpstateEnabled;
+ lpBpp->fMarkEnable = FALSE;
+ }
+
+ /*
+ ** Move to the next breakpoint
+ */
+
+ hBpt = LLPlleFindNext( PlliBpList, hBpt );
+ }
+
+ RestoreDebuggerPdTd();
+
+ return BPNOERROR;
+} /* BPCommit() */
+
+/*** BPUnCommit
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+BPSTATUS PASCAL
+BPUnCommit(
+ VOID
+ )
+{
+ HBPT hBpt;
+ HBPT hBpt2;
+ LPBPP lpBpp;
+
+ /*
+ ** Get the first item and walk the list of all breakpoints looking
+ ** for those marked for change
+ */
+
+ hBpt = LLPlleFindNext( PlliBpList, (HBPT) NULL );
+
+ while ( hBpt != NULL ) {
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ if ( lpBpp->fNewMark ) {
+
+ if ( lpBpp->fMarkChange ) {
+ //
+ // Remove replacement BP
+ //
+ LLFDeletePlleFromLl( PlliBpList, lpBpp->ChangeHbpt );
+ lpBpp->ChangeHbpt = NULL;
+ lpBpp->fMarkChange = FALSE;
+ }
+
+ if (lpBpp->fMarkAdd) {
+ assert( llpBpp->fMarkDelete == FALSE );
+
+ hBpt2 = hBpt;
+ hBpt = LLPlleFindNext( PlliBpList, hBpt );
+
+ LLFDeletePlleFromLl( PlliBpList, hBpt2 );
+ continue;
+
+ } else if (lpBpp->fMarkDelete) {
+ /*
+ ** We are retracting a deletion of a breakpoint.
+ ** Just mark it as no longer being a canidate for
+ ** deletion
+ */
+
+ lpBpp->fMarkDelete = FALSE;
+ }
+
+ //
+ // Fix the enable/disable marks
+ // kkk
+ if (lpBpp->bpstate & bpstateEnabled) {
+ lpBpp->fMarkEnable = TRUE;
+ lpBpp->fMarkDisable = FALSE;
+ } else {
+ lpBpp->fMarkEnable = FALSE;
+ lpBpp->fMarkDisable = TRUE;
+ }
+
+ lpBpp->fNewMark = FALSE;
+ }
+ /*
+ ** Move to the next breakpoint
+ */
+
+ hBpt = LLPlleFindNext( PlliBpList, hBpt );
+ }
+
+ return BPNOERROR;
+} /* BPUnCommit() */
+
+/*** BPSetHpid
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL BPSetHpid( HBPT hBpt, HPID hPid)
+{
+ LPBPP lpBpp;
+
+ lpBpp = LLLpvFromPlle( hBpt );
+ lpBpp->hPid = hPid;
+
+ return BPNOERROR;
+} /* BPSetHpid() */
+
+BPSTATUS PASCAL
+BPGetHpid(
+ HBPT hBpt,
+ HPID *phPid
+ )
+/*++
+
+Routine Description:
+
+ Retrieve the HPID associated with a breakpoint.
+
+Arguments:
+
+ hBpt - Supplies a handle to the breakpoint to be queried
+ phPid - Supplies a pointer to a buffer to copy the HPID to
+
+Return Value:
+
+ BPNOERROR
+
+--*/
+{
+ LPBPP lpBpp;
+
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ //
+ // If the breakpoint is not instantiated, the hPid may not be
+ // correct.
+ //
+ if ( (lpBpp->bpstate & bpstateSets) == bpstateNotSet ) {
+ BPSetPidTid( lpBpp );
+ }
+
+ *phPid = lpBpp->hPid;
+
+ return BPNOERROR;
+}
+
+
+BPSTATUS PASCAL
+BPGetIpid(
+ HBPT hBpt,
+ UINT *piPid
+ )
+/*++
+
+Routine Description:
+
+ Retrieve the IPID associated with a breakpoint.
+
+Arguments:
+
+ hBpt - Supplies a handle to the breakpoint to be queried
+ piPid - Supplies a pointer to a buffer to copy the IPID to
+
+Return Value:
+
+ BPNOERROR
+
+--*/
+{
+ LPBPP lpBpp;
+
+ lpBpp = LLLpvFromPlle( hBpt );
+ *piPid = lpBpp->iPid;
+
+ return BPNOERROR;
+}
+
+
+BPSTATUS PASCAL
+BPGetHtid(
+ HBPT hBpt,
+ HTID *phTid
+ )
+/*++
+
+Routine Description:
+
+ Retrieve the HTID associated with a breakpoint.
+
+Arguments:
+
+ hBpt - Supplies a handle to the breakpoint to be queried
+ phTid - Supplies a pointer to a buffer to copy the HTID to
+
+Return Value:
+
+ BPNOERROR
+
+--*/
+{
+ LPBPP lpBpp;
+
+ lpBpp = LLLpvFromPlle( hBpt );
+ *phTid = lpBpp->fThread ? lpBpp->hTid : 0;
+
+ return BPNOERROR;
+}
+
+
+
+
+/*** BPSetTmp
+**
+** Synopsis:
+** bpstatus = BPSetTmp(lpaddr, hPid, hTid, phBpt)
+**
+** Entry:
+** lpaddr - Pointer to address structure to set breakpoint at
+** hPid - Handle to PID to set breakpoint in
+** hTid - Handlt to TID to set breakpoint in
+** phBpt - Optional return location for handle to breakpoint set
+**
+** Returns:
+** status of the operation. BPNOERROR if no errors occured
+**
+** Description:
+** This routine will create a breakpoint structure and add to the list
+** of all breakpoints. The type of breakpoint to be created is of
+** class BP_TEMPORARY. These will normally be cleared by the debugger
+** if another event occurs or the breakpoint is hit.
+**
+*/
+
+BPSTATUS PASCAL
+BPSetTmp(
+ LPADDR lpaddr,
+ HPID hPid,
+ HTID hTid,
+ HBPT FAR * phBpt
+ )
+{
+ HBPT hBpt = LLPlleCreate(PlliBpList);
+ LPBPP lpBpp;
+ BPSTATUS Ret = BPNOERROR;
+
+ if (hBpt == NULL)
+ return BPOOMemory;
+
+ *phBpt = hBpt;
+ lpBpp = LLLpvFromPlle(hBpt);
+
+ _fmemset(lpBpp, 0, sizeof(*lpBpp));
+
+ lpBpp->hPid = hPid;
+ lpBpp->hTid = hTid;
+ lpBpp->fTemporary = TRUE;
+ lpBpp->addr = *lpaddr;
+ lpBpp->fCodeAddr = TRUE;
+
+ SaveDebuggerPdTd();
+ SetDebuggerPdTd( lpBpp );
+
+ BPInitBps( lpBpp, BpsBuffer, TRUE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone);
+ RestoreDebuggerPdTd();
+
+ lpBpp->bpstate = bpstateEnabled | bpstateSet;
+ lpBpp->dwNotify = DwNotification(BpsBuffer)[0];
+
+ LLInsertPlleInLl( PlliBpList, hBpt, 0);
+
+ return Ret;
+} /* BPSetTmp() */
+
+/*** BPClearAllTmp
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL
+BPClearAllTmp(
+ HPID hPid,
+ HTID hTid
+ )
+{
+ HBPT hBpt;
+ HBPT hBpt2;
+ LPBPP lpBpp;
+
+ hBpt = LLPlleFindNext( PlliBpList, (HBPT) NULL);
+
+ while (hBpt) {
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ if ( (lpBpp->fTemporary) &&
+ (lpBpp->hPid == hPid) &&
+ ( (hTid == 0) || (lpBpp->hTid == hTid) ) ) {
+
+ BPInitBps( lpBpp, BpsBuffer, FALSE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone);
+ hBpt2 = hBpt;
+ hBpt = LLPlleFindNext( PlliBpList, hBpt );
+
+ LLFDeletePlleFromLl( PlliBpList, hBpt2 );
+
+// MMFreeHmem( (HDEP) hBpt2 ); // M00BUG -- free handle
+ } else {
+
+ hBpt = LLPlleFindNext( PlliBpList, hBpt );
+ }
+ }
+
+ return BPNOERROR;
+} /* BPClearAllTmp() */
+
+
+/*** BPHbptFromI
+**
+** Synopsis:
+** bpstatus = BPHbptFromI(phbpt, i)
+**
+** Entry:
+** phbpt - pointer to hbpt to be filled in
+** i - breakpoint number to look for
+**
+** Returns:
+** bpstatus code
+**
+** Description:
+** This routine will look for a breakpoint which has the specified
+** breakpoint index number and return the handle to the breakpoint
+** if it is found. The routine will find the first breakpoints which
+** has the correct number if multiple exist on the list.
+*/
+
+BPSTATUS PASCAL BPHbptFromI(HBPT FAR * phbpt, UINT i)
+{
+ HBPT hbpt;
+ LPBPP lpBpp;
+
+ /*
+ **
+ */
+
+ Dbg( BPNextHbpt( &hbpt, bptFirst ) == BPNOERROR );
+ if (hbpt != NULL) {
+ do {
+ lpBpp = LLLpvFromPlle( hbpt );
+ if (lpBpp->iBreakpointNum == i) {
+ *phbpt = hbpt;
+ return( BPNOERROR );
+ }
+ Dbg( BPNextHbpt( &hbpt, bptNext ) == BPNOERROR );
+ } while (hbpt != NULL);
+ }
+
+ return BPNoMatch;
+} /* BPHbptFromI() */
+
+
+/*** BPIFromHbpt
+**
+** Synopsis:
+** bpstatus = BPIFromHbpt(lpu, hBpt)
+**
+** Entry:
+** lpu - pointer to UINT to return the index in
+** hBpt - breakpoint handle to get the index of
+**
+** Returns:
+** BPNOERROR
+**
+** Description:
+** This routine will get the index from a breakpoint handle.
+**
+*/
+
+BPSTATUS FAR PASCAL BPIFromHbpt(UINT FAR * lpu, HBPT hBpt)
+{
+ LPBPP lpBpp;
+
+ lpBpp = LLLpvFromPlle( hBpt );
+ *lpu = lpBpp->iBreakpointNum;
+
+ return BPNOERROR;
+} /* BPIFromHbpt() */
+
+/*** BPHbptFromFileLine
+**
+** Synopsis:
+** bpstatus = BPHbptFromFileLine(szFile, iLine, phbpt)
+**
+** Entry:
+** szFile - Source file name to clear breakpoint from
+** iLine - Line number to clear breakpoint from
+** phbpt - pointer to where to return found breakpoint handle
+**
+** Returns:
+** BPNOERROR if one matching breakpoint was found, BPAmbigous if
+** multiple breakpoints were found and BPNoBreakpoint of no breakpoints
+** were found
+**
+** Description:
+** This function will search through the list of breakpoints looking
+** for enabled breakpoints which match the requested file/line pair.
+** We return the handle to the first breakpoint found and continue
+** searching for a second in which case we notify of ambiguity.
+**
+** The highlighting information is used to do this search.
+*/
+
+
+BPSTATUS PASCAL BPHbptFromFileLine(char FAR * szFile, UINT iLine, HBPT FAR * phbpt)
+{
+ HBPT hbpt;
+ char rgch[256];
+ char rgchSource[256];
+ LPBPP lpBpp;
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+ *phbpt = NULL;
+
+ _splitpath( szFile, drive, dir, fname, ext );
+ wsprintf( rgchSource, "%s%s", fname, ext );
+
+ //
+ // Walk though the set of breakpoints. Don't look at anything which
+ // is not enabled. Look for matching file/source
+ //
+ Dbg( BPNextHbpt( &hbpt, bptFirst) == BPNOERROR );
+
+ while (hbpt != NULL) {
+ lpBpp = LLLpvFromPlle( hbpt );
+
+ if ( (lpBpp->bpstate & bpstateEnabled) && lpBpp->fHighlight ) {
+
+ if (lpBpp->iHighlightLine == iLine) {
+
+ GetAtomName( lpBpp->atmHighlightFile, rgch, sizeof(rgch)-1);
+
+ _splitpath( rgch, drive, dir, fname, ext );
+ wsprintf( rgch, "%s%s", fname, ext );
+
+ if ( _stricmp( rgch, rgchSource ) == 0) {
+ if (*phbpt == NULL) {
+ *phbpt = hbpt;
+ } else {
+ return BPAmbigous;
+ }
+ }
+ }
+ }
+
+ Dbg( BPNextHbpt( &hbpt, bptNext) == BPNOERROR );
+ }
+
+ return (*phbpt == NULL) ? BPNoBreakpoint : BPNOERROR;
+} /* BPHbptFromFileLine() */
+
+/*** BPAddrFromHbpt
+**
+** Synopsis:
+** bpstatus = BPAddrFromHbpt(hbpt, lpaddr)
+**
+** Entry:
+** hbpt - handle to breakpoint structure to get address from
+** lpaddr - pointer to address record to return in
+**
+** Returns:
+** BP error code status
+**
+** Description:
+** This function will return the address field of a breakpoint. This
+** is mainly used for functions such as go until command line parsing.
+*/
+
+BPSTATUS PASCAL BPAddrFromHbpt(HBPT hbpt, ADDR FAR * lpaddr)
+{
+ LPBPP lpBpp = LLLpvFromPlle( hbpt );
+
+ /*
+ ** Verify that the handle given us is good
+ */
+
+ if (lpBpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ /*
+ ** breakpoint must be either Virtual or Set in order to have an
+ ** address connected with it
+ */
+
+ if (lpBpp->bpstate & bpstateNotSet) {
+ return BPError;
+ }
+
+ /*
+ ** Copy over the address field and return
+ */
+
+ *lpaddr = lpBpp->addr;
+
+ return BPNOERROR;
+
+} /* BPAddrFromHbpt() */
+
+/*** BPFreeHbpt
+**
+** Synopsis:
+** bpstatus = BPFreeHbpt(hbpt)
+**
+** Entry:
+** hbpt - Handle to breakpoint to be freed
+**
+** Returns:
+** BP status code
+**
+** Description:
+** This function may be used to free a breakpoint which has never been
+** placed onto the list of breakpoints. Once it is placed on
+** the list of breakpoints you must used BPDelete and BP Commit
+** to remove and delete it.
+*/
+
+BPSTATUS PASCAL BPFreeHbpt( HBPT hbpt )
+{
+ // M00BUG -- verify not on PlliBpList
+
+ MMFreeHmem( (HDEP) hbpt );
+
+ return BPNOERROR;
+} /* BPFreeHbpt() */
+
+
+/*** BPHbptFromAddr
+**
+** Synopsis:
+** bpstatus = BPHbptFromAddr(lpaddr, lphbpt)
+**
+** Entry:
+** lpaddr - pointer to address to compare againist
+** lphbpt - pointer to where to return the hbpt if found
+**
+** Returns:
+** BP Status code -- BPNOERROR if one found, BPAmbigous if multiple
+** are found and BPNoBreakpoint if none are found
+**
+** Description:
+** This function will go though the list of set breakpoints and
+** determine if there is a breakpoint at the given address
+*/
+
+BPSTATUS FAR PASCAL BPHbptFromAddr(ADDR FAR * lpaddr, HBPT FAR * lphbpt)
+{
+ HBPT hbpt;
+ LPBPP lpBpp;
+
+ /*
+ ** Initialize in case of error
+ */
+
+ *lphbpt = NULL;
+ SYUnFixupAddr( lpaddr );
+
+ Dbg( BPNextHbpt( &hbpt, bptFirst) == BPNOERROR );
+
+ while (hbpt != NULL) {
+ lpBpp = LLLpvFromPlle( hbpt );
+
+ if (!(lpBpp->bpstate & bpstateDeleted))
+ if ((lpBpp->bpstate & (bpstateEnabled | bpstateSet)) == (bpstateEnabled | bpstateSet)) {
+ if ( ((lpaddr->mode.fFlat && lpBpp->addr.mode.fFlat) ||
+ (lpaddr->addr.seg == lpBpp->addr.addr.seg)) &&
+ (lpaddr->addr.off == lpBpp->addr.addr.off)) {
+ if (*lphbpt == NULL) {
+ *lphbpt = hbpt;
+ } else {
+ return BPAmbigous;
+ }
+ }
+ }
+
+ Dbg( BPNextHbpt( &hbpt, bptNext) == BPNOERROR );
+ }
+
+ return (*lphbpt == NULL) ? BPNoBreakpoint : BPNOERROR;
+} /* BPHbptFromAddr() */
+
+
+#ifdef ANIMATE_EXPRBP
+extern BOOL PASCAL MoveEditorToAddr(PADDR pAddr);
+BOOL PASCAL HighlightBP(PADDR pAddr, BOOL Set);
+BOOL PASCAL HighlightBP(PADDR pAddr, BOOL Set)
+{
+ char szFname[_MAX_PATH];
+ int FnameLine;
+ int doc;
+ LINESTATUSACTION action;
+
+ if ( BPCBGetSourceFromAddr(
+ pAddr,
+ szFname,
+ sizeof(szFname), &FnameLine ) ) {
+
+ if (FindDoc(szFname, &doc, TRUE))
+ {
+ if (Set) action = LINESTATUS_ON;
+ else action = LINESTATUS_OFF;
+ LineStatus(doc, FnameLine, BRKPOINT_LINE, action, FALSE, TRUE);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif
+
+
+/*** BPCheckHbpt
+**
+** Synopsis:
+** bpstatus = BPCheckHbpt(cxf, pfn)
+**
+** Entry:
+** cxf - context to evalute the breakpoint in
+** pfn - function to call with hBpt of breakpoint hit
+**
+** Returns:
+** BP Status code --
+** BPNoBreakpoint - if no breakpoint is set at this address
+** BPTmpBreakpoint - if only temp breakpoints are set at this address
+** BPPassBreakpoint - if set breakpoint is found but does not meet
+** the breakpoint criteria
+** BPNOERROR - if a set breakpoint is found and all breakpoint
+** criteria is met
+**
+** Description:
+** This function will go though the list of set breakpoints and
+** determine if the conditions on a breakpoint has been hit. All
+** breakpoints will be evalutated.
+*/
+
+BPSTATUS FAR PASCAL
+BPCheckHbpt(
+ CXF cxf,
+ LPFNBPCALLBACK pfn,
+ HPID hPid,
+ HTID hTid,
+ DWORD dwNotify
+ )
+{
+ HBPT hBpt;
+ LPBPP lpBpp;
+ BPSTATUS bpstatus = BPNoBreakpoint;
+ ADDR addr;
+ BPSTATUS bpstatusT;
+ BOOL f;
+ UINT Msg;
+
+
+
+#ifdef ANIMATE_EXPRBP
+ static ADDR LastAddr = {0};
+ static BOOL F = FALSE;
+#endif
+
+
+ addr = *(SHPAddrFromPCxf(&cxf));
+ SYUnFixupAddr( &addr );
+
+
+#ifdef ANIMATE_EXPRBP
+ if ( F ) {
+ HighlightBP( &LastAddr, FALSE );
+ } else {
+ F = TRUE;
+ }
+ MoveEditorToAddr( &addr );
+ HighlightBP( &addr, TRUE );
+ LastAddr = addr;
+#endif
+
+
+
+ Dbg( BPNextHbpt( &hBpt, bptFirst) == BPNOERROR);
+
+ while (hBpt != NULL) {
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ /*
+ ** Is the breakpoint set?
+ */
+
+ if ((lpBpp->bpstate & bpstateSet) != 0) {
+
+ ADDR addrBp = lpBpp->addr;
+
+ SYFixupAddr( &addrBp );
+ SYFixupAddr( &addr );
+
+
+ /*
+ ** Check to see if we have an address for this breakpoint and
+ ** if it is the same.
+ */
+
+ if (lpBpp->fCodeAddr &&
+ ((emiAddr(addr) != emiAddr(addrBp)) ||
+ (GetAddrSeg(addr) != GetAddrSeg(addrBp)) ||
+ (GetAddrOff(addr) != GetAddrOff(addrBp)))) {
+
+ goto miss;
+ }
+
+ //
+ // Check to see if we have a thread for this breakpoint
+ // and if it is the same.
+ //
+ if ( lpBpp->fThread &&
+ (lpBpp->hTid != LptdCur->htid)
+ ) {
+
+ if ( bpstatus == BPNoBreakpoint ) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+
+
+ /*
+ ** Check for an expression
+ */
+
+ if (lpBpp->fExpression) {
+ if ((bpstatusT = BPCheckExprLpBpp(lpBpp, cxf, &f)) != BPNOERROR) {
+ if ( lpBpp->fCodeAddr ) {
+ pfn( hBpt, bpstatusT );
+ bpstatus = BPNOERROR;
+ } else {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+ if (!f) {
+ if (bpstatus == BPNoBreakpoint) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+ }
+
+ /*
+ ** Check for memory change
+ */
+
+ if (lpBpp->fMemory && lpBpp->dwNotify != dwNotify) {
+ bpstatus = BPNoBreakpoint;
+ goto miss;
+ }
+
+#if 0
+ if ((bpstatusT = BPCheckMemoryLpBpp(lpBpp, cxf, &f)) != BPNOERROR) {
+ if ( lpBpp->fCodeAddr ) {
+ pfn( hBpt, bpstatusT );
+ bpstatus = BPNOERROR;
+ } else {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+ if (!f) {
+ if (bpstatus == BPNoBreakpoint) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+#endif
+
+ /*
+ ** Check for pass counts
+ */
+
+ if (lpBpp->iPassCount) {
+ lpBpp->iPassCount -= 1;
+ if (bpstatus == BPNoBreakpoint) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+
+ //
+ // Check for message breakpoint
+ //
+ if ( lpBpp->fMsg ) {
+
+ //
+ // Parse the message if not already parsed.
+ //
+ if ( !lpBpp->fMsgParsed ) {
+
+ if (bpstatus == BPNoBreakpoint) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+
+ //
+ // Get the message.
+ //
+ if ( GetMsg( lpBpp, cxf, &Msg ) ) {
+
+ //
+ // Determine if we got a match
+ //
+ if ( lpBpp->fMsgClass ) {
+ if ( !MatchMsgClass( lpBpp, lpBpp->MsgMap, Msg ) ) {
+ if ( bpstatus == BPNoBreakpoint ) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+ } else {
+ if ( Msg != lpBpp->Msg ) {
+ if ( bpstatus == BPNoBreakpoint ) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+ }
+ } else {
+ if ( bpstatus == BPNoBreakpoint ) {
+ bpstatus = BPPassBreakpoint;
+ }
+ goto miss;
+ }
+ }
+
+
+ /*
+ ** Check for a temporary breakpoint
+ */
+
+ if (lpBpp->fTemporary) {
+
+ //
+ // Process & thread should match, if they don't,
+ // we should skip it.
+ //
+ if (bpstatus != BPNOERROR) {
+ if ((lpBpp->hPid == hPid) &&
+ (lpBpp->hTid == hTid)) {
+ bpstatus = BPTmpBreakpoint;
+ } else {
+ bpstatus = BPPassBreakpoint;
+ }
+ }
+ goto miss;
+ }
+
+
+ /*
+ ** We managed to get a breakpoint which met
+ ** all of the criteria so call the callback function
+ ** and alter the return code to say we really hit
+ ** a breakpoint
+ */
+
+ pfn(hBpt, BPNOERROR);
+ bpstatus = BPNOERROR;
+ }
+
+ miss:
+ Dbg( BPNextHbpt( &hBpt, bptNext) == BPNOERROR );
+ }
+ return( bpstatus );
+} /* BPCheckHbpt() */
+
+
+
+BOOL
+ParseBpMsg(
+ LPBPP lpBpp,
+ LPMSGMAP MsgMap
+ )
+{
+ BOOL Ok = FALSE;
+ DWORD MsgMask = 0;
+ char Buffer[ MAX_PATH ];
+ char *p = Buffer;
+
+ //
+ // See if the Message atom refers to a message, if it
+ // doesn't then try to form a mask from it.
+ //
+ if ( !(Ok = FindMsg( lpBpp, MsgMap ) ) ) {
+
+ //
+ // This is not a valid message, assume it is a CV-style
+ // message mask, which consists of characters specifying
+ // message classes:
+ //
+ // m - mouse
+ // w - window
+ // n - input
+ // s - system
+ // i - init
+ // c - clipboard
+ // d - dde
+ // z - nonclient
+ //
+ GetAtomName( lpBpp->atmMsg, Buffer, sizeof(Buffer)-1);
+
+ Ok = (*p != '\0');
+ while ( (*p != '\0') && (*p != ' ') && (*p != '\t') ) {
+
+ switch ( *p++ ) {
+
+ case 'M':
+ case 'm':
+ MsgMask |= MSG_TYPE_MOUSE;
+ break;
+
+ case 'W':
+ case 'w':
+ MsgMask |= MSG_TYPE_WINDOW;
+ break;
+
+ case 'N':
+ case 'n':
+ MsgMask |= MSG_TYPE_INPUT;
+ break;
+
+ case 'S':
+ case 's':
+ MsgMask |= MSG_TYPE_SYSTEM;
+ break;
+
+ case 'I':
+ case 'i':
+ MsgMask |= MSG_TYPE_INIT;
+ break;
+
+ case 'C':
+ case 'c':
+ MsgMask |= MSG_TYPE_CLIPBOARD;
+ break;
+
+ case 'D':
+ case 'd':
+ MsgMask |= MSG_TYPE_DDE;
+ break;
+
+ case 'Z':
+ case 'z':
+ MsgMask |= MSG_TYPE_NONCLIENT;
+ break;
+
+ default:
+ Ok = FALSE;
+ break;
+ }
+ }
+
+ if ( Ok ) {
+ lpBpp->fMsgClass = TRUE;
+ lpBpp->Msg = MsgMask;
+ }
+ }
+
+ if ( Ok ) {
+ lpBpp->fMsgParsed = TRUE;
+ lpBpp->MsgMap = MsgMap;
+ }
+
+ return Ok;
+}
+
+
+
+BOOL
+GetMsg(
+ LPBPP lpBpp,
+ CXF cxf,
+ UINT *Msg
+ )
+{
+ HSYM hSym;
+ HTM hTm;
+ HTM hTmChild;
+ uint End;
+ EESTATUS RetErr;
+ UOFF32 Offset;
+ char *Value;
+ int i;
+ EEHSTR hValue = 0;
+ BOOL Ok = FALSE;
+ CXF Cxf = cxf;
+
+ if (!ADDR_IS_LI (*SHpADDRFrompCXT (SHpCXTFrompCXF (&Cxf)))) {
+ SYUnFixupAddr (SHpADDRFrompCXT (SHpCXTFrompCXF (&Cxf)));
+ }
+
+ //
+ // Get TM for the function
+ //
+ Offset = SHGetNearestHSYM( SHpADDRFrompCXT(SHpCXTFrompCXF(&Cxf)),
+ SHHMODFrompCXT(SHpCXTFrompCXF(&Cxf)),
+ EECODE,
+ &hSym );
+
+ RetErr = EEGetTMFromHSYM( hSym,
+ &Cxf.cxt,
+ &hTm,
+ &End,
+ FALSE);
+
+ if ( RetErr == EENOERROR ) {
+
+
+ RetErr = EEGetChildTM( &hTm, 1, &hTmChild, &i, FALSE, 10 );
+
+ if ( RetErr == EENOERROR ) {
+
+ RetErr = EEvaluateTM(
+ &hTmChild,
+ SHpFrameFrompCXF(&Cxf),
+ EEVERTICAL
+ );
+
+ if ( RetErr == EENOERROR ) {
+
+ RetErr = EEGetValueFromTM(
+ &hTmChild,
+ 10,
+ NULL,
+ &hValue );
+
+ if ( RetErr == EENOERROR) {
+
+ Value = MMLpvLockMb( hValue );
+ *Msg = atol( Value );
+ MMbUnlockMb( hValue );
+ Ok = TRUE;
+ }
+ }
+ }
+
+ }
+
+ return Ok;
+}
+
+
+BOOL
+FindMsg(
+ LPBPP lpBpp,
+ LPMSGMAP MsgMap
+ )
+{
+ LPMSGINFO MsgInfo;
+ char Buffer[ MAX_PATH ];
+ BOOL Ok = FALSE;
+
+ GetAtomName( lpBpp->atmMsg, Buffer, sizeof(Buffer)-1);
+
+ MsgInfo = MsgMap->MsgInfo;
+ while ( MsgInfo && MsgInfo->MsgText ) {
+ if ( !_stricmp( MsgInfo->MsgText, Buffer ) ) {
+ lpBpp->fMsgParsed = TRUE;
+ lpBpp->Msg = MsgInfo->Msg;
+ Ok = TRUE;
+ break;
+ }
+ MsgInfo++;
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOL
+MatchMsgClass(
+ LPBPP lpBpp,
+ LPMSGMAP MsgMap,
+ UINT Msg
+ )
+{
+ MSGINFO Key;
+ LPMSGINFO MsgInfo;
+ BOOL Ok = FALSE;
+
+ Key.Msg = Msg;
+ MsgInfo = bsearch( &Key, MsgMap->MsgInfo, MsgMap->Count,
+ sizeof( MsgMap->MsgInfo[0] ), MsgCmp );
+
+ if ( MsgInfo ) {
+ Ok = ( MsgInfo->MsgMask & lpBpp->Msg ) ? TRUE : FALSE;
+ }
+
+ return Ok;
+}
+
+
+int _CRTAPI1
+MsgCmp (
+ const void *p1,
+ const void *p2
+ )
+{
+ LPMSGINFO MsgInfo1 = (LPMSGINFO)p1;
+ LPMSGINFO MsgInfo2 = (LPMSGINFO)p2;
+
+ if ( MsgInfo1->Msg < MsgInfo2->Msg ) {
+ return -1;
+ } else if ( MsgInfo1->Msg > MsgInfo2->Msg ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+int _CRTAPI1
+MsgCmpName (
+ const void *p1,
+ const void *p2
+ )
+{
+ LPMSGINFO MsgInfo1 = (LPMSGINFO)p1;
+ LPMSGINFO MsgInfo2 = (LPMSGINFO)p2;
+
+ return _stricmp( MsgInfo1->MsgText, MsgInfo2->MsgText );
+}
+
+/*** BPQueryCmdOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryCmdOfHbpt(hBpt, lpb, cb)
+**
+** Entry:
+** hBpt - Handle to breakpoint to query
+** lpb - pointer to buffer to be filled in
+** cb - number of characters in the buffer
+**
+** Return:
+** break point error code
+**
+** Description:
+** This command is used to query out the command string associated with
+** a breakpoint command.
+*/
+
+
+BPSTATUS PASCAL BPQueryCmdOfHbpt(HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if ( !lpbpp->szCmdLine) {
+ *lpb = 0;
+ return BPNOERROR;
+ }
+
+ strcpy(lpb, lpbpp->szCmdLine);
+
+ return BPNOERROR;
+} /* BPQueryCmdOfHbpt() */
+
+/*** BPQueryBPTypeOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryBPTypeOfHbpt( hBpt, lpint );
+**
+** Entry:
+** hBpt - handle of breakpoint to get the type of
+** lpint - pointer to location to return the type in
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the breakpoint type for the requested
+** breakpoint type.
+*/
+
+BPSTATUS PASCAL BPQueryBPTypeOfHbpt( HBPT hBpt, int FAR * lpint )
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ int j;
+
+ //
+ // The CodeTypes & WndProcTypes arrays let us determine type
+ // type of a BP fast without the need for a switch statement
+ //
+ static int CodeTypes[] = {
+ -1,
+ BPEXPRCHGD,
+ BPEXPRTRUE,
+ -1,
+ BPLOC,
+ BPLOCEXPRCHGD,
+ BPLOCEXPRTRUE,
+ -1
+ };
+
+ static int WndProcTypes[] = {
+ -1,
+ -1,
+ -1,
+ -1,
+ BPWNDPROC,
+ BPWNDPROCEXPRCHGD,
+ BPWNDPROCEXPRTRUE,
+ -1
+ };
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ //
+ // Form type index
+ //
+ j = (lpbpp->fCodeAddr*4) + (lpbpp->fExpression*2) + (lpbpp->fMemory);
+
+ //
+ // Get the type from one of the Type arrays using the index
+ // generated.
+ //
+ if ( lpbpp->fMsg ) {
+
+ //
+ // No indexing needed (only one type for this).
+ //
+ assert( lpbpp->fWndProc );
+ assert( lpbpp->fCodeAddr );
+ *lpint = BPWNDPROCMSGRCVD;
+
+ } else if ( lpbpp->fWndProc ) {
+
+ //
+ // Use WndProc array
+ //
+ assert( lpbpp->fCodeAddr );
+ *lpint = WndProcTypes[j];
+
+ } else {
+
+ //
+ // Use the "normal" array
+ //
+ *lpint = CodeTypes[j];
+ }
+
+ assert( *lpint != -1 );
+
+ return BPNOERROR;
+} /* BPQueryBPTypeOfHbpt() */
+
+/*** BPQueryLocationOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryLocationOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the location for
+** lpb - pointer to location to return the location in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the location for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL BPQueryLocationOfHbpt( HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ char rgch[260];
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+
+ *lpb = 0;
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if (!lpbpp->fCodeAddr) {
+ return BPNOERROR;
+ }
+
+ /*
+ ** Put in the default context if it exists
+ */
+
+ if ((lpbpp->atmCxtDef) != 0 && (lpbpp->szAddrExpr != NULL)) {
+ GetAtomName( lpbpp->atmCxtDef, rgch, sizeof(rgch) );
+ if (strlen( rgch ) > cb) {
+ return BPError;
+ }
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+ }
+
+ /*
+ ** Get the real context if specified
+ */
+
+ if (lpbpp->atmAddrCxt != 0) {
+ assert( lpbpp->szAddrExpr != NULL);
+
+ GetAtomName(lpbpp->atmAddrCxt, rgch, sizeof(rgch) );
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+ }
+
+ /*
+ ** Get the full expression if specified
+ */
+
+ if (lpbpp->szAddrExpr != NULL) {
+ strcpy( rgch, lpbpp->szAddrExpr );
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+
+ _fstrcat(lpb, rgch);
+ cb -= strlen(rgch);
+ }
+
+ return BPNOERROR;
+} /* BPQueryLocationOfHbpt() */
+
+
+/*** BPQueryExprOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryExprOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the expresion for
+** lpb - pointer to location to return the expresion in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the expresion for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL BPQueryExprOfHbpt( HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if (lpbpp->fExpression == FALSE) {
+ return BPNOERROR;
+ }
+
+ assert(lpbpp->atmExpr != 0);
+
+ GetAtomName(lpbpp->atmExpr, lpb, cb);
+
+ return BPNOERROR;
+} /* BPQueryExprOfHbpt() */
+
+
+/*** BPQueryMessageOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryMessageOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the message for
+** lpb - pointer to location to return the message in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the message for the requested
+** message breakpoint.
+*/
+
+BPSTATUS PASCAL BPQueryMessageOfHbpt( HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if ( !lpbpp->fMsg ) {
+ return BPNOERROR;
+ }
+
+ assert(lpbpp->atmMsg != 0);
+
+ GetAtomName(lpbpp->atmMsg, lpb, cb);
+
+ return BPNOERROR;
+}
+
+
+/*** BPQueryMemoryOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryMemoryOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the memory for
+** lpb - pointer to location to return the memory in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the memory expression for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL BPQueryMemoryOfHbpt( HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if (lpbpp->fMemory == FALSE) {
+ return BPNOERROR;
+ }
+
+ assert(lpbpp->atmData != 0);
+
+ GetAtomName(lpbpp->atmData, lpb, cb);
+
+ return BPNOERROR;
+} /* BPQueryMemoryOfHbpt() */
+
+
+/*** BPQueryMemorySizeOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryMemorySizeOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the memory cmp size for
+** lpb - pointer to location to return the memory cmp size in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the memory compare size for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL BPQueryMemorySizeOfHbpt( HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ char rgchT[40];
+ BPSTATUS bpstatus = BPNOERROR;
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if (lpbpp->fMemory == FALSE) {
+ return BPNOERROR;
+ }
+
+ if ( (lpbpp->cbDataSize == 0) && (lpbpp->atmRangeSize != 0) ) {
+ GetAtomName(lpbpp->atmRangeSize, lpb, cb);
+ } else {
+ sprintf(rgchT, "%d", lpbpp->cbDataSize);
+ if (strlen(rgchT) >= cb) {
+ bpstatus = BPOutOfSpace;
+ } else {
+ _fstrcpy(lpb, rgchT);
+ }
+ }
+
+ return BPNOERROR;
+} /* BPQueryMemorySizeOfHbpt() */
+
+
+/*** BPQueryPassCntOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryPassCntOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the pass count for
+** lpb - pointer to location to return the pass count in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the pass count for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL BPQueryPassCntOfHbpt( HBPT hBpt, char FAR * lpb, UINT cb)
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ char rgch[260];
+
+ /*
+ ** Initialize to empty return string
+ */
+
+ *lpb = 0;
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ /*
+ ** Check for a non-evaluated pass count expression
+ */
+
+ if (lpbpp->atmPassCount != 0) {
+ assert( lpbpp->macPassCount == 0);
+
+ GetAtomName(lpbpp->atmPassCount, rgch, sizeof(rgch));
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+
+ _fstrcpy(lpb, rgch);
+ }
+
+ /*
+ ** Now check for an evaluated pass count
+ */
+
+ if (lpbpp->macPassCount != 0) {
+ sprintf( rgch, "%d-%d", lpbpp->macPassCount, lpbpp->macPassCount - lpbpp->iPassCount);
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+
+ _fstrcpy(lpb, rgch);
+ }
+
+ return BPNOERROR;
+} /* BPQueryPassCntOfHbpt() */
+
+/*** BPQueryPassleftOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryPassleftOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the pass count for
+** lpb - pointer to location to return the pass count in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the pass count left for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL
+BPQueryPassLeftOfHbpt(
+ HBPT hBpt,
+ char FAR * lpb,
+ UINT cb
+ )
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ char rgch[260];
+
+ //
+ // Initialize to empty return string
+ //
+ *lpb = 0;
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if ( lpbpp->atmPassCount != 0 ) {
+ sprintf( rgch, "%d", lpbpp->iPassCount );
+
+ if ( strlen(rgch) > cb ) {
+ return BPError;
+ }
+ _fstrcpy(lpb, rgch);
+ }
+
+ return BPNOERROR;
+}
+
+
+
+/*** BPQueryThreadOfHbpt
+**
+** Synopsis:
+** bpstatus = BPQueryThreadOfHbpt( hBpt, lpb, cb);
+**
+** Entry:
+** hBpt - handle of breakpoint to get the thread for
+** lpb - pointer to location to return the thread in
+** cb - count of bytes for lpb
+**
+** Return:
+** return bp status code
+**
+** Description:
+** This function will return the threadt for the requested
+** breakpoint.
+*/
+
+BPSTATUS PASCAL
+BPQueryThreadOfHbpt(
+ HBPT hBpt,
+ char FAR * lpb,
+ UINT cb
+ )
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ char rgch[260];
+
+ /*
+ ** Initialize to empty return string
+ */
+
+ *lpb = 0;
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if (lpbpp->fThread ) {
+ sprintf( rgch, "%d", lpbpp->iTid );
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+
+ _fstrcpy(lpb, rgch);
+ }
+
+
+ return BPNOERROR;
+}
+
+BPSTATUS PASCAL
+BPQueryProcessOfHbpt(
+ HBPT hBpt,
+ char FAR * lpb,
+ UINT cb
+ )
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ char rgch[260];
+ LPPD lppd;
+ BOOL Ok = FALSE;
+
+ /*
+ ** Initialize to empty return string
+ */
+
+ *lpb = 0;
+
+ if (lpbpp == NULL) {
+ return BPBadBPHandle;
+ }
+
+ if (lpbpp->fProcess ) {
+
+ sprintf( rgch, "%d", lpbpp->iPid );
+ Ok = TRUE;
+
+ } else if ( (lpbpp->bpstate & bpstateSets) != bpstateNotSet ) {
+
+ //
+ // Get the process ID for the process
+ //
+ lppd = LppdOfHpid(lpbpp->hPid);
+ if (lppd) {
+ sprintf( rgch, "%d", lppd->ipid );
+ Ok = TRUE;
+ }
+ }
+
+ if ( Ok ) {
+ if (strlen(rgch) > cb) {
+ return BPError;
+ }
+ _fstrcpy(lpb, rgch);
+ }
+
+ return BPNOERROR;
+}
+
+BPSTATUS PASCAL
+BPQueryHighlightLineOfHbpt(
+ HBPT hBpt,
+ UINT *Line
+ )
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ BPSTATUS Ret = BPNOERROR;
+
+ if ( lpbpp->fHighlight ) {
+ *Line = lpbpp->iHighlightLine;
+ } else {
+ Ret = BPError;
+ }
+
+ return Ret;
+}
+
+/*** BpGetHtm
+**
+** Synopsis:
+** bpstatus = BpGetHtm(lpBpp, szBpt, fExpr)
+**
+** Entry:
+** lpBpp - pointer to breakpoint structure to fill in
+** szBpt - pointer to string containning the expression
+** fExpr - TRUE if expr, FALSE if address
+**
+** Return:
+** breakpoint status code
+**
+** Description:
+** This function is used to get the expression portion of a breakpoint
+** expression and get the parse tree for the expression. It will be
+** saved away in the breakpoint structure for later use.
+*/
+
+LOCAL BPSTATUS PASCAL
+BpGetHtm(
+ LPBPP lpBpp,
+ char FAR * szBpt,
+ BOOL fExpr
+ )
+{
+ uint strIndex;
+ EESTATUS Err;
+
+ /*
+ ** Check to see if the expression is enclosed in quotes, if so then
+ ** strip them off.
+ */
+
+ if (*szBpt == '\"') {
+ szBpt ++;
+ if (szBpt[_fstrlen(szBpt)-1] != '\"') {
+ } else {
+ szBpt[_fstrlen(szBpt)-1] = 0;
+ }
+ }
+
+ if (fExpr) {
+ lpBpp->atmExpr = AddAtom(szBpt);
+ lpBpp->fExpression = TRUE;
+ } else {
+ lpBpp->atmData = AddAtom(szBpt);
+ lpBpp->fMemory = TRUE;
+ }
+
+ /*
+ ** Attemp to parse it and check for an error return code
+ */
+
+ if ((Err = EEParse(szBpt, radix, fCaseSensitive, &lpBpp->hTm, &strIndex)) != EENOERROR) {
+ return BPBadDataSize;
+ }
+
+ return BPNOERROR;
+} /* BpGetHtm() */
+
+/*** BPCheckExprLpBpp
+**
+** Synopsis:
+** bpstatus = BPCheckExprLpBpp(lpBpp)
+**
+** Entry:
+** lpBpp - pointer to breakpoint structure
+**
+** Returns:
+** BP Status code
+**
+** Description:
+** This function will evaluate the expression assocated with
+** the passed in breakpoint.
+*/
+
+LOCAL BPSTATUS PASCAL BPCheckExprLpBpp( LPBPP lpBpp, CXF cxf, BOOL * pf )
+{
+ RI ri;
+ HTI hTi;
+ PTI pTi;
+ UINT i;
+ int fStop = 0;
+
+ /*
+ ** get the TM for this expression
+ */
+
+ memset( &ri, 0, sizeof(ri) );
+ ri.fValue = TRUE;
+ ri.fSzBytes = TRUE;
+
+ /*
+ ** Evaluate the expression
+ */
+
+ if ( EEBindTM( &lpBpp->hTm, SHpCXTFrompCXF(&cxf), TRUE, TRUE, FALSE ) ||
+ EEvaluateTM( &lpBpp->hTm, SHpFrameFrompCXF(&cxf), EEHORIZONTAL) ||
+ EEInfoFromTM( &lpBpp->hTm, &ri, &hTi) ) {
+
+ return BPBadExpression;
+ }
+
+ /*
+ ** Or this thing together, if all zeros, then we will make a FALSE
+ ** if any bits set if won't be a false.
+ */
+
+ pTi = MMLpvLockMb ( hTi );
+
+ if (pTi->fResponse.fValue &&
+ pTi->fResponse.fSzBytes) {
+
+ for ( i=0 ; i<pTi->cbValue ; i++) {
+ fStop |= pTi->Value[i];
+ }
+ }
+
+ MMbUnlockMb( hTi );
+ EEFreeTI( &hTi );
+
+ /*
+ ** If there is no change or if the expression evaluator fails, don't stop
+ */
+
+ *pf = fStop;
+ return BPNOERROR;
+} /* BPCheckExprLpBpp() */
+
+
+
+#if 0
+/*** BPCheckMemoryLpBpp
+**
+** Synopsis:
+** bpstatus = BPCheckMemoryLpBpp(lpBpp)
+**
+** Entry:
+** lpBpp - pointer to breakpoint structure
+**
+** Returns:
+** BP Status code
+**
+*/
+
+LOCAL BPSTATUS PASCAL
+BPCheckMemoryLpBpp(
+ LPBPP lpBpp,
+ CXF cxf,
+ BOOL * pf
+ )
+{
+ BOOL f = FALSE;
+ BOOL Ok = TRUE;
+ BPSTATUS Status = EENOERROR;
+ PVOID rgb;
+
+
+ //
+ // Get the current memory contents
+ //
+
+ Assert( lpBpp->cbDataSize != 0 );
+
+ if (lpBpp->BpType == BP_DATA_READ || lpBpp->BpType == BP_EXECUTE) {
+ *pf = TRUE;
+ return EENOERROR;
+ }
+
+ rgb = (PBYTE)malloc( lpBpp->cbDataSize );
+
+ if ( !rgb ) {
+
+ Status = EEGENERAL;
+
+ } else {
+
+ if ( lpBpp->Mem == NULL ) {
+
+ char rgch[256];
+ int cch;
+
+ GetAtomName(lpBpp->atmData, rgch, sizeof(rgch)-1);
+ Ok = (CPGetAddress( rgch, &cch, &(lpBpp->AddrMem), radix, &cxf,
+ FALSE, FALSE) == EENOERROR);
+ }
+
+ if ( !Ok ) {
+
+ Status = EEGENERAL;
+
+ } else {
+
+ SYFixupAddr( &(lpBpp->AddrMem) );
+ Dbg(OSDSetAddr( lpBpp->hPid, lpBpp->hTid, (ADR)adrCurrent, &(lpBpp->AddrMem)) == xosdNone);
+ SYUnFixupAddr( &(lpBpp->AddrMem) );
+ Dbg(OSDPtrace( osdReadBuf, lpBpp->cbDataSize, rgb, lpBpp->hPid, lpBpp->hTid) == (XOSD)lpBpp->cbDataSize);
+
+ if ( lpBpp->Mem == NULL ) {
+
+ //
+ // We have no buffer to compare against. Let's say that
+ // memory changed.
+ //
+ lpBpp->Mem = malloc( lpBpp->cbDataSize );
+
+ if ( lpBpp->Mem == NULL ) {
+ Status = EEGENERAL;
+ }
+
+ f = TRUE;
+
+ } else {
+
+ //
+ // Succeed if memory change
+ //
+ f = memicmp( lpBpp->Mem, rgb, lpBpp->cbDataSize );
+ }
+
+ }
+
+ //
+ // Remember the memory contents for next time
+ //
+ if ( f && (lpBpp->Mem != NULL) ) {
+
+ memcpy( lpBpp->Mem, rgb, lpBpp->cbDataSize );
+ }
+
+ free( rgb );
+
+ }
+
+ *pf = f;
+ return Status;
+}
+#endif
+
+
+
+BOOL
+PASCAL
+BPIsMarkedForDeletion(
+ IN HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Determines if a breakpoint is flagged for deletion.
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ BOOL - TRUE if the breakpoint is marked for deletion,
+ FALSE otherwise.
+
+
+--*/
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ BOOL fMarked;
+
+ fMarked = lpbpp->fMarkDelete;
+ return fMarked;
+}
+
+
+BOOL
+PASCAL
+BPIsDisabled(
+ IN HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Determines if a breakpoint is disabled
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ BOOL - TRUE if the breakpoint is disabled
+ FALSE otherwise.
+
+
+--*/
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ BOOL f;
+
+ f = ((lpbpp->bpstate & bpstateSets) == bpstateSet);
+
+ if (lpbpp->bpstate & bpstateEnabled) {
+ f = lpbpp->fMarkDisable;
+ } else {
+ f = !lpbpp->fMarkEnable;
+ }
+
+ return f;
+}
+
+BOOL
+PASCAL
+BPIsInstantiated(
+ IN HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Determines if a breakpoint is instantiated
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ BOOL - TRUE if the breakpoint is instantiated
+ FALSE otherwise.
+
+
+--*/
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ BOOL f;
+
+ f = ((lpbpp->bpstate & bpstateSets) == bpstateSet);
+ return f;
+}
+
+
+BOOL
+PASCAL
+BPUninstantiate(
+ IN HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Uninstantiates a breakpoint
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ BOOL - TRUE if the breakpoint is uninstantiated
+ FALSE otherwise.
+
+
+--*/
+{
+ LPBPP lpBpp = LLLpvFromPlle( hBpt );
+ BOOL f;
+
+ if ((lpBpp->bpstate & bpstateSets) == bpstateSet) {
+
+ BPRemoveHighLight( lpBpp );
+
+ //
+ // Mark the breakpoint as uninstantiated.
+ //
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateNotSet;
+ lpBpp->fMarkAdd = TRUE;
+
+ BPAddHighLight( lpBpp );
+
+ //
+ // Remove physical breakpoint
+ //
+ BPInitBps( lpBpp, BpsBuffer, FALSE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone);
+
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount--;
+#if 0
+ if (lpBpp->Mem != NULL ) {
+ free( lpBpp->Mem );
+ lpBpp->Mem = NULL;
+ }
+#endif
+ }
+
+ f = TRUE;
+
+ } else {
+
+ lpBpp->bpstate &= ~bpstateSets;
+ lpBpp->bpstate |= bpstateNotSet;
+ f = FALSE;
+ }
+
+ return f;
+}
+
+
+
+
+BOOL
+PASCAL
+BPIsQuiet(
+ IN HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Determines if a breakpoint is quiet
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ BOOL - TRUE if the breakpoint is quiet
+ FALSE otherwise.
+
+
+--*/
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+ BOOL f;
+
+ f = (BOOL)(lpbpp->fQuiet);
+ return f;
+}
+
+VOID
+PASCAL
+BPSetQuiet(
+ IN HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Sets the breakpoint to quiet
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ None
+
+
+--*/
+{
+ LPBPP lpbpp = LLLpvFromPlle( hBpt );
+
+ lpbpp->fQuiet = TRUE;
+}
+
+
+
+
+char *
+BPShortenContext(
+ IN char *szSrc,
+ OUT char *szDst
+ )
+/*++
+
+Routine Description:
+
+ Formats a breakpoint context. The formatting consists
+ of reducing the file specifications from full paths to
+ the mere file names.
+
+Arguments:
+
+ szSrc - Supplies the original context.
+ szDst - Supplies the buffer where the formatted context is placed.
+
+Return Value:
+
+ char * - Pointer to szDst if success. NULL if failure.
+
+
+--*/
+
+{
+ char *p, *q;
+ char *sz;
+
+ *szDst = '\0';
+ p = szSrc;
+
+ if (*p == OPENCONTEXTOP) {
+
+ szDst[0] = *p++;
+ szDst[1] = 0;
+
+ if (q = strchr( p, ',' )) {
+
+ p = q+1;
+ strcat(szDst,",");
+
+ if (q = strchr(p,',')) {
+
+ *q = '\0';
+ if ( sz = GetFileName(p) ) {
+ strcat( szDst, sz );
+ }
+ *q = ',';
+ p = q+1;
+ strcat(szDst,",");
+ }
+
+ if ( q = strchr(p,CLOSECONTEXTOP)) {
+
+ *q = '\0';
+ if ( sz = GetFileName(p) ) {
+ strcat( szDst, sz );
+ }
+ *q = CLOSECONTEXTOP;
+ strcat(szDst,"}");
+
+ return szDst;
+ }
+
+ } else if ( q = strchr(p,CLOSECONTEXTOP)) {
+
+ *q = '\0';
+ if ( sz = GetFileName(p) ) {
+ strcat( szDst, sz );
+ }
+ *q = CLOSECONTEXTOP;
+ strcat(szDst,"}");
+
+ return szDst;
+
+ } else {
+ //
+ // Invalid context!
+ //
+ strcpy( szDst, szSrc );
+ }
+ }
+
+ return NULL;
+}
+
+
+
+static
+void
+BPBoundFixContext(
+ IN OUT LPBPP pBpp
+ )
+
+/*++
+
+Routine Description:
+
+ Edits the contexts in a breakpoint to include the breakpoint
+ bindings.
+
+ We will be editing out the function name since this is causing us
+ problems with C++ and should not be a problem until we get into
+ the nested languages issues later. (i.e. PASCAL)
+
+Arguments:
+
+ pBpp - Supplies pointer to the breakpoint.
+
+Return Value:
+
+ none
+
+--*/
+
+{
+
+ CXT Cxt;
+ char * p;
+ char * q;
+ EEHSTR eehstr;
+ INT Line;
+ char rgch[256];
+ char File[256];
+
+ SaveDebuggerPdTd();
+ SetDebuggerPdTd( pBpp );
+
+ memset( &Cxt, 0, sizeof(Cxt ));
+ SHSetCxt( &(pBpp->addr), &Cxt );
+
+ Dbg( EEFormatCXTFromPCXT(&Cxt, &eehstr, FALSE) == EENOERROR);
+
+ *rgch = '\0';
+
+ if ( eehstr ) {
+
+ p = MMLpvLockMb( eehstr );
+
+ if ( *p ) {
+
+ DAssert(*p == OPENCONTEXTOP);
+
+ q = rgch;
+ *q++ = *p++;
+
+ while (*p != ',') { /* Skip over the function name */
+ p++;
+ }
+ strcpy(q, p);
+ }
+
+ MMbUnlockMb( eehstr );
+ EEFreeStr( eehstr );
+
+ if ( *rgch ) {
+ if ( pBpp->atmAddrCxt ) {
+
+ DeleteAtom(pBpp->atmAddrCxt);
+ pBpp->atmAddrCxt = AddAtom(rgch);
+
+ } else {
+
+ if ( pBpp->atmCxtDef ) {
+ DeleteAtom(pBpp->atmCxtDef);
+ }
+ pBpp->atmCxtDef = AddAtom(rgch);
+ }
+ }
+ }
+
+ //
+ // Now set the highlight
+ //
+ *File = '\0';
+
+ if ( BPCBGetSourceFromAddr( &(pBpp->addr),
+ File,
+ sizeof(File),
+ &Line ) ) {
+
+ if ( pBpp->atmHighlightFile ) {
+ DeleteAtom( pBpp->atmHighlightFile );
+ }
+
+ //
+ // Set the file to highlight
+ //
+ p = rgch;
+ if ( p = strchr(p,',' ) ) {
+ p++;
+ q = strchr(p,',' );
+ *q = '\0';
+
+ pBpp->atmHighlightFile = AddAtom( p );
+ pBpp->iHighlightLine = Line;
+ pBpp->fHighlight = TRUE;
+ }
+ }
+
+ RestoreDebuggerPdTd();
+}
+
+
+LOCAL VOID
+BPInitBps(
+ LPBPP lpBpp,
+ LPBPS Bps,
+ BOOL Set
+ )
+/*++
+
+Routine Description:
+
+ Set up the BPS structure to send to OSDebug. This only handles one
+ breakpoint, and does not currently support batches of breakpoints.
+
+Arguments:
+
+ lpBpp - Supplies the breakpoint structure used by the BP engine to
+ describe the breakpoint. This will be translated here into a
+ BPIS struct for OSDBreakpoint.
+
+ Bps - Returns a BPS structure containing the BPIS structure which
+ will be prepared here.
+
+ Set - Supplies TRUE if the BP is to be set, FALSE if it is to
+ be cleared.
+
+Return Value:
+
+ None
+
+--*/
+{
+ LPBPIS Bpis;
+
+ assert( lpBpp );
+ assert( Bps );
+
+ Bpis = RgBpis(Bps);
+
+ Bps->cbpis = 1;
+ Bps->fSet = Set;
+
+ Bpis->htid = lpBpp->hTid;
+ Bpis->fOneThd = lpBpp->hTid ? TRUE : FALSE;
+
+ DwNotification(Bps)[0] = lpBpp->dwNotify;
+
+ //
+ // Note that we treat message breakpoints as bptpExec and let
+ // the shell do all the work.
+ //
+ if ( lpBpp->fCodeAddr ) {
+
+ SYFixupAddr(&(lpBpp->addr));
+
+ if ( lpBpp->fMemory || lpBpp->fExpression ) {
+ Bpis->bpns = bpnsCheck;
+ } else {
+ Bpis->bpns = bpnsStop;
+ }
+ Bpis->bptp = bptpExec;
+ Bpis->exec.addr = lpBpp->addr;
+
+ SYUnFixupAddr(&(lpBpp->addr));
+
+ } else if ( lpBpp->fMemory ) {
+
+ SYFixupAddr(&(lpBpp->AddrMem));
+
+ Bpis->bpns = bpnsStop;
+
+ if (lpBpp->BpType & BP_EXECUTE) {
+ Bpis->bptp = bptpDataExec;
+ } else if (lpBpp->BpType & BP_DATA_CHANGED) {
+ Bpis->bptp = bptpDataC;
+ } else if (lpBpp->BpType & BP_DATA_WRITE) {
+ Bpis->bptp = bptpDataW;
+ } else if (lpBpp->BpType & BP_DATA_READ) {
+ Bpis->bptp = bptpDataR;
+ }
+ Bpis->data.addr = lpBpp->AddrMem;
+ Bpis->data.cb = lpBpp->cbDataSize;
+
+ SYUnFixupAddr(&(lpBpp->AddrMem));
+
+ } else if ( lpBpp->fExpression) {
+
+ //
+ // expression BP with no code or data address:
+ // this is a walk BP.
+ //
+
+ memset(&Bpis->data.addr, 0, sizeof(ADDR));
+ Bpis->bpns = bpnsCheck;
+ Bpis->data.cb = 0;
+ Bpis->bptp = bptpDataR;
+
+ }
+}
+
+
+VOID
+SaveDebuggerPdTd (
+ void
+ )
+{
+ LppdOld = LppdCur;
+ LptdOld = LptdCur;
+}
+
+VOID
+RestoreDebuggerPdTd (
+ void
+ )
+{
+ LppdCur = LppdOld;
+ LptdCur = LptdOld;
+ if ( LppdCur && LptdCur ) {
+ StatusPidTid(LppdCur->ipid, LptdCur->itid);
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+}
+
+VOID
+SetDebuggerPdTd(
+ LPBPP lpBpp
+ )
+{
+ LPPD lppd;
+
+ lppd = LppdOfHpid(lpBpp->hPid);
+ if (lppd) {
+ LppdCur = lppd;
+ LptdCur = LppdCur->lptdList;
+ if ( LppdCur && LptdCur ) {
+ StatusPidTid(LppdCur->ipid, LptdCur->itid);
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ }
+}
+
+
+VOID BPReplace(
+ LPBPP lpBpp
+ )
+{
+ BPP Bpp;
+ LPBPP lpBppNew;
+
+ if ( lpBpp->fMarkChange && lpBpp->ChangeHbpt != NULL ) {
+
+ //
+ // If original is set, remove it
+ //
+ if ( !lpBpp->fMarkAdd && (lpBpp->bpstate & bpstateSet) ) {
+
+ //
+ // Remove breakpoint
+ //
+ if (lpBpp->bpstate == (bpstateSet | bpstateEnabled)) {
+
+ BPInitBps( lpBpp, BpsBuffer, FALSE );
+ Dbg(OSDBreakpoint( lpBpp->hPid, BpsBuffer ) == xosdNone);
+ if ( lpBpp->fMemory ) {
+ MemoryBpCount--;
+ }
+ }
+
+ BPRemoveHighLight( lpBpp );
+ }
+
+ //
+ // Save original BP
+ //
+ Bpp = *lpBpp;
+
+ //
+ // Get New one
+ //
+ lpBppNew = LLLpvFromPlle( lpBpp->ChangeHbpt );
+
+ //
+ // Copy new one over current one
+ //
+ *lpBpp = *lpBppNew;
+
+ //
+ // Keep change flags
+ //
+ lpBpp->fMarkAdd = TRUE;
+ lpBpp->fMarkDisable = Bpp.fMarkDisable;
+ lpBpp->fMarkEnable = Bpp.fMarkEnable;
+ lpBpp->fReplacement = FALSE;
+
+ //
+ // Deallocate stuff
+ //
+ LLFDeletePlleFromLl( PlliBpList, Bpp.ChangeHbpt );
+
+ if ( Bpp.atmHighlightFile ) {
+ DeleteAtom( Bpp.atmHighlightFile );
+ }
+
+#if 0
+ if ( Bpp.Mem ) {
+ free( Bpp.Mem );
+ }
+#endif
+
+ if ( Bpp.atmAddrCxt ) {
+ DeleteAtom( Bpp.atmAddrCxt );
+ }
+
+ if ( Bpp.atmCxtDef ) {
+ DeleteAtom( Bpp.atmCxtDef );
+ }
+
+ if ( Bpp.atmPassCount ) {
+ DeleteAtom( Bpp.atmPassCount );
+ }
+
+ if ( Bpp.atmExpr ) {
+ DeleteAtom( Bpp.atmExpr );
+ }
+
+ if ( Bpp.atmData ) {
+ DeleteAtom( Bpp.atmData );
+ }
+
+ if ( Bpp.atmRangeSize ) {
+ DeleteAtom( Bpp.atmRangeSize );
+ }
+
+ if ( Bpp.atmMsg ) {
+ DeleteAtom( Bpp.atmMsg );
+ }
+
+ if ( Bpp.szAddrExpr ) {
+ free( Bpp.szAddrExpr );
+ }
+
+ if ( Bpp.szCmdLine ) {
+ free( Bpp.szCmdLine );
+ }
+ }
+}
+
+
+HMOD PASCAL BPFileNameToMod( char * FileName )
+{
+ HEXE hexe = (HEXE)NULL;
+ HMOD hmod;
+
+
+ while ( hexe = SHGetNextExe( hexe ) ) {
+
+ hmod = (HMOD)NULL;
+
+ while ( hmod = SHGetNextMod( hexe, hmod ) ) {
+
+ if ( SLHsfFromFile( hmod, FileName ) ) {
+ return hmod;
+ }
+ }
+ }
+
+ return (HMOD)NULL;
+}
+
+
+/*** BPUpdateMemory
+**
+** Synopsis:
+** bpstatus = BPUpdateMemory( size )
+**
+** Entry:
+** size - size of memory changed
+**
+** Returns:
+** BPSTATUS
+**
+** Description:
+**
+*/
+
+BPSTATUS PASCAL
+BPUpdateMemory(
+ ULONG Size
+ )
+{
+#if 1
+ return BPNOERROR;
+#else
+ BPSTATUS Ret = BPNOERROR;
+ ADDR AddrCur;
+ ADDR AddrBp;
+ HBPT hBpt;
+ LPBPP lpBpp;
+
+ if ( MemoryBpCount > 0 ) {
+
+ if ( LppdCur && LptdCur && LptdCur->tstate != tsRunning ) {
+
+ //
+ // Get the address of the memory that was changed. Note that this
+ // assumes that nobody has changed the adrCurrent since the
+ // memory was changed.
+ //
+ OSDGetAddr( LppdCur->hpid, LptdCur->htid, adrCurrent, &AddrCur );
+
+ //
+ // Loop thru all the breakpoints looking for instantiated Memory
+ // breakpoints.
+ //
+ Dbg( BPNextHbpt( &hBpt, bptFirst) == BPNOERROR);
+ while (hBpt != NULL) {
+
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ if ( (lpBpp->bpstate & bpstateSet) != 0 &&
+ lpBpp->fMemory // &&
+ //lpBpp->Mem ) if 0
+ {
+
+ //
+ // If the breakpoint uses the memory that was changed,
+ // update its buffer.
+ //
+ AddrBp = lpBpp->AddrMem;
+ SYFixupAddr( &AddrBp );
+
+ if ( GetAddrSeg( AddrCur ) == GetAddrSeg( AddrBp ) &&
+ GetAddrOff( AddrCur ) >= GetAddrOff( AddrBp ) &&
+ (GetAddrOff( AddrCur ) + Size ) <=
+ (GetAddrOff( AddrBp ) + lpBpp->cbDataSize) ) {
+
+ if ( OSDSetAddr( lpBpp->hPid,
+ lpBpp->hTid,
+ (ADR)adrCurrent,
+ &AddrBp) == xosdNone ) {
+ Dbg(OSDPtrace( osdReadBuf,
+ lpBpp->cbDataSize,
+ lpBpp->Mem,
+ lpBpp->hPid,
+ lpBpp->hTid) ==
+ (XOSD)lpBpp->cbDataSize);
+ }
+ }
+ }
+
+ Dbg( BPNextHbpt( &hBpt, bptNext) == BPNOERROR );
+ }
+ }
+ }
+
+ return Ret;
+#endif
+}
+
+
+VOID
+PASCAL
+BPSegLoad(
+ ULONG Selector
+ )
+{
+ HBPT hBpt = 0;
+ LPBPP lpBpp;
+ int Count;
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+
+ while (hBpt != NULL) {
+
+ lpBpp = LLLpvFromPlle( hBpt );
+
+ if (lpBpp->bpstate == (bpstateVirtual | bpstateEnabled)) {
+ lpBpp->fMarkAdd = TRUE;
+ Count++;
+ }
+
+ Dbg(BPNextHbpt( &hBpt, bptNext) == BPNOERROR);
+ }
+
+ if ( Count > 0 ) {
+ BPCommit();
+ }
+}
+
+BOOL
+PASCAL
+BPSymbolLoading (
+ BOOL Enabled
+ )
+{
+ BOOL f = SymbolLoadingEnabled;
+ SymbolLoadingEnabled = Enabled;
+ return f;
+}
+
+BOOL
+PASCAL
+BPSymbolsMayBeAvailable (
+ HBPT hBpt
+ )
+/*++
+
+Routine Description:
+
+ Returns TRUE if there is any possibility that we might be able to
+ bind this BP with the currently loaded symbols.
+
+Arguments:
+
+ hBpt - Supplies breakpoint handle
+
+Return Value:
+
+ None
+
+
+--*/
+{
+ LPBPP lpBpp = LLLpvFromPlle( hBpt );
+ BOOL Ret = TRUE;
+ char rgch[ 256 ];
+ char *p;
+ char *Module;
+ HEXE Hexe;
+ LPDEBUGDATA DebugData;
+
+
+ if ( lpBpp ) {
+
+ if ( lpBpp->atmCxtDef != 0 || lpBpp->atmAddrCxt != 0 ) {
+
+ rgch[0] = 0;
+
+ if ( lpBpp->atmAddrCxt != 0 ) {
+ GetAtomName( lpBpp->atmAddrCxt, rgch, sizeof(rgch)-1 );
+ } else {
+ GetAtomName( lpBpp->atmCxtDef, rgch, sizeof(rgch)-1 );
+ }
+
+ Module = NULL;
+ SplitExpression( rgch, &p, &Module );
+
+ if ( Module ) {
+
+ p = strpbrk( Module, "} \t" );
+
+ if ( p ) {
+
+ *p = 0;
+
+ Hexe = SHGethExeFromName( Module );
+
+ if ( !Hexe ) {
+
+ Ret = FALSE;
+
+ } else {
+
+ DebugData = SHGetDebugData( Hexe );
+
+ if ( DebugData ) {
+ switch ( DebugData->she ) {
+ case sheDeferSyms:
+ case sheNone:
+ case sheSymbolsConverted:
+ break;
+
+ default:
+ Ret = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return Ret;
+}
diff --git a/private/windbg/windbg/calls.c b/private/windbg/windbg/calls.c
new file mode 100644
index 000000000..2d749eba9
--- /dev/null
+++ b/private/windbg/windbg/calls.c
@@ -0,0 +1,241 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ calls.c
+
+Abstract:
+
+ This file contains the UI code for dealing with the call stack dialog box
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+extern LPSHF Lpshf;
+
+/*** SetUpCallsListBox
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void SetUpCallsListBox(HWND hDlg)
+{
+ char *pch;
+ int i;
+ WPARAM cxExtent = 0;
+ SIZE size;
+ HDC hdc;
+ TEXTMETRIC tm;
+ HFONT hFont;
+ HWND hList;
+ char szCallItem[255];
+
+ // ensure that the calls stack is set up
+
+ CLGetWalkbackStack(LppdCur, LptdCur);
+
+ // set up the menu items
+
+ hList = GetDlgItem( hDlg, ID_CALLS_CALLSTACK );
+ SendMessage( hList, WM_SETREDRAW, FALSE, 0L );
+ hdc = GetDC( hList );
+
+ for (i = 0; i < (int)G_cisCallsInfo.cEntries; i++) {
+ // get this stack element
+
+ pch = CLGetProcName(i, szCallItem, sizeof(szCallItem), FALSE);
+ if (!*pch)
+ break;
+
+ GetTextExtentPoint( hdc, szCallItem, strlen(szCallItem), &size );
+ if (size.cx > (LONG)cxExtent) {
+ cxExtent = size.cx;
+ }
+
+ SendMessage( hList, LB_ADDSTRING, 0, (LONG)(LPSTR)szCallItem );
+ }
+
+ hFont = (HFONT)SendMessage( hList, WM_GETFONT, 0, 0L );
+ if (hFont != NULL) {
+ SelectObject( hdc, hFont );
+ }
+ GetTextMetrics( hdc, &tm );
+ ReleaseDC( hList, hdc );
+ cxExtent = cxExtent + tm.tmMaxCharWidth;
+
+ SendMessage( hList, LB_SETHORIZONTALEXTENT, cxExtent, 0L );
+ SendMessage( hList, WM_SETREDRAW, TRUE, 0L );
+
+ // Put us back at the top of the list box
+
+ SendMessage( hList, LB_SETTOPINDEX, 0, 0L );
+
+ if (i > 0) {
+ // Something was added so set the top item as currently selected
+ SendMessage( hList, LB_SETCURSEL, 0, 0L );
+ }
+ return;
+} /* SetUpCallsListBox() */
+
+/*** DispCallInfo
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL PASCAL NEAR DispCallInfo(HWND hWnd, int iCall)
+{
+ CXF CXFT;
+
+ Unreferenced( hWnd );
+
+ // Get the CXT
+
+ memset(&CXFT, 0, sizeof(CXF));
+
+ // Get the CXT
+
+ *SHpADDRFrompCXT(SHpCXTFrompCXF(&CXFT)) =
+ G_cisCallsInfo.frame[iCall].addrCSIP;
+ *SHpFrameFrompCXF(&CXFT) = G_cisCallsInfo.frame[iCall].Frame;
+
+ if (G_cisCallsInfo.frame[iCall].module) {
+ // now set the rest of the context
+
+ if (!ADDR_IS_LI(G_cisCallsInfo.frame[iCall].addrCSIP)) {
+ SYUnFixupAddr(&G_cisCallsInfo.frame[iCall].addrCSIP);
+ }
+ SHSetCxt(&G_cisCallsInfo.frame[iCall].addrCSIP, SHpCXTFrompCXF(&CXFT));
+ }
+
+ // Try and load corresponding source file...
+
+ if (MoveEditorToAddr(SHpADDRFrompCXT(SHpCXTFrompCXF(&CXFT)))) {
+
+ //
+ //... and display corresponding locals
+ // Set the EM to use the registers from the right frame.
+ //
+ OSDSetFrameContext( LppdCur->hpid, LptdCur->htid, iCall, 0 );
+
+ if ( GetLocalHWND != 0) {
+ SendMessage(GetLocalHWND(), WU_UPDATE, (WPARAM)(LPSTR)&CXFT, 0L);
+ }
+ } else {
+ if (disasmView == -1) {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ }
+ }
+
+ if (disasmView != -1) {
+ ViewDisasm(SHpADDRFrompCXT(SHpCXTFrompCXF(&CXFT)), disasmForce);
+ }
+ return TRUE;
+} /* DispCallInfo() */
+
+/*** DlgCalls
+**
+** Synopsis:
+** bool = DlgCalls(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg
+** message
+** wParam
+** lParam
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL EXPORT DlgCalls(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ int i;
+ HWND hCallList = GetDlgItem(hDlg, ID_CALLS_CALLSTACK);
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ // set up the calls list box
+ SetUpCallsListBox(hDlg);
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == LBN_DBLCLK)
+ {
+ goto Calls_Goto;
+ }
+ switch (wParam) {
+
+ case ID_CALLS_GOTO:
+Calls_Goto:
+ // Set the source window to the context from
+ // the selected call
+
+ // is anything selected...
+ i = (int)SendMessage(hCallList, LB_GETCURSEL, 0, 0L);
+
+ if (i != LB_ERR) {
+ if (DispCallInfo(hDlg, i)) {
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ } else {
+ ErrorBox(ERR_Dbg_Calls_No_Source);
+ SetFocus(hCallList);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case ID_CALLS_CALLSTACK:
+ if (HIWORD(lParam) == LBN_DBLCLK) {
+ goto Calls_Goto;
+ }
+ break;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_CALLS_HELP));
+ return TRUE;
+ }
+ break;
+ }
+
+ case WM_DESTROY:
+ break;
+ }
+
+ return FALSE;
+} /* DlgCalls() */
diff --git a/private/windbg/windbg/callswin.c b/private/windbg/windbg/callswin.c
new file mode 100644
index 000000000..6bab5b8bd
--- /dev/null
+++ b/private/windbg/windbg/callswin.c
@@ -0,0 +1,2453 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ callswin.c
+
+Abstract:
+
+ This module contains the main line code for display of calls window.
+
+Author:
+
+ Wesley Witt (wesw) 6-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+typedef struct _tagCALLSWINOPTIONS {
+ DWORD Length;
+ USHORT Frameptr : 1;
+ USHORT RetAddr : 1;
+ USHORT FuncName : 1;
+ USHORT Displacement : 1;
+ USHORT Params : 1;
+ USHORT Stack : 1;
+ USHORT Source : 1;
+ USHORT Module : 1;
+ USHORT Rtf : 1;
+ USHORT FrameNum : 1;
+ USHORT Unused : 6;
+ USHORT MaxFrames;
+} CALLSWINOPTIONS, *PCALLSWINOPTIONS;
+
+
+extern CXF CxfIp;
+extern LPSHF Lpshf;
+
+
+#define SAVE_EBP(f) f.Reserved[0]
+#define TRAP_TSS(f) f.Reserved[1]
+#define TRAP_EDITED(f) f.Reserved[1]
+#define SAVE_TRAP(f) f.Reserved[2]
+
+#define ADDREQ(a,b) ((a).Offset == (b).Offset && \
+ (a).Segment == (b).Segment && \
+ (a).Mode == (b).Mode )
+
+HWND hWndCalls;
+STACKFRAME stkFrameSave;
+STACKINFO StackInfo[MAX_FRAMES];
+DWORD FrameCount;
+HWND hwndList;
+int myView;
+HFONT hFontList;
+HBRUSH hbrBackground;
+CALLSWINOPTIONS Options = { //
+ // *** Set the options struct to some
+ // *** reasonable default values
+ //
+ sizeof(CALLSWINOPTIONS),
+ TRUE, // Frameptr
+ TRUE, // RetAddr
+ TRUE, // FuncName
+ TRUE, // Displacement
+ TRUE, // Params
+ FALSE, // Stack
+ FALSE, // Source
+ TRUE, // Module
+ FALSE, // Rtf
+ FALSE, // FrameNum
+ 0, // Unused
+ 100 // MaxFrames;
+ };
+
+
+extern LPPD LppdCommand;
+extern LPTD LptdCommand;
+
+extern HWND GetLocalHWND(void);
+
+VOID
+FillStackFrameWindow(
+ HWND hwndList,
+ BOOL fRefresh
+ );
+
+LONG
+CreateCallsWindow(
+ HWND hWnd,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+VOID
+GetProcInfo(
+ LPSTACKINFO si,
+ BOOL fFull
+ );
+
+void
+FormatStackFrameString(
+ LPSTR lsz,
+ DWORD cb,
+ LPSTACKINFO si,
+ PCALLSWINOPTIONS pOpt,
+ DWORD width
+ );
+
+BOOL
+GoUntilStackFrame(
+ LPSTACKINFO si
+ );
+
+VOID
+ModifyStyle(
+ HWND hwnd,
+ INT styleBit,
+ BOOL toggle
+ );
+
+
+HWND
+GetCallsHWND(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Helper function that returns the window handle
+ for the calls window.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ HWND for the calls window, or NULL if the window is closed.
+
+--*/
+
+{
+ return(hWndCalls);
+}
+
+BOOL
+IsCallsInFocus(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Determines whether the calls window is in focus.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE - the calls window is in focus
+ FALSE - the calls window is not in focus
+
+--*/
+
+{
+ HWND hwndFocus = GetFocus();
+
+ if (hwndFocus == hWndCalls ||
+ hwndFocus == hwndList) {
+
+ return TRUE;
+
+ }
+
+ return FALSE;
+}
+
+
+LONG
+CallsWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Window procedure for the calls stack window.
+
+Arguments:
+
+ hwnd - window handle
+ msg - message number
+ wParam - first message parameter
+ lParam - second message parameter
+
+Return Value:
+
+ TRUE - did not process the message
+ FALSE - did process the message
+
+--*/
+
+{
+ DWORD lbItem;
+ RECT cRect;
+ LPCHOOSEFONT cf;
+
+
+ switch (msg) {
+ case WM_CREATE:
+ memset( &stkFrameSave.AddrFrame, 0, sizeof(ADDRESS) );
+ memset( &stkFrameSave.AddrReturn, 0, sizeof(ADDRESS) );
+ return CreateCallsWindow( hwnd, wParam, lParam );
+
+ case WM_MDIACTIVATE:
+ if (hwnd == (HWND) lParam) {
+ hwndActive = hwnd;
+ hwndActiveEdit = hwnd;
+ curView = myView;
+/***
+ CheckMenuItem( hWindowSubMenu,
+ (WORD)FindWindowMenuId(CALLS_WIN,curView,TRUE),
+ MF_CHECKED
+ );
+***/
+ EnableRibbonControls(ERC_ALL, FALSE);
+ } else {
+/***
+ CheckMenuItem( hWindowSubMenu,
+ (WORD)FindWindowMenuId(CALLS_WIN,curView,TRUE),
+ MF_UNCHECKED
+ );
+***/
+ hwndActive = NULL;
+ hwndActiveEdit = NULL;
+ curView = -1;
+ }
+ break;
+
+ case WM_MOUSEACTIVATE:
+ return MA_ACTIVATE;
+
+ case WM_WINDOWPOSCHANGED:
+ if (((LPWINDOWPOS)lParam)->flags & SWP_NOSIZE) {
+ break;
+ }
+ GetClientRect( hwnd, &cRect );
+ MoveWindow( hwndList,
+ 0,
+ 0,
+ cRect.right - cRect.left,
+ cRect.bottom - cRect.top,
+ TRUE
+ );
+ FillStackFrameWindow( hwndList, FALSE );
+ break;
+
+ case WM_SETFOCUS:
+ SetFocus( hwndList );
+ return 0;
+
+ case WM_COMMAND:
+ if (HIWORD(wParam) == LBN_DBLCLK) {
+ lbItem = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
+ GotoFrame( lbItem );
+ }
+ if (LOWORD(wParam) == IDM_RUN_TOCURSOR) {
+ lbItem = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
+ if (!GoUntilStackFrame( &StackInfo[lbItem] )) {
+ MessageBeep( MB_OK );
+ }
+ }
+ break;
+
+ case WM_VKEYTOITEM:
+ if (LOWORD(wParam) == VK_RETURN) {
+ lbItem = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
+ GotoFrame( lbItem );
+ } else
+ if (LOWORD(wParam) == (DWORD)'G') {
+ lbItem = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
+ if (!GoUntilStackFrame( &StackInfo[lbItem] )) {
+ MessageBeep( MB_OK );
+ }
+ } else
+ if (LOWORD(wParam) == (DWORD)'R') {
+ FillStackFrameWindow( hwndList, TRUE );
+ }
+ break;
+
+ case WU_OPTIONS:
+ FillStackFrameWindow( hwndList, TRUE );
+ return TRUE;
+
+ case WU_UPDATE:
+ FillStackFrameWindow( hwndList, TRUE );
+ return TRUE;
+
+ case WU_INFO:
+ return TRUE;
+
+ case WU_DBG_LOADEM:
+ return TRUE;
+
+ case WU_DBG_LOADEE:
+ return TRUE;
+
+ case WU_SETWATCH:
+ return TRUE;
+
+ case WU_AUTORUN:
+ return TRUE;
+
+ case WU_DBG_UNLOADEE:
+ case WU_DBG_UNLOADEM:
+ case WU_INVALIDATE:
+ SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
+ FrameCount = 0;
+ return FALSE;
+
+ case WM_SETFONT:
+ cf = (LPCHOOSEFONT)lParam;
+ DeleteObject( hFontList );
+ hFontList = CreateFontIndirect( cf->lpLogFont );
+ Views[myView].font = hFontList;
+ SendMessage( hwndList, WM_SETFONT, (WPARAM)hFontList, (LPARAM)FALSE );
+ InvalidateRect(hwndList, NULL, TRUE);
+ InvalidateRect(hwnd, NULL, TRUE);
+ FillStackFrameWindow( hwndList, TRUE );
+ return TRUE;
+
+ case WU_CLR_BACKCHANGE:
+ DeleteObject( hbrBackground );
+ hbrBackground = CreateSolidBrush( StringColors[CallsWindow].BkgndColor);
+ return TRUE;
+
+ case WU_CLR_FORECHANGE:
+ return TRUE;
+
+ case WM_CTLCOLORLISTBOX:
+ SetBkColor( (HDC)wParam, StringColors[CallsWindow].BkgndColor );
+ SetTextColor( (HDC)wParam, StringColors[CallsWindow].FgndColor);
+ return (LRESULT)(hbrBackground);
+
+ case WM_DESTROY:
+ DeleteObject( hbrBackground );
+ DeleteWindowMenuItem (myView);
+ Views[myView].Doc = -1;
+ hWndCalls = NULL;
+ FrameCount = 0;
+ hwndList = NULL;
+ break;
+ }
+
+ return DefMDIChildProc( hwnd, msg, wParam, lParam );
+}
+
+
+VOID
+FillStackFrameWindow(
+ HWND hwndList,
+ BOOL fRefresh
+ )
+
+/*++
+
+Routine Description:
+
+ This functions clears the calls stack window and fills it with the
+ stack trace information contained in the StackInfo structure. If
+ the fRefresh flag is TRUE then the stack trace is refreshed.
+
+Arguments:
+
+ hwndList - Window handle for the listbox that contains the call stack
+ fRefresh - TRUE - the stack trace should be refreshed
+ FALSE - the current stack trace is simply displayed
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD i;
+ char buf[1024*4];
+ HFONT hFont;
+ HDC hdc;
+ TEXTMETRIC tm;
+ DWORD width;
+ RECT rect;
+ DWORD lbItem;
+ SIZE size;
+ WPARAM cxExtent = 0;
+
+
+ if (fRefresh) {
+ i = Options.MaxFrames;
+ if (GetCompleteStackTrace( 0, 0, 0, StackInfo, &i, TRUE, TRUE )) {
+ FrameCount = i;
+ }
+ }
+
+ lbItem = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
+ SendMessage( hwndList, WM_SETREDRAW, FALSE, 0L );
+ SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
+
+ //
+ // get the text metrics for the font currently in use
+ //
+ hdc = GetDC( hwndList );
+ hFont = (HFONT)SendMessage( hwndList, WM_GETFONT, 0, 0 );
+ if (hFont != NULL) {
+ SelectObject( hdc, hFont );
+ }
+ GetTextMetrics( hdc, &tm );
+
+ //
+ // is it a fixed pitched font? (yes using not is correct!)
+ //
+ if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
+
+ //
+ // calculate the width of the listbox in characters
+ //
+ GetWindowRect( hwndList, &rect );
+
+ if (FrameCount > (DWORD)((rect.bottom - rect.top) / tm.tmHeight)) {
+ //
+ // there will be a vertical scroll bar in the listbox
+ // so we must subtract the width of the scroll bar
+ // from the width
+ //
+ width = (rect.right - rect.left - GetSystemMetrics(SM_CXVSCROLL) - 1)
+ / tm.tmMaxCharWidth;
+ } else {
+ width = (rect.right - rect.left) / tm.tmMaxCharWidth;
+ }
+
+ } else {
+
+ //
+ // zero says do not right justify the source info
+ //
+ width = 0;
+
+ }
+
+ for (i=0; i<FrameCount; i++) {
+
+ //
+ // format the string
+ //
+ FormatStackFrameString( buf, sizeof(buf), &StackInfo[i], &Options, width );
+
+ //
+ // get the width of the item
+ //
+ GetTextExtentPoint( hdc, buf, strlen(buf), &size );
+ if (size.cx > (LONG)cxExtent) {
+ cxExtent = size.cx;
+ }
+
+ //
+ // now lets add the data to the listbox
+ //
+ SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM) buf );
+ }
+
+ cxExtent = cxExtent + tm.tmMaxCharWidth;
+
+ if (environParams.horizScrollBars) {
+ SendMessage( hwndList, LB_SETHORIZONTALEXTENT, cxExtent, 0L );
+ }
+ SendMessage( hwndList, LB_SETCURSEL, (lbItem>FrameCount)?0:lbItem, 0 );
+ SendMessage( hwndList, WM_SETREDRAW, TRUE, 0L );
+
+ ReleaseDC( hwndList, hdc );
+
+ return;
+}
+
+void
+CreateAddress(
+ LPADDRESS lpaddress,
+ LPADDR lpaddr
+ )
+
+/*++
+
+Routine Description:
+
+ Helper function that transforms a LPADDRESS into a LPADDR. This is
+ necessary because IMAGEHLP and WINDBG do not use the same address
+ packet structures.
+
+Arguments:
+
+ lpaddress - pointer to a source LPADDRESS structure
+ lpaddr - pointer to a destination LPADDR structure
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ZeroMemory( lpaddr, sizeof(*lpaddr) );
+
+ lpaddr->addr.off = (OFFSET)lpaddress->Offset;
+ lpaddr->addr.seg = lpaddress->Segment;
+ lpaddr->mode.fFlat = lpaddress->Mode == AddrModeFlat;
+ lpaddr->mode.fOff32 = lpaddress->Mode == AddrMode1632;
+ lpaddr->mode.fReal = lpaddress->Mode == AddrModeReal;
+
+#ifdef OSDEBUG4
+ OSDUnFixupAddress( LppdCur->hpid, LptdCur->htid, lpaddr );
+#else
+ OSDPtrace( osdUnFixupAddr, 0, lpaddr, LppdCur->hpid, LptdCur->htid );
+#endif
+}
+
+void
+LoadSymbols(
+ LPADDRESS lpaddress
+ )
+
+/*++
+
+Routine Description:
+
+ Helper function that ensures that symbols are loaded for the
+ address specified in the lpaddress argument.
+
+Arguments:
+
+ lpaddress - pointer to a source LPADDRESS structure
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addr;
+
+
+ CreateAddress( lpaddress, &addr );
+
+ if ( (HPID)emiAddr( addr ) == LppdCur->hpid ) {
+ //
+ // Get right EMI and load symbols if defered
+ //
+ emiAddr( addr ) = 0;
+ ADDR_IS_LI( addr ) = FALSE;
+
+#ifdef OSDEBUG4
+ OSDSetEmi( LppdCur->hpid, LptdCur->htid, &addr );
+#else
+ OSDPtrace( osdSetEmi, wNull, &addr, LppdCur->hpid, LptdCur->htid );
+#endif
+ if ( (HPID)emiAddr( addr ) != LppdCur->hpid ) {
+
+ SHWantSymbols( (HEXE)emiAddr( addr ) );
+
+ }
+ }
+}
+
+
+VOID
+GetSymbolFromAddr(
+ LPADDR lpaddr,
+ PHSYM lpsymbol,
+ LPDWORD lpclt,
+ LPBOOL lpfInProlog
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets an HSYM for the address provided.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ lpsymbol - The HSYM that receives the HSYM for lpaddr.
+ lpclt - Indicates the symbol type.
+ lpfInProlog - Is the address in the function prolog?
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addrT;
+ HBLK hblk;
+ ADDR addr;
+ ADDR addr2;
+ CHAR rgch[256];
+ CXT cxt;
+
+
+
+ addr = *lpaddr;
+
+ addr2 = *lpaddr;
+ SYUnFixupAddr( &addr2 );
+
+ ZeroMemory( &cxt, sizeof ( CXT ) );
+ SHSetCxt( &addr, &cxt );
+
+ if (SHHPROCFrompCXT(&cxt)) {
+
+ *lpsymbol = (HSYM) SHHPROCFrompCXT ( &cxt );
+ *lpclt = cltProc;
+ SHAddrFromHsym( &addrT, *lpsymbol );
+ SetAddrOff( &addr, GetAddrOff(addrT) );
+ *lpfInProlog = SHIsInProlog( &cxt );
+
+ } else if (SHHBLKFrompCXT( &cxt )) {
+
+ hblk = SHHBLKFrompCXT( &cxt );
+ ZeroMemory( &addrT, sizeof ( ADDR ) );
+ SHAddrFromHsym( &addrT, (HSYM) hblk );
+ if (SHGetSymName((HSYM)hblk,rgch) != NULL ) {
+ *lpsymbol = (HSYM) hblk;
+ *lpclt = cltBlk;
+ } else {
+ *lpsymbol = (HSYM) NULL;
+ *lpclt = cltNone;
+ }
+ SetAddrOff( &addr, GetAddrOff ( addrT ) );
+ *lpfInProlog = FALSE;
+
+ } else
+ if ( PHGetNearestHsym( &addr2,
+ (HEXE)(SHpADDRFrompCXT( &cxt ) ->emi),
+ (PHSYM) lpsymbol ) < 0xFFFFFFFF ) {
+
+ ZeroMemory( &addrT, sizeof ( ADDR ) );
+ SHAddrFromHsym( &addrT, *lpsymbol );
+ *lpclt = cltPub;
+ SetAddrOff( &addr, GetAddrOff( addrT ) );
+ *lpfInProlog = FALSE;
+
+ } else {
+
+ *lpsymbol = (HSYM) NULL;
+ *lpclt = cltNone;
+ *lpfInProlog = FALSE;
+
+ }
+}
+
+VOID
+GetContextString(
+ LPADDR lpaddr,
+ HSYM symbol,
+ DWORD clt,
+ LPSTR lpszContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function formats a context string for the address provided.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ symbol - The HSYM for lpaddr.
+ clt - Indicates the symbol type.
+ lpszContext - Buffer that receives the context string.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addrT;
+ ADDR addr;
+ HDEP hstr;
+ CXT cxt;
+
+
+ if (clt == cltNone) {
+ return;
+ }
+
+ if (symbol == 0) {
+ return;
+ }
+
+ addr = *lpaddr;
+
+ ZeroMemory( &cxt, sizeof(CXT) );
+ SHSetCxt( &addr, &cxt );
+ if (clt != cltNone) {
+ *SHpADDRFrompCXT( &cxt ) = addr;
+ } else {
+ *SHpADDRFrompCXT( &cxt ) = *lpaddr;
+ }
+ SHHMODFrompCXT( &cxt ) = SHHMODFrompCXT( &cxt );
+
+ if (clt == cltProc) {
+
+ SHAddrFromHsym( &addrT, symbol );
+ SetAddrOff( SHpADDRFrompCXT( &cxt ), GetAddrOff( addrT ) );
+ SHHPROCFrompCXT( &cxt ) = (HPROC) symbol;
+ SHHBLKFrompCXT( &cxt ) = (HBLK) symbol;
+
+ } else if (clt == cltBlk) {
+
+ SHHBLKFrompCXT( &cxt ) = (HBLK) symbol;
+
+ }
+
+ EEFormatCXTFromPCXT( &cxt, &hstr, runDebugParams.fShortContext );
+ if (runDebugParams.fShortContext) {
+ strcpy( lpszContext, (LPSTR)MMLpvLockMb(hstr) );
+ } else {
+ BPShortenContext( (LPSTR)MMLpvLockMb(hstr), lpszContext );
+ }
+
+ MMbUnlockMb(hstr);
+ EEFreeStr(hstr);
+}
+
+
+VOID
+GetDisplacement(
+ LPADDR lpaddr,
+ HSYM symbol,
+ ADDRESS addrPC,
+ LPDWORD lpdwDisplacement,
+ LPADDR lpProcAddr
+ )
+
+/*++
+
+Routine Description:
+
+ This function get the function address and the displacement that lpaddr is
+ from the beginning of the function.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ symbol - The HSYM for lpaddr.
+ addrPC - Current program counter that is used for the displacement
+ calculation.
+ lpdwDisplacement - Pointer to a DWORD that receives the displacement.
+ lpProcAddr - Pointer to an ADDR that receives the function address.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addr;
+ CXT cxt;
+
+
+ if (symbol == 0) {
+ return;
+ }
+
+ addr = *lpaddr;
+ ZeroMemory( &cxt, sizeof ( CXT ) );
+ SHSetCxt( &addr, &cxt );
+
+ addr = *SHpAddrFrompCxt( &cxt );
+ SHAddrFromHsym( &addr, symbol );
+ SYFixupAddr( &addr );
+ *lpProcAddr = addr;
+ SYUnFixupAddr( lpProcAddr );
+ *lpdwDisplacement = addrPC.Offset - GetAddrOff(addr);
+}
+
+
+VOID
+GetModuleName(
+ LPADDR lpaddr,
+ LPSTR lpszModule
+ )
+
+/*++
+
+Routine Description:
+
+ This function get the module name for the lpaddr provided.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ lpszModule - Buffer that receives the module name.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addr;
+
+ addr = *lpaddr;
+ SYFixupAddr( &addr );
+ SHGetModule( &addr, lpszModule );
+#ifdef DBCS
+ CharUpper( lpszModule );
+#else
+ _strupr( lpszModule );
+#endif
+}
+
+
+VOID
+GetFrameInfo(
+ LPADDR lpaddr,
+ ADDRESS AddrFrame,
+ PCXF lpCxf
+ )
+
+/*++
+
+Routine Description:
+
+ This function fills in the FRAME structure in the lpCxf passed in.
+ The FRAME information is used to position the debugger at a virtual
+ frame for the purposes of examining the locals at that frame. It
+ is also used to evaluate an expression in the context of a previous
+ stack frame.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ AddrFrame - Desired stack frame address.
+ lpCxf - Pointer to a CXF structure that receives the FRAME.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addrData;
+ ADDR addrT;
+ FRAME frame;
+
+
+ ZeroMemory( &frame, sizeof(frame) );
+ switch (AddrFrame.Mode) {
+ case AddrModeFlat:
+ frame.mode.fFlat = TRUE;
+ frame.mode.fOff32 = TRUE;
+ frame.mode.fReal = FALSE;
+ break;
+
+ case AddrModeReal:
+ frame.mode.fFlat = FALSE;
+ frame.mode.fOff32 = FALSE;
+ frame.mode.fReal = TRUE;
+ break;
+
+ case AddrMode1616:
+ frame.mode.fFlat = FALSE;
+ frame.mode.fOff32 = FALSE;
+ frame.mode.fReal = FALSE;
+ break;
+
+ case AddrMode1632:
+ frame.mode.fFlat = FALSE;
+ frame.mode.fOff32 = TRUE;
+ frame.mode.fReal = FALSE;
+ break;
+ }
+
+ SetFrameBPSeg( frame, AddrFrame.Segment );
+ SetFrameBPOff( frame, AddrFrame.Offset );
+ frame.SS = AddrFrame.Segment;
+ OSDGetAddr ( LppdCur->hpid, LptdCur->htid, adrData, &addrData );
+ frame.DS = GetAddrSeg ( addrData );
+ frame.TID = LptdCur->htid;
+ frame.PID = LppdCur->hpid;
+ addrT = *lpaddr;
+ SYFixupAddr( &addrT );
+ *SHpADDRFrompCXT(SHpCXTFrompCXF( lpCxf )) = addrT;
+ *SHpFrameFrompCXF(lpCxf) = frame;
+ if (!ADDR_IS_LI(addrT)) {
+ SYUnFixupAddr( &addrT );
+ }
+ SHSetCxt(&addrT, SHpCXTFrompCXF( lpCxf ));
+}
+
+
+VOID
+GetFunctionName(
+ LPADDR lpaddr,
+ HSYM symbol,
+ LPSTR lpszProcName
+ )
+
+/*++
+
+Routine Description:
+
+ This function get the function name for the provided symbol.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ symbol - The HSYM for lpaddr.
+ lpszProcName - Buffer that receives the function name.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (symbol) {
+ SHGetSymName( symbol, lpszProcName );
+ } else {
+ sprintf( lpszProcName, "0x%08x", lpaddr->addr.off );
+ }
+}
+
+
+VOID
+GetFunctionParameters(
+ LPADDR lpaddr,
+ HSYM symbol,
+ DWORD FrameNum,
+ LPSTR lpszParams,
+ CXF Cxf
+ )
+
+/*++
+
+Routine Description:
+
+ This function formats a string that represents the parameters to
+ the function specified by symbol.
+
+Arguments:
+
+ lpaddr - An ADDR struct contining the address of the symbol.
+ symbol - The HSYM for lpaddr.
+ FrameNum - Frame number (zero relative).
+ lpszParams - Buffer that receives the parameters string.
+ Cxf - Frame context.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addr;
+ CXT cxt;
+ HTM htm;
+ DWORD strIndex;
+ USHORT cParm = 0;
+ SHFLAG shflag = FALSE;
+ LPSTR p;
+ DWORD i;
+ HTM htmParm;
+ EEHSTR hName;
+ LPSTR lpch;
+ FRAME frame;
+
+
+ if (symbol == 0) {
+ return;
+ }
+
+ addr = *lpaddr;
+ ZeroMemory( &cxt, sizeof ( CXT ) );
+ SHSetCxt( &addr, &cxt );
+
+ fUseFrameContext = TRUE;
+ OSDSetFrameContext( LppdCur->hpid, LptdCur->htid, FrameNum, 0 );
+
+ if (EEGetTMFromHSYM( symbol, &cxt, &htm, &strIndex, FALSE ) != EENOERROR) {
+ goto exit;
+ }
+
+ if (EEcParamTM( &htm, &cParm, &shflag ) != EENOERROR) {
+ goto exit;
+ }
+
+ p = lpszParams;
+ frame = *SHpFrameFrompCXF( &Cxf );
+
+ for ( i = 0; i < cParm; i++ ) {
+ if (EEGetParmTM( &htm, (EERADIX) i, &htmParm, &strIndex, FALSE, radix ) == EENOERROR ) {
+ EEvaluateTM( &htmParm, &frame, EEVERTICAL );
+ if (EEGetValueFromTM( &htmParm, radix, (PEEFORMAT)"p", &hName ) == EENOERROR ) {
+ lpch = MMLpvLockMb ( hName );
+ memcpy ( p, lpch, strlen(lpch) );
+ p += strlen(lpch);
+ MMbUnlockMb ( hName );
+ EEFreeStr ( hName );
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ EEFreeTM (&htmParm);
+ }
+ }
+
+ if (shflag) {
+ memcpy( p, "...", 3 );
+ p += 3;
+ }
+
+ while (( *( p - 1 ) == ' ' ) || ( *( p - 1 ) == ',' ) ) {
+ p--;
+ }
+ *p = '\0';
+
+exit:
+ fUseFrameContext = FALSE;
+ EEFreeTM ( &htm );
+}
+
+VOID
+GetProcInfo(
+ LPSTACKINFO si,
+ BOOL fFull
+ )
+
+/*++
+
+Routine Description:
+
+ This function fills in the STACKINFO structure with all of the
+ necessary information for a stack trace display.
+
+Arguments:
+
+ si - pointer to a STACKINFO structure
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HSYM symbol;
+ ADDR addr;
+ DWORD clt;
+
+
+ //
+ // clear out all of the struct except the frame & frame count
+ //
+ ZeroMemory( si->ProcName, sizeof(STACKINFO) - offsetof(STACKINFO,ProcName) );
+
+ //
+ // load symbols
+ //
+ LoadSymbols( &si->StkFrame.AddrPC );
+ LoadSymbols( &si->StkFrame.AddrReturn );
+
+ //
+ // fixup the address
+ //
+ CreateAddress( &si->StkFrame.AddrPC, &addr );
+
+ GetSymbolFromAddr( &addr, &symbol, &clt, &si->fInProlog );
+ if (fFull) {
+ GetContextString( &addr, symbol, clt, si->Context );
+ GetFunctionName( &addr, symbol, si->ProcName );
+ GetModuleName( &addr, si->Module );
+ }
+ GetDisplacement( &addr, symbol, si->StkFrame.AddrPC, &si->Displacement, &si->ProcAddr );
+ GetFrameInfo( &addr, si->StkFrame.AddrFrame, &si->Cxf );
+ if (fFull) {
+ GetFunctionParameters( &addr, symbol, si->FrameNum, si->Params, si->Cxf );
+ }
+}
+
+
+BOOL
+GotoFrame(
+ int iCall
+ )
+
+/*++
+
+Routine Description:
+
+ This function positions either the source window or the
+ disassembly window to the address referenced by the
+ STAKINFO structure that is indexed by iCall.
+
+Arguments:
+
+ si - pointer to a array of STACKINFO structures
+ iCall - index of the desired STACKINFO structure
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CXF *cxf = &StackInfo[iCall].Cxf;
+
+
+ LocalFrameNumber = iCall;
+
+ if (MoveEditorToAddr(SHpADDRFrompCXT(SHpCXTFrompCXF(cxf)))) {
+ OSDSetFrameContext( LppdCur->hpid, LptdCur->htid, iCall, 0 );
+ if ( GetLocalHWND() != 0) {
+ SendMessage(GetLocalHWND(), WU_UPDATE, (WPARAM)(LPSTR)cxf, 0L);
+ }
+ } else {
+ if (disasmView == -1) {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ }
+ BringWindowToTop( Views[disasmView].hwndFrame );
+ SetFocus( Views[disasmView].hwndFrame );
+ }
+
+ if (disasmView != -1) {
+ ViewDisasm(SHpADDRFrompCXT(SHpCXTFrompCXF(cxf)), disasmForce);
+ }
+
+ return TRUE;
+}
+
+
+void
+OpenCallsWindow(
+ int type,
+ LPWININFO lpWinInfo,
+ int Preference
+ )
+
+/*++
+
+Routine Description:
+
+ This function opend a calls window.
+
+Arguments:
+
+ type - window type (calls window)
+ lpWinInfo - initial window position
+ Preference - view index
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WORD classId;
+ WORD winTitle;
+ HWND hWnd;
+ int view;
+ BOOL fZoomed;
+
+ MDICREATESTRUCT mcs;
+ char class[MAX_MSG_TXT];
+ char title[MAX_MSG_TXT];
+ char final[MAX_MSG_TXT+4];
+
+
+ classId = SYS_Calls_wClass;
+ winTitle = SYS_CallsWin_Title;
+ hWnd = GetCallsHWND();
+
+ if (hWnd) {
+ if (IsIconic(hWnd)) {
+ OpenIcon(hWnd);
+ }
+ SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM)hWnd, (ULONG)type);
+ return;
+ }
+
+ if (hwndActive)
+ fZoomed = IsZoomed(hwndActive) || IsZoomed(GetParent(hwndActive));
+
+ //
+ // Determine which view index we are going to use
+ //
+ if ( (Preference != -1) && (Views[Preference].Doc == -1) ) {
+ view = Preference;
+ }
+
+ else {
+ for (view=0; (view<MAX_VIEWS)&&(Views[view].Doc!=-1); view++);
+ }
+
+ if (view == MAX_VIEWS) {
+ ErrorBox(ERR_Too_Many_Opened_Views);
+ return;
+ }
+
+ // Get the Window Title and Window Class
+
+ Dbg(LoadString(hInst, classId, class, MAX_MSG_TXT));
+ Dbg(LoadString(hInst, winTitle, title, MAX_MSG_TXT));
+ RemoveMnemonic(title,title);
+ sprintf(final,"<%d> %s",view+1,title);
+
+ // Make sure the Menu gets setup
+ AddWindowMenuItem(-type, view);
+
+ // Have MDI Client create the Child
+
+ mcs.szTitle = final;
+ mcs.szClass = class;
+ mcs.hOwner = hInst;
+ if (lpWinInfo) {
+ mcs.x = lpWinInfo->coord.left;
+ mcs.y = lpWinInfo->coord.top;
+ mcs.cx = lpWinInfo->coord.right - lpWinInfo->coord.left;
+ mcs.cy = lpWinInfo->coord.bottom - lpWinInfo->coord.top;
+ mcs.style = (lpWinInfo->style & ~(WS_MAXIMIZE));
+ } else {
+ mcs.x = mcs.cx = CW_USEDEFAULT;
+ mcs.y = mcs.cy = CW_USEDEFAULT;
+ mcs.style = 0L;
+ }
+ mcs.lParam = (ULONG) (type | (view << 16));
+
+ hWnd = (HANDLE)SendMessage(hwndMDIClient, WM_MDICREATE, 0,
+ (LPARAM)(LPMDICREATESTRUCT)&mcs);
+
+ SetWindowWord(hWnd, GWW_VIEW, (WORD)view);
+
+ Views[view].hwndFrame = hWnd;
+ Views[view].hwndClient = 0;
+ Views[view].NextView = -1; /* No next view */
+ Views[view].Doc = -type;
+
+ if (fZoomed) {
+ ShowWindow(hWnd, SW_MAXIMIZE);
+ }
+
+ return;
+}
+
+LONG
+CreateCallsWindow(
+ HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates a calls window and fills the window
+ with a current stack trace.
+
+Arguments:
+
+ hwnd - calls window handle
+ wParam - font handle
+ lParam - pointer to a CREATESTRUCT
+
+Return Value:
+
+ Zero.
+
+--*/
+
+{
+ MDICREATESTRUCT *mdi;
+ int iView;
+ int iType;
+ RECT cRect;
+ DWORD dwStyle;
+
+
+ mdi = (MDICREATESTRUCT*)(((CREATESTRUCT*)lParam)->lpCreateParams);
+ myView = iView = (mdi->lParam >> 16) & 0xffff;
+ iType = (WORD)(mdi->lParam & 0xffff);
+ hWndCalls = hwnd;
+ GetClientRect( hwnd, &cRect );
+
+ dwStyle = WS_CHILD |
+ WS_VISIBLE |
+ LBS_NOTIFY |
+ LBS_NOINTEGRALHEIGHT |
+ LBS_WANTKEYBOARDINPUT;
+
+ if (environParams.vertScrollBars) {
+ dwStyle |= WS_VSCROLL;
+ }
+
+ if (environParams.horizScrollBars) {
+ dwStyle |= WS_HSCROLL;
+ }
+
+ hwndList = CreateWindow( "LISTBOX",
+ NULL,
+ dwStyle,
+ cRect.left,
+ cRect.top,
+ cRect.right - cRect.left,
+ cRect.bottom - cRect.top,
+ hwnd,
+ NULL,
+ GetModuleHandle(NULL),
+ NULL
+ );
+
+ hFontList = Views[myView].font;
+ if (!hFontList) {
+ Views[myView].font = hFontList = CreateFontIndirect( &defaultFont );
+ }
+ SendMessage( hwndList, WM_SETFONT, (WPARAM)hFontList, (LPARAM)FALSE );
+ hbrBackground = CreateSolidBrush( StringColors[CallsWindow].BkgndColor );
+
+ FillStackFrameWindow( hwndList, TRUE );
+
+ return 0;
+}
+
+
+LOGERR NEAR PASCAL
+LogCallStack(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function will dump a call stack to the command window.
+
+Arguments:
+
+ lpsz - arguments to callstack
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LPSTACKINFO StackInfo = NULL;
+ BOOL bSpecial = FALSE;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ DWORD i;
+ DWORD k = MAX_FRAMES;
+ int err;
+ int cch;
+ XOSD xosd = xosdNone;
+ CHAR buf[512];
+ CHAR errmsg[512];
+ DWORD StackAddr = 0;
+ DWORD FrameAddr = 0;
+ DWORD PCAddr = 0;
+ LPSTR p;
+ CALLSWINOPTIONS Options = { //
+ // *** Set the options struct to some
+ // *** reasonable default values
+ //
+ sizeof(CALLSWINOPTIONS),
+ TRUE, // Frameptr
+ TRUE, // RetAddr
+ TRUE, // FuncName
+ TRUE, // Displacement
+ TRUE, // Params
+ FALSE, // Stack
+ FALSE, // Source
+ TRUE, // Module
+ FALSE, // Rtf
+ FALSE, // FrameNum,
+ 0, // Unused
+ 500 // MaxFrames;
+ };
+ DWORD dwFrames = Options.MaxFrames;
+
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ TDWildInvalid();
+ PDWildInvalid();
+
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ i = sizeof(STACKINFO) * dwFrames;
+ StackInfo = malloc( i );
+ if (!StackInfo) {
+ CmdLogFmt( "Could not allocate memory for stack trace\n" );
+ goto done;
+ }
+ ZeroMemory( StackInfo, i );
+
+ //
+ // this code processes the 'K' command modifiers
+ //
+ // b - print first 3 parameters from stack
+ // s - print source information (file & lineno)
+ // v - runtime function information (fpo/pdata)
+ //
+ lpsz = CPSkipWhitespace(lpsz);
+ while (lpsz && *lpsz && *lpsz != ' ') {
+ switch (tolower(*lpsz)) {
+ case 'b':
+ Options.Frameptr = TRUE;
+ Options.RetAddr = TRUE;
+ Options.Displacement = TRUE;
+ Options.Stack = TRUE;
+ Options.Module = TRUE;
+ bSpecial = TRUE;
+ break;
+
+ case 's':
+ Options.Source = TRUE;
+ break;
+
+ case 'v':
+ Options.Rtf = TRUE;
+ break;
+
+ case 'n':
+ Options.FrameNum = TRUE;
+ break;
+
+ case ' ':
+ break;
+
+ default:
+ goto nextparse;
+ }
+ ++lpsz;
+ }
+
+nextparse:
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == '=') {
+ lpsz++;
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (!*lpsz) {
+ CmdLogFmt( "Missing stack frame\r\n" );
+ goto done;
+ }
+ p = CPszToken(lpsz, "");
+ FrameAddr = CPGetNbr( lpsz, radix, TRUE, &CxfIp, errmsg, &err );
+ if (err) {
+ CmdLogFmt( "Bad frame address\r\n" );
+ goto done;
+ }
+
+ lpsz = CPSkipWhitespace(p);
+ if (!*lpsz) {
+ CmdLogFmt( "Missing stack address\r\n" );
+ goto done;
+ }
+ p = CPszToken(lpsz, "");
+ StackAddr = CPGetNbr( lpsz, radix, TRUE, &CxfIp, errmsg, &err );
+ if (err) {
+ CmdLogFmt( "Bad stack address\r\n" );
+ goto done;
+ }
+
+ lpsz = CPSkipWhitespace(p);
+ if (!*lpsz) {
+ CmdLogFmt( "Missing PC\r\n" );
+ goto done;
+ }
+ p = CPszToken(lpsz, "");
+ PCAddr = CPGetNbr( lpsz, radix, TRUE, &CxfIp, errmsg, &err );
+ if (err) {
+ CmdLogFmt( "Bad PC address\r\n" );
+ goto done;
+ }
+
+ lpsz = CPSkipWhitespace(p);
+
+ }
+
+ if (*lpsz) {
+ if (*lpsz == 'l' || *lpsz == 'L') {
+ lpsz = CPSkipWhitespace(++lpsz);
+ }
+ if (!*lpsz) {
+ err = 1;
+ } else {
+ k = CPGetInt(lpsz, &err, &cch);
+ }
+ if (err || k < 1) {
+ CmdLogVar(ERR_Bad_Count);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ GetCompleteStackTrace( FrameAddr, StackAddr, PCAddr, StackInfo, &dwFrames, FALSE, TRUE );
+
+ k = min( k, dwFrames );
+
+ for (i=0; i<k; i++) {
+
+ if (i==0) {
+ if (bSpecial) {
+ switch( StackInfo[i].StkFrame.AddrPC.Mode ) {
+ case AddrModeFlat:
+ CmdLogFmt("FramePtr RetAddr Param1 Param2 Param3 Function Name\r\n");
+ break;
+
+ case AddrModeReal:
+ case AddrMode1616:
+ CmdLogFmt("FramePtr RetAddr Param1 Param2 Param3 Function Name\r\n");
+ break;
+
+ case AddrMode1632:
+ CmdLogFmt("FramePtr RetAddr Param1 Param2 Param3 Function Name\r\n");
+ break;
+ }
+ }
+ }
+
+ FormatStackFrameString( buf, sizeof(buf), &StackInfo[i], &Options, 0 );
+
+ CmdLogFmt( buf );
+ CmdLogFmt( "\r\n" );
+ }
+
+done:
+ if (StackInfo) {
+ free( StackInfo );
+ }
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+}
+
+
+INT
+LookupFrameAddress(
+ LPSTACKINFO lpsi,
+ DWORD frames,
+ ADDR addr
+ )
+
+/*++
+
+Routine Description:
+
+ Locates an address in the callback stack area.
+
+Arguments:
+
+ addr - An ADDR struct contining the address to find in the calls stack
+
+Return Value:
+
+ Index of the located stack frame or -1 on error.
+
+--*/
+
+{
+ int i;
+ ADDR addrPC;
+
+ SYUnFixupAddr( &addr );
+
+ for (i=0; i<(INT)frames; i++) {
+ CreateAddress( &lpsi[i].StkFrame.AddrPC, &addrPC );
+ SYUnFixupAddr( &addrPC );
+ if ((GetAddrSeg(lpsi[i].ProcAddr) == GetAddrSeg(addr)) &&
+ ((GetAddrOff(addr) >= GetAddrOff(lpsi[i].ProcAddr)) &&
+ (GetAddrOff(addr) < lpsi[i].StkFrame.AddrPC.Offset))) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+PCXF
+CLGetFuncCXF(
+ PADDR paddr,
+ PCXF pcxf
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used to resolve a context operator by filling in the
+ frame structure in the CXF passed in. Because this function may be called
+ while in the middle of an expression evaluation care must be taken to NEVER
+ call the EE while in this function. The EE is not re-entrant!
+
+Arguments:
+
+ paddr - An ADDR struct contining the address of the evaluation
+ pcxf - Pointer to a CXF struture
+
+Return Value:
+
+ Always return pcxf.
+
+--*/
+
+{
+ LPSTACKINFO StackInfo;
+ DWORD dwFrames = MAX_FRAMES;
+ INT frame;
+ ADDR addr;
+
+
+ Assert ( ADDR_IS_LI (*paddr));
+ addr = *paddr;
+ ZeroMemory( pcxf, sizeof ( CXF ) );
+
+ frame = sizeof(STACKINFO) * dwFrames;
+ StackInfo = malloc( frame );
+ if (!StackInfo) {
+ goto exit;
+ }
+ ZeroMemory( StackInfo, frame );
+
+ GetCompleteStackTrace( 0, 0, 0, StackInfo, &dwFrames, FALSE, FALSE );
+
+ if (dwFrames == 0) {
+ goto exit;
+ }
+
+ frame = LookupFrameAddress( StackInfo, MAX_FRAMES, addr );
+
+ if (frame == -1) {
+ goto exit;
+ }
+
+ CreateAddress( &StackInfo[frame].StkFrame.AddrPC, &addr );
+
+ SHSetCxt( &addr, &pcxf->cxt );
+
+ pcxf->Frame = StackInfo[frame].Cxf.Frame;
+ pcxf->cxt.addr = addr;
+
+exit:
+ if (StackInfo) {
+ free( StackInfo );
+ }
+
+ return pcxf;
+}
+
+
+BOOL FAR PASCAL EXPORT
+DlgCallsOptions(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog procedure for the calls stack options dialog.
+
+Arguments:
+
+ hwnd - window handle
+ msg - message number
+ wParam - first message parameter
+ lParam - second message parameter
+
+Return Value:
+
+ TRUE - did not process the message
+ FALSE - did process the message
+
+--*/
+
+{
+ switch (message) {
+ case WM_INITDIALOG:
+ CheckDlgButton( hDlg, ID_CWOPT_FRAMEPTR, Options.Frameptr );
+ CheckDlgButton( hDlg, ID_CWOPT_RETADDR, Options.RetAddr );
+ CheckDlgButton( hDlg, ID_CWOPT_FUNCNAME, Options.FuncName );
+ CheckDlgButton( hDlg, ID_CWOPT_DISPLACEMENT, Options.Displacement );
+ CheckDlgButton( hDlg, ID_CWOPT_PARAMS, Options.Params );
+ CheckDlgButton( hDlg, ID_CWOPT_STACK, Options.Stack );
+ CheckDlgButton( hDlg, ID_CWOPT_SOURCE, Options.Source );
+ CheckDlgButton( hDlg, ID_CWOPT_MODULE, Options.Module );
+ CheckDlgButton( hDlg, ID_CWOPT_RTF, Options.Rtf );
+ SetDlgItemInt ( hDlg, ID_CWOPT_MAXFRAMES, Options.MaxFrames, 0 );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK :
+ Options.Frameptr = IsDlgButtonChecked( hDlg, ID_CWOPT_FRAMEPTR );
+ Options.RetAddr = IsDlgButtonChecked( hDlg, ID_CWOPT_RETADDR );
+ Options.FuncName = IsDlgButtonChecked( hDlg, ID_CWOPT_FUNCNAME );
+ Options.Displacement = IsDlgButtonChecked( hDlg, ID_CWOPT_DISPLACEMENT );
+ Options.Params = IsDlgButtonChecked( hDlg, ID_CWOPT_PARAMS );
+ Options.Stack = IsDlgButtonChecked( hDlg, ID_CWOPT_STACK );
+ Options.Source = IsDlgButtonChecked( hDlg, ID_CWOPT_SOURCE );
+ Options.Module = IsDlgButtonChecked( hDlg, ID_CWOPT_MODULE );
+ Options.Rtf = IsDlgButtonChecked( hDlg, ID_CWOPT_RTF );
+ Options.MaxFrames = GetDlgItemInt( hDlg, ID_CWOPT_MAXFRAMES, &lParam, 0 );
+ UpdateDebuggerState( UPDATE_CALLS );
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ case IDWINDBGHELP:
+ WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_CALLSOPT_HELP);
+ return (TRUE);
+ }
+ }
+
+ return FALSE;
+}
+
+PLONG
+GetCallsStatus(
+ int nView
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates a CALLSWINOPTIONS structure, fills
+ it with the current options settings and then returns a
+ pointer to the newly allocated structure.
+
+Arguments:
+
+ nView - view number for calls window
+
+Return Value:
+
+ Pointer to a CALLSWINOPTIONS structure.
+
+--*/
+
+{
+ PCALLSWINOPTIONS pCallsOpt;
+
+
+ pCallsOpt = (PCALLSWINOPTIONS) malloc( sizeof(CALLSWINOPTIONS) );
+
+ pCallsOpt->Length = Options.Length;
+ pCallsOpt->Frameptr = Options.Frameptr;
+ pCallsOpt->RetAddr = Options.RetAddr;
+ pCallsOpt->FuncName = Options.FuncName;
+ pCallsOpt->Displacement = Options.Displacement;
+ pCallsOpt->Params = Options.Params;
+ pCallsOpt->Stack = Options.Stack;
+ pCallsOpt->Source = Options.Source;
+ pCallsOpt->Module = Options.Module;
+ pCallsOpt->Rtf = Options.Rtf;
+ pCallsOpt->FrameNum = Options.FrameNum;
+ pCallsOpt->MaxFrames = Options.MaxFrames;
+
+ return (PLONG)pCallsOpt;
+}
+
+
+void
+FreeCallsStatus(
+ int nView,
+ PLONG pStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This function frees a previously allocated CALLSWINOPTIONS structure.
+
+Arguments:
+
+ nView - view number for calls window
+ pStatus - Pointer to a CALLSWINOPTIONS structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ free( pStatus );
+
+ return;
+}
+
+void
+SetCallsStatus(
+ int nView,
+ PLONG Status
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the calls window options to the set of options
+ passed in by Status.
+
+Arguments:
+
+ nView - view number for calls window
+ pStatus - Pointer to a CALLSWINOPTIONS structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCALLSWINOPTIONS pCallsOpt = (PCALLSWINOPTIONS) Status;
+
+
+ Options.Frameptr = pCallsOpt->Frameptr;
+ Options.RetAddr = pCallsOpt->RetAddr;
+ Options.FuncName = pCallsOpt->FuncName;
+ Options.Displacement = pCallsOpt->Displacement;
+ Options.Params = pCallsOpt->Params;
+ Options.Stack = pCallsOpt->Stack;
+ Options.Source = pCallsOpt->Source;
+ Options.Module = pCallsOpt->Module;
+ Options.Rtf = pCallsOpt->Rtf;
+ Options.FrameNum = pCallsOpt->FrameNum;
+ Options.MaxFrames = pCallsOpt->MaxFrames;
+
+ return;
+}
+
+
+void
+FormatStackFrameString(
+ LPSTR lsz,
+ DWORD cb,
+ LPSTACKINFO si,
+ PCALLSWINOPTIONS pOpt,
+ DWORD width
+ )
+
+/*++
+
+Routine Description:
+
+ This function formats a string that reresents a stack frame and places
+ the data in the buffer pointed to by lsz. The current options control
+ the format of the data.
+
+Arguments:
+
+ nView - view number for calls window
+ pStatus - Pointer to a CALLSWINOPTIONS structure.
+
+ lsz - Pointer to a buffer that receives the formatted string.
+ cb - length of the lsz buffer.
+ si - Stack frame that is to be formatted.
+ pOpt - Options to control the formatting.
+ width - If non-zero this value indicates that the source information
+ is to be right justified in the buffer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPSTR beg = lsz;
+ DWORD i;
+ ADDR addr;
+ CHAR SrcFname[MAX_PATH];
+ WORD lineno;
+ CHAR szFname[_MAX_FNAME];
+ CHAR szExt[_MAX_EXT];
+ UINT processor;
+ PFPO_DATA pFpoData;
+
+
+ *lsz = '\0';
+
+ if (pOpt->FrameNum) {
+ if (radix == 10) {
+ sprintf( lsz, "%02d ", si->FrameNum );
+ } else if (radix == 16) {
+ sprintf( lsz, "%02x ", si->FrameNum );
+ } else if (radix == 8) {
+ sprintf( lsz, "%02o ", si->FrameNum );
+ }
+ lsz += strlen( lsz );
+ }
+
+ switch( si->StkFrame.AddrReturn.Mode ) {
+ case AddrModeFlat:
+ if (pOpt->Frameptr) {
+ sprintf( lsz, "%08x ", si->StkFrame.AddrFrame.Offset );
+ lsz += strlen( lsz );
+ }
+ if (pOpt->RetAddr) {
+ sprintf( lsz, "%08x ", si->StkFrame.AddrReturn.Offset );
+ lsz += strlen( lsz );
+ }
+ break;
+
+ case AddrMode1616:
+ case AddrModeReal:
+ if (pOpt->Frameptr) {
+ sprintf( lsz, "%04x:%04x ",
+ si->StkFrame.AddrFrame.Segment,
+ si->StkFrame.AddrFrame.Offset
+ );
+ lsz += strlen( lsz );
+ }
+ if (pOpt->RetAddr) {
+ sprintf( lsz, "%04x:%04x ",
+ si->StkFrame.AddrReturn.Segment,
+ si->StkFrame.AddrReturn.Offset
+ );
+ lsz += strlen( lsz );
+ }
+ break;
+
+ case AddrMode1632:
+ if (pOpt->Frameptr) {
+ sprintf( lsz, "%04x:%08x ",
+ si->StkFrame.AddrFrame.Segment,
+ si->StkFrame.AddrFrame.Offset
+ );
+ lsz += strlen( lsz );
+ }
+ if (pOpt->RetAddr) {
+ sprintf( lsz, "%04x:%08x ",
+ si->StkFrame.AddrReturn.Segment,
+ si->StkFrame.AddrReturn.Offset
+ );
+ lsz += strlen( lsz );
+ }
+ break;
+ }
+
+ if (pOpt->RetAddr || pOpt->Frameptr) {
+ strcat( lsz, " " );
+ lsz += strlen( lsz );
+ }
+
+ if (pOpt->Stack) {
+ if (si->StkFrame.AddrReturn.Mode == AddrModeFlat) {
+ sprintf( lsz, "%08x %08x %08x ",
+ si->StkFrame.Params[0],
+ si->StkFrame.Params[1],
+ si->StkFrame.Params[2]
+ );
+ } else {
+ sprintf( lsz, "%04x %04x %04x ",
+ LOWORD(si->StkFrame.Params[0]),
+ HIWORD(si->StkFrame.Params[0]),
+ LOWORD(si->StkFrame.Params[1])
+ );
+ }
+ lsz += strlen( lsz );
+ }
+
+ if (pOpt->Module && si->Context[0]) {
+ strcat( lsz, si->Context );
+ lsz += strlen( lsz );
+ }
+
+ if (pOpt->FuncName) {
+ if (si->ProcName[0] == '_') {
+ char *p;
+ strcat( lsz, &si->ProcName[1] );
+ p = strchr(lsz, '@');
+ if (p) {
+ *p = '\0';
+ }
+ lsz += strlen( lsz );
+ } else {
+ strcat( lsz, si->ProcName );
+ lsz += strlen( lsz );
+ }
+ }
+
+ if (pOpt->Displacement && si->Displacement) {
+ sprintf( lsz, "+0x%x", si->Displacement );
+ lsz += strlen( lsz );
+ }
+
+ if (pOpt->Params && si->Params[0]) {
+ sprintf( lsz, "(%s)", si->Params );
+ lsz += strlen( lsz );
+ }
+
+ if (pOpt->Rtf) {
+ OSDGetDebugMetric ( LppdCur->hpid, 0, mtrcProcessorType, &processor );
+ if (processor == mptix86) {
+ pFpoData = si->StkFrame.FuncTableEntry;
+ if (pFpoData) {
+ switch (pFpoData->cbFrame) {
+ case FRAME_FPO:
+ if (pFpoData->fHasSEH) {
+ sprintf(lsz, " (FPO: [seh] ");
+ } else if (pFpoData->fUseBP) {
+ sprintf(lsz, " (FPO: [ebp %08x] ", SAVE_EBP(si->StkFrame));
+ } else {
+ sprintf(lsz, " (FPO: ");
+ }
+ lsz += strlen( lsz );
+ sprintf(lsz, "[%d,%d,%d])", pFpoData->cdwParams,
+ pFpoData->cdwLocals,
+ pFpoData->cbRegs);
+ break;
+
+ case FRAME_TRAP:
+ {
+ sprintf(lsz, " (FPO: [%d,%d] TrapFrame%s @ %08lx)",
+ pFpoData->cdwParams,
+ pFpoData->cdwLocals,
+ (TRAP_EDITED(si->StkFrame)) ? "" : "-EDITED",
+ SAVE_TRAP(si->StkFrame) );
+ }
+ break;
+
+ case FRAME_TSS:
+ sprintf(lsz, " (FPO: TaskGate %lx:0)", TRAP_TSS(si->StkFrame));
+ break;
+
+ default:
+ sprintf(lsz, "(UKNOWN FPO TYPE)");
+ break;
+ }
+ lsz += strlen( lsz );
+ }
+ }
+ }
+
+ if (pOpt->Source) {
+ ZeroMemory( &addr, sizeof(addr) );
+ addr.addr.off = (OFFSET)si->StkFrame.AddrPC.Offset;
+ addr.addr.seg = si->StkFrame.AddrPC.Segment;
+ addr.mode.fFlat = si->StkFrame.AddrPC.Mode == AddrModeFlat;
+ addr.mode.fOff32 = si->StkFrame.AddrPC.Mode == AddrMode1632;
+ addr.mode.fReal = si->StkFrame.AddrPC.Mode == AddrModeReal;
+ if (GetSourceFromAddress( &addr, SrcFname, sizeof(SrcFname), &lineno )) {
+ _splitpath( SrcFname, NULL, NULL, szFname, szExt );
+ if (width) {
+
+ //------------------------------------------------------
+ // this code right justifies the source info string
+ //------------------------------------------------------
+
+ //
+ // put the string in a safe place
+ //
+ sprintf( SrcFname, " [ %s%s @ %4d ]", szFname, szExt, lineno );
+
+ if (width > (lsz-beg) + strlen(SrcFname)) {
+
+ //
+ // pad the string with spaces
+ //
+ for (i=0; i<width-(lsz-beg)+1; i++) {
+ *(lsz+i) = ' ';
+ }
+
+ //
+ // re-position the pointer to the end
+ //
+ lsz = beg + width - strlen(SrcFname);
+
+ }
+
+ //
+ // spew the string to it's new home
+ //
+ sprintf( lsz, "%s", SrcFname );
+
+ } else {
+
+ sprintf( lsz, " [ %s%s @ %d ]", szFname, szExt, lineno );
+
+ }
+
+ lsz += strlen( lsz );
+ }
+ }
+
+ return;
+}
+
+
+BOOL
+GoUntilStackFrame(
+ LPSTACKINFO si
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets a breakpoint at the address indicated in the requested
+ stack frame and then continues the thread.
+
+Arguments:
+
+ si - Stack frame that is to control the bp.
+
+Return Value:
+
+ TRUE - Thread was continued to the requested address.
+ FALSE - Thread could not be continued or bp could not be set.
+
+--*/
+
+{
+ ADDR addr;
+ HBPT hbpt = NULL;
+ CHAR buf[256];
+ CXF cxf = CxfIp;
+
+ sprintf( buf, "0x%x", si->StkFrame.AddrPC.Offset );
+
+ if (BPParse(&hbpt, buf, NULL, NULL, LppdCur ? LppdCur->hpid: 0) != BPNOERROR) {
+ return FALSE;
+ }
+
+ if (BPBindHbpt( hbpt, &cxf ) == BPNOERROR) {
+ if (BPAddrFromHbpt( hbpt, &addr ) != BPNOERROR) {
+ return FALSE;
+ }
+ if (BPFreeHbpt( hbpt ) != BPNOERROR) {
+ return FALSE;
+ }
+ if (!GoUntil(&addr)) {
+ return FALSE;
+ }
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ return TRUE;
+ }
+
+ BPFreeHbpt( hbpt );
+ return FALSE;
+}
+
+
+BOOL
+GetCompleteStackTrace(
+ DWORD FramePointer,
+ DWORD StackPointer,
+ DWORD ProgramCounter,
+ LPSTACKINFO StackInfo,
+ LPDWORD lpdwFrames,
+ BOOL fQuick,
+ BOOL fFull
+ )
+
+/*++
+
+Routine Description:
+
+ This function calls OSDEBUG to get the individual stack frames.
+ The STACKINFO structure is filled in with the information returned from
+ OSDEBUG.
+
+Arguments:
+
+ FramePointer - If non-zero this is the beginning frame pointer.
+
+ StackPointer - If non-zero this is the beginning stack pointer .
+
+ ProgramCounter - If non-zero this is the beginning program counter.
+
+ StackInfo - Pointer to an array of STACKINFO structures.
+
+ lpdwFrames - Number of frames to get from OSDEBUG.
+
+ fQuick - If TRUE and the frame pointer is the same as the last
+ call to this function the only the first frame is updated.
+
+ fFull - If TRUE all fields in the frame are filled in
+
+Return Value:
+
+ TRUE - Stack trace completed ok.
+
+ FALSE - Could not obtain a stack trace.
+
+--*/
+
+{
+ DWORD i;
+ STACKFRAME stkFrame;
+ XOSD xosd;
+ DWORD numFrames = *lpdwFrames;
+ BYTE buf[sizeof(IOCTLGENERIC) + sizeof(KDHELP)];
+ PIOCTLGENERIC pig = (PIOCTLGENERIC)buf;
+
+ *lpdwFrames = 0;
+
+ if ((!LppdCur) || (!LptdCur)) {
+ return FALSE;
+ }
+
+ ZeroMemory( &stkFrame, sizeof(stkFrame) );
+
+ //
+ // If IG_KSTACK_HELP is recognized, fill in helper data
+ //
+
+ pig->ioctlSubType = IG_KSTACK_HELP;
+ pig->length = sizeof(KDHELP);
+ xosd = OSDIoctl( LppdCur->hpid,
+ LptdCur->htid,
+ ioctlGeneric,
+ sizeof(buf),
+ (LPV)buf );
+ if (xosd == xosdNone) {
+ stkFrame.KdHelp = *(PKDHELP)(buf + sizeof(IOCTLGENERIC));
+ }
+
+ if (FramePointer) {
+ stkFrame.AddrFrame.Offset = FramePointer;
+ stkFrame.AddrFrame.Mode = AddrModeFlat;
+ }
+
+ if (StackPointer) {
+ stkFrame.AddrStack.Offset = StackPointer;
+ stkFrame.AddrStack.Mode = AddrModeFlat;
+
+ }
+
+ if (ProgramCounter) {
+ stkFrame.AddrPC.Offset = ProgramCounter;
+ stkFrame.AddrPC.Mode = AddrModeFlat;
+ }
+
+ for (i=0; i<numFrames; i++) {
+
+ if (i==0) {
+ xosd = OSDStackWalkSetup( LppdCur->hpid, LptdCur->htid, FALSE, (LPSTKSTR)&stkFrame );
+ } else {
+ xosd = OSDStackWalkNext( LppdCur->hpid, LptdCur->htid, (LPSTKSTR)&stkFrame );
+ }
+
+ if (xosd != xosdNone) {
+ break;
+ }
+
+ StackInfo[i].StkFrame = stkFrame;
+ StackInfo[i].FrameNum = i;
+
+ GetProcInfo( &StackInfo[i], fFull );
+
+ if ( fQuick && i== 0 ) {
+ //
+ // If the first frame has the same frame and return
+ // addresses as the previosly cached one, then we
+ // don't bother getting the rest of the stack trace since
+ // it has not changed.
+ //
+ if ( ADDREQ( stkFrame.AddrFrame, stkFrameSave.AddrFrame ) &&
+ ADDREQ( stkFrame.AddrReturn, stkFrameSave.AddrReturn ) ) {
+ return FALSE;
+ }
+ stkFrameSave.AddrFrame = stkFrame.AddrFrame;
+ stkFrameSave.AddrReturn = stkFrame.AddrReturn;
+
+ } else if (i) {
+
+ //
+ // If the current frame is the same as the previous frame,
+ // we stop so we don't end up with a long list of bogus
+ // frames.
+ //
+ if ( ADDREQ( stkFrame.AddrPC, StackInfo[i-1].StkFrame.AddrPC ) &&
+ ADDREQ( stkFrame.AddrFrame, StackInfo[i-1].StkFrame.AddrFrame ) ) {
+ break;
+ }
+ }
+ }
+
+ *lpdwFrames = i;
+
+ return TRUE;
+}
+
+LPSTR
+GetLastFrameFuncName(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the symbol name of the last stack frame. What this
+ really accomplishes is getting the name of the function that was
+ passed to CreateThread(). If the last symbol name is BaseThreadStart() then
+ the previous frame's symbol name is used.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Pointer to a string that contains the function name. The caller is
+ responsible for free()ing the memory.
+
+--*/
+
+{
+ LPSTR fname = NULL;
+ LPSTACKINFO StackInfo = NULL;
+ DWORD dwFrames = MAX_FRAMES;
+ DWORD i;
+
+
+ i = sizeof(STACKINFO) * dwFrames;
+ StackInfo = malloc( i );
+ if (!StackInfo) {
+ goto exit;
+ }
+ ZeroMemory( StackInfo, i );
+
+ GetCompleteStackTrace( 0, 0, 0, StackInfo, &dwFrames, FALSE, TRUE );
+
+ if (dwFrames == 0) {
+ goto exit;
+ }
+
+ if (_stricmp(StackInfo[dwFrames-1].ProcName,"BaseThreadStart")==0 ||
+ _stricmp(StackInfo[dwFrames-1].ProcName,"_BaseThreadStart@8")==0) {
+ if (dwFrames > 1) {
+ fname = _strdup(StackInfo[dwFrames-2].ProcName);
+ goto exit;
+ }
+ }
+
+ fname = _strdup(StackInfo[dwFrames-1].ProcName);
+
+exit:
+ if (StackInfo) {
+ free( StackInfo );
+ }
+ return fname;
+}
+
+BOOL
+IsValidFrameNumber(
+ INT FrameNumber
+ )
+{
+ DWORD i;
+
+ //
+ // update the call stack
+ //
+ i = Options.MaxFrames;
+ if (GetCompleteStackTrace( 0, 0, 0, StackInfo, &i, TRUE, TRUE )) {
+ FrameCount = i;
+ }
+
+ //
+ // update the window if one exists
+ //
+ if (hWndCalls && hwndList) {
+ FillStackFrameWindow( hwndList, FALSE );
+ }
+
+ if (FrameNumber >= 0 && FrameNumber <= (INT)FrameCount) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+PCXF
+ChangeFrame(
+ int iCall
+ )
+{
+ CXF *cxf = &StackInfo[iCall].Cxf;
+
+ if (LppdCur && LptdCur) {
+ OSDSetFrameContext( LppdCur->hpid, LptdCur->htid, iCall, 0 );
+ }
+
+ return cxf;
+}
diff --git a/private/windbg/windbg/cl.c b/private/windbg/windbg/cl.c
new file mode 100644
index 000000000..7161c2776
--- /dev/null
+++ b/private/windbg/windbg/cl.c
@@ -0,0 +1,587 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cl.c
+
+Abstract:
+
+ This file contains the code required to do the actual walking of the
+ debuggers stack (with help from the OSDEBUG layer). The display of
+ the data is done else where.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+#define IsSegEqual(a, b) ((a) == (b))
+
+
+CIS G_cisCallsInfo;
+
+extern LPSHF Lpshf; /* Pointer to SH entry structure */
+extern EI Ei;
+#define Lpei (&Ei)
+
+/*** CLLookupAddress
+**
+** Purpose: To lookup an address in the callback stack area
+**
+** Input:
+** paddr - A pointer to an ADDR struct contining the address to
+** find in the calls stack
+**
+** Output:
+** Returns The index into the calls stack containing the address
+**
+** Exceptions:
+**
+** Notes: -1 returned on error
+**
+*/
+
+int PASCAL CLLookupAddress ( ADDR addr )
+{
+ int ifme;
+
+ for ( ifme = 0; ifme < (int) G_cisCallsInfo.cEntries; ifme++ ) {
+ FME *pfme = &(G_cisCallsInfo.frame [ ifme ] );
+
+ if ( pfme->symbol == (HSYM) NULL ) {
+ continue;
+ }
+
+ if (!ADDR_IS_LI(pfme->addrProc)) {
+ SYUnFixupAddr( &pfme->addrProc);
+ }
+
+ if (!ADDR_IS_LI(pfme->addrCSIP)) {
+ SYUnFixupAddr( &pfme->addrCSIP);
+ }
+
+ if ( IsSegEqual (
+ (ushort) GetAddrSeg ( pfme->addrProc ),
+ (ushort) GetAddrSeg ( addr )
+ ) &&
+ GetAddrOff ( pfme->addrProc ) <= GetAddrOff ( addr ) &&
+ GetAddrOff ( pfme->addrCSIP ) >= GetAddrOff ( addr ) ) {
+
+ return ifme;
+ }
+ }
+
+ return -1;
+} /* CLLookupAddress() */
+
+/*** CLGetParams
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+char * CLGetParams ( PHTM phtm, FRAME *pframe, int *pcbMax, char *pch )
+{
+ ushort i = 0;
+ ushort cParm = 0;
+ char FAR * lpch;
+ SHFLAG shflag = FALSE;
+ HTM htmParm;
+ EEHSTR hName;
+ uint strIndex;
+
+#ifdef DBCS
+ char *pchOrg = pch;
+#endif
+
+ if ( EEcParamTM ( phtm, &cParm, &shflag ) == EENOERROR ) {
+
+ *pch++ = '('; // )
+ *pcbMax -= 1;
+
+ for ( i = 0; i < cParm; i++ ) {
+
+ if ( *pcbMax > 0 &&
+ EEGetParmTM ( phtm, (EERADIX) i, &htmParm, &strIndex, FALSE ) == EENOERROR ) {
+
+ EEvaluateTM ( &htmParm, pframe, EEHORIZONTAL );
+ if ( EEGetValueFromTM ( &htmParm, radix, (PEEFORMAT) "p", &hName ) ==
+ EENOERROR ) {
+ int ich;
+
+ lpch = MMLpvLockMb ( hName );
+ _fmemcpy ( pch, lpch,
+ ( ich = min ( *pcbMax, (int)_fstrlen ( lpch ) ) )
+ );
+ pch += ich;
+ *pcbMax -= ich + 1;
+ MMbUnlockMb ( hName );
+ EEFreeStr ( hName );
+
+ *pch++ = ',';
+ *pch++ = ' ';
+ }
+ EEFreeTM (&htmParm);
+ }
+ }
+
+ if ( ( shflag == TRUE ) && ( *pcbMax > 3 ) ) {
+ memcpy ( pch, "...", 3 );
+ pch += 3;
+ *pcbMax -= 3;
+ }
+
+#ifdef DBCS
+ do {
+ pch = CharPrev(pchOrg, pch);
+ if (*pch != ' ' && *pch != ',') {
+ pch = CharNext(pch);
+ break;
+ }
+ } while (pch > pchOrg);
+#else
+ while (( *( pch - 1 ) == ' ' ) || ( *( pch - 1 ) == ',' ) ) {
+ pch--;
+ }
+#endif
+ *pch++ = ')';
+ }
+
+ return pch;
+} /* CLGetParams*/
+
+
+/*** CLGetProcName
+*
+* Purpose: To format a line to be diplayed in the calls menu
+*
+* Input:
+* num - The index into the stack frame
+* pch - A pointer a buffer to put the string
+*
+* Output:
+* Returns .....
+*
+* Exceptions:
+*
+* Notes:
+* to prevent output buffer overruns (pch) , we need to check the length
+* during format. but instead of checking for length every time we xfer into
+* output buffer, we check at selected points in the code and make certain
+* safe assumptions eg the length passed to us will be able to accomodate
+* the symbol name totally etc. Thus we remain ok and save some code & time
+*
+*/
+
+
+char * PASCAL CLGetProcName ( int ifme, char *pch, int cbMax, BOOL bSpecial )
+{
+ char * pchT;
+ DWORD dwDisplacement;
+ int len;
+ HTM htm;
+ EEHSTR hName;
+ ushort retval;
+ CXT cxt;
+ ADDR addrT;
+ uint strIndex;
+ HDEP hstr;
+ char szContext[MAX_USER_LINE];
+
+ FME * pfme = &(G_cisCallsInfo.frame [ ifme ]);
+ HSYM symbol = pfme->symbol;
+
+ cbMax -= 2;
+ pchT = pch;
+
+ memset ( &cxt, 0, sizeof ( cxt ) );
+ if ( pfme->clt != cltNone ) {
+ *SHpADDRFrompCXT ( &cxt ) = pfme->addrProc;
+ }
+ else {
+ *SHpADDRFrompCXT ( &cxt ) = pfme->addrCSIP;
+ }
+ SHHMODFrompCXT ( &cxt ) = pfme->module;
+
+ switch ( pfme->clt) {
+
+ case cltNone:
+ {
+ ADDR addrT = pfme->addrCSIP;
+
+ SYFixupAddr ( &addrT );
+ EEFormatAddr( &addrT, pch, cbMax, runDebugParams.ShowSegVal * EEFMT_SEG);
+ len = strlen(pch);
+ pchT += len;
+ break;
+
+ }
+ case cltProc:
+
+ Dbg(SHAddrFromHsym ( &addrT, symbol ));
+
+ //SetAddrOff (
+ // SHpADDRFrompCXT ( &cxt ) ,
+ // GetAddrOff ( *SHpADDRFrompCXT ( &cxt ) ) + GetAddrOff ( addrT )
+ // );
+ SetAddrOff (
+ SHpADDRFrompCXT ( &cxt ) ,
+ GetAddrOff ( addrT )
+ );
+ SHHPROCFrompCXT ( &cxt ) = (HPROC) symbol;
+ SHHBLKFrompCXT( &cxt ) = (HBLK) symbol;
+ goto MakeName;
+
+ case cltBlk:
+
+ SHHBLKFrompCXT ( &cxt ) = (HBLK) symbol;
+
+ case cltPub:
+MakeName:
+
+ //
+ // include the context string if the command is KB
+ //
+ if (bSpecial) {
+ EEFormatCXTFromPCXT(&cxt, &hstr);
+ BPShortenContext( (LPSTR)MMLpvLockMb(hstr), szContext);
+ MMbUnlockMb(hstr);
+ EEFreeStr(hstr);
+ strcpy( pchT, szContext );
+ pchT += strlen( szContext );
+ }
+
+ retval = EEGetTMFromHSYM ( symbol, &cxt, &htm, &strIndex, FALSE );
+
+ Assert( retval != EECATASTROPHIC );
+
+ if ( retval != EENOERROR ) {
+
+ // try to get something from this miserable symbol.
+
+ if (SHGetSymName(symbol, pch)) {
+ return pch;
+ } else {
+ *pchT = 0;
+ return pch;
+ }
+ }
+
+ // should always be able to convert an hSym
+
+ Assert ( retval == EENOERROR );
+
+ if ( EEGetNameFromTM ( &htm, &hName ) == EENOERROR ) {
+
+ char far * lpch = MMLpvLockMb ( hName );
+
+ _fmemcpy (
+ pchT,
+ lpch,
+ len = min ( cbMax, (int) _fstrlen (lpch) )
+ );
+ pchT += len;
+ cbMax -= len;
+ MMbUnlockMb ( hName );
+ EEFreeStr ( hName );
+ }
+
+ //
+ // calculate the displacement
+ //
+ if (bSpecial) {
+ addrT = *SHpAddrFrompCxt(&cxt);
+ SHAddrFromHsym(&addrT, symbol);
+ SYFixupAddr(&addrT);
+ dwDisplacement = GetAddrOff(pfme->addrCSIP) - GetAddrOff(addrT);
+ if (dwDisplacement > 0) {
+ pchT += wsprintf( pchT, "+0x%x", dwDisplacement );
+ }
+ }
+
+
+ /* Get the argument values, but only for procs */
+
+ if ( ( cbMax > 0 ) && pfme->clt == cltProc ) {
+
+ fUseFrameContext = TRUE;
+ OSDSetFrameContext( LppdCur->hpid, LptdCur->htid, ifme, 0 );
+ pchT = CLGetParams ( &htm, &pfme->Frame, &cbMax, pchT );
+ fUseFrameContext = FALSE;
+ }
+
+ EEFreeTM ( &htm );
+ break;
+
+ }
+
+ *pchT = '\0';
+ errno = 0; /* clear out any I/O errors */
+ return pch;
+} /* CLGetProcName() */
+
+/*** CLSetProcAddr
+*
+* Purpose: To set up the symbols part of the stack frame structure
+*
+* Input:
+* pfme addrCSIP must be set up.
+* Output:
+* pfme The stack frame to fill in the result
+* Elements:
+* symbol
+* clt
+* addrProc
+* module
+*
+*
+* Returns:
+*
+* Exceptions:
+*
+* Notes:
+*
+*/
+void PASCAL NEAR CLSetProcAddr ( FME *pfme, int *fInProlog )
+{
+ CXT cxt;
+ ADDR addrT;
+
+ *fInProlog = FALSE;
+ pfme->addrProc = pfme->addrCSIP;
+
+ memset ( &cxt, 0, sizeof ( CXT ) );
+ SHSetCxt ( &pfme->addrProc, &cxt );
+ //if ( !SHHMODFrompCXT ( &cxt ) ) {
+ //pfme->symbol = (HSYM) NULL;
+ //pfme->clt = cltNone;
+ //return;
+ //}
+
+ pfme->addrProc = *SHpADDRFrompCXT ( &cxt );
+ pfme->module = SHHMODFrompCXT ( &cxt );
+
+ // block also may have a name. If it does, use it as the symbol in the
+ // calls stack.
+
+
+ if ( SHHPROCFrompCXT ( &cxt ) ) {
+ pfme->symbol = (HSYM) SHHPROCFrompCXT ( &cxt );
+ pfme->clt = cltProc;
+ Dbg(SHAddrFromHsym ( &addrT, pfme->symbol ));
+ SetAddrOff (
+ &pfme->addrProc,
+ GetAddrOff ( addrT )
+ );
+ *fInProlog = SHIsInProlog ( &cxt );
+ }
+ else if ( SHHBLKFrompCXT ( &cxt ) ) {
+ HBLK hblk;
+ ADDR addrT;
+ char rgch [ 100 ];
+
+ hblk = SHHBLKFrompCXT ( &cxt );
+ memset ( &addrT, 0, sizeof ( ADDR ) );
+
+ Dbg(SHAddrFromHsym ( &addrT, (HSYM) hblk ));
+ if ( SHGetSymName ( (HSYM) hblk, rgch ) != NULL ) {
+ pfme->symbol = (HSYM) hblk;
+ pfme->clt = cltBlk;
+ }
+
+ SetAddrOff (
+ &pfme->addrProc,
+ GetAddrOff ( addrT )
+ );
+ }
+ else if ( PHGetNearestHsym (
+ (PADDR)&pfme->addrCSIP,
+ (HEXE)(SHpADDRFrompCXT( &cxt ) ->emi),
+ //SHHexeFromHmod ( SHHMODFrompCXT ( &cxt ) ),
+ (PHSYM) &pfme->symbol ) <
+ 0xFFFFFFFF ) {
+ ADDR addrT;
+
+ memset ( &addrT, 0, sizeof ( ADDR ) );
+
+ Dbg(SHAddrFromHsym ( &addrT, pfme->symbol ));
+
+ pfme->clt = cltPub;
+ SetAddrOff ( &pfme->addrProc, GetAddrOff ( addrT ) );
+ }
+ else {
+ pfme->symbol = (HSYM) NULL;
+ pfme->clt = cltNone;
+ }
+} /* CLSetProcAddr() */
+
+/*** CLGetWalkbackStack
+*
+* Purpose: To set up the calls walkback structure
+*
+* Input:
+*
+* Output:
+* Returns:
+*
+* Exceptions:
+*
+* Notes:
+* The rules are:
+* BP must point to the previous BP on the stack.
+* The return address must be at BP+2.
+*
+* Currently we don't support the _saveregs options or
+* _fastcall with stack checking on.
+*
+* Also any function without symbolics are skipped in the
+* the trace back.
+*/
+
+void CLGetWalkbackStack ( LPPD lppd, LPTD lptd )
+{
+ STKSTR stkStr;
+ BOOL fInProlog = FALSE;
+ XOSD xosd = xosdNone;
+ int ifme;
+ BOOL fDone = FALSE;
+ FME * pfme = &(G_cisCallsInfo.frame[0]);
+ ADDR addrData;
+
+ /*
+ * Determine if the current Program Counter address is in
+ * the prolog of the current function. This information is
+ * needed to start the stack walk operation.
+ */
+
+ OSDGetAddr(lppd->hpid, lptd->htid, adrPC, &pfme->addrCSIP);
+#ifdef OSDEBUG4
+ OSDUnFixupAddress(lppd->hpid, lptd->htid, &pfme->addrCSIP);
+#else
+ OSDPtrace(osdUnFixupAddr, 0, &pfme->addrCSIP, lppd->hpid, lptd->htid);
+#endif
+ CLSetProcAddr ( pfme, &fInProlog);
+
+ for (ifme=0; ifme<ifmeMax+1 && xosd==xosdNone; ifme++) {
+ if (ifme == 0) {
+ xosd = OSDStackWalkSetup(lppd->hpid, lptd->htid, fInProlog, &stkStr);
+ } else {
+ xosd = OSDStackWalkNext( lppd->hpid, lptd->htid, &stkStr );
+ }
+ pfme = &(G_cisCallsInfo.frame[ifme]);
+ pfme->addrCSIP = stkStr.addrPC;
+#ifdef OSDEBUG4
+ OSDUnFixupAddress(lppd->hpid, lptd->htid, &pfme->addrCSIP);
+#else
+ OSDPtrace(osdUnFixupAddr, 0, &pfme->addrCSIP, lppd->hpid, lptd->htid);
+#endif
+ CLSetProcAddr(pfme, &fInProlog );
+ pfme->addrCSIP = stkStr.addrPC;
+ pfme->addrRet = stkStr.addrRetAddr;
+ if (ADDR_IS_LI(stkStr.addrFrame)) {
+ SYFixupAddr( &stkStr.addrFrame );
+ }
+ pfme->Frame.mode = stkStr.addrFrame.mode;
+ SetFrameBPSeg ( pfme->Frame , GetAddrSeg ( stkStr.addrFrame ) );
+ SetFrameBPOff ( pfme->Frame , GetAddrOff ( stkStr.addrFrame ) );
+ pfme->Frame.SS = GetAddrSeg ( stkStr.addrFrame );
+ OSDGetAddr ( LppdCur->hpid, LptdCur->htid, adrData, &addrData );
+ pfme->Frame.DS = GetAddrSeg ( addrData );
+ pfme->Frame.TID = LptdCur->htid;
+ pfme->Frame.PID = LppdCur->hpid;
+ pfme->ulParams[0] = stkStr.ulParams[0];
+ pfme->ulParams[1] = stkStr.ulParams[1];
+ pfme->ulParams[2] = stkStr.ulParams[2];
+ pfme->ulParams[3] = stkStr.ulParams[3];
+ pfme->fFar = stkStr.fFar;
+ }
+
+ OSDStackWalkCleanup(lppd->hpid, lptd->htid, &stkStr);
+
+ G_cisCallsInfo.cEntries = ifme;
+
+ return;
+} /* CLGetWalkBackstack() */
+
+/*** CLGetFuncCXF
+**
+** Purpose: To get a frame given an address of a function on the
+** calls stack
+**
+** Input:
+** paddr - A pointer to the address of the function
+**
+** Output:
+** pCXF - A pointer to an empty CXF, This will be filled in with
+** the scope and frame of the function.
+** Returns:
+** A pointer to the CXF if successful, NULL otherwise.
+**
+** Exceptions:
+**
+** Notes: A NULL is returned if the function could not be found on
+** the calls stack, OR if the function has no symbolic info.
+**
+*/
+
+PCXF LOADDS PASCAL CLGetFuncCXF ( PADDR paddr, PCXF pcxf )
+{
+ ADDR addr;
+ int ifme;
+ FME * pfme = NULL;
+
+ Assert ( ADDR_IS_LI (*paddr));
+ addr = *paddr;
+ _fmemset ( pcxf, 0, sizeof ( CXF ) );
+
+ CLGetWalkbackStack ( LppdCur, LptdCur );
+
+ // get the stack element
+
+ ifme = CLLookupAddress ( addr );
+ if ( ifme != -1 ) {
+ pfme = &(G_cisCallsInfo.frame [ ifme ] );
+ }
+
+ if ( pfme != NULL && ( pfme->clt == cltProc || pfme->clt == cltBlk ) ) {
+
+ /*
+ * Fill in the return address, then subtract 1 if ifme > 0, this
+ * is due to the fact that the instruction AFTER the call
+ * may not be in the same context as the call itself.
+ */
+
+ addr = pfme->addrCSIP;
+ if (ifme > 0) {
+ SetAddrOff( &addr, GetAddrOff(addr) - 1);
+ }
+ SHSetCxt( &addr, &pcxf->cxt );
+
+ // fill in the CXF
+
+ pcxf->Frame = pfme->Frame;
+ pcxf->cxt.addr = addr;
+
+ return pcxf;
+ }
+
+ return NULL;
+}
diff --git a/private/windbg/windbg/cmdexec0.c b/private/windbg/windbg/cmdexec0.c
new file mode 100644
index 000000000..0b79cf04a
--- /dev/null
+++ b/private/windbg/windbg/cmdexec0.c
@@ -0,0 +1,3363 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cmdexec0.c
+
+Abstract:
+
+ This file contains the front end code for parsing the various commands
+ for the command window, and the code for the debugger control commands.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-92
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/************************** Data declaration *************************/
+
+/****** Publics ********/
+
+// M00TODO a-kentf put these defaults in (windbg.h? cmdexec.h?)
+ULONG ulRipBreakLevel = 1;
+ULONG ulRipNotifyLevel = 3;
+
+ULONG ulPseudo[10]={0,0,0,0,0,0,0,0,0,0};
+LPSTR lpszLastSearch=NULL;
+
+LPPD LppdCommand;
+LPTD LptdCommand;
+
+BOOL FSetLptd; // Was thread specified
+BOOL FSetLppd; // Was process specified
+
+INT BpCmdPid;
+INT BpCmdTid;
+
+BOOL fWaitForDebugString;
+LPSTR lpCmdString;
+
+CHAR szLoggerBuf[MAX_USER_LINE+2];
+
+
+/****** Locals ********/
+
+
+
+char szPrompt[ PROMPT_SIZE ] = "> ";
+
+BOOL NEAR PASCAL
+StringLogger(
+ LPSTR szStr,
+ BOOL fFileLog,
+ BOOL fSendRemote,
+ BOOL fPrintLocal
+ );
+
+typedef LOGERR (*DOTHANDLER)(LPSTR lpsz, DWORD dwData);
+
+typedef struct _DOT_COMMAND {
+ LPSTR lpName;
+ DOTHANDLER lpfnHandler;
+ DWORD dwArg;
+ LPSTR lpDesc;
+} DOT_COMMAND, *LPDOTCOMMAND;
+
+DOT_COMMAND DotTable[] = {
+ "attach", LogAttach, 0,
+ "<pid> debug an existing process",
+ "break", LogBreak, 0,
+ " stop the current process",
+ "connect", LogConnect, 0,
+ " connect windbg to a remote session",
+ "disconnect", LogDisconnect, 0,
+ " disconnect windbg from a remote session",
+ "kill", LogKill, 0,
+ "<pnumber> kill a process being debugged",
+ "list", LogList, 0,
+ "<address> List source/asm for an address",
+ "logopen", LogFileOpen, FALSE,
+ "[filename] truncate log file",
+ "logappend", LogFileOpen, TRUE,
+ "[filename] append to log file",
+ "logclose", LogFileClose, 0,
+ " close log file",
+ "opt", LogOptions, 0,
+ "[args] .opt ? for options",
+ "reload", LogReload, 0,
+ "[filename] Reloads kernel modules",
+ "sleep", LogSleep, 0,
+ "<seconds> Delay execution",
+ "source", LogSource, 0,
+ "<scriptfile> Read debugger script",
+ "start", LogStart, 0,
+ "<program> debug a program",
+ "title", LogTitle, 0,
+ "<window title> set the window title",
+ "waitforstr", LogWaitForString, 0,
+ " wait for a debugstring",
+};
+#define NDOTS (sizeof(DotTable)/sizeof(DOT_COMMAND))
+
+BOOL OnOffBOOLHandler(LPVOID, int, LPSTR, BOOL);
+BOOL OnOffByteHandler(LPVOID, int, LPSTR, BOOL);
+BOOL AsmOptHandler(LPVOID, int, LPSTR, BOOL);
+BOOL DllSetHandler(LPVOID, int, LPSTR, BOOL);
+BOOL DllPathSetHandler(LPVOID, int, LPSTR, BOOL);
+BOOL HelpHandler(LPVOID, int, LPSTR, BOOL);
+BOOL KdBaudHandler(LPVOID, int, LPSTR, BOOL);
+BOOL KdPortHandler(LPVOID, int, LPSTR, BOOL);
+BOOL KdCacheHandler(LPVOID, int, LPSTR, BOOL);
+BOOL KdPlatformHandler(LPVOID, int, LPSTR, BOOL);
+BOOL BackgroundSymHandler(LPVOID, int, LPSTR, BOOL);
+
+
+typedef BOOL (*OPTHANDLER)(LPVOID lpData, int cbSize, LPSTR lpVal, BOOL fSet);
+
+typedef struct tagOPTIONSTRUCT {
+ LPSTR lpName; // name for user to use
+ LPVOID lpData; // actual data
+ int cbSize; // for string fields or whatever
+ OPTHANDLER lpfnHandler; // work function
+ LPSTR lpDesc; // help text
+} OPTIONSTRUCT, *LPOPTIONSTRUCT;
+
+
+//static BOOL fFakeFlag = FALSE;
+static OPTIONSTRUCT OptionTable[] =
+{
+//
+// The help entry must be the first entry in this table
+//
+ "?", 0,0, HelpHandler,
+ " This list",
+ "AsmSymbols", (LPVOID) dopSym, 0, AsmOptHandler,
+ "{on/off} Show symbols in disassembly",
+ "AsmRaw", (LPVOID) dopRaw, 0, AsmOptHandler,
+ "{on/off} Show raw data in disassembly",
+ "AttachGo",&runDebugParams.fAttachGo, 0, OnOffBOOLHandler,
+ "{on/off} Don't break into newly attached processes",
+ "BackgroundSym", &runDebugParams.fShBackground, 0, BackgroundSymHandler,
+ "{on/off} Background symbol loading",
+ "CaseSensitive", &fCaseSensitive, 0, OnOffBOOLHandler,
+ "{on/off} Sets case sensitivity",
+ "ChildGo",&runDebugParams.fChildGo, 0, OnOffBOOLHandler,
+ "{on/off} Don't break into new child processes",
+ "CommandRepeat", &runDebugParams.fCommandRepeat, 0, OnOffBOOLHandler,
+ "{on/off} Repeat last command with enter",
+ "DllEE", 0, DLL_EXPR_EVAL, DllSetHandler,
+ "<filename> Expression evaluator dll",
+ "DllEm", 0, DLL_EXEC_MODEL, DllSetHandler,
+ "<filename> Execution model dll",
+ "DllSh", 0, DLL_SYMBOL_HANDLER, DllSetHandler,
+ "<filename> Symbol handler dll",
+ "DllTl", 0, DLL_TRANSPORT, DllSetHandler,
+ "<filename [args]> Transport layer dll",
+ "DllPath",0,0, DllPathSetHandler,
+ "<path1;path2...> Search path for symbols",
+ "EPStep", &runDebugParams.fEPIsFirstStep, 0, OnOffBOOLHandler,
+ "{on/off} First step goes to entry point, not main",
+ "ExitGo", &runDebugParams.fGoOnThreadTerm, 0, OnOffBOOLHandler,
+ "{on/off} Don't stop on threasd terminations",
+ "InheritHandles", &runDebugParams.fInheritHandles, 0, OnOffBOOLHandler,
+ "{on/off} Debuggee inherits handles - for debugging debuggers",
+ "IgnoreAll", &runDebugParams.fIgnoreAll, 0, OnOffBOOLHandler,
+ "{on/off} Ignore all symbols messages",
+ "KdInitialBp", &runDebugParams.KdParams.fInitialBp, 0, OnOffBOOLHandler,
+ "{on/off} Kernel debugger stop at initial breakpoint",
+ "KdEnable", &runDebugParams.fKernelDebugger, 0, OnOffBOOLHandler,
+ "{on/off} Enable Kernel debugger",
+ "KdGoExit", &runDebugParams.KdParams.fGoExit, 0, OnOffBOOLHandler,
+ "{on/off} Go on Exit",
+ "KdUseModem", &runDebugParams.KdParams.fUseModem, 0, OnOffBOOLHandler,
+ "{on/off} Kernel debugger use modem controls",
+ "KdBaudRate", &runDebugParams.KdParams.dwBaudRate, 0, KdBaudHandler,
+ "{on/off} Kernel debugger baud rate (1200/2400/4800/9600/38400/56000)",
+ "KdPort", &runDebugParams.KdParams.dwPort, 0, KdPortHandler,
+ "{on/off} Kernel debugger communication port (1/2/3/4)",
+ "KdCacheSize", &runDebugParams.KdParams.dwCache, 0, KdCacheHandler,
+ "{on/off} Kernel debugger memory cache size",
+ "KdPlatform", &runDebugParams.KdParams.dwPlatform, 0, KdPlatformHandler,
+ "{on/off} Kernel debugger target system platform (x86/mips/alpha/ppc)",
+ "MasmEval", &runDebugParams.fMasmEval, 0, OnOffBOOLHandler,
+ "{on/off} Masm Style Expression Evaluation",
+ "NotifyExit",&runDebugParams.fNotifyThreadTerm, 0, OnOffBOOLHandler,
+ "{on/off} Print a message for thread termination",
+ "NotifyNew",&runDebugParams.fNotifyThreadCreate, 0, OnOffBOOLHandler,
+ "{on/off} Print a message for new threads",
+ "Verbose", &runDebugParams.fVerbose, 0, OnOffBOOLHandler,
+ "{on/off} Verbose output mode",
+};
+
+#define NOPTS (sizeof(OptionTable) / sizeof(OPTIONSTRUCT))
+
+HANDLE hFileLog = INVALID_HANDLE_VALUE;
+extern CRITICAL_SECTION csLog;
+
+static FILE * fpAutoRun = (FILE *)NULL;
+
+static int XNew = 0;
+static int YNew = 0;
+
+static BOOL FDebugString = FALSE;
+static int XNewDebug;
+static int YNewDebug;
+
+static BOOL (FAR PASCAL *lpfnLineProc)(LPSTR lpsz) = CmdExecuteLine;
+static void (FAR PASCAL *lpfnPromptProc)(BOOL,BOOL) = CmdExecutePrompt;
+
+static char FAR * LpszCmdPtr = (char FAR *)NULL; //
+static char FAR * LpszCmdBuff = (char FAR *)NULL; //
+
+
+/****** Externs from ??? *******/
+
+extern LPSHF Lpshf; // vector table for symbol handler
+extern CXF CxfIp;
+extern EI Ei;
+
+LOGERR LogExtension(LPSTR lpsz);
+LOGERR LogVersion(LPSTR lpsz);
+BOOL NotifyDmOfProcessorChange(DWORD);
+
+/************************** Code *************************/
+
+/**************** Option handler functions *****************/
+
+/*
+ * These return TRUE when they succeed, false when they don't.
+ */
+BOOL
+HelpHandler(
+ LPVOID lpData,
+ int cbSize,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+{
+ int i;
+ if (!fSet) {
+ *lpVal = 0;
+ } else {
+ for (i = 0; i < NOPTS; i++) {
+ CmdLogFmt("%s %s\r\n",
+ OptionTable[i].lpName,
+ OptionTable[i].lpDesc);
+ }
+ }
+ return TRUE;
+}
+
+
+BOOL
+OnOffBOOLHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+
+ cb - Supplies more data
+
+ lpVal - Supplies pointer to user input or string to format into
+
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ int n;
+ BOOL fOK = FALSE;
+ char szToken[MAX_USER_LINE];
+
+ Unreferenced( cb );
+
+ if (!fSet) {
+ sprintf(lpVal, (*(BOOL *)lpData) ? "on" : "off");
+ return TRUE;
+ }
+
+ n = CPCopyToken(&lpVal, szToken);
+
+ if (*CPSkipWhitespace(lpVal)) {
+
+ CmdLogVar(ERR_Command_Error);
+
+ } else if (_stricmp(szToken, "yes") == 0
+ || _stricmp(szToken, "y") == 0
+ || _stricmp(szToken, "true") == 0
+ || _stricmp(szToken, "1") == 0
+ || _stricmp(szToken, "on") == 0 ) {
+
+ *(BOOL *)lpData = TRUE;
+ fOK = TRUE;
+
+ } else if (_stricmp(szToken, "no") == 0
+ || _stricmp(szToken, "n") == 0
+ || _stricmp(szToken, "false") == 0
+ || _stricmp(szToken, "0") == 0
+ || _stricmp(szToken, "off") == 0 ) {
+
+ *(BOOL *)lpData = FALSE;
+ fOK = TRUE;
+
+ } else {
+
+ CmdLogVar(ERR_True_False);
+
+ }
+
+ return fOK;
+}
+
+
+BOOL
+OnOffByteHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a byte for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+
+ cb - Supplies more data
+
+ lpVal - Supplies pointer to user input or string to format into
+
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ BOOL flag;
+ BOOL fOK;
+
+ flag = (BOOL)*((BYTE *)lpData);
+
+ fOK = OnOffBOOLHandler((LPVOID)&flag, cb, lpVal, fSet);
+ if (fOK) {
+ *((BYTE *)lpData) = (BYTE)flag;
+ }
+ return fOK;
+}
+
+
+
+BOOL
+AsmOptHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+
+ cb - Supplies more data
+
+ lpVal - Supplies pointer to user input or string to format into
+
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ BOOL fOK;
+ BOOL flag;
+ int dops = (int) lpData;
+
+ flag = (runDebugParams.DisAsmOpts & dops) ? 1 : 0;
+
+ fOK = OnOffBOOLHandler((LPVOID)&flag, cb, lpVal, fSet);
+
+ if (fOK) {
+ if (fSet) {
+ if (flag) {
+ runDebugParams.DisAsmOpts |= dops;
+ } else {
+ runDebugParams.DisAsmOpts &= ~dops;
+ }
+ }
+ }
+ return fOK;
+}
+
+
+BOOL
+DllSetHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to change the set of DLLs used by windbg.
+ This is for use with scripting only.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+
+ cb - Supplies data size
+
+ lpVal - Supplies pointer to user input or string to format into
+
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ Unreferenced( lpData );
+
+ if (fSet) {
+ SetDllName(cb, lpVal);
+ } else {
+ LPSTR lp = GetDllName(cb);
+ strcpy(lpVal, lp? lp : "");
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+DllPathSetHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+{
+ int len;
+ LPSTR lpsz;
+ char sz[2000];
+ PIOCTLGENERIC pig;
+
+ if (!fSet) {
+ len = ModListGetSearchPath( NULL, 0 );
+ if (!len) {
+ *lpVal = 0;
+ } else {
+ lpsz = malloc(len);
+ ModListGetSearchPath( lpsz, len );
+ // BUGBUG kentf this is sleazy, but I don't have time to change it
+ strncpy(lpVal, lpsz, MAX_USER_LINE);
+ lpVal[MAX_USER_LINE-1] = 0;
+ free(lpsz);
+ }
+ } else {
+ ModListSetSearchPath( lpVal );
+ if ( runDebugParams.fKernelDebugger && LptdCur && DebuggeeAlive()) {
+ FormatKdParams( sz, FALSE );
+ pig = (PIOCTLGENERIC)malloc(strlen(sz) + 1 + sizeof(IOCTLGENERIC));
+ if (!pig) {
+ return FALSE;
+ }
+ pig->ioctlSubType = IG_DM_PARAMS;
+ pig->length = strlen(sz) + 1;
+ strcpy((LPSTR)pig->data,sz);
+ OSDIoctl( LppdCur->hpid,
+ LptdCur->htid,
+ ioctlGeneric,
+ strlen(sz) + 1 + sizeof(IOCTLGENERIC),
+ (LPV)pig );
+ free( pig );
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+KdBaudHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+ cb - Supplies more data
+ lpVal - Supplies pointer to user input or string to format into
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ DWORD i;
+ char szToken[MAX_USER_LINE];
+
+
+ if (!fSet) {
+ sprintf(lpVal, "%d", runDebugParams.KdParams.dwBaudRate );
+ return TRUE;
+ }
+
+ i = CPCopyToken(&lpVal, szToken);
+
+ if (*CPSkipWhitespace(lpVal)) {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+
+ for (i=0; i<strlen(szToken); i++) {
+ if (!isdigit(szToken[i])) {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+ }
+
+ runDebugParams.KdParams.dwBaudRate = atol( szToken );
+
+ return TRUE;
+}
+
+
+BOOL
+KdPortHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+ cb - Supplies more data
+ lpVal - Supplies pointer to user input or string to format into
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ DWORD i;
+ char szToken[MAX_USER_LINE];
+ LPSTR p = szToken;
+
+
+ if (!fSet) {
+ sprintf(lpVal, "COM%d", runDebugParams.KdParams.dwPort );
+ return TRUE;
+ }
+
+ i = CPCopyToken(&lpVal, szToken);
+
+ if (*CPSkipWhitespace(lpVal)) {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+
+ if (_strnicmp(p, "com", 3) == 0) {
+ p += 3;
+ if (strlen(p) == 1 && isdigit(*p)) {
+ runDebugParams.KdParams.dwPort = *p - '0';
+ } else {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+ } else {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+KdCacheHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+ cb - Supplies more data
+ lpVal - Supplies pointer to user input or string to format into
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ DWORD i;
+ char szToken[MAX_USER_LINE];
+
+
+ if (!fSet) {
+ sprintf(lpVal, "%d", runDebugParams.KdParams.dwCache );
+ return TRUE;
+ }
+
+ i = CPCopyToken(&lpVal, szToken);
+
+ if (*CPSkipWhitespace(lpVal)) {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+
+ for (i=0; i<strlen(szToken); i++) {
+ if (!isdigit(szToken[i])) {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+ }
+
+ runDebugParams.KdParams.dwCache = atol( szToken );
+
+ return TRUE;
+}
+
+
+BOOL
+KdPlatformHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+ cb - Supplies more data
+ lpVal - Supplies pointer to user input or string to format into
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ DWORD i;
+ char szToken[MAX_USER_LINE];
+
+
+ if (!fSet) {
+ switch (runDebugParams.KdParams.dwPlatform ) {
+ case 0:
+ strcpy(lpVal, "x86" );
+ break;
+
+ case 1:
+ strcpy(lpVal, "mips" );
+ break;
+
+ case 2:
+ strcpy(lpVal, "alpha" );
+ break;
+ case 3:
+ strcpy(lpVal, "ppc" );
+ break;
+ }
+ return TRUE;
+ }
+
+ i = CPCopyToken(&lpVal, szToken);
+
+ if (*CPSkipWhitespace(lpVal)) {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+
+ if (_stricmp(szToken, "x86") == 0) {
+ runDebugParams.KdParams.dwPlatform = 0;
+ } else
+ if (_stricmp(szToken, "mips") == 0) {
+ runDebugParams.KdParams.dwPlatform = 1;
+ } else
+ if (_stricmp(szToken, "alpha") == 0) {
+ runDebugParams.KdParams.dwPlatform = 2;
+ } else
+ if (_stricmp(szToken, "ppc") == 0) {
+ runDebugParams.KdParams.dwPlatform = 3;
+ } else {
+ CmdLogVar(ERR_Command_Error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+BackgroundSymHandler(
+ LPVOID lpData,
+ int cb,
+ LPSTR lpVal,
+ BOOL fSet
+ )
+/*++
+
+Routine Description:
+
+ Handle boolean switches, with a native BOOL for the data item.
+
+Arguments:
+
+ lpData - Supplies pointer to data
+
+ cb - Supplies more data
+
+ lpVal - Supplies pointer to user input or string to format into
+
+ fSet - Supplies TRUE for set, FALSE for read/format
+
+Return Value:
+
+ TRUE when successful, FALSE if something is wrong.
+
+--*/
+{
+ int n;
+ BOOL fOK;
+ char szToken[MAX_USER_LINE];
+
+ Unreferenced( cb );
+
+ fOK = OnOffBOOLHandler(lpData, cb, lpVal, fSet);
+ if (!fSet) {
+ return fOK;
+ }
+
+ if (fOK) {
+ if (*(BOOL *)lpData) {
+ LPFNSHSTARTBACKGROUND lpfn;
+ lpfn = (LPFNSHSTARTBACKGROUND) GetProcAddress( HModSH, "SHStartBackground" );
+ if (lpfn) {
+ lpfn();
+ }
+ } else {
+ LPFNSHSTOPBACKGROUND lpfn;
+ lpfn = (LPFNSHSTOPBACKGROUND) GetProcAddress( HModSH, "SHStopBackground" );
+ if (lpfn) {
+ lpfn();
+ }
+ }
+ }
+
+ return fOK;
+}
+
+/************************** *************************/
+
+void NEAR PASCAL
+CmdSetDefaultCmdProc(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Set input and prompt procs to the default (CmdExecuteLine)
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ CmdSetCmdProc(CmdExecuteLine, CmdExecutePrompt);
+ CmdSetAutoHistOK(TRUE);
+ CmdSetEatEOLWhitespace(TRUE);
+}
+
+
+void NEAR PASCAL
+CmdSetCmdProc(
+ BOOL (FAR PASCAL *lpfnLP)(LPSTR lpsz),
+ void (FAR PASCAL *lpfnPP)(BOOL,BOOL)
+ )
+/*++
+
+Routine Description:
+
+ Set the input and prompt procs for the command window.
+
+Arguments:
+
+ lpfnLP - pointer to the line input function
+ lpfnPP - pointer to the prompt printer function
+
+Return Value:
+
+ none
+
+--*/
+{
+ lpfnLineProc = lpfnLP;
+ lpfnPromptProc = lpfnPP;
+}
+
+void FAR PASCAL
+CmdDoPrompt(
+ BOOL fRemote,
+ BOOL fLocal
+ )
+/*++
+
+Routine Description:
+
+ Calls the current prompt printer function, then sets the line to the left
+ of the cursor readonly.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ int XOld;
+ int YOld;
+ int XPos = Views[cmdView].X;
+ int YPos = Views[cmdView].Y;
+
+ if (fLocal) {
+ CmdInsertInit();
+ FDebugString = FALSE;
+
+ // is there already a prompt here?
+ GetRORegion(cmdView, &XOld, &YOld);
+ if (YOld == YNew && XOld > 0) {
+ XNew = XOld;
+ StringLogger("\r\n", FALSE, FALSE, TRUE);
+
+ if (YPos > YOld) {
+ YPos++;
+ } else if (YPos == YOld && XPos >= XOld) {
+ YPos++;
+ XPos -= XOld;
+ }
+ }
+
+ XOld = XNew;
+ YOld = YNew;
+ }
+
+ (*lpfnPromptProc)(fRemote, fLocal);
+
+ if (fLocal) {
+
+ SetRORegion(cmdView, XNew, YNew);
+
+ if (YPos > YOld) {
+ PosXY(cmdView, XPos, YPos + YNew - YOld, FALSE);
+ } else if (YPos == YOld) {
+ PosXY(cmdView, XPos+XNew, YNew, FALSE);
+ } else {
+ PosXY(cmdView, XPos, YPos, FALSE);
+ }
+ }
+}
+
+BOOL FAR PASCAL
+CmdDoLine(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Calls the current line input function
+
+Arguments:
+
+ lpsz - Supplies a line to be handled by the line input function
+
+Return Value:
+
+ BOOL value from line input function: TRUE for synchronous, FALSE for asynch
+
+--*/
+{
+ return (*lpfnLineProc)(lpsz);
+}
+
+
+VOID FAR PASCAL
+CmdPrependCommands(
+ LPTD lptd,
+ LPSTR lpsz
+ )
+
+/*++
+Routine Description:
+
+ This function will take the argument lpsz and prepend any
+ commands in this string to the command line on the thread.
+
+Arguments:
+
+ lptd - Supplies pointer to thread to add commands to
+ lpsz - Supplies commands to add to the threads context
+
+Return Value:
+
+ None
+
+--*/
+{
+ // NOTENOTE a-kentf something calls with an empty string - beta2
+ if (!lpsz || *lpsz == '\0') {
+ return;
+ }
+
+ Assert( lpsz != (LPSTR)NULL );
+ Assert( *lpsz != '\0' );
+
+ if (lptd == (LPTD)NULL) {
+ if ( LpszCmdBuff == (char FAR *)NULL ) {
+ LpszCmdBuff = LpszCmdPtr = _strdup(lpsz);
+ } else {
+ LPSTR lpszT;
+
+ lpszT = malloc( strlen(LpszCmdPtr) + strlen(lpsz) + 2);
+ strcpy(lpszT, lpsz);
+ strcat(lpszT, ";");
+ strcat(lpszT, LpszCmdPtr);
+ free( LpszCmdBuff );
+
+ LpszCmdPtr = LpszCmdBuff = lpszT;
+ }
+ } else if (lptd->lpszCmdBuffer == (LPSTR)NULL) {
+ lptd->lpszCmdBuffer = lptd->lpszCmdPtr = _strdup( lpsz );
+ } else {
+ LPSTR lpszT;
+
+ lpszT = malloc( strlen(lptd->lpszCmdPtr) + strlen(lpsz) + 2);
+ strcpy(lpszT, lpsz);
+ strcat(lpszT, ";");
+ strcat(lpszT, lptd->lpszCmdPtr);
+ free(lptd->lpszCmdBuffer);
+
+ lptd->lpszCmdBuffer = lptd->lpszCmdPtr = lpszT;
+ }
+
+ return;
+} /* CmdPrependCommands() */
+
+void NEAR PASCAL
+CmdExecutePrompt(
+ BOOL fRemote,
+ BOOL fLocal
+ )
+/*++
+
+Routine Description:
+
+ Print the command prompt and position the cursor after it
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ if (fLocal) {
+ CmdInsertInit();
+ }
+ StringLogger( szPrompt, TRUE, fRemote, fLocal );
+}
+
+void
+CmdSetDefaultPrompt(
+ LPSTR lpPrompt
+ )
+{
+ if (!lpPrompt) {
+ strcpy(szPrompt, "> ");
+ } else {
+ strcpy(szPrompt, lpPrompt);
+ }
+}
+
+LPSTR
+CmdGetDefaultPrompt(
+ LPSTR lpPrompt
+ )
+{
+ if (!lpPrompt) {
+ return szPrompt;
+ } else {
+ return strcpy(lpPrompt, szPrompt);
+ }
+}
+
+BOOL NEAR PASCAL
+CmdExecuteLine(
+ LPSTR lpszArg
+ )
+/*++
+
+Routine Description:
+
+ This function will parse up any existing strings for the current
+ thread and execute commands. If lpsz is non-null then the
+ commands represented by this string will be placed first on
+ the threads command list.
+
+Arguments:
+
+ lpsz - Supplies pointer to string containing commands to be executed
+
+Return Value:
+
+ TRUE if the command is synchronous and FALSE if it is asynchronous
+
+--*/
+
+{
+ LPSTR lpsz1;
+ LPSTR lpsz2;
+ int iSrc;
+ int cmdRet;
+ char ch;
+ LPTD lptd;
+ char rgchT[256];
+ BOOL fQuote;
+ char localArg[1024];
+
+
+
+ //
+ // in case the caller passes in a read only string
+ //
+ if (lpszArg) {
+ strcpy( localArg, lpszArg );
+ lpszArg = &localArg[0];
+ }
+
+ if (lpszArg && (lpszArg[0] == '*')) {
+ lpszArg = NULL;
+ }
+
+ if ((LptdCur == NULL) && (lpszArg == NULL) && (LpszCmdBuff == NULL)) {
+ return TRUE;
+ }
+
+ /*
+ * If there are any steps left to be executed from a previous command
+ * these take precedence over any new commands to be executed
+ */
+
+ if ((LptdCur != NULL) && (LptdCur->cStepsLeft != 0)) {
+ if (lpszArg != 0) {
+ CmdPrependCommands(LptdCur, lpszArg);
+ }
+
+ LptdCur->cStepsLeft -= 1;
+ if (ExecDebuggee((LptdCur->flags & tfStepOver) ? EXEC_STEPOVER : EXEC_TRACEINTO)) {
+ return FALSE;
+ }
+ LptdCur->cStepsLeft = 0;
+ return TRUE;
+ }
+
+ do {
+ /*
+ ** Setup for parsing and executing from the current thread
+ */
+
+ lptd = LptdCur;
+ if (lpszArg) {
+ lpsz1 = lpszArg;
+ iSrc = 1;
+ lpszArg = NULL;
+ } else if ((lptd != NULL) && (lptd->lpszCmdBuffer != NULL)) {
+ lpsz1 = lptd->lpszCmdPtr;
+ iSrc = 0;
+ } else {
+ lpsz1 = LpszCmdPtr;
+ iSrc = 2;
+ }
+
+ if (lpsz1 == NULL) {
+ return TRUE;
+ }
+
+ lpsz2 = lpsz1;
+
+ /*
+ ** Scan across the command looking for either the end of the command
+ ** This is denoted by either a semi-colon or the end of the string.
+ */
+
+ fQuote = FALSE;
+ while (*lpsz1) {
+ if (*lpsz1 == '\"') {
+ fQuote = !fQuote;
+ } else if (!fQuote && (*lpsz1 == ';')) {
+ break;
+ }
+#ifdef DBCS
+ lpsz1 = CharNext(lpsz1);
+#else
+ lpsz1 ++;
+#endif
+ }
+
+ ch = *lpsz1;
+ *lpsz1 = 0;
+
+ /*
+ ** Update the thread state information to deal with the possiblity
+ ** of a thread switch while executing the command
+ */
+
+ if (ch == 0) {
+ switch( iSrc ) {
+ /*
+ ** We are about to execute the last command from the
+ ** threads buffer. Copy it locally and free
+ ** the thread state buffer
+ */
+
+ case 0: // Input from thread buffer
+ Assert( lptd != NULL );
+ Assert(lptd->lpszCmdBuffer != NULL);
+
+ strcpy(rgchT, lptd->lpszCmdPtr);
+ lpsz2 = &rgchT[0];
+ free( lptd->lpszCmdBuffer);
+ lptd->lpszCmdBuffer = lptd->lpszCmdPtr = NULL;
+
+ break;
+
+ /*
+ ** No updates are needed -- We just executed a single
+ ** command from the input argument and no modifications
+ ** of the thread state are needed.
+ */
+
+ case 1: // Input from argument buffer
+ break;
+
+ /*
+ ** We are about to execute the last command from
+ ** the global buffer. Copy it locally and free
+ ** the global command buffer.
+ */
+
+ case 2: // Input from global buffer
+
+ Assert( LpszCmdBuff != NULL );
+
+ strcpy(rgchT, LpszCmdPtr);
+ lpsz2 = &rgchT[0];
+ free( LpszCmdBuff );
+ LpszCmdBuff = LpszCmdPtr = NULL;
+ break;
+
+ default:
+ Assert(FALSE);
+ break;
+ }
+ } else {
+ lpsz1++;
+
+ switch (iSrc) {
+ /*
+ ** Just need to update the state information for
+ ** this thread
+ */
+
+ case 0:
+ lptd->lpszCmdPtr = lpsz1;
+ break;
+
+ /*
+ ** Need to prepend the rest of this command line onto
+ ** the thread command buffer
+ */
+
+ case 1:
+ CmdPrependCommands( lptd, lpsz1 );
+ break;
+
+ /*
+ ** Just update the pointer state on the global
+ ** command buffer
+ */
+
+ case 2:
+ LpszCmdPtr = lpsz1;
+ break;
+
+ default:
+ Assert(FALSE);
+ break;
+ }
+ }
+
+ /*
+ ** Execute this command and grab the return code. It will tell use if
+ ** this specific command was syncronous or not.
+ */
+
+ cmdRet = CmdExecuteCmd(lpsz2);
+
+ /*
+ ** Loop while the last command was successful and
+ ** synchronous. Plus there is either a command in the
+ ** current thread buffer or the global buffer.
+ */
+ } while ((cmdRet == CMD_RET_SYNC) &&
+ (((LptdCur != NULL) && (LptdCur->lpszCmdPtr != NULL)) ||
+ (LpszCmdPtr != NULL)));
+
+ if (cmdRet == CMD_RET_ERROR) {
+ //
+ // clear remaining commands on this thread and globally.
+ //
+ if (LptdCur && LptdCur->lpszCmdBuffer) {
+ free(LptdCur->lpszCmdBuffer);
+ LptdCur->lpszCmdPtr = LptdCur->lpszCmdBuffer = NULL;
+ }
+ if (LpszCmdBuff) {
+ free( LpszCmdBuff );
+ LpszCmdBuff = LpszCmdPtr = NULL;
+ }
+ }
+
+ return ((cmdRet == CMD_RET_SYNC) || (cmdRet == CMD_RET_ERROR));
+} /* CmdExecLine() */
+
+
+int NEAR PASCAL
+CmdExecuteCmd(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function will parse up and attempt to execute a command string
+ this command string is equivalent to a return terminated string
+ rather than a single command. The return is optional as zero
+ termination will work equally well.
+
+Arguments:
+
+ lpsz - Supplies pointer to the string containning command to be executed
+
+Return Value:
+
+ CMD_RET_SYNC - command is syncronous
+ CMD_RET_ASYNC - command is async
+ CMD_RET_ERROR - command was in error
+
+
+--*/
+{
+ int retCmd = CMD_RET_SYNC;
+ LOGERR logerror = LOGERROR_NOERROR;
+ UINT i;
+ BOOL err;
+ int cb;
+ LPSTR lpszSave = lpsz;
+ LPSTR lpszT;
+ LPSTR lpszX;
+ char ch;
+
+ static char chLastDump = 0;
+
+ // Skip over any preceeding white space
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ return(CMD_RET_SYNC);
+ }
+
+ // Strip off any trailing white space
+
+ for (lpszX = lpsz-1, lpszT = lpsz; *lpszT; lpszT++) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*lpszT) && *(lpszT+1)) {
+ lpszX = lpszT + 1;
+ lpszT++;
+ } else
+#endif
+ if (!isspace(*lpszT)) {
+ lpszX = lpszT;
+ }
+ }
+
+ if (lpszX+1 != lpszT) {
+ *(lpszX + 1) = 0;
+ }
+
+ // Strip off anything relative to threads or processes which
+ // may preceed the command
+ //
+ // Possible starting strings are:
+ //
+ // lead := processID | threadID | processID threadID | <blank>
+ // processID := '|' Number | '|' '.'
+ // threadID := '~' Number | '~' '.'
+
+ LppdCommand = LppdCur;
+ LptdCommand = LptdCur;
+ FSetLptd = FALSE;
+ FSetLppd = FALSE;
+ BpCmdPid = LppdCommand? LppdCommand->ipid : 0;
+ BpCmdTid = LptdCommand? LptdCommand->itid : -1;
+
+ if (*lpsz == '|') {
+ FSetLppd = TRUE;
+ lpsz = CPSkipWhitespace(lpsz+1);
+ if (*lpsz == 0) {
+ logerror = LogProcess();
+ goto done;
+ } else if (*lpsz == '.') {
+ lpsz++;
+ } else if (*lpsz == '*') {
+ BpCmdPid = -1;
+ LppdCommand = (LPPD) -1;
+ lpsz++;
+ } else {
+ i = (int) CPGetInt(lpsz, &err, &cb);
+ if (err) {
+ logerror = LOGERROR_UNKNOWN;
+ goto done;
+ } else {
+ BpCmdPid = i;
+ lpsz += cb;
+ LppdCommand = ValidLppdOfIpid(i);
+ if ( LppdCommand == NULL ) {
+ LptdCommand = NULL;
+ } else {
+ LptdCommand = LppdCommand->lptdList;
+ }
+ }
+ }
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == '~') {
+ FSetLptd = TRUE;
+ lpsz = CPSkipWhitespace(lpsz+1);
+ if (*lpsz == 0) {
+ logerror = LogThread();
+ goto done;
+ } else if (*lpsz == '.') {
+ BpCmdTid = LptdCommand? LptdCommand->itid : 0;
+ lpsz++;
+ } else if (*lpsz == '*') {
+ BpCmdTid = -1;
+ LptdCommand = (LPTD) -1;
+ lpsz++;
+ } else {
+ i = (int) CPGetInt(lpsz, &err, &cb);
+ if (err) {
+ logerror = LOGERROR_UNKNOWN;
+ goto done;
+ } else if (LppdCommand == (LPPD) -1) {
+ CmdInsertInit();
+ CmdLogVar(ERR_No_Thread_With_Wildproc);
+ logerror = LOGERROR_QUIET;
+ goto done;
+ } else {
+ BpCmdTid = i;
+ lpsz += cb;
+ if ( LppdCommand == NULL ) {
+ LptdCommand = NULL;
+ } else {
+ LptdCommand = LptdOfLppdItid(LppdCommand, i);
+ NotifyDmOfProcessorChange( i );
+ }
+ }
+ }
+ }
+
+ /*
+ ** Skip across any leading white space.
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ //
+ // For Breakpoint set, we accept nonexistend Process/Thread. For
+ // all other commands, Process/Thread must be valid if specified.
+ //
+ if ( !( (*lpsz == 'B' || *lpsz == 'b') &&
+ (*(lpsz+1) == 'P' || *(lpsz+1) == 'p') ) ) {
+
+ if ( FSetLppd ) {
+ if ( LppdCur == NULL ) {
+ CmdInsertInit();
+ CmdLogVar(ERR_Process_Not_Exist);
+ logerror = LOGERROR_QUIET;
+ goto done;
+ } else if ( LppdCommand == NULL ) {
+ logerror = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ }
+
+ if ( FSetLptd ) {
+ if ( LptdCur == NULL ) {
+ CmdInsertInit();
+ CmdLogVar(ERR_No_Threads);
+ logerror = LOGERROR_QUIET;
+ goto done;
+ } else if ( LptdCommand == NULL ) {
+ logerror = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ }
+ }
+
+ /*
+ ** Now run through a big switch statement so that we can breakup
+ ** the command
+ */
+
+ switch ( *lpsz++ ) {
+ case 0:
+ if (FSetLptd || FSetLppd) {
+
+ if (LppdCommand == NULL || LppdCommand == (LPPD)-1
+ || LptdCommand == NULL || LptdCommand == (LPTD)-1)
+ {
+ logerror = LOGERROR_UNKNOWN;
+ } else {
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ StatusPidTid(LppdCur->ipid, LptdCur->itid);
+ UpdateDebuggerState(UPDATE_WINDOWS);
+ }
+ }
+ break;
+
+ case '.':
+ logerror = LogDotCommand(lpsz);
+ if (logerror == LOGERROR_ASYNC) {
+ retCmd = CMD_RET_ASYNC;
+ }
+ break;
+
+ case '*': // Comments
+ retCmd = CMD_RET_SYNC;
+ break;
+
+ case '+': // Pause
+ if (AutoRun != arSource && AutoRun != arCmdline) {
+ logerror = LOGERROR_UNKNOWN;
+ }
+ retCmd = CMD_RET_ASYNC;
+ break;
+
+ case '-': // Continue
+ if (AutoRun == arSource || AutoRun == arCmdline) {
+ PostMessage(Views[cmdView].hwndClient, WU_AUTORUN, 0, 0);
+ } else {
+ logerror = LOGERROR_UNKNOWN;
+ }
+ break;
+
+ case '?':
+ logerror = LogEvaluate(lpsz);
+ break;
+
+ case '%':
+ logerror = LogFrameChange(lpsz);
+ break;
+
+#ifdef MICHE
+ case 'a':
+ case 'A':
+ logerror = LogAssemble(lpsz);
+ break;
+#endif
+
+ case 'b':
+ case 'B':
+ switch( *lpsz++ ) {
+ case 'c':
+ case 'C':
+ logerror = LogBPChange(lpsz, LOG_BP_CLEAR);
+ break;
+
+ case 'd':
+ case 'D':
+ logerror = LogBPChange(lpsz, LOG_BP_DISABLE);
+ break;
+
+ case 'e':
+ case 'E':
+ logerror = LogBPChange(lpsz, LOG_BP_ENABLE);
+ break;
+
+ case 'l':
+ case 'L':
+ if (*CPSkipWhitespace(lpsz) != 0) {
+ logerror = LOGERROR_UNKNOWN;
+ } else {
+ logerror = LogBPList();
+ }
+ break;
+
+ case 'p':
+ case 'P':
+ logerror = LogBPSet(FALSE, lpsz);
+ break;
+
+ case 'a':
+ case 'A':
+ logerror = LogBPSet(TRUE, lpsz);
+ break;
+
+ default:
+ logerror = LOGERROR_UNKNOWN;
+ }
+ break;
+
+ case 'c':
+ case 'C':
+ logerror = LogCompare(lpsz);
+ break;
+
+
+ case 'd':
+#ifdef MS_INTERNAL_DONT_COMPILE_THIS_DAMMIT
+ if ( lpsz[0] == 'C'
+ && lpsz[1] == 'R'
+ && lpsz[2] == 'E'
+ && lpsz[3] == 'D'
+ && lpsz[4] == 'I'
+ && lpsz[5] == 'T'
+ && lpsz[6] == 'S'
+ && lpsz[7] == 0)
+ {
+ logerror = LOGERROR_NOERROR;
+ Egg();
+ break;
+ }
+#endif
+ case 'D':
+ if (*CPSkipWhitespace(lpsz) == 0) {
+ ch = chLastDump;
+ } else {
+ ch = *lpsz++;
+ }
+
+ if (ch == 'c' || ch == 'C') {
+ logerror = LogDisasm(lpsz,FALSE);
+ } else {
+ logerror = LogDumpMem(ch, lpsz);
+ }
+ chLastDump = ch;
+ break;
+
+ case 'e':
+ case 'E':
+ logerror = LogEnterMem(lpsz);
+ break;
+
+ case 'f':
+ case 'F':
+ if (*lpsz == 'i' || *lpsz == 'I') {
+ logerror = LogFill(++lpsz);
+ } else if (*lpsz == 'r' || *lpsz == 'R') {
+ logerror = LogRegisters(++lpsz, TRUE);
+ } else {
+ logerror = LogFreeze(lpsz, TRUE);
+ }
+ break;
+
+ case 'h':
+ case 'H':
+ logerror = LogHelp(lpsz);
+ break;
+
+ case 'g':
+ case 'G':
+ if (*lpsz == 'h' || *lpsz == 'H') {
+ logerror = LogGoException(++lpsz, TRUE);
+ } else if (*lpsz == 'n' || *lpsz == 'N') {
+ logerror = LogGoException(++lpsz, FALSE);
+ } else {
+ logerror = LogGoUntil(lpsz);
+ }
+ retCmd = CMD_RET_ASYNC;
+ break;
+
+ case 'k':
+ case 'K':
+ logerror = LogCallStack(lpsz);
+ break;
+
+ case 'l':
+ case 'L':
+ if (*lpsz == 'n' || *lpsz == 'N') {
+ logerror = LogListNear(++lpsz);
+ } else if (*lpsz == 'm' || *lpsz == 'M') {
+ logerror = LogListModules(++lpsz);
+ } else if (*lpsz == 'd' || *lpsz == 'D') {
+ logerror = LogLoadDefered(++lpsz);
+ } else if (*lpsz == '\0' || *lpsz == ' ' || *lpsz == '\t') {
+ logerror = LogRestart(lpsz);
+ } else {
+ logerror = LOGERROR_UNKNOWN;
+ }
+ break;
+
+ case 'm':
+ case 'M':
+ logerror = LogMovemem(lpsz);
+ break;
+
+ case 'n':
+ case 'N':
+ logerror = LogRadix(lpsz);
+ break;
+
+ case 'p':
+ case 'P':
+ logerror = LogStep(lpsz, TRUE);
+ retCmd = CMD_RET_ASYNC;
+ break;
+
+ case 'q':
+ case 'Q':
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz == 0) {
+ PostMessage(hwndFrame, WM_COMMAND, IDM_FILE_EXIT, 0L);
+ } else {
+ logerror = LOGERROR_UNKNOWN;
+ }
+ retCmd = CMD_RET_ASYNC;
+ break;
+
+ case 'r':
+ case 'R':
+ if (*lpsz == 'e' && _strnicmp(lpsz,"emote",5)==0) {
+ lpsz += 5;
+ logerror = LogRemote(lpsz);
+ } else {
+ logerror = LogRegisters(lpsz, FALSE);
+ }
+ break;
+
+ case 's':
+ case 'S':
+ switch (*lpsz) {
+ case 'e':
+ case 'E':
+ LogSetErrorLevel(++lpsz);
+ break;
+ case 'x':
+ case 'X':
+ logerror = LogException(++lpsz);
+ break;
+ case '-':
+ StatusSrc(TRUE);
+ break;
+ case '+':
+ StatusSrc(FALSE);
+ break;
+ default:
+ logerror = LogSearch(lpsz);
+ break;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ logerror = LogStep(lpsz, FALSE);
+ retCmd = CMD_RET_ASYNC;
+ break;
+
+ case 'u':
+ case 'U':
+ logerror = LogDisasm(lpsz,FALSE);
+ break;
+
+ case '#':
+ logerror = LogSearchDisasm(lpsz);
+ break;
+
+ case 'w':
+ case 'W':
+ if (*lpsz == 't' || *lpsz == 'T') {
+ logerror = LogWatchTime(lpsz+1);
+ } else {
+ logerror = LOGERROR_UNKNOWN;
+ }
+ break;
+
+ case 'x':
+ case 'X':
+ logerror = LogExamine(lpsz);
+ break;
+
+ case 'v':
+ case 'V':
+ if (*lpsz == 'e' && _strnicmp(lpsz,"ersion",6)==0) {
+ logerror = LogVersion(lpsz);
+ } else {
+ logerror = LOGERROR_UNKNOWN;
+ }
+ break;
+
+ case 'z':
+ case 'Z':
+ logerror = LogFreeze(lpsz, FALSE);
+ break;
+
+ case '!':
+ logerror = LogExtension(lpsz);
+ break;
+
+ default:
+ logerror = LOGERROR_UNKNOWN;
+ break;
+ }
+
+ /*
+ **
+ */
+
+done:
+ switch (logerror) {
+ case LOGERROR_CP:
+ // get CP error string...
+
+ default:
+ case LOGERROR_UNKNOWN:
+ CmdInsertInit();
+ CmdLogVar(ERR_Command_Error);
+ // fall thru
+
+ case LOGERROR_QUIET:
+ retCmd = CMD_RET_ERROR;
+ break;
+
+ case LOGERROR_ASYNC:
+ case LOGERROR_NOERROR:
+ break;
+
+ }
+
+ return( retCmd );
+} /* CmdExecuteCmd() */
+
+
+VOID FAR PASCAL
+CmdInsertInit(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Set the insertion point to the beginning of the last
+ line in the window.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ if (cmdView == -1) {
+ OpenDebugWindow(COMMAND_WIN, NULL, -1);
+ }
+
+ XNew = 0;
+ YNew = max(Docs[Views[cmdView].Doc].NbLines-1, 0);
+
+ return;
+} /* CmdInsertInit() */
+
+
+DWORD
+LogFileWrite(
+ LPBYTE lpb,
+ DWORD cb
+ )
+{
+ if (hFileLog == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
+
+ EnterCriticalSection( &csLog );
+
+ WriteFile( hFileLog, lpb, cb, &cb, NULL );
+
+ LeaveCriticalSection( &csLog );
+
+ return cb;
+}
+
+
+BOOL NEAR PASCAL
+StringLogger(
+ LPSTR szStr,
+ BOOL fFileLog,
+ BOOL fSendRemote,
+ BOOL fPrintLocal
+)
+/*++
+
+Routine Description:
+
+ This function is used to record data into the command window. It
+ will take care of checking for overflow in the current command line.
+
+ It is used in association with CmdInsertInit.
+
+ Additionally this function will log the string in the log file if
+ logging to file is currently enabled.
+
+Arguments:
+
+ buf - Supplies the string to be logged in the command window.
+ fFileLog - Supplies TRUE if logging to a log file is desired.
+
+Return Value:
+
+ TRUE if sucessful and FALSE otherwise
+
+--*/
+{
+ LPLINEREC pLine;
+ LPBLOCKDEF pBlock;
+ int cWide;
+
+ int doc = Views[cmdView].Doc;
+
+ int PosXold = Views[cmdView].X;
+ int PosYold = Views[cmdView].Y;
+ int XOld = XNew; // remember original insertion point
+ int YOld = YNew;
+ int XNext; // IP after pending insert
+ int YNext;
+ int Xro;
+ int Yro;
+ int ytmp;
+ LPSTR lpsz;
+ int cch;
+ LPSTR lpPut;
+ BOOL fDidCR = FALSE;
+ BOOL fRet = TRUE;
+ CHAR szLoggerBuf[MAX_USER_LINE+2];
+
+
+ AuxPrintf(1, "### %s", szStr);
+
+ /*
+ * Ensure that the command window exists
+ */
+
+ Assert(cmdView != -1);
+
+ /*
+ * We are going to insert at XNew,YNew.
+ * We need to know where we ended up...
+ */
+
+ YNext = YNew;
+ XNext = XNew;
+
+ lpsz = szStr;
+ lpPut = szLoggerBuf;
+
+ if (!fPrintLocal) {
+
+ if (fFileLog) {
+ LogFileWrite( lpsz, strlen(lpsz) );
+ }
+
+ if (fSendRemote) {
+ SendClientOutput( lpsz, strlen(lpsz) );
+ }
+
+ return fRet;
+ }
+
+ for ( ; *lpsz; lpPut = szLoggerBuf) {
+
+ ytmp = YNew; // FirstLine modifies the lineNo!!!!
+
+ // find how much line we have to work with:
+ Dbg (FirstLine(doc, &pLine, &ytmp, &pBlock));
+ cWide = AlignToTabs(pLine->Length - LHD,
+ pLine->Length - LHD,
+ (LPSTR)pLine->Text);
+
+ while (*lpsz) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*lpsz) && *(lpsz+1)) {
+ if (XNext + 2 < (MAX_USER_LINE - cWide)) {
+ *lpPut++ = *lpsz++;
+ *lpPut++ = *lpsz++;
+ XNext += 2;
+ continue;
+ } else {
+ goto DoNewline;
+ }
+ }
+#endif
+
+ if (*lpsz == '\r') {
+
+ // if there is a newline, eat it:
+ if (*++lpsz == '\n') {
+ lpsz++;
+ }
+ goto DoNewline;
+
+ } else if (*lpsz == '\n') {
+
+ lpsz++;
+ goto DoNewline;
+
+ } else {
+ int cx = 1;
+ if (*lpsz == '\t') {
+ cx = tabSize - (XNext % tabSize);
+ }
+ if (XNext + cx < (MAX_USER_LINE - cWide)) {
+
+ *lpPut++ = *lpsz++;
+ XNext += cx;
+
+ } else {
+
+ DoNewline:
+
+ *lpPut++ = '\r';
+ *lpPut++ = '\n';
+ YNext++;
+ XNext = 0;
+ fDidCR = TRUE;
+ break;
+ }
+ }
+ }
+
+ *lpPut = '\0';
+
+ // remember readonly info, clear it:
+ GetRORegion(cmdView, &Xro, &Yro);
+ SetRORegion(cmdView, 0, 0);
+
+ // spew buffer
+ cch = lpPut - szLoggerBuf;
+ fRet = InsertBlock(doc, XNew, YNew, cch, szLoggerBuf);
+
+ // fix read only marker
+ if (fRet) {
+ if (YNew < Yro) {
+ Yro += YNext - YNew;
+ } else if (YNew == Yro && XNew < Xro) {
+ Yro += YNext - YNew;
+ Xro += XNext - XNew;
+ }
+ }
+
+ SetRORegion(cmdView, Xro, Yro);
+
+ if (!fRet) {
+ break;
+ }
+
+ // remember new insertion point
+ XNew = XNext;
+ YNew = YNext;
+
+ if (fFileLog) {
+ LogFileWrite( szLoggerBuf, cch );
+ }
+
+ if (fSendRemote) {
+ SendClientOutput( szLoggerBuf, cch );
+ }
+
+ }
+
+ // are there too many lines in the buffer?
+ ytmp = max(Docs[doc].NbLines, 1) - MAX_CMDWIN_LINES;
+ if (ytmp > 0) {
+ //
+ // delete more than we need to so it doesn't happen
+ // every time a line is printed.
+ //
+ ytmp += 20;
+ GetRORegion(cmdView, &Xro, &Yro);
+ SetRORegion(cmdView, 0, 0);
+ // This means delete full lines
+ DeleteBlock(doc, 0, 0, 0, ytmp);
+ YNew -= ytmp;
+ YOld -= ytmp;
+ PosYold -= ytmp;
+ Yro -= ytmp;
+ YNewDebug -= ytmp;
+ SetRORegion(cmdView, Xro, Yro);
+ InvalidateRect(Views[cmdView].hwndClient, NULL, FALSE);
+ }
+
+ SetVerticalScrollBar(cmdView, FALSE);
+
+ InvalidateLines(cmdView, YOld, YNew, TRUE);
+
+ if (YOld <= PosYold) {
+ // insert was on or before cursor line:
+ PosYold += YNew - YOld;
+ }
+
+ PosXY(cmdView, PosXold, PosYold, FALSE);
+
+ if (fDidCR) {
+ UpdateWindow(Views[cmdView].hwndClient);
+ }
+
+ return fRet;
+} /* StringLogger() */
+
+int FAR CDECL
+CmdLogVar(
+ WORD wFormat,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Format arguments with vsprintf, print with stringlogger
+
+Arguments:
+
+ wFormat - Supplies resource ID for format string
+ .... - Optional args supply values to be formatted by vsprintf
+
+Return Value:
+
+ Return value from StringLogger
+
+--*/
+{
+ char szFormat[MAX_MSG_TXT];
+ char szText[MAX_VAR_MSG_TXT];
+ va_list vargs;
+
+ // load format string from resource file
+ Dbg(LoadString(hInst, wFormat, (LPSTR)szFormat, MAX_MSG_TXT));
+ va_start(vargs, wFormat);
+ vsprintf(szText, szFormat, vargs);
+ va_end(vargs);
+
+ if (cmdView == -1) {
+ OpenDebugWindow(COMMAND_WIN, NULL, -1);
+ }
+
+ /*
+ * If we just change from doing a debug string to doing something else
+ * then we need to insert a return in the command string.
+ */
+
+ FDebugString = FALSE;
+
+ return StringLogger(szText, TRUE, TRUE, TRUE) &&
+ StringLogger("\r\n", TRUE, TRUE, TRUE);
+} /* CmdLogVar() */
+
+int FAR CDECL
+CmdLogFmt(
+ LPSTR lpFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Format arguments with vsprintf and print result with StringLogger
+
+Arguments:
+
+ lpFmt - Supplies pointer to format string
+ ... - Optional args supply values to be formatted
+
+Return Value:
+
+ Return value from StringLogger
+
+--*/
+{
+ char szText[MAX_VAR_MSG_TXT];
+ va_list vargs;
+
+
+ va_start(vargs, lpFmt);
+ _vsnprintf(szText, MAX_VAR_MSG_TXT-1, lpFmt, vargs);
+ va_end(vargs);
+
+ if (cmdView == -1) {
+ OpenDebugWindow(COMMAND_WIN, NULL, -1);
+ }
+
+ /*
+ * If we just change from doing a debug string to doing something else
+ * then we need to insert a return in the command string.
+ */
+
+ FDebugString = FALSE;
+
+ return StringLogger(szText, TRUE, TRUE, TRUE);
+} /* CmdLogFmt() */
+
+BOOL FAR PASCAL
+CmdNoLogString(
+ LPSTR buf
+ )
+/*++
+
+Routine Description:
+
+ This function is used to record data into the command window. It
+ will take care of checking for overflow in the current command line.
+
+ It is used in association with CmdInsertInit.
+
+Arguments:
+
+ buf - Supplies the string to be logged in the command window
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise.
+
+--*/
+
+{
+ /*
+ * If we just change from doing a debug string to doing something else
+ * then we need to insert a return in the command string.
+ */
+
+ if (cmdView == -1) {
+ OpenDebugWindow(COMMAND_WIN, NULL, -1);
+ }
+
+ FDebugString = FALSE;
+
+ return StringLogger(buf, FALSE, TRUE, TRUE);
+} /* CmdNoLogString() */
+
+VOID FAR PASCAL
+CmdLogDebugString(
+ LPSTR lpStr,
+ BOOL fSendRemote
+ )
+/*++
+
+Routine Description:
+
+ This function is used to put out debug strings into the command
+ window. This needs to deal with the possiblity of not having
+ returns on the end of a string.
+
+Arguments:
+
+ lpStr - Supplies pointer to characters to be displayed
+
+Return Value:
+
+ None
+
+--*/
+{
+ static fDebugNewline;
+ static XNewSave;
+
+ char * lpch;
+ char * lpch2;
+
+ XNewSave = XNew;
+
+ if (!FDebugString) {
+ CmdInsertInit();
+ fDebugNewline = TRUE;
+ } else {
+ XNew = XNewDebug;
+ YNew = YNewDebug;
+ }
+
+ // don't modify src string!!
+ lpch = _strdup(lpStr);
+ lpch2 = lpch;
+ for (;;) {
+ if (*lpch2 == 0) {
+ if (lpch2 > lpch) {
+ StringLogger(lpch, TRUE, fSendRemote, TRUE);
+ }
+ break;
+ } else if (fDebugNewline) {
+ StringLogger("\r\n", FALSE, FALSE, TRUE);
+ --YNew;
+ fDebugNewline = FALSE;
+ } else if (*lpch2 == '\n') {
+ *lpch2++ = 0;
+ StringLogger(lpch, TRUE, fSendRemote, TRUE);
+ lpch = lpch2;
+ fDebugNewline = TRUE;
+ StringLogger("\r\n", TRUE, fSendRemote, FALSE);
+ CmdInsertInit();
+ } else if (*lpch2 == '\r') {
+ *lpch2++ = 0;
+ if (*lpch2 == '\n') {
+ lpch2++;
+ }
+ StringLogger(lpch, TRUE, fSendRemote, TRUE);
+ lpch = lpch2;
+ fDebugNewline = TRUE;
+ StringLogger("\r\n", TRUE, fSendRemote, FALSE);
+ CmdInsertInit();
+ } else {
+#ifdef DBCS
+ lpch2 = CharNext( lpch2 );
+#else
+ lpch2++;
+#endif
+ }
+ }
+
+ FDebugString = TRUE;
+ XNewDebug = XNew;
+ YNewDebug = YNew;
+
+ CmdInsertInit();
+ XNew = XNewSave;
+} /* CmdLogDebugString() */
+
+
+VOID FAR PASCAL
+CmdFileString(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function is used to dump a string only to the log file.
+
+Arguments:
+
+ lpsz - Supplies string to be dumped to the file
+
+Return Value:
+
+ None
+
+--*/
+{
+ LogFileWrite( lpsz, strlen(lpsz) );
+ return;
+} /* CmdFileString() */
+
+BOOL FAR PASCAL
+CmdAutoRunInit(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to set up the internal AutoRun variables
+ to read command from a file and get them processed
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ Assert( AutoRun == arSource || AutoRun == arCmdline );
+
+ if ((fpAutoRun = fopen(PszAutoRun, "rb")) == NULL) {
+ return FALSE;
+ }
+
+ PostMessage(Views[cmdView].hwndClient, WU_AUTORUN, 0, 0);
+
+ return TRUE;
+} /* CmdAutoRunInit() */
+
+void
+CmdAutoRunNext(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Get the next line from the auto run file and cause it to be processed
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ char rgchCmd[300];
+ char * ptr;
+
+ Assert(AutoRun != arNone);
+
+ if (AutoRun == arQuit) {
+ return;
+ }
+
+ while (fgets(rgchCmd, sizeof(rgchCmd), fpAutoRun) != NULL) {
+
+ /*
+ ** Sanitize
+ */
+
+#ifdef DBCS
+ ptr = rgchCmd + strlen(rgchCmd);
+ while (ptr > rgchCmd) {
+ ptr = CharPrev(rgchCmd, ptr);
+ if ( *ptr != '\n' && *ptr != '\r') {
+ break;
+ }
+ *ptr = '\0';
+ }
+#else
+ ptr = rgchCmd + strlen(rgchCmd) - 1;
+ while ( *ptr == '\n' || *ptr == '\r') {
+ *ptr-- = '\0';
+ }
+#endif
+
+ /*
+ ** Log the command into the command window
+ */
+
+ if (cmdView != -1) {
+ Views[cmdView].X = 0;
+ }
+ CmdDoPrompt(TRUE, TRUE);
+ CmdLogFmt("%s\r\n", rgchCmd);
+
+ /*
+ ** Do it, and return on asynch commands
+ */
+
+ if (CmdDoLine(rgchCmd) == FALSE) {
+ return;
+ }
+ }
+
+ /*
+ ** We have run out of input so attempt to shut down the system
+ */
+
+ if (AutoRun == arSource) {
+ // revert to normal input
+ AutoRun = arNone;
+ } else {
+ AutoRun = arQuit;
+ PostMessage(hwndFrame, WM_COMMAND, IDM_FILE_EXIT, 0L);
+ }
+ return;
+
+} /* CmdAutoRunNext() */
+
+
+LOGERR NEAR PASCAL
+LogSource(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ AutoRun = arSource;
+ PszAutoRun = _strdup(lpsz);
+
+ if (CmdAutoRunInit()) {
+ return LOGERROR_NOERROR;
+ } else {
+ CmdLogVar( ERR_File_Open, PszAutoRun );
+ free(PszAutoRun);
+ PszAutoRun = NULL;
+ return LOGERROR_QUIET;
+ }
+}
+
+
+LOGERR NEAR PASCAL
+LogFileOpen(
+ LPSTR lpsz,
+ DWORD fAppend
+ )
+/*++
+
+Routine Description:
+
+ This function will open up a log file name. By default if no
+ name is specified we will use "QCWIN.LOG" as the default name.
+ If fAppend is TRUE then we append to the end if the specified
+ file, else we create the requested file.
+
+Arguments:
+
+ lpsz - Supplies string containning the log file name
+ fAppend - Supplies TRUE if append to the specified file
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ char rgch[256];
+
+ CmdInsertInit();
+ /*
+ ** Skip over any leading whitespace
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ /*
+ ** Setup a default name if none was specified
+ */
+
+ if (*lpsz == 0) {
+ MakeFileNameFromProg(".LOG", rgch);
+ lpsz = rgch;
+ }
+
+ /*
+ ** If a handle is already open then we will close that file
+ */
+
+ if (hFileLog != INVALID_HANDLE_VALUE) {
+ CloseHandle( hFileLog );
+ }
+
+ /*
+ ** Open a handle onto the requested file
+ */
+
+ hFileLog = CreateFile( lpsz,
+ GENERIC_WRITE | GENERIC_READ,
+ 0,
+ NULL,
+ fAppend ? OPEN_ALWAYS : CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, // | FILE_FLAG_WRITE_THROUGH,
+ NULL
+ );
+
+ if (fAppend) {
+ SetFilePointer(hFileLog, 0, NULL, FILE_END);
+ }
+ if (hFileLog == INVALID_HANDLE_VALUE) {
+ CmdLogVar(ERR_File_Open, lpsz);
+ return LOGERROR_QUIET;
+ }
+
+ /*
+ ** All done -- return
+ */
+
+ return LOGERROR_NOERROR;
+} /* LogFileOpen() */
+
+LOGERR NEAR PASCAL
+LogFileClose(
+ LPSTR lpUnused,
+ DWORD dwUnused
+ )
+/*++
+
+Routine Description:
+
+ Close the log file
+
+Arguments:
+
+ None
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LOGERR lerr = LOGERROR_NOERROR;
+ CmdInsertInit();
+ EnterCriticalSection( &csLog );
+ if (hFileLog != INVALID_HANDLE_VALUE) {
+ CloseHandle(hFileLog);
+ hFileLog = INVALID_HANDLE_VALUE;
+ } else {
+ CmdLogVar(ERR_File_Not_Open);
+ lerr = LOGERROR_QUIET;
+ }
+
+ LeaveCriticalSection( &csLog );
+ return lerr;
+} /* LogFileClose() */
+
+
+LOGERR NEAR PASCAL
+LogWaitForString(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+/*++
+
+Routine Description:
+
+ Waits for a debug string
+
+Arguments:
+
+ lpsz - Supplies string containning the log file name
+ fAppend - not used
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ CmdInsertInit();
+ /*
+ ** Skip over any leading whitespace
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ return LOGERROR_QUIET;
+ }
+
+ lpCmdString = _strdup(lpsz);
+ fWaitForDebugString = TRUE;
+
+ /*
+ ** All done -- return
+ */
+
+ return LOGERROR_ASYNC;
+} /* LogWaitForString() */
+
+
+LOGERR NEAR PASCAL
+LogSleep(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+/*++
+
+Routine Description:
+
+ Waits for n seconds.
+
+Arguments:
+
+ lpsz - seconds to sleep
+ fAppend - not used
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ CmdInsertInit();
+ /*
+ ** Skip over any leading whitespace
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ return LOGERROR_QUIET;
+ }
+
+ Sleep( atol(lpsz) * 1000 );
+
+ /*
+ ** All done -- return
+ */
+
+ return LOGERROR_NOERROR;
+} /* LogSleep() */
+
+
+LOGERR NEAR PASCAL
+LogBreak(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+/*++
+
+Routine Description:
+
+ Call AsyncStop() to halt debuggee.
+
+Arguments:
+
+ lpsz - not used
+ fAppend - not used
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ CmdInsertInit();
+
+ AsyncStop();
+
+ return LOGERROR_NOERROR;
+} /* LogBreak() */
+
+
+LOGERR NEAR PASCAL
+LogDotHelp(
+ LPSTR lpsz
+ )
+{
+ int i;
+ CmdInsertInit();
+ for (i = 0; i < NDOTS; i++) {
+ CmdLogFmt("%s %s\r\n", DotTable[i].lpName, DotTable[i].lpDesc);
+ }
+ return LOGERROR_NOERROR;
+}
+
+
+LOGERR NEAR PASCAL
+LogDotCommand(
+ LPSTR lpsz
+ )
+{
+ int i;
+ int l;
+ LPPD lppd;
+ LPTD lptd;
+ BOOL fNoError = FALSE;
+ XOSD xosd = xosdUnknown;
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (!*lpsz) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ if (*lpsz == '?') {
+
+ LogDotHelp(lpsz + 1);
+ fNoError = TRUE;
+
+ } else if (_strnicmp(lpsz, "help", (size_t) 4) == 0) {
+
+ LogDotHelp(lpsz + 4);
+ fNoError = TRUE;
+
+ } else {
+
+ for (i = 0; i < NDOTS; i++) {
+ l = strlen(DotTable[i].lpName);
+ if (_strnicmp(lpsz, DotTable[i].lpName, l) == 0)
+ {
+ break;
+ }
+ }
+
+ if (i < NDOTS) {
+ return (*DotTable[i].lpfnHandler)(lpsz+l, DotTable[i].dwArg);
+ }
+ }
+
+ // Pass unrecognized commands and "?" or "help" to the EM:
+
+ lppd = LppdCur;
+ lptd = LptdCur;
+ if (!lppd || !lppd->hpid) {
+ lppd = LppdFirst;
+ lptd = NULL;
+ }
+ if (lppd && lppd->hpid) {
+ xosd = OSDIoctl(lppd->hpid,
+ lptd? lptd->htid : 0,
+ ioctlCustomCommand,
+ strlen(lpsz)+1,
+ (LPVOID)lpsz);
+ }
+
+ return (fNoError || xosd == xosdNone)? LOGERROR_NOERROR : LOGERROR_UNKNOWN;
+}
+
+LOGERR NEAR PASCAL
+LogOptions(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+/*++
+
+Routine Description:
+
+ .opt command
+
+Arguments:
+
+ lpsz - Supplies command line tail
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ int i;
+ int n;
+ char szToken[MAX_USER_LINE];
+
+ CmdInsertInit();
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (!*lpsz) {
+ for (i = 0; i < NOPTS; i++) {
+ (*OptionTable[i].lpfnHandler)(OptionTable[i].lpData,
+ OptionTable[i].cbSize,
+ szToken,
+ FALSE);
+ CmdLogFmt("%-10s\t\t%s\r\n", OptionTable[i].lpName, szToken);
+ }
+ return LOGERROR_NOERROR;
+ }
+
+ n = CPCopyToken(&lpsz, szToken);
+ lpsz = CPSkipWhitespace(lpsz);
+
+ for (i = 0; i < NOPTS; i++) {
+ if (_stricmp(OptionTable[i].lpName, szToken) == 0) {
+ break;
+ }
+ }
+
+ if (i >= NOPTS) {
+ CmdLogVar(ERR_Invalid_Option);
+ return LOGERROR_QUIET;
+ }
+
+ // special for help:
+ if (i == 0) {
+ (*OptionTable[i].lpfnHandler)(OptionTable[i].lpData,
+ OptionTable[i].cbSize,
+ lpsz,
+ TRUE);
+ return LOGERROR_NOERROR;
+
+ } else if (!*lpsz) {
+ (*OptionTable[i].lpfnHandler)(OptionTable[i].lpData,
+ OptionTable[i].cbSize,
+ szToken,
+ FALSE);
+ CmdLogFmt("%-10s %s\r\n", OptionTable[i].lpName, szToken);
+ return LOGERROR_NOERROR;
+ } else if ((*OptionTable[i].lpfnHandler)(OptionTable[i].lpData,
+ OptionTable[i].cbSize,
+ lpsz,
+ TRUE)) {
+ return LOGERROR_NOERROR;
+ } else {
+ return LOGERROR_QUIET;
+ }
+}
+
+
+LOGERR NEAR PASCAL
+LogRadix(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function is used to change the display and input radix for
+ the system.
+
+Arguments:
+
+ lpsz - String with the command
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ int err;
+ int cch;
+ int i;
+
+ CmdInsertInit();
+
+ /*
+ ** Check for no arguement
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz == 0) {
+ CmdLogFmt("%d\r\n", radix);
+ return LOGERROR_NOERROR;
+ }
+
+ /*
+ ** An argument -- must be a number in base 10
+ */
+
+ i = (int) CPGetInt(lpsz, &err, &cch);
+ if (err) {
+ return LOGERROR_UNKNOWN;
+ }
+ if (i != 8 && i != 10 && i != 16) {
+ CmdLogVar(ERR_Radix_Invalid);
+ return LOGERROR_QUIET;
+ }
+
+ UpdateRadix(i);
+
+ return LOGERROR_NOERROR;
+} /* LogRadix() */
+
+
+LOGERR NEAR PASCAL
+LogSetErrorLevel(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Set error reporting and break levels for RIPs.
+
+Arguments:
+
+ lpsz - Supplies tail of command, after "se"
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ int i;
+ char chCmd;
+ int err, cch;
+
+ CmdInsertInit();
+
+ chCmd = *lpsz++;
+
+ if (!strchr("bBwW", chCmd)) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ /*
+ ** Check for no argument
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz == 0) {
+ CmdLogVar(DBG_Notify_Break_Levels, ulRipNotifyLevel, ulRipBreakLevel);
+ return LOGERROR_NOERROR;
+ }
+
+ /*
+ ** An argument -- must be a number in base 10
+ */
+
+ i = (int) CPGetInt(lpsz, &err, &cch);
+ if (err) {
+ return LOGERROR_UNKNOWN;
+ }
+ if (i < 0 || i > 3) {
+ CmdLogVar(ERR_Error_Level_Invalid);
+ return LOGERROR_QUIET;
+ }
+
+ if (chCmd == 'w' || chCmd == 'W') {
+ ulRipNotifyLevel = (ULONG)i;
+ } else {
+ ulRipBreakLevel = (ULONG)i;
+ if ((ULONG)i > ulRipNotifyLevel) {
+ ulRipNotifyLevel = (ULONG)i;
+ }
+ }
+
+ return LOGERROR_NOERROR;
+} /* LogSetErrorLevel() */
+
+
+LOGERR NEAR PASCAL
+LogReload(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ LPPD lppd;
+ LPTD lptd;
+ XOSD xosd = xosdUnknown;
+ MSG msg;
+ PIOCTLGENERIC pig;
+
+
+ IsKdCmdAllowed();
+
+ lppd = LppdCur;
+ lptd = LptdCur;
+ if (!lppd || !lppd->hpid) {
+ lppd = LppdFirst;
+ lptd = NULL;
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (lppd && lppd->hpid) {
+ pig = (PIOCTLGENERIC)malloc(strlen(lpsz) + 1 + sizeof(IOCTLGENERIC));
+ if (!pig) {
+ return FALSE;
+ }
+ pig->ioctlSubType = IG_RELOAD;
+ pig->length = strlen(lpsz) + 1;
+ strcpy((LPSTR)pig->data, lpsz);
+ xosd = OSDIoctl( lppd->hpid,
+ NULL,
+ ioctlGeneric,
+ strlen(lpsz) + 1 + sizeof(IOCTLGENERIC),
+ (LPV)pig );
+ free( pig );
+ }
+
+ if (xosd == xosdNone) {
+ while (GetMessage( &msg, NULL, 0, 0 )) {
+ ProcessQCQPMessage( &msg );
+ if (WaitForSingleObject( hEventIoctl, 0 ) == WAIT_OBJECT_0) {
+ ResetEvent( hEventIoctl );
+ break;
+ }
+ }
+
+ UpdateDebuggerState( UPDATE_CONTEXT );
+ }
+
+ return (xosd == xosdNone) ? LOGERROR_NOERROR : LOGERROR_UNKNOWN;
+}
+
+
+
+LOGERR NEAR PASCAL
+LogList(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+
+/*++
+
+Routine Description:
+
+ This routine prints mixed mode source & disassembly for a
+ address that is computed from the expression in the string
+ passed in. If the string is null then the list starts where
+ the last one left off.
+
+ Wesley Witt (wesw) - 29-May-1994
+
+Arguments:
+
+ lpsz - Supplies the expression
+ dwUnused - as it says its unused
+
+Return Value:
+
+ Log error code.
+
+ --*/
+
+{
+ #define MAX_LINES 10
+ INT cch;
+ static ADDR addr = {0};
+ ADDR addrT;
+ ADDR addrN;
+ SDI sds;
+ LPSTR p;
+ CHAR buf[256];
+ LPSTR lpch;
+ INT cb;
+ DWORD i;
+ BOOL SourceFound;
+ CHAR SrcFname[MAX_PATH];
+ CHAR SrcFnameN[MAX_PATH];
+ WORD lineno;
+ DWORD dwLineno;
+ DWORD lastLineno = 0;
+ INT doc;
+ LPLINEREC lr;
+ LPBLOCKDEF bd;
+ SHOFF cbLn;
+ SHOFF dbLn;
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ //
+ // get the address for the user's expression
+ //
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz) {
+ if (!CPGetAddress( lpsz, &cch, &addr, radix, &CxfIp, fCaseSensitive, FALSE ) == 0) {
+ CmdLogVar( ERR_AddrExpr_Invalid );
+ return LOGERROR_QUIET;
+ }
+ } else if (addr.addr.off == 0) {
+ addr = CxfIp.cxt.addr;
+ }
+
+ for (i=0; i<MAX_LINES; i++) {
+
+ //
+ // create a fixedup and unfixedup address
+ //
+ addrT = addr;
+ SYUnFixupAddr(&addr);
+ SYFixupAddr(&addrT);
+
+ //
+ // assume we cannot find any source
+ //
+ SourceFound = FALSE;
+
+ //
+ // locate the source file and line number for this address
+ //
+ if (!GetSourceFromAddress( &addr, SrcFname, sizeof(SrcFname), &lineno )) {
+ goto disasm;
+ }
+
+ //
+ // locate the document for the found source file name
+ //
+ if (!FindDoc( SrcFname, &doc, TRUE )) {
+ //
+ // the document was not found so lets map it in and
+ // create a document record
+ //
+ if (SrcMapSourceFilename( SrcFname, sizeof(SrcFname),
+ SRC_MAP_OPEN, FindDoc1 ) < 0) {
+ goto disasm;
+ }
+
+ //
+ // locate the document for the found source file name
+ //
+ if (!FindDoc( SrcFname, &doc, TRUE )) {
+ goto disasm;
+ }
+ }
+
+ //
+ // adjust the line number and save it away in a dword
+ //
+ lineno = min(max(1, (int)lineno), (int)Docs[doc].NbLines) - 1;
+ dwLineno = lineno;
+ if (!FirstLine( doc, &lr, &dwLineno, &bd )) {
+ goto disasm;
+ }
+
+ //
+ // this call is used only to get the code size for the
+ // current line number
+ //
+ if (!SLLineFromAddr ( &addr, &lineno, &cbLn, &dbLn )) {
+ goto disasm;
+ }
+
+ //
+ // print the source text
+ //
+ CmdLogFmt( "%4d: %s\n", dwLineno, lr->Text );
+
+ //
+ // set the source found flag to success
+ //
+ SourceFound = TRUE;
+
+disasm:
+ //
+ // this is where the code is unassembled
+ // if there was no source found the this loop will
+ // unassemble one instrustion and move on to the next address
+ //
+
+ //
+ // set the disasm options to the user's settings
+ //
+ sds.dop = (runDebugParams.DisAsmOpts & ~(0x800)) | dopAddr | dopOpcode | dopOperands;
+
+ //
+ // use the current source address
+ //
+ sds.addr = addrT;
+
+ do {
+ //
+ // call the disassm routine in the EM
+ //
+ if (OSDUnassemble( LppdCur->hpid, LptdCur->htid, &sds ) != xosdNone) {
+ CmdLogFmt( "Could not unassemble code for address 0x%08x\n", sds.addr.addr.off );
+ return LOGERROR_QUIET;
+ }
+
+ //
+ // format the assm code
+ //
+ p = &buf[0];
+ *p = 0;
+
+ if (sds.ichAddr != -1) {
+ sprintf(p, "%s ", &sds.lpch[sds.ichAddr]);
+ p += strlen(p);
+ }
+ cb = strlen(&sds.lpch[sds.ichAddr]) + 2;
+
+ if (sds.ichBytes != -1) {
+ lpch = sds.lpch + sds.ichBytes;
+ while (strlen(lpch) > 16) {
+ sprintf(p, "%16.16s\r\n%*s", lpch, cb, " ");
+ p += strlen(p);
+ lpch += 16;
+ }
+ cb = 17 - strlen(lpch);
+ sprintf(p, "%-17s", lpch);
+ p += strlen(p);
+ }
+
+ sprintf(p, "%-12s ", &sds.lpch[sds.ichOpcode]);
+ p += strlen(p);
+
+ if (sds.ichOperands != -1) {
+ sprintf(p, "%-25s ", &sds.lpch[sds.ichOperands]);
+ p += strlen(p);
+ } else if (sds.ichComment != -1) {
+ sprintf(p, "%25s ", " ");
+ p += strlen(p);
+ }
+
+ if (sds.ichComment != -1) {
+ sprintf(p, "%s", &sds.lpch[sds.ichComment]);
+ p += strlen(p);
+ }
+
+ //
+ // print the formatted code
+ //
+ CmdLogFmt( "%s\r\n", buf );
+
+ //
+ // if there was no source found then bail out
+ //
+ if (!SourceFound) {
+ break;
+ }
+ } while (sds.addr.addr.off <= addrT.addr.off + cbLn);
+
+ //
+ // setup for the next source line
+ //
+ addr = sds.addr;
+
+ //
+ // this causes the dead source, ie source that did not generate
+ // any code, to be printed.
+ //
+ if (i < MAX_LINES-1) {
+ //
+ // start at the last ending address
+ //
+ addrN = addr;
+
+ //
+ // the dead source is printed when the source file name for the
+ // next address is the same as the last address and ...
+ //
+ if ((GetSourceFromAddress( &addrN, SrcFnameN, sizeof(SrcFnameN), &lineno )) &&
+ (_stricmp(SrcFname, SrcFnameN) == 0)) {
+ //
+ // the line number is more that one greater
+ //
+ lineno = min(max(1, (int)lineno), (int)Docs[doc].NbLines) - 1;
+ if (lineno > dwLineno + 1) {
+ //
+ // enumerate all the dead source lines and print them
+ //
+ while ((DWORD)lineno > dwLineno) {
+ if (NextLine( doc, &lr, &dwLineno, &bd )) {
+ CmdLogFmt( "%4d: %s\n", dwLineno, lr->Text );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // return success
+ //
+ return LOGERROR_NOERROR;
+}
+
+BOOL
+NotifyDmOfProcessorChange(
+ DWORD Processor
+ )
+{
+ XOSD xosd = xosdUnknown;
+ PIOCTLGENERIC pig;
+
+
+ if (!runDebugParams.fKernelDebugger) {
+ return FALSE;
+ }
+
+ pig = (PIOCTLGENERIC)malloc(sizeof(ULONG) + sizeof(IOCTLGENERIC));
+ if (!pig) {
+ return FALSE;
+ }
+ pig->ioctlSubType = IG_CHANGE_PROC;
+ pig->length = sizeof(ULONG);
+ ((PULONG)pig->data)[0] = Processor;
+ xosd = OSDIoctl(
+ LppdCur->hpid,
+ NULL,
+ ioctlGeneric,
+ pig->length + sizeof(IOCTLGENERIC),
+ (LPV)pig
+ );
+ free( pig );
+ return xosd == xosdNone;
+}
diff --git a/private/windbg/windbg/cmdexec1.c b/private/windbg/windbg/cmdexec1.c
new file mode 100644
index 000000000..72ba3dd4c
--- /dev/null
+++ b/private/windbg/windbg/cmdexec1.c
@@ -0,0 +1,4127 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cmdexec1.c
+
+Abstract:
+
+ This file contains the code for the execution related commands in
+ the command window.
+
+Author:
+
+ Kent Forschmiedt (a-kentf) 20-Jul-92
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include "dbugexcp.h"
+
+#ifdef DBCS
+#include <mbstring.h>
+#define strchr _mbschr
+#define strcspn _mbscspn
+#endif
+
+/************************** Data declaration *************************/
+
+/****** Publics ********/
+
+extern LPPD LppdCommand;
+extern LPTD LptdCommand;
+
+extern BOOL FSetLptd; // Was thread specified
+extern BOOL FSetLppd; // Was process specified
+
+extern INT BpCmdPid;
+extern INT BpCmdTid;
+
+extern EXCEPTION_LIST *DefaultExceptionList;
+
+extern ULONG ulPseudo[];
+
+/****** Locals ********/
+
+
+/****** Externs from ??? *******/
+
+extern LPSHF Lpshf; // vector table for symbol handler
+extern CXF CxfIp;
+extern EI Ei;
+
+
+LPSTR ParseContext_FileName(LPSTR lpContext);
+
+void LogSx( EXCEPTION_LIST *eList );
+
+
+/************************** Code *************************/
+/****************************************************************************
+ *
+ * Helper and common functions
+ *
+ ****************************************************************************/
+
+BOOL FAR PASCAL
+GoOK(
+ LPPD lppd,
+ LPTD lptd
+ )
+/*++
+
+Routine Description:
+
+ Determine whether a thread is GOable
+
+Arguments:
+
+ lppd - Supplies pointer to process struct
+ lptd - Supplies pointer to thread struct
+
+Return Value:
+
+ TRUE if runnable, FALSE if not.
+
+--*/
+{
+ if (!lppd || !lptd) {
+ return FALSE;
+ }
+ if (lppd->fFrozen) {
+ return FALSE;
+ }
+
+ switch (lppd->pstate) {
+ case psNoProgLoaded:
+ case psPreRunning:
+ case psExited:
+ case psDestroyed:
+ return FALSE;
+
+ case psRunning:
+ case psStopped:
+ break;
+ }
+
+ switch (lptd->tstate) {
+ case tsPreRunning:
+ case tsStopped:
+ case tsRipped:
+ case tsExited:
+ break;
+
+ case tsRunning:
+ case tsException1:
+ case tsException2:
+ return FALSE;
+ }
+
+ return TRUE;
+} /* GoOK() */
+
+BOOL FAR PASCAL
+GoExceptOK(
+ LPPD lppd,
+ LPTD lptd
+ )
+/*++
+
+Routine Description:
+
+ Determine whether a thread is in an exception,
+ and can therefore GoHandled or GoUnHandled.
+
+Arguments:
+
+ lppd - Supplies pointer to process struct
+ lptd - Supplies pointer to thread struct
+
+Return Value:
+
+ TRUE if runnable, FALSE if not.
+
+--*/
+{
+ if (!lppd || !lptd) {
+ return FALSE;
+ }
+ if (lppd->fFrozen) {
+ return FALSE;
+ }
+
+ switch (lppd->pstate) {
+ case psNoProgLoaded:
+ case psPreRunning:
+ case psExited:
+ case psDestroyed:
+ return FALSE;
+
+ case psRunning:
+ case psStopped:
+ break;
+ }
+
+ switch (lptd->tstate) {
+ case tsPreRunning:
+ case tsStopped:
+ case tsRipped:
+ case tsExited:
+ case tsRunning:
+ break;
+
+ case tsException1:
+ case tsException2:
+ return TRUE;
+ }
+
+ return FALSE;
+} /* GoExceptOK() */
+
+
+BOOL FAR PASCAL
+StepOK(
+ LPPD lppd,
+ LPTD lptd
+ )
+/*++
+
+Routine Description:
+
+ Determine whether a thread is steppable.
+ This will return TRUE for frozen threads, so caller will
+ have to deal with that specially.
+
+Arguments:
+
+ lppd - Supplies pointer to process structure
+ lptd - Supplies pointer to thread structure
+
+Return Value:
+
+ TRUE if steppable, FALSE if not
+
+--*/
+{
+ if (!lppd || !lptd) {
+ return FALSE;
+ }
+
+ if (lppd->fFrozen || lptd->fFrozen) {
+ return FALSE;
+ }
+
+ switch (lppd->pstate) {
+ case psNoProgLoaded:
+ case psPreRunning:
+ case psExited:
+ case psDestroyed:
+ return FALSE;
+
+ case psRunning:
+ case psStopped:
+ break;
+ }
+
+ switch (lptd->tstate) {
+ case tsPreRunning:
+ case tsStopped:
+ break;
+
+ case tsRunning:
+ case tsException1:
+ case tsException2:
+ case tsRipped:
+ case tsExited:
+ return FALSE;
+ }
+
+ return TRUE;
+} /* StepOK() */
+
+
+void NEAR PASCAL
+NoRunExcuse(
+ LPPD lppd,
+ LPTD lptd
+ )
+/*++
+
+Routine Description:
+
+ Print a message about why we can't run or step
+
+Arguments:
+
+ lppd - Supplies pointer to process that isn't runnable
+ lptd - Supplies pointer to thread that isn't runnable
+
+Return Value:
+
+ None
+
+--*/
+{
+ if (!lppd) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ return;
+ }
+
+ if (lppd->fFrozen) {
+ CmdLogVar(ERR_Cant_Run_Frozen_Proc);
+ return;
+ }
+
+ switch (lppd->pstate) {
+
+ case psNoProgLoaded:
+ CmdLogVar(ERR_Debuggee_Not_Loaded);
+ break;
+ case psExited:
+ case psDestroyed:
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ break;
+ case psPreRunning:
+ CmdLogVar(ERR_Debuggee_Starting);
+ break;
+
+ default:
+ Assert(lptd);
+ if (!lptd) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ return;
+ }
+ if (lptd->fFrozen) {
+ CmdLogVar(ERR_Cant_Step_Frozen);
+ return;
+ }
+ switch (lptd->tstate) {
+ case tsRunning:
+ CmdLogVar(ERR_Already_Running);
+ break;
+ case tsException1:
+ case tsException2:
+ CmdLogVar(ERR_Cant_Go_Exception);
+ break;
+ case tsRipped:
+ CmdLogVar(ERR_Cant_Step_Rip);
+ break;
+ case tsExited:
+ CmdLogVar(ERR_Thread_Exited);
+ break;
+ default:
+ CmdLogVar(ERR_Command_Error);
+ break;
+ }
+ }
+
+ return;
+} /* NoRunExcuse() */
+
+SHFLAG PASCAL
+PHCmpAlwaysMatch(
+ LPSSTR lpsstr,
+ LPV lpv,
+ LSZ lpb,
+ SHFLAG fcase
+ )
+/*++
+
+Routine Description:
+
+ Compare function for PHFindNameInPublics which always succeeds.
+
+Arguments:
+
+ lpsstr
+ lpv
+ lpb
+ fcase
+
+Return Value:
+
+ Always 0
+
+--*/
+{
+ return 0;
+}
+
+
+void
+ThreadStat(
+ LPPD lppd
+ )
+/*++
+
+Routine Description:
+
+ Prints status for all threads in a process
+
+Arguments:
+
+ lppd - Supplies process to look at
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LPTD lptd;
+ LPTD lptdSave;
+ TST tst;
+ XOSD xosd;
+
+ if (lppd->lptdList == NULL) {
+ CmdLogVar(ERR_No_Threads);
+ return;
+ }
+
+ for (lptd = lppd->lptdList; lptd != NULL; lptd = lptd->lptdNext) {
+
+ xosd = OSDGetThreadStatus(lppd->hpid, lptd->htid, &tst);
+
+ if (xosd != xosdNone) {
+ CmdLogFmt("No status for thread %d\r\n", lptd->itid);
+ } else {
+ CmdLogFmt("%s%2d %s %s %s",
+ (lptd == LptdCur)? "*" : " ",
+ lptd->itid,
+ tst.rgchThreadID,
+ tst.rgchState,
+ tst.rgchPriority );
+
+ if (tst.dwTeb) {
+ CmdLogFmt(" 0x%08x", tst.dwTeb );
+ }
+
+ lptdSave = LptdCur;
+ LptdCur = lptd;
+ CmdLogFmt( " %s", GetLastFrameFuncName() );
+ LptdCur = lptdSave;
+
+ CmdLogFmt( "\r\n" );
+ }
+ }
+}
+
+
+static BOOL
+makemask(
+ char ** ppch,
+ WORD * pmask
+ )
+{
+ WORD mask = 0;
+
+ Assert ( ppch != NULL );
+ Assert ( *ppch != NULL );
+
+ if (!**ppch || **ppch == ' ' || **ppch == '\t') {
+ mask = HSYMR_lexical |
+ HSYMR_function |
+ HSYMR_module |
+ HSYMR_exe |
+ HSYMR_public |
+ HSYMR_global;
+ }
+
+ while ( **ppch != '\0' && **ppch != ' ' && **ppch != '\t' ) {
+ BOOL fAdd = TRUE;
+
+ fAdd = (BOOL)( *( *ppch + 1 ) != '-' );
+
+ switch ( **ppch ) {
+
+ case 'l':
+ case 'L':
+ if( fAdd ) {
+ mask |= HSYMR_lexical;
+ } else {
+ mask &= ~HSYMR_lexical;
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ if( fAdd ) {
+ mask |= HSYMR_function;
+ } else {
+ mask &= ~HSYMR_function;
+ }
+ break;
+
+ case 'c':
+ case 'C':
+ if ( fAdd ) {
+ mask |= HSYMR_class;
+ } else {
+ mask &= ~HSYMR_class;
+ }
+ break;
+
+ case 'm':
+ case 'M':
+ if( fAdd ) {
+ mask |= HSYMR_module;
+ } else {
+ mask &= ~HSYMR_module;
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ if( fAdd ) {
+ mask |= HSYMR_exe;
+ } else {
+ mask &= ~HSYMR_exe;
+ }
+ break;
+
+ case 'p':
+ case 'P':
+ if( fAdd ) {
+ mask |= HSYMR_public;
+ } else {
+ mask &= ~HSYMR_public;
+ }
+ break;
+
+ case 'g':
+ case 'G':
+ if( fAdd ) {
+ mask |= HSYMR_global;
+ } else {
+ mask &= ~HSYMR_global;
+ }
+ break;
+
+ case '*':
+ if( fAdd ) {
+ mask = HSYMR_allscopes;
+ } else {
+ mask = 0x0000;
+ }
+ break;
+
+ default:
+
+ // invalid syntax
+ return FALSE;
+ }
+
+ (*ppch)++;
+
+ if( (**ppch == '+') || (**ppch == '-') ) {
+ (*ppch)++;
+ }
+ }
+
+ *pmask = mask;
+ return TRUE;
+}
+
+
+/*****************************************************************************
+ *
+ * Command Entry Points
+ *
+ *****************************************************************************/
+
+LOGERR NEAR PASCAL
+LogAttach(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ LONG pid = 0;
+ HANDLE hEvent;
+ LPSTR lpsz1;
+ char szError[300];
+ BOOL fReconnect = FALSE;
+
+ extern LPSTR LpszCommandLine;
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ /*
+ ** Check for no argument
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz == 0) {
+
+ fReconnect = TRUE;
+
+ } else {
+
+ lpsz1 = CPszToken(lpsz, "");
+ if (!lpsz1) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ if (CPGetCastNbr(lpsz, T_LONG, radix, fCaseSensitive,
+ &CxfIp, (LPSTR)&pid, szError) != EENOERROR) {
+ CmdLogFmt("%s\r\n", szError);
+ return LOGERROR_QUIET;
+ }
+
+ lpsz = lpsz1;
+
+ }
+
+ hEvent = (HANDLE)0;
+
+ if (!AttachDebuggee((DWORD)pid, hEvent)) {
+
+ CmdLogVar(ERR_Attach_Failed);
+ return LOGERROR_QUIET;
+
+ }
+
+ //
+ // AttachDebuggee() guarantees that the proc
+ // is finished loading on return.
+ //
+
+ if (runDebugParams.fAttachGo) {
+ LptdCur->fGoOnTerm = TRUE;
+ Go();
+ CmdLogVar(DBG_Attach_Running);
+ } else {
+ CmdLogVar(DBG_Attach_Stopped);
+ if ((!LptdCur->tstate & tsException1) && (!LptdCur->tstate & tsException2)) {
+ SetPTState(-1,tsStopped);
+ }
+ UpdateDebuggerState(UPDATE_WINDOWS);
+ }
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogStart(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ char *av[2];
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz == 0) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ av[0] = lpsz;
+ av[1] = NULL;
+ if (!RestartDebuggee(1, av)) {
+ CmdLogVar(ERR_Start_Failed);
+ return LOGERROR_QUIET;
+ }
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogKill(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ LPPD lppd;
+ XOSD xosd;
+ int err;
+ int cch;
+ int i;
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ /*
+ ** Check for no argument
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz == 0) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ /*
+ ** An argument -- must be a number in base 10
+ */
+
+ i = (int) CPGetInt(lpsz, &err, &cch);
+ if (err) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ lppd = ValidLppdOfIpid(i);
+ if (!lppd) {
+ CmdLogVar(ERR_Process_Not_Exist);
+ return LOGERROR_QUIET;
+ }
+
+ xosd = OSDProgramFree(lppd->hpid);
+
+ if (xosd != xosdNone) {
+ CmdLogVar(ERR_Kill_Failed);
+ return LOGERROR_QUIET;
+ }
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogConnect(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ ConnectDebugger();
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogDisconnect(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ XOSD xosd;
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ if (!LppdFirst) {
+ CmdLogFmt("not connected\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ CmdLogFmt("Connection to remote has been broken\r\n" );
+ CmdLogFmt("Stopped debugging\r\n" );
+
+ if (runDebugParams.fDisconnectOnExit && LppdCur && LptdCur) {
+ xosd = OSDDisconnect( LppdCur->hpid, LptdCur->htid );
+ } else {
+ xosd = OSDDisconnect( LppdFirst->hpid, NULL );
+ }
+
+ DisconnectDebuggee();
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogTitle(
+ LPSTR lpsz,
+ DWORD dwUnused
+ )
+{
+ CmdInsertInit();
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ strcpy( runDebugParams.szTitle, lpsz );
+
+ SetWindowText( hwndFrame, lpsz );
+
+ CmdLogFmt("Window title has been changed to %s\r\n", lpsz );
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogRemote(
+ LPSTR lpsz
+ )
+{
+ BOOL fAppend = FALSE;
+
+ CmdInsertInit();
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (((*lpsz == '/') || (*lpsz == '-')) && (tolower(*(lpsz+1)) == 'a')) {
+ lpsz += 2;
+ lpsz = CPSkipWhitespace(lpsz);
+ fAppend = TRUE;
+ }
+
+ StartRemoteServer( lpsz, fAppend );
+
+ return LOGERROR_NOERROR;
+}
+
+LOGERR NEAR PASCAL
+LogBPSet(
+ BOOL fDataBp,
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This routine is used by the command processor to add a breakpoint
+ to the set of breakpoints. The breakpoint will be added and, if
+ the debugger is running, committed.
+
+Arguments:
+
+ fDataBp - TRUE if the command is BA command
+ FALSE if the command is a BP command
+
+ lpsz - Supplies string containing the breakpoint command to be added
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ BPSTATUS bpstatus;
+ HBPT hbpt;
+ int iBp = -1;
+ int err, nRet;
+ int cch;
+ EESTATUS eest;
+ ADDR addr;
+ CHAR BaSize;
+ CHAR BaType;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ char szStr[MAX_USER_LINE], szC[MAX_USER_LINE];
+ LPSTR lpsz1, lpFile;
+ BOOL bMap = FALSE;
+
+ CmdInsertInit();
+
+ IsKdCmdAllowed();
+
+ PDWildInvalid();
+ PreRunInvalid();
+
+ if (*CPSkipWhitespace(lpsz) == 0) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ if (fDataBp) {
+ lpsz = CPSkipWhitespace( lpsz );
+ switch (tolower(*lpsz)) {
+ case 'e':
+ case 'r':
+ case 'w':
+ BaType = *lpsz;
+ break;
+
+ default:
+ CmdLogFmt( "BA command missing type [e|r|w]\n" );
+ return LOGERROR_QUIET;
+ }
+ lpsz++;
+ lpsz = CPSkipWhitespace( lpsz );
+ switch (*lpsz) {
+ case '1':
+ case '2':
+ case '4':
+ BaSize = *lpsz;
+ break;
+
+ default:
+ CmdLogFmt( "BA command missing size [1|2|4]\n" );
+ return LOGERROR_QUIET;
+ }
+ lpsz++;
+
+ eest = CPGetAddress(
+ lpsz,
+ &cch,
+ &addr,
+ radix,
+ &CxfIp,
+ fCaseSensitive,
+ runDebugParams.fMasmEval );
+
+ if (eest != EENOERROR) {
+ CmdLogFmt( "Invalid address\n" );
+ return LOGERROR_QUIET;
+ }
+
+ SYFixupAddr(&addr);
+
+ sprintf( szStr, "=\"0x%08x\" /R%c /A%c ", addr.addr.off, BaSize, BaType );
+
+ if (FSetLppd) {
+ sprintf(szStr + strlen(szStr), " /H%d", BpCmdPid);
+ }
+
+ if (FSetLptd && BpCmdTid != -1) {
+ sprintf(szStr + strlen(szStr), " /T%d", BpCmdTid);
+ }
+
+ bpstatus = BPParse(
+ &hbpt,
+ szStr,
+ NULL,
+ NULL,
+ LppdCur ? LppdCur->hpid : 0
+ );
+
+ } else {
+
+ _fstrcpy(szStr, lpsz);
+ lpsz = szStr;
+
+ if (FSetLppd) {
+ sprintf(szStr + strlen(szStr), " /H%d", BpCmdPid);
+ }
+
+ if (FSetLptd && BpCmdTid != -1) {
+ sprintf(szStr + strlen(szStr), " /T%d", BpCmdTid);
+ }
+
+ if (isdigit(*lpsz)) {
+ iBp = CPGetInt(lpsz, &err, &cch);
+ lpsz += cch;
+ if (BPHbptFromI(&hbpt, iBp) != BPNoMatch) {
+ CmdLogVar(ERR_Breakpoint_Already_Used, iBp);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+
+ //
+ // require space after bp[n]
+ //
+ lpsz1 = CPSkipWhitespace(lpsz);
+ if (lpsz1 == lpsz) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ if (!DebuggeeActive()) {
+ //try to parse a filename out of the context set
+ strcpy (szC, lpsz1);
+ lpFile = ParseContext_FileName(szC);
+
+ if (lpFile != (LPSTR)NULL) {
+ bMap = FALSE;
+ nRet = SrcMapSourceFilename (lpFile,_MAX_PATH,
+ SRC_MAP_OPEN, NULL);
+
+ if ((nRet >= 1) && (nRet <= 2)) {
+ bMap = TRUE;
+ }
+ }
+ }
+
+ bpstatus = BPParse(
+ &hbpt,
+ lpsz1,
+ NULL,
+ (bMap == TRUE) ? lpFile : NULL,
+ LppdCur ? LppdCur->hpid : 0
+ );
+
+ }
+
+ if (bpstatus != BPNOERROR) {
+
+ //
+ // NOTENOTE a-kentf we can do better than "command error" here
+ //
+ rVal = LOGERROR_UNKNOWN;
+
+ } else if ( BPAddToList(hbpt, iBp) != BPNOERROR ) {
+
+ //
+ // NOTENOTE a-kentf here, too
+ //
+ rVal = LOGERROR_UNKNOWN;
+
+ } else {
+
+ if (DebuggeeActive() ) {
+
+ BPSTATUS Status;
+
+ Status = BPBindHbpt( hbpt, NULL );
+
+ if ( LppdCur != NULL ) {
+ if ( Status == BPCancel ) {
+ CmdLogVar(ERR_Breakpoint_Not_Set);
+ } else if ( Status != BPNOERROR ) {
+ CmdLogVar(ERR_Breakpoint_Not_Instantiated);
+ }
+ }
+ }
+ ChangeDebuggerState();
+ Dbg(BPCommit() == BPNOERROR);
+ }
+
+
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ return rVal;
+} /* LogBPSet() */
+
+
+LPSTR
+ParseContext_FileName(
+ LPSTR lpContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is used by the command processor to parse the context
+ set for filenames
+
+Arguments:
+
+ lpContext - Supplies string containing the context set to be be parsed
+
+Return Value:
+
+ LPSTR or (NULL)
+
+--*/
+
+{
+ LPSTR lpBegin;
+ LPSTR lpEnd;
+ LPSTR lpTarget = (LPSTR)NULL;
+
+ //
+ // Skip module
+ //
+ if ( lpBegin = strchr( lpContext, ',' ) ) {
+
+ //
+ // Skip blanks
+ //
+ lpBegin++;
+ lpBegin += strspn( lpBegin, " \t" );
+
+ //
+ // Get end of filename
+ //
+ lpEnd = lpBegin + strcspn( lpBegin, ",} " );
+ *lpEnd = '\0';
+
+ if ( lpEnd > lpBegin ) {
+ lpTarget = lpBegin;
+ }
+ }
+
+ return lpTarget;
+}
+
+
+
+LOGERR NEAR PASCAL
+LogBPList(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This routine will display a list of the breakpoints in
+ the command window.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ HBPT hbpt = 0;
+ HPID hpid;
+ char rgch[256];
+
+ CmdInsertInit();
+ PreRunInvalid();
+
+ Dbg(BPNextHbpt(&hbpt, bptNext) == BPNOERROR);
+
+ if (hbpt == NULL) {
+ /*
+ ** No breakpoints to list
+ */
+
+ // not really an error
+ CmdLogVar(ERR_No_Breakpoints);
+
+ } else {
+ for ( ; hbpt != NULL; BPNextHbpt( &hbpt, bptNext )) {
+
+ if (FSetLppd && LppdCommand && LppdCommand != (LPPD)-1) {
+ BPGetHpid(hbpt, &hpid);
+ if (hpid != LppdCommand->hpid) {
+ continue;
+ }
+ }
+
+ Dbg( BPFormatHbpt( hbpt, rgch, sizeof(rgch), BPFCF_ITEM_COUNT) == BPNOERROR );
+ CmdLogFmt("%s\r\n", rgch );
+ }
+ }
+
+ return LOGERROR_NOERROR;
+} /* LogBPList() */
+
+
+LOGERR NEAR PASCAL
+LogBPChange(
+ LPSTR lpszArgs,
+ int iAction
+ )
+/*++
+
+Routine Description:
+
+ This function will go through the set of arguments looking for
+ a set of breakpoint numbers (or asterisk) and perform the action
+ on each of the requested breakpoints.
+
+Arguments:
+
+ lpszArgs - Supplies string containing the set of breakpoints to change
+ iAction - Supplies which action to perform - Enable, Disable, Delete
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ HBPT hbpt;
+ HBPT hbptN;
+ int i, j;
+ int err;
+ int cb;
+ UINT ipid;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ BPSTATUS Status;
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+ PreRunInvalid();
+
+ lpszArgs = CPSkipWhitespace(lpszArgs);
+
+ /*
+ ** There are two possible sets of values at this point. The first
+ ** is an asterisk ('*'), the second is a number or set of whitespace
+ ** separated numbers.
+ */
+
+ if (*lpszArgs == '\0') {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ if (*lpszArgs == '*') {
+ if (*CPSkipWhitespace(lpszArgs+1)) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ Dbg( BPNextHbpt(&hbpt, bptFirst) == BPNOERROR);
+ for ( ; hbpt != NULL; hbpt = hbptN) {
+
+ hbptN = hbpt;
+ Dbg( BPNextHbpt( &hbptN, bptNext ) == BPNOERROR);
+
+ if (LppdCommand && LppdCommand != (LPPD)-1) {
+ BPGetIpid(hbpt, &ipid);
+ if (LppdCommand->ipid != ipid) {
+ continue;
+ }
+ }
+
+ switch ( iAction ) {
+ case LOG_BP_DISABLE:
+ BPDisable( hbpt );
+ break;
+
+ case LOG_BP_ENABLE:
+ Status = BPEnable( hbpt );
+ if ( Status != BPNOERROR ) {
+ CmdLogVar(ERR_Breakpoint_Not_Instantiated);
+ }
+ break;
+
+ case LOG_BP_CLEAR:
+ BPDelete( hbpt );
+ break;
+ }
+ }
+ } else {
+ while ( *(lpszArgs = CPSkipWhitespace(lpszArgs)) ) {
+
+ i = (int) CPGetInt(lpszArgs, &err, &cb);
+ if (err) {
+ BPUnCommit();
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ lpszArgs = CPSkipWhitespace(lpszArgs + cb);
+ j = i;
+ if (*lpszArgs == '-') {
+ j = CPGetInt((lpszArgs = CPSkipWhitespace(lpszArgs+1)), &err, &cb);
+ if (err) {
+ BPUnCommit();
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ lpszArgs = CPSkipWhitespace(lpszArgs + cb);
+ }
+
+ if (*lpszArgs == ',') {
+ lpszArgs++;
+ }
+
+ for ( ; i <= j; i++) {
+ err = BPHbptFromI( &hbpt, i );
+ if (err != BPNOERROR) {
+ CmdLogVar(ERR_Breakpoint_Not_Exist, i);
+ } else {
+ switch ( iAction ) {
+ case LOG_BP_DISABLE:
+ BPDisable( hbpt );
+ break;
+
+ case LOG_BP_ENABLE:
+ Status = BPEnable( hbpt );
+ if ( Status != BPNOERROR ) {
+ CmdLogVar(ERR_Breakpoint_Not_Instantiated);
+ }
+ break;
+
+ case LOG_BP_CLEAR:
+ BPDelete( hbpt );
+ break;
+ }
+ }
+ }
+ }
+ }
+ ChangeDebuggerState();
+ BPCommit();
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+} /* LogBPChange() */
+
+
+LOGERR NEAR PASCAL
+LogEvaluate(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function will take a string, evalute it and display either
+ the result or an error message
+
+Arguments:
+
+ lpsz - pointer to string to be evaluated
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ typedef struct _tagHTMLIST {
+ struct _tagHTMLIST *next;
+ LPSTR lpszName;
+ LPSTR lpszValue;
+ BOOL fArg;
+ } HTMLIST, *LPHTMLIST;
+
+ HTMLIST head = {0};
+ LPHTMLIST tail = NULL;
+ LPHTMLIST found;
+ HTM hTm = NULL;
+ HTM hTmChild = NULL;
+ HTM hTmPtr = NULL;
+ HTM hTmParm = NULL;
+ EEHSTR hValue = 0;
+ EEHSTR hName = 0;
+ UINT strIndex;
+ EESTATUS eeErr;
+ LPSTR lpszValue;
+ LPSTR lpszName;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ DWORD i;
+ DWORD j;
+ RI rti = {0};
+ HTI hti;
+ PTI pti;
+ EEPDTYP ExpTyp;
+ BOOL fExpandable;
+ DWORD len;
+ CXF cxf;
+ HMEM hsyml = 0;
+ PHSL_HEAD lphsymhead;
+ PHSL_LIST lphsyml;
+ HSYM hSym;
+ BOOL fEmpty = FALSE;
+ BOOL fFmtStr = FALSE;
+ LOGERR rval;
+ EEHSTR hErrStr;
+ LPSTR pErrStr;
+ DWORD cChild = 0;
+ DWORD cPtr = 0;
+ SHORT cParm = 0;
+ SHFLAG shflag;
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ PreRunInvalid();
+
+ //
+ // Check for no expression
+ //
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ CmdNoLogString("");
+
+ if (LocalFrameNumber) {
+ cxf = *ChangeFrame( LocalFrameNumber );
+ } else {
+ cxf = CxfIp;
+ }
+
+ if (*lpsz == '.' && strlen(lpsz) == 1) {
+
+ if (!LppdCur) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ eeErr = EENOERROR;
+ rval = LOGERROR_QUIET;
+ goto exit;
+ }
+
+ tail = &head;
+
+ SHGetNearestHSYM( &cxf.cxt.addr, cxf.cxt.hMod, EECODE, &hSym );
+ if (hSym) {
+ eeErr = EEGetTMFromHSYM( hSym, &cxf.cxt, &hTm, &i, shflag );
+ if (eeErr == EENOERROR) {
+
+ eeErr = EEcParamTM( &hTm, &cParm, &shflag );
+ if (eeErr) {
+ goto exit;
+ }
+
+ for ( i=0; i<(DWORD)cParm; i++ ) {
+ eeErr = EEGetParmTM( &hTm, (EERADIX)i, &hTmParm, &strIndex, FALSE, radix );
+ if (eeErr) {
+ continue;
+ }
+ eeErr = EEvaluateTM( &hTmParm, SHpFrameFrompCXF(&cxf), EEVERTICAL);
+ if (eeErr) {
+ EEFreeTM( &hTmParm );
+ continue;
+ }
+ eeErr = EEGetNameFromTM( &hTmParm, &hName );
+ if (eeErr) {
+ EEFreeTM( &hTmParm );
+ continue;
+ }
+ eeErr = EEGetValueFromTM( &hTmParm, radix, NULL, &hValue );
+ if (eeErr) {
+ EEFreeStr( hName );
+ EEFreeTM( &hTmParm );
+ continue;
+ }
+
+ lpszName = MMLpvLockMb( hName );
+ lpszValue = MMLpvLockMb( hValue );
+
+ tail->next = malloc( sizeof(HTMLIST) );
+ tail = tail->next;
+ tail->next = NULL;
+ tail->lpszName = _strdup( lpszName );
+ tail->lpszValue = _strdup( lpszValue );
+ tail->fArg = TRUE;
+
+ MMbUnlockMb( hValue );
+ MMbUnlockMb( hName );
+ EEFreeStr( hValue );
+ EEFreeStr( hName );
+ }
+ EEFreeTM( &hTm );
+ }
+ }
+
+ eeErr = EEGetHSYMList ( &hsyml, &cxf.cxt, HSYMR_lexical + HSYMR_function, NULL, FALSE );
+ if (!hsyml) {
+ goto exit;
+ }
+
+ len = 0;
+ lphsymhead = MMLpvLockMb ( hsyml );
+
+ lphsyml = (PHSL_LIST)(lphsymhead + 1);
+
+ for ( i = 0; i != lphsymhead->blockcnt; i++ ) {
+ for ( j = 0; j != lphsyml->symbolcnt; j++ ) {
+ if ( SHCanDisplay ( lphsyml->hSym[j] ) ) {
+ hSym = lphsyml->hSym[j];
+ if (!hSym) {
+ continue;
+ }
+ eeErr = EEGetTMFromHSYM( hSym, &cxf.cxt, &hTm, &strIndex, FALSE );
+ if (eeErr) {
+ continue;
+ }
+
+ eeErr = EEvaluateTM( &hTm, SHpFrameFrompCXF(&cxf), EEVERTICAL);
+ if (eeErr) {
+ EEFreeTM( &hTm );
+ break;
+ }
+
+ eeErr = EEGetNameFromTM( &hTm, &hName );
+ if (eeErr) {
+ EEFreeTM( &hTm );
+ continue;
+ }
+
+ eeErr = EEGetValueFromTM( &hTm, radix, NULL, &hValue );
+ if (eeErr) {
+ EEFreeStr( hName );
+ EEFreeTM( &hTm );
+ continue;
+ }
+
+ lpszValue = MMLpvLockMb( hValue );
+ lpszName = MMLpvLockMb( hName );
+
+ len = max( len, strlen(lpszName) );
+
+ found = head.next;
+ while (found) {
+ if (found->fArg && (_stricmp(found->lpszName,lpszName)==0)) {
+ break;
+ }
+ found = found->next;
+ }
+
+ if (!found) {
+ tail->next = malloc( sizeof(HTMLIST) );
+ tail = tail->next;
+ tail->next = NULL;
+ tail->lpszName = _strdup( lpszName );
+ tail->lpszValue = _strdup( lpszValue );
+ tail->fArg = FALSE;
+ }
+
+ MMbUnlockMb( hValue );
+ MMbUnlockMb( hName );
+ EEFreeStr( hValue );
+ EEFreeStr( hName );
+ EEFreeTM( &hTm );
+ }
+ }
+ lphsyml = (PHSL_LIST) &(lphsyml->hSym[j]);
+ }
+
+ MMbUnlockMb ( hsyml );
+
+ found = head.next;
+ while (found) {
+ if (found->fArg) {
+ CmdLogFmt( " <arg> " );
+ } else {
+ CmdLogFmt( " " );
+ }
+ CmdLogFmt( "%-*s %s\r\n", len, found->lpszName, found->lpszValue );
+ found = found->next;
+ }
+
+ rval = LOGERROR_NOERROR;
+ eeErr = EENOERROR;
+ goto exit;
+ }
+
+ eeErr = EEParse(lpsz, radix, fCaseSensitive, &hTm, &strIndex);
+ if (eeErr) {
+ goto exit;
+ }
+
+ eeErr = EEBindTM( &hTm, SHpCXTFrompCXF(&cxf), TRUE, FALSE, FALSE );
+ if (eeErr) {
+ goto exit;
+ }
+
+ eeErr = EEvaluateTM( &hTm, SHpFrameFrompCXF(&cxf), EEVERTICAL );
+ if (eeErr) {
+ goto exit;
+ }
+
+ ExpTyp = EEIsExpandable ( &hTm );
+ if ( ExpTyp == EENOTEXP || ExpTyp == EETYPENOTEXP ) {
+ fExpandable = FALSE;
+ } else {
+ fExpandable = TRUE;
+ eeErr = EEcChildrenTM( &hTm, &cChild, &shflag );
+ if (eeErr) {
+ goto exit;
+ }
+ if (ExpTyp == EEPOINTER) {
+ eeErr = EEDereferenceTM ( &hTm, &hTmPtr, &strIndex, fCaseSensitive );
+ if (eeErr) {
+ goto exit;
+ }
+ eeErr = EEcChildrenTM( &hTmPtr, &cPtr, &shflag );
+ if (eeErr) {
+ goto exit;
+ }
+ eeErr = EEvaluateTM( &hTm, SHpFrameFrompCXF(&cxf), EEVERTICAL );
+ if (eeErr) {
+ goto exit;
+ }
+ }
+ }
+
+ eeErr = EEInfoFromTM( &hTm, &rti, &hti );
+ if (eeErr || hti == NULL) {
+ goto exit;
+ }
+ pti = MMLpvLockMb( hti );
+ if (pti == NULL) {
+ goto exit;
+ }
+ if (pti->u.fFunction && IsProcRunning(LppdCur)) {
+ EEFreeTI( &hti );
+ goto exit;
+ }
+ fFmtStr = pti->u.fFmtStr;
+ EEFreeTI( &hti );
+
+ if (fExpandable) {
+ eeErr = EEGetNameFromTM( &hTm, &hName );
+ if (eeErr == EENOERROR) {
+ lpszName = MMLpvLockMb( hName );
+ CmdLogFmt( "%s ", lpszName );
+ MMbUnlockMb( hName );
+ EEFreeStr( hName );
+ }
+
+ if (ExpTyp == EEPOINTER && cChild == 1) {
+ //
+ // this is a pointer to a class or a structure
+ //
+ if (cPtr) {
+ //
+ // the class/structure has members
+ //
+ cChild = cPtr;
+ EEFreeTM( &hTm );
+ hTm = hTmPtr;
+ eeErr = EEvaluateTM( &hTm, SHpFrameFrompCXF(&cxf), EEVERTICAL );
+ if (eeErr) {
+ goto exit;
+ }
+ } else {
+ //
+ // this is an empty class/structure
+ //
+ fExpandable = FALSE;
+ fEmpty = TRUE;
+ EEFreeTM( &hTmPtr );
+ }
+ }
+ }
+
+ eeErr = EEGetValueFromTM( &hTm, radix, NULL, &hValue);
+ if (eeErr) {
+ goto exit;
+ }
+
+ lpszValue = MMLpvLockMb( hValue );
+ if (!fExpandable) {
+ ulPseudo[CV_REG_PSEUDO9-CV_REG_PSEUDO1] = strtoul(lpszValue, NULL, 0);
+ }
+
+ if (fExpandable && ExpTyp == EEPOINTER && cChild == 0 && (!fFmtStr)) {
+
+ //
+ // this is pointer to an agregate type or the user wants a string printed
+ //
+ eeErr = EEvaluateTM( &hTmPtr, SHpFrameFrompCXF(&cxf), EEVERTICAL );
+ if (eeErr) {
+ EEFreeTM( &hTmPtr );
+ goto exit;
+ }
+
+ eeErr = EEGetValueFromTM( &hTmPtr, radix, NULL, &hName );
+ if (eeErr) {
+ EEFreeTM( &hTmPtr );
+ goto exit;
+ }
+
+ lpszName = MMLpvLockMb( hName );
+
+ CmdLogFmt( "%s %s\r\n", lpszValue, lpszName );
+
+ EEFreeStr( hValue );
+ EEFreeStr( hName );
+ MMbUnlockMb( hValue );
+ MMbUnlockMb( hName );
+ EEFreeTM( &hTmPtr );
+
+ goto exit;
+
+ } else {
+
+ if (fEmpty) {
+ CmdLogFmt("%s (empty class/structure)\r\n", lpszValue);
+ } else {
+ CmdLogFmt("%s\r\n", lpszValue);
+ }
+ MMbUnlockMb( hValue );
+ EEFreeStr( hValue );
+
+ if (fExpandable && cChild > 0 && fFmtStr) {
+ goto exit;
+ }
+ }
+
+ if (fExpandable) {
+
+ //
+ // first loop thru all of the children to see what the longest name is
+ //
+ for (i=0,len=0; i<cChild; i++) {
+ eeErr = EEGetChildTM ( &hTm, i, &hTmChild, &strIndex, fCaseSensitive, radix );
+ if (eeErr) {
+ break;
+ }
+
+ eeErr = EEGetNameFromTM( &hTmChild, &hName );
+ if (eeErr) {
+ EEFreeTM( &hTmChild );
+ continue;
+ }
+ lpszName = MMLpvLockMb( hName );
+ len = max( len, strlen(lpszName) );
+
+ MMbUnlockMb( hName );
+ EEFreeStr( hName );
+ EEFreeTM( &hTmChild );
+ }
+
+ SetCtrlCTrap();
+
+ for (i=0; i<cChild; i++) {
+ if (CheckCtrlCTrap()) {
+ break;
+ }
+
+ eeErr = EEGetChildTM ( &hTm, i, &hTmChild, &strIndex, fCaseSensitive, radix );
+ if (eeErr) {
+ break;
+ }
+
+ eeErr = EEvaluateTM( &hTmChild, SHpFrameFrompCXF(&cxf), EEVERTICAL);
+ if (eeErr) {
+ EEFreeTM( &hTmChild );
+ break;
+ }
+
+ eeErr = EEGetNameFromTM( &hTmChild, &hName );
+ if (eeErr) {
+ EEFreeTM( &hTmChild );
+ break;
+ }
+
+ eeErr = EEGetValueFromTM( &hTmChild, radix, NULL, &hValue);
+ if (eeErr) {
+ EEFreeTM( &hTmChild );
+ EEFreeStr( hName );
+ break;
+ }
+
+ lpszValue = MMLpvLockMb( hValue );
+ lpszName = MMLpvLockMb( hName );
+
+ CmdLogFmt( " %-*s %s\r\n", len, lpszName, lpszValue );
+
+ MMbUnlockMb( hValue );
+ MMbUnlockMb( hName );
+ EEFreeStr( hValue );
+ EEFreeStr( hName );
+ EEFreeTM( &hTmChild );
+ }
+
+ ClearCtrlCTrap();
+ }
+
+exit:
+
+ if (eeErr != EENOERROR) {
+ pErrStr = NULL;
+ if (!EEGetError( &hTm, eeErr, &hErrStr)) {
+ pErrStr = MMLpvLockMb( hErrStr );
+ }
+ if (!pErrStr) {
+ CmdLogFmt( "Unknown error\r\n");
+ } else {
+ CmdLogFmt( "%s\r\n", pErrStr );
+ MMbUnlockMb ( (HDEP) hErrStr );
+ EEFreeStr( hErrStr );
+ }
+ rval = LOGERROR_QUIET;
+ }
+
+ if (hTm) {
+ EEFreeTM( &hTm );
+ }
+
+ if (tail) {
+ found = tail->next;
+ while (found) {
+ free( found->lpszName );
+ free( found->lpszValue );
+ tail = found->next;
+ free( found );
+ found = tail;
+ }
+ }
+
+ if (LocalFrameNumber) {
+ ChangeFrame( 0 );
+ }
+
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ UpdateDebuggerState(UPDATE_DATAWINS);
+
+ return LOGERROR_NOERROR;
+}
+
+
+LOGERR NEAR PASCAL
+LogFrameChange(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function will take a string, evalute it and display either
+ the result or an error message
+
+Arguments:
+
+ lpsz - pointer to string to be evaluated
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LPSTR lpsz1;
+ DWORD frame;
+ CHAR szError[300];
+
+
+
+ lpsz1 = CPszToken( lpsz, "" );
+ if (!lpsz1) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ if (!LppdCur) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ return LOGERROR_QUIET;
+ }
+
+ if (CPGetCastNbr( lpsz, T_LONG, radix, fCaseSensitive, &CxfIp, (LPSTR)&frame, szError) != EENOERROR) {
+ CmdLogFmt("%s\r\n", szError);
+ return LOGERROR_QUIET;
+ }
+ lpsz = lpsz1;
+
+ if (IsValidFrameNumber( frame )) {
+ LocalFrameNumber = frame;
+ } else {
+ CmdLogFmt( "Invalid frame number\r\n" );
+ return LOGERROR_QUIET;
+ }
+
+ UpdateDebuggerState(UPDATE_DATAWINS);
+
+ return LOGERROR_NOERROR;
+}
+
+
+LOGERR
+XWorker(
+ LPSTR lpRE,
+ WORD mask,
+ PCXF lpCxf
+ )
+{
+ HMEM hsyml = 0;
+ PHSL_LIST lphsyml;
+ PHSL_HEAD lphsymhead;
+ EESTATUS eest;
+ BOOL fAbort;
+ HTM hTM;
+ ADDR addr;
+
+ UINT i;
+ UINT j;
+ int cch;
+ LOGERR err = LOGERROR_QUIET;
+
+ char szAddr[100];
+ char szNameBuf[257];
+ char szContext[257];
+ HMEM hStr = 0;
+ LPSTR lpStr;
+
+
+
+ SetCtrlCTrap();
+ fAbort = FALSE;
+ do {
+ eest = EEGetHSYMList ( &hsyml, &lpCxf->cxt, mask, lpRE, TRUE );
+ if ( eest ) {
+
+ // error occured, display error msg and get out
+ CVExprErr ( eest, CMDWINDOW, &hTM, NULL);
+ fAbort = TRUE;
+
+ } else {
+
+ // display the syms
+ lphsymhead = MMLpvLockMb ( hsyml );
+ lphsyml = (PHSL_LIST)(lphsymhead + 1);
+
+ for ( i = 0; !fAbort && i != (UINT)lphsymhead->blockcnt; i++ ) {
+
+ *szContext = 0;
+ if ( lphsyml->status.hascxt &&
+ !EEFormatCXTFromPCXT(&lphsyml->Cxt, &hStr, runDebugParams.fShortContext)) {
+
+ lpStr = MMLpvLockMb( hStr );
+ if (runDebugParams.fShortContext) {
+ strcpy( szContext, lpStr );
+ } else {
+ BPShortenContext( lpStr, szContext);
+ strcat( szContext, " " );
+ }
+
+ MMbUnlockMb(hStr);
+ EEFreeStr(hStr);
+
+ }
+
+ szNameBuf[0] = '&';
+
+ for ( j = 0; !fAbort && j < (UINT)lphsyml->symbolcnt; j++ ) {
+
+ if ( SHGetSymName ( lphsyml->hSym[j],
+ (LPSTR)szNameBuf+1 ) ) {
+
+ eest = EENOERROR;
+ addr = *SHpAddrFrompCxt(&lpCxf->cxt);
+ if (!SHAddrFromHsym(&addr, lphsyml->hSym[j])) {
+ eest = CPGetAddress(szNameBuf,
+ &cch,
+ &addr,
+ radix,
+ lpCxf,
+ fCaseSensitive,
+ FALSE);
+ }
+ if (eest == EENOERROR) {
+ SYFixupAddr(&addr);
+ EEFormatAddr(&addr,
+ szAddr,
+ sizeof(szAddr),
+ runDebugParams.ShowSegVal
+ * EEFMT_SEG);
+ CmdLogFmt("%s %s%s\n",
+ szAddr,
+ szContext,
+ szNameBuf+1 );
+ }
+ }
+ fAbort = CheckCtrlCTrap();
+ }
+ lphsyml = (PHSL_LIST) &(lphsyml->hSym[j]);
+ }
+
+ MMbUnlockMb ( hsyml );
+ }
+ } while ( !fAbort && ! lphsymhead->status.endsearch );
+
+ if (!fAbort) {
+ err = LOGERROR_NOERROR;
+ }
+
+ ClearCtrlCTrap();
+
+ if ( hsyml ) {
+ EEFreeHSYMList ( &hsyml );
+ }
+
+ return fAbort;
+}
+
+
+
+LOGERR NEAR PASCAL
+LogExamine(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ eXamine symbols command:
+ x <pattern>
+
+ pattern may include * and ? as in DOS filename matching.
+
+Arguments:
+
+ lpsz - Supplies pointer to command tail
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+#define CONTEXT_TEMPLATE "{,,%s}0"
+
+ CXF cxf;
+ EESTATUS eest;
+ HTM hTM;
+ HCXTL hCXTL;
+ PCXTL pCXTL;
+ LPSTR lpRE;
+ LPSTR lpCxt;
+ LPSTR p;
+ char szStr[257];
+ WORD mask;
+ int cc;
+ ADDR addr;
+ int err = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ err = LOGERROR_QUIET;
+ goto done;
+ }
+
+ p = CPSkipWhitespace( lpsz );
+ if (p && _stricmp(p,"*!")==0) {
+ LogListModules("");
+ return LOGERROR_NOERROR;
+ }
+
+ //
+ // set up the mask
+ //
+ if (!makemask ( &lpsz, &mask )) {
+ err = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ if (!fCaseSensitive) {
+ mask |= HSYMR_nocase;
+ }
+
+ memset(&cxf, 0, sizeof(cxf));
+
+ lpCxt = NULL;
+ p = NULL;
+
+ if ( *lpsz == '{' ) {
+
+ for (p = lpsz; *p && *p != '}'; ) {
+#ifdef DBCS
+ p = CharNext(p);
+#else
+ p++;
+#endif
+ }
+
+ if (!*p) {
+ err = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ lpCxt = _fmalloc( p-lpsz + 3 );
+ strncpy(lpCxt, lpsz, p-lpsz+1);
+ lpCxt[p-lpsz+1] = '0';
+ lpCxt[p-lpsz+2] = '\0';
+
+ lpsz = CPSkipWhitespace(p+1);
+
+ } else if ( p = strchr(lpsz, '!') ) {
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ lpCxt = _fmalloc( (p-lpsz) + strlen(CONTEXT_TEMPLATE) );
+
+ *p = '\0';
+ sprintf( lpCxt, CONTEXT_TEMPLATE, lpsz );
+ *p = '!';
+ lpsz = CPSkipWhitespace(p+1);
+
+ } else {
+
+ addr = CxfIp.cxt.addr;
+ SYFixupAddr(&addr);
+ SHGetModule(&addr,szStr);
+
+ lpCxt = malloc( strlen(szStr) + strlen(CONTEXT_TEMPLATE) );
+ sprintf( lpCxt, CONTEXT_TEMPLATE, szStr );
+
+ lpsz = CPSkipWhitespace(lpsz);
+ }
+
+ eest = EEParse(lpCxt, radix, fCaseSensitive, &hTM, &cc);
+ if (!eest) {
+ eest = EEBindTM(&hTM, &CxfIp.cxt, TRUE, FALSE, FALSE);
+ if (!eest) {
+ eest = EEGetCXTLFromTM(&hTM, &hCXTL);
+ }
+ }
+
+ _ffree ( lpCxt );
+
+ if (!eest) {
+
+ pCXTL = MMLpvLockMb (hCXTL);
+ cxf.cxt = pCXTL->rgHCS[0].CXT;
+ MMbUnlockMb (hCXTL);
+
+ } else if ( hTM ) {
+
+ // error occured, bail out
+ CVExprErr (eest, CMDWINDOW, &hTM, NULL);
+ EEFreeTM(&hTM);
+ err = LOGERROR_QUIET;
+ goto done;
+
+ } else {
+
+ EEFreeTM(&hTM);
+ CmdLogVar(ERR_Bad_Context);
+ goto done;
+ }
+
+ EEFreeTM(&hTM);
+
+ lpRE = lpsz;
+
+ // UNDONE: The tests below don't make sense to me. Why check for either alpha or '_', '@'? BryanT
+
+ if ( isalpha(*lpRE) || *lpRE == '_' ) {
+ *szStr = '_';
+ strcpy(szStr+1, lpRE);
+ err = XWorker(szStr, mask, &cxf);
+ }
+ if ( isalpha(*lpRE) || *lpRE == '@' ) {
+ *szStr = '@';
+ strcpy(szStr+1, lpRE);
+ err = XWorker(szStr, mask, &cxf);
+ }
+ if ( isalpha(*lpRE) || (*lpRE == '.' && *(lpRE + 1) == '.') ) {
+ *szStr = '.';
+ *(szStr+1) = '.';
+ strcpy(szStr+2, lpRE);
+ err = XWorker(szStr, mask, &cxf);
+ }
+ if (err == LOGERROR_NOERROR) {
+ err = XWorker(lpRE, mask, &cxf);
+ }
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ return err;
+}
+
+
+LOGERR NEAR PASCAL
+LogException(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function will take a string, evalute it as a hex digit and
+ either disable or enable it. If the string is null then we will
+ print out a list of all the known exceptions and whether they
+ are handled or not.
+
+Arguments:
+
+ lpsz - pointer to string holding the hex numbered exception
+
+Return Value:
+
+ NOTENOTE No error code at this point
+
+--*/
+{
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ char chCmd;
+ BOOLEAN fException = FALSE;
+ BOOLEAN fName = FALSE;
+ BOOLEAN fCmd = FALSE;
+ BOOLEAN fCmd2 = FALSE;
+ BOOLEAN fInvalid = FALSE;
+ DWORD Exception;
+ LPSTR lpName = NULL;
+ LPSTR lpCmd = NULL;
+ LPSTR lpCmd2 = NULL;
+ EXCEPTION_LIST *eList;
+ EXCEPTION_DESCRIPTION Exd;
+
+
+ CmdInsertInit();
+ //
+ // NOTENOTE a-kentf thread wildcard is supposed to be valid here (LogException)
+ //
+ PDWildInvalid();
+ TDWildInvalid();
+
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ //
+ // Get default exception list if necessary
+ //
+ if ( !LppdCur && !DefaultExceptionList ) {
+ if ( !GetDefaultExceptionList() ) {
+ CmdLogVar(ERR_No_ExceptionList);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+
+ //
+ // Get and Action:
+ //
+ // D - Disable
+ // E - Enable
+ // N - Notify
+ // Blank - List
+ //
+ chCmd = *lpsz;
+ if ( chCmd != '\0' ) {
+#ifdef DBCS
+ if ( IsDBCSLeadByte( chCmd ) ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+#endif
+ lpsz++;
+ if ( strchr( " \t", chCmd ) ) {
+ chCmd = '\0';
+ } else if ( !strchr( "dDeEnN", chCmd ) ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ }
+
+ //
+ // Parse line
+ //
+ rVal = ParseException( lpsz,
+ radix,
+ &fException,
+ NULL,
+ &fName,
+ &fCmd,
+ &fCmd2,
+ &fInvalid,
+ &Exception,
+ NULL,
+ &lpName,
+ &lpCmd,
+ &lpCmd2 );
+
+ if ( rVal != LOGERROR_NOERROR ) {
+ if ( fInvalid ) {
+ CmdLogVar(ERR_Exception_Invalid);
+ }
+
+ goto done;
+ }
+
+ //
+ // Validate arguments & Execute the command
+ //
+ switch (chCmd) {
+ case '\0':
+ //
+ // Plain sx command
+ //
+ if ( fName || fCmd || fCmd2 ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ break;
+
+ case 'd':
+ case 'D':
+ //
+ // Can contain: Name
+ //
+ if ( !fException ) {
+ rVal = LOGERROR_QUIET;
+ CmdLogVar(ERR_Exception_Invalid);
+ goto done;
+ } else if ( fCmd || fCmd2 ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ Exd.dwExceptionCode = Exception;
+ Exd.efd = efdIgnore;
+ if (fName) {
+ strncpy(Exd.rgchDescription,
+ lpName? lpName : "",
+ EXCEPTION_STRING_SIZE);
+ }
+ if (LppdCur) {
+ OSDSetExceptionState(LppdCur->hpid, LptdCur->htid, &Exd);
+ }
+ break;
+
+ case 'n':
+ case 'N':
+ //
+ // Can contain: Name & Cmd2
+ //
+ if ( !fException ) {
+ rVal = LOGERROR_QUIET;
+ CmdLogVar(ERR_Exception_Invalid);
+ goto done;
+ } else if ( fCmd ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ Exd.dwExceptionCode = Exception;
+ Exd.efd = efdNotify;
+ if (fName) {
+ strncpy(Exd.rgchDescription,
+ lpName? lpName : "",
+ EXCEPTION_STRING_SIZE);
+ }
+ if (LppdCur) {
+ OSDSetExceptionState(LppdCur->hpid, LptdCur->htid, &Exd);
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ //
+ // Can contain: Name, Cmd & Cmd2
+ //
+ if ( !fException ) {
+ rVal = LOGERROR_QUIET;
+ CmdLogVar(ERR_Exception_Invalid);
+ goto done;
+ }
+ Exd.dwExceptionCode = Exception;
+ Exd.efd = efdStop;
+ if (fName) {
+ strncpy(Exd.rgchDescription,
+ lpName? lpName : "",
+ EXCEPTION_STRING_SIZE);
+ }
+ if (LppdCur) {
+ OSDSetExceptionState(LppdCur->hpid, LptdCur->htid, &Exd);
+ }
+ break;
+ }
+
+ if ( fException ) {
+
+ //
+ // Try to find this exception on the processes exception list
+ //
+ for (eList = LppdCur ? LppdCur->exceptionList : DefaultExceptionList;
+ eList;
+ eList = eList->next) {
+ if (eList->dwExceptionCode==Exception) {
+ break;
+ }
+ }
+ }
+
+ if ( chCmd == '\0' ) {
+ //
+ // Execute plain sx command if requested.
+ //
+ if ( fException ) {
+ //
+ // Display specified exception
+ //
+ if ( eList ) {
+
+ LogSx( eList );
+
+ } else {
+
+ CmdLogVar(ERR_Exception_Unknown, Exception);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ } else {
+
+ //
+ // Display all exceptions
+ //
+ for (eList = LppdCur ? LppdCur->exceptionList :
+ DefaultExceptionList;
+ eList;
+ eList = eList->next)
+ {
+ LogSx( eList );
+ }
+ }
+
+ } else {
+ //
+ // Add exception if not in list
+ //
+ if (!eList) {
+ eList=(EXCEPTION_LIST*)malloc(sizeof(EXCEPTION_LIST));
+ eList->dwExceptionCode = Exception;
+ eList->lpName = NULL;
+ eList->lpCmd = NULL;
+ eList->lpCmd2 = NULL;
+ eList->efd = efdIgnore;
+
+ if ( LppdCur ) {
+ LppdCur->exceptionList =
+ InsertException( LppdCur->exceptionList, eList);
+ if ( LppdCur->ipid == 0 ) {
+ DefaultExceptionList = LppdCur->exceptionList;
+ }
+ } else {
+ DefaultExceptionList =
+ InsertException( DefaultExceptionList, eList);
+ }
+ }
+
+ //
+ // Set appropriate fields
+ //
+ eList->efd = Exd.efd;
+
+ if (fName) {
+ if (eList->lpName) {
+ free(eList->lpName);
+ }
+ eList->lpName = lpName;
+ }
+
+ if (fCmd) {
+ if (eList->lpCmd) {
+ free(eList->lpCmd);
+ }
+ eList->lpCmd = lpCmd;
+ }
+
+ if (fCmd2) {
+ if (eList->lpCmd2) {
+ free(eList->lpCmd2);
+ }
+ eList->lpCmd2 = lpCmd2;
+ }
+ }
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ if ( rVal != LOGERROR_NOERROR ) {
+ //
+ // Free allocated memory
+ //
+ if ( lpName ) {
+ free( lpName );
+ }
+
+ if ( lpCmd ) {
+ free( lpCmd );
+ }
+
+ if ( lpCmd2 ) {
+ free( lpCmd2 );
+ }
+ }
+ return rVal;
+}
+
+
+
+
+void
+LogSx(
+ EXCEPTION_LIST *eList
+ )
+/*++
+
+Routine Description:
+
+ Displays the given exception in the command window
+
+Arguments:
+
+ eList - Supplies exception to display
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ char Buffer[512];
+
+ FormatException( eList->efd,
+ eList->dwExceptionCode,
+ eList->lpName,
+ eList->lpCmd,
+ eList->lpCmd2,
+ " ",
+ Buffer );
+
+ CmdLogFmt("%s\r\n", Buffer );
+}
+
+
+
+
+LOGERR NEAR PASCAL
+LogFreeze(
+ LPSTR lpsz,
+ BOOL fFreeze
+ )
+/*++
+
+Routine Description:
+
+ This function is used from the command line to freeze and thaw
+ debuggee threads. We use LptdCommand to determine which thread
+ should be frozen or thawed.
+
+Arguments:
+
+ lpsz - Supplies argument list; should be empty
+ fFreeze - Supplies TRUE if freeze the thread, FALSE if thaw the thread
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+
+ CmdInsertInit();
+ PreRunInvalid();
+
+ if (*lpsz != 0) {
+
+ rVal = LOGERROR_UNKNOWN;
+
+ } else if (LptdCommand == (LPTD)-1) {
+
+ if (LppdCur == NULL) {
+
+ rVal = LOGERROR_UNKNOWN;
+
+ } else {
+
+ for (LptdCur = LppdCur->lptdList; LptdCur; LptdCur = LptdCur->lptdNext) {
+#ifdef OSDEBUG4
+ if (OSDFreezeThread(LptdCur->lppd->hpid, LptdCur->htid,
+ fFreeze) == xosdNone)
+#else
+ if (OSDPtrace(fFreeze ? osdFreeze : osdThaw,
+ 0, 0, LptdCur->lppd->hpid, LptdCur->htid)
+ == xosdNone)
+#endif
+ {
+ LptdCur->fFrozen = fFreeze;
+ }
+ else
+ {
+ CmdLogVar((WORD)(fFreeze? ERR_Cant_Freeze : ERR_Cant_Thaw));
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+ }
+ }
+
+ } else {
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ if (LptdCur == NULL)
+ {
+ rVal = LOGERROR_UNKNOWN;
+ }
+ else if (LptdCur == (LPTD) -1)
+ {
+ Assert(FALSE);
+ }
+ else if (fFreeze && LptdCur->fFrozen)
+ {
+ CmdLogVar(ERR_Thread_Is_Frozen);
+ rVal = LOGERROR_QUIET;
+ }
+ else if (!fFreeze && !LptdCur->fFrozen)
+ {
+ CmdLogVar(ERR_Thread_Not_Frozen);
+ rVal = LOGERROR_QUIET;
+ }
+#ifdef OSDEBUG4
+ else if (OSDFreezeThread(LptdCur->lppd->hpid, LptdCur->htid, fFreeze)
+ == xosdNone)
+#else
+ else if (OSDPtrace(fFreeze ? osdFreeze : osdThaw,
+ 0, 0, LptdCur->lppd->hpid, LptdCur->htid)
+ == xosdNone)
+#endif
+ {
+ LptdCur->fFrozen = fFreeze;
+ }
+ else
+ {
+ CmdLogVar((WORD)(fFreeze? ERR_Cant_Freeze : ERR_Cant_Thaw));
+ rVal = LOGERROR_QUIET;
+ }
+ }
+
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+} /* LogFreeze() */
+
+
+LOGERR NEAR PASCAL
+LogGoException(
+ LPSTR lpsz,
+ BOOL fHandled
+ )
+/*++
+
+Routine Description:
+
+ GH and GN commands. Continue handled or unhandled from exception.
+
+Arguments:
+
+ lpsz - Supplies pointer to tail of command
+
+ fHandled - Supplies flag indicating whether exception should be
+ handled or not.
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ XOSD xosd;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+
+ CmdInsertInit();
+
+ if (runDebugParams.fKernelDebugger && runDebugParams.KdParams.fUseCrashDump) {
+ CmdLogFmt( "Go is not allowed for crash dumps\n" );
+ return rVal;
+ }
+
+ TDWildInvalid();
+ PDWildInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ if (*CPSkipWhitespace(lpsz) != '\0') {
+ rVal = LOGERROR_UNKNOWN;
+ } if (LptdCur == NULL) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ } else if (LptdCur->tstate != tsException1 && LptdCur->tstate != tsException2) {
+ CmdLogVar(ERR_Not_At_Exception);
+ rVal = LOGERROR_QUIET;
+ } else {
+ EXOP exop = {0};
+ exop.fSingleThread = TRUE;
+ exop.fInitialBP = TRUE;
+ exop.fPassException = !fHandled;
+ xosd = OSDGo(LppdCur->hpid, LptdCur->htid, &exop);
+ if (xosd == xosdNone) {
+ SetPTState(psRunning, tsRunning);
+ } else {
+ CmdLogVar(ERR_Cant_Cont_Exception);
+ rVal = LOGERROR_QUIET;
+ }
+ }
+
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+}
+
+
+LOGERR NEAR PASCAL
+LogGoUntil(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This routine will parse out an address, set a temp breakpoint
+ at the address and issue a go command
+
+ Syntax:
+ g [=startaddr] [address]
+
+Arguments:
+
+ lpsz - address to put the temporary breakpoint at
+
+Return Value:
+
+ LOGERR code
+
+--*/
+{
+ ADDR addr;
+ HBPT hbpt = NULL;
+ CXF cxf = CxfIp;
+ LPPD LppdT;
+ LPTD LptdT;
+ LOGERR rVal = LOGERROR_NOERROR;
+
+
+ CmdInsertInit();
+
+ if (runDebugParams.fKernelDebugger && runDebugParams.KdParams.fUseCrashDump) {
+ CmdLogFmt( "Go is not allowed for crash dumps\n" );
+ return rVal;
+ }
+
+ PDWildInvalid();
+
+ /*
+ * If debugger is initializing, bail out.
+ */
+
+ PreRunInvalid();
+
+ /*
+ * Different process, implies any thread:
+ */
+ if (FSetLppd && !FSetLptd) {
+
+ /*
+ * change process and make thread wildcard
+ */
+
+ FSetLppd = FALSE;
+ LppdT = LppdCur;
+ LppdCur = LppdCommand;
+ LptdT = LptdCur;
+ LptdCur = LppdCur->lptdList;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ LptdCommand = (LPTD)-1;
+ FSetLptd = TRUE;
+
+ rVal = LogGoUntil(lpsz);
+
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ return rVal;
+ }
+
+
+ /*
+ * Any process, any thread:
+ */
+ if (LptdCommand == (LPTD)-1) {
+
+ BOOL fDidSomething = FALSE;
+
+ FSetLptd = TRUE; // this should already be true, in fact.
+
+ for (LptdCommand = LppdCur->lptdList; LptdCommand; LptdCommand = LptdCommand->lptdNext) {
+ if (GoOK(LppdCur, LptdCommand)) {
+ fDidSomething = TRUE;
+ if ((rVal = LogGoUntil(lpsz)) != LOGERROR_NOERROR) {
+ return rVal;
+ }
+ }
+ }
+
+ if (!fDidSomething) {
+ CmdLogVar(ERR_Process_Cant_Go);
+ rVal = LOGERROR_QUIET;
+ }
+
+ return rVal;
+ }
+
+ /*
+ * switch debugger context to requested proc/thread
+ */
+
+ if (FSetLppd || FSetLptd) {
+ LppdT = LppdCur;
+ LppdCur = LppdCommand;
+ LptdT = LptdCur;
+ LptdCur = LptdCommand;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ cxf = CxfIp;
+ }
+
+
+ if (DebuggeeActive()) {
+ if (!GoOK(LppdCur, LptdCur)) {
+ NoRunExcuse(LppdCur, LptdCur);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ } else if (DebuggeeAlive()) {
+ NoRunExcuse(GetLppdHead(), NULL);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** If this is a no argument go command then just do the go and be done
+ ** with the whole mess.
+ */
+ if (*lpsz == 0) {
+ if (LptdCur && LptdCur->fFrozen) {
+ CmdLogVar(DBG_Go_When_Frozen);
+ }
+ if (ExecDebuggee(EXEC_GO)) {
+ rVal = LOGERROR_NOERROR;
+ goto done;
+ } else {
+ CmdLogVar(ERR_Go_Failed);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+
+ if (LptdCur && LptdCur->fFrozen) {
+ CmdLogVar(ERR_Simple_Go_Frozen);
+ return LOGERROR_QUIET;
+ }
+
+ /*
+ ** If the debuggee is not loaded then we need to get it loaded so that
+ ** we have symbols that can be evaluated
+ */
+
+ if (!DebuggeeAlive()) {
+ if (!ExecDebuggee(EXEC_RESTART)) {
+ CmdLogVar(ERR_Cant_Start_Proc);
+ return LOGERROR_QUIET;
+ }
+ LppdCommand = LppdCur;
+ LptdCommand = LppdCur->lptdList;
+ }
+
+ /*
+ ** Can this happen?
+ */
+
+ if (LppdCur->pstate == psExited) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ /*
+ ** Check for a starting address optional argument. If no arguments
+ ** are left then issue a go command after changing the current
+ ** instruction pointer.
+ */
+
+ if (*lpsz == '=') {
+ CmdLogFmt(" NYI: starting address\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ /*
+ ** Now get the termination address, note that we need to replace any
+ ** leading periods ('.') with '@'s as these must really be line numbers
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (BPParse(&hbpt,
+ lpsz,
+ NULL,
+ NULL,
+ LppdCur ? LppdCur->hpid: 0)
+ != BPNOERROR)
+ {
+ Assert( hbpt == NULL );
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+
+ } else if (BPBindHbpt( hbpt, &cxf ) == BPNOERROR) {
+
+ /*
+ ** go the go until
+ */
+ Dbg( BPAddrFromHbpt( hbpt, &addr ) == BPNOERROR) ;
+ Dbg( BPFreeHbpt( hbpt ) == BPNOERROR) ;
+ GoUntil(&addr);
+
+ } else if (!LppdCur->fHasRun) {
+
+ /*
+ * haven't executed entrypoint: save it for later
+ */
+ LppdCur->hbptSaved = (HANDLE)hbpt;
+ Go();
+
+ } else {
+
+ /*
+ * bind failed
+ */
+ Dbg( BPFreeHbpt( hbpt ) == BPNOERROR );
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ }
+
+
+done:
+ if (FSetLppd || FSetLptd) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogGoUntil() */
+
+int _CRTAPI1
+CompareModEntryBySelector(
+ const void *pMod1,
+ const void *pMod2
+ )
+{
+ LPMODULE_ENTRY Mod1 = (LPMODULE_ENTRY)pMod1;
+ LPMODULE_ENTRY Mod2 = (LPMODULE_ENTRY)pMod2;
+
+ if ( ModuleEntrySelector(Mod1) < ModuleEntrySelector(Mod2) ) {
+ return -1;
+ } else if ( ModuleEntrySelector(Mod1) > ModuleEntrySelector(Mod2) ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+int _CRTAPI1
+CompareModEntryByAddress(
+ const void *pMod1,
+ const void *pMod2
+ )
+{
+ return ModuleEntryBase((LPMODULE_ENTRY)pMod1) < ModuleEntryBase((LPMODULE_ENTRY)pMod2) ? -1 : 1;
+}
+
+
+BOOL
+FormatHSym(
+ HSYM hsym,
+ PCXT cxt,
+ char *szStr
+ )
+{
+ ushort retval;
+ HTM htm;
+ uint strIndex;
+ EEHSTR eehstr;
+ USHORT cb;
+ BOOL Ok = FALSE;
+
+ retval = EEGetTMFromHSYM ( hsym, cxt, &htm, &strIndex, FALSE );
+
+ if ( retval == EENOERROR ) {
+ retval = EEGetExprFromTM( &htm, &radix, &eehstr, &cb);
+
+ if ( retval == EENOERROR ) {
+ strcpy(szStr, MMLpvLockMb( eehstr ));
+ MMbUnlockMb( eehstr );
+ EEFreeStr( eehstr );
+ Ok = TRUE;
+ }
+
+ EEFreeTM( &htm );
+ }
+
+ if ( !Ok ) {
+ Ok = (BOOL)SHGetSymName(hsym, szStr);
+ }
+
+ return Ok;
+}
+
+
+
+
+LOGERR NEAR PASCAL
+LogListNear(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ ln "list near" command:
+ ln <addr>
+
+Arguments:
+
+ lpsz - Supplies pointer to command tail
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ ADDR addr;
+ ADDR addr1;
+ HSYM hsymP;
+ HSYM hsymN;
+ DWORD dwOff;
+ DWORD dwOffP;
+ DWORD dwOffN;
+
+ HDEP hsyml;
+ PHSL_HEAD lphsymhead;
+ PHSL_LIST lphsyml;
+ LPMODULE_LIST lpModList;
+ LPMODULE_ENTRY lpModEntry;
+
+ int cch;
+ char szStr[MAX_USER_LINE];
+ char szContext[MAX_USER_LINE];
+ LPSTR lpContext;
+ CXT cxt;
+ HDEP hstr;
+ UINT n;
+ EESTATUS eest;
+ XOSD xosd;
+
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ TDWildInvalid();
+ PDWildInvalid();
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** get address
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ lpsz = ".";
+ }
+
+ if (CPGetAddress(lpsz, &cch, &addr, radix, &CxfIp, fCaseSensitive, FALSE) == 0) {
+ if (*CPSkipWhitespace(lpsz + cch) != 0) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ } else {
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if ((HPID)emiAddr( addr ) == LppdCur->hpid && ADDR_IS_LI(addr)) {
+ emiAddr( addr ) = 0;
+ ADDR_IS_LI( addr ) = FALSE;
+#ifdef OSDEBUG4
+ OSDSetEmi(LppdCur->hpid,LptdCur->htid,&addr);
+#else
+ OSDPtrace(osdSetEmi, wNull, &addr, LppdCur->hpid, LptdCur->htid);
+#endif
+ if ( (HPID)emiAddr( addr ) != LppdCur->hpid ) {
+ SHWantSymbols( (HEXE)emiAddr( addr ) );
+ }
+ SYUnFixupAddr(&addr);
+ }
+
+ memset(&cxt, 0, sizeof(cxt));
+ SHSetCxt(&addr, &cxt);
+
+
+ // the following hack works around a shortcoming of CV info.
+ // We only have module maps for code contributor segments, so
+ // we can't get a useful CXT for a data address. A little
+ // brute force abuse will generate a usable HMOD:
+
+ // (this is going to be harder if the address is segmented...
+ // I didn't try to solve that one.)
+
+ if ( SHHMODFrompCXT( &cxt ) == NULL ) {
+
+ addr1 = addr;
+ SYFixupAddr(&addr1);
+
+ // get module table
+
+ xosd = OSDGetModuleList( LppdCur->hpid,
+ LptdCur->htid,
+ TRUE,
+ NULL,
+ &lpModList );
+
+ if (xosd == xosdNone && ModuleListCount(lpModList) > 0 ) {
+ qsort( FirstModuleEntry(lpModList),
+ ModuleListCount(lpModList),
+ sizeof(MODULE_ENTRY),
+ CompareModEntryByAddress );
+
+ // find nearest exe
+
+ lpModEntry = FirstModuleEntry(lpModList);
+
+ for ( n = 0; n < ModuleListCount( lpModList ) - 1; n++) {
+
+ if (GetAddrOff(addr1) <
+ ModuleEntryBase(NextModuleEntry(lpModEntry)) )
+ {
+ break;
+ }
+
+ lpModEntry = NextModuleEntry(lpModEntry);
+ }
+
+ SHHMODFrompCXT( &cxt ) = SHGetNextMod(ModuleEntryHexe(lpModEntry), NULL);
+ }
+ }
+
+ hsyml = 0;
+ eest = EEGetHSYMList(&hsyml, &cxt,
+ HSYMR_module | HSYMR_global | HSYMR_public, NULL, TRUE);
+ if (eest != EENOERROR) {
+ rVal = LOGERROR_CP;
+ goto done;
+ }
+
+ lphsymhead = MMLpvLockMb ( hsyml );
+ lphsyml = (PHSL_LIST)(lphsymhead + 1);
+
+ dwOffP = 0xffffffff;
+ dwOffN = 0xffffffff;
+ hsymP = 0;
+ hsymN = 0;
+
+ SYFixupAddr(&addr);
+ addr1 = addr;
+ for ( n = 0; n < (UINT)lphsyml->symbolcnt; n++ ) {
+ if (SHAddrFromHsym(&addr1, lphsyml->hSym[n])) {
+ SYFixupAddr(&addr1);
+ if (!ADDR_IS_FLAT(addr1) && !ADDR_IS_FLAT(addr) &&
+ GetAddrSeg(addr1) != GetAddrSeg(addr))
+ {
+ continue;
+ }
+ if (GetAddrOff(addr1) <= GetAddrOff(addr)) {
+ dwOff = GetAddrOff(addr) - GetAddrOff(addr1);
+ if (dwOff < dwOffP) {
+ dwOffP = dwOff;
+ hsymP = lphsyml->hSym[n];
+ }
+ } else {
+ dwOff = GetAddrOff(addr1) - GetAddrOff(addr);
+ if (dwOff < dwOffN) {
+ dwOffN = dwOff;
+ hsymN = lphsyml->hSym[n];
+ }
+ }
+ }
+ }
+
+ MMbUnlockMb(hsyml);
+
+ if (!hsymP && !hsymN) {
+ CmdLogVar(DBG_Symbol_Not_Found);
+ } else {
+
+ EEFormatCXTFromPCXT( &cxt, &hstr, runDebugParams.fShortContext );
+
+ lpContext = MMLpvLockMb( hstr );
+
+ if (runDebugParams.fShortContext) {
+ strcpy( szContext, lpContext );
+ } else {
+ BPShortenContext( lpContext, szContext);
+ }
+
+ MMbUnlockMb(hstr);
+ EEFreeStr(hstr);
+
+ if ( hsymP && FormatHSym(hsymP, &cxt, szStr) ) {
+ CmdLogFmt("%s%s+%#0x\r\n", szContext, szStr, dwOffP);
+ }
+
+ if ( hsymN && FormatHSym(hsymN, &cxt, szStr) ) {
+ CmdLogFmt("%s%s-%#0x\r\n", szContext, szStr, dwOffN);
+ }
+ }
+
+ MMFreeHmem(hsyml);
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogListNear() */
+
+
+
+LOGERR NEAR PASCAL
+ListModules(
+ LOGERR *prVal,
+ BOOL Flat,
+ BOOL SelSort,
+ LPSTR ModName
+ )
+/*++
+
+Routine Description:
+
+ Lists modules
+
+Arguments:
+
+ rVal - Pointer to LOGERR
+ Flat - Flat flag
+ SelSort - Sort by selector flag
+ ModName - Module name to look for (optional)
+
+Return Value:
+
+ TRUE if modules listed.
+
+--*/
+{
+ XOSD xosd;
+ LPMODULE_LIST ModList;
+ LPMODULE_ENTRY ModEntry;
+ DWORD Mod;
+ LPSTR LastName;
+ BOOL Ok = FALSE;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPSTR lpch;
+ LPSTR lpModName;
+ LPSTR lpSymName;
+ CHAR buf[100];
+
+
+ //
+ // Get module list
+ //
+ if ( !LppdCur || !LptdCur ) {
+
+ rVal = LOGERROR_UNKNOWN;
+
+ } else {
+
+ xosd = OSDGetModuleList( LppdCur->hpid,
+ LptdCur->htid,
+ Flat,
+ ModName,
+ &ModList );
+
+ if ( xosd != xosdNone ) {
+
+ //
+ // Could not get module list!
+ //
+ rVal = LOGERROR_UNKNOWN;
+
+ } else {
+
+ if ( !ModName ) {
+ if ( Flat ) {
+ CmdLogFmt("\r\n" );
+ CmdLogFmt("Flat Modules:\r\n" );
+ } else {
+ CmdLogFmt("\r\n" );
+ CmdLogFmt("Segmented Modules:\r\n" );
+ }
+ }
+
+ if ( ModuleListCount(ModList) > 0 ) {
+
+ Ok = TRUE;
+
+ //
+ // Sort Module list
+ //
+ if ( SelSort ) {
+
+ //
+ // Sort by selector
+ //
+ qsort( FirstModuleEntry(ModList),
+ ModuleListCount(ModList),
+ sizeof(MODULE_ENTRY),
+ CompareModEntryBySelector );
+ } else {
+
+ //
+ // Sort by Base address
+ //
+ qsort( FirstModuleEntry(ModList),
+ ModuleListCount(ModList),
+ sizeof(MODULE_ENTRY),
+ CompareModEntryByAddress );
+ }
+
+ //CmdLogFmt("\r\n" );
+ if ( Flat ) {
+ CmdLogFmt(" Base Limit Name\r\n" );
+ CmdLogFmt(" -------- -------- ------------\r\n");
+ } else {
+ CmdLogFmt(" Sel Base Limit Seg Name\r\n" );
+ CmdLogFmt(" ---- -------- -------- ---- ------------\r\n");
+ }
+
+ ModEntry = FirstModuleEntry(ModList);
+ LastName = NULL;
+
+ for ( Mod = 0, ModEntry = FirstModuleEntry(ModList);
+ Mod < ModuleListCount( ModList );
+ Mod++, ModEntry = NextModuleEntry(ModEntry) ) {
+
+ lpSymName = SHGetSymFName( ModuleEntryHexe(ModEntry) );
+ lpModName = SHGetModNameFromHexe( ModuleEntryHexe(ModEntry) );
+
+ if ( ModuleEntryFlat(ModEntry) ) {
+
+ CmdLogFmt( " %08X - %08X %-8s",
+ ModuleEntryBase(ModEntry),
+ ModuleEntryBase(ModEntry) + ModuleEntryLimit(ModEntry),
+ lpModName
+ );
+
+ lpch = SHLszGetErrorText((SHE)ModuleEntryType(ModEntry));
+ if (lpch) {
+ sprintf( buf, "(%s)", lpch );
+ CmdLogFmt( "\t%-30s", buf );
+ }
+
+ CmdLogFmt( "\t%s", lpSymName );
+
+ CmdLogFmt("\r\n");
+
+ } else {
+
+ if ( !ModuleEntryFlat(ModEntry) ) {
+
+ if ( !SelSort &&
+ LastName &&
+ _stricmp( LastName, lpModName )) {
+
+ CmdLogFmt("\r\n" );
+ }
+
+ LastName = lpModName;
+ }
+
+ if ( ModuleEntryReal(ModEntry ) ) {
+ CmdLogFmt(" %04x (Real mode) %04x ",
+ ModuleEntrySelector(ModEntry),
+ ModuleEntrySegment(ModEntry) );
+
+ } else {
+ CmdLogFmt(" %04x %08x %08x %04x ",
+ ModuleEntrySelector(ModEntry),
+ ModuleEntryBase(ModEntry),
+ ModuleEntryLimit(ModEntry),
+ ModuleEntrySegment(ModEntry) );
+ }
+
+ CmdLogFmt( "\t%s", lpModName );
+
+ CmdLogFmt( "\t%s", lpSymName );
+
+ CmdLogFmt("\r\n");
+ }
+ }
+ }
+
+ //
+ // Deallocate module list
+ //
+ FreeModuleList( ModList );
+ }
+ }
+
+ *prVal = rVal;
+ return Ok;
+}
+
+
+LOGERR NEAR PASCAL
+LogListModules(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ lm "list modules" command
+
+Arguments:
+
+ lpsz - Supplies pointer to command tail
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ char ModNameBuffer[ MAX_PATH ];
+ char *ModName;
+ LOGERR rVal = LOGERROR_NOERROR;
+ BOOL Flat = FALSE;
+ BOOL Sgm = FALSE;
+ BOOL SelSort = FALSE;
+ BOOL Ok;
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ if ( !DebuggeeActive() ) {
+
+ //
+ // No debuggee - nothing to do.
+ //
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+
+ } else {
+
+ //
+ // Parse arguments
+ //
+ *ModNameBuffer = '\0';
+ if ( lpsz && *lpsz ) {
+ lpsz = CPSkipWhitespace(lpsz);
+ while ( rVal == LOGERROR_NOERROR && lpsz && *lpsz ) {
+ switch (*lpsz) {
+ case '/':
+ lpsz++;
+ switch( *lpsz ) {
+ case 'f':
+ case 'F':
+ if ( !Flat ) {
+ Flat = TRUE;
+ lpsz++;
+ }
+ break;
+
+ case 's':
+ case 'S':
+ if ( !Sgm ) {
+ Sgm = TRUE;
+ lpsz++;
+ }
+ break;
+
+ case 'o':
+ case 'O':
+ if ( !SelSort ) {
+ SelSort = TRUE;
+ lpsz++;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if ( *lpsz && *lpsz != ' ' && *lpsz != '\t' ) {
+ rVal = LOGERROR_UNKNOWN;
+ }
+ break;
+
+ default:
+ if ( *ModNameBuffer ) {
+ rVal = LOGERROR_UNKNOWN;
+ } else {
+ char *p = ModNameBuffer;
+ while ( *lpsz && *lpsz != ' ' && *lpsz != '\t' ) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*lpsz)) {
+ *p++ = *lpsz++;
+ }
+#endif
+ *p++ = *lpsz++;
+ }
+ *p++ = '\0';
+ }
+ break;
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+ }
+ }
+
+ if ( rVal == LOGERROR_NOERROR ) {
+
+ //
+ // Validate switches
+ //
+ if ( !Flat && !Sgm ) {
+ //
+ // If command did not specify Flat or Sgm, we set
+ // both by default.
+ //
+ Flat = Sgm = TRUE;
+ }
+
+ //
+ // SelSort is valid only if listing segmented modules
+ //
+ if ( SelSort && !Sgm ) {
+ rVal = LOGERROR_UNKNOWN;
+ }
+ }
+
+ if ( rVal == LOGERROR_NOERROR ) {
+
+ //
+ // Now do the listing
+ //
+ Ok = FALSE;
+ ModName = *ModNameBuffer ? ModNameBuffer : NULL;
+
+ //
+ // List Segmented modules
+ //
+ if ( Sgm ) {
+
+ Ok = ListModules( &rVal, FALSE, SelSort, ModName );
+
+ if ( !ModName && !Ok ) {
+ CmdLogVar(ERR_NoModulesFound);
+ }
+ }
+
+ //
+ // List flat modules, unless we are looking for a specific
+ // module and we already found it.
+ //
+ if ( rVal == LOGERROR_NOERROR && Flat && !( Ok && ModName ) ) {
+
+ Ok = ListModules( &rVal, TRUE, FALSE, ModName );
+
+ if ( !ModName && !Ok ) {
+ CmdLogVar(ERR_NoModulesFound);
+ }
+ }
+
+ if ( rVal == LOGERROR_NOERROR ) {
+ if ( ModName && !Ok ) {
+ CmdLogVar(ERR_ModuleNotFound, ModName);
+ }
+ }
+ }
+ }
+
+ return rVal;
+}
+
+
+
+
+
+LOGERR NEAR PASCAL
+LogProcess(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Enumerate processes
+
+Arguments:
+
+ None
+
+Return Value:
+
+ LOGERR code
+
+--*/
+{
+ LPPD lppd;
+
+ PST pst;
+
+ CmdInsertInit();
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ return LOGERROR_NOERROR;
+ }
+
+ lppd = GetLppdHead();
+ Assert(lppd != NULL);
+
+ for ( ;lppd != NULL; lppd = lppd->lppdNext) {
+
+ if (lppd->pstate == psDestroyed) {
+ continue;
+ }
+
+ if (OSDGetProcessStatus(lppd->hpid, &pst) != xosdNone) {
+ CmdLogFmt("No status for process %d\r\n", lppd->ipid);
+ } else {
+ CmdLogFmt("%c%2d %s %s\r\n",
+ lppd == LppdCur? '*' : ' ',
+ lppd->ipid,
+ pst.rgchProcessID,
+ pst.rgchProcessState);
+ }
+ }
+
+
+
+#if 0
+
+ long l;
+ UINT cbPid;
+ char rgb[10];
+ char rgch[100];
+ LPPD lppd;
+ LPSTR lpzStatus;
+
+ CmdInsertInit();
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ return LOGERROR_NOERROR;
+ }
+
+ lppd = GetLppdHead();
+ Assert(lppd != NULL);
+
+ OSDGetDebugMetric( mtrcPidSize, lppd->hpid, 0, &l);
+ cbPid = (UINT) l;
+
+ for ( ;lppd != NULL; lppd = lppd->lppdNext) {
+
+ if (lppd->pstate == psDestroyed) {
+ continue;
+ }
+
+ OSDGetDebugMetric(mtrcPidValue, lppd->hpid, 0, (LPL) &rgb);
+ EEFormatMemory(rgch, cbPid*2+1, rgb, cbPid*8, fmtUInt|fmtZeroPad, 16);
+ OSDPtrace(osdProcStatus, 0, &lpzStatus, lppd->hpid, 0);
+
+ CmdLogFmt("%c%2d %s %s\r\n", lppd == LppdCur? '*' : ' ', lppd->ipid, rgch, lpzStatus);
+ }
+#endif
+
+ return LOGERROR_NOERROR;
+} /* LogProcess() */
+
+
+LOGERR NEAR PASCAL
+LogRestart(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This routine will restart the debuggee. If needed it will change
+ the command line as well. If there is no command line present
+ then the command line is not changed.
+
+Arguments:
+
+ lpsz - Supplies new command line to be used
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ lpsz = CPSkipWhitespace(lpsz);
+
+ CmdInsertInit();
+
+ if ( LppdCur && IsProcRunning( LppdCur ) ) {
+ CmdLogVar(ERR_Stop_B4_Restart);
+ return LOGERROR_QUIET;
+ }
+
+ if (runDebugParams.fKernelDebugger && DebuggeeActive()) {
+ CmdLogFmt("Target system already running\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ if (*lpsz) {
+ if (LpszCommandLine) {
+ free(LpszCommandLine);
+ }
+ LpszCommandLine = _strdup(lpsz);
+ }
+
+ if (!ExecDebuggee(EXEC_RESTART)) {
+ return LOGERROR_UNKNOWN;
+ }
+ return LOGERROR_NOERROR;
+} /* LogRestart() */
+
+
+LOGERR PASCAL NEAR
+LogStep(
+ LPSTR lpsz,
+ BOOL fStep
+ )
+/*++
+
+Routine Description:
+
+ This function is used from the command line to do either a
+ step or a trace. If an argument is present it is assumed
+ to be a count for a number of steps to make
+
+Arguments:
+
+ lpsz - Supplies argument list for step/trace count
+ fStep - Supplies TRUE to step or FALSE to trace
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ int cStep;
+ int err;
+ int cch;
+ CXF cxf = CxfIp;
+ LPPD LppdT;
+ LPTD LptdT;
+ BOOL fRegisters = FALSE;
+ LOGERR rVal = LOGERROR_NOERROR;
+
+
+ CmdInsertInit();
+ if (runDebugParams.fKernelDebugger && runDebugParams.KdParams.fUseCrashDump) {
+ CmdLogFmt( "Steps are not allowed for crash dumps\n" );
+ return rVal;
+ }
+
+ // NOTENOTE a-kentf thread wildcard is supposed to be valid here (LogStep)
+ TDWildInvalid();
+ PDWildInvalid();
+
+
+ PreRunInvalid();
+
+ /*
+ * Check for no argument -- then just do a single step or trace
+ */
+
+ if (*lpsz == 'r') {
+ fRegisters = TRUE;
+ lpsz++;
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ cStep = 1;
+
+ if (*lpsz != 0) {
+ cStep = (int) CPGetInt(lpsz, &err, &cch);
+ if (err || cStep < 1) {
+ CmdLogVar(ERR_Bad_Count);
+ return LOGERROR_QUIET;
+ }
+ }
+
+ /*
+ ** If the debuggee is not loaded then we need to get it loaded so that
+ ** we have symbols that can be evaluated
+ */
+ if (!DebuggeeAlive()) {
+ if (!ExecDebuggee(EXEC_RESTART)) {
+ CmdLogVar(ERR_Cant_Start_Proc);
+ return LOGERROR_QUIET;
+ }
+ LppdCommand = LppdCur;
+ LptdCommand = LppdCur->lptdList;
+ }
+
+ /*
+ * make sure thread is now runnable
+ */
+
+ if (!StepOK(LppdCommand, LptdCommand)) {
+ NoRunExcuse(LppdCommand, LptdCommand);
+ return LOGERROR_QUIET;
+ }
+
+ LppdT = LppdCur;
+ LptdT = LptdCur;
+
+ if (LptdCur != LptdCommand) {
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ if (ExecDebuggee( fStep ? EXEC_STEPOVER : EXEC_TRACEINTO ) == 0) {
+ if (LptdCur) {
+ LptdCur->cStepsLeft = 0;
+ }
+ rVal = LOGERROR_UNKNOWN;
+ } else {
+ Assert(LptdCur);
+ LptdCur->cStepsLeft = cStep - 1;
+ LptdCur->flags &= ~tfStepOver;
+ LptdCur->flags |= (fStep ? tfStepOver : 0);
+ LptdCur->fRegisters = fRegisters;
+ LptdCur->fDisasm = TRUE;
+ rVal = LOGERROR_NOERROR;
+ }
+
+ if (LptdT != LptdCur) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ return rVal;
+} /* LogStep() */
+
+
+LOGERR NEAR PASCAL
+LogThread(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Enumerate threads
+
+Arguments:
+
+ None
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LPPD lppd;
+
+ CmdInsertInit();
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ return LOGERROR_QUIET;
+ }
+
+ if (LppdCommand == NULL) {
+
+ CmdLogVar(ERR_No_Threads);
+
+ } else if (LppdCommand != (LPPD)-1) {
+
+ ThreadStat(LppdCommand);
+
+ } else {
+ for (lppd = GetLppdHead(); lppd; lppd = lppd->lppdNext) {
+ if (lppd->pstate == psDestroyed) {
+ continue;
+ }
+ CmdLogFmt("\r\nProcess %d:\r\n", lppd->ipid);
+ ThreadStat(lppd);
+ }
+ }
+
+ return LOGERROR_NOERROR;
+} /* LogThread() */
+
+
+LOGERR NEAR PASCAL
+LogLoadDefered(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Loads defered symbols for a module
+
+Arguments:
+
+ lpsz - Supplies new command line to be used
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LOGERR LogErr = LOGERROR_QUIET;
+ HEXE hexe;
+ LPDEBUGDATA DebugData;
+
+ CmdInsertInit();
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if ( *lpsz == 0 ) {
+
+ CmdLogFmt( "Load: Must specify module name\r\n" );
+
+ } else {
+
+ hexe = SHGethExeFromName( lpsz );
+
+ if ( hexe ) {
+
+ DebugData = SHGetDebugData( hexe );
+
+ if ( DebugData ) {
+
+ if ( DebugData->she == sheDeferSyms ) {
+ SHWantSymbols( hexe );
+ }
+
+ } else {
+
+ CmdLogFmt( "Load: Could not load %s\r\n", lpsz );
+ }
+
+ } else {
+
+ CmdLogFmt( "Load: Could not load %s\r\n", lpsz );
+ }
+ }
+
+ return LogErr;
+}
+
+
+LOGERR NEAR PASCAL
+LogWatchTime(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Loads defered symbols for a module
+
+Arguments:
+
+ lpsz - Supplies new command line to be used
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ LOGERR LogErr = LOGERROR_QUIET;
+ int cch;
+ ADDR addr;
+ ADDR addr1;
+ CXT cxt;
+ HDEP hsyml;
+ PHSL_HEAD lphsymhead;
+ PHSL_LIST lphsyml;
+ UINT n;
+ DWORD dwOff;
+ DWORD dwOffP;
+ DWORD dwOffN;
+ DWORD dwAddrP;
+ DWORD dwAddrN;
+ HSYM hsymP;
+ HSYM hsymN;
+ HDEP hstr;
+ EESTATUS eest;
+ char szContext[MAX_USER_LINE];
+ char szStr[MAX_USER_LINE];
+ PIOCTLGENERIC pig;
+ LPBYTE lpb;
+
+
+ CmdInsertInit();
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (_stricmp(lpsz,"stop")==0) {
+
+ pig = (PIOCTLGENERIC) malloc( sizeof(IOCTLGENERIC) );
+ if (!pig) {
+ CmdLogFmt("Could not allocate memory for wt command\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ pig->ioctlSubType = IG_WATCH_TIME_STOP;
+ pig->length = 0;
+
+ OSDIoctl( LppdCur->hpid, LptdCur->htid, ioctlGeneric, sizeof(IOCTLGENERIC), (LPV)pig );
+
+ free( pig );
+
+ return LogErr;
+ }
+
+ //
+ // first lets do an effective loglistnear command
+ //
+
+ if (!CPGetAddress(".", &cch, &addr, 16, &CxfIp, FALSE, FALSE) == 0) {
+ CmdLogFmt("Could not find a symbol for current location\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ ZeroMemory(&cxt, sizeof(cxt));
+ SHSetCxt(&addr, &cxt);
+
+ hsyml = 0;
+ eest = EEGetHSYMList(&hsyml, &cxt, HSYMR_public, NULL, TRUE);
+ if (eest != EENOERROR) {
+ CmdLogFmt("Could not find a symbol for current location\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ lphsymhead = MMLpvLockMb ( hsyml );
+ lphsyml = (PHSL_LIST)(lphsymhead + 1);
+
+ dwOffP = 0xffffffff;
+ dwOffN = 0xffffffff;
+ dwAddrP = 0xffffffff;
+ dwAddrN = 0xffffffff;
+ hsymP = 0;
+ hsymN = 0;
+
+ SYFixupAddr(&addr);
+ addr1 = addr;
+ for ( n = 0; n < (UINT)lphsyml->symbolcnt; n++ ) {
+
+ if (SHAddrFromHsym(&addr1, lphsyml->hSym[n])) {
+ SYFixupAddr(&addr1);
+ if (GetAddrSeg(addr1) != GetAddrSeg(addr)) {
+ continue;
+ }
+ if (GetAddrOff(addr1) <= GetAddrOff(addr)) {
+ dwOff = GetAddrOff(addr) - GetAddrOff(addr1);
+ if (dwOff < dwOffP) {
+ dwOffP = dwOff;
+ dwAddrP = GetAddrOff(addr1);
+ hsymP = lphsyml->hSym[n];
+ }
+ } else {
+ dwOff = GetAddrOff(addr1) - GetAddrOff(addr);
+ if (dwOff < dwOffN) {
+ dwOffN = dwOff;
+ dwAddrN = GetAddrOff(addr1);
+ hsymN = lphsyml->hSym[n];
+ }
+ }
+ }
+
+ }
+
+ MMbUnlockMb(hsyml);
+ MMFreeHmem(hsyml);
+
+ if (!hsymP || !hsymN) {
+ CmdLogFmt("Could not find a symbol for current location\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ EEFormatCXTFromPCXT( &cxt, &hstr, runDebugParams.fShortContext );
+ if (runDebugParams.fShortContext) {
+ strcpy( szContext, (LPSTR)MMLpvLockMb(hstr) );
+ } else {
+ BPShortenContext( (LPSTR)MMLpvLockMb(hstr), szContext );
+ }
+ MMbUnlockMb(hstr);
+ EEFreeStr(hstr);
+ FormatHSym(hsymP, &cxt, szStr);
+ strcat(szContext,szStr);
+
+ //
+ // now notify the dm that the wt command should start now
+ //
+
+ n = (2 * sizeof(DWORD)) + strlen(szContext) + 1;
+
+ pig = (PIOCTLGENERIC) malloc( n + sizeof(IOCTLGENERIC) );
+ if (!pig) {
+ CmdLogFmt("Could not allocate memory for wt command\r\n");
+ return LOGERROR_QUIET;
+ }
+
+ pig->ioctlSubType = IG_WATCH_TIME;
+ pig->length = n;
+
+ lpb = (LPBYTE) pig->data;
+ *(LPDWORD)lpb = dwAddrP;
+ lpb += sizeof(DWORD);
+ *(LPDWORD)lpb = dwAddrN - 1;
+ lpb += sizeof(DWORD);
+ strcpy(lpb,szContext);
+
+ OSDIoctl( LppdCur->hpid, LptdCur->htid, ioctlGeneric, n + sizeof(IOCTLGENERIC), (LPV)pig );
+
+ free( pig );
+
+ return LogErr;
+}
diff --git a/private/windbg/windbg/cmdexec2.c b/private/windbg/windbg/cmdexec2.c
new file mode 100644
index 000000000..5e0d224ee
--- /dev/null
+++ b/private/windbg/windbg/cmdexec2.c
@@ -0,0 +1,3297 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cmdexec2.c
+
+Abstract:
+
+ This file contains the commands for examining and modifying
+ debuggee data - memory and registers.
+
+Author:
+
+ Kent Forschmiedt (a-kentf) 20-Jul-92
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+
+//Prototypes
+
+void NEAR PASCAL CmdAsmPrompt (BOOL,BOOL);
+BOOL NEAR PASCAL CmdAsmLine (LPSTR lpsz);
+void NEAR PASCAL CmdEnterPrompt (BOOL,BOOL);
+BOOL NEAR PASCAL CmdEnterLine (LPSTR lpsz);
+LOGERR NEAR PASCAL DoEnterMem (LPSTR lpsz,LPADDR lpAddr,int type,BOOL fMulti);
+LOGERR NEAR PASCAL GetValueList (LPSTR lpsz,int type,BOOL fMulti,LPBYTE lpBuf,int cchBuf,LPINT pcb);
+int NEAR PASCAL LetterToType (char c);
+BOOL mismatch (ADDR addr0,LPBYTE lpBuf0,ADDR addr1,LPBYTE lpBuf1,int len);
+LOGERR NEAR PASCAL LogAssemble (LPSTR lpsz);
+LOGERR NEAR PASCAL LogCompare (LPSTR lpsz);
+LOGERR NEAR PASCAL LogDumpMem (char chType, LPSTR lpsz);
+LOGERR NEAR PASCAL LogEnterMem (LPSTR lpsz);
+LOGERR NEAR PASCAL LogFill (LPSTR lpsz);
+LOGERR NEAR PASCAL LogMovemem (LPSTR lpsz);
+LOGERR NEAR PASCAL LogRegisters (LPSTR lpsz, BOOL fFP);
+LOGERR NEAR PASCAL LogSearch (LPSTR lpsz);
+
+BOOL NEAR PASCAL
+StringLogger(
+ LPSTR szStr,
+ BOOL fFileLog,
+ BOOL fSendRemote,
+ BOOL fPrintLocal
+ );
+
+
+/************************** Data declaration *************************/
+
+/****** Publics ********/
+
+extern LPPD LppdCommand;
+extern LPTD LptdCommand;
+
+extern BOOL FSetLptd; // Was thread specified
+extern BOOL FSetLppd; // Was process specified
+
+extern ULONG ulPseudo[];
+extern LPSTR lpszLastSearch;
+
+/****** Locals ********/
+
+struct dmfi {
+ int cBytes;
+ UINT fmtType;
+ UINT radix;
+ UINT cAcross;
+ UINT cchItem;
+ UINT cItems;
+};
+
+static struct dmfi dmfi[] = {
+// cBytes fmtType radix cAcross cchItem cItems
+ { 1, fmtAscii, 0, 32, 1, 32*8}, // 0
+ { 1, fmtUInt, 16, 16, 2, 16*8}, // 1
+ { 2, fmtUInt, 16, 8, 4, 8*8}, // 2
+ { 4, fmtUInt, 16, 4, 8, 4*8}, // 3
+ { 4, fmtFloat, 10, 1, 14, 1*8}, // 4
+ { 8, fmtFloat, 10, 1, 22, 1*8}, // 5
+ {10, fmtFloat, 10, 1, 30, 1*8}, // 6
+ { 2, fmtUnicode, 0, 32, 1, 32*8} // 7
+};
+
+//
+// Command help text.
+//
+static char *HelpText[] = {
+ "[__GENERAL__]",
+ " Enter Help <command> for help on a specific command. ",
+ " Help is available on the following commands: ",
+ " ",
+ " ? Evaluate expression ",
+ " . Dot command ",
+ " ! Execute extension ",
+ " # Regular expression search thru dissasm ",
+ " %% Changes current context to the stack frame specified ",
+ " BC Clear breakponts ",
+ " BE Enable breakpoints ",
+ " BD Disable breakpoints ",
+ " BL List breakpoints ",
+ " BP Set breakpoints ",
+ " C Compare memory ",
+ " D Dump memory ",
+ " E Enter memory ",
+ " F Freeze/Thaw thread ",
+ " FI Fill memory ",
+ " FR Display/Enter FP regs. ",
+ " G Go ",
+ " Help Help ",
+ " K Stack trace ",
+ " L Restart ",
+ " LD Load defered symbols ",
+ " LM List loaded modules",
+ " LN List near symbols ",
+ " M Move memory ",
+ " N Set radix ",
+ " P Program step ",
+ " Q Quit ",
+ " R Display/Enter register ",
+ " REMOTE Start remote server ",
+ " S Search memory ",
+ " S+ Enable source mode ",
+ " S- Disable source mode ",
+ " SE Set error level ",
+ " SX List exception actions ",
+ " SXD Disable exception actions ",
+ " SXN Notify on exception ",
+ " SXE Enable exception ",
+ " T Trace into ",
+ " U Unfreeze thread ",
+ " X Find symbols ",
+ " Z Freeze/Thaw thread ",
+ " <addr> Address expression ",
+ " <range> Range expression ",
+ " ",
+ "[ ? ] ",
+ " ? <expression> - Evaluates an expression ",
+ " ?. - Lists local variables for current context ",
+ " ",
+ "[ . ] ",
+ " .<command> - Execute given dot-command ",
+ " ",
+ " For a list of available dot-commands, type \".?\" ",
+ " ",
+ "[ ! ] ",
+ " ![Dll].<Extension> - Execute an extension ",
+ " ",
+ "[ # ] ",
+ " # [pattern] - Search for pattern ",
+ " ",
+ "[ % ] ",
+ " %<frame-number> - Changes current context to the stack frame specified ",
+ " Hint: use 'KN' command to get frame number ",
+ " ",
+ "[ BC ] ",
+ " BC <id-list> - Clear specified breakpoints ",
+ " ",
+ "[ BE ] ",
+ " BE <id-list> - Enable specified breakpoints ",
+ " ",
+ "[ BD ] ",
+ " BD <id-list> - Disable specified breakpoints ",
+ " ",
+ "[ BL ] ",
+ " BL <id-list> - List specified breakpoints ",
+ " ",
+ "[ BP ] ",
+ " BP[id] <condition> [<options>] - Set a breakpoint ",
+ " ",
+ " id - Assign given id to the breakpoint. ",
+ " condition - Break condition: ",
+ " ",
+ " [context]@<line> - Break at source line ",
+ " ?<expression> - Break if expression is true ",
+ " =<addr> [/R<size>] - Break if memory has changed ",
+ " ",
+ " [context]<addr> [msg-condition] ",
+ " - Break at address ",
+ " msg-condition: ",
+ " /M<msg-name> - Message name to check for ",
+ " /M<msg-class> - Message class to check for ",
+ " msg-class can be a combination of: ",
+ " M - Mouse ",
+ " W - Window ",
+ " N - Input ",
+ " S - System ",
+ " I - Init ",
+ " C - Clipboard ",
+ " D - DDE ",
+ " Z - Nonclient ",
+ " ",
+ " options: ",
+ " ",
+ " /P<count> - Skip first <count> times ",
+ " /Q - Suppress unresolved BP dialog ",
+ " /H<number> - Attach BP to process <number> ",
+ " /T<number> - Attach BP to thread <number> ",
+ " /C\"<cmd-list>\" - Execute <cmd-list> when hit ",
+ " ",
+ "[ C ] ",
+ " C [range] [addr] - Compare memory ",
+ " ",
+ "[ D ] ",
+ " D<mode> <addr> | <range> - Dump memory ",
+ " ",
+ " mode - Can be one of the following: ",
+ " ",
+ " C - Code (Disassembly) ",
+ " A - ASCII ",
+ " U - Unicode ",
+ " B - Byte ",
+ " W - Word ",
+ " D - Doubleword ",
+ " S - 4-byte real ",
+ " I - 8-byte real ",
+ " T - 10-byte real ",
+ " ",
+ "[ E ] ",
+ " E<mode> <addr> [value-list] - Enter memory ",
+ " ",
+ " mode - Can be one of the following: ",
+ " ",
+ " A - ASCII ",
+ " U - Unicode ",
+ " B - Byte ",
+ " W - Word ",
+ " D - Doubleword ",
+ " S - 4-byte real ",
+ " I - 8-byte real ",
+ " T - 10-byte real ",
+ " ",
+ "[ F ] ",
+ "[ Z ] ",
+ " ~[.|*|<id>]F - Freezes specified thread. ",
+ " ~[.|*|<id>]Z ",
+ " ",
+ "[ FI ] ",
+ " FI<mode> <range> <value-list> - Fill memory ",
+ " ",
+ " mode - Can be one of the following ",
+ " ",
+ " A - ASCII ",
+ " U - Unicode ",
+ " B - Byte ",
+ " W - Word ",
+ " D - Doubleword ",
+ " S - 4-byte real ",
+ " I - 8-byte real ",
+ " T - 10-byte real ",
+ " ",
+ "[ FR ] ",
+ " FR [<reg>[=<value>]] - Display/Enter floating-point register ",
+ " ",
+ "[ G ] ",
+ " G [=<start>] [break] - Starts execution at start, and continues ",
+ " until break. ",
+ " ",
+ " GH - Go, mark exception as handled ",
+ " ",
+ " GN - Go, mark exception as not handled ",
+ " ",
+ "[ Help ] ",
+ " Help [command] - Display help ",
+ " ",
+ " Displays help on a specific command. For a list of all ",
+ " available commands, ommit the command argument. ",
+ " ",
+ "[ K ] ",
+ " K<BSVN> [=frameaddr stackaddr programcounter] [<frames>] - Dump stack trace ",
+ " ",
+ " B - Stack trace includes 3 dwords from stack ",
+ " S - Stack trace includes source file and line number ",
+ " V - Stack trace includes runtime function information ",
+ " N - Stack trace includes frame number ",
+ " ",
+ "[ L ] ",
+ " L - Restarts debuggee ",
+ " ",
+ "[ LD ] ",
+ " LD <module-name> - Loads defered symbols for specified ",
+ " module. ",
+ " ",
+ "[ LM ] ",
+ " LM [f|s [o]] [module-name] - List loaded module information ",
+ " ",
+ " f - List flat modules ",
+ " s - List segmented modules ",
+ " o - Sort segmented modules by selector ",
+ " ",
+ "[ LN ] ",
+ " LN <addr> - List near symbols ",
+ " ",
+ "[ M ] ",
+ " M <range> <addr> - Move memory ",
+ " ",
+ "[ N ] ",
+ " N<radix> - Set default radix ",
+ " ",
+ " radix - Can be 8, 10, or 16 ",
+ " ",
+ "[ P ] ",
+ " P [repeat] - Program step ",
+ " ",
+ "[ Q ] ",
+ " Q - Quits WinDbg ",
+ " ",
+ "[ R ] ",
+ " R [<reg>[=<value>]] - Display/Enter register ",
+ " ",
+ "[ REMOTE ] ",
+ " REMOTE <pipe name> - Start remote server for pipe name",
+ " REMOTE - Display remote server status",
+ " REMOTE stop - Terminate the remote server",
+ " ",
+ "[ S ] ",
+ " S <range> <value-list> - Search memory ",
+ " ",
+ "[ S+ ] ",
+ "[ S- ] ",
+ " S+ - Enable source mode ",
+ " S- - Disable source mode ",
+ " ",
+ "[ SE ] ",
+ " SE<B|W> [0-3] - Set RIP break/warning level ",
+ " ",
+ " B - Set break level ",
+ " W - Set warning level ",
+ " ",
+ "[ SX ] ",
+ " SX - List exception actions ",
+ " ",
+ "[ SXD ] ",
+ " SXD <exception> [name] - Disables specified exception action ",
+ " ",
+ "[ SXN ] ",
+ " SXN <exception> [name] - Notify on exception ",
+ " ",
+ "[ SXE ] ",
+ " SXE <exception> [/C cmd] [name] - Enable exception action ",
+ " ",
+ "[ T ] ",
+ " T [repeat] - Trace into ",
+ " ",
+ "[ U ] ",
+ " U <addr> - Unassemble ",
+ " ",
+ "[ X ] ",
+ " X<scope> [context]<pattern> - Find symbols within the ",
+ " given scope that match ",
+ " the specified pattern. ",
+ " ",
+ " scope - A combination of the following: ",
+ " ",
+ " L - Lexical ",
+ " F - Function ",
+ " C - Class ",
+ " M - Module ",
+ " E - Exe ",
+ " P - Public ",
+ " G - Global ",
+ " * - All ",
+ " ",
+ " Note: The command \"x*!\" has the magic meaning ",
+ " of listing loaded modules, i.e. it is equivalent ",
+ " to the LM command. ",
+ " ",
+ "[ <addr> ] ",
+ " Any valid expression may be used where an address ",
+ " is required. Windbg recognizes standard C/C++ expressions, ",
+ " so any of the following are syntactically valid: ",
+ " ",
+ " 0x55000 ",
+ " MyDll!MyFunc ",
+ " szBuffer+6 ",
+ " ",
+ "[ <range> ] ",
+ " A range expression is one of: ",
+ " ",
+ " <addr1> <addr2> ",
+ " Addresses from addr1 to addr2, inclusive ",
+ " ",
+ " <addr> L <count> ",
+ " Addresses from addr extending for <count> items. The ",
+ " size of the item is determined by the command; for ",
+ " example, the dd command has a size of 4, while db has ",
+ " an item size of 1. "
+ " ",
+ " <addr> I <integer expression> ",
+ " only valid in the U command: specifies a count in ",
+ " instructions rather than a fixed byte size. ",
+ " ",
+ "[__END__]"
+};
+
+
+#define IsTopicHeader(p) (*(p) == '[')
+
+
+
+// These are always stored in fixed-up form, never module relative.
+static ADDR addrLastDumpStart;
+static ADDR addrLastDumpEnd;
+static ADDR addrLastEnterStart;
+static ADDR addrLastEnterEnd;
+
+ADDR addrLastDisasmStart;
+static ADDR addrLastDisasmEnd;
+
+static ADDR addrAsm; // for assemble and enter commands
+static int nEnterType; // data type for interactive enter
+static int cEnterItem; // item offset from enter address
+
+
+/****** Externs from ??? *******/
+
+extern LPSHF Lpshf; // vector table for symbol handler
+extern CXF CxfIp;
+extern EI Ei;
+
+/************************** Code *************************/
+
+
+
+/******************************************************************************
+ *
+ * Functions for displaying help
+ *
+ ******************************************************************************/
+
+BOOL
+TopicMatch (
+ char * Header,
+ char * Topic
+ )
+{
+ char HdrBuf[ MAX_PATH ];
+ char TopicBuf[ MAX_PATH ];
+ char *p;
+ size_t i;
+ BOOL Match = FALSE;
+
+ i = strspn( Header, "[ \t" );
+ p = Header+i;
+ strcpy( HdrBuf, p );
+ p = strpbrk( HdrBuf, " \t]" );
+
+ if ( p ) {
+ *p = 0;
+
+ i = strspn( Topic, " \t" );
+ p = Topic+i;
+ strcpy( TopicBuf, p );
+ p = strpbrk( TopicBuf, " \t" );
+
+ if ( p ) {
+ *p = 0;
+ }
+
+ Match = !_stricmp( HdrBuf, TopicBuf );
+ }
+
+ return Match;
+}
+
+
+char **
+FindTopic(
+ LPSTR Topic
+ )
+{
+ char **Text = HelpText;
+
+ while ( Text ) {
+ if ( IsTopicHeader( *Text ) ) {
+
+ if ( TopicMatch( *Text, "__END__" ) ) {
+
+ Text = NULL;
+ break;
+
+ } else if ( TopicMatch( *Text, Topic ) ) {
+
+ while ( IsTopicHeader( *Text ) ) {
+ Text++;
+ }
+ break;
+ }
+ }
+ Text++;
+ }
+
+ return Text;
+}
+
+
+BOOL
+DisplayTopic(
+ LPSTR Topic
+ )
+{
+ char **TopicText;
+ BOOL Found = FALSE;
+
+ TopicText = FindTopic( Topic );
+
+ if ( TopicText ) {
+ Found = TRUE;
+ while ( !IsTopicHeader( *TopicText ) ) {
+ CmdLogFmt( *TopicText );
+ CmdLogFmt( "\r\n" );
+ TopicText++;
+ }
+ }
+
+ return Found;
+}
+
+
+BOOL
+CmdHelp (
+ LPSTR Topic
+ )
+/*++
+
+Routine Description:
+
+ Displays help, either general or for a specific topic
+
+Arguments:
+
+ Topic - Supplies topic (NULL for general help)
+
+Return Value:
+
+ FALSE if topic not found.
+
+--*/
+{
+ BOOL Found = TRUE;
+
+ if ( Topic ) {
+
+ if ( !DisplayTopic( Topic) ) {
+ CmdLogFmt( "No help available on %s\r\n", Topic );
+ Found = FALSE;
+ }
+
+ } else {
+
+ DisplayTopic( "__GENERAL__" );
+ }
+
+ return Found;
+}
+
+
+
+/************************************************************************************
+ *
+ * Helper and common functions
+ *
+ ************************************************************************************/
+
+void NEAR PASCAL
+CmdAsmPrompt(
+ BOOL fRemote,
+ BOOL fLocal
+ )
+/*++
+
+Routine Description:
+
+ Print the address prompt string for assembler input.
+ Set the printed area readonly.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ char szStr[100];
+ uint flags;
+
+ if (runDebugParams.ShowSegVal) {
+ flags = EEFMT_SEG;
+ } else {
+ flags = EEFMT_32;
+ SYFixupAddr( &addrAsm );
+ }
+
+ CmdInsertInit();
+
+ EEFormatAddr( &addrAsm, szStr, sizeof(szStr), flags);
+ strcat(szStr, "> ");
+
+ StringLogger(szStr, TRUE, fRemote, fLocal );
+} /* CmdAsmPrompt */
+
+
+BOOL NEAR PASCAL
+CmdAsmLine(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Assemble one line.
+
+Arguments:
+
+ lpsz - Supplies string containing line to be assembled
+
+Return Value:
+
+ Always TRUE; this is a synchronous command.
+
+--*/
+{
+ XOSD xosd;
+
+ /*
+ ** We got only the part of the line that the user typed
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ /*
+ ** Check for blank line
+ */
+
+ AuxPrintf(0, "Asm: \"%s\"", lpsz);
+
+ lpsz = CPSkipWhitespace( lpsz );
+ if (*lpsz == 0) {
+
+ CmdSetDefaultCmdProc();
+
+ } else {
+
+ /*
+ ** Assemble up the line
+ */
+
+ ADDR addrT = addrAsm;
+ xosd = OSDAssemble( LppdCur->hpid, LptdCur->htid, &addrT, lpsz);
+ if (xosd != xosdNone) {
+ CmdLogVar(ERR_Bad_Assembly);
+ } else {
+ addrAsm = addrT;
+ }
+ }
+ return TRUE;
+} /* CmdAsmLine() */
+
+
+void NEAR PASCAL
+CmdEnterPrompt(
+ BOOL fRemote,
+ BOOL fLocal
+ )
+/*++
+
+Routine Description:
+
+ Print prompt line for interactive enter
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ char bBuf[30];
+ char szStr[200];
+ LPSTR pStr;
+ int cb;
+#ifdef OSDEBUG4
+ XOSD xosd;
+#endif
+
+ CmdInsertInit();
+
+ pStr = szStr;
+
+ EEFormatAddr(&addrAsm, pStr, sizeof(szStr) - (pStr - szStr),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ strcat(szStr, " ");
+ pStr += strlen(szStr);
+
+#ifdef OSDEBUG4
+ xosd = OSDReadMemory(LppdCur->hpid, LptdCur->htid, &addrAsm, bBuf,
+ dmfi[nEnterType].cBytes, &cb);
+ if (xosd != xosdNone) {
+ cb = 0;
+ }
+#else
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addrAsm) == xosdNone);
+ cb = OSDPtrace(osdReadBuf, dmfi[nEnterType].cBytes,
+ bBuf, LppdCur->hpid, LptdCur->htid);
+#endif
+
+ if (cb != dmfi[nEnterType].cBytes) {
+
+ memset(pStr, '?', dmfi[nEnterType].cchItem);
+ pStr[dmfi[nEnterType].cchItem] = 0;
+ pStr += strlen(pStr);
+
+ } else {
+
+ int rdx = dmfi[nEnterType].radix;
+ int fmt = dmfi[nEnterType].fmtType;
+ int cch = dmfi[nEnterType].cchItem;
+ if (rdx == 16) {
+ rdx = radix;
+ if (rdx == 8) {
+ cch = (dmfi[nEnterType].cBytes * 8 + 2) / 3;
+ } else if (rdx == 10) {
+ // this is close...
+ cch = (dmfi[nEnterType].cBytes * 8 + 1) / 3;
+ }
+ }
+ if (rdx == 16 || rdx == 8) {
+ fmt |= fmtZeroPad;
+ }
+ EEFormatMemory(pStr,
+ cch + 1,
+ bBuf,
+ dmfi[nEnterType].cBytes*8,
+ fmt,
+ rdx);
+
+ pStr += strlen(pStr);
+ }
+
+ strcat(pStr, "> ");
+ StringLogger(szStr, TRUE, fRemote, fLocal);
+}
+
+
+BOOL NEAR PASCAL
+CmdEnterLine(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Handle a line entered by the user in interactive enter mode. This takes
+ one data item at a time, writes it to memory, and increments the memory
+ pointer by the size of the data item.
+
+Arguments:
+
+ lpsz - Supplies string to be parsed into a data item
+
+Return Value:
+
+ Always TRUE, signifying a synchronous command
+
+--*/
+{
+ int err;
+
+ if (*lpsz == '\0') {
+ // empty line - all done.
+ CmdSetDefaultCmdProc();
+ }
+ else if ( *(lpsz = CPSkipWhitespace(lpsz)) == '\0'
+ || (*lpsz == '/' && *CPSkipWhitespace(lpsz+1) == '\0'))
+ {
+ // space(s) or '/' on empty line - keep old value and step
+ GetAddrOff(addrAsm) += dmfi[nEnterType].cBytes;
+ addrLastEnterEnd = addrAsm;
+ }
+ else
+ {
+ err = DoEnterMem(lpsz, &addrAsm, nEnterType, FALSE);
+ if (err == LOGERROR_UNKNOWN) {
+ CmdLogVar(ERR_Edit_Failed);
+ } else {
+ addrLastEnterEnd = addrAsm;
+ }
+ }
+
+ return TRUE;
+}
+
+
+LOGERR NEAR PASCAL
+DoEnterMem(
+ LPSTR lpsz,
+ LPADDR lpAddr,
+ int type,
+ BOOL fMulti
+ )
+/*++
+
+Routine Description:
+
+ Executive for all styles of E commands. Takes an argument list, decodes
+ it and stores data.
+
+Arguments:
+
+ lpsz - Supplies text of data to parse
+ lpAddr - Supplies address where data are to be stored
+ type - Supplies type of data expected
+ fMulti - Supplies flag for whether to allow multiple items
+
+Return Value:
+
+ LOGERR code
+
+--*/
+{
+ int cb;
+ BYTE buf[2 * MAX_USER_LINE];
+ LOGERR rVal;
+ XOSD xosd;
+
+ rVal = GetValueList(lpsz, type, fMulti, buf, sizeof(buf), &cb);
+ if (rVal == LOGERROR_NOERROR) {
+
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, lpAddr) == xosdNone);
+ xosd = OSDPtrace(osdWriteBuf, cb, buf, LppdCur->hpid, LptdCur->htid);
+ UpdateDebuggerState(UPDATE_DATAWINS);
+
+ if (xosd == xosdNone) {
+ GetAddrOff(*lpAddr) += cb;
+ } else {
+ CmdLogVar(ERR_Edit_Failed);
+ rVal = LOGERROR_QUIET;
+ }
+ }
+ return rVal;
+} /* DoEnterMem() */
+
+
+LOGERR NEAR PASCAL
+GetValueList(
+ LPSTR lpsz,
+ int type,
+ BOOL fMulti,
+ LPBYTE lpBuf,
+ int cchBuf,
+ LPINT pcb
+ )
+/*++
+
+Routine Description:
+
+ This parses value lists for enter, fill, and search commands.
+ This function wants to consume the entire string, and will print
+ a message and return an error code if it cannot.
+
+Arguments:
+
+ lpsz - Supplies string to be parsed
+ type - Supplies data type
+ fMulti - Supplies multiple items allowed if TRUE
+ lpBuf - Returns parsed data
+ pcb - returns bytes count of result
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ CHAR chQuote;
+ CHAR szCopyBuf[MAX_USER_LINE];
+ CHAR szMisc[500];
+ LPBYTE lpb;
+ int cch;
+ int cb;
+ int i;
+ DWORD dw;
+
+ //
+ // get value list
+ //
+ switch (type) {
+ default:
+ return LOGERROR_UNKNOWN;
+
+ case LOG_DM_ASCII:
+ case LOG_DM_UNICODE:
+
+ // accept a string of some length
+ // M00UNICODE this assumes that console input is ANSI
+
+ chQuote = *lpsz;
+ cb = CPCopyString(&lpsz, szCopyBuf, '\\', chQuote == '\'' || chQuote == '"');
+ if (cb == 0 || *(lpsz = CPSkipWhitespace(lpsz)) != '\0')
+ {
+ CmdLogVar(ERR_String_Invalid);
+ return LOGERROR_QUIET;
+ }
+ if (chQuote == '"') {
+ // include \0 in quoted strings
+ cb++;
+ }
+
+ if (type == LOG_DM_ASCII) {
+ memcpy(lpBuf, szCopyBuf, cb);
+ } else {
+ mbtowc((WCHAR *)lpBuf, szCopyBuf, cb);
+ cb = 2 * MultiByteToWideChar(
+ CP_ACP,
+ 0,
+ szCopyBuf,
+ cb,
+ (LPWSTR)lpBuf,
+ cchBuf);
+ }
+
+ break;
+
+
+ case LOG_DM_BYTE:
+ case LOG_DM_WORD:
+ case LOG_DM_DWORD:
+////////////////////////////////////////////////////
+// //
+// If you add e.g. LOG_DM_QWORD here, you must //
+// change the CPGetCastNbr call and the //
+// decoding code to use the largest integer //
+// size supported! //
+// //
+////////////////////////////////////////////////////
+
+ lpb = lpBuf;
+ i = 0;
+ while (cch = CPCopyToken(&lpsz, szCopyBuf)) {
+
+ if (CPGetCastNbr(szCopyBuf,
+ T_LONG,
+ radix,
+ fCaseSensitive,
+ &CxfIp,
+ (LPSTR) &dw,
+ (LPSTR) &szMisc)
+ != EENOERROR)
+ {
+
+ CmdLogVar(ERR_Expr_Invalid);
+ return LOGERROR_QUIET;
+
+ } else {
+
+ switch (type) {
+ case LOG_DM_BYTE:
+ *lpb = (BYTE)dw;
+ break;
+
+ case LOG_DM_WORD:
+ *(WORD *)lpb = (WORD)dw;
+ break;
+
+ case LOG_DM_DWORD:
+ *(DWORD *)lpb = dw;
+ break;
+ }
+
+ i++;
+ lpb += dmfi[type].cBytes;
+
+ }
+ }
+
+ if (i > 1 && !fMulti) {
+ CmdLogVar(ERR_Expr_Invalid);
+ return LOGERROR_QUIET;
+ }
+
+ cb = i * dmfi[type].cBytes;
+
+ break;
+ case LOG_DM_4REAL:
+ case LOG_DM_8REAL:
+ case LOG_DM_TREAL:
+ lpb = lpBuf;
+ i = 0;
+ while (cch = CPCopyToken(&lpsz, szCopyBuf)) {
+
+ if (EEUnformatMemory(
+ lpb,
+ szCopyBuf,
+ 8 * dmfi[type].cBytes,
+ dmfi[type].fmtType,
+ radix )
+ != EENOERROR)
+ {
+
+ CmdLogVar(ERR_Expr_Invalid);
+ return LOGERROR_QUIET;
+
+ } else {
+
+ i++;
+ lpb += dmfi[type].cBytes;
+
+ }
+ }
+
+ if (i > 1 && !fMulti) {
+ CmdLogVar(ERR_Expr_Invalid);
+ return LOGERROR_QUIET;
+ }
+
+ cb = i * dmfi[type].cBytes;
+
+ break;
+
+ }
+
+ *pcb = cb;
+
+ return LOGERROR_NOERROR;
+} /* GetValueList() */
+
+
+int NEAR PASCAL
+LetterToType(
+ char c
+ )
+/*++
+
+Routine Description:
+
+ Parser helper function, returns type for d, e, f, s commands.
+
+Arguments:
+
+ c - character to map to a type code
+
+Return Value:
+
+ type code
+
+--*/
+{
+ int type;
+ switch (c) {
+ default:
+ type = LOG_DM_UNKNOWN;
+ break;
+ case 'b':
+ case 'B':
+ type = LOG_DM_BYTE;
+ break;
+ case 'w':
+ case 'W':
+ type = LOG_DM_WORD;
+ break;
+ case 'd':
+ case 'D':
+ type = LOG_DM_DWORD;
+ break;
+ case 'i':
+ case 'I':
+ type = LOG_DM_8REAL;
+ break;
+ case 's':
+ case 'S':
+ type = LOG_DM_4REAL;
+ break;
+ case 't':
+ case 'T':
+ type = LOG_DM_TREAL;
+ break;
+ case 'a':
+ case 'A':
+ type = LOG_DM_ASCII;
+ break;
+ case 'u':
+ case 'U':
+ type = LOG_DM_UNICODE;
+ break;
+ }
+ return type;
+}
+
+
+BOOL
+mismatch(
+ ADDR addr0,
+ LPBYTE lpBuf0,
+ ADDR addr1,
+ LPBYTE lpBuf1,
+ int len
+ )
+/*++
+
+Routine Description:
+
+ Helper for LogCompare(). Print addresses and bytes for any bytes not matching in
+ the two buffers.
+
+Arguments:
+
+ addr0 - Supplies debuggee address that data in lpBuf0 came from.
+ lpBuf0 - Supplies pointer to first data
+ addr1 - Supplies debuggee address that data in lpBuf1 came from.
+ lpBuf0 - Supplies pointer to second data
+ len - Supplies number of bytes to compare
+
+Return Value:
+
+ TRUE if buffers didn't match
+
+--*/
+{
+ int i;
+ char sza0[20];
+ char sza1[20];
+ BOOL fMismatch = FALSE;
+ for (i = 0; i < len; i++) {
+ if (lpBuf0[i] != lpBuf1[i]) {
+ fMismatch = TRUE;
+ EEFormatAddr(&addr0, sza0, sizeof(sza0),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ EEFormatAddr(&addr1, sza1, sizeof(sza1),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogFmt("%s %02x - %s %02x\r\n", sza0, lpBuf0[i], sza1, lpBuf1[i]);
+ }
+ GetAddrOff(addr0) += 1;
+ GetAddrOff(addr1) += 1;
+ }
+ return fMismatch;
+}
+
+
+//
+// miniature stdio
+//
+typedef struct tagMSTREAM {
+ BYTE *_ptr; // next char in buffer
+ int _cnt; // chars remaining in buffer
+ BYTE *_base; // base of buffer
+ int _flag; // error flag
+ ADDR _addr; // next read address
+ int _len; // limit; bytes unread
+} MSTREAM, FAR * LPMSTREAM;
+static MSTREAM mstream;
+#define getb(P) (--(P)->_cnt >= 0 ? *((P)->_ptr++) : filb(P))
+#define errorb(P) ((P)->_flag)
+#define MSE_END 1
+#define MSE_FAIL 2
+
+static LPMSTREAM
+openb(
+ LPADDR lpAddr,
+ int len
+ )
+/*++
+
+Routine Description:
+
+ Set up for stream input from debuggee memory at lpAddr, for maximum
+ of len bytes.
+
+Arguments:
+
+ lpAddr - Supplies pointer to ADDR struct for start address
+ len - Supplies maximum bytes to read
+
+Return Value:
+
+ None
+
+--*/
+{
+ mstream._cnt = 0;
+ mstream._addr = *lpAddr;
+ mstream._flag = 0;
+ mstream._len = len;
+ return &mstream;
+}
+
+
+static void
+tellb(
+ LPMSTREAM lpMstream,
+ LPADDR lpAddr
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ *lpAddr = lpMstream->_addr;
+ GetAddrOff(*lpAddr) -= lpMstream->_cnt;
+}
+
+
+static int
+filb(
+ LPMSTREAM lpMstream
+ )
+{
+ int cb;
+ if (lpMstream->_flag) {
+ return -1;
+ }
+ if (lpMstream->_base == NULL) {
+ lpMstream->_base = _fmalloc(MEMBUF_SIZE);
+ }
+
+ cb = lpMstream->_len < MEMBUF_SIZE ? lpMstream->_len : MEMBUF_SIZE;
+ if (cb < 1) {
+ lpMstream->_flag = MSE_END;
+ return -1;
+ }
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &lpMstream->_addr) == xosdNone);
+ cb = OSDPtrace(osdReadBuf, cb, lpMstream->_base, LppdCur->hpid, LptdCur->htid);
+ if (cb < 1) {
+ lpMstream->_flag = MSE_FAIL;
+ return -1;
+ }
+ GetAddrOff(lpMstream->_addr) += cb;
+ lpMstream->_len -= cb;
+ lpMstream->_cnt = cb - 1;
+ lpMstream->_ptr = lpMstream->_base;
+ return *lpMstream->_ptr++;
+}
+
+#ifdef _ALPHA_
+/************************************************************************************
+ *
+ * Command entry points
+ *
+ ************************************************************************************/
+
+LOGERR NEAR PASCAL
+LogAssemble(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This is the command used to start the assembler up.
+
+Arguments:
+
+ lpsz - arguments to assemble command
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ int cch;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+
+
+ PDWildInvalid();
+ TDWildInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ Assert( cmdView != -1);
+
+ CmdInsertInit();
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** Check for an address argument
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrPC, &addrAsm);
+ }
+ else {
+ if (CPGetAddress(lpsz, &cch, &addrAsm, radix, &CxfIp, fCaseSensitive, FALSE) != 0) {
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ lpsz += cch;
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz != 0) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ /*
+ ** We have a working address now set up for doing the the assembly
+ */
+
+ // this is happening between the CmdDoLine() and
+ // CmdDoPrompt() calls - we will get the right prompt.
+
+ CmdSetCmdProc(CmdAsmLine, CmdAsmPrompt);
+ CmdSetAutoHistOK(FALSE);
+ CmdSetEatEOLWhitespace(FALSE);
+
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+} /* LogAssemble() */
+#endif
+
+
+LOGERR NEAR PASCAL
+LogCompare(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Compare command:
+ c <range> <addr>
+
+Arguments:
+
+ lpsz - command tail
+
+Return Value:
+
+ LOGERROR code
+
+--*/
+{
+ int err;
+ int cch;
+ int i;
+ ADDR addr0;
+ ADDR addr1;
+ DWORD dwLen;
+ DWORD dwBytes;
+ DWORD dwcb;
+ LONG nDW;
+ UINT buf0[MEMBUF_SIZE/sizeof(UINT)];
+ UINT buf1[MEMBUF_SIZE/sizeof(UINT)];
+ BOOL fMatched;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ char szStr[100];
+
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+
+ err = CPGetRange(lpsz, &cch, &addr0, &addr1, radix, 0, 1, &CxfIp, fCaseSensitive, FALSE);
+ //
+ // no default here
+ //
+ if (err != EENOERROR) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (GetAddrOff(addr1) < GetAddrOff(addr0)) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ dwLen = GetAddrOff(addr1) - GetAddrOff(addr0) + 1;
+
+ lpsz = CPSkipWhitespace(lpsz + cch);
+ err = CPGetAddress(lpsz, &cch, &addr1, radix, &CxfIp, fCaseSensitive, FALSE);
+ if (err != EENOERROR) {
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ SYFixupAddr(&addr1);
+
+ fMatched = TRUE;
+
+ while (dwLen) {
+
+ dwBytes = (dwLen < MEMBUF_SIZE)? dwLen : MEMBUF_SIZE;
+
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr0) == xosdNone);
+ dwcb = OSDPtrace( osdReadBuf, dwBytes, (BYTE *)buf0, LppdCur->hpid, LptdCur->htid);
+ if (dwcb < 1) {
+ EEFormatAddr(&addr0, szStr, sizeof(szStr),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogVar(ERR_Read_Failed_At, szStr);
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ // only read as many bytes as previous read got:
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr1) == xosdNone);
+ dwcb = OSDPtrace( osdReadBuf, dwcb, (BYTE *)buf1, LppdCur->hpid, LptdCur->htid);
+ if (dwcb < 1) {
+ EEFormatAddr(&addr1, szStr, sizeof(szStr),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogVar(ERR_Read_Failed_At, szStr);
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ dwBytes = dwcb;
+
+ SetCtrlCTrap();
+ // dwords much faster than bytes, but watch out for endian bias:
+ nDW = dwBytes / sizeof(UINT);
+ for (i = 0; i < nDW; i++) {
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+ if (buf0[i] != buf1[i] &&
+ mismatch(addr0, (LPBYTE)&buf0[i], addr1, (LPBYTE)&buf1[i], sizeof(UINT))) {
+ fMatched = FALSE;
+ }
+ GetAddrOff(addr0) += sizeof(UINT);
+ GetAddrOff(addr1) += sizeof(UINT);
+ }
+ nDW = dwBytes % sizeof(UINT);
+ if (nDW) {
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+ if (mismatch(addr0, (LPBYTE)&buf0[i], addr1, (LPBYTE)&buf1[i], nDW)) {
+ fMatched = FALSE;
+ }
+
+ GetAddrOff(addr0) += nDW;
+ GetAddrOff(addr1) += nDW;
+ }
+
+ dwLen -= dwBytes;
+ }
+ ClearCtrlCTrap();
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogCompare() */
+
+
+BOOLEAN
+MatchPattern(
+ PUCHAR String,
+ PUCHAR Pattern
+ )
+{
+ UCHAR c, p, l;
+
+ for (; ;) {
+ switch (p = *Pattern++) {
+ case 0: // end of pattern
+ return *String ? FALSE : TRUE; // if end of string TRUE
+
+ case '*':
+ while (*String) { // match zero or more char
+ if (MatchPattern (String++, Pattern))
+ return TRUE;
+ }
+ return MatchPattern (String, Pattern);
+
+ case '?':
+ if (*String++ == 0) // match any one char
+ return FALSE; // not end of string
+ break;
+
+ case '[':
+ if ( (c = *String++) == 0) // match char set
+ return FALSE; // syntax
+
+ c = toupper(c);
+ l = 0;
+ while (p = *Pattern++) {
+ if (p == ']') // if end of char set, then
+ return FALSE; // no match found
+
+ if (p == '-') { // check a range of chars?
+ p = *Pattern; // get high limit of range
+ if (p == 0 || p == ']')
+ return FALSE; // syntax
+
+ if (c >= l && c <= p)
+ break; // if in range, move on
+ }
+
+ l = p;
+ if (c == p) // if char matches this element
+ break; // move on
+ }
+
+ while (p && p != ']') // got a match in char set
+ p = *Pattern++; // skip to end of set
+
+ break;
+
+ default:
+ c = *String++;
+ if (toupper(c) != p) // check for exact char
+ return FALSE; // not a match
+
+ break;
+ }
+ }
+}
+
+
+LOGERR NEAR PASCAL
+LogDisasm(
+ LPSTR lpsz,
+ BOOL fSearch
+ )
+/*++
+
+Routine Description:
+
+ This function does the dump code command.
+
+ Syntax:
+ dc
+ dc address [endaddr]]
+ dc address l cBytes
+ dc address I cInstrunctions
+
+Arguments:
+
+ lpsz - argument list for dump code command
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ SDI sds;
+ int cch;
+ ADDR addr;
+ ADDR endAddr;
+ BOOL fAddr = FALSE;
+ int err;
+ int x;
+ int cLine = 8;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPSTR lpch;
+ int cb;
+ LPSTR currFunc = NULL;
+ NEARESTSYM nsym;
+ LPSTR p;
+ CHAR buf[256];
+ MSG msg;
+ BOOL fNotFound = FALSE;
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ TDWildInvalid();
+ PDWildInvalid();
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** If no arguments are given use the current CS:IP.
+ */
+
+ if (*lpsz == 0) {
+
+ if (addrLastDisasmEnd.addr.seg == 0 && addrLastDisasmEnd.addr.off == 0) {
+ OSDGetAddr(LptdCur->lppd->hpid, LptdCur->htid, (ADR)adrPC,
+ &addrLastDisasmEnd);
+ SYFixupAddr(&addrLastDisasmEnd);
+ } else {
+ SYSanitizeAddr(&addrLastDisasmEnd);
+ }
+ addr = addrLastDisasmEnd;
+
+ } else {
+
+ /*
+ ** The argument must be an address -- so try and get it.
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ err = CPGetRange(lpsz, &cch, &addr, &endAddr, radix,
+ 0, 1, &CxfIp, fCaseSensitive, FALSE);
+
+ if (err == EEOPTIONAL) {
+
+ //
+ // dc <addr> I <count>
+ //
+ cLine = GetAddrOff(endAddr) - GetAddrOff(addr) + 1;
+
+ } else if (err == EEDEFAULT) {
+
+ cLine = 8;
+
+ } else if (err != EENOERROR) {
+
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+
+ } else if (GetAddrOff(endAddr) < GetAddrOff(addr)) {
+ //
+ // this will be true if EEDEFAULT -
+ // be sure that case comes before this one.
+ //
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+
+ } else {
+
+ fAddr = TRUE;
+ }
+
+ lpsz += cch;
+ }
+
+ addrLastDisasmStart = addr;
+
+ /*
+ ** Check that all characters are used
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+ if (*lpsz != 0) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ /*
+ ** Now do the dissassembly
+ */
+
+ sds.dop = (runDebugParams.DisAsmOpts & ~(0x800)) | dopAddr | dopOpcode | dopOperands;
+ sds.addr = addr;
+
+ if ( !fAddr ) {
+ endAddr = sds.addr;
+ }
+
+ SetCtrlCTrap();
+
+ if (!fSearch) {
+ ZeroMemory( &nsym, sizeof(nsym) );
+ if (GetNearestSymbolInfo( &sds.addr, &nsym )) {
+ if (nsym.hsymP) {
+ currFunc = FormatSymbol( nsym.hsymP, &nsym.cxt );
+ CmdLogFmt( "%s+0x%x:\r\n", currFunc, GetAddrOff(sds.addr) - GetAddrOff(nsym.addrP) );
+ free( currFunc );
+ } else {
+ if (!fNotFound) {
+ CmdLogFmt( "<unknown>\r\n" );
+ }
+ fNotFound = TRUE;
+ }
+ }
+ }
+
+ while (TRUE) {
+
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ if (fAddr) {
+ if (GetAddrOff(endAddr) < GetAddrOff(sds.addr)) {
+ break;
+ }
+ } else {
+ //
+ // Stop displaying when we are about to wrap around
+ //
+ if (GetAddrOff(endAddr) > GetAddrOff(sds.addr )) {
+ break;
+ }
+
+ if ((!fSearch) && (!cLine)) {
+ break;
+ }
+ }
+
+ cLine -= 1;
+
+ if (!fSearch && (GetAddrOff(sds.addr) >= GetAddrOff(nsym.addrN))) {
+ ZeroMemory( &nsym, sizeof(nsym) );
+ if (GetNearestSymbolInfo( &sds.addr, &nsym )) {
+ if (nsym.hsymP) {
+ currFunc = FormatSymbol( nsym.hsymP, &nsym.cxt );
+ CmdLogFmt( "%s+0x%x:\r\n", currFunc, GetAddrOff(sds.addr) - GetAddrOff(nsym.addrP) );
+ free( currFunc );
+ } else {
+ if (!fNotFound) {
+ CmdLogFmt( "<unknown>\r\n" );
+ }
+ fNotFound = TRUE;
+ }
+ }
+ }
+
+ x = 0;
+ if ( !fAddr ) {
+ endAddr = sds.addr;
+ }
+ if (OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sds) != xosdNone) {
+
+ rVal = LOGERROR_UNKNOWN;
+ break;
+
+ } else {
+
+ p = &buf[0];
+ *p = 0;
+
+ if (sds.ichAddr != -1) {
+ sprintf(p, "%s ", &sds.lpch[sds.ichAddr]);
+ p += strlen(p);
+ }
+ cb = _fstrlen(&sds.lpch[sds.ichAddr]) + 2;
+
+ if (sds.ichBytes != -1) {
+ lpch = sds.lpch + sds.ichBytes;
+ while (_fstrlen(lpch) > 16) {
+ sprintf(p, "%16.16s\r\n%*s", lpch, cb, " ");
+ p += strlen(p);
+ lpch += 16;
+ }
+ cb = 17 - _fstrlen(lpch);
+ sprintf(p, "%-17s", lpch);
+ p += strlen(p);
+ }
+
+ sprintf(p, "%-12s ", &sds.lpch[sds.ichOpcode]);
+ p += strlen(p);
+
+ if (sds.ichOperands != -1) {
+ sprintf(p, "%-25s ", &sds.lpch[sds.ichOperands]);
+ p += strlen(p);
+ } else if (sds.ichComment != -1) {
+ sprintf(p, "%25s ", " ");
+ p += strlen(p);
+ }
+
+ if (sds.ichComment != -1) {
+ sprintf(p, "%s", &sds.lpch[sds.ichComment]);
+ p += strlen(p);
+ }
+
+ if (fSearch) {
+ if (MatchPattern( buf, lpszLastSearch )) {
+ ZeroMemory( &nsym, sizeof(nsym) );
+ if (GetNearestSymbolInfo( &sds.addr, &nsym )) {
+ if (nsym.hsymP) {
+ currFunc = FormatSymbol( nsym.hsymP, &nsym.cxt );
+ CmdLogFmt( "%s+0x%x:\r\n", currFunc, GetAddrOff(sds.addr) - GetAddrOff(nsym.addrP) );
+ free( currFunc );
+ } else {
+ if (!fNotFound) {
+ CmdLogFmt( "<unknown>\r\n" );
+ }
+ fNotFound = TRUE;
+ }
+ }
+ break;
+ } else {
+ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ ProcessQCQPMessage(&msg);
+ }
+ }
+ } else {
+ CmdLogFmt( "%s\r\n", buf );
+ }
+ }
+ }
+
+ ClearCtrlCTrap();
+
+ addrLastDisasmEnd = sds.addr;
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+} /* LogDisasm() */
+
+
+LOGERR NEAR PASCAL
+LogSearchDisasm(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function does a regular expression search of the disasm output.
+
+Arguments:
+
+ lpsz - search pattern
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ if (!*lpsz && lpszLastSearch && !*lpszLastSearch) {
+ CmdLogFmt( "You must specify a search pattern\r\n" );
+ return LOGERROR_QUIET;
+ }
+
+ if (*lpsz) {
+ if (lpszLastSearch && *lpszLastSearch) {
+ free( lpszLastSearch );
+ }
+ lpsz = CPSkipWhitespace(lpsz);
+ lpszLastSearch = malloc( strlen(lpsz) + 16 );
+ if (!lpszLastSearch) {
+ CmdLogFmt( "Out of memory doing search\r\n" );
+ return LOGERROR_QUIET;
+ }
+ if (*lpsz != '*') {
+ *lpszLastSearch = '*';
+ strcpy( lpszLastSearch+1, lpsz );
+ }
+ if (lpszLastSearch[strlen(lpszLastSearch)-1] != '*') {
+ strcat(lpszLastSearch,"*");
+ }
+ _strupr( lpszLastSearch );
+ }
+
+ return LogDisasm( "", TRUE );
+}
+
+
+LOGERR NEAR PASCAL
+LogDumpMem(
+ char chType,
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ This function is the generic function which is used to dump
+ memory to the command window.
+
+Arguments:
+
+ lpsz - Supplies argument list for memory dump command
+ type - Supplies type of memory to be dumpped
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ char rgch[100]; // format into this string
+ char rgch3[100]; // ascii dump for db
+ BYTE rgb[100]; // bytes to be formatted
+ int i;
+ int j;
+ int jj;
+ ADDR addr; // address to format at
+ ADDR addr1; // tmp
+ int cch; // parser variable
+ int cb; // bytes read by OSDebug
+ int cItems; // dmfi[].cItems
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ int err;
+ int type;
+ BOOL fQuit;
+#ifdef DBCS
+ BOOL bDBCS = FALSE;
+ BYTE chSave;
+ static UINT uiCodePage = (UINT)-1;
+#endif
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ PDWildInvalid();
+ TDWildInvalid();
+ PreRunInvalid();
+
+ type = LetterToType(chType);
+ if (type == LOG_DM_UNKNOWN) {
+ return LOGERROR_UNKNOWN;
+ }
+ cItems = dmfi[type].cItems;
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ /*
+ ** Check the debugger is alive
+ */
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** Get the address to start dumping memory at.
+ ** Either this is specified in the command or it is a continue from
+ ** a previous command.
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) { // no arg
+
+ // if we haven't dumped, look at what we just entered:
+ if (addrLastDumpEnd.addr.seg == 0 && addrLastDumpEnd.addr.off == 0) {
+ addrLastDumpEnd = addrLastEnterStart;
+ }
+ // if nothing is there, try what we just disassembled:
+ if (addrLastDumpEnd.addr.seg == 0 && addrLastDumpEnd.addr.off == 0) {
+ addrLastDumpEnd = addrLastDisasmStart;
+ }
+ if (addrLastDumpEnd.addr.seg == 0 && addrLastDumpEnd.addr.off == 0) {
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrData, &addrLastDumpEnd);
+ } else {
+ SYSanitizeAddr(&addrLastDumpEnd);
+ }
+ addr = addrLastDumpEnd;
+
+ } else {
+
+ err = CPGetRange(lpsz, &cch, &addr, &addr1, radix,
+ cItems, dmfi[type].cBytes, &CxfIp, fCaseSensitive,
+ runDebugParams.fMasmEval);
+
+ if (err != EENOERROR && err != EEDEFAULT)
+ {
+ CmdInsertInit();
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (GetAddrOff(addr1) < GetAddrOff(addr)) {
+ CmdInsertInit();
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ cItems = (addr1.addr.off - addr.addr.off + dmfi[type].cBytes) / dmfi[type].cBytes;
+ if (cItems < 1) {
+ CmdInsertInit();
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** Must have used up the entire line or else it's an error
+ */
+
+ lpsz = CPSkipWhitespace(lpsz + cch);
+ if (*lpsz != 0) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+ }
+
+ /*
+ ** Dump out the memory
+ */
+
+ addrLastDumpStart = addr;
+
+ SetCtrlCTrap();
+
+#ifdef DBCS
+ //Initialize
+ bDBCS = FALSE;
+#endif
+
+ //
+ // Be sure to leave this loop normally, or ClearCtrlCTrap()
+ //
+ for (i = 0, j = 0, fQuit = 0; !fQuit && i < cItems; i++) {
+
+ // if at beginning of line, get address, display it
+ if (j == 0) {
+ //
+ // check for abort
+ // remainder of command line should be discarded
+ //
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ EEFormatAddr(&addr, rgch, sizeof(rgch),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogFmt("%s%s", rgch, (type == LOG_DM_ASCII || type == LOG_DM_UNICODE)? " " : " ");
+
+ rgch3[0] = 0;
+ }
+
+ // format and display next data item
+
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr) == xosdNone);
+ cb = OSDPtrace( osdReadBuf, dmfi[type].cBytes, rgb, LppdCur->hpid, LptdCur->htid);
+
+ if (cb != dmfi[type].cBytes) {
+
+ memset(rgch, '?', sizeof(rgch));
+ rgch[dmfi[type].cchItem] = 0;
+ CmdLogFmt(" %s", rgch);
+
+ if (type == LOG_DM_DWORD) {
+ strcat(rgch3, "????");
+ } else {
+ strcat(rgch3, "?");
+ }
+
+ } else {
+
+ switch (type) {
+
+ case LOG_DM_4REAL:
+ case LOG_DM_8REAL:
+ case LOG_DM_TREAL:
+
+ // this should never fail
+ Dbg(EEFormatMemory(rgch,
+ 2 * dmfi[type].cBytes + 1,
+ rgb,
+ dmfi[type].cBytes * 8,
+ fmtUInt | fmtZeroPad, 16) == EENOERROR);
+ CmdLogFmt(" %s", rgch);
+
+ // let's not assert on FP formatting problems...
+ EEFormatMemory(
+ rgch,
+ dmfi[type].cchItem + 1,
+ rgb,
+ dmfi[type].cBytes * 8,
+ dmfi[type].fmtType,
+ dmfi[type].radix);
+ CmdLogFmt(" %s", rgch);
+
+ break;
+
+ case LOG_DM_ASCII:
+
+ if (*(LPSTR)rgb == '\0') {
+ fQuit = TRUE;
+ } else {
+ EEFormatMemory(rgch, dmfi[type].cchItem + 1, rgb, dmfi[type].cBytes*8,
+ dmfi[type].fmtType, dmfi[type].radix);
+#ifdef DBCS
+ if (bDBCS) {
+ if (j == 0) {
+ //This means that current *pszSrc is the 2nd byte
+ //of a splited DBCS
+ rgch[0] = '.';
+ } else {
+ //This DBC is changed to '.' by EEFormatMemory().
+ //So I restore it.
+ rgch[0] = chSave;
+ rgch[1] = rgb[0];
+ rgch[2] = '\0';
+ }
+ CmdLogFmt("%s", rgch);
+ bDBCS = FALSE;
+ } else if (IsDBCSLeadByte((BYTE)(0x00ff & rgb[0]))) {
+ chSave = rgb[0];
+ bDBCS = TRUE;
+ }
+ else if ((BYTE)rgb[0] >= (BYTE)0xa1 && (BYTE)rgb[0] <= (BYTE)0xdf) {
+ //'Hankaku Kana' is changed to '.' by EEFormatMemory().
+ rgch[0] = rgb[0];
+ CmdLogFmt("%s", rgch);
+ }
+ else {
+ CmdLogFmt("%s", rgch);
+ }
+#else
+ CmdLogFmt("%s", rgch);
+#endif
+ }
+ break;
+
+ case LOG_DM_UNICODE:
+
+ if (*(LPWCH)rgb == '\0') {
+ fQuit = TRUE;
+ } else {
+#ifdef DBCS
+ /*
+ * This is too bad. These kind of proccess should be done
+ * in EEFormatMemory(). But eecan???.dll shouldn't use
+ * WideCharToMultiByte() of GetACP() somehow.
+ */
+ int iCount;
+
+ if (uiCodePage == (UINT)-1) {
+ uiCodePage = GetACP();
+ }
+ iCount = WideCharToMultiByte(
+ uiCodePage, // CodePage
+ 0, // dwFlags
+ (LPWCH)rgb, // lpWideCharStr
+ 1, // cchWideCharLength
+ rgch, // lpMultiByteStr
+ MB_CUR_MAX, // cchMultiByteLength
+ NULL, // lpDefaultChar
+ NULL // lpUseDefaultChar
+ );
+
+ //This criterion should be same as one in EEFormatMemory().
+ if (iCount == 0
+ || (rgch[0] < ' ' || rgch[0] > 0x7e)
+ && !IsDBCSLeadByte(rgch[0])) {
+ rgch[0] = '.';
+ iCount = 1;
+ }
+ rgch[iCount] = 0;
+#else
+ EEFormatMemory(rgch, dmfi[type].cchItem + 1, rgb, dmfi[type].cBytes*8,
+ dmfi[type].fmtType, dmfi[type].radix);
+#endif
+ CmdLogFmt("%s", rgch);
+ }
+ break;
+
+ case LOG_DM_BYTE:
+ case LOG_DM_WORD:
+ case LOG_DM_DWORD:
+
+ if (type == LOG_DM_DWORD && i < 4) {
+ ulPseudo[i] = *(LPDWORD)&rgb[0];
+ }
+
+ EEFormatMemory(rgch, dmfi[type].cchItem + 1, rgb, dmfi[type].cBytes*8,
+ dmfi[type].fmtType | fmtZeroPad, dmfi[type].radix);
+ CmdLogFmt(" %s", rgch);
+
+ switch (type) {
+ case LOG_DM_BYTE:
+ EEFormatMemory(&rgch3[j], 1, rgb, 8, fmtAscii, 0);
+#ifdef DBCS
+ if (bDBCS) {
+ if (j == 0) {
+ //This means that current *pszSrc is the 2nd byte
+ //of a splited DBCS
+ rgch3[j] = '.';
+ } else {
+ //This DBC is changed to '.' by EEFormatMemory().
+ //So I restore it.
+ rgch3[j] = rgb[0];
+ }
+ bDBCS = FALSE;
+ } else if (IsDBCSLeadByte((BYTE)(0x00ff & rgb[0]))) {
+ rgch3[j] = rgb[0];
+ bDBCS = TRUE;
+ }
+ else if ((BYTE)rgb[0] >= (BYTE)0xa1 && (BYTE)rgb[0] <= (BYTE)0xdf) {
+ //'Hankaku Kana' is changed to '.' by EEFormatMemory().
+ rgch3[j] = rgb[0];
+ }
+#endif // DBCS
+ rgch3[j+1] = 0;
+ break;
+
+ case LOG_DM_WORD:
+#if defined(DBCS) && defined(DW_COMMAND_SUPPORT)
+ /*
+ * This functionarity shouldn't be supported.
+ * If you want support this functionarity,
+ * Just define "DW_COMMAND_SUPPORT".
+ */
+ {
+ /*
+ * This is too bad. These kind of proccess should be done
+ * in EEFormatMemory(). But eecan???.dll shouldn't use
+ * WideCharToMultiByte() of GetACP() somehow.
+ */
+ int iCount;
+
+ if (uiCodePage == (UINT)-1) {
+ uiCodePage = GetACP();
+ }
+ iCount = WideCharToMultiByte(
+ uiCodePage, // CodePage
+ 0, // dwFlags
+ (LPWCH)rgb, // lpWideCharStr
+ 1, // cchWideCharLength
+ &rgch3[j], // lpMultiByteStr
+ MB_CUR_MAX, // cchMultiByteLength
+ NULL, // lpDefaultChar
+ NULL // lpUseDefaultChar
+ );
+
+ //This criterion should be same as one in EEFormatMemory().
+ if (iCount == 0
+ || (rgch[0] < ' ' || rgch[0] > 0x7e)
+ && !IsDBCSLeadByte(rgch[0])) {
+ rgch3[j] = '.';
+ rgch3[j+1] = ' ';
+ }
+ else if (iCount == 1) {
+ rgch3[j+1] = ' ';
+ }
+ rgch3[j+2] = 0;
+ j++;
+ }
+#else
+ EEFormatMemory(&rgch3[j], 1, rgb, 16, fmtUnicode, 0);
+ rgch3[j+1] = 0;
+#endif
+ break;
+
+ case LOG_DM_DWORD:
+ for (jj = 0; jj < dmfi[type].cBytes; jj++) {
+ EEFormatMemory(&rgch3[dmfi[type].cBytes * j + jj],
+ 1, &rgb[jj], 8, fmtAscii, 0);
+ }
+ rgch3[dmfi[type].cBytes * j + jj] = 0;
+ break;
+ }
+ }
+ }
+
+ // if at end of line or end of list:
+ if ( fQuit || ++j >= (int)dmfi[type].cAcross || i >= cItems - 1) {
+#ifdef DBCS
+ if (bDBCS) {
+ //If DBC is separated by new line, add 2nd byte.
+ if (type == LOG_DM_BYTE) {
+ GetAddrOff(addr) += dmfi[type].cBytes;
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr) == xosdNone);
+ cb = OSDPtrace( osdReadBuf, dmfi[type].cBytes, rgb, LppdCur->hpid, LptdCur->htid);
+ GetAddrOff(addr) -= dmfi[type].cBytes;
+ rgch3[j] = rgb[0];
+ rgch3[j+1] = '\0';
+ } else if (type == LOG_DM_ASCII) {
+ GetAddrOff(addr) += dmfi[type].cBytes;
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr) == xosdNone);
+ cb = OSDPtrace( osdReadBuf, dmfi[type].cBytes, rgb, LppdCur->hpid, LptdCur->htid);
+ GetAddrOff(addr) -= dmfi[type].cBytes;
+ rgch[0] = chSave;
+ rgch[1] = rgb[0];
+ rgch[2] = '\0';
+ CmdLogFmt("%s", rgch);
+ }
+ }
+#endif // DBCS
+
+ // if in a hex mode, fill line and display ASCII version
+
+ if (type == LOG_DM_BYTE || type == LOG_DM_WORD || type == LOG_DM_DWORD) {
+ //
+ // fill row to justify right column
+ //
+ cb = (dmfi[type].cAcross - j) * (dmfi[type].cchItem + 1) + 1;
+ CmdLogFmt("%*s%s", cb, " ", rgch3);
+ }
+ // display newline
+ CmdLogFmt("\r\n");
+ j = 0;
+ }
+
+ GetAddrOff(addr) += dmfi[type].cBytes;
+
+ }
+
+ ClearCtrlCTrap();
+
+ addrLastDumpEnd = addr;
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogDumpMem() */
+
+
+LOGERR NEAR PASCAL
+LogEnterMem(
+ LPSTR lpsz
+)
+/*++
+
+Routine Description:
+
+ This function is used from the command line to do editing of memory.
+
+Arguments
+ lpsz - Supplies argument list for memory edit command
+ type - Supplies type of memory to be edited
+
+Returns:
+ log error code
+
+--*/
+{
+ int cch;
+ ADDR addr;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ int type;
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ PDWildInvalid();
+ TDWildInvalid();
+ PreRunInvalid();
+
+ type = LetterToType(*lpsz++);
+ if (type == LOG_DM_UNKNOWN) {
+ return LOGERROR_UNKNOWN;
+ }
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ //
+ // Check the debugger is really alive
+ //
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ //
+ // Get the starting address to edit at
+ //
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz == 0) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ if (CPGetAddress( lpsz, &cch, &addr, radix,
+ &CxfIp, fCaseSensitive, runDebugParams.fMasmEval) == 0) {
+ lpsz += cch;
+ } else {
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ SYFixupAddr(&addr);
+ addrLastEnterStart = addr;
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (*lpsz != 0) {
+ rVal = DoEnterMem(lpsz, &addr, type, TRUE);
+ } else {
+ //
+ // Interactive enter:
+ //
+ // set global context:
+ //
+ LppdT = LppdCommand;
+ LptdT = LptdCommand;
+
+ addrAsm = addr;
+ nEnterType = type;
+ CmdSetCmdProc(CmdEnterLine, CmdEnterPrompt);
+ CmdSetAutoHistOK(FALSE);
+ CmdSetEatEOLWhitespace(FALSE);
+ }
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogEnterMem() */
+
+
+LOGERR NEAR PASCAL
+LogFill(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ fill command
+ fi <range> {<byte list> | <quoted string>}
+ fib <range> <byte list>
+ fiw <range> <word list>
+ fid <range> <dword list>
+ fii <range> <real4 list>
+ fis <range> <real8 list>
+ fit <range> <real10 list>
+ fia <range> <ascii string>
+ fiu <range> <unicode string>
+
+Arguments:
+
+ lpsz - Supplies pointer to command tail
+
+Return Value:
+
+ LOGERR code
+
+--*/
+{
+ int cch;
+ int type;
+ ADDR addr0;
+ ADDR addr1;
+ LONG lLen;
+ BYTE buf[2 * MAX_USER_LINE];
+ LONG cb;
+ int err;
+ XOSD xosd;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ type = LetterToType(*lpsz);
+ if (type != LOG_DM_UNKNOWN) {
+ lpsz++;
+ }
+
+ //
+ // get range
+ //
+
+ err = CPGetRange(
+ lpsz,
+ &cch,
+ &addr0,
+ &addr1,
+ radix,
+ 0,
+ dmfi[(type == LOG_DM_UNKNOWN) ? LOG_DM_BYTE : type].cBytes,
+ &CxfIp,
+ fCaseSensitive,
+ FALSE);
+
+
+ //
+ // no default
+ //
+ if (err != EENOERROR) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (GetAddrOff(addr1) < GetAddrOff(addr0)) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ lLen = GetAddrOff(addr1) - GetAddrOff(addr0) + 1;
+
+ lpsz = CPSkipWhitespace(lpsz + cch);
+
+ if (type == LOG_DM_UNKNOWN) {
+ type = (*lpsz == '"' || *lpsz == '\'') ? LOG_DM_ASCII : LOG_DM_BYTE;
+ }
+
+ if (dmfi[type].cBytes && (cb = lLen % dmfi[type].cBytes) != 0) {
+ if (cb == 1) {
+ CmdLogVar(DBG_Not_Exact_Fill);
+ } else {
+ CmdLogVar(DBG_Not_Exact_Fills, cb);
+ }
+ lLen -= cb;
+ }
+
+ err = GetValueList(lpsz, type, TRUE, buf, sizeof(buf), &cb);
+ if (err != LOGERROR_NOERROR) {
+ rVal = err;
+ goto done;
+ }
+ if (cb == 0) {
+ CmdLogVar(ERR_Expr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ SetCtrlCTrap();
+ while (lLen) {
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+ if (cb > lLen) {
+ cb = lLen;
+ }
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr0) == xosdNone);
+ xosd = OSDPtrace(osdWriteBuf, cb, buf, LppdCur->hpid, LptdCur->htid);
+ if (xosd != xosdNone) {
+ EEFormatAddr(&addr0, buf, 30,
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogVar(ERR_Write_Failed_At, buf);
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+ lLen -= cb;
+ GetAddrOff(addr0) += cb;
+ }
+ ClearCtrlCTrap();
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogFill() */
+
+
+LOGERR NEAR PASCAL
+LogMovemem(
+ LPSTR lpsz
+ )
+{
+ int err;
+ int cch;
+ XOSD xosd;
+ ADDR addr0;
+ ADDR addr1;
+ LONG lLen;
+ LONG lBytes;
+ LONG lWanted;
+ BYTE buf[MEMBUF_SIZE];
+ char szStr[100];
+ int nDir;
+ BOOL fDoUpdate = FALSE;
+
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+
+ err = CPGetRange(lpsz, &cch, &addr0, &addr1, radix, 0, 1, &CxfIp, fCaseSensitive, FALSE);
+ //
+ // default can't work here
+ //
+ if (err != EENOERROR) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (GetAddrOff(addr1) < GetAddrOff(addr0)) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ lLen = GetAddrOff(addr1) - GetAddrOff(addr0) + 1;
+
+ lpsz = CPSkipWhitespace(lpsz + cch);
+ err = CPGetAddress(lpsz, &cch, &addr1, radix, &CxfIp, fCaseSensitive, FALSE);
+ if (err != EENOERROR) {
+ CmdLogVar(ERR_AddrExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ SYFixupAddr(&addr1);
+
+ if (GetAddrOff(addr0) > GetAddrOff(addr1)) {
+ nDir = 1;
+ } else {
+ nDir = -1;
+ GetAddrOff(addr0) += lLen;
+ GetAddrOff(addr1) += lLen;
+ }
+
+ lWanted = lLen;
+ SetCtrlCTrap();
+ while (lLen > 0) {
+
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ lBytes = (lLen < MEMBUF_SIZE)? lLen : MEMBUF_SIZE;
+
+ if (nDir < 0) {
+ GetAddrOff(addr0) -= lBytes;
+ GetAddrOff(addr1) -= lBytes;
+ }
+
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr0) == xosdNone);
+ lBytes = OSDPtrace( osdReadBuf, lBytes, buf, LppdCur->hpid, LptdCur->htid);
+ if (lBytes < 1) {
+ EEFormatAddr(&addr0, szStr, sizeof(szStr),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogVar(ERR_Read_Failed_At, szStr);
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ Dbg(OSDSetAddr( LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr1) == xosdNone);
+ xosd = OSDPtrace( osdWriteBuf, lBytes, buf, LppdCur->hpid, LptdCur->htid);
+ if (xosd != xosdNone) {
+ EEFormatAddr(&addr1, szStr, sizeof(szStr),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogVar(ERR_Write_Failed_At, szStr);
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+
+ lLen -= lBytes;
+
+ if (nDir > 0) {
+ GetAddrOff(addr0) += lBytes;
+ GetAddrOff(addr1) += lBytes;
+ }
+ }
+ ClearCtrlCTrap();
+
+ CmdLogVar(DBG_Bytes_Copied, lWanted - lLen, lWanted);
+
+ fDoUpdate = TRUE;
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ if (fDoUpdate) {
+ UpdateDebuggerState(UPDATE_DATAWINS);
+ }
+ return rVal;
+} /* LogMovemem() */
+
+
+LOGERR NEAR PASCAL
+LogRegisters(
+ LPSTR lpsz,
+ BOOL fFP
+ )
+/*++
+
+Routine Description:
+
+ Display the contents of one or all registers, or modify the contents of
+ a register. The regular or floating point register set may be selected
+ by the fFP flag.
+
+Arguments:
+
+ lpsz - Supplies string with the command on it
+ fFP - Supplies TRUE to use FP regs, FALSE to use integer regs
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ RD rd;
+ RT rtMask;
+ char rgch[100];
+ BYTE ab[30];
+ int cRegs;
+ int cRegWidth;
+ LPSTR lpch;
+ int i;
+ int j;
+ int y;
+ LONG ul;
+ char ch;
+ int rdx;
+ int fmt;
+ DWORD update;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal = LOGERROR_NOERROR;
+ BOOL fAllRegs = FALSE;
+
+ static int rgfmts[] = {0, fmtZeroPad|fmtUInt, fmtFloat, fmtAddress};
+
+
+ CmdInsertInit();
+ IsKdCmdAllowed();
+
+ TDWildInvalid();
+ PDWildInvalid();
+ PreRunInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ /*
+ ** Check for a live debuggee
+ */
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** Check for floating point register dump
+ */
+
+ if (fFP) {
+ rtMask = rtFPU;
+ } else {
+ rtMask = rtCPU;
+ }
+
+ if (lpsz[0] == 't' && lpsz[1] == '\0') {
+ fAllRegs = TRUE;
+ lpsz++;
+ }
+
+ if (runDebugParams.RegModeExt || fAllRegs) {
+ rtMask |= rtExtended;
+ } else {
+ rtMask |= rtRegular;
+ }
+
+ if (runDebugParams.RegModeMMU || fAllRegs) {
+ rtMask |= rtSpecial;
+ }
+
+ /*
+ ** If no arguments then just dump the registers
+ */
+
+ OSDGetDebugMetric(LppdCur->hpid, LptdCur->htid, mtrcCRegs, &ul);
+ cRegs = (int) ul;
+
+ if (*lpsz == 0) {
+
+ y = 0;
+
+ for (i=0; i<cRegs; i++) {
+
+ Dbg( OSDGetRegDesc( LppdCur->hpid, LptdCur->htid, i, &rd) == xosdNone );
+
+ if (((rd.rt & rtProcessMask) == (rtMask & rtProcessMask)) &&
+ ((rd.rt & rtMask & rtGroupMask) != 0)) {
+
+ cRegWidth = (rd.cbits + 7)/ 8 * 2;
+ if ((y > 0 && (rd.rt & rtNewLine)) ||
+ (y + 2 + _fstrlen(rd.lpsz) + 1 + cRegWidth) > 80) {
+ CmdLogFmt("\r\n");
+ y = 0;
+ } else {
+ if (y != 0) {
+ CmdLogFmt(" ");
+ y += 2;
+ }
+ }
+
+
+ CmdLogFmt("%s=", rd.lpsz);
+ Dbg( OSDReadReg(LppdCur->hpid, LptdCur->htid, rd.hReg, ab) == xosdNone );
+
+ fmt = rgfmts[(rd.rt & rtFmtTypeMask) >> rtFmtTypeShift];
+
+ if ((fmt & fmtBasis) != fmtFloat) {
+ rdx = 16;
+ } else {
+ rdx = 10;
+ for (j = 0; j < LOG_DM_MAX; j++) {
+ if (dmfi[j].fmtType == (UINT)(fmt & fmtBasis)
+ && (UINT)dmfi[j].cBytes*8 == rd.cbits) {
+ cRegWidth = dmfi[j].cchItem;
+ break;
+ }
+ }
+ Assert(j < LOG_DM_MAX);
+ }
+ Assert(cRegWidth+1 <= sizeof(rgch));
+ EEFormatMemory(rgch, cRegWidth+1, ab, rd.cbits, fmt, rdx);
+ CmdLogFmt("%s", rgch);
+
+ y += _fstrlen(rd.lpsz) + cRegWidth + 1;
+ }
+ }
+ if (y != 0) {
+ CmdLogFmt("\r\n");
+ }
+
+ rVal = LOGERROR_NOERROR;
+ goto done;
+ }
+
+ /*
+ ** Now check for a specific register to have been requested.
+ */
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+#ifdef DBCS
+ for (lpch = lpsz; (*lpch != 0) && (*lpch != '=') && (*lpch != ' ');
+ lpch = CharNext(lpch));
+#else
+ for (lpch = lpsz; (*lpch != 0) && (*lpch != '=') && (*lpch != ' '); lpch++);
+#endif
+ ch = *lpch;
+ *lpch = 0;
+
+#ifdef DBCS
+ lpsz = CharUpper(lpsz); // Convert to uppercase name
+#else
+ lpsz = _strupr(lpsz); // Convert to uppercase name
+#endif
+
+ for (i=0; i<cRegs; i++) {
+ Dbg( OSDGetRegDesc( LppdCur->hpid, LptdCur->htid, i, &rd) == xosdNone );
+ // match name and CPU; all groups allowed.
+ if (_stricmp(lpsz, rd.lpsz) == 0
+ && (rd.rt & rtProcessMask) == (rtMask & rtProcessMask) ) {
+ break;
+ }
+ }
+
+ if (i >= cRegs) {
+ CmdLogVar(ERR_Register_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ *lpch = ch;
+ lpch = CPSkipWhitespace(lpch);
+ if (*lpch && *lpch!='=') {
+ CmdLogFmt("Missing assigment operator\r\n");
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ /*
+ ** Only display of requested register
+ */
+
+ if (*lpch != '=') {
+
+ cRegWidth = (rd.cbits + 7)/ 8 * 2;
+ CmdLogFmt("%s: ", rd.lpsz);
+ Dbg(OSDReadReg(LppdCur->hpid, LptdCur->htid, rd.hReg, ab) == xosdNone );
+
+
+ fmt = rgfmts[(rd.rt & rtFmtTypeMask) >> rtFmtTypeShift];
+
+ if ((fmt & fmtBasis) != fmtFloat) {
+ rdx = 16;
+ } else {
+ rdx = 10;
+ for (j = 0; j < LOG_DM_MAX; j++) {
+ if (dmfi[j].fmtType == (UINT)(fmt & fmtBasis)
+ && (UINT)dmfi[j].cBytes*8 == rd.cbits) {
+ cRegWidth = dmfi[j].cchItem;
+ break;
+ }
+ }
+ Assert(j < LOG_DM_MAX);
+ }
+ Assert(cRegWidth+1 <= sizeof(rgch));
+ EEFormatMemory(rgch, cRegWidth+1, ab, rd.cbits, fmt, rdx);
+ CmdLogFmt("%s\r\n", rgch);
+
+ rVal = LOGERROR_NOERROR;
+ goto done;
+ }
+
+
+ /*
+ ** Change a register
+ */
+
+ lpch++; // Skip over '='
+
+ // make sure there is a value
+ lpch = CPSkipWhitespace(lpch);
+ if (!*lpch) {
+ CmdLogVar(ERR_Expr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+// MBH -
+// for the moment, just say T_QUAD (was T_LONG), but should
+// be dependent on the number of bits in the register.
+//
+ if (rd.rt & rtCPU) {
+ if (CPGetCastNbr(lpch, T_QUAD, radix, fCaseSensitive,
+ &CxfIp, (LPSTR) ab, (LPSTR) rgch) != EENOERROR) {
+ CmdLogVar(ERR_Expr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ } else if (rd.rt & rtFPU) {
+ if (CPGetFPNbr(lpch, rd.cbits, radix, fCaseSensitive,
+ &CxfIp, (LPSTR)ab, (LPSTR) rgch) != EENOERROR) {
+ CmdLogVar(ERR_Expr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ } else {
+ CmdLogVar(ERR_Cant_Assign_To_Reg);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (OSDWriteReg(LppdCur->hpid, LptdCur->htid, rd.hReg, ab) != xosdNone) {
+ rVal = LOGERROR_UNKNOWN;
+ }
+
+ update = UPDATE_DATAWINS;
+ if (rd.rt & rtFrame) {
+ update |= UPDATE_CONTEXT;
+ }
+ if (rd.rt & rtPC) {
+ update |= UPDATE_SOURCE | UPDATE_DISASM | UPDATE_CONTEXT;
+ }
+
+ UpdateDebuggerState(update);
+
+
+done:
+
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ return rVal;
+} /* LogRegisters() */
+
+
+LOGERR NEAR PASCAL
+LogSearch(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Search command:
+ s <range> <value list>
+
+ Current implementation supports bytes or string for value list,
+ or specific data types in command name, i.e. sb, sd, su
+
+Arguments:
+
+ lpsz - Supplies pointer to tail of command
+
+Return Value:
+
+ LOGERR code
+
+--*/
+{
+ int cch;
+ int type;
+ ADDR addr0;
+ ADDR addr1;
+ LONG lLen;
+ BYTE buf[2 * MAX_USER_LINE];
+ LONG cb;
+ int c;
+ BYTE * pm1;
+ BYTE * pm9;
+ BYTE * pmm;
+ int nm;
+ int err;
+ LPMSTREAM lpM;
+ LOGERR rVal = LOGERROR_NOERROR;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ char szStr[100];
+
+
+ CmdInsertInit();
+
+ PDWildInvalid();
+ TDWildInvalid();
+ PreRunInvalid();
+
+ /*
+ ** Check for a live debuggee
+ */
+
+ if (!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+
+ type = LetterToType(*lpsz);
+ if (type != LOG_DM_UNKNOWN) {
+ lpsz++;
+ }
+ //
+ // get range
+ //
+
+ err = CPGetRange(lpsz, &cch, &addr0, &addr1, radix, 0, 1, &CxfIp, fCaseSensitive, FALSE);
+ //
+ // default not allowed here
+ //
+ if (err != EENOERROR) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (GetAddrOff(addr1) < GetAddrOff(addr0)) {
+ CmdLogVar(ERR_RangeExpr_Invalid);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ lLen = GetAddrOff(addr1) - GetAddrOff(addr0) + 1;
+
+ lpsz = CPSkipWhitespace(lpsz + cch);
+
+ if (type == LOG_DM_UNKNOWN) {
+ type = (*lpsz == '"' || *lpsz == '\'') ? LOG_DM_ASCII : LOG_DM_BYTE;
+ }
+
+ err = GetValueList(lpsz, type, TRUE, buf, sizeof(buf), &cb);
+ if (err != LOGERROR_NOERROR) {
+ rVal = err;
+ goto done;
+ }
+
+ lpM = openb(&addr0, lLen);
+
+#define next() (pm1 < pm9 ? ((int)(UINT)*pm1++) : (pm9=buf,getb(lpM)))
+
+ // use match string for pushback queue after partial match
+ pm1 = buf;
+ pm9 = buf;
+
+ // match count, pointer to next unmatched char
+ nm = 0;
+ pmm = buf;
+
+ SetCtrlCTrap();
+ //
+ // if a partial match failed, scan from begin+1 for new match
+ //
+ while ((c = next()) != -1) {
+ //
+ // this ^C checking could seriously damage performance.
+ // maybe it should happen in the getb macro, only on
+ // buffer reloads.
+ //
+ if (CheckCtrlCTrap()) {
+ rVal = LOGERROR_QUIET;
+ break;
+ }
+ if (c == (int)(UINT)*pmm) {
+ nm++;
+ pmm++;
+
+ if (nm == cb) {
+ //
+ // Hit!
+ // figure out address
+ //
+ tellb(lpM, &addr1);
+ GetAddrOff(addr1) -= nm;
+ EEFormatAddr(&addr1, szStr, sizeof(szStr),
+ runDebugParams.ShowSegVal * EEFMT_SEG);
+ CmdLogFmt("%s\r\n", szStr);
+
+ //
+ // keep searching as though this match failed;
+ // this will score on overlapped matches.
+ //
+ pm9 = pmm;
+ pm1 = buf + 1;
+
+ nm = 0;
+ pmm = buf;
+ }
+
+ } else if (nm) {
+ //
+ // A partial match just failed.
+ // we have read nm characters; the match starting at the first
+ // failed, so we need to start scanning again at the second.
+ //
+ pm9 = pmm;
+ pm1 = buf + 1;
+ nm = 0;
+ pmm = buf;
+ }
+ }
+ ClearCtrlCTrap();
+#undef next
+
+done:
+ if (LptdCur != LptdT || LppdCur != LppdT) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ UpdateDebuggerState(UPDATE_CONTEXT);
+ }
+ return rVal;
+} /* LogSearch() */
+
+
+
+
+
+LOGERR NEAR PASCAL
+LogHelp(
+ LPSTR lpsz
+ )
+/*++
+
+Routine Description:
+
+ Display help
+
+Arguments:
+
+ lpsz - Supplies pointer to tail of command
+
+Return Value:
+
+ LOGERR code
+
+--*/
+{
+ LOGERR rVal = LOGERROR_NOERROR;
+ char *Tok;
+
+ CmdInsertInit();
+
+ if ( !_strnicmp( lpsz, "elp",3 ) ) {
+ lpsz+=3;
+ } else {
+ rVal = LOGERROR_UNKNOWN;
+ }
+
+ if ( rVal == LOGERROR_NOERROR ) {
+
+ if ( *lpsz != 0 && *lpsz != ' ' && *lpsz != '\t' ) {
+
+ rVal = LOGERROR_UNKNOWN;
+
+ } else {
+
+ Tok = strtok( lpsz, " \t" );
+
+ if ( Tok ) {
+
+ do {
+ CmdHelp( Tok );
+ } while ( Tok = strtok( NULL, " \t" ) );
+
+ } else {
+
+ CmdHelp( NULL );
+ }
+ }
+ }
+
+ return rVal;
+}
diff --git a/private/windbg/windbg/cmdwin.c b/private/windbg/windbg/cmdwin.c
new file mode 100644
index 000000000..790a9cccf
--- /dev/null
+++ b/private/windbg/windbg/cmdwin.c
@@ -0,0 +1,2206 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdwin.c
+
+Abstract:
+
+ This file contains the window procedure code for dealing with the
+ command window. This window uses the document manager to deal with
+ keeping track of the characters in the buffer.
+
+ This window has the following strange properties:
+
+ It is read-only except on the last line
+ The first portion of the last line is read-only
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+/************************** INCLUDE FILES *******************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef FE_IME
+#include <ime.h>
+#endif
+
+extern LPSHF Lpshf;
+extern CXF CxfIp;
+
+
+/************************** Externals *************************/
+
+BOOL FCmdDoingInput;
+
+extern BOOL fWaitForDebugString;
+extern LPSTR lpCmdString;
+extern ADDR addrLastDisasmStart;
+
+/************************** Internal Prototypes *************************/
+/************************** Data declaration *************************/
+
+static BOOL FAutoRunSuppress = FALSE;
+
+PCTRLC_HANDLER pPolledCtrlCHandler = NULL;
+BOOL fCtrlCPressed = FALSE; // Ctrl-C pressed flag for EditWndProc
+
+static PCTRLC_HANDLER PcchHead = NULL;
+
+static BOOL fEatEOLWhitespace = TRUE; // eat space at end of line
+static BOOL FAutoHistOK = FALSE;
+
+static char szOldPrompt[PROMPT_SIZE];
+
+/************************** Code *************************/
+
+void FAR PASCAL
+BPCallbackHbpt(
+ HBPT hBpt,
+ BPSTATUS bpstatus
+ )
+/*++
+
+Routine Description:
+
+ This function will be called for each breakpoint which
+ mets its criteria
+
+Arguments:
+
+ hBpt - Supplies breakpoint which met the breakpoint criteria
+ bpstatus - Supplies breakpoint status code during evaluation
+
+Return Value:
+
+ None
+
+--*/
+{
+ UINT i;
+ char rgchT[256];
+
+ if (bpstatus != BPNOERROR) {
+ Dbg( BPIFromHbpt( &i, hBpt ) == BPNOERROR);
+
+ CmdInsertInit();
+ CmdLogFmt("Error checking breakpoint #%d\r\n", i);
+// NOTENOTE a-kentf put text in resource
+
+ return;
+ }
+
+ if (LptdCur->fInFuncEval == FALSE) {
+ Dbg( BPIFromHbpt( &i, hBpt) == BPNOERROR );
+
+ CmdInsertInit();
+// NOTENOTE a-kentf put text in resource
+ CmdLogFmt("Breakpoint #%d hit\r\n", i);
+
+ Dbg( BPQueryCmdOfHbpt( hBpt, rgchT, sizeof(rgchT)-1) == BPNOERROR );
+
+ if (*rgchT != 0) {
+ CmdPrependCommands(LptdCur, rgchT);
+ }
+ }
+
+ return;
+} /* BPCallbackHbpt() */
+
+BOOL FAR PASCAL
+DoStopEvent(
+ LPTD lptd
+ )
+{
+ if (*szStopEventCmd) {
+ CmdPrependCommands(lptd, szStopEventCmd);
+ }
+
+ if (lptd && lptd->fDisasm && !AutoTest) {
+ CmdPrependCommands(lptd, "u . l1");
+ }
+
+ if (lptd && lptd->fRegisters) {
+ CmdPrependCommands(lptd, "r");
+ }
+
+ if (lptd) {
+ lptd->fRegisters = FALSE;
+ lptd->fDisasm = FALSE;
+ }
+
+ addrLastDisasmStart.addr.seg = 0;
+ addrLastDisasmStart.addr.off = 0;
+
+ return FALSE;
+}
+
+
+BOOL FAR PASCAL
+CmdHandleInputString(
+ LPSTR lpsz
+ )
+{
+ CmdSetDefaultPrompt( szOldPrompt );
+ CmdSetDefaultCmdProc();
+ OSDSendReply(LppdCur->hpid, strlen(lpsz) + 1, lpsz);
+ return TRUE;
+}
+
+
+BOOL FAR PASCAL
+CmdExecNext(
+ DBC unusedIW,
+ LPARAM unusedL
+ )
+/*++
+
+Routine Description:
+
+ This function causes two things to occur. First the command window
+ is updated to reflect the command/event which just occurred and
+ secondly the command processor state machine is consulted to see
+ if there are any more commands to be executed from the command
+ window.
+
+Arguments:
+
+ dbcCallback - Supplies the call back which caused this update to occur
+ lParam - Supplies information about the callback
+
+Return Value:
+
+ TRUE if update the screen and FALSE otherwise
+
+--*/
+{
+ long lExit;
+ LPSTR lpch;
+ LPSTR lpsz;
+ long l;
+ DWORD dw;
+ int dbcCallback;
+
+ HEXE emi;
+ SHE she;
+ BPSTATUS bpstatus;
+ XOSD xosd;
+ CXT cxt;
+ ADDR addr;
+ DWORD dwNotify;
+
+ HPID hpid;
+ HTID htid;
+ LPPD lppd;
+ LPTD lptd;
+
+ LPPD LppdT;
+ LPTD LptdT;
+ BOOL fExecNext;
+ int bfRefresh;
+ BOOL fGetFocus;
+ BOOL fRunning;
+ BOOL fReply;
+ int iter = 0;
+
+ static int fRecurse = FALSE;
+
+ extern BOOL FKilling;
+
+ if (fRecurse) {
+ return TRUE;
+ }
+
+ fRecurse = TRUE;
+
+ while (GetQueueLength() != 0) {
+
+ if (iter++ == 10) {
+ fRecurse = FALSE;
+ PostMessage(hwndFrame, DBG_REFRESH, 0, 0);
+ return FALSE;
+ }
+
+
+ /*
+ * Inititalization of variables;
+ */
+
+ LppdT = LppdCur;
+ LptdT = LptdCur;
+ fExecNext = TRUE;
+ bfRefresh = UPDATE_ALLDBGWIN;
+ fGetFocus = FALSE;
+
+ /*
+ * Get the next command to be processed
+ */
+
+ dbcCallback = GetQueueItemLong();
+
+#if 0
+// BUGBUG -- jls Need to put in new code to deal with this problem.
+ if ((DbgState == ds_error) && (dbcCallback != dbcInfoAvail)) {
+ fRecurse = FALSE;
+ return FALSE;
+ }
+#endif
+
+ /*
+ * Set up the command window to allow for doing input.
+ */
+
+ CmdInsertInit();
+
+ /*
+ *
+ */
+
+ switch ((DBC)dbcCallback) {
+
+ case dbcError: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ hpid = (HPID)GetQueueItemLong();
+ htid = (HTID)GetQueueItemLong();
+ xosd = (XOSD)GetQueueItemLong();
+ lpsz = (LPSTR)GetQueueItemLong();
+
+ LppdCur = LppdOfHpid(hpid);
+ LptdCur = LptdOfLppdHtid(LppdCur, htid);
+
+ CmdLogFmt("%s\r\n", lpsz);
+ free(lpsz);
+
+ fGetFocus = TRUE;
+ fExecNext = FALSE;
+
+ if (LppdCur->pstate == psPreRunning) {
+ /*
+ * we aren't going to get the breakpoint...
+ */
+
+ LppdCur->pstate = psRunning;
+ for (lptd = LppdCur->lptdList; lptd; lptd = lptd->lptdNext) {
+ lptd->tstate = tsRunning;
+ }
+ Dbg( BPFreeHbpt( (HBPT)LppdCur->hbptSaved ) == BPNOERROR) ;
+ LppdCur->hbptSaved = NULL;
+ BPTResolveAll(LppdCur->hpid,TRUE);
+ SetProcessExceptions(LppdCur);
+ VarMsgBox(NULL, DBG_Attach_Deadlock,
+ MB_OK | MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TASKMODAL);
+ }
+
+ bfRefresh = UPDATE_CONTEXT | UPDATE_WINDOWS;
+ break;
+
+
+
+
+ case dbcLoadComplete:
+
+ lptd = (LPTD) GetQueueItemLong();
+ Assert(lptd != NULL);
+
+ dwNotify = GetQueueItemLong();
+
+ LptdCur = lptd;
+ LppdCur = lptd->lppd;
+
+ Assert(LppdCur->pstate == psPreRunning);
+
+ LptdCur->tstate = tsStopped;
+
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ BPTResolveAll(LppdCur->hpid,TRUE);
+
+ /*
+ * The process is no longer "PreRunning",
+ * but the thread is.
+ */
+
+ LppdCur->pstate = psStopped;
+
+ SetProcessExceptions(LppdCur);
+
+#ifdef SHOW_MAGIC
+ CmdLogFmt("(Process loaded)\r\n");
+#endif
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+
+ /*
+ * Handle go/stop for child here.
+ * For attachee, it is handled in AttachDebuggee()
+ */
+
+ if (LppdCur->fChild) {
+ if (runDebugParams.fChildGo) {
+ Go();
+ } else {
+ DoStopEvent(lptd);
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+ fExecNext = TRUE;
+ bfRefresh = UPDATE_ALLDBGWIN;
+ }
+ }
+
+ break;
+
+
+ case dbcEntryPoint:
+
+ lptd = (LPTD) GetQueueItemLong();
+ Assert(lptd != NULL);
+
+ dwNotify = GetQueueItemLong();
+
+ LptdCur = lptd;
+ lppd =
+ LppdCur = lptd->lppd;
+
+ LptdCur->tstate = tsStopped;
+
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+
+ fRunning = FALSE;
+
+ if (lppd->fInitialStep) {
+
+ // If stepping in source mode,
+ // we will land here.
+
+ // If we are in "regular" mode, try
+ // to find main or WINMAIN or whatever.
+
+ if (!runDebugParams.fEPIsFirstStep) {
+ cxt = *SHpCXTFrompCXF(&CxfIp);
+ fRunning = get_initial_context(&cxt, FALSE);
+ //fRunning = get_initial_context(&cxt, TRUE);
+ if (fRunning) {
+ SYFixupAddr(SHpAddrFrompCxt(&cxt));
+ GoUntil( SHpAddrFrompCxt(&cxt) );
+ } else {
+ VarMsgBox (NULL,
+ ERR_NoSymbols,
+ MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TASKMODAL);
+ }
+ fGetFocus = TRUE;
+ }
+
+ } else if (lppd->hbptSaved) {
+
+ if (!get_initial_context(SHpCXTFrompCXF(&CxfIp), FALSE)) {
+ get_initial_context(SHpCXTFrompCXF(&CxfIp), TRUE);
+ }
+ if (BPBindHbpt( (HBPT)lppd->hbptSaved, &CxfIp ) != BPNOERROR) {
+ Dbg( BPFreeHbpt( (HBPT)lppd->hbptSaved ) == BPNOERROR) ;
+ lppd->hbptSaved = NULL;
+ CmdLogVar(ERR_Unable_To_Complete_Gountil);
+ } else {
+ Dbg( BPAddrFromHbpt( (HBPT)lppd->hbptSaved, &addr ) == BPNOERROR) ;
+ Dbg( BPFreeHbpt( (HBPT)lppd->hbptSaved ) == BPNOERROR) ;
+ lppd->hbptSaved = NULL;
+
+ fRunning = TRUE;
+ GoUntil(&addr);
+ }
+
+ } else if (!lppd->fStopAtEntry) {
+
+ // if stepping in ASM mode, fStopAtEntry
+ // is like a safety BP to stop running after
+ // leaving the loader APC.
+
+ fRunning = TRUE;
+ Go();
+ }
+
+ if (fRunning) {
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ } else {
+ BPClearAllTmp( lppd->hpid, lptd->htid );
+ if (!DoStopEvent(lptd)) {
+ CmdLogVar(DBG_At_Entry_Point);
+ }
+ }
+
+ lppd->fInitialStep = FALSE;
+ lppd->fStopAtEntry = FALSE;
+
+ break;
+
+
+
+ case dbcCheckBpt:
+
+ lptd = (LPTD) GetQueueItemLong();
+ Assert(lptd != NULL);
+
+ dwNotify = GetQueueItemLong();
+
+ LptdCur = lptd;
+ LppdCur = lptd->lppd;
+
+ LptdCur->tstate = tsStopped;
+
+
+ if ( FKilling || !DebuggeeActive() ) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ } else {
+
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ bpstatus = BPCheckHbpt( CxfIp, BPCallbackHbpt,
+ lptd->lppd->hpid, lptd->htid, dwNotify);
+
+ Assert(bpstatus == BPPassBreakpoint || bpstatus == BPNOERROR);
+
+ if (bpstatus == BPPassBreakpoint) {
+
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ dw = FALSE;
+
+ } else {
+
+ DoStopEvent(lptd);
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+ dw = TRUE;
+ }
+ OSDSendReply(lptd->lppd->hpid, sizeof(DWORD), &dw);
+ }
+ break;
+
+
+
+ case dbcBpt: /* DBG_REFRESH */
+
+ lptd = (LPTD) GetQueueItemLong();
+ Assert(lptd != NULL);
+
+ dwNotify = GetQueueItemLong();
+
+ LptdCur = lptd;
+ LppdCur = lptd->lppd;
+
+ LptdCur->tstate = tsStopped;
+
+ UpdateDebuggerState(UPDATE_CONTEXT);
+
+ if ( FKilling || !DebuggeeActive() ) {
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ } else {
+
+ bpstatus = BPCheckHbpt( CxfIp, BPCallbackHbpt,
+ lptd->lppd->hpid, lptd->htid, dwNotify );
+
+ if (bpstatus == BPNoBreakpoint) {
+
+ BPClearAllTmp( lptd->lppd->hpid, lptd->htid );
+
+ DoStopEvent(lptd);
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+
+ CmdLogVar(DBG_Hard_Coded_Breakpoint);
+
+ } else if (bpstatus == BPPassBreakpoint) {
+
+ /*
+ * -- do a go as no breakpoint was matched
+ */
+
+
+ //Assert(!"Unexpected BPPassBreakpoint");
+
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ Go();
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+
+ } else {
+
+ BPClearAllTmp( lptd->lppd->hpid, lptd->htid );
+ DoStopEvent(lptd);
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+ }
+ }
+
+ break;
+
+
+
+ case dbcAsyncStop: /* DBG_REFRESH */
+
+ fExecNext = FALSE;
+
+
+
+ case dbcStep:
+
+ lptd = (LPTD) GetQueueItemLong();
+ Assert(lptd != NULL);
+
+ dwNotify = GetQueueItemLong();
+
+ LptdCur = lptd;
+ LppdCur = lptd->lppd;
+ SetPTState(-1, tsStopped);
+ BPClearAllTmp( lptd->lppd->hpid, lptd->htid );
+ if (!DoStopEvent(lptd) && dbcCallback == dbcAsyncStop) {
+ CmdLogFmt("Stopped in process %d, thread %d\r\n",
+ lptd->lppd->ipid,
+ lptd->itid);
+ }
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+ break;
+
+
+
+ case dbcModLoad: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ hpid = (HPID)GetQueueItemLong();
+ lpsz = (LPSTR)GetQueueItemLong();
+ lppd = LppdOfHpid(hpid);
+ Assert(lppd);
+ Assert(lpsz);
+
+ SHChangeProcess(lppd->hpds);
+ SetFindExeBaseName(lppd->lpBaseExeName);
+ she = SHLoadDll( lpsz, TRUE );
+ emi = SHGethExeFromName((char FAR *) lpsz);
+ Assert(emi != 0);
+ OSDRegisterEmi( hpid, 0, (HEMI)emi, lpsz);
+
+ free(lpsz);
+
+ ModListModLoad( SHGetExeName( emi ), she );
+
+ if (!lppd->lpBaseExeName) {
+ lppd->lpBaseExeName = _strdup(SHGetExeName( emi ));
+ }
+
+ if (she != sheSuppressSyms && runDebugParams.fVerbose) {
+ lpch = SHLszGetErrorText(she);
+ if (she == sheNoSymbols) {
+ CmdLogFmt("Module Load: %s", SHGetExeName( emi ));
+ } else {
+ CmdLogFmt("Module Load: %s", SHGetSymFName( emi ));
+ }
+ if (lpch) {
+ CmdLogFmt(" (%s)", lpch);
+ }
+ CmdLogFmt("\r\n");
+ }
+
+ if (lppd->pstate != psPreRunning) {
+ //
+ // A new module has been loaded. If we are not loading
+ // the statically-linked DLLs of the debugee, we must
+ // try to resolve any unresolved breakpoints.
+ //
+ if (BPTIsUnresolvedCount( hpid )) {
+ LppdCur = lppd;
+ LptdCur = lppd->lptdList;
+
+ UpdateDebuggerState( UPDATE_CONTEXT );
+
+ BPTResolveAll( hpid, FALSE );
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ }
+
+ }
+
+ //
+ // Let processing continue on the MOD load message
+ //
+ OSDLoadDllAck(hpid);
+ fExecNext = FALSE;
+ break;
+
+ case dbcModFree: /* DBG_REFRESH */
+ bfRefresh = UPDATE_CONTEXT;
+ hpid = (HPID)GetQueueItemLong();
+ lppd = LppdOfHpid(hpid);
+ Assert(lppd);
+ emi = (HEXE) GetQueueItemLong();
+ Assert(emi != 0);
+
+ ModListModUnload( SHGetExeName( emi ) );
+
+ //
+ // NOTENOTE a-kentf put text in resource
+ //
+ if (runDebugParams.fVerbose) {
+
+ LPDEBUGDATA DebugData;
+
+ DebugData = SHGetDebugData( emi );
+
+ if (!DebugData || DebugData->she != sheSuppressSyms) {
+ CmdLogFmt("Module Unload: %s\r\n", SHGetExeName( emi ));
+ }
+ }
+
+ //
+ // A module has been unloaded. We must unresolve all
+ // the breakpoints in the module.
+ //
+ if (lppd->pstate == psRunning) {
+ BPTUnResolve( emi );
+ }
+
+ SHUnloadDll( emi );
+ OSDUnLoadDllAck( hpid, emi, TRUE );
+ InvalidateAllWindows();
+
+ fExecNext = FALSE;
+ break;
+
+
+
+ case dbcCreateThread: /* DBG_INFO */
+
+ bfRefresh = UPDATE_NONE;
+ fExecNext = FALSE;
+
+ Dbg(GetQueueItemLong() == 0);
+
+ hpid = (HPID)GetQueueItemLong();
+ htid = (HTID)GetQueueItemLong();
+
+ lppd = LppdOfHpid(hpid);
+
+ if (!lppd && !LppdFirst) {
+
+ //
+ // when blowing off the debuggee, some stray events
+ // may be in this queue...
+ //
+
+ break;
+ }
+ Assert(lppd);
+
+ lptd = CreateTd(lppd, htid);
+ Assert(lptd);
+
+ LppdT = LppdCur = lppd;
+ LptdT = LptdCur = lptd;
+ UpdateDebuggerState( UPDATE_CONTEXT );
+
+ // NOTENOTE a-kentf put text in resource
+ if (runDebugParams.fNotifyThreadCreate) {
+ CmdLogFmt("Thread Create: Process=%d, Thread=%d\r\n",
+ lptd->lppd->ipid, lptd->itid);
+ }
+
+ if (LppdCur->pstate == psRunning) {
+ BPTResolveAll( hpid, TRUE );
+ }
+
+ SetPTState(-1, tsStopped);
+ Go();
+
+ break;
+
+
+
+ case dbcThreadTerm: /* DBG_REFRESH */
+ lptd = (LPTD) GetQueueItemLong();
+ if ( lptd == 0) {
+ hpid = (HPID)GetQueueItemLong();
+ htid = (HTID)GetQueueItemLong();
+ lppd = LppdOfHpid(hpid);
+ lptd = LptdOfLppdHtid(lppd, htid);
+ }
+ lExit = GetQueueItemLong();
+
+ if (!lptd && !LppdFirst) {
+
+ //
+ // when blowing off the debuggee, some stray events
+ // may be in this queue...
+ //
+
+ break;
+ }
+
+ Assert(lptd != NULL);
+ lppd = lptd->lppd;
+
+ LppdCur = lppd;
+ LptdCur = lptd;
+ SetPTState(-1, tsExited);
+
+ // NOTENOTE a-kentf put text in resource
+ if (runDebugParams.fNotifyThreadTerm) {
+ CmdLogFmt("Thread Terminate: Process=%d, Thread=%d, Exit Code=%ld\r\n",
+ lptd->lppd->ipid, lptd->itid, lExit);
+ }
+
+ if (lptd->fInFuncEval) {
+ fExecNext = FALSE;
+ LptdFuncEval = NULL;
+ }
+
+ BPTUnResolvePidTid( lppd->hpid, lptd->htid );
+
+ if (lptd->fGoOnTerm ||
+ runDebugParams.fGoOnThreadTerm ||
+ !runDebugParams.fNotifyThreadTerm) {
+ Go();
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ } else {
+ DoStopEvent(NULL);
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+ bfRefresh |= UPDATE_NOFORCE;
+ }
+ break;
+
+ case dbcThreadDestroy: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ lptd = (LPTD) GetQueueItemLong();
+ if ( lptd ) {
+ lppd = lptd->lppd;
+ Assert(lppd != NULL);
+#ifdef SHOW_MAGIC
+ CmdLogFmt("DBG: Thread Destroy: Process=%d, Thread=%d\r\n",
+ lptd->lppd->ipid, lptd->itid);
+#endif
+ if (lptd->fInFuncEval) {
+ LptdFuncEval = NULL;
+ }
+ OSDDestroyTID(lptd->htid);
+ DestroyTd(lptd);
+ if (LppdCur == lppd && LptdCur == lptd) {
+ LptdCur = NULL;
+ }
+ lptd = NULL;
+ }
+ fExecNext = FALSE;
+ break;
+
+ case dbcNewProc: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ /*
+ * This will occur on all but the first process created.
+ */
+ hpid = (HPID)GetQueueItemLong();
+ lppd = LppdOfHpid(hpid);
+
+ Assert(lppd == NULL);
+
+ lppd = CreatePd(hpid);
+
+ lppd->hpds = SHCreateProcess();
+ SHSetHpid(hpid);
+
+ SetProcessExceptions(lppd);
+
+ /*
+ * proc is PreRunning until ldr BP
+ */
+
+ lppd->pstate = psPreRunning;
+
+ /*
+ * If it is an attach, not a child, AttachDebuggee() will
+ * clear this flag in a moment.
+ */
+ lppd->fChild = TRUE;
+
+ // NOTENOTE a-kentf put text in resource
+ CmdLogFmt("Process Create: Process=%d\r\n", lppd->ipid);
+
+ /*
+ * This won't be the current process yet, because
+ * there isn't a thread for it until we get notified.
+ */
+
+ fExecNext = FALSE;
+ break;
+
+
+ case dbcProcTerm: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ lppd = LppdOfHpid((HPID) GetQueueItemLong());
+ LppdCur = lppd;
+ LptdCur = NULL;
+ SetPTState(psExited, -1);
+ lExit = GetQueueItemLong();
+
+ if (!FKilling) {
+ // NOTENOTE a-kentf put text in resource
+ CmdLogFmt("Process Terminate: Process=%d, Exit Code=%ld\r\n",
+ lppd->ipid, lExit);
+ }
+
+ /*
+ * Unresolve all the breakpoints. This way they can be
+ * resolved again upon restarting.
+ */
+
+ BPClearAllTmp( lppd->hpid, 0 );
+ BPTUnResolveAll(lppd->hpid);
+
+ fExecNext = FALSE;
+ LppdCur = NULL;
+ LptdCur = NULL;
+
+ bfRefresh |= UPDATE_NOFORCE;
+ break;
+
+ case dbcDeleteProc: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ hpid = (HPID)GetQueueItemLong();
+ lppd = LppdOfHpid(hpid);
+
+#ifdef SHOW_MAGIC
+ CmdLogFmt("DBG: Process Destroy: Process=%d\r\n", lppd->ipid);
+#endif
+
+ SHChangeProcess(lppd->hpds);
+
+ while ( emi = SHGetNextExe( (HEXE) NULL ) ) {
+ SHUnloadDll( emi );
+ OSDUnLoadDllAck( hpid, emi, FALSE );
+ }
+
+ ClearProcessExceptions(lppd);
+
+ if (!lppd->fPrecious) {
+ SHDeleteProcess(lppd->hpds);
+ OSDDestroyPID(hpid);
+ }
+
+ DestroyPd(lppd, FALSE);
+ RecycleIpid1();
+
+ if (lppd == LppdCur) {
+ LppdCur = NULL;
+ LptdCur = NULL;
+ } else if (LppdCur) {
+ SHChangeProcess(LppdCur->hpds);
+ bfRefresh |= (UPDATE_NOFORCE | UPDATE_CONTEXT);
+ }
+
+ break;
+
+ case dbcInfoAvail: /* DBG_INFO */
+
+ bfRefresh = UPDATE_NONE;
+ fExecNext = FALSE;
+
+ fReply = GetQueueItemLong(); // Reply flag
+
+ if (!GetQueueItemLong()) { /* fUniCode */
+ // ANSI
+ lpsz = (LPSTR) GetQueueItemLong(); /* String */
+ CmdLogDebugString( lpsz, TRUE );
+ } else {
+ // Unicode
+ LPWSTR lpw;
+
+ lpw = (LPWSTR) GetQueueItemLong(); /* String */
+ l = WideCharToMultiByte(CP_ACP,
+ 0,
+ lpw,
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ lpsz = malloc(l+1);
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpw,
+ -1,
+ lpsz,
+ l+1,
+ NULL,
+ NULL
+ );
+ CmdLogDebugString(lpsz, TRUE);
+ free(lpw);
+ }
+
+ if (fWaitForDebugString) {
+ char *lpsz1=lpsz;
+ while (lpsz1 && *lpsz1) {
+ if (*lpsz1 == '\r' || *lpsz1 == '\n') {
+ *lpsz1 = '\0';
+ } else {
+#ifdef DBCS
+ lpsz1 = CharNext(lpsz1);
+#else
+ lpsz1++;
+#endif
+ }
+ }
+ if (_stricmp(lpsz, lpCmdString)==0) {
+ free(lpCmdString);
+ fExecNext = TRUE;
+ }
+ }
+ free(lpsz);
+
+ if (fReply && LppdCur) {
+ OSDSendReply(LppdCur->hpid, 0, NULL);
+ }
+
+ break;
+
+ case dbcInfoReq:
+
+ bfRefresh = UPDATE_NONE;
+ fExecNext = TRUE;
+
+ if (!GetQueueItemLong()) { /* fUniCode */
+ // ANSI
+ lpsz = (LPSTR) GetQueueItemLong(); /* String */
+ } else {
+ // Unicode
+ LPWSTR lpw;
+
+ lpw = (LPWSTR) GetQueueItemLong(); /* String */
+ l = WideCharToMultiByte(CP_ACP,
+ 0,
+ lpw,
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ lpsz = malloc(l+1);
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpw,
+ -1,
+ lpsz,
+ l+1,
+ NULL,
+ NULL
+ );
+ free(lpw);
+ }
+
+ CmdGetDefaultPrompt(szOldPrompt);
+ CmdSetDefaultPrompt(lpsz);
+ CmdSetCmdProc(CmdHandleInputString, CmdExecutePrompt);
+ CmdDoPrompt(TRUE, TRUE);
+ FCmdDoingInput = TRUE;
+ free(lpsz);
+ break;
+
+ case dbcNtRip: /* DBG_REFRESH */
+ Assert(!"This never happens");
+ break;
+#if 0
+ //
+ // Will RIPs be resurrected?
+ // Does this code work on Chicago?
+ // Will Elvis return?
+ //
+ {
+ char rgchT[1024];
+ LPNT_RIP lpNtRip;
+
+ lptd = (LPTD) GetQueueItemLong();
+ Assert(lptd);
+ lppd = lptd->lppd;
+ htid = lptd->htid;
+ hpid = lppd->hpid;
+
+ LppdCur = lppd;
+ LptdCur = lptd;
+
+ lpNtRip = (LPNT_RIP)GetQueueItemLong();
+
+ SetPTState(-1, tsRipped);
+
+ if (lpNtRip->ulErrorLevel <= ulRipNotifyLevel) {
+ // NOTENOTE a-kentf put text in resource
+ switch (lpNtRip->ulErrorLevel) {
+ case SLE_WARNING:
+ lpsz = "WARNING";
+ break;
+ case SLE_MINORERROR:
+ lpsz = "ERROR";
+ break;
+ case SLE_ERROR:
+ lpsz = "FATAL";
+ break;
+ default:
+ lpsz = "UNKNOWN";
+ }
+ CmdLogFmt("%s: [%04X] ", lpsz, lpNtRip->ulErrorCode);
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lpNtRip->ulErrorCode,
+ 0,
+ rgchT,
+ sizeof(rgchT),
+ NULL);
+ lpsz = rgchT + strlen(rgchT) - 1;
+ while (lpsz > rgchT && (*lpsz == '\r' || *lpsz == '\n')) {
+#ifdef DBCS
+ *lpsz = 0;
+ lpsz = CharPrev(rgchT, lpsz);
+#else
+ *lpsz-- = 0;
+#endif
+ }
+
+ CmdLogFmt("%s\r\n", rgchT);
+ }
+
+ if (lpNtRip->ulErrorLevel <= ulRipBreakLevel) {
+ if (!DoStopEvent(lptd)) {
+ CmdLogVar(DBG_Thread_Stopped);
+ }
+ lptd->lppd->fStopAtEntry = FALSE;
+ fGetFocus = TRUE;
+ } else if (OSDPtrace(osdGo, 0, NULL, hpid, htid) != xosdNone) {
+ lptd->lppd->fStopAtEntry = FALSE;
+ CmdLogVar(ERR_Cant_Continue_Rip);
+ fGetFocus = TRUE;
+ } else {
+ SetPTState(-1, tsRunning);
+ // restore old proc/thrd
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ }
+ break;
+ }
+#endif
+
+ case dbcException: /* DBG_REFRESH */
+ {
+ EXCEPTION_FILTER_DEFAULT efd;
+ EXCEPTION_LIST *eList;
+ EPR epr;
+ XOSD err;
+
+ lptd = (LPTD) GetQueueItemLong();
+ if (lptd != 0) {
+ lppd = lptd->lppd;
+ htid = lptd->htid;
+ hpid = lppd->hpid;
+ } else {
+ hpid = (HPID)GetQueueItemLong();
+ htid = (HTID)GetQueueItemLong();
+ lppd = LppdOfHpid(hpid);
+ Assert(lppd);
+ lptd = LptdOfLppdHtid(lppd, htid);
+ }
+
+ LppdCur = lppd;
+ LptdCur = lptd;
+
+ epr = *((LPEPR) GetQueueItemLong());
+
+ if (LppdCur->pstate == psPreRunning) {
+
+ /*
+ * We hit an exception before the process
+ * had finished loading. We probably won't ever
+ * hit the loader BP, so mark this as loaded now.
+ */
+
+ LppdCur->pstate = psStopped;
+
+ BPTResolveAll(LppdCur->hpid,TRUE);
+ SetProcessExceptions(LppdCur);
+
+#ifdef SHOW_MAGIC
+ CmdLogFmt("(Exception caught while loading)\r\n");
+#endif
+ }
+
+ for ( eList = LppdCur->exceptionList; eList;
+ eList = eList->next ) {
+ if ( eList->dwExceptionCode == epr.ExceptionCode ) {
+ break;
+ }
+ }
+
+ if (epr.dwFirstChance) {
+ efd = (eList == 0)? efdStop : eList->efd;
+ SetPTState(-1, tsException1);
+ } else {
+ efd = efdStop;
+ SetPTState(-1, tsException2);
+ }
+
+ AuxPrintf(1, "Exception %d, efd == %d", epr.ExceptionCode, efd);
+
+ switch (efd) {
+ case efdNotify:
+ case efdStop:
+ CmdLogVar((WORD)((epr.dwFirstChance)?
+ DBG_Exception1_Occurred : DBG_Exception2_Occurred),
+ epr.ExceptionCode,
+ (eList == NULL || eList->lpName == NULL) ?
+ "Unknown" : eList->lpName);
+
+ if ( efd == efdStop ) {
+ fGetFocus = TRUE;
+ lptd->lppd->fStopAtEntry = FALSE;
+ if ( eList ) {
+ if ( epr.dwFirstChance && eList->lpCmd ) {
+ CmdPrependCommands(lptd, eList->lpCmd);
+ } else if ( !epr.dwFirstChance && eList->lpCmd2 ) {
+ CmdPrependCommands(lptd, eList->lpCmd2);
+ }
+ }
+ if (!DoStopEvent(lptd)) {
+ CmdLogVar(DBG_Thread_Stopped);
+ }
+ break;
+ }
+
+
+ case efdIgnore:
+
+ // go unhandled
+ {
+ EXOP exop = {0};
+ exop.fPassException = TRUE;
+ err = OSDGo(lppd->hpid, lptd->htid, &exop);
+ }
+
+ if (err == xosdNone) {
+ SetPTState(-1, tsRunning);
+ // restore old proc/thrd
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ } else {
+ CmdLogVar(ERR_Cant_Cont_Exception);
+ fGetFocus = TRUE;
+ }
+ break;
+
+ default:
+ // undefined efd value
+ bfRefresh = UPDATE_NONE;
+ CmdLogFmt("INTERNAL ERROR: unrecognized efd %d\r\n", efd);
+ Assert(FALSE);
+ }
+ }
+ break;
+
+ /*
+ * This message is recieved when a function call from the
+ * expression evaluator is finished.
+ *
+ * DO NOTHING
+ */
+
+ case dbcExecuteDone: /* DBG_INFO */
+ bfRefresh = UPDATE_NONE;
+ fRecurse = FALSE;
+ fExecNext = FALSE;
+ break;
+
+ case dbcIoctlDone: // Some Ioctl has finished executing
+ GetQueueItemLong();
+ SetEvent( hEventIoctl );
+ bfRefresh = UPDATE_NONE;
+ fExecNext = FALSE;
+ break;
+
+ case dbcCanStep:
+ CmdLogFmt("Should never get a %d\r\n", dbcCallback);
+ RAssert(FALSE);
+ break;
+
+ case (DBC)dbcRemoteQuit:
+ bfRefresh = UPDATE_NONE;
+ CmdLogFmt("Connection to remote has been broken\r\n" );
+ CmdLogFmt("Stopped debugging\r\n" );
+ DisconnectDebuggee();
+ fRecurse = FALSE;
+ return bfRefresh;
+
+ case (DBC)dbcChangedMemory:
+ bfRefresh = UPDATE_NONE;
+ BPUpdateMemory( GetQueueItemLong() );
+ fExecNext = FALSE;
+ bfRefresh = UPDATE_NONE;
+ break;
+
+ case dbcSegLoad:
+
+ lptd = (LPTD)GetQueueItemLong();
+ Assert(lptd != NULL);
+ lppd = lptd->lppd;
+ LppdCur = lppd;
+ LptdCur = lptd;
+
+ bfRefresh = UPDATE_NONE;
+ fExecNext = FALSE;
+
+ SHChangeProcess(lppd->hpds);
+ BPSegLoad( (ULONG)GetQueueItemLong() );
+
+ Go();
+ break;
+
+ case (DBC)dbcCommError:
+ default:
+ lptd = (LPTD) GetQueueItemLong();
+ if (lptd == NULL) {
+ hpid = (HPID)GetQueueItemLong();
+ htid = (HTID)GetQueueItemLong();
+ }
+ CmdLogFmt("Unknown %x\r\n", dbcCallback);
+ fExecNext = FALSE;
+ }
+
+ /*
+ * Thread and/or process may have been changed - try to make
+ * sure that both are valid, and update status line.
+ */
+
+ if (LptdCur != NULL) {
+ LppdCur = LptdCur->lppd;
+ } else if (LppdCur != NULL) {
+ LptdCur = LppdCur->lptdList;
+ }
+
+ if (LptdCur == NULL) {
+ GetFirstValidPDTD(&LppdCur, &LptdCur);
+ }
+
+ if (LppdCur == NULL) {
+ AuxPrintf(1, "(CmdExecNext: There are no processes)");
+ } else if (LptdCur == NULL) {
+ AuxPrintf(1, "(CmdExecNext: There are no threads)");
+ } else if (LppdCur != LppdT || LptdCur != LptdT) {
+ bfRefresh |= UPDATE_CONTEXT;
+ }
+
+ /*
+ * update status line
+ * Always do this, to be safe. If it causes excessive flashing,
+ * we can change it, but greater care must be taken to ensure that
+ * it is always correct.
+ */
+ StatusPidTid((LppdCur != NULL)? LppdCur->ipid : -1,
+ (LptdCur != NULL) ? LptdCur->itid : -1);
+
+ if (fGetFocus) {
+
+ HEXE hexe;
+ ADDR Addr;
+
+ if (LppdCur && LptdCur) {
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, adrPC, &Addr);
+ SHChangeProcess(LppdCur->hpds);
+ }
+
+ if ( (HPID)emiAddr( Addr ) == LppdCur->hpid ) {
+ //
+ // Get right EMI and load symbols if defered.
+ //
+ emiAddr( Addr ) = 0;
+#ifdef OSDEBUG4
+ OSDSetEmi(LppdCur->hpid,LptdCur->htid,&Addr);
+#else
+ OSDPtrace(osdSetEmi, wNull, &Addr, LppdCur->hpid, LptdCur->htid);
+#endif
+ }
+
+ hexe = (HEXE)emiAddr( Addr );
+ if ( hexe && (HPID)hexe != LppdCur->hpid ) {
+ SHWantSymbols( hexe );
+ }
+
+ if (!RemoteRunning) {
+ EnsureFocusDebugger();
+ }
+ }
+
+
+ /*
+ * Update the users view of the world to reflect the last debug
+ * event.
+ */
+
+ if ((bfRefresh != UPDATE_NONE) &&
+ (LptdCur != NULL) && (!LptdCur->fInFuncEval)) {
+ UpdateDebuggerState(bfRefresh);
+ }
+
+ /*
+ * Worry about executing the next command on the list
+ */
+
+ if (fExecNext && (LptdCur == NULL || LptdCur->fInFuncEval == FALSE) ) {
+
+ if (CmdExecuteLine(NULL)) {
+ if ((AutoRun == arSource || AutoRun == arCmdline)
+ && !FAutoRunSuppress && !emergency ) {
+ PostMessage(Views[cmdView].hwndClient, WU_AUTORUN, 0, 0);
+ } else {
+ CmdDoPrompt(!FCmdDoingInput, FALSE);
+ }
+ } else {
+ fGetFocus = FALSE;
+ }
+ }
+
+
+ }
+
+ fRecurse = FALSE;
+ return(bfRefresh);
+} /* CmdExecNext() */
+
+
+
+BOOL FAR PASCAL
+GetAutoRunSuppress(
+ void
+ )
+{
+ return FAutoRunSuppress;
+}
+
+
+BOOL FAR PASCAL
+SetAutoRunSuppress(
+ BOOL f
+ )
+{
+ BOOL ff = FAutoRunSuppress;
+ FAutoRunSuppress = f;
+ return ff;
+}
+
+/***********************************************************************
+
+ Hotkey handler
+
+ ^C is used for a general interrupt signal. When a ^C is caught,
+ a list of handlers is walked. Each handler is executed, and the return
+ value checked. If the return value is TRUE, the walk continues. If
+ the value is FALSE, the walk is terminated.
+
+ The list is walked in MRU order; the most recently registered handler
+ is called first.
+
+***********************************************************************/
+
+
+PCTRLC_HANDLER
+AddCtrlCHandler(
+ CTRLC_HANDLER_PROC pfnFunc,
+ DWORD dwParam
+ )
+/*++
+
+Routine Description:
+
+ Add a CtrlC handler routine to the handler list.
+
+Arguments:
+
+ pfnFunc - Supplies pointer to handler function
+ dwParam - Supplies parameter to pass to function
+
+Return Value:
+
+ A pointer to the registered handler. This is only used
+ for removing the handler from the chain.
+
+--*/
+{
+ PCTRLC_HANDLER pcch = malloc(sizeof(CTRLC_HANDLER));
+ if (pcch) {
+ pcch->pfnFunc = pfnFunc;
+ pcch->dwParam = dwParam;
+ pcch->next = PcchHead;
+ PcchHead = pcch;
+ }
+ return pcch;
+}
+
+
+BOOL
+RemoveCtrlCHandler(
+ PCTRLC_HANDLER pcch
+ )
+/*++
+
+Routine Description:
+
+ Remove a CtrlC handler from the list. This can remove a specific
+ handler, or remove the last one added.
+
+Arguments:
+
+ pcch - Supplies pointer to the handler to remove. If this is
+ NULL, the last one added will be removed.
+
+Return Value:
+
+ TRUE if the handler was removed, FALSE if it did not exist.
+
+--*/
+{
+ PCTRLC_HANDLER *ppcch;
+ if (!pcch) {
+ pcch = PcchHead;
+ }
+
+ for ( ppcch = &PcchHead; *ppcch; ppcch = &((*ppcch)->next) ) {
+ if (*ppcch == pcch) {
+ *ppcch = pcch->next;
+ free(pcch);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+VOID
+DispatchCtrlCEvent(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Walk the list of Ctrl C handlers, calling each one until one
+ returns FALSE.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ PCTRLC_HANDLER pcch;
+ for (pcch = PcchHead; pcch; pcch = pcch->next) {
+ if (!(*pcch->pfnFunc)(pcch->dwParam)) {
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************
+
+
+
+*******************************************************************/
+
+BOOL
+DoCtrlCAsyncStop(
+ DWORD dwParam
+ )
+{
+ CmdInsertInit();
+ CmdLogFmt("^C <process stopping...>\r\n");
+ AsyncStop();
+
+ return dwParam;
+}
+
+
+BOOL
+PolledCtrlCHandler(
+ DWORD dwParam
+ )
+{
+ CmdInsertInit();
+ CmdLogFmt("^C\r\n");
+ fCtrlCPressed = TRUE;
+ return dwParam;
+}
+
+
+void FAR PASCAL
+SetCtrlCTrap(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This manages a polled Ctrl C trap. Add a handler which sets
+ a flag.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ fCtrlCPressed = FALSE;
+ pPolledCtrlCHandler = AddCtrlCHandler(PolledCtrlCHandler, FALSE);
+}
+
+void FAR PASCAL
+ClearCtrlCTrap(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Clear trap for polled CTRL-C
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ if (pPolledCtrlCHandler) {
+ RemoveCtrlCHandler(pPolledCtrlCHandler);
+ pPolledCtrlCHandler = NULL;
+ }
+ fCtrlCPressed = FALSE;
+}
+
+BOOL FAR PASCAL
+CheckCtrlCTrap(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Allow any hotkey events to be handled, then check the POLLED Ctrl C
+ flag. If the Ctrl C polling handler is not in use, this will return
+ FALSE and not drain the message queue.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if CTRL-C was pressed since last checked.
+
+--*/
+{
+ BOOL f;
+ MSG msg;
+
+ if (!pPolledCtrlCHandler) {
+ return FALSE;
+ }
+
+ while (PeekMessage(&msg, NULL, WM_HOTKEY, WM_HOTKEY, PM_REMOVE))
+ {
+ ProcessQCQPMessage(&msg);
+ }
+ f = fCtrlCPressed;
+ fCtrlCPressed = FALSE;
+ return f;
+}
+
+
+BOOL FAR PASCAL
+CmdSetEatEOLWhitespace(
+ BOOL ff
+ )
+/*++
+
+Routine Description:
+
+ Set value of EatEOLWhitespace flag to control behaviour of
+ data entry in command window.
+
+Arguments:
+
+ ff - Supplies new value for fEatEOLWhitespace
+
+Return Value:
+
+ Old value of fEatEOLWhitespace
+
+--*/
+{
+ BOOL f = fEatEOLWhitespace;
+ fEatEOLWhitespace = ff;
+ return f;
+}
+
+void
+CmdSetAutoHistOK(
+ BOOL f
+ )
+{
+ FAutoHistOK = f;
+}
+
+BOOL
+CmdGetAutoHistOK(
+ void
+ )
+{
+ return FAutoHistOK;
+}
+
+long FAR PASCAL EXPORT
+CmdEditProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ This function is the window message processor for the command
+ window class. It processes those messages which are of interest
+ to this specific window class and passes all other messages on to
+ the default MDI window procedure handler
+
+Arguments:
+
+ hwnd - Supplies window handle to the command window
+ msg - Supplies message to be processed
+ wParam - Supplies info about the message
+ lParam - Supplies info about the message
+
+Return Value:
+
+ various
+
+--*/
+{
+ int i;
+ int x;
+ LONG lRet;
+ int XPos, YPos;
+ int Xro, Yro;
+ BOOL fShift;
+ BOOL fCtrl;
+ int first;
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ char szStr[MAX_LINE_SIZE];
+ int doc = Views[cmdView].Doc;
+ int nLines;
+ BOOL fDoHist;
+
+ static BOOL fShowingLine = FALSE;
+ static BOOL fEdited = FALSE;
+ static int nHistoryLine = 0;
+ static int nHistBufTop = 0; // oldest command in history
+ static int nHistBufBot = 0; // where next one goes
+ static LPSTR alpszHistory[MAX_CMDWIN_HISTORY];
+
+
+ switch (msg) {
+
+ case WU_INITDEBUGWIN:
+
+ /*
+ * set up ctrlc handler
+ */
+ AddCtrlCHandler(DoCtrlCAsyncStop, FALSE);
+
+ /*
+ ** Initialize cmd processor, show initial prompt.
+ */
+
+ CmdSetDefaultCmdProc();
+ if (!AutoRun) {
+ CmdDoPrompt(TRUE, TRUE);
+ GetRORegion(cmdView, &Xro, &Yro);
+ PosXY(cmdView, Xro, Yro, FALSE);
+ }
+
+ return FALSE;
+
+
+ case WM_SETFOCUS:
+ RegisterAndMapLocalHotKey(hwnd, IDH_CTRLC, MOD_CONTROL, 'C');
+ break;
+
+ case WM_KILLFOCUS:
+ UnregisterLocalHotKey(IDH_CTRLC);
+ break;
+
+ case WM_HOTKEY:
+
+ if (wParam == IDH_CTRLC) {
+ DispatchCtrlCEvent();
+ }
+ break;
+
+ case WM_KEYDOWN:
+
+ fShift = (GetKeyState(VK_SHIFT) < 0);
+ fCtrl = (GetKeyState(VK_CONTROL) < 0);
+ GetRORegion(cmdView, &Xro, &Yro);
+ XPos = Views[cmdView].X;
+ YPos = Views[cmdView].Y;
+ nLines = max(Docs[doc].NbLines, 1);
+
+ if (YPos >= Yro && XPos >= Xro) {
+
+ if (YPos > Yro) {
+ Xro = 0;
+ }
+
+ // In writeable region
+
+ switch (wParam) {
+
+ case 'R':
+ if (fCtrl) {
+ // hack...
+ // this is just a macro for ".resync"
+ InsertBlock(doc, Xro, YPos, 7, ".resync");
+ InvalidateLines(cmdView, nLines-1, nLines-1, TRUE);
+ PosXY(cmdView, Xro + 7, nLines-1, FALSE);
+ lRet = 0;
+ break;
+ }
+
+ default:
+ fEdited = TRUE;
+ lRet = CallWindowProc(lpfnEditProc, hwnd, msg, wParam, lParam);
+ break;
+
+ case VK_UP:
+
+ lRet = 0;
+
+ if (fCtrl) {
+
+ // Execute magic ctrl-up
+ KeyDown(cmdView, wParam, fShift, FALSE);
+
+ } else {
+
+ // get previous history line, if any:
+ if (!fShowingLine) {
+
+ // up from new line; show last cmd
+ goto GotHistLine;
+
+ } else if (nHistoryLine != nHistBufTop) {
+
+ if (--nHistoryLine < 0) {
+ nHistoryLine = MAX_CMDWIN_HISTORY-1;
+ }
+ goto GotHistLine;
+ } /* else don't do anything */
+ }
+
+ lRet = 0;
+ break;
+
+ case VK_DOWN:
+
+ // get next history line
+
+ lRet = 0;
+
+ i = nHistoryLine;
+
+ if (i != nHistBufBot && ++i >= MAX_CMDWIN_HISTORY) {
+ i = 0;
+ }
+
+ if (i != nHistBufBot) {
+ nHistoryLine = i;
+ } else {
+ // no more history; forget it.
+ break;
+ }
+
+ GotHistLine:
+
+ // is history empty?
+ if (!alpszHistory[nHistoryLine]) {
+ break;
+ }
+
+ fShowingLine = TRUE;
+ fEdited = FALSE;
+
+ // erase command line...
+ DeleteBlock(doc, Xro, nLines - 1, MAX_USER_LINE, nLines - 1);
+
+ // insert new line:
+ InsertBlock(doc, Xro, nLines-1,
+ _fstrlen(alpszHistory[nHistoryLine]),
+ alpszHistory[nHistoryLine]);
+ InvalidateLines(cmdView, nLines-1, nLines-1, TRUE);
+ PosXY(cmdView, Xro + _fstrlen(alpszHistory[nHistoryLine]), nLines-1, FALSE);
+
+ break;
+
+ case VK_LEFT:
+
+ lRet = 0;
+ if (XPos > Xro) {
+ lRet = CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam );
+ } else if (fCtrl) {
+ KeyDown(cmdView, wParam, fShift, FALSE);
+ }
+ break;
+
+ case VK_BACK:
+
+ lRet = 0;
+ if (XPos > Xro) {
+ fEdited = TRUE;
+ lRet = CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam );
+ }
+ break;
+
+ case VK_HOME:
+ if (fCtrl) {
+ lRet = CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam );
+ } else {
+ PosXY(cmdView, Xro, nLines-1, FALSE);
+ }
+ break;
+
+ case VK_ESCAPE:
+
+ // erase command line...
+ DeleteBlock(doc, Xro, nLines - 1, MAX_USER_LINE, nLines - 1);
+ PosXY(cmdView, Xro, nLines - 1, FALSE);
+ InvalidateLines(cmdView, nLines-1, nLines-1, TRUE);
+
+ fShowingLine = FALSE;
+ fEdited = TRUE;
+ break;
+
+ case VK_RETURN:
+
+ first = YPos;
+ FirstLine(doc, &pl, &first, &pb);
+ if (!fEatEOLWhitespace) {
+ x = pl->Length - LHD;
+ } else {
+ // put cursor after last non-white char on line
+ // ExpandTabs() expands the string into global
+ // el[] and remembers the length in elLen.
+ ExpandTabs(&pl);
+ x = elLen-1;
+ while (x > -1) {
+ if (isspace(el[x])) {
+ --x;
+ } else {
+ break;
+ }
+ }
+ x++;
+ }
+ x = max(x, Xro);
+
+
+ if (!runDebugParams.fCommandRepeat || !CmdGetAutoHistOK() || x != Xro) {
+ PosXY(cmdView, x, YPos, FALSE);
+ fDoHist = TRUE;
+ } else {
+ fDoHist = FALSE;
+ if (!alpszHistory[nHistoryLine]) {
+ *szStr = 0;
+ } else {
+ _fstrcpy(szStr, alpszHistory[nHistoryLine]);
+
+ if (tolower(*szStr) == 'g' || tolower(*szStr) == '.' ||
+ tolower(*szStr) == 'l') {
+
+ *szStr = 0;
+
+ } else {
+
+ InsertBlock(doc, Xro, YPos,
+ _fstrlen(alpszHistory[nHistoryLine]),
+ alpszHistory[nHistoryLine]);
+ InvalidateLines(cmdView, nLines-1, nLines-1, TRUE);
+ PosXY(cmdView,
+ Xro + _fstrlen(alpszHistory[nHistoryLine]),
+ YPos,
+ FALSE);
+
+ }
+ }
+ }
+
+ // give user visual feedback
+ SetCaret(cmdView, 0, YPos, -1);
+ UpdateWindow(hwnd);
+
+ // give CR to edit mangler
+ lRet = CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam );
+
+ // the line we just entered (reload it, it may have been mangled):
+ first = YPos;
+ FirstLine(doc, &pl, &first, &pb);
+
+ if (fDoHist) {
+ _fstrncpy(szStr, pl->Text + Xro, x - Xro);
+ szStr[x - Xro] = 0;
+ // remember history
+ // this version remembers everything in order,
+ // but still only resets the history line when
+ // it has been edited.
+ if (*szStr) {
+ if (alpszHistory[nHistBufBot]) {
+ Assert(nHistBufBot == nHistBufTop);
+ _ffree(alpszHistory[nHistBufTop++]);
+ if (nHistBufTop >= MAX_CMDWIN_HISTORY) {
+ nHistBufTop = 0;
+ }
+ }
+ if (!fShowingLine || fEdited) {
+ nHistoryLine = nHistBufBot;
+ }
+ alpszHistory[nHistBufBot++] = _strdup(szStr);
+ if (nHistBufBot >= MAX_CMDWIN_HISTORY) {
+ nHistBufBot = 0;
+ }
+ }
+ }
+
+ fShowingLine = FALSE;
+
+ CmdFileString(szStr);
+ CmdFileString("\r\n");
+ SendClientOutput(szStr, strlen(szStr));
+ SendClientOutput("\r\n", 2);
+ CmdDoLine(szStr);
+ CmdDoPrompt(TRUE, TRUE);
+
+ lRet = 0;
+ break;
+ }
+
+ } else {
+
+ // in readonly region
+ // everything has to work here... the edit mangler will protect
+ // the readonly region, so we can just throw everything at it, but
+ // we need to decide when to fall onto the command line, and when
+ // to leave things alone...
+
+ first = nLines - 1;
+ FirstLine(doc, &pl, &first, &pb);
+
+ if (wParam == CTRL_M) {
+ // position at end of cmd line
+ ClearSelection(cmdView);
+ PosXY(cmdView, pl->Length-LHD, nLines - 1, FALSE);
+ lRet = 0;
+ } else {
+
+ EnableReadOnlyBeep(FALSE);
+ lRet = CallWindowProc(lpfnEditProc, hwnd, msg, wParam, lParam);
+ if (QueryReadOnlyError()) {
+ // position at end of command line, and try again
+ ClearSelection(cmdView);
+ PosXY(cmdView, pl->Length-LHD, nLines - 1, FALSE);
+ lRet = CallWindowProc(lpfnEditProc, hwnd, msg, wParam,
+ lParam);
+ }
+ EnableReadOnlyBeep(TRUE);
+
+ }
+ }
+
+ return lRet;
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ if (IR_STRING != wParam) {
+ break;
+ }
+ // Fall through
+#endif
+
+ case WM_CHAR:
+
+ // the interesting cases have already been handled; we just want
+ // to fall onto the command line in case of an error
+
+ if (wParam == CTRL_R) {
+ return 0;
+ }
+
+ EnableReadOnlyBeep(FALSE);
+ lRet = CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam );
+ if (QueryReadOnlyError()) {
+ // position at end of command line, and try again
+ ClearSelection(cmdView);
+ nLines = max(Docs[doc].NbLines, 1);
+ first = nLines - 1;
+ FirstLine(doc, &pl, &first, &pb);
+ PosXY(cmdView, pl->Length-LHD, nLines - 1, FALSE);
+ lRet = CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam );
+ }
+ EnableReadOnlyBeep(TRUE);
+
+ return lRet;
+
+ case WM_PASTE:
+
+ if (OpenClipboard(hwndFrame)) {
+ HANDLE hData;
+ DWORD size;
+ LPSTR p1;
+ LPSTR p;
+
+ hData = GetClipboardData(CF_TEXT);
+
+ if (hData && (size = GlobalSize (hData))) {
+ if (size >= MAX_CLIPBOARD_SIZE) {
+ ErrorBox(ERR_Clipboard_Overflow);
+ } else if ( p = GlobalLock(hData) ) {
+ int x, y;
+ x = Views[cmdView].X;
+ y = Views[cmdView].Y;
+
+ p1 = p;
+ while (size && *p1) {
+ size--;
+#ifdef DBCS
+ if (IsDBCSLeadByte(*p1) && *(p1+1)) {
+ p1 += 2;
+ size--;
+ continue;
+ }
+#endif
+ if (*p1 == '\r' || *p1 == '\n') {
+ break;
+ }
+ p1++;
+ }
+ size = p1 - p;
+
+ InsertStream(cmdView, x, y, size, p, TRUE);
+ PosXY(cmdView, x + size, y, TRUE);
+ DbgX(GlobalUnlock (hData) == FALSE);
+ }
+ CloseClipboard();
+ }
+ }
+ return 0;
+
+ case WM_DESTROY:
+ /*
+ ** Destroy this instance of the window proc
+ */
+
+ //UnregisterHotKey(NULL, IDH_CTRLC);
+ UnregisterHotKey(hwnd, IDH_CTRLC);
+
+ while (RemoveCtrlCHandler(NULL)) {
+ ;
+ }
+
+ FreeProcInstance((WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC,
+ (DWORD)lpfnEditProc));
+ break;
+
+ case WU_AUTORUN:
+ /*
+ ** Need to get and process an auto-run command
+ */
+
+ CmdAutoRunNext();
+ break;
+
+ case WU_LOG_REMOTE_CMD:
+ //
+ // Echo and handle a command sent by a remote client
+ //
+
+ CmdDoLine( (LPSTR)lParam );
+ CmdDoPrompt(!FCmdDoingInput, FALSE);
+ FCmdDoingInput = FALSE;
+
+ if (wParam) {
+ free((LPVOID)lParam);
+ }
+ break;
+
+ case WU_LOG_REMOTE_MSG:
+ //
+ // print some random junk from a remote client
+ //
+ CmdInsertInit();
+ if (!wParam) {
+ GetRORegion(cmdView, &Xro, &Yro);
+ first = Yro;
+ FirstLine(doc, &pl, &first, &pb);
+
+ _fstrncpy(szStr, pl->Text, Xro);
+ szStr[Xro] = 0;
+
+ CmdLogDebugString(szStr, FALSE);
+ }
+
+ CmdLogDebugString( (LPSTR)lParam, TRUE);
+
+ free( (LPSTR)lParam );
+
+ break;
+
+ }
+ return ( CallWindowProc( lpfnEditProc, hwnd, msg, wParam, lParam ) );
+} /* CmdEditProc() */
diff --git a/private/windbg/windbg/codemgr.c b/private/windbg/windbg/codemgr.c
new file mode 100644
index 000000000..0f42c0170
--- /dev/null
+++ b/private/windbg/windbg/codemgr.c
@@ -0,0 +1,5830 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ codemgr.c
+
+Abstract:
+
+ This file contains the majority of the interface code to the
+ OSDebug API
+
+Author:
+
+ Jim Schaad (jimsch)
+ Griffith Wm. Kadnier (v-griffk) 16-Jan-1993
+
+Environment:
+
+ Win32 user mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define MAX_MAPPED_ROOTS (5)
+
+extern AVS Avs;
+extern HWND GetLocalHWND(void);
+extern HWND GetFloatHWND(void);
+extern HWND GetWatchHWND(void);
+extern HWND GetCallsHWND(void);
+extern HWND GetCpuHWND(void);
+extern EXCEPTION_LIST *InsertException( EXCEPTION_LIST *List, EXCEPTION_LIST *eList);
+
+
+typedef struct _BROWSESTRUCT {
+ DWORD Rslt;
+ DWORD DlgId;
+ DLGPROC DlgProc;
+ LPSTR FileName;
+ DWORD FnameSize;
+} BROWSESTRUCT, *LPBROWSESTRUCT;
+
+
+DWORD FAR PASCAL ExtGetExpression( LPSTR lpsz );
+
+LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+
+BOOL
+FAR PASCAL EXPORT DlgFileSearchResolve(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+);
+
+
+
+#define EENOERROR 0
+
+
+extern CVF Cvf;
+extern CRF Crf;
+extern KNF Knf;
+extern DBF Dbf;
+
+extern EXCEPTION_LIST *DefaultExceptionList;
+
+EESTATUS LOADDS PASCAL MELoadEEParse(char FAR *, EERADIX, SHFLAG, PHTM, uint FAR *);
+XOSD PASCAL LOADDS OSDCallbackFunc(USHORT, HPID, HTID, UINT, LONG);
+
+int get_a_procedure(PCXT pCXT,char *szName,BOOL fSearchAll);
+
+
+DBGSTATE DbgState = ds_normal;
+
+CXF CxfIp;
+
+HTL Htl = 0; /* Handle to transport layer */
+HEM Hem = 0; /* Handle to execution module */
+HPID HpidBase; /* Handle to base PID */
+HTID HtidBase; /* Handle to base TID */
+
+LPPD LppdFirst = NULL;
+
+LPSHF Lpshf = NULL; /* Pointer to SH entry structure */
+ATOM * RgAtomMaskedNames = NULL; /* Names of masked source files */
+int CMacAtomMasked = 0; /* Size of array */
+int CAtomMasked = 0; /* Count of atoms in array */
+
+struct MpPair {
+ ATOM atomSrc;
+ ATOM atomTarget;
+} * RgAtomMappedNames = NULL; /* Mapping from source to target names */
+int CMacAtomMapped = 0; /* Size of array */
+int CAtomMapped = 0; /* Count of mappings in array */
+
+// Structure to map one root to another
+
+struct MRootPair {
+ DWORD dwSrcLen;
+ LPSTR lpszSrcRoot;
+ LPSTR lpszTargetRoot;
+} RgMappedRoots[MAX_MAPPED_ROOTS];
+UINT CMappedRoots = 0;
+static INT MatchedList[MAX_DOCUMENTS];
+static int dwMatchCnt = 0;
+static int dwMatchIdx = 0;
+static CHAR szFSSrcName[MAX_PATH];
+static BOOL FAddToSearchPath = FALSE;
+static BOOL FAddToRootMap = FALSE;
+
+static CHAR szBrowsePrompt[256];
+static CHAR szBrowseFname[256];
+static BOOL fBrowseAnswer;
+
+/*
+** Expression Evaluator items
+*/
+
+CI Ci = { sizeof(CI), 0, &Cvf, &Crf };
+EXF Exf = {NULL, NULL, MELoadEEParse};
+EI Ei = {
+ sizeof(EI), 0, &Exf
+};
+#define Lpei (&Ei)
+
+#define QUEUE_SIZE 1024
+static long RgbDbgMsgBuffer[QUEUE_SIZE];
+static int iDbgMsgBufferFront = 0;
+static int iDbgMsgBufferBack = 0;
+static CRITICAL_SECTION csDbgMsgBuffer;
+
+
+BOOL FKilling = FALSE;
+
+HWND HwndDebuggee = NULL;
+
+/*********************** Prototypes *****************************************/
+
+BOOL FLoadEmTl(void);
+LRESULT SendMessageNZ(HWND,UINT,WPARAM,LPARAM);
+
+BOOL RootNameIsMapped(LPSTR, LPSTR, UINT);
+
+BOOL SrcNameIsMasked(ATOM);
+BOOL SrcNameIsMapped(ATOM, LSZ, UINT);
+INT MatchOpenedDoc(LPSTR, UINT);
+BOOL SrcSearchOnPath(LSZ, UINT, BOOL);
+BOOL SrcSearchOnRoot(LSZ, UINT);
+BOOL SrcBrowseForFile(LSZ, UINT);
+BOOL MiscBrowseForFile(
+ LSZ lpb,
+ UINT cb,
+ LSZ lpDir,
+ UINT cchDir,
+ int nDefExt,
+ int nIdDlgTitle,
+ void (*fnSetMapped)(LSZ, LSZ),
+ LPOFNHOOKPROC lpfnHook
+ );
+VOID SrcSetMasked(LSZ);
+VOID SrcSetMapped(LSZ, LSZ);
+VOID ExeSetMapped(LSZ, LSZ);
+void EnsureFocusDebuggee( void );
+
+VOID CmdMatchOpenedDocPrompt(BOOL, BOOL);
+BOOL CmdMatchOpenedDocInputString(LPSTR);
+
+
+VOID
+InitCodemgr(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Initialize private data for Codemgr.c
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ InitializeCriticalSection(&csDbgMsgBuffer);
+}
+
+
+LRESULT
+SendMessageNZ(
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+/*++
+
+Routine Description:
+
+ Call SendMessage() if and only if the handle is non-zero
+
+Arguments:
+
+ Exactly the same as the Win32 SendMessage() call.
+
+
+Return Value:
+
+ The return from the SendMessage() or 0 if we didn't send it.
+
+--*/
+{
+ if (hWnd) {
+ return( SendMessage(hWnd, uMsg, wParam, lParam) );
+ }
+
+ else {
+ return(0);
+ }
+}
+
+
+BOOL PASCAL
+DbgCommandOk(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This routine is called before issuing any debugger commands.
+ it will validate will all the appropriate windows that no
+ editing commands are current in progess which would cause the
+ debugger to abort out.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return TRUE;
+} /* DbgOk() */
+
+
+BOOL PASCAL
+DbgFEmLoaded(
+ void
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ return (Hem != 0);
+} /* DbgFEmLoaded() */
+
+
+void PASCAL
+Go(
+ void
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ EXOP exop = {0};
+
+
+ LocalFrameNumber = 0;
+
+ // OSDGetFrame(LppdCur->hpid, LptdCur->htid, (DWORD)-1, &LptdCur->htid);
+
+ if (OSDGo(LppdCur->hpid, LptdCur->htid, &exop) == xosdNone) {
+ if (LppdCur->pstate == psPreRunning) {
+ SetPTState(-1, tsRunning);
+ } else {
+ SetPTState(psRunning, tsRunning);
+ LppdCur->fHasRun = TRUE;
+ }
+ EnsureFocusDebuggee();
+ }
+
+ return;
+} /* Go() */
+
+
+BOOL PASCAL
+GoUntil(
+ PADDR paddr
+ )
+/*++
+
+Routine Description:
+
+ Set temporary breakpoint and go
+ Modelled after go_until in CV0.C
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ HBPT hBpt;
+
+ if (BPSetTmp(paddr, LppdCur->hpid, LptdCur->htid, &hBpt) != BPNOERROR) {
+ return FALSE;
+ }
+ LptdCur->fDisasm = TRUE;
+
+ AuxPrintf(3, "GoUntil - doing the go!!!, BP set at 0x%X:0x%X",
+ GetAddrSeg(*paddr),
+ GetAddrOff(*paddr));
+ Go();
+
+ return TRUE;
+} /* GoUntil() */
+
+
+int PASCAL
+Step(
+ int Overcalls,
+ int StepMode
+ )
+/*++
+
+Routine Description:
+
+ Single step at source or assembler code level.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ WORD wLn = 0;
+ SHOFF cbLn = 0;
+ SHOFF dbLn = 0;
+ CXT cxt;
+ ADDR addr;
+ ADDR addr2;
+ EXOP exop = {0};
+
+ if (!DebuggeeAlive()) {
+ AuxPrintf(1, "STEP - child is dead");
+ return FALSE;
+ }
+
+ LocalFrameNumber = 0;
+ //OSDGetFrame(LppdCur->hpid, LptdCur->htid, (DWORD)-1, &LptdCur->htid);
+
+ exop.fStepOver = Overcalls;
+
+ switch (StepMode) {
+ case ASMSTEPPING: // step a machine instruction
+
+ if (OSDSingleStep(LppdCur->hpid, LptdCur->htid, &exop) != xosdNone) {
+ return FALSE;
+ } else {
+ // it is possible to do many steps before entering
+ // the real debuggee. Set the stop at entry flag
+ // to ensure that we stop after leaving the loader.
+ if (!LppdCur->fHasRun) {
+ LppdCur->fStopAtEntry = TRUE;
+ }
+
+ SetPTState(psRunning, tsRunning);
+
+ EnsureFocusDebuggee();
+ return TRUE;
+ }
+
+ case SRCSTEPPING: // step a source line
+
+ // If this is an initial step, the breakpoint
+ // will be resolved at the entrypoint event.
+ if (!LppdCur->fHasRun ) {
+ LppdCur->fInitialStep = 1;
+ Go();
+ return TRUE;
+ }
+
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, adrPC, &addr);
+
+ if (!ADDR_IS_LI( addr ) ) {
+ SYUnFixupAddr ( &addr );
+ }
+
+ SHHmodFrompCxt(&cxt) = (HMOD) NULL;
+ SHSetCxt(&addr, &cxt);
+
+ if (!SHHmodFrompCxt(&cxt) ||
+ !SLLineFromAddr ( &addr, &wLn, &cbLn, &dbLn )) {
+
+ exop.fInitialBP = TRUE;
+ if (OSDSingleStep(LppdCur->hpid, LptdCur->htid, &exop)
+ != xosdNone) {
+ return FALSE;
+ } else {
+ SetPTState(psRunning, tsRunning);
+ EnsureFocusDebuggee();
+ return TRUE;
+ }
+
+ } else {
+
+ Assert( cbLn >= dbLn );
+ if (cbLn < dbLn) {
+ return FALSE;
+ }
+
+ SYFixupAddr(&addr);
+ addr2 = addr;
+ GetAddrOff(addr2) += cbLn - dbLn;
+ exop.fInitialBP = TRUE;
+
+ if (OSDRangeStep(LppdCur->hpid, LptdCur->htid,
+ &addr, &addr2, &exop) != xosdNone) {
+ return FALSE;
+ } else {
+ SetPTState(psRunning, tsRunning);
+ EnsureFocusDebuggee();
+ return TRUE;
+ }
+ }
+
+ default:
+ Assert(FALSE);
+ break;
+ }
+ return FALSE;
+} /* Step() */
+
+
+BOOL PASCAL
+DebuggeeRunning(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This will return TRUE iff the child debuggee current thread
+ is actually executing code.
+
+Arguments:
+
+
+Return Value:
+
+ TRUE if the debuggee is currently running, FALSE otherwise
+
+--*/
+{
+ //
+ // The name of the function (and of SetDebugeeRunning) is
+ // ambiguous. Does this mean the current process/thread is
+ // running? Or any thread in the current process? Or
+ // any process being debugged?
+ //
+ // From the way people use the function seems like its
+ // semantics are "Current thread is running" so it is
+ // implemented that way.
+ //
+ if ( LptdCur != NULL ) {
+ return (LptdCur->tstate == tsRunning);
+ }
+
+ return FALSE;
+} /* DebuggeeRunning() */
+
+
+BOOL PASCAL
+IsProcRunning(
+ LPPD lppd
+ )
+/*++
+
+Routine Description:
+
+ Alternative to DebuggeeRunning(); determines whether process
+ is actually running, not suspended.
+
+Arguments:
+
+ lppd - Supplies pointer to process descriptor
+
+Return Value:
+
+ TRUE if running, FALSE if not
+
+--*/
+{
+ LPTD lptd;
+ if (lppd == NULL) {
+ return FALSE;
+ }
+ if (!DebuggeeActive()) {
+ return FALSE;
+ }
+
+ for (lptd = lppd->lptdList; lptd; lptd = lptd->lptdNext) {
+ if (lptd->tstate != tsRunning) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*********************************************************************
+
+ UI oriented general purpose functions for debugging sessions
+
+*********************************************************************/
+
+
+/*** GetExecutableFilename
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+** Address of passed buffer if successful, NULL otherwise
+**
+** Description:
+** Gets the full path name of the current executable file -
+** from the project if there is one, or from the current
+** source file otherwise.
+**
+*/
+
+PSTR PASCAL
+GetExecutableFilename(
+ PSTR executable,
+ UINT size
+ )
+{
+ LPSTR ProgramName;
+
+ if ( ProgramName = GetCurrentProgramName(FALSE) ) {
+ _fstrncpy( executable, ProgramName, min ( size, strlen( ProgramName )+1 ) );
+ return executable;
+ } else {
+ return NULL;
+ }
+}
+
+
+void PASCAL
+BuildRelativeFilename(
+ LPSTR rgchSource,
+ LPSTR rgchBase,
+ LPSTR rgchDest,
+ int cbDest
+ )
+
+/*++
+
+Routine Description:
+
+ Given a filename and base directory build the
+ fully specified filename.
+
+ Note that BaseDir can be a fully qualified path name
+ (ie including filename) or just the directory. If
+ just the directory is passed it should contain the
+ trailing '\\'.
+
+Arguments:
+
+ rgchSource - Supplies the source name to build relative path for
+ rgchBase - Supplies the Base directory to build path relative to
+ rgchDest - Supplies a Buffer to place the absolute path name to
+ cbDest - Supplies the Length of buffer
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ char * pchDest;
+ char * pchSource = rgchSource;
+ char * pchBase = rgchBase;
+ int iDriveCur = _getdrive();
+ char rgchDirCur[_MAX_PATH];
+ int iDriveSrc;
+
+ _getcwd(rgchDirCur, sizeof(rgchDirCur));
+
+ /*
+ * Check to see if either of the passed in directories have
+ * drives specified.
+ */
+
+#ifdef DBCS
+ if (!IsDBCSLeadByte(pchSource[0]) && pchSource[1] == ':') {
+#else
+ if (pchSource[1] == ':') {
+#endif
+ iDriveSrc = toupper(pchSource[0]) - 'A' + 1;
+ pchSource += 2;
+ if (_chdrive( iDriveSrc ) == -1) {
+ goto nextDrive;
+ }
+ pchBase = 0;
+ } else {
+ nextDrive:
+#ifdef DBCS
+ if (!IsDBCSLeadByte(pchBase[0]) && pchBase[1] == ':') {
+#else
+ if (pchBase[1] == ':') {
+#endif
+ iDriveSrc = toupper(pchBase[0]) - 'A' + 1;
+ pchBase += 2;
+ if (_chdrive( iDriveSrc ) == -1) {
+ iDriveSrc = iDriveCur;
+ }
+ } else {
+ iDriveSrc = iDriveCur;
+ }
+ }
+
+ rgchDest[0] = 'A' + iDriveSrc - 1;
+ rgchDest[1] = ':';
+ rgchDest[2] = '\\';
+ pchDest = &rgchDest[2];
+
+ /*
+ * Now check to see if either base is based at the root. If not
+ * then we need to the get current directory for that drive.
+ */
+
+ if ((pchSource[0] == '\\') || (pchSource[0] == '/')) {
+ pchSource ++;
+ pchBase = NULL;
+ cbDest -= 3;
+ } else if ((pchBase != NULL) &&
+ ((pchBase[0] == '\\') || (pchBase[0] == '/'))) {
+ pchBase ++;
+ cbDest -= 3;
+ } else {
+ Dbg(_getcwd(rgchDest, cbDest-1) != NULL);
+#ifdef DBCS
+ pchDest = CharPrev(rgchDest, rgchDest + strlen(rgchDest));
+ if (*pchDest != '\\') {
+ if (IsDBCSLeadByte(*pchDest)) {
+ pchDest += 2;
+ } else {
+ pchDest++;
+ }
+ *pchDest = '\\';
+ }
+#else // !DBCS
+ pchDest = rgchDest + strlen(rgchDest) - 1;
+ if (*pchDest != '\\') {
+ *++pchDest = '\\';
+ }
+#endif // !DBCS
+ cbDest = cbDest - (pchDest - rgchDest + 1);
+ }
+
+ /*
+ * Now lets copy from the base to the destination looking for
+ * any funnyness in the path being copied.
+ */
+
+ if (pchBase != NULL) {
+ char ch;
+#ifdef DBCS
+ char * pch = CharPrev(pchBase, pchBase + strlen(pchBase));
+ if (pch == pchBase) {
+ // Make sure the result is same as US code.
+ pch = pchBase - 1;
+ }
+#else
+ char * pch = pchBase + strlen(pchBase) - 1;
+#endif
+
+ while ((pch >= pchBase) &&
+ ((*pch != '\\') && (*pch != '/'))) {
+#ifdef DBCS
+ if ((pch = CharPrev(pchBase, pch)) == pchBase) {
+ // Make sure the result is same as US code.
+ pch--;
+ }
+#else
+ pch--;
+#endif
+ }
+
+ if ((*pch == '\\') || (*pch == '/')) {
+ pch++;
+ ch = *pch;
+ *pch = 0;
+ } else {
+#ifdef DBCS
+ ch = *(pch = CharNext(pch));
+ pch = *pch ? pch : pch+1;
+#else
+ ch = *++pch;
+#endif
+ *pch = 0;
+ }
+
+ while (*pchBase != 0) {
+ if (*pchBase == '.') {
+ if (pchBase[1] == '.') {
+ if ((pchBase[2] == '\\') || (pchBase[2] == '/')) {
+ /*
+ * Found the string '..\' in the input, move up to the
+ * next '\' unless the next character up is a ':'
+ */
+
+#ifdef DBCS
+ pchDest = CharPrev(rgchDest, pchDest);
+ cbDest += ((IsDBCSLeadByte(*pchDest)) ? 2 : 1);
+#else
+ pchDest--;
+ cbDest += 1;
+#endif
+ if (*pchDest == ':') {
+ pchDest++;
+ cbDest -= 1;
+ } else {
+ while (*pchDest != '\\') {
+ Assert(*pchDest != ':');
+#ifdef DBCS
+ pchDest = CharPrev(rgchDest, pchDest);
+ cbDest += ((IsDBCSLeadByte(*pchDest)) ? 2 : 1);
+#else
+ pchDest--;
+ cbDest += 1;
+#endif
+ }
+ }
+
+ pchBase += 3;
+ } else {
+ /*
+ * Found the string '..X' where X was not '\', this
+ * is "illegal" but copy it straight over
+ */
+
+ *++pchDest = *pchBase++;
+ *++pchDest = *pchBase++;
+ cbDest -= 2;
+ }
+ } else if ((pchBase[1] == '\\') || (pchBase[1] == '/')) {
+ /*
+ * We just found the string '.\' This is an ignore string
+ */
+
+ pchBase += 2;
+ } else {
+ /*
+ * We just found the string '.X' where X was not '\', this
+ * is legal and just copy over
+ */
+ *++pchDest = *pchBase++;
+ cbDest -= 1;
+ }
+ } else if (*pchBase == '/') {
+ /*
+ * convert / to \
+ */
+
+ *++pchDest = '\\';
+ pchBase++;
+ cbDest -= 1;
+ } else {
+ /*
+ * No funny characters
+ */
+
+#ifdef DBCS
+ if (IsDBCSLeadByte(*pchBase) && *(pchBase+1)) {
+ *++pchDest = *pchBase++;
+ cbDest -= 1;
+ }
+#endif
+ *++pchDest = *pchBase++;
+ cbDest -= 1;
+ }
+ }
+
+ *pch = ch;
+ }
+
+ /*
+ * Now lets copy from the source to the destination looking for
+ * any funnyness in the path being copied.
+ */
+
+ while (*pchSource != 0) {
+ if (*pchSource == '.') {
+ if (pchSource[1] == '.') {
+ if ((pchSource[2] == '\\') || (pchSource[2] == '/')) {
+ /*
+ * Found the string '..\' in the input, move up to the
+ * next '\' unless the next character up is a ':'
+ */
+
+#ifdef DBCS
+ pchDest = CharPrev(rgchDest, pchDest);
+ cbDest += ((IsDBCSLeadByte(*pchDest)) ? 2 : 1);
+#else
+ pchDest--;
+ cbDest += 1;
+#endif
+ if (*pchDest == ':') {
+ pchDest++;
+ cbDest -= 1;
+ } else {
+ while (*pchDest != '\\') {
+ Assert(*pchDest != ':');
+#ifdef DBCS
+ pchDest = CharPrev(rgchDest, pchDest);
+ cbDest += ((IsDBCSLeadByte(*pchDest)) ? 2 : 1);
+#else
+ pchDest--;
+ cbDest += 1;
+#endif
+ }
+ }
+
+ pchSource += 3;
+ } else {
+ /*
+ * Found the string '..X' where X was not '\', this
+ * is "illegal" but copy it straight over
+ */
+
+ *++pchDest = *pchSource++;
+ *++pchDest = *pchSource++;
+ cbDest -= 2;
+ }
+ } else if ((pchSource[1] == '\\') || (pchSource[1] == '/')) {
+ /*
+ * We just found the string '.\' This is an ignore string
+ */
+
+ pchSource += 2;
+ } else {
+ /*
+ * We just found the string '.X' where X was not '\', this
+ * is legal and just copy over
+ */
+ *++pchDest = *pchSource++;
+ cbDest -= 1;
+ }
+ } else {
+ /*
+ * No funny characters
+ */
+
+#ifdef DBCS
+ if (IsDBCSLeadByte(*pchSource) && *(pchSource+1)) {
+ *++pchDest = *pchSource++;
+ cbDest -= 1;
+ }
+#endif
+ *++pchDest = *pchSource++;
+ cbDest -= 1;
+ }
+ }
+
+ *++pchDest = 0;
+
+ Dbg(_chdir(rgchDirCur) == 0);
+ return;
+} /* BuildRelativeFilename() */
+
+
+void FAR PASCAL
+EnsureFocusDebugger(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Set the foreground window to the debugger, if it wasn't already.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (AutoTest) {
+ return;
+ }
+
+ HwndDebuggee = GetForegroundWindow();
+
+ if ((HwndDebuggee != hwndFrame) && !IsChild(hwndFrame, HwndDebuggee)) {
+ SetForegroundWindow(hwndFrame);
+ }
+ return;
+} /* EnsureFocusDebugger() */
+
+
+void
+EnsureFocusDebuggee(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Set the foreground window to the client, or out best guess as to
+ what the client was
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ return;
+} /* EnsureFocusDebuggee() */
+
+
+void PASCAL
+UpdateDebuggerState(
+ UINT UpdateFlags
+ )
+/*++
+
+Routine Description:
+
+ According to the passed flags asks the various debug
+ windows (Watch, Locals, etc) to update their displays.
+
+ ??? Also take care of handling system state when debuggee dies.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ BOOL Active;
+ ADDR addr = {0};
+ int indx;
+ int iViewCur = curView;
+
+ Active = DebuggeeActive();
+
+
+ /*
+ ** Get a current CS:IP for the expression evaluator
+ */
+
+ if (Active && (UpdateFlags & UPDATE_CONTEXT)) {
+
+ Assert(LppdCur && LptdCur);
+ if (LppdCur && LptdCur) {
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, adrPC, &addr);
+ SHChangeProcess(LppdCur->hpds);
+ if ( ! ADDR_IS_LI ( addr ) ) {
+ SYUnFixupAddr ( &addr );
+ }
+ memset(&CxfIp, 0, sizeof(CxfIp));
+ SHSetCxt(&addr, SHpCxtFrompCxf( &CxfIp ) );
+ OSDSetFrame(LppdCur->hpid,
+ LptdCur->htid,
+ SHpFrameFrompCxf(&CxfIp));
+ }
+ }
+
+ if ( (UpdateFlags & UPDATE_CPU) && Active) {
+ SendMessageNZ( GetCpuHWND(), WU_UPDATE, 0, 0L);
+ }
+
+ if ( (UpdateFlags & UPDATE_FLOAT) && Active) {
+ SendMessageNZ( GetFloatHWND(), WU_UPDATE, 0, 0l);
+ }
+
+
+ if ( (UpdateFlags & UPDATE_LOCALS) && Active) {
+ // Set the EM to use the registers from the current frame.
+ //
+ OSDSetFrameContext( LppdCur->hpid, LptdCur->htid, 0, 0 );
+ SendMessageNZ( GetLocalHWND(), WU_UPDATE, 0, 0L);
+ }
+
+ if ( UpdateFlags & UPDATE_WATCH) {
+ SendMessageNZ( GetWatchHWND(), WU_UPDATE, 0, 0L);
+ }
+
+ if ( UpdateFlags & UPDATE_CALLS) {
+ SendMessageNZ( GetCallsHWND(), WU_UPDATE, 0, 0L);
+ }
+
+
+
+ /*
+ **
+ */
+
+ if (UpdateFlags & UPDATE_SOURCE)
+ {
+ char SrcFname[_MAX_PATH];
+ WORD SrcLine;
+ int doc;
+ int saveDoc = TraceInfo.doc;
+ BOOL GotNext = FALSE;
+
+ iViewCur = curView;
+
+ if (!Active)
+ {
+ ClearAllDocStatus(BRKPOINT_LINE|CURRENT_LINE|UBP_LINE);
+ goto OtherWindows;
+ }
+
+ /*
+ ** Clear out any existing current source line highlighting
+ */
+
+ if (TraceInfo.doc != -1) {
+ if (Docs[TraceInfo.doc].FirstView != -1) {
+ LineStatus(TraceInfo.doc, TraceInfo.CurTraceLine,
+ CURRENT_LINE, LINESTATUS_OFF, FALSE, TRUE);
+ }
+
+ TraceInfo.doc = -1;
+ TraceInfo.CurTraceLine = -1;
+ }
+
+
+ if (GetCurrentSource(SrcFname, sizeof(SrcFname), &SrcLine))
+ {
+ AuxPrintf(1, "Got Source:%s, Line:%u", (LPSTR)SrcFname, SrcLine);
+
+ if (UpdateFlags & UPDATE_NOFORCE) {
+ GotNext = SrcMapSourceFilename(SrcFname, sizeof(SrcFname),
+ SRC_MAP_ONLY, FindDoc1);
+ } else {
+ GotNext = SrcMapSourceFilename(SrcFname, sizeof(SrcFname),
+ SRC_MAP_OPEN, FindDoc1);
+ }
+
+ /*
+ **
+ */
+
+ if (GotNext > 0) {
+ Dbg( FindDoc1(SrcFname, &doc, TRUE) );
+ }
+
+ if (GotNext > 0) {
+ //Update line appearance and bring up view on top
+
+
+ if (iViewCur == -1) {
+ BringWindowToTop(Views[Docs[doc].FirstView].hwndFrame);
+ SetFocus(Views[Docs[doc].FirstView].hwndClient);
+ }
+ else if (Views[iViewCur].Doc > -1) {
+ if ((Docs[Views[iViewCur].Doc].docType == DOC_WIN) ||
+ ((Docs[Views[iViewCur].Doc].docType == DISASM_WIN) &&
+ (!status.fSrcMode) &&
+ (saveDoc == -1))) {
+ BringWindowToTop(Views[Docs[doc].FirstView].hwndFrame);
+ SetFocus(Views[Docs[doc].FirstView].hwndClient);
+ }
+ else {
+ SetWindowPos(Views[Docs[doc].FirstView].hwndFrame,
+ Views[iViewCur].hwndFrame, 0, 0, 0, 0,
+ SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
+ if (GotNext == 2) {
+ BringWindowToTop(Views[iViewCur].hwndFrame);
+ SetFocus(Views[iViewCur].hwndClient);
+ }
+ }
+ } else if (!status.fSrcMode || disasmView == -1) {
+ SetWindowPos(Views[Docs[doc].FirstView].hwndFrame,
+ Views[iViewCur].hwndFrame, 0, 0, 0, 0,
+ SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
+ if (GotNext == 2) {
+ BringWindowToTop(Views[iViewCur].hwndFrame);
+ SetFocus(Views[iViewCur].hwndClient);
+ }
+ }
+
+ LineStatus(doc, SrcLine, CURRENT_LINE, LINESTATUS_ON, TRUE, TRUE);
+
+ TraceInfo.doc = doc;
+ TraceInfo.CurTraceLine = SrcLine;
+ }
+ else
+ {
+ /*
+ ** Ensure that disasm window exists
+ */
+
+ if ((disasmView == -1) && !(UpdateFlags & UPDATE_NOFORCE) &&
+ (!(runDebugParams.DisAsmOpts & dopDemand)))
+ {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ if (Views[iViewCur].Doc < 0) {
+ if (Views[iViewCur].Doc != -1) {
+ BringWindowToTop(Views[iViewCur].hwndFrame);
+ SetFocus(Views[iViewCur].hwndClient);
+ }
+
+ } else if (Docs[Views[iViewCur].Doc].docType != DOC_WIN) {
+ BringWindowToTop(Views[iViewCur].hwndFrame);
+ SetFocus(Views[iViewCur].hwndClient);
+ }
+
+ // ntbug #3787
+ // StatusSrc(TRUE); // Switch to ASM mode
+
+ }
+ }
+ }
+ else
+ {
+ AuxPrintf(1, "No Source from GetCurrentSource");
+
+ /*
+ ** Ensure that a disassembler window exists. Everybody
+ ** seems to think that this is a good idea.
+ */
+
+ if ((disasmView == -1) && !(UpdateFlags & UPDATE_NOFORCE) &&
+ (!(runDebugParams.DisAsmOpts & dopDemand)))
+ {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ if (Views[iViewCur].Doc < 0) {
+
+ if (Views[iViewCur].Doc != -1) {
+ BringWindowToTop(Views[iViewCur].hwndFrame);
+ SetFocus(Views[iViewCur].hwndClient);
+ }
+
+ } else if (Docs[Views[iViewCur].Doc].docType != DOC_WIN) {
+
+ BringWindowToTop(Views[iViewCur].hwndFrame);
+ SetFocus(Views[iViewCur].hwndClient);
+ }
+ // ntbug #3787
+ // StatusSrc(TRUE); // Switch to ASM mode
+ }
+
+ }
+ }
+
+OtherWindows:
+
+ for (indx = 0; indx < MAX_VIEWS; indx++) {
+ if (Views[indx].Doc > -1) {
+ if (Docs[Views[indx].Doc].docType == MEMORY_WIN) {
+ memView = indx;
+ if ((MemWinDesc[memView].fLive) ||
+ (UpdateFlags & UPDATE_MEMORY)) {
+ // check of valid views or sparse array
+ ViewMem(indx, TRUE);
+ }
+ }
+ }
+ }
+
+
+ if (UpdateFlags & UPDATE_DISASM) {
+ if (disasmView != -1 && Active) {
+ ViewDisasm(SHPAddrFromPCxf(&CxfIp), DISASM_PC);
+ if (status.fSrcMode &&
+ ((curView == disasmView) ||
+ ((Views[curView].Doc > -1) &&
+ (Docs[Views[curView].Doc].docType == DOC_WIN) )))
+ {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ BringWindowToTop(GetParent(Views[disasmView].hwndClient));
+ SetFocus(Views[disasmView].hwndClient);
+ }
+
+
+ }
+ }
+
+
+
+ // NOTENOTE jimsch -- need to filter this on something
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ return;
+} /* UpdateDebuggerState() */
+
+
+/*** SetDebugLines
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Given a doc, set the debug line highlights,
+** (ie breakpoints, current_line) that refer to that doc.
+**
+** NOTE: This can be called whether or not there is a current
+** debuggee. When there isn't, only source line bps
+** are highlighted.
+*/
+
+void SetDebugLines(int doc, BOOL ResetTraceInfo)
+{
+ Unreferenced( doc );
+ Unreferenced( ResetTraceInfo );
+
+ BPHighlightSourceFile( Docs[doc].FileName );
+} /* SetDebugLines() */
+
+
+/*** AdjustDebugLines
+**
+** Synopsis:
+** void = AdjustDebugLines(DocNumber, StartLine, NumberLines, Added)
+**
+** Entry:
+** DocNumber - Index of document to have lines adjusted for
+** StartLine - First line to be adjusted
+** NumberLines - Number of lines to adjust by
+** Added - TRUE if lines were inserted FALSE if lines were deleted
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Updates source/line breakpoint nodes when lines are
+** added/deleted to a file in the editor. If Added is
+** TRUE the lines have been added otherwise they've been
+** deleted. Also updates the TraceInfo var.
+** NOTE: This is called from the editor every time a block is
+** added or deleted.
+** Insertions are always performed BEFORE the StartLine.
+** Deletions are always performed INCLUDING the StartLine.
+** StartLine is passed 0 relative.
+**
+** Also note that for the TraceInfo, all we avoid is
+** having multiple trace lines. If lines are added
+** or deleted to a file the current line will still
+** seem wrong as this info. comes from the debugging
+** info.
+**
+*/
+
+void PASCAL AdjustDebugLines(int DocNumber, int StartLine, int NumberLines, BOOL Added)
+{
+ Unused(DocNumber);
+ Unused(StartLine);
+ Unused(NumberLines);
+ Unused(Added);
+} /* AdjustDebugLines() */
+
+
+/*********************************************************************
+
+ General Task Management Routines
+
+ KillDebuggee
+ AttachDebuggee
+ RestartDebuggee
+
+*********************************************************************/
+
+
+BOOL
+KillDebuggee(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This routine will check to see if a debuggee is currently
+ loaded in the system. If so it will kill the debuggee and
+ any children.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if the child was killed and FALSE otherwise
+
+--*/
+{
+ MSG msg;
+ LPPD lppd;
+ HPID hpid;
+ BOOL fTmp;
+ BOOL rVal = TRUE;
+
+
+ /*
+ ** Clear out any existing current source line highlighting
+ */
+
+ if (TraceInfo.doc != -1) {
+ if (Docs[TraceInfo.doc].FirstView != -1) {
+ LineStatus(TraceInfo.doc, TraceInfo.CurTraceLine,
+ CURRENT_LINE, LINESTATUS_OFF, FALSE, TRUE);
+ }
+
+ TraceInfo.doc = -1;
+ TraceInfo.CurTraceLine = -1;
+ }
+
+ FKilling = TRUE;
+ fTmp = SetAutoRunSuppress(TRUE);
+
+ for (;;) {
+
+ /*
+ ** See if there is anything to kill
+ */
+
+ lppd = GetLppdHead();
+ while (lppd &&
+ (lppd->pstate == psDestroyed
+ || lppd->pstate == psError
+ || lppd->pstate == psNoProgLoaded))
+ {
+ lppd = lppd->lppdNext;
+ }
+
+ if (!lppd) {
+ break;
+ }
+
+ hpid = lppd->hpid;
+ BPTUnResolveAll(hpid);
+
+
+ /*
+ * This is a synchronous call and we must
+ * pump callback messages through until the
+ * process has been deleted.
+ */
+
+ if ( (OSDProgramFree(hpid) != xosdNone)
+ && (lppd->pstate != psDestroyed) ) {
+
+ // if it got killed while we weren't looking,
+ // there should already be a message in the queue:
+
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ ProcessQCQPMessage(&msg);
+ lppd = LppdOfHpid( hpid );
+ if ((lppd == NULL) || (lppd->pstate == psDestroyed)) {
+ break;
+ }
+ }
+
+ // if it didn't go away, mark it as damaged:
+
+ if (lppd && (lppd == LppdOfHpid(hpid))) {
+ lppd->pstate = psError;
+ }
+
+ //
+ // this is for the case in the kernel debugger where the init
+ // of the dm fails (com port problems) and the createprocess
+ // never happens.
+ //
+ } else if (lppd->pstate == psPreRunning) {
+ lppd->pstate = psDestroyed;
+
+ } else if ( (lppd->pstate != psDestroyed)
+ || (lppd != LppdOfHpid(hpid)) ) { // <--is this possible??
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ lppd = LppdOfHpid( hpid );
+ if ((lppd == NULL) || (lppd->pstate == psDestroyed))
+ {
+ break;
+ }
+ }
+
+ }
+
+ }
+
+ SetAutoRunSuppress(fTmp);
+ FKilling = FALSE;
+
+
+ if (rVal) {
+ // if we succeeded in killing everything...
+ SetIpid(1);
+ }
+
+ return( rVal );
+} /* KillDebuggee() */
+
+
+void
+ClearDebuggee(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This function is called to implement Run.Stop Debugging. It will
+ kill any currently loaded debugee and unload all of the debugging DLLs.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HCURSOR hcursor;
+ LPSTR lpsz;
+ int len;
+
+ hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ if (DbgState == ds_init) {
+ CmdLogVar(ERR_DbgState);
+ return;
+ }
+
+ if (DebuggeeActive()) {
+ KillDebuggee();
+ }
+
+ len = ModListGetSearchPath( NULL, 0 );
+ if (len) {
+ lpsz = malloc(len);
+ ModListGetSearchPath( lpsz, len );
+ ModListInit();
+ ModListSetSearchPath( lpsz );
+ free(lpsz);
+ }
+ ModListAdd( "ntoskrnl.exe" , sheNone );
+
+ if (LppdFirst) {
+ if (LppdFirst->hpds) {
+ SHDeleteProcess(LppdFirst->hpds);
+ }
+ OSDDestroyPID( HpidBase );
+ DestroyPd( LppdFirst, TRUE );
+ LppdFirst = LppdCur = NULL;
+ SetIpid(0);
+ }
+
+ if (HModEM != 0) {
+
+ SendMessageNZ( GetCpuHWND(), WU_DBG_UNLOADEM, 0, 0); // Give'em a
+ SendMessageNZ( GetFloatHWND(), WU_DBG_UNLOADEM, 0, 0); // Chance
+
+ OSDDeleteEM( Hem );
+ FreeLibrary( HModEM );
+
+ HModEM = 0;
+ Hem = 0;
+ HpidBase = 0;
+ HtidBase = 0;
+ }
+
+
+ if (HModTL != 0) {
+ OSDDeleteTL( Htl );
+ FreeLibrary( HModTL );
+ HModTL = 0;
+ Htl = 0;
+ }
+
+ if (HModEE != 0) {
+
+ SendMessageNZ( GetCpuHWND(), WU_DBG_UNLOADEE, 0, 0); // Give'em a change
+ SendMessageNZ( GetFloatHWND(), WU_DBG_UNLOADEE, 0, 0); // to Unload
+ SendMessageNZ( GetLocalHWND(), WU_DBG_UNLOADEE, 0, 0);
+ SendMessageNZ( GetWatchHWND(), WU_DBG_UNLOADEE, 0, 0);
+ SendMessageNZ( GetCallsHWND(), WU_DBG_UNLOADEE, 0, 0);
+
+ FreeLibrary( HModEE );
+ HModEE = 0;
+ Ei.pStructExprAPI = &Exf;
+ }
+
+ if (HModSH != 0) {
+ LPFNSHSTOPBACKGROUND lpfn;
+ LPFNSHUNINIT lpfn2;
+ if (runDebugParams.fShBackground) {
+ lpfn = (LPFNSHSTOPBACKGROUND) GetProcAddress( HModSH, "SHStopBackground" );
+ if (lpfn) {
+ lpfn();
+ }
+ }
+ lpfn2 = (LPFNSHUNINIT) GetProcAddress( HModSH, "SHUninit" );
+ if (lpfn2) {
+ lpfn2();
+ }
+ FreeLibrary( HModSH );
+ HModSH = 0;
+ Lpshf = NULL;
+ }
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ memset( &CxfIp, 0, sizeof( CxfIp ) );
+ SetCursor(hcursor);
+
+ return;
+} /* ClearDebuggee() */
+
+
+void
+DisconnectDebuggee(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This function is called to implement Run.Disconnect
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HCURSOR hcursor;
+ LPSTR lpsz;
+ int len;
+
+ hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ if (DbgState == ds_init) {
+ CmdLogVar(ERR_DbgState);
+ return;
+ }
+
+ if (LppdFirst) {
+ if (LppdFirst->hpds) {
+ SHDeleteProcess(LppdFirst->hpds);
+ }
+ OSDDestroyPID( HpidBase );
+ DestroyPd( LppdFirst, TRUE );
+ }
+
+ len = ModListGetSearchPath( NULL, 0 );
+ if (len) {
+ lpsz = malloc(len);
+ ModListGetSearchPath( lpsz, len );
+ ModListInit();
+ ModListSetSearchPath( lpsz );
+ free( lpsz );
+ }
+ ModListAdd( "ntoskrnl.exe" , sheNone );
+
+ SetIpid(0);
+ LppdFirst = NULL;
+ LppdCur = NULL;
+ LptdCur = NULL;
+
+ if (HModTL != 0) {
+ OSDDeleteTL( Htl );
+ Htl = 0;
+ FreeLibrary( HModTL );
+ HModTL = 0;
+ }
+
+ if (HModEM != 0) {
+
+ SendMessageNZ( GetCpuHWND(), WU_DBG_UNLOADEM, 0, 0); // Give'em a
+ SendMessageNZ( GetFloatHWND(), WU_DBG_UNLOADEM, 0, 0); // Chance
+
+ OSDDeleteEM( Hem );
+ FreeLibrary( HModEM );
+
+ HModEM = 0;
+ Hem = 0;
+ HpidBase = 0;
+ HtidBase = 0;
+ }
+
+ if (HModEE != 0) {
+
+ SendMessageNZ( GetCpuHWND(), WU_DBG_UNLOADEE, 0, 0); // Give'em a change
+ SendMessageNZ( GetFloatHWND(), WU_DBG_UNLOADEE, 0, 0); // to Unload
+ SendMessageNZ( GetLocalHWND(), WU_DBG_UNLOADEE, 0, 0);
+ SendMessageNZ( GetWatchHWND(), WU_DBG_UNLOADEE, 0, 0);
+ SendMessageNZ( GetCallsHWND(), WU_DBG_UNLOADEE, 0, 0);
+
+ FreeLibrary( HModEE );
+ HModEE = 0;
+ Ei.pStructExprAPI = &Exf;
+ }
+
+ if (HModSH != 0) {
+ LPFNSHSTOPBACKGROUND lpfn;
+ LPFNSHUNINIT lpfn2;
+ if (runDebugParams.fShBackground) {
+ lpfn = (LPFNSHSTOPBACKGROUND) GetProcAddress( HModSH, "SHStopBackground" );
+ if (lpfn) {
+ lpfn();
+ }
+ }
+ lpfn2 = (LPFNSHUNINIT) GetProcAddress( HModSH, "SHUninit" );
+ if (lpfn2) {
+ lpfn2();
+ }
+ FreeLibrary( HModSH );
+ HModSH = 0;
+ Lpshf = NULL;
+ }
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ memset( &CxfIp, 0, sizeof( CxfIp ) );
+ SetCursor(hcursor);
+
+ return;
+} /* DisconnectDebuggee() */
+
+
+void
+SetProcessExceptions(
+ LPPD lppd
+ )
+{
+ EXCEPTION_DESCRIPTION exd;
+ EXCEPTION_LIST *List;
+
+ //
+ // If we don't have a default exception list yet, load it.
+ //
+ if ( !DefaultExceptionList ) {
+
+ //
+ // Loop through all the exceptions known to OSDebug
+ //
+ OSDGetExceptionState(lppd->hpid, NULL, &exd, exfFirst);
+
+ do {
+
+ EXCEPTION_LIST *eList=
+ (EXCEPTION_LIST*)malloc(sizeof(EXCEPTION_LIST));
+
+ eList->next = NULL;
+ eList->dwExceptionCode = exd.dwExceptionCode;
+ eList->efd = exd.efd;
+ eList->lpName = _strdup(exd.rgchDescription);
+ eList->lpCmd = NULL;
+ eList->lpCmd2 = NULL;
+
+ DefaultExceptionList = InsertException( DefaultExceptionList, eList );
+
+ } while (OSDGetExceptionState(lppd->hpid, NULL, &exd, exfNext)
+ ==xosdNone);
+ }
+
+ if ( DefaultExceptionList ) {
+
+ if ( lppd->ipid == 0 ) {
+
+ //
+ // The exception list for process 0 is the default exception list.
+ //
+ lppd->exceptionList = DefaultExceptionList;
+
+ } else {
+
+ //
+ // All other processes get a copy of the default exception list.
+ //
+ List = DefaultExceptionList;
+
+ while ( List ) {
+
+ EXCEPTION_LIST *eList=(EXCEPTION_LIST*)malloc(sizeof(EXCEPTION_LIST));
+
+ eList->next = NULL;
+ eList->dwExceptionCode = List->dwExceptionCode;
+ eList->efd = List->efd;
+ eList->lpName = List->lpName ? _strdup(List->lpName) : NULL;
+ eList->lpCmd = List->lpCmd ? _strdup(List->lpCmd) : NULL;
+ eList->lpCmd2 = List->lpCmd2 ? _strdup(List->lpCmd2) : NULL;
+
+ lppd->exceptionList = InsertException( lppd->exceptionList, eList);
+
+ List = List->next;
+ }
+ }
+
+ //
+ // Traverse the list and tell OSDebug not to ignore all exceptions
+ // that are not to be ignored (OSDebug will ignore all exceptions
+ // by default).
+ //
+ List = DefaultExceptionList;
+
+ while ( List ) {
+
+ exd.dwExceptionCode = List->dwExceptionCode;
+ exd.efd = List->efd;
+ strncpy(exd.rgchDescription,
+ List->lpName? List->lpName: "",
+ EXCEPTION_STRING_SIZE);
+ OSDSetExceptionState( lppd->hpid, NULL, &exd );
+
+ List = List->next;
+ }
+ }
+}
+
+
+void
+ClearProcessExceptions(
+ LPPD lppd
+ )
+{
+ EXCEPTION_LIST *el, *elt;
+
+ if ( lppd->ipid != 0 ) {
+
+ //
+ // For all processes other than process 0, we must deallocate
+ // the list. Process 0 is special since its exception list is
+ // the default exception list, which does not go away.
+ //
+ for ( el = lppd->exceptionList; el; el = elt ) {
+
+ elt = el->next;
+
+ if ( el->lpName ) {
+ free( el->lpName );
+ }
+
+ if ( el->lpCmd ) {
+ free( el->lpCmd );
+ }
+
+ if ( el->lpCmd2 ) {
+ free( el->lpCmd2 );
+ }
+
+ free(el);
+ }
+ }
+
+ lppd->exceptionList = NULL;
+}
+
+
+
+VOID
+GetDebugeePrompt(
+ void
+ )
+{
+ LPPROMPTMSG pm;
+
+ pm = (LPPROMPTMSG) malloc( sizeof(PROMPTMSG)+PROMPT_SIZE );
+ if (!pm) {
+ return;
+ }
+ memset( pm, 0, sizeof(PROMPTMSG)+PROMPT_SIZE );
+ pm->len = PROMPT_SIZE;
+ CmdGetDefaultPrompt( pm->szPrompt );
+ if (OSDGetPrompt( LppdCur->hpid, pm ) == xosdNone) {
+ CmdSetDefaultPrompt( pm->szPrompt );
+ }
+ free( pm );
+ return;
+}
+
+
+BOOL
+ConnectDebugger(
+ void
+ )
+{
+ /*
+ ** Check to see if we have already loaded an EM/DM pair and created
+ ** the base process descriptor. If not then we need to do so now.
+ */
+ char str[9];
+
+ if (LppdFirst == NULL) {
+
+ if (!FLoadEmTl()) {
+ return FALSE;
+ }
+
+ /*
+ ** Hook this process up to the symbol handler
+ */
+
+ LppdCur->hpds = SHCreateProcess();
+ SHSetHpid(HpidBase);
+
+ } else if (LppdCur == NULL) {
+
+ LppdCur = LppdFirst;
+
+ }
+
+ SHChangeProcess(LppdCur->hpds);
+
+ GetDebugeePrompt();
+
+ if (runDebugParams.fAlternateSS) {
+ strcpy(str, "slowstep");
+ OSDIoctl(LppdCur->hpid,0,ioctlCustomCommand,8,str);
+ }
+
+ return TRUE;
+} /* ConnectDebugger() */
+
+
+BOOL
+AttachDebuggee(
+ DWORD dwProcessId,
+ HANDLE hEventGo
+ )
+/*++
+
+Routine Description:
+
+ Debug an active process. Tell osdebug to hook up to a
+ running process. If the process crashed, the system has
+ provided an event handle to signal when the debugger is
+ ready to field the second chance exception.
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ XOSD xosd;
+ BOOL fMakingRoot;
+ MSG msg;
+ int Errno;
+ LPPD lppd;
+ BOOL fTmp;
+ DWORD dwStatus;
+ LPSTR lpProgramName;
+ char szStr[MAX_CMDLINE_TXT];
+
+ /*
+ * First, do some of the stuff that RestartDebuggee()
+ * does to get talking to the DM and friends.
+ */
+
+ /*
+ ** Disable all of the buttons
+ */
+
+ EnableRibbonControls(ERC_ALL, TRUE);
+
+ if (!ConnectDebugger()) {
+ EnableRibbonControls(ERC_ALL, FALSE);
+ return FALSE;
+ }
+
+ OSDSetPath( LppdCur->hpid, environParams.SrchPath, NULL );
+
+ fMakingRoot = (LppdFirst->lppdNext == NULL
+ && (LppdFirst->pstate == psNoProgLoaded));
+ // not psDestroyed. We don't restart proc 0 with an attach.
+
+ if (fMakingRoot) {
+ lpProgramName = GetCurrentProgramName(FALSE);
+ if (lpProgramName && *lpProgramName) {
+ strcpy(szStr, lpProgramName);
+ if (LpszCommandLine && *LpszCommandLine) {
+ strcat(szStr, " ");
+ strcat(szStr, LpszCommandLine);
+ }
+ if (!runDebugParams.fKernelDebugger) {
+ CmdLogVar(DBG_Losing_Command_Line, szStr);
+ LoadProgram(lpProgramName);
+ } else {
+ LoadProgram(UntitledProgramName);
+ }
+ }
+ }
+
+ xosd = OSDDebugActive(LppdFirst->hpid,
+ dwProcessId,
+ hEventGo,
+ &dwStatus);
+
+ if (xosd != xosdNone) {
+
+ if (fMakingRoot) {
+ DbgState = ds_error;
+ }
+ SetPTState(psNoProgLoaded, -1);
+
+ switch( xosd ) {
+
+ case xosdAccessDenied:
+ Errno = ERR_File_Read;
+ break;
+
+ case xosdOutOfMemory:
+ Errno = ERR_Cannot_Allocate_Memory;
+ break;
+
+ case xosdCannotDebug:
+ Errno = ERR_Cannot_Debug;
+ break;
+
+ case xosdVDMRunning:
+ Errno = ERR_VDM_Running;
+ break;
+
+ default:
+ case xosdBadFormat:
+ case xosdUnknown:
+ Errno = ERR_Cant_Load;
+ break;
+
+ }
+
+ fTmp = SetAutoRunSuppress(TRUE);
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ ProcessQCQPMessage(&msg);
+ }
+ SetAutoRunSuppress(fTmp);
+
+ sprintf(szStr, "process %d, status == %d", dwProcessId, dwStatus);
+ ErrorBox(Errno, szStr);
+
+ DbgState = ds_normal;
+
+ if (fMakingRoot) {
+ ClearDebuggee();
+ }
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ return FALSE;
+
+ } else {
+
+ /*
+ * Process messages until the loader breakpoint has been handled.
+ */
+
+ fTmp = SetAutoRunSuppress(TRUE);
+
+ // wait for new process...
+ if (fMakingRoot) {
+ lppd = LppdFirst;
+ lppd->pstate = psPreRunning;
+ } else {
+ HPID hpid = 0;
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ if (msg.wParam == dbcNewProc) {
+ hpid = (HPID) msg.lParam;
+ }
+ if ((hpid != 0) &&
+ (lppd = LppdOfHpid((HPID) msg.lParam)) != NULL) {
+ break;
+ }
+ }
+ }
+
+ // wait for it to finish loading
+ lppd->fChild = FALSE;
+ lppd->fHasRun = FALSE;
+ lppd->fInitialStep = FALSE;
+ lppd->hbptSaved = NULL;
+ lppd->fStopAtEntry = FALSE;
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ if (lppd->pstate != psPreRunning) {
+ break;
+ }
+ }
+
+ SetAutoRunSuppress(fTmp);
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+
+ if (lppd->pstate != psRunning && lppd->pstate != psStopped) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+} /* AttachDebuggee() */
+
+
+BOOL
+RestartDebuggee(
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ MSG msg;
+ char * lpb;
+ int Errno;
+ XOSD xosd;
+ ULONG ulFlags = 0;
+ BOOL fTmp;
+ int n;
+ BOOL fMakingRoot;
+ LPPD lppd;
+
+ Unreferenced( argc );
+
+ /*
+ ** Disable all of the buttons
+ */
+
+ EnableRibbonControls(ERC_ALL, TRUE);
+
+ if (!ConnectDebugger()) {
+ EnableRibbonControls(ERC_ALL, FALSE);
+ return FALSE;
+ }
+
+ fMakingRoot = (LppdFirst->lppdNext == NULL) &&
+ ((LppdFirst->pstate == psNoProgLoaded) ||
+ (LppdFirst->pstate == psDestroyed));
+
+ /*
+ ** Mark as being in the original load so defer working with
+ ** any breakpoints until all initial DLL load notifications are done
+ */
+
+ if (fMakingRoot) {
+ DbgState = ds_init; //??
+ }
+
+ if (runDebugParams.fDebugChildren) {
+ ulFlags |= ulfMultiProcess;
+ }
+
+ if (runDebugParams.fInheritHandles) {
+ ulFlags |= ulfInheritHandles;
+ }
+
+ if (runDebugParams.fWowVdm) {
+ ulFlags |= ulfWowVdm;
+ }
+
+ if (AutoTest) {
+ ulFlags |= ulfNoActivate;
+ }
+
+ if (argv[0]) {
+ n = strlen(argv[0]) + 3;
+ } else {
+ n = 3;
+ }
+ if (argv[1]) {
+ n += strlen(argv[1]) + 1;
+ }
+ lpb = malloc( n );
+ strcpy(lpb, "\"");
+ if (argv[0]) {
+ strcat(lpb, argv[0]);
+ }
+ strcat(lpb, "\"");
+ if (argv[1]) {
+ strcat(lpb, " ");
+ strcat(lpb, argv[1]);
+ }
+
+ OSDSetPath( LppdCur->hpid, environParams.SrchPath, NULL );
+
+ xosd = OSDProgramLoad(LppdCur->hpid, lpb, "WINDBG: ", ulFlags);
+ free(lpb);
+
+ if (xosd != xosdNone) {
+
+ DbgState = ds_error;
+
+ switch( xosd ) {
+ case xosdFileNotFound:
+ Errno = ERR_File_Not_Found;
+ break;
+
+ case xosdSharingViolation:
+ case xosdAccessDenied:
+ Errno = ERR_File_Read;
+ break;
+
+ case xosdOpenFailed:
+ Errno = ERR_File_Open;
+ break;
+
+ case xosdOutOfMemory:
+ Errno = ERR_Cannot_Allocate_Memory;
+ break;
+
+ case xosdCannotDebug:
+ Errno = ERR_Cannot_Debug;
+ break;
+
+ case xosdVDMRunning:
+ Errno = ERR_VDM_Running;
+ break;
+
+ default:
+ case xosdBadFormat:
+ case xosdUnknown:
+ Errno = ERR_Cant_Load;
+ break;
+
+ }
+
+ ErrorBox(Errno, (LPSTR) argv[0]);
+
+ DbgState = ds_normal;
+
+ if (fMakingRoot) {
+ ClearDebuggee();
+ }
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+ InvalidateAllWindows();
+
+ return FALSE;
+
+ } else {
+
+ /*
+ * Before draining message queue, ensure that thread state is right
+ */
+
+
+ fTmp = SetAutoRunSuppress(TRUE);
+
+ // wait for new process...
+ if (fMakingRoot) {
+
+ //
+ // we never see a dbcNewProc for this process,
+ // so set things up here.
+ //
+
+ lppd = LppdFirst;
+ lppd->pstate = psPreRunning;
+ lppd->ctid = 0;
+ DbgState = ds_normal;
+
+ } else {
+
+ //
+ // Process messages until the loader breakpoint has been handled,
+ // or the half started debuggee is killed.
+ //
+
+ HPID hpid = 0;
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ if (msg.wParam == dbcNewProc) {
+ hpid = (HPID) msg.lParam;
+ DbgState = ds_normal;
+ }
+ if ((hpid != 0) &&
+ (lppd = LppdOfHpid((HPID) msg.lParam)) != NULL) {
+ break;
+ }
+ }
+ }
+
+ // wait for it to finish loading
+ lppd->fChild = FALSE;
+ lppd->fHasRun = FALSE;
+ lppd->fInitialStep = FALSE;
+ lppd->hbptSaved = NULL;
+ lppd->fStopAtEntry = FALSE;
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ if (lppd->pstate != psPreRunning) {
+ break;
+ }
+ }
+
+ SetAutoRunSuppress(fTmp);
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+ InvalidateAllWindows();
+
+ if (runDebugParams.fKernelDebugger &&
+ runDebugParams.KdParams.fUseCrashDump) {
+ //
+ // lets be nice and do an automatic symbol reload
+ //
+ CmdExecuteLine( ".reload" );
+ }
+
+ return (LppdCur != NULL && LptdCur != NULL) &&
+ (LptdCur->tstate == tsRunning || LptdCur->tstate == tsStopped ||
+ LptdCur->tstate == tsException1 || LptdCur->tstate == tsException2);
+ }
+} /* RestartDebuggee() */
+
+
+BOOL
+DebuggeeAlive(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This function is used to determine if the debugger is currently
+ active with a child process.
+
+ See Also:
+ DebuggeeActive()
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if there is currently a debuggee process and FALSE otherwise
+
+--*/
+{
+ return GetLppdHead() != (LPPD)0;
+} /* DebuggeeAlive() */
+
+
+BOOL
+DebuggeeActive(
+ void
+ )
+/*++
+
+Routine Description:
+
+ This function is used to determine if the debugger currently has
+ a debuggee which is in a state where it is partially debugged.
+ The difference between this and DebuggeeAlive is that if a debuggee
+ has not been run or it has been terminated this will return FALSE
+ while DebuggeeAlive will return TRUE.
+
+ See Also:
+ DebuggeeAlive
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if debuggee is in an active state and FALSE otherwise
+
+--*/
+{
+ LPPD lppd;
+
+ /*
+ * If any process is loaded, we have a debuggee:
+ */
+
+ for (lppd = GetLppdHead(); lppd; lppd = lppd->lppdNext) {
+ switch (lppd->pstate) {
+ case psNoProgLoaded:
+ case psExited:
+ case psDestroyed:
+ case psError:
+ break;
+
+ default:
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+} /* DebuggeeActive() */
+
+
+/*** GetSourceFromAddress
+**
+** Synopsis:
+** bool = GetSourceFromAddress(pADDR, SrcFname, SrcLen, pSrcLine)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL
+GetSourceFromAddress(
+ PADDR pADDR,
+ PSTR SrcFname,
+ int SrcLen,
+ WORD *pSrcLine
+ )
+{
+ ADDR addr;
+ WORD wLn;
+ SHOFF cbLn;
+ SHOFF dbLn;
+ HSF hsf;
+ LPCH lpchFname;
+ CXT CXTT;
+ char TmpSrcFname[_MAX_PATH];
+ char Executable[_MAX_PATH];
+
+ AuxPrintf(1, "GetSourceFromAddress - 0x%X:0x%X, emi:%X",
+ (WORD)GetAddrSeg(*pADDR),
+ (WORD)GetAddrOff(*pADDR),
+ (WORD)emiAddr(*pADDR));
+
+ if ( ! ADDR_IS_LI ( *pADDR ) ) {
+ SYUnFixupAddr ( pADDR );
+ }
+
+ addr = *pADDR;
+
+ SHHMODFrompCXT(&CXTT) = (HMOD) NULL;
+
+ /*
+ ** Translate the given addresss into a file and line.
+ */
+
+ SHSetCxt(pADDR, &CXTT);
+
+ if (SHHMODFrompCXT(&CXTT)
+ && SLLineFromAddr (&addr, &wLn, &cbLn, &dbLn)
+ && (hsf = SLHsfFromPcxt (&CXTT)) ) {
+
+ // Canonicalise the found file relative to the ProgramName
+
+ lpchFname = SLNameFromHsf (hsf);
+#if 0
+ Assert(SrcLen > 0);
+ _fmemcpy ( SrcFname, lpchFname + 1, min(SrcLen-1, *lpchFname));
+ SrcFname[*lpchFname] = '\0';
+#else
+ _fmemcpy ( TmpSrcFname, lpchFname + 1, *lpchFname);
+ TmpSrcFname[*lpchFname] = '\0';
+ GetExecutableFilename(Executable, sizeof(Executable));
+ BuildRelativeFilename(TmpSrcFname,
+ Executable,
+ SrcFname,
+ SrcLen);
+#endif
+ /// M00HACK
+ {
+ char * lpch = SrcFname + strlen(SrcFname);
+#ifdef DBCS
+ while (lpch > SrcFname && *lpch != '.'){
+ lpch = CharPrev(SrcFname, lpch);
+ }
+#else
+ while (*lpch != '.') lpch--;
+#endif
+ if (_stricmp(lpch, ".OBJ") == 0) {
+ strcpy(lpch, ".C");
+ }
+ }
+ /// M00HACK
+ *pSrcLine = wLn;
+ return TRUE;
+ }
+
+ return FALSE;
+} /* GetSourceFromAddress() */
+
+/*** GetCurrentSource
+**
+** Synopsis:
+** bool = GetCurrentSource(SrcFname, SrcLen, pSrcLine)
+**
+** Entry:
+** SrcFname :
+** SrcLen :
+** pSrcLine :
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+BOOL GetCurrentSource(PSTR SrcFname, int SrcLen, WORD *pSrcLine)
+{
+ ADDR addr;
+
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, adrPC, &addr);
+ return GetSourceFromAddress(&addr, SrcFname, SrcLen, pSrcLine);
+}
+
+
+/*** MoveEditorToAddr
+**
+** Synopsis:
+** bool = MoveEditorToAddr(pAddr)
+**
+** Entry:
+** pAddr - Address to move the editor to
+**
+** Returns:
+** TRUE if successful and FALSE otherwise
+**
+** Description:
+** This function will take the address in the structure pAddr and
+** move the editor so that the source line cooresponding to the address
+** will be in the front window and the cursor placed on that line
+*/
+
+BOOL PASCAL MoveEditorToAddr(PADDR pAddr)
+{
+ char szFname[_MAX_PATH];
+ WORD FnameLine;
+ int doc;
+ BOOL GotSource;
+
+ GotSource = FALSE;
+ if (GetSourceFromAddress( pAddr, szFname, sizeof(szFname), &FnameLine)) {
+ GotSource = SrcMapSourceFilename(szFname, sizeof(szFname),
+ SRC_MAP_OPEN, NULL);
+ switch( GotSource ) {
+ case -2:
+ return FALSE;
+
+ case -1:
+ return FALSE;
+
+ case 0:
+ return FALSE;
+
+ case 1:
+ case 2:
+ GotSource = FindDoc(szFname, &doc, TRUE);
+ break;
+
+ default:
+ Assert(FALSE);
+ break;
+ }
+
+ if (!GotSource) {
+ GotSource = ((AddFile(MODE_OPEN, DOC_WIN, (LPSTR)szFname, NULL, NULL, TRUE, -1, -1) != -1) &&
+ FindDoc(szFname, &doc, TRUE));
+ if (FSourceOverlay && GotSource) {
+ int iView;
+ WINDOWPLACEMENT wp;
+
+ for (iView=0; iView < MAX_VIEWS; iView++) {
+ if ((Views[iView].Doc > -1) &&
+ (Docs[Views[iView].Doc].docType == DOC_WIN) &&
+ (Views[iView].Doc != doc)) {
+ GetWindowPlacement( Views[iView].hwndFrame, &wp );
+ SetWindowPlacement(Views[Docs[doc].FirstView].hwndFrame,
+ &wp);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+
+ if (GotSource) {
+ // Make sure window is visible
+
+ BringWindowToTop(Views[Docs[doc].FirstView].hwndFrame);
+
+ SendMessage (Views[Docs[doc].FirstView].hwndClient, WM_SETFOCUS,0,0L);
+
+ //SetFocus (Views[Docs[doc].FirstView].hwndClient);
+
+ // And show the function
+
+ GotoLine(Docs[doc].FirstView, FnameLine, TRUE);
+ }
+
+ return GotSource;
+} /* MoveEditorToAddr() */
+
+BOOL
+ToggleInRange(
+ int thisView,
+ DWORD dwLineNumber,
+ DWORD Lines,
+ BOOL LoadSymbols,
+ HBPT hBpt,
+ char *rgch
+ )
+{
+ BOOL BpSet = FALSE;
+ char szCurLine[300];
+ BPSTATUS bpstatus;
+ UINT LineBpt;
+ BOOL OldLoadSymbols;
+
+ OldLoadSymbols = BPSymbolLoading( LoadSymbols );
+
+ //
+ // See if there is a breakpoint on this file/line pair already.
+ // Note that we only check for existing breakpoints in the first
+ // line of the range, so that we'll toggle (i.e. clear) existing
+ // breakpoints only if clicking over a highlighted line.
+ //
+ bpstatus = BPHbptFromFileLine(rgch, dwLineNumber, &hBpt);
+ if (bpstatus == BPNOERROR || bpstatus == BPAmbigous) {
+
+ BPDelete(hBpt);
+ ChangeDebuggerState();
+ BPCommit();
+ BpSet = TRUE;
+
+ } else {
+
+ Assert(bpstatus == BPNoBreakpoint);
+
+ while ( dwLineNumber < Lines ) {
+ //
+ // Set up a breakpoint node and a command string for the
+ // current line
+ // Make a current line BP command
+ //
+ sprintf(szCurLine, "%c%d", BP_LINELEADER, dwLineNumber);
+
+ bpstatus = BPParse(&hBpt, szCurLine, NULL, rgch,
+ LppdCur ? LppdCur->hpid : 0 );
+
+ if (bpstatus != BPNOERROR) {
+ dwLineNumber++;
+ } else {
+
+ Dbg(BPAddToList( hBpt, -1 ) == BPNOERROR);
+
+ if (DebuggeeAlive()) {
+
+ bpstatus = BPBindHbpt( hBpt, NULL );
+
+ if (bpstatus != BPNOERROR) {
+ /*
+ * If this file is in a module that we have loaded,
+ * then the line is not valid, so we discard the
+ * breakpoint. Otherwise this file might belong
+ * to a module that has not been loaded yet, so
+ * we leave the uninstantiated BP to be resolved
+ * later on.
+ */
+
+ if ( BPFileNameToMod( rgch ) || !LoadSymbols ) {
+ BPUnCommit();
+ if ( bpstatus != BPCancel ) {
+ dwLineNumber++;
+ continue;
+ }
+ }
+ }
+ }
+ ChangeDebuggerState();
+ BPCommit();
+ if (BPQueryHighlightLineOfHbpt(hBpt, &LineBpt) == BPNOERROR) {
+ dwLineNumber = (DWORD)LineBpt;
+ }
+ PosXYCenter(thisView, Views[thisView].X, dwLineNumber-1, FALSE);
+ BpSet = TRUE;
+ break;
+ }
+ }
+ }
+
+ BPSymbolLoading( OldLoadSymbols );
+
+ return BpSet;
+} /* ToggleInRange() */
+
+
+
+/*** ToggleLocBP
+**
+** Synopsis:
+** bool = ToggleLocBP()
+**
+** Entry:
+** None
+**
+** Returns:
+** TRUE if successful, FALSE otherwise.
+**
+** Description:
+** Toggles the breakpoint at the current editor line.
+**
+*/
+
+BOOL PASCAL
+ToggleLocBP(
+ void
+ )
+{
+ char szCurLine[300];
+ char rgch[300];
+ HBPT hBpt;
+ BPSTATUS bpstatus;
+ ADDR addr;
+ ADDR addr2;
+ DWORD dwLineNumber;
+ int thisView = curView;
+
+
+ //
+ // can't do this if windbg is the kernel debugger and the system is running
+ //
+ if ( runDebugParams.fKernelDebugger && IsProcRunning(LppdCur) ) {
+ CmdInsertInit();
+ CmdLogFmt( "Cannot set breakpoints while the target system is running\r\n" );
+ MessageBeep(0);
+ return FALSE;
+ }
+
+ //
+ // check first that a window is active
+ //
+ if (hwndActiveEdit == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Could be the disassembler window
+ //
+
+ if (Views[thisView].Doc < 0) {
+
+ //
+ // Must be in a src or disasm window to do this
+ //
+ return FALSE;
+
+ } else if (Docs[Views[thisView].Doc].docType == DISASM_WIN) {
+
+ if (!DisasmGetAddrFromLine(&addr, Views[thisView].Y)) {
+ return FALSE;
+ }
+
+ //
+ // Check to see if breakpoint already at this address
+ //
+ addr2 = addr;
+ bpstatus = BPHbptFromAddr(&addr2, &hBpt);
+ if ((bpstatus == BPNOERROR) || (bpstatus == BPAmbigous)) {
+ BPDelete(hBpt);
+ ChangeDebuggerState();
+ BPCommit();
+ return TRUE;
+ }
+
+ Assert( bpstatus == BPNoBreakpoint );
+
+ EEFormatAddr(&addr, szCurLine, sizeof(szCurLine), 0);
+
+ bpstatus =
+ BPParse( &hBpt, szCurLine, NULL, NULL, LppdCur ? LppdCur->hpid : 0);
+
+ if (bpstatus != BPNOERROR) {
+ return FALSE;
+ } else {
+
+ Dbg(BPAddToList( hBpt, -1) == BPNOERROR);
+ Assert(DebuggeeAlive());
+ bpstatus = BPBindHbpt( hBpt, NULL );
+
+ if (bpstatus != BPNOERROR) {
+ BPUnCommit();
+ return FALSE;
+ }
+ ChangeDebuggerState();
+ BPCommit();
+ return TRUE;
+ }
+
+ } else if (Docs[Views[thisView].Doc].docType == DOC_WIN) {
+
+ //
+ // Ok to do this in source win
+ //
+
+ //
+ // Deal with any mapping of file names
+ //
+ _fstrcpy(rgch, Docs[Views[thisView].Doc].FileName);
+ SrcBackMapSourceFilename(rgch, sizeof(rgch));
+
+ // set the line number to the current line (where the caret is)
+ dwLineNumber = Views[thisView].Y+1;
+
+ if ( ToggleInRange(
+ thisView,
+ dwLineNumber,
+ min( (DWORD)Docs[Views[thisView].Doc].NbLines+1, dwLineNumber+20 ),
+ FALSE,
+ hBpt,
+ rgch ) ) {
+
+ return TRUE;
+
+ }
+
+ if ( ToggleInRange(
+ thisView,
+ dwLineNumber,
+ (DWORD)Docs[Views[thisView].Doc].NbLines+1,
+ TRUE,
+ hBpt,
+ rgch ) ) {
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+} /* ToggleLocBP() */
+
+
+/*** ContinueToCursor
+**
+** Synopsis:
+** bool = ContinueToCursor()
+**
+** Entry:
+** Nothing
+**
+** Returns:
+** TRUE on success and FALSE on failure
+**
+** Description:
+** Attemps to do a GoUntil to the address that corresponds to the
+** source line at the current cursor position in the editor
+*/
+
+BOOL PASCAL
+ContinueToCursor(
+ int View,
+ int line
+ )
+{
+ char szCurLine[255];
+ char rgch[300];
+ HBPT hBpt;
+ ADDR addr;
+ BPSTATUS bpstatus;
+
+ //
+ // Check for active window
+ //
+ if (hwndActiveEdit == NULL) {
+ return FALSE;
+ }
+
+ //
+ // If we get here then the debuggee must be alive. If it is not
+ // also active then return FALSE. We can't do anything in that case
+ //
+ Assert( DebuggeeAlive() );
+
+ //
+ // Check first for a disassembler window.
+ //
+
+ if (Views[View].Doc < 0) {
+ //
+ // Can't do this in a pane window
+ //
+ return FALSE;
+ } else if (Docs[Views[View].Doc].docType == DISASM_WIN) {
+ if (DisasmGetAddrFromLine(&addr, line)) {
+ GoUntil(&addr);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else if (Docs[Views[View].Doc].docType != DOC_WIN) {
+ //
+ // Must be in a source window in order to do this
+ //
+ return FALSE;
+ }
+
+ if (!DebuggeeActive()) {
+ return FALSE;
+ }
+
+ sprintf(szCurLine, "%c%d", BP_LINELEADER, line + 1);
+
+ //
+ // Back map the current file name to the original file name
+ // if it has been changed
+ //
+ _fstrcpy(rgch, Docs[Views[View].Doc].FileName);
+ SrcBackMapSourceFilename(rgch, sizeof(rgch));
+
+ bpstatus = BPParse(&hBpt,
+ szCurLine,
+ NULL,
+ rgch,
+ LppdCur ? LppdCur->hpid : 0);
+ if (bpstatus != BPNOERROR) {
+
+ return FALSE;
+
+ } else if ((bpstatus = BPBindHbpt( hBpt, &CxfIp )) == BPNOERROR) {
+
+ Dbg( BPAddrFromHbpt( hBpt, &addr ) == BPNOERROR );
+ Dbg( BPFreeHbpt( hBpt ) == BPNOERROR );
+ GoUntil( &addr );
+
+ } else if (!LppdCur->fHasRun) {
+
+ // not yet at entrypoint: save it for later
+ LppdCur->hbptSaved = (HANDLE)hBpt;
+ Go();
+
+ } else {
+
+ // it should have bound
+ Dbg( BPFreeHbpt( hBpt ) == BPNOERROR );
+ return FALSE;
+ }
+
+ return TRUE;
+} /* ContinueToCursor() */
+
+
+void PASCAL
+UpdateRadix(
+ UINT newradix
+ )
+/*++
+
+Routine Description:
+
+ Change the global radix and update any windows that need to track radix.
+
+Arguments:
+
+ newradix - Supplies new radix value: 8, 10 or 16
+
+Return Value:
+
+ None
+
+--*/
+{
+ Assert(newradix == 8 || newradix == 10 || newradix == 16);
+
+ if (newradix != radix) {
+ radix = newradix;
+ UpdateDebuggerState(UPDATE_RADIX);
+ ChangeDebuggerState();
+ }
+
+ return;
+} /* UpdateRadix() */
+
+
+void PASCAL ZapInt3s(void)
+{
+ MessageBeep(0);
+}
+
+
+int NEAR PASCAL
+GetQueueLength()
+{
+ int i;
+
+
+ EnterCriticalSection(&csDbgMsgBuffer);
+
+ // OK so its not the length -- all I currently really care about
+ // is if there are any messages setting and waiting for me.
+
+ i = iDbgMsgBufferFront - iDbgMsgBufferBack;
+ LeaveCriticalSection(&csDbgMsgBuffer);
+ return i;
+} /* GetQueueLength() */
+
+
+
+BOOLEAN NEAR PASCAL
+AddQueueItemLong(
+ long l
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ int newBufferFront;
+ BOOLEAN fEmpty;
+
+ EnterCriticalSection(&csDbgMsgBuffer);
+
+ newBufferFront = (iDbgMsgBufferFront + 1) % QUEUE_SIZE;
+
+ while (newBufferFront == iDbgMsgBufferBack) {
+ LeaveCriticalSection(&csDbgMsgBuffer);
+ Sleep(1000);
+ EnterCriticalSection(&csDbgMsgBuffer);
+ }
+
+ fEmpty = (GetQueueLength() == 0);
+ RgbDbgMsgBuffer[iDbgMsgBufferFront] = l;
+
+ iDbgMsgBufferFront = newBufferFront;
+
+ LeaveCriticalSection(&csDbgMsgBuffer);
+
+ return fEmpty;
+}
+
+
+long PASCAL
+GetQueueItemLong(
+ void
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ long l;
+
+ EnterCriticalSection(&csDbgMsgBuffer);
+
+ while (iDbgMsgBufferFront == iDbgMsgBufferBack) {
+ LeaveCriticalSection(&csDbgMsgBuffer);
+ Sleep(1000);
+ EnterCriticalSection(&csDbgMsgBuffer);
+ }
+
+ l = RgbDbgMsgBuffer[iDbgMsgBufferBack];
+
+ iDbgMsgBufferBack = (iDbgMsgBufferBack + 1) % QUEUE_SIZE;
+
+ LeaveCriticalSection(&csDbgMsgBuffer);
+
+ return l;
+}
+
+
+LPTD LOCAL PASCAL
+CBLptdOfHpidHtid(
+ HPID hpid,
+ HTID htid
+ )
+/*++
+
+Routine Description:
+
+ This is a specialized debugger version of this function. It should
+ only be called from the callback routine. It will return a thread
+ pointer if one can be found and otherwise will push the process
+ and thread handles onto the save memory area.
+
+Arguments:
+
+ hpid - osdebug handle to a process
+ htid - osdebug handle to a thread
+
+Return Value:
+
+ pointer to thread descriptor block if one exists for the thread
+ and process handles. Otherwise it will return NULL.
+
+--*/
+{
+ LPPD lppd;
+ LPTD lptd = NULL;
+
+ lppd = LppdOfHpid(hpid);
+ if (lppd) {
+ lptd = LptdOfLppdHtid( lppd, htid );
+ }
+ AddQueueItemLong((LONG) lptd);
+ if (lptd == NULL) {
+ AddQueueItemLong((LONG) hpid);
+ AddQueueItemLong((LONG) htid);
+ }
+
+ return( lptd );
+} /* CBLptdOfHpidHtid() */
+
+
+XOSD PASCAL LOADDS
+OSDCallbackFunc(
+ USHORT wMsg,
+ HPID hpid,
+ HTID htid,
+ UINT wParam,
+ LONG lParam
+ )
+/*++
+
+Routine Description:
+
+ This function posts a message to the main message pump to be
+ processed in CmdNextExec. All of the relevent data is posted
+ as part of the message. This must be done for the Win16 case
+ as things such as memory allocation are not good here since this
+ could called be non-syncronous.
+
+Arguments:
+
+ wMsg - Callback message number (dbc*)
+
+ hpid - process ID for the message
+
+ htid - thread ID for the message
+
+ wParam - Data about the message
+
+ lParam - Data about the message
+
+Return Value:
+
+ xosdNone - never returns an error
+
+--*/
+{
+ BOOLEAN fPostMsg = FALSE;
+
+ LPBPR lpbpr;
+ LPINF lpinf;
+ LPADDR lpaddr;
+ HSYM hSym;
+ UOFF32 uoff;
+ CXF Cxf;
+ CANSTEP *CanStep;
+ FUNCTION_INFO FunctionInfo;
+ ADDR Addr;
+ WORD wLn;
+ SHOFF cbLn;
+ SHOFF dbLn;
+
+
+ switch ((DBC)wMsg) {
+ case dbcInfoAvail:
+ case dbcInfoReq:
+ lpinf = (LPINF)lParam;
+ fPostMsg = AddQueueItemLong( wMsg );
+ if ( (DBC)wMsg == dbcInfoAvail ) {
+ AddQueueItemLong( lpinf->fReply );
+ } else {
+ Assert( lpinf->fReply );
+ }
+
+ AddQueueItemLong( lpinf->fUniCode );
+ if (!lpinf->fUniCode) {
+ AddQueueItemLong( (LONG) _strdup(lpinf->buffer) );
+ } else {
+ int l = lstrlenW((LPWSTR)lpinf->buffer);
+ LPWSTR lpw = malloc(2*l + 2);
+ memcpy(lpw, lpinf->buffer, 2*l);
+ lpw[l] = 0;
+ AddQueueItemLong( (LONG) lpw );
+ }
+ break;
+
+ case dbcStep:
+
+ case dbcBpt:
+ case dbcCheckBpt:
+ //case dbcSendBpt:
+
+ //case dbcWatchPoint:
+ //case dbcCheckWatchPoint:
+ //case dbcSendWatchPoint:
+
+ //case dbcMsgBpt:
+ //case dbcCheckMsgBpt:
+ //case dbcSendMsgBpt:
+
+ case dbcAsyncStop:
+ case dbcEntryPoint:
+ case dbcLoadComplete:
+
+ fPostMsg = AddQueueItemLong( wMsg );
+ CBLptdOfHpidHtid( hpid, htid );
+
+ Assert(wParam == sizeof(BPR));
+ lpbpr = (LPBPR)lParam;
+ AddQueueItemLong(lpbpr->dwNotify);
+
+ break;
+
+ case dbcProcTerm:
+ fPostMsg = AddQueueItemLong( wMsg );
+ AddQueueItemLong( (LONG) hpid );
+ AddQueueItemLong((LONG) lParam); // Save away exit code
+ break;
+
+ case dbcDeleteProc:
+ fPostMsg = AddQueueItemLong( wMsg );
+ AddQueueItemLong( (LONG) hpid );
+ break;
+
+ case dbcModFree:
+ fPostMsg = AddQueueItemLong( wMsg );
+ AddQueueItemLong( (LONG) hpid );
+ AddQueueItemLong((LONG) lParam);
+ break;
+
+ case dbcModLoad:
+ fPostMsg = AddQueueItemLong( wMsg );
+ AddQueueItemLong((LONG) hpid);
+ AddQueueItemLong((LONG) _strdup((LSZ)lParam)); // remember name
+ break;
+
+ case dbcError:
+ fPostMsg = AddQueueItemLong( wMsg );
+ AddQueueItemLong((LONG) hpid);
+ AddQueueItemLong((LONG) htid);
+ AddQueueItemLong((LONG) wParam);
+ AddQueueItemLong((LONG)_strdup((LSZ) lParam));
+ break;
+
+ case dbcCanStep:
+ lpaddr = (LPADDR) lParam;
+
+ if ( (HPID)emiAddr( *lpaddr ) == hpid && ADDR_IS_LI(*lpaddr) ) {
+
+ //
+ // This is magic, don't ask.
+ //
+ emiAddr( *lpaddr ) = 0;
+ ADDR_IS_LI( *lpaddr ) = FALSE;
+
+#ifdef OSDEBUG4
+ OSDSetEmi(hpid,htid,lpaddr);
+#else
+ OSDPtrace(osdSetEmi, wNull, lpaddr, hpid, htid);
+#endif
+ }
+ if ( (HPID)emiAddr( *lpaddr ) != hpid ) {
+ SHWantSymbols( (HEXE)emiAddr( *lpaddr ) );
+ }
+
+ SHSetCxt( lpaddr, SHpCxtFrompCxf( &Cxf ) );
+
+ CanStep = (CANSTEP*)lParam;
+
+ uoff = SHGetNearestHSYM( lpaddr, Cxf.cxt.hMod , EECODE, &hSym );
+
+ if ( uoff != CV_MAXOFFSET && SHIsThunk( hSym ) ) {
+
+ CanStep->Flags = CANSTEP_THUNK;
+
+ } else if (uoff == CV_MAXOFFSET &&
+ !SLLineFromAddr( lpaddr, &wLn, NULL, NULL)) {
+
+ CanStep->Flags = CANSTEP_NO;
+
+ } else {
+
+ uoff = 0;
+ Addr = Cxf.cxt.addr;
+ SYFixupAddr( &Addr );
+
+ if (OSDGetFunctionInfo( hpid, &Addr, &FunctionInfo ) == xosdNone) {
+ if (GetAddrOff(FunctionInfo.AddrPrologEnd) > GetAddrOff(Addr)) {
+ uoff = GetAddrOff(FunctionInfo.AddrPrologEnd) -
+ GetAddrOff(Addr);
+ }
+ } else if ( !status.fSrcMode ) {
+ while( SHIsInProlog( &Cxf.cxt ) ) {
+ Cxf.cxt.addr.addr.off++;
+ uoff++;
+ }
+ }
+
+ CanStep->Flags = CANSTEP_YES;
+ CanStep->PrologOffset = uoff;
+
+ }
+
+ return (xosdNone);
+
+ case dbcLastAddr:
+
+ //
+ // We will return:
+ //
+ // If SRC mode and have src for line - Last addr in line
+ // If SRC mode and no src for line - Zero
+ // if ASM mode - Same addr
+ //
+ lpaddr = (LPADDR) lParam;
+
+ if ( !status.fSrcMode ) {
+
+ if ( SLLineFromAddr( lpaddr, &wLn, &cbLn, &dbLn ) ) {
+
+ Assert( cbLn >= dbLn );
+ if (cbLn >= dbLn) {
+ lpaddr->addr.off += cbLn - dbLn;
+ }
+ } else {
+ memset( lpaddr, 0, sizeof( ADDR ) );
+ }
+ }
+
+ return (xosdNone);
+
+
+ case dbcFlipScreen:
+ return xosdNone;
+
+ case dbcException:
+ fPostMsg = AddQueueItemLong( wMsg );
+ CBLptdOfHpidHtid( hpid, htid);
+ AddQueueItemLong(lParam);
+ break;
+
+ case dbcThreadTerm:
+ fPostMsg = AddQueueItemLong( wMsg );
+ CBLptdOfHpidHtid( hpid, htid );
+ AddQueueItemLong((LONG) lParam); // Save away exit code
+ break;
+
+ case dbcExecuteDone:
+ AddQueueItemLong( wMsg );
+ PostMessage(hwndFrame, DBG_REFRESH, dbcExecuteDone, xosdNone);
+ return xosdNone;
+
+
+ case dbcNtRip:
+ fPostMsg = AddQueueItemLong( wMsg );
+ CBLptdOfHpidHtid( hpid, htid );
+ AddQueueItemLong((LONG) lParam);
+ break;
+
+
+ case dbcNewProc:
+ //
+ // hpid belongs to root proc; new hpid is in wParam.
+ //
+ AddQueueItemLong( wMsg );
+ AddQueueItemLong( (LONG)(HPID)(wParam));
+ PostMessage(hwndFrame, DBG_REFRESH, dbcNewProc, wParam);
+ return xosdNone;
+
+ case (DBC)dbcRemoteQuit:
+ fPostMsg = AddQueueItemLong( wMsg );
+ break;
+
+ case (DBC)dbcChangedMemory:
+ fPostMsg = AddQueueItemLong( wMsg );
+ AddQueueItemLong( (LONG) lParam );
+ break;
+
+ case dbcSegLoad:
+ fPostMsg = AddQueueItemLong( wMsg );
+ CBLptdOfHpidHtid( hpid, htid) ;
+ AddQueueItemLong(lParam);
+ break;
+
+ case dbcCreateThread:
+ default:
+ fPostMsg = AddQueueItemLong( wMsg );
+ CBLptdOfHpidHtid( hpid, htid);
+ break;
+ }
+
+ if (fPostMsg) {
+ PostMessage(hwndFrame, DBG_REFRESH, 0, 0);
+ }
+ return (xosdNone);
+} /* OSDCallbackFunc() */
+
+
+/*** FDebInit
+**
+** Synopsis:
+** bool = FDebInit()
+**
+** Entry:
+** none
+**
+** Returns:
+** TRUE if the debugger was initialized successfully and FALSE
+** if the debugger failed to initialize
+**
+** Description:
+** Initialize the OSDebug debugger.
+**
+*/
+
+
+BOOL PASCAL FDebInit()
+{
+
+ if (OSDInit(&Dbf) != xosdNone) {
+ return (FALSE); /* Error during initialization */
+ }
+
+ BPInit();
+
+ StatusPidTid((UINT) -1, (UINT) -1);
+
+ return (TRUE);
+} /* FDebInit() */
+
+/*** FDebTerm
+**
+** Synopsis:
+** bool = FDebTerm()
+**
+** Entry:
+** None
+**
+** Returns:
+** TRUE if successful and FALSE otherwise
+**
+** Description:
+** This routine will go back and do any clean up necessary to
+** kill all of the debugger dlls, debuggee processes and so forth.
+*/
+
+BOOL PASCAL
+FDebTerm(
+ void
+ )
+{
+ KillDebuggee();
+
+ if (LppdFirst) {
+ SHDeleteProcess(LppdFirst->hpds);
+ OSDDestroyPID(LppdFirst->hpid);
+ DestroyPd(LppdFirst, TRUE);
+ LppdFirst = LppdCur = NULL;
+ SetIpid(0);
+ }
+
+ if (Hem) {
+ OSDDeleteEM( Hem );
+ Hem = 0;
+ }
+ if (Htl) {
+ OSDDeleteTL( Htl );
+ Htl = 0;
+ }
+
+ OSDTerm();
+
+ return TRUE;
+} /* FDebTerm() */
+
+
+
+BOOL
+DllVersionMatch(
+ HANDLE hMod,
+ LPSTR pName,
+ LPSTR pType,
+ BOOL fNoisy
+ )
+{
+ DBGVERSIONPROC pVerProc;
+ BOOL Ok = TRUE;
+ LPAVS pavs;
+
+ pVerProc = (DBGVERSIONPROC)GetProcAddress(hMod, DBGVERSIONPROCNAME);
+ if (!pVerProc) {
+
+ Ok = FALSE;
+ if (fNoisy) {
+ ErrorBox(ERR_Not_Windbg_DLL, pName);
+ }
+
+ } else {
+
+ pavs = (*pVerProc)();
+
+ if (pType[0] != pavs->rgchType[0] || pType[1] != pavs->rgchType[1]) {
+
+ Ok = FALSE;
+ if (fNoisy) {
+ ErrorBox(ERR_Wrong_DLL_Type,
+ pName, (LPSTR)pavs->rgchType, (LPSTR)pType);
+ }
+
+ } else if (Avs.rlvt != pavs->rlvt) {
+
+ Ok = FALSE;
+ if (fNoisy) {
+ ErrorBox(ERR_Wrong_DLL_Version, pName,
+ pavs->rlvt, pavs->iRmj, Avs.rlvt, Avs.iRmj);
+ }
+
+ } else if (Avs.iRmj != pavs->iRmj) {
+
+ Ok = FALSE;
+ if (fNoisy) {
+ ErrorBox(ERR_Wrong_DLL_Version, pName,
+ pavs->rlvt, pavs->iRmj, Avs.rlvt, Avs.iRmj);
+ }
+
+ }
+
+ }
+
+ return Ok;
+}
+
+
+
+HANDLE
+LoadHelperDll(
+ LPSTR psz,
+ LPSTR pType,
+ BOOL fError
+ )
+/*++
+
+Routine Description:
+
+ Load a debugger DLL, verify that it is the correct type
+ and version.
+
+Arguments:
+
+ psz - Supplies string contianing name of DLL to be loaded
+ pType - Supplies type string
+ fError - Supplies flag saying whether to display an error message
+ on failure.
+
+Returns:
+
+ HMODULE to library or NULL
+
+--*/
+{
+ HANDLE hMod;
+ BOOL fail = FALSE;
+
+ hMod = LoadLibrary(psz);
+
+#ifndef WIN32
+ if (hMod <= 32) {
+ fail = TRUE;
+ hMod = NULL;
+ }
+#else
+ if (hMod == NULL) {
+ fail = TRUE;
+ }
+#endif
+ else if (!DllVersionMatch( hMod, psz, pType, fError ) ) {
+ FreeLibrary( hMod );
+ hMod = NULL;
+ fail = TRUE;
+ }
+
+ if (fail && fError) {
+ ErrorBox(ERR_Cannot_Load_DLL, (LPSTR) psz);
+ }
+
+ return hMod;
+} /* LoadHelperDll() */
+
+/*** FLoadShEe
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL PASCAL FloadShEe(
+ DWORD mach
+ )
+{
+ LPFNSHINIT lpfn2;
+ LPFNEEINIT lpfn3;
+ char * szDll;
+ char * szDllEEAuto;
+ char * lpch;
+ char chSave;
+ HCURSOR hcursor;
+ int Errno;
+
+
+ CmdInsertInit();
+
+ /*
+ ** Place the hour glass icon onto the screen
+ */
+
+ hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ /*
+ **
+ */
+
+ if (Lpshf == NULL) {
+ szDll = GetDllName(DLL_SYMBOL_HANDLER);
+
+ if (szDll == NULL) {
+ SetCursor(hcursor);
+ ErrorBox(ERR_DLL_Symbol_Unspecified);
+ return( FALSE );
+ }
+
+ if ((HModSH = LoadHelperDll(szDll, "SH", TRUE)) == 0) {
+ SetCursor(hcursor);
+ return( FALSE );
+ }
+
+ if ((lpfn2 = (LPFNSHINIT) GetProcAddress(HModSH, "SHInit")) == NULL) {
+ Errno = ERR_Invalid_Debugger_Dll;
+ goto errRet;
+ }
+
+ if (lpfn2(&Lpshf, &Knf) == FALSE) {
+ Errno = ERR_Initializing_Debugger;
+ goto errRet;
+ }
+ }
+
+ szDll = GetDllName(DLL_EXPR_EVAL);
+
+ if (szDll == NULL) {
+ SetCursor(hcursor);
+ InformationBox(ERR_DLL_Expr_Unspecified);
+ return( FALSE );
+ }
+
+ switch (mach) {
+ case mptix86:
+ szDllEEAuto = "eecxxx86.dll";
+ break;
+
+ case mptmips:
+ szDllEEAuto = "eecxxmip.dll";
+ break;
+
+ case mptdaxp:
+ szDllEEAuto = "eecxxalp.dll";
+ break;
+
+ case mptmppc:
+ szDllEEAuto = "eecxxppc.dll";
+ break;
+
+ case mptUnknown:
+ default:
+ szDllEEAuto = szDll;
+ break;
+ }
+
+ if (_stricmp( szDll, szDllEEAuto ) != 0) {
+ CmdLogFmt("Wrong EE specified, overidden by %s\r\n", szDllEEAuto );
+ szDll = szDllEEAuto;
+ }
+
+ /*
+ ** Check for either a space or a tab following the name of the DLL
+ ** if so then replace that character with a 0 and ignore the rest
+ ** of the string
+ */
+
+ if ((lpch = strchr(szDll, ' ')) == NULL) {
+ lpch = strchr(szDll, '\t');
+ }
+
+ if (lpch != NULL) {
+ chSave = *lpch;
+ *lpch = 0;
+ }
+
+ if ((HModEE = LoadHelperDll(szDll, "EE", TRUE)) == 0) {
+ if (lpch != NULL) {
+ *lpch = chSave;
+ }
+ SetCursor(hcursor);
+ return FALSE;
+ }
+
+ if (lpch != NULL) {
+ *lpch = chSave;
+ }
+
+
+ if ((lpfn3 = (LPFNEEINIT) GetProcAddress(HModEE, "EEInitializeExpr")) == NULL) {
+ Errno = ERR_Invalid_Debugger_Dll;
+ goto errRet;
+ }
+ lpfn3(&Ci, &Ei);
+
+ /*
+ ** Back fill any structures
+ */
+
+ CopyShToEe();
+
+ /*
+ ** Make sure that open windows find out about the new EE
+ */
+
+ SendMessageNZ( GetCpuHWND(), WU_DBG_LOADEE, 0, 0); // Give'em a change
+ SendMessageNZ( GetFloatHWND(), WU_DBG_LOADEE, 0, 0); // to Unload
+ SendMessageNZ( GetLocalHWND(), WU_DBG_LOADEE, 0, 0);
+ SendMessageNZ( GetWatchHWND(), WU_DBG_LOADEE, 0, 0);
+ SendMessageNZ( GetCallsHWND(), WU_DBG_LOADEE, 0, 0);
+
+
+ /*
+ ** Set the mouse cursor back to the origial one
+ */
+
+ SetCursor(hcursor);
+
+ EESetSuffix( SuffixToAppend );
+
+ return(TRUE);
+
+errRet:
+ SetCursor( hcursor );
+ ErrorBox( Errno, szDll );
+ return FALSE;
+} /* FLoadShEe() */
+
+
+BOOL
+FLoadEmTl(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to load the Execution Module and the
+ Transport Layer DLLs
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the dlls were sucessfully loaded and FALSE otherwise.
+
+--*/
+{
+ char *szDllTL;
+ char *szDllEM;
+ char *szDllEMAuto;
+ char *szDllErr;
+ EMFUNC lpfnEm;
+ TLFUNC lpfnTl;
+ HCURSOR hcursor;
+ char *lpch;
+ char chSave;
+ int Errno;
+ DWORD mach = 0;
+ char szInitString[1024];
+ char *p;
+#ifdef OSDEBUG4
+ XOSD xosd;
+#endif
+
+
+ CmdInsertInit();
+
+ hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ szDllTL = GetDllName(DLL_TRANSPORT);
+ szDllErr = szDllTL;
+
+ if (szDllTL == NULL) {
+ SetCursor(hcursor);
+ InformationBox(ERR_DLL_Transport_Unspecified);
+ return( FALSE );
+ }
+
+#ifndef OSDEBUG4
+ /*
+ ** There may be parameters following the name of the transport
+ ** dll. These are initializer commands
+ */
+
+ if ((lpch = strchr(szDllTL, ' ')) == NULL) {
+ lpch = strchr(szDllTL, '\t');
+ }
+
+ if (lpch != NULL) {
+ chSave = *lpch;
+ *lpch = 0;
+ }
+
+ /*
+ ** Now that we have just the name of the DLL attempt to load it
+ */
+#endif
+
+ if ((HModTL = LoadHelperDll(szDllTL, "TL", TRUE)) == 0) {
+ if (lpch != NULL) {
+ *lpch = chSave;
+ }
+ SetCursor(hcursor);
+ return(FALSE);
+ }
+
+#ifndef OSDEBUG4
+ /*
+ ** Restore the save character and point to the initailizer string
+ */
+
+ if (lpch != NULL) {
+ *lpch = chSave;
+ lpch++;
+ } else {
+ lpch = "";
+ }
+
+ strcpy( szInitString, lpch );
+
+ /*
+ ** add the kernel debugger options
+ */
+
+ if (runDebugParams.fKernelDebugger) {
+ p = &szInitString[strlen(szInitString)];
+ if (szInitString[0]) {
+ strcat( p++, " " );
+ }
+ FormatKdParams( p, TRUE );
+ }
+#endif
+
+ /*
+ ** Now get the entry point for the transport DLL
+ */
+
+ if ((lpfnTl = (TLFUNC) GetProcAddress(HModTL, "TLFunc")) == NULL) {
+ Errno = ERR_Invalid_Debugger_Dll;
+ goto errRet;
+ }
+
+#ifdef OSDEBUG4
+
+ xosd = OSDAddTL( lpfnTL, &Dbf, &Htl );
+
+ if (xosd == xosdNone) {
+ xosd = WKSPSetupTL( Htl );
+ }
+
+ switch ( xosd ) {
+
+ case xosdNone:
+ break; // cool, we're set up.
+
+ case xosdBadVersion:
+ case xosdBadRemoteVersion:
+ Errno = ERR_Wrong_Remote_DLL_Version;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdCannotConnect:
+ Errno = ERR_Cannot_Connect;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdCantOpenComPort:
+ Errno = ERR_Cant_Open_Com_Port;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+
+ case xosdBadComParameters:
+ Errno = ERR_Bad_Com_Parameters;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdBadPipeServer:
+ Errno = ERR_Bad_Pipe_Server;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdBadPipeName:
+ Errno = ERR_Bad_Pipe_Name;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ default:
+ Errno = ERR_Initializing_Debugger;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+ }
+
+#else
+
+ switch (OSDInitTL(lpfnTl, &Dbf)) {
+ case xosdNone: // all ok
+ break;
+
+ default:
+ Errno = ERR_Initializing_Debugger;
+ goto errRet;
+ break;
+ }
+
+
+ switch (OSDAddTL(lpfnTl, &Htl, szInitString)) {
+ case xosdNone:
+ mach = *(LPDWORD)szInitString;
+ break; // cool, we're connected.
+
+ case xosdBadVersion:
+ case xosdBadRemoteVersion:
+ Errno = ERR_Wrong_Remote_DLL_Version;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdCannotConnect:
+ Errno = ERR_Cannot_Connect;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdCantOpenComPort:
+ Errno = ERR_Cant_Open_Com_Port;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+
+ case xosdBadComParameters:
+ Errno = ERR_Bad_Com_Parameters;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdBadPipeServer:
+ Errno = ERR_Bad_Pipe_Server;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ case xosdBadPipeName:
+ Errno = ERR_Bad_Pipe_Name;
+ szDllErr = lpch;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+
+ default:
+ Errno = ERR_Initializing_Debugger;
+ OSDDeinitTL(lpfnTl); // must do here because Htl == NULL and
+ // we won't do OSDDeleteTL.
+ goto errRet;
+ break;
+ }
+#endif
+
+ /*
+ **
+ */
+
+ if (!FloadShEe(mach)) {
+ SetCursor(hcursor);
+ return FALSE;
+ }
+
+ szDllEM = GetDllName(DLL_EXEC_MODEL);
+ szDllErr = szDllEM;
+
+ if (szDllEM == NULL) {
+ SetCursor(hcursor);
+ Errno = ERR_DLL_Exec_Unspecified;
+ goto errRet;
+ }
+
+ switch (mach) {
+ case mptix86:
+ szDllEMAuto = "emx86.dll";
+ break;
+
+ case mptmips:
+ szDllEMAuto = "emmip.dll";
+ break;
+
+ case mptdaxp:
+ szDllEMAuto = "emalp.dll";
+ break;
+
+ case mptmppc:
+ szDllEMAuto = "emppc.dll";
+ break;
+
+ case mptUnknown:
+ default:
+ szDllEMAuto = szDllEM;
+ break;
+ }
+
+ if (_stricmp( szDllEM, szDllEMAuto ) != 0) {
+ CmdLogFmt("Wrong EM specified, overidden by %s\r\n", szDllEMAuto );
+ szDllEM = szDllEMAuto;
+ }
+
+ if ((HModEM = LoadHelperDll(szDllEM, "EM", TRUE)) == 0) {
+ SetCursor(hcursor);
+ Errno = 0; // LoadHelperDll already complained.
+ goto errRet;
+ }
+
+ if ((lpfnEm = (EMFUNC) GetProcAddress(HModEM, "EMFunc")) == NULL) {
+ Errno = ERR_Invalid_Debugger_Dll;
+ goto errRet;
+ }
+
+ if (OSDAddEM(lpfnEm, &Dbf, &Hem, emNative) != xosdNone) {
+ Errno = ERR_Initializing_Debugger;
+ goto errRet;
+ }
+
+#ifdef OSDEBUG4
+
+ // Do setup stuff here
+
+ if (WKSPSetupEM( Hem ) != xosdNone) {
+ Errno = ERR_Initializing_Debugger;
+ goto errRet;
+ }
+
+
+ //
+ // in OSDEBUG4, EM will load the DM during the first emfCreateHpid
+ //
+
+ switch (OSDCreateHpid(OSDCallbackFunc, Hem, Htl, &HpidBase)) {
+ case xosdNone:
+ break; // all cool
+
+ case xosdBadRemoteVersion:
+ Errno = ERR_Wrong_Remote_DLL_Version;
+ szDllErr = szDllTL;
+ goto errRet;
+ break;
+
+ case xosdCannotConnect:
+ Errno = ERR_Cannot_Connect;
+ szDllErr = szDllTL;
+ goto errRet;
+ break;
+
+ default:
+ Errno = ERR_Initializing_Debugger;
+ goto errRet;
+ break;
+ }
+
+#else // OSDEBUG4
+
+ switch (OSDCreatePID(OSDCallbackFunc, Hem, Htl, &HpidBase)) {
+ case xosdNone:
+ break; // all cool
+
+ case xosdBadRemoteVersion:
+ Errno = ERR_Wrong_Remote_DLL_Version;
+ szDllErr = szDllTL;
+ goto errRet;
+ break;
+
+ case xosdCannotConnect:
+ Errno = ERR_Cannot_Connect;
+ szDllErr = szDllTL;
+ goto errRet;
+ break;
+
+ default:
+ Errno = ERR_Initializing_Debugger;
+ goto errRet;
+ break;
+ }
+#endif // OSDEBUG4
+
+ /*
+ ** Set up the Process Descriptor block for the base process
+ **
+ ** Clear out the pointer to the current thread descripter block.
+ */
+
+ SetIpid(0);
+ LppdCur = LppdFirst = CreatePd( HpidBase );
+ LppdFirst->fPrecious = TRUE;
+ LptdCur = NULL;
+
+ if (runDebugParams.fShBackground) {
+ LPFNSHSTARTBACKGROUND lpfn;
+ lpfn = (LPFNSHSTARTBACKGROUND) GetProcAddress( HModSH, "SHStartBackground" );
+ if (lpfn) {
+ lpfn();
+ }
+ }
+
+ /*
+ ** Tell other people about the newly loaded EM
+ */
+
+ SendMessageNZ( GetCpuHWND(), WU_DBG_LOADEM, 0, 0);
+ SendMessageNZ( GetFloatHWND(), WU_DBG_LOADEM, 0, 0);
+
+ SetCursor(hcursor);
+
+ return TRUE ;
+
+
+errRet:
+
+ if (Hem) {
+ OSDDeleteEM( Hem );
+ }
+ if (HModEM) {
+ FreeLibrary(HModEM);
+ }
+ HModEM = NULL;
+ lpfnEm = NULL;
+ Hem = 0;
+
+ if (Htl) {
+ OSDDeleteTL( Htl );
+ }
+ if (HModTL) {
+ FreeLibrary(HModTL);
+ }
+ HModTL = NULL;
+ lpfnTl = NULL;
+ Htl = 0;
+
+ SetCursor( hcursor );
+
+ if (Errno != 0)
+ {
+ ErrorBox(Errno, szDllErr);
+ }
+ return FALSE;
+} /* FLoadEmTl() */
+
+
+/*** BPQuerySrcWinFls
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+
+BOOL PASCAL BPQuerySrcWinFls(char * pfls)
+{
+ Unreferenced( pfls );
+
+ return FALSE;
+} /* BPQuerySrcWinFls() */
+
+
+/*** MELoadEEParse
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+EESTATUS LOADDS PASCAL MELoadEEParse(char FAR * lpb, EERADIX iRadix,
+ SHFLAG shflag, PHTM phtm, uint FAR * lpus)
+{
+ if (!FloadShEe(mptUnknown))
+ return (EESTATUS) -1;
+#define Lpei (&Ei)
+
+ return(EEParse(lpb, iRadix, shflag, phtm, lpus));
+} /* MELoadEEParse() */
+
+
+/*** BPCBGetSouceFromAddr
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL PASCAL BPCBGetSourceFromAddr(LPADDR pAddr, char FAR * rgchFile, int cchFile, int FAR * pLine)
+{
+ WORD iLine;
+ if (GetSourceFromAddress(pAddr, rgchFile, cchFile, &iLine)) {
+ *pLine = iLine;
+ return TRUE;
+ }
+
+ return FALSE;
+} /* BPCBGetSourceFromAddr() */
+
+
+/*** SrcNameIsMasked
+**
+** Synopsis:
+** bool = SrcNameIsMasked(atm)
+**
+** Entry:
+** atm - Atom of file to look for in the set of masked files
+**
+** Returns:
+** TRUE if a match was found and FALSE otherwise
+**
+** Description:
+** This routine will look through the set of masked out file names
+** which are stored in an array of atoms looking for a match. If
+** one is found the the name is considered to be masked out and TRUE
+** will be returned. If no match is found then FALSE is returned.
+*/
+
+BOOL SrcNameIsMasked(ATOM atm)
+{
+ int i;
+
+ for (i=0; i<CAtomMasked; i++) {
+ if (RgAtomMaskedNames[i] == atm) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+} /* SrcNameIsMasked() */
+
+
+/*** SrcNameIsMapped
+**
+** Synopsis:
+** bool = SrcNameIsMapped(atm, lpb, cb)
+**
+** Entry:
+** atm - Atom for the file to be mapped from
+** lpb - buffer to return the mapped to name if mapping exists
+** cb - size of lpb in bytes
+**
+** Returns:
+** TRUE if a mapping was found and FALSE otherwise
+**
+** Description:
+** This function will look through the set of mappings looking for
+** a match to the input file name (atm). If a mapping is found then
+** the name of the map to file is returned in the buffer lpb.
+*/
+
+
+BOOL SrcNameIsMapped(ATOM atm, LSZ lpb, UINT cb)
+{
+ int i;
+
+ for (i=0; i<CAtomMapped; i++) {
+ if (RgAtomMappedNames[i].atomSrc == atm) {
+ GetAtomName(RgAtomMappedNames[i].atomTarget, lpb, cb);
+ return TRUE;
+ }
+ }
+ return FALSE;
+} /* SrcNameIsMapped() */
+
+/*** MatchOpenedDoc
+**
+** Synopsis:
+** int = MatchOpenedDoc
+**
+** Entry:
+** lpszSrc - buffer containing entry & exit filename
+** cbSrc - size of lpszSrc buffer in bytes
+**
+** Returns:
+** -1 - error occurred
+** 0 - no match
+** 1 - found and possibly mapping added
+**
+** Description:
+** This routine searches through the doc list and matches doc
+** that has the same file name as lpszSrc. If there is a match,
+** the file has not been mapped, and one of the following conditions
+** is true:
+** 1. The file satisfies root mapping transformation
+** 2. The file can be found along the source search path
+** 3. The user agrees on the mapping
+** then a 1 will be returned.
+*/
+INT
+MatchOpenedDoc(
+ LPSTR lpszSrc,
+ UINT cbSrc
+)
+{
+ LPSTR SrcFile = GetFileName(lpszSrc);
+ CHAR szDestName[MAX_PATH];
+ int doc;
+
+ dwMatchCnt = 0;
+ if ( SrcFile ) {
+ for (doc = 0; doc < MAX_DOCUMENTS; doc++) {
+ if (Docs[doc].docType == DOC_WIN && Docs[doc].FirstView != -1 &&
+ _stricmp(GetFileName(Docs[doc].FileName), SrcFile) == 0) {
+ // found a match just based on filename only
+ strcpy(szDestName, Docs[doc].FileName);
+ if (SrcBackMapSourceFilename(szDestName, sizeof(szDestName)) == 0) {
+ // file has no backward mapping
+ if (RootNameIsMapped(lpszSrc, szDestName, sizeof(szDestName)) &&
+ _stricmp(szDestName, Docs[doc].FileName) == 0) {
+ SrcSetMapped(lpszSrc, szDestName);
+ if (cbSrc <= strlen(szDestName))
+ return (-1); // error
+ else {
+ strcpy(lpszSrc, szDestName);
+ return (1); // matched and mapped
+ }
+ } else if (strcpy(szDestName, lpszSrc) &&
+ SrcSearchOnPath(szDestName, sizeof(szDestName), FALSE) &&
+ _stricmp(szDestName, Docs[doc].FileName) == 0) {
+ SrcSetMapped(lpszSrc, szDestName);
+ if (cbSrc <= strlen(szDestName))
+ return (-1); // error
+ else {
+ strcpy(lpszSrc, szDestName);
+ return (1); // matched and mapped
+ }
+ } else { // ask user
+ MatchedList[dwMatchCnt++] = doc;
+ }
+ }
+ }
+ }
+ }
+ if (dwMatchCnt > 0 && !AutoTest) {
+ if (NoPopups) {
+ MSG msg;
+matchopeneddocagain:
+ sprintf( szBrowsePrompt, "File %s can be mapped to several opened documents.\n", lpszSrc );
+ fBrowseAnswer = FALSE;
+ CmdSetCmdProc( CmdMatchOpenedDocInputString, CmdMatchOpenedDocPrompt );
+ CmdSetAutoHistOK(FALSE);
+ CmdSetEatEOLWhitespace(FALSE);
+ CmdDoPrompt( TRUE, TRUE );
+ while (GetMessage( &msg, NULL, 0, 0 )) {
+ ProcessQCQPMessage( &msg );
+ if (fBrowseAnswer) {
+ break;
+ }
+ }
+ if (szBrowseFname[0]) {
+ dwMatchIdx = atoi(szBrowseFname);
+ if (0 < dwMatchIdx && dwMatchIdx <= dwMatchCnt) {
+ SrcFile = Docs[MatchedList[dwMatchIdx-1]].FileName;
+ SrcSetMapped(lpszSrc, SrcFile);
+ if (cbSrc <= strlen(SrcFile))
+ return(-1);
+ else {
+ strcpy(lpszSrc, SrcFile);
+ return(1);
+ }
+ } else {
+ goto matchopeneddocagain;
+ }
+ }
+ CmdSetDefaultCmdProc();
+ CmdDoPrompt(TRUE, TRUE);
+ return 0;
+ }
+ strcpy(szFSSrcName, lpszSrc);
+ StartDialog( DLG_FSRESOLVE, DlgFileSearchResolve );
+ if (dwMatchIdx >= 0) {
+ SrcFile = Docs[MatchedList[dwMatchIdx]].FileName;
+ SrcSetMapped(lpszSrc, SrcFile);
+
+ if (FAddToSearchPath)
+ AddToSearchPath(SrcFile);
+ else if (FAddToRootMap)
+ RootSetMapped(lpszSrc, SrcFile);
+
+ if (cbSrc <= strlen(SrcFile))
+ return(-1);
+ else {
+ strcpy(lpszSrc, SrcFile);
+ return(1);
+ }
+ }
+ }
+ return 0;
+} // MatchOpenedDoc
+
+
+/*** SrcSearchOnPath
+**
+** Synopsis:
+** bool = SrcSearchOnPath(lpb, cb)
+**
+** Entry:
+** lpb - buffer containing entry & exit filename
+** cb - size of lpb in bytes
+**
+** Returns:
+** TRUE if the file was found in the search path and FALSE otherwise
+**
+** Description:
+** This routine will strip down to the base file name of the
+** source file the system is currently looking for and check for
+** the file in the current working directory, the exe's directory
+** and on the directories specified in the SourcePath tools.ini
+** variable. If the file is found then the full path is returned
+** in lpb.
+*/
+
+
+BOOL SrcSearchOnPath(LSZ lpb, UINT cb, BOOL fAddToMap)
+{
+ char rgch[_MAX_PATH];
+ char rgch2[_MAX_PATH];
+ char rgchFName[_MAX_FNAME+_MAX_EXT];
+ BOOL Found;
+ char *p;
+
+ //
+ // Get file name
+ //
+ _splitpath(lpb, szDrive, szDir, szFName, szExt);
+ strcpy(rgchFName, szFName);
+ strcat(rgchFName, szExt);
+
+ //
+ // Look in the current directory.
+ //
+ Found = FindNameOn(rgch, sizeof(rgch), ".", rgchFName);
+
+ if ( !Found ) {
+
+ //
+ // Not in current directory, look in EXE directory.
+ //
+ if ( GetCurrentProgramName(FALSE) ) {
+ strcpy( rgch, GetCurrentProgramName(FALSE) );
+ _splitpath(rgch, szDrive, szDir, szFName, szExt );
+ strcpy( rgch2, szDrive );
+ strcat( rgch2, szDir );
+#ifdef DBCS
+ p = CharPrev(rgch2, rgch2 + strlen(rgch2));
+#else
+ p = rgch2 + strlen(rgch2) - 1;
+#endif
+ if ( *p == '\\' ) {
+ *p = '\0';
+ }
+
+ Found = FindNameOn(rgch, sizeof(rgch), rgch2, rgchFName);
+ }
+
+ if ( !Found ) {
+ //
+ // Not in EXE directory, look along SourcePath.
+ //
+ Found = FindNameOn(rgch, sizeof(rgch), GetDllName(DLL_SOURCE_PATH), rgchFName);
+ }
+ }
+
+ if ( Found ) {
+
+ if (strlen(rgch) > cb) {
+
+ //
+ // Not enough space in return buffer
+ //
+ Found = FALSE;
+
+ } else {
+
+ if (fAddToMap)
+ SrcSetMapped(lpb, rgch);
+
+ _fstrcpy(lpb, rgch);
+ }
+ }
+
+ return Found;
+} /* SrcSearchOnPath() */
+
+/*** SrcSearchOnRoot
+**
+** Synopsis:
+** bool = SrcSearchOnRoot(lpb, cb)
+**
+** Entry:
+** lpb - buffer containing entry & exit filename
+** cb - size of lpb in bytes
+**
+** Returns:
+** TRUE if the file was found by root mapping and FALSE otherwise
+**
+** Description:
+** This routine compares the given file's root with those stored
+** in the root mapping table. If not found, it uses the debuggee's
+** drive to locate the source.
+*/
+BOOL SrcSearchOnRoot(LSZ lpb, UINT cb)
+{
+ char rgch[_MAX_PATH];
+ char rgch2[_MAX_PATH];
+ char rgchDest[_MAX_PATH];
+ BOOL Found;
+ char *p;
+ int i;
+
+ Found = RootNameIsMapped(lpb, rgchDest, sizeof(rgchDest));
+
+#if 0
+ if (!Found) {
+ _splitpath(lpb, szDrive, szDir, szFName, szExt);
+ Assert(szDir[0] == '\\');
+ sprintf(rgch, "%s%s%s", (szDir[0] == '\\') ? szDir+1 : szDir,
+ szFName, szExt); // src without drive
+
+ //
+ // Look into the debuggee's drive
+ //
+ if ( GetCurrentProgramName(FALSE) ) {
+ if (_fullpath(rgch2, GetCurrentProgramName(FALSE), sizeof(rgch2)) != NULL) {
+ // make sure drive letter exists and not the same as
+ // the original one as it would have been searched
+ if (rgch2[1] == ':' && _strnicmp(szDrive, rgch2, 2) != 0) {
+ rgch2[2] = '\0';
+ Found = FindNameOn(rgchDest, sizeof(rgchDest), rgch2, rgch);
+ }
+ }
+ }
+ }
+#endif
+
+ if ( Found ) {
+ if (strlen(rgchDest) >= cb) {
+ //
+ // Not enough space in return buffer
+ //
+ Found = FALSE;
+ } else {
+ SrcSetMapped(lpb, rgchDest);
+ _fstrcpy(lpb, rgchDest);
+ }
+ }
+ return Found;
+} /* SrcSearchOnRoot() */
+
+
+
+BOOL
+MiscBrowseForFile(
+ LSZ lpb,
+ UINT cb,
+ LSZ lpDir,
+ UINT cchDir,
+ int nDefExt,
+ int nIdDlgTitle,
+ void (*fnSetMapped)(LSZ, LSZ),
+ LPOFNHOOKPROC lpfnHook
+ )
+/*++
+
+Routine Description:
+
+ Tell the user that we can't find a file, and allow him to
+ browse for a it using a standard File Open dialog.
+
+Arguments:
+
+ lpb - Supplies name of requested file,
+ Returns fully qualified path
+ cb - Supplies size of buffer at lpb
+ lpDir - Supplies directory to start browse in,
+ Returns directory file was found in
+ cchDir - Supplies size of buffer at lpDir
+ nDefExt - Supplies resource id for default extension filter
+ nIdDlgTitle - Supplies res id for dialog title string
+ fnSetMapped - Supplies pointer to function for mapping
+ requested name to returned name.
+
+
+Return Value:
+
+ If a file is found, return TRUE and copy the path into
+ the buffer at lpb.
+
+--*/
+{
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ DWORD dwFlags = OFN_FILEMUSTEXIST|
+ OFN_PATHMUSTEXIST|
+ OFN_HIDEREADONLY|
+ OFN_NOCHANGEDIR|
+ OFN_SHOWHELP|
+ OFN_ENABLETEMPLATE;
+ char rgchT[_MAX_PATH];
+ char CurrentDirectory[_MAX_PATH ];
+ BOOL Ret = FALSE;
+
+ Assert(_fstrlen(lpb) < sizeof(rgchT));
+ _fstrcpy(rgchT, lpb);
+
+ if (DLG_Browse_Filebox_Title != nIdDlgTitle) {
+ _splitpath( rgchT, NULL, NULL, fname, ext );
+ _makepath( rgchT, NULL, NULL, fname, ext );
+ }
+
+ GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory );
+ if ( *lpDir ) {
+ SetCurrentDirectory( lpDir );
+ }
+
+ if (StartFileDlg(hwndFrame,
+ nIdDlgTitle,
+ nDefExt,
+ ID_BROWSE_HELP,
+ FILEOPENORD,
+ rgchT,
+ &dwFlags,
+ lpfnHook)
+ ) {
+ Assert( strlen(rgchT) < cb );
+
+ if ( strlen(rgchT)+1 <= cb) {
+ (*fnSetMapped)(lpb, rgchT);
+ _fstrcpy(lpb, rgchT);
+ GetCurrentDirectory( cchDir, lpDir);
+ Ret = TRUE;
+ }
+ }
+
+ SetCurrentDirectory( CurrentDirectory );
+
+ return Ret;
+} /* MiscBrowseForFile() */
+
+BOOL NEAR PASCAL
+StringLogger(
+ LPSTR szStr,
+ BOOL fFileLog,
+ BOOL fSendRemote,
+ BOOL fPrintLocal
+);
+
+VOID
+CmdMatchOpenedDocPrompt(
+ BOOL fRemote,
+ BOOL fLocal
+ )
+{
+ int i;
+ LPSTR lpszName;
+
+ CmdInsertInit();
+ StringLogger( szBrowsePrompt, TRUE, fRemote, fLocal );
+ StringLogger( "Please select from one of the followings or <CR> for none:\n", TRUE, fRemote, fLocal );
+ for (i=0; i < dwMatchCnt; i++) {
+ lpszName = Docs[MatchedList[i]].FileName;
+ sprintf(szBrowsePrompt, "%d. %s\n", i+1, lpszName);
+ StringLogger( szBrowsePrompt, TRUE, fRemote, fLocal );
+ }
+}
+
+BOOL
+CmdMatchOpenedDocInputString(
+ LPSTR lpsz
+ )
+{
+ strcpy( szBrowseFname, lpsz );
+ fBrowseAnswer = TRUE;
+ CmdSetDefaultCmdProc();
+ return TRUE;
+}
+
+VOID
+CmdBrowsePrompt(
+ BOOL fRemote,
+ BOOL fLocal
+ )
+{
+ CmdInsertInit();
+ StringLogger( szBrowsePrompt, TRUE, fRemote, fLocal );
+}
+
+BOOL
+CmdBrowseInputString(
+ LPSTR lpsz
+ )
+{
+ strcpy( szBrowseFname, lpsz );
+ fBrowseAnswer = TRUE;
+ CmdSetDefaultCmdProc();
+ return TRUE;
+}
+
+BOOL
+DlgBrowse(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ static LPBROWSESTRUCT lpbs;
+ char szAskBrowse[_MAX_PATH];
+ char szTemp[FILES_MENU_WIDTH + 1];
+
+ switch (message) {
+ case WM_INITDIALOG :
+ lpbs = ( LPBROWSESTRUCT) lParam;
+ AdjustFullPathName( lpbs->FileName, szTemp, FILES_MENU_WIDTH );
+ strcpy( szAskBrowse, "Browse for: " );
+ strcat(szAskBrowse, szTemp );
+ strcat( szAskBrowse, " ?" );
+ SetDlgItemText( hDlg, ID_BROWSEFOR, szAskBrowse );
+ SetForegroundWindow( hDlg );
+ MessageBeep( 0 );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDCANCEL:
+ case IDOK:
+ case ID_IGNOREALL:
+ lpbs->Rslt = wParam;
+ EndDialog( hDlg,wParam );
+ return TRUE;
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg,szHelpFileName, HELP_CONTEXT, ID_ASKBROWSE_HELP));
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+DWORD
+BrowseThread(
+ LPVOID lpv
+ )
+{
+ HWND hDlg;
+ MSG msg;
+ LPBROWSESTRUCT lpbs = (LPBROWSESTRUCT)lpv;
+
+
+ hDlg = CreateDialogParam( hInst, MAKEINTRESOURCE(lpbs->DlgId), NULL, lpbs->DlgProc, (LPARAM)lpbs );
+ if (!hDlg) {
+ return FALSE;
+ }
+
+ ShowWindow( hDlg, SW_SHOW );
+
+ while ((lpbs->Rslt == (DWORD)-1) && (GetMessage (&msg, NULL, 0, 0))) {
+ if (!IsDialogMessage( hDlg, &msg )) {
+ TranslateMessage ( &msg );
+ DispatchMessage ( &msg );
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL
+SrcBrowseForFile(
+ LSZ lpb,
+ UINT cb
+ )
+{
+ HANDLE hThread;
+ DWORD id;
+ BROWSESTRUCT bs;
+ MSG msg;
+
+ /*
+ * Check to see if running from scripts -- if so then
+ * don't bring up this dialog and error boxes.
+ */
+
+ if (AutoTest) {
+ return FALSE;
+ }
+
+ if (NoPopups) {
+browseagain:
+ sprintf( szBrowsePrompt, "Cannot load [ %s ] - Enter new path or <CR> to ignore ", lpb );
+ fBrowseAnswer = FALSE;
+ CmdSetCmdProc( CmdBrowseInputString, CmdBrowsePrompt );
+ CmdSetAutoHistOK(FALSE);
+ CmdSetEatEOLWhitespace(FALSE);
+ CmdDoPrompt( TRUE, TRUE );
+ while (GetMessage( &msg, NULL, 0, 0 )) {
+ ProcessQCQPMessage( &msg );
+ if (fBrowseAnswer) {
+ break;
+ }
+ }
+ if (szBrowseFname[0]) {
+ if (FileExist( szBrowseFname )) {
+ strcpy( lpb, szBrowseFname );
+ return TRUE;
+ } else {
+ goto browseagain;
+ }
+ }
+
+ CmdSetDefaultCmdProc();
+ CmdDoPrompt(TRUE, TRUE);
+ return FALSE;
+ }
+
+ EnsureFocusDebugger();
+
+ strcpy(szBrowse, lpb);
+
+ bs.Rslt = (DWORD)-1;
+ bs.DlgId = DLG_ASKSRCBROWSE;
+ bs.DlgProc = DlgBrowse;
+ bs.FileName = lpb;
+ bs.FnameSize = cb;
+
+ hThread = CreateThread( NULL, 0, BrowseThread, (LPVOID)&bs, 0, &id );
+ if (!hThread) {
+ return FALSE;
+ }
+
+ WaitForSingleObject( hThread, INFINITE );
+
+ switch(bs.Rslt) {
+ case IDCANCEL:
+ return FALSE;
+
+ case ID_IGNOREALL:
+ runDebugParams.fIgnoreAll = TRUE;
+ return FALSE;
+ }
+
+ return MiscBrowseForFile(lpb,
+ cb,
+ SrcFileDirectory,
+ sizeof(SrcFileDirectory),
+ DEF_Ext_C,
+ DLG_Browse_Filebox_Title,
+ SrcSetMapped,
+ GetOpenFileNameHookProc);
+} /* SrcBrowseForFile() */
+
+BOOL
+ExeBrowseForFile(
+ LSZ lpb,
+ UINT cb
+ )
+{
+ HANDLE hThread;
+ DWORD id;
+ BROWSESTRUCT bs;
+
+
+ if (AutoTest || runDebugParams.fIgnoreAll) {
+ return FALSE;
+ }
+
+ strcpy(szBrowse, lpb);
+
+ bs.Rslt = (DWORD)-1;
+ bs.DlgId = DLG_ASKEXEBROWSE;
+ bs.DlgProc = DlgBrowse;
+ bs.FileName = lpb;
+ bs.FnameSize = cb;
+
+ hThread = CreateThread( NULL, 0, BrowseThread, (LPVOID)&bs, 0, &id );
+ if (!hThread) {
+ return FALSE;
+ }
+
+ WaitForSingleObject( hThread, INFINITE );
+
+ switch(bs.Rslt) {
+ case IDCANCEL:
+ return FALSE;
+
+ case ID_IGNOREALL:
+ runDebugParams.fIgnoreAll = TRUE;
+ return FALSE;
+ }
+
+ return MiscBrowseForFile(lpb,
+ cb,
+ ExeFileDirectory,
+ sizeof(ExeFileDirectory),
+ DEF_Ext_SYM,
+ DLG_Browse_UserDll_Title,
+ ExeSetMapped,
+ GetOpenDllNameHookProc);
+}
+
+
+BOOL
+ExeBrowseBadSym(
+ LSZ lpb,
+ UINT cb
+ )
+{
+ HANDLE hThread;
+ DWORD id;
+ BROWSESTRUCT bs;
+
+
+ if (AutoTest) {
+ return FALSE;
+ }
+
+ if (runDebugParams.fIgnoreAll) {
+ return TRUE;
+ }
+
+ strcpy(szBrowse, lpb);
+
+ bs.Rslt = (DWORD)-1;
+ bs.DlgId = DLG_BADSYMBOLS;
+ bs.DlgProc = DlgBrowse;
+ bs.FileName = lpb;
+ bs.FnameSize = cb;
+
+ hThread = CreateThread( NULL, 0, BrowseThread, (LPVOID)&bs, 0, &id );
+ if (!hThread) {
+ return FALSE;
+ }
+
+ WaitForSingleObject( hThread, INFINITE );
+
+ switch(bs.Rslt) {
+ case IDCANCEL:
+ return FALSE;
+
+ case ID_IGNOREALL:
+ runDebugParams.fIgnoreAll = TRUE;
+ return FALSE;
+ }
+
+ return MiscBrowseForFile(lpb,
+ cb,
+ ExeFileDirectory,
+ sizeof(ExeFileDirectory),
+ DEF_Ext_SYM,
+ DLG_Browse_UserDll_Title,
+ ExeSetMapped,
+ GetOpenDllNameHookProc);
+}
+
+VOID
+ExeSetMapped(
+ LSZ lsz1,
+ LSZ lsz2
+ )
+{
+ // nobody home
+}
+
+/*** SrcSetMasked
+**
+** Synopsis:
+** void = SrcSetMasked(lsz)
+**
+** Entry:
+** lsz - Pointer to byte array for unfound name
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This routine will take the entry name and set it as to be
+** masked out. This allows use to prevent re-display of error
+** messages on the same file.
+*/
+
+VOID SrcSetMasked(LSZ lsz)
+{
+ ATOM atom;
+
+ atom = AddAtom(lsz);
+ if (atom == 0)
+ return;
+
+ if (RgAtomMaskedNames == NULL) {
+ CMacAtomMasked = 10;
+ RgAtomMaskedNames = (ATOM *) malloc(sizeof(ATOM)*CMacAtomMasked);
+ } else if (CAtomMasked == CMacAtomMasked) {
+ CMacAtomMasked += 10;
+ RgAtomMaskedNames = (ATOM *) realloc(RgAtomMaskedNames, sizeof(ATOM)*CMacAtomMasked);
+ }
+
+ RgAtomMaskedNames[CAtomMasked] = atom;
+ CAtomMasked += 1;
+ return;
+} /* SrcSetMasked() */
+
+/*** SrcSetMapped
+**
+** Synopsis:
+** void = SrcSetmapped(lsz1, lsz2)
+**
+** Entry:
+** lsz1 - Name of file to be mapped from
+** lsz2 - Name of file to be mapped to
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function will setup a mapping of source file names from
+** file name lsz1 to lsz2. This will allow for a fast reamapping
+** without haveing to do searches or ask the user a second time.
+**
+*/
+
+VOID SrcSetMapped(LSZ lsz1, LSZ lsz2)
+{
+ ATOM atomSrc = AddAtom(lsz1);
+ ATOM atomTrg = AddAtom(lsz2);
+
+ if (RgAtomMappedNames == NULL) {
+ CMacAtomMapped = 10;
+ RgAtomMappedNames = (struct MpPair *) malloc(sizeof(*RgAtomMappedNames)*CMacAtomMapped);
+ } else if (CAtomMapped == CMacAtomMapped) {
+ CMacAtomMapped += 10;
+ RgAtomMappedNames = (struct MpPair *) realloc(RgAtomMappedNames, sizeof(*RgAtomMappedNames)*CMacAtomMapped);
+ }
+
+ RgAtomMappedNames[CAtomMapped].atomSrc = atomSrc;
+ RgAtomMappedNames[CAtomMapped].atomTarget = atomTrg;
+ CAtomMapped += 1;
+} /* SrcSetMapped() */
+
+
+/*** SrcMapSourceFilename
+**
+** Synopsis:
+** int = SrcMapSourceFilename(lpszSrc, cbSrc, flags)
+**
+** Entry:
+** lpszSrc - Source buffer to map file in
+** cbSrc - size of source buffer
+** flags - flags to control behavior
+**
+** Returns:
+** -2 - operation canceled
+** -1 - error occured
+** 0 - No mapping done -- no source file mapped
+** 1 - Mapping done -- no file openned
+** 2 - Mapping done -- openned a new source window
+**
+** Description:
+** This function will setup a mapping of source file names from
+** file name lsz1 to lsz2. This will allow for a fast reamapping
+** without haveing to do searches or ask the user a second time.
+**
+*/
+
+int
+PASCAL
+SrcMapSourceFilename(
+ LPSTR lpszSrc,
+ UINT cbSrc,
+ int flags,
+ FINDDOC lpFindDoc
+)
+{
+ ATOM atomFile;
+ int doc;
+
+ /*
+ ** Step 1. Is this file actually in a source window. If
+ ** so then no changes need to be made to the source
+ ** file name.
+ */
+ if (lpFindDoc == NULL)
+ lpFindDoc = FindDoc;
+
+ if ((*lpFindDoc)(lpszSrc, &doc, TRUE)) {
+ return (1);
+ }
+
+ /*
+ ** Step 2. Make sure file is not on the "I'don't want to hear about it
+ ** list". If file has been mapped or exists on disk, it would not
+ ** not have been on this list.
+ */
+
+ atomFile = FindAtom(lpszSrc);
+ if (atomFile != (ATOM) NULL &&
+ SrcNameIsMasked(atomFile)) {
+ return 0;
+ }
+
+ /*
+ ** Step 3. Now check to see if the file has been previously remapped
+ ** or not
+ */
+
+ if ((atomFile != (ATOM) NULL) &&
+ SrcNameIsMapped(atomFile, lpszSrc, cbSrc)) {
+ if ((*lpFindDoc)(lpszSrc, &doc, TRUE)) {
+ return 1;
+ } else if (flags & SRC_MAP_OPEN) {
+ if (AddFile(MODE_OPEN, DOC_WIN, lpszSrc, NULL, NULL, TRUE, -1, -1) != -1) {
+ if (FSourceOverlay) {
+ int iView;
+ WINDOWPLACEMENT wp;
+
+ Dbg((*lpFindDoc)(lpszSrc, &doc, TRUE));
+
+ for (iView=0; iView < MAX_VIEWS; iView++) {
+ if ((Views[iView].Doc > -1) &&
+ (Docs[Views[iView].Doc].docType == DOC_WIN) &&
+ (Views[iView].Doc != doc)) {
+ GetWindowPlacement( Views[iView].hwndFrame, &wp );
+ SetWindowPlacement(Views[Docs[doc].FirstView].hwndFrame,
+ &wp);
+ break;
+ }
+ }
+ }
+ return 2;
+ }
+ return -1;
+ }
+ return 0;
+ }
+
+ /*
+ ** Step 4. The file we are looking for is not on the "I don't
+ ** want to hear about it list" and has no forward mapping.
+ ** Let's consider opened file of the same name.
+ */
+
+ doc = MatchOpenedDoc(lpszSrc, cbSrc);
+ if (doc != 0)
+ return(doc);
+
+ /*
+ ** Step 5. Does the requested file in fact actually exist on
+ ** the disk. If so then we want to read in the file
+ ** if requested and return the correct code.
+ **
+ ** This step does not need to be taken if we are just remapping
+ ** the file name. In this case we are just interested if we
+ ** have done any type of file mapping on the name yet.
+ */
+
+ if ((flags & SRC_MAP_OPEN) && FileExist(lpszSrc)) {
+ if (flags & SRC_MAP_OPEN) {
+ if (AddFile(MODE_OPEN, DOC_WIN, lpszSrc, NULL, NULL, TRUE, -1, -1) != -1) {
+ if (FSourceOverlay) {
+ int iView;
+ WINDOWPLACEMENT wp;
+
+ Dbg((*lpFindDoc)(lpszSrc, &doc, TRUE));
+
+ for (iView=0; iView < MAX_VIEWS; iView++) {
+ if ((Views[iView].Doc > -1) &&
+ (Docs[Views[iView].Doc].docType == DOC_WIN) &&
+ (Views[iView].Doc != doc)) {
+ GetWindowPlacement( Views[iView].hwndFrame, &wp );
+ SetWindowPlacement(Views[Docs[doc].FirstView].hwndFrame,
+ &wp);
+ break;
+ }
+ }
+
+ }
+ return 2;
+ } else {
+ return -1;
+ }
+ }
+ return 1;
+ }
+
+ /*
+ ** Step 6. Now check to see if the file can be root map
+ ** or not
+ */
+
+ if (SrcSearchOnRoot(lpszSrc, cbSrc)) {
+ if ((*lpFindDoc)(lpszSrc, &doc, TRUE) ) {
+ return 1;
+ } else if (flags & SRC_MAP_OPEN) {
+ if (AddFile(MODE_OPEN, DOC_WIN, lpszSrc, NULL, NULL, TRUE, -1, -1) != -1) {
+ if (FSourceOverlay) {
+ int iView;
+ WINDOWPLACEMENT wp;
+
+ Dbg((*lpFindDoc)(lpszSrc, &doc, TRUE));
+
+ for (iView=0; iView < MAX_VIEWS; iView++) {
+ if ((Views[iView].Doc > -1) &&
+ (Docs[Views[iView].Doc].docType == DOC_WIN) &&
+ (Views[iView].Doc != doc)) {
+ GetWindowPlacement( Views[iView].hwndFrame, &wp );
+ SetWindowPlacement(Views[Docs[doc].FirstView].hwndFrame,
+ &wp);
+ break;
+ }
+ }
+ }
+ return 2;
+ }
+ return -1;
+ }
+ return 0;
+ }
+
+ /*
+ ** If we are only interested in checking for an existing re-mapping
+ ** on the source file then we do not need to go any futher
+ */
+
+ if (flags & SRC_MAP_ONLY) {
+ return 0;
+ }
+
+ /*
+ ** Step 7. We must now search the source file path for the file. This
+ ** needs to include the cwd and exe directory for the file
+ */
+
+ if (SrcSearchOnPath(lpszSrc, cbSrc, TRUE) ||
+ SrcBrowseForFile(lpszSrc, cbSrc)) {
+ if ((*lpFindDoc)(lpszSrc, &doc, TRUE)) {
+ return 1;
+ } else if (flags & SRC_MAP_OPEN) {
+ if (AddFile(MODE_OPEN, DOC_WIN, lpszSrc, NULL, NULL, TRUE, -1, -1) != -1) {
+ if (FSourceOverlay) {
+ int iView;
+ WINDOWPLACEMENT wp;
+
+ Dbg((*lpFindDoc)(lpszSrc, &doc, TRUE));
+
+ for (iView=0; iView < MAX_VIEWS; iView++) {
+ if ((Views[iView].Doc > -1) &&
+ (Docs[Views[iView].Doc].docType == DOC_WIN) &&
+ (Views[iView].Doc != doc)) {
+ GetWindowPlacement( Views[iView].hwndFrame, &wp );
+ SetWindowPlacement(Views[Docs[doc].FirstView].hwndFrame,
+ &wp);
+ break;
+ }
+ }
+ }
+ return 2;
+ }
+ return -1;
+ }
+ return 0;
+ }
+
+ SrcSetMasked(lpszSrc); // add file to the I don't
+ // want to hear about it list.
+
+ return 0;
+} /* SrcMapSourceFilename() */
+
+
+/*** SrcBackMapSourceFilename
+**
+** Synopsis:
+** int = SrcBackMapSourceFilename(lpszTarget, cbTarget)
+**
+** Entry:
+** lpszTarget - Source buffer to map file from
+** cbTarget - size of source buffer
+**
+** Returns:
+** 0 - No mapping done -- no source file mapped
+** 1 - Mapping done
+**
+** Description:
+** This function will look from a mapping which goes to the
+** file lpszTarget and replace it with the source file. Thus
+** this code does the opposit of SrcMapSourceFilename.
+**
+*/
+
+int PASCAL SrcBackMapSourceFilename(LPSTR lpszTarget, UINT cbTarget)
+{
+ ATOM atomTarget;
+ int i;
+
+ /*
+ * Look for the file name in the atom table. If it can't be found
+ * then there must not be any mapping for this file.
+ */
+
+ atomTarget = FindAtom(lpszTarget);
+
+ if (atomTarget == (ATOM) NULL) {
+ return 0;
+ }
+
+ for (i=0; i<CAtomMapped; i++) {
+ if (RgAtomMappedNames[i].atomTarget == atomTarget) {
+ GetAtomName(RgAtomMappedNames[i].atomSrc, lpszTarget, cbTarget);
+ return 1;
+ }
+ }
+
+ return 0;
+} /* SrcBackMapSourceFilename() */
+
+VOID FAR PASCAL
+SetPTState(
+ PSTATE pstate,
+ TSTATEX tstate
+ )
+/*++
+
+Routine Description:
+
+ Set current process and thread states
+
+Arguments:
+
+ pstate - Supplies new pstate, or -1 to leave it the same
+ tstate - Supplies new tstate, or -1 to leave it the same
+
+Return Value:
+
+ none
+
+--*/
+{
+ if (pstate >= 0) {
+ if (LppdCur != NULL) LppdCur->pstate = pstate;
+ }
+ if (tstate >= 0) {
+ if (LptdCur != NULL) LptdCur->tstate = tstate;
+ }
+ EnableRibbonControls(ERC_ALL, FALSE);
+} /* SetPTState() */
+
+
+
+VOID
+AsyncStop(
+ void
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will send a message to the DM to cause an ASYNC stop
+ on the current thread.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ /*
+ * If the current process is not running then we don't need
+ * to do an ASYNC stop
+ */
+
+ if (!LppdCur) {
+ MessageBeep(MB_OK);
+ CmdLogFmt("Cannot stop the current process\r\n");
+ return;
+ }
+
+ /*
+ * Send down the ASYNC STOP message
+ */
+
+ OSDAsyncStop(LppdCur->hpid, 0);
+
+ return;
+} /* AsyncStop() */
+
+void
+FormatKdParams(
+ LPSTR p,
+ BOOL fIncludeDm
+ )
+{
+ #define append(s,n) p=p+sprintf(p,s,n)
+ #define modalias(m,a) p=p+sprintf(p,"alias=%s#%s",m,a)
+ LPSTR lpsz;
+ int len;
+
+ if (fIncludeDm) {
+ switch (runDebugParams.KdParams.dwPlatform) {
+ case 0:
+ strcpy( p, "DM:DMKDX86.DLL " );
+ break;
+
+ case 1:
+ strcpy( p, "DM:DMKDMIP.DLL " );
+ break;
+
+ case 2:
+ strcpy( p, "DM:DMKDALP.DLL " );
+ break;
+
+ case 3:
+ strcpy( p, "DM:DMKDPPC.DLL " );
+ break;
+ }
+ p += strlen(p);
+ }
+ append( "baudrate=%d ", runDebugParams.KdParams.dwBaudRate );
+ append( "port=%d ", runDebugParams.KdParams.dwPort );
+ append( "cache=%d ", runDebugParams.KdParams.dwCache );
+ append( "initialbp=%d ", runDebugParams.KdParams.fInitialBp );
+ append( "usemodem=%d ", runDebugParams.KdParams.fUseModem );
+ append( "goexit=%d ", runDebugParams.KdParams.fGoExit );
+ if (runDebugParams.KdParams.szCrashDump[0]) {
+ append( "crashdump=%s ", runDebugParams.KdParams.szCrashDump );
+ }
+ len = ModListGetSearchPath( NULL, 0 );
+ if (len) {
+ lpsz = malloc( len );
+ ModListGetSearchPath( lpsz, len );
+ append( "symbolpath=%s ", lpsz );
+ free(lpsz);
+ }
+}
+
+//
+// Root Mapping Routines
+//
+
+/*** RootSetMapped
+**
+** Synopsis:
+** BOOL = RootSetMapped(lsz1, lsz2)
+**
+** Entry:
+** lsz1 - Name of file to be mapped from
+** lsz2 - Name of file to be mapped to
+**
+** Returns:
+** TRUE if mapping was successfully recorded
+**
+** Description:
+** This function will setup a mapping of source root to target root.
+** This will allow for a fast reamapping without haveing to do
+** searches or ask the user a second time.
+**
+*/
+
+BOOL
+RootSetMapped(
+ LSZ lpszSrcRoot,
+ LSZ lpszTargetRoot
+)
+{
+ UINT i;
+ LPSTR p, q;
+ CHAR chpSaved, chqSaved;
+
+ if (lpszSrcRoot == NULL || lpszTargetRoot == NULL ||
+ *lpszSrcRoot == '\0' || *lpszTargetRoot == '\0')
+ return FALSE; // strlen is zero
+
+ if (!((lpszSrcRoot[1] == ':' ||
+ (lpszSrcRoot[0] == '\\' && lpszSrcRoot[1] == '\\')) &&
+ (lpszTargetRoot[1] == ':' ||
+ (lpszTargetRoot[0] == '\\' && lpszTargetRoot[1] == '\\'))
+ )
+ )
+ return FALSE; // ignore non fullpath for now
+
+ p = lpszSrcRoot + strlen(lpszSrcRoot) - 1;
+ q = lpszTargetRoot + strlen(lpszTargetRoot) - 1;
+
+ while (p >= lpszSrcRoot && q >= lpszTargetRoot) {
+ if (*(p--) != *(q--)) {
+ p += 2;
+ q += 2;
+ if (*p == ':') {
+ p++;
+ q++;
+ if (*p == '\\') {
+ p++;
+ q++;
+ }
+ } else if (*p == '\\') {
+ p++;
+ q++;
+ }
+ chpSaved = *p;
+ chqSaved = *q;
+ *p = *q = '\0';
+ for (i=0; i<CMappedRoots; i++) {
+ if (_stricmp(RgMappedRoots[i].lpszSrcRoot, lpszSrcRoot) == 0 &&
+ _stricmp(RgMappedRoots[i].lpszTargetRoot, lpszTargetRoot) == 0)
+ return TRUE; // already there
+ }
+ if (CMappedRoots >= MAX_MAPPED_ROOTS) {
+ memcpy(RgMappedRoots,
+ &(RgMappedRoots[1]),
+ sizeof(struct MRootPair)*--CMappedRoots);
+ }
+
+ if ((RgMappedRoots[CMappedRoots].lpszSrcRoot = _strdup(lpszSrcRoot)) == NULL)
+ return FALSE;
+ if ((RgMappedRoots[CMappedRoots].lpszTargetRoot = _strdup(lpszTargetRoot)) == NULL) {
+ free(RgMappedRoots[CMappedRoots].lpszSrcRoot);
+ return FALSE; // error - out of memory? - skip the mapping
+ }
+
+ RgMappedRoots[CMappedRoots++].dwSrcLen = strlen(lpszSrcRoot);
+ *p = chpSaved;
+ *q = chqSaved;
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+} /* RootSetMapped() */
+
+/*** RootNameIsMapped
+**
+** Synopsis:
+** BOOL = RootNameIsMapped(lpb, lpszDest, cbDest)
+**
+** Entry:
+** lpb - Name of file to try for root mapping
+** lpszDest - Name of file root mapped to
+** cbDest - Size of lpszDest buffer
+**
+** Returns:
+** TRUE if mapping was successfully done
+**
+** Description:
+** This function will try to map the given source in lpb to it's mapped
+** location. If file does exists, it will return TRUE and the new full
+** file path thru lpszDest.
+**
+*/
+
+BOOL
+RootNameIsMapped(
+ LPSTR lpb,
+ LPSTR lpszDest,
+ UINT cbDest
+)
+{
+ struct MRootPair *lpRoot;
+ char rgch[_MAX_PATH];
+ char *p;
+ INT i;
+
+ for (i=(INT)CMappedRoots-1; i >= 0; i--) {
+ lpRoot = &(RgMappedRoots[i]);
+ if (_strnicmp(lpRoot->lpszSrcRoot, lpb, lpRoot->dwSrcLen) == 0) {
+ strcpy(rgch, lpRoot->lpszTargetRoot);
+ p = rgch + strlen(rgch) - 1;
+ if (*p == '\\')
+ *p = 0;
+ if (FindNameOn(lpszDest, cbDest,
+ rgch, lpb+lpRoot->dwSrcLen))
+ return(TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+/*** GetRootNameMappings
+**
+** Synopsis:
+** BOOL = GetRootNameMappings(String, Length)
+**
+** Entry:
+** String - Address of the variable pointing to the multistring
+** Length - Address of Length of the multi-string
+**
+** Returns:
+** TRUE if operation completed successfully
+**
+** Description:
+** This function scans thru all the root mappings and returns
+** all the source and target roots in the form of a multi-string
+**
+*/
+BOOL
+GetRootNameMappings(
+ LPSTR *String,
+ DWORD *Length
+)
+{
+ struct MRootPair *lpRoot = RgMappedRoots;
+ UINT i;
+
+ for (i=0; i<CMappedRoots; lpRoot++, i++) {
+ if (!AddToMultiString(String, Length, lpRoot->lpszSrcRoot))
+ return(FALSE);
+ if (!AddToMultiString(String, Length, lpRoot->lpszTargetRoot))
+ return(FALSE);
+ }
+ return(TRUE);
+}
+
+
+/*** SetRootNameMappings
+**
+** Synopsis:
+** BOOL = SetRootNameMappings(String, Length)
+**
+** Entry:
+** String - Pointer to the multistring
+** Length - Length of the multi-string
+**
+** Returns:
+** TRUE if operation completed successfully
+**
+** Description:
+** This function clears all the current root mappings
+** and reconstruct the root mappings table thru the given
+** multi-string.
+**
+*/
+BOOL
+SetRootNameMappings(
+ LPSTR String,
+ DWORD Length
+)
+{
+ struct MRootPair *lpRoot = RgMappedRoots;
+ DWORD Next = 0;
+ UINT i;
+ LPSTR lpsztmp1, lpsztmp2;
+
+ for (i=0; i<CMappedRoots; lpRoot++, i++) {
+ if (lpRoot->lpszSrcRoot)
+ free(lpRoot->lpszSrcRoot);
+ if (lpRoot->lpszTargetRoot)
+ free(lpRoot->lpszTargetRoot);
+ }
+ CMappedRoots = 0;
+
+ lpRoot = RgMappedRoots;
+ while ((lpsztmp1 = GetNextStringFromMultiString(String, Length, &Next)) &&
+ (lpsztmp2 = GetNextStringFromMultiString(String, Length, &Next))) {
+ lpRoot->dwSrcLen = strlen(lpsztmp1);
+ if ((lpRoot->lpszSrcRoot = _strdup(lpsztmp1)) == NULL)
+ return (FALSE);
+ if ((lpRoot->lpszTargetRoot = _strdup(lpsztmp2)) == NULL) {
+ free(lpRoot->lpszSrcRoot);
+ return (FALSE);
+ }
+
+ lpRoot++;
+ CMappedRoots++;
+
+ if (CMappedRoots >= MAX_MAPPED_ROOTS)
+ return (GetNextStringFromMultiString(String, Length, &Next) == NULL);
+ lpsztmp2 = NULL;
+ }
+ return (lpsztmp1 == NULL);
+}
+
+BOOL
+FAR PASCAL EXPORT DlgFileSearchResolve(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+
+ HDC hdc;
+ int i;
+ int j;
+ int Idx;
+ int LargestString = 0;
+ SIZE Size;
+ HWND hList;
+ LPSTR lpszName;
+ CHAR rgch[128];
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+
+ case WM_INITDIALOG:
+
+ SendDlgItemMessage(hDlg, ID_FSRESOLVE_STRING, WM_SETTEXT,
+ 0, (DWORD)szFSSrcName);
+
+ LoadString(hInst, DLG_ResolveFSCaption, rgch, sizeof(rgch));
+
+ SetWindowText( hDlg, rgch );
+
+ hList = GetDlgItem(hDlg, ID_FSRESOLVE_LIST);
+
+ for (i=0; i < dwMatchCnt; i++) {
+ lpszName = Docs[MatchedList[i]].FileName;
+
+ hdc = GetDC( hList );
+ GetTextExtentPoint(hdc, lpszName, strlen(lpszName), &Size );
+ ReleaseDC( hList, hdc );
+
+ if ( Size.cx > LargestString ) {
+ LargestString = Size.cx;
+ SendMessage(hList,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ SendMessage(hList, LB_ADDSTRING, 0, (LONG)lpszName);
+ }
+
+ SendMessage(hList, LB_SETCURSEL, 0, 0L);
+
+ CheckRadioButton(hDlg, ID_FSRESOLVE_ADDNONE, ID_FSRESOLVE_ADDSOURCE,
+ ID_FSRESOLVE_ADDNONE);
+
+ dwMatchIdx = -1;
+
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+ case ID_FSRESOLVE_USE:
+ Idx = SendDlgItemMessage(hDlg, ID_FSRESOLVE_LIST,
+ LB_GETCURSEL, 0, 0);
+ dwMatchIdx = Idx;
+ Assert(dwMatchIdx < dwMatchCnt);
+ FAddToSearchPath = IsDlgButtonChecked( hDlg, ID_FSRESOLVE_ADDSOURCE );
+ FAddToRootMap = IsDlgButtonChecked(hDlg, ID_FSRESOLVE_ADDROOT);
+ if (FAddToSearchPath || FAddToRootMap) {
+ Assert(FAddToSearchPath != FAddToRootMap);
+ Assert(IsDlgButtonChecked(hDlg, ID_FSRESOLVE_ADDNONE) == FALSE);
+ } else
+ Assert(IsDlgButtonChecked(hDlg, ID_FSRESOLVE_ADDNONE));
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+
+ case IDCANCEL: // none
+ dwMatchIdx = -1;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_FSRESOLVE_HELP) );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
diff --git a/private/windbg/windbg/colors.c b/private/windbg/windbg/colors.c
new file mode 100644
index 000000000..cb5803498
--- /dev/null
+++ b/private/windbg/windbg/colors.c
@@ -0,0 +1,887 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Colors.c
+
+Abstract:
+
+ This module contains the implementation for Windbg's color support.
+
+Author:
+
+ David J. Gilman (davegi) 30-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 01-Sep-1992
+
+Environment:
+
+ CRT, Windows, User Mode
+
+--*/
+
+//
+// Get access to OEM bitmap constants.
+//
+
+#define OEMRESOURCE
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern HWND GetLocalHWND(void);
+extern HWND GetFloatHWND(void);
+extern HWND GetWatchHWND(void);
+extern HWND GetCpuHWND(void);
+extern HWND GetCallsHWND(void);
+
+
+
+
+LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+
+
+//
+// Common dialog IDs
+//
+
+//
+// Helper macros to enable / disable 'Set' buttons.
+//
+
+//
+// VOID DisableSetButtons()
+//
+
+#define DisableSetButtons( ) \
+ { \
+ EnableWindow( \
+ GetDlgItem( hDlg, IDC_PUSH_DEFAULT ), \
+ FALSE \
+ ); \
+ EnableWindow( \
+ GetDlgItem( hDlg, IDC_PUSH_SET_FOREGROUND ), \
+ FALSE \
+ ); \
+ EnableWindow( \
+ GetDlgItem( hDlg, IDC_PUSH_SET_BACKGROUND ), \
+ FALSE \
+ ); \
+ }
+
+//
+// VOID ToggleSetButtons( )
+//
+
+#define ToggleSetButtons( ) \
+ { \
+ EnableWindow( \
+ GetDlgItem( hDlg, IDC_PUSH_DEFAULT ), \
+ ( Selections == 0 ) ? FALSE : TRUE \
+ ); \
+ EnableWindow( \
+ GetDlgItem( hDlg, IDC_PUSH_SET_FOREGROUND ), \
+ ( Selections == 0 ) ? FALSE : TRUE \
+ ); \
+ EnableWindow( \
+ GetDlgItem( hDlg, IDC_PUSH_SET_BACKGROUND ), \
+ ( Selections == 0 ) ? FALSE : TRUE \
+ ); \
+ }
+
+
+//
+// Registered message for hooking CHOOSECOLOR's OK button.
+//
+
+UINT WmColorOk = 0;
+
+//
+// Resource text for "Select All" / "Clear All" button text.
+//
+
+TCHAR SelectAllText[ MAX_PATH ];
+TCHAR ClearAllText[ MAX_PATH ];
+
+//
+// CHOOSECOLOR's dialog hook proc.
+//
+
+BOOL ChooseColorHookProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam);
+
+//
+// Color values used by colorizable strings.
+//
+
+#define UBLACK RGB (000, 000, 000)
+#define DARK_RED RGB (128, 000, 000)
+#define DARK_GREEN RGB (000, 128, 000)
+#define DARK_YELLOW RGB (128, 128, 000)
+#define DARK_BLUE RGB (000, 000, 128)
+#define DARK_MAGENTA RGB (128, 000, 128)
+#define DARK_CYAN RGB (000, 128, 128)
+#define DARK_GRAY RGB (128, 128, 128)
+#define LIGHT_GRAY RGB (192, 192, 192)
+#define LIGHT_RED RGB (255, 000, 000)
+#define LIGHT_GREEN RGB (000, 255, 000)
+#define LIGHT_YELLOW RGB (255, 255, 000)
+#define LIGHT_BLUE RGB (000, 000, 255)
+#define LIGHT_MAGENTA RGB (255, 000, 255)
+#define LIGHT_CYAN RGB (000, 255, 255)
+#define UWHITE RGB (255, 255, 255)
+
+//
+// Colorizable string IDs.
+//
+
+UINT
+StringIds[ ] = {
+
+ IDS_SOURCE_WINDOW,
+ IDS_DUMMY_WINDOW,
+ IDS_WATCH_WINDOW,
+ IDS_LOCALS_WINDOW,
+ IDS_CPU_WINDOW,
+ IDS_DISASSEMBLER_WINDOW,
+ IDS_COMMAND_WINDOW,
+ IDS_FLOAT_WINDOW,
+ IDS_MEMORY_WINDOW,
+ IDS_CALLS_WINDOW,
+ IDS_BREAKPOINT_LINE,
+ IDS_CURRENT_LINE,
+ IDS_CURRENTBREAK_LINE,
+ IDS_UNINSTANTIATEDBREAK,
+ IDS_TAGGED_LINE,
+ IDS_TEXT_SELECTION,
+ IDS_KEYWORD,
+ IDS_IDENTIFIER,
+ IDS_COMMENT,
+ IDS_NUMBER,
+ IDS_REAL,
+ IDS_STRING,
+ IDS_ACTIVEEDIT,
+ IDS_CHANGEHISTORY
+
+};
+
+//
+// Resource text for colorizable strings.
+//
+
+STRINGTEXT
+StringText[ MAX_STRINGS ];
+
+//
+// Default colorizable string colors.
+//
+
+STRINGCOLORS
+DefaultStringColors[ ] = {
+
+//
+// Forground Background
+// --------- ----------
+//
+
+//
+// Windows
+// -------
+//
+
+ UBLACK, UWHITE, // Source
+ UBLACK, UWHITE, // Dummy--DO NOT REMOVE!!GWK
+ UBLACK, UWHITE, // Watch
+ UBLACK, UWHITE, // Locals
+ UBLACK, UWHITE, // Registers
+ UBLACK, UWHITE, // Disassembler
+ UBLACK, UWHITE, // Command
+ UBLACK, UWHITE, // Floating Point Registers
+ UBLACK, UWHITE, // Memory
+ UBLACK, UWHITE, // Calls
+
+//
+// Lines
+// -----
+//
+
+ UWHITE, LIGHT_RED, // Breakpoints
+ UBLACK, LIGHT_YELLOW, // Current
+ UBLACK, LIGHT_GREEN, // Current&Break
+ UBLACK, LIGHT_MAGENTA, // UninstatiatedBreak
+ LIGHT_RED, LIGHT_CYAN, // Tagged
+ UWHITE, UBLACK, // Selection
+
+//
+// Syntax
+// ------
+//
+
+ DARK_MAGENTA, UWHITE, // Keyword
+ UBLACK, UWHITE, // Identifier
+ UBLACK, LIGHT_GRAY, // Comment
+ LIGHT_BLUE, UWHITE, // Number
+ DARK_GRAY, UWHITE, // Real
+ DARK_CYAN, UWHITE, // String
+ DARK_BLUE, UWHITE, // ActiveEdit
+ LIGHT_RED, UWHITE // ChangeHistory
+};
+
+//
+// Colorizable string colors, initialized to DefaultStringColors.
+//
+
+STRINGCOLORS
+StringColors[ ] = {
+
+//
+// Forground Background
+// --------- ----------
+//
+
+//
+// Windows
+// -------
+//
+
+ UBLACK, UWHITE, // Source
+ UBLACK, UWHITE, // Dummy--DO NOT REMOVE!!GWK
+ UBLACK, UWHITE, // Watch
+ UBLACK, UWHITE, // Locals
+ UBLACK, UWHITE, // Registers
+ UBLACK, UWHITE, // Disassembler
+ UBLACK, UWHITE, // Command
+ UBLACK, UWHITE, // Floating Point Registers
+ UBLACK, UWHITE, // Memory
+ UBLACK, UWHITE, // Calls
+
+//
+// Lines
+// -----
+//
+
+ UWHITE, LIGHT_RED, // Breakpoints
+ UBLACK, LIGHT_YELLOW, // Current
+ UBLACK, LIGHT_GREEN, // Current&Break
+ UBLACK, LIGHT_MAGENTA, // UninstatiatedBreak
+ LIGHT_RED, LIGHT_CYAN, // Tagged
+ UWHITE, UBLACK, // Selection
+
+//
+// Syntax
+// ------
+//
+
+ DARK_MAGENTA, UWHITE, // Keyword
+ UBLACK, UWHITE, // Identifier
+ UBLACK, LIGHT_GRAY, // Comment
+ LIGHT_BLUE, UWHITE, // Number
+ DARK_GRAY, UWHITE, // Real
+ DARK_CYAN, UWHITE, // String
+ DARK_BLUE, UWHITE, // ActiveEdit
+ LIGHT_RED, UWHITE // ChangeHistory
+
+};
+
+
+//
+// User defined custom colors.
+//
+
+COLORREF
+CustomColors[ ] = {
+
+ UBLACK,
+ DARK_RED,
+ DARK_GREEN,
+ DARK_YELLOW,
+ DARK_BLUE,
+ DARK_MAGENTA,
+ DARK_CYAN,
+ DARK_GRAY,
+ LIGHT_GRAY,
+ LIGHT_RED,
+ LIGHT_GREEN,
+ LIGHT_YELLOW,
+ LIGHT_BLUE,
+ LIGHT_MAGENTA,
+ LIGHT_CYAN,
+ UWHITE
+};
+
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+Notes:
+
+ Even though the IDC_LIST_ITEMS control is owner draw, the
+ WM_MEASUREITEM is not handled as the default sizes are acceptable.
+
+--*/
+
+
+BOOL ChooseColorHookProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
+{
+ UINT i,j;
+ PDRAWITEMSTRUCT DrawItemStruct;
+ LPCHOOSECOLOR ChooseColor;
+ PTCHAR ButtonText;
+ UINT SelectedStringIds[MAX_STRINGS];
+ HWND hDlgItem;
+
+ static WORD SetColorButtonId;
+ static BOOL ApplyFlag;
+ static HBITMAP hBitmap;
+ static HDC hDCMem;
+ static BITMAP Bitmap;
+ static UINT Selections;
+ static HDC mHdc; //hdc of windbg
+
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+
+ mHdc = GetWindowDC (hwndFrame);
+
+ if ((hDlgItem = GetDlgItem (hDlg,IDC_LIST_ITEMS)) == (HWND)NULL)
+ {
+ return (FALSE);
+ }
+
+ // Initialize the list of items to colorize.
+
+ for ( i = 0; i < (MAX_STRINGS - 1); i++ )
+ {
+ SendMessage (hDlgItem,LB_ADDSTRING,0,( LPARAM ) StringText[i].Text);
+ }
+
+
+ // Initialize the 'selected' (i.e. checkmark) bitmap.
+
+ if ((hBitmap = LoadBitmap( NULL, MAKEINTRESOURCE( OBM_CHECK ))) == (HBITMAP)NULL)
+ {
+ return FALSE;
+ }
+
+
+ // Get the size of the 'selected' (i.e. checkmark) bitmap.
+
+ if ( GetObject( hBitmap, sizeof( BITMAP ), &Bitmap ) == 0 )
+ {
+ return FALSE;
+ }
+
+
+ // Remember that the compatible DC has not been created.
+
+ hDCMem = NULL;
+
+
+ // Default to setting the foreground color.
+ SetColorButtonId = IDC_PUSH_SET_FOREGROUND;
+
+
+ // Default to being able to Select All.
+
+ Selections = 0;
+
+
+ // Disable the 'Set' buttons when there is no selections.
+
+ DisableSetButtons( );
+
+
+ // Default to OK button meaning OK (see IDC_PUSH_SET*).
+
+ ApplyFlag = FALSE;
+
+ return TRUE;
+
+ case WM_DESTROY:
+
+ // Delete the objects needed to draw the 'selected' bitmap.
+
+ ReleaseDC (hwndFrame,mHdc); //release the frame DC
+
+ DeleteDC( hDCMem );
+ DeleteObject( hBitmap );
+
+ RedrawWindow ((HWND)hwndMDIClient,(LPRECT)NULL,(HRGN)NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); // schedule everything for redraw
+
+ return FALSE;
+
+ case WM_COMMAND:
+
+ switch ( LOWORD( wParam ))
+ {
+ case IDWINDBGHELP:
+ case pshHelp:
+
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_COLORDLG_HELP));
+ return TRUE;
+
+ case IDC_PUSH_DEFAULT:
+ // Reinitialize the colors to their default values and
+ // repaint the colorizable strings listbox.
+
+ // Get the IDs for each selected string.
+
+ SendDlgItemMessage(hDlg,IDC_LIST_ITEMS,LB_GETSELITEMS,( WPARAM ) MAX_STRINGS,(LPARAM) SelectedStringIds);
+
+ // For each of the selected strings reset the colors to their default values.
+
+ for ( i = 0; i < Selections; i++ )
+ {
+ if (SelectedStringIds[i] > 0)
+ {
+ j = SelectedStringIds[i] + 1;
+ }
+ else
+ {
+ j = 0;
+ }
+
+
+ StringColors[j].FgndColor = DefaultStringColors[j].FgndColor;
+ StringColors[j].BkgndColor = DefaultStringColors[j].BkgndColor;
+ }
+
+
+ RedrawWindow (GetDlgItem( hDlg, IDC_LIST_ITEMS ),NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW);
+
+ SendMessageNZ( GetCpuHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetLocalHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_CLR_FORECHANGE, 0, 0L);
+
+ SendMessageNZ( GetCpuHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetLocalHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+
+
+ return TRUE;
+
+ case IDC_PUSH_SET_FOREGROUND:
+ case IDC_PUSH_SET_BACKGROUND:
+
+ // Simulate a push of the OK button so that the current
+ // CHOOSECOLOR structure can be grabbed.
+
+ ApplyFlag = TRUE;
+
+ SetColorButtonId = LOWORD( wParam );
+
+ SendMessage(hDlg,WM_COMMAND,IDOK,0L);
+
+ return TRUE;
+
+ case IDC_PUSH_SELECT_ALL:
+
+ // Toggle the Select All / Clear All state.
+
+ if ( Selections == (MAX_STRINGS-1) )
+ {
+ Selections = 0;
+ ButtonText = SelectAllText;
+ }
+ else
+ {
+ Selections = (MAX_STRINGS-1);
+ ButtonText = ClearAllText;
+ }
+
+ // Select / deselect all of the colorizable strings.
+
+ SendDlgItemMessage (hDlg,IDC_LIST_ITEMS,LB_SETSEL,(WPARAM) Selections,(LPARAM) -1);
+
+ // Set the appropriate text for the "Select All / Clear All" button.
+
+ SendDlgItemMessage (hDlg,IDC_PUSH_SELECT_ALL,WM_SETTEXT,0,(LPARAM) ButtonText);
+
+ // Disable the 'Set' buttons when there is no selections, otherwise enable them.
+
+ ToggleSetButtons( );
+
+ return TRUE;
+
+ }
+ break;
+
+ case WM_DRAWITEM:
+
+ DrawItemStruct = (PDRAWITEMSTRUCT) lParam;
+
+ // If the message is intended for the colorizable strings list box, draw it.
+
+ if (DrawItemStruct->CtlID == IDC_LIST_ITEMS)
+ {
+ // Treat drawing the entire item and drawing a selected item the same.
+
+ if (DrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT))
+ {
+ // Set the appropriate foreground and background colors for this item.
+
+
+ if (DrawItemStruct->itemID > 0)
+ {
+ i=DrawItemStruct->itemID + 1;
+ }
+ else
+ {
+ i=0;
+ }
+
+ SetTextColor (DrawItemStruct->hDC, StringColors[i].FgndColor);
+
+ SetBkColor (DrawItemStruct->hDC, StringColors[i].BkgndColor);
+
+ // Draw the text, leaving room for the 'selected' bitmap.
+
+ ExtTextOut (DrawItemStruct->hDC,
+ (int)(DrawItemStruct->rcItem.left + Bitmap.bmWidth * 1.5),
+ DrawItemStruct->rcItem.top,
+ ETO_OPAQUE,
+ &(DrawItemStruct->rcItem),
+ StringText[DrawItemStruct->itemID].Text,
+ StringText[DrawItemStruct->itemID].Length,
+ NULL);
+
+
+ // If the item is selected draw the selection bitmap.
+
+ if (DrawItemStruct->itemState & ODS_SELECTED)
+ {
+
+ // Create the compatible DC if it was never created.
+
+ if (hDCMem == NULL)
+ {
+ hDCMem = CreateCompatibleDC (DrawItemStruct->hDC);
+
+ // Couldn't create the memory DC.
+
+ if (hDCMem == NULL)
+ {
+ return FALSE;
+ }
+
+ // Couldn't select the bitmap into the DC.
+
+ if (SelectObject (hDCMem, hBitmap) == NULL)
+ {
+ return FALSE;
+ }
+ }
+
+ // Blt the 'selected' bitmap to the left of the item.
+ // Always use black unless the background is black,
+ // then use white.
+
+ SetTextColor (DrawItemStruct->hDC,
+ (StringColors[ i ].BkgndColor == UBLACK)
+ ? UWHITE
+ : UBLACK);
+
+ if (BitBlt (DrawItemStruct->hDC,
+ DrawItemStruct->rcItem.left,
+ DrawItemStruct->rcItem.top,
+ DrawItemStruct->rcItem.right - DrawItemStruct->rcItem.left,
+ DrawItemStruct->rcItem.bottom - DrawItemStruct->rcItem.top,
+ hDCMem,
+ 0,
+ 0,
+ SRCCOPY) == FALSE )
+ {
+ return FALSE;
+ }
+ }
+
+ // If the item is being selected or deselected.
+
+ if (DrawItemStruct->itemAction & ODA_SELECT)
+ {
+ // If the item is being selected...
+
+ if (DrawItemStruct->itemState & ODS_SELECTED)
+ {
+ // One more item selected.
+
+ Selections++;
+
+ // If the last item was just selected, set the
+ // 'Clear All' button text.
+
+ if (Selections == (MAX_STRINGS - 1))
+ {
+ ButtonText = ClearAllText;
+
+ SendDlgItemMessage (hDlg,
+ IDC_PUSH_SELECT_ALL,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) ButtonText);
+ }
+
+ }
+ else
+ {
+ // If the item is being deselected...
+
+ // If the last item was just de-selected, set the
+ // 'Select All' button text.
+
+ // Check for MAX_STRINGS before the decrement so
+ // that only transitions cause the WM_SETTEXT.
+
+ if (Selections == (MAX_STRINGS - 1))
+ {
+ ButtonText = SelectAllText;
+
+ SendDlgItemMessage (hDlg,
+ IDC_PUSH_SELECT_ALL,
+ WM_SETTEXT,
+ 0,
+ (LPARAM) ButtonText);
+ }
+
+ // One less item selected.
+
+ Selections--;
+ }
+
+ // Disable the 'Set' buttons when there is no
+ // selections, otherwise enable them.
+
+ ToggleSetButtons( );
+ }
+ }
+
+ // If the item has the focus, draw the focus rectangle.
+
+ if (DrawItemStruct->itemAction & ODA_FOCUS)
+ {
+ DrawFocusRect (DrawItemStruct->hDC,&(DrawItemStruct->rcItem));
+ }
+
+ // Set the appropriate text for the "Select All / Clear All" button.
+
+ return TRUE;
+ }
+ break;
+
+ default:
+
+ // Handle the registered OK button message if it was
+ // generated due to one of the 'Set Foreground / Set Background'
+ // buttons being pressed.
+
+ if ((message == WmColorOk) && ApplyFlag )
+ {
+ // Reset the flag so a real press of OK will work.
+
+ ApplyFlag = FALSE;
+
+ ChooseColor = (LPCHOOSECOLOR) lParam;
+
+ // Get the IDs for each selected string.
+
+ SendDlgItemMessage (hDlg,
+ IDC_LIST_ITEMS,
+ LB_GETSELITEMS,
+ (WPARAM) MAX_STRINGS,
+ (LPARAM) SelectedStringIds);
+
+ // For each of the selected strings set the appropriate color
+ // based on the foreground / background radio buttons.
+
+ for (i = 0; i < Selections; i++)
+ {
+ if (SelectedStringIds[i] > 0)
+ {
+ j = SelectedStringIds[i] + 1;
+ }
+ else
+ {
+ j = 0;
+ }
+
+
+ if (SetColorButtonId == IDC_PUSH_SET_FOREGROUND)
+ {
+ StringColors[j].FgndColor = GetNearestColor (mHdc, ChooseColor->rgbResult);
+ }
+ else
+ {
+ StringColors[j].BkgndColor = GetNearestColor (mHdc, ChooseColor->rgbResult);
+ }
+
+ }
+
+ // Repaint the colorizable strings listbox.
+
+
+
+
+
+ RedrawWindow (GetDlgItem( hDlg, IDC_LIST_ITEMS ),
+ NULL,
+ NULL,
+ RDW_INVALIDATE | RDW_UPDATENOW);
+
+ SendMessageNZ( GetCpuHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetLocalHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_CLR_FORECHANGE, 0, 0L);
+
+ SendMessageNZ( GetCpuHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetLocalHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+
+BOOL SelectColor(HWND hWnd)
+{
+ UINT i;
+ INT Length;
+ CHOOSECOLOR Cc;
+ STRINGCOLORS TmpStringColors[MAX_STRINGS];
+ COLORREF TmpCustomColors[MAX_STRINGS];
+
+ // If WmColorOK is zero then the message has never been registered.
+ // Use this as a trigger for performing one time initialization.
+
+ if (WmColorOk == 0)
+ {
+ if ((WmColorOk = RegisterWindowMessage (COLOROKSTRING)) == 0)
+ {
+ return(FALSE); // Couldn't register the message
+ }
+
+ // Load the text for the colorizable strings.
+
+ for (i = 0; i < MAX_STRINGS; i++)
+ {
+ if ((StringText[i].Length = LoadString (hInst,
+ StringIds[i],
+ StringText[i].Text,
+ sizeof (StringText[i].Text))) == 0)
+ {
+ return(FALSE); // Couldn't load the string resource.
+ }
+
+ }
+
+ for (i = 1; i < (MAX_STRINGS - 1); i++)
+ {
+ StringText[i].Length = StringText[i+1].Length;
+ strcpy (StringText[i].Text, StringText[i+1].Text);
+
+ //memcpy (&StringText[i], &StringText[i+1], sizeof(StringText));
+ }
+
+
+
+
+ // Load the "Select All" / "Clear All" button text.
+
+ if ((Length = LoadString (hInst,
+ IDS_SELECT_ALL,
+ SelectAllText,
+ sizeof (SelectAllText))) == 0)
+ {
+ return(FALSE); // Couldn't load the string resource.
+ }
+
+
+ if ((Length = LoadString (hInst,
+ IDS_CLEAR_ALL,
+ ClearAllText,
+ sizeof (ClearAllText))) == 0)
+ {
+ return(FALSE); // Couldn't load the string resource.
+ }
+
+ }
+
+ // Make copies of the volatile data in case the user presses Cancel.
+
+ memcpy( TmpStringColors, StringColors, sizeof( TmpStringColors ));
+ memcpy( TmpCustomColors, CustomColors, sizeof( TmpCustomColors ));
+
+ // Initialize the CHOOSECOLOR structure.
+
+ Cc.lStructSize = sizeof( CHOOSECOLOR );
+ Cc.hwndOwner = hWnd;
+ Cc.hInstance = NULL;
+ Cc.rgbResult = RGB (64, 188, 188);
+ Cc.lpCustColors = CustomColors;
+ Cc.Flags = CC_ENABLEHOOK
+ | CC_ENABLETEMPLATE
+ | CC_FULLOPEN
+ | CC_RGBINIT
+ | CC_SHOWHELP;
+ Cc.lCustData = 0;
+ Cc.lpfnHook = ChooseColorHookProc;
+ Cc.lpTemplateName = MAKEINTRESOURCE( DLG_CHOOSECOLOR );
+
+ // Let the user choose colors.
+
+ if (ChooseColor (&Cc))
+ {
+ // The user pressed OK.
+
+ return TRUE;
+ }
+ else
+ {
+ // The user pressed Cancel or closed the dialog.
+ // Restore the user's original string and custom colors.
+
+ memcpy( StringColors, TmpStringColors, sizeof( StringColors ));
+ memcpy( CustomColors, TmpCustomColors, sizeof( CustomColors ));
+
+ SendMessageNZ( GetCpuHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetLocalHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_CLR_FORECHANGE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_CLR_FORECHANGE, 0, 0L);
+
+ SendMessageNZ( GetCpuHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetLocalHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_CLR_BACKCHANGE, 0, 0L);
+
+ return FALSE;
+ }
+}
diff --git a/private/windbg/windbg/confirm.c b/private/windbg/windbg/confirm.c
new file mode 100644
index 000000000..8028af6da
--- /dev/null
+++ b/private/windbg/windbg/confirm.c
@@ -0,0 +1,143 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ confirm.c
+
+Abstract:
+
+ This file contains the code for dealing with the dialog box used to
+ confirm that a replacement is to be preformed.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/*** DlgConfirm
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+/****************************************************************************
+
+ FUNCTION: DlgConfirm(HWND, unsigned, WORD, LONG)
+
+ PURPOSE: Processes messages for "CONFIRM" dialog box
+ (When changing text occurences)
+
+ MESSAGES:
+
+ WM_INITDIALOG - Initialize dialog box
+ WM_COMMAND- Input received
+
+****************************************************************************/
+
+BOOL FAR PASCAL EXPORT DlgConfirm(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ switch (message) {
+
+ case WM_INITDIALOG:
+ SetFocus(GetDlgItem(hDlg, ID_CONFIRM_REPLACE));
+ break;
+
+ case WM_ACTIVATE :
+
+ if ((wParam != 0) &&
+#ifdef WIN32
+ ((HWND) lParam == hwndFrame) &&
+#else
+ (LOWORD(lParam) == hwndFrame) &&
+#endif
+ (!frMem.firstConfirmInvoc && hwndActiveEdit)) {
+
+ //Disable Replace and Replace all buttons
+
+ EnableWindow(GetDlgItem(hDlg, ID_CONFIRM_REPLACE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_CONFIRM_REPLACEALL), FALSE);
+ SetFocus(GetDlgItem(hDlg, ID_CONFIRM_FINDNEXT));
+
+ //Set search start to current position
+
+ frMem.leftCol = frMem.rightCol = Views[curView].X;
+ frMem.line = Views[curView].Y;
+
+ //Set search stop limit to the current position
+
+ SetStopLimit();
+ }
+ frMem.firstConfirmInvoc = FALSE;
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+
+ case ID_CONFIRM_REPLACEALL :
+
+ frMem.replaceAll = TRUE;
+ ReplaceAll();
+ frMem.replaceAll = FALSE;
+ frMem.exitModelessReplace = TRUE;
+ return TRUE;
+
+ case IDCANCEL:
+ frMem.exitModelessReplace = TRUE;
+ return TRUE;
+
+ case ID_CONFIRM_FINDNEXT:
+ //Disable Replace and Replace all buttons
+ EnableWindow(GetDlgItem(hDlg, ID_CONFIRM_REPLACE), TRUE);
+ EnableWindow(GetDlgItem(hDlg, ID_CONFIRM_REPLACEALL), TRUE);
+
+ frMem.exitModelessReplace = (!FindNext(frMem.line, frMem.rightCol, FALSE, TRUE, FALSE)
+ || frMem.allFileDone
+ || frMem.hadError);
+ return TRUE;
+
+ case ID_CONFIRM_REPLACE:
+
+ ReplaceOne();
+ InvalidateLines(curView, frMem.line, frMem.line, FALSE);
+ frMem.exitModelessReplace = (!FindNext(frMem.line, frMem.rightCol, FALSE, TRUE, FALSE)
+ || frMem.allFileDone
+ || frMem.hadError);
+
+ //Replace "Cancel" pushbutton with "Done"
+
+ Dbg(LoadString(hInst, SYS_Done, szTmp, sizeof(szTmp)));
+ SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPSTR)szTmp);
+ return TRUE;
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_CONFIRM_HELP));
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ frMem.hDlgConfirmWnd = NULL; //Must be here to void reentrancy prob.
+ FlushKeyboard();
+ break;
+ }
+
+ return (FALSE);
+}
+
diff --git a/private/windbg/windbg/cp.c b/private/windbg/windbg/cp.c
new file mode 100644
index 000000000..424a474f3
--- /dev/null
+++ b/private/windbg/windbg/cp.c
@@ -0,0 +1,1162 @@
+/*** cp.c -- Command Parsing Subsystem API
+
+
+Copyright <C> 1990, Microsoft Corporation
+
+Purpose:
+
+
+*************************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern EI Ei;
+#define Lpei (&Ei)
+#include <malloc.h>
+#include <string.h>
+
+#define SPACE (' ')
+//#define TAB (0xf)
+#define NEWCMDDELIMITER (';')
+#define OPENPAREN ('(')
+#define CLOSEPAREN (')')
+#define OPENCURLY ('{')
+#define CLOSECURLY ('}')
+#define OPENSQUARE ('[')
+#define CLOSESQUARE (']')
+#define DOUBLEQUOTE ('"')
+#define BACKSLASH ('\\')
+#define MAXNESTING (50)
+
+#define MAXQUOTE (5)
+static char rgchOpenQuote[MAXQUOTE] = {'\"', '\'', '(', '{', '['};
+static char rgchCloseQuote[MAXQUOTE] = {'\"', '\'', ')', '}', ']'};
+static char rgchfQuoted[MAXQUOTE];
+
+static char rgchDelim[] = { ' ', '\t', ',' };
+#define MAXDELIM (sizeof(rgchDelim) / sizeof(rgchDelim[0]))
+
+extern LPSHF Lpshf;
+
+
+/*** CPszToken - Get token from string and terminate it with '\0'
+
+Purpose: parse string given static token and delimiter tables This
+ function uses a stack based method to determe the level of
+ open and closing quote pairs.
+
+Input: szSrc - command line entered by user
+
+Output: we modify szSrc to null terminate the token currently pointed to
+
+ Returns: pointer to last char in token + 1
+ null if error
+
+Exceptions:
+
+Notes:
+
+
+*************************************************************************/
+char FAR * FAR PASCAL
+CPszToken (
+ char FAR * szSrc,
+ char FAR * szUserDelim
+)
+{
+ int rgiStack[MAXNESTING];
+ int iSP = 0;
+ int fCharType;
+ int iQuoteIndex;
+ int fDone = 0;
+
+ Assert( szSrc != NULL );
+
+ szSrc = CPAdvance(szSrc, szUserDelim);
+
+ while ( !fDone && *szSrc ) {
+
+ fCharType = CPQueryChar ( szSrc, szUserDelim );
+ if ( fCharType == CPISOPENQUOTE ) {
+
+ iQuoteIndex = CPQueryQuoteIndex ( szSrc );
+ rgiStack[iSP++] = iQuoteIndex;
+ }
+ else if ( fCharType == CPISCLOSEQUOTE ) {
+ if ( iSP && *szSrc == rgchCloseQuote[rgiStack[iSP - 1]] ) {
+ iSP--;
+ }
+ else {
+ fDone = 1;
+ szSrc = NULL;
+ }
+ }
+ else if ( fCharType == CPISOPENANDCLOSEQUOTE ) {
+ if ( iSP && rgiStack[iSP - 1] == (iQuoteIndex = CPQueryQuoteIndex ( szSrc ) ) ) {
+ if ( iSP && *szSrc == rgchCloseQuote[rgiStack[iSP - 1]]) {
+ iSP--;
+ }
+ else {
+ fDone = 1;
+ szSrc = NULL;
+ }
+ }
+ else {
+ iQuoteIndex = CPQueryQuoteIndex ( szSrc );
+ rgiStack[iSP++] = iQuoteIndex;
+ }
+ }
+ else if ( fCharType == CPISDELIM ) {
+ if ( !iSP ) {
+ fDone = 1;
+ *szSrc = 0;
+ }
+ }
+ if ( szSrc ) {
+ szSrc++;
+ }
+ }
+ if ( szSrc ) {
+ if (*szSrc == '\0') {
+ szSrc == NULL;
+ } else {
+ //*(szSrc - 1) = '\0';
+ szSrc = CPAdvance(szSrc, "");
+ }
+ }
+
+ return szSrc;
+}
+
+
+int FAR PASCAL
+CPCopyString(
+ LPSTR * lplps,
+ LPSTR lpT,
+ char chEscape,
+ BOOL fQuote
+ )
+/*++
+
+Routine Description:
+
+ Scan and copy an optionally quoted C-style string. If the first character is
+ a quote, a matching quote will terminate the string, otherwise the scanning will
+ stop at the first whitespace encountered. The target string will be null
+ terminated if any characters are copied.
+
+Arguments:
+
+ lplps - Supplies a pointer to a pointer to the source string
+ lpt - Supplies a pointer to the target string
+ chEscape - Supplies the escape character (typically '\\')
+ fQuote - Supplies a flag indicating whether the first character is a quote
+
+Return Value:
+
+ The number of characters copied into lpt[]. If an error occurs, -1 is returned.
+
+--*/
+{
+ LPSTR lps = *lplps;
+ LPSTR lpt = lpT;
+ int i;
+ int n;
+ int err = 0;
+ char cQuote;
+
+ if (fQuote) {
+ if (*lps) cQuote = *lps++;
+ }
+
+ while (!err) {
+
+ if (*lps == 0)
+ {
+ if (fQuote) err = 1;
+ else *lpt = '\0';
+ break;
+ }
+ else if (fQuote && *lps == cQuote)
+ {
+ *lpt = '\0';
+ // eat the quote
+ lps++;
+ break;
+ }
+ else if (!fQuote && (!*lps || *lps == ' ' || *lps == '\t' || *lps == '\r' || *lps == '\n'))
+ {
+ *lpt = '\0';
+ break;
+ }
+
+ else if (*lps != chEscape)
+ {
+ *lpt++ = *lps++;
+ }
+ else
+ {
+ switch (*++lps) {
+ case 0:
+ err = 1;
+ --lps;
+ break;
+
+ default: // any char - usually escape or quote
+ *lpt++ = *lps;
+ break;
+
+ case 'b': // backspace
+ *lpt++ = '\b';
+ break;
+
+ case 'f': // formfeed
+ *lpt++ = '\f';
+ break;
+
+ case 'n': // newline
+ *lpt++ = '\n';
+ break;
+
+ case 'r': // return
+ *lpt++ = '\r';
+ break;
+
+ case 's': // space
+ *lpt++ = ' ';
+ break;
+
+ case 't': // tab
+ *lpt++ = '\t';
+ break;
+
+ case '0': // octal escape
+ for (n = 0, i = 0; i < 3; i++) {
+ ++lps;
+ if (*lps < '0' || *lps > '7') {
+ --lps;
+ break;
+ }
+ n = (n<<3) + *lps - '0';
+ }
+ *lpt++ = (UCHAR)(n & 0xff);
+ break;
+ }
+ lps++; // skip char from switch
+ }
+
+ } // while
+
+ if (err) {
+ return -1;
+ } else {
+ *lplps = lps;
+ return lpt - lpT;
+ }
+}
+
+
+int FAR PASCAL
+CPCopyToken(
+ LPSTR * lplps,
+ LPSTR lpt
+ )
+/*++
+
+Routine Description:
+
+ Copy a whitespace delimited token into lpt[]. Lpt[] is not modified
+ if there is no token to copy. If a token is copied, it is null terminated.
+
+Arguments:
+
+ lplps - Supplies a pointer to a pointer to a string of characters
+ lpt - Supplies a pointer to the string to receive the token
+
+Return Value:
+
+ The number of characters copied into lpt[]. If return value is 0,
+ lpt[] is unmodified. The pointer pointed to by lplps is modified to
+ point to the character where scanning stopped; either the whitespace
+ after the token or the null at the end of the string.
+
+--*/
+{
+ LPSTR lps = *lplps;
+ int cc = 0;
+ // DON'T modify lpt[] if there is no token!!
+ while (*lps && (*lps == ' ' || *lps == '\t' || *lps == '\r' || *lps == '\n')) lps++;
+ while (*lps && *lps != ' ' && *lps != '\t' && *lps != '\r' && *lps != '\n') {
+ *lpt++ = *lps++;
+ *lpt = 0;
+ cc++;
+ }
+ *lplps = lps; // points to separator or 0
+ return cc;
+}
+
+
+/*** CPQueryChar - Check the delimiter and Quote table for given char
+
+Purpose: Given a character return whether or not it is a character in our
+ delimiter table or our Quoting table
+
+Input: szSrc - command line entered by user
+
+Output:
+
+ Returns:
+
+Exceptions:
+
+Notes:
+
+
+*************************************************************************/
+int FAR PASCAL
+CPQueryChar (
+ char FAR * szSrc,
+ char FAR * szUserDelim
+ )
+{
+
+ int i, nUserDelim;
+
+ Assert( szSrc != NULL );
+ nUserDelim = _fstrlen( szUserDelim );
+ for ( i = 0; i < MAXQUOTE; i++ ) {
+ if (*szSrc == rgchOpenQuote[i] && *szSrc == rgchCloseQuote[i] ) {
+ return CPISOPENANDCLOSEQUOTE;
+ }
+ else if (*szSrc == rgchOpenQuote[i] ) {
+ return CPISOPENQUOTE;
+ }
+ else if ( *szSrc == rgchCloseQuote[i] ) {
+ return CPISCLOSEQUOTE;
+ }
+ }
+
+ for ( i = 0; i < MAXDELIM; i++ ) {
+ if ( *szSrc == rgchDelim[i] ) {
+ return CPISDELIM;
+ }
+ }
+
+ for ( i = 0; i <= nUserDelim; i++ ) {
+ if ( *szSrc == szUserDelim[i] ) {
+ return CPISDELIM;
+ }
+ }
+ return CPNOERROR;
+}
+
+/*** CPQueryQuoteIndex - Given a Character return the index
+
+Purpose: Given a character we must be able to get the index in the quote table
+ for the character
+
+Input: szSrc - command line entered by user
+
+Output:
+
+ Returns:
+
+Exceptions:
+
+Notes:
+
+
+*************************************************************************/
+int FAR PASCAL
+CPQueryQuoteIndex(
+ char FAR * szSrc
+ )
+{
+
+ int i;
+
+ Assert( szSrc != NULL );
+ for ( i = 0; i < MAXQUOTE; i++ ) {
+ if (*szSrc == rgchOpenQuote[i] ) {
+ return i;
+ }
+ }
+ return CPNOTINQUOTETABLE;
+}
+
+ /*** CPAdvance - Advance over all leading delimiters
+
+Purpose: Given a string return a pointer to the next non-delimiter character
+
+Input: szSrc - command line entered by user
+
+Output:
+
+ Returns: pointer to the next non-delimiter character in szSrc
+
+Exceptions:
+
+Notes:
+
+
+*************************************************************************/
+char FAR * FAR PASCAL
+CPAdvance (
+ char FAR * szSrc,
+ char FAR * szUserDelim )
+{
+
+ while ( *szSrc && CPQueryChar ( szSrc, szUserDelim ) == CPISDELIM ) {
+ szSrc++;
+ }
+ return szSrc;
+}
+
+/*** CPGetCastNbr
+*
+* Purpose: To convert an expression into a number of a specific type
+*
+* Input:
+* szExpr - The expression to evaluate
+* type - The type to which the value should be cast
+*
+* Output:
+* pValue - The numeric value is stuffed into pValue
+* szErrMsg- If this is non-null, an error message string is stuffed here
+*
+* Returns The error message number
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+int FAR PASCAL
+CPGetCastNbr(
+ char FAR * szExpr,
+ USHORT type,
+ int Radix,
+ int fCase,
+ PCXF pCxf,
+ char FAR * pValue,
+ char FAR * szErrMsg
+ )
+{
+ HTM hTM = (HTM)NULL;
+ HTI hTI = (HTI)NULL;
+ PTI pTI = NULL;
+ long vResult = 0;
+ RI RIT;
+ EESTATUS Err;
+ UINT strIndex;
+
+ // initialize some stuff
+ Err = EENOERROR;
+ if (szErrMsg) {
+ *szErrMsg = '\0';
+ }
+
+ memset( &RIT, 0, sizeof(RI) );
+ RIT.fValue = TRUE;
+ RIT.Type = type;
+ RIT.fSzBytes = TRUE;
+
+ // parse the expression
+
+ Err = EEParse(szExpr, Radix, fCase, &hTM, &strIndex);
+ if(!Err) Err = EEBindTM(&hTM, SHpCXTFrompCXF(pCxf), TRUE, FALSE, FALSE);
+ if(!Err) Err = EEvaluateTM(&hTM, SHpFrameFrompCXF(pCxf), EEHORIZONTAL);
+ if(!Err) Err = EEInfoFromTM(&hTM, &RIT, &hTI);
+
+
+ if (!Err) {
+ // lock down the TI
+ if( !hTI || !(pTI = (PTI) MMLpvLockMb (hTI)) ) {
+
+ Err = NOROOM;
+
+ } else {
+
+ // now see if we have the value
+ if( pTI->fResponse.fValue && pTI->fResponse.Type == RIT.Type ) {
+ _fmemcpy (pValue, (char FAR *) pTI->Value, (short) pTI->cbValue);
+ } else {
+ Err = BADTYPECAST;
+ }
+ MMbUnlockMb(hTI);
+ }
+
+ // get the error
+ if( szErrMsg ) {
+ CVMessage(ERRORMSG, Err, MSGSTRING, szErrMsg);
+ }
+
+ // get the error
+
+ } else {
+
+ if ( szErrMsg ) {
+ CVExprErr(Err, MSGSTRING, &hTM, szErrMsg);
+ } else {
+ CVExprErr ( Err, MSGGERRSTR, &hTM, NULL );
+ Err = GEXPRERR;
+ }
+
+ }
+ // free any handles
+ if(hTM) {
+ EEFreeTM(&hTM);
+ }
+
+ if( hTI ) {
+ EEFreeTI(&hTI);
+ }
+
+ // return the error code
+
+ return(Err);
+}
+
+
+
+/*** CPGetNbr
+*
+* Purpose: To convert and expression into a number
+*
+* Input:
+* szExpr - The expression to evaluate
+*
+* Output:
+* pErr - The Expression Evaluators error msg nbr.
+*
+* Returns The numeric value of the expression. Or zero. If the result
+* is zero, check the Err value to determine if an error occured.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+long FAR PASCAL
+CPGetNbr(
+ char FAR * szExpr,
+ int Radix,
+ int fCase,
+ PCXF pCxf,
+ char FAR * szErrMsg,
+ int FAR * pErr )
+{
+ long Value;
+
+ *pErr = CPGetCastNbr(szExpr,
+ 0x22,
+ Radix,
+ fCase,
+ pCxf,
+ (char FAR *)&Value,
+ szErrMsg);
+
+ return (*pErr == EENOERROR) ? Value : 0;
+}
+
+
+int FAR PASCAL
+CPGetFPNbr(
+ LPSTR lpExpr,
+ int cBits,
+ int nRadix,
+ int fCase,
+ PCXF pCxf,
+ LPSTR lpBuf,
+ LPSTR lpErr
+ )
+/*++
+
+Routine Description:
+
+ Get a floating point number. This is a front end for CPGetCastNbr
+ which maps a bitcount into an OMF type.
+
+Arguments:
+
+ lpExpr - Supplies expr to evaluate
+ cBits - Supplies size in bits of result type
+ nRadix - Supplies default radix for integer exprs
+ fCase - Supplies case sensitivity flag
+ pCxf - Supplies context/frame for EE
+ lpBuf - Return result in buffer this points to
+ lpErr - Return error string from EE
+
+Return Value:
+
+ EEERROR code
+
+--*/
+{
+ USHORT omftype;
+
+ switch (cBits) {
+ case 32:
+ omftype = T_REAL32;
+ break;
+
+ case 64:
+ omftype = T_REAL64;
+ break;
+
+ case 80:
+ omftype = T_REAL80;
+ break;
+
+ default:
+ return EECATASTROPHIC;
+ }
+
+ return CPGetCastNbr(
+ lpExpr,
+ omftype,
+ nRadix,
+ fCase,
+ pCxf,
+ lpBuf,
+ lpErr);
+}
+
+
+/*** CPGetInt
+**
+*/
+
+long FAR PASCAL
+CPGetInt(
+ char FAR * szExpr,
+ int FAR * pErr,
+ int FAR * cLength)
+{
+ long lVal = 0;
+ int cb = 0;
+
+ /*
+ ** Clear out the error field first
+ */
+
+ *pErr = FALSE;
+
+ /*
+ ** First check for a null string. Return 0 and an error
+ */
+
+ if (*szExpr == 0) {
+ *pErr = TRUE;
+ return 0;
+ }
+
+ /*
+ ** Check that first character is numeric
+ */
+
+ if ((*szExpr < '0') || ('9' < *szExpr)) {
+ *pErr = TRUE;
+ return 0;
+ }
+
+ /*
+ **
+ */
+
+ while (('0' <= *szExpr) && (*szExpr <= '9')) {
+ lVal = lVal*10 + *szExpr - '0';
+ szExpr++;
+ cb += 1;
+ }
+
+ /*
+ **
+ */
+
+ *cLength = cb;
+ return lVal;
+} /* CPGetInt() */
+
+int FAR PASCAL
+CPGetAddress(
+ LPSTR lpExprOrig,
+ int FAR * lpcch,
+ ADDR FAR * lpAddr,
+ EERADIX radix,
+ CXF FAR * pcxf,
+ BOOL fCase,
+ BOOL fSpecial
+ )
+/*++
+
+Routine Description:
+
+ This routine will attempt to take the first whitespace delimited
+ portion of the expression string and convert it into an address.
+ If the routine is not successful then it will give a reason error
+ code.
+
+
+Arguments:
+
+ lpExpr - string which has the address in it
+
+ lpcch - pointer to return location for count of characters used
+
+ lpaddr - pointer to address structure to return value in
+
+ radix - radix to use for evaluation
+
+ pcxf - pointer to cxf structure
+
+ fCase - TRUE if case sensitive parse
+
+ fSpecial -
+
+Return Value:
+
+
+--*/
+{
+ HTM hTm = (HTM) NULL;
+ HTI hTi = (HTI) NULL;
+ PTI pTi = NULL;
+ RI ri;
+ EESTATUS eeErr = EENOERROR;
+ UINT strIndex;
+ int cch = 0;
+ LPSTR lpExpr;
+ LPSTR lpsz0;
+ LPSTR lpch;
+ LPSTR p;
+ HEXE hexe;
+ CHAR szFullContext[512];
+ LPSTR ExeName;
+ SHE She;
+ LPDEBUGDATA DebugData;
+ BOOL fUse;
+ BOOL fLoad;
+ CHAR fname[MAX_PATH];
+
+
+ /*
+ ** Setup Initialization
+ */
+
+ memset( &ri, 0, sizeof(RI) );
+ memset( lpAddr, 0, sizeof(*lpAddr));
+ ri.fAddr = TRUE;
+
+ /*
+ ** Skip over leading white space and then find the next white space
+ */
+
+ lpsz0 = lpExpr = _strdup(lpExprOrig);
+
+ lpExpr = CPSkipWhitespace(lpExpr);
+ lpch = CPszToken(lpExpr, "");
+
+ if (!*lpExpr || !lpch) {
+
+ eeErr = EEGENERAL;
+
+ } else {
+
+ //
+ // get the length of the expr
+ //
+ cch = lpch - lpExpr;
+
+ //
+ // check for a context override
+ //
+ p = strchr( lpExpr, '}' );
+ if (!p) {
+ p = strchr( lpExpr, '!' );
+ }
+
+ if (!p) {
+
+ //
+ // Parse the expression
+ //
+ eeErr = EEParse(lpExpr, radix, fCase, &hTm, &strIndex);
+ if (eeErr == EENOERROR) {
+ eeErr = EEBindTM(&hTm,
+ SHpCXTFrompCXF(pcxf),
+ TRUE,
+ FALSE,
+ fSpecial
+ );
+ }
+ if (eeErr == EENOERROR) {
+ eeErr = EEvaluateTM(&hTm, SHpFrameFrompCXF(pcxf), EEHORIZONTAL);
+ }
+ if (eeErr == EENOERROR) {
+ eeErr = EEInfoFromTM(&hTm, &ri, &hTi);
+ }
+
+ } else {
+
+ //
+ // first try the context passed in
+ //
+ eeErr = EEParse(lpExpr, radix, fCase, &hTm, &strIndex);
+ if (eeErr == EENOERROR) {
+ eeErr = EEBindTM(&hTm,
+ SHpCXTFrompCXF(pcxf),
+ TRUE,
+ FALSE,
+ fSpecial
+ );
+ }
+ if (eeErr == EENOERROR) {
+ eeErr = EEvaluateTM(&hTm,
+ SHpFrameFrompCXF(pcxf),
+ EEHORIZONTAL
+ );
+ }
+ if (eeErr == EENOERROR) {
+ eeErr = EEInfoFromTM(&hTm, &ri, &hTi);
+ }
+
+ if (eeErr != EENOERROR) {
+ //
+ // search all contexts looking for the expression
+ //
+ fLoad = FALSE;
+search_again:
+ hexe = (HEXE) NULL;
+ while ((( hexe = SHGetNextExe( hexe ) ) != 0) ) {
+
+ //
+ // We try a module only if its symbols are loaded. If the
+ // symbols are defered and the caller wants to load them,
+ // we load them.
+ //
+ fUse = FALSE;
+ DebugData = SHGetDebugData( hexe );
+ if ( DebugData ) {
+ switch ( DebugData->she ) {
+ case sheDeferSyms:
+ if ( fLoad ) {
+ SHWantSymbols( hexe );
+ DebugData = SHGetDebugData( hexe );
+ She = DebugData->she;
+ if ( She == sheNone ||
+ She == sheSymbolsConverted ) {
+ fUse = TRUE;
+ }
+ }
+ break;
+
+ case sheNone:
+ case sheSymbolsConverted:
+ fUse = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ( fUse ) {
+
+ //
+ // format a fully qualified symbol name
+ //
+ ExeName = SHGetExeName( hexe );
+ if (ExeName) {
+ _splitpath( ExeName, NULL, NULL, fname, NULL );
+ sprintf( szFullContext, "%s!%s", fname, p+1 );
+ } else {
+ strcpy( szFullContext, lpExpr );
+ }
+
+ //
+ // try to parse and bind the expression
+ //
+ eeErr = EEParse(szFullContext,
+ radix,
+ fCase,
+ &hTm,
+ &strIndex
+ );
+ if (eeErr == EENOERROR) {
+ eeErr = EEBindTM(&hTm,
+ SHpCXTFrompCXF(pcxf),
+ TRUE,
+ FALSE,
+ fSpecial
+ );
+ }
+ if (eeErr == EENOERROR) {
+ eeErr = EEvaluateTM(&hTm,
+ SHpFrameFrompCXF(pcxf),
+ EEHORIZONTAL
+ );
+ }
+ if (eeErr == EENOERROR) {
+ eeErr = EEInfoFromTM(&hTm, &ri, &hTi);
+ }
+ if (eeErr == EENOERROR) {
+ break;
+ }
+ if (hTm) {
+ EEFreeTM( &hTm );
+ }
+ if (hTi) {
+ EEFreeTI( &hTi );
+ }
+ }
+ }
+
+ if ((eeErr != EENOERROR) && (!fLoad)) {
+ fLoad = TRUE;
+ goto search_again;
+ }
+ }
+ }
+
+
+ //
+ // Extract the desired information
+ //
+
+ if (eeErr == EENOERROR) {
+ if (!hTi || !(pTi = (PTI) MMLpvLockMb( hTi ))) {
+ eeErr = EEGENERAL;
+ } else {
+
+ *lpcch = cch;
+
+ if (pTi->fResponse.fAddr) {
+ *lpAddr = pTi->u2.AI;
+ } else if (pTi->fResponse.fValue && pTi->fResponse.fSzBytes &&
+ pTi->cbValue >= sizeof(WORD)) {
+
+ switch( pTi->cbValue ) {
+ case sizeof(WORD):
+ SetAddrOff( lpAddr, *((WORD FAR *) pTi->Value));
+ break;
+
+ case sizeof(DWORD):
+ SetAddrOff( lpAddr, *((DWORD FAR *) pTi->Value));
+ break;
+ }
+
+ // set the segment
+
+ if ((pTi->u.SegType & EEDATA) == EEDATA) {
+ ADDR addrData = {0};
+
+ OSDGetAddr( LppdCur->hpid, LptdCur->htid, adrData, &addrData );
+ SetAddrSeg( lpAddr, (SEGMENT) GetAddrSeg( addrData ));
+ ADDR_IS_FLAT(*lpAddr) = ADDR_IS_FLAT(addrData);
+ SYUnFixupAddr ( lpAddr );
+ } else if ((pTi->u.SegType & EECODE) == EECODE) {
+ ADDR addrPC = {0};
+
+ OSDGetAddr( LppdCur->hpid, LptdCur->htid, adrPC, &addrPC);
+ SetAddrSeg( lpAddr, (SEGMENT) GetAddrSeg( addrPC ));
+ ADDR_IS_FLAT(*lpAddr) = ADDR_IS_FLAT(addrPC);
+ SYUnFixupAddr( lpAddr );
+ } else {
+ ADDR addrData = {0};
+
+ OSDGetAddr( LppdCur->hpid, LptdCur->htid, adrData, &addrData );
+ SetAddrSeg( lpAddr, (SEGMENT) GetAddrSeg( addrData ));
+ ADDR_IS_FLAT(*lpAddr) = ADDR_IS_FLAT(addrData);
+ SYUnFixupAddr ( lpAddr );
+ }
+ }
+ MMbUnlockMb( hTi );
+ }
+ }
+
+ }
+ /*
+ ** Free up any handles
+ */
+
+ if (hTm) EEFreeTM( &hTm );
+ if (hTi) EEFreeTI( &hTi );
+ free(lpsz0);
+
+ return eeErr;
+} /* CPGetAddress() */
+
+
+int FAR PASCAL
+CPGetRange(
+ char FAR * lpszExpr,
+ int FAR * lpcch,
+ ADDR FAR * lpAddr1,
+ ADDR FAR * lpAddr2,
+ EERADIX radix,
+ int cbDefault,
+ int cbSize,
+ CXF FAR * pcxf,
+ BOOL fCase,
+ BOOL fSpecial
+ )
+
+/*++
+
+Routine Description:
+
+ Decode a range expression of the form:
+ addr1 [ l count | addr2 ]
+
+ return it as two addresses.
+
+Arguments:
+
+ lpszExpr - Supplies pointer to argument string
+ lpcch - Returns count of characters used
+ lpAddr1 - Returns start address
+ lpAddr2 - Returns end address + 1
+ radix - Supplies default radix for expression parser
+ cbDefault - Supplies default item count value
+ cbSize - Supplies size in bytes of data item
+ pcxf - Supplies pointer to context/frame info
+ fCase - Supplies case sensitivity flag for parser
+
+Return Value:
+
+ 0 For success, or error code (from parser?)
+ Note: this will succeed if addr2 < addr1 or addr1.seg != adr2.seg;
+ caller must decide whether range makes sense.
+
+--*/
+{
+ LPSTR lpsz;
+ LPSTR lpsz1;
+ LPSTR lpsz0;
+ ADDR addr1, addr2;
+ int err;
+ int cch;
+ long ll;
+ char ch;
+ BOOL fOptional = FALSE;
+ BOOL fDefault = FALSE;
+ BOOL fError = FALSE;
+
+ lpsz0 = lpsz = _strdup(lpszExpr);
+
+ // first arg must be an address:
+ if ((err = CPGetAddress(lpsz, &cch, &addr1, radix, pcxf, fCase, fSpecial)) != EENOERROR) {
+ fError = TRUE;
+ goto done;
+ }
+
+ // Then, see how much s/b added to get the end.
+
+ lpsz = CPSkipWhitespace(lpsz + cch);
+
+ if ((ch = *lpsz) == '\0') {
+
+ // no second part - fill in default
+ addr2 = addr1;
+ fDefault = TRUE;
+ ll = (cbDefault - 1) * cbSize;
+
+ } else if (!strchr("iIlL", ch) || *(lpsz = CPSkipWhitespace(lpsz+1)) == '\0') {
+
+ // End address specified (not L or L is last token)
+
+ // must be an addr
+ if ((err = CPGetAddress(lpsz, &cch, &addr2, radix, pcxf, fCase, fSpecial)) != EENOERROR) {
+ fError = TRUE;
+ goto done;
+ }
+
+ ll = 0;
+
+ lpsz += cch;
+
+ } else {
+
+ // Length specified
+
+ // see which kind of count it is:
+ if (ch == 'i' || ch == 'I') {
+ fOptional = TRUE;
+ }
+
+ if (!(lpsz1 = CPszToken(lpsz, ""))) {
+ fError = TRUE;
+ goto done;
+ }
+
+ ll = CPGetNbr(lpsz, radix, fCase, pcxf, NULL, &err);
+ if (ll == 0 && err != EENOERROR) {
+ fError =TRUE;
+ goto done;
+ }
+
+ lpsz = lpsz1;
+
+ if (cbSize > 1) {
+ ll *= cbSize;
+ }
+
+ ll--;
+ addr2 = addr1;
+ }
+
+ // Fixup each address to the final values.
+
+ SYFixupAddr ( &addr1 );
+ SYFixupAddr ( &addr2 );
+ GetAddrOff(addr2) += ll;
+
+ *lpcch = lpsz - lpsz0;
+ *lpAddr1 = addr1;
+ *lpAddr2 = addr2;
+
+done:
+ free(lpsz0);
+
+ if (fError) {
+ return EEGENERAL;
+ } else if (fDefault) {
+ return EEDEFAULT;
+ } else if (fOptional) {
+ return EEOPTIONAL;
+ } else {
+ return EENOERROR;
+ }
+
+} /* CPGetRange */
+
+
+
+/*** CPSkipWhitespace
+**
+** Synopsis:
+** lpsz = CPSkipWhitespace(lpszIn)
+**
+** Entry:
+** lpszIn - string to skip white space on
+**
+** Returns:
+** Pointer to first non-white space character in string
+**
+** Description:
+** This function will skip over any leading white space in a string
+** and return a pointer to the first non-whitespace character
+**
+*/
+
+char FAR * FAR PASCAL
+CPSkipWhitespace(
+ char FAR * lpszIn
+ )
+{
+ while (*lpszIn == ' ' || *lpszIn == '\t') lpszIn++;
+ return( lpszIn );
+} /* CPSkipWhiteSpace() */
diff --git a/private/windbg/windbg/cpuwin.c b/private/windbg/windbg/cpuwin.c
new file mode 100644
index 000000000..aab2e5150
--- /dev/null
+++ b/private/windbg/windbg/cpuwin.c
@@ -0,0 +1,755 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cpuwin.c
+
+Abstract:
+
+ This module contains the routines to manipulate the CPU Window
+
+Author:
+
+ William J. Heaton (v-willhe) 20-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+/*
+ * Preprocessor
+ */
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#define EACOUNT 4 //for effective address display offsets
+
+/*
+ * Global Memory (PROGRAM)
+ */
+
+extern CXF CxfIp; // for EA calcs v-griffk
+
+/*
+ * Global Memory (FILE)
+ */
+
+static LONG MustBe = 0xFFFFFFFF;
+static HWND hWndCpu;
+static PREGINFO pCpu;
+static UINT CpuCnt = 0;
+
+static HWND hWndFloat;
+static PREGINFO pFloat;
+static UINT FloatCnt = 0;
+
+static char szValue[1024];
+
+
+
+
+
+
+
+
+/*
+ * Prototypes
+ */
+
+VOID AgeCpuValues( PREGINFO pReg, UINT nCnt);
+PREGINFO CpuInitRegs(RT rtType, FT ftType, BOOL fFlagsAppend, UINT *cnt);
+BOOL CpuVerifyNew( PREGINFO pReg, UINT oln, UINT count);
+PSTR GetCpuString( PREGINFO pInfo, UINT nCnt, UINT PanelNumber, UINT Index);
+PSTR GetCpuValue( PREGINFO pInfo, UINT n);
+PSTR GetEA( UINT n);
+BOOL CPUSetValue( PPANE p, PREGINFO pReg );
+
+/*
+ * Start of Code
+ */
+
+/*** GetFloatHWND
+**
+** Synopsis:
+** hWnd = GetFloatHWND()
+**
+** Entry:
+** None
+**
+** Returns:
+** Pointer to the current Float window handle.
+**
+*/
+
+HWND GetFloatHWND(VOID)
+{
+ return(hWndFloat);
+}
+
+
+/*** GetCpuHWND
+**
+** Synopsis:
+** hWnd = GetCpuHWND()
+**
+** Entry:
+** None
+**
+** Returns:
+** Pointer to the current Register window handle.
+**
+*/
+
+HWND GetCpuHWND(VOID)
+{
+ return(hWndCpu);
+}
+
+
+/*** CPUSetValue
+**
+** Synopsis:
+** BOOL CPUSetValue( PPANE p )
+**
+** Entry:
+** p - Pane Information
+**
+** Returns:
+** Pointer to the current Register window handle.
+**
+*/
+
+
+BOOL CPUSetValue( PPANE p, PREGINFO pReg )
+{
+ UINT iReg = p->CurIdx;
+
+ BYTE lpb[10];
+ //BYTE lpb[8];
+
+ /*
+ ** If we're not editing or not in the right pane
+ ** its a no-op (a successful no-op)
+ */
+
+ if ( p->nCtrlId != ID_PANE_RIGHT)
+ return(TRUE);
+ if ( !p->Edit )
+ return(TRUE);
+
+
+ /*
+ ** Convert the character buffer into a byte buffer
+ */
+
+ if (EEUnformatMemory(lpb, p->EditBuf, pReg[iReg].cbits, pReg[iReg].type, 16) != EENOERROR)
+ return(FALSE);
+
+ //if (EEUnformatMemory(lpb, p->EditBuf, pReg[iReg].cbits,fmtUInt, 16) != EENOERROR)
+ // return(FALSE);
+
+ /*
+ ** Write back the register to the CPU
+ */
+
+ if (pReg[iReg].hFlag == -1) {
+ OSDWriteReg(LppdCur->hpid, LptdCur->htid, pReg[iReg].hReg, lpb);
+ }
+
+ else {
+ OSDWriteFlag(LppdCur->hpid, LptdCur->htid, pReg[iReg].hFlag, lpb);
+ }
+
+ return(TRUE);
+
+} /* CPUSetValue */
+
+/*** CpuVerifyNew
+ *
+ * Purpose: Determine if a registerss result has changed since
+ * the last time a user saw it
+ *
+ * Input:
+ * pvit - A pointer to the vit
+ * oln - Item number of interest
+ *
+ * Output:
+ * Returns:
+ * TRUE/FALSE the item has changed
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+BOOL CpuVerifyNew( PREGINFO pReg, UINT oln, UINT count)
+{
+ // No Registers, No change
+ if ( pReg == 0) return(FALSE);
+
+ // EA always get painted
+ if ( oln >= count) return(TRUE);
+
+ GetCpuString(pReg,count, ID_PANE_RIGHT, oln);
+
+
+
+ // Do we have a string at all?
+ if ( pReg[oln].pszValueP || pReg[oln].pszValueC) {
+
+ // Do we have both strings?
+ if ( pReg[oln].pszValueP && pReg[oln].pszValueC) {
+ if ((!_strcmpi(pReg[oln].pszValueC, pReg[oln].pszValueP))
+ && (pReg[oln].fChanged == FALSE)) {
+
+ return(FALSE);
+ } else if ((!_strcmpi(pReg[oln].pszValueC, pReg[oln].pszValueP))
+ && (pReg[oln].fChanged == TRUE)) {
+ pReg[oln].fChanged = FALSE;
+ return(TRUE);
+ }
+
+ }
+
+ // Nope, It changed
+ pReg[oln].fChanged = TRUE;
+ return(TRUE);
+ }
+
+ // Nope, No change
+ return(FALSE);
+
+} /* CpuVerifyNew() */
+
+
+/*** CPUEditProc
+**
+** Synopsis:
+** long = CPUEditProc(hwnd, msg, wParam, lParam)
+**
+** Entry:
+** hwnd - handle to window to process message for
+** msg - message to be processed
+** wParam - information about message to be processed
+** lParam - information about message to be processed
+**
+** Returns:
+**
+** Description:
+** MDI function to handle register window messages
+**
+*/
+
+LONG FAR PASCAL LOADDS CPUEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ PPANE p = (PPANE)lParam;
+ PPANEINFO pInfo = (PPANEINFO)wParam;
+
+ PREGINFO *ppReg = (p->Type == CPU_WIN) ? &pCpu : &pFloat;
+ PREGINFO pReg = (p->Type == CPU_WIN) ? pCpu : pFloat;
+ UINT *pnCnt = (p->Type == CPU_WIN) ? &CpuCnt : &FloatCnt;
+ HWND *phwnd = (p->Type == CPU_WIN) ? &hWndCpu : &hWndFloat;
+
+ UINT i;
+
+ switch (msg) {
+
+
+ case WM_DESTROY:
+ *phwnd = NULL;
+
+ // No Break intended
+
+ case WU_DBG_UNLOADEM:
+ case WU_DBG_UNLOADEE:
+
+ for( i=0 ; i < *pnCnt ; i++) {
+ if ( pReg[i].pszValueC ) free( pReg[i].pszValueC );
+ if ( pReg[i].pszValueP ) free( pReg[i].pszValueP );
+ }
+ if ( pReg ) free( pReg );
+
+ *ppReg = NULL;
+ *pnCnt = 0;
+ break;
+
+ case WU_INVALIDATE:
+
+ if (p != (PPANE)NULL)
+ {
+ InvalidateRect(p->hWndButton, NULL, TRUE);
+ InvalidateRect(p->hWndLeft, NULL, TRUE);
+ InvalidateRect(p->hWndRight, NULL, TRUE);
+ UpdateWindow (p->hWndLeft);
+ UpdateWindow (p->hWndRight);
+ }
+ break;
+
+
+ case WU_INITDEBUGWIN:
+
+ *phwnd = hwnd;
+ SendMessage(p->hWndLeft, EM_SETREADONLY,(WPARAM)TRUE,0l);
+ SendMessage(p->hWndRight,EM_SETREADONLY,(WPARAM)TRUE,0l);
+ if ( !DbgFEmLoaded() ) return(FALSE);
+
+
+
+ // No Break intended
+
+
+ case WU_DBG_LOADEM:
+
+ if ( p->Type == CPU_WIN) {
+ RT rtType = rtCPU |
+ (runDebugParams.RegModeMMU? rtSpecial : 0) |
+ (runDebugParams.RegModeExt? rtExtended : rtRegular);
+ pCpu = CpuInitRegs(rtType, ftRegular, TRUE, &CpuCnt);
+ SendMessage(p->hWndLeft, LB_SETCOUNT, *pnCnt+EACOUNT, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, *pnCnt+EACOUNT, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, *pnCnt+EACOUNT, 0);
+ } else {
+ RT rtType = rtFPU |
+ (runDebugParams.RegModeExt? rtExtended : rtRegular);
+ pFloat = CpuInitRegs(rtType, ftFP, TRUE, &FloatCnt);
+ SendMessage(p->hWndLeft, LB_SETCOUNT, *pnCnt, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, *pnCnt, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, *pnCnt, 0);
+ }
+ p->MaxIdx = ((p->Type == CPU_WIN)?(*pnCnt + EACOUNT):*pnCnt);
+
+ p->CurIdx = 0;
+
+ // No Break intended
+
+
+ case WU_UPDATE:
+
+ // Is EM loaded?
+ if ( !DbgFEmLoaded() ) return(FALSE);
+
+ AgeCpuValues( *ppReg, *pnCnt);
+ for ( i= p->TopIdx; i < (UINT)(p->TopIdx + p->PaneLines) ; i++) {
+ if ( CpuVerifyNew(*ppReg,i,*pnCnt) ) {
+ PaneInvalidateItem( p->hWndRight, p, (WORD)i);
+ }
+ }
+
+
+ p->RightOk = TRUE;
+ CheckPaneScrollBar(p, (WORD)((p->Type == CPU_WIN)?(*pnCnt + EACOUNT):*pnCnt));
+ break;
+
+ case WU_SETWATCH:
+ if ( CPUSetValue(p, pReg) ) {
+ p->RightOk = FALSE;
+ UpdateDebuggerState(UPDATE_WINDOWS);
+ return(TRUE);
+ }
+ break;
+
+ case WU_INFO:
+ i = pInfo->ItemId;
+
+ pInfo->ReadOnly = TRUE;
+ pInfo->NewText = FALSE;
+ pInfo->pBuffer = GetCpuString(*ppReg,*pnCnt,pInfo->CtrlId,i);
+ pInfo->pFormat = NULL; // No formatting allowed
+
+ // If Its a Value Pane and Its a real register, allow edits
+ // and....Set the Change History
+
+ if ((pInfo->CtrlId == ID_PANE_RIGHT) && ((WORD)i < ((p->Type == CPU_WIN)?(p->MaxIdx - EACOUNT):p->MaxIdx))) {
+ pInfo->ReadOnly = FALSE;
+ if ( DbgFEmLoaded() ) {
+ if ( pReg[i].pszValueP && pReg[i].pszValueC) {
+ pInfo->NewText = strcmp( pReg[i].pszValueP,pReg[i].pszValueC);
+ }
+ }
+ }
+
+ return(TRUE);
+
+ case WU_OPTIONS:
+ return(TRUE);
+ }
+
+ return FALSE;
+} /* CPUEditProc() */
+
+
+
+
+
+/*** CpuInitRegs()
+**
+** Synopsis:
+** void = CpuInitRegs()
+**
+** Entry:
+** none
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This routine sets up our internal description of what a CPU window
+** will look like. Several things must be noted here.
+**
+** 1. This routine may be called multiple times if you load up a
+** new EM or if you change EM models.
+**
+** 2. This routines requires that an EM be loaded in order to succeed
+**
+** 3. This routine will use a set of flags to determine which set
+** of register is to be "formatted".
+**
+** 4. Actual positioning of the register is still done in the
+** ViewCPU routine not here.
+**
+*/
+
+PREGINFO
+CpuInitRegs(
+ RT rtType,
+ FT ftType,
+ BOOL fFlagsAppend,
+ UINT *cnt
+ )
+{
+ DWORD dw;
+ int cRegs;
+ int cFlags;
+ int i;
+ int j;
+ RD rd;
+ FD fd;
+ int cSaveRegs = 0;
+ int cbSaveArea = 0;
+ HTID htid = (LptdCur != NULL) ? LptdCur->htid : (HTID)0;
+ PREGINFO LpCpuInfo = NULL;
+
+ DAssert( LppdCur != NULL );
+ DAssert( DbgFEmLoaded() );
+
+ /*
+ ** Get the count of Register Description records in the EM
+ */
+
+ OSDGetDebugMetric(LppdCur->hpid, htid, mtrcCRegs, &dw);
+ cRegs = (int) dw;
+ OSDGetDebugMetric(LppdCur->hpid, htid, mtrcCFlags, &dw);
+ cFlags = (int) dw;
+#if 0
+ Dbg( OSDGetDebugMetric(mtrcCRegs , LppdCur->hpid, htid, &ul) == xosdNone );
+ cRegs = (int) ul;
+ Dbg( OSDGetDebugMetric(mtrcCFlags, LppdCur->hpid, htid, &ul) == xosdNone );
+ cFlags = (int) ul;
+#endif
+ /*
+ ** Now determine how many of them we really want to look at and
+ ** display to the user
+ */
+
+
+ for (i=0; i<cRegs; i++) {
+ Dbg( OSDGetRegDesc( LppdCur->hpid, htid, i, &rd) == xosdNone );
+ if ( ((rd.rt & rtProcessMask) == (rtType & rtProcessMask)) &&
+ ((rd.rt & rtType & rtGroupMask) != 0)) {
+ cSaveRegs += 1;
+ }
+ }
+
+ for (i=0; i<cFlags; i++) {
+ Dbg( OSDGetFlagDesc( LppdCur->hpid, htid, i, &fd) == xosdNone );
+ if ( (fd.ft & ftType) == ftType ) {
+ cSaveRegs += 1;
+ }
+ }
+
+ /*
+ ** Now allocate space for use to hold the information about
+ ** the registers
+ */
+
+ LpCpuInfo = malloc(cSaveRegs * sizeof(*LpCpuInfo));
+
+ /*
+ ** Now fill in the elements of the information structure
+ ** to the best of our ability
+ */
+
+ for (i=0, j=0; i<cRegs; i++) {
+ Dbg( OSDGetRegDesc( LppdCur->hpid, htid, i, &rd) == xosdNone);
+ if ( ((rd.rt & rtProcessMask) == (rtType & rtProcessMask)) &&
+ ((rd.rt & rtType & rtGroupMask) != 0) ) {
+ LpCpuInfo[j].lpsz = rd.lpsz;
+ LpCpuInfo[j].hReg = rd.hReg;
+ LpCpuInfo[j].hFlag = (UINT) -1;
+ LpCpuInfo[j].cbits = rd.cbits;
+ LpCpuInfo[j].offValue = cbSaveArea;
+ LpCpuInfo[j].pszValueC = NULL;
+ LpCpuInfo[j].pszValueP = NULL;
+
+ if ( (rd.rt & rtFmtTypeMask) == rtInteger )
+ LpCpuInfo[j].type = fmtUInt | fmtZeroPad;
+
+ else if ( ( rd.rt & rtFmtTypeMask) == rtFloat)
+ LpCpuInfo[j].type = fmtFloat;
+ else
+ DAssert(FALSE);
+
+ cbSaveArea += (rd.cbits + 7) / 8;
+ j += 1;
+ }
+ }
+
+ if (fFlagsAppend) {
+ for (i=0; i<cFlags; i++) {
+ Dbg( OSDGetFlagDesc( LppdCur->hpid, htid, i, &fd) == xosdNone );
+ if ((fd.ft & ftType) == ftType ) {
+ LpCpuInfo[j].lpsz = fd.lpsz;
+ LpCpuInfo[j].hReg = fd.hReg;
+ LpCpuInfo[j].hFlag = i;
+ LpCpuInfo[j].type = fmtUInt;
+ LpCpuInfo[j].cbits = fd.cbits;
+ LpCpuInfo[j].offValue = cbSaveArea;
+ LpCpuInfo[j].pszValueC = NULL;
+ LpCpuInfo[j].pszValueP = NULL;
+ cbSaveArea += (fd.cbits + 7) / 8;
+ j += 1;
+ }
+ }
+ }
+
+ DAssert( j == cSaveRegs );
+
+ *cnt = cSaveRegs;
+ return(LpCpuInfo);
+} /* CpuInitRegs() */
+
+
+/* AgeCpuValues
+**
+**
+** Synopsis:
+** void AgeCpuValues( PREGINFO pReg, UINT nCnt);
+**
+** Purpose:
+** Age the Register value strings by moving it to the previous value.
+** If we have a previous value free it. Null the current value.
+**
+** Input:
+** pReg - Pointer to the Register Info
+** nCnt - Count of Registers
+**
+** Output:
+** None
+**
+** Exceptions:
+**
+** Notes:
+**
+*/
+
+
+VOID AgeCpuValues( PREGINFO pReg, UINT nCnt)
+{
+ ULONG i;
+
+ for ( i = 0; i < nCnt; i++) {
+
+ if ( pReg[i].pszValueP )
+ free(pReg[i].pszValueP);
+
+ // Move Current to Prev. and Null current
+
+ pReg[i].pszValueP = pReg[i].pszValueC;
+ pReg[i].pszValueC = NULL;
+ }
+} // AgeCpuValues
+
+
+
+/*** GetCpuString
+ *
+ * Purpose:
+ * Get the String associated with a register index
+ *
+ * Input:
+ * UINT PanelNumber - Panel whos string we need (BUTTON, LEFT, RIGHT)
+ * UINT n - Index of the register
+ *
+ * Output:
+ * PSTR Pointer to the buffer containing the string.
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+PSTR GetCpuString( PREGINFO pInfo, UINT nMax, UINT PanelNumber, UINT nCnt)
+{
+ Unreferenced(nMax);
+
+ if ( pInfo == NULL || LppdCur == NULL || LptdCur == NULL) {
+ return(" ");
+ }
+
+ // Focus in on the one we want
+ switch (PanelNumber) {
+
+ case ID_PANE_BUTTON:
+ if ( nCnt < nMax )
+ return("~");
+ else
+ return("~" );
+
+ case ID_PANE_LEFT:
+ if ( nCnt < nMax ) {
+ return(pInfo[nCnt].lpsz);
+ }
+
+ else if ( nCnt == nMax + 1 ) {
+ return( "EA" );
+ }
+
+ else
+ return( " " );
+
+ case ID_PANE_RIGHT:
+ if ( nCnt < nMax) {
+ if ( pInfo[nCnt].pszValueC == NULL)
+ pInfo[nCnt].pszValueC = _strdup(GetCpuValue(pInfo,nCnt));
+ return(pInfo[nCnt].pszValueC);
+ }
+
+ else
+ return GetEA( nCnt - nMax );
+ }
+
+ return( " " );
+} // GetCpuString
+
+
+/* GetCpuValue
+**
+**
+** Synopsis:
+** void GetCpuValue( PREGINFO pReg, UINT nCnt);
+**
+** Purpose:
+** Get the value string assoicated with the <nCnt>th register.
+**
+** Input:
+** pReg - Pointer to the Register Info
+** nCnt - Count of Registers
+**
+** Output:
+** Returns a pointer to a string.
+**
+** Exceptions:
+**
+** Notes:
+** Treat the string as READ-ONLY or else.
+**
+*/
+
+
+
+PSTR GetCpuValue( PREGINFO pInfo, UINT n)
+{
+ BYTE lpb[100];
+ UINT digits; // precision expected
+
+ // Read the Value
+ if ( pInfo[n].hFlag == -1)
+ OSDReadReg(LppdCur->hpid,LptdCur->htid,pInfo[n].hReg,&lpb);
+ else
+ OSDReadFlag(LppdCur->hpid,LptdCur->htid,pInfo[n].hFlag,&lpb);
+
+ // Format the Value
+ szValue[0] = 0;
+ DAssert( sizeof(szValue) > (pInfo[n].cbits+3)/4 + 1);
+
+ if (pInfo[n].type == fmtFloat)
+ digits = 26;
+ else
+ digits = (pInfo[n].cbits+3)/4 + 1;
+
+ EEFormatMemory(szValue, digits,
+ lpb,pInfo[n].cbits, pInfo[n].type,16);
+ return(szValue);
+
+} // GetCpuValue
+
+
+
+/* GetEA
+**
+**
+** Synopsis:
+** PSTR GetEA( UINT nCnt);
+**
+** Purpose:
+** Get one of the EA for the current instruction.
+**
+** Input:
+** nCnt - The EA to Get (1-based)
+**
+** Output:
+** None
+**
+** Exceptions:
+**
+** Notes:
+** A nCnt of zero returns blank....it simplifies the caller
+**
+*/
+
+PSTR GetEA( UINT n)
+{
+ SDI sds;
+ ADDR AddrPC;
+
+ if ( LppdCur && LptdCur && n > 0 ) {
+ AddrPC = *SHpADDRFrompCXT(&CxfIp.cxt);
+ SYFixupAddr(&AddrPC);
+
+ sds.dop = dopEA|dopFlatAddr;
+ sds.addr = AddrPC;
+ OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sds);
+
+ switch ( n ) {
+
+ case 1:
+ if ( sds.ichEA0 != -1) return(&sds.lpch[sds.ichEA0]);
+ break;
+
+ case 2:
+ if ( sds.ichEA1 != -1) return(&sds.lpch[sds.ichEA1]);
+ break;
+
+ case 3:
+ if ( sds.ichEA2 != -1) return(&sds.lpch[sds.ichEA2]);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return( " " );
+}
diff --git a/private/windbg/windbg/cvextras.c b/private/windbg/windbg/cvextras.c
new file mode 100644
index 000000000..2509ba29b
--- /dev/null
+++ b/private/windbg/windbg/cvextras.c
@@ -0,0 +1,498 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cvextras.c
+
+Abstract:
+
+ This file contains some routines stolen from CodeView. They should all
+ be cleaned up and moved to apisupp.c or codemgr.c
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+extern EI Ei;
+#define Lpei (&Ei)
+
+#define MAXERRMSG 256
+
+extern CXF CxfIp;
+extern LPSHF Lpshf;
+
+
+BOOL CDECL AuxPrintf(int i, char far *text, ...);
+
+
+SHFLAG PASCAL
+PHExactCmp (
+ LPSSTR lpsstr,
+ LPV lpv,
+ LSZ lpb,
+ SHFLAG fCase
+ )
+{
+ unsigned char cb;
+ SHFLAG shf = TRUE;
+
+ Unreferenced( lpv );
+
+ if ( lpb ) {
+ cb = *lpb;
+
+ // if length is diff, they are not equal
+ if ( lpsstr && lpsstr->cb == cb ) {
+ if ( fCase ) {
+ shf = (SHFLAG) memcmp ( lpb + 1, lpsstr->lpName, cb );
+ } else {
+ shf = (SHFLAG) _strnicmp( lpb + 1, (LPSTR) lpsstr->lpName, cb );
+ }
+ }
+ }
+ return shf;
+}
+
+
+SHFLAG PASCAL
+PHAtCmp(
+ LPSSTR lpsstr,
+ LPV lpv,
+ LSZ lpb,
+ SHFLAG fCase
+ )
+/*++
+
+--*/
+{
+ UINT cbm;
+ UINT cbt;
+ UINT i;
+ char *pm;
+
+ // lpsstr is what we are looking for; we will
+ // accept an exact match, or we will match an '@'
+ // in lpb with our EOS.
+
+ if (!lpsstr || !lpb) {
+ return 1;
+ }
+
+ cbm = lpsstr->cb;
+ cbt = *lpb++;
+
+ pm = lpsstr->lpName;
+
+ if (fCase) {
+ for (i = 0; i < cbt; i++) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*lpb)) {
+ if (*lpb++ != *pm++ || *lpb++ != *pm++) {
+ return 1;
+ }
+ i++;
+ continue;
+ }
+#endif
+ if (i == cbm && *lpb == '@') {
+ return 0;
+ }
+ if (*lpb++ != *pm++) {
+ return 1;
+ }
+ }
+ } else {
+ for (i = 0; i < cbt; i++) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*lpb)) {
+ if (*lpb++ != *pm++ || *lpb++ != *pm++) {
+ return 1;
+ }
+ i++;
+ continue;
+ }
+#endif
+ if (i == cbm && *lpb == '@') {
+ return 0;
+ }
+ if (toupper(*lpb++) != toupper(*pm++)) {
+ return 1;
+ }
+ }
+ }
+
+ // i == cbt...
+ if (i == cbm) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+//! LCLWN.H
+typedef int lts; //* error status number
+
+//! LCLWN.C
+LTS pascal FTError(LTS ltsCode)
+{
+ AuxPrintf(1, "FtError code: %d", (int)ltsCode);
+ return ltsCode;
+}
+
+#ifdef WIN32
+char in386mode = TRUE;
+#else
+char in386mode = FALSE;
+#endif
+
+/*** get_a_procedure
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+int
+get_a_procedure(
+ PCXT pCXT,
+ char *szName
+ )
+{
+ HSYM hSym;
+ HMOD hMod;
+ ADDR addr = {0};
+ HEXE hexe = (HEXE) NULL;
+ SSTR sstr;
+ BOOL fFound = FALSE;
+
+ sstr.cb = (BYTE) strlen(szName);
+ sstr.lpName = szName;
+ sstr.searchmask = SSTR_NoHash;
+
+ if( !pCXT || !szName || !(*szName) ) {
+ return FALSE;
+ }
+
+ hMod = SHHMODFrompCXT(pCXT);
+ if (!hMod) {
+ // no symbols
+ return FALSE;
+ }
+ hexe = SHHexeFromHmod(hMod);
+ DAssert(hexe);
+ if (!hexe) {
+ return FALSE;
+ }
+ hSym = PHFindNameInPublics (
+ (HSYM) NULL,
+ hexe,
+ &sstr,
+ TRUE,
+ PHAtCmp);
+ fFound = (hSym != NULL);
+
+ if (!fFound) {
+ return FALSE;
+ } else {
+ Dbg(SHAddrFromHsym( &addr, hSym));
+
+ emiAddr( addr ) = (HEMI)hexe;
+ ADDR_IS_LI( addr ) = TRUE;
+
+ return (SHSetCxt ( &addr, pCXT ) != NULL);
+ }
+} /* get_a_procedure() */
+
+int
+get_initial_context_helper(
+ PCXT pCXT
+ )
+{
+ // Look for main for a windows exe first
+
+ // dotdot names are for the PPC
+ if(get_a_procedure(pCXT,"..main")) return(TRUE);
+ if(get_a_procedure(pCXT,"..WinMain")) return(TRUE);
+
+ if(get_a_procedure(pCXT,"_WinMain")) return(TRUE);
+ if(get_a_procedure(pCXT,"WinMain")) return(TRUE);
+ if(get_a_procedure(pCXT,"wWinMain")) return(TRUE);
+ if(get_a_procedure(pCXT,"WINMAIN")) return(TRUE);
+
+ // Not there? Try for a Windows TTY
+
+ if(get_a_procedure(pCXT,"_main")) return(TRUE);
+ if(get_a_procedure(pCXT,"main")) return(TRUE);
+ if(get_a_procedure(pCXT,"wmain")) return(TRUE);
+ if(get_a_procedure(pCXT,"MAIN")) return(TRUE);
+
+ if(get_a_procedure(pCXT,"ENTGQQ")) return(TRUE);
+
+ return(FALSE);
+} /* get_initial_context() */
+
+/*** get_initial_context
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+int
+get_initial_context(
+ PCXT pCXT,
+ BOOL fSearchAll
+ )
+{
+ CXT Cxt;
+ HEXE hexe;
+ HMOD hMod;
+ LPDEBUGDATA DebugData;
+
+ if ( !fSearchAll ) {
+
+ return get_initial_context_helper( pCXT );
+
+ } else {
+
+ Cxt = *pCXT;
+
+ for (hexe = (HEXE)NULL; hexe = SHGetNextExe ( hexe ); ) {
+
+ DebugData = SHGetDebugData( hexe );
+ if ( DebugData->she == sheDeferSyms ) {
+ SHWantSymbols(hexe);
+ }
+
+ hMod = SHGetNextMod( hexe, (HMOD)NULL );
+ if ( hMod ) {
+ SHHMODFrompCXT( &Cxt ) = hMod;
+
+ if ( get_initial_context_helper( &Cxt ) ) {
+ *pCXT = Cxt;
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+void
+CVMessage (
+ MSGTYPE msgtype,
+ MSGID msgid,
+ MSGWHERE msgwhere,
+ ...
+ )
+{
+ static char szCVErr[] = "Error";
+ static char szCVWarn[] = "Warning";
+ static char szCVMsg[] = "Message";
+ static char szEmpty[] = "";
+ static char szFormat[] = "CV%04u %s: ";
+ static char gszErrStr[ MAXERRMSG ];
+ static MSGID gMSGID;
+
+ LPSTR szMsg;
+ LPSTR szStringLoc;
+ LPSTR szErr;
+ char rgch[ MAXERRMSG ];
+ va_list va_mark;
+
+ AuxPrintf(1, (LPSTR)"!!!CVMessage!!!");
+ //
+ // Set the beginning of the variable argument marker, and call vsprintf
+ // with that marker. If no template vars in error_string (szMsg), this
+ // is just the same as using szMsg.
+ //
+ va_start (va_mark, msgwhere );
+
+ // if we want it in a string, get the sting pointer
+ if (msgwhere == MSGSTRING) {
+ szStringLoc = va_arg(va_mark, LPSTR);
+ }
+
+ if (msgid == GEXPRERR) {
+ msgid = gMSGID;
+ strcpy(rgch, gszErrStr);
+ } else {
+ switch (msgtype) {
+ case INFOMSG:
+ szMsg = (char *) msgid;
+ vsprintf(rgch, szMsg, va_mark);
+ break;
+
+ case EXPREVALMSG:
+ strcpy(rgch, va_arg(va_mark, LPSTR));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ va_end ( va_mark );
+ szMsg = rgch;
+ //
+ // if not able to use cw or we want to go to the cmd window, go there.
+ //
+
+ switch (msgtype) {
+ case EXPREVALMSG:
+ case ERRORMSG:
+ szErr = szCVErr;
+ break;
+ case WARNMSG:
+ szErr = szCVWarn;
+ break;
+ case MESSAGEMSG:
+ szErr = szCVMsg;
+ break;
+ default:
+ szErr = szEmpty;
+ break;
+ }
+
+ if (msgwhere == MSGSTRING) {
+ strcpy(szStringLoc, szMsg);
+ } else if (msgwhere == MSGGERRSTR) {
+ gMSGID = msgid;
+ strcpy(gszErrStr, szMsg);
+ } else if (msgwhere == CMDWINDOW) {
+ AuxPrintf(1, szFormat, msgid, (LPSTR)szErr);
+ AuxPrintf(1, szMsg);
+ if (strlen(szErr) == 0) szErr = szCVMsg;
+
+ CmdLogFmt("%s\r\n", (LPSTR)szMsg);
+ } else if (msgwhere == MSGBOX) {
+ VarMsgBox(NULL, SYS_My_String, MB_OK|MB_APPLMODAL|MB_ICONHAND, (LPSTR)szMsg);
+ }
+}
+
+// CVExprErr appears unmodified...
+
+/*** CVExprErr
+*
+* Purpose: To get or print an expression evaluator error message
+*
+* Input:
+* Err - The expression evaluator msg number
+* msgwhere - The place to print the message
+* CMDWINDOW, MSGBOX, STATLINE
+* phTM - The expression evlauators TM
+* szErr - If this is non NULL, the message is not printed, but rather
+* it is returned in the string. The size of this buffer must
+* be at least ???
+*
+* Output:
+*
+* None
+*
+* Exceptions:
+*
+* Notes:
+*
+*/
+void pascal
+CVExprErr(
+ EESTATUS Err,
+ MSGWHERE msgwhere,
+ PHTM phTM,
+ char far * szErr
+)
+{
+ EEHSTR hErrStr;
+
+ char FAR * pErrStr;
+
+ // check for internal catastrophic conditions
+ if( !phTM || !(*phTM) ) {
+ Err = EECATASTROPHIC;
+ }
+
+ // now print this expression evaluator error
+ switch( Err ) {
+
+ default:
+
+ // get the error string from the EE
+ if( !EEGetError(phTM, Err, &hErrStr) ) {
+
+ // lock the string in memory
+ if( (pErrStr = MMLpvLockMb( (HDEP) hErrStr )) ) {
+ if( msgwhere == MSGSTRING ) {
+ CVMessage(EXPREVALMSG, EXPRERROR, msgwhere, szErr, pErrStr);
+ } else {
+ CVMessage(EXPREVALMSG, EXPRERROR, msgwhere, pErrStr);
+ }
+ MMbUnlockMb ( (HDEP) hErrStr );
+
+ } else {
+
+ // we really are having problems
+ Err = EECATASTROPHIC;
+
+ }
+
+ // free the error string
+ EEFreeStr( hErrStr );
+ }
+
+ // only exit if not catastrophic
+ if( Err != EECATASTROPHIC ) {
+ break;
+ }
+
+ // otherwise say catastrophic error
+
+ case EECATASTROPHIC:
+ case EENOMEMORY:
+ CVMessage(ERRORMSG, Err, msgwhere, szErr);
+ break;
+
+ // don't print an error
+ case EENOERROR:
+ break;
+
+ }
+} /* CVExprErr() */
+
+
+static int iee = -1;
+
+
+unsigned long SYGetReg ( WORD ireg ) {
+ unsigned long lValue = 0;
+
+ OSDReadReg ( LppdCur->hpid, LptdCur->htid, ireg, &lValue );
+
+ return lValue;
+}
diff --git a/private/windbg/windbg/data.c b/private/windbg/windbg/data.c
new file mode 100644
index 000000000..6f86b1685
--- /dev/null
+++ b/private/windbg/windbg/data.c
@@ -0,0 +1,319 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ data.c
+
+Abstract:
+
+ This file contains declarations for global data items
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/****************************************************************************
+
+ GLOBAL VARIABLES :
+
+****************************************************************************/
+
+// Version Info:
+#ifdef DEBUGVER
+DEBUG_VERSION('W','D',"WinDBG Shell, DEBUG")
+#else
+RELEASE_VERSION('W','D',"WinDBG Shell")
+#endif
+
+// Handle to main window
+HWND hwndFrame = NULL;
+
+// Handle to MDI client
+HWND hwndMDIClient = NULL;
+
+// Handle to currently activated child
+HWND hwndActive = NULL;
+
+// Handle to edit control
+HWND hwndActiveEdit = NULL;
+
+// Handle to currently activated MDI debug window
+HWND hwndDebug = NULL;
+
+//Handle to instance data
+HANDLE hInst;
+
+//Generic words
+WORD wGeneric1, wGeneric2;
+
+//Help mode flag; TRUE = "ON"
+BOOL bHelp = FALSE;
+
+//Help file name
+char szHelpFileName[_MAX_PATH];
+
+//Handle to accelerator table
+HANDLE hAccTable;
+
+//Handle to .INI file
+int iniHandle;
+
+//Handle to .INI file
+int iniHandle;
+
+//Items Colors
+ITEMSCOLORS itemsForCols;
+ITEMSCOLORS itemsBakCols;
+
+//Syntax Coloring
+BOOL syntaxColors = TRUE;
+
+// command "ignore registry" flag
+BOOL IgnoreDefault = FALSE;
+
+//QcQp Environ Params
+ENVIRONPARAMS __FAR environParams;
+int tabSize;
+
+//RunDebug Params
+RUNDEBUGPARAMS runDebugParams;
+
+// Commands to execute on certain events
+char szStopEventCmd[MAX_CMDLINE_TXT] = "";
+
+//Status line (text,multiKey,Overtype,ReadOnly,CapsLock,NumLock,Line,Col)
+STATUS status;
+
+//Ribbon
+RIBBON ribbon;
+
+//Standard Dos File Extensions
+char szStarDotC[DOS_EXT_SIZE];
+char szStarDotH[DOS_EXT_SIZE];
+char szStarDotCPP[DOS_EXT_SIZE];
+char szStarDotCXX[DOS_EXT_SIZE];
+char szStarDotExe[DOS_EXT_SIZE];
+char szStarDotCom[DOS_EXT_SIZE];
+char szStarDotStar[DOS_EXT_SIZE];
+
+//Temporary storage for a file path
+char szPath[_MAX_PATH];
+char szDrive[_MAX_DRIVE];
+char szDir[_MAX_DIR];
+char szFName[_MAX_FNAME];
+char szExt[_MAX_EXT];
+
+//Temporary string variable used by all modules
+char szTmp[TMP_STRING_SIZE];
+
+//Editor : Current view
+int curView = -1;
+
+//Default Items Colors
+LPITEMSCOLORS defaultForCols;
+LPITEMSCOLORS defaultBakCols;
+
+//Array position in ppszMakefileExtTab of currently selected extension
+WORD nCurExt;
+
+// Handles to Include and Library Environment strings.
+HANDLE hEnvIncludeStr = (HANDLE)NULL;
+HANDLE hEnvLibraryStr = (HANDLE)NULL;
+
+//Keyboard Hooks functions
+HHOOK hKeyHook;
+
+//Find & Replace Data Structure
+_FINDREPLACE FAR findReplace;
+_FINDREPLACEMEM FAR frMem;
+
+//Editor : Global documents struct
+DOCREC Docs[MAX_DOCUMENTS];
+
+//Editor : Global documents struct
+VIEWREC Views[MAX_VIEWS];
+
+//Currently highlighted trace line (F8/F10)
+TRACEINFO TraceInfo = {-1, 0};
+
+//CrLf
+char CrLf[] = "\r\n";
+
+//Number of different colors in a line
+int nbColors;
+
+//Screen colors saved
+//Line len divided by 2 because different colors will be separated
+//by spaces
+COLORINFO colors[MAX_USER_LINE + 3]; //+ 3 =When selecting
+
+//Emergency Flag (exit without processing WM_DESTROY and WM_CLOSE, or
+//cancelled rec)
+BOOL emergency = FALSE;
+
+//Data for Documents Handling
+int rd_fh;
+LPSTR rd_buf;
+int rd_offset;
+int rd_read;
+int rd_doc;
+
+//CheckSum in ini file
+WORD checkSum;
+
+//Record buffer overflow counter
+WORD recordBufferOverflow;
+
+//Current Help Id for Open, Merge, Save and Open project dialog box
+WORD curHelpId;
+
+//Empty string
+char szNull[1] = "";
+
+//State of keyboard when key is down
+BOOL isShiftDown;
+BOOL isCtrlDown;
+
+//Record stop mark
+int stopMarkStatus = HAS_STOP;
+
+//For modeless dialog box control
+BOOL exitModelessDlg;
+
+//Editor : Standard editor win proc and subclassing functions
+WNDPROC lpfnEditProc;
+
+//Debugger window view #
+int disasmView = -1;
+int cmdView = -1;
+int memView = -1;
+int callsView = -1;
+
+//Fonts variables
+int __FAR fontsNb = 0;
+int __FAR fontSizesNb = 0;
+int __FAR fontCur = 0;
+int __FAR fontSizeCur = 0;
+LPLOGFONT fonts = NULL; //Variable size
+LPINT fontSizes = NULL; //Variable size
+LPINT fontSizesPoint = NULL; //Variable size
+LOGFONT defaultFont;
+
+//Last position of cursor before undo
+int mC;
+int dL;
+
+// Number of dialog/message boxes currently open
+int FAR BoxCount;
+
+int iDebugLevel = 0;
+UINT radix = 10;
+
+//Option file full path name (qcwin.ini)
+char FAR iniFileName[_MAX_PATH];
+
+//Regular expression pattern (must be near)
+struct patType *pat = NULL;
+
+//TRUE after PostQuitMessage has been called.
+BOOL QuitTheSystem = FALSE;
+
+//Keep overtype status
+BOOL FAR oldOvertype;
+
+//True when terminate application has been called
+BOOL FAR TerminatedApp = FALSE;
+
+//Default ini mode
+BOOL defaultIni = FALSE;
+
+//Checking date of files for reload
+BOOL checkFileDate = FALSE;
+
+//Critical section for editor
+BOOL editorIsCritical = FALSE;
+
+//Title bar data
+TITLEBAR TitleBar;
+
+//Current line expanded (tabs converted)
+char el[MAX_USER_LINE * 2 + 1];
+int elLen;
+
+//Current line and current block
+LPLINEREC pcl;
+LPBLOCKDEF pcb;
+
+//View tabs
+BOOL viewTabs = FALSE;
+
+//Playing records mode
+BOOL playingRecords = FALSE;
+
+//Windows Version
+int winVer;
+
+//Scroll origin, KEYBOARD or MOUSE
+WORD scrollOrigin;
+
+//Autotest mode for test suites
+AUTORUN AutoRun = arNone;
+BOOL AutoTest = FALSE;
+BOOL NoPopups = FALSE;
+BOOL RemoteRunning = FALSE;
+LPSTR PszAutoRun = NULL;
+
+// Low memory messages
+char LowMemoryMsg[MAX_MSG_TXT];
+char LowMemoryMsg2[MAX_MSG_TXT];
+
+// WinDBG title text
+char MainTitleText[MAX_MSG_TXT];
+
+char fCaseSensitive = 1;
+char SuffixToAppend = '\0';
+
+//
+LPSTR LpszCommandLine = iniFileName;
+
+LPTD LptdCur=NULL; // Pointer to the current thread
+LPPD LppdCur=NULL; // Pointer to the current process
+
+HANDLE HModSH = 0; // Symbol handler DLL handle
+HANDLE HModEE = 0; // Expression evaluator DLL
+HANDLE HModTL = 0; // Transport layer DLL handle
+HANDLE HModEM = 0; // Execution model DLL handler
+
+BOOL FSourceOverlay = TRUE;
+
+//
+// Used to determine if the Current or the most recently set
+// Frame CONTEXT should be used for reading register variables.
+//
+BOOL fUseFrameContext = FALSE;
+
+//
+// if this is not -1 then it indicates a logical
+// frame number to use for locals display & evaluation
+//
+INT LocalFrameNumber;
+//
+// event to signal the completion of an ioctl
+//
+HANDLE hEventIoctl;
+
+CRITICAL_SECTION csLog;
+
+OSVERSIONINFO OsVersionInfo;
diff --git a/private/windbg/windbg/dbgext.c b/private/windbg/windbg/dbgext.c
new file mode 100644
index 000000000..4acc83f0b
--- /dev/null
+++ b/private/windbg/windbg/dbgext.c
@@ -0,0 +1,1581 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cmdexec0.c
+
+Abstract:
+
+ This file contains the front end code for parsing the various commands
+ for the command window, and the code for the debugger control commands.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-92
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// prototypes
+//
+DWORD
+ExtGetExpression(
+ LPSTR lpsz
+ );
+
+VOID
+ExtGetSymbol(LPVOID offset,
+ PUCHAR pchBuffer,
+ LPDWORD lpDisplacement
+ );
+
+DWORD
+ExtDisasm(LPDWORD lpOffset,
+ LPSTR lpBuffer,
+ ULONG fShowEffectiveAddress
+ );
+
+BOOL
+ExtReadProcessMemory(DWORD offset,
+ LPVOID lpBuffer,
+ DWORD cb,
+ LPDWORD lpcbBytesRead
+ );
+
+BOOL
+ExtWriteProcessMemory(DWORD offset,
+ LPVOID lpBuffer,
+ DWORD cb,
+ LPDWORD lpcbBytesWritten
+ );
+
+BOOL
+ExtGetThreadContext(DWORD Processor,
+ LPCONTEXT lpContext,
+ DWORD cbSizeOfContext
+ );
+
+BOOL
+ExtSetThreadContext(DWORD Processor,
+ LPCONTEXT lpContext,
+ DWORD cbSizeOfContext
+ );
+
+BOOL
+ExtIoctl(USHORT IoctlType,
+ LPVOID lpvData,
+ DWORD cbSize
+ );
+
+DWORD
+ExtCallStack(DWORD FramePointer,
+ DWORD StackPointer,
+ DWORD ProgramCounter,
+ PEXTSTACKTRACE StackFrames,
+ DWORD Frames
+ );
+
+LOGERR
+LogPageIn(
+ LPSTR lpsz
+ );
+
+DWORD OsVersion;
+static BOOL fApp = FALSE;;
+static char AppName[ MAX_PATH ];
+
+
+#define MAX_EXTDLLS 32
+#define DEFAULT_EXTENSION_LIB "ntsdexts"
+
+#define EXT_NOT_LOADED 0
+#define EXT_LOADED 1
+#define EXT_NEEDS_LOADING 2
+
+typedef struct _EXTCOMMANDS {
+ CMDID CmdId;
+ LPSTR CmdString;
+ LPSTR HelpString;
+} EXTCOMMANDS, *LPEXTCOMMANDS;
+
+typedef struct _EXTLOAD {
+ HANDLE Module;
+ DWORD Version;
+ DWORD Calls;
+ BOOL OldStyle;
+ DWORD Loaded;
+ BOOL DoVersionCheck;
+ CHAR Name[32];
+ PWINDBG_EXTENSION_DLL_INIT pDllInit;
+ PWINDBG_CHECK_VERSION pCheckVersion;
+ EXCEPTION_RECORD ExceptionRecord;
+} EXTLOAD, *LPEXTLOAD;
+
+
+static WINDBG_EXTENSION_APIS WindbgExtensions =
+ {
+ sizeof(WindbgExtensions),
+ (PWINDBG_OUTPUT_ROUTINE)CmdLogFmt,
+ (PWINDBG_GET_EXPRESSION)ExtGetExpression,
+ ExtGetSymbol,
+ (PWINDBG_DISASM)ExtDisasm,
+ CheckCtrlCTrap,
+ ExtReadProcessMemory,
+ (PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE)ExtWriteProcessMemory,
+ ExtGetThreadContext,
+ ExtSetThreadContext,
+ ExtIoctl,
+ ExtCallStack
+ };
+
+
+static EXTCOMMANDS ExtCommands[] =
+ {
+ CMDID_NULL, NULL, NULL,
+ CMDID_HELP, "?", "Display this help information",
+ CMDID_DEFAULT, "default", "Change the default extension dll",
+ CMDID_LOAD, "load", "Load an extension dll",
+ CMDID_NOVERSION, "noversion", "Disable extension dll version checking",
+ CMDID_RELOAD, "reload", "Reload kernel symbols (KD only)",
+ CMDID_SYMPATH, "sympath", "Change or display the symbol path",
+ CMDID_UNLOAD, "unload", "Unload the default extension dll",
+ CMDID_PAGEIN, "pagein", "Attempt to make a page present"
+ };
+
+#define ExtMaxCommands (sizeof(ExtCommands)/sizeof(EXTCOMMANDS))
+
+static EXTLOAD LoadedExts[MAX_EXTDLLS];
+static DWORD NumLoadedExts;
+static LPSTR DefaultExt;
+
+#define BUILD_MAJOR_VERSION 3
+#define BUILD_MINOR_VERSION 5
+#define BUILD_REVISION API_VERSION_NUMBER
+API_VERSION ApiVersion = { BUILD_MAJOR_VERSION, BUILD_MINOR_VERSION, API_VERSION_NUMBER, 0 };
+
+extern LPSHF Lpshf; // vector table for symbol handler
+extern CXF CxfIp;
+extern EI Ei;
+extern LPPD LppdCommand;
+extern LPTD LptdCommand;
+
+
+
+DWORD
+ExtGetExpression(
+ LPSTR lpsz
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the expression specified by lpsz.
+
+Arguments:
+
+ lpsz - Supplies the expression string.
+
+Return Value:
+
+ Value of expression.
+
+--*/
+
+{
+ ADDR addr;
+ int cch;
+ char *expr;
+
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (CPGetAddress(lpsz, &cch, &addr, radix, &CxfIp, fCaseSensitive, runDebugParams.fMasmEval) != 0) {
+ if (DefaultExt && tolower(DefaultExt[0]) == 'k' && tolower(DefaultExt[1]) == 'd') {
+ expr = malloc( strlen(lpsz) + 32 );
+ strcpy( expr, "nt!" );
+ strcat( expr, lpsz );
+ if (CPGetAddress(expr, &cch, &addr, radix, &CxfIp, fCaseSensitive, runDebugParams.fMasmEval) != 0) {
+ free( expr );
+ return 0;
+ }
+ free( expr );
+ } else {
+ return 0;
+ }
+ }
+
+ SYFixupAddr(&addr);
+
+ return addr.addr.off;
+}
+
+
+
+VOID
+ExtGetSymbol(
+ LPVOID offset,
+ PUCHAR pchBuffer,
+ LPDWORD lpDisplacement
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the symbol string.
+
+Arguments:
+
+ offset - Address offset.
+
+ pchBuffer - Pointer to the buffer to store symbol string.
+
+ lpDisplacement - Pointer to the displacement.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ADDR addr;
+ LPADDR loc = SHpADDRFrompCXT(&CxfIp.cxt);
+ ODR odr;
+
+ AddrInit( &addr, 0, 0, (UOFF32)offset, TRUE, TRUE, FALSE, FALSE );
+ SYFixupAddr(&addr);
+
+ if (pchBuffer[0] == '!') {
+ if (SHGetModule(&addr, pchBuffer)) {
+ _strupr( pchBuffer );
+ strcat( pchBuffer, "!" );
+ pchBuffer += strlen(pchBuffer);
+ } else {
+ *pchBuffer = '\0';
+ }
+ } else {
+ *pchBuffer = '\0';
+ }
+
+ odr.lszName = pchBuffer;
+
+ SHGetSymbol(&addr, loc, sopNone, &odr);
+
+ *lpDisplacement = odr.dwDeltaOff;
+}
+
+
+
+
+DWORD
+ExtDisasm(
+ LPDWORD lpOffset,
+ LPSTR lpBuffer,
+ ULONG fShowEffectiveAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function does the disassembly.
+
+Arguments:
+
+ lpOffset - Pointer to address offset.
+
+ lpBuffer - Pointer to the buffer to store instruction.
+
+ fShowEffectiveAddress - Show effective address if TRUE.
+
+
+Return Value:
+
+ TRUE for success; FALSE for failure.
+
+--*/
+
+{
+ SDI sdi;
+ BOOL f;
+ LPSTR lpch;
+
+
+ /*
+ ** Get the current CS:IP.
+ */
+
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrPC, &sdi.addr);
+
+ /*
+ ** Set address and do the disassembly.
+ */
+
+ sdi.addr.addr.off = *lpOffset;
+ SYFixupAddr(&sdi.addr);
+ sdi.dop = (runDebugParams.DisAsmOpts & ~(0x800)) | dopAddr | dopOpcode
+ | dopOperands | (fShowEffectiveAddress ? dopEA : 0);
+
+ f = (OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sdi) == xosdNone);
+
+ /*
+ ** See if the disassembly is successful.
+ */
+
+ if(f == 0 || sdi.lpch[sdi.ichOpcode] == '?') {
+ return FALSE;
+ }
+
+ /*
+ ** Copy instruction to lpBuffer.
+ */
+
+ lpch = lpBuffer;
+ if(sdi.ichAddr != -1) {
+ sprintf(lpch, "%s ", &sdi.lpch[sdi.ichAddr]);
+ lpch += strlen(&sdi.lpch[sdi.ichAddr]) + 2; // + 2 -- 2 spaces
+ }
+
+ if(sdi.ichBytes != -1) {
+ sprintf(lpch, "%-17s", &sdi.lpch[sdi.ichBytes]);
+ lpch += max(17, strlen(&sdi.lpch[sdi.ichBytes]));
+ }
+
+ sprintf(lpch, "%-12s", &sdi.lpch[sdi.ichOpcode]);
+ lpch += max(12, strlen(&sdi.lpch[sdi.ichOpcode]));
+
+ if(sdi.ichOperands != -1) {
+ sprintf(lpch, "%-25s", &sdi.lpch[sdi.ichOperands]);
+ lpch += max(25, strlen(&sdi.lpch[sdi.ichOperands]));
+ }
+
+ if(sdi.ichComment != -1) {
+ sprintf(lpch, "%s", &sdi.lpch[sdi.ichComment]);
+ lpch += strlen(&sdi.lpch[sdi.ichComment]);
+ }
+
+ if(fShowEffectiveAddress) {
+
+ *lpch++ = ';';
+ if(sdi.ichEA0 != -1) {
+ sprintf(lpch, "%s ", &sdi.lpch[sdi.ichEA0]);
+ lpch += strlen(&sdi.lpch[sdi.ichEA0]) + 2; // + 2 -- 2 spaces
+ }
+
+ if(sdi.ichEA1 != -1) {
+ sprintf(lpch, "%s ", &sdi.lpch[sdi.ichEA1]);
+ lpch += strlen(&sdi.lpch[sdi.ichEA1]) + 2; // + 2 -- 2 spaces
+ }
+
+ if(sdi.ichEA2 != -1) {
+ sprintf(lpch, "%s", &sdi.lpch[sdi.ichEA2]);
+ lpch += strlen(&sdi.lpch[sdi.ichEA2]);
+ }
+ }
+
+ *lpch++ = '\r';
+ *lpch++ = '\n';
+ *lpch = '\0';
+
+ /*
+ ** Set next offset before return.
+ */
+
+ *lpOffset = sdi.addr.addr.off;
+
+ return TRUE;
+}
+
+
+
+
+BOOL
+ExtReadProcessMemory(
+ DWORD offset,
+ LPVOID lpBuffer,
+ DWORD cb,
+ LPDWORD lpcbBytesRead
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads the debuggee's memory.
+
+Arguments:
+
+ offset - Address offset.
+
+ lpBuffer - Supplies pointer to the buffer.
+
+ cb - Specifies the number of bytes to read.
+
+ lpcbBytesRead - Actual number of bytes read; this parameter is optional.
+
+Return Value:
+
+ TRUE for success; FALSE for failure.
+
+--*/
+
+{
+ ADDR addr;
+ DWORD cbBytesRead = 0;
+
+ AddrInit( &addr, 0, 0, offset, TRUE, TRUE, FALSE, FALSE );
+
+#ifdef OSDEBUG4
+ OSDFixupAddress(LppdCur->hpid, LptdCur->htid, &addr);
+ OSDReadMemory(LppdCur->hpid, LptdCur->htid, &addr, lpBuffer, cb,
+ &cbBytesRead);
+#else
+ SYFixupAddr(&addr);
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr)
+ == xosdNone);
+ cbBytesRead = OSDPtrace(osdReadBuf, (int)cb, lpBuffer, LppdCur->hpid,
+ LptdCur->htid);
+#endif
+
+ if(lpcbBytesRead) {
+ *lpcbBytesRead = (cbBytesRead >= 0 ? cbBytesRead : 0);
+ }
+
+ return cbBytesRead == cb;
+}
+
+
+
+
+BOOL
+ExtWriteProcessMemory(
+ DWORD offset,
+ LPVOID lpBuffer,
+ DWORD cb,
+ LPDWORD lpcbBytesWritten
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes the debuggee's memory.
+
+Arguments:
+
+ offset - Address offset.
+
+ lpBuffer - Supplies pointer to the buffer.
+
+ cb - Specifies the number of bytes to write.
+
+ lpcbBytesWritten - Actual number of bytes written;
+ this parameter is optional.
+
+Return Value:
+
+ TRUE for success; FALSE for failure.
+
+--*/
+
+{
+ ADDR addr;
+ XOSD xosd;
+#ifdef OSDEBUG4
+ DWORD cbBytesWritten;
+#endif
+
+ AddrInit( &addr, 0, 0, offset, TRUE, TRUE, FALSE, FALSE );
+
+#ifdef OSDEBUG4
+ OSDFixupAddress(LppdCur->hpid, LptdCur->htid, &addr);
+ xosd = OSDWriteMemory(LppdCur->hpid, LptdCur->htid, &addr, lpBuffer, cb,
+ &cbBytesWritten);
+ if ( xosd == xosdNone ) {
+ if (lpcbBytesWritten) {
+ *lpcbBytesWritten = cbBytesWritten;
+ }
+ }
+#else
+ SYFixupAddr(&addr);
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrCurrent, &addr)
+ == xosdNone);
+ xosd = OSDPtrace(osdWriteBuf, (int)cb, lpBuffer, LppdCur->hpid,
+ LptdCur->htid);
+ if ( xosd == xosdNone ) {
+ if (lpcbBytesWritten) {
+ *lpcbBytesWritten = cb;
+ }
+ }
+#endif
+
+ return (xosd == xosdNone);
+}
+
+
+
+
+BOOL
+ExtGetThreadContext(
+ DWORD Processor,
+ LPCONTEXT lpContext,
+ DWORD cbSizeOfContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets thread context.
+
+Arguments:
+
+ lpContext - Supplies pointer to CONTEXT strructure.
+
+ cbSizeOfContext - Supplies the size of CONTEXT structure.
+
+Return Value:
+
+ TRUE for success; FALSE for failure.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(cbSizeOfContext);
+
+ /*
+ ** Note: use of sizeof(LPCONTEXT) and (LPV)&lpContext below is an
+ ** implementation-specific choice.
+ **
+ ** The data being passed into the IOCTL routine is in fact the pointer
+ ** to where to place the context rather than an actual context itself.
+ ** This explains the use of sizeof(LPCONTEXT) rather than size(CONTEXT)
+ ** as the parameter being passed in.
+ */
+
+ return OSDIoctl( LppdCur->hpid,
+ runDebugParams.fKernelDebugger ? (HTID)Processor : LptdCur->htid,
+ ioctlGetThreadContext,
+ sizeof(LPCONTEXT),
+ (LPV)&lpContext
+ ) == xosdNone;
+}
+
+
+
+
+BOOL
+ExtSetThreadContext(
+ DWORD Processor,
+ LPCONTEXT lpContext,
+ DWORD cbSizeOfContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets thread context.
+
+Arguments:
+
+ lpContext - Supplies pointer to CONTEXT strructure.
+
+ cbSizeOfContext - Supplies the size of CONTEXT structure.
+
+Return Value:
+
+ TRUE for success; FALSE for failure.
+
+--*/
+
+{
+
+ return OSDIoctl( LppdCur->hpid,
+ runDebugParams.fKernelDebugger ? (HTID)Processor : LptdCur->htid,
+ ioctlSetThreadContext,
+ cbSizeOfContext,
+ (LPV)lpContext
+ ) == xosdNone;
+}
+
+
+
+BOOL
+ExtIoctl(
+ USHORT IoctlType,
+ LPVOID lpvData,
+ DWORD cbSize
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE for success
+ FALSE for failure
+
+--*/
+
+{
+ XOSD xosd;
+ PIOCTLGENERIC pig;
+
+
+ pig = (PIOCTLGENERIC) malloc( cbSize + sizeof(IOCTLGENERIC) );
+ if (!pig) {
+ return FALSE;
+ }
+
+ pig->ioctlSubType = IoctlType;
+ pig->length = cbSize;
+ memcpy( pig->data, lpvData, cbSize );
+
+ xosd = OSDIoctl( LppdCur->hpid,
+ LptdCur->htid,
+ ioctlGeneric,
+ cbSize + sizeof(IOCTLGENERIC),
+ (LPV)pig
+ );
+
+ memcpy( lpvData, pig->data, cbSize );
+
+ free( pig );
+ return xosd == xosdNone;
+}
+
+
+DWORD
+ExtCallStack(
+ DWORD FramePointer,
+ DWORD StackPointer,
+ DWORD ProgramCounter,
+ PEXTSTACKTRACE StackFrames,
+ DWORD Frames
+ )
+/*++
+
+Routine Description:
+
+ This function will dump a call stack to the command window.
+
+Arguments:
+
+ lpsz - arguments to callstack
+
+Return Value:
+
+ log error code
+
+--*/
+{
+ STACKINFO si[50];
+ DWORD dwFrames = 50;
+ DWORD i;
+
+
+ if (!GetCompleteStackTrace( FramePointer,
+ StackPointer,
+ ProgramCounter,
+ si,
+ &dwFrames,
+ FALSE,
+ TRUE )) {
+ return 0;
+ }
+
+ for (i=0; i<dwFrames; i++) {
+ StackFrames[i].ProgramCounter = si[i].StkFrame.AddrPC.Offset;
+ StackFrames[i].ReturnAddress = si[i].StkFrame.AddrReturn.Offset;
+ StackFrames[i].FramePointer = si[i].StkFrame.AddrFrame.Offset;
+ StackFrames[i].Args[0] = si[i].StkFrame.Params[0];
+ StackFrames[i].Args[1] = si[i].StkFrame.Params[1];
+ StackFrames[i].Args[2] = si[i].StkFrame.Params[2];
+ StackFrames[i].Args[3] = si[i].StkFrame.Params[3];
+ }
+
+ return dwFrames;
+}
+
+
+LONG
+ExtensionExceptionFilterFunction(
+ LPSTR msg,
+ LPEXCEPTION_POINTERS lpep
+ )
+{
+ CmdLogFmt( "\r\n%s addr=0x%08x, ec=0x%08x\r\n\r\n",
+ msg,
+ lpep->ExceptionRecord->ExceptionAddress,
+ lpep->ExceptionRecord->ExceptionCode );
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+LPSTR
+ParseBangCommand(
+ LPSTR lpsz,
+ LPSTR *lpszMod,
+ LPSTR *lpszFnc,
+ PCMDID pCmdId
+ )
+{
+ DWORD i;
+ long ProcessorType;
+
+
+ //
+ // Start assuming ExtensionMod exists: ExtensionMod
+ // "^"
+ // lpszMod
+ //
+
+ *lpszMod = lpsz;
+ while((*lpsz != '.') && (*lpsz != ' ') && (*lpsz != '\t') && (*lpsz != '\0')) {
+ lpsz++;
+ }
+
+ if (*lpsz != '.') {
+
+ //
+ // If ExtensionMod is absent(no '.'), set this: Function'\0'
+ // ^ ^
+ // lpszFnc lpsz
+ //
+ // and use the default dll.
+ //
+
+ *lpszFnc = *lpszMod;
+ if ( *lpsz != '\0' ) {
+ *lpsz++ = '\0';
+ }
+
+ if (DefaultExt) {
+
+ *lpszMod = DefaultExt;
+
+ } else {
+
+ if (runDebugParams.fKernelDebugger) {
+ ProcessorType = -1;
+ if (OSDGetDebugMetric( LppdCur->hpid,
+ LptdCur->htid,
+ mtrcProcessorType,
+ &ProcessorType ) != xosdNone ) {
+ CmdLogFmt( "Cannot get processor metric\r\n" );
+ return NULL;
+ }
+ switch( ProcessorType ) {
+ case mptmips:
+ *lpszMod = "kdextmip.dll";
+ break;
+
+ case mptdaxp:
+ *lpszMod = "kdextalp.dll";
+ break;
+
+ case mptmppc:
+ *lpszMod = "kdextppc.dll";
+ break;
+
+ case mptix86:
+ default:
+ *lpszMod = "kdextx86.dll";
+ break;
+ }
+ } else {
+ *lpszMod = DEFAULT_EXTENSION_LIB;
+ }
+
+ }
+
+ } else {
+
+ //
+ // If we found '.', set this: ExtensionMod'\0'
+ // ^ ^
+ // lpszMod lpsz
+ //
+
+ *lpsz++ = '\0';
+
+ //
+ // Set function: Function'\0'
+ // ^ ^
+ // lpszFnc lpsz
+ //
+
+ *lpszFnc = lpsz;
+ while((*lpsz != ' ') && (*lpsz != '\t') && (*lpsz != '\0')) {
+ lpsz++;
+ }
+
+ if(*lpsz != '\0') {
+ *lpsz++ = '\0';
+ }
+ }
+
+ //
+ // look to see if the user entered one of the built-in commands
+ //
+ *pCmdId = CMDID_NULL;
+ for (i=1; i<ExtMaxCommands; i++) {
+ if (_stricmp( *lpszFnc, ExtCommands[i].CmdString ) == 0) {
+ *pCmdId = ExtCommands[i].CmdId;
+ if (ExtCommands[i].CmdId == CMDID_LOAD) {
+ *lpszMod = lpsz;
+ }
+ break;
+ }
+ }
+
+ _strlwr( *lpszFnc );
+
+ return lpsz;
+}
+
+
+BOOL
+LoadExtensionDll(
+ LPEXTLOAD ExtLoad
+ )
+{
+ ExtLoad->Module = LoadLibrary( ExtLoad->Name );
+ if (!ExtLoad->Module) {
+ ExtLoad->Module = LoadLibrary( DEFAULT_EXTENSION_LIB );
+ if (ExtLoad->Module) {
+ strcpy( ExtLoad->Name, DEFAULT_EXTENSION_LIB );
+ } else {
+ return FALSE;
+ }
+ }
+
+ ExtLoad->Loaded = EXT_LOADED;
+ NumLoadedExts++;
+
+ DefaultExt = ExtLoad->Name;
+
+ CmdLogFmt( "Debugger extension library [%s] loaded\n", ExtLoad->Name );
+
+ ExtLoad->pDllInit = (PWINDBG_EXTENSION_DLL_INIT)GetProcAddress
+ ( ExtLoad->Module, "WinDbgExtensionDllInit" );
+
+ if (ExtLoad->pDllInit == NULL) {
+ ExtLoad->OldStyle = TRUE;
+ } else {
+ ExtLoad->OldStyle = FALSE;
+ ExtLoad->pCheckVersion = (PWINDBG_CHECK_VERSION)
+ GetProcAddress( ExtLoad->Module, "CheckVersion");
+
+ if (ExtLoad->pCheckVersion) {
+ ExtLoad->DoVersionCheck = TRUE;
+ } else {
+ ExtLoad->DoVersionCheck = FALSE;
+ }
+
+ if (OsVersion == 0) {
+ OSDGetDebugMetric( LppdCur->hpid,
+ LptdCur->htid,
+ mtrcOSVersion,
+ &OsVersion );
+ }
+
+ __try {
+
+ (ExtLoad->pDllInit)( &WindbgExtensions,
+ HIWORD(OsVersion),
+ LOWORD(OsVersion) );
+
+ } __except (ExtensionExceptionFilterFunction(
+ "DllInit() failed", GetExceptionInformation())) {
+ return FALSE;
+
+ }
+ }
+
+ if (runDebugParams.fNoVersion) {
+ ExtLoad->DoVersionCheck = FALSE;
+ }
+
+ return TRUE;
+}
+
+
+LOGERR
+LogExtension(
+ LPSTR lpsz
+ )
+
+/*++
+
+Routine Description:
+
+ Invoke ntsd extensions in WinDbg command window. Extension command syntax:
+
+ ![ExtensionMod.]Function Argument-string
+
+ If ExtensionMod is absent, use the default "ntsdexts" dll. This function
+ first parses lpsz and ends up with lpszMod ==> ExtensionMod(or "ntsdexts"),
+ lpszFnc ==> Function, and lpsz ==> Argument-string. It then does
+ LoadLibrary()(as needed), GetProcAddress(), and (ExtensionRountion)().
+
+Arguments:
+
+ lpsz - Supplies argument string and points one position right after '!'.
+
+Return Value:
+
+ Log error code.
+
+ --*/
+
+{
+ PWINDBG_EXTENSION_ROUTINE WindbgExtRoutine;
+ PWINDBG_OLD_EXTENSION_ROUTINE WindbgOldExtRoutine;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal;
+ ADDR addrPC;
+ LPSTR lpszMod;
+ LPSTR lpszFnc;
+ LPSTR lpszArgs;
+ long l;
+ HANDLE hProcess;
+ HANDLE hThread;
+ INT len;
+ INT mi;
+ CMDID CmdId;
+
+
+ IsKdCmdAllowed();
+ TDWildInvalid();
+ PDWildInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ CmdInsertInit();
+
+
+ if (!DebuggeeActive()) {
+ CmdLogFmt( "Bang commands are not allowed until the debuggee is loaded\n" );
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ if (!*lpsz) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ lpszArgs = ParseBangCommand( lpsz, &lpszMod, &lpszFnc, &CmdId );
+
+ switch (CmdId) {
+ case CMDID_DEFAULT:
+ if (!lpszArgs) {
+ CmdLogFmt("Extension dll %s unloaded\r\n",DefaultExt);
+ goto done;
+ }
+
+ for( mi=0; mi<MAX_EXTDLLS; mi++) {
+ if (_stricmp( LoadedExts[mi].Name, lpszArgs ) == 0) {
+ CmdLogFmt( "%s is now the default extension dll\n", lpszArgs );
+ DefaultExt = LoadedExts[mi].Name;
+ rVal = LOGERROR_NOERROR;
+ goto done;
+ }
+ }
+
+ CmdLogFmt( "%s extension dll is not loaded\n", lpszArgs );
+ rVal = LOGERROR_QUIET;
+ goto done;
+
+ case CMDID_RELOAD:
+ rVal = LogReload(lpszArgs, 0);
+ goto done;
+
+ case CMDID_SYMPATH:
+ if (!*lpszArgs) {
+ len = ModListGetSearchPath( NULL, 0 );
+ if (!len) {
+ CmdLogFmt( "Sympath =\n" );
+ } else {
+ lpsz = malloc(len);
+ ModListGetSearchPath( lpsz, len );
+ CmdLogFmt( "Sympath = %s\n", lpsz );
+ free(lpsz);
+ }
+ } else {
+ char szBuf[MAX_USER_LINE];
+ CPCopyString(&lpszArgs, szBuf, '\0', *lpszArgs == '"');
+ ModListSetSearchPath( szBuf );
+ }
+ rVal = LOGERROR_NOERROR;
+ goto done;
+
+ case CMDID_PAGEIN:
+ rVal = LogPageIn(lpszArgs);
+ goto done;
+
+ }
+
+ if(!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ for( mi=0; mi<MAX_EXTDLLS; mi++) {
+ if (_stricmp( LoadedExts[mi].Name, lpszMod ) == 0) {
+ //
+ // it has already been loaded
+ //
+ break;
+ }
+ }
+
+ if (mi == MAX_EXTDLLS) {
+ //
+ // could not find the module, so it must need to be loaded
+ // so lets look for an empty slot
+ //
+ for( mi=0; mi<MAX_EXTDLLS; mi++) {
+ if (LoadedExts[mi].Loaded == EXT_NOT_LOADED) {
+ break;
+ }
+ }
+ }
+
+ if (mi == MAX_EXTDLLS) {
+ CmdLogFmt( "Too many extension dlls loaded\n" );
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ if (LoadedExts[mi].Loaded == EXT_NOT_LOADED ||
+ LoadedExts[mi].Loaded == EXT_NEEDS_LOADING) {
+ //
+ // either this ext dll has never been loaded or
+ // it has been unloaded. in either case we need
+ // to load the sucker now.
+ //
+ strcpy( LoadedExts[mi].Name, lpszMod );
+ if (!LoadExtensionDll( &LoadedExts[mi] )) {
+ CmdLogFmt("Cannot load '%s'\r\n", lpszMod);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+
+ switch (CmdId) {
+ case CMDID_LOAD:
+ rVal = LOGERROR_NOERROR;
+ goto done;
+
+ case CMDID_UNLOAD:
+ FreeLibrary( LoadedExts[mi].Module );
+ LoadedExts[mi].Module = NULL;
+ LoadedExts[mi].Loaded = EXT_NOT_LOADED;
+ NumLoadedExts--;
+ DefaultExt = NULL;
+ CmdLogFmt("Extension dll %s unloaded\r\n",LoadedExts[mi].Name);
+ rVal = LOGERROR_NOERROR;
+ goto done;
+
+ case CMDID_NOVERSION:
+ CmdLogFmt("Extension dll system version checking is disabled\r\n");
+ LoadedExts[mi].DoVersionCheck = FALSE;
+ runDebugParams.fNoVersion = TRUE;
+ rVal = LOGERROR_NOERROR;
+ goto done;
+
+ case CMDID_HELP:
+ lpszFnc = "help";
+ break;
+ }
+
+ WindbgExtRoutine =
+ (PWINDBG_EXTENSION_ROUTINE)GetProcAddress( LoadedExts[mi].Module, lpszFnc );
+
+ if (!WindbgExtRoutine) {
+ for( mi=0; mi<MAX_EXTDLLS; mi++) {
+ if (LoadedExts[mi].Loaded == EXT_NEEDS_LOADING) {
+ if (!LoadExtensionDll( &LoadedExts[mi] )) {
+ CmdLogFmt("Cannot load '%s'\r\n", LoadedExts[mi].Name);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+ if (LoadedExts[mi].Loaded == EXT_LOADED) {
+ WindbgExtRoutine =
+ (PWINDBG_EXTENSION_ROUTINE)GetProcAddress( LoadedExts[mi].Module, lpszFnc );
+ if (WindbgExtRoutine) {
+ break;
+ }
+ }
+ }
+ if (!WindbgExtRoutine) {
+ CmdLogFmt("Missing extension: '%s.%s'\r\n", LoadedExts[mi].Name, lpszFnc);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+ }
+
+ WindbgOldExtRoutine = (PWINDBG_OLD_EXTENSION_ROUTINE) WindbgExtRoutine;
+
+ if (LoadedExts[mi].DoVersionCheck) {
+ __try {
+
+ (LoadedExts[mi].pCheckVersion)();
+
+ } __except (ExtensionExceptionFilterFunction(
+ "CheckVersion() failed", GetExceptionInformation())) {
+ rVal = LOGERROR_QUIET;
+ goto done;
+
+ }
+ }
+
+ //
+ // Get debuggee's process handle.
+ //
+ l = (long)&hProcess;
+ OSDIoctl(LppdCur->hpid, 0, ioctlGetProcessHandle, sizeof(l), &l);
+
+ //
+ // Get debuggee's thread handle.
+ //
+ l = (long)&hThread;
+ OSDIoctl(LppdCur->hpid, LptdCur->htid, ioctlGetThreadHandle, sizeof(l), &l);
+
+ //
+ // Get the current CS:IP.
+ //
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, (ADR)adrPC, &addrPC);
+
+ //
+ // Enable the extension to detect ControlC.
+ //
+ SetCtrlCTrap();
+
+ //
+ // Call the extension function. Note: if ExtensionRountine is a pointer
+ // to a function that is in fact declared as PNTSD_EXTENSION_ROUTINE(like
+ // those in ntsdexts.c), then last 4 remote apis of varible WindbgExtensions
+ // are not applicable.
+ //
+
+ if (CmdId == CMDID_HELP) {
+ //
+ // print the extension dll list
+ //
+ if (NumLoadedExts > 1) {
+ CmdLogFmt( "*** Loaded Extension Dlls:\n" );
+ for( l=0; l<MAX_EXTDLLS; l++) {
+ if (LoadedExts[l].Loaded == EXT_LOADED) {
+ CmdLogFmt( "%d %s\n", l+1, LoadedExts[l].Name );
+ }
+ }
+ CmdLogFmt( "\n" );
+ }
+
+ //
+ // print the help for the built-in commands
+ //
+ CmdLogFmt( "\nWinDbg built in bang commands:\n\n" );
+ for (l=1; l<ExtMaxCommands; l++) {
+ CmdLogFmt( "%-27s - %s\n", ExtCommands[l].CmdString, ExtCommands[l].HelpString );
+ }
+ CmdLogFmt( "\n%s Bang Commands:\n\n", LoadedExts[mi].Name );
+ }
+
+ __try {
+
+ if (LoadedExts[mi].OldStyle) {
+ (WindbgOldExtRoutine)( hProcess,
+ hThread,
+ addrPC.addr.off,
+ (PWINDBG_EXTENSION_APIS)&WindbgExtensions,
+ lpszArgs );
+ } else {
+ (WindbgExtRoutine)( hProcess,
+ hThread,
+ addrPC.addr.off,
+ LptdCur ? LptdCur->itid : 0,
+ lpszArgs );
+ }
+
+ } __except (ExtensionExceptionFilterFunction(
+ "Extension function faulted", GetExceptionInformation())) {
+
+ }
+
+ LoadedExts[mi].Calls++;
+
+ //
+ // Disable ControlC detection.
+ //
+
+ ClearCtrlCTrap();
+
+ CmdLogFmt("\r\n");
+
+ rVal = LOGERROR_NOERROR;
+
+ done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+
+ return rVal;
+}
+
+
+VOID
+PrintDllBuildInfo(
+ LPSTR DllBaseName,
+ BOOL GetPlatform
+ )
+{
+ long ProcessorType;
+ LPSTR p;
+ CHAR name[MAX_PATH];
+ CHAR buf[MAX_PATH];
+ DWORD tstamp;
+ HANDLE hMod;
+
+
+ if (GetPlatform) {
+ ProcessorType = -1;
+ if (OSDGetDebugMetric( LppdCur->hpid,
+ LptdCur->htid,
+ mtrcProcessorType,
+ &ProcessorType ) != xosdNone ) {
+ return;
+ }
+
+ switch( ProcessorType ) {
+ case mptix86:
+ p = "x86";
+ break;
+
+ case mptmips:
+ p = "mip";
+ break;
+
+ case mptdaxp:
+ p = "alp";
+ break;
+
+ case mptmppc:
+ p = "ppc";
+ break;
+
+ default:
+ p = "";
+ break;
+ }
+ } else {
+ p = "";
+ }
+
+ sprintf( name, "%s%s.dll", DllBaseName, p );
+
+ hMod = GetModuleHandle( name );
+ if (!hMod) {
+ return;
+ }
+
+ buf[0] = 0;
+ GetModuleFileName( hMod, buf, sizeof(buf) );
+ _strlwr( buf );
+ tstamp = GetTimestampForLoadedLibrary( hMod );
+ p = ctime( &tstamp );
+ p[strlen(p)-1] = 0;
+ CmdLogFmt(
+ "%-20s: %d.%d.%d, built: %s [name: %s]\n",
+ name,
+ 0,
+ 0,
+ 0,
+ p,
+ buf );
+
+ return;
+}
+
+
+LOGERR
+LogVersion(
+ LPSTR lpsz
+ )
+{
+ CHAR buf[MAX_PATH];
+ DWORD tstamp;
+ DWORD mi;
+ LPSTR p;
+ LPAPI_VERSION lpav;
+ LPEXT_API_VERSION lpextav;
+ PWINDBG_EXTENSION_API_VERSION ExtensionApiVersion;
+ LPPD LppdT = LppdCur;
+ LPTD LptdT = LptdCur;
+ LOGERR rVal;
+ BOOL save;
+
+
+
+ IsKdCmdAllowed();
+ TDWildInvalid();
+ PDWildInvalid();
+
+ LppdCur = LppdCommand;
+ LptdCur = LptdCommand;
+
+ CmdInsertInit();
+
+ if(!DebuggeeActive()) {
+ CmdLogVar(ERR_Debuggee_Not_Alive);
+ rVal = LOGERROR_QUIET;
+ goto done;
+ }
+
+ CmdLogFmt( "\n" );
+
+ GetModuleFileName( NULL, buf, sizeof(buf) );
+ _strlwr( buf );
+ tstamp = GetTimestampForLoadedLibrary( GetModuleHandle( NULL ) );
+ p = ctime( &tstamp );
+ p[strlen(p)-1] = 0;
+ CmdLogFmt(
+ "%-20s: %d.%d.%d, built: %s [name: %s]\n",
+ "windbg",
+ ApiVersion.MajorVersion,
+ ApiVersion.MinorVersion,
+ ApiVersion.Revision,
+ p,
+ buf );
+
+ PrintDllBuildInfo( "shcv", FALSE );
+ PrintDllBuildInfo( "symcvt", FALSE );
+ PrintDllBuildInfo( "tlloc", FALSE );
+ PrintDllBuildInfo( "tlpipe", FALSE );
+ PrintDllBuildInfo( "tlser", FALSE );
+ PrintDllBuildInfo( "em", TRUE );
+ PrintDllBuildInfo( "eecxx", TRUE );
+ PrintDllBuildInfo( "dm", FALSE );
+ PrintDllBuildInfo( "dmkd", TRUE );
+
+ lpav = ImagehlpApiVersion();
+ GetModuleFileName( GetModuleHandle("imagehlp.dll"), buf, sizeof(buf) );
+ tstamp = GetTimestampForLoadedLibrary( GetModuleHandle( "imagehlp.dll" ) );
+ p = ctime( &tstamp );
+ p[strlen(p)-1] = 0;
+ _strlwr( buf );
+ CmdLogFmt(
+ "%-20s: %d.%d.%d, built: %s [name: %s]\n",
+ "imagehlp",
+ lpav->MajorVersion,
+ lpav->MinorVersion,
+ lpav->Revision,
+ p,
+ buf );
+
+ if (DefaultExt) {
+ for( mi=0; mi<MAX_EXTDLLS; mi++) {
+ if (_stricmp( LoadedExts[mi].Name, DefaultExt ) == 0) {
+ break;
+ }
+ }
+
+ ExtensionApiVersion = (PWINDBG_EXTENSION_API_VERSION)
+ GetProcAddress( LoadedExts[mi].Module, "ExtensionApiVersion" );
+ if (ExtensionApiVersion) {
+ lpextav = ExtensionApiVersion();
+ GetModuleFileName( LoadedExts[mi].Module, buf, sizeof(buf) );
+ tstamp = GetTimestampForLoadedLibrary( LoadedExts[mi].Module );
+ p = ctime( &tstamp );
+ p[strlen(p)-1] = 0;
+ _strlwr( buf );
+ CmdLogFmt(
+ "%-20s: %d.%d.%d, built: %s [name: %s]\n",
+ LoadedExts[mi].Name,
+ lpextav->MajorVersion,
+ lpextav->MinorVersion,
+ lpextav->Revision,
+ p,
+ buf );
+ }
+ save = LoadedExts[mi].DoVersionCheck;
+ LoadedExts[mi].DoVersionCheck = FALSE;
+ LogExtension( "version" );
+ LoadedExts[mi].DoVersionCheck = save;
+ }
+
+ CmdLogFmt( "\n" );
+
+ rVal = LOGERROR_NOERROR;
+
+done:
+ LppdCur = LppdT;
+ LptdCur = LptdT;
+
+ return rVal;
+}
+
+
+LPSTR
+GetExtensionDllNames(
+ LPDWORD len
+ )
+{
+ DWORD mi;
+ LPSTR DllNames;
+ LPSTR p;
+
+
+ if (!NumLoadedExts) {
+ return NULL;
+ }
+ for( mi=0,*len=0; mi<MAX_EXTDLLS; mi++) {
+ if (LoadedExts[mi].Loaded == EXT_LOADED) {
+ *len += (strlen(LoadedExts[mi].Name) + 1);
+ }
+ }
+ if (!*len) {
+ return NULL;
+ }
+ *len += 2;
+ DllNames = malloc( *len );
+ if (!DllNames) {
+ return NULL;
+ }
+ ZeroMemory( DllNames, *len );
+ for( mi=0,p=DllNames; mi<MAX_EXTDLLS; mi++) {
+ if (LoadedExts[mi].Loaded == EXT_LOADED) {
+ strcpy( p, LoadedExts[mi].Name );
+ p += (strlen(p) + 1);
+ }
+ }
+ return DllNames;
+}
+
+
+VOID
+SetExtensionDllNames(
+ LPSTR DllNames
+ )
+{
+ DWORD mi;
+ LPSTR p;
+
+
+ p = DllNames;
+ for( mi=0; mi<MAX_EXTDLLS; mi++) {
+ if (LoadedExts[mi].Loaded == EXT_LOADED) {
+ FreeLibrary( LoadedExts[mi].Module );
+ LoadedExts[mi].Module = NULL;
+ LoadedExts[mi].Loaded = EXT_NOT_LOADED;
+ NumLoadedExts--;
+ }
+ }
+ mi = 0;
+ ZeroMemory( LoadedExts, sizeof(LoadedExts) );
+ while( p && *p ) {
+ strcpy( LoadedExts[mi].Name, p );
+ LoadedExts[mi].Loaded = EXT_NEEDS_LOADING;
+ mi += 1;
+ p += (strlen(p) + 1);
+ }
+}
+
+LOGERR
+LogPageIn(
+ LPSTR lpsz
+ )
+{
+ LPPD lppd;
+ LPTD lptd;
+ XOSD xosd = xosdUnknown;
+ MSG msg;
+ PIOCTLGENERIC pig;
+ int cch;
+ EESTATUS eest;
+ ADDR addr;
+
+
+ IsKdCmdAllowed();
+
+ lppd = LppdCur;
+ lptd = LptdCur;
+ if (!lppd || !lppd->hpid) {
+ lppd = LppdFirst;
+ lptd = NULL;
+ }
+
+ if (!runDebugParams.fKernelDebugger) {
+ CmdLogFmt( "Command allowed only for kernel debugging\n" );
+ return LOGERROR_QUIET;
+ }
+
+ lpsz = CPSkipWhitespace(lpsz);
+
+ eest = CPGetAddress(
+ lpsz,
+ &cch,
+ &addr,
+ radix,
+ &CxfIp,
+ fCaseSensitive,
+ runDebugParams.fMasmEval
+ );
+
+ if (eest != EENOERROR) {
+ CmdLogFmt( "Invalid address\n" );
+ return LOGERROR_QUIET;
+ }
+
+ SYFixupAddr( &addr );
+
+ if (lppd && lppd->hpid) {
+ pig = (PIOCTLGENERIC)malloc(sizeof(ULONG) + sizeof(IOCTLGENERIC));
+ if (!pig) {
+ CmdLogFmt( "Could not allocate memory, bummer...\n" );
+ return LOGERROR_QUIET;
+ }
+ pig->ioctlSubType = IG_PAGEIN;
+ pig->length = sizeof(ULONG);
+ ((PULONG)pig->data)[0] = addr.addr.off;
+ xosd = OSDIoctl(
+ lppd->hpid,
+ NULL,
+ ioctlGeneric,
+ pig->length + sizeof(IOCTLGENERIC),
+ (LPV)pig
+ );
+ if (xosd == xosdNone) {
+ Go();
+ }
+ free( pig );
+ }
+
+ return (xosd == xosdNone) ? LOGERROR_NOERROR : LOGERROR_UNKNOWN;
+}
diff --git a/private/windbg/windbg/dbugdll.c b/private/windbg/windbg/dbugdll.c
new file mode 100644
index 000000000..7a57f011c
--- /dev/null
+++ b/private/windbg/windbg/dbugdll.c
@@ -0,0 +1,1648 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dbugdll.c
+
+Abstract:
+
+ This file contains the code for dealing with the Debugger Dll Dialog box
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+/*************************************************************************/
+
+/* names of keys and tags */
+
+/*************************************************************************/
+
+#define SH_KEY "Symbol Handler"
+#define SH_PREFIX "SH"
+#define TL_KEY "Transport Layer"
+#define TL_PREFIX "TL"
+#define EE_KEY "Expression Evaluator"
+#define EE_PREFIX "EE"
+#define EM_KEY "Execution Model"
+#define EM_PREFIX "EM"
+
+#define DESCRIPTION "Description"
+#define PATH "Path"
+#define PARAMS "Parameters"
+
+
+/*************************************************************************/
+
+/* Local types */
+
+/*************************************************************************/
+
+
+typedef struct tagDLLINFO {
+ struct tagDLLINFO *pNext;
+ PSTR pShortName;
+ PSTR pDescription;
+ PSTR pPath;
+ PSTR pParams;
+} DLLINFO, *PDLLINFO;
+
+
+typedef struct tagLISTINFO {
+ int nId;
+ int nDllIndex;
+ LPSTR lpName;
+ LPSTR lpPrefix;
+ PDLLINFO pDefaults;
+ PDLLINFO pFreeList;
+ PDLLINFO pDLLList;
+ BOOL fDirty;
+ BOOL fLoaded;
+} LISTINFO, *PLISTINFO;
+
+
+typedef struct tagCHDBDLGINFO {
+ PLISTINFO pL;
+ PDLLINFO pD;
+ BOOL fNew;
+} CHDBDLGINFO, *PCHDBDLGINFO;
+
+/*************************************************************************/
+
+/* Local protos */
+
+/*************************************************************************/
+
+static PLISTINFO ListInfoFromId(int nId);
+static int IdFromDllIndex(int iDll);
+static void GetListItem(int nId, int nCurSel,
+ PDLLINFO ** pppList, PDLLINFO * ppInfo);
+static void DestroyDLLInfoList(PDLLINFO * ppList);
+static void RemoveItem(PDLLINFO * ppList, PDLLINFO pItem);
+static void FreeItem(PDLLINFO pItem);
+static void AddItem(PDLLINFO *ppList, PDLLINFO pItem);
+static PDLLINFO DupItem(PDLLINFO pSrc);
+static void FillDLLInfoList(int nId);
+static void FillDLLInfoCombo(HWND hDlg, int nId);
+static BOOL ValidateDLL(HWND hDlg, int nId);
+static void CleanDirtyDLLList(HWND hDlg, int nId, BOOL fDoSave);
+
+void SetOkButtonToDefault( HWND hDlg );
+
+
+BOOL FAR PASCAL EXPORT DlgChDbugDll(HWND, UINT, WPARAM, LONG);
+
+#define LPKeyNameFromId(I) (ListInfoFromId(I)->lpName)
+#define LPPrefixFromId(I) (ListInfoFromId(I)->lpPrefix)
+#define PDefaultsFromId(I) (ListInfoFromId(I)->pDefaults)
+#define PFreeListFromId(I) (ListInfoFromId(I)->pFreeList)
+#define PDLLListFromId(I) (ListInfoFromId(I)->pDLLList)
+#define FDirtyFromId(I) (ListInfoFromId(I)->fDirty)
+#define FLoadedFromId(I) (ListInfoFromId(I)->fLoaded)
+#define DllIndexFromId(I) (ListInfoFromId(I)->nDllIndex)
+
+
+/*************************************************************************/
+
+/* local data */
+
+/*************************************************************************/
+
+static WNDPROC lpfnButtonProc;
+static BOOL fActionButtonPressed;
+
+/*************************************************************************/
+
+/* these are pointers to malloc'ed strings */
+
+/*************************************************************************/
+static char * WHITESPACE = "\t ";
+static char * rgszDllNames[ MAXLHSINDEX ] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+static char * rgszDllKeys[ MAXLHSINDEX ] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*************************************************************************/
+/* default values for DLL choices. For each of the 4 DLLs, if there */
+/* are no entries in the registry, this list will be loaded instead. */
+/*************************************************************************/
+static DLLINFO SHDefaults[] = {
+ NULL, "CV4", "CodeView version 4 symbols", "shcv.dll", "",
+ NULL, NULL, NULL, NULL, NULL
+};
+
+static DLLINFO EEDefaults[] = {
+
+#if defined(HOST_MIPS)
+
+ NULL, "MIPS C++", "C++ with MIPS register set", "eecxxmip.dll", "",
+ NULL, "x86 C++", "C++ with x86 register set", "eecxxx86.dll", "",
+ NULL, "ALPHA C++", "C++ with ALPHA register set", "eecxxalp.dll", "",
+ NULL, "PPC C++", "C++ with PPC register set", "eecxxppc.dll", "",
+
+#elif defined(HOST_i386)
+
+ NULL, "x86 C++", "C++ with x86 register set", "eecxxx86.dll", "",
+ NULL, "MIPS C++", "C++ with MIPS register set", "eecxxmip.dll", "",
+ NULL, "ALPHA C++", "C++ with ALPHA register set", "eecxxalp.dll", "",
+ NULL, "PPC C++", "C++ with PPC register set", "eecxxppc.dll", "",
+
+#elif defined(HOST_ALPHA)
+
+ NULL, "ALPHA C++", "C++ with ALPHA register set", "eecxxalp.dll", "",
+ NULL, "MIPS C++", "C++ with MIPS register set", "eecxxmip.dll", "",
+ NULL, "x86 C++", "C++ with x86 register set", "eecxxx86.dll", "",
+ NULL, "PPC C++", "C++ with PPC register set", "eecxxppc.dll", "",
+
+#elif defined(HOST_PPC)
+
+ NULL, "PPC C++", "C++ with PPC register set", "eecxxppc.dll", "",
+ NULL, "ALPHA C++", "C++ with ALPHA register set", "eecxxalp.dll", "",
+ NULL, "MIPS C++", "C++ with MIPS register set", "eecxxmip.dll", "",
+ NULL, "x86 C++", "C++ with x86 register set", "eecxxx86.dll", "",
+
+#endif
+ NULL, NULL, NULL, NULL, NULL
+};
+
+static DLLINFO TLDefaults[] = {
+ NULL, "LOCAL", "Debugging on same machine", "tlloc.dll", "",
+ NULL, "PIPES", "Named pipe: host=targethost, pipe=windbg", "tlpipe.dll", "targethost windbg",
+ NULL, "SER3", "Serial - COM1, 300 baud", "tlser.dll", "com1:300",
+ NULL, "SER12", "Serial - COM1, 1200 baud", "tlser.dll", "com1:1200",
+ NULL, "SER24", "Serial - COM1, 2400 baud", "tlser.dll", "com1:2400",
+ NULL, "SER96", "Serial - COM1, 9600 baud", "tlser.dll", "com1:9600",
+ NULL, "SER192", "Serial - COM1, 19200 baud", "tlser.dll", "com1:19200",
+ NULL, NULL, NULL, NULL, NULL
+};
+
+static DLLINFO EMDefaults[] = {
+
+#if defined(HOST_MIPS)
+
+ NULL, "EMMip", "MIPS CPU", "emmip.dll", "",
+ NULL, "EMx86", "x86 CPU", "emx86.dll", "",
+ NULL, "EMAlpha", "ALPHA CPU", "emalp.dll", "",
+ NULL, "EMPPC", "PPC CPU", "emppc.dll", "",
+
+#elif defined(HOST_i386)
+
+ NULL, "EMx86", "x86 CPU", "emx86.dll", "",
+ NULL, "EMMip", "MIPS CPU", "emmip.dll", "",
+ NULL, "EMAlpha", "ALPHA CPU", "emalp.dll", "",
+ NULL, "EMPPC", "PPC CPU", "emppc.dll", "",
+
+#elif defined(HOST_ALPHA)
+
+ NULL, "EMAlpha", "ALPHA CPU", "emalp.dll", "",
+ NULL, "EMMip", "MIPS CPU", "emmip.dll", "",
+ NULL, "EMx86", "x86 CPU", "emx86.dll", "",
+ NULL, "EMPPC", "PPC CPU", "emppc.dll", "",
+
+#elif defined(HOST_PPC)
+
+ NULL, "EMPPC", "PPC CPU", "emppc.dll", "",
+ NULL, "EMAlpha", "ALPHA CPU", "emalp.dll", "",
+ NULL, "EMMip", "MIPS CPU", "emmip.dll", "",
+ NULL, "EMx86", "x86 CPU", "emx86.dll", "",
+
+#endif
+ NULL, NULL, NULL, NULL, NULL
+};
+
+/*************************************************************************/
+/* Initial values for each of the 4 DLL lists. */
+/*************************************************************************/
+static LISTINFO ListInfo[] = {
+ ID_DBUGDLL_SHCOMBO, DLL_SYMBOL_HANDLER, SH_KEY, SH_PREFIX, SHDefaults, NULL, NULL, FALSE, FALSE,
+ ID_DBUGDLL_EECOMBO, DLL_EXPR_EVAL, EE_KEY, EE_PREFIX, EEDefaults, NULL, NULL, FALSE, FALSE,
+ ID_DBUGDLL_TLCOMBO, DLL_TRANSPORT, TL_KEY, TL_PREFIX, TLDefaults, NULL, NULL, FALSE, FALSE,
+ ID_DBUGDLL_EMCOMBO, DLL_EXEC_MODEL, EM_KEY, EM_PREFIX, EMDefaults, NULL, NULL, FALSE, FALSE
+};
+#define LISTINFOSIZE (sizeof(ListInfo)/sizeof(LISTINFO))
+
+
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+
+/* exported functions */
+
+/*****************************************************************************/
+
+
+
+
+void
+SetDllName(
+ int iDll,
+ LPSTR lpName
+ )
+/*++
+
+Routine Description:
+
+ This sets the current DLL without using a registry key.
+ This is for use by e.g. a .opt command or command line
+ option. The corresponding key value will be cleared,
+ so that the combobox entry for this dll will be empty.
+
+Arguments:
+
+ iDll - Supplies the DLL index number
+ lpName - Supplies a pointer to the new name
+
+Returns:
+
+ nothing
+
+--*/
+{
+ if (rgszDllNames[iDll] != NULL) {
+ free(rgszDllNames[iDll]);
+ }
+ if (rgszDllKeys[iDll] != NULL) {
+ free(rgszDllKeys[iDll]);
+ rgszDllKeys[iDll] = NULL;
+ }
+
+ lpName += strspn( lpName, WHITESPACE );
+ rgszDllNames[iDll] = _strdup(lpName);
+
+ return;
+} /* SetDllName() */
+
+
+void
+SetDllKey(
+ int iDll,
+ LPSTR lpKey
+ )
+/*++
+
+Routine Description:
+
+ Sets the current DLL by registry key. Both the key
+ and the DLL command line will be remembered.
+
+Arguments:
+
+ iDll - Supplies the DLL index number
+ lpKey - Supplies pointer to the key name
+
+Returns:
+
+ nothing
+
+--*/
+{
+ char szBuf[2 * MAX_PATH];
+
+ if (!GetDllNameFromKey(iDll, lpKey, szBuf)) {
+ ErrorBox(ERR_Dll_Key_Missing,
+ lpKey,
+ LPKeyNameFromId(IdFromDllIndex(iDll)));
+ return;
+ }
+
+ if (rgszDllNames[iDll] != NULL) {
+ free(rgszDllNames[iDll]);
+ }
+ rgszDllNames[iDll] = _strdup(szBuf);
+
+ if (rgszDllKeys[iDll] != NULL) {
+ free(rgszDllKeys[iDll]);
+ }
+ rgszDllKeys[iDll] = _strdup(lpKey);
+
+ return;
+
+} /* SetDllKey() */
+
+
+LPSTR
+GetDllName(
+ int iDll
+ )
+/*++
+
+Routine Description:
+
+ Get the current DLL command line
+
+Arguments:
+
+ iDll - Supplies the DLL index number
+
+Returns:
+
+ A pointer to the current DLL command line for the
+ supplied index. It may be a NULL, meaning there is
+ no DLL currently selected.
+
+--*/
+{
+ return rgszDllNames[iDll];
+} /* GetDllName() */
+
+
+LPSTR
+GetDllKey(
+ int iDll
+ )
+/*++
+
+Routine Description:
+
+ Get the registry key for the current DLL
+
+Arguments:
+
+ iDll - Supplies DLL index number
+
+Returns:
+
+ A pointer to the registry key (just the base name) for
+ the supplied index. It will be NULL if there is no currently
+ selected DLL or it was set with SetDllName().
+
+--*/
+{
+ return rgszDllKeys[iDll];
+}
+
+
+BOOL
+GetDllNameFromKey(
+ int iDll,
+ LPSTR lpKey,
+ LPSTR lpBuf
+ )
+/*++
+
+Routine Description:
+
+ Get the DLL command line for a given key and index.
+
+Arguments:
+
+ iDll - Supplies DLL index number
+ lpKey - Supplies pointer to requested key
+ lpBuf - Supplies pointer to buffer to put string in.
+
+Returns:
+
+ TRUE if key is found, FALSE if not.
+
+--*/
+{
+ PDLLINFO pInfo;
+ int nId = IdFromDllIndex(iDll);
+ PDLLINFO * ppList = &PDLLListFromId(nId);
+ BOOL rVal = FALSE;
+
+ FillDLLInfoList(nId);
+
+ for (pInfo = *ppList; pInfo; pInfo = pInfo->pNext) {
+ if (_stricmp(lpKey, pInfo->pShortName) == 0) {
+ strcpy(lpBuf, pInfo->pPath);
+ if (pInfo->pParams && *(pInfo->pParams)) {
+ strcat(lpBuf, " ");
+ strcat(lpBuf, pInfo->pParams);
+ }
+ rVal = TRUE;
+ break;
+ }
+ }
+
+ return rVal;
+} /* GetDllNameFromKey() */
+
+
+BOOL
+GetDefaultDllKey(
+ int iDll,
+ LPSTR lpBuf
+ )
+/*++
+
+Routine Description:
+
+ Get the default key for a DLL type. Current implementation
+ says the default is the first in the list.
+
+Arguments:
+
+ iDll - Supplies DLL index number
+ lpBuf - Supplies pointer to a buffer to copy key into
+
+Returns:
+
+ TRUE if there is a list for iDll, FALSE if not.
+
+--*/
+{
+ BOOL rVal = FALSE;
+ int nId = IdFromDllIndex(iDll);
+ PDLLINFO * ppList = &PDLLListFromId(nId);
+
+ FillDLLInfoList(nId);
+
+ if (*ppList) {
+ strcpy(lpBuf, (*ppList)->pShortName);
+ rVal = TRUE;
+ }
+
+ return rVal;
+} /* GetDefaultDllKey() */
+
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+
+
+static PLISTINFO
+ListInfoFromId(
+ int nId
+ )
+/*++
+
+Routine Description:
+
+ Get the LISTINFO record for a DLL type.
+
+Arguments:
+
+ nId - Supplies the dialog id for the DLL type
+
+Returns:
+
+ A pointer to the LISTINFO record
+
+--*/
+{
+ static int idCache = -1;
+ static PLISTINFO pCache = NULL;
+
+ int i;
+
+ if (nId != idCache) {
+ idCache = nId;
+ pCache = NULL;
+ for (i = 0; i < LISTINFOSIZE; i++) {
+ if (ListInfo[i].nId == nId) {
+ pCache = (ListInfo + i);
+ break;
+ }
+ }
+ }
+ return pCache;
+}
+
+
+static int
+IdFromDllIndex(
+ int iDll
+ )
+/*++
+
+Routine Description:
+
+ Maps a DLL index number to a dialog ID number
+
+Arguments:
+
+ iDll - Supplies a DLL index number
+
+Returns:
+
+ Dialog id for DLL type, or -1 if there is none.
+
+--*/
+{
+ int i;
+ for (i = 0; i < LISTINFOSIZE; i++) {
+ if (ListInfo[i].nDllIndex == iDll) {
+ return ListInfo[i].nId;
+ }
+ }
+ return -1;
+}
+
+
+static void
+GetListItem(
+ int nId,
+ int nCurSel,
+ PDLLINFO ** pppList,
+ PDLLINFO * ppItem
+ )
+/*++
+
+Routine Description:
+
+ Get a DLLINFO item, and a pointer to the list head
+ pointer. This provides what is needed to manipulate
+ the list containing an item without much fuss.
+
+Arguments:
+
+ nId - Supplies Id of DLL type
+ nCurSel - Supplies list index to requested item
+ pppList - Returns pointer to list head pointer
+ ppItem - Returns pointer to list item
+
+Returns:
+
+ nothing
+
+--*/
+{
+ PDLLINFO pItem;
+ PDLLINFO * ppL;
+ int i;
+
+ ppL = &PDLLListFromId(nId);
+ Assert(ppL);
+ pItem = *ppL;
+
+ for (i = 0; i < nCurSel; i++) {
+ Assert(pItem);
+ pItem = pItem->pNext;
+ }
+
+ *pppList = ppL;
+ *ppItem = pItem;
+}
+
+
+static void
+DestroyDLLInfoList(
+ PDLLINFO * ppList
+ )
+/*++
+
+Routine Description:
+
+ Delete a linked list of DLLINFO items. Free all of the
+ contained data.
+
+Arguments:
+
+ ppList - Supplies pointer to pointer to list to be freed.
+
+Returns:
+
+ nothing. The Supplied pointer will be cleared.
+
+--*/
+{
+ PDLLINFO p;
+ PDLLINFO pList = *ppList;
+ while (pList) {
+ p = pList->pNext;
+ FreeItem(pList);
+ pList = p;
+ }
+ *ppList = NULL;
+}
+
+
+static void
+RemoveItem(
+ PDLLINFO * ppList,
+ PDLLINFO pItem
+ )
+/*++
+
+Routine Description:
+
+ Remove a DLLINFO item from a list. Does NOT free
+ the item.
+
+Arguments:
+
+ ppList - Supplies pointer to list head pointer
+ pItem - Supplies pointer to item
+
+Returns:
+
+ nothing
+
+--*/
+{
+ while (*ppList) {
+ if (*ppList == pItem) {
+ *ppList = pItem->pNext;
+ break;
+ }
+ ppList = &((*ppList)->pNext);
+ }
+}
+
+
+static void
+FreeItem(
+ PDLLINFO pItem
+ )
+/*++
+
+Routine Description:
+
+ Discard a DLLINFO record, and all contained data.
+
+Arguments:
+
+ pItem - Supplies pointer to item
+
+Returns:
+
+ nothing
+
+--*/
+{
+ if (pItem->pShortName) {
+ free(pItem->pShortName);
+ }
+ if (pItem->pDescription) {
+ free(pItem->pDescription);
+ }
+ if (pItem->pPath) {
+ free(pItem->pPath);
+ }
+ if (pItem->pParams) {
+ free(pItem->pParams);
+ }
+ free(pItem);
+}
+
+
+static void
+AddItem(
+ PDLLINFO *ppList,
+ PDLLINFO pItem
+ )
+/*++
+
+Routine Description:
+
+ Add item to end of list
+
+Arguments:
+
+ ppList - Supplies pointer to pointer to head of list
+ pItem - Supplies pointer to item to add
+
+Returns:
+
+ nothing
+
+--*/
+{
+ while (*ppList) {
+ ppList = &(*ppList)->pNext;
+ }
+ *ppList = pItem;
+ pItem->pNext = NULL;
+}
+
+
+static PDLLINFO
+DupItem(
+ PDLLINFO pSrc
+ )
+/*++
+
+Routine Description:
+
+ Make a copy of a DLLINFO record, making new copies
+ of all malloc'd data it contains.
+
+Arguments:
+
+ pSrc - Supplies pointer to item to copy
+
+Returns:
+
+ Pointer to new item.
+
+--*/
+{
+ PDLLINFO p = (PDLLINFO)malloc(sizeof(DLLINFO));
+ memset(p, 0, sizeof(DLLINFO));
+ if (pSrc->pShortName) {
+ p->pShortName = _strdup(pSrc->pShortName);
+ }
+ if (pSrc->pDescription) {
+ p->pDescription = _strdup(pSrc->pDescription);
+ }
+ if (pSrc->pPath) {
+ p->pPath = _strdup(pSrc->pPath);
+ }
+ if (pSrc->pParams) {
+ p->pParams = _strdup(pSrc->pParams);
+ }
+ return p;
+}
+
+
+static void
+DllEnumProc(
+ HKEY hKey,
+ LPSTR lpKeyName,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ Callback for EnumOptionItems. Collects DLLINFO entries
+ from registry to make a list.
+
+Arguments:
+
+ hKey - Supplies handle to dll list key in registry
+ lpKeyName - Supplies pointer to the name of the list entry
+ lParam - Supplies pointer to list head
+
+Returns:
+
+
+--*/
+{
+ DWORD dwSize;
+ char szBuf[MAX_PATH];
+ PDLLINFO *ppList = (PDLLINFO *)lParam;
+ PDLLINFO pItem = malloc(sizeof(DLLINFO));
+
+ memset(pItem, 0, sizeof(DLLINFO));
+
+ pItem->pShortName = _strdup(lpKeyName);
+
+ szBuf[0] = 0;
+ dwSize = sizeof(szBuf);
+ GetOptionSubItem(hKey, lpKeyName, DESCRIPTION, szBuf, &dwSize);
+ pItem->pDescription = _strdup(szBuf);
+
+ szBuf[0] = 0;
+ dwSize = sizeof(szBuf);
+ GetOptionSubItem(hKey, lpKeyName, PATH, szBuf, &dwSize);
+ pItem->pPath = _strdup(szBuf);
+
+ szBuf[0] = 0;
+ dwSize = sizeof(szBuf);
+ GetOptionSubItem(hKey, lpKeyName, PARAMS, szBuf, &dwSize);
+ pItem->pParams = _strdup(szBuf);
+
+ AddItem(ppList, pItem);
+}
+
+
+static void
+FormatEntry(
+ LPSTR lpBuf,
+ PDLLINFO pInfo
+ )
+/*++
+
+Routine Description:
+
+ Formats a DLLINFO record for display
+
+Arguments:
+
+ lpBuf - Supplies pointer to string to format into
+ pInfo - Supplies pointer to DLLINFO record
+
+Returns:
+
+ nothing
+
+--*/
+{
+ sprintf(lpBuf, "%-8s %s",
+ pInfo->pShortName,
+ pInfo->pDescription);
+}
+
+
+static void
+FillDLLInfoCombo(
+ HWND hDlg,
+ int nId
+)
+/*++
+
+Routine Description:
+
+ Fills a combo box from the corresponding DLLINFO list
+
+Arguments:
+
+ hDlg - Supplies handle to dialog box
+ nId - Supplies id for combobox
+
+Returns:
+
+ nothing
+
+--*/
+{
+ PDLLINFO pInfo;
+ char szBuf[MAX_PATH];
+ PDLLINFO * ppList = &PDLLListFromId(nId);
+ HWND hCtl = GetDlgItem(hDlg, nId);
+ int nSel;
+ int nItems;
+ LPSTR lpSelKey = rgszDllKeys[DllIndexFromId(nId)];
+
+ SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
+
+ nSel = -1;
+ nItems = 0;
+ for (pInfo = *ppList; pInfo; pInfo = pInfo->pNext) {
+ FormatEntry(szBuf, pInfo);
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuf);
+ if (lpSelKey && _stricmp(pInfo->pShortName, lpSelKey) == 0) {
+ nSel = nItems;
+ }
+ ++nItems;
+ }
+ SendMessage(hCtl, CB_SETCURSEL, nSel, 0);
+}
+
+
+static void
+FillDLLInfoList(
+ int nId
+ )
+/*++
+
+Routine Description:
+
+ Fills a DLLINFO list. List is retrieved from registry if
+ anything is stored there; otherwise the default list is loaded.
+
+Arguments:
+
+ nId - Dialog id for desired list
+
+Returns:
+
+ nothing
+
+--*/
+{
+ HKEY hKey;
+ PDLLINFO pInfo;
+ PDLLINFO pDefaults;
+ PDLLINFO * ppList = &PDLLListFromId(nId);
+
+ if (*ppList) {
+ return;
+ }
+
+ FDirtyFromId(nId) = FALSE;
+
+ if (!IgnoreDefault) {
+ hKey = GetOptionKey(LPKeyNameFromId(nId), TRUE);
+ EnumOptionItems(hKey, DllEnumProc, (LPARAM)(LPVOID)(ppList));
+ RegCloseKey(hKey);
+ }
+
+ if (*ppList) {
+
+ FLoadedFromId(nId) = TRUE;
+
+ } else {
+ //
+ // registry options list was empty
+ //
+ FLoadedFromId(nId) = FALSE;
+ pDefaults = PDefaultsFromId(nId);
+ while (pDefaults->pShortName) {
+
+ pInfo = malloc(sizeof(DLLINFO));
+ *pInfo = *pDefaults++;
+
+ pInfo->pShortName = _strdup(pInfo->pShortName);
+ pInfo->pDescription = _strdup(pInfo->pDescription);
+ pInfo->pPath = _strdup(pInfo->pPath);
+ pInfo->pParams = _strdup(pInfo->pParams);
+
+ AddItem(ppList, pInfo);
+ }
+ }
+
+ return;
+}
+
+
+static void
+SetDllFromId(
+ HWND hDlg,
+ int nId
+ )
+/*++
+
+Routine Description:
+
+ Sets current DLL for given type to the item selected in combobox
+
+Arguments:
+
+ hDlg - Supplies window handle for dialog
+ nId - Supplies dialog id of combobox
+
+Returns:
+
+ nothing
+
+--*/
+{
+ PDLLINFO * ppList;
+ PDLLINFO pInfo;
+
+ GetListItem(nId,
+ SendMessage(GetDlgItem(hDlg, nId), CB_GETCURSEL, 0, 0),
+ &ppList,
+ &pInfo);
+
+ SetDllKey(DllIndexFromId(nId), pInfo->pShortName);
+}
+
+
+static BOOL
+ValidateDLL(
+ HWND hDlg,
+ int nId
+ )
+/*++
+
+Routine Description:
+
+ Verify that the selected DLL exists and is the correct
+ type and version.
+
+Arguments:
+
+ hDlg - Supplies window handle for dialog
+ nId - Supplies id of combobox
+
+Returns:
+
+ TRUE if DLL is valid or user said use it anyway; FALSE otherwise
+
+--*/
+{
+ PDLLINFO * ppList;
+ PDLLINFO pInfo;
+ HANDLE hDll;
+ BOOL rVal = TRUE;
+
+ GetListItem(nId,
+ SendMessage(GetDlgItem(hDlg, nId), CB_GETCURSEL, 0, 0),
+ &ppList,
+ &pInfo);
+
+ if (pInfo
+ && pInfo->pPath
+ && (hDll = LoadHelperDll(pInfo->pPath, LPPrefixFromId(nId), FALSE))) {
+ FreeLibrary(hDll);
+ rVal = TRUE;
+ } else {
+ rVal = VarMsgBox(hDlg,
+ DBG_Bad_DLL_YESNO,
+ MB_YESNO | MB_ICONQUESTION,
+ pInfo? pInfo->pShortName: "");
+ rVal = (rVal == IDNO);
+ }
+
+ return rVal;
+}
+
+
+static void
+CleanDirtyDLLList(
+ HWND hDlg,
+ int nId,
+ BOOL fDoSave
+ )
+/*++
+
+Routine Description:
+
+ Do most of the "commit" business for the dialog. Execute
+ pending additions, changes and deletions on the registry.
+
+ Free the free list.
+
+ If fDoSave is FALSE, clean up lists, but don't change registry.
+
+Arguments:
+
+ hDlg - Supplies window handle for dialog
+ nId - Supplies id of combobox
+ fDoSave - Save/abort flag
+
+Returns:
+
+ nothing
+
+--*/
+{
+ HKEY hKey;
+ PDLLINFO pInfo;
+
+ if (!FDirtyFromId(nId)) {
+ return;
+ }
+
+ if (!fDoSave) {
+
+ // in the abort case, a dirty list must be
+ // discarded, because we don't have its initial
+ // state stored anywhere.
+
+ DestroyDLLInfoList(&PDLLListFromId(nId));
+
+ } else {
+
+ hKey = GetOptionKey(LPKeyNameFromId(nId), TRUE);
+
+ if (FLoadedFromId(nId)) {
+ for (pInfo = PFreeListFromId(nId); pInfo; pInfo = pInfo->pNext) {
+ DeleteOptionItem(hKey, pInfo->pShortName);
+ }
+ }
+
+ //
+ // save all of the ones on the list
+ //
+
+ for (pInfo = PDLLListFromId(nId); pInfo; pInfo = pInfo->pNext) {
+ SetOptionSubItem(hKey, pInfo->pShortName, DESCRIPTION, pInfo->pDescription);
+ SetOptionSubItem(hKey, pInfo->pShortName, PATH, pInfo->pPath);
+ SetOptionSubItem(hKey, pInfo->pShortName, PARAMS, pInfo->pParams);
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ DestroyDLLInfoList(&PFreeListFromId(nId));
+ FDirtyFromId(nId) = FALSE;
+}
+
+
+LRESULT CALLBACK
+ButtonSubProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (message) {
+ case WM_LBUTTONDOWN:
+ fActionButtonPressed = TRUE;
+ break;
+
+ case WM_LBUTTONUP:
+ fActionButtonPressed = FALSE;
+ if (SendMessage(hWnd, WM_NCHITTEST, 0, lParam) != HTCLIENT) {
+ PostMessage(GetParent(hWnd), WU_RESTOREFOCUS, 0, 0);
+ }
+ break;
+ }
+ return CallWindowProc(lpfnButtonProc, hWnd, message, wParam, lParam);
+}
+
+/*****************************************************************************/
+
+/* Dialog Procs */
+
+/*****************************************************************************/
+
+BOOL FAR PASCAL EXPORT
+DlgDbugdll(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+/*++
+
+Routine Description:
+
+ Processes messages for "Debug Dlls" dialog box
+
+Arguments:
+
+ hDlg - handle for the dialog box
+ message - Message number
+ wParam - parameter for message
+ lParam - parameter for message
+
+Return Value:
+
+ TRUE or FALSE - this is a DlgProc
+
+--*/
+{
+ PDLLINFO pInfo;
+ PDLLINFO * ppList;
+ CHDBDLGINFO cdi;
+ HWND hCtl;
+ int l;
+
+ static int nCurSel;
+ static int nIdCurrent;
+ static HFONT hFont;
+
+ static HWND hOK;
+ static HWND hCANCEL;
+ static HWND hHELP;
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+
+ hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT);
+
+ SendMessage(GetDlgItem(hDlg, ID_DBUGDLL_SHCOMBO), WM_SETFONT, (WPARAM)hFont, 0);
+ SendMessage(GetDlgItem(hDlg, ID_DBUGDLL_EECOMBO), WM_SETFONT, (WPARAM)hFont, 0);
+ SendMessage(GetDlgItem(hDlg, ID_DBUGDLL_TLCOMBO), WM_SETFONT, (WPARAM)hFont, 0);
+ SendMessage(GetDlgItem(hDlg, ID_DBUGDLL_EMCOMBO), WM_SETFONT, (WPARAM)hFont, 0);
+
+
+ FillDLLInfoList(ID_DBUGDLL_SHCOMBO);
+ FillDLLInfoCombo(hDlg, ID_DBUGDLL_SHCOMBO);
+
+ FillDLLInfoList(ID_DBUGDLL_EECOMBO);
+ FillDLLInfoCombo(hDlg, ID_DBUGDLL_EECOMBO);
+
+ FillDLLInfoList(ID_DBUGDLL_TLCOMBO);
+ FillDLLInfoCombo(hDlg, ID_DBUGDLL_TLCOMBO);
+
+ FillDLLInfoList(ID_DBUGDLL_EMCOMBO);
+ FillDLLInfoCombo(hDlg, ID_DBUGDLL_EMCOMBO);
+
+ nCurSel = -1;
+ nIdCurrent = -1;
+
+ hOK = GetDlgItem(hDlg, IDOK);
+ hCANCEL = GetDlgItem(hDlg, IDCANCEL);
+ hHELP = GetDlgItem(hDlg, IDWINDBGHELP);
+
+ // picky button magic...
+ lpfnButtonProc = (WNDPROC)GetWindowLong(
+ GetDlgItem(hDlg, ID_DBUGDLL_ADD),
+ GWL_WNDPROC);
+ SetWindowLong(GetDlgItem(hDlg, ID_DBUGDLL_ADD),
+ GWL_WNDPROC,
+ (LONG)ButtonSubProc);
+ SetWindowLong(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE),
+ GWL_WNDPROC,
+ (LONG)ButtonSubProc);
+ SetWindowLong(GetDlgItem(hDlg, ID_DBUGDLL_DELETE),
+ GWL_WNDPROC,
+ (LONG)ButtonSubProc);
+
+ return (TRUE);
+
+
+ case WM_DESTROY:
+ break;
+
+ case WU_RESTOREFOCUS:
+ SetOkButtonToDefault( hDlg );
+ if (nIdCurrent != -1) {
+ SetFocus(GetDlgItem(hDlg, nIdCurrent));
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+
+ //
+ // Notifications:
+ //
+
+ switch (LOWORD(wParam)) {
+
+ default:
+ break;
+
+ case ID_DBUGDLL_SHCOMBO:
+ case ID_DBUGDLL_EECOMBO:
+ case ID_DBUGDLL_TLCOMBO:
+ case ID_DBUGDLL_EMCOMBO:
+
+ switch (HIWORD(wParam)) {
+
+ default:
+ break;
+
+ case CBN_KILLFOCUS:
+ if (!fActionButtonPressed) {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_ADD), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_DELETE), FALSE);
+ }
+ break;
+
+ case CBN_SETFOCUS:
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_ADD), TRUE);
+ if (SendMessage((HWND)lParam, CB_GETCOUNT, 0, 0) > 0) {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE), TRUE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_DELETE), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_DELETE), FALSE);
+ }
+ // fall thru...
+
+ case CBN_SELCHANGE:
+ nIdCurrent = LOWORD(wParam);
+ nCurSel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
+ if (nCurSel >= 0) {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE), TRUE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_DELETE), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_DELETE), FALSE);
+ }
+
+ return TRUE;
+ }
+ }
+
+
+ //
+ // Commands:
+ //
+
+ switch (wParam) {
+ case ID_DBUGDLL_ADD:
+ //
+ // make an empty DLLINFO and bring up edit dlg
+ //
+
+ hCtl = GetDlgItem(hDlg, nIdCurrent);
+
+ pInfo = malloc(sizeof(DLLINFO));
+ memset(pInfo, 0, sizeof(DLLINFO));
+
+ cdi.pL = ListInfoFromId(nIdCurrent);
+ cdi.pD = pInfo;
+ cdi.fNew = TRUE;
+
+ if (DialogBoxParam(hInst,
+ MAKEINTRESOURCE(DLG_CH_DBUGDLL),
+ hDlg,
+ DlgChDbugDll,
+ (LPARAM)(LPVOID)&cdi))
+ {
+ FDirtyFromId(nIdCurrent) = TRUE;
+ AddItem(&PDLLListFromId(nIdCurrent), pInfo);
+ FillDLLInfoCombo(hDlg, nIdCurrent);
+ nCurSel = SendMessage(hCtl, CB_GETCOUNT, 0, 0) - 1;
+ SendMessage(hCtl, CB_SETCURSEL, nCurSel, 0);
+ } else {
+ FreeItem(pInfo);
+ }
+
+ SetOkButtonToDefault( hDlg );
+ SetFocus(GetDlgItem(hDlg, nIdCurrent));
+
+ return TRUE;
+
+ case ID_DBUGDLL_CHANGE:
+
+ //
+ // Invoke edit on the currently selected DLLINFO
+ //
+
+ hCtl = GetDlgItem(hDlg, nIdCurrent);
+
+ GetListItem(nIdCurrent, nCurSel, &ppList, &pInfo);
+
+ cdi.pL = ListInfoFromId(nIdCurrent);
+ cdi.pD = pInfo;
+ cdi.fNew = FALSE;
+
+ if (DialogBoxParam(hInst,
+ MAKEINTRESOURCE(DLG_CH_DBUGDLL),
+ hDlg,
+ DlgChDbugDll,
+ (LPARAM)(LPVOID)&cdi))
+
+ {
+ FDirtyFromId(nIdCurrent) = TRUE;
+ FillDLLInfoCombo(hDlg, nIdCurrent);
+ SendMessage(hCtl, CB_SETCURSEL, nCurSel, 0);
+ }
+
+ SetOkButtonToDefault( hDlg );
+ SetFocus(GetDlgItem(hDlg, nIdCurrent));
+
+ return TRUE;
+
+ case ID_DBUGDLL_DELETE:
+
+ hCtl = GetDlgItem(hDlg, nIdCurrent);
+
+ GetListItem(nIdCurrent, nCurSel, &ppList, &pInfo);
+
+ if (VarMsgBox(hDlg, DBG_Deleting_DLL, MB_OKCANCEL | MB_TASKMODAL,
+ LPKeyNameFromId(nIdCurrent), pInfo->pShortName) == IDOK) {
+
+ RemoveItem(ppList, pInfo);
+ AddItem(&PFreeListFromId(nIdCurrent), pInfo);
+ FDirtyFromId(nIdCurrent) = TRUE;
+
+ SendMessage(hCtl, CB_DELETESTRING, nCurSel, 0);
+ l = SendMessage(hCtl, CB_GETCOUNT, 0, 0);
+ if (l <= 0) {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_CHANGE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGDLL_DELETE), FALSE);
+ } else {
+ if (nCurSel >= l) {
+ nCurSel = 0;
+ }
+ SendMessage(hCtl, CB_SETCURSEL, nCurSel, 0);
+ }
+ }
+
+ SetOkButtonToDefault( hDlg );
+ SetFocus(GetDlgItem(hDlg, nIdCurrent));
+
+ return TRUE;
+
+
+ case IDOK:
+
+ //
+ // validate all the DLLs before changing anything
+ //
+
+ if (!ValidateDLL(hDlg, ID_DBUGDLL_SHCOMBO)) {
+ SetFocus(GetDlgItem(hDlg, ID_DBUGDLL_SHCOMBO));
+ PostMessage(hDlg, WM_COMMAND, ID_DBUGDLL_CHANGE, 0L);
+ } else if (!ValidateDLL(hDlg, ID_DBUGDLL_EECOMBO)) {
+ SetFocus(GetDlgItem(hDlg, ID_DBUGDLL_EECOMBO));
+ PostMessage(hDlg, WM_COMMAND, ID_DBUGDLL_CHANGE, 0L);
+ } else if (!ValidateDLL(hDlg, ID_DBUGDLL_TLCOMBO)) {
+ SetFocus(GetDlgItem(hDlg, ID_DBUGDLL_TLCOMBO));
+ PostMessage(hDlg, WM_COMMAND, ID_DBUGDLL_CHANGE, 0L);
+ } else if (!ValidateDLL(hDlg, ID_DBUGDLL_EMCOMBO)) {
+ SetFocus(GetDlgItem(hDlg, ID_DBUGDLL_EMCOMBO));
+ PostMessage(hDlg, WM_COMMAND, ID_DBUGDLL_CHANGE, 0L);
+ } else {
+
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_SHCOMBO, TRUE);
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_EECOMBO, TRUE);
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_TLCOMBO, TRUE);
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_EMCOMBO, TRUE);
+
+ SetDllFromId(hDlg, ID_DBUGDLL_SHCOMBO);
+ SetDllFromId(hDlg, ID_DBUGDLL_EECOMBO);
+ SetDllFromId(hDlg, ID_DBUGDLL_TLCOMBO);
+ SetDllFromId(hDlg, ID_DBUGDLL_EMCOMBO);
+
+ EnableRibbonControls( ERC_ALL, FALSE );
+
+ EndDialog(hDlg, TRUE);
+ }
+ return TRUE;
+
+ case IDCANCEL:
+
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_SHCOMBO, FALSE);
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_EECOMBO, FALSE);
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_TLCOMBO, FALSE);
+ CleanDirtyDLLList(hDlg, ID_DBUGDLL_EMCOMBO, FALSE);
+
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_DBUGDLL_HELP));
+ return TRUE;
+
+ }
+ return (TRUE);
+ }
+ return (FALSE);
+} /* DlgDbugdll */
+
+
+
+BOOL FAR PASCAL EXPORT
+DlgChDbugDll(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+/*++
+
+Routine Description:
+
+ Processes messages for "Change Debug Dll" dialog box
+
+Arguments:
+
+ hDlg - handle for the dialog box
+ message - Message number
+ wParam - parameter for message
+ lParam - parameter for message
+
+Return Value:
+
+ TRUE or FALSE - this is a DlgProc
+
+--*/
+{
+ int l;
+ PDLLINFO pt;
+
+ static PDLLINFO pInfo;
+ static PLISTINFO pList;
+ static BOOL fNew;
+
+
+
+ char szBuf[MAX_PATH+MAX_PATH];
+ switch (message) {
+
+ default:
+ break;
+
+ case WM_INITDIALOG:
+
+ //
+ // there will be a parameter, which is a PCHDBDLLINFO
+ // if the struct has pointers in it, initialize the
+ // edit boxes to contain the text pointed to.
+ //
+
+ Assert(lParam);
+ pInfo = ((PCHDBDLGINFO)lParam)->pD;
+ pList = ((PCHDBDLGINFO)lParam)->pL;
+ fNew = ((PCHDBDLGINFO)lParam)->fNew;
+
+ SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM) pList->lpName );
+
+ if (pInfo->pShortName) {
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_NAME),
+ WM_SETTEXT,
+ 0,
+ (LPARAM)(LPSTR)pInfo->pShortName);
+ }
+ EnableWindow(GetDlgItem(hDlg, ID_CHDBDLL_NAME), fNew);
+ if (pInfo->pDescription) {
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_DESC),
+ WM_SETTEXT,
+ 0,
+ (LPARAM)(LPSTR)pInfo->pDescription);
+ }
+ if (pInfo->pPath) {
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_PATH),
+ WM_SETTEXT,
+ 0,
+ (LPARAM)(LPSTR)pInfo->pPath);
+ }
+ if (pInfo->pParams) {
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_PARAM),
+ WM_SETTEXT,
+ 0,
+ (LPARAM)(LPSTR)pInfo->pParams);
+ }
+
+
+ return TRUE;
+
+ case WM_DESTROY:
+
+ break;
+
+ case WM_COMMAND:
+
+ switch (wParam) {
+
+ default:
+ break;
+
+ case IDOK:
+
+
+ //
+ // copy the strings into the DLLINFO struct
+ //
+
+ //
+ // Verify that key is not empty, and unique
+ //
+
+ if (SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_NAME),
+ WM_GETTEXT, sizeof(szBuf), (LPARAM)(LPSTR)szBuf) == 0) {
+ VarMsgBox(hDlg,
+ ERR_Empty_Shortname,
+ MB_OK | MB_ICONINFORMATION);
+ return TRUE;
+ }
+
+ for (pt = pList->pDLLList; pt; pt = pt->pNext) {
+ if (pt != pInfo && _stricmp(szBuf, pt->pShortName) == 0) {
+ VarMsgBox(hDlg,
+ ERR_Not_Unique_Shortname,
+ MB_OK | MB_ICONINFORMATION,
+ szBuf);
+ return TRUE;
+ }
+ }
+
+ if (pInfo->pShortName) {
+ free(pInfo->pShortName);
+ }
+ pInfo->pShortName = _strdup(szBuf);
+
+ if (pInfo->pDescription) {
+ free(pInfo->pDescription);
+ }
+ l = SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_DESC),
+ WM_GETTEXTLENGTH, 0, 0);
+ pInfo->pDescription = malloc(++l);
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_DESC),
+ WM_GETTEXT, l, (LPARAM)(LPSTR)pInfo->pDescription);
+
+ if (pInfo->pPath) {
+ free(pInfo->pPath);
+ }
+ l = SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_PATH),
+ WM_GETTEXTLENGTH, 0, 0);
+ pInfo->pPath = malloc(++l);
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_PATH),
+ WM_GETTEXT, l, (LPARAM)(LPSTR)pInfo->pPath);
+
+ if (pInfo->pParams) {
+ free(pInfo->pParams);
+ }
+ l = SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_PARAM),
+ WM_GETTEXTLENGTH, 0, 0);
+ pInfo->pParams = malloc(++l);
+ SendMessage(GetDlgItem(hDlg, ID_CHDBDLL_PARAM),
+ WM_GETTEXT, l, (LPARAM)(LPSTR)pInfo->pParams);
+
+ EndDialog(hDlg, TRUE);
+
+ return TRUE;
+
+
+ case IDCANCEL:
+
+ //
+ // bail out
+ //
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_CHDBDLL_HELP));
+ return TRUE;
+
+
+ }
+
+
+ }
+ return FALSE;
+}
diff --git a/private/windbg/windbg/dbugexcp.c b/private/windbg/windbg/dbugexcp.c
new file mode 100644
index 000000000..ce8351586
--- /dev/null
+++ b/private/windbg/windbg/dbugexcp.c
@@ -0,0 +1,1484 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dbugexcp.c
+
+Abstract:
+
+ This file contains the code for dealing with the Debug Exceptions
+ dialog box.
+
+Author:
+
+ Kent Forschmiedt (kentf) 02-15-1994
+ Griffith Wm. Kadnier (v-griffk) 09-25-1992
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include "dbugexcp.h"
+
+
+//
+// Externals
+//
+extern CXF CxfIp;
+
+extern EXCEPTION_LIST *DefaultExceptionList;
+
+
+//
+// Tabs in list box
+//
+INT ExTabs[] = { 10, 20 };
+#define NUMTABS 2
+
+struct {
+ EXCEPTION_FILTER_DEFAULT efd;
+ LPSTR lpName;
+} EfdMap[] = {
+ efdIgnore, "Ignore",
+ efdStop, "Enabled",
+ efdNotify, "Notify",
+ efdCommand,"Command"
+};
+#define NUMEFD (sizeof(EfdMap) / sizeof(EfdMap[0]))
+
+
+//
+// Local data
+
+static int LargestString;
+static EXCEPTION_LIST * pDisplayedList;
+static EXCEPTION_LIST * pOriginalList;
+static BOOL FSettingUp = FALSE;
+
+static int DbgExcpt__defButtonID;
+static WNDPROC DbgExcpt__origWindowProcADD;
+static HWND DbgExcpt__currDlg;
+
+struct {
+ LPSTR str;
+ DWORD val;
+} ExceptAbbrs[] = {
+ "av", (DWORD) EXCEPTION_ACCESS_VIOLATION,
+ "3c", (DWORD) 0xc0000037, //STATUS_PORT_DISCONNECTED
+ "ip", (DWORD) EXCEPTION_IN_PAGE_ERROR,
+ "cc", (DWORD) DBG_CONTROL_C,
+ "ce", (DWORD) CONTROL_C_EXIT,
+ "dz", (DWORD) EXCEPTION_INT_DIVIDE_BY_ZERO
+};
+
+#define EXCEPTION_ABBR_COUNT (sizeof(ExceptAbbrs)/sizeof(ExceptAbbrs[0]))
+
+
+
+//
+// Local functions
+//
+void
+SetFields(
+ HWND hDlg,
+ int idx
+ );
+
+static void
+AddExcptToListbox(
+ HWND hDlg,
+ EXCEPTION_LIST *eItem
+ );
+
+static void
+FillListbox(
+ HWND hDlg,
+ EXCEPTION_LIST *eList
+ );
+
+static void
+UpdateExcptInListbox(
+ HWND hDlg,
+ EXCEPTION_LIST *eItem
+ );
+
+
+static int
+ExcptIndex(
+ EXCEPTION_LIST * eList,
+ DWORD dwExcpt
+ );
+
+static EXCEPTION_LIST *
+GetExcpt(
+ EXCEPTION_LIST * eList,
+ int idx
+ );
+
+static EXCEPTION_LIST *
+DupExcpt(
+ EXCEPTION_LIST *eItem
+ );
+
+static void
+RemoveExcpt(
+ EXCEPTION_LIST ** peList,
+ EXCEPTION_LIST * eItem
+ );
+
+static void
+DeleteExcpt(
+ EXCEPTION_LIST *eItem
+ );
+
+static void
+DeleteList(
+ EXCEPTION_LIST *eList
+ );
+
+static LRESULT CALLBACK
+DbgExcpt__ButtonSubProcADD (HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam);
+
+static BOOL DbgExcpt__EndDialog (HWND hDlg, int result);
+
+static int DlgBox__GetDefButtonID (HWND hDlg);
+static BOOL DlgBox__SetDefButtonID (HWND hDlg, int idNewDefButton);
+
+
+/*** DlgDbugexceptions
+**
+** Synopsis:
+** bool = DlgDbugexceptions(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg - handle for the dialog box
+** message - Message number
+** wParam - parameter for message
+** lParam - parameter for message
+**
+** Returns:
+**
+**
+** Description:
+** Processes messages for "Debug Exception's" subdialog box
+**
+** MESSAGES:
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT
+DlgDbugexcept(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int idx;
+ int i;
+ DWORD dwExceptionCode;
+ char szStr[1000];
+ INT wTabs[NUMTABS];
+ long BaseUnit;
+ EXCEPTION_LIST *eItem;
+ EXCEPTION_DESCRIPTION exd;
+ char szText[MAX_CMDLINE_TXT];
+ char szCmd[MAX_CMDLINE_TXT];
+ char szCmd2[MAX_CMDLINE_TXT];
+ char **ppstr;
+
+ char szError[64];
+ int err;
+
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+
+ //
+ // Before we do anything else, we instance-subclass the ADD button
+ // to watch for WM_ENABLE messages. We want the ADD button
+ // to be the default button whenever it is enabled, but
+ // when it is disabled, we want the OK button to become the
+ // default.
+ //
+ DbgExcpt__currDlg = hDlg;
+ DbgExcpt__origWindowProcADD
+ = (WNDPROC) SetWindowLong (GetDlgItem (hDlg, ID_DBUGEXC_ADD),
+ GWL_WNDPROC,
+ (LONG) DbgExcpt__ButtonSubProcADD);
+
+ //
+ // If we don't have an exception list, we must load the EM and
+ // initialize the default exception list.
+ //
+ if ( !LppdCur && !DefaultExceptionList ) {
+ if ( !GetDefaultExceptionList() ) {
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+ }
+ }
+
+ BaseUnit = GetDialogBaseUnits();
+ for ( i = 0; i < NUMTABS; i++ ) {
+ wTabs[i] = ExTabs[i] * HIWORD(BaseUnit)/4;
+ }
+
+ //
+ // Initialize Action
+ //
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_ACTION, CB_RESETCONTENT, 0, 0L);
+ for (i = 0; i < NUMEFD; i++) {
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_ACTION, CB_ADDSTRING, 0,
+ (LPARAM)EfdMap[i].lpName);
+ }
+
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST, LB_SETTABSTOPS, NUMTABS,
+ (LPARAM)wTabs);
+ //
+ // Fill in the list box with current exceptions
+ //
+
+ pOriginalList = LppdCur ? LppdCur->exceptionList : DefaultExceptionList;
+ pDisplayedList = NULL;
+
+ for ( eItem = pOriginalList; eItem; eItem = eItem->next ) {
+ pDisplayedList = InsertException(pDisplayedList, DupExcpt(eItem));
+ }
+ FillListbox(hDlg, pDisplayedList);
+
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST, LB_SETCURSEL, (WPARAM)-1,
+ 0L);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGEXC_DELETE), FALSE);
+ EnableWindow(GetDlgItem(hDlg,ID_DBUGEXC_ADD), FALSE);
+
+ SetFields(hDlg, LB_ERR);
+
+ SetFocus( GetDlgItem( hDlg, ID_DBUGEXC_EXCNUM ) );
+
+
+ return TRUE;
+
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam)) {
+
+ case ID_DBUGEXC_CMD:
+ case ID_DBUGEXC_CMD2:
+ case ID_DBUGEXC_EXCNAME:
+
+ if (FSettingUp) {
+ break;
+ }
+
+ if (HIWORD(wParam) == EN_CHANGE &&
+ (idx = SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST,
+ LB_GETCURSEL, 0, 0L)) >= 0) {
+
+ eItem = GetExcpt(pDisplayedList, idx);
+ SendMessage((HWND)lParam, WM_GETTEXT, sizeof(szText),
+ (LPARAM)(LPSTR)szText);
+ switch(LOWORD(wParam)) {
+ case ID_DBUGEXC_CMD:
+ ppstr = &eItem->lpCmd;
+ break;
+ case ID_DBUGEXC_CMD2:
+ ppstr = &eItem->lpCmd2;
+ break;
+ case ID_DBUGEXC_EXCNAME:
+ ppstr = &eItem->lpName;
+ break;
+ }
+ if (*ppstr) {
+ free(*ppstr);
+ }
+ *ppstr = _strdup(szText);
+ UpdateExcptInListbox(hDlg, eItem);
+ }
+ break;
+
+ case ID_DBUGEXC_EXCNUM:
+
+ if (HIWORD(wParam) == EN_CHANGE) {
+
+ // get the value, try to match it with an existing one
+ GetDlgItemText(hDlg, ID_DBUGEXC_EXCNUM, (LPSTR)szStr,
+ MAX_CMDLINE_TXT);
+ err = (*szStr == 0);
+ if (!err) {
+ dwExceptionCode = CPGetNbr(szStr, 16, TRUE, &CxfIp,
+ (LPSTR)szError, &err);
+ }
+ if (!err) {
+ idx = ExcptIndex( pDisplayedList, dwExceptionCode);
+ }
+ if (err || idx < 0) {
+ // clear list selection
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST, LB_SETCURSEL,
+ (WPARAM)-1, 0);
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGEXC_DELETE), FALSE);
+ if (err) {
+ EnableWindow(GetDlgItem(hDlg,ID_DBUGEXC_ADD), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hDlg,ID_DBUGEXC_ADD), TRUE);
+ }
+ } else {
+ // it matches:
+ // select the matching list item
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST, LB_SETCURSEL,
+ idx, 0);
+ if (!FSettingUp) {
+ // LB_SETCURSEL does not send LBN_SELCHANGE, so:
+ SetFields(hDlg, idx);
+ }
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGEXC_DELETE), TRUE);
+ EnableWindow(GetDlgItem(hDlg,ID_DBUGEXC_ADD), FALSE);
+ }
+ }
+
+ break;
+
+
+ case ID_DBUGEXC_ACTION:
+
+ if (HIWORD(wParam) == CBN_SELCHANGE && !FSettingUp) {
+
+ SendMessage( (HWND)lParam,
+ CB_GETLBTEXT,
+ SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0L ),
+ (LPARAM)(LPSTR)szStr );
+ DAssert(*szStr);
+
+ for ( i = 0; i < NUMEFD; i++ ) {
+ if ( !_strcmpi( EfdMap[i].lpName, szStr ) ) {
+ break;
+ }
+ }
+ DAssert(i < NUMEFD);
+
+ idx = SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST,
+ LB_GETCURSEL, 0, 0L);
+ if (idx >= 0) {
+ eItem = GetExcpt(pDisplayedList, idx);
+ eItem->efd = EfdMap[i].efd;
+ UpdateExcptInListbox(hDlg, eItem);
+ }
+ }
+
+ break;
+
+
+ case ID_DBUGEXC_EXCLIST:
+
+ switch (HIWORD(wParam)) {
+ case LBN_SETFOCUS:
+ case LBN_SELCHANGE:
+
+ //
+ // Fill out edit fields with Exception info
+ //
+ idx = SendDlgItemMessage(hDlg,
+ ID_DBUGEXC_EXCLIST,
+ LB_GETCURSEL,
+ 0,
+ 0);
+ if (idx < 0) {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGEXC_DELETE), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hDlg, ID_DBUGEXC_DELETE), TRUE);
+ SetFields(hDlg, idx);
+ }
+ break;
+ }
+ break;
+
+
+ case ID_DBUGEXC_ADD:
+
+ if (HIWORD(wParam) != BN_CLICKED) {
+ break;
+ }
+
+ GetDlgItemText(hDlg,ID_DBUGEXC_EXCNUM,(LPSTR) szStr, sizeof(szStr));
+ DAssert(*szStr);
+
+ dwExceptionCode = CPGetNbr(szStr, radix, TRUE, &CxfIp,
+ (LPSTR)szError, &err);
+ DAssert(ExcptIndex(pDisplayedList, dwExceptionCode) == -1);
+
+ //dwExceptionCode &= 0xEFFFFFFF; // ?????????????????
+
+ GetDlgItemText(hDlg,ID_DBUGEXC_ACTION,(LPSTR) szStr, sizeof(szStr));
+ DAssert(*szStr);
+
+ for ( i = 0; i < NUMEFD; i++ ) {
+ if ( !_strcmpi( EfdMap[i].lpName, szStr ) ) {
+ break;
+ }
+ }
+ DAssert(i < NUMEFD);
+
+ //
+ // Seems ok, so add the exception to the list
+ //
+ GetDlgItemText(hDlg,ID_DBUGEXC_EXCNAME, (LPSTR)szText,
+ MAX_CMDLINE_TXT);
+ GetDlgItemText(hDlg,ID_DBUGEXC_CMD, (LPSTR)szCmd, MAX_CMDLINE_TXT);
+ GetDlgItemText(hDlg,ID_DBUGEXC_CMD2,(LPSTR)szCmd2,MAX_CMDLINE_TXT);
+
+ eItem = malloc(sizeof(EXCEPTION_LIST));
+ ZeroMemory(eItem, sizeof(*eItem));
+ eItem->dwExceptionCode = dwExceptionCode;
+ eItem->efd = EfdMap[i].efd;
+ if (*szText) {
+ eItem->lpName = _strdup(szText);
+ }
+ if (*szCmd) {
+ eItem->lpCmd = _strdup(szCmd);
+ }
+ if (*szCmd2) {
+ eItem->lpCmd2 = _strdup(szCmd2);
+ }
+
+ pDisplayedList = InsertException(pDisplayedList, eItem);
+ FillListbox(hDlg, pDisplayedList);
+ idx = ExcptIndex(pDisplayedList, eItem->dwExceptionCode);
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_EXCLIST, LB_SETCURSEL, idx, 0L);
+ EnableWindow((HWND)lParam, FALSE);
+ SetFocus( GetDlgItem( hDlg, ID_DBUGEXC_EXCNUM ) );
+
+ break;
+
+
+ case ID_DBUGEXC_DELETE:
+
+ if (HIWORD(wParam) != BN_CLICKED) {
+ break;
+ }
+
+ idx = SendDlgItemMessage(hDlg,ID_DBUGEXC_EXCLIST,LB_GETCURSEL,0,0L);
+ DAssert(idx >= 0);
+
+ eItem = GetExcpt(pDisplayedList, idx);
+ RemoveExcpt(&pDisplayedList, eItem);
+ DeleteExcpt(eItem);
+ SendDlgItemMessage(hDlg,ID_DBUGEXC_EXCLIST,LB_DELETESTRING,idx,0L);
+
+ //
+ // We want standard handling of the enable/disable situation after
+ // the Delete happens. We get it by notifying the dialog that there
+ // has been a change in the exception number...
+ //
+ PostMessage (hDlg, WM_COMMAND,
+ MAKEWPARAM(ID_DBUGEXC_EXCNUM,EN_CHANGE),
+ MAKELPARAM(0,0));
+
+ break;
+
+
+ case IDOK:
+
+ //
+ // if there is a process, walk the lists and
+ // update OSDebug.
+ //
+
+ if (LppdCur) {
+ for (eItem = pOriginalList; eItem; eItem = eItem->next) {
+ if (ExcptIndex(pDisplayedList,eItem->dwExceptionCode) < 0) {
+ exd.dwExceptionCode = eItem->dwExceptionCode;
+ OSDGetExceptionState(LppdCur->hpid,
+ NULL,
+ &exd,
+ exfSpecified
+ );
+ exd.efd = efdStop;
+ OSDSetExceptionState(LppdCur->hpid,
+ NULL,
+ &exd
+ );
+ }
+ }
+
+ for (eItem = pDisplayedList; eItem; eItem = eItem->next) {
+ exd.dwExceptionCode = eItem->dwExceptionCode;
+ OSDGetExceptionState(LppdCur->hpid,
+ NULL,
+ &exd,
+ exfSpecified
+ );
+ exd.efd = eItem->efd;
+ OSDSetExceptionState(LppdCur->hpid,
+ NULL,
+ &exd
+ );
+ }
+ }
+
+ // discard the original list
+ DeleteList(pOriginalList);
+
+ //
+ // the displayed list becomes the current one
+ //
+ // Remember that the exception list for process 0 is
+ // the default exception list. If we modified the
+ // exception list for process 0, update the Default
+ // exception list pointer.
+ //
+
+ if (!LppdCur || LppdCur->ipid == 0) {
+ DefaultExceptionList = pDisplayedList;
+ }
+ if (LppdCur) {
+ LppdCur->exceptionList = pDisplayedList;
+ }
+
+ EndDialog(hDlg, TRUE);
+ break;
+
+
+ case IDCANCEL:
+
+ DeleteList(pDisplayedList);
+ pDisplayedList = NULL;
+
+ EndDialog(hDlg, TRUE);
+ break;
+
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,
+ (DWORD)ID_DBUGEXC_HELP));
+ break;
+ }
+ return (TRUE);
+
+ }
+ return (FALSE);
+}
+
+
+void
+SetFields(
+ HWND hDlg,
+ int idx
+ )
+{
+ char Buffer[256];
+ int i;
+ EXCEPTION_LIST *eItem;
+
+ FSettingUp = TRUE;
+
+ if ( idx == LB_ERR ) {
+
+ SetDlgItemText(hDlg,ID_DBUGEXC_EXCNUM, (LPSTR)"");
+ SetDlgItemText(hDlg,ID_DBUGEXC_EXCNAME, (LPSTR)"");
+ SetDlgItemText(hDlg,ID_DBUGEXC_CMD, (LPSTR)"");
+ SetDlgItemText(hDlg,ID_DBUGEXC_CMD2, (LPSTR)"");
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_ACTION, CB_SETCURSEL, 0, 0L);
+
+ } else {
+
+ eItem = GetExcpt(pDisplayedList, idx);
+
+ sprintf( Buffer, "0x%08lx", eItem->dwExceptionCode );
+
+ SetDlgItemText(hDlg,ID_DBUGEXC_EXCNUM,(LPSTR)Buffer);
+
+ for ( i=0; i < NUMEFD; i++ ) {
+ if ( EfdMap[i].efd == eItem->efd ) {
+ break;
+ }
+ }
+ DAssert(i < NUMEFD);
+
+ SendDlgItemMessage(hDlg, ID_DBUGEXC_ACTION, CB_SELECTSTRING, 0,
+ (LPARAM)(LPSTR)EfdMap[i].lpName);
+ SetDlgItemText(hDlg,ID_DBUGEXC_EXCNAME, eItem->lpName);
+ SetDlgItemText(hDlg,ID_DBUGEXC_CMD, eItem->lpCmd);
+ SetDlgItemText(hDlg,ID_DBUGEXC_CMD2, eItem->lpCmd2);
+ }
+
+ FSettingUp = FALSE;
+}
+
+
+BOOL
+GetDefaultExceptionList (
+ VOID
+ )
+{
+ LPSTR szDll;
+ EMFUNC lpfnEm = NULL;
+ EXCEPTION_DESCRIPTION exd;
+ BOOL fRemoveEM = FALSE;
+
+ extern DBF Dbf;
+ extern HEM Hem;
+
+ if (HModEM == NULL) {
+ szDll = GetDllName(DLL_EXEC_MODEL);
+ if ((HModEM = LoadHelperDll(szDll, "EM", TRUE)) == 0) {
+ return FALSE;
+ }
+
+ if ((lpfnEm = (EMFUNC) GetProcAddress(HModEM, "EMFunc")) == NULL) {
+ FreeLibrary(HModEM);
+ HModEM = NULL;
+ return FALSE;
+ }
+
+ fRemoveEM = TRUE;
+ }
+
+
+ //
+ // Loop through all the exceptions known to OSDebug
+ //
+ OSDGetExceptionState(NULL, (HTID)lpfnEm, &exd, exfFirst);
+ do {
+
+ EXCEPTION_LIST *eList= (EXCEPTION_LIST*)malloc(sizeof(EXCEPTION_LIST));
+
+ eList->next = NULL;
+ eList->dwExceptionCode = exd.dwExceptionCode;
+ eList->efd = exd.efd;
+ eList->lpName = _strdup(exd.rgchDescription);
+ eList->lpCmd = NULL;
+ eList->lpCmd2 = NULL;
+
+ DefaultExceptionList = InsertException( DefaultExceptionList, eList );
+
+ } while (OSDGetExceptionState(NULL, (HTID)lpfnEm, &exd, exfNext) == xosdNone);
+
+ if (fRemoveEM) {
+ FreeLibrary(HModEM);
+ HModEM = NULL;
+ }
+
+ return TRUE;
+}
+
+
+
+LOGERR
+ParseException(
+ LPSTR String,
+ UINT Radix,
+ BOOLEAN *fException,
+ BOOLEAN *fEfd,
+ BOOLEAN *fName,
+ BOOLEAN *fCmd,
+ BOOLEAN *fCmd2,
+ BOOLEAN *fInvalid,
+ DWORD *pException,
+ EXCEPTION_FILTER_DEFAULT *pEfd,
+ LPSTR *lpName,
+ LPSTR *lpCmd,
+ LPSTR *lpCmd2
+ )
+/*++
+
+Routine Description:
+
+ Parses an exception string.
+
+Arguments:
+
+ String - Exception String
+
+ Radix - Radix to use for converting exception number
+
+ fException - TRUE if exception present
+
+ fName - TRUE if name present
+
+ fCmd - TRUE if /C present
+
+ fCmd2 - TRUE if /C2 present
+
+ fInvalid - TRUE if invalid exception
+
+ pException - Pointer to exception No.
+
+ lpName - Pointer to name
+
+ lpCmd - Pointer to Cmd
+
+ lpCmd2 - Pointer to Cmd2
+
+Return Value:
+
+ LOGERROR_NOERROR or error code.
+
+--*/
+{
+ int n;
+ char error[64];
+ int err;
+ BOOLEAN fSecond;
+ char szStr[MAX_USER_LINE];
+ char szCmd[MAX_USER_LINE];
+ LPSTR lp;
+ char chTmp;
+ LPSTR lpStr;
+ LPSTR lpsz = String;
+ LOGERR rVal = LOGERROR_NOERROR;
+ BOOLEAN fInName = FALSE;
+
+ //
+ // Initialize stuff
+ //
+ *fException = FALSE;
+ *fName = FALSE;
+ *fCmd = FALSE;
+ *fCmd2 = FALSE;
+ *fInvalid = FALSE;
+ *lpName = NULL;
+ *lpCmd = NULL;
+ *lpCmd2 = NULL;
+
+ //
+ // Parse exception number. It is always the first token after the command
+ //
+ lpsz = CPSkipWhitespace(lpsz);
+ if ( *lpsz ) {
+
+ n = CPCopyToken( &lpsz, szStr );
+ if ( n == 0 ) {
+ rVal = LOGERROR_QUIET;
+ *fInvalid = TRUE;
+ goto done;
+ }
+
+ err = 1;
+ for (n = 0; n < EXCEPTION_ABBR_COUNT; n++) {
+ if (_strcmpi(szStr, ExceptAbbrs[n].str) == 0) {
+ *pException = ExceptAbbrs[n].val;
+ err = 0;
+ break;
+ }
+ }
+
+ if (err) {
+ *pException = CPGetNbr(szStr, Radix, TRUE, &CxfIp, (LPSTR)error, &err);
+ }
+
+ if ( !err ) {
+ *fException = TRUE;
+ } else {
+ rVal = LOGERROR_QUIET;
+ *fInvalid = TRUE;
+ goto done;
+ }
+
+ lpsz = CPSkipWhitespace( lpsz );
+ }
+
+ //
+ // If required to parse EFD, do it
+ //
+ if ( *lpsz && fEfd && pEfd ) {
+
+ *fEfd = FALSE;
+
+ n = CPCopyToken( &lpsz, szStr );
+
+ if ( n == 0 ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ if ( !_strcmpi( szStr, "Deleted" ) ) {
+ *pEfd = (EXCEPTION_FILTER_DEFAULT)-1;
+ *fEfd = TRUE;
+ } else if ( !_strcmpi( szStr, "Disabled" ) ) {
+ *pEfd = efdIgnore;
+ *fEfd = TRUE;
+ } else {
+ for ( n = 0; n < NUMEFD; n++ ) {
+ if ( !_strcmpi( EfdMap[n].lpName, szStr ) ) {
+ *pEfd = EfdMap[n].efd;
+ *fEfd = TRUE;
+ break;
+ }
+ }
+ }
+
+ lpsz = CPSkipWhitespace( lpsz );
+ }
+
+ //
+ // Parse the rest of the line
+ //
+ lpStr = szStr;
+ *lpStr = '\0';
+
+ if ( *lpsz ) {
+
+ while ( *lpsz ) {
+
+ if ( *lpsz == '/' && !fInName ) {
+
+ //
+ // Switch
+ //
+ lpsz++;
+ switch ( *lpsz ) {
+ case 'c':
+ case 'C':
+
+ //
+ // /C or /C2 switches
+ //
+ lpsz++;
+ if ( *lpsz == '2' ) {
+ fSecond = TRUE;
+ lpsz++;
+ } else {
+ fSecond = FALSE;
+ }
+
+ if ( (*fCmd && !fSecond) || (*fCmd2 && fSecond) ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ if ( *lpsz == '"' ) {
+ //
+ // Get up to matching quote
+ //
+ lpsz++;
+ if ( lp = strchr( lpsz, '"' ) ) {
+
+ chTmp = *lp;
+ *lp = '\0';
+
+ strcpy( szCmd, lpsz );
+
+ *lp = chTmp;
+ lpsz = lp+1;
+
+ } else {
+
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ } else {
+
+ //
+ // Get up to matching blank
+ //
+ n = strcspn( lpsz, " \t" );
+ chTmp = *(lpsz + n);
+ *(lpsz + n) = '\0';
+
+ strcpy( szCmd, lpsz );
+
+ *(lpsz + n) = chTmp;
+ lpsz += n;
+ }
+
+ if ( fSecond ) {
+ *fCmd2 = TRUE;
+ if ( *szCmd ) {
+ *lpCmd2 = _strdup(szCmd);
+ }
+ } else {
+ *fCmd = TRUE;
+ if ( *szCmd ) {
+ *lpCmd = _strdup(szCmd);
+ }
+ }
+
+ lpsz = CPSkipWhitespace( lpsz );
+ break;
+
+ default:
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ } else {
+
+ //
+ // Exception Text
+ //
+
+ if ( *fCmd || *fCmd2 ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ //
+ // Keep adding to name
+ //
+ if ( *lpsz == '"' ) {
+ //
+ // Quoted string, copy up to matching quote
+ //
+ lpsz++;
+ while ( *lpsz && *lpsz != '"' ) {
+ *lpStr++ = *lpsz++;
+ }
+
+ if ( *lpsz != '"' ) {
+ rVal = LOGERROR_UNKNOWN;
+ goto done;
+ }
+
+ lpsz++;
+
+ } else {
+
+ fInName = ( *lpsz != ' ' && *lpsz != '\t' );
+
+ *lpStr++ = *lpsz++;
+ }
+ }
+ }
+
+ //
+ // Remove blanks at end of text.
+ //
+ *lpStr = '\0';
+ while ( lpStr > szStr && (*lpStr == ' '|| *lpStr == '\t' ) ) {
+ *lpStr-- = '\0';
+ }
+
+ if ( *szStr ) {
+ *lpName = _strdup( szStr );
+ *fName = TRUE;
+ }
+ }
+
+done:
+ if ( rVal == LOGERROR_UNKNOWN ) {
+ //
+ // Free allocated memory
+ //
+ if ( *lpName ) {
+ free( *lpName );
+ *lpName = NULL;
+ *fName = FALSE;
+ }
+ if ( *lpCmd ) {
+ free( *lpCmd );
+ *lpCmd = NULL;
+ *fCmd = FALSE;
+ }
+
+ if ( *lpCmd2 ) {
+ free( *lpCmd2 );
+ *lpCmd2 = NULL;
+ *fCmd2 = FALSE;
+ }
+ }
+
+ return rVal;
+}
+
+
+void
+FormatException (
+ EXCEPTION_FILTER_DEFAULT Efd,
+ DWORD Exception,
+ LPSTR lpName,
+ LPSTR lpCmd,
+ LPSTR lpCmd2,
+ LPSTR Separator,
+ LPSTR Buffer
+ )
+/*++
+
+Routine Description:
+
+ Formats an exception
+
+Arguments:
+
+ Efd - Efd
+ Exception - Exception code
+ lpName - Name
+ lpCmd - Cmd
+ lpCmd2 - Cmd2
+ Separator - Separator
+ Buffer - Output buffer
+
+Return Value:
+
+ none
+
+--*/
+{
+
+ LPSTR lpAction;
+ BOOLEAN Quote;
+ int i;
+
+
+ if ( Efd == (EXCEPTION_FILTER_DEFAULT)-1) {
+ lpAction = "Deleted";
+ } else {
+ for ( i = 0; i < NUMEFD; i++ ) {
+ if ( EfdMap[i].efd == Efd ) {
+ lpAction = EfdMap[i].lpName;
+ break;
+ }
+ }
+ }
+
+ sprintf( Buffer,"%08lx%s%-8.8s%s%s",
+ Exception,
+ Separator,
+ lpAction,
+ Separator,
+ (lpName && *lpName) ? lpName : "Unknown");
+
+ if (lpCmd && *lpCmd) {
+ strcat( Buffer, " /C" );
+ Quote = ( strcspn( lpCmd, " \t" ) < strlen( lpCmd ) );
+ if ( Quote ) {
+ strcat( Buffer, "\"" );
+ }
+ strcat( Buffer, lpCmd );
+ if ( Quote ) {
+ strcat( Buffer, "\"" );
+ }
+ }
+
+ if (lpCmd2 && *lpCmd2) {
+ strcat( Buffer, " /C2" );
+ Quote = ( strcspn( lpCmd2, " \t" ) < strlen( lpCmd2 ) );
+ if ( Quote ) {
+ strcat( Buffer, "\"" );
+ }
+ strcat( Buffer, lpCmd2 );
+ if ( Quote ) {
+ strcat( Buffer, "\"" );
+ }
+ }
+}
+
+
+EXCEPTION_LIST *
+InsertException(
+ EXCEPTION_LIST *List,
+ EXCEPTION_LIST *eList
+ )
+{
+ EXCEPTION_LIST *Prev = NULL;
+ EXCEPTION_LIST *Excep = List;
+
+ while ( Excep && (Excep->dwExceptionCode < eList->dwExceptionCode) ) {
+ Prev = Excep;
+ Excep = Excep->next;
+ }
+
+ eList->next = Excep;
+ if ( Prev ) {
+ Prev->next = eList;
+ } else {
+ List = eList;
+ }
+
+ return List;
+}
+
+
+
+
+static int
+ExcptIndex(
+ EXCEPTION_LIST * eList,
+ DWORD dwExcpt
+ )
+{
+ int i = 0;
+ while (eList) {
+ if (eList->dwExceptionCode == dwExcpt) {
+ return i;
+ }
+ eList = eList->next;
+ i++;
+ }
+ return -1;
+}
+
+
+static EXCEPTION_LIST *
+GetExcpt(
+ EXCEPTION_LIST * eList,
+ int idx
+ )
+{
+ while (eList && idx) {
+ eList = eList->next;
+ idx--;
+ }
+ DAssert(eList);
+ return eList;
+}
+
+
+static void
+FillListbox(
+ HWND hDlg,
+ EXCEPTION_LIST *eList
+ )
+{
+ HDC hdc;
+ SIZE Size;
+ char szStr[2000];
+ HWND hwnd = GetDlgItem(hDlg, ID_DBUGEXC_EXCLIST);
+
+ SendMessage(hwnd, LB_RESETCONTENT, 0, 0L);
+ LargestString = 0;
+
+ while (eList) {
+ FormatException( eList->efd, eList->dwExceptionCode,
+ eList->lpName, eList->lpCmd,
+ eList->lpCmd2, "\t", szStr );
+
+ hdc = GetDC(hwnd);
+ GetTextExtentPoint(hdc, szStr, strlen(szStr), &Size );
+ ReleaseDC(hwnd, hdc );
+
+ if ( Size.cx > LargestString ) {
+ LargestString = Size.cx;
+ SendMessage(hwnd, LB_SETHORIZONTALEXTENT, (WPARAM)LargestString, 0);
+ }
+
+ SendMessage(hwnd, LB_ADDSTRING, 0, (LONG)((LPSTR)szStr));
+
+ eList = eList->next;
+ }
+}
+
+
+static void
+UpdateExcptInListbox(
+ HWND hDlg,
+ EXCEPTION_LIST *eItem
+ )
+{
+ HDC hdc;
+ SIZE Size;
+ char szStr[2000];
+ HWND hwnd = GetDlgItem(hDlg, ID_DBUGEXC_EXCLIST);
+ int idx = ExcptIndex(pDisplayedList, eItem->dwExceptionCode);
+ int oldsel = SendMessage(hwnd, LB_GETCURSEL, 0, 0L);
+
+ DAssert(idx >= 0);
+
+ if (idx < 0) {
+ return;
+ }
+
+ FormatException( eItem->efd, eItem->dwExceptionCode,
+ eItem->lpName, eItem->lpCmd,
+ eItem->lpCmd2, "\t", szStr );
+
+ hdc = GetDC(hwnd);
+ GetTextExtentPoint(hdc, szStr, strlen(szStr), &Size );
+ ReleaseDC(hwnd, hdc);
+
+ if ( Size.cx > LargestString ) {
+ LargestString = Size.cx;
+ SendMessage(hwnd, LB_SETHORIZONTALEXTENT, (WPARAM)LargestString, 0 );
+ }
+ SendMessage(hwnd, LB_DELETESTRING, idx, 0L);
+ SendMessage(hwnd, LB_INSERTSTRING, idx, (LPARAM)(LPSTR)szStr);
+ SendMessage(hwnd, LB_SETCURSEL, oldsel, 0L);
+}
+
+
+static EXCEPTION_LIST *
+DupExcpt(
+ EXCEPTION_LIST *eList
+ )
+{
+ EXCEPTION_LIST *e = (EXCEPTION_LIST*)malloc(sizeof(*e));
+ if (e) {
+ memcpy(e, eList, sizeof(*e));
+ }
+ if (e->lpName) {
+ e->lpName = _strdup(e->lpName);
+ }
+ if (e->lpCmd) {
+ e->lpCmd = _strdup(e->lpCmd);
+ }
+ if (e->lpCmd2) {
+ e->lpCmd2 = _strdup(e->lpCmd2);
+ }
+ return e;
+}
+
+
+static void
+RemoveExcpt(
+ EXCEPTION_LIST ** peList,
+ EXCEPTION_LIST * eItem
+ )
+{
+ while (*peList) {
+ if (*peList == eItem) {
+ *peList = (*peList)->next;
+ return;
+ }
+ peList = &(*peList)->next;
+ }
+}
+
+
+static void
+DeleteExcpt(
+ EXCEPTION_LIST *eItem
+ )
+{
+ if (eItem->lpName) {
+ free(eItem->lpName);
+ }
+ if (eItem->lpCmd) {
+ free(eItem->lpCmd);
+ }
+ if (eItem->lpCmd2) {
+ free(eItem->lpCmd2);
+ }
+ free(eItem);
+}
+
+
+static void
+DeleteList(
+ EXCEPTION_LIST *eList
+ )
+{
+ EXCEPTION_LIST *e;
+ while (eList) {
+ e = eList->next;
+ DeleteExcpt(eList);
+ eList = e;
+ }
+}
+
+
+/****************************************************************************
+*
+* static int DlgBox__GetDefButtonID (hDlg)
+*
+* "Get the ID of the dialog's default button, if there is one."
+*
+* Answers: the ID of the default button, if found; otherwise, 0.
+*
+* Requires: hDlg is a valid dialog handle.
+*
+* Ensures: true
+*
+* Modifies: <nothing>
+*
+* Raises: <nothing>
+*
+* COMMENTS: If 'hDlg' is not a valid window, then we return 0, also.
+*
+\***************************************************************************/
+
+static int
+DlgBox__GetDefButtonID (HWND hDlg)
+{
+ int answer = 0;
+
+ if (!IsWindow (hDlg))
+ { answer = 0; }
+ else
+ {
+ int work = SendMessage (hDlg, DM_GETDEFID, 0, 0);
+
+ answer = ((HIWORD(work)) == DC_HASDEFID)
+ ? ((int)(LOWORD (work)))
+ : 0;
+ }
+
+ return (answer);
+}
+
+
+
+/****************************************************************************
+*
+* static BOOL DlgBox__SetDefButtonID (hDlg, idNewDefButton)
+*
+* "Set the dialog's default button ID."
+*
+* Answers: TRUE if the action completes; FALSE otherwise.
+*
+* Requires: hDlg is a valid dialog handle;
+* iNewDefButton is non-zero.
+*
+* Ensures: if 'idNewDefButton' is the current default ID, then
+* nothing happens;
+* else
+* the dialog's default button is set to 'idNewDefButton';
+* the previous default button's border is set to BS_PUSHBUTTON;
+* endif
+*
+* Modifies: *hDlg
+*
+* Raises: <nothing>
+*
+* COMMENTS: <none>
+*
+\***************************************************************************/
+
+static BOOL
+DlgBox__SetDefButtonID (HWND hDlg, int idNewDefButton)
+{
+ BOOL answer = FALSE;
+
+ if (!IsWindow (hDlg) || idNewDefButton == 0)
+ { answer = FALSE; }
+
+ else
+ {
+ BOOL idCurrDefButton = DlgBox__GetDefButtonID (hDlg);
+
+ answer = TRUE;
+
+ if (idCurrDefButton != idNewDefButton)
+ {
+
+ if (idCurrDefButton != 0)
+ {
+ (void)
+ SendDlgItemMessage (hDlg, idCurrDefButton,
+ BM_SETSTYLE,
+ ((WPARAM) (LOWORD (BS_PUSHBUTTON))),
+ MAKELPARAM (TRUE, 0));
+ }
+
+ (void)
+ SendMessage (hDlg, DM_SETDEFID,
+ idNewDefButton,
+ 0);
+ }
+ }
+
+ return (answer);
+}
+
+
+
+
+/****************************************************************************
+*
+* static LRESULT CALLBACK DbgExcpt__ButtonSubProcADD (hWnd, message,
+* wParam,
+* lParam)
+*
+* "The WindowProc to be used when subclassing the ADD button. Our
+* goal is to have either the ADD button or the OK button be the default,
+* choosing the former whenever it has been enabled, otherwise the latter."
+*
+* Answers: The result of CallWindowProc(), invoked against the
+* parent dialog (here, stored in a static variable at
+* file scope).
+*
+* Requires: hWnd is the Exceptions dialog's ADD window.
+*
+* Ensures: if this window is being enabled, then
+* it is the default button for the dialog
+* else
+* the OK button is the default button for the dialog
+* endif
+* finally
+* the original WindowProc() is invoked against the parent;
+* endfinally
+*
+* Modifies: <nothing>
+*
+* Raises: <nothing>
+*
+* COMMENTS: The instance-subclassing actions are in WM_INITDIALOG.
+*
+\***************************************************************************/
+
+static LRESULT CALLBACK
+DbgExcpt__ButtonSubProcADD (HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (message)
+ {
+ default:
+ break;
+
+ case (WM_ENABLE):
+ {
+ BOOL isEnabled = ((BOOL) wParam);
+ if (isEnabled)
+ { DlgBox__SetDefButtonID (DbgExcpt__currDlg, ID_DBUGEXC_ADD); }
+ else
+ { DlgBox__SetDefButtonID (DbgExcpt__currDlg, IDOK); }
+ }
+ break;
+ }
+
+ return (CallWindowProc (DbgExcpt__origWindowProcADD,
+ hWnd,
+ message, wParam, lParam));
+}
+
+
+
+
+/****************************************************************************
+*
+* static BOOL DbgExcpt__EndDialog (hDlg, result)
+*
+* "Before we call EndDialog(), we ensure that the static variables
+* are in a vacant state."
+*
+* Answers: The result of calling EndDialog().
+*
+* Requires: true
+*
+* Ensures: All static variables have been reset to their initial values.
+*
+* Modifies: All static varaibles.
+*
+* Raises: <nothing>
+*
+* COMMENTS: Just in case, eh?
+*
+\***************************************************************************/
+
+static BOOL
+DbgExcpt__EndDialog (HWND hDlg, int result)
+{
+ LargestString = 0;
+ pDisplayedList = 0;
+ pOriginalList = 0;
+ FSettingUp = FALSE;
+
+ DbgExcpt__defButtonID = 0;
+ DbgExcpt__origWindowProcADD = 0;
+ DbgExcpt__currDlg = 0;
+
+ return (EndDialog (hDlg, result));
+}
diff --git a/private/windbg/windbg/dbugrun.c b/private/windbg/windbg/dbugrun.c
new file mode 100644
index 000000000..638e75b85
--- /dev/null
+++ b/private/windbg/windbg/dbugrun.c
@@ -0,0 +1,167 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dbugrun.c
+
+Abstract:
+
+ This file has the code for dealing with the Debug Run dialog box
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 09-30-1992
+ Craig Derouen (v-craigd)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+/*** DlgDbugrun
+**
+** Synopsis:
+** bool = DlgDbugrun(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg - handle for the dialog box
+** message - Message number
+** wParam - parameter for message
+** lParam - parameter for message
+**
+** Returns:
+**
+**
+** Description:
+** Processes messages for "Run Options" subdialog box
+**
+** MESSAGES:
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT
+DlgDbugrun(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ int bRet;
+ int n;
+ LPSTR lpTemp;
+ char szTemp[MAX_PATH];
+
+ static LPSTR lpNewDb;
+ static LPSTR lpOldDb;
+
+#define ZFREE(P) ((P)?(free(P),((P)=(void*)0)):(void*)0)
+
+ Unused(lParam);
+
+ switch (message) {
+
+ default:
+ break;
+
+ case WM_INITDIALOG:
+
+ /*
+ * Parse out the parameters
+ */
+
+ lpTemp = GetCurrentProgramName(TRUE);
+ AdjustFullPathName(lpTemp, szTemp, 27);
+
+ SetDlgItemText(hDlg, ID_DBUGRUN_RTEXT, szTemp);
+
+ ZFREE(lpNewDb);
+ ZFREE(lpOldDb);
+
+ if (GetCurrentProgramName( FALSE )) {
+
+ if (!LpszCommandLine) {
+ LpszCommandLine = malloc(1);
+ *LpszCommandLine = 0;
+ }
+
+ lpTemp = LpszCommandLine;
+ while (isspace(*lpTemp)) {
+ lpTemp++;
+ }
+
+ lpOldDb = _strdup(lpTemp);
+
+ SetDlgItemText(hDlg,ID_DBUGRUN_ATEXT, lpOldDb);
+ }
+ return (TRUE);
+
+
+ case WM_COMMAND:
+ switch (wParam) {
+
+ case IDOK:
+
+ n = SendDlgItemMessage(hDlg,
+ ID_DBUGRUN_ATEXT,
+ WM_GETTEXTLENGTH,
+ 0,
+ 0);
+ lpNewDb = malloc(n + 1);
+ GetDlgItemText(hDlg,
+ ID_DBUGRUN_ATEXT,
+ lpNewDb,
+ n+1);
+
+ //strip out leading whitespace
+
+ lpTemp = lpNewDb;
+ while (isspace(*lpTemp)) {
+ lpTemp++;
+ }
+
+ if (strcmp (lpTemp, lpOldDb)) {
+ ZFREE(LpszCommandLine);
+ LpszCommandLine = _strdup(lpTemp);
+
+ if (DebuggeeAlive()) {
+ bRet = MessageBox (hDlg,
+ "Arguments have changed... Restart now with new arguments?",
+ "Program Arguments",
+ MB_APPLMODAL | MB_ICONQUESTION | MB_YESNO);
+
+ if (bRet == IDYES) {
+ PostMessage (hwndFrame,
+ WM_COMMAND,
+ IDM_RUN_RESTART,
+ 0L);
+ }
+ }
+ }
+
+ /*
+ * Fall through
+ */
+
+ case IDCANCEL:
+ ZFREE(lpOldDb);
+ ZFREE(lpNewDb);
+ EndDialog(hDlg, TRUE);
+ break;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_DBUGRUN_HELP));
+ break;
+
+ }
+ return (TRUE);
+
+ }
+ return (FALSE);
+} /* DlgDbugrun */
diff --git a/private/windbg/windbg/dialogs.dlg b/private/windbg/windbg/dialogs.dlg
new file mode 100644
index 000000000..807091f3d
--- /dev/null
+++ b/private/windbg/windbg/dialogs.dlg
@@ -0,0 +1,920 @@
+1 DLGINCLUDE "include\\dialogs.h"
+
+DLG_CALLS DIALOG 11, 22, 299, 109
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Calls"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Call Stack:", -1, 6, 6, 128, 10, NOT WS_GROUP
+ LISTBOX ID_CALLS_CALLSTACK, 6, 18, 244, 83, WS_VSCROLL |
+ WS_HSCROLL | WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "&Go To", ID_CALLS_GOTO, 254, 15, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 254, 32, 40, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 254, 51, 40, 14, WS_GROUP
+END
+
+DLG_CONFIRM DIALOG 0, 0, 278, 24
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Replace"
+FONT 8, "MS Shell DLG"
+BEGIN
+ PUSHBUTTON "&Find Next", ID_CONFIRM_FINDNEXT, 6, 5, 50, 14,
+ WS_GROUP
+ DEFPUSHBUTTON "&Replace", ID_CONFIRM_REPLACE, 60, 5, 50, 14, WS_GROUP
+ PUSHBUTTON "Replace &All", ID_CONFIRM_REPLACEALL, 114, 5, 50, 14,
+ WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 168, 5, 50, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 222, 5, 50, 14, WS_GROUP
+END
+
+DLG_DEBUGDLL DIALOG 29, 30, 350, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Debugger DLLs"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Symbol Handler", -1, 16, 9, 102, 8
+ COMBOBOX ID_DBUGDLL_SHCOMBO, 14, 23, 254, 50, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Expression Evaluator", -1, 16, 44, 102, 8
+ COMBOBOX ID_DBUGDLL_EECOMBO, 14, 56, 254, 50, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Transport Layer", -1, 16, 80, 102, 8
+ COMBOBOX ID_DBUGDLL_TLCOMBO, 14, 92, 254, 50, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Execution &Model", -1, 16, 117, 102, 8
+ COMBOBOX ID_DBUGDLL_EMCOMBO, 14, 130, 254, 50, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 286, 11, 47, 14, WS_TABSTOP
+ PUSHBUTTON "Cancel", IDCANCEL, 286, 33, 47, 14, WS_TABSTOP
+ PUSHBUTTON "&Help", 100, 286, 54, 47, 14, WS_TABSTOP
+ PUSHBUTTON "A&dd...", ID_DBUGDLL_ADD, 286, 84, 47, 14, NOT WS_TABSTOP
+ PUSHBUTTON "De&lete", ID_DBUGDLL_DELETE, 286, 106, 47, 14,
+ NOT WS_TABSTOP
+ PUSHBUTTON "&Change...", ID_DBUGDLL_CHANGE, 286, 128, 47, 14,
+ NOT WS_TABSTOP
+END
+
+DLG_DEBUGEXCP DIALOG 67, 21, 248, 233
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Debugger Exceptions"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "E&xcept #", ID_DBUGEXC_EXCLABEL1, 4, 10, 37, 8
+ EDITTEXT ID_DBUGEXC_EXCNUM, 4, 22, 48, 12, ES_AUTOHSCROLL
+ LTEXT "Na&me", ID_DBUGEXC_NAMELABEL1, 60, 10, 86, 8
+ EDITTEXT ID_DBUGEXC_EXCNAME, 60, 22, 125, 12, ES_AUTOHSCROLL
+ LTEXT "Ac&tion", ID_DBUGEXC_ACTLABEL1, 4, 40, 48, 8
+ COMBOBOX ID_DBUGEXC_ACTION, 4, 52, 48, 48, CBS_DROPDOWN |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "&First Chance Command", ID_DBUGEXC_CMDLABEL1, 4, 70,
+ 100, 8
+ EDITTEXT ID_DBUGEXC_CMD, 4, 82, 182, 12, ES_AUTOHSCROLL
+ LTEXT "Second &Chance Command", ID_DBUGEXC_CMDLABEL2, 4, 100,
+ 85, 8
+ EDITTEXT ID_DBUGEXC_CMD2, 4, 112, 182, 12, ES_AUTOHSCROLL
+ LTEXT "Exce&ption List", ID_DBUGEXC_EXCLABEL, 4, 130, 100, 8
+ LISTBOX ID_DBUGEXC_EXCLIST, 4, 142, 239, 85, LBS_SORT |
+ LBS_USETABSTOPS | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+ PUSHBUTTON "OK", IDOK, 207, 10, 35, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 207, 30, 35, 14
+ DEFPUSHBUTTON "A&dd", ID_DBUGEXC_ADD, 207, 60, 35, 14
+ PUSHBUTTON "D&elete", ID_DBUGEXC_DELETE, 207, 80, 35, 14
+ PUSHBUTTON "&Help", 100, 207, 110, 35, 14
+END
+
+DLG_RUNOPT DIALOG 6, 18, 160, 100
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Debugger Run Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Debuggee", ID_DBUGRUN_RLABEL, 3, 7, 37, 8
+ LTEXT "", ID_DBUGRUN_RTEXT, 3, 23, 110, 12
+ LTEXT "A&rguments", ID_DBUGRUN_ALABEL, 3, 62, 37, 8
+ EDITTEXT ID_DBUGRUN_ATEXT, 3, 78, 110, 12, ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK", IDOK, 126, 9, 29, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 126, 33, 29, 14
+ PUSHBUTTON "&Help", 100, 126, 79, 29, 14
+END
+
+DLG_FIND DIALOG 9, 22, 232, 83
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Find"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Fi&nd What:", -1, 6, 8, 38, 10
+ COMBOBOX ID_FIND_WHAT, 47, 6, 128, 80, CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ AUTOCHECKBOX "Match &Whole Word Only", ID_FIND_WHOLEWORD, 6, 26, 97,
+ 12, WS_GROUP
+ AUTOCHECKBOX "Match &Case", ID_FIND_MATCHUPLO, 6, 41, 90, 12,
+ WS_GROUP
+ AUTOCHECKBOX "Regular &Expression", ID_FIND_REGEXP, 6, 56, 90, 12,
+ WS_GROUP
+ GROUPBOX "Direction", -1, 101, 40, 74, 28
+ AUTORADIOBUTTON "&Up", ID_FIND_UP, 107, 53, 28, 12, WS_GROUP
+ AUTORADIOBUTTON "&Down", ID_FIND_DOWN, 137, 53, 33, 12
+ DEFPUSHBUTTON "&Find Next", ID_FIND_NEXT, 180, 6, 45, 14, WS_GROUP
+ PUSHBUTTON "&Tag All", ID_FIND_TAGALL, 180, 23, 45, 14, WS_DISABLED |
+ WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 180, 40, 45, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 180, 62, 45, 14, WS_GROUP
+END
+
+DLG_FINDNEXT DIALOG 0, 0, 224, 24
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Find"
+FONT 8, "MS Shell DLG"
+BEGIN
+ DEFPUSHBUTTON "&Find Next", IDOK, 6, 5, 50, 14, WS_GROUP
+ PUSHBUTTON "&Tag All", ID_FINDNEXT_TAGALL, 60, 5, 50, 14,
+ WS_DISABLED | WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 114, 5, 50, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 168, 5, 50, 14, WS_GROUP
+END
+
+DLG_FUNCTION DIALOG 8, 25, 174, 65
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Address"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "A&ddress:", -1, 6, 10, 92, 8, NOT WS_GROUP
+ EDITTEXT ID_FUNCTION_FUNCNAME, 6, 24, 116, 12, ES_AUTOHSCROLL |
+ WS_GROUP
+ DEFPUSHBUTTON "OK", IDOK, 128, 6, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 128, 23, 40, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 128, 45, 40, 14, WS_GROUP
+END
+
+DLG_LINE DIALOG 8, 25, 108, 65
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Line"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Number:", -1, 6, 6, 50, 10, NOT WS_GROUP
+ EDITTEXT ID_LINE_LINE, 6, 19, 50, 12, ES_AUTOHSCROLL | WS_GROUP
+ DEFPUSHBUTTON "OK", IDOK, 62, 6, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 62, 23, 40, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 62, 45, 40, 14, WS_GROUP
+END
+
+DLG_MEMORY DIALOG 6, 18, 269, 157
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Memory Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Addre&ss Expression:", -1, 13, 6, 70, 8
+ EDITTEXT ID_MEMORY_ADDRESS, 12, 15, 171, 12, ES_AUTOHSCROLL
+ LTEXT "&Display Format:", -1, 13, 31, 63, 8
+ LISTBOX ID_MEMORY_FORMAT, 12, 40, 170, 96, WS_VSCROLL |
+ WS_TABSTOP
+ AUTOCHECKBOX "&Fill Window", ID_MEMORY_FILL, 12, 132, 173, 10
+ AUTOCHECKBOX "&Re-Evaluate Expression Always (Live)", ID_MEMORY_LIVE,
+ 12, 142, 173, 10
+ DEFPUSHBUTTON "OK", IDOK, 223, 6, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 223, 27, 40, 14
+ PUSHBUTTON "&Help", 100, 223, 49, 40, 14
+END
+
+DLG_MESSAGES DIALOG 62, 16, 166, 172
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Messages"
+FONT 8, "MS Shell DLG"
+BEGIN
+ GROUPBOX "Message Type", -1, 6, 4, 84, 44
+ AUTORADIOBUTTON "&Single", ID_MESSAGE_CHOOSEMESSAGE, 12, 16, 65, 12,
+ WS_GROUP
+ AUTORADIOBUTTON "&Class", ID_MESSAGE_CHOOSECLASS, 12, 32, 68, 12
+ LTEXT "Single &Message", ID_MESSAGE_MESSAGETITLE, 6, 52, 54, 8
+ COMBOBOX ID_MESSAGE_MESSAGE, 6, 65, 107, 80, CBS_DROPDOWNLIST |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Message Class", ID_MESSAGE_CLASSTITLE, 6, 84, 150, 82
+ AUTOCHECKBOX "M&ouse", ID_MESSAGE_CLASSMOUSE, 19, 96, 56, 12,
+ WS_GROUP
+ AUTOCHECKBOX "&Window", ID_MESSAGE_CLASSWINDOW, 19, 112, 55, 12
+ AUTOCHECKBOX "&Input", ID_MESSAGE_CLASSINPUT, 19, 128, 54, 12
+ AUTOCHECKBOX "S&ystem", ID_MESSAGE_CLASSSYSTEM, 19, 144, 54, 12
+ AUTOCHECKBOX "Initiali&zation", ID_MESSAGE_CLASSINIT, 97, 96, 55, 12
+ AUTOCHECKBOX "C&lipboard", ID_MESSAGE_CLASSCLIPBOARD, 97, 112, 55, 12
+ AUTOCHECKBOX "&DDE", ID_MESSAGE_CLASSDDE, 97, 128, 58, 12
+ AUTOCHECKBOX "&Nonclient", ID_MESSAGE_CLASSNONCLIENT, 97, 144, 57, 12
+ DEFPUSHBUTTON "OK", IDOK, 120, 8, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 120, 25, 40, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 120, 47, 40, 14, WS_GROUP
+END
+
+DLG_PROCESS DIALOG 6, 18, 257, 118
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Set Process"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT " PN PID Status", -1, 19, 7, 123, 8
+ LISTBOX ID_PROCESS_LIST, 12, 21, 170, 83, LBS_USETABSTOPS |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 208, 17, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 208, 36, 40, 14
+ PUSHBUTTON "&Help", 100, 208, 63, 40, 14
+ PUSHBUTTON "&Select", ID_PROCESS_SELECT, 208, 87, 40, 14
+END
+
+DLG_REPLACE DIALOG 28, 48, 230, 86
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Replace"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Fi&nd What:", -1, 6, 10, 48, 10
+ COMBOBOX ID_REPLACE_WHAT, 57, 8, 112, 80, CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Re&place With:", -1, 6, 27, 51, 10, NOT WS_GROUP
+ COMBOBOX ID_REPLACE_REPLACEWITH, 57, 25, 112, 80, CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | CBS_OEMCONVERT | WS_VSCROLL |
+ WS_TABSTOP
+ AUTOCHECKBOX "Match &Whole Word Only", ID_REPLACE_WHOLEWORD, 6, 42,
+ 120, 12, WS_GROUP
+ AUTOCHECKBOX "Match &Case", ID_REPLACE_MATCHUPLO, 6, 55, 88, 12,
+ WS_GROUP
+ AUTOCHECKBOX "Regular &Expression", ID_REPLACE_REGEXP, 6, 68, 81, 12,
+ WS_GROUP
+ DEFPUSHBUTTON "&Find Next", ID_REPLACE_FINDNEXT, 175, 6, 50, 14,
+ WS_GROUP
+ PUSHBUTTON "Replace &All", ID_REPLACE_REPLACEALL, 175, 24, 50, 14,
+ WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 175, 42, 50, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 175, 68, 50, 14, WS_GROUP
+END
+
+DLG_RUNDEBUG DIALOG 53, 17, 253, 238
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Debugger Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ GROUPBOX "&Debugger", ID_DBUGOPT_DEBUGGERGROUP, 4, 0, 109, 146,
+ WS_GROUP
+ AUTOCHECKBOX "Ignore Case", ID_DBUGOPT_CASESENSITIVE, 11, 12, 96, 10,
+ WS_GROUP
+ AUTOCHECKBOX "Display Segment", ID_DBUGOPT_DISPSEG, 11, 22, 96, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Debug Child Processes", ID_DBUGOPT_CHILDREN, 11, 32, 96,
+ 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Go on Thread Terminate", ID_DBUGOPT_EXITGO, 11, 42, 96,
+ 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Go on Process Attach", ID_DBUGOPT_ATTACHGO, 11, 52, 96,
+ 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Go on Child Create", ID_DBUGOPT_CHILDGO, 11, 62, 96, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Command Repeat", ID_DBUGOPT_COMMANDREPEAT, 11, 72, 96, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Separate WOW VDM", ID_DBUGOPT_WOWVDM, 11, 82, 96, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Alternate Single Stepping", ID_DBUGOPT_ALTSS, 11, 92,
+ 96, 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Disconnect on Exit", ID_DBUGOPT_DISCONNECT, 11, 102, 96,
+ 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Verbose Output", ID_DBUGOPT_VERBOSE, 11, 112, 96, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Ignore Bad Symbols", ID_DBUGOPT_IGNOREALL, 11, 122, 96, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Abbreviated Context", ID_DBUGOPT_CONTEXT, 11, 132, 96, 10,
+ NOT WS_TABSTOP
+
+ GROUPBOX "D&isassembler", ID_DBUGOPT_DISASMGROUP, 116, 0, 132, 64,
+ WS_GROUP
+ AUTOCHECKBOX "Display Segment in Address", ID_DISASMOPT_SHOWSEG, 119,
+ 10, 120, 10, WS_GROUP
+ AUTOCHECKBOX "Display Raw Bytes", ID_DISASMOPT_SHOWBYTE, 119, 20, 120,
+ 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Uppercase Symbols and Opcodes", ID_DISASMOPT_CASE, 119,
+ 30, 120, 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Display Symbols", ID_DISASMOPT_SHOWSYMB, 119, 40, 120,
+ 10, NOT WS_TABSTOP
+ AUTOCHECKBOX "Open Window on Demand", ID_DISASMOPT_DEMAND, 119, 50,
+ 120, 10, NOT WS_TABSTOP
+
+ GROUPBOX "&Logfile", ID_LFOPT_GROUP,
+ 116, 64, 132, 50,
+ WS_GROUP
+ AUTOCHECKBOX "Append", ID_LFOPT_APPEND,
+ 120, 78, 85, 10,
+ WS_GROUP
+ AUTOCHECKBOX "Open Automatically", ID_LFOPT_AUTO,
+ 120, 88, 85, 10,
+ NOT WS_TABSTOP
+ LTEXT "&Name:", ID_LFOPT_FNAMELABEL,
+ 120, 102, 23, 8,
+ WS_GROUP
+ EDITTEXT ID_LFOPT_FNAME,
+ 145, 99, 98, 12,
+ ES_AUTOHSCROLL | WS_GROUP
+
+
+ LTEXT "S&ource Search Paths:", ID_DBUGOPT_SRCHPATHLABEL, 4,
+ 152, 73, 8
+ EDITTEXT ID_DBUGOPT_SRCHPATH, 76, 149, 168, 12, ES_AUTOHSCROLL
+ GROUPBOX "Radi&x", ID_DBUGOPT_RADIXGROUP, 18, 165, 61, 45,
+ WS_GROUP
+ AUTORADIOBUTTON "Octal", ID_DBUGOPT_RADIXOCT, 22, 175, 32, 10, WS_GROUP |
+ WS_TABSTOP
+ AUTORADIOBUTTON "Decimal", ID_DBUGOPT_RADIXDEC, 22, 185, 39, 10
+ AUTORADIOBUTTON "Hex", ID_DBUGOPT_RADIXHEX, 22, 195, 32, 10
+
+ GROUPBOX "&Registers", ID_DBUGOPT_REGISTERGROUP, 83, 165, 60, 44,
+ WS_GROUP
+ AUTORADIOBUTTON "Regular", ID_DBUGOPT_REGREG, 86, 177, 54, 10, WS_GROUP |
+ WS_TABSTOP
+ AUTORADIOBUTTON "Extended", ID_DBUGOPT_REGEXT, 86, 187, 54, 10
+ AUTOCHECKBOX "MMU-System", ID_DBUGOPT_REGMMU, 86, 197, 54, 10, NOT
+ WS_TABSTOP
+
+ GROUPBOX "&Symbol Suffix", ID_DBUGOPT_SUFFIXGROUP, 146, 165, 65,
+ 44, WS_GROUP
+ AUTORADIOBUTTON "A (ANSI)", ID_DBUGOPT_SUFFIXA, 150, 178, 58, 10,
+ WS_GROUP | WS_TABSTOP
+ AUTORADIOBUTTON "W (UNICODE)", ID_DBUGOPT_SUFFIXW, 150, 188, 58, 10
+ AUTORADIOBUTTON "None", ID_DBUGOPT_SUFFIXNONE, 150, 198, 58, 10
+
+
+ DEFPUSHBUTTON "OK", IDOK, 14, 219, 62, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 92, 219, 62, 14
+ PUSHBUTTON "&Help", 100, 170, 219, 62, 14
+END
+
+DLG_KERNELDBG DIALOG 17, 43, 255, 144
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Kernel Debugger Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ GROUPBOX "&Flags", -1, 5, 4, 122, 85, WS_GROUP
+ AUTOCHECKBOX "Stop at Initial Breakpoint", ID_KD_INITIALBP, 14, 17,
+ 103, 10
+ AUTOCHECKBOX "Enable Kernel Debugging", ID_KD_ENABLE, 14, 28, 103, 10,
+ NOT WS_TABSTOP
+ AUTOCHECKBOX "Go on Exit", ID_KD_GOEXIT, 14, 40, 103, 10, NOT
+ WS_TABSTOP
+ GROUPBOX "&Communications", -1, 131, 4, 118, 85, WS_GROUP
+ LTEXT "&Baud Rate", ID_KD_BAUDRATE_LABEL, 139, 21, 41, 8
+ COMBOBOX ID_KD_BAUDRATE, 181, 19, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Port", ID_KD_PORT_LABEL, 139, 37, 20, 8
+ COMBOBOX ID_KD_PORT, 181, 35, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "C&ache Size", ID_KD_CACHE_LABEL, 139, 54, 41, 9
+ COMBOBOX ID_KD_CACHE, 181, 51, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "P&latform", ID_KD_PLATFORM_LABEL, 139, 71, 41, 9
+ COMBOBOX ID_KD_PLATFORM, 181, 68, 48, 35, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Crash &Dump:", ID_KD_CRASH_LABEL, 8, 98, 46, 8
+ EDITTEXT ID_KD_CRASH, 56, 95, 151, 12, ES_AUTOHSCROLL
+ PUSHBUTTON "B&rowse", ID_KD_CRASH_BROWSE, 210, 95, 40, 12
+ DEFPUSHBUTTON "OK", IDOK, 18, 124, 62, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 96, 124, 62, 14
+ PUSHBUTTON "&Help", 100, 174, 124, 62, 14
+END
+
+DLG_BREAKPOINTS DIALOG 13, 20, 271, 222
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Breakpoints"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Break:", -1, 6, 8, 40, 10
+ COMBOBOX ID_SETBREAK_ACTION, 49, 6, 138, 90, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "L&ocation:", ID_SETBREAK_SLOCATION, 6, 24, 40, 10, NOT
+ WS_GROUP
+ EDITTEXT ID_SETBREAK_LOCATION, 49, 23, 138, 12, ES_AUTOHSCROLL |
+ ES_OEMCONVERT
+ LTEXT "&Wnd Proc:", ID_SETBREAK_SWNDPROC, 6, 40, 40, 10, NOT
+ WS_GROUP
+ COMBOBOX ID_SETBREAK_WNDPROC, 49, 38, 138, 54, CBS_DROPDOWN |
+ CBS_AUTOHSCROLL | CBS_OEMCONVERT | CBS_SORT | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "E&xpression:", ID_SETBREAK_SEXPRESSION, 6, 56, 40, 10,
+ WS_GROUP
+ EDITTEXT ID_SETBREAK_EXPRESSION, 49, 56, 138, 12, ES_AUTOHSCROLL
+ LTEXT "Len&gth:", ID_SETBREAK_SLENGTH, 6, 74, 40, 10, NOT
+ WS_GROUP
+ EDITTEXT ID_SETBREAK_LENGTH, 49, 73, 60, 12
+ LTEXT "Pa&ss Count:", -1, 6, 90, 40, 10, NOT WS_GROUP
+ EDITTEXT ID_SETBREAK_PASS, 49, 90, 45, 12
+ LTEXT "Left:", -1, 109, 91, 17, 10, NOT WS_GROUP
+ LTEXT "", ID_SETBREAK_PASSESLEFTCOUNT, 142, 91, 45, 10, NOT
+ WS_GROUP
+ LTEXT "&Process:", -1, 6, 105, 30, 10, NOT WS_GROUP
+ EDITTEXT ID_SETBREAK_PROCESS, 49, 105, 45, 12
+ LTEXT "&Thread:", -1, 105, 105, 26, 10, NOT WS_GROUP
+ EDITTEXT ID_SETBREAK_THREAD, 141, 105, 45, 12
+ LTEXT "Comma&nds:", -1, 6, 125, 40, 10, NOT WS_GROUP
+ EDITTEXT ID_SETBREAK_CMDS, 49, 123, 138, 12, ES_AUTOHSCROLL
+ LTEXT "B&reakpoints:", -1, 7, 140, 42, 10, NOT WS_GROUP
+ LISTBOX ID_SETBREAK_BREAKPOINT, 6, 151, 182, 66, WS_VSCROLL |
+ WS_HSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 195, 6, 55, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 195, 23, 55, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 195, 41, 55, 14, WS_GROUP
+ PUSHBUTTON "&Messages...", ID_SETBREAK_MESSAGES, 195, 64, 55, 14,
+ WS_GROUP
+ PUSHBUTTON "A&dd", ID_SETBREAK_ADD, 196, 97, 55, 14, WS_GROUP
+ PUSHBUTTON "C&lear", ID_SETBREAK_DELETE, 196, 115, 55, 14, WS_GROUP
+ PUSHBUTTON "&Clear All", ID_SETBREAK_CLEARALL, 196, 134, 55, 14,
+ WS_GROUP
+ PUSHBUTTON "D&isable", ID_SETBREAK_DISABLE, 196, 153, 55, 14,
+ WS_GROUP
+ PUSHBUTTON "Enabl&e", ID_SETBREAK_ENABLE, 196, 172, 55, 14,
+ WS_GROUP
+ PUSHBUTTON "Modif&y", ID_SETBREAK_CHANGE, 196, 192, 55, 14,
+ WS_GROUP
+END
+
+DLG_THREAD DIALOG 6, 18, 269, 171
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Set Thread"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT " TN TID Status", -1, 12, 43, 190, 8
+ LISTBOX ID_THREAD_LIST, 12, 60, 170, 79, LBS_USETABSTOPS |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 220, 5, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 220, 25, 40, 14
+ PUSHBUTTON "&Help", 100, 220, 50, 40, 14
+ PUSHBUTTON "F&reeze", ID_THREAD_FREEZE, 220, 70, 40, 14
+ PUSHBUTTON "&Freeze All", ID_THREAD_FREEZEALL, 220, 90, 40, 14
+ PUSHBUTTON "&Thaw All", ID_THREAD_THAWALL, 220, 110, 40, 14
+ PUSHBUTTON "&Select", ID_THREAD_SELECT, 220, 130, 40, 14
+END
+
+DLG_UNRESOLVED DIALOG 0, 0, 240, 90
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Unresolved Breakpoint"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "", ID_UNRESOLVED_HBPT, 10, 6, 225, 14, SS_NOPREFIX
+ LTEXT "", ID_UNRESOLVED_DESC, 10, 26, 225, 18, SS_NOPREFIX
+ PUSHBUTTON "&Clear", ID_UNRESOLVED_CLEAR, 12, 50, 55, 14
+ PUSHBUTTON "&Disable", ID_UNRESOLVED_DISABLE, 12, 70, 55, 14
+ DEFPUSHBUTTON "De&fer", ID_UNRESOLVED_DEFER, 92, 50, 55, 14
+ PUSHBUTTON "&Quiet Defer", ID_UNRESOLVED_QUIET, 92, 70, 55, 14
+ PUSHBUTTON "&Breakpoints", ID_UNRESOLVED_BREAKPOINTS, 172, 50, 55, 14
+ PUSHBUTTON "&Help", 100, 172, 70, 55, 14
+END
+
+DLG_WATCH DIALOG 7, 21, 283, 131
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Watch Expression"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "E&xpression:", -1, 6, 8, 42, 10, NOT WS_GROUP
+ EDITTEXT ID_WATCH_EXPRESSION, 51, 6, 180, 12, ES_AUTOHSCROLL |
+ ES_OEMCONVERT | WS_GROUP
+ LTEXT "Curren&t Expressions:", -1, 6, 24, 225, 10, NOT
+ WS_GROUP
+ LISTBOX ID_WATCH_CUREXPRESSION, 6, 36, 225, 89, LBS_HASSTRINGS |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Add", ID_WATCH_ADD, 237, 76, 40, 14, WS_GROUP
+ PUSHBUTTON "De&lete", ID_WATCH_DELETE, 237, 93, 40, 14, WS_GROUP
+ PUSHBUTTON "&Clear All", ID_WATCH_CLEARALL, 237, 110, 40, 14,
+ WS_GROUP
+ DEFPUSHBUTTON "OK", IDOK, 237, 6, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 237, 23, 40, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 237, 45, 40, 14, WS_GROUP
+END
+
+DLG_BPRESOLVE DIALOG 77, 26, 196, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION ""
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "", ID_BPRESOLVE_STRING, 6, 9, 176, 8
+ LTEXT "This expression can be instantiated in several modules.",
+ -1, 5, 31, 190, 15
+ LTEXT "Select the module to be used from the following list:",
+ -1, 4, 44, 124, 17
+ LISTBOX ID_BPRESOLVE_LIST, 4, 65, 123, 83, LBS_MULTIPLESEL |
+ WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "&Use", ID_BPRESOLVE_USE, 146, 74, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 146, 105, 40, 14
+END
+
+DLG_PROGRAM_OPEN DIALOG 6, 18, 294, 197
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Program Open"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Programs:", -1, 10, 9, 33, 8, NOT WS_GROUP
+ LISTBOX ID_PROGOPEN_PROGRAMS, 9, 20, 200, 71, LBS_SORT |
+ WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+ LTEXT "&Workspaces:", -1, 9, 101, 43, 8, NOT WS_GROUP
+ LISTBOX ID_PROGOPEN_WORKSPACES, 8, 113, 201, 62, WS_VSCROLL |
+ WS_HSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 248, 6, 40, 14
+ PUSHBUTTON "&New...", ID_PROGOPEN_NEW, 248, 30, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 248, 54, 40, 14
+ PUSHBUTTON "&Help", 100, 248, 78, 40, 14
+END
+
+DLG_PROGRAM_CLOSE DIALOG 69, 87, 261, 72
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Program Close"
+FONT 8, "MS Shell DLG"
+BEGIN
+ CTEXT "", ID_PROGCLOSE_TEXT1, 11, 8, 234, 12, NOT WS_GROUP
+ CTEXT "", ID_PROGCLOSE_TEXT2, 11, 23, 234, 12, NOT WS_GROUP
+ DEFPUSHBUTTON "&Yes", 6, 26, 52, 40, 14
+ PUSHBUTTON "&No", 7, 82, 52, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 138, 52, 40, 14
+ PUSHBUTTON "&Help", 100, 194, 52, 40, 14
+END
+
+DLG_PROGRAM_SAVEAS DIALOG 104, 36, 172, 81
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Save As"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Workspace name:", -1, 5, 7, 80, 8, NOT WS_GROUP
+ COMBOBOX ID_PROGSAVEAS_WORKSPACES, 5, 19, 108, 35, CBS_DROPDOWN |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 126, 6, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 126, 30, 40, 14
+ PUSHBUTTON "&Help", 100, 126, 54, 40, 14
+ AUTOCHECKBOX "Make &Default", ID_PROGSAVEAS_MAKEDEFAULT, 5, 58, 56,
+ 10
+END
+
+DLG_PROGRAM_DELETE DIALOG 6, 18, 294, 197
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Program Delete"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Programs:", -1, 10, 9, 33, 8, NOT WS_GROUP
+ LISTBOX ID_PROGDELETE_PROGRAMS, 9, 20, 200, 71, LBS_SORT |
+ WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+ LTEXT "&Workspaces:", -1, 9, 101, 43, 8, NOT WS_GROUP
+ LISTBOX ID_PROGDELETE_WORKSPACES, 8, 113, 201, 62,
+ LBS_MULTIPLESEL | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 248, 6, 40, 14
+ PUSHBUTTON "&Delete", ID_PROGDELETE_DELETE, 248, 30, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 248, 54, 40, 14
+ PUSHBUTTON "&Help", 100, 248, 78, 40, 14
+END
+
+DLG_CHOOSECOLOR DIALOG 45, -59, 298, 266
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Color"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Ba&sic Colors:", -1, 4, 4, 140, 9
+ CONTROL "", COLOR_BOX1, "Static", SS_SIMPLE | WS_GROUP |
+ WS_TABSTOP, 4, 14, 140, 86
+ LTEXT "&Custom Colors:", -1, 4, 106, 140, 9
+ CONTROL "", COLOR_CUSTOM1, "Static", SS_SIMPLE | WS_GROUP |
+ WS_TABSTOP, 4, 115, 140, 28
+ DEFPUSHBUTTON "OK", IDOK, 67, 243, 44, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 127, 243, 44, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 187, 243, 44, 14, WS_GROUP
+ CONTROL "", COLOR_RAINBOW, "Static", SS_BLACKFRAME, 152, 4, 118,
+ 116
+ CONTROL "", COLOR_LUMSCROLL, "Static", SS_SIMPLE, 280, 4, 8, 116
+ CONTROL "", COLOR_CURRENT, "Static", SS_BLACKFRAME, 152, 124, 40,
+ 26
+ RTEXT "Color|", -1, 152, 151, 20, 9
+ LTEXT "S&olid", -1, 172, 151, 20, 9
+ PUSHBUTTON "&o", COLOR_SOLID, 300, 200, 4, 14, WS_GROUP
+ RTEXT "&Hue:", COLOR_HUEACCEL, 194, 126, 20, 9
+ EDITTEXT COLOR_HUE, 216, 124, 18, 12, WS_GROUP
+ RTEXT "&Sat:", COLOR_SATACCEL, 194, 140, 20, 9
+ EDITTEXT COLOR_SAT, 216, 138, 18, 12, WS_GROUP
+ RTEXT "&Lum:", COLOR_LUMACCEL, 194, 154, 20, 9
+ EDITTEXT COLOR_LUM, 216, 152, 18, 12, WS_GROUP
+ RTEXT "&Red:", COLOR_REDACCEL, 243, 126, 24, 9
+ EDITTEXT COLOR_RED, 269, 124, 18, 12, WS_GROUP
+ RTEXT "&Green:", COLOR_GREENACCEL, 243, 140, 24, 9
+ EDITTEXT COLOR_GREEN, 269, 138, 18, 12, WS_GROUP
+ RTEXT "&Blue:", COLOR_BLUEACCEL, 243, 154, 24, 9
+ EDITTEXT COLOR_BLUE, 269, 152, 18, 12, WS_GROUP
+ PUSHBUTTON "&Add to Custom Colors", COLOR_ADD, 152, 169, 142, 14,
+ WS_GROUP
+ LTEXT "&Items:", -1, 4, 145, 20, 8
+ LISTBOX IDC_LIST_ITEMS, 4, 155, 136, 75, LBS_MULTIPLESEL |
+ LBS_OWNERDRAWFIXED | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Set &Foreground", IDC_PUSH_SET_FOREGROUND, 153, 190, 61,
+ 14, WS_GROUP
+ PUSHBUTTON "Set Bac&kground", IDC_PUSH_SET_BACKGROUND, 153, 209, 61,
+ 14, WS_GROUP
+ PUSHBUTTON "Set &Default", IDC_PUSH_DEFAULT, 232, 190, 61, 14,
+ WS_GROUP
+ PUSHBUTTON "Selec&t All", IDC_PUSH_SELECT_ALL, 232, 209, 61, 14,
+ WS_GROUP
+END
+
+DLG_CHOOSEFONT DIALOG 13, 54, 264, 147
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Font"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Font:", 1088, 6, 3, 40, 9
+ COMBOBOX 1136, 6, 13, 94, 54, CBS_SIMPLE | CBS_OWNERDRAWFIXED |
+ CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS |
+ CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Font St&yle:", 1089, 108, 3, 44, 9
+ COMBOBOX 1137, 108, 13, 64, 54, CBS_SIMPLE | CBS_DISABLENOSCROLL |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Size:", 1090, 179, 3, 30, 9
+ COMBOBOX 1138, 179, 13, 32, 54, CBS_SIMPLE | CBS_OWNERDRAWFIXED |
+ CBS_SORT | CBS_HASSTRINGS | CBS_DISABLENOSCROLL |
+ WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 218, 6, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 218, 23, 40, 14, WS_GROUP
+ PUSHBUTTON "&Apply", 1026, 218, 40, 40, 14, WS_GROUP
+ PUSHBUTTON "&Help", 1038, 218, 57, 40, 14, WS_GROUP
+ GROUPBOX "Effects", 1072, 6, 72, 84, 34, WS_GROUP
+ AUTOCHECKBOX "Stri&keout", 1040, 10, 82, 49, 10
+ AUTOCHECKBOX "&Underline", 1041, 10, 94, 51, 10, NOT WS_TABSTOP
+ LTEXT "&Color:", 1091, 6, 110, 30, 9
+ COMBOBOX 1139, 6, 120, 84, 100, CBS_DROPDOWNLIST |
+ CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_HASSTRINGS |
+ WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Sample", 1073, 98, 72, 160, 49, WS_GROUP
+ CTEXT "", 1093, 98, 124, 160, 20, SS_NOPREFIX | NOT WS_GROUP
+ CTEXT "--Sample Text--", 1092, 104, 81, 149, 37, SS_NOPREFIX |
+ NOT WS_VISIBLE
+ AUTOCHECKBOX "&Make Default", IDC_CHECK_MAKE_DEFAULT, 98, 127, 61, 10
+END
+
+1536 DIALOG 36, 24, 276, 157
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Open"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "File &Name:", 1090, 6, 6, 76, 9
+ EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ LISTBOX 1120, 6, 32, 90, 85, LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "D&irectories:", -1, 110, 6, 92, 9
+ LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX
+ LISTBOX 1121, 110, 32, 92, 85, LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "List Files of &Type:", 1089, 6, 121, 90, 9
+ COMBOBOX 1136, 6, 131, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL |
+ WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:", 1091, 110, 121, 92, 9
+ COMBOBOX 1137, 110, 131, 92, 68, CBS_DROPDOWNLIST |
+ CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT |
+ CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 208, 6, 62, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 208, 24, 62, 14, WS_GROUP
+ PUSHBUTTON "&Help", 1038, 208, 42, 62, 14, WS_GROUP
+ AUTOCHECKBOX "&Read Only", 1040, 208, 62, 44, 10, WS_GROUP
+ GROUPBOX "Add Directory to",-1,208,76,62,49
+ CONTROL "N&one",1069,"Button",BS_AUTORADIOBUTTON,213,88,31,10
+ CONTROL "Root &Map",1070,"Button",BS_AUTORADIOBUTTON, 213,100,44,10
+ CONTROL "&Source Path",1071,"Button",BS_AUTORADIOBUTTON,213,112,52,
+ 10
+ PUSHBUTTON "Net&work...", 1037, 208, 131, 62, 14, WS_GROUP
+END
+
+DLG_ENVIRONMENT DIALOG 6, 18, 219, 148
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Environment"
+FONT 8, "MS Shell DLG"
+BEGIN
+ GROUPBOX "Tab Settings", ID_ENV_TABGROUP, 10, 7, 74, 65
+ GROUPBOX "Scroll Bars", ID_ENV_SCROLLGROUP, 96, 6, 60, 66
+ LTEXT "&Tab Stops:", ID_ENV_TABSTOPSTXT, 18, 22, 36, 8
+ EDITTEXT ID_ENV_TABSTOPS, 61, 18, 15, 12, ES_AUTOHSCROLL
+ AUTORADIOBUTTON "&Keep Tabs", ID_ENV_TABKEEP, 19, 39, 47, 10
+ AUTORADIOBUTTON "&Insert Spaces", ID_ENV_TABSPAC, 19, 54, 57, 10
+ AUTOCHECKBOX "&Vertical", ID_ENV_SCROLLVER, 103, 24, 40, 10
+ AUTOCHECKBOX "&Horizontal", ID_ENV_SCROLLHOR, 103, 44, 45, 10
+ LTEXT "&Undo/Redo Buffer Size:", ID_ENV_REDOSIZE_TXT, 12, 86,
+ 77, 8
+ EDITTEXT ID_ENV_REDOSIZE, 94, 83, 39, 12, ES_AUTOHSCROLL
+ AUTOCHECKBOX "&Search for program along PATH", ID_ENV_SRCHPATH, 12,
+ 100, 115, 10
+ AUTOCHECKBOX "&Ask to save workspace if modified", ID_ENV_ASKSAVE, 12,
+ 118, 135, 10
+ DEFPUSHBUTTON "OK", IDOK, 169, 11, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 169, 33, 40, 14
+ PUSHBUTTON "&Help", 100, 169, 55, 40, 14
+END
+
+DLG_USERDLL DIALOG 43, 38, 303, 244
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "User DLLs"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Module Name", ID_USERDLL_LIST_TEXT, 4, 9, 76, 8
+ LTEXT "Load Plan", ID_USERDLL_LIST_TEXT2, 85, 9, 70, 8
+ LTEXT "Current Status", ID_USERDLL_LIST_TEXT3, 164, 9, 70, 8
+ LISTBOX ID_USERDLL_LIST, 4, 19, 295, 108,
+ LBS_MULTIPLESEL | LBS_USETABSTOPS | WS_VSCROLL |
+ WS_TABSTOP | LBS_EXTENDEDSEL
+
+ CONTROL "", ID_USERDLL_NAME_BOX, "Static", SS_BLACKFRAME, 4, 127,
+ 296, 13
+ LTEXT "", ID_USERDLL_NAME, 6, 130, 293, 8
+
+ LTEXT "Symbol Search &Path:", ID_USERDLL_SRCHPATH_TEXT, 4, 148, 74, 8
+ EDITTEXT ID_USERDLL_SRCHPATH, 77, 144, 222, 12, ES_AUTOHSCROLL
+
+ GROUPBOX "&Location", ID_USERDLL_LOC_GRP, 4, 162, 56, 55
+ AUTORADIOBUTTON "Local", ID_USERDLL_LOCAL, 13, 180, 38, 10
+ AUTORADIOBUTTON "Remote", ID_USERDLL_REMOTE, 13, 195, 42, 10
+
+ GROUPBOX "&Symbols", ID_USERDLL_SYM_GRP, 70, 162, 68, 55
+ AUTORADIOBUTTON "Load", ID_USERDLL_LOAD, 78, 175, 37, 10, WS_GROUP
+ AUTORADIOBUTTON "Defer", ID_USERDLL_DEFER, 78, 188, 38, 10
+ AUTORADIOBUTTON "Suppress", ID_USERDLL_SUPPRESS, 78, 201, 49, 10
+
+ LTEXT "Default:", ID_USERDLL_ADD_DEFAULT_TEXT, 148, 166, 39, 8
+ CONTROL "", ID_USERDLL_DEFAULT_BOX, "Static", SS_BLACKFRAME, 176, 163,
+ 77, 13
+ LTEXT "", ID_USERDLL_ADD_DEFAULT, 178, 166, 74, 8
+
+ LTEXT "&New DLL name:", ID_USERDLL_ADD_NAME_TEXT, 4, 226, 59, 10
+ EDITTEXT ID_USERDLL_ADD_NAME, 68, 222, 185, 12, ES_AUTOHSCROLL
+
+ DEFPUSHBUTTON "OK", IDOK, 259, 162, 40, 14
+ PUSHBUTTON "Defaul&t", ID_USERDLL_DEFAULT, 167, 181, 40, 14
+ PUSHBUTTON "Modif&y", ID_USERDLL_CHANGE, 213, 181, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 259, 181, 40, 14
+ PUSHBUTTON "&Add", ID_USERDLL_ADD, 167, 200, 40, 14
+ PUSHBUTTON "D&elete", ID_USERDLL_DELETE, 213, 200, 40, 14
+ PUSHBUTTON "&Browse", ID_USERDLL_BROWSE, 259, 200, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 259, 220, 40, 14
+END
+
+DLG_ASKSRCBROWSE DIALOG 0, 0, 224, 48
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Source Not Found"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Browse for: ", ID_BROWSEFOR, 6, 5, 200, 25
+ DEFPUSHBUTTON "&Ignore", IDCANCEL, 6, 29, 50, 14, WS_GROUP
+ PUSHBUTTON "&Browse for Source File", IDOK, 60, 29, 100, 14,
+ WS_GROUP
+ PUSHBUTTON "&Help", 100, 168, 29, 50, 14, WS_GROUP
+END
+
+DLG_ASKEXEBROWSE DIALOG 48, 89, 224, 48
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Symbol Information Not Found"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "Browse for: ", ID_BROWSEFOR, 6, 5, 200, 25
+ DEFPUSHBUTTON "&Ignore", IDCANCEL, 6, 28, 50, 14, WS_GROUP
+ PUSHBUTTON "Ignore &All", ID_IGNOREALL, 60, 28, 50, 14, WS_GROUP
+ PUSHBUTTON "&Browse", IDOK, 114, 28, 50, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 168, 28, 50, 14, WS_GROUP
+END
+
+DLG_QUICKWATCH DIALOG 112, 121, 289, 152
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Quickwatch"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Watch:", -1, 6, 5, 29, 10, NOT WS_GROUP
+ EDITTEXT ID_QUICKW_MODIFY, 35, 3, 199, 12, ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Evaluate", ID_QUICKW_ZOOM, 237, 2, 48, 14, WS_GROUP
+ PUSHBUTTON "&Add Watch", ID_QUICKW_ADD, 237, 19, 48, 14, WS_GROUP
+ PUSHBUTTON "&Remove Last", ID_QUICKW_REM_LAST, 237, 36, 48, 14, WS_GROUP
+ PUSHBUTTON "E&xit", IDCANCEL, 237, 54, 48, 14, WS_GROUP
+ PUSHBUTTON "&Help", 100, 237, 72, 48, 14, WS_GROUP
+ CONTROL "", ID_QUICKW_LIST, "QuickClass", WS_DLGFRAME, 6, 17,
+ 229, 133
+
+END
+
+DLG_CH_DBUGDLL DIALOG 6, 18, 294, 116
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Change Debug DLL"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Short Name:", -1, 9, 18, 46, 8
+ EDITTEXT ID_CHDBDLL_NAME, 57, 17, 154, 12, ES_AUTOHSCROLL
+ LTEXT "&Description:", -1, 9, 42, 46, 8
+ EDITTEXT ID_CHDBDLL_DESC, 57, 41, 154, 12, ES_AUTOHSCROLL
+ LTEXT "&Path:", -1, 9, 66, 46, 8
+ EDITTEXT ID_CHDBDLL_PATH, 57, 65, 154, 12, ES_AUTOHSCROLL
+ LTEXT "P&arameters:", -1, 9, 90, 46, 8
+ EDITTEXT ID_CHDBDLL_PARAM, 57, 89, 154, 12, ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK", IDOK, 223, 15, 52, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 223, 37, 52, 14
+ PUSHBUTTON "&Help", 100, 223, 60, 52, 14
+END
+
+ID_CHDBDLL_PATH DIALOG 6, 18, 233, 118
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Functions"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "The function exists in several modules.",
+ ID_FUNCRES_LABEL1, 9, 17, 135, 8
+ LTEXT "Select the one you want to view.", ID_FUNCRES_LABEL2,
+ 11, 28, 108, 8
+ LISTBOX ID_FUNCRES_LIST, 9, 42, 124, 63, WS_VSCROLL | WS_HSCROLL
+ PUSHBUTTON "Use", ID_FUNCRES_USE, 187, 39, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 187, 63, 40, 14
+ PUSHBUTTON "Help", 100, 187, 88, 40, 14
+END
+
+DLG_PANEOPTIONS DIALOG 135, 93, 211, 82
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Pane Manager Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Format:", -1, 2, 10, 27, 10
+ EDITTEXT ID_FUNCRES_LABEL2, 33, 9, 32, 12, ES_AUTOHSCROLL
+ GROUPBOX "&Window Options", -1, 2, 27, 152, 46
+ AUTORADIOBUTTON "&Always Expand First Level", ID_FUNCRES_LIST, 10, 44, 119, 10
+ AUTORADIOBUTTON "&Don't Expand Automatically", ID_FUNCRES_USE, 11, 57, 98, 10
+ DEFPUSHBUTTON "OK", IDOK, 165, 6, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 165, 23, 40, 14
+ PUSHBUTTON "&Help", 100, 165, 40, 40, 14
+END
+
+
+DLG_BPCANIUSETHUNK DIALOG 77, 26, 196, 77
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "No Implementation Found"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "", ID_BPCANIUSETHUNK_STRING, 6, 9, 176, 8
+ LTEXT "Implementation was not found. Is it OK to set breakpoint in thunk?",
+ -1, 5, 31, 190, 15
+ DEFPUSHBUTTON "OK", IDOK, 50, 57, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 106, 57, 40, 14
+END
+
+DLG_CALLSWINOPTIONS DIALOG 130, 55, 144, 192
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Calls Window Options"
+FONT 8, "MS Shell DLG"
+BEGIN
+ AUTOCHECKBOX "Frame Pointer", ID_CWOPT_FRAMEPTR, 14, 14, 128, 10
+ AUTOCHECKBOX "Return Address", ID_CWOPT_RETADDR, 14, 30, 128, 10
+ AUTOCHECKBOX "Function Name", ID_CWOPT_FUNCNAME, 14, 44, 128, 10
+ AUTOCHECKBOX "Displacement", ID_CWOPT_DISPLACEMENT, 14, 59, 128, 10
+ AUTOCHECKBOX "Parameters", ID_CWOPT_PARAMS, 14, 74, 128, 10
+ AUTOCHECKBOX "First 4 DWORDS From Stack", ID_CWOPT_STACK, 14, 89, 128,
+ 10
+ AUTOCHECKBOX "Source Information", ID_CWOPT_SOURCE, 14, 104, 128, 10
+ AUTOCHECKBOX "Module Name", ID_CWOPT_MODULE, 14, 118, 128, 10
+ AUTOCHECKBOX "Runtime Function Info", ID_CWOPT_RTF, 15, 132, 128, 10
+ LTEXT "Maximum Frames", ID_CWOPT_MAXFRAMES_LABEL, 10, 152, 65,
+ 8
+ EDITTEXT ID_CWOPT_MAXFRAMES, 71, 149, 32, 12, ES_AUTOHSCROLL
+ PUSHBUTTON "OK", IDOK, 6, 172, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 52, 172, 40, 14
+ PUSHBUTTON "Help", 100, 98, 172, 40, 14
+END
+
+DLG_BADSYMBOLS DIALOG 86, 109, 276, 73
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Bad Symbolic Information"
+FONT 8, "MS Shell DLG"
+BEGIN
+ CTEXT "The file %s either has no symbolic information or the checksum/timestamp is wrong",
+ ID_BADSYM_TEXT, 8, 4, 264, 43
+ DEFPUSHBUTTON "&Browse", IDOK, 40, 55, 40, 14
+ PUSHBUTTON "&Use", IDCANCEL, 85, 55, 40, 14
+ PUSHBUTTON "Use &Always", ID_IGNOREALL, 129, 55, 45, 14
+ PUSHBUTTON "&Help", 100, 179, 55, 40, 14
+END
+
+DLG_TASKLIST DIALOG 74, 41, 194, 161
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Process Selection"
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "&Process List:", ID_TL_TASK_LIST_LABEL, 10, 6, 49, 8
+ LISTBOX ID_TL_TASK_LIST, 8, 17, 177, 101, WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Select", IDOK, 13, 135, 47, 20
+ PUSHBUTTON "&Cancel", IDCANCEL, 73, 135, 47, 20
+ PUSHBUTTON "&Help", 100, 133, 135, 47, 20
+END
+
+DLG_FSRESOLVE DIALOG 77, 26, 201, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION ""
+FONT 8, "MS Shell DLG"
+BEGIN
+ LTEXT "", ID_FSRESOLVE_STRING, 6, 9, 176, 8
+ LTEXT "This file can be mapped to several opened documents.",
+ -1, 5, 31, 190, 15
+ LTEXT "Please select the document to be used from the following list:",
+ -1, 4, 44, 124, 17
+ LISTBOX ID_FSRESOLVE_LIST, 4, 65, 123, 90, WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "&Use", ID_FSRESOLVE_USE, 133, 65, 62, 14
+ PUSHBUTTON "None", IDCANCEL, 133, 83, 62, 14
+ GROUPBOX "Add Directory to",-1,133,101,62,49
+ CONTROL "N&one",ID_FSRESOLVE_ADDNONE,"Button",BS_AUTORADIOBUTTON,138,113,31,10
+ CONTROL "Root &Map",ID_FSRESOLVE_ADDROOT,"Button",BS_AUTORADIOBUTTON, 138,125,44,10
+ CONTROL "&Source Path",ID_FSRESOLVE_ADDSOURCE,"Button",BS_AUTORADIOBUTTON,138,137,52,
+ 10
+END
+
+
diff --git a/private/windbg/windbg/disasm.c b/private/windbg/windbg/disasm.c
new file mode 100644
index 000000000..0686aca06
--- /dev/null
+++ b/private/windbg/windbg/disasm.c
@@ -0,0 +1,1062 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ disasm.c
+
+Abstract:
+
+ This file contains the code which controls the disassembly window.
+ It is a normal MDI window. The creation of each line of disassembly
+ is done by OSDEBUG.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+/************************** INCLUDE FILES *******************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef FE_IME
+#include <ime.h>
+#endif
+
+
+
+
+/************************** Structs and Defines *************************/
+/************************** Internal Prototypes *************************/
+
+int DsmGetBackAddress(void);
+void DisasmAlignInstr(ADDR *);
+
+/************************** Data declaration *************************/
+
+
+ADDR AddrDisasm;
+UINT CbDisasm;
+int StDisasm = DISASM_NONE;
+int CLinesDisasm = 0;
+long UlBaseOff;
+
+extern CXF CxfIp;
+extern LPSHF Lpshf;
+#define Lpei (&Ei)
+extern EI Ei;
+
+#undef LOCAL
+#define LOCAL
+
+/**********************************************************************/
+
+LOCAL void DisasmSetVScroll(VOID);
+LOCAL void DoVertScroll(HWND, WPARAM, LPARAM);
+
+
+/************************** Code *************************/
+
+
+void FAR PASCAL
+ViewDisasm(
+ LPADDR lpaddr,
+ int cmd
+ )
+
+/*++
+
+Routine Description:
+
+ This function will cause the disassembly window to be voided and
+ refershed in the edit manager. It reconstucts or adds to the existing
+ buffer.
+
+Arguments:
+
+ lpaddr - Supplies an address which is used in the disassembly
+ cmd - Supplies the operation to be preformed on the data
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int doc = Views[disasmView].Doc;
+ RECT rc;
+ int cLine;
+ SDI sds;
+ int x;
+ int y;
+ int i;
+ int cb;
+ NPVIEWREC v = &Views[disasmView];
+ BOOL fDisplay = FALSE;
+ BOOL fHighlight = FALSE;
+ BOOL fBreakpt = FALSE;
+ HBPT hbpt;
+ BPSTATUS bpstatus;
+ ADDR addrT;
+ ADDR addrPC;
+ ADDR addrT2;
+ int iLineFirst = v->iYTop;
+ int iPC = -1;
+ int iForce = -1;
+ int iLineCur = v->Y;
+ OFFSET offStart;
+ static BOOL fRecurse = FALSE;
+
+ /*
+ * Prevent recursive calls to this routine
+ */
+
+ if (fRecurse) {
+ return;
+ }
+ fRecurse = TRUE;
+
+ /*
+ * Assert that we really have a window to play with
+ */
+
+ Assert(disasmView != -1);
+
+ /*
+ * Don't bother if the window is currently iconized
+ */
+
+ if (IsIconic(GetParent(Views[disasmView].hwndClient))) {
+ fRecurse = FALSE;
+ return;
+ }
+
+ /*
+ * If no child active then clean out the existing listing and
+ * return with out any thing else happening
+ */
+
+ if (!DebuggeeActive() || LptdCur == NULL) {
+ v->Y = v->iYTop = 0;
+ DeleteAll(doc);
+ if (UlBaseOff != 0) {
+ SetScrollRange(Views[disasmView].hwndClient, SB_VERT, 0, 0, FALSE);
+ UlBaseOff = 0;
+ }
+ fRecurse = FALSE;
+ return;
+ }
+
+ if (UlBaseOff == 0) {
+ SetScrollRange(Views[disasmView].hwndClient, SB_VERT,
+ 0, 8*1024, FALSE);
+ SetScrollPos(Views[disasmView].hwndClient, SB_VERT, 0, TRUE);
+ }
+
+ /*
+ * Compute the number of lines for display in the window
+ */
+
+ GetClientRect(Views[disasmView].hwndClient, &rc);
+ cLine = rc.bottom / v->charHeight;
+
+ /*
+ * Use some minimum size to keep small windows from going crazy
+ */
+
+ if (cLine == 0) {
+ cLine = 1;
+ }
+
+ /*
+ * If the screen size if larger than the number of lines cached
+ * then force redisplay
+ */
+
+ if (cLine > CLinesDisasm) {
+ fDisplay = TRUE;
+ }
+
+ /*
+ * Look at all of the paging commands to see if we have a suffiecnt
+ * amount of data cached in the edit buffers.
+ */
+
+ if ((cmd & disasmDownPage) == disasmDownPage) {
+ if (iLineFirst + 2*cLine + 2 > CLinesDisasm) {
+ fDisplay = TRUE;
+ cLine = CLinesDisasm + cLine + 2;
+ } else {
+ fRecurse = FALSE;
+ return;
+ }
+ } else if ((cmd & disasmDownLine) == disasmDownLine) {
+ if (iLineFirst + cLine + 1 > CLinesDisasm) {
+ fDisplay = TRUE;
+ cLine = CLinesDisasm + cLine + 2;
+ } else {
+ fRecurse = FALSE;
+ return;
+ }
+ } else if ((cmd & disasmUpPage) == disasmUpPage) {
+ if (iLineFirst >= cLine) {
+ fRecurse = FALSE;
+ return;
+ } else {
+ i = DsmGetBackAddress();
+ iLineFirst += i;
+ iLineCur += i;
+ cLine = CLinesDisasm + i;
+ fDisplay = TRUE;
+ }
+ } else if ((cmd & disasmUpLine) == disasmUpLine) {
+ if (iLineFirst > 0) {
+ fRecurse = FALSE;
+ return;
+ } else {
+ i = DsmGetBackAddress();
+ iLineFirst += i;
+ iLineCur += i;
+ cLine = CLinesDisasm + i;
+ fDisplay = TRUE;
+ }
+ } else if ((cmd & disasmHighlight) == disasmHighlight ) {
+ cLine = __max(cLine,CLinesDisasm);
+ fDisplay = TRUE;
+ }
+
+ /*
+ * If we are suppose to have the PC in the current window then it
+ * was passed in as our parmeter. Check to see if PC is
+ * in the current range if display
+ */
+
+ if (lpaddr != NULL) {
+ SYFixupAddr(lpaddr);
+ }
+
+ if (cmd & disasmRefresh) {
+ fDisplay = TRUE;
+ for (i=iLineFirst; i< Docs[doc].NbLines ; i++) {
+ if (DisasmGetAddrFromLine(&addrT2, i)) {
+ StDisasm = -1;
+ AddrDisasm = addrT2;
+ break;
+ }
+ }
+ iLineCur = iLineCur - iLineFirst;
+ iLineFirst = 0;
+ }
+
+
+ if ((StDisasm == DISASM_NONE) ||
+ (cmd & disasmForce)) {
+ fDisplay = TRUE;
+ DisasmGetAddrFromLine(&AddrDisasm, iLineFirst);
+ iLineFirst = iLineCur = 0;
+ }
+
+ if ((cmd & disasmForce) &&
+ ((lpaddr->emi != AddrDisasm.emi) ||
+ (AddrDisasm.addr.seg != lpaddr->addr.seg) ||
+ (AddrDisasm.addr.off > lpaddr->addr.off) ||
+ (AddrDisasm.addr.off + CbDisasm <= lpaddr->addr.off))) {
+
+ AddrDisasm = *lpaddr;
+ StDisasm = -1;
+ UlBaseOff = ((AddrDisasm.addr.off + 2*1024 - 1) & ~(4*1024-1)) - 4*1024;
+ iLineFirst = iLineCur = 0;
+ }
+
+ /*
+ * Get the set of parameters which control the display of the
+ * disassembly window
+ */
+
+ if (fDisplay) {
+ v->Y = v->iYTop = 0;
+ DeleteAll(doc);
+ sds.dop = (runDebugParams.DisAsmOpts & ~(0x800)) | dopAddr |
+ dopOpcode | dopOperands;
+ } else {
+ sds.dop = 0;
+ }
+
+ if ((StDisasm == DISASM_NONE) &&
+ !((cmd & disasmPC) || (cmd & disasmForce))) {
+ fRecurse = FALSE;
+ return;
+ }
+
+ /*
+ * Initialize the address and disassembler query structures
+ */
+
+ sds.addr = AddrDisasm;
+
+ /*
+ * Grab a copy of the PC address so that we can check for a
+ * current PC highlight.
+ */
+
+ addrT2 = addrPC = *SHpADDRFrompCXT(&CxfIp.cxt);
+ SYFixupAddr(&addrPC);
+
+ /*
+ * Now start doing the dump into the edit window. Put a label
+ * here in case when we finish doing the dump we have not managed
+ * to get a desired address in the window.
+ */
+
+ again:
+
+ offStart = sds.addr.addr.off;
+
+ /*
+ * Dump the info into the buffer
+ */
+
+ for (i=0, y=0; i<cLine; i++, y++) {
+ /*
+ * Check to see if the current display offset is the
+ * same as that of the program counter.
+ */
+
+ if (addrPC.addr.off == sds.addr.addr.off) {
+ fHighlight = TRUE;
+ }
+
+ /*
+ * Check to see if the current display offset has a
+ * breakpoint set.
+ */
+
+ memcpy(&addrT, &sds.addr, sizeof(ADDR));
+ bpstatus = BPHbptFromAddr(&addrT, &hbpt);
+ fBreakpt = (bpstatus == BPNOERROR) || (bpstatus == BPAmbigous);
+
+ /*
+ * Now check to see if we have a label on the current line.
+ */
+
+ if (fDisplay) {
+ char rgchSymbol[60];
+ ADDR addrT = sds.addr;
+ LPCH lpchSymbol;
+ ODR odr;
+
+ addrT.emi = 0;
+ ADDR_IS_LI(addrT) = FALSE;
+ SYUnFixupAddr(&addrT);
+
+ odr.lszName = rgchSymbol;
+
+ lpchSymbol = SHGetSymbol(&addrT, &addrT2, sopNone, &odr);
+ if ((lpchSymbol != NULL) && (odr.dwDeltaOff == 0)) {
+ x = strlen(rgchSymbol);
+ InsertBlock(doc, 0, y, x, rgchSymbol);
+ InsertBlock(doc, x, y, 3, ":\r\n");
+ y += 1;
+ LineStatus(doc, y, DASM_LABEL_LINE, LINESTATUS_ON, FALSE, FALSE);
+ }
+ } else {
+ if (QueryLineStatus(doc, y+1, DASM_LABEL_LINE)) {
+ y += 1;
+ }
+ }
+
+ /*
+ * Check for force addresses
+ */
+
+ if (cmd & disasmForce) {
+ if (lpaddr->addr.off == sds.addr.addr.off) {
+ iForce = y;
+ }
+ }
+
+ /*
+ * Now finally get down to doing the actual disassembly. We
+ * call the EM to get most of the information and then
+ * just worry about the display
+ */
+
+ if (OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sds) == xosdNone) {
+ if (fDisplay) {
+ x = 0;
+ InsertBlock(doc, x, y, 2, (LPSTR) "\r\n");
+
+ if (sds.ichAddr != -1) {
+ cb = _fstrlen(&sds.lpch[sds.ichAddr]);
+ InsertBlock(doc, x, y, cb, &sds.lpch[sds.ichAddr]);
+ x = cb+1;
+ }
+
+ if (sds.ichBytes != -1) {
+ cb = _fstrlen(&sds.lpch[sds.ichBytes]);
+ InsertBlock(doc, x, y, cb, &sds.lpch[sds.ichBytes]);
+ x += __max(17, cb+1); // M00TODO -- 32-bits should be 17
+ }
+
+ Assert(sds.ichOpcode != -1);
+ cb = _fstrlen(&sds.lpch[sds.ichOpcode]);
+ InsertBlock(doc, x, y, cb, &sds.lpch[sds.ichOpcode]);
+ x += __max(12, cb+1);
+
+ if (sds.ichOperands != -1) {
+ cb = _fstrlen(&sds.lpch[sds.ichOperands]);
+ InsertBlock(doc, x, y, cb, &sds.lpch[sds.ichOperands]);
+ x += __max(25, cb+1);
+ }
+
+ if (sds.ichComment != -1) {
+ cb = _fstrlen(&sds.lpch[sds.ichComment]);
+ InsertBlock(doc, x, y, cb, &sds.lpch[sds.ichComment]);
+ x += __max(20, cb+1);
+ }
+ }
+
+ /*
+ * Deal with highlighting
+ */
+
+ if (fHighlight) {
+ LineStatus(doc, y+1, CURRENT_LINE, LINESTATUS_ON,
+ FALSE, !fDisplay);
+
+
+ fHighlight = FALSE;
+ iPC = y;
+ } else if (QueryLineStatus(doc, y+1, CURRENT_LINE)) {
+ LineStatus(doc, y+1, CURRENT_LINE, LINESTATUS_OFF,
+ FALSE, !fDisplay);
+
+ }
+
+ if (fBreakpt) {
+ LineStatus(doc, y+1, BRKPOINT_LINE, LINESTATUS_ON,
+ FALSE, !fDisplay);
+ } else if (QueryLineStatus(doc, y+1, BRKPOINT_LINE)) {
+ LineStatus(doc, y+1, BRKPOINT_LINE, LINESTATUS_OFF,
+ FALSE, !fDisplay);
+ }
+
+ } else {
+ }
+ }
+
+ /*
+ * If we are doing a pc update then we must have
+ * this address displayed on the screen
+ */
+
+ if ((cmd & disasmPC) && (iPC == -1) && fDisplay) {
+ AddrDisasm = *lpaddr;
+ sds.addr = AddrDisasm;
+ cmd &= ~disasmPC;
+ goto again;
+ }
+
+ /*
+ * Check to see if FORCE made it
+ */
+
+ if ((cmd & disasmForce) && (iForce == -1) && fDisplay) {
+ AddrDisasm = *lpaddr;
+ sds.addr = AddrDisasm;
+ cmd &= ~disasmForce;
+ goto again;
+ }
+
+ /*
+ * Deal with force and none redisplay
+ */
+
+ if ((cmd & DISASM_PC) == DISASM_PC) {
+ if (iLineFirst > iPC) {
+ iLineFirst = iPC;
+ } else if (iLineFirst + cLine < iPC) {
+ iLineFirst = iPC;
+ }
+ iLineCur = iPC;
+
+ if (fDisplay) {
+ ;
+ } else {
+ v->iYTop = iLineFirst;
+ InvalidateLines(disasmView, 0, LAST_LINE, FALSE);
+ }
+ }
+
+ /*
+ * Force a full repaint of the screen
+ */
+
+ if (fDisplay) {
+ v->iYTop = iLineFirst;
+ InvalidateLines(disasmView, 0, LAST_LINE, FALSE);
+
+ CbDisasm = (UINT) (sds.addr.addr.off - AddrDisasm.addr.off);
+ CLinesDisasm = cLine;
+ }
+
+ if (iLineCur != -1) {
+ iLineCur = min(iLineCur, Docs[v->Doc].NbLines-1);
+ v->Y = iLineCur;
+ if (curView == disasmView) {
+ SetCaret(disasmView, v->X, v->Y, -1);
+ }
+ }
+
+ DisasmSetVScroll();
+ fRecurse = FALSE;
+ return;
+} /* ViewDisasm() */
+
+
+/*** DisasmGetAddrFromLine
+**
+** Synopsis:
+** bool = DisasmGetAddrFromLine( lpAddr, iLine )
+**
+** Entry:
+** lpAddr - pointer to address structure to fill in
+** iLIne - line number to get address of
+**
+** Return:
+** TRUE if an address was retrived else FALSE
+**
+** Description:
+** This function is used to get the address corresponding to
+** a line in the disassembler window.
+*/
+
+BOOL FAR PASCAL DisasmGetAddrFromLine( LPADDR lpAddr, UINT iLine)
+{
+ int doc = Views[disasmView].Doc;
+ LPBLOCKDEF pb;
+ LPLINEREC pl;
+ int first = iLine;
+ char FAR * lpch;
+ char ch;
+ char rgch[50];
+
+ /*
+ ** Check to see if there is assembler or source code on this line
+ ** don't allow to goto source code only to assembler
+ */
+
+ FirstLine(doc, &pl, &first, &pb);
+
+ lpch = &pl->Text[0];
+ if ((*lpch < '0') || (*lpch > '9')) {
+ return FALSE;
+ }
+
+ while ((*lpch != 0) &&
+ ((('0' <= *lpch) && (*lpch <= '9')) ||
+ (('a' <= *lpch) && (*lpch <= 'f')) ||
+ (('A' <= *lpch) && (*lpch <= 'F')) ||
+ ('x' == *lpch) ||
+ (':' == *lpch) ||
+ ('#' == *lpch))) {
+ lpch++;
+ }
+
+ ch = *lpch;
+ *lpch = 0;
+
+ _fstrcpy(rgch, &pl->Text[0]);
+ *lpch = ch;
+
+
+ if (EEUnFormatAddr(lpAddr, rgch) != EENOERROR) {
+ return FALSE;
+ }
+
+ SYUnFixupAddr(lpAddr);
+ SYFixupAddr(lpAddr);
+
+ return TRUE;
+} /* DisasmGetAddrLine() */
+
+
+
+void
+DisasmSetVScroll(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to set the vertical scroll bar position. It
+ will get the first line which has an address and then position
+ the scroll bar according to that address. Additionally it will
+ adjust the scroll bar range if necessary according to the address.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int i;
+ ADDR addr;
+
+ /*
+ * Check that there is something in the window first.
+ */
+
+ if ((disasmView == -1) ||
+ (Docs[Views[disasmView].Doc].NbLines < 1)) {
+ return;
+ }
+
+ /*
+ * Get the first address after the top line in the window
+ */
+
+ for (i=0; TRUE; i++) {
+ if (Docs[Views[disasmView].Doc].NbLines <= i+Views[disasmView].iYTop) {
+ return;
+ }
+
+ if (DisasmGetAddrFromLine( &addr, i+Views[disasmView].iYTop )) {
+ break;
+ }
+ }
+
+ /*
+ * Now set the position in the scroll bar
+ */
+
+ i = addr.addr.off - UlBaseOff;
+
+ if ((i < 2*1024) || (i > 6*1024)) {
+ UlBaseOff = ((addr.addr.off + 2*1024 - 1) & ~(4*1024-1)) - 4*1024;
+ i = addr.addr.off - UlBaseOff;
+
+ }
+
+
+ SetScrollPos(Views[disasmView].hwndClient, SB_VERT, i, TRUE);
+
+ return;
+} /* DisasmSetVScroll() */
+
+
+
+LOCAL void
+DoVertScroll(
+ HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routin is used to process the vertical scroll messages for the
+ disassembly window
+
+Arguments:
+
+ hwnd - Supplies the handle to the disassmbly window
+ wParam - Supplies the wParam of the WM_VSCROLL message
+ lparam - Supplies the lParam of the WM_VSCROLL message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int vScrollInc;
+ int vScrollPos;
+ RECT rcl;
+ int lines;
+ int vWinLines;
+ NPVIEWREC v = &Views[disasmView];
+ int newY;
+ ADDR addr;
+
+ /*
+ * Get info we need
+ */
+
+ vScrollPos = v->iYTop;
+ lines = Docs[v->Doc].NbLines - 1;
+ GetClientRect(hwnd, &rcl);
+ vWinLines = max( 1, rcl.bottom / v->charHeight);
+
+ switch (LOWORD(wParam)) {
+ case SB_LINEUP:
+ vScrollInc = -1;
+ break;
+
+ case SB_LINEDOWN:
+ vScrollInc = 1;
+ break;
+
+ case SB_PAGEUP:
+ if (vWinLines > 6) {
+ vScrollInc = -vWinLines + 3;
+ } else {
+ vScrollInc = -vWinLines;
+ }
+ break;
+
+ case SB_PAGEDOWN:
+ if (vWinLines > 6) {
+ vScrollInc = vWinLines - 3;
+ } else {
+ vScrollInc = vWinLines;
+ }
+ break;
+
+ case SB_THUMBPOSITION:
+ memcpy(&addr, &AddrDisasm, sizeof(ADDR));
+ SYFixupAddr(&addr);
+ // align the offset to 32 bit machine word as PPC/MIPS/ALPHA
+ // instructions are 32 bits wide each
+ // It does not matter to the x86 as it always disasm -0x100
+ // ahead to get in sync.
+ addr.addr.off = (UlBaseOff + HIWORD(wParam)) & ~0x3;
+ DisasmAlignInstr(&addr); // realign starting address in x86 case
+ Unreferenced( lParam );
+ ViewDisasm(&addr, disasmForce);
+ return;
+
+ default:
+ return;
+
+ }
+
+ /*
+ * Some adjustments may be necessary to deal with the fact
+ * that the window is created on the fly.
+ *
+ * Are we paging to some place which is prior to the current
+ * start of the window. If so then we need to generate some
+ * more information at the start of the file.
+ */
+
+ if (vScrollPos + vScrollInc < 0) {
+ do {
+ ViewDisasm(NULL, disasmUpPage);
+ vScrollPos = v->iYTop;
+ if (AddrDisasm.addr.off == 0) {
+ break;
+ }
+ if (lines == Docs[v->Doc].NbLines - 1) {
+ break;
+ }
+ lines = Docs[v->Doc].NbLines - 1;
+ } while (vScrollPos + vScrollInc < 0);
+ lines = Docs[v->Doc].NbLines - 1;
+ } else if (vScrollPos + vScrollInc + vWinLines > Docs[v->Doc].NbLines - 1) {
+ do {
+ ViewDisasm(NULL, disasmDownPage);
+ DAssert(vScrollPos == v->iYTop);
+ if (Docs[v->Doc].NbLines == 1) {
+ return;
+ }
+ if (lines == Docs[v->Doc].NbLines - 1) {
+ break;
+ }
+ lines = Docs[v->Doc].NbLines - 1;
+ } while (vScrollPos + vScrollInc + vWinLines > Docs[v->Doc].NbLines - 1);
+ lines = Docs[v->Doc].NbLines - 1;
+ }
+
+
+ /*
+ * Continue with normal code VScroll code
+ */
+
+ newY = min(lines, v->Y + vScrollInc);
+
+ if (vScrollInc < 0) {
+ vScrollInc = max(vScrollInc, -vScrollPos);
+ } else {
+ lines -=(vScrollPos + vWinLines);
+ if ((rcl.bottom + v->charHeight - 1) % v->charHeight) {
+ lines++;
+ }
+ vScrollInc = max(min(vScrollInc, lines), 0);
+ }
+ vScrollPos += vScrollInc;
+
+ if (vScrollInc != 0) {
+
+ /*
+ * Set scroll-bar positions before refreshing the screen because
+ * we use the scroll-bar positions during the PAINT event
+ */
+
+ v->iYTop = vScrollPos;
+
+ ScrollWindow(hwnd, 0, - v->charHeight * vScrollInc, NULL, NULL);
+ UpdateWindow(hwnd);
+
+ }
+
+#if 0
+ if (scrollOrigin & FROM_KEYBOARD) {
+ if (scrollOrigin & SELECTING) {
+ int OldYR;
+
+ if (!v->BlockStatus) {
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->BlockXR = v->X;
+ v->BlockYL = v->BlockYR = v->Y;
+ }
+ PosXY(view, v->X, newY, FALSE);
+ OldYR = v->BlockYR;
+ v->BlockXR = v->X;
+ v->BlockYR = v->Y;
+ InvalidateLines(view, min(OldYR, v->BlockYR), max (OldYR, v->BlockYR), FALSE);
+ } else {
+ PosXY(view, v->X, newY, FALSE);
+ }
+ }
+#endif // 0
+ return;
+} /* DoVertScroll() */
+
+/*** DisasmEditProc
+**
+** Synopsis:
+** long = DisasmEditProc(hwnd, msg, wParam, lParam)
+**
+** Entry:
+** hwnd - window handle to the disassembly window
+** msg - Message to be processes
+** wParam - info about the message
+** lParam - info about the message
+**
+** Returns:
+**
+** Description:
+** This function is the window message processor for the disassembly
+** window class. It processes those messages which are of interest
+** to this specific window class and passes all other messages on to
+** the default MDI window procedure handler
+**
+*/
+
+long FAR PASCAL EXPORT
+DisasmEditProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+
+ switch ( msg ) {
+ case WU_INITDEBUGWIN:
+ /*
+ **
+ */
+
+ StDisasm = DISASM_NONE;
+ memset(&AddrDisasm, 0, sizeof(AddrDisasm));
+ UlBaseOff = 1; /* Force the scroll bar to be hidden */
+ Views[disasmView].iYTop = 0; /* Give use a line to start with */
+ if (DebuggeeActive()) {
+ UlBaseOff = 0;
+ ViewDisasm(SHpADDRFrompCXT(&CxfIp.cxt), DISASM_PC);
+ }
+ break;
+
+ case WM_KEYDOWN:
+ switch ( wParam ) {
+ case VK_PRIOR:
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
+ return FALSE;
+
+ case VK_NEXT:
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
+ return FALSE;
+
+ case VK_UP:
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
+ return FALSE;
+
+ case VK_DOWN:
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
+ return FALSE;
+
+ case VK_HOME:
+ ViewDisasm(SHpADDRFrompCXT(&CxfIp.cxt), DISASM_PC);
+ return FALSE;
+ }
+ return FALSE;
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ if (IR_STRING == wParam) {
+ return TRUE;
+ }
+ break;
+#endif
+
+ case WM_CHAR:
+ return FALSE;
+
+ case WM_VSCROLL:
+ DoVertScroll(hwnd, wParam, lParam);
+ SetFocus (hwnd);
+ return FALSE;
+
+ case WM_FONTCHANGE:
+ ViewDisasm(&AddrDisasm, DISASM_OTHER);
+ return FALSE;
+
+ case WM_SIZE:
+ CallWindowProc(lpfnEditProc, hwnd, msg, wParam, lParam);
+ if (wParam != SIZEICONIC) {
+ ViewDisasm(&AddrDisasm, DISASM_OTHER);
+ }
+ WindowTitle( disasmView, 0 );
+ return FALSE;
+
+ }
+ return CallWindowProc(lpfnEditProc, hwnd, msg, wParam, lParam);
+} /* DisasmWndProc() */
+
+/*** DsmGetBackAddress
+**
+** Synopsis:
+** int = DsmGetBackAddress()
+**
+** Entry:
+** None
+**
+** Returns:
+** count of lines in the added space
+**
+** Description:
+**
+*/
+
+int DsmGetBackAddress()
+{
+ SDI sdi;
+ int i;
+ ADDR addr;
+ ADDR addr2;
+ ADDR addrT2;
+ char rgchSymbol[60];
+ ODR odr;
+ char * lpchSymbol;
+
+ sdi.addr = AddrDisasm;
+ sdi.dop = 0;
+ if (sdi.addr.addr.off < 0x100) {
+ sdi.addr.addr.off = 0;
+ } else {
+ sdi.addr.addr.off -= 0x100;
+
+ /*
+ ** disassemble 10 instructions in an attempt to syncronize with
+ ** the true code stream
+ */
+
+ for (i=0; i<10; i++) {
+ if (OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sdi) == xosdNone) {
+ } else {
+ Assert(FALSE);
+ }
+ }
+ }
+
+ addr = sdi.addr;
+ odr.lszName = rgchSymbol;
+ for (i=0; TRUE; i++) {
+ if (sdi.addr.addr.off >= AddrDisasm.addr.off) {
+ AddrDisasm = addr;
+ return( i );
+ }
+ addr2 = sdi.addr;
+ addr2.emi = 0;
+ ADDR_IS_LI(addr2) = FALSE;
+ SYUnFixupAddr(&addr2);
+ lpchSymbol = SHGetSymbol(&addr2, &addrT2, sopNone, &odr);
+ if ((lpchSymbol != NULL) && (odr.dwDeltaOff == 0)) {
+ i += 1;
+ }
+
+ if (OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sdi) != xosdNone) {
+ Assert(FALSE);
+ }
+ }
+ Assert(FALSE);
+ return( 0 );
+} /* DsmGetBackAddress() */
+
+/*** DisasmAlignInstr
+**
+** Synopsis:
+** DisasmAlignInstr
+**
+** Entry:
+** Starting address
+**
+** Returns:
+** None
+**
+** Description:
+** Modify address offset to match instructions boundary if necessary.
+*/
+
+void DisasmAlignInstr(ADDR *curraddr)
+{
+ SDI sdi;
+ int i;
+
+ sdi.addr = *curraddr;
+ sdi.dop = 0;
+ if (sdi.addr.addr.off < 0x100) {
+ curraddr->addr.off = 0;
+ return;
+ } else {
+ sdi.addr.addr.off -= 0x100;
+
+ /*
+ ** disassemble 10 instructions in an attempt to syncronize with
+ ** the true code stream
+ */
+
+ for (i=0;i<0x100;i++) {
+ if (OSDUnassemble(LppdCur->hpid, LptdCur->htid, &sdi) == xosdNone) {
+ } else {
+ Assert(FALSE);
+ }
+ if (sdi.addr.addr.off >= curraddr->addr.off) {
+ *curraddr = sdi.addr;
+ return;
+ }
+ }
+ }
+}
+
diff --git a/private/windbg/windbg/docfile.c b/private/windbg/windbg/docfile.c
new file mode 100644
index 000000000..64ede3f7e
--- /dev/null
+++ b/private/windbg/windbg/docfile.c
@@ -0,0 +1,1247 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ docfile.c
+
+Abstract:
+
+ This file contains some of the routines which deal with the document
+ buffer.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define NON_VALID_LEVEL 32000
+#define START_COMMENT 1
+#define END_COMMENT 2
+
+
+/*** Flush
+**
+** Synopsis:
+** bool = Flush(szFileName)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL NEAR PASCAL Flush(LPSTR FileName)
+{
+ int written;
+
+ written = _lwrite (rd_fh, rd_buf, rd_offset);
+ if (written == -1)
+ return ErrorBox(ERR_File_Write, (LPSTR)FileName);;
+ if (written < rd_offset)
+ return ErrorBox(ERR_File_Disk_Full, (LPSTR)FileName);
+ return TRUE;
+} /* Flush() */
+
+/*** PutChar
+**
+*/
+
+BOOL NEAR PASCAL PutChar(LPSTR FileName, char ch)
+{
+ if (rd_offset >= DISK_BLOCK_SIZE) {
+ if (!Flush(FileName))
+ return FALSE;
+ rd_offset = 0;
+ }
+ rd_buf[rd_offset++] = ch;
+ return TRUE;
+} /* PutChar() */
+
+/*** LoadChar
+**
+** Synopsis:
+** char = LoadChar()
+**
+** Entry:
+** none
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+char NEAR PASCAL LoadChar()
+{
+ if (rd_offset >= rd_read)
+ if (rd_read < DISK_BLOCK_SIZE)
+ return CTRL_Z;
+ else {
+ rd_read = _lread (rd_fh, rd_buf, DISK_BLOCK_SIZE);
+ if (rd_read < 0)
+ return -1;
+ else if (rd_read == 0)
+ return CTRL_Z;
+ rd_offset = 0;
+ }
+ return (char)rd_buf[rd_offset++];
+} /* LoadChar() */
+
+
+/*** StoreLine
+**
+** Synopsis:
+** bool = StoreLine()
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL NEAR PASCAL StoreLine(char *line, int lineLen, int *offset, BYTE *prevLength,
+ LPBLOCKDEF * pCurBlock)
+{
+ LPLINEREC pl;
+
+ if ((*offset + (LHD + lineLen)) > BLOCK_SIZE) {
+
+ //We arrived at the end of the block. Allocates a new one.
+
+ if (!AllocateBlock(*pCurBlock, NULL, pCurBlock))
+ return FALSE;
+
+ ((*pCurBlock)->PrevBlock)->NextBlock = *pCurBlock;
+ *offset = 0;
+ if ((*pCurBlock)->PrevBlock == NULL)
+ *prevLength = 0;
+ }
+ (*pCurBlock)->LastLineOffset = *offset;
+ pl = (LPLINEREC)((*pCurBlock)->Data + *offset);
+ AssertAligned(pl);
+
+ pl->PrevLength = *prevLength;
+ pl->Length = (BYTE)(LHD + lineLen);
+ pl->Status = 0;
+ _fmemmove((LPSTR)(pl->Text), (LPSTR)line, lineLen);
+
+ *prevLength = (BYTE)(LHD + lineLen);
+ *offset += LHD + lineLen;
+#ifdef ALIGN
+ *offset = (*offset + 3) & ~3;
+#endif
+ return TRUE;
+} /* StoreLine() */
+
+/*** TruncateLine
+**
+** Synopsis:
+** bool = TruncateLine(line, nbLines)
+**
+** Entry:
+** line
+** nbLines
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL NEAR PASCAL TruncateLine(PSTR line, int nbLines)
+{
+ if (QuestionBox(ERR_Truncate_Line, MB_OKCANCEL, nbLines + 1) == IDOK) {
+ line[MAX_USER_LINE] = CR;
+ return TRUE;
+ }
+ return FALSE;
+} /* TruncateLine() */
+
+/*** LoadLine
+**
+** Synopsis:
+** w = LoadLine(szLine, pLineLen, nbLines)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+WORD NEAR PASCAL LoadLine(PSTR line, int *lineLen, int nbLines)
+{
+ char prevCh = 0;
+ register char ch;
+ int level = NON_VALID_LEVEL;
+ int extLineLen = 0;
+ int totLen;
+
+ *lineLen = 0;
+
+ while (TRUE) {
+
+ //Load next char, don't call LoadChar function to go faster
+
+ if (rd_offset >= rd_read)
+ if (rd_read < DISK_BLOCK_SIZE)
+ ch = CTRL_Z;
+ else {
+ rd_read = _lread (rd_fh, rd_buf, DISK_BLOCK_SIZE);
+ if (rd_read < 0)
+ return ERR_File_Read;
+ else {
+ if (rd_read == 0)
+ ch = CTRL_Z;
+ else
+ ch = (char)rd_buf[0];
+ }
+ rd_offset = 1;
+ }
+ else
+ ch = (char)rd_buf[rd_offset++];
+
+ switch (ch) {
+
+ case CR:
+ break;
+
+ case LF:
+ if (*lineLen > MAX_USER_LINE)
+ {
+ if (TruncateLine(line, nbLines))
+ {
+
+ if (environParams.keepTabs)
+ (*lineLen)--;
+ else
+ *lineLen = MAX_USER_LINE;
+
+ }
+ else
+ return END_ABORT;
+ }
+ return END_OF_LINE;
+
+
+
+ case TAB:
+ {
+ int i;
+
+ //Calc number of spaces to insert
+
+ if (environParams.keepTabs)
+ totLen = extLineLen;
+ else
+ totLen = *lineLen;
+
+ i = tabSize - (totLen % tabSize);
+
+ if (totLen + i >= MAX_USER_LINE) {
+ if (TruncateLine(line, nbLines)) {
+
+ char k;
+
+ //Padd blanks until end of line or remove char
+
+ if (environParams.keepTabs)
+ (*lineLen)--;
+ else
+ while (*lineLen < (MAX_USER_LINE))
+ line[(*lineLen)++] = ' ';
+
+
+
+ //Discard rest of line from input file
+
+ do {
+ k = LoadChar();
+ } while (k != - 1 && k != CTRL_Z && k != LF);
+ switch (k) {
+ case -1:
+ return ERR_File_Read;
+ case LF:
+ return END_OF_LINE;
+ case CTRL_Z:
+ return END_OF_FILE;
+ }
+
+ return END_OF_LINE;
+
+ } else
+ return END_ABORT;
+ }
+
+ //Skip if we keep the tab
+
+ if (environParams.keepTabs) {
+ extLineLen += i;
+ goto defaut;
+ }
+
+ //Insert spaces otherwise
+
+ while (i--)
+ line[(*lineLen)++] = ' ';
+ break;
+ }
+
+ case CTRL_Z:
+ return END_OF_FILE;
+
+ default:
+ defaut:
+ if (environParams.keepTabs)
+ totLen = extLineLen;
+ else
+ totLen = *lineLen;
+
+ if (totLen > MAX_USER_LINE) {
+ if (TruncateLine(line, nbLines)) {
+
+ char k;
+
+ if (environParams.keepTabs)
+ (*lineLen)--;
+ else
+ *lineLen = MAX_USER_LINE;
+
+
+ //Discard rest of line from input file
+ do {
+ k = LoadChar();
+ } while (k != - 1 && k != CTRL_Z && k != LF);
+ switch (k) {
+ case -1:
+ return ERR_File_Read;
+ case LF:
+ return END_OF_LINE;
+ case CTRL_Z:
+ return END_OF_FILE;
+ }
+ return END_OF_LINE;
+
+
+ } else
+ return END_ABORT;
+ }
+ line[(*lineLen)++] = (char)ch;
+ extLineLen++;
+ }
+ prevCh = ch;
+ }
+} /* LoadLine() */
+
+/*** LoadFile
+**
+** Synopsis:
+** bool = LoadFile(d)
+**
+** Entry:
+** d - Notepad Document record for file to be loaded
+**
+** Returns:
+** TRUE if the file was loaded and FALSE otherwise
+**
+** Description:
+** Load file in memory and initialize blocks.
+*/
+
+BOOL NEAR PASCAL LoadFile(int doc)
+{
+ NPDOCREC d =&Docs[doc];
+ char line[MAX_USER_LINE + 1];
+ int offset; //Current offset of storage in block
+ int lineLen;
+ BYTE prevLength; //Previous line size
+ HCURSOR hSaveCursor;
+ struct _stat fileStat;
+ WORD res;
+ WORD nbLines = 0;
+ OFSTRUCT of;
+
+ if ((rd_fh = OpenFile(d->FileName, &of, OF_READWRITE | OF_SHARE_DENY_NONE)) < 0) {
+ //
+ // Let's try as a readonly, and cancel if failed
+ //
+ if ((rd_fh = OpenFile(d->FileName, &of, OF_READ | OF_SHARE_DENY_NONE)) < 0) {
+ ErrorBox( ERR_File_Open, (LPSTR)d->FileName );
+ return FALSE;
+ } else {
+ d->readOnly = TRUE;
+ }
+ }
+
+ //Store file date
+
+ if (_fstat(rd_fh, &fileStat) == 0)
+ d->time = fileStat.st_mtime;
+ else
+ time(&d->time);
+
+ if ((rd_buf = DocAlloc(DISK_BLOCK_SIZE)) == NULL) {
+ ErrorBox(SYS_Allocate_Memory);
+ goto error1;
+ }
+
+ //Alloc first block
+
+ if (!AllocateBlock(NULL, NULL, &d->FirstBlock))
+ return FALSE;
+
+ //If we are in reload mode, and a message box shows up, a repaint
+ //of the document being loaded is done, so force number of lines
+ //to a value != 0
+
+ d->NbLines = MAX_LINE_NUMBER;
+
+ d->LastBlock = d->FirstBlock;
+ rd_read = DISK_BLOCK_SIZE;
+ rd_offset = DISK_BLOCK_SIZE;
+ offset = 0;
+ prevLength = 0;
+
+ //Set the Hour glass cursor
+
+ hSaveCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
+
+ //Read file line after line
+
+ res = LoadLine(line, &lineLen, nbLines);
+ while (res == END_OF_LINE) {
+
+ //Truncate a file too large
+
+ if (nbLines >= MAX_LINE_NUMBER - 1) {
+ ErrorBox(ERR_Truncate_Doc);
+ res = END_OF_FILE;
+ break;
+ }
+
+ if (!StoreLine(line, lineLen, &offset, &prevLength, &d->LastBlock)) {
+ res = END_ABORT;
+ break;
+ }
+
+ res = LoadLine(line, &lineLen, ++nbLines);
+ }
+
+ //Take decisions
+
+ switch (res) {
+
+ case END_OF_FILE:
+
+ //Store last line
+
+ if (StoreLine(line, lineLen, &offset, &prevLength, &d->LastBlock)) {
+
+ nbLines++;
+
+ //Free memory
+
+ if (!DocFree(rd_buf))
+ InternalErrorBox(SYS_Free_Memory);
+
+ //Restore cursor
+
+ SetCursor(hSaveCursor);
+
+ _lclose (rd_fh);
+ d->NbLines = nbLines;
+ return TRUE;
+ } else
+ goto abort;
+
+ case ERR_File_Read:
+ case ERR_Not_A_Text_File:
+ ErrorBox(res, (LPSTR)d->FileName);
+ //Fall through
+
+ case END_ABORT:
+ {
+ LPBLOCKDEF pB;
+
+ abort:
+ while (TRUE) {
+
+ pB = (d->LastBlock)->PrevBlock;
+ if (!DocFree((LPSTR)d->LastBlock))
+ InternalErrorBox(SYS_Free_Memory);
+ d->LastBlock = pB;
+ if (pB == NULL)
+ break;
+ }
+ SetCursor(hSaveCursor);
+ break;
+ }
+
+ default:
+ Assert(FALSE);
+ break;
+ }
+
+ //Restore cursor
+
+ SetCursor(hSaveCursor);
+
+ if (!DocFree(rd_buf))
+ InternalErrorBox(SYS_Free_Memory);
+
+ error1: {
+ _lclose (rd_fh);
+ }
+
+ return FALSE;
+} /* LoadFile() */
+
+/*** MergeFile
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL MergeFile(LPSTR FileName, int view)
+{
+ HCURSOR hSaveCursor;
+ char line[MAX_USER_LINE + 1];
+ int offset; //Current offset of storage in block
+ int lineLen; // length of line
+ BYTE prevLength; //Previous line size
+ NPVIEWREC v = &Views[view];
+ WORD res;
+ NPDOCREC d =&Docs[v->Doc];
+ LPLINEREC pCurLine, pLastLine;
+ LPBLOCKDEF pCurBlock, pNewBlock;
+ int y;
+
+ Assert( v->Doc >= 0);
+
+
+ if ((rd_fh = _lopen(FileName, OF_READ)) < 0)
+ return ErrorBox(ERR_File_Open, (LPSTR)FileName);
+
+ if ((rd_buf = DocAlloc(DISK_BLOCK_SIZE)) == NULL) {
+ ErrorBox(SYS_Allocate_Memory);
+ goto error1;
+ }
+
+ rd_read = DISK_BLOCK_SIZE;
+ rd_offset = DISK_BLOCK_SIZE;
+ lineLen = 0;
+
+ //Delete selected text if any
+ if (v->BlockStatus) {
+
+ int XR, YR;
+
+ GetBlockCoord (view, &(v->X), &(v->Y), &XR, &YR);
+ DeleteStream(view, v->X, v->Y, XR, YR, FALSE);
+ }
+
+ //Set the Hour glass cursor
+ hSaveCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ //Insert first line
+
+ res = LoadLine(line, &lineLen, d->NbLines);
+ if (res == END_OF_FILE || res == END_OF_LINE) {
+
+ //Add a CR+LF
+ if (res == END_OF_LINE) {
+ line[lineLen] = CR;
+ line[lineLen + 1] = LF;
+ lineLen += 2;
+ }
+ if (!InsertBlock(v->Doc, v->X, v->Y, (WORD) lineLen, line))
+ goto error2;
+ }
+ else {
+
+ if (res == ERR_File_Read || res == ERR_Not_A_Text_File)
+ ErrorBox(res, (LPSTR)FileName);
+ goto error2;
+ }
+
+ if (res != END_OF_FILE) {
+
+ //Get current line status (we just inserted it)
+
+ y = v->Y;
+ if (!FirstLine(v->Doc, &pCurLine, &y, &pCurBlock))
+ return FALSE;
+
+ //Get next line (just after the line we just inserted)
+
+ if (!NextLine(v->Doc, &pCurLine, &y, &pCurBlock))
+ return FALSE;
+
+ //Set offset to StoreLine start
+ offset = (LPSTR)pCurLine - (LPSTR)pCurBlock->Data;
+ prevLength = pCurLine->PrevLength;
+
+ //Split block in 2 blocks by first allocating a new block and then
+ //copying right side of block in new block
+
+ if (!AllocateBlock(pCurBlock, pCurBlock->NextBlock, &pNewBlock))
+ return FALSE;
+
+ pLastLine = (LPLINEREC)(pCurBlock->Data + pCurBlock->LastLineOffset);
+ _fmemmove(pNewBlock->Data, (LPSTR)pCurLine,
+ (LPSTR)pLastLine - (LPSTR)pCurLine + pLastLine->Length);
+
+ //Set new old block len and new new block len
+ pCurBlock->LastLineOffset = (LPSTR)pCurLine - (LPSTR)pCurBlock->Data - pCurLine->PrevLength;
+ pNewBlock->LastLineOffset = (LPSTR)pLastLine - (LPSTR)pCurLine;
+
+ //Backward links next block with new one
+ if (pCurBlock->NextBlock == NULL)
+ d->LastBlock = pNewBlock;
+ else
+ (pCurBlock->NextBlock)->PrevBlock = pNewBlock;
+
+ //Forward link current block with new block
+
+ pCurBlock->NextBlock = pNewBlock;
+
+ CloseLine(v->Doc, &pCurLine, y, &pCurBlock);
+
+ //Read and store all lines in new blocks
+
+ res = LoadLine(line, &lineLen, d->NbLines);
+ while (res == END_OF_LINE) {
+
+ //Truncate a file too large
+
+ if (d->NbLines >= MAX_LINE_NUMBER - 1) {
+ ErrorBox(ERR_Truncate_Doc);
+ res = END_OF_FILE;
+ break;
+ }
+
+ if (!StoreLine(line, lineLen, &offset, &prevLength, &pCurBlock)) {
+ res = END_ABORT;
+ break;
+ }
+
+ res = LoadLine(line, &lineLen, ++d->NbLines);
+ }
+
+ //Take decisions
+ switch (res) {
+
+ case END_OF_FILE:
+
+ //Store last line
+ if (StoreLine(line, lineLen, &offset, &prevLength, &pCurBlock)) {
+
+ d->NbLines++;
+
+ //Forward link of last allocated block with new block
+
+ pCurBlock->NextBlock = pNewBlock;
+
+ //Backward link of new block with last allocated block
+
+ pNewBlock->PrevBlock = pCurBlock;
+ ((LPLINEREC)(pNewBlock->Data))->PrevLength = (BYTE)(lineLen + LHD);
+
+ //Free memory
+
+ if (!DocFree(rd_buf))
+ InternalErrorBox(SYS_Free_Memory);
+
+ //Restore cursor
+
+ SetCursor(hSaveCursor);
+
+ //Check syntax if C
+
+ if (d->language == C_LANGUAGE) {
+ d->lineTop = 0;
+ d->lineBottom = d->NbLines;
+ CheckSyntax(v->Doc);
+ }
+ SetVerticalScrollBar(view, TRUE);
+
+ PosXY(view, v->X, v->Y, FALSE);
+ InvalidateRect(v->hwndClient, (LPRECT)NULL, FALSE);
+
+ _lclose (rd_fh);
+ return TRUE;
+ }
+ else
+ goto abort;
+
+ case ERR_File_Read:
+ case ERR_Not_A_Text_File:
+ ErrorBox(res, (LPSTR)FileName);
+ //Fall through
+
+ case END_ABORT:
+ {
+
+ abort:
+ SetCursor(hSaveCursor);
+ break;
+ }
+
+ default:
+ Assert(FALSE);
+ break;
+ }
+
+ } else
+ InvalidateRect(v->hwndClient, (LPRECT)NULL, FALSE);
+
+ error2: {
+ SetCursor (hSaveCursor);
+ if (!DocFree(rd_buf))
+ InternalErrorBox(SYS_Free_Memory);
+ }
+
+ error1: {
+ _lclose (rd_fh);
+ }
+
+ return FALSE;
+} /* MergeFile() */
+
+/*** CreateUntitled
+**
+** Synopsis:
+** void = CreateUntitled(szFileName, i)
+**
+** Entry:
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Create or open a new document
+**
+*/
+
+void NEAR PASCAL CreateUntitled(PSTR FileName, int i)
+{
+ char tmp[MAX_MSG_TXT];
+
+ Dbg(LoadString(hInst, SYS_Untitled_File, tmp, MAX_MSG_TXT));
+ sprintf((LPSTR)FileName, (LPSTR)tmp, i, (LPSTR)(szStarDotC + 1));
+}
+
+
+int PASCAL
+OpenDocument(
+ WORD mode,
+ WORD type,
+ int doc,
+ LPSTR FileName,
+ int dupView,
+ int Preference
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to create a new document or to duplicate
+ the view of an existing document.
+
+Arguments:
+
+ mode - Supplies MODE_DUPLICATE if the document is to be duplicated
+ MODE_RELOAD if the file is to be reloaded
+ MODE_CREATE if the document is to be created
+ type - Supplies the document type
+ doc - Supplies
+ FileName - Supplies a pointer to the name of the file for the document
+ dupView - Supplies the view to be duplicated (mode == MODE_DUPLICATE)
+ Preference - Supplies the view preference (-1 if none)
+
+Return Value:
+
+ -1 on failure
+ view number on success (>= 0)
+ return-value - Description of conditions needed to return value. - or -
+
+--*/
+
+{
+ LPLINEREC pl;
+ int view;
+ BOOL create;
+ int n;
+ int language;
+ NPDOCREC d;
+ NPVIEWREC views;
+
+ /*
+ * In mode duplicate, we create a new view being a copy of the previous
+ * view of the same document
+ */
+
+ if (mode == MODE_DUPLICATE) {
+
+ /*
+ * Search a free entry for the view we will create
+ */
+
+ if ( (Preference != -1) && Views[ Preference ].Doc == -1 ) {
+ view = Preference;
+ } else {
+ for (view = 0; (view < MAX_VIEWS) && (Views[view].Doc != -1); view++);
+ }
+
+ if (view == MAX_VIEWS) {
+ ErrorBox(ERR_Too_Many_Opened_Views);
+ return -1;
+ }
+
+ /*
+ * Copy parameters from previous view
+ */
+
+ Assert( Docs[Views[dupView].Doc].FirstView >= 0);
+
+ /*
+ * Find the last view for this document
+ */
+
+ n = dupView;
+ while (Views[n].NextView != -1) {
+ n = Views[n].NextView;
+ }
+
+ Assert(n < MAX_VIEWS);
+
+ /*
+ * Attach new view to last one found
+ */
+
+ Views[view] = Views[n];
+ Views[n].NextView = view;
+ Views[view].hwndClient = NULL;
+
+ /*
+ *
+ */
+
+ Views[view].iYTop = Views[dupView].iYTop;
+
+ /*
+ * Enlist view in window menu
+ */
+
+ AddWindowMenuItem(Views[dupView].Doc, view);
+
+ return view;
+
+ } else if (mode == MODE_RELOAD)
+ view = Docs[doc].FirstView;
+
+ /*
+ * First search a free entry for the document
+ */
+
+ if (mode != MODE_RELOAD) {
+ for (doc = 0;
+ (doc < MAX_DOCUMENTS) && (Docs[doc].FirstView != -1);
+ doc++);
+ }
+
+ if (doc >= MAX_DOCUMENTS) {
+ ErrorBox(ERR_Too_Many_Opened_Documents);
+ return -1;
+ }
+
+ d = &Docs[doc];
+
+ if (type == DOC_WIN) {
+
+ /*
+ * Check if file is not already loaded
+ */
+
+ if (mode == MODE_RELOAD) {
+ DestroyDocument(doc);
+ language = SetLanguage(doc);
+ } else {
+ if (FileName != NULL) {
+
+ _fstrcpy(szPath, FileName);
+ _fullpath(d->FileName, szPath, _MAX_PATH);
+
+ for (n = 0; n < MAX_DOCUMENTS; n++) {
+ if (Docs[n].FirstView != -1
+ && _strcmpi(Docs[n].FileName, d->FileName) == 0) {
+
+ StatusText(ERR_File_Already_Loaded, STATUS_INFOTEXT, TRUE, FileName);
+ MessageBeep(0);
+
+ /*
+ * Reactivate window
+ */
+
+ SendMessage(hwndMDIClient, WM_MDIACTIVATE,
+ (WPARAM) Views[Docs[n].FirstView].hwndFrame,
+ 0L);
+ return -1;
+ }
+ }
+
+ language = SetLanguage(doc);
+
+ } else {
+
+ /*
+ * Initialize document record and first view
+ */
+
+ register int i, j;
+
+ for (i = 0; i < MAX_DOCUMENTS; i++) {
+ CreateUntitled(d->FileName, i + 1);
+ for (j = 0; j < MAX_DOCUMENTS; j++) {
+ if (j != doc &&
+ _strcmpi (d->FileName, Docs[j].FileName) == 0) {
+ break;
+ }
+ }
+ if (j >= MAX_DOCUMENTS) {
+ break;
+ }
+ }
+
+ language = C_LANGUAGE;
+ }
+ }
+ } else {
+
+ WORD winTitle;
+ char rgch[_MAX_PATH];
+
+ language = NO_LANGUAGE;
+
+ /*
+ * Non Document type, Load window title from ressource
+ */
+
+ switch (type) {
+
+ case DISASM_WIN:
+ winTitle = SYS_DisasmWin_Title;
+ break;
+ case COMMAND_WIN:
+ winTitle = SYS_CmdWin_Title;
+ break;
+ case MEMORY_WIN:
+ winTitle = SYS_MemoryWin_Title;
+ break;
+ default:
+ Assert(FALSE);
+ return -1;
+ break;
+ }
+ Dbg(LoadString(hInst, winTitle, rgch, MAX_MSG_TXT));
+ RemoveMnemonic(rgch, d->FileName);
+
+ if (type == MEMORY_WIN) {
+ lstrcat (d->FileName,"(");
+ lstrcat (d->FileName,TempMemWinDesc.szAddress);
+ lstrcat (d->FileName,")");
+ }
+ }
+
+ /*
+ * Then search a free entry for the first view we will create
+ */
+
+ if (mode != MODE_RELOAD) {
+
+ if ( (Preference != -1) && Views[ Preference ].Doc == -1 ) {
+ view = Preference;
+ } else {
+ for (view = 0; view < MAX_VIEWS && Views[view].Doc != -1; view++);
+ }
+ if (view == MAX_VIEWS) {
+ ErrorBox(ERR_Too_Many_Opened_Views);
+ return -1;
+ }
+ }
+
+ /*
+ * Check if file exist
+ */
+
+ if (mode == MODE_CREATE || type != DOC_WIN) {
+ create = TRUE;
+ } else {
+ if (mode == MODE_OPEN || FileExist(FileName)) {
+ create = FALSE;
+ } else {
+ if (mode == MODE_OPENCREATE) {
+
+ /*
+ * Ask user whether to create or cancel
+ */
+
+ if (QuestionBox(SYS_Does_Not_Exist_Create,
+ MB_YESNO, (LPSTR)FileName) == IDYES) {
+ create = TRUE;
+ } else {
+ return -1;
+ }
+ } else {
+ create = FALSE;
+ }
+ }
+ }
+
+ d->readOnly = FALSE;
+ d->docType = type;
+ d->language = (WORD) language;
+ d->untitled = (FileName == NULL);
+ d->ismodified = FALSE;
+
+ if (create) {
+
+ LPBLOCKDEF pb;
+
+ /*
+ * Initialize the file with a null-string
+ */
+
+
+ d->LastBlock = d->FirstBlock = (LPBLOCKDEF)DocAlloc(sizeof(BLOCKDEF));
+ time(&d->time);
+
+ if (d->FirstBlock == NULL) {
+ ErrorBox(SYS_Allocate_Memory);
+ return -1;
+ }
+
+ pb = d->FirstBlock;
+
+ /*
+ * Initialize first block
+ */
+
+ pb->PrevBlock = pb->NextBlock = NULL;
+ pb->LastLineOffset = 0;
+
+ /*
+ * Initialize first line
+ */
+
+ pl = (LPLINEREC)pb->Data;
+ pl->PrevLength = 0;
+ pl->Length = LHD;
+ pl->Status = 0;
+
+ d->NbLines = 1; /* We start with one null line */
+
+ } else {
+
+ /*
+ * Load the file and check if it's a valid one
+ */
+
+ if (!LoadFile(doc)) {
+ return -1;
+ }
+ }
+
+ /*
+ * Initialize current pointers
+ */
+
+ d->CurrentBlock = d->FirstBlock;
+ d->CurrentLine = 0;
+ d->CurrentLineOffset = 0;
+ pl = (LPLINEREC)(d->FirstBlock->Data);
+ ExpandTabs(&pl);
+
+ /*
+ * Undo/redo part
+ */
+
+ d->undo.h = 0;
+ d->redo.h = 0;
+ d->playCount = REC_CANNOTUNDO;
+ if (environParams.undoRedoSize == 0L || type != DOC_WIN) {
+ d->recType = REC_STOPPED;
+ } else {
+ d->recType = REC_UNDO;
+ }
+ CreateRecBuf(doc, REC_UNDO, environParams.undoRedoSize);
+
+ if (mode == MODE_RELOAD) {
+ RefreshWindowsTitle(doc);
+ } else {
+
+ /*
+ * Initialize view part
+ */
+
+ views = &Views[view];
+ views->NextView = -1;
+ views->X = views->Y = 0;
+ views->hwndClient = views->hwndFrame = NULL;
+ views->hScrollBar = environParams.horizScrollBars;
+ views->vScrollBar = environParams.vertScrollBars;
+ views->scrollFactor = 0;
+ views->iYTop = -1;
+
+ /*
+ * Everything is OK, add title in window menu and return the view
+ */
+
+ d->FirstView = view;
+ views->Doc = doc;
+ AddWindowMenuItem(doc, view);
+ }
+
+ /*
+ * Check syntax if C
+ */
+
+ if (d->language == C_LANGUAGE) {
+ d->lineTop = 0;
+ d->lineBottom = d->NbLines;
+ CheckSyntax(doc);
+ }
+
+ return view;
+} /* OpenDocument() */
+
+/*** SaveDocument
+**
+*/
+
+//Save document with (possibly) a new file name
+BOOL FAR PASCAL SaveDocument(int doc, LPSTR FileName)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+ register WORD i;
+ WORD len;
+ HCURSOR hSaveCursor;
+ NPDOCREC d = &Docs[doc];
+
+ //Set the Hour glass cursor
+ hSaveCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ //Create file
+ if ((rd_fh = _lcreat(FileName, 0)) < 0) {
+ ErrorBox(ERR_File_Create, (LPSTR)FileName);
+ goto error0;
+ }
+
+ //Allocate space for Disk Buffer
+
+ if ((rd_buf = DocAlloc(DISK_BLOCK_SIZE)) == NULL) {
+ ErrorBox(SYS_Allocate_Memory);
+ goto error1;
+ }
+
+ rd_offset = 0; y = 0;
+
+ //Get first line
+ if (!FirstLine (doc, &pl, &y, &pb))
+ return FALSE;
+
+ //Save each line of file
+ while (TRUE) {
+
+ //Remove trailing blanks
+ len = (WORD) (pl->Length - LHD);
+#ifdef DBCS
+ {
+ TCHAR *pch1;
+
+ pch1 = pl->Text + (pl->Length - LHD);
+
+ while (pch1 > pl->Text) {
+ pch1 = CharPrev(pl->Text, pch1);
+ if (*pch1 != ' ' && *pch1 != TAB) {
+ break;
+ }
+ len --;
+ }
+ }
+#else // !DBCS
+ while (len && (pl->Text[len - 1] == ' ' || pl->Text[len - 1] == TAB))
+ len --;
+#endif
+
+ //Write line
+ i = 0;
+ while (i < len) {
+
+ PutChar(FileName, pl->Text[i]);
+ i++;
+ }
+
+ if (y >= d->NbLines) {
+ if (rd_offset && !Flush(FileName))
+ goto error2;
+ break;
+ }
+ else {
+ PutChar (FileName, CR);
+ PutChar (FileName, LF);
+ if (!NextLine (doc, &pl, &y, &pb))
+ goto error2;
+ }
+ }
+
+ _lclose (rd_fh);
+
+ //Update internal file date
+ time(&d->time);
+
+ CloseLine(doc, &pl, y, &pb);
+
+ d->ismodified = FALSE;
+ RefreshWindowsTitle(doc);
+
+ SetCursor (hSaveCursor);
+
+ return TRUE;
+
+ error2:
+ CloseLine(doc, &pl, y, &pb);
+ if (!DocFree(rd_buf))
+ InternalErrorBox(SYS_Free_Memory);
+
+ error1:
+ _lclose (rd_fh);
+
+ error0:
+ SetCursor (hSaveCursor);
+ return FALSE;
+} /* SaveDocument() */
diff --git a/private/windbg/windbg/document.c b/private/windbg/windbg/document.c
new file mode 100644
index 000000000..625a67150
--- /dev/null
+++ b/private/windbg/windbg/document.c
@@ -0,0 +1,2319 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ document.c
+
+Abstract:
+
+ This file contains the code which deals with the underlying document
+ file.
+
+Author:
+
+ Jim Schaad (jimsch)
+ Griffith Wm. Kadnier (v-griffk) 1-Nov-1992
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define ROREGION(d,X,Y) ((d)->RORegionSet && ((Y)<(d)->RoY2 || ((Y)==(d)->RoY2 && (X)<(d)->RoX2)))
+
+
+//Prototypes
+
+void NEAR PASCAL ReadOnlyBeep (void);
+LPBLOCKDEF NEAR PASCAL FreeBlock (int doc, LPBLOCKDEF pCurBlock);
+void NEAR PASCAL ModifiedDoc (int doc);
+BOOL NEAR PASCAL FindInsertSpace (int doc, LPBLOCKDEF *pCurBlock, LPLINEREC *pCurLine, LPSTR pBlockEnd, int sizeExpansion);
+BOOL NEAR PASCAL CancelDelete (int doc);
+BOOL NEAR PASCAL PartialLineDelete (int doc, LPBLOCKDEF *pCurBlock, LPLINEREC *pCurLine, int *totalSize, int col1, int col2, BOOL moveToNextLine);
+BOOL NEAR PASCAL FullLineDelete (int doc, LPBLOCKDEF *pCurBlock, LPLINEREC *pCurLine, int *totalSize);
+BOOL NEAR PASCAL JoinLines (int doc, LPBLOCKDEF pCurBlock, LPLINEREC pCurLine, int *totalSize, int lineNb, int col1);
+
+
+/****************************************************************************
+ Document Structure in memory
+ ----------------------------
+ (Use TABULATION = 3 if drawing looks bad)
+- Blocks are allocated using malloc
+
+ Line status (tags,
+ ----------> error, breakpoint, <-
+ | in C comment, ...) |
+ | |
+ | Previous line | ---------> Previous line
+ | --------> length (in previous | | length
+ | | Block for Line 0) | |
+ | | | |
+ | | ------> Line Length | | -------> Line length
+ | | | | | |
+ | | | --> Chars | | | | ----> Chars
+ | | | | | | | | |
+ | | | | v | | | |
+ | | | | | ... | | | |
+ | | | | | |_|_|_|_________| |_|_|...__| |_|_|_|____| <-Unused->| | | |
+ | | | | | Line 0 Block n Line...1 Line m Block n space | | | |
+__| |_|_|_|_________________________...____________________________| |_|_|__
+
+ | | | | Block n ^ |
+ | | | | | |
+ v | | ---> Offset of Last line in block --- v
+ | |
+Block | | Block
+n - 1 | -----> Address of Block n + 1 (0 if last block) n + 1
+ |
+ |
+ -------> Address of Block n - 1 (0 if first block)
+
+****************************************************************************/
+
+static BOOL fReadOnlyErrorStatus = FALSE;
+static BOOL fReadOnlyBeepEnabled = TRUE;
+
+
+void NEAR PASCAL
+ReadOnlyBeep(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Report a readonly error condition; set flag and
+ beep if the beep flag is set.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ none
+
+--*/
+{
+ fReadOnlyErrorStatus = TRUE;
+ if (fReadOnlyBeepEnabled) {
+ MessageBeep(0);
+ }
+}
+
+void FAR PASCAL
+EnableReadOnlyBeep(
+ BOOL f
+ )
+/*++
+
+Routine Description:
+
+ Set or clear the beep flag. Always clears the error status flag.
+
+Arguments:
+
+ f - supplies new flag value
+
+Return Value:
+
+ none
+
+--*/
+{
+ fReadOnlyBeepEnabled = (f != 0);
+ fReadOnlyErrorStatus = FALSE;
+}
+
+BOOL FAR PASCAL
+QueryReadOnlyError(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Examine the read only error status flag. Status flag is cleared
+ after examining the value.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Value of readonly error status - TRUE or FALSE.
+
+--*/
+{
+ BOOL f = fReadOnlyErrorStatus;
+ fReadOnlyErrorStatus = FALSE;
+ return f;
+}
+
+LPSTR FAR PASCAL
+DocAlloc(
+ WORD bytes
+ )
+{
+ LPVOID lpv = malloc(bytes);
+ if (lpv) {
+ ZeroMemory(lpv, bytes);
+ }
+ return lpv;
+}
+
+BOOL FAR PASCAL
+DocFree(
+ LPVOID lpv
+ )
+{
+ free(lpv);
+ return TRUE;
+}
+
+//Allocates and initialize a block, update doc pointers
+BOOL FAR PASCAL
+AllocateBlock(
+ LPBLOCKDEF pPrevBlock,
+ LPBLOCKDEF pNextBlock,
+ LPBLOCKDEF *pNewBlock
+ )
+{
+ //Allocate memory
+ *pNewBlock = (LPBLOCKDEF)DocAlloc(sizeof(BLOCKDEF));
+ if (*pNewBlock == NULL) {
+ return ErrorBox(SYS_Allocate_Memory);
+ }
+
+ //Do initialization work
+ (*pNewBlock)->NextBlock = pNextBlock;
+ (*pNewBlock)->PrevBlock = pPrevBlock;
+ (*pNewBlock)->LastLineOffset = 0;
+
+ return TRUE;
+}
+
+//Free current block, link previous and next blocks, update doc pointers
+LPBLOCKDEF NEAR PASCAL
+FreeBlock(
+ int doc,
+ LPBLOCKDEF pCurBlock
+ )
+{
+ LPBLOCKDEF nextBlock = pCurBlock->NextBlock;
+
+ //Link previous block to next block
+ if (pCurBlock->PrevBlock == NULL) {
+ Docs[doc].FirstBlock = nextBlock;
+ } else {
+ pCurBlock->PrevBlock->NextBlock = nextBlock;
+ }
+ if (nextBlock == NULL) {
+ Docs[doc].LastBlock = pCurBlock->PrevBlock;
+ } else {
+ pCurBlock->NextBlock->PrevBlock = pCurBlock->PrevBlock;
+ }
+
+ //Release memory
+ if (!DocFree((LPSTR)pCurBlock)) {
+ InternalErrorBox(SYS_Free_Memory);
+ }
+
+ return nextBlock;
+}
+
+/*** InitializeDocument
+**
+** Synopsis:
+** void = InitializeDocument(void)
+**
+** Entry:
+** none
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Initialize global variables used by the module
+*/
+
+void
+InitializeDocument(
+ void
+ )
+{
+ register i;
+ for (i = 0; i < MAX_DOCUMENTS; i++) {
+ Docs[i].FirstView = -1;
+ }
+ for (i = 0; i < MAX_VIEWS; i++) {
+ Views[i].Doc = -1;
+ }
+} /* InitializeDocument() */
+
+/*** FirstLine
+**
+** Synopsis:
+** bool = FirstLine(doc, pl, lineNb, pb)
+**
+** Entry:
+** doc - Current document index
+** pl - Place where the line is to be stored
+** lineNb - pointer to line to be searched (incremented after search)
+** pb - pointer to block pointer to be returned
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL
+FirstLine (
+ int doc,
+ LPLINEREC *pl,
+ int *lineNb,
+ LPBLOCKDEF *pb
+ )
+{
+ LPLINEREC stop;
+ int l;
+ NPDOCREC d = &Docs[doc];
+
+ Assert (*lineNb < d->NbLines);
+
+ //Exit if line was the last loaded
+ if (*lineNb == d->CurrentLine) {
+ *pb = d->CurrentBlock;
+ *pl = (LPLINEREC)((LPSTR)(*pb)->Data + d->CurrentLineOffset);
+ (*lineNb)++;
+
+ //Expand line
+ ExpandTabs(pl);
+ pcl = *pl;
+ pcb = *pb;
+
+ return TRUE;
+ }
+
+ //First evaluate from which block do we start
+ if (*lineNb <= (d->CurrentLine >> 1)) {
+
+ //Go up from first line
+ *pb = d->FirstBlock;
+
+ l = *lineNb;
+ *pl = (LPLINEREC)((*pb)->Data);
+ stop = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+
+ while (l--) {
+
+ //Get next line
+ if (*pl < stop) {
+
+ //We are below the last line of the block,
+ // get just the next line
+ (LPSTR)*pl += (*pl)->Length;
+
+ } else {
+
+ //We are at the last line of the block. Load the next block
+ //and initialize line
+ Assert(*pl == stop);
+ Assert((*pb)->NextBlock != NULL);
+ *pb = (*pb)->NextBlock;
+ *pl = (LPLINEREC)((*pb)->Data);
+ stop = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+ }
+ }
+ } else if (*lineNb <= d->CurrentLine) {
+
+ //Go down from current line
+ *pb = d->CurrentBlock;
+
+ l = d->CurrentLine - *lineNb;
+ *pl = (LPLINEREC)((*pb)->Data + d->CurrentLineOffset);
+ stop = (LPLINEREC)((*pb)->Data);
+
+ while (l--) {
+ if (*pl > stop) {
+ (LPSTR)*pl -= (*pl)->PrevLength;
+ } else {
+ Assert(*pl == stop);
+ Assert((*pb)->PrevBlock != NULL);
+ *pb = (*pb)->PrevBlock;
+ *pl = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+ stop = (LPLINEREC)((*pb)->Data);
+ }
+ }
+ } else if (*lineNb <= (d->CurrentLine + (d->NbLines-d->CurrentLine) >> 1)) {
+
+ //Go up from current line
+ *pb = d->CurrentBlock;
+
+ l = *lineNb - d->CurrentLine;
+ *pl = (LPLINEREC)((*pb)->Data + d->CurrentLineOffset);
+ stop = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+
+ while (l--) {
+ if (*pl < stop) {
+ (LPSTR)*pl += (*pl)->Length;
+ } else {
+ Assert(*pl == stop);
+ Assert((*pb)->NextBlock != NULL);
+ *pb = (*pb)->NextBlock;
+ *pl = (LPLINEREC)((*pb)->Data);
+ stop = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+ }
+ }
+ }
+ else {
+
+ // Go down from last line
+ *pb = d->LastBlock;
+ l = d->NbLines - *lineNb -1;
+ *pl = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+ stop = (LPLINEREC)((*pb)->Data);
+
+ while (l--) {
+ if (*pl > stop) {
+ (LPSTR)*pl -= (*pl)->PrevLength;
+ } else {
+ Assert(*pl == stop);
+ Assert((*pb)->PrevBlock != NULL);
+ *pb = (*pb)->PrevBlock;
+ *pl = (LPLINEREC)((*pb)->Data + (*pb)->LastLineOffset);
+ stop = (LPLINEREC)((*pb)->Data);
+ }
+ }
+ }
+
+ //Increment line count
+ (*lineNb)++;
+
+ //Expand line
+ ExpandTabs(pl);
+ pcl = *pl;
+ pcb = *pb;
+
+ return TRUE;
+} /* FirstLine() */
+
+/*** NextLine
+**
+** Synopsis:
+** bool = NextLine(doc, pl, lineno, bl, pb)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL
+NextLine(
+ int doc,
+ LPLINEREC *pl,
+ int *lineNb,
+ LPBLOCKDEF *pb
+ )
+{
+ NPDOCREC d = &Docs[doc];
+
+ if (*lineNb >= d->NbLines) {
+ *lineNb = LAST_LINE;
+ return TRUE;
+ }
+ Assert(*lineNb >= 0);
+ Assert(((LPSTR)*pl - (LPSTR)(*pb)->Data) <= (*pb)->LastLineOffset);
+
+ //Return next line
+ if ((LPSTR)*pl == (LPSTR)((*pb)->Data + (*pb)->LastLineOffset)) {
+
+ //We are at the last line of the block. Load next block
+
+ Assert((*pb)->NextBlock != NULL);
+ *pb = (*pb)->NextBlock;
+
+ //First line of next block
+
+ *pl = (LPLINEREC)((*pb)->Data);
+
+ AssertAligned( *pl );
+ }
+ else {
+ int i;
+
+ //Get pointer to next line
+
+ i = (*pl)->Length;
+#ifdef ALIGN
+ i = (i + 3) & ~3;
+#endif
+
+ *pl = (LPLINEREC)((LPSTR)*pl + i);
+
+ AssertAligned( *pl );
+ }
+
+ (*lineNb)++;
+
+ //Expand line
+ ExpandTabs(pl);
+ pcl = *pl;
+ pcb = *pb;
+
+ return TRUE;
+} /* NextLine() */
+
+/*** PreviousLine
+**
+*/
+
+BOOL FAR PASCAL
+PreviousLine(
+ int doc,
+ LPLINEREC *pl,
+ int lineNb,
+ LPBLOCKDEF *pb
+ )
+{
+ NPDOCREC d = &Docs[doc];
+
+ if (lineNb <= 0) {
+ return TRUE;
+ }
+
+ Assert(lineNb < d->NbLines);
+ Assert(((LPSTR)(*pl)-(LPSTR)(*pb)->Data) <= (*pb)->LastLineOffset);
+
+ //Return previous line
+ if ((LPSTR)(*pl) == (LPSTR)((*pb)->Data)) {
+
+ //We are at the first line of the block. Load previous block
+ Assert((*pb)->PrevBlock != NULL);
+ *pb = (*pb)->PrevBlock;
+
+ //Last line of previous block
+ *pl = (LPLINEREC)((LPSTR)(*pb)->Data + (*pb)->LastLineOffset);
+ } else {
+
+ //Get pointer to previous line
+ *pl = (LPLINEREC)((LPSTR)(*pl) - (*pl)->PrevLength);
+ }
+
+ //Expand line
+ ExpandTabs(pl);
+ pcl = *pl;
+ pcb = *pb;
+
+ return TRUE;
+} /* PreviousLine() */
+
+/*** CloseLine
+**
+** Synopsis:
+** void = CloseLine()
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void FAR PASCAL
+CloseLine (
+ int doc,
+ LPLINEREC *pl,
+ int lineNb,
+ LPBLOCKDEF *pb
+ )
+{
+ NPDOCREC d = &Docs[doc];
+
+ //Save current line infos
+
+ d->CurrentBlock = *pb;
+ d->CurrentLine = lineNb - 1;
+ d->CurrentLineOffset = (LPSTR)(*pl) - (LPSTR)(*pb)->Data;
+
+ return;
+} /* CloseLine() */
+
+/*** FirstNonBlank
+**
+*/
+
+int FAR PASCAL
+FirstNonBlank(
+ int doc,
+ int line
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ register int x;
+
+ if (!FirstLine(doc, &pl, &line, &pb)) {
+ return FALSE;
+ }
+ CloseLine(doc, &pl, line, &pb);
+
+ x = 0;
+ while (x < elLen && el[x] == ' ') {
+ x++;
+ }
+ if (x >= (elLen)) {
+ x = 0;
+ }
+
+ return x;
+} /* FirstNonBlank() */
+
+void FAR PASCAL
+CheckSyntax(
+ int doc
+ )
+{
+ NPDOCREC d = &Docs[doc];
+ LPBLOCKDEF pCurBlock;
+ LPLINEREC pCurLine;
+ char register prevCh;
+ char register ch;
+ int register i;
+ int line = d->lineTop;
+ int savedLineBottom;
+ int curStatus, prevStatus;
+ int curLevel, prevLevel;
+
+ if (d->lineBottom >= d->NbLines) {
+ d->lineBottom--;
+ }
+ Assert(d->lineBottom < d->NbLines);
+ savedLineBottom = d->lineBottom;
+
+ //Load previous line to get previous line status
+
+ if (line > 0) {
+ line--;
+ if (!FirstLine(doc, &pCurLine, &line, &pCurBlock)) {
+ return;
+ }
+
+ //Compute previous line comment level and status
+
+ prevStatus = pCurLine->Status & COMMENT_LINE;
+ if (prevStatus == COMMENT_LINE) {
+ prevLevel = 1;
+ } else {
+
+ for (i = 0, prevCh = ' ', prevLevel = 0;
+ i < pCurLine->Length - LHD; i++) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(pCurLine->Text[i]) && pCurLine->Text[i+1]) {
+ prevCh = ' ';
+ i++;
+ continue;
+ }
+#endif
+ ch = pCurLine->Text[i];
+ if (prevCh == '/' && ch == '*') {
+ prevLevel++;
+ }
+ if (prevCh == '*' && ch == '/') {
+ prevLevel = -1;
+ }
+ prevCh = ch;
+ }
+ }
+ if (!NextLine(doc, &pCurLine, &line, &pCurBlock)) {
+ return;
+ }
+
+ } else {
+ Assert(line == 0);
+ prevStatus = prevLevel = 0;
+ if (!FirstLine(doc, &pCurLine, &line, &pCurBlock)) {
+ return;
+ }
+ }
+
+ //Scan now every line between lineTop and lineBottom and possibly
+ //extend lineBottom if needed
+
+ while (TRUE) {
+
+ //Compute current line comment level and status
+
+ curStatus = pCurLine->Status & COMMENT_LINE;
+ for (i = 0, prevCh = ' ', curLevel = 0; i < pCurLine->Length - LHD;
+ i++) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(pCurLine->Text[i]) && pCurLine->Text[i+1]) {
+ prevCh = ' ';
+ i++;
+ continue;
+ }
+#endif
+ ch = pCurLine->Text[i];
+
+ if (prevCh == '/' && ch == '*') {
+ if (i <= 1 || pCurLine->Text[i-2] != '/') {
+ curLevel++;
+ }
+ }
+
+ if (prevCh == '*' && ch == '/') {
+ curLevel = -1;
+ }
+ prevCh = ch;
+ }
+
+ //Impossible combination
+
+ Assert(prevStatus == 0 || prevLevel >= 0);
+
+ //Set or reset multiline status
+
+ if (prevStatus == 0 && prevLevel <= 0) {
+ if (curLevel > 0) {
+ SET(pCurLine->Status, COMMENT_LINE);
+ } else {
+ RESET(pCurLine->Status, COMMENT_LINE);
+ }
+
+ } else if (curLevel >= 0) {
+
+ SET(pCurLine->Status, COMMENT_LINE);
+
+ } else {
+
+ RESET(pCurLine->Status, COMMENT_LINE);
+
+ }
+
+ //Current line info is now previous
+
+ prevStatus = pCurLine->Status & COMMENT_LINE;
+
+ //Check stop conditions
+
+ if (line > d->lineBottom) {
+ if (curStatus == prevStatus) {
+ break;
+ } else {
+ d->lineBottom++;
+ }
+ }
+
+ //Current level is previous one
+
+ prevLevel = curLevel;
+
+ //Stop if at end of doc
+
+ if (line >= d->NbLines) {
+ break;
+ }
+
+ //Return next line
+
+ if ((LPSTR)pCurLine ==
+ (LPSTR)(pCurBlock->Data + pCurBlock->LastLineOffset)) {
+ pCurBlock = pCurBlock->NextBlock;
+ pCurLine = (LPLINEREC)(pCurBlock->Data);
+ }
+ else {
+ pCurLine = (LPLINEREC)((LPSTR)pCurLine + pCurLine->Length);
+ }
+ line++;
+
+ }
+
+ if (!syntaxColors) {
+ d->lineBottom = savedLineBottom;
+ }
+
+ CloseLine(doc, &pCurLine, line, &pCurBlock);
+
+ return;
+} /* CheckSyntax() */
+
+/*** ModifiedDoc
+**
+** Synopsis:
+** void = ModifiedDoc(doc)
+**
+** Entry:
+** doc - index of document which has been modified
+**
+** Returns:
+** Nothing:
+**
+** Description:
+** Marks the document as having been modified and updates the
+** title if it has not previously been modified
+**
+*/
+
+void NEAR PASCAL
+ModifiedDoc(
+ int doc
+ )
+{
+
+ //Document is modified
+ if (!Docs[doc].ismodified) {
+ Docs[doc].ismodified = TRUE;
+ RefreshWindowsTitle(doc);
+ }
+ return;
+} /* ModifiedDoc() */
+
+void FAR PASCAL
+ExpandTabs(
+ LPLINEREC *pl
+ )
+{
+ register int i = 0;
+ register int j = 0;
+ int len = (*pl)->Length - LHD;
+ LPSTR pc = (*pl)->Text;
+
+ memset(el, ' ', MAX_USER_LINE * 2);
+ while (i < len) {
+#ifdef DBCS
+ if (IsDBCSLeadByte((BYTE)pc[i])) {
+ el[j++] = pc[i++];
+ el[j++] = pc[i++];
+ } else
+#endif
+ if (pc[i] == TAB) {
+ j += tabSize - (j % tabSize);
+ i++;
+ }
+ else {
+ el[j++] = pc[i++];
+ }
+ }
+
+ Assert(j <= MAX_USER_LINE);
+ elLen = j;
+}
+
+int FAR PASCAL
+AlignToTabs(
+ int editCol,
+ int len,
+ LPSTR pc
+ )
+{
+ register int col, realCol;
+
+ col = realCol = 0;
+ while (realCol < editCol) {
+
+ if (col >= len) {
+ col += (editCol - realCol);
+ break;
+ }
+#ifdef DBCS
+ if (IsDBCSLeadByte(pc[col]))
+ realCol += 2;
+ else
+#endif
+ if (pc[col] == TAB) {
+ realCol += tabSize - (realCol % tabSize);
+ } else {
+ realCol++;
+ }
+
+ if (realCol <= editCol) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(pc[col]))
+ col += 2;
+ else
+#endif
+ col++;
+ }
+ }
+
+ return col;
+} /* AlignToTabs() */
+
+BOOL NEAR PASCAL
+FindInsertSpace(
+ int doc,
+ LPBLOCKDEF *pCurBlock,
+ LPLINEREC *pCurLine,
+ LPSTR pBlockEnd,
+ int sizeExpansion
+ )
+{
+ LPBLOCKDEF pNextBlock;
+ LPLINEREC pNextLineEnd, pTmpLine = *pCurLine;
+ int moveSize;
+ BOOL newBlockCreated = FALSE;
+ int curLineOffset;
+
+ //Check not to move first line of current block in next block
+
+ if ((LPSTR)*pCurLine - (LPSTR)(*pCurBlock)->Data == 0) {
+ (LPSTR)pTmpLine += pTmpLine->Length;
+ }
+
+ moveSize = pBlockEnd - (LPSTR)pTmpLine;
+
+ if ((*pCurBlock)->NextBlock == NULL) {
+
+ //Create a new block
+
+ if (!AllocateBlock(*pCurBlock, NULL, &pNextBlock)) {
+ return FALSE;
+ }
+ newBlockCreated = TRUE;
+ Docs[doc].LastBlock = pNextBlock;
+
+ pNextLineEnd = (LPLINEREC)pNextBlock->Data;
+ }
+ else {
+
+ //Before allocating a new block, look into next block
+ //to see if we have space to insert chars and to move in
+ //current line and lines after
+
+ pNextBlock = (*pCurBlock)->NextBlock;
+
+ pNextLineEnd = (LPLINEREC)(pNextBlock->Data
+ + pNextBlock->LastLineOffset);
+ pNextLineEnd = (LPLINEREC)((LPSTR)pNextLineEnd
+ + pNextLineEnd->Length);
+
+ if (moveSize + sizeExpansion > (int)(BLOCK_SIZE
+ - ((LPSTR)pNextLineEnd - (LPSTR)pNextBlock->Data))) {
+
+ LPBLOCKDEF pNewBlock;
+
+ //We have not enough space in next block, so insert
+ //a new created block
+
+ if (!AllocateBlock(*pCurBlock, pNextBlock, &pNewBlock)) {
+ return FALSE;
+ }
+
+ newBlockCreated = TRUE;
+ pNextBlock->PrevBlock = pNewBlock;
+
+ //Next block is new block
+
+ pNextBlock = pNewBlock;
+ pNextLineEnd = (LPLINEREC)pNextBlock->Data;
+ }
+ }
+
+ curLineOffset = (LPSTR)pTmpLine - (LPSTR)(*pCurBlock)->Data;
+
+ //Link current block to next
+ (*pCurBlock)->NextBlock = pNextBlock;
+
+ //Shift right next blocks chars
+
+ _fmemmove(pNextBlock->Data + moveSize,
+ pNextBlock->Data,
+ (LPSTR)pNextLineEnd - (LPSTR)pNextBlock->Data);
+
+ //And copy chars from current block to next block
+
+ _fmemmove(pNextBlock->Data, (LPSTR)pTmpLine, moveSize);
+
+ Assert(moveSize >= LHD);
+
+ //Rework pointers
+
+ if (newBlockCreated) {
+ pNextBlock->LastLineOffset = (*pCurBlock)->LastLineOffset -
+ curLineOffset;
+ } else {
+ pNextBlock->LastLineOffset += moveSize;
+ }
+
+
+ (*pCurBlock)->LastLineOffset = curLineOffset - pTmpLine->PrevLength;
+
+ //Current block is next block if current line is not block first line
+
+ if ((LPSTR)*pCurLine != (LPSTR)(*pCurBlock)->Data) {
+
+ //Cur line is now next block first line
+
+ *pCurLine = (LPLINEREC)pNextBlock->Data;
+
+ //Next block becomes current block
+
+ *pCurBlock = pNextBlock;
+
+ }
+
+ return TRUE;
+} /* FindInsertSpace() */
+
+//When your file has an Undo buffer, be sure to set the undo/redo
+//engine to UNDO before inserting chars, otherwise they will be stored
+//in the REDO buffer
+
+BOOL FAR PASCAL
+InsertBlock(
+ int doc,
+ int col,
+ int line,
+ int size,
+ LPSTR buf
+ )
+{
+ LPLINEREC pCurLine, pLastLine, pNextLine;
+ LPBLOCKDEF pCurBlock, pNextBlock;
+ LPSTR charsBegin;
+ LPSTR charsEnd;
+ LPSTR start, pBlockEnd;
+ int sizeExpansion, newLineLen, charsSize;
+ int extraBlanks, lineLen;
+ int nextLineLength;
+ int freeBlockSize;
+ BOOL addOneLine;
+ NPDOCREC d = &Docs[doc];
+ UNDOREDOREC pUndoRedo;
+ int startLine = line;
+ BOOL firstLine = TRUE;
+ int nbLines = d->NbLines;
+ char lineBuf[MAX_LINE_SIZE];
+ int expandedLen;
+
+ //Beep and exit if file is ReadOnly
+
+ if (d->readOnly || ROREGION(d,col,line)) {
+ ReadOnlyBeep();
+ return FALSE;
+ } else {
+ // Clear error status
+ QueryReadOnlyError();
+ }
+
+ if (size == 0) {
+ return TRUE;
+ }
+
+ editorIsCritical = TRUE;
+ Assert(line < d->NbLines);
+ col = min(col, MAX_USER_LINE);
+
+ d->lineTop = d->lineBottom = line;
+
+ //Get information from line where we insert
+
+ if (!FirstLine(doc, &pCurLine, &line, &pCurBlock)) {
+ goto errRet;
+ }
+
+ //Align column respecting tabs
+
+ if (playingRecords) {
+ expandedLen = ConvertPosX(col);
+ } else {
+ expandedLen = col;
+ col = AlignToTabs(expandedLen, pCurLine->Length - LHD,
+ (LPSTR)pCurLine->Text);
+ }
+ Assert(col >= 0);
+
+ //Open an edit record
+
+ if (!OpenRec(doc, DELETESTREAM, col, line - 1)) {
+ goto errRet;
+ }
+
+ //Initialize rec buffer ptr if we will read chars from undo/redo record
+
+ if (buf) {
+ charsBegin = charsEnd = buf;
+ } else if (d->recType == REC_UNDO) {
+ pUndoRedo = d->redo;
+ } else if (d->recType == REC_REDO) {
+ pUndoRedo = d->undo;
+ } else {
+ Assert(FALSE);
+ return FALSE;
+ }
+
+ //Insert until buffer empty
+
+ while (size) {
+
+ if (buf != NULL) {
+
+ //Extract chars from supplied buf until EOF, EOL or end of buffer
+
+ while (size && *charsEnd != CR) {
+ if (*charsEnd == TAB) {
+ expandedLen += tabSize - (expandedLen % tabSize);
+ } else {
+ expandedLen++;
+ }
+ charsEnd++;
+ size--;
+ }
+ } else {
+
+ //Extract from undo/redo records buffer a line, or the text if
+ //no CR+LF found (no overflow protection needed, by definition
+ //lines in undo/redo buf are never beyond maximum)
+
+ charsBegin = (LPSTR)lineBuf;
+ ReadLineFromBuf(&pUndoRedo, lineBuf, &size, &expandedLen,&charsEnd);
+ }
+
+ if (size == 0) {
+ addOneLine = FALSE;
+ } else if ( (addOneLine = (*charsEnd == CR)) &&
+ d->NbLines >= MAX_LINE_NUMBER) {
+ ErrorBox(ERR_Too_Many_Lines);
+ goto errRet;
+ }
+
+ lineLen = pCurLine->Length - LHD;
+
+ //We are in a line, check if we are after last char
+
+ extraBlanks = max (col - lineLen, 0);
+
+ //Compute new line len whether chars end with a CR or not
+
+ newLineLen = sizeExpansion = charsSize = charsEnd - charsBegin;
+ if (addOneLine) {
+ newLineLen += col + LHD;
+ sizeExpansion += LHD;
+
+ //Adjust startline for breakpoints and error handling
+
+ if (firstLine && col > 0) {
+ startLine++;
+ }
+ } else {
+
+ int newCol = col;
+
+ newLineLen += (pCurLine->Length + extraBlanks);
+
+ //Now see if what we insert in current line will not expand
+ //line len beyond maximum
+
+ if (extraBlanks == 0) {
+
+ while (newCol < lineLen) {
+ if (pCurLine->Text[newCol] == TAB) {
+ expandedLen += tabSize - (expandedLen % tabSize);
+ } else {
+ expandedLen++;
+ }
+ newCol++;
+ }
+
+ }
+ }
+
+ //Check new line length
+
+ if (expandedLen > MAX_USER_LINE) {
+ ErrorBox(ERR_Line_Too_Long);
+ goto errRet;
+ }
+
+ firstLine = FALSE;
+
+ //Possibly add extraBlanks to buffer size expansion
+
+ sizeExpansion += extraBlanks;
+
+ //Sorry but recursivity eats stack
+
+ reDoIt:
+
+ //Keep a pointer on last line of block
+
+ pLastLine = (LPLINEREC)((LPSTR)pCurBlock->Data +
+ pCurBlock->LastLineOffset);
+
+ //Check block size
+
+ freeBlockSize = BLOCK_SIZE - pCurBlock->LastLineOffset -
+ pLastLine->Length;
+
+ //Compute very end of block
+
+ pBlockEnd = (LPSTR)pLastLine + pLastLine->Length;
+ Assert(pBlockEnd <= (LPSTR)(pCurBlock)->Data + BLOCK_SIZE);
+
+ //Do we have room in current block
+
+ if (freeBlockSize >= sizeExpansion) {
+
+ //We have space to insert chars in current block
+
+ //If we add a line, first update next line length
+
+ if (addOneLine) {
+ nextLineLength = pCurLine->Length - (BYTE)newLineLen
+ + (BYTE)sizeExpansion;
+ pNextLine = (LPLINEREC)((LPSTR)pCurLine + pCurLine->Length);
+
+ //Write future line length in next line prev length field,
+ //if line is the last of block, load next block
+
+ if (((LPSTR)pNextLine - (LPSTR)pCurBlock->Data)
+ <= pCurBlock->LastLineOffset) {
+ pNextLine->PrevLength = (BYTE)nextLineLength;
+ } else {
+
+ //Write header only if there is a line after
+
+ pNextBlock = pCurBlock->NextBlock;
+ if (pNextBlock != NULL) {
+
+ //Set next line pointer in first line of Next Block
+
+ pNextLine = (LPLINEREC)pNextBlock->Data;
+ pNextLine->PrevLength = (BYTE)nextLineLength;
+ }
+ }
+ }
+
+ //Compute the position where to insert
+
+ start = (LPSTR)(pCurLine) + min(col + LHD, (int)pCurLine->Length);
+
+ //Shift right part
+
+ _fmemmove(start + sizeExpansion, start, pBlockEnd - start);
+
+ //First insert the extraBlanks if any
+
+ _fmemset(start, ' ', extraBlanks);
+ start += extraBlanks;
+
+ //Then insert chars
+
+ _fmemmove(start, charsBegin, charsSize);
+
+ //Possibly adjust block last Line Offset
+ // - We inserted before last line, propagate line extension
+ // - We inserted at last line, propagate line extension
+ // only if a new line is inserted
+
+ if (pCurLine < pLastLine) {
+ pCurBlock->LastLineOffset +=sizeExpansion;
+ } else if (pCurLine = pLastLine) {
+ if (addOneLine) {
+ pCurBlock->LastLineOffset +=newLineLen;
+ }
+ } else {
+ Assert(FALSE);
+ return FALSE;
+ }
+
+ pNextLine = (LPLINEREC)((LPSTR)pCurLine + newLineLen);
+ Assert((LPSTR)pNextLine - (LPSTR)pCurBlock->Data <= BLOCK_SIZE);
+
+ //Write next line header, in block or in next block
+
+ if (((LPSTR)pCurLine - (LPSTR)pCurBlock->Data)
+ == pCurBlock->LastLineOffset) {
+
+ //Write header only if there is a line after
+
+ pNextBlock = pCurBlock->NextBlock;
+ if (pNextBlock != NULL) {
+
+ //Set next line pointer to first line of Next Block
+
+ pNextLine = (LPLINEREC)pNextBlock->Data;
+ pNextLine->PrevLength = (BYTE)newLineLen;
+
+ }
+
+ } else
+
+ //Not at last line of block, Set next line previous line
+
+ pNextLine->PrevLength = (BYTE)newLineLen;
+
+ //If we insert a new line : Change next line length and
+ //set current line status to 0 if it's a brand new line
+
+ if (addOneLine) {
+ pNextLine->Length = (BYTE)nextLineLength;
+ if (col == 0) {
+
+ //Propagate status to next line
+
+ pNextLine->Status = pCurLine->Status;
+ pCurLine->Status = 0;
+ } else {
+
+ //Set next line status to 0
+
+ AssertAligned(pNextLine);
+ pNextLine->Status = 0;
+ }
+ }
+
+ //Set cur line length
+
+ pCurLine->Length = (BYTE)newLineLen;
+
+ } else {
+
+ if (!FindInsertSpace(doc, &pCurBlock, &pCurLine, pBlockEnd,
+ sizeExpansion)) {
+ goto errRet;
+ }
+
+ //Insert chars in next block
+
+ goto reDoIt;
+
+ }
+
+ if (addOneLine) {
+ charsEnd += 2;
+ size -=2;
+ d->lineBottom++;
+ d->NbLines++;
+ expandedLen = 0;
+ }
+
+ charsBegin = charsEnd;
+ col = 0;
+ if (size || addOneLine) {
+ pCurLine = pNextLine;
+ }
+
+ }
+
+ //Close undo/redo record
+
+ CloseRec(doc, max(0, (int)((start - (LPSTR)pCurLine->Text) + charsSize)),
+ d->lineBottom, TRUE);
+
+ //Inform breakpoints and errors handlers of what we did in the text
+ //(only if it's a real insertion)
+
+ if (d->recType != REC_STOPPED && d->NbLines > nbLines) {
+ AdjustDebugLines(doc, startLine, d->NbLines - nbLines, TRUE);
+ }
+
+ CloseLine(doc, &pCurLine, d->lineBottom + 1, &pCurBlock);
+
+ //Document is modified
+
+ ModifiedDoc(doc);
+
+ //If there was nothing to record, tells the system that now we have
+ //something in buffer
+
+ if (d->playCount == REC_CANNOTUNDO) {
+ d->playCount = 0;
+ }
+
+ if (d->language != NO_LANGUAGE) {
+ CheckSyntax(doc);
+ }
+
+ editorIsCritical = FALSE;
+
+ return TRUE;
+
+ errRet: {
+
+ //Cancel recording
+
+ CloseRec(doc, 0, 0, FALSE);
+
+ //Try to resynchronize system on first line of document
+
+ pCurLine = (LPLINEREC)d->FirstBlock->Data;
+ CloseLine(doc, &pCurLine, 1, &d->FirstBlock);
+
+ editorIsCritical = FALSE;
+ return FALSE;
+ }
+
+} /* InsertBlock() */
+
+BOOL NEAR PASCAL
+CancelDelete(
+ int doc
+ )
+{
+
+ if (QuestionBox(ERR_UndoRedoBufferTooSmall, MB_YESNO) == IDYES) {
+
+ //Cancel this record and stop recording for this action
+ CloseRec(doc, 0, 0, FALSE);
+ Docs[doc].recType = REC_HADOVERFLOW;
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+//Delete characters on a single line, pointers are unaffected
+BOOL NEAR PASCAL
+PartialLineDelete(
+ int doc,
+ LPBLOCKDEF *pCurBlock,
+ LPLINEREC *pCurLine,
+ int * totalSize,
+ int col1,
+ int col2,
+ BOOL moveToNextLine
+ )
+{
+ int moveSize;
+ LPLINEREC pNextLine, pLastLine;
+ LPBLOCKDEF pNextBlock = *pCurBlock;
+
+ //Adjust col1 and col2 inside the line
+ col1 = min(col1, (*pCurLine)->Length - LHD);
+ col2 = min(col2, (*pCurLine)->Length - LHD);
+ moveSize = col2 - col1;
+
+ //Send deleted chars to record buffer and roll back
+ //if buffer full
+ if (!AppendToRec(doc, (*pCurLine)->Text + col1, moveSize, FALSE, totalSize))
+ if (CancelDelete(doc))
+ return FALSE;
+
+ pLastLine = (LPLINEREC)((*pCurBlock)->Data + (*pCurBlock)->LastLineOffset);
+
+ //Move chars
+ if (moveSize > 0) {
+ _fmemmove((LPSTR)(*pCurLine)->Text + col1,
+ (LPSTR)(*pCurLine)->Text + col2,
+ (LPSTR)pLastLine + pLastLine->Length
+ - ((LPSTR)(*pCurLine)->Text + col2));
+ }
+
+ //Update current line length
+ (*pCurLine)->Length -= (BYTE) moveSize;
+
+ //Update last line offset and next line previous length (in current
+ //or in next block)
+ if ((*pCurLine) == pLastLine) {
+
+ //Next line is in next block
+ pNextBlock = (*pCurBlock)->NextBlock;
+ if (pNextBlock != NULL) {
+
+ //Set next line pointer to first line of Next Block and
+ //update previous length
+ pNextLine = (LPLINEREC)pNextBlock->Data;
+ pNextLine->PrevLength -= (BYTE) moveSize;
+
+ }
+
+ }
+ else {
+
+ (*pCurBlock)->LastLineOffset -= moveSize;
+ pNextLine = (LPLINEREC)((LPSTR)*pCurLine + (*pCurLine)->Length);
+ pNextLine->PrevLength -= (BYTE) moveSize;
+ }
+
+ if (moveToNextLine) {
+ *pCurLine = pNextLine;
+ *pCurBlock = pNextBlock;
+ }
+
+ return TRUE;
+
+}
+
+//Deletes the pCurLine in the pCurBlock and adjust them to the
+//next line, if the line was the last line of the block, the block
+//is deleted
+BOOL NEAR PASCAL
+FullLineDelete(
+ int doc,
+ LPBLOCKDEF *pCurBlock,
+ LPLINEREC *pCurLine,
+ int *totalSize
+ )
+{
+ LPLINEREC pLastLine;
+ BYTE prevLineLen = (*pCurLine)->PrevLength;
+
+ //First send deleted chars to record buffer
+ if (!AppendToRec(doc, (*pCurLine)->Text, (*pCurLine)->Length - LHD, TRUE,
+ totalSize)) {
+ if (CancelDelete(doc)) {
+ return FALSE;
+ }
+ }
+
+ //Compute lastLine and nextLine in block
+ pLastLine = (LPLINEREC)((*pCurBlock)->Data + (*pCurBlock)->LastLineOffset);
+ if (*pCurLine == pLastLine) {
+
+ //If line is also the first line of block, delete the block
+ if (*pCurLine == (LPLINEREC)(*pCurBlock)->Data) {
+
+ Assert((*pCurBlock)->LastLineOffset == 0);
+
+ //Document may be empty, reinitialize first block
+ if ((*pCurBlock)->PrevBlock == NULL &&
+ (*pCurBlock)->NextBlock == NULL) {
+ (*pCurLine)->Length = LHD;
+ (*pCurLine)->Status = 0;
+ (*pCurBlock)->LastLineOffset = 0;
+ Docs[doc].NbLines = 1;
+ Assert((*pCurLine)->PrevLength == 0);
+ Assert(Docs[doc].FirstBlock == *pCurBlock);
+ Assert(Docs[doc].LastBlock == *pCurBlock);
+ return TRUE;
+ } else {
+
+ //Delete block, and set current block to next block
+ *pCurBlock = FreeBlock(doc, *pCurBlock);
+ }
+
+ } else {
+
+ //Adjust the current block last offset
+ (*pCurBlock)->LastLineOffset -= prevLineLen;
+ Assert((*pCurBlock)->LastLineOffset >= 0);
+
+ //Set curBlock to next block
+ *pCurBlock = (*pCurBlock)->NextBlock;
+
+ }
+
+ //Set next line to first line of block
+ if (*pCurBlock != NULL) {
+ *pCurLine = (LPLINEREC)(*pCurBlock)->Data;
+ }
+
+ } else {
+
+ LPLINEREC pNextLine = (LPLINEREC)((LPSTR)*pCurLine +
+ (*pCurLine)->Length);
+
+ //Adjust block last offset
+ (*pCurBlock)->LastLineOffset -= (*pCurLine)->Length;
+ Assert((*pCurBlock)->LastLineOffset >= 0);
+
+ //Now shift left rest of block chars
+ _fmemmove(*pCurLine,
+ (LPSTR)pNextLine,
+ (LPSTR)pLastLine + pLastLine->Length - (LPSTR)pNextLine);
+ }
+
+ //If next line exist, change it's header, otherwise resynchronise
+ if (*pCurBlock != NULL) {
+ (*pCurLine)->PrevLength = prevLineLen;
+ } else {
+ *pCurBlock = Docs[doc].LastBlock;
+ *pCurLine = (LPLINEREC)((*pCurBlock)->Data +
+ (*pCurBlock)->LastLineOffset);
+ }
+
+ Docs[doc].NbLines--;
+
+ return TRUE;
+}
+
+//Join the current line to the preceding, pad blanks if necessary
+BOOL NEAR PASCAL
+JoinLines(
+ int doc,
+ LPBLOCKDEF pCurBlock,
+ LPLINEREC pCurLine,
+ int *totalSize,
+ int lineNb,
+ int col1
+ )
+{
+ NPDOCREC d = &Docs[doc];
+ WORD undoRedoState = d->recType;
+ int limit;
+ LPLINEREC pPrevLine;
+ char tmpLine[MAX_USER_LINE + 2]; //2 = Possible CR+LF
+ WORD status;
+ BOOL language = d->language;
+
+ //First compose the resulting new line
+ if (pCurLine == (LPLINEREC)pCurBlock->Data) {
+ pCurBlock = pCurBlock->PrevBlock;
+ Assert(pCurBlock != NULL);
+ pPrevLine = (LPLINEREC)((LPSTR)pCurBlock->Data +
+ pCurBlock->LastLineOffset);
+ } else {
+ pPrevLine = (LPLINEREC)((LPSTR)pCurLine - pCurLine->PrevLength);
+ }
+
+ //Save portion of first line and save status (unless all first line
+ //is deleted)
+ if (col1 >0) {
+ status = pPrevLine->Status;
+ } else {
+ status = 0;
+ }
+
+ limit = min(col1, pPrevLine->Length - LHD);
+ _fmemmove((LPSTR)tmpLine, (LPSTR)pPrevLine->Text, limit);
+
+ //We may have now to pad line with blanks
+ for(; limit < MAX_USER_LINE && limit < col1; limit++) {
+ tmpLine[limit] = ' ';
+ }
+
+ //Append now current line
+ if (limit + pCurLine->Length - LHD <= MAX_USER_LINE) {
+ _fmemmove((LPSTR)tmpLine + limit, (LPSTR)pCurLine->Text,
+ pCurLine->Length - LHD);
+ limit += pCurLine->Length - LHD;
+ }
+ else {
+ ErrorBox(ERR_Line_Too_Long);
+ return FALSE;
+ }
+
+ //Check line overflow
+ if (limit >= MAX_USER_LINE) {
+ ErrorBox(ERR_Line_Too_Long);
+ return FALSE;
+ }
+
+ //Append a CR+LF
+ memmove(tmpLine + limit, CrLf, 2);
+ limit += 2;
+
+ //Insert the new one
+ CloseLine(doc, &pPrevLine, lineNb--, &pCurBlock);
+
+ //Stop Recording
+ d->recType = REC_STOPPED;
+
+ d->language = NO_LANGUAGE; //To avoid syntax check
+ if (!InsertBlock(doc, 0, lineNb++, limit, (LPSTR)tmpLine)) {
+ return FALSE;
+ }
+ d->language = (WORD) language;
+
+ //Resynchronize to next line
+ pCurBlock = d->CurrentBlock;
+ pCurLine = (LPLINEREC)((LPSTR)pCurBlock->Data + d->CurrentLineOffset);
+ pCurLine->Status = 0;
+
+ //Write saved status in previous line (the one just inserted)
+ if (pCurLine == (LPLINEREC)pCurBlock->Data) {
+
+ LPBLOCKDEF pPrevBlock = pCurBlock->PrevBlock;
+ if (pPrevBlock != NULL) {
+ ((LPLINEREC)((LPSTR)pPrevBlock->Data + pPrevBlock->LastLineOffset)) ->Status = status;
+ }
+ } else {
+ ((LPLINEREC)((LPSTR)pCurLine - pCurLine->PrevLength))->Status = status;
+ }
+
+ //Delete now the 2 lines
+ if (!FullLineDelete(doc, &pCurBlock, &pCurLine, totalSize)) {
+ return FALSE;
+ }
+ if (!FullLineDelete(doc, &pCurBlock, &pCurLine, totalSize)) {
+ return FALSE;
+ }
+ d->recType = undoRedoState;
+ CloseLine(doc, &pCurLine, min(d->NbLines, lineNb + 1), &pCurBlock);
+
+ return TRUE;
+}
+
+
+//When your file has an Undo buffer, be sure to set the undo/redo
+//engine to UNDO before deleting chars, otherwise they will be stored
+//in the REDO buffer
+BOOL FAR PASCAL
+DeleteBlock(
+ int doc,
+ int col1,
+ int line1,
+ int col2,
+ int line2
+ )
+{
+ LPLINEREC pCurLine;
+ LPBLOCKDEF pCurBlock;
+ int curLine = line1, startLine = line1;
+ int editCol1, editCol2;
+ NPDOCREC d = &Docs[doc];
+ int totalSize = 0;
+ WORD undoRedoState;
+ int totalNbLines = d->NbLines;
+
+ //Beep and exit if file is ReadOnly
+ if (d->readOnly || ROREGION(d,col1,line1)) {
+ ReadOnlyBeep();
+ return FALSE;
+ } else {
+ // Clear error status
+ QueryReadOnlyError();
+ }
+
+ //Verifications and adjustements
+ Assert(line1 < totalNbLines);
+ Assert(line2 <= totalNbLines);
+ Assert(line2 >= line1);
+ editCol1 = min(col1, MAX_USER_LINE);
+ editCol2 = min(col2, MAX_USER_LINE + 1);
+ d->lineTop = d->lineBottom = line1;
+
+ editorIsCritical = TRUE;
+
+ //Get information about line we start delete
+ if (!FirstLine (doc, &pCurLine, &line1, &pCurBlock)) {
+ //Try to resynchronize system on first line of document
+ pCurLine = (LPLINEREC)(d->FirstBlock->Data);
+ CloseLine(doc, &pCurLine, 1, &d->FirstBlock);
+ ClearSelection(curView);
+ editorIsCritical = FALSE;
+ return FALSE;
+ }
+ line1--;
+
+ //Remember record action
+ undoRedoState = d->recType;
+
+ //Align column respecting tabs
+ if (playingRecords) {
+ col1 = editCol1;
+ } else {
+ col1 = AlignToTabs(editCol1, pCurLine->Length - LHD, (LPSTR)pCurLine->Text);
+ }
+
+ //Open an edit record, if buffer full, ask the user for action
+ if (!OpenRec(doc, INSERTSTREAM, col1, curLine)) {
+ if (CancelDelete(doc)) {
+ goto rollBack;
+ }
+ }
+
+ //Full line(s) delete
+ if (col1 == 0 && col2 == 0) {
+
+ for (curLine = line1; curLine < line2; curLine++) {
+ if (!FullLineDelete(doc, &pCurBlock, &pCurLine, &totalSize)) {
+ goto rollBack;
+ }
+ }
+ CloseLine(doc, &pCurLine, line1+1, &pCurBlock);
+
+ } else if (line1 == line2) {
+
+ if (playingRecords) {
+ col2 = editCol2;
+ } else {
+ col2 = AlignToTabs(editCol2, pCurLine->Length - LHD, (LPSTR)pCurLine->Text);
+ }
+
+ //The 2 columns could be in the same tab
+ if (col1 == col2) {
+ col2++;
+ }
+
+ if (!PartialLineDelete(doc, &pCurBlock, &pCurLine, &totalSize, col1, col2, FALSE)) {
+ goto rollBack;
+ }
+ CloseLine(doc, &pCurLine, line1+1, &pCurBlock);
+
+ } else {
+
+ //Tricky case, deletion spreads over several lines
+ Assert(curLine < line2);
+
+ //Delete the right part of first line
+ if (!PartialLineDelete(doc,
+ &pCurBlock,
+ &pCurLine,
+ &totalSize,
+ col1,
+ pCurLine->Length - LHD,
+ TRUE)) {
+ goto rollBack;
+ }
+
+ //Insert a fake CrLf in Undo buffer,
+ if (!AppendToRec(doc, (LPSTR)NULL, 0, TRUE, &totalSize)) {
+ if (CancelDelete(doc)) {
+ goto rollBack;
+ }
+ }
+
+ //Delete lines in between
+ for (curLine = line1+1; curLine < line2; curLine++) {
+ if (!FullLineDelete(doc, &pCurBlock, &pCurLine, &totalSize)) {
+ goto rollBack;
+ }
+ }
+
+ if (playingRecords) {
+ col2 = editCol2;
+ } else {
+ col2 = AlignToTabs(editCol2, pCurLine->Length - LHD, (LPSTR)pCurLine->Text);
+ }
+
+ //Delete the left part of last line
+ if (!PartialLineDelete(doc,
+ &pCurBlock,
+ &pCurLine,
+ &totalSize,
+ 0,
+ col2,
+ FALSE)) {
+ goto rollBack;
+ }
+
+ //Rebuild resulting line
+ if (!JoinLines(doc, pCurBlock, pCurLine, &totalSize, line1+1, col1)) {
+ goto rollBack;
+ }
+
+ //Inform breakpoints and errors handler
+ if (col1 > 0) {
+ startLine++;
+ }
+ }
+
+ //Document is modified
+ ModifiedDoc(doc);
+
+ //Inform breakpoints handler of what we did in the text
+ if (d->NbLines < totalNbLines) {
+ AdjustDebugLines(doc, startLine, totalNbLines - d->NbLines, FALSE);
+ }
+
+ //If the recording was canceled, this close will do nothing
+ CloseRec(doc, 0, 0, TRUE);
+
+ //If there was nothing to record, tells the system that now we have
+ //something in buffer, if we had an overflow, restart Undo/Redo
+ if (d->recType != REC_HADOVERFLOW) {
+ d->recType = undoRedoState;
+ } else {
+ d->playCount = REC_CANNOTUNDO;
+ }
+
+ if (d->language != NO_LANGUAGE) {
+ CheckSyntax(doc);
+ }
+
+ editorIsCritical = FALSE;
+ return TRUE;
+
+
+ //Record buffer full
+ rollBack: {
+
+ CloseRec(doc, 0, 0, TRUE);
+
+ //Document is modified
+ ModifiedDoc(doc);
+
+ //Try to resynchronize system on first line of document
+ pCurBlock = d->FirstBlock;
+ pCurLine = (LPLINEREC)pCurBlock->Data;
+
+ CloseLine(doc, &pCurLine, 1, &pCurBlock);
+ ClearSelection(curView);
+ editorIsCritical = FALSE;
+
+ //Play the recorded information
+ PlayRec(doc, d->recType, FALSE, FALSE);
+ return FALSE;
+ }
+}
+
+BOOL FAR PASCAL
+DeleteAll(
+ int doc
+ )
+{
+ return DeleteBlock(doc, 0, 0, MAX_USER_LINE + 1, Docs[doc].NbLines - 1);
+}
+
+BOOL FAR PASCAL
+ReplaceCharInBlock(
+ int doc,
+ int x,
+ int y,
+ int ch
+ )
+{
+ LPLINEREC pCurLine;
+ LPBLOCKDEF pCurBlock;
+ NPDOCREC d = &Docs[doc];
+ int realX;
+
+ //Beep and exit if file is ReadOnly
+ if (d->readOnly || ROREGION(d,x,y)) {
+ ReadOnlyBeep();
+ return TRUE;
+ } else {
+ // Clear error status
+ QueryReadOnlyError();
+ }
+
+ //Get information from line we replace char
+ if (!FirstLine (doc, &pCurLine, &y, &pCurBlock))
+ return FALSE;
+ CloseLine(doc, &pCurLine, y, &pCurBlock);
+
+ if (playingRecords) {
+ realX = x;
+ } else {
+ realX = AlignToTabs(x, pCurLine->Length - LHD, (LPSTR)pCurLine->Text);
+ }
+
+ if (realX >= pCurLine->Length - LHD) {
+
+ //Character position is after line last char, insert char
+ return InsertBlock(doc, x, y - 1, 1, (LPSTR)&ch);
+
+ } else {
+
+ d->lineTop = d->lineBottom = y - 1;
+
+ //It's a real replace, open an edit record, append char and
+ //close record
+ if (!OpenRec(doc, REPLACECHAR, realX, y - 1)) {
+ return FALSE;
+ }
+ if (!AppendToRec(doc, (LPSTR)pCurLine->Text + realX, 1, FALSE, NULL)) {
+ return FALSE;
+ }
+ CloseRec(doc, 0, 0, TRUE);
+
+ //Character is inside line, just replace it
+ pCurLine->Text[realX] = (char)ch;
+
+ //Document is modified
+ ModifiedDoc(doc);
+
+ if (d->language != NO_LANGUAGE) {
+ CheckSyntax(doc);
+ }
+ return TRUE;
+ }
+}
+
+ULONG FAR PASCAL CountCharsInDocument(
+ int doc)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+ ULONG nbChars;
+
+ y = 0;
+ //Load first line of document
+ if (!FirstLine (doc, &pl, &y, &pb)) {
+ Assert(FALSE);
+ return 0L;
+ }
+
+ //Count chars in first line
+ nbChars = pl->Length - LHD + 2; //2 = CR+LF
+
+ //Count chars in middle lines
+ while (y < Docs[doc].NbLines) {
+
+ //Load next line of document
+ if (!NextLine (doc, &pl, &y, &pb)) {
+ Assert(FALSE);
+ return 0;
+ }
+
+ //Count chars in current line
+ nbChars += pl->Length - LHD + 2; //2 = CR+LF
+
+ }
+
+ //Refresh pointers
+ CloseLine (doc, &pl, y, &pb);
+
+ return nbChars;
+
+}
+
+//Scan all document and try to compress data by moving lines and
+//filling blocks
+BOOL FAR PASCAL
+CompactDocument(
+ int doc
+ )
+{
+ LPLINEREC pCurLine, pNextLine;
+ LPBLOCKDEF pCurBlock, pNextBlock;
+ int freeBlockSize;
+ BOOL more;
+ NPDOCREC d = &Docs[doc];
+ long spaceRecovered = 0;
+
+ //Load last line of first block
+ pCurBlock = d->FirstBlock;
+ pNextBlock = pCurBlock->NextBlock;
+
+ while (pNextBlock != NULL) {
+
+ pNextLine = (LPLINEREC)(pNextBlock->Data);
+
+ more = TRUE;
+ while (more) {
+
+ pCurLine = (LPLINEREC)(pCurBlock->Data + pCurBlock->LastLineOffset);
+ freeBlockSize = BLOCK_SIZE - pCurBlock->LastLineOffset -
+ pCurLine->Length;
+
+ //Have we space to move next line in current block ?
+ if (freeBlockSize < (int)pNextLine->Length) {
+
+ more = FALSE;
+
+ } else {
+
+ //Move first line from next block in current block
+ pCurBlock->LastLineOffset += pCurLine->Length;
+ _fmemmove((LPSTR)pCurLine + pCurLine->Length,
+ pNextLine,
+ pNextLine->Length);
+
+ //Remove line from next block
+ pNextBlock->LastLineOffset -= pNextLine->Length;
+ spaceRecovered += pNextLine->Length;
+ _fmemmove((LPSTR)pNextBlock->Data,
+ (LPSTR)pNextLine + pNextLine->Length,
+ BLOCK_SIZE - ((LPSTR)pNextLine + pNextLine->Length -
+ (LPSTR)pNextBlock->Data));
+
+ //Free next block if empty
+ if (pNextBlock->LastLineOffset < 0) {
+ pNextBlock = FreeBlock(doc, pNextBlock);
+ if (pNextBlock == NULL) {
+ more = FALSE;
+ } else {
+ pNextLine = (LPLINEREC)(pNextBlock->Data);
+ }
+ }
+ }
+ }
+
+ //Next block becomes current block
+ pCurBlock = pCurBlock->NextBlock;
+ if (pCurBlock != NULL) {
+ pNextBlock = pCurBlock->NextBlock;
+ }
+ }
+
+ //Resynchronize to first line of document
+ d->CurrentLine = 0;
+ d->CurrentBlock = d->FirstBlock;
+ d->CurrentLineOffset = 0;
+ return TRUE;
+}
+
+BOOL FAR PASCAL
+CheckDocument(
+ int doc
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb, previousBlock;
+ BOOL curBlockFound = FALSE, lastBlockFound = FALSE;
+ BOOL curLineFound = FALSE;
+ BYTE curLen;
+ int nbLines = 0;
+ NPDOCREC d = &Docs[doc];
+ int nbBl = 0;
+ DWORD dataSize = 0;
+ DWORD totalSize;
+
+ pb = d->FirstBlock;
+ Assert(pb != NULL);
+ previousBlock = NULL;
+ curLen = 0;
+
+ while (pb != NULL) {
+
+ if (pb == d->CurrentBlock) {
+ curBlockFound = TRUE;
+ }
+ if (pb == d->LastBlock) {
+ lastBlockFound = TRUE;
+ }
+ if (pb->PrevBlock != previousBlock) {
+ return AuxPrintf(1, "ChkDoc:Prev block pointer (Line %i)", nbLines);
+ }
+
+ if (pb->LastLineOffset > BLOCK_SIZE - LHD) {
+ return AuxPrintf(1, "ChkDoc:Line last offset above (Line %i)",
+ nbLines);
+ }
+ if (pb->LastLineOffset < 0) {
+ return AuxPrintf(1, "ChkDoc:Line last offset below (Line %i)",
+ nbLines);
+ }
+
+ pl = (LPLINEREC)(pb)->Data;
+
+ while (pl <= (LPLINEREC)(pb->Data + pb->LastLineOffset)) {
+
+ if (d->CurrentBlock == pb) {
+ if (d->CurrentLineOffset == ((LPSTR)pl - (LPSTR)pb->Data)) {
+ curLineFound = TRUE;
+ if (nbLines != d->CurrentLine) {
+ return AuxPrintf(1, "ChkDoc:Bad current line (Line %i)",
+ nbLines);
+ }
+ }
+ }
+
+ if (pl->PrevLength != curLen) {
+ return AuxPrintf(1, "ChkDoc:Bad prev length (Line %i)",
+ nbLines);
+ }
+ curLen = pl->Length;
+ dataSize += curLen;
+ if (curLen < LHD) {
+ return AuxPrintf(1, "ChkDoc:Bad length (Line %i)", nbLines);
+ }
+ if ((LPSTR)pl + curLen > (LPSTR)pb->Data + BLOCK_SIZE) {
+ return AuxPrintf(1, "ChkDoc:Line above block (Line %i)",
+ nbLines);
+ }
+ (LPSTR)pl += curLen;
+ nbLines++;
+ }
+
+ previousBlock = pb;
+ pb = pb->NextBlock;
+ if (pb == NULL) {
+ if (d->LastBlock != previousBlock) {
+ return AuxPrintf(1, "ChkDoc: Bad last block (Line %i)",
+ nbLines);
+ }
+ }
+
+ nbBl++;
+ }
+
+ totalSize = (DWORD)nbBl * sizeof(BLOCKDEF);
+ AuxPrintf(1,
+ "Blocks = %i, Total Size = %lu, Data Size = %lu, Efficiency = %lu\\%",
+ nbBl, totalSize, dataSize, (100 * dataSize) / totalSize);
+ if (!curBlockFound) {
+ return AuxPrintf(1, "ChkDoc:Lost cur block (Line %i)", nbLines);
+ }
+ if (!lastBlockFound) {
+ return AuxPrintf(1, "ChkDoc:Lost last block (Line %i)", nbLines);
+ }
+ if (!curLineFound){
+ return AuxPrintf(1, "ChkDoc:Lost cur line (Line %i)", nbLines);
+ }
+ if (nbLines != d->NbLines) {
+ return AuxPrintf(1,
+ "ChkDoc:Wrong total of lines (Doc = %i, Count = %i)",
+ d->NbLines, nbLines);
+ }
+
+ return TRUE;
+}
+
+void FAR PASCAL
+DumpDocument(
+ int doc
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int line = 0;
+ char s[10], t[10];
+ NPDOCREC d = &Docs[doc];
+ int i;
+
+ pb = d->FirstBlock;
+ while (pb != NULL) {
+ _itoa(HIWORD((DWORD)pb), t, 16);
+ while ((int)strlen(t) <= 4) {
+ strcat(t, " ");
+ }
+ strcat(t, ":");
+ pl = (LPLINEREC)(pb)->Data;
+ while (pl <= (LPLINEREC)(pb->Data + pb->LastLineOffset)) {
+
+ s[0]='\0';
+ if (d->CurrentBlock == pb) {
+ if (d->CurrentLineOffset == ((LPSTR)pl - (LPSTR)pb->Data)) {
+ _itoa((int)d->CurrentLine, s, 10);
+ }
+ }
+
+ while ((int)strlen(s) <= 2) {
+ strcat(s, " ");
+ }
+
+ _fstrncpy((LPSTR)szTmp, pl->Text, pl->Length - LHD);
+ for (i = 0; i < (int)strlen(szTmp); i++) {
+#ifdef DBCS
+ if(IsDBCSLeadByte((BYTE)szTmp[i])) i++;
+#endif
+ if (szTmp[i] == TAB) {
+ szTmp[i] = 126;
+ }
+ }
+ szTmp[min(200, pl->Length - LHD)] = '\0';
+ AuxPrintf(1, "%s%3u [%3i,%3i,%3i] %s '%s'",
+ (LPSTR)t, line++, pl->Status, pl->PrevLength,
+ pl->Length, (LPSTR)s, (LPSTR)szTmp);
+ strcpy(t," :");
+ (LPSTR)pl += pl->Length;
+ }
+ pb = pb->NextBlock;
+ }
+
+ AuxPrintf(1, "");
+}
+
+BOOL FAR PASCAL
+DestroyDocument(
+ int doc
+ )
+{
+ LPBLOCKDEF pb;
+ NPDOCREC d = &Docs[doc];
+
+ //Destroy undo and possibly redo buffers
+ DestroyRecBuf(doc, REC_UNDO);
+ if (d->playCount != 0 && d->playCount != REC_CANNOTUNDO) {
+ DestroyRecBuf(doc, REC_REDO);
+ }
+
+ //And blocks of memory allocated for it
+ while (d->FirstBlock != NULL) {
+
+ pb = d->FirstBlock;
+
+ Assert(pb->NextBlock != NULL || pb == d->LastBlock);
+
+ d->FirstBlock = pb->NextBlock;
+ if (!DocFree((LPSTR)pb)) {
+ InternalErrorBox(SYS_Free_Memory);
+ }
+ }
+
+ return TRUE;
+}
+
+//Retrieve chars on a line
+BOOL FAR PASCAL
+GetTextAtLine(
+ int doc,
+ int line,
+ int col1,
+ int col2,
+ LPSTR text
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+
+ if (!FirstLine (doc, &pl, &line, &pb))
+ return FALSE;
+ CloseLine(doc, &pl, line, &pb);
+
+ col2 = min(col2, elLen);
+ col1 = min(col1, col2);
+ _fmemmove(text, el + col1, col2 - col1);
+ text[col2 - col1] = '\0';
+ return TRUE;
+}
+
+/*
+void FAR PASCAL
+SetTabs(
+ int doc,
+ int oldTab,
+ int newTab
+ )
+{
+
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y = 0, k, nbTabs, len;
+ int newSpaces, oldSpaces;
+ char buf[MAX_USER_LINE];
+
+ //Get first line
+ if (!FirstLine (doc, &pl, &y, &pb))
+ return;
+ CloseLine(doc, &pl, y, &pb);
+
+ //Read and change every line of document
+ while (y < Docs[doc].NbLines) {
+
+ len = pl->Length - LHD;
+
+ //Do we have to convert line beginning spaces to tabs
+ if (len > 0) {
+
+ nbTabs = 0;
+
+ //Count real tabs
+ k = 0;
+ while ((k < len) && pl->Text[k] == ' ')
+ if ((++k % oldTab) == 0)
+ nbTabs++;
+
+ if (nbTabs > 0) {
+
+ //Remove spaces from line (deleting and inserting a new line)
+ oldSpaces = oldTab * nbTabs;
+ _fmemmove((LPSTR)buf, pl->Text + oldSpaces, len - oldSpaces);
+ DeleteBlock(doc, 0, y - 1, 0, y);
+ newSpaces = newTab * nbTabs;
+ _fmemmove((LPSTR)buf + newSpaces, (LPSTR)buf, newSpaces);
+ _fmemset((LPSTR)buf, ' ', newSpaces);
+
+ len += newSpaces - oldSpaces;
+ _fmemmove((LPSTR)buf + len, "\r\n", 2);
+ InsertBlock(doc, 0, y - 1, len + 2, (LPSTR)buf);
+ }
+
+ }
+
+ if (!FirstLine (doc, &pl, &y, &pb))
+ return;
+ CloseLine(doc, &pl, y, &pb);
+ }
+}
+*/
diff --git a/private/windbg/windbg/edit.c b/private/windbg/windbg/edit.c
new file mode 100644
index 000000000..2540f2074
--- /dev/null
+++ b/private/windbg/windbg/edit.c
@@ -0,0 +1,4849 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ edit.c
+
+Abstract:
+
+ This file contains the routines which deal with the edit manager.
+
+Author:
+
+ Griffith Kadnier (v-griffk)
+
+Environment:
+
+ Win32 - User
+
+Notes:
+
+ This file also contains edit2.c
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+//Prototypes
+
+int NEAR PASCAL mini (int a, int b);
+int NEAR PASCAL maxi (int a, int b);
+int NEAR PASCAL Pos2Pix (int view, int x, int y);
+int NEAR PASCAL AdjustPosX (int x, BOOL goingRight);
+VOID NEAR PASCAL CSyntax (WORD curWinColor, WORD status, WORD prevStatus);
+BOOL NEAR PASCAL MarkStatusLine (int doc, WORD status, WORD prevStatus);
+void NEAR PASCAL SelectLine (int view, int firstX, int lastX);
+void NEAR PASCAL MarkSelectedLine (int view, int line);
+void NEAR PASCAL PatchTabs (int view);
+void NEAR PASCAL WriteLine (int view, int line, HDC hDC, int X, int Y, PRECT pRc, WORD prevStatus);
+void NEAR PASCAL SelPosXY (int view, int X, int Y);
+void NEAR PASCAL MoveRightWord (int view, BOOL Sel, int posX, int posY);
+void NEAR PASCAL SortBlock (int view);
+void NEAR PASCAL FindMatching (int view);
+
+
+
+/***
+
+a-seanl 3/1/94
+
+ Notes On Color Coding For Pre-Processor Instructions.
+
+We presume that the source file has successfully compiled (or else the
+user couldn't even get this far). Therefore, we can be casual in our
+search for pre-processor directives. Specifically, we assume that if the
+first non-whitespace character on a line is '#', then we have a
+pre-processor line, and that all words after that are either user
+identifiers or pre-processor directives.
+
+If the line begins with '#if', then 'defined' becomes a reserved word.
+
+If the line begins with '#pragma', then all of the complier pragmas
+become reserved words.
+
+Otherwise, our handling of color information follows the same steps as the
+original color-coding procedure, except that we must select which set
+of reserved words to search.
+
+Note that this all happens down in the body of CSyntax().
+
+Note also that we now need to watch carefully for continuation lines.
+
+In fact, this is going to get so hairy that I don't think it needs to
+done yet. There are lots of other brush fires that are considerably,
+hotter, eh?
+
+***/
+
+
+
+
+static
+char*
+Edit__preProcDirectives[] =
+ {
+ "define", "elif", "else", "endif", "error", "if",
+ "ifdef", "ifndef", "include", "line", "pragma", "undef"
+ };
+
+static
+char*
+Edit__preProcPragmas[] =
+ {
+ "alloc_text",
+ "auto_inline",
+ "best_case",
+ "check_pointer",
+ "check_stack",
+ "code_seg",
+ "comment",
+ "compiler",
+ "data_seg",
+ "default",
+ "disable",
+ "error",
+ "exestr",
+ "full_generality",
+ "function",
+ "hdrstop",
+ "init_seg",
+ "inline_depth",
+ "inline_recursion",
+ "intrinsic",
+ "lib",
+ "linesize",
+ "loop_opt",
+ "message",
+ "multiple_inheritance",
+ "native_caller",
+ "off",
+ "on",
+ "once",
+ "optimize",
+ "pack",
+ "page",
+ "pagesize",
+ "pointers_to_members",
+ "pop",
+ "push",
+ "same_seg",
+ "setlocale",
+ "single_inheritance",
+ "skip",
+ "string_pooling",
+ "subtitle",
+ "title",
+ "user",
+ "virtual_inheritance",
+ "vtordisp"
+ "warning",
+ };
+
+
+
+
+//Editor : Table of C 2.00 Keywords-MUST remain in sorted order!!!
+//
+// [April 1994]
+// Note: The second group is a single-underbar version of the first group. The
+// compiler (v7.0) uses the double underbar for ANSI's sake, but allows the
+// single underbar for backwards compatibility. The only discrepancy is the
+// '__declspec' keywaord, and that appears to nothave a single-underbar version.
+//
+// We include the Win32 extended syntax keywords:
+//
+// dllexport, dllimport, naked, thread
+//
+// [May 1994]
+// Note: The list is now current with VC++ 2.0 sources, courtesy of richards (Rich Shupak).
+// They do something with '_declspec', so now we will, too.
+//
+
+char *(CKeywords[]) = {
+
+ "__asm",
+ "__based",
+ "__cdecl",
+ "__declspec",
+ "__emit",
+ "__except",
+ "__export",
+ "__far",
+ "__fastcall",
+ "__finally",
+ "__fortran",
+ "__huge",
+ "__inline",
+ "__int16",
+ "__int32",
+ "__int64",
+ "__int8",
+ "__interrupt",
+ "__leave"
+ "__loadds",
+ "__multiple_inheritance",
+ "__nctag",
+ "__near",
+ "__nounwind",
+ "__novtordisp",
+ "__pascal",
+ "__resume",
+ "__saveregs",
+ "__segment",
+ "__segname",
+ "__self",
+ "__single_inheritance",
+ "__stdcall",
+ "__try",
+ "__virtual_inheritance",
+
+
+ "_asm",
+ "_based",
+ "_cdecl",
+ "_declspec",
+ "_emit",
+ "_except",
+ "_export",
+ "_far",
+ "_fastcall",
+ "_finally",
+ "_fortran",
+ "_huge",
+ "_inline",
+ "_int16",
+ "_int32",
+ "_int64",
+ "_int8",
+ "_interrupt",
+ "_leave"
+ "_loadds",
+ "_multiple_inheritance",
+ "_nctag",
+ "_near",
+ "_nounwind",
+ "_novtordisp",
+ "_pascal",
+ "_resume",
+ "_saveregs",
+ "_segment",
+ "_segname",
+ "_self",
+ "_single_inheritance",
+ "_stdcall",
+ "_try",
+
+
+ "_virtual_inheritance",
+
+
+ "auto",
+ "break",
+ "case",
+ "catch",
+ "cdecl",
+ "char",
+ "class",
+ "const",
+ "continue",
+ "default",
+ "delete",
+ "dllexport",
+ "dllimport",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "extern",
+ "far",
+ "float",
+ "for",
+ "fortran",
+ "friend",
+ "goto",
+ "huge",
+ "if",
+ "inline",
+ "int",
+ "interrupt",
+ "long",
+ "naked",
+ "near",
+ "new",
+ "operator",
+ "pascal",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "thread",
+ "throw",
+ "try",
+ "typedef",
+ "union",
+ "unsigned",
+ "virtual",
+ "void",
+ "volatile",
+ "while"
+
+};
+
+
+
+
+// colors for Textout()
+
+#define FORECOLOR(colorRef) ( StringColors[ colorRef ].FgndColor )
+#define BACKCOLOR(colorRef) ( StringColors[ colorRef ].BkgndColor )
+
+
+//To make the difference between a mouse and keyboard scroll
+
+#define FROM_MOUSE 0x0
+#define FROM_KEYBOARD 0x1
+#define SELECTING 0x2
+
+
+int NEAR PASCAL mini (int a, int b)
+{
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+int NEAR PASCAL maxi(int a, int b)
+{
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+//Pix2Pos - convert a position in pixel to its nearest position in char
+int FAR PASCAL Pix2Pos(
+ int view,
+ int X,
+ int Y)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ register int pix, idx;
+ int pix1;
+ NPVIEWREC v = &Views[view];
+ int blankWidth = v->charWidth[' '];
+#ifdef DBCS
+ BOOL bDBCS = FALSE;
+ SIZE SizeDBCS;
+ char szDBCS[3];
+ HDC hDCTmp = 0;
+#endif // DBCS
+
+ //Normalize
+ if (Y < 0)
+ Y = 0;
+
+ Assert(v->Doc >= 0);
+ Assert(Y < Docs[v->Doc].NbLines);
+
+ // Get text of line
+ if (!FirstLine(v->Doc, &pl, &Y, &pb))
+ return 0;
+#ifdef DBCS
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ Dbg(hDCTmp = GetDC(v->hwndClient));
+ Dbg(SelectObject(hDCTmp, v->font));
+ }
+#endif
+
+ idx = 0;
+ pix = 0;
+ while (pix < X) {
+#ifdef DBCS
+ bDBCS = FALSE;
+ if (idx < elLen - 1 && IsDBCSLeadByte((BYTE)el[idx])) {
+ bDBCS = TRUE;
+
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ szDBCS[0] = el[idx];
+ szDBCS[1] = el[idx+1];
+ szDBCS[2] = '\0';
+ GetTextExtentPoint(
+ hDCTmp, szDBCS, 2, &SizeDBCS);
+ pix += (SizeDBCS.cx - v->Tmoverhang);
+ } else
+ pix += v->charWidthDBCS;
+ idx += 2;
+ } else if (idx >= elLen) {
+ pix += blankWidth;
+ idx++;
+ } else {
+ pix += (v->charWidth[(BYTE)(el[idx])] - v->Tmoverhang);
+ idx++;
+ }
+#else // !DBCS
+ if (idx >= (pl->Length - LHD))
+ pix += blankWidth;
+ else
+ pix += (v->charWidth[(BYTE)(pl->Text[idx])] - v->Tmoverhang);
+ idx++;
+#endif // !DBCS
+ }
+
+ if (pix != X) {
+ pix1 = pix;
+#ifdef DBCS
+ if (bDBCS) {
+ idx -= 2;
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ szDBCS[0] = el[idx];
+ szDBCS[1] = el[idx+1];
+ szDBCS[2] = '\0';
+ GetTextExtentPoint(
+ hDCTmp, szDBCS, 2, &SizeDBCS);
+ pix -= (SizeDBCS.cx - v->Tmoverhang);
+ } else
+ pix -= v->charWidthDBCS;
+ } else {
+ idx--;
+ if (idx >= elLen)
+ pix -= blankWidth;
+ else
+ pix -= v->charWidth[(BYTE)(el[idx])];
+ }
+ if ((pix + ((pix1 - pix) >> 1)) < X) {
+ if (bDBCS)
+ idx+=2;
+ else
+ idx++;
+ }
+#else // !DBCS
+ idx--;
+ if (idx >= (pl->Length - LHD))
+ pix -= blankWidth;
+ else
+ pix -= (v->charWidth[(BYTE)(pl->Text[idx])] - v->Tmoverhang);
+ if ((pix + ((pix1 - pix) >> 1)) < X)
+ idx++;
+#endif
+ }
+
+#ifdef DBCS
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ Dbg(ReleaseDC (v->hwndClient, hDCTmp));
+ }
+#endif
+ CloseLine (v->Doc, &pl, Y, &pb);
+ return idx;
+}
+
+//Pos2Pix - convert a position in character to its position in pixels
+int NEAR PASCAL Pos2Pix(
+ int view,
+ int x,
+ int y)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ NPVIEWREC v = &Views[view];
+ register int i, xPixel;
+ int *charWidth = Views[view].charWidth;
+#ifdef DBCS
+ SIZE SizeDBCS;
+ char szDBCS[3];
+ HDC hDCTmp = 0;
+#endif
+
+ //Normalize
+ Assert(v->Doc >= 0);
+ Assert(y < Docs[v->Doc].NbLines);
+ if (x < 0)
+ x = 0;
+ if (x > MAX_USER_LINE)
+ x = MAX_USER_LINE;
+ if (y < 0)
+ y = 0;
+
+ // Get text of line
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return 0;
+ CloseLine(v->Doc, &pl, y, &pb);
+
+#ifdef DBCS
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ Dbg(hDCTmp = GetDC(v->hwndClient));
+ Dbg(SelectObject(hDCTmp, v->font));
+ }
+#endif
+ //We do not need to take care of the position beyond line,
+ //"el" is allways filled with spaces
+ xPixel = 0;
+ for (i = 0; i < x; i++)
+#ifdef DBCS
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ szDBCS[0] = el[i];
+ szDBCS[1] = el[i+1];
+ szDBCS[2] = '\0';
+ GetTextExtentPoint(
+ hDCTmp, szDBCS, 2, &SizeDBCS);
+ xPixel += (SizeDBCS.cx - v->Tmoverhang);
+ } else
+ xPixel += Views[view].charWidthDBCS;
+ i++;
+ } else
+#endif // DBCS
+ xPixel += (charWidth[(BYTE)el[i]] - v->Tmoverhang);
+
+#ifdef DBCS
+ if (v->wViewPitch == VIEW_PITCH_VARIABLE) {
+ Dbg(ReleaseDC (v->hwndClient, hDCTmp));
+ }
+#endif
+ return xPixel;
+}
+
+
+
+void FAR PASCAL
+SetCaret(
+ int view,
+ int x,
+ int y,
+ int pixelPos
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to set the caret at a specfic X, Y position.
+
+Arguments:
+
+ view - Supplies the index of the view to set caret in
+ x - Supplies the X pos (character) to set caret at
+ y - Supplies the Y pos (line) to set caret at
+ pixelPos - Supplies the pixel position to set cursor at.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NPVIEWREC v = &Views[view];
+ int yPos = v->iYTop;
+#if 0
+ char obuf[80];
+#endif
+
+ if (pixelPos == -1) {
+ pixelPos = Pos2Pix(view, x, y);
+ }
+
+ if (yPos == -1) {
+ yPos = GetScrollPos(v->hwndClient, SB_VERT);
+ }
+
+ SetCaretPos(pixelPos - v->maxCharWidth * GetScrollPos(v->hwndClient, SB_HORZ),
+ (int)(((long)y - (long)yPos) * (long)v->charHeight));
+
+#ifdef FE_IME
+ ImeMoveConvertWin(v->hwndClient,
+ pixelPos - v->maxCharWidth
+ * GetScrollPos(v->hwndClient, SB_HORZ),
+ (int)(((long)y - (long)yPos) * (long)v->charHeight));
+#endif
+
+#if 0
+ wsprintf (obuf," SCP called in edit.c with %d , %d\n",pixelPos - v->maxCharWidth * GetScrollPos(v->hwndClient, SB_HORZ),
+ (int)(((long)y - (long)yPos) * (long)v->charHeight));
+#endif
+
+
+
+
+ return;
+} /* SetCaret() */
+
+
+void FAR PASCAL
+InvalidateLines(
+ int actualView,
+ int FromL,
+ int ToL,
+ BOOL lineAdded
+ )
+/*++
+
+Routine Description:
+
+ This function is called to invalidate lines in a window. The
+ lines to be invalided are passed in. The routine will invalidate
+ all views on the same document.
+
+Arguments:
+
+ actualView - Supplies the view index to be invalidated
+ FromL - Starting line to invalidate
+ ToL - Ending line to invalidate
+ lineAdded - TRUE if lines were added to the view.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ RECT rcl;
+ int minim;
+ int maxim;
+ long k;
+ int view = Docs[Views[actualView].Doc].FirstView;
+ HWND hwnd;
+ int charHeight;
+ int yPos;
+
+ Assert(view >= 0 && view < MAX_VIEWS);
+ Assert(Views[actualView].Doc >= 0);
+
+ while (view != -1) {
+ yPos = Views[view].iYTop;
+ hwnd = Views[view].hwndClient;
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+ GetClientRect(hwnd, &rcl);
+ charHeight = Views[view].charHeight;
+
+ /*
+ * Beware of integer overflow
+ */
+
+ k = (long)(FromL - yPos) * charHeight;
+ if (k > 32767) {
+ minim = 32767;
+ } else if (k < -32767) {
+ minim = -32767;
+ } else {
+ minim = (int)k;
+ }
+
+ if ((ToL == LAST_LINE) || lineAdded) {
+ maxim = rcl.bottom;
+ } else {
+ k = (long)(ToL - yPos + 1) * charHeight;
+
+ if (k > 32767) {
+ maxim = 32767;
+ } else if (k < -32767) {
+ maxim = -32767;
+ } else {
+ maxim = (int)k;
+ }
+ }
+
+ if (minim < rcl.bottom && maxim > rcl.top) {
+ if (minim > rcl.top) {
+ rcl.top = minim;
+ }
+
+ if (maxim < rcl.bottom) {
+ rcl.bottom = maxim;
+ }
+
+ InvalidateRect(hwnd, &rcl, TRUE);
+ }
+ view = Views[view].NextView;
+ }
+ return;
+} /* InvalidateLines() */
+
+int NEAR PASCAL AdjustPosX(
+ int x,
+ BOOL goingRight)
+{
+ register int i = 0;
+ register int j = 0;
+ int k;
+ int len = pcl->Length - LHD;
+
+ while (i < len && j < x) {
+#ifdef DBCS
+ if (IsDBCSLeadByte((BYTE)pcl->Text[i])) {
+ if (x == j+1) {
+ if (goingRight)
+ return j+2;
+ else
+ return j;
+ }
+ j += 2;
+ i++;
+ } else
+#endif
+ if (pcl->Text[i] == TAB) {
+ k = j;
+ j += tabSize - (j % tabSize);
+ if (x > k && x < j) {
+ if (goingRight)
+ return j;
+ else
+ return k;
+ }
+ }
+ else
+ j++;
+ i++;
+ }
+
+ Assert(j <= MAX_USER_LINE);
+ return x;
+}
+
+
+void FAR PASCAL
+InternalPosXY(
+ int view,
+ int X,
+ int Y,
+ BOOL fDebugger,
+ BOOL fCenter
+ )
+
+/*++
+
+Routine Description:
+
+ This function will cause the cursor to be placed at a specific
+ location in a window.
+
+Arguments:
+
+ view - Supplies the view index to postion in
+ x - Supplies the X (character) position
+ y - Supplies the Y (line) position
+ fDebugger - Supplies TRUE if called by the debugger placement routines
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int firstL;
+ int firstLn;
+ int firstC,firstCol;
+ int winNbLines;
+ int XX;
+ int XC;
+ RECT rc;
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int yPos;
+
+ /*
+ * Normalize
+ */
+
+ Assert(Y <= Docs[v->Doc].NbLines - 1);
+ Assert(v->Doc >= 0);
+
+ if (X < 0) {
+ X = 0;
+ }
+ if (X > MAX_USER_LINE) {
+ X = MAX_USER_LINE;
+ }
+ if (Y < 0) {
+ Y = 0;
+ }
+
+ /*
+ * Get text of line
+ */
+
+ if (!FirstLine(v->Doc, &pl, &Y, &pb)) {
+ return;
+ }
+ CloseLine (v->Doc, &pl, Y, &pb);
+ Y--;
+
+ /*
+ * Convert to edit if coming from undo/redo
+ */
+
+ if (playingRecords) {
+ X = ConvertPosX(X);
+ }
+
+ /*
+ * Skip tabs white space
+ */
+
+ X = AdjustPosX(X, (X >= v->X && Y == v->Y));
+ v->X = X;
+ v->Y = Y;
+
+ if (view == curView) {
+ StatusLineColumn(Y + 1, X + 1);
+ }
+
+ /*
+ * See if we have to remove or put back scrollbars
+ */
+
+ EnsureScrollBars(view, FALSE);
+
+ /*
+ * Get size of client data area. This should wait until after scroll
+ * bars may have been added.
+ */
+
+ GetClientRect(hwnd, &rc);
+
+ /*
+ * Take care of vertical scroll
+ */
+
+ yPos = v->iYTop;
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+ firstLn = firstL = yPos;
+
+ /*
+ * Compute nb of lines seen in window
+ */
+
+ winNbLines = rc.bottom / v->charHeight;
+
+ if (rc.bottom % v->charHeight) {
+ winNbLines++;
+ }
+
+ if (Y < firstL) {
+ if (fDebugger) {
+ if (winNbLines < 6) {
+ firstL = Y;
+ }
+ else {
+ firstL = Y - (winNbLines/5);
+ if (firstL < 0) {
+ firstL = 0;
+ }
+ }
+ }
+ else {
+ if (fCenter) {
+ firstL = Y - (winNbLines / 2);
+ }
+ else {
+ firstL = Y;
+ }
+ }
+ }
+ else
+ if (Y >= (firstL + (winNbLines - 1))) {
+ if (fDebugger) {
+ if (winNbLines < 6) {
+ firstL = Y;
+ }
+ else {
+ firstL = Y - (winNbLines/5);
+ }
+ }
+ else {
+ if (fCenter) {
+ firstL = Y - (winNbLines / 2);
+ }
+ else {
+ firstL = Y - (winNbLines - 2);
+ }
+ }
+ }
+
+ /*
+ * Set scroll-bar positions before refreshing the screen.
+ * We use the scroll-bar positions during the PAINT event
+ */
+
+ if (firstL != firstLn) {
+ if (v->iYTop == -1) {
+ SetScrollPos(hwnd, SB_VERT, firstL, TRUE);
+ } else {
+ v->iYTop = firstL;
+ }
+ ScrollWindow(hwnd, 0, (firstLn - firstL) * v->charHeight, NULL, NULL);
+ UpdateWindow (hwnd);
+ }
+
+ /*
+ * Take care of horizontal scroll
+ */
+
+ firstCol = firstC = GetScrollPos(hwnd, SB_HORZ);
+ XC = firstC * v->maxCharWidth;
+ XX = Pos2Pix(view, X, Y);
+
+ if (XX <= XC) {
+ firstC = maxi((XX - (rc.right / SCROLL_RATIO)) / v->maxCharWidth, 0);
+ } else {
+ if (XX >= XC + rc.right) {
+ firstC = (XX - rc.right + (rc.right / SCROLL_RATIO)) / v->maxCharWidth;
+ }
+ }
+
+ /*
+ * Set scroll-bar positions before refreshing the screen.
+ * We use the scroll-bar positions during the PAINT event
+ */
+
+ if (firstC != firstCol) {
+ SetScrollPos(hwnd, SB_HORZ, firstC, TRUE);
+ ScrollWindow(hwnd, (firstCol - firstC) * v->maxCharWidth, 0, NULL, NULL);
+ UpdateWindow (hwnd);
+ //InvalidateRect (hwnd,NULL,TRUE);
+ }
+
+ if (view == curView) {
+ SetCaret(view, X, Y, XX);
+ }
+
+ return;
+} /* InternalPosXY() */
+
+
+void FAR PASCAL
+PosXY(
+ int view,
+ int X,
+ int Y,
+ BOOL fDebugger
+ )
+
+/*++
+
+Routine Description:
+
+ This function will cause the cursor to be placed at a specific
+ location in a window.
+
+Arguments:
+
+ view - Supplies the view index to postion in
+ x - Supplies the X (character) position
+ y - Supplies the Y (line) position
+ fDebugger - Supplies TRUE if called by the debugger placement routines
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ InternalPosXY( view, X, Y, fDebugger, FALSE );
+}
+
+
+void FAR PASCAL
+PosXYCenter(
+ int view,
+ int X,
+ int Y,
+ BOOL fDebugger
+ )
+
+/*++
+
+Routine Description:
+
+ This function will cause the cursor to be placed at a specific
+ location in a window.
+
+Arguments:
+
+ view - Supplies the view index to postion in
+ x - Supplies the X (character) position
+ y - Supplies the Y (line) position
+ fDebugger - Supplies TRUE if called by the debugger placement routines
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ InternalPosXY( view, X, Y, fDebugger, TRUE );
+}
+
+int _CRTAPI1 Compare(const char **left, const char **right)
+{
+ return strcmp(*left, *right);
+}
+
+//Create attr table for a C source line
+//This function is designed for speed, not to look nice...
+ VOID NEAR PASCAL CSyntax(
+ WORD curWinColor,
+ WORD status,
+ WORD prevStatus)
+{
+ register int i;
+ ULONG fore, back;
+ ULONG defaultFore;
+ ULONG defaultBack;
+ char ch, *pst;
+ int start;
+ BOOL wasInDefault = FALSE;
+ BOOL isFrac = FALSE;
+
+
+ colors[0].nbChars = 0;
+ colors[0].fore = defaultFore = FORECOLOR(curWinColor);
+ colors[0].back = defaultBack = BACKCOLOR(curWinColor);
+ i = 0;
+
+ if (elLen > 1 && !(status & COMMENT_LINE) && (prevStatus & COMMENT_LINE)) {
+ start = 0;
+
+ //Closing multiline comments
+#ifdef DBCS
+ while (i < elLen - 1) {
+ if (IsDBCSLeadByte(el[i])) {
+ i += 2;
+ } else if (el[i] == '*' && el[i + 1] == '/') {
+ break;
+ } else {
+ i++;
+ }
+ }
+#else // !DBCS
+ while (i < elLen - 1 && (el[i] != '*' || el[i + 1] != '/'))
+ i++;
+#endif
+ Assert(i < elLen - 1);
+
+ i += 2;
+
+ colors[0].fore = FORECOLOR(Cols_Comment);
+ colors[0].back = BACKCOLOR(Cols_Comment);
+ colors[0].nbChars = i - start;
+ nbColors = 1;
+ colors[1].nbChars = 0;
+
+ }
+
+ while (i < elLen) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(el[i])) {
+ colors[nbColors].nbChars+=2;
+ wasInDefault = TRUE;
+ i += 2;
+ continue;
+ }
+#endif
+
+ start = i;
+ ch = el[i++];
+
+ if ((ch == ' ') && isFrac)
+ {
+ isFrac = FALSE;
+ }
+
+ if (IsCharAlpha(ch) || ch == '_' || ch == '#') {
+
+ char savedChar;
+
+ isFrac = FALSE;
+
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+ pst = el + i - 1;
+ while (i < elLen && (CHARINALPHASET(el[i])))
+ i++;
+ savedChar = el[i];
+ el[i] = 0;
+
+ if (bsearch((char *)&pst, CKeywords, sizeof(CKeywords) / sizeof(CKeywords[0]), sizeof(CKeywords[0]), (int (_CRTAPI1 *)(const void *, const void *))Compare) != NULL) {
+ fore = FORECOLOR(Cols_Keyword);
+ back = BACKCOLOR(Cols_Keyword);
+ }
+ else {
+ fore = FORECOLOR(Cols_Identifier);
+ back = BACKCOLOR(Cols_Identifier);
+ }
+ el[i] = savedChar;
+
+ }
+ else
+ switch (ch) {
+
+ //Number
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+
+ fore = FORECOLOR(Cols_Number);
+ back = BACKCOLOR(Cols_Number);
+
+ if (i < elLen && ch == '0' && (el[i] == 'x' || el[i] == 'X')) {
+
+ //We have an hexadecimal number
+ while ((i < elLen) && ((el[i] >= '0' && el[i] <= '9') || (el[i] == 'x') || (el[i] == 'X') || ((el[i] >= 'a') && (el[i] <= 'f')) || ((el[i] >= 'A') && (el[i] <= 'F'))))
+ i++;
+ }
+ else {
+
+ BOOL isExponent = FALSE;
+
+ //We have a non hexa number
+ while ((i < elLen) && ((el[i] >= '0' && el[i] <= '9') || (!isFrac && (el[i] == '.'))
+ || el[i] == 'e' || el[i] == 'E'
+ || (isExponent && (el[i] == '-' || el[i] == '+')))) {
+ if (el[i] == 'e' || el[i] == 'E' || el[i] == '.') {
+
+ //Precisely, we have a real number
+ fore = FORECOLOR(Cols_Real);
+ back = BACKCOLOR(Cols_Real);
+
+ if (el[i] != '.')
+ isExponent = TRUE;
+ else
+ isFrac = TRUE;
+ }
+ i++;
+ }
+
+ }
+ break;
+
+ case '.':
+
+ if (i < elLen && (el[i] >= '0' && el[i] <= '9') && !isFrac) {
+
+ BOOL isExponent = FALSE;
+
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+
+ //We have a real number
+ while ((i < elLen) && ((el[i] >= '0' && el[i] <= '9')
+ || el[i] == 'e' || el[i] == 'E'
+ || (isExponent && (el[i] == '-' || el[i] == '+')))) {
+
+ if (el[i] == 'e' || el[i] == 'E')
+ isExponent = TRUE;
+ i++;
+ }
+
+ fore = FORECOLOR(Cols_Real);
+ back = BACKCOLOR(Cols_Real);
+ }
+ else
+
+ //We have something else
+ goto defaut;
+
+ break;
+
+ case '"':
+
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+
+ fore = FORECOLOR(Cols_String);
+ back = BACKCOLOR(Cols_String);
+
+ //Now search for a second '"'
+#ifdef DBCS
+ {
+ int iBackSlash1 = -2;
+ int iBackSlash2 = -2;
+
+ do {
+ //Handle possible double '\\' before a '"'
+ if (i < 1) {
+ break;
+ } else if (IsDBCSLeadByte(el[i])) {
+ i += 2;
+ } else {
+ if (el[i] == '\\') {
+ iBackSlash1 = iBackSlash2;
+ iBackSlash2 = i;
+ } else if (el[i] == '"') {
+ if (i != iBackSlash2 + 1
+ || (i == iBackSlash2 + 1 && i == iBackSlash1 + 2)) {
+ break;
+ }
+ }
+ i++;
+ }
+ } while (i < elLen);
+ }
+#else // !DBCS
+ do {
+
+ //Handle possible double '\\' before a '"'
+ if (el[i] == '"') {
+
+ if (i < 1 || el[i - 1] != '\\')
+ break;
+ else {
+ if (i >= 2 && el[i - 2] == '\\')
+ break;
+ }
+ }
+
+ i++;
+ } while (i < elLen);
+#endif // !DBCS
+ if (i >= elLen)
+ goto done;
+
+ i++;
+ break;
+
+ case '\'':
+
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+
+
+ fore = FORECOLOR(Cols_String);
+ back = BACKCOLOR(Cols_String);
+
+ //Now search for a second "'"
+#ifdef DBCS
+ {
+ int iBackSlash1 = -2;
+ int iBackSlash2 = -2;
+
+ do {
+ //Handle possible double '\\' before a '"'
+ if (i < 1) {
+ break;
+ } else if (IsDBCSLeadByte(el[i])) {
+ i += 2;
+ } else {
+ if (el[i] == '\\') {
+ iBackSlash1 = iBackSlash2;
+ iBackSlash2 = i;
+ } else if (el[i] == '\'') {
+ if (i != iBackSlash2 + 1
+ || (i == iBackSlash2 + 1 && i == iBackSlash1 + 2)) {
+ break;
+ }
+ }
+ i++;
+ }
+ } while (i < elLen);
+ }
+#else // !DBCS
+ do {
+
+ //Handle possible double "\\" before a "'"
+ if (el[i] == '\'') {
+
+ if (i < 1 || el[i - 1] != '\\')
+ break;
+ else {
+ if (i >= 2 && el[i - 2] == '\\')
+ break;
+ }
+ }
+
+ i++;
+ } while (i < elLen);
+#endif // !DBCS
+
+ if (i >= elLen)
+ goto done;
+ i++;
+ break;
+
+ //Opening Comments
+ case '/':
+
+ fore = FORECOLOR(Cols_Comment);
+ back = BACKCOLOR(Cols_Comment);
+
+ //Comment
+ if (i < elLen && el[i] == '*') {
+
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+
+ i++;
+
+#ifdef DBCS
+ while (i < elLen - 1) {
+ if (IsDBCSLeadByte(el[i])) {
+ i += 2;
+ } else if (el[i] == '*' && el[i + 1] == '/') {
+ break;
+ } else {
+ i++;
+ }
+ }
+#else // !DBCS
+ while (i < elLen - 1 && (el[i] != '*' || el[i + 1] != '/'))
+ i++;
+#endif
+
+ //Begin of a multiline comment
+ if (i >= elLen - 1)
+ goto done;
+
+ i += 2;
+ }
+ else {
+ if (i < elLen && el[i] == '/') {
+ if (wasInDefault) {
+ colors[nbColors].fore = defaultFore;
+ colors[nbColors].back = defaultBack;
+ nbColors++;
+ wasInDefault = FALSE;
+ }
+ goto done;
+ }
+ else
+ goto defaut;
+ }
+
+ break;
+
+ default:
+ defaut:
+ colors[nbColors].nbChars++;
+ wasInDefault = TRUE;
+ break;
+ }
+
+ if (!wasInDefault) {
+ colors[nbColors].fore = fore;
+ colors[nbColors].back = back;
+ colors[nbColors].nbChars = i - start;
+ nbColors++;
+ colors[nbColors].nbChars = 0;
+ }
+ }
+
+ colors[nbColors].fore = FORECOLOR(curWinColor);
+ colors[nbColors].back = BACKCOLOR(curWinColor);
+ colors[nbColors].nbChars = 2 * MAX_USER_LINE - i;
+ return;
+
+ done: {
+ colors[nbColors].fore = fore;
+ colors[nbColors].back = back;
+ colors[nbColors].nbChars = 2 * MAX_USER_LINE - start;
+ }
+
+}
+
+
+//Mark status attributes
+BOOL NEAR PASCAL MarkStatusLine(
+ int doc,
+ WORD status,
+ WORD prevStatus)
+{
+ ULONG fore, back;
+
+ //Colors for tags, current debug line, breakpoint and comment lines
+ if (status > 0) {
+
+
+
+ if ((status & UBP_LINE) && (!(status & BRKPOINT_LINE))) {
+ fore = FORECOLOR(Cols_UnInstantiatedBreakpoint);
+ back = BACKCOLOR(Cols_UnInstantiatedBreakpoint);
+ goto markAllLine;
+ }
+
+ if (status & CURRENT_LINE) {
+ if ((status & BRKPOINT_LINE) || (status & UBP_LINE))
+ {
+ fore = FORECOLOR(Cols_CurrentBreak);
+ back = BACKCOLOR(Cols_CurrentBreak);
+ }
+ else
+ {
+ fore = FORECOLOR(Cols_CurrentLine);
+ back = BACKCOLOR(Cols_CurrentLine);
+ }
+ goto markAllLine;
+ }
+
+ if (status & BRKPOINT_LINE) {
+ if (status & CURRENT_LINE)
+ {
+ fore = FORECOLOR(Cols_CurrentBreak);
+ back = BACKCOLOR(Cols_CurrentBreak);
+ }
+ else
+ {
+ fore = FORECOLOR(Cols_BreakpointLine);
+ back = BACKCOLOR(Cols_BreakpointLine);
+ }
+ goto markAllLine;
+ }
+
+ if (status & TAGGED_LINE) {
+ fore = FORECOLOR(Cols_TaggedLine);
+ back = BACKCOLOR(Cols_TaggedLine);
+ goto markAllLine;
+ }
+
+ if (syntaxColors && Docs[doc].language != NO_LANGUAGE
+ && (status & COMMENT_LINE)
+ && (prevStatus & COMMENT_LINE)) {
+ fore = FORECOLOR(Cols_Comment);
+ back = BACKCOLOR(Cols_Comment);
+ goto markAllLine;
+ }
+
+ }
+
+ return FALSE;
+
+ markAllLine : {
+ colors[nbColors].nbChars = 2 * MAX_USER_LINE;
+ colors[nbColors].fore = fore;
+ colors[nbColors].back = back;
+ return TRUE;
+ }
+
+}
+
+void NEAR PASCAL SelectLine(
+ int view,
+ int firstX,
+ int lastX)
+{
+ int firstTot = 0, firstColSel = 0;
+ int lastTot, lastColSel;
+ int lastRemain;
+ int colNb, inSelect;
+ COLORINFO c;
+
+ Unused(view);
+ Unused(colNb);
+ Unused(inSelect);
+ Unused(c);
+
+ //Handle the case where all right part of line is selected
+ if (lastX == MAX_USER_LINE) {
+
+ if (firstX == 0) {
+ colors[0].fore = FORECOLOR(Cols_Selection);
+ colors[0].back = BACKCOLOR(Cols_Selection);
+ colors[0].nbChars = 2 * MAX_USER_LINE;
+ nbColors = 0;
+ return;
+ }
+
+ //Find the position of firstX in the color array
+ while (firstTot <= firstX) {
+ firstTot += colors[firstColSel].nbChars;
+ if (firstTot <= firstX)
+ firstColSel++;
+ }
+ Assert(firstColSel <= nbColors);
+
+ colors[firstColSel].nbChars -= (firstTot - firstX);
+ nbColors = firstColSel + 1;
+ colors[nbColors].fore = FORECOLOR(Cols_Selection);
+ colors[nbColors].back = BACKCOLOR(Cols_Selection);
+ colors[nbColors].nbChars = 2 * MAX_USER_LINE - firstX;
+ return;
+ }
+ else {
+
+ //Handle the case where all left part of line is selected
+ if (firstX == 0) {
+
+ if (lastX == 0)
+ return;
+
+ if (lastX == MAX_USER_LINE) {
+ colors[0].fore = FORECOLOR(Cols_Selection);
+ colors[0].back = BACKCOLOR(Cols_Selection);
+ colors[0].nbChars = 2 * MAX_USER_LINE;
+ nbColors = 0;
+ return;
+ }
+
+ //Find the position of lastX in the color array
+ lastTot = lastColSel = 0;
+ while (lastTot < lastX) {
+ lastTot += colors[lastColSel].nbChars;
+ if (lastTot < lastX)
+ lastColSel++;
+ }
+ Assert(lastColSel <= nbColors);
+ lastRemain = lastTot - lastX;
+
+ //Insert a new color
+ if (lastRemain != 0) {
+ nbColors++;
+ memmove(&colors[1], &colors[0], nbColors * sizeof(COLORINFO));
+ }
+
+ //Remove all colors before lastX
+ nbColors -= lastColSel;
+ memmove(&colors[0], &colors[lastColSel], (nbColors + 1) * sizeof(COLORINFO));
+
+ colors[0].fore = FORECOLOR(Cols_Selection);
+ colors[0].back = BACKCOLOR(Cols_Selection);
+ colors[0].nbChars = lastX;
+
+ if (lastRemain == 0)
+ return;
+
+ colors[1].nbChars = lastRemain;
+
+ }
+ else {
+
+ //Find the position of firstX in the color array
+ while (firstTot <= firstX) {
+ firstTot += colors[firstColSel].nbChars;
+ if (firstTot <= firstX)
+ firstColSel++;
+ }
+ Assert(firstColSel <= nbColors);
+
+ //Find the position of lastX in the color array
+ lastTot = lastColSel = 0;
+ while (lastTot < lastX) {
+ lastTot += colors[lastColSel].nbChars;
+ if (lastTot < lastX)
+ lastColSel++;
+ }
+ Assert(lastColSel <= nbColors);
+ lastRemain = lastTot - lastX;
+
+ //Selection inside the same color
+ if (firstColSel == lastColSel) {
+
+ //Duplicate the element and leave space for selection
+ nbColors++;
+ lastColSel += 2;
+ memmove(&colors[lastColSel], &colors[firstColSel], (nbColors - firstColSel) * sizeof(COLORINFO));
+ nbColors++;
+
+ //Align non selected left part
+ colors[firstColSel].nbChars -= (firstTot - firstX);
+
+ //Align non selected right part
+ colors[lastColSel].nbChars = lastRemain;
+
+ //Set selection
+ firstColSel++;
+ colors[firstColSel].fore = FORECOLOR(Cols_Selection);
+ colors[firstColSel].back = BACKCOLOR(Cols_Selection);
+ colors[firstColSel].nbChars = lastX - firstX;
+ return;
+ }
+
+ //Selection spreads over more than one color
+ nbColors++;
+ lastColSel++;
+ memmove(&colors[firstColSel + 1], &colors[firstColSel], (nbColors - firstColSel) * sizeof(COLORINFO));
+
+ //Align non selected left part
+ colors[firstColSel].nbChars -= (firstTot - firstX);
+
+ firstColSel++;
+ memmove(&colors[firstColSel + 1], &colors[lastColSel], (nbColors - lastColSel + 1) * sizeof(COLORINFO));
+ nbColors -= (lastColSel - firstColSel - 1);
+ lastColSel -= (lastColSel - firstColSel - 1);
+
+ //Align non selected right part
+ colors[lastColSel].nbChars = lastRemain;
+
+ //Set selection
+ colors[firstColSel].fore = FORECOLOR(Cols_Selection);
+ colors[firstColSel].back = BACKCOLOR(Cols_Selection);
+ colors[firstColSel].nbChars = lastX - firstX;
+ }
+ }
+}
+
+//Mark Selected line
+void NEAR PASCAL MarkSelectedLine(
+ int view,
+ int line)
+{
+ int firstY,lastY;
+ int firstX,lastX;
+
+ GetBlockCoord(view, &firstX, &firstY, &lastX, &lastY);
+
+ if (line < firstY || line > lastY)
+ return;
+
+ if (line > firstY && line < lastY) {
+ nbColors = 0;
+ colors[0].nbChars = 2 * MAX_USER_LINE;
+ colors[0].fore = FORECOLOR(Cols_Selection);
+ colors[0].back = BACKCOLOR(Cols_Selection);
+ }
+ else {
+ if (line == firstY && line != lastY)
+ SelectLine(view, firstX, MAX_USER_LINE);
+ else {
+ if (line == lastY && line != firstY)
+ SelectLine(view, 0, lastX);
+ else {
+ if (firstX != lastX)
+ SelectLine(view, firstX, lastX);
+ }
+ }
+ }
+}
+
+void NEAR PASCAL PatchTabs(
+ int view)
+{
+ register int i = 0;
+ register int j = 0;
+ int len = pcl->Length - LHD;
+ LPSTR pc = pcl->Text;
+ uchar tabMark;
+
+ if (Views[view].charSet == OEM_CHARSET)
+ tabMark = 175;
+ else
+ tabMark = 187;
+ while (i < len) {
+ if (pc[i] == TAB) {
+ el[j] = tabMark;
+ j += tabSize - (j % tabSize);
+ }
+ else
+ j++;
+ i++;
+ }
+ Assert(j <= MAX_USER_LINE);
+}
+
+
+
+/*** WriteLine
+**
+** Synopsis:
+** void = WriteLine(view, line, hDC, X, Y, prevStatus)
+**
+** Entry:
+** view - View for which to display a line
+** line - line number in view to display
+** hDC - device context on which to display the line
+** X - X coordinate of line to display
+** Y - Y coordinate of line to display
+** prevStatus - The previous syntax parsing status
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function will cause a specified line to be displayed on the
+** screen. Any syntax coloring will be done as needed as well as
+** the foreground/background coloration needed for the sepcific window
+*/
+
+void NEAR PASCAL WriteLine(int view, int line, HDC hDC, int X, int Y, PRECT pRc, WORD prevStatus)
+{
+ register int i, rX;
+ register int total = 0;
+ NPVIEWREC v = &Views[view];
+ WORD curColor = Docs[v->Doc].docType;
+ int nb;
+ char elCopy[2 * MAX_USER_LINE + 1];
+ DWORD penPos = 0;
+ int penPosX = 0;
+
+ nbColors = 0;
+
+ rX = pRc->right; // get it into a register
+
+ Assert(v->Doc >= 0);
+
+ if (!MarkStatusLine(v->Doc, pcl->Status, prevStatus)) {
+
+ switch (Docs[v->Doc].language) {
+ case C_LANGUAGE:
+
+ if (syntaxColors) {
+ CSyntax(curColor, pcl->Status, prevStatus);
+ break;
+ }
+
+ //Fall Thru if false
+
+ case PASCAL_LANGUAGE:
+ default:
+ colors[0].nbChars = 2 * MAX_USER_LINE;
+ colors[0].fore = FORECOLOR(curColor);
+ colors[0].back = BACKCOLOR(curColor);
+ break;
+ }
+ }
+
+ if (v->BlockStatus)
+ {
+ MarkSelectedLine(view, line);
+ }
+
+
+ if (viewTabs) {
+ memmove(elCopy, el, 2 * MAX_USER_LINE);
+ PatchTabs(view);
+ }
+
+ //Optimize colors array
+
+ i = 0;
+ while (i < nbColors) {
+ if (colors[i].fore == colors[i + 1].fore && colors[i].back == colors[i + 1].back) {
+ colors[i + 1].nbChars += colors[i].nbChars;
+ memmove(&colors[i], &colors[i + 1], (nbColors - i) * sizeof(COLORINFO));
+ nbColors--;
+ }
+ else
+ i++;
+ }
+
+ rX -= X;
+ MoveToX(hDC, X, Y, NULL);
+ for (i = 0; i <= nbColors; i++) {
+ if (penPosX < rX)
+ {
+ SetTextColor(hDC, colors[i].fore);
+ SetBkColor(hDC, colors[i].back);
+ nb = colors[i].nbChars;
+
+ TextOut(hDC, X, Y, (LPSTR)(el + total), nb); // Don't clear the backgroud beforehand
+ }
+ else
+ {
+ break;
+ }
+
+
+#ifdef WIN32
+ {
+ POINT lppoint;
+ GetCurrentPositionEx(hDC, &lppoint);
+ penPosX = lppoint.x;
+ }
+
+#else
+ penPos = GetCurrentPosition(hDC);
+ penPosX = LOWORD(penPos);
+#endif
+ total += nb;
+ }
+
+ if (viewTabs)
+ memmove(el, elCopy, elLen);
+} /* NWriteLine() */
+
+
+
+void FAR PASCAL
+PaintText(
+ int view,
+ HDC hDC,
+ PRECT rcl
+ )
+/*++
+
+Routine Description:
+
+ This routine is called in response to a WM_PAINT message to
+ do the transfer from the edit buffer to the display of data
+
+Arguments:
+
+ view - Supplies the view index to be painted
+ hDC - Supplies the device context handle to paint in
+ rcl - Supplies pointer the rectangle to be painted
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int xPos;
+ int yPos;
+ int first;
+ int last;
+ int stop;
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int Y;
+ int charHeight;
+ HFONT hOldFont;
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ WORD prevStatus;
+
+
+ Assert(v->Doc >= 0);
+
+
+ /*
+ * Select the current view Font
+ */
+
+ Dbg(hOldFont = SelectObject(hDC, v->font));
+
+ SetTextAlign(hDC, TA_UPDATECP);
+
+ /*
+ * Get scroll-bars position
+ */
+
+ xPos = -GetScrollPos(hwnd, SB_HORZ) * v->maxCharWidth;
+ yPos = v->iYTop;
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+
+ charHeight = v->charHeight;
+
+ /*
+ * Calc first & last line to display
+ */
+
+ first = yPos + rcl->top / charHeight;
+ last = yPos + (rcl->bottom - 1) / charHeight;
+
+ Y = rcl->top - (rcl->top % charHeight);
+
+ stop = Docs[v->Doc].NbLines;
+ Assert (stop != 0);
+
+ if (first < stop) {
+
+ Assert(first < Docs[v->Doc].NbLines);
+ if (first == 0) {
+ prevStatus = 0;
+ if (!FirstLine(v->Doc, &pl, &first, &pb)) {
+ return;
+ }
+ } else {
+ first--;
+ if (!FirstLine(v->Doc, &pl, &first, &pb)) {
+ return;
+ }
+ prevStatus = pl->Status;
+ if (!NextLine(v->Doc, &pl, &first, &pb))
+ return;
+ }
+
+ while (TRUE) {
+
+ WriteLine(view, first - 1, hDC, xPos, Y, rcl, prevStatus);
+ Y += charHeight;
+ prevStatus = pl->Status;
+ if (first > last || first == stop)
+ break;
+ else
+ if (!NextLine(v->Doc, &pl, &first, &pb))
+ return;
+ }
+
+ CloseLine(v->Doc, &pl, first, &pb);
+ }
+
+ if (first <= last) {
+
+ HBRUSH hBrush = CreateSolidBrush(BACKCOLOR(Docs[v->Doc].docType));
+
+ if (hBrush) {
+ rcl->top = Y;
+ FillRect (hDC, rcl, hBrush);
+ DeleteObject(hBrush);
+ }
+ }
+
+ SelectObject(hDC, hOldFont);
+ return;
+} /* PaintText() */
+
+
+void FAR PASCAL
+VertScroll(
+ int view,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ This routine is called in response to a WM_VSCROLL message
+
+Arguments:
+
+ view - Supplies the view index to be scrolled
+ wParam - Supplies wParam message for WM_VSCROLL
+ lParam - Supplies lParam message for WM_VSCROLL
+
+Return Value:
+
+ None.
+
+--*/
+{
+ int vScrollInc;
+ int vScrollPos;
+ RECT rcl;
+ int lines;
+ int vWinLines;
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ int newY;
+
+ /*
+ * We should never get here if we are in a disassembly window.
+ * The message must be handled in the edit proc for disasm.
+ */
+
+ Assert(v->Doc >= 0);
+ Assert(Docs[v->Doc].docType != DISASM_WIN);
+ Assert(v->iYTop == -1);
+
+ /*
+ * Get info we need
+ */
+
+ vScrollPos = GetScrollPos(hwnd, SB_VERT);
+ lines = Docs[v->Doc].NbLines - 1;
+ GetClientRect(hwnd, &rcl);
+ vWinLines = max( 1, rcl.bottom / v->charHeight);
+
+ switch (LOWORD(wParam)) {
+
+ case SB_LINEUP:
+ vScrollInc = -1;
+ break;
+
+ case SB_LINEDOWN:
+ vScrollInc = 1;
+ break;
+
+ case SB_PAGEUP:
+ vScrollInc = -vWinLines;
+ break;
+
+ case SB_PAGEDOWN:
+ vScrollInc = vWinLines;
+ break;
+
+ case SB_THUMBTRACK:
+ vScrollInc = ((int)HIWORD(wParam)) - vScrollPos;
+ break;
+
+
+ case SB_THUMBPOSITION:
+#ifdef WIN32
+ vScrollInc = HIWORD(wParam) - vScrollPos;
+ Unreferenced( lParam );
+#else
+ vScrollInc = LOWORD(lParam) - vScrollPos;
+#endif
+ break;
+
+ default:
+ return;
+
+ }
+
+ newY = mini(lines, v->Y + vScrollInc);
+
+ if (vScrollInc < 0) {
+ vScrollInc = maxi(vScrollInc, -vScrollPos);
+ } else {
+ lines -=(vScrollPos + vWinLines);
+ if ((rcl.bottom + v->charHeight - 1) % v->charHeight) {
+ lines++;
+ }
+ vScrollInc = maxi(mini(vScrollInc, lines), 0);
+ }
+ vScrollPos += vScrollInc;
+
+ if (vScrollInc != 0) {
+
+ /*
+ * Set scroll-bar positions before refreshing the screen because
+ * we use the scroll-bar positions during the PAINT event
+ */
+
+ if (v->iYTop == -1) {
+ SetScrollPos(hwnd, SB_VERT, vScrollPos, TRUE);
+ } else {
+ v->iYTop = vScrollPos;
+ }
+
+ ScrollWindow(hwnd, 0, - v->charHeight * vScrollInc, NULL, NULL);
+ UpdateWindow(hwnd);
+
+ }
+
+ if (scrollOrigin & FROM_KEYBOARD) {
+ if (scrollOrigin & SELECTING) {
+ int OldYR;
+
+ if (!v->BlockStatus) {
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->BlockXR = v->X;
+ v->BlockYL = v->BlockYR = v->Y;
+ }
+ PosXY(view, v->X, newY, FALSE);
+ OldYR = v->BlockYR;
+ v->BlockXR = v->X;
+ v->BlockYR = v->Y;
+ InvalidateLines(view, mini(OldYR, v->BlockYR), maxi (OldYR, v->BlockYR), FALSE);
+ } else {
+ PosXY(view, v->X, newY, FALSE);
+ }
+ }
+#ifdef FE_IME
+ else {
+ // This is to change a position of IME conversion window
+ SetCaret(view, v->X, v->Y, Pos2Pix(view, v->X, v->Y));
+ }
+#endif
+ return;
+} /* VertScroll() */
+
+void FAR PASCAL
+HorzScroll(
+ int view,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ int hScrollInc;
+ int hScrollPos;
+ RECT rcl;
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ int newX = v->X;
+
+ // Get info we need
+
+ Assert(v->Doc >= 0);
+
+ hScrollPos = GetScrollPos(hwnd, SB_HORZ);
+ GetClientRect(hwnd, &rcl);
+
+ switch (LOWORD(wParam)) {
+
+ case SB_LINEUP:
+ hScrollInc = mini(-1, (-rcl.right / SCROLL_RATIO) / v->maxCharWidth);
+ break;
+
+ case SB_LINEDOWN:
+ hScrollInc = maxi(1, (rcl.right / SCROLL_RATIO) / v->maxCharWidth);
+ break;
+
+ case SB_PAGEUP:
+ hScrollInc = mini(-1, -rcl.right / v->maxCharWidth);
+ break;
+
+ case SB_PAGEDOWN:
+ hScrollInc = maxi(1, rcl.right / v->maxCharWidth);
+ break;
+
+ case SB_THUMBTRACK:
+ hScrollInc = ((int)HIWORD(wParam)) - hScrollPos;
+ break;
+
+
+ case SB_THUMBPOSITION:
+#ifdef WIN32
+ hScrollInc = HIWORD(wParam) - hScrollPos;
+ Unreferenced( lParam );
+#else
+ hScrollInc = LOWORD(lParam) - hScrollPos;
+#endif
+ break;
+
+ default:
+ hScrollInc = 0;
+ }
+
+ if (hScrollInc = maxi(-hScrollPos, mini(hScrollInc, MAX_USER_LINE - hScrollPos)))
+ {
+ int XC, XX;
+
+ XC = hScrollPos * v->maxCharWidth;
+ XX = Pos2Pix(view, newX, v->Y);
+ if (XX < XC) {
+ newX = Pix2Pos(view, XC, v->Y);
+ XX = Pos2Pix(view, newX, v->Y);
+ if (XX < XC)
+ newX++;
+ }
+ else
+ if (XX >= (XC + rcl.right - (v->maxCharWidth + v->maxCharWidth))) {
+ newX = Pix2Pos (view, XC + rcl.right - (v->maxCharWidth + v->maxCharWidth), v->Y);
+ XX = Pos2Pix(view, newX, v->Y);
+ if (XX >= (XC + rcl.right - (v->maxCharWidth + v->maxCharWidth)))
+ newX--;
+ }
+ Assert(v->Y < Docs[v->Doc].NbLines);
+
+ //Set scroll-bar positions before refreshing the screen
+ //we use the scroll-bar positions during the PAINT event
+ if (newX < MAX_USER_LINE
+ || (newX >= MAX_USER_LINE && hScrollInc < 0)) {
+ hScrollPos += hScrollInc;
+ SetScrollPos(hwnd, SB_HORZ, hScrollPos, TRUE);
+ ScrollWindow(hwnd, -v->maxCharWidth * hScrollInc, 0, NULL, NULL);
+ UpdateWindow(hwnd);
+
+ }
+
+#ifdef FE_IME
+ // This is to change a position of IME conversion window
+ SetCaret(view, v->X, v->Y, Pos2Pix(view, v->X, v->Y));
+#endif
+ }
+}
+
+void NEAR PASCAL SelPosXY(
+ int view,
+ int X,
+ int Y)
+{
+ int OldYR;
+ NPVIEWREC v = &Views[view];
+
+ Assert(v->Doc >= 0);
+
+ if (GetCapture() == v->hwndClient)
+ return;
+
+ //Normalize
+ Assert(Y <= Docs[v->Doc].NbLines - 1);
+ if (X < 0)
+ X = 0;
+ if (X > MAX_USER_LINE)
+ X = MAX_USER_LINE;
+ if (Y < 0)
+ Y = 0;
+
+ if (!v->BlockStatus) {
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->BlockXR = v->X;
+ v->BlockYL = v->BlockYR = v->Y;
+ }
+
+ PosXY(view, X, Y, FALSE);
+ OldYR = v->BlockYR;
+ v->BlockXR = v->X;
+ v->BlockYR = v->Y;
+
+ InvalidateLines(view, mini(OldYR, v->BlockYR), maxi (OldYR, v->BlockYR), FALSE);
+}
+
+//Return length of line
+int FAR PASCAL GetLineLength(
+ int view,
+ BOOL skipBlanks,
+ int line)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ register int X;
+ NPVIEWREC v = &Views[view];
+
+ Assert(v->Doc >= 0);
+
+ if (!FirstLine(v->Doc, &pl, &line, &pb))
+ return 0;
+ CloseLine (v->Doc, &pl, line, &pb);
+ X = elLen;
+#ifdef DBCS
+ if (skipBlanks) {
+ register int i;
+
+ X = 0;
+ for (i = 0 ; i < elLen ; i++) {
+ if (IsDBCSLeadByte(el[i]) && i+1 < elLen) {
+ i++;
+ X = i+1;
+ } else if (' ' != el[i]) {
+ X = i+1;
+ }
+ }
+ }
+#else // !DBCS
+ if (skipBlanks)
+ while (X > 0 && el[X - 1] == ' ')
+ X--;
+#endif
+ return X;
+}
+
+
+//Move cursor to prev word
+void NEAR PASCAL MoveLeftWord(
+ int view,
+ BOOL Sel,
+ int posX,
+ int posY)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int x;
+ int y;
+ NPVIEWREC v = &Views[view];
+
+ y = posY;
+
+ Assert(v->Doc >= 0);
+ Assert(y < Docs[v->Doc].NbLines);
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return;
+
+ //y has been incremented. Adjust y to its previous position
+ y--;
+
+ x = mini(posX, elLen);
+ do {
+ while (x == 0) {
+ if (y == 0)
+
+ //Top of file
+ goto done;
+
+ else {
+
+ //FirstLine has incremented y. As we have decremented
+ //adjust it to its expected position before calling
+ //CloseLine
+ y++;
+ CloseLine(v->Doc, &pl, y, &pb);
+
+ //Decrements twice because we want to go to the previous line
+ y-= 2;
+
+ Assert(y < Docs[v->Doc].NbLines);
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return;
+
+ y--; // adjust y to the right value
+ x = elLen;
+ }
+ }
+#ifdef DBCS
+ {
+ int iLeftChar = -1;
+ int i;
+
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ iLeftChar = i;
+ i++;
+ } else if (CHARINKANASET(el[i])) {
+ iLeftChar = i;
+ } else if (CHARINALPHASET(el[i])) {
+ iLeftChar = i;
+ }
+ }
+ x = (-1 != iLeftChar) ? iLeftChar : 0;
+ }
+#else // !DBCS
+
+ //Now x is different from zero. Skip till we find a valid
+ //word character
+ while (x > 0 && !(CHARINALPHASET(el[x - 1])))
+ x--;
+#endif // !DBCS
+
+ //Now either x is equal to zero or set after a word character
+ } while (x == 0);
+
+#ifdef DBCS
+ {
+ int iLeftChar = -1;
+ int i;
+
+ //make sure if the cursor isn't on middle of DBCS char
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ if (x == i + 1) {
+ x = i;
+ break;
+ }
+ i++;
+ }
+ }
+ for (i = 0 ; i <= x ; i++) {
+ if (IsDBCSLeadByte(el[i])) {
+ if (IsDBCSLeadByte(el[x])) {
+#ifdef DBCS_WORD_MULTI
+ if (-1 == iLeftChar) {
+ iLeftChar = i;
+ }
+#else
+ // Suppose one DBCS char is one word.
+ iLeftChar = i;
+#endif // DBCS_WORD_MULTI
+ } else {
+ iLeftChar = -1;
+ }
+ i++;
+ } else if (CHARINKANASET(el[i])) {
+ if (CHARINKANASET(el[x])) {
+ if (-1 == iLeftChar) {
+ iLeftChar = i;
+ }
+ } else {
+ iLeftChar = -1;
+ }
+ } else if (CHARINALPHASET(el[i])) {
+ if (CHARINALPHASET(el[x])) {
+ if (-1 == iLeftChar) {
+ iLeftChar = i;
+ }
+ } else {
+ iLeftChar = -1;
+ }
+ } else {
+ iLeftChar = -1;
+ }
+ }
+ x = (-1 != iLeftChar) ? iLeftChar : 0;
+ }
+#else // !DBCS
+ do {
+ x--;
+ } while (x >= 0 && CHARINALPHASET(el[x]));
+
+ //Now x is less than 0 or set to a none word character
+ x++;
+#endif
+
+done:
+ y++;
+ CloseLine(v->Doc, &pl, y, &pb);
+ y--;
+
+ if (Sel)
+ SelPosXY(view, x, y);
+ else
+ PosXY(view, x, y, FALSE);
+}
+
+
+void NEAR PASCAL MoveRightWord(
+ int view,
+ BOOL Sel,
+ int posX,
+ int posY)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int x;
+ int y;
+ NPVIEWREC v = &Views[view];
+
+#ifdef DBCS // ***************************************************************
+ BYTE chWord;
+
+ y = posY;
+
+ Assert (v->Doc >= 0);
+ Assert (y < Docs[v->Doc].NbLines);
+
+ if (!FirstLine(v->Doc, &pl, &y, &pb)) {
+ return;
+ }
+ CloseLine(v->Doc, &pl, y, &pb);
+ y--;
+
+ posX = mini(posX, elLen);
+
+ //make sure if the cursor isn't on middle of DBCS char
+ for (x = 0 ; x < posX ; x++) {
+ if (IsDBCSLeadByte((BYTE)el[x])) {
+ if (posX == x + 1) {
+ break;
+ }
+ x++;
+ }
+ }
+
+ if (CHARINWORDCHAR(el[x])) {
+ chWord = el[x];
+ } else {
+
+ /****************************/
+ /* skip non-word characters */
+ /****************************/
+
+ while (y < Docs[v->Doc].NbLines) {
+ if (!FirstLine(v->Doc, &pl, &y, &pb)) {
+ return;
+ }
+ CloseLine(v->Doc, &pl, y, &pb);
+ y--;
+
+ while (x < elLen) {
+ if (CHARINWORDCHAR(el[x])) {
+ chWord = el[x];
+ break;
+ }
+ x++;
+ }
+
+ if (x < elLen) {
+ break;
+ }
+ x = 0;
+ y++;
+ }
+
+ if (y >= (Docs[v->Doc].NbLines)) {
+ PosXY(view, elLen, y - 1, FALSE);
+ return;
+ }
+ if (!Sel) {
+ PosXY(view, x, y, FALSE);
+ return;
+ }
+ }
+
+ /**************************/
+ /* search the end of word */
+ /**************************/
+
+ while (x < elLen) {
+#ifdef DBCS_WORD_MULTI
+#else
+ if (IsDBCSLeadByte(chWord)) {
+ // Suppose one DBCS char is one word.
+ x += 2;
+ break;
+ }
+#endif
+ if (IsDBCSLeadByte(el[x])) {
+ if (!IsDBCSLeadByte(chWord)) {
+ break;
+ }
+ x += 2;
+ } else if (CHARINKANASET(el[x])) {
+ if (!CHARINKANASET(chWord)) {
+ break;
+ }
+ x++;
+ } else if (CHARINALPHASET(el[x])) {
+ if (!CHARINALPHASET(chWord)) {
+ break;
+ }
+ x++;
+ } else {
+ break;
+ }
+ }
+
+ if (Sel) {
+ SelPosXY(view, x, y);
+ return;
+ }
+
+ /*******************************/
+ /* search the top of next word */
+ /*******************************/
+
+ while (y < Docs[v->Doc].NbLines) {
+ if (!FirstLine(v->Doc, &pl, &y, &pb)) {
+ return;
+ }
+ CloseLine(v->Doc, &pl, y, &pb);
+ y--;
+
+ while (x < elLen) {
+ if (CHARINWORDCHAR(el[x])) {
+ break;
+ }
+ x++;
+ }
+
+ if (x < elLen) {
+ break;
+ }
+ x = 0;
+ y++;
+ }
+ if (y >= (Docs[v->Doc].NbLines)) {
+ PosXY(view, elLen, y - 1, FALSE);
+ } else {
+ PosXY(view, x, y, FALSE);
+ }
+ return;
+
+#else // !DBCS *************************************************************
+
+ y = posY;
+
+ Assert (v->Doc >= 0);
+ Assert (y < Docs[v->Doc].NbLines);
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return;
+
+ //y has been incremented. Adjust y to its previous position
+ y--;
+
+ x = mini(posX, elLen);
+
+ while (TRUE) {
+ if (x < elLen && CHARINALPHASET(el[x]))
+
+ if (Sel)
+ goto done;
+ else
+ do {
+ x++;
+ } while (x < elLen && CHARINALPHASET(el[x]));
+
+ if (x >= elLen)
+ if (y < (Docs[v->Doc].NbLines-1)) {
+ x = 0;
+ y++;
+
+ //FirstLine has incremented y. As we have decremented
+ //adjust it to its expected position before calling
+ //CloseLine
+ CloseLine(v->Doc, &pl, y, &pb);
+
+ Assert (y < Docs[v->Doc].NbLines);
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return;
+ y--;
+
+ if (x >= elLen || !CHARINALPHASET(el[x]))
+ continue;
+ else
+ goto done;
+ }
+ else {
+ PosXY(view, GetLineLength(view, TRUE, y), y, FALSE);
+ return;
+ }
+
+ do {
+ x++;
+ } while (x < elLen && !CHARINALPHASET(el[x]));
+
+ if (x < elLen)
+ goto done;
+ }
+done:
+ if (Sel) {
+ while (x < elLen && CHARINALPHASET(el[x]))
+ x++;
+ SelPosXY(view, x,y);
+ }
+ else
+ PosXY(view, x,y, FALSE);
+ y++;
+ CloseLine(v->Doc, &pl, y, &pb);
+#endif // !DBCS end *********************************************************
+}
+
+void FAR PASCAL ClearSelection(int view)
+{
+ NPVIEWREC v = &Views[view];
+
+ Assert(v->Doc >= 0);
+ if (v->BlockStatus)
+ {
+ v->BlockStatus = FALSE;
+ InvalidateLines(view, mini(v->BlockYL, v->BlockYR), maxi(v->BlockYL, v->BlockYR), FALSE);
+ }
+}
+
+
+void FAR PASCAL
+MouseMove(
+ int view,
+ WPARAM wParam,
+ int X,
+ int Y
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called in response to a mouse move message.
+
+Arguments:
+
+ view - Supplies the view index for the mouse move
+ wParam - Supplies wParam for the WM_MOUSEMOVE
+ X - Supplies the X location of the ouse (LOWORD(lParam))
+ Y - Supplies the Y location of the ouse (HIWORD(lParam))
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ int yPos = v->iYTop;
+
+ Assert(v->Doc >= 0);
+
+ Unused(wParam);
+
+ if (GetCapture() == hwnd) {
+
+ RECT rcl;
+ int OldYR;
+
+ GetClientRect(hwnd, &rcl);
+ if (X < 0) {
+ X = 0;
+ } else if (X >= rcl.right) {
+ X = rcl.right - 1;
+ }
+
+ if (Y < 0) {
+ Y = 0;
+ } else if (Y >= rcl.bottom) {
+ Y = rcl.bottom - 1;
+ }
+
+ if (yPos == -1) {
+ yPos = GetScrollPos( hwnd, SB_VERT);
+ }
+ Y = mini(yPos + Y / v->charHeight, Docs[v->Doc].NbLines - 1);
+ X = mini(Pix2Pos(view,
+ GetScrollPos(hwnd, SB_HORZ) * v->maxCharWidth + X, Y),
+ MAX_USER_LINE);
+ X = AdjustPosX(X, FALSE);
+ OldYR = v->BlockYR;
+ v->BlockXR = X;
+ v->BlockYR = Y;
+ PosXY(view, X, Y, FALSE);
+ InvalidateLines(view, mini(OldYR, v->BlockYR), maxi(OldYR, v->BlockYR), FALSE);
+ }
+ return;
+} /* MouseMove() */
+
+void FAR PASCAL TimeOut(
+ int view)
+{
+ POINT point;
+ RECT rcl;
+ BOOL ok1,ok2;
+ int scrl;
+ HWND hwnd = Views[view].hwndClient;
+
+ GetCursorPos (&point);
+ ScreenToClient (hwnd, &point);
+
+ GetClientRect(hwnd, &rcl);
+
+ ok1 = ok2 = TRUE;
+ if ((point.x < 0) && ((scrl = GetScrollPos(hwnd, SB_VERT)) > 0))
+ SendMessage(hwnd, WM_HSCROLL, SB_LINEUP, 0L);
+ else
+ if (point.x >= rcl.right)
+ SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0L);
+ else
+ ok1 = FALSE;
+
+ if ((point.y < 0) && ((scrl = GetScrollPos(hwnd, SB_VERT)) > 0))
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0L);
+ else
+ if (point.y >= rcl.bottom)
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0L);
+ else
+ ok2 = FALSE;
+
+ if (ok1 || ok2)
+ MouseMove(view, 0, point.x, point.y);
+}
+
+void NEAR PASCAL SortBlock(
+ int view)
+{
+ NPVIEWREC v = &Views[view];
+
+ Assert(v->Doc >= 0);
+
+ if ((v->BlockYL > v->BlockYR)
+ || (v->BlockYL == v->BlockYR && v->BlockXL > v->BlockXR)) {
+
+ int xx = v->BlockXR , yy = v->BlockYR;
+
+ v->BlockXR = v->BlockXL;
+ v->BlockYR = v->BlockYL;
+ v->BlockXL = xx;
+ v->BlockYL = yy;
+
+ }
+}
+
+
+void FAR PASCAL
+ButtonDown(
+ int view,
+ WPARAM wParam,
+ int X,
+ int Y
+ )
+/*++
+
+Routine Description:
+
+ This routine is called in response to a WM_LBUTTON message.
+
+ We capture the mouse and setup a timer to send us regular messages
+ so that we can still do page downs even if the mouse does not move.
+ This is a normal windows program technique.
+
+Arguments:
+
+ view - Supplies the view index for the window
+ wParam - Supplies the wParam for the WM_LBUTTON message
+ X - Supplies the X position of the mouse
+ Y - Supplies the Y position of the mouse
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ RECT rcl;
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ int yPos = v->iYTop;
+
+ Assert(v->Doc >= 0);
+
+ GetClientRect(hwnd, &rcl);
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+
+ Y = mini(yPos + Y / v->charHeight,
+ Docs[v->Doc].NbLines - 1);
+ X = mini(Pix2Pos(view, GetScrollPos(hwnd, SB_HORZ) * v->maxCharWidth + X,
+ Y), MAX_USER_LINE);
+
+ X = AdjustPosX(X, FALSE);
+
+ if (wParam & MK_SHIFT) {
+ if (v->BlockStatus) {
+ SortBlock(view);
+ InvalidateLines(view, v->BlockYL, v->BlockYR, FALSE);
+ if ((Y > v->BlockYL) || (Y == v->BlockYL && X > v->BlockXL)) {
+ v->BlockXR = X;
+ v->BlockYR = Y;
+ } else {
+ v->BlockXL = X;
+ v->BlockYL = Y;
+ }
+ } else {
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->X;
+ v->BlockYL = v->Y;
+ v->BlockXR = X;
+ v->BlockYR = Y;
+ SortBlock(view);
+ }
+
+ InvalidateLines(view, v->BlockYL, v->BlockYR, FALSE);
+ } else {
+ ClearSelection(view);
+ v->BlockStatus = TRUE;
+ v->BlockXL = X;
+ v->BlockYL = Y;
+ v->BlockXR = X;
+ v->BlockYR = Y;
+ }
+
+ SetCaret(view, X, Y, -1);
+ SetTimer(hwnd, 100, 50, (TIMERPROC)NULL);
+ SetCursor(LoadCursor(NULL, IDC_IBEAM));
+ SetCapture(hwnd);
+
+ return;
+} /* ButtonDown() */
+
+
+void FAR PASCAL
+ButtonUp(
+ int view,
+ WPARAM wParam,
+ int X,
+ int Y
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called in response to a WM_LBUTTONUP message.
+
+ It will clean up what ever was done in ButtonDown about
+ capturing the cursor.
+
+Arguments:
+
+ view - Supplies the index to the view of the current window
+ wParam - Supplies the wParam for the message
+ X - Supplies the X position of the message
+ Y - Supplies the Y position of the messagen
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ int yPos = v->iYTop;
+
+ Unused(wParam);
+
+ Assert(v->Doc >= 0);
+
+ if (GetCapture() == hwnd) {
+
+ RECT rcl;
+
+ GetClientRect(hwnd, &rcl);
+ if (X < 0) {
+ X = 0;
+ } else if (X >= rcl.right) {
+ X = rcl.right-1;
+ }
+
+ if (Y < 0) {
+ Y = 0;
+ } else if (Y >= rcl.bottom) {
+ Y = rcl.bottom-1;
+ }
+
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+
+ Y = mini(yPos + Y / v->charHeight, Docs[v->Doc].NbLines - 1);
+ X = mini(Pix2Pos(view,
+ GetScrollPos(hwnd, SB_HORZ) * v->maxCharWidth + X,
+ Y), MAX_USER_LINE);
+ X = AdjustPosX(X, FALSE);
+
+ SortBlock(view);
+
+ if ((Y > v->BlockYL) || (Y == v->BlockYL && X > v->BlockXL)) {
+ v->BlockXR = X;
+ v->BlockYR = Y;
+ } else {
+ v->BlockXL = X;
+ v->BlockYL = Y;
+ }
+
+ InvalidateLines(view, v->BlockYL, v->BlockYR, FALSE);
+
+ KillTimer(hwnd, 100);
+ if (v->BlockXL == v->BlockXR && v->BlockYL == v->BlockYR) {
+ v->BlockStatus = FALSE;
+ }
+ PosXY(view, X, Y, FALSE);
+ ReleaseCapture();
+ }
+
+ return;
+} /* ButtonUp() */
+
+BOOL FAR PASCAL GetSelectedText(
+ int view,
+ BOOL *lookAround,
+ LPSTR pText,
+ int maxSize,
+ LPINT leftCol,
+ LPINT rightCol)
+{
+
+ NPVIEWREC v = &Views[view];
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int XL,XR;
+ int YL,YR;
+
+ Assert(v->Doc >= 0);
+
+ if (!v->BlockStatus)
+ return FALSE;
+
+ GetBlockCoord(view, &XL, &YL, &XR, &YR);
+
+ //If selection is on 1 line, returns all selection
+ if (YL == YR) {
+ if (!FirstLine(v->Doc, &pl, &YL, &pb))
+ goto err;
+ XR = mini(elLen, XR);
+
+ maxSize = mini(maxSize, XR - XL);
+ if (maxSize > 0) {
+ _fmemmove(pText, (LPSTR)(el + XL), maxSize);
+ pText[maxSize] = '\0';
+ }
+ if (leftCol)
+ *leftCol = XL;
+ if (rightCol)
+ *rightCol = XR;
+
+ CloseLine (v->Doc, &pl, YL, &pb);
+ }
+ else {
+
+ //Multiline selection, set line to line where cursor is
+ if (v->Y != YL)
+ YL = YR;
+
+ //Return word at or nearest to cursor
+ return GetWordAtXY(view, v->X, YL, FALSE, lookAround, TRUE,
+ (LPSTR)pText, maxSize, leftCol, rightCol);
+ }
+ return TRUE;
+
+ err : {
+ Assert(FALSE);
+ return FALSE;
+ }
+}
+
+/*** InsertStream
+**
+** Synopsis:
+** bool = InsertStream(view, x, y, size, Buf, destroyRedo)
+**
+** Entry:
+** view - which view to do the insert on
+** x - location to do the insert at
+** y - location to do the insert at
+** size - count of characters to insert
+** Buf - pointer to buffer to be inserted
+** destroyRedo - TRUE if no redo is allowed now
+**
+** Returns:
+** TRUE on success else FALSE
+**
+** Description:
+**
+*/
+
+BOOL
+PASCAL
+InsertStream (
+ int view,
+ int x,
+ int y,
+ int size,
+ LPSTR Buf,
+ BOOL destroyRedo
+ )
+{
+ NPVIEWREC v = &Views[view];
+ NPDOCREC d = &Docs[v->Doc];
+ BOOL lineAdded;
+ BOOL prevStopMark = stopMarkStatus;
+
+ Assert(v->Doc >= 0);
+ if (v->Doc < 0) {
+ return FALSE;
+ }
+
+ //Destroy Redo Buffer if we start re-editing in a middle of a
+ //undo/redo session
+
+ if (destroyRedo)
+ DestroyRecBuf(v->Doc, REC_REDO);
+
+ if (v->BlockStatus) {
+ int XR, YR;
+
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that records have no stop marks after
+ //this record
+
+ stopMarkStatus = NEXT_HAS_NO_STOP;
+
+ GetBlockCoord (view, &(v->X), &(v->Y), &XR, &YR);
+ DeleteStream(view, v->X, v->Y, XR, YR, FALSE);
+ } else {
+ v->X = x;
+ v->Y = y;
+ }
+
+ //Insert characters
+
+ if (InsertBlock(v->Doc, v->X, v->Y, size, Buf)) {
+ lineAdded = (d->lineTop != d->lineBottom);
+ InvalidateLines(view, d->lineTop, d->lineBottom, lineAdded);
+ if (lineAdded)
+ SetVerticalScrollBar(view, TRUE);
+
+ //Put undo/redo engine back in normal state
+
+ if (prevStopMark == HAS_STOP)
+ stopMarkStatus = HAS_STOP;
+
+ return TRUE;
+ } else
+ return FALSE;
+} /* InsertStream() */
+
+BOOL FAR PASCAL ReplaceChar(
+ int view,
+ int x,
+ int y,
+ int ch,
+ BOOL destroyRedo)
+{
+
+ NPVIEWREC v = &Views[view];
+ BOOL prevStopMark = stopMarkStatus;
+
+ Assert(v->Doc >= 0);
+
+ //Destroy Redo Buffer if we start re-editing in a middle of a
+ //undo/redo session
+ if (destroyRedo)
+ DestroyRecBuf(v->Doc, REC_REDO);
+
+ if (v->BlockStatus) {
+ int XR, YR;
+
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that records have no stop marks after
+ //this record
+ stopMarkStatus = NEXT_HAS_NO_STOP;
+
+ GetBlockCoord (view, &(v->X), &(v->Y), &XR, &YR);
+ DeleteStream(view, v->X, v->Y, XR, YR, FALSE);
+ }
+ else {
+ v->X = x;
+ v->Y = y;
+ }
+
+ //Replace character and update line
+ if (ReplaceCharInBlock(v->Doc, v->X, v->Y, ch)) {
+ InvalidateLines(view, Docs[v->Doc].lineTop, Docs[v->Doc].lineBottom, FALSE);
+
+ //Put undo/redo engine back in normal state
+ if (prevStopMark == HAS_STOP)
+ stopMarkStatus = HAS_STOP;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+//Delete stream
+BOOL FAR PASCAL
+DeleteStream(
+ int view,
+ int XL,
+ int YL,
+ int XR,
+ int YR,
+ BOOL destroyRedo
+ )
+{
+ NPVIEWREC v = &Views[view];
+
+ Assert(v->Doc >= 0);
+
+ //Destroy Redo Buffer if we start re-editing in a middle of a
+ //undo/redo session
+ if (destroyRedo) {
+ DestroyRecBuf(v->Doc, REC_REDO);
+ }
+
+ //Delete block
+ if (!DeleteBlock(v->Doc, XL, YL, XR, YR)) {
+
+ return FALSE;
+
+ } else {
+
+ InvalidateLines(view,
+ Docs[v->Doc].lineTop,
+ Docs[v->Doc].lineBottom,
+ YL != YR);
+
+ if (YL != YR) {
+ SetVerticalScrollBar(view, TRUE);
+ }
+
+ v->BlockStatus = FALSE;
+
+ return TRUE;
+ }
+}
+
+//Delete all stream
+BOOL FAR PASCAL
+DeleteAllStream(
+ int view,
+ BOOL destroyRedo
+ )
+{
+ return DeleteStream(view,
+ 0,
+ 0,
+ MAX_USER_LINE,
+ Docs[Views[view].Doc].NbLines - 1,
+ destroyRedo);
+}
+
+//Paste stream
+BOOL FAR PASCAL
+PasteStream (
+ int view,
+ int XL,
+ int YL,
+ int XR,
+ int YR
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+ long size, sz;
+ LPSTR p;
+ HANDLE hData;
+ NPVIEWREC v = &Views[view];
+#ifdef DEBUGGING
+ LPSTR p1;
+#endif
+
+ Assert(v->Doc >= 0);
+ Assert(YL <= YR && YR < Docs[v->Doc].NbLines);
+
+ //Get information to compute size of clipboard buffer
+ y = YL;
+ if (!FirstLine(v->Doc, &pl, &y, &pb)) {
+ return FALSE;
+ }
+ XL = AlignToTabs(XL, pl->Length - LHD, (LPSTR)pl->Text);
+
+ if (YL == YR) {
+ if (XL >= (pl->Length - LHD)) {
+ size = 0;
+ } else {
+ XR = AlignToTabs(XR, pl->Length - LHD, (LPSTR)pl->Text);
+ size = mini(XR, (pl->Length - LHD)) - XL;
+ }
+ } else {
+
+ //Compute size of first line
+ size = pl->Length - LHD - mini(XL, (pl->Length - LHD));
+
+ //Compute size of middle lines
+ while (y < YR) {
+ if (!NextLine(v->Doc, &pl, &y, &pb)) {
+ return FALSE;
+ }
+ size += 2 + (pl->Length - LHD);
+ }
+
+ //Compute size of last line
+ if (!NextLine(v->Doc, &pl, &y, &pb)){
+ return FALSE;
+ }
+ XR = AlignToTabs(XR, pl->Length - LHD, (LPSTR)pl->Text);
+ size += 2 + mini((pl->Length - LHD), XR);
+
+ }
+ CloseLine (v->Doc, &pl, y, &pb);
+
+ if (size >= MAX_CLIPBOARD_SIZE) {
+ ErrorBox(ERR_Clipboard_Overflow);
+ return FALSE;
+ }
+
+ Dbg(hData = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, size + 1));
+ if (!hData) {
+ return FALSE;
+ }
+
+ Dbg((p = GlobalLock (hData)) != NULL);
+
+ if (p == NULL) {
+ return FALSE;
+ }
+
+#ifdef DEBUGGING
+ p1 = p;
+#endif
+ y = YL;
+ if (!FirstLine(v->Doc, &pl, &y, &pb)) {
+ return FALSE;
+ }
+
+ if (YL == YR) {
+ if (XL >= (pl->Length - LHD)) {
+ sz = 0;
+ } else {
+ sz = mini(XR, (pl->Length - LHD)) - XL;
+ _fmemmove(p, (LPSTR)(pl->Text + XL), (unsigned)sz);
+ p += sz;
+ }
+ } else {
+
+ //Copy first line
+ sz = (pl->Length - LHD) - XL;
+ if (sz > 0) {
+ _fmemmove(p, (LPSTR)(pl->Text + XL), (unsigned)sz);
+ p += sz;
+ }
+
+ //Copy middle lines (if any)
+ while (y < YR) {
+ if (!NextLine(v->Doc, &pl, &y, &pb)){
+ return FALSE;
+ }
+
+ _fmemmove(p, (LPSTR)CrLf, 2);
+ p += 2;
+ _fmemmove(p, pl->Text, pl->Length - LHD);
+ p += pl->Length - LHD;
+ }
+
+ _fmemmove(p, (LPSTR)CrLf, 2);
+ p += 2;
+
+ //Copy last line
+ if (!NextLine(v->Doc, &pl, &y, &pb)){
+ return FALSE;
+ }
+ _fmemmove((LPSTR)szTmp, pl->Text, pl->Length - LHD);
+ szTmp[pl->Length - LHD] = '\0';
+ _fmemmove(p, pl->Text, mini((pl->Length - LHD), XR));
+ p += mini((pl->Length - LHD), XR);
+ }
+ *p = '\0';
+ CloseLine (v->Doc, &pl, y, &pb);
+
+#ifdef DEBUGGING
+ Assert(lstrlen(p1) == (int)size);
+#endif
+
+ DbgX(GlobalUnlock(hData) == 0);
+
+ if (OpenClipboard (/*GetDesktopWindow())*/ hwndFrame)) {
+ EmptyClipboard();
+ hData = SetClipboardData(CF_TEXT, hData);
+ CloseClipboard();
+ }
+}
+
+//Find matching {[( ... )]}
+void NEAR PASCAL FindMatching(
+ int view)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ NPVIEWREC v = &Views[view];
+ int y = v->Y;
+ char source, target, ch;
+ int k, level = 0;
+ BOOL found = FALSE, goDown;
+
+
+ Assert(v->Doc >= 0);
+
+ //Load line
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ goto err;
+
+ //See if X in range
+ if (v->X < elLen) {
+
+ source = el[v->X];
+
+ //See if char at cursor is in '{' '[' '(' '}' ']' ')'
+ switch (source) {
+ case '{':
+ target = '}';
+ goDown = TRUE;
+ break;
+ case '[':
+ target = ']';
+ goDown = TRUE;
+ break;
+ case '(':
+ target = ')';
+ goDown = TRUE;
+ break;
+ case '}':
+ target = '{';
+ goDown = FALSE;
+ break;
+ case ']':
+ target = '[';
+ goDown = FALSE;
+ break;
+ case ')':
+ target = '(';
+ goDown = FALSE;
+ break;
+
+ //No match char
+ default:
+ CloseLine(v->Doc, &pl, y, &pb);
+ MessageBeep(0);
+ return;
+ }
+
+
+ if (goDown) {
+
+ int n = y;
+ k = v->X + 1;
+
+ //Go down in text
+ while (n <= Docs[v->Doc].NbLines && !found) {
+
+ //Parse current line
+ while (k < elLen && !found) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(el[k]) && k+1 < elLen) {
+ k+=2;
+ continue;
+ }
+#endif
+ ch = el[k];
+ found = (ch == target && level == 0);
+ if (ch == source)
+ level++;
+ if (ch == target)
+ level--;
+ k++;
+ }
+
+ if (y < Docs[v->Doc].NbLines && !found) {
+ if (!NextLine(v->Doc, &pl, &y, &pb))
+ goto err;
+ k = 0;
+ }
+ n++;
+ }
+
+ k--;
+ }
+ else {
+
+ //Adjust y
+ y--;
+ k = v->X - 1;
+
+ //Go up in text
+ while (y >= 0 && !found) {
+
+ //Parse current line
+ while (k >= 0 && !found) {
+ ch = el[k];
+#ifdef DBCS
+ if (ch == source || ch == target) {
+ register int i;
+ BOOL bDBCS = FALSE;
+
+ for (i = 0 ; i <= k ; i++) {
+ if (IsDBCSLeadByte(el[i]) && i+1 < elLen) {
+ if (i+1 == k){
+ bDBCS = TRUE;
+ break;
+ }
+ }
+ }
+ if (bDBCS) {
+ k -= 2;
+ continue;
+ }
+ }
+#endif // DBCS
+ found = (ch == target && level == 0);
+ if (ch == source)
+ level++;
+ if (ch == target)
+ level--;
+ k--;
+ }
+
+ if (y > 0 && !found) {
+ if (!PreviousLine(v->Doc, &pl, y, &pb))
+ goto err;
+ k = elLen;
+ }
+ y--;
+ }
+ k++;
+
+ //Reajust y
+ y += 2;
+ }
+
+ }
+
+ if (found)
+ PosXY(view, k, y - 1, FALSE);
+ else
+ MessageBeep(0);
+ CloseLine(v->Doc, &pl, y, &pb);
+ return;
+
+ err: {
+ Assert(FALSE);
+ return;
+ }
+
+}
+
+// Get block coord
+void FAR PASCAL GetBlockCoord(
+ int view,
+ int *XL,
+ int *YL,
+ int *XR,
+ int *YR)
+{
+ NPVIEWREC v = &Views[view];
+
+ Assert(v->Doc >= 0);
+
+ if (v->BlockYL < v->BlockYR) {
+ *XL = v->BlockXL;
+ *XR = v->BlockXR;
+ *YL = v->BlockYL;
+ *YR = v->BlockYR;
+ }
+ else
+ if (v->BlockYL > v->BlockYR) {
+ *XL = v->BlockXR;
+ *XR = v->BlockXL;
+ *YL = v->BlockYR;
+ *YR = v->BlockYL;
+ }
+ else {
+ *XL = mini(v->BlockXL, v->BlockXR);
+ *XR = maxi(v->BlockXL, v->BlockXR);
+ *YL = *YR = v->BlockYL;
+ }
+}
+
+void FAR PASCAL
+DeleteKey(
+ int view)
+{
+ int XL,XR;
+ int YL,YR;
+ NPVIEWREC v = &Views[view];
+ BOOL fRet;
+
+ Assert(v->Doc >= 0);
+
+ GetBlockCoord (view, &XL, &YL, &XR, &YR);
+ if (v->BlockStatus && (XL != XR || YL != YR)) {
+ fRet = DeleteStream(view, XL, YL, XR, YR, TRUE);
+ } else {
+ XL = v->X;
+ YL = v->Y;
+
+ if (XL < GetLineLength(view, TRUE, YL)) {
+#ifdef DBCS
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+
+ if (!FirstLine(v->Doc, &pl, &YL, &pb)) {
+ return;
+ }
+ CloseLine(v->Doc, &pl, YL, &pb);
+ YL--;
+ if (IsDBCSLeadByte((BYTE)(el[XL]))) {
+ if (fRet = DeleteStream(view, XL, YL, XL + 2, YL, TRUE)) {
+ SetReplaceDBCSFlag(&Docs[v->Doc], FALSE);
+ }
+ } else
+#endif // DBCS
+ fRet = DeleteStream(view, XL, YL, XL + 1, YL, TRUE);
+ } else if (YL < (Docs[v->Doc].NbLines - 1)) {
+ fRet = DeleteStream(view, XL, YL, 0, YL + 1, TRUE);
+ }
+ }
+ if (fRet && (YL <= (Docs[v->Doc].NbLines - 1))) {
+ PosXY(view, XL, YL, FALSE);
+ }
+}
+
+/*** KeyDown
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+void FAR PASCAL
+KeyDown(
+ int view,
+ WPARAM wParam,
+ BOOL shiftDown,
+ BOOL ctrlDown
+ )
+/*++
+
+Routine Description:
+
+ This function is called in response to a WM_KEYDOWN message to
+ do processing of some key sequences for the editor.
+
+Arguments:
+
+ view - Supplies the view index of the current window
+ wParam - Supplies the wParam field for the WM_KEYDOWN message
+ shiftDown - Supplies TRUE if a shift key is presed
+ ctrlDown - Supplies TRUE if a control key is pressed
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int posX;
+ int posY;
+ int nLine;
+ NPVIEWREC v = &Views[view];
+ HWND hwnd = v->hwndClient;
+ int yPos;
+
+ Assert(v->Doc >= 0);
+
+ posX = v->X;
+ posY = v->Y;
+
+ switch (wParam) {
+
+ case VK_SHIFT:
+ case VK_CONTROL:
+ return;
+
+ case VK_LEFT:
+ if (shiftDown) {
+ if (ctrlDown)
+ MoveLeftWord(view, TRUE, posX, posY);
+ else
+ SelPosXY(view, posX - 1, posY);
+ goto end;
+ }
+ break;
+
+ case VK_RIGHT:
+ if (shiftDown) {
+ if (ctrlDown)
+ MoveRightWord(view, TRUE, posX, posY);
+ else
+ SelPosXY(view, posX + 1, posY);
+ goto end;
+ }
+ break;
+
+ case VK_UP:
+ if (shiftDown) {
+ SelPosXY(view, Pix2Pos(view, Pos2Pix(view, posX, posY), posY - 1),
+ posY - 1);
+ goto end;
+ }
+ break;
+
+ case VK_DOWN:
+ if (shiftDown) {
+ if ((posY + 1) < (Docs[v->Doc].NbLines)) {
+ SelPosXY(view, Pix2Pos(view, Pos2Pix(view, posX, posY), posY + 1),
+ posY + 1);
+ //goto end;
+ }
+ goto end;
+ }
+ break;
+
+ case VK_PRIOR:
+ if (shiftDown) {
+ scrollOrigin = FROM_KEYBOARD | SELECTING;
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0L);
+ scrollOrigin = FROM_MOUSE;
+ goto end;
+ }
+ break;
+
+ case VK_NEXT:
+
+ if (shiftDown) {
+ scrollOrigin = FROM_KEYBOARD | SELECTING;
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0L);
+ scrollOrigin = FROM_MOUSE;
+ goto end;
+ }
+ break;
+
+ case VK_HOME:
+ if (shiftDown) {
+ if (ctrlDown)
+ SelPosXY(view, 0, 0);
+ else {
+ int X = FirstNonBlank(v->Doc, posY);
+
+ if (posX != X)
+ SelPosXY(view, X, posY);
+ else
+ SelPosXY(view, 0, posY);
+ }
+ goto end;
+ }
+ break;
+
+ case VK_END:
+ if (shiftDown) {
+ if (ctrlDown)
+ SelPosXY(view,
+ GetLineLength(view, FALSE, Docs[v->Doc].NbLines - 1),
+ Docs[v->Doc].NbLines-1);
+ else
+ SelPosXY(view,
+ GetLineLength(view, TRUE, posY),
+ posY);
+ goto end;
+ }
+ break;
+
+ case VK_F1:
+ {
+ BOOL lookAround = TRUE;
+
+ if (GetCurrentText(curView, &lookAround, (LPSTR)szTmp,
+ MAX_USER_LINE, NULL, NULL)) {
+
+ Dbg(WinHelp(hwndFrame, szHelpFileName, HELP_PARTIALKEY,
+ (DWORD)(LPSTR)szTmp));
+
+
+ }
+ else
+ MessageBeep(0);
+ break;
+ }
+
+ case VK_F3:
+ if (ctrlDown) {
+ BOOL lookAround = TRUE;
+ BOOL error = FALSE;
+
+ if (GetCurrentText(curView, &lookAround,
+ (LPSTR)findReplace.findWhat,
+ MAX_USER_LINE, &frMem.leftCol,
+ &frMem.rightCol)) {
+
+ //Cursor is not on a word, so start search from cursor
+ if (lookAround)
+ frMem.leftCol = frMem.rightCol = v->X;
+
+ InsertInPickList(FIND_PICK);
+
+ //Give control to modeless dialog box if active
+
+ if (frMem.hDlgFindNextWnd) {
+ SetFocus(frMem.hDlgFindNextWnd);
+ SendMessage(frMem.hDlgFindNextWnd, WM_COMMAND, IDOK, 0L);
+ }
+ else if (frMem.hDlgConfirmWnd) {
+
+ SetFocus(frMem.hDlgConfirmWnd);
+ SendMessage(frMem.hDlgConfirmWnd, WM_COMMAND, ID_CONFIRM_FINDNEXT, 0L);
+ } else {
+ FindNext(v->Y, frMem.rightCol, v->BlockStatus, TRUE, TRUE);
+ }
+ } else if (StartDialog(DLG_FIND, DlgFind)) {
+ Find();
+ }
+ }
+ break;
+ }
+
+ switch (wParam) {
+
+ case VK_LEFT:
+ ClearSelection(view);
+ if (ctrlDown)
+ MoveLeftWord(view, FALSE, posX, posY);
+ else
+ PosXY(view, posX - 1, posY, FALSE);
+ goto end;
+
+ case VK_RIGHT:
+ ClearSelection(view);
+ if (ctrlDown)
+ MoveRightWord(view, FALSE, posX, posY);
+ else
+ PosXY(view, posX + 1, posY, FALSE);
+ goto end;
+
+ case VK_UP:
+ ClearSelection(view);
+ if (ctrlDown) {
+ int bottomLine;
+ RECT rc;
+ int yPos;
+
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0L);
+ GetClientRect(hwnd, &rc);
+ bottomLine = ((rc.bottom - 1) / v->charHeight);
+
+ yPos = v->iYTop;
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+ if (posY >= yPos + bottomLine) {
+ posY--;
+ }
+ PosXY(view, v->X, posY, FALSE);
+ } else {
+ PosXY(view, Pix2Pos(view, Pos2Pix(view, posX, posY), posY - 1),
+ posY - 1, FALSE);
+ }
+ goto end;
+
+ case VK_DOWN:
+ ClearSelection(view);
+ if (ctrlDown) {
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0L);
+ yPos = v->iYTop;
+ if (yPos == -1) {
+ yPos = GetScrollPos(hwnd, SB_VERT);
+ }
+ posY = maxi(yPos, posY);
+ PosXY(view, v->X, posY, FALSE);
+ } else if (posY < (Docs[v->Doc].NbLines-1)) {
+ PosXY(view, Pix2Pos(view, Pos2Pix(view, posX, posY), posY + 1),
+ posY + 1, FALSE);
+ }
+ goto end;
+
+ case VK_PRIOR:
+ ClearSelection(view);
+ if (ctrlDown) {
+ RECT rcl;
+
+ GetClientRect (hwnd, &rcl);
+ posX = Pix2Pos(view, Pos2Pix(view, posX, posY) - rcl.right, posY);
+ PosXY(view, posX, v->Y, FALSE);
+ } else {
+ scrollOrigin = FROM_KEYBOARD;
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0L);
+ scrollOrigin = FROM_MOUSE;
+ }
+ goto end;
+
+ case VK_NEXT:
+ ClearSelection(view);
+ if (ctrlDown) {
+ RECT rcl;
+
+ GetClientRect (hwnd, &rcl);
+ posX = Pix2Pos(view, Pos2Pix(view, posX, posY) + rcl.right, posY);
+ PosXY(view, posX, v->Y, FALSE);
+ } else {
+ scrollOrigin = FROM_KEYBOARD;
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0L);
+ scrollOrigin = FROM_MOUSE;
+ }
+ goto end;
+
+ case VK_HOME:
+ ClearSelection(view);
+ if (ctrlDown) {
+ PosXY(view, 0, 0, FALSE);
+ } else {
+ int X = FirstNonBlank(v->Doc, posY);
+
+ if (posX != X) {
+ PosXY(view, X, posY, FALSE);
+ } else {
+ PosXY(view, 0, posY, FALSE);
+ }
+ }
+ goto end;
+
+ case VK_END:
+ ClearSelection(view);
+
+ if (ctrlDown) {
+ PosXY(view,
+ GetLineLength(view, FALSE, Docs[v->Doc].NbLines - 1),
+ Docs[v->Doc].NbLines - 1, FALSE);
+ }
+ else
+ if (((nLine = GetLineLength(view, TRUE, posY)) == 1) && (Docs[Views[curView].Doc].docType == COMMAND_WIN)) {
+ PosXY(view, GetLineLength(view, TRUE, posY) + 1, posY, FALSE);
+ }
+ else {
+ PosXY(view, GetLineLength(view, TRUE, posY), posY, FALSE);
+ }
+ goto end;
+
+ case VK_RETURN:
+ {
+ BOOL overtype;
+ BOOL prevStopMark = stopMarkStatus;
+
+ //Ctrl+Return is like return when overtyping
+
+
+ overtype = status.overtype;
+ status.overtype = FALSE;
+
+
+ //Insert CR/LF at current cursor position if not Overtyping
+ //or if cursor beyond file when overtyping
+
+ if (( (status.overtype == FALSE) &&
+ (Docs[v->Doc].forcedOvertype == FALSE))
+ || ((Docs[v->Doc].docType == DOC_WIN)
+ && (posY == Docs[v->Doc].NbLines - 1)
+ && (posX >= GetLineLength(view, TRUE, posY))))
+ {
+ if (InsertStream(view, posX, posY, 2, (LPSTR)CrLf, TRUE)) {
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int i = 0;
+
+ //Restore cursor to initial Y position (if some text was selected)
+
+ posY = v->Y;
+
+ //Copy blank chars from previous line
+
+ if (!FirstLine(v->Doc, &pl, &posY, &pb)) {
+ return;
+ }
+
+ posX = 0;
+ while (i < pl->Length - LHD) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(pl->Text[i])) {
+ break;
+ } else
+#endif
+ if (pl->Text[i] == ' ') {
+ posX++;
+ } else if (pl->Text[i] == TAB) {
+ posX += (tabSize - posX % tabSize);
+ } else {
+ break;
+ }
+ i++;
+ }
+ CloseLine(v->Doc, &pl, posY, &pb);
+
+ //If line starts with blanks, pad blanks to autoindent newly inserted line
+
+ if (i > 0) {
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that this record have no stop marks
+
+ stopMarkStatus = HAS_NO_STOP;
+
+ InsertStream(view, 0, posY, i, (LPSTR)pl->Text, FALSE);
+
+ //Put undo/redo engine back in normal state
+
+ if (prevStopMark == HAS_STOP) {
+ stopMarkStatus = HAS_STOP;
+ }
+
+ }
+
+ //Only to avoid desynchonization between return key
+ //hold generating a bunch of vk_return and scroll bar
+ //messages processed less often
+
+ SetVerticalScrollBar(view, FALSE);
+
+ //Reposition cursor
+
+ PosXY(view, posX, posY, FALSE);
+ }
+ } else {
+ //Avoid to move cursor below last line when overtyping
+
+ if (++posY >= Docs[v->Doc].NbLines) {
+ goto enough;
+ }
+
+ //Reposition cursor at 1st char of next line
+
+ PosXY(view, FirstNonBlank(v->Doc, posY), posY, FALSE);
+
+ }
+
+ enough:
+ // Ctrl+Return reset real overtype status
+
+ status.overtype = overtype;
+
+ goto end;
+ }
+
+ case VK_DELETE:
+ DeleteKey(view);
+ goto end;
+
+ case VK_BACK:
+ {
+ int XL,XR;
+ int YL,YR;
+
+ GetBlockCoord(view, &XL, &YL, &XR, &YR);
+ if (v->BlockStatus && (XL != XR || YL != YR)) {
+ if (DeleteStream(view, XL, YL, XR, YR, TRUE)) {
+ PosXY(view, XL, YL, FALSE);
+ }
+ } else {
+ if (posX > 0) {
+
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+#ifdef DBCS
+ BOOL bDBCS;
+#endif
+
+ if (!FirstLine(v->Doc, &pl, &posY, &pb))
+ goto end;
+ posY--;
+ XL = AdjustPosX(posX - 1, FALSE);
+#ifdef DBCS
+ bDBCS = IsDBCSLeadByte((BYTE)(el[XL])) ? TRUE : FALSE;
+#endif
+ if (DeleteStream(view, posX - 1, posY, posX, posY, TRUE)) {
+#ifdef DBCS
+ if (bDBCS) {
+ SetReplaceDBCSFlag(&Docs[v->Doc], FALSE);
+ }
+#endif
+ PosXY(view, XL, posY, FALSE);
+ }
+ } else if (posY > 0) {
+
+ int X = GetLineLength(view, TRUE, posY - 1);
+
+ if (DeleteStream(view, X, posY - 1, posX, posY, TRUE)) {
+ PosXY(view, X, posY - 1, FALSE);
+ }
+ }
+ }
+ goto end;
+ }
+
+ case VK_TAB:
+ {
+ int NewX;
+ int XL,XR;
+ int YL,YR;
+ BOOL prevStopMark = stopMarkStatus;
+ int len;
+
+ //Do we have a selection ?
+
+ if (v->BlockStatus) {
+
+ int startY;
+
+ GetBlockCoord(view, &XL, &YL, &XR, &YR);
+ startY = YL;
+
+ //If selection is on one line only, it's a normal TAB
+
+ if (YL == YR && XR < MAX_USER_LINE)
+ goto normal;
+
+ //Otherwise, we shift selection
+
+ DestroyRecBuf(v->Doc, REC_REDO);
+
+ //If we are at col 0 of last line, exclude it
+
+ if (XR == 0)
+ YR--;
+
+ //Resize selection to include all the lines moved
+
+ v->BlockXL = 0;
+ v->BlockYL = startY;
+ v->BlockXR = MAX_USER_LINE;
+ v->BlockYR = YR;
+
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that records have no stop marks after
+ //this record
+
+ stopMarkStatus = NEXT_HAS_NO_STOP;
+
+ if (shiftDown) {
+
+ //Unindent lines selected
+
+ while (startY <= YR) {
+
+ if (!DeleteBlock(v->Doc, 0, startY,
+ mini((int)tabSize,
+ FirstNonBlank(v->Doc, startY)),
+ startY))
+ goto err;
+ startY++;
+ }
+ } else {
+
+ char tmp[MAX_TAB_WIDTH];
+
+ if (environParams.keepTabs) {
+ len = 1;
+ tmp[0] = TAB;
+ } else {
+ len = tabSize;
+ memset(tmp, ' ', len);
+ }
+
+ //Indent lines selected
+
+ while (startY <= YR) {
+ if (!InsertBlock(v->Doc, 0, startY, len, (LPSTR)tmp))
+ break;
+ startY++;
+ }
+ }
+
+ InvalidateLines(view, YL, YR, TRUE);
+
+ //Put undo/redo engine back in normal state
+
+ if (prevStopMark == HAS_STOP)
+ stopMarkStatus = HAS_STOP;
+ } else {
+
+ normal:
+
+ //Handle Shift Tab
+
+ if (shiftDown) {
+ if (posX > 0) {
+ ClearSelection(view);
+ PosXY(view, (posX - 1) - (posX - 1) % tabSize, posY, FALSE);
+ }
+ goto end;
+ }
+
+ if (v->BlockStatus) {
+
+ if (status.overtype)
+ ClearSelection(view);
+ else {
+
+ //More than 1 edit action for this, operation. Tell
+ //the undo/redo engine that records have no stop
+ //marks after this record
+
+ stopMarkStatus = NEXT_HAS_NO_STOP;
+
+ DeleteStream(view, XL, YL, XR, YR, TRUE);
+ posX = XL;
+ posY = YL;
+ }
+ }
+
+ //Compute new position
+
+ NewX = (posX - (posX % tabSize)) + tabSize;
+ if (NewX > MAX_USER_LINE)
+ NewX = MAX_USER_LINE;
+ if (environParams.keepTabs) {
+ len = 1;
+ szTmp[0] = TAB;
+ } else {
+ len = NewX - posX;
+ memset(szTmp, ' ', len);
+ }
+
+ if (NewX != posX) {
+
+ if (!status.overtype
+ && InsertStream(view, posX, posY, len, (LPSTR)szTmp, TRUE))
+ {
+ PosXY(view, NewX, posY, FALSE);
+ }
+ }
+
+ //Put undo/redo engine back in normal state
+
+ if (prevStopMark == HAS_STOP)
+ stopMarkStatus = HAS_STOP;
+ }
+ }
+ }
+
+
+ //Exit without clearing possible multikey
+
+ return;
+
+ err:
+ {
+ Assert(FALSE);
+ return;
+ }
+
+ //If a multikey was started, cancel it
+
+ end:
+ {
+ StatusMultiKey(FALSE);
+ }
+ return;
+} /* KeyDown() */
+
+
+/*** PressChar
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+//A key has being pressed and has been translated to a valid character**
+*/
+
+
+
+void FAR PASCAL
+PressChar(
+ HWND hwnd,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ This routine is called in response to a WM_CHAR message. It will
+ handle any keyboard messages not dealt with in KeyDown
+
+Arguments:
+
+ hwnd - Supplies the handle of the window for the message
+ wParam - Supplies the wParam field of the message
+ lParam - Supplies the lParam field of the message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ NPVIEWREC v = &Views[view];
+ NPDOCREC d = &Docs[v->Doc];
+ int yPos;
+#ifdef DBCS
+ static BOOL bDBCS = FALSE;
+ static BYTE szBuf[4];
+#endif
+
+ Assert(v->Doc >= 0);
+
+ if ((lParam & (1 << 31)) != 0 || IsIconic(GetParent(hwnd))) {
+ return;
+ }
+#ifdef DBCS
+ if (bDBCS) {
+ bDBCS = FALSE;
+ szBuf[1] = (BYTE)wParam;
+ szBuf[2] = '\0';
+
+ if ((status.overtype || d->forcedOvertype)
+ && !v->BlockStatus) {
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+
+ /**********************************************/
+ /* if over-write mode and no text is selected */
+ /**********************************************/
+ if (!FirstLine(v->Doc, &pl, &v->Y, &pb)) {
+ return;
+ }
+ CloseLine(v->Doc, &pl, v->Y, &pb);
+ v->Y--;
+
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->X;
+ v->BlockYL = v->Y;
+ v->BlockYR = v->Y;
+ if (IsDBCSLeadByte((BYTE)(el[v->X]))) {
+ v->BlockXR = v->X + 2;
+ } else if (v->bDBCSOverWrite) {
+ if (v->X + 2 < elLen) {
+ if (IsDBCSLeadByte((BYTE)(el[v->X + 1]))) {
+ szBuf[2] = ' ';
+ szBuf[3] = '\0';
+ v->BlockXR = v->X + 3;
+ } else {
+ v->BlockXR = v->X + 2;
+ }
+ } else {
+ v->BlockXR = v->X + 1;
+ }
+ } else {
+ v->BlockXR = v->X + 1;
+ }
+
+ if (InsertStream(view, v->X, v->Y, lstrlen(szBuf), szBuf, TRUE)) {
+ SetReplaceDBCSFlag(d, TRUE);
+ PosXY(view, v->X + lstrlen(szBuf), v->Y, FALSE);
+ }
+ } else {
+ if (InsertStream(view, v->X, v->Y, 2, szBuf, TRUE)) {
+ PosXY(view, v->X + 2, v->Y, FALSE);
+ }
+ }
+ return;
+ }
+#endif // DBCS
+
+ /*
+ * See if we have the prefix to multikey function
+ */
+
+ if (wParam == MULTIKEY) {
+ /*
+ * If it's multikey again, cancel multikey
+ */
+
+ StatusMultiKey(!status.multiKey);
+ } else {
+
+ /*
+ * Test if we want to process a multikey function
+ */
+
+ if (status.multiKey) {
+
+ char ch = (char) LOWORD((DWORD)AnsiUpper((LPSTR)MAKELONG(wParam, 0)));
+ switch (ch) {
+
+ /*
+ * Emulate Cursor at line begin
+ */
+
+ case CTRL_S:
+ case 'S':
+ PosXY(view, 0, v->Y, FALSE);
+ break;
+
+ /*
+ * Emulate Cursor at line end
+ */
+
+ case CTRL_D:
+ case 'D':
+ KeyDown(view, VK_END, FALSE, FALSE);
+ break;
+
+ /*
+ * Cursor at top of window
+ */
+
+ case CTRL_E:
+ case 'E':
+ yPos = v->iYTop;
+ if (yPos == -1) {
+ yPos = GetScrollPos(v->hwndClient, SB_VERT);
+ }
+ PosXY(view, v->X, yPos, FALSE);
+ break;
+
+ /*
+ * Cursor at bottom of window
+ */
+
+ case CTRL_X:
+ case 'X':
+ {
+ RECT rcl;
+
+ GetClientRect(v->hwndClient, &rcl);
+ rcl.bottom /= v->charHeight;
+ yPos = v->iYTop;
+ if (yPos == -1) {
+ yPos = GetScrollPos(v->hwndClient, SB_VERT);
+ }
+ PosXY(view, v->X, mini(rcl.bottom + yPos - 1,
+ d->NbLines - 1), FALSE);
+ break;
+ }
+
+ //Emulate Cursor at beginning of file
+
+ case CTRL_R:
+ case 'R':
+ KeyDown(view, VK_HOME, FALSE, TRUE);
+ break;
+
+ //Emulate Cursor at end of file
+
+ case CTRL_C:
+ case 'C':
+ KeyDown(view, VK_END, FALSE, TRUE);
+ break;
+
+ //Copy up to end of line in clipboard and delete
+
+ case CTRL_Y:
+ case 'Y':
+ PasteStream(view, v->X, v->Y, MAX_USER_LINE, v->Y);
+ DeleteStream(view, v->X, v->Y, MAX_USER_LINE, v->Y, TRUE);
+ break;
+
+ //Find Dialog box
+
+ case CTRL_F:
+ case 'F':
+
+ //FindNext box may already be there
+
+ if (frMem.hDlgFindNextWnd)
+ SetFocus(frMem.hDlgFindNextWnd);
+ else {
+ if (StartDialog(DLG_FIND, DlgFind))
+ Find();
+ }
+ break;
+
+ //Replace Dialog box
+
+ case CTRL_A:
+ case 'A':
+ if (d->docType == DOC_WIN) {
+
+ //Replace box may already be there
+
+ if (frMem.hDlgConfirmWnd) {
+ SetFocus(frMem.hDlgConfirmWnd);
+ } else {
+ if (StartDialog(DLG_REPLACE, DlgReplace))
+ Replace();
+ }
+ } else
+ MessageBeep(0);
+ break;
+
+ //Ooops, wrong key
+
+ default:
+ MessageBeep(0);
+ break;
+
+ }
+
+ //End of multikey function
+
+ StatusMultiKey(FALSE);
+ return;
+ }
+
+ switch(wParam) {
+
+ //Those are Handled in KeyDown
+
+ case TAB:
+ case CTRL_M:
+ break;
+
+ //Emulate Left Arrow
+
+ case CTRL_S:
+ KeyDown(view, VK_LEFT, FALSE, FALSE);
+ break;
+
+ //Emulate Right Arrow
+
+ case CTRL_D:
+ KeyDown(view, VK_RIGHT, FALSE, FALSE);
+ break;
+
+ //Emulate Word Left
+
+ case CTRL_A:
+ KeyDown(view, VK_LEFT, FALSE, TRUE);
+ break;
+
+ //Emulate Word Right
+
+ case CTRL_F:
+ KeyDown(view, VK_RIGHT, FALSE, TRUE);
+ break;
+
+ //Emulate Up Arrow
+
+ case CTRL_E:
+ KeyDown(view, VK_UP, FALSE, FALSE);
+ break;
+
+ //Emulate Down Arrow
+
+ case CTRL_X:
+ KeyDown(view, VK_DOWN, FALSE, FALSE);
+ break;
+
+ //Change Overtype
+
+ case CTRL_V:
+ StatusOvertype(!status.overtype);
+ break;
+
+ //Emulate first non blank char next line
+
+ case CTRL_J:
+ if (LOBYTE(HIWORD(lParam)) != RETURN_SCANCODE)
+ KeyDown(view, VK_RETURN, FALSE, TRUE);
+ break;
+
+ //Emulate Backspace if key is not the backspace key
+
+ case CTRL_H:
+ break;
+
+ //Emulate Delete
+
+ case CTRL_G:
+ KeyDown(view, VK_DELETE, FALSE, FALSE);
+ break;
+
+ //Delete rest of word
+
+ case CTRL_T:
+ {
+ int rightCol;
+
+ //Get number of chars to delete
+
+ GetWordAtXY(view, v->X, v->Y,
+ FALSE, NULL, FALSE, NULL, 0, NULL, &rightCol);
+
+ //Copy them to clipboard and delete
+
+ PasteStream(view, v->X, v->Y, rightCol, v->Y);
+ DeleteStream(view, v->X, v->Y, rightCol, v->Y, TRUE);
+ break;
+ }
+
+ //Lowercase/Uppercase chars at cursor or in selection
+
+ case CTRL_U:
+ {
+ char lineBuf[MAX_USER_LINE + 1];
+ BOOL prevStopMark = stopMarkStatus;
+
+ //If selection on
+
+ if (v->BlockStatus) {
+ int XL,XR, bufXL, bufXR;
+ int YL,YR, yStart;
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int editLen, bufLen;
+
+ GetBlockCoord (view, &XL, &YL, &XR, &YR);
+ yStart = YL;
+
+ DestroyRecBuf(v->Doc, REC_REDO);
+
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that records have no stop marks after
+ //this record
+
+ stopMarkStatus = NEXT_HAS_NO_STOP;
+
+ //Copy every line selected in a buffer, upcase/locase
+ //the buffer, and delete old text then insert new text
+
+ while (YL <= YR) {
+ if (!FirstLine(v->Doc, &pl, &YL, &pb))
+ goto err;
+ bufXL = AlignToTabs(XL, pl->Length - LHD, (LPSTR)pl->Text);
+ if (YL - 1 == YR) {
+ bufXR = AlignToTabs(XR, pl->Length - LHD, (LPSTR)pl->Text);
+ editLen = mini(XR, elLen) - XL;
+ bufLen = mini(bufXR, pl->Length - LHD) - bufXL;
+ }
+ else {
+ editLen = elLen - XL;
+ bufLen = pl->Length - LHD - bufXL;
+ }
+ if (bufLen > 0) {
+ _fmemmove((LPSTR)lineBuf, (LPSTR)pl->Text + bufXL, bufLen);
+ lineBuf[bufLen] = '\0';
+ if (isShiftDown)
+ AnsiUpper((LPSTR)lineBuf);
+ else
+ AnsiLower((LPSTR)lineBuf);
+ CloseLine(v->Doc, &pl, YL, &pb);
+ if (!DeleteBlock(v->Doc, XL, YL - 1, XL + editLen, YL - 1))
+ goto err;
+ if (!InsertBlock(v->Doc, XL, YL - 1, bufLen, (LPSTR)lineBuf))
+ break;
+ }
+ XL = 0;
+ }
+
+ InvalidateLines(view, yStart, YR, FALSE);
+
+ //Put undo/redo engine back in normal state
+
+ if (prevStopMark == HAS_STOP)
+ stopMarkStatus = HAS_STOP;
+
+ }
+ else {
+
+ int leftCol;
+ PSTR ps;
+ BOOL f = FALSE;
+
+ //Upcase/lowcase char at cursor
+
+ if (GetWordAtXY(view, v->X, v->Y, FALSE, &f, FALSE,
+ lineBuf, MAX_USER_LINE, &leftCol, NULL)) {
+ ps = lineBuf + v->X - leftCol;
+ ps[v->X + 1] = '\0';
+ if (isShiftDown)
+ AnsiUpper((LPSTR)ps);
+ else
+ AnsiLower((LPSTR)ps);
+
+ ReplaceChar(view, v->X, v->Y, *ps, TRUE);
+ }
+
+ }
+ break;
+
+ }
+
+ //Delete current line and copy to clipboard
+
+ case CTRL_Y:
+ {
+ int yLimit = Docs[v->Doc].NbLines - 1;
+ int x = 0;
+
+ if (v->Y >= yLimit)
+ x = MAX_USER_LINE;
+ else
+ yLimit = v->Y + 1;
+
+ ClearSelection(view);
+ PosXY(view, 0, v->Y, FALSE);
+ PasteStream(view, 0, v->Y, x, yLimit);
+ DeleteStream(view, 0, v->Y, x, yLimit, TRUE);
+
+ break;
+ }
+
+ //Emulate Line Up
+
+ case CTRL_W:
+ KeyDown(view, VK_UP, FALSE, TRUE);
+ break;
+
+ //Emulate Line Down
+
+ case CTRL_Z:
+ KeyDown(view, VK_DOWN, FALSE, TRUE);
+ break;
+
+ //Emulate Page Up
+
+ case CTRL_R:
+ KeyDown(view, VK_PRIOR, FALSE, FALSE);
+ break;
+
+ //Emulate Page Down
+
+ case CTRL_C:
+ KeyDown(view, VK_NEXT, FALSE, FALSE);
+ break;
+
+ //Insert blank line above
+
+ case CTRL_N:
+ {
+
+ int oldX = v->X, oldY = v->Y;
+ KeyDown(view, VK_RETURN, FALSE, FALSE);
+ PosXY(view, oldX, oldY, FALSE);
+ break;
+ }
+
+ //Clear selection
+
+ case ESCAPE:
+ ClearSelection(view);
+ break;
+
+ //Find matching {[( ... )]}
+
+ case CTRL_RIGHTBRACKET:
+ FindMatching(view);
+ break;
+
+ //Normal char or unknown CTRL chars
+
+ default:
+#ifdef DBCS
+ if (IsDBCSLeadByte((BYTE)wParam)) {
+ szBuf[0] = (BYTE)wParam;
+ bDBCS = TRUE;
+ break;
+ }
+#endif
+ if (wParam >= ' ') {
+
+ BOOL ok;
+
+ //Replace or insert char at cursor location
+
+ if (status.overtype || d->forcedOvertype) {
+#ifdef DBCS
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ BOOL bDBCS;
+
+ if (!FirstLine(v->Doc, &pl, &v->Y, &pb)) {
+ break;
+ }
+ CloseLine(v->Doc, &pl, v->Y, &pb);
+ v->Y--;
+
+ szBuf[0] = (BYTE)wParam;
+ szBuf[1] = '\0';
+
+ bDBCS = IsDBCSLeadByte((BYTE)(el[v->X])) ? TRUE : FALSE;
+ if (bDBCS && !v->BlockStatus) {
+ if (v->bDBCSOverWrite) {
+ szBuf[1] = ' ';
+ szBuf[2] = '\0';
+ }
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->X;
+ v->BlockXR = v->X + 2;
+ v->BlockYL = v->Y;
+ v->BlockYR = v->Y;
+ }
+ if (bDBCS || v->BlockStatus) {
+ if (ok = InsertStream(view, v->X, v->Y,
+ lstrlen(szBuf), szBuf, TRUE)) {
+ if (bDBCS) {
+ SetReplaceDBCSFlag(d, TRUE);
+ }
+ }
+ } else
+#endif // DBCS
+ ok = ReplaceChar(view, v->X, v->Y, wParam, TRUE);
+ } else {
+ ok = InsertStream(view, v->X, v->Y, 1, (LPSTR)&wParam, TRUE);
+ }
+
+ //Reposition Cursor
+
+ if (ok) {
+ PosXY(view, v->X + 1, v->Y, FALSE);
+ }
+ }
+ else
+ MessageBeep(0);
+ break;
+
+ }
+ }
+
+ return;
+
+ err:
+ {
+ Assert(FALSE);
+ return;
+ }
+} /* PressChar() */
+
+
+
+/*** SetRORegion
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+void SetRORegion (int view, int Xro, int Yro)
+{
+ NPVIEWREC v = &Views[view];
+ NPDOCREC d = &Docs[v->Doc];
+
+ Assert(v->Doc >= 0);
+
+ //Set DOCREC structures
+
+ if (Xro == 0 && Yro == 0)
+ d->RORegionSet = FALSE;
+ else
+ d->RORegionSet = TRUE;
+
+
+ d->RoX2 = Xro;
+ d->RoY2 = Yro;
+
+} /* SetRORegion () */
+
+
+
+
+/*** GetRORegion
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+BOOL GetRORegion (int view, LPINT Xro, LPINT Yro)
+{
+ NPVIEWREC v = &Views[view];
+ NPDOCREC d = &Docs[v->Doc];
+
+ Assert(v->Doc >= 0);
+
+ if (d->RORegionSet == TRUE)
+ {
+ //Get DOCREC structures
+
+ *Xro = d->RoX2;
+ *Yro = d->RoY2;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+} /* GetRORegion () */
+
diff --git a/private/windbg/windbg/editutil.c b/private/windbg/windbg/editutil.c
new file mode 100644
index 000000000..6158e9e54
--- /dev/null
+++ b/private/windbg/windbg/editutil.c
@@ -0,0 +1,196 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ editutil.c
+
+Abstract:
+
+ This file contains the codes to interface into the edit manager
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern void FAR PASCAL InvalidateLines (int, int, int, BOOL);
+
+
+/*** InsertEditLine
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+** NB inserts above y
+*/
+
+void PASCAL InsertEditLine(int doc, LPSTR EditText, int y, BOOL VisualUpdate)
+{
+ int EditLen;
+
+ EditLen = _fstrlen(EditText);
+
+ InsertBlock(doc, 0, y, EditLen, EditText);
+ if (_fstrcmp(EditText+EditLen-2, CrLf) != 0)
+ {
+ // Ensure CrlLf
+ InsertBlock(doc, (int)EditLen, y, sizeof(CrLf), (LPSTR)CrLf);
+ }
+
+ SetVerticalScrollBar(Docs[doc].FirstView, FALSE);
+
+ if (VisualUpdate)
+ {
+ InvalidateLines(Docs[doc].FirstView, y, LAST_LINE, FALSE);
+ }
+ return;
+} /* InsertEditLine() */
+
+/*** DeleteEditLine
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void PASCAL DeleteEditLine(int doc, int y, BOOL VisualUpdate)
+{
+ DeleteBlock(doc, 0, y, 0, y+1);
+
+ SetVerticalScrollBar(Docs[doc].FirstView, FALSE);
+
+ if (VisualUpdate)
+ {
+ InvalidateLines(Docs[doc].FirstView, y, LAST_LINE, FALSE);
+ }
+ return;
+} /* DeleteEditLine() */
+
+/*** AddEditLine
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void PASCAL AddEditLine(int doc, LPSTR EditText, BOOL VisualUpdate)
+{
+ char szBuffer[MAX_USER_LINE+1];
+ int lastLine;
+ int lastLineLen;
+
+ // Is there any text on the last line?
+ lastLine = Docs[doc].NbLines-1;
+ Dbg(GetTextAtLine(doc, lastLine, 0, sizeof(szBuffer)-1, szBuffer));
+ lastLineLen = strlen(szBuffer);
+ if (lastLineLen != 0)
+ {
+ // We need to append a CrLf to the last line first
+ InsertBlock(doc, lastLineLen, lastLine, sizeof(CrLf), (LPSTR)CrLf);
+ // And then replace the text at the new last line
+ InsertBlock(doc, 0, lastLine+1, _fstrlen(EditText), EditText);
+ }
+ else
+ {
+ // We just insert above the last line
+ InsertEditLine(doc, EditText, lastLine, VisualUpdate);
+ }
+
+ SetVerticalScrollBar(Docs[doc].FirstView, FALSE);
+ return;
+} /* AddEditLine() */
+
+/*** ReplaceEditLine
+**
+** Synopsis:
+** void = ReplaceEditLine(doc, EditText, y, VisualUpdate)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void PASCAL ReplaceEditLine(int doc, LPSTR EditText, int y, BOOL VisualUpdate)
+{
+ DeleteBlock(doc, 0, y, MAX_USER_LINE, y);
+ InsertBlock(doc, 0, y, _fstrlen(EditText), EditText);
+
+ SetVerticalScrollBar(Docs[doc].FirstView, FALSE);
+
+ if (VisualUpdate)
+ {
+ InvalidateLines(Docs[doc].FirstView, y, LAST_LINE, FALSE);
+ }
+ return;
+} /* ReplaceEditLine() */
+
+
+/*** SetDocLines
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Sets the number of lines in a document accordingly
+** This zaps the current contents
+**
+*/
+
+void PASCAL SetDocLines(int doc, int lines)
+{
+ int i;
+ int curLines;
+
+ Assert(lines > 0);
+
+ curLines = Docs[doc].NbLines;
+
+ if (lines > curLines)
+ {
+ // Add some at the end
+ for (i = 0; i < lines-curLines; i++)
+ {
+ AddEditLine(doc, szNull, FALSE);
+ }
+ }
+ else if (lines < curLines)
+ {
+ // Take them off from the end.
+
+ DeleteBlock(doc, 0, lines-1, MAX_USER_LINE, curLines-1);
+ SetVerticalScrollBar(Docs[doc].FirstView, FALSE);
+ }
+ return;
+} /* SetDocLines() */
diff --git a/private/windbg/windbg/environ.c b/private/windbg/windbg/environ.c
new file mode 100644
index 000000000..d3589dd00
--- /dev/null
+++ b/private/windbg/windbg/environ.c
@@ -0,0 +1,244 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ environ.c
+
+Abstract:
+
+ This file contains the code to deal with Options.Environment dialog
+ box.
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern void FAR PASCAL InvalidateLines (int, int, int, BOOL);
+
+int NEAR PASCAL ChangeTabs(int doc, int newTabSize);
+
+extern BOOLEAN AskToSave;
+
+BOOL FAR PASCAL EXPORT
+DlgEnviron(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+)
+{
+ char Buffer[256];
+ int View;
+ int Doc;
+ int k;
+ int TabStops;
+ long RedoSize;
+ BOOLEAN KeepTabs;
+ BOOLEAN HorScroll;
+ BOOLEAN VerScroll;
+ BOOLEAN SrchPath;
+
+ switch (message) {
+ case WM_INITDIALOG:
+
+ sprintf(Buffer, "%d", environParams.tabStops);
+ SendMessage( GetDlgItem(hDlg, ID_ENV_TABSTOPS), WM_SETTEXT, 0, (DWORD)(LPSTR)Buffer);
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_TABKEEP),
+ BM_SETCHECK, environParams.keepTabs, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_TABSPAC),
+ BM_SETCHECK, !environParams.keepTabs, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_SCROLLHOR),
+ BM_SETCHECK, environParams.horizScrollBars, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_SCROLLVER),
+ BM_SETCHECK, environParams.vertScrollBars, 0L );
+
+ sprintf(Buffer, "%d", environParams.undoRedoSize);
+ SendMessage( GetDlgItem(hDlg, ID_ENV_REDOSIZE), WM_SETTEXT, 0, (DWORD)(LPSTR)Buffer);
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_SRCHPATH),
+ BM_SETCHECK, environParams.SrchPath, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_ASKSAVE),
+ BM_SETCHECK, AskToSave, 0L );
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK :
+
+ SendMessage( GetDlgItem(hDlg, ID_ENV_TABSTOPS ),
+ WM_GETTEXT, sizeof(Buffer), (LONG)(LPSTR)Buffer );
+ TabStops = atol(Buffer);
+
+ KeepTabs = (SendMessage( GetDlgItem(hDlg, ID_ENV_TABKEEP),
+ BM_GETCHECK, 0, 0L ) == 1);
+
+
+ if ( TabStops != environParams.tabStops ||
+ KeepTabs != environParams.keepTabs ) {
+
+ for (Doc = 0; Doc < MAX_DOCUMENTS; Doc++) {
+ if (Docs[Doc].FirstView != -1) {
+ k = ChangeTabs(Doc, TabStops);
+ if (k > 0) {
+ SendDlgItemMessage(hDlg, ID_ENV_TABSTOPS, EM_SETSEL, 0, MAKELONG(0, 32767));
+ ErrorBox(ERR_Tab_Too_Big, k, (LPSTR)Docs[Doc].FileName);
+ SetFocus(GetDlgItem(hDlg, ID_ENV_TABSTOPS));
+ return TRUE;
+ }
+ }
+ }
+
+ environParams.tabStops = TabStops;
+ environParams.keepTabs = KeepTabs;
+ tabSize = environParams.tabStops;
+
+ for (View = 0; View < MAX_VIEWS; View++) {
+ if (Views[View].Doc >= 0) {
+ InvalidateLines( View, 0, Docs[Views[View].Doc].NbLines - 1, FALSE );
+ }
+ }
+ }
+
+ HorScroll = environParams.horizScrollBars;
+ VerScroll = environParams.vertScrollBars;
+
+ environParams.horizScrollBars = (SendMessage( GetDlgItem(hDlg, ID_ENV_SCROLLHOR),
+ BM_GETCHECK, 0, 0L ) == 1);
+
+ environParams.vertScrollBars = (SendMessage( GetDlgItem(hDlg, ID_ENV_SCROLLVER),
+ BM_GETCHECK, 0, 0L ) == 1);
+
+ if ( HorScroll != environParams.horizScrollBars ||
+ VerScroll != environParams.vertScrollBars ) {
+
+ for (View = 0; View < MAX_VIEWS; View++) {
+ if (Views[View].Doc >= 0) {
+
+ EnsureScrollBars(View, FALSE);
+ PosXY(View, Views[View].X, Views[View].Y, FALSE);
+ }
+ }
+ }
+
+
+ RedoSize = environParams.undoRedoSize;
+ SendMessage( GetDlgItem(hDlg, ID_ENV_REDOSIZE ),
+ WM_GETTEXT, sizeof(Buffer), (LONG)(LPSTR)Buffer );
+ environParams.undoRedoSize = atol(Buffer);
+
+ SrchPath = environParams.SrchPath;
+
+ environParams.SrchPath = (SendMessage( GetDlgItem(hDlg, ID_ENV_SRCHPATH),
+ BM_GETCHECK, 0, 0L ) == 1);
+
+ AskToSave = (SendMessage( GetDlgItem(hDlg, ID_ENV_ASKSAVE),
+ BM_GETCHECK, 0, 0L ) == 1);
+
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDCANCEL:
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_ENVIRON_HELP));
+ return (TRUE);
+ }
+ }
+ return FALSE;
+
+}
+
+/*** ChangeTabs
+**
+** Synopsis:
+** int = ChangeTabs(doc, newTabSize)
+**
+** Entry:
+** doc - Document to change tabs in
+** newTabSize - New size to set the tabs to
+**
+** Returns:
+** 0 if tab width is ok else the line number for which the
+** line size is too great
+**
+** Description:
+**
+*/
+
+int NEAR PASCAL ChangeTabs(int doc, int newTabSize)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+ register int i;
+ register int j;
+ int len;
+
+ y = 0;
+
+ //
+ // Check expanded len of all tabs
+ //
+ if (!FirstLine(doc, &pl, &y, &pb)) {
+ return 0;
+ }
+
+ while (TRUE) {
+
+ len = pl->Length - LHD;
+
+ if (len > 0) {
+
+ i = 0;
+ j = 0;
+
+ //
+ // Compute len of line expanded with tabs
+ //
+ while (i < len) {
+ if (pl->Text[i] == TAB) {
+ j += newTabSize - (j % newTabSize);
+ } else {
+ j++;
+ }
+ i++;
+ }
+
+ if (j > MAX_USER_LINE) {
+ CloseLine(doc, &pl, y, &pb);
+ return y;
+ }
+ }
+
+ if (y >= Docs[doc].NbLines) {
+ break;
+ } else {
+ if (!NextLine(doc, &pl, &y, &pb)) {
+ return 0;
+ }
+ }
+ }
+
+ CloseLine(doc, &pl, y, &pb);
+ return 0;
+}
diff --git a/private/windbg/windbg/find.c b/private/windbg/windbg/find.c
new file mode 100644
index 000000000..57c992fb3
--- /dev/null
+++ b/private/windbg/windbg/find.c
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ find.c
+
+Abstract:
+
+ This file contains the code for dealing with the Find Dialog box
+
+Author:
+
+ Jim Schaad (jimsch)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#define extraPick (*((BOOL *)&wGeneric1))
+
+/*** DlgFind
+**
+** Synopsis:
+** bool = DlgFind(hwnd, message, wParam, lParam)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes messages for "FIND" dialog box
+** (Edit Find Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT DlgFind(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ Unused(lParam);
+
+ switch (message) {
+
+ case WM_INITDIALOG: {
+
+ BOOL lookAround = TRUE;
+ int i;
+ LPSTR s;
+
+ frMem.replaceAll = FALSE;
+ frMem.oneLineDone = FALSE;
+ frMem.allTagged = FALSE;
+ SetStopLimit();
+ StatusMultiKey(FALSE);
+
+ //Retrieve text from document, blank string if nothing found
+ //and send string to dialog box
+ if (GetCurrentText(curView, &lookAround,
+ (LPSTR)findReplace.findWhat,
+ MAX_USER_LINE, &frMem.leftCol, NULL)) {
+
+ //Temporarly put the string in the picklist
+ extraPick = InsertInPickList(FIND_PICK);
+
+ }
+ else
+ extraPick = FALSE;
+
+ frMem.rightCol = frMem.leftCol;
+
+ SendDlgItemMessage(hDlg, ID_FIND_WHAT,
+ CB_LIMITTEXT, MAX_USER_LINE, (DWORD) NULL);
+ SendDlgItemMessage(hDlg, ID_FIND_WHAT, WM_SETTEXT, 0,
+ (DWORD)((LPSTR)findReplace.findWhat));
+
+ //Transfer boolean values to Dialog Box
+ SendDlgItemMessage(hDlg, ID_FIND_MATCHUPLO, BM_SETCHECK,
+ findReplace.matchCase, 0L);
+ SendDlgItemMessage(hDlg, ID_FIND_WHOLEWORD, BM_SETCHECK,
+ !findReplace.regExpr & findReplace.wholeWord, 0L);
+ SendDlgItemMessage(hDlg, ID_FIND_REGEXP, BM_SETCHECK,
+ findReplace.regExpr, 0L);
+ EnableWindow(GetDlgItem(hDlg, ID_FIND_WHOLEWORD),
+ !findReplace.regExpr);
+
+ if (Views[curView].Doc > -1)
+ {
+ if (Docs[Views[curView].Doc].docType == DOC_WIN)
+ {
+ EnableWindow(GetDlgItem(hDlg, ID_FIND_TAGALL),TRUE);
+ }
+ }
+
+ if (findReplace.goUp)
+ SendDlgItemMessage(hDlg, ID_FIND_UP, BM_SETCHECK, TRUE, 0L);
+ else
+ SendDlgItemMessage(hDlg, ID_FIND_DOWN, BM_SETCHECK, TRUE, 0L);
+
+ //Set the line to start find
+ frMem.line = Views[curView].Y;
+
+ //Fill find pick list
+ for (i = 0 ; i < findReplace.nbInPick[FIND_PICK]; i++) {
+ Dbg(s = (LPSTR)GlobalLock(findReplace.hPickList[FIND_PICK][i]));
+ SendDlgItemMessage(hDlg, ID_FIND_WHAT, CB_INSERTSTRING, (WPARAM)-1,
+ (LPARAM)s);
+
+ //SendMessage( GetDlgItem( hDlg, ID_FIND_WHAT ),
+ // CB_INSERTSTRING,
+ // (WPARAM)-1,
+ // (LPARAM)s );
+
+ Dbg(GlobalUnlock (findReplace.hPickList[FIND_PICK][i]) == FALSE);
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMMAND: {
+ switch (wParam) {
+
+ case ID_FIND_TAGALL:
+ if (extraPick)
+ RemoveFromPick(FIND_PICK);
+
+ if (SendDlgItemMessage(hDlg, ID_FIND_WHAT, WM_GETTEXT,
+ MAX_USER_LINE,
+ (DWORD)((LPSTR)findReplace.findWhat))) {
+ InsertInPickList(FIND_PICK);
+
+ if (FindNext(Views[curView].Y, Views[curView].X,
+ FALSE, FALSE, TRUE)) {
+ if (!frMem.hadError)
+ TagAll(frMem.line);
+ }
+ }
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case ID_FIND_MATCHUPLO:
+ findReplace.matchCase = !findReplace.matchCase;
+ return TRUE;
+
+ case ID_FIND_REGEXP:
+ findReplace.regExpr = !findReplace.regExpr;
+ SendDlgItemMessage(hDlg, ID_FIND_WHOLEWORD, BM_SETCHECK,
+ !findReplace.regExpr & findReplace.wholeWord, 0L);
+ EnableWindow(GetDlgItem(hDlg, ID_FIND_WHOLEWORD),
+ !findReplace.regExpr);
+ return TRUE;
+
+ case ID_FIND_WHOLEWORD:
+ findReplace.wholeWord = !findReplace.wholeWord;
+ return TRUE;
+
+ case ID_FIND_UP:
+ findReplace.goUp = TRUE;
+ return TRUE;
+
+ case ID_FIND_DOWN:
+ findReplace.goUp = FALSE;
+ return TRUE;
+
+ case ID_FIND_NEXT: {
+
+ if (SendDlgItemMessage(hDlg, ID_FIND_WHAT, WM_GETTEXT,
+ MAX_USER_LINE,
+ (DWORD)((LPSTR)findReplace.findWhat))) {
+ InsertInPickList(FIND_PICK);
+ if (FindNext(Views[curView].Y, Views[curView].X,
+ FALSE, TRUE, TRUE)) {
+
+ frMem.firstFindNextInvoc = TRUE;
+ EndDialog(hDlg, !frMem.hadError);
+ }
+ else {
+ SetStopLimit();
+ SetFocus(GetDlgItem(hDlg, ID_FIND_WHAT));
+ }
+ }
+ return TRUE;
+ }
+
+ case IDCANCEL : {
+
+ LPSTR old;
+
+ //Remove the extra pick we inserted
+ if (extraPick)
+ RemoveFromPick(FIND_PICK);
+
+ //Replace the findWhat with the latest in picklist
+ if (findReplace.nbInPick[FIND_PICK] > 0) {
+ Dbg(old = (LPSTR)GlobalLock(findReplace.hPickList[FIND_PICK][0]));
+ lstrcpy(findReplace.findWhat, old);
+ Dbg(GlobalUnlock(findReplace.hPickList[FIND_PICK][0]) == FALSE);
+ }
+ else
+ findReplace.findWhat[0] = '\0';
+
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_FIND_HELP));
+ return TRUE;
+ }
+ break;
+ }
+ }
+
+ return (FALSE);
+} /* DlgFind() */
+
diff --git a/private/windbg/windbg/findnext.c b/private/windbg/windbg/findnext.c
new file mode 100644
index 000000000..1b122ed9a
--- /dev/null
+++ b/private/windbg/windbg/findnext.c
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ findnext.c
+
+Abstract:
+
+ This file contains the code for dealing with the Findnext Dialog box
+
+Author:
+
+ Kent Forschmiedt (kentf)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+/*** DlgFindNext
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL EXPORT
+DlgFindNext(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ switch (message) {
+
+ case WM_INITDIALOG :
+
+ if (Views[curView].Doc > -1) {
+ if (Docs[Views[curView].Doc].docType == DOC_WIN) {
+ EnableWindow(GetDlgItem(hDlg, ID_FINDNEXT_TAGALL),TRUE);
+ }
+ }
+ return TRUE;
+
+ case WM_ACTIVATE :
+
+ if (wParam != 0 &&
+#ifdef WIN32
+ (HWND) lParam == hwndFrame
+#else
+ LOWORD(lParam) == hwndFrame
+#endif
+ && !frMem.firstFindNextInvoc && hwndActiveEdit) {
+
+ //Set search start to current position
+
+ frMem.leftCol = frMem.rightCol = Views[curView].X;
+ frMem.line = Views[curView].Y;
+
+ //Set search stop limit to the current position
+ SetStopLimit();
+ }
+ frMem.firstFindNextInvoc = FALSE;
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+
+ case IDCANCEL:
+ frMem.exitModelessFind = TRUE;
+ return TRUE;
+
+ case IDOK:
+ frMem.exitModelessFind =
+ (!FindNext(frMem.line,
+ frMem.rightCol,
+ FALSE, TRUE, FALSE)
+ || frMem.allFileDone
+ || frMem.hadError);
+ return TRUE;
+
+ case ID_FINDNEXT_TAGALL:
+ TagAll(Views[curView].Y);
+ frMem.allTagged = TRUE;
+ frMem.exitModelessFind = TRUE;
+ return TRUE;
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg,szHelpFileName, HELP_CONTEXT, ID_FINDNEXT_HELP));
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ frMem.hDlgFindNextWnd = NULL; //Must be here to void reentrancy prob.
+ FlushKeyboard();
+ break;
+ }
+
+ return (FALSE);
+} /* DlgFindNext() */
diff --git a/private/windbg/windbg/findrep.c b/private/windbg/windbg/findrep.c
new file mode 100644
index 000000000..0a05ab0a7
--- /dev/null
+++ b/private/windbg/windbg/findrep.c
@@ -0,0 +1,1223 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ findrep.c
+
+Abstract:
+
+ This module contains find and replace code for the editor
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 01-Aug-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+//Prototypes
+
+void NEAR PASCAL SetDialogPos (BOOL forced, HWND hDlg);
+void NEAR PASCAL RefreshView (int startingCol,int endingCol,BOOL selectFoundText);
+char NEAR *REmalloc (size_t size);
+BOOL NEAR PASCAL RESearch (NPSTR line, int *xStart, int *xEnd);
+BOOL NEAR PASCAL SearchLineBack (int lineNb,int *xStart,int *xEnd,PSTR findWhat);
+BOOL NEAR PASCAL FindPrev (int startingLine,int startingCol,BOOL startFromSelection,BOOL selectFoundText,BOOL errorIfNotFound,HCURSOR hSaveCursor,PSTR findWhat);
+BOOL NEAR PASCAL SearchLineForw (int lineNb,int *xStart,int *xEnd,PSTR findWhat);
+
+
+
+
+
+void NEAR PASCAL
+SetDialogPos(
+ BOOL forced,
+ HWND hDlg)
+{
+ RECT r, rInt;
+ int y;
+ NPVIEWREC v = &Views[curView];
+ BOOL inter;
+
+ Assert(v->Doc >= 0);
+
+ y = (v->Y - GetScrollPos(v->hwndClient, SB_VERT)) * v->charHeight;
+ GetWindowRect(v->hwndClient, &r);
+
+ //Calculate caret pos and a virtual rectangle
+ y += r.top;
+ rInt.left = 0;
+ rInt.right = GetSystemMetrics(SM_CXSCREEN);
+ rInt.top = y;
+ rInt.bottom = y + v->charHeight;
+
+ //See if our dialog box hide the caret
+ GetWindowRect(hDlg, &r);
+ inter = IntersectRect(&rInt, &r, &rInt);
+
+ if (forced || inter) {
+ y += (v->charHeight / 2);
+
+ //Put the dialogbox where we have the biggest free space
+ if ((forced && !inter) || y > (GetSystemMetrics(SM_CYSCREEN) / 2)) {
+ y = 0;
+ } else {
+ y = GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top);
+ }
+ MoveWindow(hDlg,
+ (GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) / 2,
+ y, r.right - r.left, r.bottom - r.top, TRUE);
+ ShowWindow(hDlg, SW_NORMAL);
+ }
+}
+
+void FAR PASCAL
+SetStopLimit(
+ void
+ )
+{
+ frMem.stopLine = Views[curView].Y;
+ frMem.stopCol = Views[curView].X;
+ frMem.allFileDone = FALSE;
+ frMem.oneLineDone = FALSE;
+}
+
+void NEAR PASCAL
+RefreshView(
+ int startingCol,
+ int endingCol,
+ BOOL selectFoundText
+ )
+{
+ NPVIEWREC v = &Views[curView];
+
+ Assert(v->Doc >= 0);
+
+ //First put cursor at left of selection to possibly scroll
+ //hidden word
+ PosXY(curView, startingCol, frMem.line, TRUE);
+ PosXY(curView, endingCol, frMem.line, TRUE);
+
+ //Now select text found
+ if (selectFoundText) {
+ ClearSelection(curView);
+ v->BlockStatus = TRUE;
+ v->BlockYL = frMem.line;
+ v->BlockYR = frMem.line;
+ v->BlockXL = startingCol;
+ v->BlockXR = endingCol;
+ }
+
+ //Refresh line
+ InvalidateLines(curView, frMem.line, frMem.line, FALSE);
+
+ //Change position of modeless dialog boxes if needed
+ if (frMem.hDlgConfirmWnd) {
+ SetDialogPos(FALSE, frMem.hDlgConfirmWnd);
+ }
+ if (frMem.hDlgFindNextWnd) {
+ SetDialogPos(FALSE, frMem.hDlgFindNextWnd);
+ }
+}
+
+char NEAR *
+REmalloc(
+ size_t size
+ )
+{
+ return (char NEAR *)LocalAlloc(LPTR, size);
+}
+
+BOOL NEAR PASCAL
+RESearch(
+ NPSTR line,
+ int *xStart,
+ int *xEnd
+ )
+{
+ int maxREStack = 256;
+ BOOL done;
+ RE_OPCODE **stack; //Allocation for RE stack
+
+ //We may redo it if we need more stack
+ do {
+
+ done = TRUE;
+
+ //Do not search if start is out of string
+ if (*xStart >= (int)strlen(line)) {
+ break;
+ }
+
+ //Allocates the stack for the regular expression
+ stack = (RE_OPCODE **)REmalloc(maxREStack * sizeof(*stack));
+
+ //Try the match
+ switch (REMatch(pat, line, line + *xStart, stack, maxREStack, TRUE)) {
+
+ case REM_MATCH: {
+
+ int len = RELength(pat, 0);
+
+ if (len > 0) {
+ *xStart = (REStart(pat) - line);
+ *xEnd = *xStart + len;
+ Dbg(LocalFree((HANDLE)stack) == NULL);
+ return TRUE;
+ } else if (len == 0) {
+ *xEnd = *xStart + 1;
+ Dbg(LocalFree((HANDLE)stack) == NULL);
+ return TRUE;
+ }
+ break;
+ }
+
+ case REM_NOMATCH:
+ break;
+
+ case REM_STKOVR:
+ //The RE engine had a stack overflow. Add 256 bytes
+ //and try again
+ maxREStack += 256;
+ done = FALSE;
+ break;
+
+ case REM_INVALID:
+ ErrorBox(ERR_RegExpr_Invalid, (LPSTR)findReplace.findWhat);
+ frMem.hadError = TRUE;
+ break;
+
+ case REM_UNDEF:
+ ErrorBox(ERR_RegExpr_Undef, (LPSTR)findReplace.findWhat);
+ frMem.hadError = TRUE;
+ break;
+
+ default:
+ break;
+
+ }
+
+ Dbg(LocalFree((HANDLE)stack) == NULL);
+
+ } while (!done);
+
+ return FALSE;
+}
+
+BOOL NEAR PASCAL
+SearchLineBack(
+ int lineNb,
+ int *xStart,
+ int *xEnd,
+ PSTR findWhat
+ )
+{
+ char line[MAX_USER_LINE + 1];
+ BOOL found = FALSE;
+ int xLimit = min(*xStart, elLen);
+
+ //Make a local copy of the line
+ _fmemmove(line, (LPSTR)el, xLimit);
+ line[xLimit] = '\0';
+
+ if (findReplace.regExpr) {
+
+ while (!found && *xStart >= 0)
+ if (!(found = RESearch(line, xStart, xEnd)))
+ (*xStart)--;
+
+ } else {
+ register int xCur;
+ register int k;
+ int limit = lstrlen(findWhat);
+
+ if (!findReplace.matchCase)
+ AnsiUpper((LPSTR)line);
+
+ while (!found && *xStart >= 0) {
+
+ xCur = *xStart;
+
+#ifdef DBCS
+ for (; xCur < xLimit;
+ IsDBCSLeadByte(line[xCur]) ? xCur+=2 : xCur++) {
+#else
+ for (; xCur < xLimit; xCur++) {
+#endif
+
+ if (xCur + limit > elLen)
+ break;
+
+ //Select type of comparison according to user choice
+ k = 0;
+ while (k < limit && line[xCur + k] == findWhat[k]) {
+#ifdef DBCS
+ {
+ if (IsDBCSLeadByte(line[xCur + k])) {
+ if (xCur + k + 1 >= xLimit)
+ break;
+ if (line[xCur + k + 1] != findWhat[k + 1])
+ break;
+ k += 2;
+ } else {
+ k++;
+ }
+ }
+#else // !DBCS
+ k++;
+#endif
+ }
+
+ if (k == limit) {
+ *xEnd = xCur + k;
+
+ //If we search for a whole word
+ if (findReplace.wholeWord) {
+ BOOL separator;
+
+#ifdef DBCS
+ BOOL bDBCS = FALSE;
+ int i;
+
+ for (i = 0; i < xCur; i++) {
+ if (IsDBCSLeadByte(line[i])) {
+ bDBCS = TRUE;
+ i++;
+ } else {
+ bDBCS = FALSE;
+ }
+ }
+#endif // DBCS
+ if (xCur > 0) {
+#ifdef DBCS
+ if (bDBCS)
+ separator = TRUE;
+ else
+#endif
+ separator = !CHARINALPHASET(line[xCur - 1]);
+ } else {
+ separator = TRUE;
+ }
+ if (separator) {
+ if (xCur + limit < elLen) {
+ separator = !CHARINALPHASET(line[xCur + limit]);
+ } else {
+ separator = TRUE;
+ }
+ }
+ if (separator) {
+ *xStart = xCur;
+ found = TRUE;
+ }
+ break;
+ } else {
+ *xStart = xCur;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ (*xStart)--;
+ }
+ }
+ }
+
+ if (frMem.oneLineDone
+ && lineNb == frMem.stopLine
+ && (*xStart <= frMem.stopCol || !found)) {
+ frMem.allFileDone = TRUE;
+ }
+
+ if (!found) {
+ *xEnd = *xStart = MAX_LINE_SIZE;
+ }
+
+ return found;
+}
+
+BOOL NEAR PASCAL
+FindPrev(
+ int startingLine,
+ int startingCol,
+ BOOL startFromSelection,
+ BOOL selectFoundText,
+ BOOL errorIfNotFound,
+ HCURSOR hSaveCursor,
+ PSTR findWhat
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ NPVIEWREC v = &Views[curView];
+ BOOL found = FALSE;
+ int endingCol;
+
+ Assert(v->Doc >= 0);
+
+ //The caller wants us to start from begin of selected text
+ if (startFromSelection) {
+
+ int XL,XR;
+ int YL,YR;
+
+ Assert(v->BlockStatus);
+ GetBlockCoord(curView, &XL, &YL, &XR, &YR);
+ startingCol = XL;
+ }
+
+ //Scan text from current line till beginning of file
+ if (!FirstLine(v->Doc, &pl, &startingLine, &pb)) {
+ goto err;
+ }
+
+ startingLine--;
+
+ do {
+ found = SearchLineBack(startingLine,
+ &startingCol,
+ &endingCol,
+ findWhat);
+ if (frMem.hadError) {
+ goto out;
+ }
+ if (found) {
+ break;
+ }
+ if (!PreviousLine(v->Doc, &pl, startingLine, &pb)) {
+ goto err;
+ }
+ startingLine--;
+ frMem.oneLineDone = TRUE;
+ } while (startingLine >= 0);
+
+ startingLine = max(startingLine, 0);
+ CloseLine(v->Doc, &pl, startingLine + 1, &pb);
+
+ //Scan text from end till current line
+ if (!found) {
+
+ if (!frMem.replaceAll && (!frMem.allFileDone || !frMem.replacing)) {
+ if (status.hidden) {
+ ErrorBox(STA_Find_Hit_EOF);
+ } else {
+ StatusText(STA_Find_Hit_EOF, STATUS_INFOTEXT, FALSE);
+ }
+ }
+
+ startingLine = Docs[v->Doc].NbLines - 1;
+ if (!FirstLine(v->Doc, &pl, &startingLine, &pb)) {
+ goto err;
+ }
+ startingLine--;
+
+ do {
+
+ found = SearchLineBack(startingLine,
+ &startingCol,
+ &endingCol,
+ findWhat);
+ if (frMem.hadError) {
+ goto out;
+ }
+ if (found) {
+ break;
+ }
+ if (!PreviousLine(v->Doc, &pl, startingLine, &pb)) {
+ goto err;
+ }
+ startingLine--;
+ frMem.oneLineDone = TRUE;
+ } while (startingLine >= frMem.line);
+
+ startingLine = max(startingLine, 0);
+ CloseLine(v->Doc, &pl, startingLine + 1, &pb);
+ }
+
+ if (found) {
+
+ //Next find will start from here
+ frMem.line = startingLine;
+ frMem.leftCol = frMem.rightCol = startingCol;
+
+ if (!frMem.replaceAll) {
+ RefreshView(startingCol, endingCol, selectFoundText);
+ }
+
+ } else if (errorIfNotFound) {
+ if (findReplace.regExpr) {
+ ErrorBox(ERR_No_RegExp_Match, (LPSTR)findReplace.findWhat);
+ } else {
+ ErrorBox(ERR_String_Not_Found, (LPSTR)findReplace.findWhat);
+ }
+ }
+
+ //Restore cursor
+ SetCursor(hSaveCursor);
+
+ return found;
+
+ err : {
+ //Restore cursor
+ SetCursor(hSaveCursor);
+
+ Assert(FALSE);
+ return FALSE;
+ }
+
+ out : {
+ //Restore cursor
+ SetCursor(hSaveCursor);
+ CloseLine(v->Doc, &pl, startingLine, &pb);
+ return FALSE;
+ }
+}
+
+BOOL NEAR PASCAL
+SearchLineForw(
+ int lineNb,
+ int *xStart,
+ int *xEnd,
+ PSTR findWhat
+ )
+{
+
+ char line[MAX_USER_LINE + 1];
+ BOOL found = FALSE;
+ int xLimit = elLen;
+
+ //Make a local copy of the line
+ _fmemmove(line, (LPSTR)el, xLimit);
+ line[xLimit] = '\0';
+
+ if (findReplace.regExpr) {
+ found = RESearch(line, xStart, xEnd);
+ } else {
+
+ register int xCur = *xStart;
+ register int k;
+ int limit = lstrlen(findWhat);
+
+ if (!findReplace.matchCase) {
+ AnsiUpper((LPSTR)line);
+ }
+
+#ifdef DBCS
+ for (; xCur < xLimit;
+ IsDBCSLeadByte(line[xCur]) ? xCur+=2 : xCur++) {
+#else
+ for (; xCur < xLimit; xCur++) {
+#endif
+
+ if (xCur + limit > elLen) {
+ break;
+ }
+
+ //Select type of comparison according to user choice
+ k = 0;
+ while (k < limit && line[xCur + k] == findWhat[k]) {
+#ifdef DBCS
+ {
+ if (IsDBCSLeadByte(line[xCur + k])) {
+ if (xCur + k + 1 >= xLimit)
+ break;
+ if (line[xCur + k + 1] != findWhat[k + 1])
+ break;
+ k += 2;
+ } else {
+ k++;
+ }
+ }
+#else // !DBCS
+ k++;
+#endif
+ }
+
+ if (k == limit) {
+ *xEnd = xCur + k;
+
+ //If we search for a whole word
+ if (!findReplace.wholeWord) {
+
+ *xStart = xCur;
+ found = TRUE;
+ break;
+
+ } else {
+ BOOL separator;
+#ifdef DBCS
+ BOOL bDBCS = FALSE;
+ int i;
+
+ for (i = 0; i < xCur; i++) {
+ if (IsDBCSLeadByte(line[i])) {
+ bDBCS = TRUE;
+ i++;
+ } else {
+ bDBCS = FALSE;
+ }
+ }
+#endif // DBCS
+ if (xCur > 0) {
+#ifdef DBCS
+ if (bDBCS)
+ separator = TRUE;
+ else
+#endif
+ separator = !CHARINALPHASET(line[xCur - 1]);
+ } else {
+ separator = TRUE;
+ }
+ if (separator) {
+ if (xCur + limit < xLimit) {
+ separator = !CHARINALPHASET(line[xCur + limit]);
+ } else {
+ separator = TRUE;
+ }
+ }
+ if (separator) {
+ *xStart = xCur;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (frMem.oneLineDone
+ && lineNb - 1 == frMem.stopLine
+ && (*xStart >= frMem.stopCol || !found))
+ {
+ frMem.allFileDone = TRUE;
+ }
+
+ if (!found) {
+ *xEnd = *xStart = 0;
+ }
+
+ return found;
+}
+
+BOOL FAR PASCAL
+FindNext(
+ int startingLine,
+ int startingCol,
+ BOOL startFromSelection,
+ BOOL selectFoundText,
+ BOOL errorIfNotFound
+ )
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ NPVIEWREC v = &Views[curView];
+ BOOL found = FALSE;
+ HCURSOR hSaveCursor;
+ char findWhat[MAX_USER_LINE + 1];
+ int endingCol;
+
+ Assert(v->Doc >= 0);
+
+ frMem.hadError = FALSE;
+
+ //Transfer target to a near variable, and upcase it if we are making
+ //a no case
+ _fstrcpy(findWhat, findReplace.findWhat);
+ if (!findReplace.matchCase)
+ AnsiUpper((LPSTR)findWhat);
+
+ //Set the Hour glass cursor
+ hSaveCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ frMem.line = startingLine;
+ StatusText(SYS_StatusClear, STATUS_INFOTEXT, FALSE);
+
+ //Set elements if regular expressions mode is selected
+ if (findReplace.regExpr) {
+
+ tools_alloc = REmalloc;
+
+ //For unknown reasons RE Engine take care of the dynamic Allocs
+ //but you have to do the freeing ...
+ if (pat != NULL) {
+ Dbg(LocalFree((HANDLE)pat) == NULL);
+ pat = NULL;
+ }
+
+ //Compile the regular expression, selecting Unix mode
+ //(WARNING : RECompile can return NULL)
+ pat = RECompile(findWhat,
+ (flagType)findReplace.matchCase,
+ (flagType)FALSE);
+ }
+
+ //Another func takes care of the !@?!ing search going Up
+ if (findReplace.goUp) {
+ return FindPrev(startingLine,
+ startingCol,
+ startFromSelection,
+ selectFoundText,
+ errorIfNotFound,
+ hSaveCursor,
+ findWhat);
+ }
+
+ //The caller wants us to start from end of selected text
+ if (startFromSelection && v->BlockStatus) {
+
+ int XL,XR;
+ int YL,YR;
+
+ GetBlockCoord(curView, &XL, &YL, &XR, &YR);
+ startingCol = XL;
+
+ //When replacing, we want to first replace the word selected
+ if (!frMem.replacing) {
+ startingCol++;
+ }
+
+ //Adjust stop column
+ if (YL == frMem.stopLine) {
+ frMem.stopCol = XL;
+ }
+ }
+
+ //Scan text from current line till end of file
+ if (!FirstLine(v->Doc, &pl, &startingLine, &pb)) {
+ goto err;
+ }
+
+ do {
+
+ found = SearchLineForw(startingLine, &startingCol, &endingCol, findWhat);
+ if (frMem.hadError) {
+ goto out;
+ }
+ if (found) {
+ break;
+ }
+
+ if (!NextLine(v->Doc, &pl, &startingLine, &pb)){
+ goto err;
+ }
+ frMem.oneLineDone = TRUE;
+
+ } while (startingLine != LAST_LINE);
+ CloseLine(v->Doc, &pl, startingLine, &pb);
+
+ //Scan text from beginning till current line
+ if (!found) {
+
+ if (!frMem.replaceAll && (!frMem.allFileDone || !frMem.replacing)) {
+ if (status.hidden) {
+ ErrorBox(STA_Find_Hit_EOF);
+ } else {
+ StatusText(STA_Find_Hit_EOF, STATUS_INFOTEXT, FALSE);
+ }
+ }
+
+ startingLine = 0;
+ if (!FirstLine(v->Doc, &pl, &startingLine, &pb)) {
+ goto err;
+ }
+
+ do {
+ found = SearchLineForw(startingLine,
+ &startingCol,
+ &endingCol,
+ findWhat);
+ if (frMem.hadError) {
+ goto out;
+ }
+ if (found) {
+ break;
+ }
+ if (!NextLine(v->Doc, &pl, &startingLine, &pb)) {
+ goto err;
+ }
+ frMem.oneLineDone = TRUE;
+ } while (startingLine != LAST_LINE
+ || startingLine - 1 <= frMem.line);
+ CloseLine(v->Doc, &pl, startingLine, &pb);
+ }
+
+ if (found) {
+
+ //Next find will start from here
+ frMem.line = startingLine - 1;
+ frMem.leftCol = startingCol;
+
+ if (frMem.replacing) {
+ frMem.rightCol = endingCol;
+ } else {
+ frMem.rightCol = startingCol + 1;
+ }
+
+ if (!frMem.replaceAll) {
+ RefreshView(startingCol, endingCol, selectFoundText);
+ }
+
+ } else if (errorIfNotFound) {
+
+ if (findReplace.regExpr) {
+ ErrorBox(ERR_No_RegExp_Match, (LPSTR)findReplace.findWhat);
+ } else {
+ ErrorBox(ERR_String_Not_Found, (LPSTR)findReplace.findWhat);
+ }
+
+ }
+
+ //Restore cursor
+ SetCursor(hSaveCursor);
+
+ return found;
+
+ err : {
+ //Restore cursor
+ SetCursor(hSaveCursor);
+
+ Assert(FALSE);
+ return FALSE;
+ }
+
+ out : {
+ //Restore cursor
+ SetCursor(hSaveCursor);
+
+ CloseLine(v->Doc, &pl, startingLine, &pb);
+
+ return FALSE;
+ }
+}
+
+void FAR PASCAL
+ReplaceOne(
+ void
+ )
+{
+ BOOL prevStopMark = stopMarkStatus;
+
+ int repLen = lstrlen(findReplace.replaceWith);
+
+ DestroyRecBuf(Views[curView].Doc, REC_REDO);
+
+ //Do the replacement
+ DeleteBlock(Views[curView].Doc,
+ frMem.leftCol,
+ frMem.line,
+ frMem.rightCol,
+ frMem.line);
+
+ if (repLen > 0) {
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that this record have no stop marks
+ stopMarkStatus = HAS_NO_STOP;
+
+ InsertBlock(Views[curView].Doc,
+ frMem.leftCol,
+ frMem.line,
+ repLen,
+ (LPSTR)findReplace.replaceWith);
+
+ //Put undo/redo engine back in normal state
+ if (prevStopMark == HAS_STOP) {
+ stopMarkStatus = HAS_STOP;
+ }
+ }
+
+ //Reajust the stop column if line is the stopLine and if we
+ //replaced before the stop column
+ if (frMem.line == frMem.stopLine && frMem.leftCol < frMem.stopCol) {
+ frMem.stopCol += repLen - (frMem.rightCol - frMem.leftCol);
+ }
+
+ //Reajust the next start
+ frMem.rightCol = frMem.leftCol + repLen;
+
+ //Count the occurences
+ frMem.nbReplaced++;
+}
+
+void FAR PASCAL
+ReplaceAll(
+ void
+ )
+{
+ BOOL prevStopMark = stopMarkStatus;
+
+ //More than 1 edit action for this, operation. Tell the
+ //undo/redo engine that records have no stop marks after
+ //this record
+ stopMarkStatus = NEXT_HAS_NO_STOP;
+
+ ReplaceOne();
+ while(FindNext(frMem.line, frMem.rightCol, FALSE, TRUE, FALSE)
+ && !frMem.allFileDone && !frMem.hadError) {
+ ReplaceOne();
+ }
+
+ InvalidateLines(curView, 0, LAST_LINE, FALSE);
+
+ //Put undo/redo engine back in normal state
+ if (prevStopMark == HAS_STOP) {
+ stopMarkStatus = HAS_STOP;
+ }
+}
+
+void FAR PASCAL
+Replace(
+ void
+ )
+{
+ MSG msg;
+ NPVIEWREC v = &Views[curView];
+
+ Assert(v->Doc >= 0);
+
+ //If we replace all, do it. Else control replace with a modeless box
+ if (frMem.replaceAll) {
+ ReplaceAll();
+ } else {
+ //Create the Confirm dialog box (modeless)
+ //Dbg((LONG) (frMem.lpConfirmProc = MakeProcInstance(DlgConfirm, hInst)));
+
+ frMem.lpConfirmProc = (WNDPROC)DlgConfirm;
+
+ Dbg(frMem.hDlgConfirmWnd = CreateDialog(hInst,
+ MAKEINTRESOURCE(DLG_CONFIRM),
+ hwndFrame,
+ frMem.lpConfirmProc));
+ //Now show Confirm dialog
+ SetDialogPos(TRUE, frMem.hDlgConfirmWnd);
+
+ frMem.exitModelessReplace = FALSE;
+
+ //Process our message loop until user Confirm dialog box is over
+ while (!frMem.exitModelessReplace
+ && hwndActiveEdit
+ && !TerminatedApp
+ && GetMessage(&msg, NULL, 0, 0))
+ {
+ if (msg.message == WM_SYSKEYDOWN
+ && (msg.wParam >= '0' && msg.wParam <= '9'))
+ {
+
+ SetFocus(hwndFrame);
+ ProcessQCQPMessage(&msg);
+
+ } else if (msg.message == WM_KEYDOWN && msg.wParam == VK_F3) {
+
+ if (GetFocus() != frMem.hDlgConfirmWnd) {
+
+ ProcessQCQPMessage(&msg);
+
+ } else {
+ frMem.exitModelessReplace = (!FindNext(frMem.line,
+ frMem.rightCol,
+ FALSE,
+ TRUE,
+ FALSE)
+ || frMem.allFileDone
+ || frMem.hadError);
+ }
+
+ } else if (IsDialogMessage(frMem.hDlgConfirmWnd, &msg)) {
+
+ if (msg.message == WM_KEYDOWN && msg.wParam == VK_F1) {
+ Dbg(PostMessage(frMem.hDlgConfirmWnd,
+ WM_COMMAND,
+ IDWINDBGHELP,
+ 0L));
+ }
+
+ } else {
+
+ ProcessQCQPMessage(&msg);
+
+ }
+ }
+
+ findReplace.goUp = frMem.goUpCopy;
+
+ if (!TerminatedApp && hwndActiveEdit) {
+ SetFocus(hwndActiveEdit);
+ }
+
+ //Destroy the Confirm dialog box
+ if (IsWindow(frMem.hDlgConfirmWnd)) {
+ Dbg(DestroyWindow(frMem.hDlgConfirmWnd));
+ frMem.hDlgConfirmWnd = 0;
+ }
+
+ //Destroy proc instance
+ //FreeProcInstance(frMem.lpConfirmProc);
+
+ }
+
+ if (!TerminatedApp && hwndActiveEdit) {
+
+ //Clear selection
+ ClearSelection(curView);
+ if (frMem.replaceAll) {
+ PosXY(curView, v->X, v->Y, TRUE);
+ } else {
+ PosXY(curView, v->BlockXL, v->BlockYL, TRUE);
+ }
+
+ //Prompt the number of replace done (if any)
+ if (frMem.nbReplaced) {
+ if (status.hidden) {
+ ErrorBox(SYS_Nb_Of_Occurrences_Replaced, frMem.nbReplaced);
+ } else {
+ StatusText(SYS_Nb_Of_Occurrences_Replaced,
+ STATUS_INFOTEXT,
+ FALSE,
+ frMem.nbReplaced);
+ }
+ }
+
+ }
+
+ frMem.replaceAll = FALSE;
+ frMem.replacing = FALSE;
+
+}
+
+/*** Find
+**
+** Synopsis:
+** void = Find()
+**
+** Entry:
+** None
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function deals with the "during" find dialog box. It looks
+** for the "next" item if needed
+**
+*/
+
+void FAR PASCAL Find(void)
+{
+ MSG msg;
+
+ //Control find progression with a modeless box
+ //Create the FindNext dialog box (modeless)
+
+ //Dbg((LONG) (frMem.lpFindNextProc = MakeProcInstance(DlgFindNext, hInst)));
+
+ frMem.lpFindNextProc = (WNDPROC)DlgFindNext;
+
+ Dbg(frMem.hDlgFindNextWnd = CreateDialog(hInst,
+ MAKEINTRESOURCE(DLG_FINDNEXT),
+ hwndFrame,
+ frMem.lpFindNextProc));
+
+ //Now show FindNext dialog
+
+ SetDialogPos(TRUE, frMem.hDlgFindNextWnd);
+
+ frMem.exitModelessFind = FALSE;
+
+ //Process our message loop until user FindNext dialog box is over
+
+ while (!frMem.exitModelessFind
+ && hwndActiveEdit
+ && !TerminatedApp
+ && GetMessage(&msg, NULL, 0, 0))
+ {
+
+ if (msg.message == WM_KEYDOWN && msg.wParam == VK_F3) {
+ if (GetFocus() == frMem.hDlgFindNextWnd) {
+ frMem.exitModelessFind = (!FindNext(frMem.line,
+ frMem.rightCol,
+ FALSE,
+ TRUE,
+ FALSE)
+ || frMem.allFileDone
+ || frMem.hadError);
+ } else {
+ ProcessQCQPMessage(&msg);
+ }
+ } else if (msg.message == WM_SYSKEYDOWN
+ && (msg.wParam >= '0' && msg.wParam <= '9'))
+ {
+ SetFocus(hwndFrame);
+ ProcessQCQPMessage(&msg);
+ } else if (IsDialogMessage(frMem.hDlgFindNextWnd, &msg)) {
+ if (msg.message == WM_KEYDOWN && msg.wParam == VK_F1) {
+ PostMessage(frMem.hDlgFindNextWnd, WM_COMMAND, IDWINDBGHELP, 0L);
+ }
+ } else {
+ ProcessQCQPMessage(&msg);
+ }
+ }
+
+ //Give focus to the edit window
+
+ if (!TerminatedApp && hwndActiveEdit) {
+
+ SetFocus(hwndActiveEdit);
+
+ //Clear the selection
+ if (Views[curView].Doc >= 0) {
+ ClearSelection(curView);
+
+ if (frMem.allTagged) {
+ PosXY(curView, 0, Views[curView].BlockYL, TRUE);
+ } else if (Views[curView].BlockXL != Views[curView].X) {
+ PosXY(curView, Views[curView].X, Views[curView].Y, TRUE);
+ } else {
+ PosXY(curView,
+ Views[curView].BlockXL,
+ Views[curView].BlockYL,
+ TRUE);
+ }
+ }
+ }
+
+ //Destroy the FindNext dialog box
+
+ if (IsWindow(frMem.hDlgFindNextWnd)) {
+ Dbg(DestroyWindow(frMem.hDlgFindNextWnd));
+ frMem.hDlgFindNextWnd = 0;
+ }
+
+ //Destroy proc instance
+ //FreeProcInstance(frMem.lpFindNextProc);
+
+ return;
+} /* Find() */
+
+void FAR PASCAL TagAll(
+ int y)
+{
+ Assert(Views[curView].Doc >= 0);
+
+ frMem.replaceAll = TRUE;
+ Views[curView].X = Views[curView].Y = frMem.line = frMem.rightCol = 0;
+ SetStopLimit();
+ while (FindNext(frMem.line, frMem.rightCol, FALSE, TRUE, FALSE)
+ && !frMem.allFileDone
+ && !frMem.hadError)
+ {
+ LineStatus(Views[curView].Doc,
+ frMem.line + 1,
+ TAGGED_LINE,
+ LINESTATUS_ON,
+ FALSE,
+ FALSE);
+ }
+
+ frMem.replaceAll = FALSE;
+ ClearSelection(curView);
+ InvalidateLines(curView, 0, LAST_LINE, FALSE);
+ PosXY(curView, 0 , y, FALSE);
+}
+
+BOOL FAR PASCAL
+InsertInPickList(
+ WORD type
+ )
+{
+ int i, j;
+ LPSTR s[MAX_PICK_LIST];
+ BOOL found = FALSE;
+ int nb = findReplace.nbInPick[type];
+ LPSTR newString;
+
+ if (type == FIND_PICK) {
+ newString = findReplace.findWhat;
+ } else {
+ newString = findReplace.replaceWith;
+ }
+
+ //First lock memory for existing strings
+ for (i = 0; i < nb; i++) {
+ Dbg(s[i] = (LPSTR)GlobalLock(findReplace.hPickList[type][i]));
+ }
+
+ //First check if string is not already in list
+ i = 0;
+ while (i < nb && !found) {
+ found = (_fstrcmp(s[i], newString) == 0);
+ if (!found) {
+ i++;
+ }
+ }
+
+ if (found) {
+
+ //String already exist, move it to first place
+ if (i > 0) {
+ lstrcpy((LPSTR)szTmp, s[i]);
+ for (j = i; j > 0; j--) {
+ lstrcpy(s[j], s[j - 1]);
+ }
+ lstrcpy(s[0], (LPSTR)szTmp);
+ }
+ } else {
+
+ //String not found, do we have a new space to create ?
+ if (nb < MAX_PICK_LIST) {
+ Dbg(findReplace.hPickList[type][nb] =
+ GlobalAlloc(GMEM_MOVEABLE, MAX_USER_LINE + 1));
+ Dbg(s[nb] = (LPSTR)GlobalLock(findReplace.hPickList[type][nb]));
+ nb++;
+ }
+
+ //Shift list
+ for (i = nb - 1; i >= 1; i--) {
+ lstrcpy(s[i], s[i - 1]);
+ }
+ lstrcpy(s[0], newString);
+ }
+
+ //Now list is Most Recently Used sorted, unlock memory
+ for (i = 0 ; i < nb; i++) {
+ Dbg(GlobalUnlock (findReplace.hPickList[type][i]) == FALSE);
+ }
+
+ findReplace.nbInPick[type] = nb;
+ return !found;
+}
+
+void FAR PASCAL
+RemoveFromPick(
+ WORD type)
+{
+ int i;
+
+ if (findReplace.nbInPick[type] <= 0) {
+ return;
+ }
+
+ //Free the first element
+ Dbg(GlobalFree(findReplace.hPickList[type][0]) == NULL);
+
+ //Shift the pick list
+ for (i = 1; i < findReplace.nbInPick[type]; i++) {
+ findReplace.hPickList[type][i - 1] = findReplace.hPickList[type][i];
+ }
+
+ findReplace.nbInPick[type]--;
+}
+
diff --git a/private/windbg/windbg/fonts.c b/private/windbg/windbg/fonts.c
new file mode 100644
index 000000000..79ddab1a2
--- /dev/null
+++ b/private/windbg/windbg/fonts.c
@@ -0,0 +1,288 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Fonts.c
+
+Abstract:
+
+ This module contains the font support for Windbg.
+
+Author:
+
+ David J. Gilman (davegi) 30-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 11-Sep-1992
+
+Environment:
+
+ CRT, Windows, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// Common Dlg IDs
+//
+
+extern HWND GetLocalHWND(void);
+extern HWND GetFloatHWND(void);
+extern HWND GetWatchHWND(void);
+extern HWND GetCpuHWND(void);
+
+
+void ComputeOverhangs (HDC, int, int, LPINT);
+
+
+LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+
+
+//#undef GetCurrentWindowType
+//#define GetCurrentWindowType () (0)
+
+
+// Font for each window type in Windbg, ordered by the WINDOW_FONT type.
+
+
+//LOGFONT WindowLogFont [sizeof (WINDOW_FONT)];
+
+
+// Determines if the system font should be used (i.e. SelectFont or
+// SetWindowLogFonts) have never been called.
+
+
+//BOOL UseSystemFontFlag = TRUE;
+
+
+
+/*++
+
+Routine Description:
+
+ This routine is the hook proc for the common dialogs ChooseFont API.
+ The only functionality it adds is to communicate the state of the
+ Make Default check box.
+
+Arguments:
+
+ Standard proc arguments.
+
+Return Value:
+
+ BOOL - Returns TRUE is the supplied message is handled.
+
+--*/
+
+
+BOOL ChooseFontHookProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static LPCHOOSEFONT Cf;
+
+ switch( message ) {
+
+ case WM_INITDIALOG:
+
+ //
+ // Capture the pointer to the CHOOSEFONT structure.
+ //
+
+ Cf = ( LPCHOOSEFONT ) lParam;
+
+ //
+ // Assume that the to be selected font is not the default.
+ //
+
+ Cf->lCustData = FALSE;
+ SendDlgItemMessage( hDlg, IDC_CHECK_MAKE_DEFAULT, BM_SETCHECK, 0, 0 );
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam )) {
+
+ case IDWINDBGHELP:
+ case pshHelp:
+
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_FONTDLG_HELP));
+ return TRUE;
+
+ case IDC_CHECK_MAKE_DEFAULT:
+
+ //
+ // The user wants the selected font to be the default for all
+ // Windbg windows.
+ //
+
+ Cf->lCustData = TRUE;
+ return TRUE;
+
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+
+BOOL SelectFont (HWND hWnd)
+{
+ CHOOSEFONT Cf;
+ LOGFONT TmpWindowLogFont;
+ NPVIEWREC v = &Views[curView];
+
+
+
+ GetObject (v->font, sizeof (LOGFONT), &TmpWindowLogFont);
+
+ // Initialize the CHOOSEFONT structure.
+
+ Cf.lStructSize = sizeof (CHOOSEFONT);
+ Cf.hwndOwner = hWnd;
+ Cf.hDC = NULL;
+ Cf.lpLogFont = &TmpWindowLogFont;
+ Cf.iPointSize = 0;
+ Cf.Flags = CF_ENABLEHOOK
+ | CF_ENABLETEMPLATE
+ | CF_INITTOLOGFONTSTRUCT
+ | CF_SCREENFONTS
+ | CF_FORCEFONTEXIST
+ | CF_NOSIMULATIONS
+#ifdef DBCS
+ | CF_NOVERTFONTS
+#endif
+ | CF_SHOWHELP;
+
+ Cf.rgbColors = RGB (0, 0, 0);
+ Cf.lCustData = 0;
+ Cf.lpfnHook = ChooseFontHookProc;
+ Cf.lpTemplateName = MAKEINTRESOURCE (DLG_CHOOSEFONT);
+ Cf.hInstance = NULL;
+ Cf.lpszStyle = NULL;
+ Cf.nFontType = SCREEN_FONTTYPE;
+ Cf.nSizeMin = 0;
+ Cf.nSizeMax = 0;
+
+ // Let the user choose a font.
+
+ if (ChooseFont (&Cf)) {
+ NPDOCREC d;
+ TEXTMETRIC tm;
+ HDC hDC;
+ UINT uSwitch;
+
+ if (v->Doc < -1)
+ {
+ uSwitch = -(v->Doc);
+ }
+ else
+ {
+ d = &Docs[v->Doc]; //Views[indx].Doc
+ uSwitch = d->docType;
+ }
+
+ switch (uSwitch) {
+
+ case WATCH_WIN:
+ SendMessageNZ( GetWatchHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case LOCALS_WIN:
+ SendMessageNZ( GetLocalHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case CPU_WIN:
+ SendMessageNZ( GetCpuHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case FLOAT_WIN:
+ SendMessageNZ( GetFloatHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case CALLS_WIN:
+ SendMessageNZ( GetCallsHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ default:
+ //Initialize font information for current view
+ Dbg(hDC = GetDC(v->hwndClient));
+ Dbg(v->font = CreateFontIndirect(Cf.lpLogFont));
+ Dbg(SelectObject(hDC, v->font));
+ Dbg(GetTextMetrics (hDC, &tm));
+ v->charHeight = tm.tmHeight;
+ v->maxCharWidth =tm.tmMaxCharWidth;
+ v->aveCharWidth =tm.tmAveCharWidth;
+ v->charSet = tm.tmCharSet;
+ v->Tmoverhang = tm.tmOverhang;
+ GetCharWidth(hDC,
+ 0,
+ MAX_CHARS_IN_FONT - 1,
+ (LPINT)v->charWidth);
+
+#ifdef DBCS
+ GetDBCSCharWidth(hDC, &tm, v);
+#endif
+
+ //ComputeOverhangs (hDC, 0,MAX_CHARS_IN_FONT -1, (LPINT)v->charWidth);
+
+ Dbg(ReleaseDC (v->hwndClient, hDC));
+
+ //Refresh display to print text with new font
+ InvalidateRect(v->hwndClient, (LPRECT)NULL, FALSE);
+ SendMessage(v->hwndClient, WM_FONTCHANGE, 0, 0L);
+ DestroyCaret ();
+ CreateCaret(v->hwndClient, 0, 3, v->charHeight);
+ ShowCaret(v->hwndClient);
+ PosXY(curView, v->X, v->Y, FALSE);
+ ReleaseDC (v->hwndClient, hDC);
+ }
+
+ // If the user checked the Make Default button...
+ // Save the user's font selection as the default.
+
+ if (Cf.lCustData == TRUE) {
+ memcpy(
+ &defaultFont,
+ Cf.lpLogFont,
+ sizeof (LOGFONT)
+ );
+ }
+
+ return TRUE;
+
+ } else {
+
+ // The user pressed Cancel or closed the dialog.
+
+ return FALSE;
+ }
+}
+
+/*=======================================================================*/
+
+void ComputeOverhangs (HDC hdc, int cstart, int cend, LPINT charwidths)
+{
+ int i;
+ SIZE csize;
+ char cstring[2];
+
+
+ for (i = cstart; i <= cend; i++)
+ {
+ cstring[0] = (char)i;
+ GetTextExtentPoint (hdc,cstring,1,&csize);
+ charwidths[i] = (int)csize.cx;
+ }
+}
diff --git a/private/windbg/windbg/fs.c b/private/windbg/windbg/fs.c
new file mode 100644
index 000000000..437250f3a
--- /dev/null
+++ b/private/windbg/windbg/fs.c
@@ -0,0 +1,118 @@
+#include "precomp.h"
+#pragma hdrstop
+
+//FsQueryPath(sz, lpb, cb)
+
+
+USHORT PASCAL FsCanonFilename(PSTR szName, PSTR pbBuf, USHORT cbBuf)
+{
+#ifdef JIMSCH
+ char * pbSrc;
+ int cbWrk = FsQueryMaxPath()*2;
+ char * pbWrk;
+ char * pb1;
+ char * pb2;
+
+ if ((pbSrc = malloc(_fstrlen(szName)+1)) == NULL) {
+ error = ERROR_OUT_OF_NEAR_MEM;
+ }
+ _fstrcpy(pbSrc, szName);
+
+ if ((pbWrk = malloc(cbWrk)) == NULL) {
+ }
+
+ FsCvtPathSep(pbSrc);
+
+ pb1 = pbSrc;
+ pb2 = pbWrk;
+
+ if (pb1[1] == ':') {
+ *pb2++ = *pb1++; /* Copy over drive leter and colon */
+ *pb2++ = *pb1++;
+ } else {
+ *pb2++ = FsQueryCurDisk();
+ *pb2++ = ':';
+ }
+
+ if (*pb1 == '\\') {
+ _fstrcpy(pb2, pb1);
+ } else {
+ *pb2++ = '\\';
+ if (!FsQueryCurDir(pbWrk[0], pb2, cbWrk-3)) {
+ error;
+ }
+ pb2 += strlen(pb2);
+ *pb2++ = '\\';
+ _fstrcpy(pb2, pb1);
+ }
+
+ pb1 = pbWrk;
+ pb2 = pbBuf;
+
+ while (*pb1) {
+ if (*pb1 == '.') {
+ if (pb[1] == '\\') {
+ // goto DotSlash
+
+ } else if (pb[1] == '.') {
+ if (pb[2] == '\\') {
+ /*
+ ** Found a "..\" construct. If the last character stored
+ ** in the destination buffer was '\', attempt to remove
+ ** the previous directory. Note that the user could
+ ** try and fool use with something like
+ **
+ ** X:\..\foo.c
+ **
+ ** (i.e., we cannot back out the directory), so we check
+ ** for this case explicitly. If we find this case, fail.
+ **
+ ** If the last character stored in the destination buffer
+ ** was NOT '\', just store the first '.' character from
+ ** the work buffer (would be something of the form
+ ** "dir\subdir..\file", where "subdir.." is the name
+ ** of a directory).
+ **
+ */
+
+ if (pb2[-1] == '\\') {
+
+ }
+
+ }
+ }
+ }
+ // FCF_StoreChar
+ *pb2++ = *pb1++;
+ cbBuf -= 1;
+ if (cbBuf == 1) {
+ }
+ }
+#endif
+ Unused (cbBuf);
+ strcpy(pbBuf, szName);
+ AnsiUpper(pbBuf);
+
+ return(TRUE);
+} /* FsCanonFileName() */
+
+
+VOID PASCAL FsChgExt( PSTR sz1, PSTR sz2)
+{
+ Unused(sz1);
+ Unused(sz2);
+ return;
+} /* FsChgExt() */
+
+PSTR PASCAL FsQueryExt( PSTR sz1 )
+{
+ PSTR pch = sz1 + strlen(sz1);
+
+ while ((*pch != '.') && (*pch != '\\')) {
+ pch -= 1;
+ }
+
+ if (*pch == '.') return (pch+1);
+ return NULL;
+} /* FsQueryExt() */
+
diff --git a/private/windbg/windbg/function.c b/private/windbg/windbg/function.c
new file mode 100644
index 000000000..70190f230
--- /dev/null
+++ b/private/windbg/windbg/function.c
@@ -0,0 +1,421 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Author:
+
+ Griffith Kadnier (v-griffk)
+
+Environment:
+
+ Win32 - User
+
+Notes:
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef DBCS
+#include <mbstring.h>
+#define strpbrk _mbspbrk
+#define strchr _mbschr
+#endif
+
+
+/************************** Data declaration *************************/
+
+extern CXF CxfIp;
+extern SHF FAR *Lpshf;
+
+
+typedef struct _FUNCLIST {
+ PSTR Str;
+ ADDR Addr;
+} FUNCLIST, *PFUNCLIST;
+
+
+PFUNCLIST FuncList;
+int FuncListSize;
+BOOL FuncFound;
+ADDR FuncAddr;
+
+BOOL FAR PASCAL EXPORT
+DlgFuncResolve(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+extern EESTATUS PASCAL
+BPADDRFromTM(
+ PHTM,
+ unsigned short FAR *,
+ LPADDR
+ );
+
+/************************** Code *************************/
+
+/*** LocateFunction
+**
+** Synopsis:
+** bool = LocateFunction(szStr, pCXTOut)
+**
+** Entry:
+** szStr - string containning the address to goto
+** pCXTOut - pointer to context in which to place the address
+**
+** Returns:
+** TRUE if the address was successfuly found and FALSE otherwise
+**
+** Description:
+**
+*/
+
+BOOL NEAR PASCAL
+LocateFunction(
+ PSTR szStr,
+ PADDR pAddr
+ )
+{
+ TML TMLT;
+ TML TMLT2;
+ USHORT bpsegtype = EECODE;
+ int stringindex;
+ PHTM TMList;
+ PHTM pTMList;
+ PHTM pTMList2;
+ int i;
+
+ EESTATUS eeErr;
+ PSTR p;
+ PSTR Function;
+ PSTR Module;
+ char Buffer[ 256 ];
+ BOOL Ok = FALSE;
+ BOOL Found = FALSE;
+ HEXE hexe = (HEXE) NULL;
+ PSTR Str;
+
+
+
+ FuncList = NULL;
+ FuncListSize = 0;
+
+ eeErr = EEParseBP(szStr, radix, fCaseSensitive, &CxfIp, &TMLT, 0L,
+ &stringindex, FALSE);
+
+ if (eeErr == EEGENERAL) {
+
+ /*
+ * Kill current error message
+ */
+
+ EEFreeTML(&TMLT);
+
+
+ //
+ // If no module was specified, try all modules.
+ //
+
+ strcpy( Buffer, szStr );
+
+ if ( p = strchr( Buffer, ',' ) ) {
+
+ if ( p = strpbrk( p+1, ",}" ) ) {
+
+ if ( *p == '}' ) {
+
+ *p++ = ',';
+ *p = '\0';
+ Ok = TRUE;
+
+ } else {
+
+#ifdef DBCS
+ if (!IsDBCSLeadByte(*p)) {
+#endif
+ p++;
+ while ( *p == ' ' && *p == '\t' ) {
+ p++;
+ }
+
+ if ( *p == '}' ) {
+ *p = '\0';
+ Ok = TRUE;
+ }
+#ifdef DBCS
+ }
+#endif
+ }
+
+ if ( Ok ) {
+ Function = szStr + (p - Buffer);
+ Module = p;
+ }
+ }
+
+ } else {
+
+ strcpy( Buffer, "{,," );
+ Module = Buffer + strlen( Buffer );
+ Function = szStr;
+ Ok = TRUE;
+ }
+
+ if ( Ok ) {
+ Str = NULL;
+ TMLT.hTMList = (HDEP) NULL;
+ pTMList = NULL;
+
+ while ((( hexe = SHGetNextExe( hexe ) ) != 0) ) {
+ *Module = '\0';
+ strcat( Buffer, SHGetExeName(hexe));
+ strcat( Buffer, "}" );
+ strcat( Buffer, Function );
+
+ eeErr = EEParseBP(Buffer, radix, fCaseSensitive, &CxfIp,
+ &TMLT2, 0, &stringindex, FALSE);
+
+ if ( eeErr == EENOERROR ) {
+ if ( !pTMList ) {
+
+ TMLT = TMLT2;
+ pTMList = (HTM FAR *) MMLpvLockMb( TMLT.hTMList );
+
+ } else {
+
+ pTMList2 = (HTM FAR *) MMLpvLockMb( TMLT2.hTMList );
+
+ for (i=0; i< (int) TMLT2.cTMListAct; i++) {
+ DAssert( TMLT2.cTMListAct < TMLT.cTMListMax );
+ pTMList[ TMLT.cTMListAct++ ] = pTMList2[ i ];
+ pTMList2[i] = (HDEP) NULL;
+ }
+
+ MMbUnlockMb( TMLT2.hTMList );
+
+ TMLT2.cTMListAct = 0;
+ EEFreeTML(&TMLT2);
+ }
+ }
+ }
+
+ if (pTMList) {
+ MMbUnlockMb( TMLT.hTMList );
+ eeErr = EENOERROR;
+ } else {
+ eeErr = EEGENERAL;
+ }
+ }
+ }
+
+ if (eeErr == EENOERROR) {
+ TMList = (PHTM) MMLpvLockMb( TMLT.hTMList );
+
+ while (TMLT.cTMListAct > 1) {
+ eeErr = (EESTATUS) BPTResolve( szStr, &TMLT, &CxfIp, FALSE);
+
+ if (eeErr != EENOERROR) {
+ break;
+ }
+
+ if (TMLT.cTMListAct > 1) {
+ ErrorBox(0);
+ }
+ }
+
+ if (TMLT.cTMListAct == 1) {
+ if (!(eeErr = EEvaluateTM( &TMList[0], SHpFrameFrompCXF(&CxfIp),
+ EEBPADDRESS))) {
+ eeErr = BPADDRFromTM( &TMList[0], &bpsegtype, pAddr);
+ }
+ }
+ }
+
+ return eeErr == EENOERROR;
+} /* LocateFunction() */
+
+
+BOOL FAR PASCAL EXPORT
+DlgFuncResolve(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ int Index;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+
+ case WM_INITDIALOG:
+
+ FuncFound = FALSE;
+
+ for ( Index = 0; Index < FuncListSize; Index++ ) {
+ SendMessage( GetDlgItem(hDlg, ID_FUNCRES_LIST ),
+ LB_ADDSTRING, 0, (LONG)(LPSTR)FuncList[Index].Str );
+ }
+ break;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+ case ID_FUNCRES_USE:
+ Index = SendMessage( GetDlgItem(hDlg, ID_FUNCRES_LIST ),
+ LB_GETCURSEL, 0, 0L );
+ FuncAddr = FuncList[Index].Addr;
+ FuncFound = TRUE;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+
+ case IDCANCEL:
+ FuncFound = FALSE;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT,
+ ID_FUNCRES_HELP) );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+/*** DlgFunction
+**
+** Synopsis:
+** bool = DlgFunction(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to dialog box
+** message - Message to be processed
+** wParam - info about current message
+** lParam - info about current message
+**
+** Returns:
+** TRUE if we handled the message and FALSE otherwise
+**
+** Description:
+** This function is the dialog proc for the View.Address menu item.
+** It will get an address from the user and will change the the requested
+** source window and move the cursor to that line.
+*/
+
+BOOL FAR PASCAL
+DlgFunction(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ char szFuncName[128];
+ HWND hFuncName;
+ ADDR addr;
+
+ Unreferenced( lParam );
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ /*
+ ** Initialize the edit item for the address field
+ */
+
+ Dbg((hFuncName = GetDlgItem(hDlg, ID_FUNCTION_FUNCNAME))!=NULL);
+ Dbg(SendMessage(hFuncName, EM_LIMITTEXT, sizeof(szFuncName)-1, 0L));
+
+ /*
+ ** Initialise entry field with current selection
+ */
+
+ *szFuncName = '\0';
+
+ if (Views[curView].Doc > -1) {
+ if ((hwndActiveEdit != NULL) &&
+ (Docs[Views[curView].Doc].docType == DOC_WIN)) {
+ BOOL lookAround = TRUE;
+
+ GetCurrentText(curView, &lookAround, (LPSTR)szFuncName,
+ min(MAX_USER_LINE, sizeof(szFuncName)-1),
+ NULL, NULL);
+ }
+ }
+
+ /*
+ ** Send the text and select it
+ */
+
+ SendMessage(hFuncName, WM_SETTEXT, 0, (DWORD)(LPSTR)szFuncName);
+#ifdef WIN32
+ SendMessage(hFuncName, EM_SETSEL, 0, (DWORD) -1);
+#else
+ SendMessage(hFuncName, EM_SETSEL, 0, MAKELONG(0, 0x7FFF));
+#endif
+
+ SetFocus(hFuncName);
+ return (FALSE);
+
+ case WM_COMMAND:
+ switch (wParam) {
+ /*
+ ** Get the address string and attempt to change to the
+ ** desired address
+ */
+
+ case IDOK :
+ Dbg((hFuncName = GetDlgItem(hDlg, ID_FUNCTION_FUNCNAME))!=NULL);
+ GetDlgItemText(hDlg, ID_FUNCTION_FUNCNAME,
+ (LPSTR)szFuncName, sizeof(szFuncName));
+
+ if (!LocateFunction(szFuncName, &addr)) {
+
+ ErrorBox2(hDlg, MB_TASKMODAL, ERR_Function_Locate);
+ SendMessage(hFuncName, EM_SETSEL, 0, (DWORD) -1);
+ SetFocus(hFuncName);
+
+ } else {
+
+ if (!MoveEditorToAddr(&addr)) {
+ if (disasmView == -1) {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ }
+ }
+
+ if (disasmView != -1) {
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ ViewDisasm(&addr, disasmForce);
+ }
+
+ EndDialog(hDlg, TRUE);
+ }
+
+ return TRUE;
+
+ case IDCANCEL :
+ EndDialog(hDlg, FALSE);
+ return (TRUE);
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg,szHelpFileName,HELP_CONTEXT,ID_FUNCTION_HELP));
+ return (TRUE);
+ }
+
+ break;
+ }
+
+ return (FALSE);
+} /* DlgFunction() */
diff --git a/private/windbg/windbg/include/apisupp.h b/private/windbg/windbg/include/apisupp.h
new file mode 100644
index 000000000..274638c1c
--- /dev/null
+++ b/private/windbg/windbg/include/apisupp.h
@@ -0,0 +1,106 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Apisupp.h
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _APISUPP_ )
+#define _APISUPP_
+
+#include "cvtypes.hxx"
+#include "od.h"
+
+#define MHOmfLock(a) (a)
+#define MHOmfUnLock(a)
+
+extern LPTD LptdFuncEval;
+
+void
+CopyShToEe(
+ void
+ );
+
+void
+SYSetFrame(
+ FRAME*
+ pFrame
+ );
+
+XOSD
+SYFixupAddr(
+ PADDR paddr
+ );
+
+XOSD
+SYUnFixupAddr(
+ PADDR addr
+ );
+
+XOSD
+SYSanitizeAddr(
+ PADDR paddr
+ );
+
+XOSD
+SYIsStackSetup(
+ HPID hpidCurr,
+ HTID htidCurr,
+ PADDR paddr
+ );
+
+VOID
+SetFindExeBaseName(
+ LPSTR lpName
+ );
+
+VOID FAR LOADDS PASCAL SplitPath( LSZ lsz1, LSZ lsz2, LSZ lsz3, LSZ lsz4, LSZ lsz5 );
+
+void FAR * PASCAL LOADDS MHAlloc(size_t cb);
+void FAR * PASCAL MHRealloc(void FAR * lpv, size_t cb);
+void PASCAL MHFree(void FAR * lpv);
+
+HDEP PASCAL MMAllocHmem(size_t cb);
+HDEP PASCAL MMReallocHmem(HDEP hmem, size_t cb);
+void PASCAL MMFreeHmem(HDEP hmem);
+BOOL PASCAL MMFIsLocked(HDEP hMem);
+
+void*
+MMLpvLockMb(
+ HDEP hmem
+ );
+
+void
+MMbUnlockMb(
+ HDEP hmem
+ );
+
+BOOL PASCAL LOADDS DHGetNumber( char FAR *, int FAR *);
+
+
+typedef struct _NEARESTSYM {
+ CXT cxt;
+ ADDR addrP;
+ HSYM hsymP;
+ ADDR addrN;
+ HSYM hsymN;
+} NEARESTSYM, *LPNEARESTSYM;
+
+LPSTR GetNearestSymbolFromAddr(LPADDR lpaddr, LPADDR lpAddrRet);
+BOOL GetNearestSymbolInfo(LPADDR lpaddr, LPNEARESTSYM lpnsym);
+LPSTR FormatSymbol(HSYM hsym, PCXT lpcxt);
+
+#endif // _APISUPP_
diff --git a/private/windbg/windbg/include/bpitypes.h b/private/windbg/windbg/include/bpitypes.h
new file mode 100644
index 000000000..72430b547
--- /dev/null
+++ b/private/windbg/windbg/include/bpitypes.h
@@ -0,0 +1,115 @@
+/*
+** This file contains the set of internal data structures
+** for the break point engine.
+*/
+
+/*
+** This defines what a parsed but unbound break point line looks
+** like.
+*/
+
+typedef struct BPP {
+
+ //
+ // Mark flags
+ //
+ ULONG fNewMark :1; // Newly Marked
+ ULONG fMarkAdd :1; // Mark for addition
+ ULONG fMarkDelete :1; // Mark for deletion
+ ULONG fMarkDisable :1; // Mark for disable
+ ULONG fMarkEnable :1; // Mark for enable
+ ULONG fMarkChange :1; // Mark for change
+ ULONG fReplacement :1; // Replaces a changed BP
+
+ //
+ // Flags to determine breakpoint type
+ //
+ ULONG fWndProc :1; // Window Proc BP: Requires fCodeAddr
+ ULONG fCodeAddr :1; // Code Addr. BP
+ ULONG fExpression :1; // Expression BP
+ ULONG fMemory :1; // Memory BP
+ ULONG fMsg :1; // Msg BP
+ ULONG fMsgClass :1; // Msg is Msg class (i.e. mask)
+ ULONG fMsgParsed :1; // Msg has been parsed
+ ULONG fTemporary :1; // Temp BP, for gountil
+
+ //
+ // Other flags
+ //
+ ULONG fHighlight :1; // Is the highlight currently marked?
+ ULONG fQuiet :1; // Quiet defer
+ ULONG fProcess :1; // Process set
+ ULONG fThread :1; // Thread set
+
+ UINT iBreakpointNum; // Breakpoint Number
+ BPSTATE bpstate; // BP state
+ HTM hTm; // Handle to expression parse tree
+
+ //
+ // Breakpoint Address
+ //
+ ADDR addr; // CS:IP Address
+ HPID hPid; // PID for the breakpoint
+ HTID hTid; // TID for the breakpoint
+ CXF Cxf; // Breakpoint context
+
+ UINT iPid; // Process number
+ UINT iTid; // Thread number
+
+ DWORD dwNotify; // Tag to bind w/ em/dm's BP
+
+
+ //
+ // Highlight info
+ //
+ ATOM atmHighlightFile; // File where the hightlight currently is
+ UINT iHighlightLine; // Line where the hightlight currently is
+
+ //
+ // Pass count stuff
+ //
+ UINT iPassCount; // Number of hits left to pass
+ UINT macPassCount; // Original number of hits left to pass
+
+ //
+ // Memory Breakpoint stuff
+ //
+ UINT cbDataSize; // Number of bytes to check
+ ADDR AddrMem; // Memory address to check
+#if 0
+ PBYTE Mem; // Previous memory contents
+#endif
+
+ //
+ // Flags to indicate read, readwrite, execute, or code
+ //
+ DWORD BpType;
+
+ //
+ // Message breakpoint stuff
+ //
+ DWORD Msg; // Msg or Msg class
+ LPMSGMAP MsgMap; // Msg Map
+
+ //
+ // Change handle if marked for change
+ //
+ HBPT ChangeHbpt;
+
+ //
+ // BP options in string & atom form
+ //
+ ATOM atmAddrCxt; // Address Context
+ char *szAddrExpr; // CS:IP Address
+ ATOM atmCxtDef; // BP Cxt. i.e {,file,exe}
+ ATOM atmPassCount; // BP pass count
+ char *szCmdLine; // Commands to execute
+ ATOM atmExpr; // Exp. for Expression BPs
+ ATOM atmData; // Data BP address expression
+ ATOM atmRangeSize; // Data BP data size - see cbDataSize
+ ATOM atmMsg; // Message string
+
+} BPP;
+
+typedef struct BPP FAR * LPBPP;
+
diff --git a/private/windbg/windbg/include/bptypes.h b/private/windbg/windbg/include/bptypes.h
new file mode 100644
index 000000000..8df6eb82a
--- /dev/null
+++ b/private/windbg/windbg/include/bptypes.h
@@ -0,0 +1,196 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Bptypes.h
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _BPTYPES_ )
+#define _BPTYPES_
+
+#include "eeapi.h"
+
+// Just to hide things
+#define HBPI PLLI
+#define HBPT PLLE
+
+typedef struct cpb FAR * _LPCBP;
+
+typedef union dpf {
+ UINT flags;
+ struct {
+ UINT fEmulate : 1; // If emulation is required
+ UINT fFuncBpSet : 1; // if a function breakpoint is set
+ UINT fTpFuncHit : 1; // When we hit a breakpoint set by tracepoint
+ UINT fFuncLoad : 1; // We must load the breakpoint value on function entry
+ UINT fEvalExpr : 1; // Is the expr not an lvalue
+ UINT fDataRange : 1; // if a datarange was specifed
+ UINT fBpRel : 1; // if a code range was specified
+ UINT fContext : 1; // if context checking is required
+ UINT fReg : 1; // if it is in a register
+ UINT fHighReg : 1; // if in the highbyte of reg
+ UINT fUser : 1; // for use WITHIN a proc, up to you how to use
+ UINT fHdwBrk : 1; // Is this a hardware bp
+ UINT HdwReg : 2; // The hardware reg used
+ } f;
+} DPF;
+typedef DPF FAR * PDPF;
+
+typedef struct dpi {
+ union {
+ struct {
+ ADDR DataAddr; // Data address to watch
+ } d;
+ struct {
+ ADDR BlkAddr; // the start address of the block
+ UOFFSET oEnd; // The end offset of the function
+ short oBp; // ofset from the bp
+ FRAME Frame; // the frame
+ } bp;
+ } u;
+ char * pValue; // pointer to the initial value
+ short iReg; // if in register, the reg index
+ USHORT cData; // Number of data items to watch
+ USHORT cbData; // Number of bytes in data item
+ HTM hTM; // a TM handle for the data breakpoint
+} DPI;
+typedef DPI * PDPI;
+
+
+typedef struct PBPD {
+ USHORT hthd;
+ USHORT BPType;
+ PCXF pCXF;
+ USHORT BPSegType;
+ char FAR * szCmd;
+ unsigned int fAmbig;
+ union {
+ ADDR Addr;
+ struct {
+ unsigned int cBPMax;
+ TML TMLT;
+ } u;
+ } u;
+ PDPI pDPI;
+ DPF DPF;
+ USHORT cPass;
+ char FAR * szOptCmd;
+ int iErr;
+ char SubType;
+ int (FAR *lpfnEval)(_LPCBP);// A possible callback function
+ long lData; // User data
+} PBP;
+typedef PBP FAR * PPBP;
+
+extern UINT radix;
+extern char fCaseSensitive;
+
+
+#define BPCODEADDR 1001
+#define BPDATAADDR 1002
+#define BPLENGTH 1003
+#define BPPASSCNT 1004
+#define BADBKPTCMD 1005
+#define WMSGALL 1006
+#define WMSGTYPE 1007
+#define WMSGCLASS 1008
+#define WMSGBPCLASS 1009
+#define WMSGBPTYPE 1010
+#define WMSGDPCLASS 1011
+#define WMSGDPTYPE 1012
+#define WMSGBPALL 1013
+#define WMSGDPALL 1014
+#define BPSTCALLBACK 1015
+#define NOCODE 1019
+#define NOTLVALUE 1020
+
+
+/**********************************************************************/
+
+#define MHOmfUnLock(a)
+
+
+#define bptNext 1
+#define bptPrevious 2
+#define bptFirst 3
+#define bptLast 4
+
+typedef enum {
+ BPNOERROR = 0, // No Error
+ BPBadDataSize = 1,
+ BPBadPassCount = 2,
+ BPBadCmdString = 3,
+ BPBadOption = 4,
+ BPBadAddrExpr = 5,
+ BPBadContextOp = 6,
+ BPOOMemory = 7,
+ BPError = 8,
+ BPBadBPHandle = 9,
+ BPNoMatch = 10,
+ BPAmbigous = 11,
+ BPNoBreakpoint = 12,
+ BPTmpBreakpoint = 13,
+ BPPassBreakpoint = 14,
+ BPBadExpression = 15,
+ BPOutOfSpace = 16,
+ BPBadThread = 17,
+ BPBadProcess = 18,
+ BPCancel = 19
+} BPSTATUS;
+
+
+#define BPLOC 0
+#define BPLOCEXPRTRUE 1
+#define BPLOCEXPRCHGD 2
+#define BPEXPRTRUE 3
+#define BPEXPRCHGD 4
+#define BPWNDPROC 5
+#define BPWNDPROCEXPRTRUE 6
+#define BPWNDPROCEXPRCHGD 7
+#define BPWNDPROCMSGRCVD 8
+
+
+/*
+** Define the states that a breakpoint can have.
+*/
+
+typedef enum {
+ bpstateNotSet = 1, /* Breakpoint is parsed */
+ bpstateVirtual = 2, /* Breakpoint is parsed & Addr-ed */
+ bpstateSet = 4, /* Breakpoint is parsed, Addr-ed & Set */
+ bpstateSets = 7, /* */
+ bpstateDisabled = 0, /* Breakpoint is Disabled */
+ bpstateEnabled = 16, /* Breakpoint is Enabled */
+ bpstateDeleted = 32 /* Breakpoint has been deleted */
+} BPSTATE;
+
+
+/*
+** BreakPoint Format Control Flags
+*/
+
+#define BPFCF_ITEM_COUNT 0x01
+#define BPFCF_ADD_DELETE 0x02
+#define BPFCF_WNDPROC 0x04
+#define BPFCF_WRKSPACE 0x08
+
+/*
+**
+*/
+
+typedef VOID (LOADDS PASCAL FAR * LPFNBPCALLBACK)(HBPT, BPSTATUS);
+
+#endif // _BPTYPES_
diff --git a/private/windbg/windbg/include/breakpts.h b/private/windbg/windbg/include/breakpts.h
new file mode 100644
index 000000000..13f1e3ea0
--- /dev/null
+++ b/private/windbg/windbg/include/breakpts.h
@@ -0,0 +1,302 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+ FILE: BREAKPTS.H
+
+ PURPOSE: Defines and prototypes for the QCQP persistent
+ breakpoint handler.
+
+**********************************************************************/
+
+/*
+** QCWin breakpoint support functions
+*/
+
+void PASCAL BPTResolveAll(HPID,BOOL);
+DWORD PASCAL BPTIsUnresolvedCount(HPID hpid);
+void PASCAL BPTUnResolve(HEXE);
+void PASCAL BPTUnResolveAll(HPID);
+int PASCAL BPTResolve( LPSTR, PVOID, PCXF, BOOL);
+void PASCAL BPTUnResolvePidTid( HPID, HTID);
+BOOL PASCAL BPTCanIUseThunk( LPSTR );
+
+
+//
+// Workspace support.
+//
+BOOL ClearWndProcHistory ( void );
+BOOL SetWndProcHistory ( LPSTR, DWORD );
+LPSTR GetWndProcHistory ( DWORD* );
+
+
+
+#define BP_LINELEADER '@'
+
+#if 0
+// CV400/CANWIN context delimeters
+#define OPENCXT '{'
+#define CLOSECXT '}'
+
+
+#if 0
+typedef enum
+{
+ BPLOC,
+ BPLOCEXPRTRUE,
+ BPLOCEXPRCHGD,
+ BPEXPRTRUE,
+ BPEXPRCHGD,
+ BPWNDPROC,
+ BPWNDPROCEXPRTRUE,
+ BPWNDPROCEXPRCHGD,
+ BPWNDPROCMSGRCVD
+}
+BREAKPOINTTYPES;
+#endif
+
+typedef enum
+{
+ BPLOCFILELINE,
+ BPLOCADDREXPR
+}
+LOCATIONTYPES;
+
+
+// The component parts of a CV400 {f,s,e} context
+
+#define FUNC_NAME_LEN 32
+typedef struct
+{
+ char Function[FUNC_NAME_LEN+1]; // or proc
+ char Source[_MAX_PATH]; // mod
+ char Exe[_MAX_PATH]; // exe
+}
+BPCONTEXT;
+
+typedef BPCONTEXT __FAR *PBPCONTEXT;
+
+
+typedef struct
+{
+ int InitLine; // Line number when BP first specified
+ int CurLine; // Current editor BP line number
+}
+BPLINE;
+
+
+typedef struct
+{
+ char AddrExpr[MAX_EXPRESS_SIZE];
+}
+BPADDREXPR;
+
+
+typedef struct
+{
+ char WndProcName[FUNC_NAME_LEN+1];
+}
+BPWNDPROCEXPR;
+
+
+typedef union
+{
+ BPLINE l;
+ BPADDREXPR ae;
+ BPWNDPROCEXPR wpe;
+}
+BPLOCATION;
+
+
+typedef struct
+{
+ BPCONTEXT Cxt;
+ BPLOCATION Loc;
+ LOCATIONTYPES LocType;
+}
+BPLOCATIONNODE;
+
+
+// NB Contexts for expressions are treated as part of
+// the expressions and left in the Expr string
+
+typedef struct
+{
+ char Expr[MAX_EXPRESS_SIZE];
+ int Len; // used for expression changed
+}
+NORMALEXPRESSION;
+
+
+typedef struct
+{
+ WORD MessageClass;
+ WORD MessageNum;
+}
+WNDPROCEXPRESSION;
+
+
+typedef union
+{
+ NORMALEXPRESSION ne;
+ WNDPROCEXPRESSION we;
+}
+BPEXPRESSIONNODE;
+
+
+typedef union
+{
+ WORD AllFlags;
+ struct
+ {
+ WORD DlgMarkAdd : 1; // This breakpoint has been marked for addition
+ WORD DlgMarkDel : 1; // This breakpoint has been marked for deletion
+ } f;
+}
+BREAKPOINTFLAGS;
+
+
+#if 0
+typedef struct BREAKPOINTNODEtag
+{
+ BREAKPOINTTYPES Type;
+ BPLOCATIONNODE bpl;
+ BPEXPRESSIONNODE bpe;
+ struct BREAKPOINTNODEtag __FAR *Next;
+
+ BREAKPOINTFLAGS Flags;
+
+ // This is a handle to the corresponding
+ // CV400 breakpoint structure. It is
+ // only, (possibly), non-NULL while the
+ // debuggee exists.
+ DWORD BoundBP;
+}
+BREAKPOINTNODE;
+
+typedef BREAKPOINTNODE __FAR *PBREAKPOINTNODE;
+#endif
+
+
+// BREAKPOINTNODE access macros:
+
+#define bpnNext(bpn) ((bpn).Next)
+#define pbpnNext(pbpn) ((pbpn)->Next)
+
+// BP type:
+#define bpnType(bpn) ((bpn).Type)
+#define pbpnType(pbpn) ((pbpn)->Type)
+
+// BP location type:
+#define bpnLocType(bpn) ((bpn).bpl.LocType)
+#define pbpnLocType(pbpn) ((pbpn)->bpl.LocType)
+
+// BP locations:
+#define bpnCxt(bpn) ((bpn).bpl.Cxt)
+#define pbpnCxt(pbpn) ((pbpn)->bpl.Cxt)
+#define bpnCxtFunction(bpn) ((bpn).bpl.Cxt.Function)
+#define pbpnCxtFunction(pbpn) ((pbpn)->bpl.Cxt.Function)
+#define bpnCxtSource(bpn) ((bpn).bpl.Cxt.Source)
+#define pbpnCxtSource(pbpn) ((pbpn)->bpl.Cxt.Source)
+#define bpnCxtExe(bpn) ((bpn).bpl.Cxt.Exe)
+#define pbpnCxtExe(pbpn) ((pbpn)->bpl.Cxt.Exe)
+#define bpnFileName(bpn) bpnCxtSource(bpn)
+#define pbpnFileName(pbpn) pbpnCxtSource(pbpn)
+#define bpnInitLine(bpn) ((bpn).bpl.Loc.l.InitLine)
+#define pbpnInitLine(pbpn) ((pbpn)->bpl.Loc.l.InitLine)
+#define bpnCurLine(bpn) ((bpn).bpl.Loc.l.CurLine)
+#define pbpnCurLine(pbpn) ((pbpn)->bpl.Loc.l.CurLine)
+#define bpnAddrExpr(bpn) ((bpn).bpl.Loc.ae.AddrExpr)
+#define pbpnAddrExpr(pbpn) ((pbpn)->bpl.Loc.ae.AddrExpr)
+#define bpnWndProc(bpn) ((bpn).bpl.Loc.wpe.WndProcName)
+#define pbpnWndProc(pbpn) ((pbpn)->bpl.Loc.wpe.WndProcName)
+
+// BP expressions:
+#define bpnExpression(bpn) ((bpn).bpe.ne.Expr)
+#define pbpnExpression(pbpn) ((pbpn)->bpe.ne.Expr)
+#define bpnExprLen(bpn) ((bpn).bpe.ne.Len)
+#define pbpnExprLen(pbpn) ((pbpn)->bpe.ne.Len)
+#define bpnMessageClass(bpn) ((bpn).bpe.we.MessageClass)
+#define pbpnMessageClass(pbpn) ((pbpn)->bpe.we.MessageClass)
+#define bpnMessageNum(bpn) ((bpn).bpe.we.MessageNum)
+#define pbpnMessageNum(pbpn) ((pbpn)->bpe.we.MessageNum)
+
+// BP flags
+#define bpnMarkAdd(bpn) ((bpn).Flags.f.DlgMarkAdd)
+#define pbpnMarkAdd(pbpn) ((pbpn)->Flags.f.DlgMarkAdd)
+#define bpnMarkDel(bpn) ((bpn).Flags.f.DlgMarkDel)
+#define pbpnMarkDel(pbpn) ((pbpn)->Flags.f.DlgMarkDel)
+
+// CV400 breakpoint structure
+// This is a handle to the linked list manager which
+// when locked gives an LPBPI
+#define bpnCV400BP(bpn) ((HLLE)((bpn).BoundBP))
+#define pbpnCV400BP(pbpn) ((HLLE)((pbpn)->BoundBP))
+
+// Utitlity macros
+#define bpnFileLineNode(bpn) \
+ (((bpnType(bpn) == BPLOC) ||\
+ (bpnType(bpn) == BPLOCEXPRTRUE) ||\
+ (bpnType(bpn) == BPLOCEXPRCHGD)) &&\
+ (bpnLocType(bpn) == BPLOCFILELINE))
+
+#define pbpnFileLineNode(pbpn) \
+ (((pbpnType(pbpn) == BPLOC) ||\
+ (pbpnType(pbpn) == BPLOCEXPRTRUE) ||\
+ (pbpnType(pbpn) == BPLOCEXPRCHGD)) &&\
+ (pbpnLocType(pbpn) == BPLOCFILELINE))
+
+// Prototypes
+BOOL PASCAL ParseCV400Location(
+ LPSTR Location,
+ PBREAKPOINTNODE Target);
+
+BOOL PASCAL ParseQC25Location(
+ LPSTR Location,
+ PBREAKPOINTNODE Target);
+
+BOOL PASCAL ParseExpression(
+ LPSTR Expression,
+ PBREAKPOINTNODE Target);
+
+BOOL PASCAL ParseWndProc(
+ LPSTR WndProc,
+ PBREAKPOINTNODE Target);
+
+// Breakpoint node procs:
+
+PBREAKPOINTNODE PASCAL AddBreakpointNode(
+ PBREAKPOINTNODE NewNodeData);
+
+BOOL PASCAL DeleteBreakpointNode(
+ int BreakpointNodeIndex);
+
+int PASCAL ClearCV400Breakpoints(void);
+
+int PASCAL ClearBreakpointNodeList(void);
+
+void PASCAL ApplyCV400Breakpoints(void);
+
+PBREAKPOINTNODE PASCAL pbpnFirstNode(void);
+
+PBREAKPOINTNODE PASCAL pbpnLastNode(void);
+
+PBREAKPOINTNODE PASCAL GetBPNodeForFileLine(
+ LPSTR File, int Line, int *pNodeIndex);
+
+void PASCAL AdjustBreakpointLines(
+ int DocNumber, int StartLine, int NumberLines,
+ BOOL Added);
+
+void PASCAL DeleteBreakpointLinesInDoc(
+ int doc);
+
+void PASCAL BuildCV400Location(
+ PBREAKPOINTNODE pBreakpoint,
+ PSTR LocSpec, WORD Len,
+ BOOL FullPaths,
+ BOOL Quote);
+
+BOOL PASCAL BuildCV400CurLocSpec(
+ PSTR CurLocSpec, WORD Len,
+ BOOL FullPaths);
+
+#endif
diff --git a/private/windbg/windbg/include/callswin.h b/private/windbg/windbg/include/callswin.h
new file mode 100644
index 000000000..1908e64c0
--- /dev/null
+++ b/private/windbg/windbg/include/callswin.h
@@ -0,0 +1,89 @@
+
+typedef struct _tagSTACKINFO {
+ STACKFRAME StkFrame;
+ DWORD FrameNum;
+ CHAR ProcName[MAX_PATH];
+ CHAR Params[MAX_PATH*3];
+ CHAR Context[MAX_PATH];
+ CHAR Module[MAX_PATH];
+ DWORD Displacement;
+ ADDR ProcAddr;
+ CXF Cxf;
+ BOOL fInProlog;
+} STACKINFO, *LPSTACKINFO;
+
+#define MAX_FRAMES 1000
+
+
+LONG
+CallsWndProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+void
+OpenCallsWindow(
+ int type,
+ LPWININFO lpWinInfo,
+ int Preference
+ );
+
+HWND
+GetCallsHWND(
+ VOID
+ );
+
+PLONG
+GetCallsStatus(
+ int ViewNumber
+ );
+
+void
+SetCallsStatus(
+ int ViewNumber,
+ PLONG ptr
+ );
+
+void
+FreeCallsStatus(
+ int ViewNumber,
+ PLONG ptr
+ );
+
+BOOL
+IsCallsInFocus(
+ VOID
+ );
+
+LPSTR
+GetLastFrameFuncName(
+ VOID
+ );
+
+BOOL
+GetCompleteStackTrace(
+ DWORD FramePointer,
+ DWORD StackPointer,
+ DWORD ProgramCounter,
+ LPSTACKINFO StackInfo,
+ LPDWORD lpdwFrames,
+ BOOL fQuick,
+ BOOL fFull
+ );
+
+BOOL
+GotoFrame(
+ int iCall
+ );
+
+PCXF
+ChangeFrame(
+ int iCall
+ );
+
+BOOL
+IsValidFrameNumber(
+ INT FrameNumber
+ );
diff --git a/private/windbg/windbg/include/change.h b/private/windbg/windbg/include/change.h
new file mode 100644
index 000000000..2aeffc8b0
--- /dev/null
+++ b/private/windbg/windbg/include/change.h
@@ -0,0 +1,12 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+#define ID_CHANGE_ALL 108
+#define ID_CHANGE_CANCEL 111
+#define ID_CHANGE_HELP 112
+#define ID_CHANGE_MATCHUPLO 105
+#define ID_CHANGE_OK 109
+#define ID_CHANGE_REGEXP 107
+#define ID_CHANGE_WHAT 102
+#define ID_CHANGE_TO 101
+#define ID_CHANGE_CONFIRM 103
+#define ID_CHANGE_WHOLEWORD 104
diff --git a/private/windbg/windbg/include/cl.h b/private/windbg/windbg/include/cl.h
new file mode 100644
index 000000000..849af5de5
--- /dev/null
+++ b/private/windbg/windbg/include/cl.h
@@ -0,0 +1,82 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cl.h
+
+Abstract:
+
+ Call Stack Walking and display routines.
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _CL_ )
+#define _CL_
+
+#include "cvinfo.h"
+#include "cvtypes.hxx"
+#include "shapi.hxx"
+
+#define ifmeMax 100
+
+typedef enum {
+ cltNone,
+ cltPub,
+ cltProc,
+ cltBlk
+} CLT;
+
+typedef struct _FME {
+ HSYM symbol;
+ char clt;
+ ADDR addrProc; /* start of procedure, or block */
+ ADDR addrRet;
+ ADDR addrCSIP; /* current return location */
+ FRAME Frame;
+ HMOD module; /* pointer to module */
+ ULONG ulParams[4]; /* first 3 words off the stack */
+ BOOL fFar; /* Far call */
+} FME; // FraMe Entry
+
+typedef struct CIS {
+ uint cEntries;
+ FME frame [ ifmeMax+1 ];
+} CIS;
+
+/*
+** EXTERNS
+*/
+
+extern CIS G_cisCallsInfo;
+
+/*
+** PROTOTYPES
+*/
+
+void CLGetWalkbackStack(LPPD lppd, LPTD lptd);
+
+char*
+CLGetProcName(
+ int num,
+ char* pch,
+ int cbMax,
+ BOOL bSpecial
+ );
+
+PCXF
+CLGetFuncCXF(
+ PADDR paddr,
+ PCXF pcxf
+ );
+
+#endif // _CL_
diff --git a/private/windbg/windbg/include/cmdexec.h b/private/windbg/windbg/include/cmdexec.h
new file mode 100644
index 000000000..7baf94a07
--- /dev/null
+++ b/private/windbg/windbg/include/cmdexec.h
@@ -0,0 +1,239 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cmdexec.h
+
+Abstract:
+
+ Prototypes and external stuctures for cmdexec.c
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _CMDEXEC_ )
+#define _CMDEXEC_
+
+#include "windbg.h"
+
+/************************** Structs and Defines *************************/
+
+#define PROMPT_SIZE 512
+
+#define LOG_BP_CLEAR 1
+#define LOG_BP_ENABLE 2
+#define LOG_BP_DISABLE 3
+
+enum {
+ LOG_DM_UNKNOWN = -1,
+ LOG_DM_ASCII = 0,
+ LOG_DM_BYTE = 1,
+ LOG_DM_WORD = 2,
+ LOG_DM_DWORD = 3,
+ LOG_DM_4REAL = 4,
+ LOG_DM_8REAL = 5,
+ LOG_DM_TREAL = 6,
+ LOG_DM_UNICODE = 7,
+ LOG_DM_MAX
+};
+
+enum {
+ CMD_RET_SYNC = 1,
+ CMD_RET_ASYNC = 2,
+ CMD_RET_ERROR = 3
+};
+
+typedef enum {
+ CMDID_NULL = 0,
+ CMDID_LOAD,
+ CMDID_UNLOAD,
+ CMDID_RELOAD,
+ CMDID_SYMPATH,
+ CMDID_PAGEIN,
+ CMDID_NOVERSION,
+ CMDID_HELP,
+ CMDID_DEFAULT
+} CMDID;
+typedef CMDID *PCMDID;
+
+
+typedef int LOGERR;
+
+#define LOGERROR_NOERROR 0
+#define LOGERROR_UNKNOWN 1
+#define LOGERROR_QUIET 2
+#define LOGERROR_CP 3
+#define LOGERROR_ASYNC 4
+
+
+#define TDWildInvalid() \
+ if (LptdCommand == (LPTD)-1) { \
+ CmdLogVar(ERR_Thread_Wild_Invalid); \
+ return LOGERROR_QUIET; \
+ }
+
+#define PDWildInvalid() \
+ if (LppdCommand == (LPPD)-1) { \
+ CmdLogVar(ERR_Process_Wild_Invalid);\
+ return LOGERROR_QUIET; \
+ }
+
+#define PreRunInvalid() \
+ if (DbgState != ds_normal \
+ || (LppdCommand && (LppdCommand != (LPPD)-1) && \
+ ( ( LppdCommand->pstate == psPreRunning ) \
+ || \
+ (LppdCommand->lptdList \
+ && LppdCommand->lptdList->tstate == tsPreRunning) \
+ ))) \
+ { CmdLogVar(ERR_DbgState); return LOGERROR_QUIET; }
+
+
+#define IsKdCmdAllowed() \
+ if ( runDebugParams.fKernelDebugger && IsProcRunning(LppdCur) ) { \
+ CmdInsertInit(); \
+ CmdLogFmt( "Cannot issue this command while target system is running\r\n" ); \
+ return LOGERROR_QUIET; \
+ }
+
+
+
+
+/************************** Public prototypes ****************************/
+
+extern BOOL FAR PASCAL CmdDoLine(LPSTR lpsz);
+extern VOID FAR PASCAL CmdDoPrompt(BOOL,BOOL);
+extern VOID FAR PASCAL CmdSetDefaultCmdProc();
+
+// this is only here to be called by CmdExecNext()...
+extern BOOL FAR PASCAL CmdExecuteLine(LPSTR);
+
+extern LPSTR CmdGetDefaultPrompt( LPSTR lpPrompt );
+extern VOID CmdSetDefaultPrompt( LPSTR lpPrompt );
+extern BOOL FAR PASCAL CmdNoLogString(LPSTR buf);
+extern int FAR CDECL CmdLogVar(WORD, ...);
+extern int FAR CDECL CmdLogFmt(LPSTR buf, ...);
+extern VOID FAR PASCAL CmdInsertInit(VOID);
+extern VOID FAR PASCAL CmdSetCursor(VOID);
+extern VOID FAR PASCAL CmdFileString(LPSTR lpsz);
+extern VOID FAR PASCAL CmdLogDebugString(LPSTR buf, BOOL fSendRemote);
+extern VOID FAR PASCAL CmdPrependCommands(LPTD lptd, LPSTR lpstr);
+extern BOOL FAR PASCAL CmdAutoRunInit(VOID);
+extern VOID FAR PASCAL CmdAutoRunNext(VOID);
+
+extern BOOL FAR PASCAL StepOK(LPPD, LPTD);
+extern BOOL FAR PASCAL GoOK(LPPD, LPTD);
+extern BOOL FAR PASCAL GoExceptOK(LPPD,LPTD);
+
+extern ULONG ulRipBreakLevel;
+extern ULONG ulRipNotifyLevel;
+
+
+
+/************************** Private Prototypes *************************/
+
+LOGERR NEAR PASCAL LogAssemble(LPSTR lpsz);
+LOGERR NEAR PASCAL LogAsmLine(LPSTR lpsz);
+LOGERR NEAR PASCAL LogBPChange(LPSTR lpsz, int iAction);
+LOGERR NEAR PASCAL LogBPList(VOID);
+LOGERR NEAR PASCAL LogBPSet(BOOL fDataBp, LPSTR lpsz);
+LOGERR NEAR PASCAL LogCallStack(LPSTR lpstr);
+LOGERR NEAR PASCAL LogCompare(LPSTR lpsz);
+LOGERR NEAR PASCAL LogConnect(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogDisasm(LPSTR lpsz,BOOL fSearch);
+LOGERR NEAR PASCAL LogDisconnect(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogDumpMem(char ch, LPSTR lpsz);
+LOGERR NEAR PASCAL LogEnterMem(LPSTR lpsz);
+LOGERR NEAR PASCAL LogException(LPSTR lpsz);
+LOGERR NEAR PASCAL LogEvaluate(LPSTR lpsz);
+LOGERR NEAR PASCAL LogFrameChange(LPSTR lpsz);
+LOGERR NEAR PASCAL LogFileClose(LPSTR lpUnused, DWORD dwUnused);
+LOGERR NEAR PASCAL LogFileOpen(LPSTR lpsz, DWORD fAppend);
+LOGERR NEAR PASCAL LogFill(LPSTR lpsz);
+LOGERR NEAR PASCAL LogFreeze(LPSTR lpsz, BOOL fFreeze);
+LOGERR NEAR PASCAL LogGoException(LPSTR lpsz, BOOL fHandled);
+LOGERR NEAR PASCAL LogGoUntil(LPSTR lpsz);
+LOGERR NEAR PASCAL LogList(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogListModules(LPSTR lpsz);
+LOGERR NEAR PASCAL LogListNear(LPSTR lpsz);
+LOGERR NEAR PASCAL LogMovemem(LPSTR lpsz);
+LOGERR NEAR PASCAL LogOptions(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogProcess(VOID);
+LOGERR NEAR PASCAL LogRadix(LPSTR lpsz);
+LOGERR NEAR PASCAL LogReload(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogRegisters(LPSTR lpsz, BOOL fFP);
+LOGERR NEAR PASCAL LogRemote(LPSTR lpsz);
+LOGERR NEAR PASCAL LogRestart(LPSTR lpsz);
+LOGERR NEAR PASCAL LogSetErrorLevel(LPSTR lpsz);
+LOGERR NEAR PASCAL LogSearch(LPSTR lpsz);
+LOGERR NEAR PASCAL LogSearchDisasm(LPSTR lpsz);
+LOGERR NEAR PASCAL LogSource(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogSleep(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogStart(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogStep(LPSTR lpsz, BOOL fStep);
+LOGERR NEAR PASCAL LogThread(VOID);
+LOGERR NEAR PASCAL LogExamine(LPSTR lpsz);
+LOGERR NEAR PASCAL LogAttach(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogKill(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogConnect(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogDotHelp(LPSTR lpsz);
+LOGERR NEAR PASCAL LogDotCommand(LPSTR lpsz);
+LOGERR NEAR PASCAL LogWaitForString(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogBreak(LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogLoadDefered( LPSTR lpsz);
+LOGERR NEAR PASCAL LogTitle( LPSTR lpsz, DWORD dwUnused);
+LOGERR NEAR PASCAL LogHelp( LPSTR lpsz);
+LOGERR NEAR PASCAL LogKernelPageIn( LPSTR lpsz);
+LOGERR NEAR PASCAL LogWatchTime( LPSTR lpsz);
+
+
+int NEAR PASCAL CmdExecuteCmd(LPSTR);
+
+VOID FAR PASCAL CmdSetDefaultCmdProc(VOID);
+VOID FAR PASCAL CmdSetCmdProc(
+ BOOL (FAR PASCAL *lpfnLP)(LPSTR lpsz),
+ VOID (FAR PASCAL *lpfnPP)(BOOL, BOOL) );
+
+int NEAR PASCAL LetterToType( char c );
+BOOL NEAR PASCAL CmdExecuteLine(LPSTR);
+VOID NEAR PASCAL CmdExecutePrompt(BOOL,BOOL);
+BOOL NEAR PASCAL CmdEnterLine(LPSTR);
+VOID NEAR PASCAL CmdEnterPrompt(BOOL,BOOL);
+BOOL NEAR PASCAL CmdAsmLine(LPSTR);
+VOID NEAR PASCAL CmdAsmPrompt(BOOL,BOOL);
+
+LOGERR NEAR PASCAL
+DoEnterMem(
+ LPSTR lpsz,
+ LPADDR lpAddr,
+ int type,
+ BOOL fMulti
+ );
+
+LOGERR NEAR PASCAL
+GetValueList(
+ LPSTR lpsz,
+ int type,
+ BOOL fMulti,
+ LPBYTE lpBuf,
+ int cchBuf,
+ LPINT pcch
+ );
+
+BOOL NEAR PASCAL GoOK(LPPD lppd, LPTD lptd );
+BOOL NEAR PASCAL StepOK(LPPD lppd, LPTD lptd );
+VOID NEAR PASCAL NoRunExcuse( LPPD lppd, LPTD lptd );
+BOOL FormatHSym(HSYM hsym, PCXT cxt, char *szStr);
+
+DWORD LogFileWrite(LPBYTE lpb, DWORD cb);
+
+#endif // _CMDEXEC_
diff --git a/private/windbg/windbg/include/cmdwin.h b/private/windbg/windbg/include/cmdwin.h
new file mode 100644
index 000000000..44a52d785
--- /dev/null
+++ b/private/windbg/windbg/include/cmdwin.h
@@ -0,0 +1,36 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+** **
+** CMDWIN.H **
+** **
+** Description: **
+** This file contains the prototypes and common declarations **
+** for the command window **
+** **
+*************************************************************************/
+
+#define MAX_CMDWIN_LINES 30000
+#define MAX_CMDWIN_HISTORY 1000
+
+typedef BOOL (WINAPI * CTRLC_HANDLER_PROC)(DWORD);
+
+typedef struct _CTRLC_HANDLER {
+ struct _CTRLC_HANDLER * next;
+ CTRLC_HANDLER_PROC pfnFunc;
+ DWORD dwParam;
+} CTRLC_HANDLER, *PCTRLC_HANDLER;
+
+extern BOOL SetAutoRunSuppress(BOOL);
+extern BOOL GetAutoRunSuppress(void);
+void CmdSetAutoHistOK(BOOL);
+BOOL CmdGetAutoHistOK(void);
+
+long FAR PASCAL EXPORT CmdEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL FAR PASCAL CmdExecNext(DBC dbcCallback, LPARAM lParam);
+BOOL FAR PASCAL DoStopEvent(LPTD);
+void FAR PASCAL SetCtrlCTrap( void );
+void FAR PASCAL ClearCtrlCTrap( void );
+BOOL FAR PASCAL CheckCtrlCTrap( void );
+BOOL FAR PASCAL CmdSetEatEOLWhitespace( BOOL ff );
+VOID FAR PASCAL DispatchCtrlCEvent(VOID);
+
+BOOL CmdHelp ( LPSTR Topic );
diff --git a/private/windbg/windbg/include/cmgrhigh.h b/private/windbg/windbg/include/cmgrhigh.h
new file mode 100644
index 000000000..aec0ee1c3
--- /dev/null
+++ b/private/windbg/windbg/include/cmgrhigh.h
@@ -0,0 +1,108 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+#define SRCSTEPPING 0
+#define ASMSTEPPING 1
+
+void InitCodemgr(void);
+void PASCAL Go(void);
+void PASCAL StepAndGo(void);
+int PASCAL Step(int Overcalls, int StepMode);
+int PASCAL StepN(int Overcalls, int StepMode, int Steps);
+BOOL PASCAL ContinueToCursor(int View, int line);
+void FormatKdParams(LPSTR,BOOL);
+
+WORD RemoveAllBreakpoints(void);
+BOOL KillDebuggee(void);
+void ClearDebuggee(void);
+void DisconnectDebuggee(void);
+BOOL ConnectDebugger(void);
+BOOL StartKernelDebugger( VOID );
+BOOL AttachDebuggee(DWORD dwProcessId, HANDLE hEventGo);
+BOOL RestartDebuggee(int argc, char *argv[]);
+BOOL DebuggeeAlive(void);
+BOOL GetCurrentSource(PSTR SrcFname, int SrcLen, WORD *pSrcLine);
+BOOL PASCAL ToggleLocBP(void);
+PSTR PASCAL GetExecutableFilename(PSTR executable, UINT size);
+void PASCAL GetUserCommandLine(PSTR CommandLine, UINT size);
+void PASCAL LoadAdditionalDLLs(void);
+void SetProcessExceptions(LPPD);
+void ClearProcessExceptions(LPPD);
+HANDLE LoadHelperDll(LPSTR psz, LPSTR pType, BOOL fError);
+BOOL ExeBrowseForFile(LSZ, UINT);
+BOOL ExeBrowseBadSym(LSZ, UINT);
+
+// #defines for UpdateFlags passed to UpdateDebuggerState
+#define UPDATE_NONE 0x0000
+#define UPDATE_CPU 0x0001
+#define UPDATE_LOCALS 0x0002
+#define UPDATE_WATCH 0x0004
+#define UPDATE_SOURCE 0x0008
+#define UPDATE_DEBUGGEE 0x0010
+#define UPDATE_DISASM 0x0020
+#define UPDATE_FLOAT 0x0040
+#define UPDATE_MEMORY 0x0080
+#define UPDATE_CALLS 0x0100
+#define UPDATE_CONTEXT 0x1000
+#define UPDATE_NOFORCE 0x2000
+
+#define UPDATE_ALLDBGWIN (UPDATE_CPU \
+ |UPDATE_LOCALS \
+ |UPDATE_WATCH \
+ |UPDATE_SOURCE \
+ |UPDATE_DISASM \
+ |UPDATE_FLOAT \
+ |UPDATE_MEMORY \
+ |UPDATE_CALLS \
+ |UPDATE_CONTEXT\
+ )
+
+
+#define UPDATE_ALLSTATES (UPDATE_ALLDBGWIN|UPDATE_DEBUGGEE)
+#define UPDATE_WINDOWS (UPDATE_ALLDBGWIN|UPDATE_NOFORCE)
+
+// windows that need to be updated when memory or registers change
+#define UPDATE_DATAWINS (UPDATE_CPU \
+ |UPDATE_LOCALS \
+ |UPDATE_WATCH \
+ |UPDATE_FLOAT \
+ |UPDATE_MEMORY \
+ |UPDATE_CALLS \
+ )
+
+// update these when radix changes
+#define UPDATE_RADIX (UPDATE_CPU|UPDATE_LOCALS|UPDATE_WATCH)
+
+// Given a filename from CodeView source line information
+// return the fully specified filename.
+void PASCAL BuildRelativeFilename(LPSTR SrcName, LPSTR BaseDir, LPSTR CanonSrcName, int CanonLen);
+
+// Sends messages to appropriate windows to update their displays according
+// to the value of UpdateFlags
+void PASCAL UpdateDebuggerState(UINT UpdateFlags);
+
+//Set in an newly opened file, visual breakpoints and current line
+void SetDebugLines(int doc, BOOL fReset);
+
+void PASCAL HighlightAllBPNodes(
+ BOOL Set);
+
+void PASCAL AdjustDebugLines(
+ int DocNumber,
+ int StartLine,
+ int NumberLines,
+ BOOL Added);
+
+BOOL PASCAL CheckExpression(
+ LPSTR Expr, int Radix, int Case);
+
+void PASCAL UpdateRadix(
+ UINT newradix);
+
+BOOL PASCAL DebuggeeRunning(
+ void);
+
+BOOL PASCAL IsProcRunning(
+ LPPD lppd);
+
+BOOL PASCAL DbgCommandOk(void);
+BOOL PASCAL DbgFEmLoaded(void);
diff --git a/private/windbg/windbg/include/cmgrlow.h b/private/windbg/windbg/include/cmgrlow.h
new file mode 100644
index 000000000..2ae120409
--- /dev/null
+++ b/private/windbg/windbg/include/cmgrlow.h
@@ -0,0 +1,65 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Cmgrlow.h
+
+Abstract:
+
+ Low-level codemgr routines (ie those requiring inside knowledge of
+ CV400).
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _CMGRLOW_ )
+#define _CMGRLOW_
+
+#include "bptypes.h"
+
+BOOL
+GetSourceFromAddress(
+ PADDR pADDR,
+ PSTR SrcFname,
+ int SrcLen,
+ WORD* pSrcLine
+ );
+
+BOOL
+HighlightBP(
+ PADDR pAddr,
+ BOOL Set
+ );
+
+BOOL
+MoveEditorToAddr(
+ PADDR pAddr
+ );
+
+HBPI
+SetCV400BP(
+ PSTR CV400BPCmd,
+ int* pBPRet,
+ BOOL UpdateScreen
+ );
+
+HBPI
+AsyncBPCommitBP(
+ PPBP ppbp
+ );
+
+void
+AsyncBPDelete(
+ HBPI hbpi
+ );
+
+#endif // _CMGRLOW_
diff --git a/private/windbg/windbg/include/codemgr.h b/private/windbg/windbg/include/codemgr.h
new file mode 100644
index 000000000..2670096e6
--- /dev/null
+++ b/private/windbg/windbg/include/codemgr.h
@@ -0,0 +1,79 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+---*/
+#ifdef OSDEBUG
+
+BOOL PASCAL FDebInit(void);
+BOOL PASCAL FDebTerm(void);
+
+#define SRCSTEPPING 0
+#define ASMSTEPPING 1
+
+
+#else
+
+// Go
+void Go(void);
+
+// Step N lines
+int StepN(int Overcalls, int StepMode, int Steps);
+
+WORD RemoveAllBreakpoints(void);
+
+BOOL LoadDebuggee(int argc, char *argv[]);
+
+BOOL RestartDebuggee(int argc, char *argv[]);
+
+void EnterHardMode(HWND hWnd, LONG lParam);
+
+void LeaveHardMode(void);
+
+int CVInitialiseForQCQP(HWND hWndMain, char *progname);
+
+void CVCleanupForQCQP(void);
+
+BOOL GetCurrentSource(PSTR SrcFname, int SrcLen, WORD *pSrcLine);
+
+#endif
+
+void AsyncStop(void);
+
+void FAR PASCAL DebuggerMessage(LPSTR Msg);
+
+// Single Step
+int pascal Step(int Overcalls, int StepMode);
+
+BOOL DebuggeeAlive(void);
+BOOL DebuggeeActive(void);
+
+void PASCAL ZapInt3s(void);
+
+
+BOOL PASCAL DbgFEmLoaded(void);
+
+int PASCAL GetQueueLength(void);
+long PASCAL GetQueueItemLong(void);
+
+BOOL PASCAL GoUntil(PADDR);
+BOOL PASCAL MoveEditorToAddr(PADDR pAddr);
+VOID FAR PASCAL SetPTState(PSTATE pstate, TSTATEX tstate);
+void FAR PASCAL EnsureFocusDebugger( void );
+
+BOOL GetRootNameMappings(LPSTR *, DWORD *);
+BOOL SetRootNameMappings(LPSTR, DWORD);
+BOOL RootSetMapped(LPSTR, LPSTR);
+/*
+** Source name mapping routines
+*/
+
+int SrcMapSourceFilename(LPSTR, UINT, int, FINDDOC);
+int SrcBackMapSourceFilename(LPSTR, UINT);
+#define SRC_MAP_NONE 0
+#define SRC_MAP_OPEN 1
+#define SRC_MAP_ONLY 2
+
+typedef enum _DBGSTATE {
+ ds_normal = 0,
+ ds_init,
+ ds_error
+} DBGSTATE;
+extern DBGSTATE DbgState;
diff --git a/private/windbg/windbg/include/colors.h b/private/windbg/windbg/include/colors.h
new file mode 100644
index 000000000..3aec14476
--- /dev/null
+++ b/private/windbg/windbg/include/colors.h
@@ -0,0 +1,169 @@
+/*++ BUILD Version: 0001 ++*/
+
+#if ! defined( _COLORS_ )
+
+#define _COLORS_
+
+
+
+//
+// Colorizable string colors type.
+//
+
+typedef
+struct
+_STRINGCOLORS {
+
+ COLORREF FgndColor;
+ COLORREF BkgndColor;
+
+} STRINGCOLORS, *PSTRINGCOLORS;
+
+//
+// Colorizable string text type.
+//
+
+typedef
+struct
+_STRINGTEXT {
+
+ UINT Length;
+ TCHAR Text[ MAX_PATH ];
+
+} STRINGTEXT, *PSTRINGTEXT;
+
+//
+// Colorizable item type.
+//
+
+typedef
+enum
+_COLOR_ITEM {
+
+ SourceWindow,
+ DummyWindow,
+ WatchWindow,
+ LocalsWindow,
+ RegistersWindow,
+ DisassemblerWindow,
+ CommandWindow,
+ FloatingPointWindow,
+ MemoryWindow,
+ CallsWindow,
+ BreakpointLine,
+ CurrentLine,
+ CurrentBreakLine,
+ UnInstantiatedBreakpoint,
+ TaggedLine,
+ TextSelection,
+ Keyword,
+ Identifier,
+ Comment,
+ Number,
+ Real,
+ String,
+ ActiveEdit,
+ ChangeHistory
+
+} COLOR_ITEM;
+
+//
+// Number of colorizable string IDs.
+//
+
+#define MAX_STRINGS ( 24 )
+
+//
+// Colorizable string colors.
+//
+
+extern STRINGCOLORS StringColors[ ];
+
+//
+// User defined custom colors.
+//
+
+extern COLORREF CustomColors[ ];
+
+//
+// COLORREF
+// GetItemForegroundColor(
+// IN COLOR_ITEM ColorItem
+// );
+//
+
+#define GetItemForegroundColor( ColorItem ) \
+ ( StringColors[ ColorItem ].FgndColor )
+
+//
+// COLORREF
+// GetItemBackgroundColor(
+// IN COLOR_ITEM ColorItem
+// );
+//
+
+#define GetItemBackgroundColor( ColorItem ) \
+ ( StringColors[ ColorItem ].BkgndColor )
+
+//
+// LPCOLORREF
+// GetItemsColors(
+// );
+//
+
+#define GetItemsColors( ) \
+ ( StringColors )
+
+//
+// int
+// GetItemsCount(
+// );
+//
+
+#define GetItemsCount( ) \
+ ( MAX_STRINGS )
+
+//
+// LPCOLORREF
+// GetCustomColors(
+// );
+//
+
+#define GetCustomColors( ) \
+ ( CustomColors )
+
+//
+// int
+// GetCustomColorsCount(
+// );
+//
+
+#define GetCustomColorsCount( ) \
+ ( NUM_CUSTOM_COLORS )
+
+//
+// VOID
+// SetItemsColors(
+// IN PSTRINGCOLORS NewStringColors
+// );
+//
+
+#define SetItemsColors( NewStringColors ) \
+ ( memcpy( StringColors, NewStringColors, sizeof( StringColors ))
+
+//
+// VOID
+// SetCustomColors(
+// IN PCOLORREF NewCustomColors
+// );
+//
+
+#define SetCustomColors( NewCustomColors ) \
+ memcpy( CustomColors, NewCustomColors, sizeof( CustomColors ));
+
+BOOL
+SelectColor(
+ HWND hWnd
+ );
+
+#endif // _COLORS_
diff --git a/private/windbg/windbg/include/cp.h b/private/windbg/windbg/include/cp.h
new file mode 100644
index 000000000..e02b056f6
--- /dev/null
+++ b/private/windbg/windbg/include/cp.h
@@ -0,0 +1,51 @@
+
+#define BADTYPECAST 101
+#define NOROOM 102
+#define GEXPRERR 105
+
+
+extern int FAR PASCAL CPCopyToken(LPSTR *lplps, LPSTR lpt);
+extern int FAR PASCAL CPCopyString(LPSTR *lplps, LPSTR lpT, char chEscape, BOOL fQuote);
+extern LPSTR FAR PASCAL CPAdvance(char FAR *, char FAR *);
+extern LPSTR FAR PASCAL CPszToken(char FAR *, char FAR *);
+extern LPSTR FAR PASCAL CPTrim(char FAR *, char);
+extern int FAR PASCAL CPQueryChar(char FAR *, char FAR *);
+extern int FAR PASCAL CPQueryQuoteIndex ( char FAR * szSrc );
+extern int FAR PASCAL CPGetCastNbr(char FAR *, USHORT, int, int, PCXF, char FAR *, char FAR *);
+extern long FAR PASCAL CPGetNbr(char FAR *, int, int, PCXF, char FAR *, int FAR *);
+extern long FAR PASCAL CPGetInt(char FAR *, int FAR *, int FAR *);
+extern int FAR PASCAL CPGetAddress(char FAR *, int FAR *, ADDR FAR *, EERADIX, CXF FAR *, BOOL, BOOL);
+extern LPSTR FAR PASCAL CPSkipWhitespace(char FAR *);
+
+extern int FAR PASCAL
+CPGetFPNbr(
+ LPSTR lpExpr,
+ int cBits,
+ int nRadix,
+ int fCase,
+ PCXF pCxf,
+ LPSTR lpBuf,
+ LPSTR lpErr);
+
+extern int FAR PASCAL
+CPGetRange(
+ LPSTR lpszExpr,
+ int FAR *lpcch,
+ LPADDR lpAddr1,
+ LPADDR lpAddr2,
+ EERADIX radix,
+ int cbDefault,
+ int cbSize,
+ CXF FAR *pcxf,
+ BOOL fCase,
+ BOOL fSpecial);
+
+typedef enum {
+ CPNOERROR,
+ CPNOARGS,
+ CPISOPENQUOTE,
+ CPISCLOSEQUOTE,
+ CPISOPENANDCLOSEQUOTE,
+ CPISDELIM,
+ CPNOTINQUOTETABLE
+} CPRETURNS;
diff --git a/private/windbg/windbg/include/cpuwin.h b/private/windbg/windbg/include/cpuwin.h
new file mode 100644
index 000000000..b71126fa6
--- /dev/null
+++ b/private/windbg/windbg/include/cpuwin.h
@@ -0,0 +1,31 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+HWND GetCpuHWND(void);
+HWND GetFloatHWND(void);
+LONG FAR PASCAL LOADDS CPUEditProc(HWND hwnd, UINT message, WPARAM wParam, LONG lParam);
+
+/*
+** This structure is used to describe all of the information needed
+** to keep track of where registers are in a window and what registers
+** are in a window
+*/
+
+typedef struct tagREGINFO REGINFO;
+typedef struct tagREGINFO *PREGINFO;
+
+struct tagREGINFO {
+ char FAR * lpsz; /* Name to display */
+ char FAR * pszValueC; /* Current Value Displayed */
+ char FAR * pszValueP; /* Last Value Displayed */
+ int x; /* X-Pos */
+ int y; /* Y-Pos */
+ int cch; /* # characters displayed */
+ UINT hReg; /* Register handle */
+ UINT hFlag; /* Flag handle */
+ UINT cbits; /* Count of bits in value */
+ UINT offValue; /* Offset of value field */
+ UINT type; /* fmtFloat or fmtUInt */
+ BOOL fChanged; /* if data has changed since last step */
+};
+
diff --git a/private/windbg/windbg/include/cvextras.h b/private/windbg/windbg/include/cvextras.h
new file mode 100644
index 000000000..b8d4e35d3
--- /dev/null
+++ b/private/windbg/windbg/include/cvextras.h
@@ -0,0 +1,47 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+enum _MSG_WHERE {
+ CMDWINDOW = 1,
+ MSGBOX,
+ STATLINE,
+ MSGSTRING,
+ MSGGERRSTR
+ };
+typedef int MSGWHERE;
+
+enum _MSG_TYPE {
+ ERRORMSG = 1,
+ WARNMSG,
+ INFOMSG,
+ MESSAGEMSG,
+ FMESSAGEMSG,
+ EXPREVALMSG
+ };
+typedef int MSGTYPE;
+typedef unsigned short MSGID;
+
+enum {
+ mStack = 1
+};
+
+#define EENOERROR 0
+
+#define EXPRERROR 255
+
+int ESilan(void);
+
+void PASCAL CVExprErr(EESTATUS, MSGWHERE, PHTM, char FAR *);
+int ESSetFromIndex(int);
+void SYSetFrame(FRAME * pFrame);
+int get_initial_context(PCXT pCXT, BOOL fSearchAll);
+
+void PASCAL UpdateUserEnvir( unsigned short fReq );
+
+void
+CVMessage (
+ MSGTYPE msgtype,
+ MSGID msgid,
+ MSGWHERE msgwhere,
+ ...
+ );
diff --git a/private/windbg/windbg/include/dbugdll.h b/private/windbg/windbg/include/dbugdll.h
new file mode 100644
index 000000000..637894f3c
--- /dev/null
+++ b/private/windbg/windbg/include/dbugdll.h
@@ -0,0 +1,46 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Dbugdll.h
+
+Abstract:
+
+ Prototypes and external stuctures for dbugdll.c
+
+Author:
+
+ Kent Forschmiedt (a-kentf) 23-dec-92
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#ifndef _DBUGDLL_H
+
+#define _DBUGDLL_H
+//
+// Debugger DLLs
+//
+#define DLL_SYMBOL_HANDLER 0
+#define DLL_EXEC_MODEL 1
+#define DLL_TRANSPORT 2
+#define DLL_EXPR_EVAL 3
+#define DLL_NO_LOAD_SYMBOLS 4
+#define DLL_SOURCE_PATH 5
+
+#define MAXLHSINDEX 6
+
+void SetDllName(int, LPSTR);
+void SetDllKey(int iDll, LPSTR lpKey);
+LPSTR GetDllName(int);
+LPSTR GetDllKey(int);
+BOOL GetDllNameFromKey(int iDll, LPSTR lpKey, LPSTR lpBuf);
+BOOL GetDefaultDllKey(int iDll, LPSTR lpBuf);
+
+
+#endif
diff --git a/private/windbg/windbg/include/dbugexcp.h b/private/windbg/windbg/include/dbugexcp.h
new file mode 100644
index 000000000..165fe9c92
--- /dev/null
+++ b/private/windbg/windbg/include/dbugexcp.h
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dbugexcp.h
+
+Abstract:
+
+ Function prototypes exported from dbugexcp.c
+
+Author:
+
+ Kent Forschmiedt (kentf) 02-15-1994
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#ifndef _DBUGEXCP_H
+#define _DBUGEXCP_H
+
+EXCEPTION_LIST *
+InsertException(
+ EXCEPTION_LIST *List,
+ EXCEPTION_LIST *eList
+ );
+
+BOOL
+GetDefaultExceptionList(
+ VOID
+ );
+
+LOGERR
+ParseException(
+ LPSTR String,
+ UINT Radix,
+ BOOLEAN *fException,
+ BOOLEAN *fEfd,
+ BOOLEAN *fName,
+ BOOLEAN *fCmd,
+ BOOLEAN *fCmd2,
+ BOOLEAN *fInvalid,
+ DWORD *pException,
+ EXCEPTION_FILTER_DEFAULT *pEfd,
+ LPSTR *lpName,
+ LPSTR *lpCmd,
+ LPSTR *lpCmd2
+ );
+
+void
+FormatException (
+ EXCEPTION_FILTER_DEFAULT Efd,
+ DWORD Exception,
+ LPSTR lpName,
+ LPSTR lpCmd,
+ LPSTR lpCmd2,
+ LPSTR Separator,
+ LPSTR Buffer
+ );
+
+#endif // _DBUGEXCP_H
diff --git a/private/windbg/windbg/include/debug.h b/private/windbg/windbg/include/debug.h
new file mode 100644
index 000000000..65aabea89
--- /dev/null
+++ b/private/windbg/windbg/include/debug.h
@@ -0,0 +1,19 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/* This include file contains the functions needed by debuggers which run
+ * under windows.
+ */
+
+/* USER functions */
+BOOL FAR PASCAL QuerySendMessage(HANDLE h1, HANDLE h2, HANDLE h3, LPMSG lpmsg);
+BOOL FAR PASCAL LockInput(HANDLE h1, HWND hwndInput, BOOL fLock);
+
+LONG FAR PASCAL GetSystemDebugState(void);
+/* Flags returned by GetSystemDebugState.
+ */
+#define SDS_MENU 0x0001
+#define SDS_SYSMODAL 0x0002
+#define SDS_NOTASKQUEUE 0x0004
+
+/* Kernel procedures */
+void FAR PASCAL DirectedYield(HANDLE hTask);
diff --git a/private/windbg/windbg/include/debugger.h b/private/windbg/windbg/include/debugger.h
new file mode 100644
index 000000000..91bc04e3a
--- /dev/null
+++ b/private/windbg/windbg/include/debugger.h
@@ -0,0 +1,78 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+#define DBG_SETUPNOTIFICATION WM_USER+20
+#define DBG_ENTERHARDMODE WM_USER+21
+#define DBG_ENTERSOFTMODE WM_USER+22
+
+#define DBG_REFRESH WM_USER+23
+#define DBG_INFO WM_USER+24
+
+
+typedef enum
+{
+ CHK_CONTINUE,
+ CHK_ENTERHARDMODE,
+ CHK_ENTERSOFTMODE,
+ CHK_WAITFORRESULT
+}
+CHECKRESULT;
+
+typedef enum
+{
+ CBID_SYSMODALMSGBOX,
+ CBID_SKIPBP,
+ CBID_REPLACEBPANDGO,
+ CBID_HANDLENOTIFICATION
+} CALLBACKID;
+
+typedef DWORD (FAR PASCAL *DBGCALLBACK)(
+ CALLBACKID callbackId,
+ DWORD data);
+
+//Prototypes
+FARPROC FAR PASCAL InitDebuggerDLL(
+ HWND hwndDebugger,
+ int __FAR *pChildPid,
+ WORD LSMMsg,
+ DBGCALLBACK Callback);
+
+void FAR PASCAL TermDebuggerDLL(
+ void);
+
+void FAR PASCAL SetCheckResult(
+ CHECKRESULT result);
+
+void FAR PASCAL SetExitHardMode(
+ void);
+
+BOOL FAR PASCAL DebuggeeInCallback(
+ void);
+
+void FAR PASCAL SetFocusDebuggee(
+ void);
+
+
+// WARNING: Windows 3.0 Internals.
+// I found these functions in the Windows 3.0 KERNEL.EXE
+// and found out empirically what they did and saw no
+// side effects. Thus there is no guarantee of their
+// portability. All testing was performed with Windows 3.0
+
+// This function takes either a module handle or an instance
+// thereof and returns the module handle or 0 otherwise
+HANDLE FAR PASCAL WKGetExePtr(HANDLE hInstance);
+
+// This function pulled in from the Windows KERNEL
+HANDLE FAR PASCAL WKGetTaskQueue(HANDLE CurrentTask);
+
+// (Un)Lock current task
+void FAR PASCAL WULockMyTask(BOOL lock);
+
+// TRUE if current task is locked
+BOOL FAR PASCAL WKIsTaskLocked(void);
+
+// Window field offset for users dialog proc in a dialog box
+// (This has got to be highly version dependent!)
+#define GWL_DIALOGFUNC 4
+
+// END: Windows 3.0 Internals.
diff --git a/private/windbg/windbg/include/dialogs.h b/private/windbg/windbg/include/dialogs.h
new file mode 100644
index 000000000..e595c4580
--- /dev/null
+++ b/private/windbg/windbg/include/dialogs.h
@@ -0,0 +1,443 @@
+#define ID_CALLS_HELP 16000
+#define ID_CFLAGS_HELP 16001
+#define ID_CONFIRM_HELP 16002
+#define ID_CUSTOM_HELP 16003
+#define ID_DBUGDLL_HELP 16004
+#define ID_DBUGEXC_HELP 16005
+#define ID_DBUGRUN_HELP 16006
+#define ID_DIRS_HELP 16007
+#define ID_FILE_HELP 16009
+#define ID_ENVIRON_HELP 16010
+#define ID_OSM_HELP 16011
+#define ID_FIND_HELP 16012
+#define ID_FINDNEXT_HELP 16013
+#define ID_FUNCTION_HELP 16014
+#define ID_LINE_HELP 16015
+#define ID_MEMORY_HELP 16016
+#define ID_MESSAGE_HELP 16017
+#define ID_MODIFY_HELP 16018
+#define ID_PROCESS_HELP 16019
+#define ID_QUICKW_HELP 16020
+#define ID_REPLACE_HELP 16021
+#define ID_DBUGOPT_HELP 16022
+#define ID_SAVEAS_HELP 16023
+#define ID_SETBREAK_HELP 16024
+#define ID_THREAD_HELP 16025
+#define ID_UNRESOLVED_HELP 16026
+#define ID_USERDLL_HELP 16027
+#define ID_WATCH_HELP 16028
+#define ID_BPRESOLVE_HELP 16029
+#define ID_PROGOPEN_HELP 16030
+#define ID_PROGCLOSE_HELP 16031
+#define ID_PROGSAVEAS_HELP 16032
+#define ID_PROGDELETE_HELP 16033
+#define ID_COLORDLG_HELP 16034
+#define ID_FONTDLG_HELP 16035
+#define ID_BROWSE_HELP 16036
+#define ID_ASKBROWSE_HELP 16037
+#define ID_FUNCRES_HELP 16038
+#define ID_CHDBDLL_HELP 16039
+
+#define ID_CPU_HELP 16040
+#define ID_LOCAL_HELP 16041
+#define ID_FLOAT_HELP 16042
+
+#define ID_KDOPT_HELP 16043 /* kernel debug option */
+#define ID_CALLSOPT_HELP 16044 /* calls option */
+
+#define ID_PROGOPEN_NEW_HELP 16045
+#define ID_FSRESOLVE_HELP 16046
+
+
+#define ID_CALLS_GOTO 2000
+#define ID_CALLS_CALLSTACK 2001
+
+#define ID_CONFIRM_FINDNEXT 2010
+#define ID_CONFIRM_REPLACE 2011
+#define ID_CONFIRM_REPLACEALL 2012
+
+#define ID_DBUGDLL_SHCOMBO 2020
+#define ID_DBUGDLL_EECOMBO 2021
+#define ID_DBUGDLL_TLCOMBO 2022
+#define ID_DBUGDLL_EMCOMBO 2023
+#define ID_DBUGDLL_CHANGE 2024
+#define ID_DBUGDLL_DELETE 2025
+#define ID_DBUGDLL_ADD 2026
+
+#define ID_CHDBDLL_NAME 2030
+#define ID_CHDBDLL_DESC 2031
+#define ID_CHDBDLL_PATH 2032
+#define ID_CHDBDLL_PARAM 2033
+#define ID_CHDBDLL_MAKEDEFAULT 2034
+
+#define ID_DBUGEXC_ADD 2050
+#define ID_DBUGEXC_DELETE 2051
+#define ID_DBUGEXC_MODIFY 2052
+#define ID_DBUGEXC_IGNORE 2053
+#define ID_DBUGEXC_NOTIFY 2054
+#define ID_DBUGEXC_STOP 2055
+#define ID_DBUGEXC_EXCNUM 2056
+#define ID_DBUGEXC_EXCNAME 2057
+#define ID_DBUGEXC_EXCLIST 2058
+#define ID_DBUGEXC_EXCLABEL 2059
+#define ID_DBUGEXC_CMDLABEL1 2060
+#define ID_DBUGEXC_EXCLABEL1 2061
+#define ID_DBUGEXC_NAMELABEL1 2062
+#define ID_DBUGEXC_ACTLABEL1 2063
+#define ID_DBUGEXC_ACTION 2064
+#define ID_DBUGEXC_CMD 2065
+#define ID_DBUGEXC_CMDLABEL2 2066
+#define ID_DBUGEXC_CMD2 2067
+
+#define ID_DBUGRUN_RLABEL 2070
+#define ID_DBUGRUN_RTEXT 2071
+#define ID_DBUGRUN_ALABEL 2072
+#define ID_DBUGRUN_ATEXT 2073
+
+#define ID_FIND_TAGALL 2090
+#define ID_FIND_MATCHUPLO 2091
+#define ID_FIND_REGEXP 2092
+#define ID_FIND_UP 2093
+#define ID_FIND_DOWN 2094
+#define ID_FIND_WHAT 2095
+#define ID_FIND_NEXT 2096
+#define ID_FIND_WHOLEWORD 2097
+
+#define ID_FINDNEXT_TAGALL 2098
+
+#define ID_FUNCTION_FUNCNAME 2100
+
+#define ID_LINE_LINE 2110
+
+#define ID_MEMORY_ADDRESS 2120
+#define ID_MEMORY_FORMAT 2121
+#define ID_MEMORY_LIVE 2122
+#define ID_MEMORY_FILL 2123
+
+
+#define ID_MESSAGE_CHOOSEMESSAGE 2130
+#define ID_MESSAGE_CHOOSECLASS 2131
+#define ID_MESSAGE_MESSAGE 2132
+#define ID_MESSAGE_CLASSMOUSE 2133
+#define ID_MESSAGE_CLASSWINDOW 2134
+#define ID_MESSAGE_CLASSINPUT 2135
+#define ID_MESSAGE_CLASSSYSTEM 2136
+#define ID_MESSAGE_CLASSINIT 2137
+#define ID_MESSAGE_CLASSCLIPBOARD 2138
+#define ID_MESSAGE_CLASSDDE 2139
+#define ID_MESSAGE_CLASSNONCLIENT 2140
+#define ID_MESSAGE_CLASSTITLE 2141
+#define ID_MESSAGE_MESSAGETITLE 2142
+
+#define ID_PROCESS_LIST 2150
+#define ID_PROCESS_SELECT 2151
+
+#define ID_REPLACE_MATCHUPLO 2160
+#define ID_REPLACE_REGEXP 2161
+#define ID_REPLACE_WHAT 2162
+#define ID_REPLACE_WHOLEWORD 2163
+#define ID_REPLACE_REPLACEWITH 2164
+#define ID_REPLACE_REPLACEALL 2165
+#define ID_REPLACE_FINDNEXT 2166
+
+#define ID_DBUGOPT_CHILDREN 2184
+#define ID_DBUGOPT_REGREG 2185
+#define ID_DBUGOPT_REGEXT 2186
+#define ID_DBUGOPT_REGMMU 2187
+#define ID_DBUGOPT_CASESENSITIVE 2188
+#define ID_DBUGOPT_DISPSEG 2189
+#define ID_DBUGOPT_RADIXOCT 2190
+#define ID_DBUGOPT_RADIXDEC 2191
+#define ID_DBUGOPT_RADIXHEX 2192
+#define ID_DBUGOPT_SUFFIXA 2194
+#define ID_DBUGOPT_SUFFIXW 2195
+#define ID_DBUGOPT_SUFFIXNONE 2196
+#define ID_DBUGOPT_SRCHPATHLABEL 2197
+#define ID_DBUGOPT_SRCHPATH 2198
+
+#define ID_DBUGOPT_EXITGO 2199
+#define ID_DBUGOPT_ATTACHGO 2200
+#define ID_DBUGOPT_CHILDGO 2201
+#define ID_DBUGOPT_RADIXGROUP 2202
+#define ID_DBUGOPT_REGISTERGROUP 2203
+#define ID_DBUGOPT_DEBUGGERGROUP 2204
+#define ID_DBUGOPT_SUFFIXGROUP 2205
+#define ID_DBUGOPT_COMMANDREPEAT 2206
+#define ID_DBUGOPT_DISASMGROUP 2207
+#define ID_DBUGOPT_WOWVDM 2208
+#define ID_DBUGOPT_ALTSS 2209
+#define ID_DBUGOPT_DISCONNECT 2216
+#define ID_DBUGOPT_VERBOSE 2217
+#define ID_DBUGOPT_IGNOREALL 2218
+#define ID_DBUGOPT_CONTEXT 2219
+
+#define ID_DISASMOPT_SHOWSEG 2220
+#define ID_DISASMOPT_SHOWBYTE 2221
+#define ID_DISASMOPT_CASE 2222
+#define ID_DISASMOPT_SHOWSOURCE 2223
+#define ID_DISASMOPT_SHOWSYMB 2224
+#define ID_DISASMOPT_DEMAND 2225
+
+#define ID_SETBREAK_ACTION 2230
+#define ID_SETBREAK_LOCATION 2231
+#define ID_SETBREAK_WNDPROC 2232
+#define ID_SETBREAK_EXPRESSION 2233
+#define ID_SETBREAK_LENGTH 2234
+#define ID_SETBREAK_PASS 2235
+#define ID_SETBREAK_PASSESLEFTCOUNT 2236
+#define ID_SETBREAK_PROCESS 2237
+#define ID_SETBREAK_THREAD 2238
+#define ID_SETBREAK_CMDS 2239
+#define ID_SETBREAK_BREAKPOINT 2240
+#define ID_SETBREAK_MESSAGES 2241
+#define ID_SETBREAK_ADD 2242
+#define ID_SETBREAK_DELETE 2243
+#define ID_SETBREAK_CLEARALL 2244
+#define ID_SETBREAK_DISABLE 2245
+#define ID_SETBREAK_ENABLE 2246
+#define ID_SETBREAK_CHANGE 2247
+#define ID_SETBREAK_SLOCATION 2248
+#define ID_SETBREAK_SWNDPROC 2249
+#define ID_SETBREAK_SEXPRESSION 2250
+#define ID_SETBREAK_SLENGTH 2251
+
+#define ID_THREAD_LIST 2270
+#define ID_THREAD_FREEZE 2271
+#define ID_THREAD_FREEZEALL 2272
+#define ID_THREAD_THAWALL 2273
+#define ID_THREAD_SELECT 2274
+#define ID_BPRESOLVE_STRING 2275
+#define ID_BPCANIUSETHUNK_STRING 2276
+
+#define ID_UNRESOLVED_HBPT 2290
+#define ID_UNRESOLVED_DESC 2291
+#define ID_UNRESOLVED_CLEAR 2292
+#define ID_UNRESOLVED_DISABLE 2293
+#define ID_UNRESOLVED_DEFER 2294
+#define ID_UNRESOLVED_QUIET 2295
+#define ID_UNRESOLVED_BREAKPOINTS 2296
+
+#define ID_WATCH_ADD 2300
+#define ID_WATCH_CLEARALL 2301
+#define ID_WATCH_DELETE 2302
+#define ID_WATCH_EXPRESSION 2303
+#define ID_WATCH_CUREXPRESSION 2304
+
+#define ID_BPRESOLVE_LIST 2320
+#define ID_BPRESOLVE_USE 2321
+#define ID_BPRESOLVE_CANCEL 2322
+
+#define ID_PROGOPEN_PROGRAMS 2330
+#define ID_PROGOPEN_WORKSPACES 2331
+#define ID_PROGOPEN_NEW 2333
+
+#define ID_PROGCLOSE_TEXT1 2340
+#define ID_PROGCLOSE_TEXT2 2341
+
+#define ID_PROGSAVEAS_WORKSPACES 2350
+#define ID_PROGSAVEAS_MAKEDEFAULT 2351
+
+#define ID_PROGDELETE_PROGRAMS 2360
+#define ID_PROGDELETE_WORKSPACES 2361
+#define ID_PROGDELETE_DELETE 2362
+
+#define ID_FSRESOLVE_USE 2370
+#define ID_FSRESOLVE_STRING 2371
+#define ID_FSRESOLVE_LIST 2372
+#define ID_FSRESOLVE_ADDNONE 2373
+#define ID_FSRESOLVE_ADDSOURCE 2374
+#define ID_FSRESOLVE_ADDROOT 2375
+
+/*******************************************************/
+/* The following are copied from colordlg.h and must */
+/* not be changed. */
+
+//#include <colordlg.h>
+// #define DLG_COLOR 10
+
+#define COLOR_HUESCROLL 700 /* color dialog */
+#define COLOR_SATSCROLL 701
+#define COLOR_LUMSCROLL 702
+#define COLOR_HUE 703
+#define COLOR_SAT 704
+#define COLOR_LUM 705
+#define COLOR_RED 706
+#define COLOR_GREEN 707
+#define COLOR_BLUE 708
+#define COLOR_CURRENT 709
+#define COLOR_RAINBOW 710
+#define COLOR_SAVE 711
+#define COLOR_ADD 712
+#define COLOR_SOLID 713
+#define COLOR_TUNE 714
+#define COLOR_SCHEMES 715
+#define COLOR_ELEMENT 716
+#define COLOR_SAMPLES 717
+#define COLOR_PALETTE 718
+#define COLOR_MIX 719
+#define COLOR_BOX1 720
+#define COLOR_CUSTOM1 721
+
+#define COLOR_HUEACCEL 723
+#define COLOR_SATACCEL 724
+#define COLOR_LUMACCEL 725
+#define COLOR_REDACCEL 726
+#define COLOR_GREENACCEL 727
+#define COLOR_BLUEACCEL 728
+
+#define NUM_BASIC_COLORS 48
+#define NUM_CUSTOM_COLORS 16
+
+/*******************************************************/
+
+#define IDC_LIST_ITEMS 2398
+#define IDC_PUSH_SET_FOREGROUND 2399
+#define IDC_PUSH_SET_BACKGROUND 2400
+#define IDC_PUSH_DEFAULT 2401
+#define IDC_PUSH_SELECT_ALL 2402
+
+#define IDC_CHECK_MAKE_DEFAULT 2410
+
+#define ID_BROWSE_ADDNONE rad14
+#define ID_BROWSE_ADDROOT rad15
+#define ID_BROWSE_ADDSOURCE rad16
+
+
+#define ID_ENV_TABGROUP 2420
+#define ID_ENV_SCROLLGROUP 2421
+#define ID_ENV_TABSTOPSTXT 2422
+#define ID_ENV_TABSTOPS 2423
+#define ID_ENV_TABKEEP 2424
+#define ID_ENV_TABSPAC 2425
+#define ID_ENV_SCROLLVER 2426
+#define ID_ENV_SCROLLHOR 2427
+#define ID_ENV_SRCHPATH 2428
+#define ID_ENV_REDOSIZE 2429
+#define ID_ENV_REDOSIZE_TXT 2430
+#define ID_ENV_ASKSAVE 2431
+
+#define ID_USERDLL_LIST_TEXT 2440
+#define ID_USERDLL_LIST_TEXT2 2441
+#define ID_USERDLL_LIST_TEXT3 2442
+#define ID_USERDLL_LIST 2443
+#define ID_USERDLL_NAME_BOX 2444
+#define ID_USERDLL_NAME 2445
+#define ID_USERDLL_SRCHPATH_TEXT 2446
+#define ID_USERDLL_SRCHPATH 2447
+#define ID_USERDLL_ADD_GRP 2448
+#define ID_USERDLL_ADD_NAME_TEXT 2449
+#define ID_USERDLL_ADD_NAME 2450
+#define ID_USERDLL_ADD_DEFAULT_TEXT 2451
+#define ID_USERDLL_DEFAULT_BOX 2452
+#define ID_USERDLL_ADD_DEFAULT 2453
+#define ID_USERDLL_LOC_GRP 2454
+#define ID_USERDLL_LOCAL 2455
+#define ID_USERDLL_REMOTE 2456
+#define ID_USERDLL_SYM_GRP 2457
+#define ID_USERDLL_LOAD 2458
+#define ID_USERDLL_DEFER 2459
+#define ID_USERDLL_SUPPRESS 2460
+#define ID_USERDLL_ADD 2461
+#define ID_USERDLL_BROWSE 2462
+#define ID_USERDLL_DEFAULT 2463
+#define ID_USERDLL_CHANGE 2464
+#define ID_USERDLL_DELETE 2465
+
+#define ID_BROWSEFOR 2485
+#define ID_IGNOREALL 2486
+#define ID_BADSYM_TEXT 2487
+#define ID_USE 2488
+
+#define ID_QUICKW_LIST 2490
+#define ID_QUICKW_ZOOM 2491
+#define ID_QUICKW_ADD 2492
+#define ID_QUICKW_MODIFY 2493
+#define ID_QUICKW_REM_LAST 2494
+
+#define ID_FUNCRES_LABEL1 2500
+#define ID_FUNCRES_LABEL2 2501
+#define ID_FUNCRES_LIST 2502
+#define ID_FUNCRES_USE 2503
+
+#define ID_PANEMGR_FORMAT 2501
+#define ID_PANEMGR_EXPAND_1ST 2502
+#define ID_PANEMGR_EXPAND_NONE 2503
+
+#define ID_KD_DEBUGGERGROUP 2601
+#define ID_KD_INITIALBP 2602
+#define ID_KD_MODEM 2603
+#define ID_KD_PORT_LABEL 2604
+#define ID_KD_PORT 2605
+#define ID_KD_BAUDRATE_LABEL 2606
+#define ID_KD_BAUDRATE 2607
+#define ID_KD_CACHE_LABEL 2608
+#define ID_KD_CACHE 2609
+#define ID_KD_PLATFORM_LABEL 2610
+#define ID_KD_PLATFORM 2611
+#define ID_KD_ENABLE 2612
+#define ID_KD_GOEXIT 2613
+#define ID_KD_CRASH 2614
+#define ID_KD_CRASH_LABEL 2615
+#define ID_KD_CRASH_BROWSE 2616
+
+#define ID_TL_TASK_LIST 2630
+#define ID_TL_TASK_LIST_LABEL 2631
+
+#define ID_LFOPT_GROUP 2701
+#define ID_LFOPT_APPEND 2702
+#define ID_LFOPT_AUTO 2703
+#define ID_LFOPT_FNAMELABEL 2704
+#define ID_LFOPT_FNAME 2705
+
+#define ID_CWOPT_FRAMEPTR 2801
+#define ID_CWOPT_RETADDR 2802
+#define ID_CWOPT_FUNCNAME 2803
+#define ID_CWOPT_DISPLACEMENT 2804
+#define ID_CWOPT_PARAMS 2805
+#define ID_CWOPT_STACK 2806
+#define ID_CWOPT_SOURCE 2807
+#define ID_CWOPT_MAXFRAMES_LABEL 2808
+#define ID_CWOPT_MAXFRAMES 2809
+#define ID_CWOPT_MODULE 2810
+#define ID_CWOPT_RTF 2811
+
+#define DLG_CALLS 3000
+#define DLG_CONFIRM 3001
+#define DLG_DEBUGDLL 3002
+#define DLG_DEBUGEXCP 3003
+#define DLG_RUNOPT 3004
+#define DLG_DISASMOPT 3005
+#define DLG_QUICKWATCH 3006
+#define DLG_PANEOPTIONS 3007
+#define DLG_FIND 3008
+#define DLG_FINDNEXT 3009
+#define DLG_FUNCTION 3010
+#define DLG_LINE 3011
+#define DLG_MEMORY 3012
+#define DLG_MESSAGES 3013
+#define DLG_CHOOSECOLOR 3014
+#define DLG_PROCESS 3015
+#define DLG_CHOOSEFONT 3016
+#define DLG_REPLACE 3017
+#define DLG_RUNDEBUG 3018
+#define DLG_BREAKPOINTS 3019
+#define DLG_USERDLL 3020
+#define DLG_WATCH 3021
+#define DLG_BPRESOLVE 3022
+#define DLG_PROGRAM_OPEN 3023
+#define DLG_PROGRAM_CLOSE 3024
+#define DLG_PROGRAM_SAVEAS 3025
+#define DLG_PROGRAM_DELETE 3026
+#define DLG_ENVIRONMENT 3027
+#define DLG_THREAD 3028
+#define DLG_UNRESOLVED 3029
+#define DLG_ASKSRCBROWSE 3030
+#define DLG_FUNCRESOLVE 3032
+#define DLG_CH_DBUGDLL 3033
+#define DLG_BPCANIUSETHUNK 3034
+#define DLG_ASKEXEBROWSE 3035
+#define DLG_KERNELDBG 3036
+#define DLG_CALLSWINOPTIONS 3037
+#define DLG_BADSYMBOLS 3038
+#define DLG_TASKLIST 3039
+#define DLG_FSRESOLVE 3040
diff --git a/private/windbg/windbg/include/disasm.h b/private/windbg/windbg/include/disasm.h
new file mode 100644
index 000000000..7d93e3287
--- /dev/null
+++ b/private/windbg/windbg/include/disasm.h
@@ -0,0 +1,39 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/*************************************************************************
+** **
+** DISASM.H **
+** **
+** Description: **
+** This file contains the prototypes and common declarations **
+** for the disassembler window **
+** **
+*************************************************************************/
+
+long FAR PASCAL EXPORT DisasmEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+BOOL FAR PASCAL DisasmGetAddrFromLine(LPADDR lpaddr, UINT iLine);
+
+void FAR PASCAL ViewDisasm(LPADDR, int);
+
+
+#define DISASM_NONE 0
+#define DISASM_OTHER 2
+#define DISASM_BRKPT 3
+
+#define disasmForce 0x01
+#define disasmHighlight 0x02
+#define disasmDown 0x04
+#define disasmLine 0x08
+#define disasmUp 0x10
+#define disasmPage 0x40
+#define disasmPC 0x80
+#define disasmRefresh 0x100
+
+#define disasmDownLine (disasmDown | disasmLine)
+#define disasmDownPage (disasmDown | disasmPage)
+#define disasmUpLine (disasmUp | disasmLine)
+#define disasmUpPage (disasmUp | disasmPage)
+
+
+#define DISASM_PC (disasmForce|disasmPC)
diff --git a/private/windbg/windbg/include/docfile.h b/private/windbg/windbg/include/docfile.h
new file mode 100644
index 000000000..282570471
--- /dev/null
+++ b/private/windbg/windbg/include/docfile.h
@@ -0,0 +1,13 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+//Create or open a new document
+int FAR PASCAL OpenDocument(WORD mode, WORD type, int doc, LPSTR FileName, int docView, int Preference);
+
+//Save a document with a specific name
+BOOL FAR PASCAL SaveDocument(
+ int Doc,
+ LPSTR FileName);
+
+BOOL FAR PASCAL MergeFile(
+ LPSTR FileName,
+ int view);
diff --git a/private/windbg/windbg/include/document.h b/private/windbg/windbg/include/document.h
new file mode 100644
index 000000000..97536e757
--- /dev/null
+++ b/private/windbg/windbg/include/document.h
@@ -0,0 +1,99 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+//Initialize document module
+void InitializeDocument(void);
+
+void FAR PASCAL EnableReadOnlyBeep( BOOL f );
+
+BOOL FAR PASCAL QueryReadOnlyError( void );
+
+BOOL FAR PASCAL FirstLine(int doc, LPLINEREC *pl, int *lineNb, LPBLOCKDEF *pb);
+
+BOOL FAR PASCAL NextLine(int doc, LPLINEREC *pl, int *lineNb, LPBLOCKDEF *pb);
+
+BOOL FAR PASCAL PreviousLine(int doc, LPLINEREC *pl, int lineNb, LPBLOCKDEF *pb);
+
+void FAR PASCAL CloseLine(int doc, LPLINEREC *pl, int lineNb, LPBLOCKDEF *pb);
+
+int FAR PASCAL FirstNonBlank(int doc, int line);
+
+//Delete a block from Col1,Line1 (inclusive) to Col2,Line2 (exclusive)
+BOOL FAR PASCAL DeleteBlock(
+ int doc,
+ int col1,
+ int line1,
+ int col2,
+ int line2);
+
+//Delete all text
+BOOL FAR PASCAL DeleteAll(
+ int doc);
+
+//Insert a block at Col,Line
+BOOL FAR PASCAL InsertBlock( int doc, int col, int line, int size, LPSTR buf);
+
+//Replace a char in a block
+BOOL FAR PASCAL ReplaceCharInBlock(
+ int doc,
+ int x,
+ int y,
+ int ch);
+
+//Count chars in document
+ULONG FAR PASCAL CountCharsInDocument(
+ int doc);
+
+//Compact document in mem
+BOOL FAR PASCAL CompactDocument(
+ int doc);
+
+//Check document coherence
+BOOL FAR PASCAL CheckDocument(
+ int doc);
+
+void FAR PASCAL DumpDocument(
+ int doc);
+
+//Destroy memory allocated for a document
+BOOL FAR PASCAL DestroyDocument(
+ int doc);
+
+//Allocate a block for document data
+BOOL FAR PASCAL AllocateBlock(
+ LPBLOCKDEF pPrevBlock,
+ LPBLOCKDEF pNextBlock,
+ LPBLOCKDEF *pNewBlock);
+
+//Retrieve chars on a line
+BOOL FAR PASCAL GetTextAtLine(
+ int doc,
+ int line,
+ int col1,
+ int col2,
+ LPSTR text);
+
+//Change tabulations in a document
+void FAR PASCAL SetTabs(
+ int doc,
+ int oldTab,
+ int newTab);
+
+BOOL FAR PASCAL CreateNewBlock(
+ LPBLOCKDEF *pNewBlock);
+
+LPSTR FAR PASCAL DocAlloc(
+ WORD bytes);
+
+BOOL FAR PASCAL DocFree(
+ LPVOID lpv);
+
+int FAR PASCAL AlignToTabs(
+ int editCol,
+ int len,
+ LPSTR pc);
+
+void FAR PASCAL ExpandTabs(
+ LPLINEREC *pl);
+
+void FAR PASCAL CheckSyntax(
+ int doc);
diff --git a/private/windbg/windbg/include/edit.h b/private/windbg/windbg/include/edit.h
new file mode 100644
index 000000000..540a20abd
--- /dev/null
+++ b/private/windbg/windbg/include/edit.h
@@ -0,0 +1,26 @@
+void FAR PASCAL PaintText(int view, HDC hDC, PRECT rcl);
+void FAR PASCAL VertScroll(int view, WPARAM wParam, LPARAM lParam);
+void FAR PASCAL HorzScroll(int view, WPARAM wParam, LPARAM lParam);
+void FAR PASCAL KeyDown(int view, WPARAM wParam, BOOL shiftDown, BOOL ctrlDown);
+void FAR PASCAL PressChar(HWND hwnd, WPARAM wParam, LPARAM lParam);
+void FAR PASCAL SetCaret(int view, int X, int Y, int pixelPos);
+void FAR PASCAL MouseMove(int view, WPARAM wParam, int X, int Y);
+void FAR PASCAL ButtonDown( int view, WPARAM wParam, int X, int Y);
+void FAR PASCAL ButtonUp(int view, WPARAM wParam, int X, int Y);
+BOOL FAR PASCAL GetSelectedText(int view, BOOL *lookAround, LPSTR pText, int maxSize, LPINT leftCol, LPINT rightCol);
+int FAR PASCAL Pix2Pos(int view, int X, int Y);
+void FAR PASCAL TimeOut(int view);
+void FAR PASCAL InvalidateLines(int actualView, int FromL, int ToL, BOOL propagate);
+void FAR PASCAL PosXY(int view, int X, int Y, BOOL fDebugger);
+void FAR PASCAL PosXYCenter(int view, int X, int Y, BOOL fDebugger);
+void FAR PASCAL GetBlockCoord(int view, int *XL, int *YL, int *XR, int *YR);
+BOOL FAR PASCAL DeleteStream(int view, int XL, int YL, int XR, int YR, BOOL destroyRedo);
+BOOL FAR PASCAL DeleteAllStream(int view, BOOL destroyRedo);
+BOOL FAR PASCAL InsertStream(int view, int X, int Y, int Size, LPSTR Buf, BOOL destroyRedo);
+BOOL FAR PASCAL ReplaceChar(int view, int x, int y, int ch, BOOL destroyRedo);
+BOOL FAR PASCAL PasteStream(int view, int XL, int YL, int XR, int YR);
+void FAR PASCAL DeleteKey(int view);
+void FAR PASCAL ClearSelection(int view);
+void SetRORegion (int view, int Xro, int Yro);
+BOOL GetRORegion (int view, LPINT Xro, LPINT Yro);
+int FAR PASCAL GetLineLength (int view, BOOL skipBlanks, int line);
diff --git a/private/windbg/windbg/include/editutil.h b/private/windbg/windbg/include/editutil.h
new file mode 100644
index 000000000..1ed54c976
--- /dev/null
+++ b/private/windbg/windbg/include/editutil.h
@@ -0,0 +1,36 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/***********************************************************************
+
+ EDITUTIL.H
+
+ Interface routines to the editor.
+
+***********************************************************************/
+
+// prototypes
+void PASCAL InsertEditLine(
+ int doc,
+ LPSTR EditText,
+ int y,
+ BOOL VisualUpdate);
+
+void PASCAL DeleteEditLine(
+ int doc,
+ int y,
+ BOOL VisualUpdate);
+
+void PASCAL AddEditLine(
+ int doc,
+ LPSTR EditText,
+ BOOL VisualUpdate);
+
+void PASCAL ReplaceEditLine(
+ int doc,
+ LPSTR EditText,
+ int y,
+ BOOL VisualUpdate);
+
+void PASCAL SetDocLines(
+ int doc,
+ int lines);
diff --git a/private/windbg/windbg/include/eeproto.h b/private/windbg/windbg/include/eeproto.h
new file mode 100644
index 000000000..20fd3ddbe
--- /dev/null
+++ b/private/windbg/windbg/include/eeproto.h
@@ -0,0 +1,42 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+---*/
+
+extern EI Ei;
+#define Lpei (&Ei)
+
+#define EEFreeStr (Lpei)->pStructExprAPI->pEEFreeStr
+#define EEGetError (Lpei)->pStructExprAPI->pEEGetError
+#define EEParse (Lpei)->pStructExprAPI->pEEParse
+#define EEBindTM (Lpei)->pStructExprAPI->pEEBindTM
+#define EEvaluateTM (Lpei)->pStructExprAPI->pEEvaluateTM
+#define EEGetExprFromTM (Lpei)->pStructExprAPI->pEEGetExprFromTM
+#define EEGetValueFromTM (Lpei)->pStructExprAPI->pEEGetValueFromTM
+#define EEGetNameFromTM (Lpei)->pStructExprAPI->pEEGetNameFromTM
+#define EEGetTypeFromTM (Lpei)->pStructExprAPI->pEEGetTypeFromTM
+#define EEFormatCXTFromPCXT (Lpei)->pStructExprAPI->pEEFormatCXTFromPCXT
+#define EEFreeTM (Lpei)->pStructExprAPI->pEEFreeTM
+#define EEParseBP (Lpei)->pStructExprAPI->pEEParseBP
+#define EEFreeTML (Lpei)->pStructExprAPI->pEEFreeTML
+#define EEInfoFromTM (Lpei)->pStructExprAPI->pEEInfoFromTM
+#define EEFreeTI (Lpei)->pStructExprAPI->pEEFreeTI
+#define EEGetCXTLFromTM (Lpei)->pStructExprAPI->pEEGetCXTLFromTM
+#define EEFreeCXTL (Lpei)->pStructExprAPI->pEEFreeCXTL
+#define EEAssignTMToTM (Lpei)->pStructExprAPI->pEEAssignTMToTM
+#define EEIsExpandable (Lpei)->pStructExprAPI->pEEIsExpandable
+#define EEAreTypesEqual (Lpei)->pStructExprAPI->pEEAreTypesEqual
+#define EEGetHtypeFromTM (Lpei)->pStructExprAPI->pEEGetHtypeFromTM
+#define EEcChildrenTM (Lpei)->pStructExprAPI->pEEcChildrenTM
+#define EEGetChildTM (Lpei)->pStructExprAPI->pEEGetChildTM
+#define EEDereferenceTM (Lpei)->pStructExprAPI->pEEDereferenceTM
+#define EEcParamTM (Lpei)->pStructExprAPI->pEEcParamTM
+#define EEGetParmTM (Lpei)->pStructExprAPI->pEEGetParmTM
+#define EEGetTMFromHSYM (Lpei)->pStructExprAPI->pEEGetTMFromHSYM
+#define EEFormatAddress (Lpei)->pStructExprAPI->pEEFormatAddress
+#define EEGetHSYMList (Lpei)->pStructExprAPI->pEEGetHSYMList
+#define EEFreeHSYMList (Lpei)->pStructExprAPI->pEEFreeHSYMList
+#define EEFormatAddr (Lpei)->pStructExprAPI->pEEFormatAddr
+#define EEUnFormatAddr (Lpei)->pStructExprAPI->pEEUnFormatAddr
+#define EEFormatEnumerate (Lpei)->pStructExprAPI->pEEFormatEnumerate
+#define EEFormatMemory (Lpei)->pStructExprAPI->pEEFormatMemory
+#define EEUnformatMemory (Lpei)->pStructExprAPI->pEEUnformatMemory
+#define EESetSuffix (Lpei)->pStructExprAPI->pEESetSuffix
diff --git a/private/windbg/windbg/include/export.h b/private/windbg/windbg/include/export.h
new file mode 100644
index 000000000..4c7b8c340
--- /dev/null
+++ b/private/windbg/windbg/include/export.h
@@ -0,0 +1,41 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/*** EXPORT.H - Exports for the main kernel directory
+*
+* GLOBAL
+* None
+*
+* LOCAL
+* None
+*
+* DESCRIPTION
+* Function prototypes and other information required to
+* communicate with any of the main kernel modules.
+*
+* HISTORY
+* 25-Oct-90 [MannyV] Distilled for NATSYS
+* 23-Dec-87 [jimsch] Created
+*/
+
+#if 0
+typedef struct {
+ UCHAR FAR * pfnBase; /* Thunk for based heap */
+ USHORT cbBase; /* Size of based data */
+ USHORT obBssStart; /* Offset of start of based bss area */
+ USHORT obBssEnd; /* Size of based bss area */
+} OVLINFO;
+
+typedef struct {
+ USHORT cb; /* Size of structure */
+ UCHAR FAR * thunk; /* Thunk of dgroup */
+ USHORT cbData; /* Offset of _edata (size of data) */
+ USHORT cbDGroup; /* Offset of _end (size of dgroup) */
+ USHORT cbStack; /* Size of stack */
+ USHORT cbHeap; /* Size of heap */
+ USHORT psFBss; /* ps for start of FAR_BSS */
+ USHORT psFEnd; /* ps for start of FAR_END */
+ /* (end of FAR_BSS) */
+ USHORT cOvl; /* Number of ovl files */
+ OVLINFO rgOvl[0]; /* Array of ovl info */
+} DGINFO;
+#endif
diff --git a/private/windbg/windbg/include/extern.h b/private/windbg/windbg/include/extern.h
new file mode 100644
index 000000000..531aba256
--- /dev/null
+++ b/private/windbg/windbg/include/extern.h
@@ -0,0 +1,346 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+#include <stdlib.h>
+
+/****************************************************************************
+
+ EXTERNALS:
+
+****************************************************************************/
+//Handle to QcQp Colors Palette
+extern HPALETTE hPal;
+
+//Handle to instance data
+extern HANDLE hInst;
+
+//Handle to ini allocated memory
+extern HANDLE hIniMem;
+
+//Handle to ini file
+extern int iniHandle;
+
+//Handle to ini file
+extern int iniHandle;
+
+//Generic handles
+extern HANDLE hGeneric1, hGeneric2;
+
+//Generic words
+extern WORD wGeneric1, wGeneric2;
+
+//Generic __FAR pointer, (typically used for Xalloc/Xfree calls)
+extern LPSTR lpGeneric1, lpGeneric2;
+
+//Handle to edit control
+extern HWND hwndActiveEdit;
+
+// Handle to currently activated MDI debug window
+extern HWND hwndDebug;
+
+//Main window frame
+extern HWND hwndFrame;
+
+//Standard File Extensions
+extern char szStarDotC[DOS_EXT_SIZE];
+extern char szStarDotH[DOS_EXT_SIZE];
+extern char szStarDotCPP[DOS_EXT_SIZE];
+extern char szStarDotCXX[DOS_EXT_SIZE];
+extern char szStarDotLib[DOS_EXT_SIZE];
+extern char szStarDotObj[DOS_EXT_SIZE];
+extern char szStarDotDef[DOS_EXT_SIZE];
+extern char szStarDotMak[DOS_EXT_SIZE];
+extern char szStarDotRc[DOS_EXT_SIZE];
+extern char szStarDotDlg[DOS_EXT_SIZE];
+extern char szStarDotIco[DOS_EXT_SIZE];
+extern char szStarDotCur[DOS_EXT_SIZE];
+extern char szStarDotBmp[DOS_EXT_SIZE];
+extern char szStarDotFnt[DOS_EXT_SIZE];
+extern char szStarDotRes[DOS_EXT_SIZE];
+extern char szStarDotExe[DOS_EXT_SIZE];
+extern char szStarDotCom[DOS_EXT_SIZE];
+extern char szStarDotDLL[DOS_EXT_SIZE];
+extern char szStarDotInc[DOS_EXT_SIZE];
+extern char szStarDotStar[DOS_EXT_SIZE];
+
+//Input/output variables
+extern char szDefExt[_MAX_EXT];
+extern char szDefPath[_MAX_PATH];
+
+// temp variables
+extern char szPath[_MAX_PATH];
+extern char szDrive[_MAX_DRIVE];
+extern char szDir[_MAX_DIR];
+extern char szFName[_MAX_FNAME];
+extern char szExt[_MAX_EXT];
+extern char szHelpFileName[_MAX_PATH];
+
+//Temp variables for various modules
+extern char szTmp[TMP_STRING_SIZE];
+
+//Items Colors
+extern ITEMSCOLORS itemsForCols;
+extern ITEMSCOLORS itemsBakCols;
+
+
+//Syntax Coloring
+extern BOOL syntaxColors;
+
+// command "ignore registry" flag
+extern BOOL IgnoreDefault;
+
+// kernel debugger mode flag
+extern BOOL KernelDebuggerMode;
+
+//QcQp Environ Params
+extern ENVIRONPARAMS __FAR environParams;
+extern int tabSize;
+
+//RunDebug Params
+extern RUNDEBUGPARAMS runDebugParams;
+
+// Commands to execute on certain events
+extern char szStopEventCmd[];
+
+//Editor : Current view
+extern int curView;
+
+//Default Items Colors
+extern LPITEMSCOLORS defaultForCols;
+extern LPITEMSCOLORS defaultBakCols;
+
+//Array position in ppszMakefileExtTab of currently selected extension
+extern WORD nCurExt;
+
+// Handles to Include and Library Environment strings.
+extern HANDLE hEnvIncludeStr;
+extern HANDLE hEnvLibraryStr;
+
+//Status line
+extern STATUS status;
+
+//Ribbon
+extern RIBBON ribbon;
+
+//Handle to Ribbon
+extern HWND hwndRibbonClient;
+
+//Help mode flag; TRUE = "ON"
+extern BOOL bHelp;
+
+// Handle to MDI client
+extern HWND hwndMDIClient;
+
+// Handle to currently activated child
+extern HWND hwndActive;
+
+//Handle to accelerator table
+extern HANDLE hAccTable;
+
+//Keyboard Hooks functions
+extern HHOOK hKeyHook;
+
+//Replace/Find Data Structure
+extern _FINDREPLACE FAR findReplace;
+extern _FINDREPLACEMEM FAR frMem;
+
+//Editor : Global documents struct
+extern DOCREC Docs[MAX_DOCUMENTS];
+
+//Editor : Global documents struct
+extern VIEWREC Views[MAX_VIEWS];
+
+// Currently highlighted trace line (F8/F10)
+extern TRACEINFO TraceInfo;
+
+//Syntax memory line
+extern char st[MAX_USER_LINE];
+
+//Syntax memory line
+extern char st[MAX_USER_LINE];
+
+//CrLf
+extern char CrLf[2];
+
+//Number of different colors in a line
+extern int nbColors;
+
+//Screen colors saved
+//Line len divided by 2 because different colors will be separated
+//by spaces
+extern COLORINFO colors[MAX_USER_LINE + 3]; //+ 3 =When selecting
+
+// Flag that allows quickw.c to tell modify.c that it has called it
+// and the expression is passed in the string pointed to by the
+// public global var lpGeneric1
+extern BOOL CalledFromQWatch;
+
+//Emergency Flag (exit without processing WM_DESTROY and WM_CLOSE, or
+//cancelled rec)
+extern BOOL emergency;
+
+//Data for Documents Handling
+extern int rd_fh;
+extern LPSTR rd_buf;
+extern int rd_offset;
+extern int rd_read;
+extern int rd_doc;
+
+//CheckSum in ini file
+extern WORD checkSum;
+
+//Record buffer overflow counter
+extern WORD recordBufferOverflow;
+
+//Current Help Id for Open, Merge, Save and Open project dialog box
+WORD curHelpId;
+
+//Empty string
+extern char szNull[1];
+
+//State of keyboard when key is down
+extern BOOL isShiftDown;
+extern BOOL isCtrlDown;
+
+//Record stop mark
+extern int stopMarkStatus;
+
+//For modeless dialog box control
+extern BOOL exitModelessDlg;
+
+//Editor : Standard editor win proc and subclassing functions
+extern WNDPROC lpfnEditProc;
+
+//Debugger window view #
+extern int cpuView;
+extern int errorView;
+extern int watchView;
+extern int localsView;
+extern int disasmView;
+extern int cmdView;
+extern int floatView;
+extern int memView;
+extern int callsView;
+
+// Error Window : Various Variables
+extern HWND hErrorsEdit;
+extern PERRORNODE __FAR CurrentError; //CurrentError is used for F3/F4 handling. (Next/Previous error)
+extern PERRORNODE __FAR FirstError, __FAR LastError;
+extern int __FAR CurrentErrorIndex;
+extern char __FAR ErrorBase[_MAX_PATH];
+
+//Fonts variables
+extern int __FAR fontsNb;
+extern int __FAR fontSizesNb;
+extern int __FAR fontCur;
+extern int __FAR fontSizeCur;
+extern LPLOGFONT fonts; //Variable size
+extern LPINT fontSizes; //Variable size
+extern LPINT fontSizesPoint; //Variable size
+extern LOGFONT defaultFont;
+
+//Last position of cursor before undo
+extern int mC;
+extern int dL;
+
+extern int iDebugLevel;
+extern UINT radix;
+
+// Number of dialog/message boxes currently open
+extern int FAR BoxCount;
+
+//Option file full path name (qcwin.ini)
+extern char FAR iniFileName[_MAX_PATH];
+
+//Regular expression pattern (must be near)
+extern struct patType *pat;
+
+//TRUE after PostQuitMessage has been called.
+extern BOOL QuitTheSystem;
+
+//Keep overtype status
+extern BOOL FAR oldOvertype;
+
+//True when terminate application has been called
+extern BOOL FAR TerminatedApp;
+
+//Default ini mode
+extern BOOL defaultIni;
+
+//Checking date of files for reload
+extern BOOL checkFileDate;
+
+//Critical section for editor
+extern BOOL editorIsCritical;
+
+//Title bar data
+extern TITLEBAR TitleBar;
+
+//Current line expanded (tabs converted)
+extern char el[MAX_USER_LINE * 2 + 1];
+extern int elLen;
+
+//Current line and current block
+extern LPLINEREC pcl;
+extern LPBLOCKDEF pcb;
+
+//View tabs
+extern BOOL viewTabs;
+
+//Playing records mode
+extern playingRecords;
+
+//Windows Version
+extern int winVer;
+
+//Scroll origin, KEYBOARD or MOUSE
+extern WORD scrollOrigin;
+
+//Autotest mode for test suites
+extern AUTORUN AutoRun;
+extern BOOL AutoTest;
+extern BOOL NoPopups;
+extern BOOL RemoteRunning;
+extern char * PszAutoRun;
+
+// Low memory messages
+extern char LowMemoryMsg[MAX_MSG_TXT];
+extern char LowMemoryMsg2[MAX_MSG_TXT];
+
+// WinDBG title text
+extern char MainTitleText[MAX_MSG_TXT];
+
+extern char fCaseSensitive;
+extern char SuffixToAppend;
+
+extern LPSTR LpszCommandLine;
+
+extern LPTD LptdCur; // Pointer to the current thread
+extern LPPD LppdCur; // Pointer to the current process
+extern LPPD LppdFirst; // Pointer to the first (or base) process
+
+
+//
+
+extern BOOL FAsmMode; // Are we currently in assembly mode?
+
+extern HANDLE HModSH; // Symbol handler DLL handle
+extern HANDLE HModEE; // Expression evaluator DLL
+extern HANDLE HModTL; // Transport layer DLL handle
+extern HANDLE HModEM; // Execution model DLL handler
+
+//
+// Current directories
+//
+extern char SrcFileDirectory[ MAX_PATH ];
+extern char ExeFileDirectory[ MAX_PATH ];
+extern char DocFileDirectory[ MAX_PATH ];
+extern char UserDllDirectory[ MAX_PATH ];
+
+extern BOOL FSourceOverlay; /* TRUE -> overlay source windows */
+
+extern BOOL fUseFrameContext; /* TRUE -> use SetFrameContext registers */
+
+extern INT LocalFrameNumber;
+extern HANDLE hEventIoctl;
+
+extern OSVERSIONINFO OsVersionInfo;
diff --git a/private/windbg/windbg/include/filedll.h b/private/windbg/windbg/include/filedll.h
new file mode 100644
index 000000000..c741bf66f
--- /dev/null
+++ b/private/windbg/windbg/include/filedll.h
@@ -0,0 +1,179 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/****************************************************************************
+ *
+ * Copyrights - Microsoft 1991
+ *
+ ****************************************************************************/
+
+// Avoids sharing violations
+#define SHARE_EXIST (OF_EXIST | OF_SHARE_DENY_NONE)
+
+
+
+//----Constants--------------------------------------------------------------
+#if !defined (psh1)
+ #define ctlFirst 0x0400
+ #define ctlLast 0x04ff
+ // Push buttons
+ #define psh1 0x0400
+ #define psh2 0x0401
+ #define psh3 0x0402
+ #define psh4 0x0403
+ #define psh5 0x0404
+ #define psh6 0x0405
+ #define psh7 0x0406
+ #define psh8 0x0407
+ #define psh9 0x0408
+ #define psh10 0x0409
+ #define psh11 0x040a
+ #define psh12 0x040b
+ #define psh13 0x040c
+ #define psh14 0x040d
+ #define psh15 0x040e
+ #define psh16 0x040f
+ // Checkboxes
+ #define chx1 0x0410
+ #define chx2 0x0411
+ #define chx3 0x0412
+ #define chx4 0x0413
+ #define chx5 0x0414
+ #define chx6 0x0415
+ #define chx7 0x0416
+ #define chx8 0x0417
+ #define chx9 0x0418
+ #define chx10 0x0419
+ #define chx11 0x041a
+ #define chx12 0x041b
+ #define chx13 0x041c
+ #define chx14 0x041d
+ #define chx15 0x041e
+ #define chx16 0x041f
+ // Radio buttons
+ #define rad1 0x0420
+ #define rad2 0x0421
+ #define rad3 0x0422
+ #define rad4 0x0423
+ #define rad5 0x0424
+ #define rad6 0x0425
+ #define rad7 0x0426
+ #define rad8 0x0427
+ #define rad9 0x0428
+ #define rad10 0x0429
+ #define rad11 0x042a
+ #define rad12 0x042b
+ #define rad13 0x042c
+ #define rad14 0x042d
+ #define rad15 0x042e
+ #define rad16 0x042f
+ // Groups, frames, rectangles, and icons
+ #define grp1 0x0430
+ #define grp2 0x0431
+ #define grp3 0x0432
+ #define grp4 0x0433
+ #define frm1 0x0434
+ #define frm2 0x0435
+ #define frm3 0x0436
+ #define frm4 0x0437
+ #define rct1 0x0438
+ #define rct2 0x0439
+ #define rct3 0x043a
+ #define rct4 0x043b
+ #define ico1 0x043c
+ #define ico2 0x043d
+ #define ico3 0x043e
+ #define ico4 0x043f
+ // Static text
+ #define stc1 0x0440
+ #define stc2 0x0441
+ #define stc3 0x0442
+ #define stc4 0x0443
+ #define stc5 0x0444
+ #define stc6 0x0445
+ #define stc7 0x0446
+ #define stc8 0x0447
+ #define stc9 0x0448
+ #define stc10 0x0449
+ #define stc11 0x044a
+ #define stc12 0x044b
+ #define stc13 0x044c
+ #define stc14 0x044d
+ #define stc15 0x044e
+ #define stc16 0x044f
+ #define stc17 0x0450
+ #define stc18 0x0451
+ #define stc19 0x0452
+ #define stc20 0x0453
+ #define stc21 0x0454
+ #define stc22 0x0455
+ #define stc23 0x0456
+ #define stc24 0x0457
+ #define stc25 0x0458
+ #define stc26 0x0459
+ #define stc27 0x045a
+ #define stc28 0x045b
+ #define stc29 0x045c
+ #define stc30 0x045d
+ #define stc31 0x045e
+ #define stc32 0x045f
+ // Listboxes
+ #define lst1 0x0460
+ #define lst2 0x0461
+ #define lst3 0x0462
+ #define lst4 0x0463
+ #define lst5 0x0464
+ #define lst6 0x0465
+ #define lst7 0x0466
+ #define lst8 0x0467
+ #define lst9 0x0468
+ #define lst10 0x0469
+ #define lst11 0x046a
+ #define lst12 0x046b
+ #define lst13 0x046c
+ #define lst14 0x046d
+ #define lst15 0x046e
+ #define lst16 0x046f
+ // Combo boxes
+ #define cmb1 0x0470
+ #define cmb2 0x0471
+ #define cmb3 0x0472
+ #define cmb4 0x0473
+ #define cmb5 0x0474
+ #define cmb6 0x0475
+ #define cmb7 0x0476
+ #define cmb8 0x0477
+ #define cmb9 0x0478
+ #define cmb10 0x0479
+ #define cmb11 0x047a
+ #define cmb12 0x047b
+ #define cmb13 0x047c
+ #define cmb14 0x047d
+ #define cmb15 0x047e
+ #define cmb16 0x047f
+ // Edit controls
+ #define edt1 0x0480
+ #define edt2 0x0481
+ #define edt3 0x0482
+ #define edt4 0x0483
+ #define edt5 0x0484
+ #define edt6 0x0485
+ #define edt7 0x0486
+ #define edt8 0x0487
+ #define edt9 0x0488
+ #define edt10 0x0489
+ #define edt11 0x048a
+ #define edt12 0x048b
+ #define edt13 0x048c
+ #define edt14 0x048d
+ #define edt15 0x048e
+ #define edt16 0x048f
+ // Scroll bars
+ #define scr1 0x0490
+ #define scr2 0x0491
+ #define scr3 0x0492
+ #define scr4 0x0493
+ #define scr5 0x0494
+ #define scr6 0x0495
+ #define scr7 0x0496
+ #define scr8 0x0497
+#endif
diff --git a/private/windbg/windbg/include/findrep.h b/private/windbg/windbg/include/findrep.h
new file mode 100644
index 000000000..36f2f8061
--- /dev/null
+++ b/private/windbg/windbg/include/findrep.h
@@ -0,0 +1,32 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+void FAR PASCAL SetStopLimit(
+ void);
+
+BOOL FAR PASCAL FindNext(
+ int startingLine,
+ int startingCol,
+ BOOL startFromSelection,
+ BOOL selectFoundText,
+ BOOL errorIfNotFound);
+
+void FAR PASCAL Find(
+ void);
+
+void FAR PASCAL ReplaceOne(
+ void);
+
+void FAR PASCAL ReplaceAll(
+ void);
+
+void FAR PASCAL Replace(
+ void);
+
+BOOL FAR PASCAL InsertInPickList(
+ WORD type);
+
+void FAR PASCAL RemoveFromPick(
+ WORD type);
+
+void FAR PASCAL TagAll(
+ int y);
diff --git a/private/windbg/windbg/include/fonts.h b/private/windbg/windbg/include/fonts.h
new file mode 100644
index 000000000..e827b87d6
--- /dev/null
+++ b/private/windbg/windbg/include/fonts.h
@@ -0,0 +1,110 @@
+/*++ BUILD Version: 0001
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Fonts.h
+
+Abstract:
+
+
+Author:
+
+ David J. Gilman (davegi) 30-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 11-Sep-1992
+
+Environment:
+
+ CRT, Windows, User Mode
+
+--*/
+
+#if ! defined( _FONTS_ )
+
+#define _FONTS_
+
+
+typedef
+enum
+_WINDOW_FONT {
+
+ DOC_WINDOW_FONT = DOC_WIN,
+ WATCH_WINDOW_FONT = WATCH_WIN,
+ LOCALS_WINDOW_FONT = LOCALS_WIN,
+ CPU_WINDOW_FONT = CPU_WIN,
+ DISASM_WINDOW_FONT = DISASM_WIN,
+ COMMAND_WINDOW_FONT = COMMAND_WIN,
+ FLOAT_WINDOW_FONT = FLOAT_WIN,
+ MEMORY_WINDOW_FONT = MEMORY_WIN,
+ DEFAULT_WINDOW_FONT
+
+} WINDOW_FONT;
+
+extern LOGFONT WindowLogFont[ ];
+
+extern BOOL UseSystemFontFlag;
+
+// WORD
+// GetCurrentWindowType(
+// );
+
+
+#define GetCurrentWindowType( ) \
+ ( Docs[Views[curView].Doc].docType )
+
+
+
+// LPLOGFONT GetWindowLogfont(IN WINDOW_FONT WindowFont);
+
+#define GetWindowLogfont( WindowFont ) \
+ ( WindowLogFont[ WindowFont ])
+
+
+
+
+// LPLOGFONT GetCurrentWindowLogfont();
+
+#define GetCurrentWindowLogfont( ) \
+ ( WindowLogFont[ GetCurrentWindowType( )])
+
+
+
+// LPLOGFONT GetDefaultWindowLogfont();
+
+#define GetDefaultWindowLogfont( ) \
+ ( WindowLogFont[ DEFAULT_WINDOW_FONT ])
+
+
+
+// int GetWindowLogfontCount();
+
+#define GetWindowLogfontCount( ) \
+ ( sizeof( WINDOW_FONT ))
+
+
+
+
+// VOID SetWindowLogfont (INT WindowType, IN LPLOGFONT NewWindowLogfont);
+
+#define SetWindowLogfont( WindowType, NewWindowLogfont) \
+ { \
+ memcpy( WindowLogFont[WindowType], NewWindowLogFont, sizeof(LOGFONT)); \
+ UseSystemFontFlag = FALSE; \
+ }
+
+
+// VOID SetDefaultWindowLogfont (IN LPLOGFONT NewDefaultWindowLogfont);
+
+#define SetDefaultWindowLogfont(NewDefaultWindowLogfont) \
+ { \
+ memcpy( WindowLogFont[DEFAULT_WINDOW_FONT], NewWindowLogFont, sizeof(LOGFONT)); \
+ UseSystemFontFlag = FALSE; \
+ }
+
+
+
+
+BOOL SelectFont (HWND hWnd);
+
+#endif // _FONTS_
diff --git a/private/windbg/windbg/include/global.h b/private/windbg/windbg/include/global.h
new file mode 100644
index 000000000..b4b65b67e
--- /dev/null
+++ b/private/windbg/windbg/include/global.h
@@ -0,0 +1,104 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Global.h
+
+Abstract:
+
+ This module is the master header file for the Windbg debugger. It is
+ included by every source module in the debugger and is expected to
+ be precompiled eventually.
+
+ It only includes .h files with global impact
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 12-Dec-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if DBG
+
+//
+// DbgPrint, ASSERT & ASSERTMSG access.
+//
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+#define DWORDLONG ULONGLONG
+
+#else
+
+typedef unsigned long PHYSICAL_ADDRESS;
+
+#endif // DBG
+
+#include <windows.h>
+#include <shellapi.h>
+
+//
+// CRT Headers
+//
+
+#include <ctype.h>
+#include <direct.h>
+#include <dos.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <malloc.h>
+#include <math.h>
+#include <memory.h>
+#include <process.h>
+#include <search.h>
+#include <share.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <sys\timeb.h>
+
+
+#include "cvinfo.h"
+#include "cvtypes.hxx"
+#include "lltypes.h"
+#include "linklist.h"
+#include "shapi.hxx"
+#include "windbg.h"
+
+#include "change.h"
+#include "cl.h"
+#include "cmdexec.h"
+#include "cmgrhigh.h"
+#include "cmgrlow.h"
+#include "debug.h"
+#include "dialogs.h"
+#include "eeproto.h"
+#include "export.h"
+#include "extern.h"
+#include "filedll.h"
+#include "inifile.h"
+#include "mstools.h"
+#include "re.h"
+#include "resource.h"
+#include "res_str.h"
+#include "sbconst.h"
+#include "settings.h"
+#include "shproto.h"
+#include "systemw3.h"
+#include "vapi.h"
+#include "windbg.h"
+#include "winpck.h"
diff --git a/private/windbg/windbg/include/helpid.h b/private/windbg/windbg/include/helpid.h
new file mode 100644
index 000000000..405e05b05
--- /dev/null
+++ b/private/windbg/windbg/include/helpid.h
@@ -0,0 +1,208 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Helpid.h
+
+Abstract:
+
+ This module contains the # defines for helpid's and identifiers for
+ Windbg's menus and menu items.
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 14-August-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+// First MDI child window ID.
+
+#define FIRST_CHILD_WINDOW_ID 33
+
+// Type of menu.
+
+#define FILE_MENU_TYPE 0
+#define PROGRAM_MENU_TYPE 1
+
+
+
+// Menu Resource Signature
+
+#define MENU_SIGNATURE 0x4000
+
+
+// Accelerator IDs
+
+#define IDA_BASE 10000
+#define IDA_FINDNEXT 10001
+
+
+
+//Base menu ID
+
+#define IDM_BASE 100
+
+//
+// File
+//
+
+#define IDM_FILE 16484
+#define IDM_FILE_NEW 16485
+#define IDM_FILE_OPEN 16486
+#define IDM_FILE_MERGE 16487
+#define IDM_FILE_CLOSE 16488
+#define IDM_FILE_SAVE 16489
+#define IDM_FILE_SAVEAS 16490
+#define IDM_FILE_SAVEALL 16491
+#define IDM_FILE_EXIT 16492
+#define IDM_FILE_FIRST 16484
+#define IDM_FILE_LAST 16492
+
+//
+// Edit
+//
+
+#define IDM_EDIT 16584
+#define IDM_EDIT_UNDO 16585
+#define IDM_EDIT_REDO 16586
+#define IDM_EDIT_CUT 16587
+#define IDM_EDIT_COPY 16588
+#define IDM_EDIT_PASTE 16589
+#define IDM_EDIT_DELETE 16590
+#define IDM_EDIT_FIND 16591
+#define IDM_EDIT_REPLACE 16592
+#define IDM_EDIT_READONLY 16593
+#define IDM_EDIT_FIRST 16584
+#define IDM_EDIT_LAST 16593
+
+//
+// View
+//
+
+#define IDM_VIEW 16684
+#define IDM_VIEW_LINE 16685
+#define IDM_VIEW_FUNCTION 16686
+#define IDM_VIEW_TOGGLETAG 16687
+#define IDM_VIEW_NEXTTAG 16688
+#define IDM_VIEW_PREVIOUSTAG 16689
+#define IDM_VIEW_CLEARALLTAGS 16690
+#define IDM_VIEW_RIBBON 16691
+#define IDM_VIEW_STATUS 16692
+#define IDM_VIEW_FIRST 16684
+#define IDM_VIEW_LAST 16692
+
+//
+// Program
+//
+
+#define IDM_PROGRAM 16784
+#define IDM_PROGRAM_OPEN 16785
+#define IDM_PROGRAM_CLOSE 16786
+#define IDM_PROGRAM_SAVE 16787
+#define IDM_PROGRAM_SAVEAS 16788
+#define IDM_PROGRAM_DELETE 16789
+#define IDM_PROGRAM_SAVE_DEFAULTS 16790
+#define IDM_PROGRAM_FIRST 16784
+#define IDM_PROGRAM_LAST 16790
+
+//
+// Run
+//
+
+#define IDM_RUN 16884
+#define IDM_RUN_RESTART 16885
+#define IDM_RUN_STOPDEBUGGING 16886
+#define IDM_RUN_GO 16887
+#define IDM_RUN_TOCURSOR 16888
+#define IDM_RUN_TRACEINTO 16889
+#define IDM_RUN_STEPOVER 16890
+#define IDM_RUN_HALT 16891
+#define IDM_RUN_SET_THREAD 16892
+#define IDM_RUN_SET_PROCESS 16893
+#define IDM_RUN_SOURCE_MODE 16894
+#define IDM_RUN_ATTACH 16895
+#define IDM_RUN_GO_HANDLED 16896
+#define IDM_RUN_GO_UNHANDLED 16897
+#define IDM_RUN_FIRST 16884
+#define IDM_RUN_LAST 16897
+
+//
+// Debug
+//
+
+#define IDM_DEBUG 16984
+#define IDM_DEBUG_CALLS 16985
+#define IDM_DEBUG_SETBREAK 16986
+#define IDM_DEBUG_QUICKWATCH 16987
+#define IDM_DEBUG_WATCH 16988
+#define IDM_DEBUG_MODIFY 16989
+#define IDM_DEBUG_FIRST 16984
+#define IDM_DEBUG_LAST 16989
+
+//
+// Options
+//
+
+#define IDM_OPTIONS 17084
+#define IDM_OPTIONS_RUN 17085
+#define IDM_OPTIONS_DEBUG 17086
+#define IDM_OPTIONS_MEMORY 17087
+#define IDM_OPTIONS_WATCH 17088
+#define IDM_OPTIONS_DISASSEMBLY 17089
+#define IDM_OPTIONS_ENVIRON 17090
+#define IDM_OPTIONS_WORKSPACE 17091
+#define IDM_OPTIONS_COLOR 17092
+#define IDM_OPTIONS_FONTS 17093
+#define IDM_OPTIONS_LOCAL 17094
+#define IDM_OPTIONS_CPU 17095
+#define IDM_OPTIONS_FLOAT 17096
+#define IDM_OPTIONS_KD 17097
+#define IDM_OPTIONS_CALLS 17098
+#define IDM_OPTIONS_USERDLL 17099
+#define IDM_OPTIONS_DBGDLL 17100
+#define IDM_OPTIONS_EXCEPTIONS 17101
+
+#define IDM_OPTIONS_FIRST 17084
+#define IDM_OPTIONS_LAST 17101
+
+
+//
+// Window
+//
+
+#define IDM_WINDOW 17184
+#define IDM_WINDOW_NEWWINDOW 17185
+#define IDM_WINDOW_CASCADE 17186
+#define IDM_WINDOW_TILE 17187
+#define IDM_WINDOW_ARRANGE 17188
+#define IDM_WINDOW_ARRANGE_ICONS 17189
+#define IDM_WINDOW_SOURCE_OVERLAY 17190
+#define IDM_WINDOW_WATCH 17191
+#define IDM_WINDOW_LOCALS 17192
+#define IDM_WINDOW_CPU 17193
+#define IDM_WINDOW_DISASM 17194
+#define IDM_WINDOW_COMMAND 17195
+#define IDM_WINDOW_FLOAT 17196
+#define IDM_WINDOW_MEMORY 17197
+#define IDM_WINDOW_CALLS 17198
+#define IDM_WINDOWCHILD 17199
+#define IDM_WINDOW_FIRST 17184
+#define IDM_WINDOW_LAST 17198
+
+//
+// Help
+//
+
+#define IDM_HELP 17284
+#define IDM_HELP_CONTENTS 17285
+#define IDM_HELP_SEARCH 17286
+#define IDM_HELP_ABOUT 17287
+#define IDM_HELP_FIRST 17284
+#define IDM_HELP_LAST 17287
diff --git a/private/windbg/windbg/include/imports.h b/private/windbg/windbg/include/imports.h
new file mode 100644
index 000000000..ceeeabc32
--- /dev/null
+++ b/private/windbg/windbg/include/imports.h
@@ -0,0 +1,64 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Imports.h
+
+Abstract:
+
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _IMPORTS_ )
+#define _IMPORTS_
+
+#include "vapi.h"
+
+typedef struct imports {
+ gdap_t (FAR PASCAL *_VapGdaGet)( void );
+ WORD (FAR PASCAL *_VapQGetEnv)(char far *, char far *, int);
+ unsigned (FAR PASCAL *_VapCbAllocSb)(SB, unsigned, int);
+ unsigned (FAR PASCAL *_VapCbReallocSb)(SB, unsigned, int);
+ unsigned long (FAR PASCAL *_VapLcbAllocSb)(SB, unsigned long, int);
+ unsigned long (FAR PASCAL *_VapLcbReallocSb)(SB, unsigned long, int);
+ VOID (FAR PASCAL *_VapFreeSb)(SB);
+ SB (FAR PASCAL *_VapSbScanNext)(SB, SB, int);
+ unsigned (FAR PASCAL *_VapCbSizeSb)(SB);
+ BOOL (FAR PASCAL *_VapFUsedSb)( SB );
+ VOID FAR * (FAR PASCAL *_VapLpLockSb)( SB );
+ VOID (FAR PASCAL *_VapUnlockSb)( SB );
+ VOID FAR * (FAR PASCAL *_VapLpLockHp)(HP);
+ VOID (FAR PASCAL *_VapUnlockHp)(HP);
+ int (FAR PASCAL *_VapUpdateFileName)(char far *, int, int);
+ int (FAR PASCAL *_VapUpdateLineCount)(int, int, int);
+ int (FAR cdecl *_VapIoOpen)(char far *, int, ...);
+ int (FAR cdecl *_VapIoClose)(int);
+ int (FAR cdecl *_VapIoRead)(int, char far *, unsigned int);
+ int (FAR cdecl *_VapIoWrite)(int, char far *, unsigned int);
+ int (FAR cdecl *_VapVioOpen)(char far *, int, ...);
+ int (FAR cdecl *_VapVioClose)(int);
+ int (FAR cdecl *_VapVioRead)(int, char far *, unsigned int);
+ int (FAR cdecl *_VapVioWrite)(int, char far *, unsigned int);
+ int (FAR cdecl *_VapVioCntl)(int, int, ...);
+ long (FAR cdecl *_VapVioSeek)(int, long, int);
+ long (FAR cdecl *_VapIoSeek)(int, long, int);
+ int (FAR cdecl *_VapIoGetFTime)(int, FTIMEDATE far *);
+ BOOL (FAR PASCAL *_KnLoadBasedSeg)(SB, UCHAR FAR *, UCHAR FAR *, USHORT);
+ void (FAR cdecl *_GlobalDump)(int);
+ void (FAR cdecl *_GlobalDump1)(int, int);
+ void (FAR cdecl *_SbDump)(int);
+ void (FAR cdecl *_SbDump1)(int, int);
+
+} IMPORTS;
+
+#endif // _IMPORTS_
diff --git a/private/windbg/windbg/include/inifile.h b/private/windbg/windbg/include/inifile.h
new file mode 100644
index 000000000..87bdc4dbb
--- /dev/null
+++ b/private/windbg/windbg/include/inifile.h
@@ -0,0 +1,15 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+//Loads ini file from disk into memory
+int FAR PASCAL LoadIniFile(
+ void);
+
+//Saves ini file to disk
+void FAR PASCAL SaveIniFile(void );
+
+BOOL FAR PASCAL ReadStrFromFile(int hFile, LPSTR lpszStr, int wMaxSize, BOOL iniFile);
+
+BOOL FAR PASCAL WriteStrToFile(
+ int hFile,
+ LPSTR lpszStr,
+ BOOL iniFile);
diff --git a/private/windbg/windbg/include/init.h b/private/windbg/windbg/include/init.h
new file mode 100644
index 000000000..d8367cb62
--- /dev/null
+++ b/private/windbg/windbg/include/init.h
@@ -0,0 +1,64 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/****************************************************************************
+
+ PROTOTYPES DECLARATION FOR INIT MODULE
+
+****************************************************************************/
+
+// Inititialize a QCQP Application
+BOOL InitApplication(HANDLE hInstance);
+
+// Inititialize a New QCQP Instance
+BOOL InitInstance(int argc, char * argv[], HANDLE hInstance, int nCmdShow);
+
+// Initialize QcQp Color Palette
+HPALETTE InitPalette(
+ VOID);
+
+// Reset the '&pItemCols' Color Items to default Foreground and Background Colors
+VOID InitDefaultColors(
+ LPITEMSCOLORS pItemForCols,
+ LPITEMSCOLORS pItemBakCols);
+
+//Reset the QpQc Environment params to their default values
+VOID InitDefaultEnvironParams(
+ LPENVIRONPARAMS pParams);
+
+//Reset the QpQc Run/Debug params to their default values
+VOID InitDefaultRunDebugParams(
+ LPRUNDEBUGPARAMS pParams);
+
+//Initialize Status Line Font
+void InitStatus (
+ HWND hwnd,
+ NPSTATUS st);
+
+//Initialize Ribbon
+void InitRibbon (
+ HWND hwnd,
+ NPRIBBON rb);
+
+//Iniitialize all possible files extension we handle
+void InitFileExtensions(
+ void);
+
+//Initialize default font
+void InitDefaultFont(
+ void);
+
+//Initialize default find and replace structure
+void InitDefaultFindReplace(
+ void);
+
+//Initialize workspace
+void InitWorkspace(
+ void);
+
+//Title bar data
+void NEAR PASCAL InitTitleBar(
+ void);
+
+//Initialize all defaults
+void FAR PASCAL InitDefaults(
+ void);
diff --git a/private/windbg/windbg/include/linklist.h b/private/windbg/windbg/include/linklist.h
new file mode 100644
index 000000000..0993f546d
--- /dev/null
+++ b/private/windbg/windbg/include/linklist.h
@@ -0,0 +1,43 @@
+#ifndef _LINKLIST_
+#define _LINKLIST_
+
+
+/*
+** Prototypes for the list manager system
+*/
+typedef struct _LLI *PLLI;
+typedef struct _LLE *PLLE;
+
+PLLI WINAPI LLPlliInit( UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE );
+PLLE WINAPI LLPlleCreate( PLLI );
+VOID WINAPI LLAddPlleToLl( PLLI, PLLE );
+VOID WINAPI LLInsertPlleInLl( PLLI, PLLE, DWORD );
+BOOL WINAPI LLFDeletePlleIndexed( PLLI, DWORD );
+BOOL WINAPI LLFDeleteLpvFromLl( PLLI, PLLE, LPV, DWORD );
+BOOL WINAPI LLFDeletePlleFromLl( PLLI, PLLE );
+PLLE WINAPI LLPlleFindNext( PLLI, PLLE );
+DWORD WINAPI LLChlleDestroyLl( PLLI );
+PLLE WINAPI LLPlleFindLpv( PLLI, PLLE, LPV, DWORD );
+DWORD WINAPI LLChlleInLl( PLLI );
+LPV WINAPI LLLpvFromPlle( PLLE );
+VOID WINAPI LLUnlockPlle( PLLE );
+PLLE WINAPI LLPlleGetLast( PLLI );
+VOID WINAPI LLPlleAddToHeadOfLI( PLLI, PLLE );
+BOOL WINAPI LLFRemovePlleFromLl( PLLI, PLLE );
+
+
+#ifdef DBLLINK
+extern PLLE WINAPI LLPlleFindPrev( PLLI, PLLE );
+#endif // DBLLINK
+
+//
+// FCheckPlli is for debug versions ONLY as an integrety check
+//
+
+#ifdef DEBUGVER
+extern BOOL PASCAL LLFCheckPlli( PLLI );
+#else // DEBUGVER
+#define LLFCheckPlli(plli) TRUE
+#endif // DEBUGVER
+
+#endif // _LINKLIST_
diff --git a/private/windbg/windbg/include/localwin.h b/private/windbg/windbg/include/localwin.h
new file mode 100644
index 000000000..fd974692a
--- /dev/null
+++ b/private/windbg/windbg/include/localwin.h
@@ -0,0 +1,7 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+HWND GetLocalHWND(void);
+LONG FAR PASCAL LOADDS LocalEditProc (HWND hwnd,UINT msg,
+ WPARAM wParam, LPARAM lParam);
+
diff --git a/private/windbg/windbg/include/makeeng.h b/private/windbg/windbg/include/makeeng.h
new file mode 100644
index 000000000..a493e92ec
--- /dev/null
+++ b/private/windbg/windbg/include/makeeng.h
@@ -0,0 +1,273 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/*********************************************************************
+
+ File: makeeng.h
+
+ Date created: 27/8/90
+
+ Author: Tim Bell
+
+ Description:
+
+ Windows Make Engine API
+
+ Modified:
+
+*********************************************************************/
+
+
+
+#ifdef LATER
+
+/* Structures definitions for the Options.Make dialog */
+typedef struct
+{
+ int nDebugMode;
+ int nProgType;
+} OPTMAKE_DLGVALS;
+
+
+/* Structures and defines for Options.Make.Compiler dialog */
+typedef enum { OPT_ON, OPT_OFF, OPT_FULL } OPTIMIZATION;
+
+#define FLAG_SIZE 128 // width of flags edit fields
+#define NUM_WARNINGS 5 // number of supported warning levels
+
+#define WARN_RANGE(i) ((i >= 0) && (i <= 4))
+
+#define DELIMETER_1 '/'
+#define DELIMETER_2 '-'
+#define OPTION_DELIMETER(ch) ((ch == DELIMETER_1) || (ch == DELIMETER_2))
+
+#define GLOBAL_FLAGS 0x1
+#define DEBUG_FLAGS 0x2
+#define RELEASE_FLAGS 0x4
+#define DEFINES_FLAGS 0x8
+
+#define MACRO_SEPARATOR '='
+
+// structure to hold settings of C Compiler Flags
+typedef struct
+{
+ // Global Flags
+ int nGBLMemModel;
+ int nGBLWarnLevel;
+ BOOL fGBLMSExts;
+
+ // Debug Flags
+ BOOL fDBCodeview;
+ BOOL fDBPtrCheck;
+ BOOL fDBIncrComp;
+
+ // Release Flags
+ OPTIMIZATION nRELOptimize;
+ BOOL fRELNoStkChk;
+
+ // Custom flags + defines
+ LPSTR lpszCustomG;
+ LPSTR lpszCustomD;
+ LPSTR lpszCustomR;
+ LPSTR lpszDefines;
+
+} CFLAGS_DLGVALS;
+
+
+typedef struct
+{
+ // Global
+ BOOL fIgnoreCase;
+ BOOL fExtDict;
+ BOOL fIgnoreDefLib;
+ WORD wStackSize;
+ WORD wAlignment;
+
+ // Debug
+ BOOL fCodeview;
+ BOOL fCVPack;
+ BOOL fMapFile;
+ BOOL fIncrLink; //%Not used anymore, can be removed if wished
+
+ // Custom flags
+ LPSTR lpszCustomG;
+ LPSTR lpszCustomD;
+ LPSTR lpszCustomR;
+
+} LNKFLAGS_DLGVALS;
+
+
+typedef struct
+{
+ // Standard flags
+ BOOL fSearchInclude;
+ BOOL fProtectMode;
+ BOOL fDisableLoadOpt;
+
+ // Custom flags + defines
+ LPSTR lpszCustom;
+ LPSTR lpszDefines;
+
+} RESFLAGS_DLGVALS;
+
+
+/* Defines */
+
+// Token ids corresponding to the positions in the above arrays
+#define LTOKEN_NOIGNORECASE 0
+#define LTOKEN_NOEXTDICTIONARY 1
+#define LTOKEN_NODEFAULTLIBRARYSEARCH 2
+#define LTOKEN_ALIGNMENT 3
+#define LTOKEN_STACK 4
+#define LTOKEN_CODEVIEW 5
+#define LTOKEN_MAP 6
+#define LTOKEN_INCREMENTAL 7
+
+#define NUM_LINK_OPTS 8
+
+
+/* ORable action flags to wMkEngUpdateProgramList */
+#define MKENG_ADDTOLIST 0x1
+#define MKENG_DELFROMLIST 0x2
+
+/* wMkEngUpdateProgramList return values */
+#define MKENG_ADDEDLISTMEMBER 1 // Successfully added
+#define MKENG_DELETEDLISTMEMBER 2 // Successfully deleted
+#define MKENG_NOFILESPEC 3 // No file specified
+#define MKENG_BADFILESPEC 4 // Bad file spec.
+#define MKENG_INVALIDLISTMEMBER 5 // Not valid file type
+#define MKENG_ONEDEFPERMAKE 6 // Attempt to add another .DEF file
+#define MKENG_ONEMAINRESOURCEPERMAKE 7 // Attept to add another .RES or .RC
+ // when a .RES or .RC already exists
+#define MKENG_MEMBERALREADYINLIST 8 // Attempt to add file already in list
+#define MKENG_FILENOTINLIST 9 // Attempt to delete file not in list
+
+
+typedef enum
+{
+ EXEC_RESTART,
+ EXEC_GO,
+ EXEC_STEPANDGO,
+ EXEC_TOCURSOR,
+ EXEC_TRACEINTO,
+ EXEC_STEPOVER
+} EXECTYPE;
+
+
+/* Prototypes */
+/* MAKEENG prototypes */
+WORD PASCAL wMkEngUpdateProgramList(PSTR pszNewListItem, WORD wUpdateAction);
+void PASCAL MkEngSetListWasNew(void);
+WORD PASCAL fMkEngSaveProgramList(void);
+void PASCAL MkEngCancelProgramList(void);
+WORD PASCAL wMkEngSetUpDispProgList(void);
+void PASCAL MkEngGetDispProgListItem(WORD wListItem, PSTR pszListItemBuffer,
+ WORD wBufferLength);
+WORD PASCAL wMkEngNumDispProgListItems(void);
+BOOL PASCAL fMkEngFindDispProgListItem(PSTR pszSearchStr, WORD *pwListItem);
+void PASCAL MkEngFreeDispProgList(void);
+BOOL PASCAL fMkEngGetCurMakefile(LPSTR pszBuffer, int wBufferLen, BOOL fOverride);
+BOOL PASCAL fMkEngMakefileLoaded(void);
+PSTR PASCAL pszMkEngCurrentExeExt(void);
+BOOL PASCAL fMkEngLoadNewProgramList(PSTR szNewMakefile);
+void PASCAL MkEngInitForceEdit(void);
+BOOL PASCAL fMkEngForceEdit(void);
+void PASCAL MkEngInitMakeEngine(void);
+void PASCAL MkEngCloseMakeEngine(void);
+void PASCAL MkEngSetProj(BOOL fForce);
+BOOL PASCAL fMkEngReadMakefile(char *szFilename);
+void PASCAL MkEngCompile(void);
+void PASCAL MkEngBuild(void);
+void PASCAL MkEngRebuild(void);
+void PASCAL MkEngClearList(void);
+ATOM __FAR * PASCAL hMkEngSaveOptMakeVals(OPTMAKE_DLGVALS *OptMakeVars);
+void PASCAL MkEngNewOptMakeVals(OPTMAKE_DLGVALS __FAR *PrevOptMakeVars,
+ OPTMAKE_DLGVALS __FAR *NewOptMakeVars);
+void PASCAL MkEngRestoreOptMakeVals(ATOM __FAR *patmMkFlags);
+void PASCAL MkEngFreeOptMakeVals(ATOM __FAR *patmMkFlags);
+int PASCAL nMkEngDosExeVal(void);
+int PASCAL nMkEngWinExeVal(void);
+int PASCAL nMkEngWinDllVal(void);
+int PASCAL nMkEngWinTtyVal(void);
+
+void PASCAL MkEngSetMacPtrs(
+ int nProgType,
+ PSTR *ppszCflagsG, PSTR *ppszCflagsD, PSTR *ppszCflagsR,
+ PSTR *ppszLflagsG, PSTR *ppszLflagsD, PSTR *ppszLflagsR);
+
+void PASCAL MkEngParseCFlags(
+ CFLAGS_DLGVALS __FAR *lpCFlags,
+ int nDebugMode,
+ int nProgType);
+
+void PASCAL MkEngUnParseCFlags(
+ CFLAGS_DLGVALS __FAR *pNewCFlags,
+ CFLAGS_DLGVALS __FAR *pCurCFlags,
+ int nDebugMode,
+ int nProgType);
+
+BOOL PASCAL fMkEngReadMacroVals(int hFile);
+BOOL PASCAL fMkEngWriteMacroVals(int hFile);
+
+void PASCAL MkEngParseResFlags(
+ RESFLAGS_DLGVALS __FAR *lpResFlags,
+ int nDebugMode,
+ int nProgType);
+
+void PASCAL MkEngUnParseResFlags(
+ RESFLAGS_DLGVALS __FAR *lpNewResFlags,
+ RESFLAGS_DLGVALS __FAR *lpCurResFlags,
+ int nDebugMode,
+ int nProgType);
+
+void PASCAL MkEngParseLnkFlags(
+ LNKFLAGS_DLGVALS __FAR *lpLnkFlags,
+ int nDebugMode,
+ int nProgType);
+
+void PASCAL MkEngUnParseLnkFlags(
+ LNKFLAGS_DLGVALS __FAR *lpNewLnkFlags,
+ LNKFLAGS_DLGVALS __FAR *lpCurLnkFlags,
+ int nDebugMode,
+ int nProgType);
+
+WORD PASCAL wMkEngStackSize(int nProgType);
+
+BOOL PASCAL MkEngSetMakeDriveDir(void);
+
+PSTR PASCAL pszWinTempFileName(PSTR pszPrefix, PSTR pszFileName);
+
+int PASCAL nCurProgType(void);
+
+int PASCAL nCurDebugMode(void);
+
+int PASCAL nWantCVPack(void);
+
+char PASCAL cCurMemModel(void);
+
+BOOL PASCAL fRCSearchInclude(void);
+
+BOOL PASCAL fDocModified(char *pszFilename, long *ptime);
+
+BOOL PASCAL fChkEditorFiles(char *pszFilename);
+
+BOOL PASCAL DebuggeeFileModified(int doc);
+
+
+BOOL PASCAL DoDefLibSearch(void);
+
+
+
+#endif
+
+
+typedef enum
+{
+ EXEC_RESTART,
+ EXEC_GO,
+ EXEC_STEPANDGO,
+ EXEC_TOCURSOR,
+ EXEC_TRACEINTO,
+ EXEC_STEPOVER
+} EXECTYPE;
+
+BOOL PASCAL ExecDebuggee(EXECTYPE ExecType);
diff --git a/private/windbg/windbg/include/memwin.h b/private/windbg/windbg/include/memwin.h
new file mode 100644
index 000000000..e30b6d1e8
--- /dev/null
+++ b/private/windbg/windbg/include/memwin.h
@@ -0,0 +1,87 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+#define MAX_CHUNK_TOREAD 4096 // maximum chunk of memory to read at one go
+
+
+LONG FAR PASCAL LOADDS
+MemoryEditProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+void ViewMem(int view, BOOL fVoidCache);
+
+
+extern char memText[MAX_MSG_TXT]; //the selected text for memory dlg
+
+
+struct memItem {
+ char iStart;
+ char cch;
+ char iFmt;
+};
+
+
+struct memWinDesc {
+ int iFormat;
+ ATOM atmAddress;
+ BOOL fLive;
+ BOOL fHaveAddr;
+ BOOL fBadRead; // dis we really read mem or just ??
+ char FAR * lpbBytes;
+ struct memItem FAR * lpMi;
+ UINT cMi;
+ BOOL fEdit;
+ BOOL fFill;
+ UINT cPerLine;
+ ADDR addr;
+ ADDR orig_addr;
+ ADDR old_addr;
+ char szAddress[MAX_MSG_TXT]; //the mem address expression in ascii
+ UINT cbRead;
+};
+
+extern struct memWinDesc MemWinDesc[MAX_VIEWS];
+extern struct memWinDesc TempMemWinDesc;
+
+/*
+** Define the set of memory formats
+*/
+
+enum {
+ MW_ASCII = 0,
+ MW_BYTE,
+ MW_SHORT,
+ MW_SHORT_HEX,
+ MW_SHORT_UNSIGNED,
+ MW_LONG,
+ MW_LONG_HEX,
+ MW_LONG_UNSIGNED,
+ MW_QUAD,
+ MW_QUAD_HEX,
+ MW_QUAD_UNSIGNED,
+ MW_REAL,
+ MW_REAL_LONG,
+ MW_REAL_TEN
+};
+
+#define MEM_FORMATS {\
+ 1, /* ASCII */ \
+ 1, /* BYTE */ \
+ 2, /* SHORT */ \
+ 2, /* SHORT_HEX */ \
+ 2, /* SHORT_UNSIGNED */ \
+ 4, /* LONG */ \
+ 4, /* LONG_HEX */ \
+ 4, /* LONG_UNSIGNED */ \
+ 8, /* QUAD */ \
+ 8, /* QUAD_HEX */ \
+ 8, /* QUAD_UNSIGNED */ \
+ 4, /* REAL */ \
+ 8, /* REAL_LONG */ \
+ 10, /* REAL_TEN */ \
+ 16 /* */ \
+}
diff --git a/private/windbg/windbg/include/menu.h b/private/windbg/windbg/include/menu.h
new file mode 100644
index 000000000..342bb5142
--- /dev/null
+++ b/private/windbg/windbg/include/menu.h
@@ -0,0 +1,484 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Menu.h
+
+Abstract:
+
+ This module contains the function prototypes and identifiers for
+ Windbg's menus and menu items.
+
+Author:
+
+ David J. Gilman (davegi) 15-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+//
+// Number of menus w/o a maximized child.
+//
+
+#define NUMBER_OF_MENUS ( 9 )
+//
+// Maximum MRU names for File and Program menu.
+//
+
+#define MAX_MRU_FILES_KEPT ( 4 )
+
+//
+// Width of names in File and Program menu.
+//
+
+#define FILES_MENU_WIDTH ( 24 )
+
+// NOTENOTE davegi From here to the next NOTENOTE needs to be removed.
+
+//Keep the 4 most recently used files (editor and project)
+extern HANDLE hFileKept[PROJECT_FILE + 1][MAX_MRU_FILES_KEPT];
+extern int nbFilesKept[PROJECT_FILE + 1];
+
+//Window submenu
+extern HMENU hWindowSubMenu;
+
+//Last menu id & id state
+extern IWORD FAR lastMenuId;
+extern IWORD FAR lastMenuIdState;
+
+void FAR PASCAL InsertKeptFileNames(
+ WORD type,
+ int menuPos,
+ WORD menuId,
+ LPSTR newName
+ );
+
+UINT
+CommandIdEnabled(
+ IN UINT MenuID
+ );
+
+void AddWindowMenuItem(
+ int doc,
+ int view);
+
+void DeleteWindowMenuItem(
+ int view);
+
+int FindWindowMenuId(
+ WORD type,
+ int viewLimit,
+ BOOL sendDocMenuId);
+
+// NOTENOTE davegi See above.
+
+//
+// Handle to main window menu.
+//
+
+extern HMENU hMainMenu;
+
+//
+// INT
+// GetActualMenuCount(
+// IN HMENU hMenu
+// );
+//
+
+#define GetActualMenuCount( ) \
+ ( GetMenuItemCount(( HMENU )( hMainMenu )) == NUMBER_OF_MENUS ) \
+ ? NUMBER_OF_MENUS \
+ : NUMBER_OF_MENUS + 1
+
+#if 0 // NOTENOTE davegi Reenable when menu code is recleaned up.
+
+//
+// List of kept files for File and Program menu.
+//
+
+typedef struct _KEPT_FILES {
+ INT CountOfKeptFiles;
+ PSZ NameOfKeptFile[ MAX_MRU_FILES_KEPT ];
+} KEPT_FILES, *PKEPT_FILES;
+
+//
+// Kept files (MRU) list.
+//
+// NOTENOTE davegi Remove when PROGRAMS and TOOLS are cleaned up.
+//
+
+extern KEPT_FILES KeptFiles[ ];
+
+//
+// Number of menus w/o a maximized child.
+//
+
+#define NUMBER_OF_MENUS ( 9 )
+
+//
+// Zero based menu positions w/o maximized child.
+//
+
+#define POSITION_IDM_FILE ( 0 )
+#define POSITION_IDM_PROGRAM ( 3 )
+#define POSITION_IDM_WINDOW ( 8 )
+
+//
+// Zero based menu item position for window menu.
+//
+
+#define POSITION_IDM_WINDOW_WATCH \
+ ( IDM_WINDOW_WATCH - IDM_WINDOW - 1 )
+#define POSITION_IDM_WINDOW_LOCALS \
+ ( IDM_WINDOW_LOCALS - IDM_WINDOW - 1 )
+#define POSITION_IDM_WINDOW_REGISTERS \
+ ( IDM_WINDOW_REGISTERS - IDM_WINDOW - 1 )
+#define POSITION_IDM_WINDOW_DISASSEMBLY \
+ ( IDM_WINDOW_DISASSEMBLY - IDM_WINDOW - 1 )
+#define POSITION_IDM_WINDOW_COMMAND \
+ ( IDM_WINDOW_COMMAND - IDM_WINDOW - 1 )
+#define POSITION_IDM_WINDOW_FLOAT_REGISTERS \
+ ( IDM_WINDOW_FLOAT_REGISTERS - IDM_WINDOW - 1 )
+
+//
+// First MDI child window ID.
+//
+
+#define FIRST_CHILD_WINDOW_ID ( 33 )
+
+//
+// Type of menu.
+//
+
+#define FILE_MENU_TYPE ( 0 )
+#define PROGRAM_MENU_TYPE ( 1 )
+
+#define IsMDIChild( menuID ) \
+ (( FIRST_CHILD_WINDOW_ID <= ( menuID )) \
+ && (( menuID ) < ( FIRST_CHILD_WINDOW_ID + MAX_DOCUMENTS ))) \
+ ? TRUE \
+ : FALSE
+
+//
+// Macros for accessing KEPT_FILES structure.
+//
+
+//
+// INT
+// GetMRUCount(
+// IN INT type
+// );
+//
+
+#define GetMRUCount( type ) \
+ KeptFiles[( INT )( type )].CountOfKeptFiles
+
+//
+// PSZ
+// GetMRUName(
+// IN INT type,
+// IN INT number
+// );
+//
+
+#define GetMRUName( type, number ) \
+ KeptFiles[( INT )( type )].NameOfKeptFile[( INT )( number )]
+
+//
+// PSZ
+// GetMRUFileName(
+// IN WPARAM wParam
+// );
+//
+
+#define GetMRUFileName( wParam ) \
+ GetMRUName( FILE_MENU_TYPE, LOWORD(( WPARAM )( wParam )) \
+ - IDM_FILE_EXIT - 1 )
+
+//
+// BOOL
+// IsMRUFile(
+// IN WPARAM wParam
+// );
+//
+
+#define IsMRUFile( wParam ) \
+ ( ( LOWORD(( WPARAM )( wParam )) > IDM_FILE_EXIT ) \
+ && ( LOWORD(( WPARAM )( wParam )) \
+ <= ( WORD )( IDM_FILE_EXIT + GetMRUCount( FILE_MENU_TYPE ))))
+
+//
+// INT
+// GetActualWindowMenuPosition(
+// );
+//
+
+#define GetActualWindowMenuPosition( ) \
+ ( GetActualMenuCount( ) == NUMBER_OF_MENUS ) \
+ ? POSITION_IDM_WINDOW \
+ : ( POSITION_IDM_WINDOW + 1 )
+
+//
+// Menu related function prototypes.
+//
+
+BOOL
+AddFileToMenu(
+ IN PSZ NameOfKeptFile,
+ IN UINT AcceleratorNumber,
+ IN HMENU hMenu,
+ IN UINT MenuItem
+ );
+
+UINT
+CommandIdEnabled(
+ IN UINT MenuID
+ );
+
+VOID
+DisableWindowMenuItem(
+ IN WORD DocType
+ );
+
+VOID
+FreeMRUList(
+ IN INT menuType
+ );
+
+#endif // 0
+UINT
+GetPopUpMenuID(
+ IN HMENU hMenu
+ );
+
+VOID
+InitializeMenu(
+ IN HANDLE hmenu
+ );
+
+#if 0
+
+BOOL
+InsertFilesInMenu(
+ IN HFILE hFile,
+ IN INT menuType,
+ IN INT lastMenuID
+ );
+
+BOOL
+InsertKeptFileNames(
+ IN INT menuType,
+ IN INT menuId,
+ IN LPSTR newName
+ );
+
+#endif // 0
+
+//
+// Menu Resource Signature
+//
+
+#define MENU_SIGNATURE 0x4000
+
+//
+// BOOL
+// IsMenuID(
+// IN DWORD ID
+// )
+//
+// Look for MENU_SIGNATURE while ensuring that we don't find
+// SC_* IDs.
+//
+
+#if SC_SIZE != 0xF000
+#error IsMenuID incompatible.
+#endif
+
+#define IsMenuID( ID ) \
+ ((( ID ) & MENU_SIGNATURE ) && ( ! (( ID ) & SC_SIZE )))
+
+//
+// Accelerator IDs
+//
+
+#define IDA_BASE ( 10000 )
+#define IDA_FINDNEXT ( IDA_BASE + 1 )
+
+// NOTENOTE davegi Get rid of FIRST/LAST bull.
+
+//
+// Base menu ID
+//
+// Note that I would have liked to define each pop-up menu ID as
+//
+// #define IDM_FILE (( IDM_BASE * 1 ) | MENU_SIGNATURE )
+//
+// but RC doesn't support multiplication.
+//
+
+#define IDM_BASE ( 100 )
+
+//
+// File
+//
+
+#define IDM_FILE ( 100 | MENU_SIGNATURE )
+#define IDM_FILE_NEW ( IDM_FILE + 1 )
+#define IDM_FILE_OPEN ( IDM_FILE + 2 )
+#define IDM_FILE_MERGE ( IDM_FILE + 3 )
+#define IDM_FILE_CLOSE ( IDM_FILE + 4 )
+#define IDM_FILE_SAVE ( IDM_FILE + 5 )
+#define IDM_FILE_SAVEAS ( IDM_FILE + 6 )
+#define IDM_FILE_SAVEALL ( IDM_FILE + 7 )
+#define IDM_FILE_EXIT ( IDM_FILE + 8 )
+#define IDM_FILE_FIRST IDM_FILE
+#define IDM_FILE_LAST IDM_FILE_EXIT
+
+//
+// Edit
+//
+
+#define IDM_EDIT ( 200 | MENU_SIGNATURE )
+#define IDM_EDIT_UNDO ( IDM_EDIT + 1 )
+#define IDM_EDIT_REDO ( IDM_EDIT + 2 )
+#define IDM_EDIT_CUT ( IDM_EDIT + 3 )
+#define IDM_EDIT_COPY ( IDM_EDIT + 4 )
+#define IDM_EDIT_PASTE ( IDM_EDIT + 5 )
+#define IDM_EDIT_DELETE ( IDM_EDIT + 6 )
+#define IDM_EDIT_FIND ( IDM_EDIT + 7 )
+#define IDM_EDIT_REPLACE ( IDM_EDIT + 8 )
+#define IDM_EDIT_READONLY ( IDM_EDIT + 9 )
+#define IDM_EDIT_FIRST IDM_EDIT
+#define IDM_EDIT_LAST IDM_EDIT_READONLY
+
+//
+// View
+//
+
+#define IDM_VIEW ( 300 | MENU_SIGNATURE )
+#define IDM_VIEW_LINE ( IDM_VIEW + 1 )
+#define IDM_VIEW_FUNCTION ( IDM_VIEW + 2 )
+#define IDM_VIEW_TOGGLETAG ( IDM_VIEW + 3 )
+#define IDM_VIEW_NEXTTAG ( IDM_VIEW + 4 )
+#define IDM_VIEW_PREVIOUSTAG ( IDM_VIEW + 5 )
+#define IDM_VIEW_CLEARALLTAGS ( IDM_VIEW + 6 )
+#define IDM_VIEW_RIBBON ( IDM_VIEW + 7 )
+#define IDM_VIEW_STATUS ( IDM_VIEW + 8 )
+#define IDM_VIEW_FIRST IDM_VIEW
+#define IDM_VIEW_LAST IDM_VIEW_STATUS
+
+//
+// Program
+//
+
+#define IDM_PROGRAM ( 400 | MENU_SIGNATURE )
+#define IDM_PROGRAM_OPEN ( IDM_PROGRAM + 1 )
+#define IDM_PROGRAM_CLOSE ( IDM_PROGRAM + 2 )
+#define IDM_PROGRAM_SAVE ( IDM_PROGRAM + 3 )
+#define IDM_PROGRAM_SAVEAS ( IDM_PROGRAM + 4 )
+#define IDM_PROGRAM_DELETE ( IDM_PROGRAM + 5 )
+#define IDM_PROGRAM_SAVE_DEFAULTS ( IDM_PROGRAM + 6 )
+#define IDM_PROGRAM_FIRST IDM_PROGRAM
+#define IDM_PROGRAM_LAST IDM_PROGRAM_SAVE_DEFAULTS
+
+//
+// Run
+//
+
+#define IDM_RUN ( 500 | MENU_SIGNATURE )
+#define IDM_RUN_RESTART ( IDM_RUN + 1 )
+#define IDM_RUN_STOPDEBUGGING ( IDM_RUN + 2 )
+#define IDM_RUN_GO ( IDM_RUN + 3 )
+#define IDM_RUN_TOCURSOR ( IDM_RUN + 4 )
+#define IDM_RUN_TRACEINTO ( IDM_RUN + 5 )
+#define IDM_RUN_STEPOVER ( IDM_RUN + 6 )
+#define IDM_RUN_HALT ( IDM_RUN + 7 )
+#define IDM_RUN_SET_THREAD ( IDM_RUN + 8 )
+#define IDM_RUN_SET_PROCESS ( IDM_RUN + 9 )
+#define IDM_RUN_SOURCE_MODE ( IDM_RUN + 10 )
+#define IDM_RUN_ATTACH ( IDM_RUN + 11 )
+#define IDM_RUN_GO_HANDLED ( IDM_RUN + 12 )
+#define IDM_RUN_GO_UNHANDLED ( IDM_RUN + 13 )
+#define IDM_RUN_GO2 ( IDM_RUN + 14 )
+#define IDM_RUN_TOCURSOR2 ( IDM_RUN + 15 )
+#define IDM_RUN_FIRST IDM_RUN
+#define IDM_RUN_LAST IDM_RUN_TOCURSOR2
+
+//
+// Debug
+//
+
+#define IDM_DEBUG ( 600 | MENU_SIGNATURE )
+#define IDM_DEBUG_CALLS ( IDM_DEBUG + 1 )
+#define IDM_DEBUG_SETBREAK ( IDM_DEBUG + 2 )
+#define IDM_DEBUG_QUICKWATCH ( IDM_DEBUG + 3 )
+#define IDM_DEBUG_WATCH ( IDM_DEBUG + 4 )
+#define IDM_DEBUG_MODIFY ( IDM_DEBUG + 5 )
+#define IDM_DEBUG_FIRST IDM_DEBUG
+#define IDM_DEBUG_LAST IDM_DEBUG_WATCH //BUG-BUG v-griffk was IDM_DEBUG_MODIFY
+
+//
+// Options
+//
+
+#define IDM_OPTIONS ( 700 | MENU_SIGNATURE )
+#define IDM_OPTIONS_RUN ( IDM_OPTIONS + 1 )
+#define IDM_OPTIONS_DEBUG ( IDM_OPTIONS + 2 )
+#define IDM_OPTIONS_MEMORY ( IDM_OPTIONS + 3 )
+#define IDM_OPTIONS_WATCH ( IDM_OPTIONS + 4 )
+#define IDM_OPTIONS_DISASSEMBLY ( IDM_OPTIONS + 5 ) // not being used
+#define IDM_OPTIONS_ENVIRON ( IDM_OPTIONS + 6 )
+#define IDM_OPTIONS_WORKSPACE ( IDM_OPTIONS + 7 )
+#define IDM_OPTIONS_COLOR ( IDM_OPTIONS + 8 )
+#define IDM_OPTIONS_FONTS ( IDM_OPTIONS + 9 )
+#define IDM_OPTIONS_LOCAL ( IDM_OPTIONS + 10)
+#define IDM_OPTIONS_CPU ( IDM_OPTIONS + 11)
+#define IDM_OPTIONS_FLOAT ( IDM_OPTIONS + 12)
+#define IDM_OPTIONS_KD ( IDM_OPTIONS + 13)
+#define IDM_OPTIONS_CALLS ( IDM_OPTIONS + 14)
+#define IDM_OPTIONS_USERDLL ( IDM_OPTIONS + 15)
+#define IDM_OPTIONS_DBGDLL ( IDM_OPTIONS + 16)
+#define IDM_OPTIONS_EXCEPTIONS ( IDM_OPTIONS + 17)
+#define IDM_OPTIONS_PANE ( IDM_OPTIONS + 18)
+
+#define IDM_OPTIONS_FIRST IDM_OPTIONS
+#define IDM_OPTIONS_LAST IDM_OPTIONS_PANE
+
+//
+// Window
+//
+
+#define IDM_WINDOW ( 800 | MENU_SIGNATURE )
+#define IDM_WINDOW_NEWWINDOW ( IDM_WINDOW + 1 )
+#define IDM_WINDOW_CASCADE ( IDM_WINDOW + 2 )
+#define IDM_WINDOW_TILE ( IDM_WINDOW + 3 )
+#define IDM_WINDOW_ARRANGE ( IDM_WINDOW + 4 )
+#define IDM_WINDOW_ARRANGE_ICONS ( IDM_WINDOW + 5 )
+#define IDM_WINDOW_SOURCE_OVERLAY ( IDM_WINDOW + 6 )
+#define IDM_WINDOW_WATCH ( IDM_WINDOW + 7 )
+#define IDM_WINDOW_LOCALS ( IDM_WINDOW + 8 )
+#define IDM_WINDOW_CPU ( IDM_WINDOW + 9 )
+#define IDM_WINDOW_DISASM ( IDM_WINDOW + 10 )
+#define IDM_WINDOW_COMMAND ( IDM_WINDOW + 11 )
+#define IDM_WINDOW_FLOAT ( IDM_WINDOW + 12 )
+#define IDM_WINDOW_MEMORY ( IDM_WINDOW + 13 )
+#define IDM_WINDOW_CALLS ( IDM_WINDOW + 14 )
+#define IDM_WINDOWCHILD ( IDM_WINDOW + 15 )
+#define IDM_WINDOW_FIRST IDM_WINDOW
+#define IDM_WINDOW_LAST IDM_WINDOW_CALLS
+
+//
+// Help
+//
+
+#define IDM_HELP ( 900 | MENU_SIGNATURE )
+#define IDM_HELP_CONTENTS ( IDM_HELP + 1 )
+#define IDM_HELP_SEARCH ( IDM_HELP + 2 )
+#define IDM_HELP_ABOUT ( IDM_HELP + 3 )
+#define IDM_HELP_FIRST IDM_HELP
+#define IDM_HELP_LAST IDM_HELP_ABOUT
diff --git a/private/windbg/windbg/include/mstools.h b/private/windbg/windbg/include/mstools.h
new file mode 100644
index 000000000..f297cfb44
--- /dev/null
+++ b/private/windbg/windbg/include/mstools.h
@@ -0,0 +1,14 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+//This file emulates the standard TOOLS.H
+
+#define MAXLINELEN 1024 /* longest line of input */
+#define TRUE 1
+#define FALSE 0
+
+typedef char flagType;
+char * (*tools_alloc) (unsigned int);
+void Move(void FAR *, void FAR *, unsigned int);
+void Fill(void FAR *, char, unsigned int);
+char *strbskip(char const *, char const *);
+extern char XLTab[], XUTab[];
diff --git a/private/windbg/windbg/include/panemgr.h b/private/windbg/windbg/include/panemgr.h
new file mode 100644
index 000000000..7619a10b8
--- /dev/null
+++ b/private/windbg/windbg/include/panemgr.h
@@ -0,0 +1,132 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+
+Module Name:
+
+ panemgr.h
+
+Abstract:
+
+ Header file for pane manager windows
+
+Author:
+
+ William Heaton (v-willhe)
+ Griffith WWm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _PANEMGR_H )
+#define _PANEMGR_H
+
+#define ID_PANE_BUTTON 0x101 // Button Panel (+/-)
+#define ID_PANE_LEFT 0x102 // Name Panel
+#define ID_PANE_RIGHT 0x103 // Value Panel
+#define ID_PANE_SIZER 0x104 // Sizer (Between Left|Right pane)
+#define ID_PANE_SCROLL 0x105 // Scrollbar
+
+#define EDITMAX 260
+
+typedef struct tagPANEINFO PANEINFO;
+typedef struct tagPANEINFO *PPANEINFO;
+
+struct tagPANEINFO {
+ UINT CtrlId; // ID_PANE_BUTTON, ID_PANE_LEFT, or ID_PANE_RIGHT
+ UINT ItemId; // Item Index in pane
+ BOOL ReadOnly; // Is the Item ReadOnly?
+ BOOL NewText; // Has the Item changed?
+ PSTR pBuffer; // The Address of the Buffer (READ-ONLY) for item
+ PSTR pFormat; // The format strings (if any)
+};
+
+typedef struct paneflags {
+ WORD Expand1st :1; // Vib contains no data
+} PFLAGS;
+
+typedef struct tagPANEMGR PANE;
+typedef struct tagPANEMGR *PPANE;
+
+struct tagPANEMGR {
+ WORD Type; // Window Type (Watch,Local,Register,Floating)
+ int iView; // View Number
+
+ WORD LineHeight; // Height of a line in a pane
+ WORD CharWidth; // Width of the widest character
+ HFONT hFont; // Font for window
+ COLOR_ITEM ColorItem; // Color Information for this window
+ HBRUSH hbrBackground; // Background brush
+
+ WORD PaneLines; // Number of lines in pane
+ WORD PanePerCent; // Percentage of left pane to right pane
+
+ LONG nXoffLeft; // Position of Left Horz. Scroll bar
+ LONG nXoffRight; // Position of Right Horz. Scroll bar
+ LONG nCaretPos; // Position of Caret (-1) if not up
+
+ UINT nCtrlId; // Pane control w\current focus
+ HWND hWndFocus; // Pane with the current focus
+ HWND hWndLeft; // Handle to Left Pane
+ HWND hWndSizer; // Handle to Sizer Bar
+ HWND hWndRight; // Handle to Right Pane
+ HWND hWndScroll; // Handle to Scroll bar
+ HWND hWndButton; // Handle to Plus/Minus Pane
+
+ WNDPROC fnEditProc; // Low-Level Edit Proc
+ BOOL LeftOk; // Has Left Pane Changed?
+ BOOL RightOk; // Has Right Pane Changed?
+ BOOL ScrollBarUp; // Is the Scroll bar visiable?
+
+ BOOL ReadOnly; // Is the current line readonly?
+ BOOL Edit; // Is the current line being edited?
+ BOOL OverType; // Are we in OverType mode?
+
+ WORD CurPos; // Current Index into Line
+ WORD CurLen; // Length of current line
+
+ WORD SelPos; // Selection Position
+ int SelLen; // Selection Length
+
+ WORD CurIdx; // Index of Current Line
+ WORD TopIdx; // Index of Top Line (Button,Left,Right)
+ WORD MaxIdx; // Count of indexs available
+
+ int X; // for caretpos()
+ int Y; // same
+
+ PFLAGS bFlags; // Flags for pane
+
+ CHAR EditBuf[EDITMAX]; // Current Edit Buffer
+};
+
+void OpenPanedWindow(int Type, LPWININFO lpWinInfo, int Preference);
+LONG CreatePane( HWND hWnd, int iView, int Type);
+void PaneKeyboardHandler(HWND hWnd, UINT message, WPARAM wParam, LONG lParam);
+
+BOOL PaneCloseEdit( PPANE p);
+void SyncPanes(PPANE p, WORD Index);
+void PaneInvalidateCurrent(HWND hWnd, PPANE p, SHORT Idx);
+void PaneInvalidateItem( HWND hWnd, PPANE p, SHORT item);
+void PaneInvalidateRow( PPANE p );
+void PaneSwitchFocus(PPANE p, HWND hWnd, BOOL fPrev);
+void CheckPaneScrollBar( PPANE p, WORD Count);
+void PaneResetIdx( PPANE p, SHORT Idx);
+void PaneSetIdx( PPANE p, SHORT NewIdx);
+void PaneSetCaret( PPANE p, LONG cx, BOOL Scroll);
+
+PLONG GetPaneStatus( int ViewNumber);
+void SetPaneStatus( int ViewNumber, PLONG ptr);
+void FreePaneStatus( int ViewNumber, PLONG ptr);
+
+void DrawPaneItem( HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis );
+void InvertButton( PPANE p );
+void ScrollPanes( PPANE p,WPARAM wParam, LPARAM lParam);
+int PaneCaretNum( PPANE p);
+
+#endif // _PANEMGR_H
+
diff --git a/private/windbg/windbg/include/pidtid.h b/private/windbg/windbg/include/pidtid.h
new file mode 100644
index 000000000..5caf404d4
--- /dev/null
+++ b/private/windbg/windbg/include/pidtid.h
@@ -0,0 +1,20 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/*
+** Set of prototypes and stuctures for process and thread handling
+*/
+
+LPPD PASCAL CreatePd(HPID hpid);
+VOID PASCAL DestroyPd(LPPD lppd, BOOL fDestroyPrecious);
+LPPD PASCAL GetLppdHead( void );
+LPPD PASCAL LppdOfHpid(HPID hpid);
+LPPD PASCAL LppdOfIpid(UINT ipid);
+LPPD PASCAL ValidLppdOfIpid(UINT ipid);
+BOOL PASCAL GetFirstValidPDTD(LPPD *plppd, LPTD *plptd);
+LPTD PASCAL CreateTd(LPPD lppd, HTID htid);
+VOID PASCAL DestroyTd(LPTD lptd);
+LPTD PASCAL LptdOfLppdHtid(LPPD lppd, HTID htid);
+LPTD PASCAL LptdOfLppdItid(LPPD lppd, UINT itid);
+VOID PASCAL SetIpid(int);
+VOID PASCAL RecycleIpid1(void);
+VOID PASCAL SetTdInfo(LPTD lptd);
diff --git a/private/windbg/windbg/include/program.h b/private/windbg/windbg/include/program.h
new file mode 100644
index 000000000..10874262e
--- /dev/null
+++ b/private/windbg/windbg/include/program.h
@@ -0,0 +1,34 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Program.h
+
+Abstract:
+
+ This module contains the prototypes for the program menu support
+ functions.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 07-July-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+extern BOOLEAN ExitingDebugger;
+
+VOID ProgramOpen( void );
+BOOLEAN ProgramClose( void );
+VOID ProgramSave( void );
+VOID ProgramSaveAs( void );
+VOID ProgramDelete( void );
+VOID ProgramSaveDefaults( void );
+
+VOID ProgramOpenPath( char *Path );
diff --git a/private/windbg/windbg/include/quickw.h b/private/windbg/windbg/include/quickw.h
new file mode 100644
index 000000000..587c7d266
--- /dev/null
+++ b/private/windbg/windbg/include/quickw.h
@@ -0,0 +1,10 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+
+// Watch Tree access routines:
+
+LONG FAR PASCAL LOADDS QuickEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+
diff --git a/private/windbg/windbg/include/re.h b/private/windbg/windbg/include/re.h
new file mode 100644
index 000000000..87095c1aa
--- /dev/null
+++ b/private/windbg/windbg/include/re.h
@@ -0,0 +1,125 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Re.h
+
+Abstract:
+
+ Common include files for regular expression compilers.
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _RE_ )
+#define _RE_
+
+#include "remi.h"
+
+#define INTERNAL near
+
+RE_OPCODE *REip; /* instruction pointer to compiled */
+struct patType *REPat; /* pointer to pattern being compiled */
+int REArg; /* count of tagged args parsed */
+
+/* defined actions for parsing */
+
+typedef int OPTYPE ;
+
+#define ACTIONMIN ((OPTYPE) 0)
+
+#define PROLOG ((OPTYPE) 0)
+#define LEFTARG ((OPTYPE) 1)
+#define RIGHTARG ((OPTYPE) 2)
+#define SMSTAR ((OPTYPE) 3)
+#define SMSTAR1 ((OPTYPE) 4)
+#define STAR ((OPTYPE) 5)
+#define STAR1 ((OPTYPE) 6)
+#define ANY ((OPTYPE) 7)
+#define BOL ((OPTYPE) 8)
+#define EOL ((OPTYPE) 9)
+#define NOTSIGN ((OPTYPE) 10)
+#define NOTSIGN1 ((OPTYPE) 11)
+#define LETTER ((OPTYPE) 12)
+#define LEFTOR ((OPTYPE) 13)
+#define ORSIGN ((OPTYPE) 14)
+#define RIGHTOR ((OPTYPE) 15)
+#define CCLBEG ((OPTYPE) 16)
+#define CCLNOT ((OPTYPE) 17)
+#define RANGE ((OPTYPE) 18)
+#define EPILOG ((OPTYPE) 19)
+#define PREV ((OPTYPE) 20)
+
+#if defined(DBCS)
+#define RANGEDBCS1 ((OPTYPE) 21)
+#define RANGEDBCS2 ((OPTYPE) 22)
+
+#define ACTIONMAX ((OPTYPE) 22)
+
+#else
+
+#define ACTIONMAX ((OPTYPE) 20)
+#endif
+
+
+/* function forward declarations */
+
+char fREMatch (struct patType *,char *,char *,char );
+struct patType * RECompile (char *, flagType, flagType);
+char REGetArg (struct patType *,int ,char *);
+char RETranslate (struct patType *,char *,char *);
+int RETranslateLength (struct patType *,char *);
+int RELength (struct patType *,int );
+char * REStart (struct patType *);
+
+typedef unsigned INTERNAL ACT (OPTYPE, unsigned int,
+ unsigned char, unsigned char);
+
+typedef ACT *PACT;
+
+ACT CompileAction;
+ACT EstimateAction;
+ACT NullAction;
+
+int pascal INTERNAL RECharType (char *);
+int pascal INTERNAL RECharLen (char *);
+int pascal INTERNAL REClosureLen (char *);
+char * pascal INTERNAL REParseRE (PACT, char *,int *);
+char * pascal INTERNAL REParseE (PACT,char *);
+char * pascal INTERNAL REParseSE (PACT,char *);
+char * pascal INTERNAL REParseClass (PACT,char *);
+char * pascal INTERNAL REParseAny (PACT,char *);
+char * pascal INTERNAL REParseBOL (PACT,char *);
+char * pascal INTERNAL REParsePrev (PACT, char *);
+char * pascal INTERNAL REParseEOL (PACT,char *);
+char * pascal INTERNAL REParseAlt (PACT,char *);
+char * pascal INTERNAL REParseNot (PACT,char *);
+char * pascal INTERNAL REParseAbbrev (PACT,char *);
+char * pascal INTERNAL REParseChar (PACT,char *);
+char * pascal INTERNAL REParseClosure (PACT,char *);
+char * pascal INTERNAL REParseGreedy (PACT,char *);
+char * pascal INTERNAL REParsePower (PACT,char *);
+char pascal INTERNAL REClosureChar (char *);
+char pascal INTERNAL Escaped (char );
+
+void pascal INTERNAL REStackOverflow (void);
+void pascal INTERNAL REEstimate (char *);
+
+#ifdef DEBUG
+void INTERNAL REDump (struct patType *p);
+#endif
+
+#if defined(KANJI)
+#define REis_kanji(c) (REKTab[(c)>>3] & REBTab[(c)&7])
+#endif
+
+#endif // _RE_
diff --git a/private/windbg/windbg/include/remi.h b/private/windbg/windbg/include/remi.h
new file mode 100644
index 000000000..cbad04865
--- /dev/null
+++ b/private/windbg/windbg/include/remi.h
@@ -0,0 +1,60 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Remi.h
+
+Abstract:
+
+
+Author:
+
+ David J. Gilman (davegi) 04-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _REMI_ )
+#define _REMI_
+
+#define MAXPATARG 10 /* 0 is entire 1-9 are valid */
+
+/* Return codes from REMatch */
+
+#define REM_MATCH 0 /* A match was found */
+#define REM_NOMATCH 1 /* No match was found */
+#define REM_UNDEF 2 /* An undefined Op-code was encountered */
+#define REM_STKOVR 3 /* The stack overflowed */
+#define REM_INVALID 4 /* A parameter was invalid */
+
+typedef unsigned char RE_OPCODE;
+
+/* structure of compiled pattern */
+
+struct patType {
+ flagType fCase; /* TRUE => case is significant */
+ flagType fUnix; /* TRUE => use unix replacement */
+ char *pArgBeg[MAXPATARG]; /* beginning of tagged strings */
+ char *pArgEnd[MAXPATARG]; /* end of tagged strings */
+ RE_OPCODE code[1]; /* pseudo-code instructions */
+};
+
+/* if RECompile fails and RESize == -1, then the input pattern had a syntax
+ * error. If RESize != -1, then we were not able to allocate enough memory
+ * to contain the pattern pcode
+ */
+int RESize; /* estimated size of pattern */
+
+int REMatch(struct patType *,char *,char *,RE_OPCODE *[], unsigned, char );
+struct patType *RECompile(char *, flagType, flagType);
+char REGetArg(struct patType *,int ,char *);
+char RETranslate(struct patType *,char *,char *);
+int RELength(struct patType *,int );
+char *REStart(struct patType *);
+
+#endif // _REMI_
diff --git a/private/windbg/windbg/include/remote.h b/private/windbg/windbg/include/remote.h
new file mode 100644
index 000000000..0209841e6
--- /dev/null
+++ b/private/windbg/windbg/include/remote.h
@@ -0,0 +1,58 @@
+#define VERSION 4
+#define REMOTE_SERVER 1
+#define REMOTE_CLIENT 2
+
+#define SERVER_READ_PIPE "\\\\%s\\PIPE\\%sIN" //Client Writes and Server Reads
+#define SERVER_WRITE_PIPE "\\\\%s\\PIPE\\%sOUT" //Server Reads and Client Writes
+
+#define COMMANDCHAR '@' //Commands intended for remote begins with this
+#define CTRLC 3
+
+#define HOSTNAMELEN 16
+
+#define CHARS_PER_LINE 45
+
+#define MAGICNUMBER 0x31109000
+#define LINESTOSEND 200
+
+#define MAX_SESSION 10
+
+typedef struct {
+ DWORD Size;
+ DWORD Version;
+ CHAR ClientName[15];
+ DWORD LinesToSend;
+ DWORD Flag;
+} SESSION_STARTUPINFO, *LPSESSION_STARTUPINFO;
+
+typedef struct {
+ DWORD MagicNumber; // New Remote
+ DWORD Size; // Size of structure
+ DWORD FileSize; // Num bytes sent
+} SESSION_STARTREPLY, *LPSESSION_STARTREPLY;
+
+typedef struct {
+ CHAR Name[HOSTNAMELEN]; // Name of client Machine;
+ BOOL Active; // Client at the other end connected
+ BOOL CommandRcvd; // True if a command recieved
+ BOOL SendOutput; // True if Sendoutput output
+ HANDLE PipeReadH; // Client sends its StdIn through this
+ HANDLE PipeWriteH; // Client gets its StdOut through this
+ OVERLAPPED OverlappedRead; //
+ OVERLAPPED OverlappedWrite; //
+ LPSTR lpBuf; // Read buffer
+ HANDLE hThread; // Session Thread
+ HANDLE hEventTerm; //
+} SESSION_TYPE, *LPSESSION_TYPE;
+
+VOID
+StartRemoteServer(
+ LPSTR PipeName,
+ BOOL fAppend
+ );
+
+VOID
+SendClientOutput(
+ LPSTR lpBuf,
+ DWORD cbBuf
+ );
diff --git a/private/windbg/windbg/include/res_str.h b/private/windbg/windbg/include/res_str.h
new file mode 100644
index 000000000..26ba5c904
--- /dev/null
+++ b/private/windbg/windbg/include/res_str.h
@@ -0,0 +1,968 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Res_str.h
+
+Abstract:
+
+ This module contains the ids for loadable resource strings.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-92
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _RES_STR_ )
+#define _RES_STR_
+
+#ifdef RESOURCES
+#define RES_STR(a, b, c) b, c
+STRINGTABLE
+BEGIN
+#else
+
+enum _RESOURCEIDS {
+#define RES_STR(a, b, c) a = b,
+#endif
+
+//
+// Error Messages
+//
+
+#define ERR_Reserved0 0
+#define ERR_Reserved1 1
+#define ERR_Reserved2 2
+RES_STR(ERR_Help_not_available_for_Menu, 1020, "Help is not available for the selected menu item")
+RES_STR(ERR_Assertion_Failed, 1021, "Assertion Failed")
+RES_STR(ERR_Init_Application, 1022, "Windbg cannot be initialized")
+RES_STR(ERR_File_Name_Too_Long, 1023, "'%s' is too long for a filename")
+RES_STR(ERR_Internal_Error, 1024, "Internal Error. Please contact Microsoft PSS (%s)")
+RES_STR(ERR_File_Not_Found, 1025, "The file '%s' cannot be found")
+RES_STR(ERR_File_Open, 1026, "The file '%s' cannot be opened")
+RES_STR(ERR_File_Create, 1027, "The file '%s' cannot be created")
+RES_STR(ERR_File_Read, 1028, "The file '%s' cannot be read")
+RES_STR(ERR_File_Write, 1029, "The file '%s' cannot be written")
+RES_STR(ERR_File_Seek, 1030, "The file pointer for '%s' cannot be positioned")
+RES_STR(ERR_File_Disk_Full, 1031, "There is not enough space on disk to save '%s' file")
+RES_STR(ERR_File_Close, 1032, "The file '%s' cannot be closed")
+RES_STR(ERR_File_Remove, 1033, "The file '%s' cannot be removed")
+RES_STR(ERR_File_Rename, 1034, "The file '%s' cannot be renamed to '%s'")
+RES_STR(ERR_File_Not_Open, 1035, "The file was not open")
+RES_STR(ERR_Ini_File_Read, 1036, "The options file cannot be read")
+RES_STR(ERR_Ini_File_Write, 1037, "The options file cannot be written")
+RES_STR(ERR_Ini_File_Close, 1038, "The options file cannot be closed")
+RES_STR(ERR_Ini_File_Seek, 1039, "The options file pointer cannot be positioned")
+RES_STR(ERR_Ini_Bad_CheckSum, 1040, "The options file was corrupted. A new file has been created using default settings.")
+RES_STR(ERR_Ini_File_Not_Compatible, 1041, "The options file is incompatible with the current version of Windbg. A new file has been created using default settings")
+RES_STR(ERR_Ini_File_Not_Found, 1042, "'%s' is not found. A new file is created.")
+RES_STR(ERR_No_File_Name_Specified, 1043, "This command requires a filename")
+RES_STR(ERR_File_Name_Is_Not_Valid, 1044, "The specified filename is invalid")
+RES_STR(ERR_Too_Many_Opened_Documents, 1045, "The maximum number of open windows has been reached")
+RES_STR(ERR_Too_Many_Opened_Views, 1046, "The maximum number of open windows has been reached")
+RES_STR(ERR_Cannot_Allocate_Memory, 1047, "Memory cannot be allocated")
+RES_STR(ERR_File_Already_Loaded, 1048, "File already loaded '%s'")
+RES_STR(ERR_Not_A_Text_File, 1049, "'%s' is not a text file")
+RES_STR(ERR_No_Help_Topic, 1050, "Help is not available for this item")
+RES_STR(ERR_Bad_File_Spec, 1051, "The file specification '%s' is invalid")
+RES_STR(ERR_Only_One_Def_File, 1052, "You can only add one Module-Definition file. Would you like to replace the current file?")
+RES_STR(ERR_Only_One_Main_Resource_File, 1053, "You can only add one Resource Script. Would you like to replace the current script?")
+RES_STR(ERR_Bad_Directory_Spec, 1054, "The directory specification '%s' is invalid")
+RES_STR(ERR_Change_Directory, 1055, "The current directory cannot be changed to '%s'")
+RES_STR(ERR_Change_Drive, 1056,"")
+RES_STR(ERR_Mak_Bad_Format, 1057, "Line %u contains a syntax error")
+RES_STR(ERR_Mak_General_Error, 1058, "The project file '%s' contains an error - %s")
+RES_STR(ERR_Must_Have_Def_For_Windows, 1059, "")
+RES_STR(ERR_Mak_Cant_Make_Temp_Def_File, 1060, "")
+RES_STR(ERR_Must_Specify_Filename, 1061, "This command requires a filename")
+RES_STR(ERR_Empty_Makefile, 1062, "")
+RES_STR(ERR_Searching_In_Winini, 1063, "No printer. The WIN.INI entry 'Application=[%s] Keyname=%s' cannot be found")
+RES_STR(ERR_Bad_Item_In_Winini, 1064, "There is an error with the WIN.INI line '%s'")
+RES_STR(ERR_Expression_Too_Complicated, 1065, "The regular expression is too complicated")
+RES_STR(ERR_Illegal_Expression, 1066, "The regular expression is invalid")
+RES_STR(ERR_Quote_Nested, 1067, "The regular expression contains a nested quote")
+RES_STR(ERR_No_Font_Selected, 1068, "No font selected")
+RES_STR(ERR_No_Size_Selected, 1069, "No size selected")
+RES_STR(ERR_Invalid_Command_Line_File, 1070, "The command line filename '%s' is invalid")
+RES_STR(ERR_Invalid_Command_Line, 1071, "Syntax error in command line")
+RES_STR(ERR_Invalid_Command_Line_Option, 1072, "The command line option '%s' is invalid")
+RES_STR(ERR_Wkspace_Window_Version, 1073, "")
+RES_STR(ERR_Cant_Load_Driver, 1074, "The driver '%s' cannot be loaded (%s)")
+RES_STR(ERR_File_Is_ReadOnly, 1075, "File is Read Only")
+RES_STR(ERR_Dbg_Calls_No_Source, 1076, "There is no source code available")
+RES_STR(ERR_Clipboard_Overflow, 1077, "There is not enough room to paste from the Clipboard")
+RES_STR(ERR_Cant_Load, 1078, "Cannot load '%s'.")
+RES_STR(ERR_Line_Too_Long, 1079, "This line contains the maximum number of characters allowed")
+RES_STR(ERR_Modified_Document_Corrupted, 1080, "This file has been corrupted. Please save it with a new name, then exit and restart Windbg")
+RES_STR(ERR_Document_Corrupted, 1081, "This file has been corrupted. Please exit and restart Windbg")
+RES_STR(ERR_UndoRedoBufferTooSmall, 1082, "There is not enough space in the Undo buffer to save this action. Would you like to continue?")
+RES_STR(ERR_UndoBuffer_Corrupted, 1083, "The Undo buffer has been corrupted. Please exit and restart Windbg")
+RES_STR(ERR_RedoBuffer_Corrupted, 1084, "The Redo buffer has been corrupted. Please exit and restart Windbg")
+RES_STR(ERR_Destroy_UndoRedo_Buffers, 1085, "Changing the Undo buffer size will destroy it's contents. Would you like to continue?")
+RES_STR(ERR_Truncate_Line, 1086, "Line #%u is too long and will be truncated. Do you want to continue?")
+RES_STR(ERR_Truncate_Doc, 1087, "There are too many lines in this file. The view will be truncated")
+RES_STR(ERR_Too_Many_Lines, 1088, "This file contains the maximum number of lines allowed")
+RES_STR(ERR_String_Not_Found, 1089, "The string '%s' was not found")
+RES_STR(ERR_Couldnt_Set_Breakpoint, 1090, "The breakpoint '%s' cannot be set")
+RES_STR(ERR_Debuggee_Is_Running, 1091, "This option is invalid while the debuggee is running")
+RES_STR(ERR_No_DLL_Caller, 1092, "No Debuggee specified")
+RES_STR(ERR_Merge_Destroy_UndoRedo, 1093, "Merging a file will destroy Undo buffer contents. Would you like to continue?")
+RES_STR(ERR_Cannot_Load_DLL, 1094, "Cannot load the DLL '%s'")
+RES_STR(ERR_DLL_Symbol_Unspecified, 1095, "Symbol Handler Dll unspecified")
+RES_STR(ERR_DLL_Expr_Unspecified, 1096, "Expression Evaluator Dll unspecified")
+RES_STR(ERR_DLL_Transport_Unspecified, 1097, "Transport layer Dll unspecified")
+RES_STR(ERR_DLL_Exec_Unspecified, 1098,"Execution Model Dll unspecified")
+RES_STR(ERR_No_RegExp_Match, 1099, "The regexp '%s' was not found")
+RES_STR(ERR_Close_When_Debugging, 1100,"Debuggee still running. Really Exit?")
+RES_STR(ERR_Duplicate_File_Name, 1101,"You cannot use the name of an open file.")
+RES_STR(ERR_RegExpr_Invalid, 1102,"'%s' is not a valid regular expression (invalid parameter).")
+RES_STR(ERR_RegExpr_Undef, 1103,"'%s' is not a valid regular expression (undefined operator).")
+RES_STR(ERR_Tabs_OutOfRange, 1104,"'Tab Stops' must be between %i and %i.")
+RES_STR(ERR_UndoRedo_OutOfRange, 1105,"'Undo Buffer Size' must be between %li and %li.")
+RES_STR(ERR_Line_OutOfRange, 1106,"'Line Number' must be between %i and %i.")
+RES_STR(ERR_Cannot_Quit, 1107,"Cannot exit Windbg.")
+RES_STR(ERR_Invalid_Exe, 1108,"'%s' is not a valid executable file.")
+RES_STR(ERR_No_Debug_Info, 1109,"'%s' does not contain debugging information. Do you want to continue?")
+RES_STR(ERR_Cannot_Debug, 1110, "Cannot load '%s' because it has an unsupported image format.")
+RES_STR(ERR_VDM_Running, 1111, "Cannot load '%s' because NTVDM is already running.")
+
+RES_STR(ERR_Not_Packed, 1200,"'%s' cannot be debugged until it has been packed. (Uncheck 'CV 3.X Format' in the Link Options dialog.) Do you want to run it?")
+RES_STR(ERR_No_Code_For_Line, 1201,"There is no code at line number for breakpoint %s")
+RES_STR(ERR_No_Exe_Build_It, 1202,"'%s' does not exist. Do you want to build it?")
+RES_STR(ERR_Lost_Default_Font, 1203,"The Default Font '%s' has been removed from the system. It has been replaced by the font '%s'.")
+RES_STR(ERR_Lost_Font, 1204,"One or more fonts used are not available. The Default Font will be substitued for them.")
+RES_STR(ERR_Tab_Too_Big, 1205,"The new Tab Stop setting makes line %i of file '%s' too long. Enter a smaller value.")
+RES_STR(ERR_Memory_Is_Low, 1206,"The available memory is low. Close other applications or exit from Windbg.")
+RES_STR(ERR_Memory_Is_Low_2, 1207,"The available memory is low. Please exit.")
+RES_STR(ERR_Invalid_Debugger_Dll, 1209,"Debugger helper dll '%s' is invalid")
+RES_STR(ERR_Initializing_Debugger, 1210,"Debugger helper dll '%s' cannot be initialized")
+
+RES_STR(ERR_AddrExpr_Invalid, 1211,"Invalid or unevaluatable address expression")
+RES_STR(ERR_RangeExpr_Invalid, 1212,"Invalid or unevaluatable range expression")
+RES_STR(ERR_Addr_NotSameSeg, 1213,"All addresses must have the same selector")
+RES_STR(ERR_Breakpoint_Not_Exist, 1214,"There is no breakpoint #%d")
+RES_STR(ERR_Breakpoint_Already_Used, 1215,"There is already a breakpoint #%d")
+RES_STR(ERR_Breakpoint_Not_Instantiated, 1216,"Breakpoint not instantiated")
+RES_STR(ERR_Debuggee_Not_Alive, 1217,"Debuggee is not alive")
+RES_STR(ERR_Process_Not_Exist, 1218,"Process does not exist")
+RES_STR(ERR_Exception_Invalid, 1219,"Invalid exception")
+RES_STR(ERR_Register_Invalid, 1220,"Invalid register")
+RES_STR(ERR_Command_Error, 1221,"Command Error")
+RES_STR(ERR_No_Breakpoints, 1222,"There are no breakpoints set")
+RES_STR(ERR_No_Threads, 1223,"No threads exist")
+RES_STR(ERR_Edit_Failed, 1224,"Unable to modify memory")
+RES_STR(ERR_Expr_Invalid, 1225,"Invalid or unevaluatable expression")
+RES_STR(ERR_Radix_Invalid, 1226,"Radix value must be 8, 10 or 16")
+RES_STR(ERR_String_Invalid, 1227,"Badly formed string")
+RES_STR(ERR_Bad_Count, 1228,"Bad count - use a positive decimal number")
+RES_STR(ERR_Bad_Assembly, 1229,"Can't assemble input")
+RES_STR(ERR_Cant_Go_Exception, 1230,"Stopped at exception - use gh or gn")
+RES_STR(ERR_Already_Running, 1231,"Thread is already running")
+RES_STR(ERR_Cant_Step_Frozen, 1232,"Can't step frozen thread - only simple go is allowed")
+RES_STR(ERR_DbgState, 1233,"Debugger is busy...")
+RES_STR(ERR_Cant_Start_Proc, 1234,"Unable to start debuggee!")
+RES_STR(ERR_Cant_Cont_Exception, 1235,"INTERNAL ERROR: Exception failed to continue")
+RES_STR(ERR_Not_At_Exception, 1236,"Thread is not at an exception")
+RES_STR(ERR_Thread_Wild_Invalid, 1237,"Thread wildcard is invalid here")
+RES_STR(ERR_Process_Wild_Invalid, 1238,"Process wildcard is invalid here")
+RES_STR(ERR_Cant_Freeze, 1239,"INTERNAL ERROR: can't freeze thread")
+RES_STR(ERR_Cant_Thaw, 1240,"INTERNAL ERROR: can't thaw thread")
+RES_STR(ERR_Stop_B4_Restart, 1241,"Can't restart while running")
+RES_STR(ERR_Cant_Step_Exited_Proc, 1242,"Can't step exited process")
+RES_STR(ERR_Thread_Exited, 1243,"Thread has exited")
+RES_STR(ERR_Cant_Continue_Rip, 1244,"INTERNAL ERROR: can't continue from RIP")
+RES_STR(ERR_Error_Level_Invalid, 1245,"Valid error levels are 0-3")
+RES_STR(ERR_Thread_Is_Frozen, 1246,"Thread is frozen")
+RES_STR(ERR_Thread_Not_Frozen, 1247,"Thread is not frozen")
+RES_STR(ERR_Cant_Step_Rip, 1248,"Only go is allowed at RIP")
+RES_STR(ERR_Bad_FP_Constant, 1249,"Invalid floating point constant")
+RES_STR(ERR_Cant_Assign_To_Reg, 1250,"You can't change that register")
+RES_STR(ERR_Simple_Go_Frozen, 1251,"Only simple go is allowed on frozen thread")
+RES_STR(ERR_Cant_Run_Frozen_Proc, 1252,"Cannot run frozen process")
+RES_STR(ERR_Go_Failed, 1253,"Go failed")
+RES_STR(ERR_Read_Failed_At, 1254,"Memory read failed at %s")
+RES_STR(ERR_Write_Failed_At, 1255,"Memory write failed at %s")
+RES_STR(ERR_No_Thread_With_Wildproc, 1256,"Can't specify thread with process wildcard")
+RES_STR(ERR_Invalid_Option, 1257,"Invalid debug option")
+RES_STR(ERR_True_False, 1258,"Valid values are ON and OFF")
+RES_STR(ERR_Bad_Context, 1259,"Bad context string")
+RES_STR(ERR_Process_Cant_Go, 1260,"Can't GO on any threads in that process")
+RES_STR(ERR_Debuggee_Starting, 1261,"Wait... debuggee is loading...")
+RES_STR(ERR_Invalid_Process_Id, 1262,"Invalid Process ID %ld")
+RES_STR(ERR_Attach_Failed, 1263,"Attach failed")
+RES_STR(ERR_Detach_Failed, 1264,"Detach failed")
+RES_STR(ERR_Kill_Failed, 1265,"Kill failed")
+RES_STR(ERR_Debuggee_Not_Loaded, 1266,"No debuggee is loaded")
+RES_STR(ERR_No_ExceptionList, 1267,"Cannot obtain exception list")
+RES_STR(ERR_DLL_Wrong_Type, 1268,"DLL %s is type %2.2s, expected %2.2s")
+RES_STR(ERR_Not_Unique_Shortname, 1269,"Short name '%s' duplicates an existing name, and must be unique.")
+RES_STR(ERR_Exception_Already_Exists, 1270,"Exception number already exists.")
+RES_STR(ERR_Invalid_Action, 1271,"Must have a valid action for new Exception.")
+RES_STR(ERR_NoSymbols, 1272,"No Symbolic Info for Debuggee")
+RES_STR(ERR_CannotModifyExcepNum, 1273,"Cannot modify exception number, use Add to add new exception.")
+RES_STR(ERR_Not_Windbg_DLL, 1274,"'%s' is not a valid WinDBG DLL")
+RES_STR(ERR_Wrong_DLL_Type, 1275,"The DLL '%s' is type '%2.2s', type '%2.2s' was expected")
+RES_STR(ERR_Wrong_DLL_Version, 1276,"DLL '%s' is release type %d, version %d. %d, %d was expected")
+RES_STR(ERR_Goto_Line, 1277,"Cannot Understand Line to goto")
+RES_STR(ERR_Function_Locate, 1278,"Cannot locate function or address")
+RES_STR(ERR_No_Cmd_With_PFlag, 1279,"Debuggee not allowed with -p option")
+RES_STR(ERR_Dll_Key_Missing, 1280,"WinDBG tried to load %s, which is not listed\r\nas a %s DLL. Use Options.Debug.Debugger Dlls to fix.")
+RES_STR(ERR_File_Deleted, 1281,"%s No longer exists on disk, use File...Save to restore it")
+RES_STR(ERR_Empty_Shortname, 1282,"You must enter a short name")
+RES_STR(ERR_Exception_Unknown, 1283,"Exception 0x%08lx unknown")
+RES_STR(ERR_NoCodeForFileLine, 1284,"Code not found, breakpoint not set")
+RES_STR(ERR_Breakpoint_Not_Set, 1285,"Breakpoint not set")
+RES_STR(ERR_Wrong_Remote_DLL_Version, 1286,"Remote Transport DLL connecting to '%s' is the wrong version")
+RES_STR(ERR_Wrong_Debuggee_DLL_Version, 1287,"Remote Debuggee Module DLL is the wrong version")
+RES_STR(ERR_Cannot_Connect, 1288,"Transport DLL '%s' cannot connect to remote")
+RES_STR(ERR_Cant_Open_Com_Port, 1289,"Remote transport can't open comm port '%s'")
+RES_STR(ERR_Bad_Com_Parameters, 1390,"Remote transport can't set comm parameters '%s'")
+RES_STR(ERR_Bad_Pipe_Server, 1391,"Remote transport can't find named pipe server '%s'")
+RES_STR(ERR_Bad_Pipe_Name, 1392,"Remote transport can't find named pipe '%s'")
+RES_STR(ERR_NoModulesFound, 1393," No modules found")
+RES_STR(ERR_ModuleNotFound, 1394,"Module '%s' not found")
+RES_STR(ERR_BP_Edited, 1395,"Breakpoint was edited but was not added.\r\nAre you sure you want to leave without adding it?")
+RES_STR(ERR_Expclass_No_Members, 1396,"Expanded Class with no members ")
+RES_STR(ERR_No_Funcs_In_Watch, 1397,"Function calls not supported in watch window ")
+RES_STR(ERR_Unable_To_Complete_Gountil, 1398,"Unable to complete Go-Until command")
+RES_STR(ERR_Start_Failed, 1399,"Start failed")
+
+
+// Memory win strings
+
+RES_STR(ERR_Expression_Not_Parsable, 1400,"Cannot Parse Expression")
+RES_STR(ERR_Expression_Not_Bindable, 1401,"Cannot Bind Expression...deferring")
+RES_STR(ERR_Memory_Context, 1402,"Memory Object is out of Context")
+
+
+RES_STR(ERR_Cant_Modify_BP_While_Running, 1410,"Debuggee must be stopped before breakpoints can be modified.")
+
+
+
+
+
+//
+// System Strings
+//
+
+RES_STR(SYS_Main_wTitle, 2000,"Windbg")
+RES_STR(SYS_Main_wClass, 2001,"QcQpClass")
+RES_STR(SYS_Cmd_wClass, 2002,"CmdClass")
+RES_STR(SYS_Float_wClass, 2003,"FloatClass")
+RES_STR(SYS_Memory_wClass, 2004,"MemoryClass")
+RES_STR(SYS_Child_wClass, 2005,"QcQpChildClass")
+RES_STR(SYS_Edit_wClass, 2006,"EditClass")
+RES_STR(SYS_Cpu_wClass, 2007,"CpuClass")
+RES_STR(SYS_Watch_wClass, 2008,"WatchClass")
+RES_STR(SYS_Locals_wClass, 2009,"LocalsClass")
+RES_STR(SYS_Ribbon_wClass, 2010,"RibbonClass")
+RES_STR(SYS_Status_wClass, 2011,"StatusClass")
+RES_STR(SYS_QCQPCtrl_wClass, 2012,"QCQPCtrlClass")
+RES_STR(SYS_Disasm_wClass, 2013,"DisasmClass")
+RES_STR(SYS_Driver_FileExt, 2014,"DRV")
+RES_STR(SYS_Help_FileExt, 2015,"HLP")
+RES_STR(SYS_Ini_FileExt, 2016,".INI")
+RES_STR(SYS_WkSpace_FileExt, 2017,"WSP")
+RES_STR(SYS_Temp_FileExt, 2018,"$$$")
+RES_STR(SYS_Assert_File, 2019,"of File")
+RES_STR(SYS_Assert_Line, 2020,"Line #")
+RES_STR(SYS_Does_Not_Exist_Create, 2021,"'%s' does not exist. Would you like to create it?")
+RES_STR(SYS_Profile_Windows_Title, 2022,"windows")
+RES_STR(SYS_Profile_Device_Param, 2023,"Device")
+RES_STR(SYS_StatusClear, 2024," ")
+RES_STR(SYS_CpuWin_Title, 2025,"&Registers")
+RES_STR(SYS_WatchWin_Title, 2026,"&Watch")
+RES_STR(SYS_LocalsWin_Title, 2027,"&Locals")
+RES_STR(SYS_DisasmWin_Title, 2028,"&Disassembly")
+RES_STR(SYS_CmdWin_Title, 2029,"C&ommand")
+RES_STR(SYS_FloatWin_Title, 2030,"&Floating Point")
+RES_STR(SYS_MemoryWin_Title, 2031,"Memory")
+RES_STR(SYS_Nb_Of_Occurrences_Replaced, 2032,"%i occurrence(s) have been replaced")
+RES_STR(SYS_File_Changed, 2033,"Another application has changed the file '%s'. Do you want to reload it?")
+RES_STR(SYS_Alt, 2034,"Alt")
+RES_STR(SYS_Shift, 2035,"Shift")
+RES_STR(SYS_Save_Changes_To, 2036,"Would you like to save the changes made in '%s'?")
+RES_STR(SYS_My_String, 2037,"%s")
+RES_STR(SYS_RunDebugProgramArguments, 2038,"&Program Arguments:")
+RES_STR(SYS_RunDebugCallingProgram, 2039,"Calling &Program:")
+RES_STR(SYS_File_Filter, 2040,"List Files of &Type:")
+RES_STR(SYS_Compiling_Title, 2041, "")
+RES_STR(SYS_Building_Title, 2042, "")
+RES_STR(SYS_Free_Memory, 2043,"Cannot free memory")
+RES_STR(SYS_Lock_Memory, 2044,"Cannot lock memory")
+RES_STR(SYS_Case_Exception, 2045,"Case exception")
+RES_STR(SYS_Wrong_List_Count, 2046,"Wrong list count")
+RES_STR(SYS_Bad_List_index, 2047,"Bad list index")
+RES_STR(SYS_Index_Outside_Range, 2048,"Index outside range")
+RES_STR(SYS_Untitled_File, 2049,"UNTITLED %d")
+RES_STR(SYS_Rebuilding_Title, 2050, "")
+RES_STR(SYS_Allocate_Memory, 2051, "")
+RES_STR(SYS_RedoBufferOverflow, 2052,"Redo Buffer Overflow")
+RES_STR(SYS_RegExpr_StackOverflow, 2053, "")
+RES_STR(SYS_RegExpr_CompileAction, 2054, "")
+RES_STR(SYS_RegExpr_EstimateAction, 2055, "")
+RES_STR(SYS_Origin_Text, 2056, "")
+RES_STR(SYS_Location_BP, 2057, "")
+RES_STR(SYS_Done, 2058,"Done")
+RES_STR(SYS_Quick_wClass, 2059,"QuickClass")
+RES_STR(SYS_Untitled_Workspace, 2060,"Untitled")
+RES_STR(SYS_Calls_wClass, 2061,"CallsClass")
+RES_STR(SYS_CallsWin_Title, 2062,"&Calls")
+
+//
+// Debugger strings
+//
+
+RES_STR(DBG_Debuggee_In_Debugger, 2200,"Program is stopped in the debugger")
+RES_STR(DBG_Src_Info_Unavailable, 2201,"No source line information. Recompile with 'CodeView Info' selected")
+RES_STR(DBG_Windows_Fatal_Error, 2202,"Fatal Error. OK to ignore, Cancel to abort Windows")
+RES_STR(DBG_DialogBox_Open, 2203, "")
+RES_STR(DBG_Int3_Replaced, 2204, "")
+RES_STR(DBG_Int1_Replaced, 2205, "")
+RES_STR(DBG_Missing_Autorun, 2206,"Autorun testing file cannot be openned")
+RES_STR(DBG_Exception1_Occurred, 2207,"First chance exception %08lx (%s) occurred")
+RES_STR(DBG_Exception2_Occurred, 2208,"Second chance exception %08lx (%s) occurred")
+RES_STR(DBG_Thread_Stopped, 2209,"Thread stopped.")
+RES_STR(DBG_Go_When_Frozen, 2210,"(Thread is still frozen)")
+RES_STR(DBG_Notify_Break_Levels, 2211,"Notify %d, Break %d")
+RES_STR(DBG_Ranges_Match, 2212,"Memory blocks are identical")
+RES_STR(DBG_Ranges_Mismatch, 2213,"Memory blocks differ")
+RES_STR(DBG_Bytes_Copied, 2214,"%u of %u bytes copied")
+RES_STR(DBG_Symbol_Not_Found, 2215,"No symbol found")
+RES_STR(DBG_Not_Exact_Fill, 2216,"Range not divisible by object size -\r\nthe last byte will not be filled")
+RES_STR(DBG_Not_Exact_Fills, 2217,"Range not divisible by object size -\r\nlast %d bytes will not be filled")
+RES_STR(DBG_Attach_Running, 2218,"Process attached - running")
+RES_STR(DBG_Attach_Stopped, 2219,"Process attached - stopped")
+RES_STR(DBG_Bad_DLL_YESNO, 2220,"Invalid debugger DLL '%s'. Do you want to fix it now?")
+RES_STR(DBG_Deleting_DLL, 2221,"\
+Deleting %s DLL configuration '%s'.\r\n\
+If a workspace refers to this configuration, you\r\n\
+you need to correct it when that workspace is next\r\n\
+loaded. Press OK to delete, Cancel to keep it.")
+RES_STR(DBG_Losing_Command_Line, 2222,"Cancelling command line '%s'")
+RES_STR(DBG_Attach_Deadlock, 2223,"\
+The debuggee is deadlocked during startup or attaching\r\n\
+to a crashed process. This is probably because the\r\n\
+crash occurred in a DllMain function. You will be able\r\n\
+to examine variables, the stack, etc., but the debuggee\r\n\
+will probably not be able to step or run.")
+RES_STR(DBG_DebugInfo, 2224, "\
+The file '%s'\r\n%s\r\n\r\nUse this file anyway?")
+RES_STR(DBG_Hard_Coded_Breakpoint, 2225, "Hard coded breakpoint hit")
+RES_STR(DBG_At_Entry_Point, 2226, "Stopped at program entry point")
+
+//
+// Status Bar Messages
+//
+
+RES_STR(STA_File, 6000, "") // Keep those in order (begin)
+RES_STR(STA_Edit, 6001, "")
+RES_STR(STA_View, 6002, "")
+RES_STR(STA_Project, 6003, "")
+RES_STR(STA_Run, 6004, "")
+RES_STR(STA_Debug, 6005, "")
+RES_STR(STA_Options, 6007, "")
+RES_STR(STA_Window, 6008, "")
+RES_STR(STA_Help, 6009, "") // Keep those in order (end)
+RES_STR(STA_Program_Opened, 6100,"Opened the program %s")
+RES_STR(STA_Undo, 6160,"Undoing Action #%i")
+RES_STR(STA_Redo, 6170,"Redoing Action #%i")
+RES_STR(STA_End_Of_Undo, 6180,"Undo is Complete")
+RES_STR(STA_End_Of_Redo, 6190,"Redo is Complete")
+RES_STR(STA_Open_MRU_File, 6200,"Open the File ")
+RES_STR(STA_Open_MRU_Project, 6210,"Open the Program ")
+RES_STR(STA_Open_MDI_Window, 6220,"Activate the Window ")
+RES_STR(STA_Find_Hit_EOF, 6240,"Hit End of File")
+RES_STR(STA_Loading_Workspace, 6241,"Loading Workspace...")
+RES_STR(STA_Saving_Workspace, 6242,"Saving Workspace...")
+RES_STR(STA_Empty, 6243," ")
+
+//
+// Resource Strings
+//
+
+RES_STR(RES_ExtDeviceMode, 3047,"EXTDEVICEMODE")
+RES_STR(RES_DeviceMode, 3048,"DEVICEMODE")
+RES_STR(RES_DeviceCapabilities, 3049,"DEVICECAPABILITIES")
+RES_STR(RES_UserDllDefaults, 3068, "")
+
+//
+// File-box title strings
+//
+
+RES_STR(DLG_Open_Filebox_Title, 3200,"Open File")
+RES_STR(DLG_SaveAs_Filebox_Title, 3201,"Save As")
+RES_STR(DLG_Merge_Filebox_Title, 3202,"Merge")
+RES_STR(DLG_Browse_Filebox_Title, 3203,"Browse For File ")
+RES_STR(DLG_Browse_DbugDll_Title, 3204,"Browse For DLL ")
+RES_STR(DLG_Browse_UserDll_Title, 3205,"Browse For Symbol Information For ")
+
+//
+// Version string
+//
+
+RES_STR(DLG_Version, 3210,"%d.%02d.%03d %s")
+RES_STR(DLG_VersionIni, 3211,"0013")
+
+//
+// Dialog Boxes Strings
+//
+ // Dont insert
+ // From here
+ // These ID numbers
+ // must be separated
+ // by one and sorted
+ // ascending
+ // Up to there
+
+RES_STR(DLG_Cols_SourceWindow, 4001,"Source Window")
+RES_STR(DLG_Cols_WatchWindow, 4002,"Watch Window")
+RES_STR(DLG_Cols_LocalsWindow, 4003,"Locals Window")
+RES_STR(DLG_Cols_CpuWindow, 4004,"Registers Window")
+RES_STR(DLG_Cols_DisasmWindow, 4005,"Disassembler Window")
+RES_STR(DLG_Cols_CommandWindow, 4006,"Command Window")
+RES_STR(DLG_Cols_FloatWindow, 4007,"Floating Point Window")
+RES_STR(DLG_Cols_MemoryWindow, 4008,"Memory Window")
+RES_STR(DLG_Cols_CallsWindow, 4009,"Calls Window")
+RES_STR(DLG_Cols_BreakpointLine, 4010,"Breakpoint Line")
+RES_STR(DLG_Cols_CurrentLine, 4011,"Current Line")
+RES_STR(DLG_Cols_TaggedLine, 4012,"Tagged Line")
+RES_STR(DLG_Cols_Selection, 4013,"Text Selection")
+RES_STR(DLG_Cols_Keyword, 4014,"Keyword")
+RES_STR(DLG_Cols_Identifier, 4015,"Identifier")
+RES_STR(DLG_Cols_Comment, 4016,"Comment")
+RES_STR(DLG_Cols_Number, 4017,"Number")
+RES_STR(DLG_Cols_Real, 4018,"Real")
+RES_STR(DLG_Cols_String, 4019,"String")
+RES_STR(DLG_Cols_Freeze, 4020,"Free&ze")
+RES_STR(DLG_Cols_Thaw, 4021,"Tha&w")
+
+ // Editor : Don't change the order without forcasting consequencies
+ // there is a link between the first several colors and the type of
+ // the document in document structure
+
+#define DLG_Cols_First 0
+RES_STR(Cols_SourceWindow, 0, "")
+RES_STR(Cols_DummyWindow, 1, "")
+RES_STR(Cols_WatchWindow, 2, "")
+RES_STR(Cols_LocalsWindow, 3, "")
+RES_STR(Cols_CpuWindow, 4, "")
+RES_STR(Cols_DisasmWindow, 5, "")
+RES_STR(Cols_CommandWindow, 6, "")
+RES_STR(Cols_FloatWindow, 7, "")
+RES_STR(Cols_MemoryWindow, 8, "")
+RES_STR(Cols_CallsWindow, 9, "")
+RES_STR(Cols_BreakpointLine, 10,"")
+RES_STR(Cols_CurrentLine, 11, "")
+RES_STR(Cols_CurrentBreak, 12, "")
+RES_STR(Cols_UnInstantiatedBreakpoint, 13, "")
+RES_STR(Cols_TaggedLine, 14, "")
+RES_STR(Cols_Selection, 15, "")
+RES_STR(Cols_Keyword, 16, "")
+RES_STR(Cols_Identifier, 17, "")
+RES_STR(Cols_Comment, 18, "")
+RES_STR(Cols_Number, 19, "")
+RES_STR(Cols_Real, 20, "")
+RES_STR(Cols_String, 21, "")
+RES_STR(Cols_ActiveEdit, 22, "")
+RES_STR(Cols_ChangeHistory, 23, "")
+#define DLG_Cols_Last 23
+
+RES_STR(DLG_Cols_Sample_Text, 4030, " -- Sample Text -- ")
+
+//
+// Compiler flags strings
+// (memory models - must be contiguous and in this order)
+//
+
+RES_STR(DLG_CFlags_Tiny, 4040,"Tiny")
+RES_STR(DLG_CFlags_Small, 4041,"Small")
+RES_STR(DLG_CFlags_Compact, 4042,"Compact")
+RES_STR(DLG_CFlags_Medium, 4043,"Medium")
+RES_STR(DLG_CFlags_Large, 4044,"Large")
+
+RES_STR(DLG_CloseText1, 4060,"Save state information for program %s")
+RES_STR(DLG_CloseText2, 4061,"(Current workspace: %s) ?")
+RES_STR(DLG_CannotUnload, 4062,"Unable to unload current program!")
+RES_STR(DLG_NoSuchWorkSpace, 4063,"Specified workspace does not exist, loading Common.")
+RES_STR(DLG_NewDefaults, 4064,"Creating Common Workspace.")
+RES_STR(DLG_LoadedDefault, 4065,"Program has no workspace, loaded Common.")
+RES_STR(DLG_WorkSpaceSaved, 4066,"Workspace saved.")
+RES_STR(DLG_WorkSpaceNotSaved, 4067,"Could not save workspace.")
+RES_STR(DLG_DefaultSaved, 4068,"Common Workspace saved.")
+RES_STR(DLG_DefaultNotSaved, 4069,"Could not save Common Workspace.")
+RES_STR(DLG_NoMsg, 4080,"Must select a message")
+RES_STR(DLG_InvalidDllVersion, 4081,"The DLL %s is not compatible with the current debugger version. Use the Options menu to set a new path and save the workspace.")
+RES_STR(DLG_AlreadyAdded, 4090,"DLL already in list, use MODIFY to change settings")
+RES_STR(DLG_ResolveBpCaption, 4091,"Ambiguous Breakpoint")
+RES_STR(DLG_ResolveFuncCaption, 4092,"Ambiguous Expression")
+RES_STR(DLG_DefaultDoesNotExist, 4093,"Default workspace not found, using Common instead")
+RES_STR(DLG_ResolveFSCaption, 4094,"Ambiguous Source File Name")
+
+//
+// Environment text strings
+//
+
+RES_STR(ENV_Include_Var_Name, 7010, "")
+RES_STR(ENV_Library_Var_Name, 7020, "")
+
+//
+// Dos Exec Errors (Keep the resource # in accordance with error #)
+//
+
+RES_STR(DOS_Err_0, 8000,"There is Not Enough Memory to Start the Application")
+RES_STR(DOS_Err_2, 8002,"Cannot Find the Application")
+RES_STR(DOS_Err_3, 8003,"Cannot Find the Application on the Specified Path")
+RES_STR(DOS_Err_5, 8005,"Cannot Dynamically Link to a Task")
+RES_STR(DOS_Err_6, 8006,"Library Requires Separate Data Segments for Each Task")
+RES_STR(DOS_Err_10, 8010,"This is the Incorrect Windows Version for This Application")
+RES_STR(DOS_Err_11, 8011,"This is an Invalid .EXE File (Non-Windows or Error in Image)")
+RES_STR(DOS_Err_12, 8012,"Cannot Run an OS/2 Application")
+RES_STR(DOS_Err_13, 8013,"Cannot Run a DOS 4.0 Application")
+RES_STR(DOS_Err_14, 8014,"This is an Unknown Application Type")
+RES_STR(DOS_Err_15, 8015,"Cannot Run an Old Windows .EXE in Protected Mode")
+RES_STR(DOS_Err_16, 8016,"Cannot Run a Second Instance of an Application Containing Multiple, Writeable Data Segments")
+RES_STR(DOS_Err_17, 8017,"Cannot Run a Second Instance of this Application in Large-Frame EMS Mode")
+RES_STR(DOS_Err_18, 8018,"Cannot Run a Protected Mode Application in Real Mode")
+
+//
+// Debug Menu option strings
+// Set Breakpoint Action listbox - do not change
+// numbering without changing the BREAKPOINTACTIONS
+// enumeration
+//
+
+#define DBG_Brk_Start_Actions 9001
+RES_STR(DBG_Brk_At_Loc, 9001,"at Location")
+RES_STR(DBG_Brk_At_Loc_Expr_True, 9002,"at Location if Expr is True")
+RES_STR(DBG_Brk_At_Loc_Expr_Chgd, 9003,"at Location if Memory has Changed")
+RES_STR(DBG_Brk_Expr_True, 9004,"if Expr is True")
+RES_STR(DBG_Brk_Expr_Chgd, 9005,"if Memory has Changed")
+RES_STR(DBG_Brk_At_WndProc, 9006,"at Wnd Proc")
+RES_STR(DBG_Brk_At_WndProc_Expr_True, 9007,"at Wnd Proc if Expr is True")
+RES_STR(DBG_Brk_At_WndProc_Expr_Chgd, 9008,"at Wnd Proc if Memory has Changed")
+RES_STR(DBG_Brk_At_WndProc_Msg_Recvd, 9009,"at Wnd Proc if Message is Received")
+#define DBG_Brk_End_Actions 9009
+
+//
+// Message strings for the message selection combobox
+//
+
+#define DBG_Msgs_Start 9020
+RES_STR(DBG_Msgs_WM_1, DBG_Msgs_Start, "WM_ACTIVATE")
+RES_STR(DBG_Msgs_WM_2, DBG_Msgs_Start+1,"WM_ACTIVATEAPP")
+RES_STR(DBG_Msgs_WM_3, DBG_Msgs_Start+2,"WM_ASKCBFORMATNAME")
+RES_STR(DBG_Msgs_WM_4, DBG_Msgs_Start+3,"WM_CANCELMODE")
+RES_STR(DBG_Msgs_WM_5, DBG_Msgs_Start+4,"WM_CHANGECBCHAIN")
+RES_STR(DBG_Msgs_WM_6, DBG_Msgs_Start+5,"WM_CHAR")
+RES_STR(DBG_Msgs_WM_7, DBG_Msgs_Start+6,"WM_CHARTOITEM")
+RES_STR(DBG_Msgs_WM_8, DBG_Msgs_Start+7,"WM_CHILDACTIVATE")
+RES_STR(DBG_Msgs_WM_9, DBG_Msgs_Start+8,"WM_CLEAR")
+RES_STR(DBG_Msgs_WM_10, DBG_Msgs_Start+9,"WM_CLOSE")
+RES_STR(DBG_Msgs_WM_11, DBG_Msgs_Start+10,"WM_COMMAND")
+RES_STR(DBG_Msgs_WM_12, DBG_Msgs_Start+11,"WM_COMPACTING")
+RES_STR(DBG_Msgs_WM_13, DBG_Msgs_Start+12,"WM_COMPAREITEM")
+RES_STR(DBG_Msgs_WM_14, DBG_Msgs_Start+13,"WM_COPY")
+RES_STR(DBG_Msgs_WM_15, DBG_Msgs_Start+14,"WM_CREATE")
+RES_STR(DBG_Msgs_WM_16, DBG_Msgs_Start+15,"WM_CTLCOLOR")
+RES_STR(DBG_Msgs_WM_17, DBG_Msgs_Start+16,"WM_CUT")
+RES_STR(DBG_Msgs_WM_18, DBG_Msgs_Start+17,"WM_DEADCHAR")
+RES_STR(DBG_Msgs_WM_19, DBG_Msgs_Start+18,"WM_DELETEITEM")
+RES_STR(DBG_Msgs_WM_20, DBG_Msgs_Start+19,"WM_DESTROY")
+RES_STR(DBG_Msgs_WM_21, DBG_Msgs_Start+20,"WM_DESTROYCLIPBOARD")
+RES_STR(DBG_Msgs_WM_22, DBG_Msgs_Start+21,"WM_DEVMODECHANGE")
+RES_STR(DBG_Msgs_WM_23, DBG_Msgs_Start+22,"WM_DRAWCLIPBOARD")
+RES_STR(DBG_Msgs_WM_24, DBG_Msgs_Start+23,"WM_DRAWITEM")
+RES_STR(DBG_Msgs_WM_25, DBG_Msgs_Start+24,"WM_ENABLE")
+RES_STR(DBG_Msgs_WM_26, DBG_Msgs_Start+25,"WM_ENDSESSION")
+RES_STR(DBG_Msgs_WM_27, DBG_Msgs_Start+26,"WM_ENTERIDLE")
+RES_STR(DBG_Msgs_WM_28, DBG_Msgs_Start+27,"WM_ERASEBKGND")
+RES_STR(DBG_Msgs_WM_29, DBG_Msgs_Start+28,"WM_FONTCHANGE")
+RES_STR(DBG_Msgs_WM_30, DBG_Msgs_Start+29,"WM_GETDLGCODE")
+RES_STR(DBG_Msgs_WM_31, DBG_Msgs_Start+30,"WM_GETFONT")
+RES_STR(DBG_Msgs_WM_32, DBG_Msgs_Start+31,"WM_GETMINMAXINFO")
+RES_STR(DBG_Msgs_WM_33, DBG_Msgs_Start+32,"WM_GETTEXT")
+RES_STR(DBG_Msgs_WM_34, DBG_Msgs_Start+33,"WM_GETTEXTLENGTH")
+RES_STR(DBG_Msgs_WM_35, DBG_Msgs_Start+34,"WM_HSCROLL")
+RES_STR(DBG_Msgs_WM_36, DBG_Msgs_Start+35,"WM_HSCROLLCLIPBOARD")
+RES_STR(DBG_Msgs_WM_37, DBG_Msgs_Start+36,"WM_ICONERASEBKGND")
+RES_STR(DBG_Msgs_WM_38, DBG_Msgs_Start+37,"WM_INITDIALOG")
+RES_STR(DBG_Msgs_WM_39, DBG_Msgs_Start+38,"WM_INITMENU")
+RES_STR(DBG_Msgs_WM_40, DBG_Msgs_Start+39,"WM_INITMENUPOPUP")
+RES_STR(DBG_Msgs_WM_41, DBG_Msgs_Start+40,"WM_KEYDOWN")
+RES_STR(DBG_Msgs_WM_42, DBG_Msgs_Start+41,"WM_KEYFIRST")
+RES_STR(DBG_Msgs_WM_43, DBG_Msgs_Start+42,"WM_KEYLAST")
+RES_STR(DBG_Msgs_WM_44, DBG_Msgs_Start+43,"WM_KEYUP")
+RES_STR(DBG_Msgs_WM_45, DBG_Msgs_Start+44,"WM_KILLFOCUS")
+RES_STR(DBG_Msgs_WM_46, DBG_Msgs_Start+45,"WM_LBUTTONDBLCLK")
+RES_STR(DBG_Msgs_WM_47, DBG_Msgs_Start+46,"WM_LBUTTONDOWN")
+RES_STR(DBG_Msgs_WM_48, DBG_Msgs_Start+47,"WM_LBUTTONUP")
+RES_STR(DBG_Msgs_WM_49, DBG_Msgs_Start+48,"WM_MBUTTONDBLCLK")
+RES_STR(DBG_Msgs_WM_50, DBG_Msgs_Start+49,"WM_MBUTTONDOWN")
+RES_STR(DBG_Msgs_WM_51, DBG_Msgs_Start+50,"WM_MBUTTONUP")
+RES_STR(DBG_Msgs_WM_52, DBG_Msgs_Start+51,"WM_MDIACTIVATE")
+RES_STR(DBG_Msgs_WM_53, DBG_Msgs_Start+52,"WM_MDICASCADE")
+RES_STR(DBG_Msgs_WM_54, DBG_Msgs_Start+53,"WM_MDICREATE")
+RES_STR(DBG_Msgs_WM_55, DBG_Msgs_Start+54,"WM_MDIDESTROY")
+RES_STR(DBG_Msgs_WM_56, DBG_Msgs_Start+55,"WM_MDIGETACTIVE")
+RES_STR(DBG_Msgs_WM_57, DBG_Msgs_Start+56,"WM_MDIICONARRANGE")
+RES_STR(DBG_Msgs_WM_58, DBG_Msgs_Start+57,"WM_MDIMAXIMIZE")
+RES_STR(DBG_Msgs_WM_59, DBG_Msgs_Start+58,"WM_MDINEXT")
+RES_STR(DBG_Msgs_WM_60, DBG_Msgs_Start+59,"WM_MDIRESTORE")
+RES_STR(DBG_Msgs_WM_61, DBG_Msgs_Start+60,"WM_MDISETMENU")
+RES_STR(DBG_Msgs_WM_62, DBG_Msgs_Start+61,"WM_MDITILE")
+RES_STR(DBG_Msgs_WM_63, DBG_Msgs_Start+62,"WM_MEASUREITEM")
+RES_STR(DBG_Msgs_WM_64, DBG_Msgs_Start+63,"WM_MENUCHAR")
+RES_STR(DBG_Msgs_WM_65, DBG_Msgs_Start+64,"WM_MENUSELECT")
+RES_STR(DBG_Msgs_WM_66, DBG_Msgs_Start+65,"WM_MOUSEACTIVATE")
+RES_STR(DBG_Msgs_WM_67, DBG_Msgs_Start+66,"WM_MOUSEFIRST")
+RES_STR(DBG_Msgs_WM_68, DBG_Msgs_Start+67,"WM_MOUSELAST")
+RES_STR(DBG_Msgs_WM_69, DBG_Msgs_Start+68,"WM_MOUSEMOVE")
+RES_STR(DBG_Msgs_WM_70, DBG_Msgs_Start+69,"WM_MOVE")
+RES_STR(DBG_Msgs_WM_71, DBG_Msgs_Start+70,"WM_NCACTIVATE")
+RES_STR(DBG_Msgs_WM_72, DBG_Msgs_Start+71,"WM_NCCALCSIZE")
+RES_STR(DBG_Msgs_WM_73, DBG_Msgs_Start+72,"WM_NCCREATE")
+RES_STR(DBG_Msgs_WM_74, DBG_Msgs_Start+73,"WM_NCDESTROY")
+RES_STR(DBG_Msgs_WM_75, DBG_Msgs_Start+74,"WM_NCHITTEST")
+RES_STR(DBG_Msgs_WM_76, DBG_Msgs_Start+75,"WM_NCLBUTTONDBLCLK")
+RES_STR(DBG_Msgs_WM_77, DBG_Msgs_Start+76,"WM_NCLBUTTONDOWN")
+RES_STR(DBG_Msgs_WM_78, DBG_Msgs_Start+77,"WM_NCLBUTTONUP")
+RES_STR(DBG_Msgs_WM_79, DBG_Msgs_Start+78,"WM_NCMBUTTONDBLCLK")
+RES_STR(DBG_Msgs_WM_80, DBG_Msgs_Start+79,"WM_NCMBUTTONDOWN")
+RES_STR(DBG_Msgs_WM_81, DBG_Msgs_Start+80,"WM_NCMBUTTONUP")
+RES_STR(DBG_Msgs_WM_82, DBG_Msgs_Start+81,"WM_NCMOUSEMOVE")
+RES_STR(DBG_Msgs_WM_83, DBG_Msgs_Start+82,"WM_NCPAINT")
+RES_STR(DBG_Msgs_WM_84, DBG_Msgs_Start+83,"WM_NCRBUTTONDBLCLK")
+RES_STR(DBG_Msgs_WM_85, DBG_Msgs_Start+84,"WM_NCRBUTTONDOWN")
+RES_STR(DBG_Msgs_WM_86, DBG_Msgs_Start+85,"WM_NCRBUTTONUP")
+RES_STR(DBG_Msgs_WM_87, DBG_Msgs_Start+86,"WM_NEXTDLGCTL")
+RES_STR(DBG_Msgs_WM_88, DBG_Msgs_Start+87,"WM_NULL")
+RES_STR(DBG_Msgs_WM_89, DBG_Msgs_Start+88,"WM_PAINT")
+RES_STR(DBG_Msgs_WM_90, DBG_Msgs_Start+89,"WM_PAINTCLIPBOARD")
+RES_STR(DBG_Msgs_WM_91, DBG_Msgs_Start+90,"WM_PAINTICON")
+RES_STR(DBG_Msgs_WM_92, DBG_Msgs_Start+91,"WM_PALETTECHANGED")
+RES_STR(DBG_Msgs_WM_93, DBG_Msgs_Start+92,"WM_PALETTEISCHANGING")
+RES_STR(DBG_Msgs_WM_94, DBG_Msgs_Start+93,"WM_PARENTNOTIFY")
+RES_STR(DBG_Msgs_WM_95, DBG_Msgs_Start+94,"WM_PASTE")
+RES_STR(DBG_Msgs_WM_96, DBG_Msgs_Start+95,"WM_QUERYDRAGICON")
+RES_STR(DBG_Msgs_WM_97, DBG_Msgs_Start+96,"WM_QUERYENDSESSION")
+RES_STR(DBG_Msgs_WM_98, DBG_Msgs_Start+97,"WM_QUERYNEWPALETTE")
+RES_STR(DBG_Msgs_WM_99, DBG_Msgs_Start+98,"WM_QUERYOPEN")
+RES_STR(DBG_Msgs_WM_100, DBG_Msgs_Start+99,"WM_QUEUESYNC")
+RES_STR(DBG_Msgs_WM_101, DBG_Msgs_Start+100,"WM_QUIT")
+RES_STR(DBG_Msgs_WM_102, DBG_Msgs_Start+101,"WM_RBUTTONDBLCLK")
+RES_STR(DBG_Msgs_WM_103, DBG_Msgs_Start+102,"WM_RBUTTONDOWN")
+RES_STR(DBG_Msgs_WM_104, DBG_Msgs_Start+103,"WM_RBUTTONUP")
+RES_STR(DBG_Msgs_WM_105, DBG_Msgs_Start+104,"WM_RENDERALLFORMATS")
+RES_STR(DBG_Msgs_WM_106, DBG_Msgs_Start+105,"WM_RENDERFORMAT")
+RES_STR(DBG_Msgs_WM_107, DBG_Msgs_Start+106,"WM_SETCURSOR")
+RES_STR(DBG_Msgs_WM_108, DBG_Msgs_Start+107,"WM_SETFOCUS")
+RES_STR(DBG_Msgs_WM_109, DBG_Msgs_Start+108,"WM_SETFONT")
+RES_STR(DBG_Msgs_WM_110, DBG_Msgs_Start+109,"WM_SETREDRAW")
+RES_STR(DBG_Msgs_WM_111, DBG_Msgs_Start+110,"WM_SETTEXT")
+RES_STR(DBG_Msgs_WM_112, DBG_Msgs_Start+111,"WM_SHOWWINDOW")
+RES_STR(DBG_Msgs_WM_113, DBG_Msgs_Start+112,"WM_SIZE")
+RES_STR(DBG_Msgs_WM_114, DBG_Msgs_Start+113,"WM_SIZECLIPBOARD")
+RES_STR(DBG_Msgs_WM_115, DBG_Msgs_Start+114,"WM_SPOOLERSTATUS")
+RES_STR(DBG_Msgs_WM_116, DBG_Msgs_Start+115,"WM_SYSCHAR")
+RES_STR(DBG_Msgs_WM_117, DBG_Msgs_Start+116,"WM_SYSCOLORCHANGE")
+RES_STR(DBG_Msgs_WM_118, DBG_Msgs_Start+117,"WM_SYSCOMMAND")
+RES_STR(DBG_Msgs_WM_119, DBG_Msgs_Start+118,"WM_SYSDEADCHAR")
+RES_STR(DBG_Msgs_WM_120, DBG_Msgs_Start+119,"WM_SYSKEYDOWN")
+RES_STR(DBG_Msgs_WM_121, DBG_Msgs_Start+120,"WM_SYSKEYUP")
+RES_STR(DBG_Msgs_WM_122, DBG_Msgs_Start+121,"WM_TIMECHANGE")
+RES_STR(DBG_Msgs_WM_123, DBG_Msgs_Start+122,"WM_TIMER")
+RES_STR(DBG_Msgs_WM_124, DBG_Msgs_Start+123,"WM_UNDO")
+RES_STR(DBG_Msgs_WM_125, DBG_Msgs_Start+124,"WM_VKEYTOITEM")
+RES_STR(DBG_Msgs_WM_126, DBG_Msgs_Start+125,"WM_VSCROLL")
+RES_STR(DBG_Msgs_WM_127, DBG_Msgs_Start+126,"WM_VSCROLLCLIPBOARD")
+RES_STR(DBG_Msgs_WM_128, DBG_Msgs_Start+127,"WM_WININICHANGE")
+#ifdef FE_IME
+// add messages for IME
+//RES_STR(DBG_Msgs_WM_129, DBG_Msgs_Start+128,"WM_CONVERTREQUESTEX")
+RES_STR(DBG_Msgs_WM_129, DBG_Msgs_Start+128,"WM_IME_CHAR")
+RES_STR(DBG_Msgs_WM_130, DBG_Msgs_Start+129,"WM_IME_COMPOSITION")
+RES_STR(DBG_Msgs_WM_131, DBG_Msgs_Start+130,"WM_IME_COMPOSITIONFULL")
+RES_STR(DBG_Msgs_WM_132, DBG_Msgs_Start+131,"WM_IME_CONTROL")
+RES_STR(DBG_Msgs_WM_133, DBG_Msgs_Start+132,"WM_IME_ENDCOMPOSITION")
+RES_STR(DBG_Msgs_WM_134, DBG_Msgs_Start+133,"WM_IME_KEYDOWN")
+RES_STR(DBG_Msgs_WM_135, DBG_Msgs_Start+134,"WM_IME_KEYLAST")
+RES_STR(DBG_Msgs_WM_136, DBG_Msgs_Start+135,"WM_IME_KEYUP")
+RES_STR(DBG_Msgs_WM_137, DBG_Msgs_Start+136,"WM_IME_NOTIFY")
+RES_STR(DBG_Msgs_WM_138, DBG_Msgs_Start+137,"WM_IME_SELECT")
+RES_STR(DBG_Msgs_WM_139, DBG_Msgs_Start+138,"WM_IME_SETCONTEXT")
+RES_STR(DBG_Msgs_WM_140, DBG_Msgs_Start+139,"WM_IME_STARTCOMPOSITION")
+RES_STR(DBG_Msgs_WM_141, DBG_Msgs_Start+140,"WM_IME_REPORT")
+RES_STR(DBG_Msgs_WM_142, DBG_Msgs_Start+141,"WM_IMEKEYDOWN")
+RES_STR(DBG_Msgs_WM_143, DBG_Msgs_Start+142,"WM_IMEKEYUP")
+#define DBG_Msgs_End DBG_Msgs_WM_143
+#else
+#define DBG_Msgs_End DBG_Msgs_WM_128
+#endif //FE_IME
+
+//
+// definitions QCQP user control string IDs stored in string table
+// each controls must be together and must use the states offset.
+//
+
+RES_STR(IDS_CTRL_TRACENORMAL, 10100 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_TRACEPUSHED, 10100 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_TRACEGRAYED, 10100 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_STEPNORMAL, 10110 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_STEPPUSHED, 10110 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_STEPGRAYED, 10110 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_BREAKNORMAL, 10120 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_BREAKPUSHED, 10120 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_BREAKGRAYED, 10120 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_GONORMAL, 10130 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_GOPUSHED, 10130 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_GOGRAYED, 10130 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_HALTNORMAL, 10140 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_HALTPUSHED, 10140 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_HALTGRAYED, 10140 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_QWATCHNORMAL, 10150 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_QWATCHPUSHED, 10150 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_QWATCHGRAYED, 10150 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_SMODENORMAL, 10160 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_SMODEPUSHED, 10160 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_SMODEGRAYED, 10160 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_AMODENORMAL, 10170 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_AMODEPUSHED, 10170 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_AMODEGRAYED, 10170 + STATE_GRAYED, "")
+
+RES_STR(IDS_CTRL_FORMATNORMAL, 10180 + STATE_NORMAL, "")
+RES_STR(IDS_CTRL_FORMATPUSHED, 10180 + STATE_PUSHED, "")
+RES_STR(IDS_CTRL_FORMATGRAYED, 10180 + STATE_GRAYED, "")
+
+
+//
+// Definitions for status line messages
+//
+
+RES_STR(STS_MESSAGE_MULTIKEY, 10200,"^Q")
+RES_STR(STS_MESSAGE_OVERTYPE, 10201,"OVR")
+RES_STR(STS_MESSAGE_READONLY, 10202,"READ")
+RES_STR(STS_MESSAGE_CAPSLOCK, 10203,"CAPS")
+RES_STR(STS_MESSAGE_NUMLOCK, 10204,"NUM")
+RES_STR(STS_MESSAGE_LINE, 10205,"00000") // 5-digits
+RES_STR(STS_MESSAGE_COLUMN, 10206,"000") // 3-digits
+RES_STR(STS_MESSAGE_SRC, 10207,"SRC")
+RES_STR(STS_MESSAGE_CURPID, 10208,"000") // 3-digits
+RES_STR(STS_MESSAGE_CURTID, 10209,"000") // 3-digits
+RES_STR(STS_MESSAGE_ASM, 10210,"ASM")
+
+//)
+// Title bar strings)
+//)
+
+RES_STR(TBR_Mode_Work, 10300," [edit]")
+RES_STR(TBR_Mode_Run, 10310," [run]")
+RES_STR(TBR_Mode_Break, 10320," [break]")
+
+//)
+// Files types description)
+//)
+
+//RES_STR(TYP_File_SOURCE, 11011,"C/C++ Source Files (*.c, *.cxx)")
+//RES_STR(TYP_File_INCLUDE, 11012,"C/C++ Include Files (*.h)")
+//RES_STR(TYP_File_ASMSRC, 11013,"ASM Source Files (*.asm, *.s)")
+
+RES_STR(TYP_File_SOURCE, 11011,"C/C++ Src (*.c,*.cpp,*.cxx)")
+RES_STR(TYP_File_INCLUDE, 11012,"C/C++ Inc (*.h)")
+RES_STR(TYP_File_ASMSRC, 11013,"ASM Src (*.asm, *.s)")
+RES_STR(TYP_File_INC, 11180,"User Inc (*.inc)")
+RES_STR(TYP_File_RC, 11100,"Resource (*.rc)")
+RES_STR(TYP_File_DLG, 11110,"Dialog (*.dlg)")
+RES_STR(TYP_File_DEF, 11090,"Definition (*.def)")
+RES_STR(TYP_File_MAK, 11060,"Project (*.mak)")
+RES_STR(TYP_File_SYM, 11261,"Symbol (*.exe,*.dll,*.dbg)")
+RES_STR(TYP_File_SYMS, 11262,"MAPSYM (*.sym)")
+RES_STR(TYP_File_DLL, 11220,"Dynamic Library (*.dll)")
+RES_STR(TYP_File_ALL, 11270,"All Files (*.*)")
+
+RES_STR(TYP_File_C, 11010,"C Source (*.c)")
+RES_STR(TYP_File_CPP, 11020,"C++ Source (*.cpp)")
+RES_STR(TYP_File_CXX, 11030,"C++ Source (*.cxx)")
+RES_STR(TYP_File_H, 11040,"C Header (*.h)")
+RES_STR(TYP_File_NOEXT, 11050,"No Extension (*.)")
+RES_STR(TYP_File_OBJ, 11080,"Object Code (*.obj)")
+RES_STR(TYP_File_EXE, 11200,"Executable (*.exe)")
+RES_STR(TYP_File_COM, 11210,"Command (*.com)")
+RES_STR(TYP_File_ASM, 11250,"Asm Files (*.asm)")
+RES_STR(TYP_File_MIPSASM, 11260,"Mips Asm Files (*.s)")
+RES_STR(TYP_File_EXE_COM, 11280,"Executable (*.exe,*.com)")
+
+
+RES_STR(DEF_Ext_C, 11300,"*.C")
+RES_STR(DEF_Ext_SOURCE, 11301,"*.C;*.CPP;*.CXX")
+RES_STR(DEF_Ext_CPP, 11310,"*.CPP")
+RES_STR(DEF_Ext_CXX, 11320,"*.CXX")
+RES_STR(DEF_Ext_INCLUDE, 11321,"*.H;*.HPP;*.HXX")
+RES_STR(DEF_Ext_H, 11330,"*.H")
+RES_STR(DEF_Ext_NOEXT, 11340,"*.")
+RES_STR(DEF_Ext_MAK, 11350,"*.MAK")
+RES_STR(DEF_Ext_OBJ, 11370,"*.OBJ")
+RES_STR(DEF_Ext_DEF, 11380,"*.DEF")
+RES_STR(DEF_Ext_RC, 11390,"*.RC")
+RES_STR(DEF_Ext_DLG, 11400,"*.DLG")
+RES_STR(DEF_Ext_INC, 11470,"*.INC")
+RES_STR(DEF_Ext_EXE, 11490,"*.EXE")
+RES_STR(DEF_Ext_COM, 11500,"*.COM")
+RES_STR(DEF_Ext_DLL, 11510,"*.DLL")
+RES_STR(DEF_Ext_ASMSRC, 11511,"*.ASM;*.S")
+RES_STR(DEF_Ext_ASM, 11540,"*.ASM")
+RES_STR(DEF_Ext_MIPSASM, 11550,"*.S")
+RES_STR(DEF_Ext_SYM, 11551,"*.DLL;*.EXE;*.DBG")
+RES_STR(DEF_Ext_SYMS, 11552,"*.SYM")
+RES_STR(DEF_Ext_ALL, 11560,"*.*")
+RES_STR(DEF_Ext_EXE_COM, 11570,"*.exe;*.com")
+
+#ifdef RESOURCES
+ //
+ // Menu Items Status bar help
+ //
+
+ IDM_FILE, "File Operations, Exit"
+ IDM_FILE_NEW, "Create a new file"
+ IDM_FILE_OPEN, "Open an existing file"
+ IDM_FILE_MERGE, "Merge a file into Active Window"
+ IDM_FILE_CLOSE, "Close Active Window"
+ IDM_FILE_SAVE, "Save Active File"
+ IDM_FILE_SAVEAS, "Save Active File with a New Name"
+ IDM_FILE_SAVEALL, "Save all open files"
+ IDM_FILE_EXIT, "Exit Windbg"
+ IDM_EDIT, "Edit Operations, Find and Replace"
+ IDM_EDIT_UNDO, "Undo the Previous Edit Action"
+ IDM_EDIT_REDO, "Redo the Previous Undo"
+ IDM_EDIT_CUT, "Move the Selected Text to the Clipboard"
+ IDM_EDIT_COPY, "Copy the Selected Text to the Clipboard"
+ IDM_EDIT_PASTE, "Paste the Clipboard Text at the Insertion Point"
+ IDM_EDIT_DELETE, "Delete the Selected Text or the Character at the Cursor"
+ IDM_EDIT_FIND, "Find Some Text"
+ IDM_EDIT_REPLACE, "Find Some Text and Replace It"
+ IDM_EDIT_READONLY, "Make the Active File Read-Only"
+ IDM_VIEW, "File Navigation, Status and Toolbars"
+ IDM_VIEW_LINE, "Move to a Specified Line Number"
+ IDM_VIEW_FUNCTION, "Move to the Specified Address"
+ IDM_VIEW_TOGGLETAG, "Toggle a Tag for the Current Line"
+ IDM_VIEW_NEXTTAG, "Move to the Next Tagged Line"
+ IDM_VIEW_PREVIOUSTAG, "Move to the Previous Tagged Line"
+ IDM_VIEW_CLEARALLTAGS, "Clear All Tags in the Active File"
+ IDM_VIEW_RIBBON, "Toggle the Toolbar On/Off"
+ IDM_VIEW_STATUS, "Toggle the Status Bar On/Off"
+ IDM_PROGRAM, "Program and Workspace Operations"
+ IDM_PROGRAM_OPEN, "Open a Program"
+ IDM_PROGRAM_CLOSE, "Close the Current Program"
+ IDM_PROGRAM_SAVE, "Save current Workspace"
+ IDM_PROGRAM_SAVEAS, "Save a Workspace"
+ IDM_PROGRAM_DELETE, "Delete Programs and Workspaces"
+ IDM_PROGRAM_SAVE_DEFAULTS, "Save user defaults"
+ IDM_RUN, "Program Execution Operations"
+ IDM_RUN_ATTACH, "Attach to a running process"
+ IDM_RUN_RESTART, "Restart the Program"
+ IDM_RUN_STOPDEBUGGING, "Stop Debugging the Current Program"
+ IDM_RUN_GO, "Run the Program"
+ IDM_RUN_TOCURSOR, "Run the Program to the Line Containing the Cursor"
+ IDM_RUN_TRACEINTO, "Trace Into the Next Statement"
+ IDM_RUN_STEPOVER, "Step Over the Next Statement"
+ IDM_RUN_HALT, "Halt the Current Program"
+ IDM_RUN_SET_THREAD, "View or set the Current Thread"
+ IDM_RUN_SET_PROCESS, "View or set the Current Process"
+ IDM_RUN_SOURCE_MODE, "Toggle Source and Assembly Mode"
+ IDM_RUN_GO_HANDLED, "Handle the Exception and Continue Running"
+ IDM_RUN_GO_UNHANDLED, "Do Not Handle the Exception, but Continue Running"
+ IDM_DEBUG, "Debugging Instruments"
+ IDM_DEBUG_CALLS, "List the Calls that Led to the Current Statement"
+ IDM_DEBUG_SETBREAK, "Set Breakpoints in the Program"
+ IDM_DEBUG_QUICKWATCH, "Quick Watch and Modify Variables/Expressions"
+ IDM_DEBUG_WATCH, "Add Variables/Expressions to the Watch Window"
+ IDM_DEBUG_MODIFY, "Change the Value of a Variable"
+ IDM_OPTIONS, "Environment Options"
+ IDM_OPTIONS_RUN, "Set Options for Running a Program"
+ IDM_OPTIONS_DEBUG, "Set Options for Debugging a Program"
+ IDM_OPTIONS_MEMORY, "Set Options for Memory Window"
+ IDM_OPTIONS_WATCH, "Set Options for Watch Window"
+ IDM_OPTIONS_LOCAL, "Set Options for Locals Window"
+ IDM_OPTIONS_CPU, "Set Options for CPU Window"
+ IDM_OPTIONS_FLOAT, "Set Options for Float Window"
+ IDM_OPTIONS_ENVIRON, "Set Windbg Environment Options"
+ IDM_OPTIONS_COLOR, "Set the Environment Colors"
+ IDM_OPTIONS_FONTS, "Select Fonts for the Windows"
+ IDM_OPTIONS_USERDLL, "Set symbol loading options"
+ IDM_OPTIONS_DBGDLL, "Set debugger modules"
+ IDM_OPTIONS_EXCEPTIONS, "Manage exception handling"
+ IDM_OPTIONS_KD, "Set kernel debugging options"
+ IDM_OPTIONS_CALLS, "Set Options for Calls Window"
+ IDM_WINDOW, "Window Arrangement and Selection"
+ IDM_WINDOW_NEWWINDOW, "Duplicate the Active Window"
+ IDM_WINDOW_CASCADE, "Arrange the Windows in a Cascaded View"
+ IDM_WINDOW_TILE, "Arrange the Windows in a Tiled View"
+ IDM_WINDOW_ARRANGE, "Arrange the Windows"
+ IDM_WINDOW_ARRANGE_ICONS, "Arrange Icons"
+ IDM_WINDOW_SOURCE_OVERLAY, "Overlay source windows"
+ IDM_WINDOW_WATCH, "Open the Watch Window"
+ IDM_WINDOW_LOCALS, "Open the Locals Window"
+ IDM_WINDOW_CPU, "Open the Registers Window"
+ IDM_WINDOW_DISASM, "Open the Disassembly Window"
+ IDM_WINDOW_COMMAND, "Open the Command Window"
+ IDM_WINDOW_FLOAT, "Open the Floating Point Window"
+ IDM_WINDOW_MEMORY, "Open a Memory Window"
+ IDM_WINDOW_CALLS, "Open a Call Stack Window"
+ IDM_HELP, "Help Contents and Searches"
+ IDM_HELP_CONTENTS, "Open the Help Table of Contents"
+ IDM_HELP_SEARCH, "Open the Help Search Dialog"
+ IDM_HELP_ABOUT, "About Windbg"
+
+ IDS_SOURCE_WINDOW, "Source Window"
+ IDS_DUMMY_WINDOW, "Dummy" //do NOT Remove!!GWK
+ IDS_WATCH_WINDOW, "Watch Window"
+ IDS_LOCALS_WINDOW, "Locals Window"
+ IDS_CPU_WINDOW, "Registers Window"
+ IDS_DISASSEMBLER_WINDOW, "Disassembler Window"
+ IDS_COMMAND_WINDOW, "Command Window"
+ IDS_FLOAT_WINDOW, "Floating Point Window"
+ IDS_MEMORY_WINDOW, "Memory Window"
+ IDS_CALLS_WINDOW, "Calls Window"
+ IDS_BREAKPOINT_LINE, "Breakpoint Line"
+ IDS_CURRENT_LINE, "Current Line"
+ IDS_CURRENTBREAK_LINE, "Current Line w/BreakPoint"
+ IDS_UNINSTANTIATEDBREAK, "Uninstantiated BreakPoint"
+ IDS_TAGGED_LINE, "Tagged Line"
+ IDS_TEXT_SELECTION, "Text Selection"
+ IDS_KEYWORD, "Keyword"
+ IDS_IDENTIFIER, "Identifier"
+ IDS_COMMENT, "Comment"
+ IDS_NUMBER, "Number"
+ IDS_REAL, "Real"
+ IDS_STRING, "String"
+ IDS_ACTIVEEDIT, "Active Edit"
+ IDS_CHANGEHISTORY, "Change History"
+
+
+ IDS_SELECT_ALL, "Select A&ll"
+ IDS_CLEAR_ALL, "Clear A&ll"
+#endif
+
+#ifdef RESOURCES
+END
+#else
+ IDS_REMOVE_WARNING
+};
+#endif
+
+
+#endif // _RES_STR_
diff --git a/private/windbg/windbg/include/resource.h b/private/windbg/windbg/include/resource.h
new file mode 100644
index 000000000..dc97e0419
--- /dev/null
+++ b/private/windbg/windbg/include/resource.h
@@ -0,0 +1,47 @@
+#define QCQPICON 3001
+#define HELPCURSOR 3002
+#define DOCICON 3003
+#define CPUICON 3004
+#define LOCALSICON 3005
+#define WATCHICON 3006
+#define DISASMICON 3007
+#define CMDICON 3008
+#define FLOATICON 3009
+#define MEMORYICON 3010
+
+#define VGA_FORMAT_NORMAL 3011
+#define VGA_FORMAT_PUSHED 3012
+#define VGA_FORMAT_GRAYED 3013
+#define VGA_TRACE_NORMAL 3014
+#define VGA_TRACE_PUSHED 3015
+#define VGA_TRACE_GRAYED 3016
+#define VGA_STEP_NORMAL 3017
+#define VGA_STEP_PUSHED 3018
+#define VGA_STEP_GRAYED 3019
+#define VGA_BREAK_NORMAL 3020
+#define VGA_BREAK_PUSHED 3021
+#define VGA_BREAK_GRAYED 3022
+#define VGA_GO_NORMAL 3023
+#define VGA_GO_PUSHED 3024
+#define VGA_GO_GRAYED 3025
+#define VGA_HALT_NORMAL 3026
+#define VGA_HALT_PUSHED 3027
+#define VGA_HALT_GRAYED 3028
+#define VGA_QWATCH_NORMAL 3029
+#define VGA_QWATCH_PUSHED 3030
+#define VGA_QWATCH_GRAYED 3031
+#define VGA_SMODE_NORMAL 3032
+#define VGA_SMODE_PUSHED 3033
+#define VGA_SMODE_GRAYED 3034
+#define VGA_AMODE_NORMAL 3035
+#define VGA_AMODE_PUSHED 3036
+#define VGA_AMODE_GRAYED 3037
+
+
+#define QCQPMAINMENU 3038
+#define QCQPMAINACC 3039
+
+#define VGA_PANE_BLANK 3040
+#define VGA_PANE_MINUS 3041
+#define VGA_PANE_PLUS 3042
+
diff --git a/private/windbg/windbg/include/ribbon.h b/private/windbg/windbg/include/ribbon.h
new file mode 100644
index 000000000..41c1761d8
--- /dev/null
+++ b/private/windbg/windbg/include/ribbon.h
@@ -0,0 +1,23 @@
+/*++ BUILD Version: 0002 // Increment this if a change has global effects
+---*/
+#define ID_RIBBON_TRACE 105
+#define ID_RIBBON_STEP 106
+#define ID_RIBBON_BREAK 107
+#define ID_RIBBON_GO 108
+#define ID_RIBBON_HALT 109
+#define ID_RIBBON_QWATCH 110
+#define ID_RIBBON_SMODE 111
+#define ID_RIBBON_AMODE 112
+#define ID_RIBBON_FORMAT 113
+
+
+// definitions for Ribbon buttons Widths and Heights for different resolutions
+// (use the same widhts and heights for now until the real dimensions come.
+
+#define RIBBON_CGA_WIDTH 18
+#define RIBBON_CGA_HEIGHT 16
+#define RIBBON_EGA_WIDTH 24
+#define RIBBON_EGA_HEIGHT 16
+#define RIBBON_VGA_WIDTH 24
+#define RIBBON_VGA_HEIGHT 22
+
diff --git a/private/windbg/windbg/include/sbconst.h b/private/windbg/windbg/include/sbconst.h
new file mode 100644
index 000000000..99903174d
--- /dev/null
+++ b/private/windbg/windbg/include/sbconst.h
@@ -0,0 +1,108 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/*** SBCONST.H - Systemwide sb handles
+*
+* GLOBAL
+* None
+*
+* LOCAL
+* None
+*
+* DESCRIPTION
+* Constant sb handles
+*
+* HISTORY
+* 26-Oct-90 [mannyv} Distilled for NATSYS
+* 26-Jan-88 [jimsch] Added some kernel handles
+* 18-Dec-87 [mattg] Created
+*
+* NOTES
+* Tabs 8.
+*/
+
+/*
+** system (CW)
+*/
+
+#define sbNil 0 /* Always */
+#define sbDds 1 /* DGROUP */
+
+/*
+** Global Routines from kernel
+*/
+
+#define sbAtomIndex 2 /* See ATOM.ASM */
+#define sbAtomStrings 3 /* See ATOM.ASM */
+#define sbKernFixed 4 /* See KERNEL.C */
+#define sbUserProg sbKernFixed
+#define sbMrk1 5 /* See NOTEPAD/MARK.C */
+#define sbMrk2 6 /* See NOTEPAD/MARK.C */
+#define sbCompRE 7 /* See NOTEPAD/SEARCH.C */
+#define sbCvPublics 8 /* Code View Public Symbols */
+#define sbScratch 9 /* General-purpose scratch SB */
+#define sbHelpBuf 10 /* See HELP directory */
+#define sbCvInfo 11 /* Points to Code View Info SB's */
+#define sbUserScreen 12 /* User Screen Region Save buffer */
+#define sbCwScreen 13 /* Cw Screen Region Save buffer */
+#define sbUserTape 14 /* User Tape buffer */
+#define sbProgramList 15 /* Main Program List buffer */
+#define sbProgDepList 16 /* Dependency Program List buffer */
+#define sbMakDepHandle 17 /* Program List dependency handles */
+#define sbMakDepHeap 18 /* Program List dependency heap */
+#define sbMakRuleList 19 /* Program List rules list */
+#define sbMrk3 20 /* */
+#define sbMrk4 21 /* */
+#define sbMrkErrors 22 /* Mark table for error window lines */
+#define sbQWatch 23 /* Quick Watch tree */
+
+/*
+** Buffers for EDITMGR
+*/
+
+#define sbShScrap 25
+
+/*
+** Buffers for PIO
+*/
+
+#define csbPIO 12 /* Number of SBs for PIO */
+
+#define sbPIOMin 26 /* First SB for PIO routines */
+#define sbPIOMax (sbPIOMin + csbPIO - 1) /* Last SB for PIO routines */
+
+/*
+** Buffers for HELP
+*/
+
+#define csbHelp 16
+
+#define sbHelpMin (sbPIOMax + 1)
+#define sbHelpMax (sbHelpMin + csbHelp - 1)
+
+/*
+** The following may be reused since multiple vaps may not be running
+** at the same time.
+*/
+
+#define sbVapMin sbHelpMax + 1
+
+/*
+** Cc VAP
+*/
+
+#define sbCcMin sbVapMin
+#define sbCcDgroup (sbCcMin) /* DGROUP handle for Compiler */
+#define sbCcPreload (sbCcMin + 1) /* First based heap */
+#define sbCcPreloadMax (sbCcPreload + 3) /* Last based heap + 1 */
+#define sbCcLpt (sbCcPreloadMax + 0) /* loop table */
+#define sbCcLps (sbCcPreloadMax + 1) /* loop stack */
+#define sbCcDtyp (sbCcPreloadMax + 2) /* debug types */
+#define sbMdt (sbCcPreloadMax + 3)
+#define sbMdtNames (sbCcPreloadMax + 4)
+#define sbCcMax (sbCcPreloadMax + 5)
+
+/*
+** Constants releated to SbScanNext
+*/
+
+#define sbReservedMax (sbVapMin + 20)
diff --git a/private/windbg/windbg/include/settings.h b/private/windbg/windbg/include/settings.h
new file mode 100644
index 000000000..b99b43d48
--- /dev/null
+++ b/private/windbg/windbg/include/settings.h
@@ -0,0 +1,16 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+#define ID_SETTINGS_AUTO 105
+#define ID_SETTINGS_BUTTONCURSOR 123
+#define ID_SETTINGS_BUTTONHELP 122
+#define ID_SETTINGS_C 102
+#define ID_SETTINGS_CANCEL 121
+#define ID_SETTINGS_HELP 113
+#define ID_SETTINGS_KEEPTABS 109
+#define ID_SETTINGS_OK 120
+#define ID_SETTINGS_PASCAL 104
+#define ID_SETTINGS_PROMPT 118
+#define ID_SETTINGS_SAVEBEFORE 117
+#define ID_SETTINGS_SCROLLBARS 110
+#define ID_SETTINGS_SMARTHELP 115
+#define ID_SETTINGS_TABSTOPS 107
diff --git a/private/windbg/windbg/include/shproto.h b/private/windbg/windbg/include/shproto.h
new file mode 100644
index 000000000..4db0d4630
--- /dev/null
+++ b/private/windbg/windbg/include/shproto.h
@@ -0,0 +1,101 @@
+#define SHCreateProcess Lpshf->pSHCreateProcess
+#define SHSetHpid Lpshf->pSHSetHpid
+#define SHDeleteProcess Lpshf->pSHDeleteProcess
+#define SHChangeProcess Lpshf->pSHChangeProcess
+#define SHAddDll Lpshf->pSHAddDll
+#define SHAddDllsToProcess Lpshf->pSHAddDllsToProcess
+#define SHLoadDll Lpshf->pSHLoadDll
+#define SHUnloadDll Lpshf->pSHUnloadDll
+#define SHGetDebugStart Lpshf->pSHGetDebugStart
+#define SHGetSymName Lpshf->pSHGetSymName
+#define SHAddrFromHsym Lpshf->pSHAddrFromHsym
+#define SHHModGetNextGlobal Lpshf->pSHHModGetNextGlobal
+#define SHModelFromADDR Lpshf->pSHModelFromADDR
+#define SHPublicNameToADDR Lpshf->pSHPublicNameToADDR
+#define SHGetSymbol Lpshf->pSHGetSymbol
+#define SHGetModule Lpshf->pSHGetModule
+#define SHGetPublicAddr Lpshf->pSHGetPublicAddr
+#define SHIsLabel Lpshf->pSHIsLabel
+#define SHSetDebuggeeDir Lpshf->pSHSetDebuggeeDir
+#define SHSetUserDir Lpshf->pSHSetUserDir
+#define SHModHasSrc Lpshf->pSHModHasSrc
+#define SHHplrbNext Lpshf->pSHHplrbNext
+#define SHGetLineInfo Lpshf->pSHGetLineInfo
+#define SHGetfip Lpshf->pSHGetfip
+#define SHSetfip Lpshf->pSHSetfip
+#define SHLrbToHFL Lpshf->pSHLrbToHFL
+#define SHXlasFill Lpshf->pSHXlasFill
+#define SHGETMODHFL Lpshf->pSHGETMODHFL
+#define SHGetSourceName Lpshf->pSHGetSourceName
+#define SHSrcFlag Lpshf->pSHSrcFlag
+#define SHXlszGetFile Lpshf->pSHXlszGetFile
+#define SHAddrToLabel Lpshf->pSHAddrToLabel
+#define SHGetSymLoc Lpshf->pSHGetSymLoc
+#define SHFIsAddrNonVirtual Lpshf->pSHFIsAddrNonVirtual
+#define SHIsFarProc Lpshf->pSHIsFarProc
+#define SHGetNextExe Lpshf->pSHGetNextExe
+#define SHGetNextMod Lpshf->pSHGetNextMod
+#define SHHexeFromHmod Lpshf->pSHHexeFromHmod
+#define SHGetCxtFromHmod Lpshf->pSHGetCxtFromHmod
+#define SHGetCxtFromHexe Lpshf->pSHGetCxtFromHexe
+#define SHSetCxt Lpshf->pSHSetCxt
+#define SHSetCxtMod Lpshf->pSHSetCxtMod
+#define SHFindNameInGlobal Lpshf->pSHFindNameInGlobal
+#define SHFindNameInContext Lpshf->pSHFindNameInContext
+#define SHGoToParent Lpshf->pSHGoToParent
+#define SHHSYMFrompCXT Lpshf->pSHHSYMFrompCXT
+#define SHNextHSYM Lpshf->pSHNextHSYM
+#define SHGetFuncCXF Lpshf->pSHGetFuncCXF
+#define SHNextHSYM Lpshf->pSHNextHSYM
+#define SHGetModName Lpshf->pSHGetModName
+#define SHGetFileName Lpshf->pSHGetFileName
+#define SHGetExeName Lpshf->pSHGetExeName
+#define SHGetModNameFromHexe Lpshf->pSHGetModNameFromHexe
+#define SHGetSymFName Lpshf->pSHGetSymFName
+#define SHGethFileFromhMod Lpshf->pSHGethFileFromhMod
+#define SHGethModFromName Lpshf->pSHGethModFromName
+#define SHGethExeFromName Lpshf->pSHGethExeFromName
+#define SHGethExeFromModuleName Lpshf->pSHGethExeFromModuleName
+#define SHGetNearestHSYM Lpshf->pSHGetNearestHsym
+#define SHIsInProlog Lpshf->pSHIsInProlog
+#define SHIsAddrInCxt Lpshf->pSHIsAddrInCxt
+#define SHLineFromADDR Lpshf->pSHLineFromADDR
+#define SHADDRFromLine Lpshf->pSHADDRFromLine
+#define SHCompareRE Lpshf->pSHCompareRE
+#define PHGetNearestHsym Lpshf->pPHGetNearestHsym
+#define PHFindNameInPublics Lpshf->pPHFindNameInPublics
+#define THGetTypeFromIndex Lpshf->pTHGetTypeFromIndex
+#define THGetNextType Lpshf->pTHGetNextType
+#define SHGetNextType Lpshf->pSHGetNextType
+#define SHLpGSNGetTable Lpshf->pSHLpGSNGetTable
+#define SHGetDebugData Lpshf->pSHGetDebugData
+#define SHCanDisplay Lpshf->pSHCanDisplay
+#define SHLszGetErrorText Lpshf->pSHLszGetErrorText
+#define SHIsThunk Lpshf->pSHIsThunk
+#define SHWantSymbols Lpshf->pSHWantSymbols
+#define SLLineFromAddr Lpshf->pSLLineFromAddr
+#define SLFLineToAddr Lpshf->pSLFLineToAddr
+#define SLNameFromHsf Lpshf->pSLNameFromHsf
+#define SLNameFromHmds Lpshf->pSLNameFromHmds
+#define SLFQueryModSrc Lpshf->pSLFQueryModSrc
+#define SLHmdsFromHsf Lpshf->pSLHmdsFromHsf
+#define SLHsfFromPcxt Lpshf->pSLHsfFromPcxt
+#define SLHsfFromFile Lpshf->pSLHsfFromFile
+
+#define SHpCXTFrompCXF(a) (&((a)->cxt))
+#define SHpFrameFrompCXF(a) (&(a)->Frame)
+#define SHHodFrompCxt(a) ((a)->hMod)
+#define SHHPROCFrompCXT(a) ((a)->hProc)
+#define SHHBLKFrompCXT(a) ((a)->hBlk)
+#define SHpADDRFrompCXT(a) (&((a)->addr))
+
+#define SHIsCXTMod(a) ((a)->hMod && !(a)->hProc && !(a)->hBlk)
+#define SHIsCXTProc(a) ((a)->hMod && (a)->hProc && !(a)->hBlk)
+#define SHIsCXTBlk(a) ((a)->hMod && (a)->hProc && (a)->hBlk)
+
+#define SHHGRPFrompCXT(a) ((a)->hGrp)
+
+#define SHpCxtFrompCxf(a) (&((a)->cxt))
+#define SHpFrameFrompCxf(a) (&(a)->Frame)
+#define SHpAddrFrompCxt(a) (&((a)->addr))
+#define SHHmodFrompCxt(a) ((a)->hMod)
diff --git a/private/windbg/windbg/include/status.h b/private/windbg/windbg/include/status.h
new file mode 100644
index 000000000..d11a565ef
--- /dev/null
+++ b/private/windbg/windbg/include/status.h
@@ -0,0 +1,7 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+//Handle the status line
+LONG FAR PASCAL EXPORT StatusWndProc (HWND hWnd, UINT message, WPARAM wParam, LONG lParam);
+
+void ResizeStatusLine (LPRECT r);
diff --git a/private/windbg/windbg/include/syntax.h b/private/windbg/windbg/include/syntax.h
new file mode 100644
index 000000000..dd6491e40
--- /dev/null
+++ b/private/windbg/windbg/include/syntax.h
@@ -0,0 +1,8 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+#define ID_SYNTAX_C 105
+#define ID_SYNTAX_CANCEL 109
+#define ID_SYNTAX_HELP 110
+#define ID_SYNTAX_NONE 102
+#define ID_SYNTAX_OK 107
+#define ID_SYNTAX_PASCAL 106
diff --git a/private/windbg/windbg/include/systemw3.h b/private/windbg/windbg/include/systemw3.h
new file mode 100644
index 000000000..916fd9cc2
--- /dev/null
+++ b/private/windbg/windbg/include/systemw3.h
@@ -0,0 +1,30 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+extern struct dbg uPTB;
+
+//I'm using the original CV400 windebug.h (old version)
+#define DBG_C_RegisterCallBack 106 // used by debuggers that run in a window and
+
+BOOL sys_init(
+ void);
+
+void sys_quit(
+ void);
+
+unsigned ptrace (
+ int request,
+ int pid,
+ ADDR addr,
+ int data);
+
+BOOL load(
+ int argc,
+ char *argv[]);
+
+void WaitForNotification(void);
+
+void SignalNotification(void);
+
+BOOL RegisterCallBack(FARPROC);
+
+void PASCAL ResetSystemw3Statics(void);
diff --git a/private/windbg/windbg/include/undoredo.h b/private/windbg/windbg/include/undoredo.h
new file mode 100644
index 000000000..38607b94b
--- /dev/null
+++ b/private/windbg/windbg/include/undoredo.h
@@ -0,0 +1,44 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+BOOL FAR PASCAL CreateRecBuf(
+ int doc,
+ BYTE recType,
+ long bytes);
+
+BOOL FAR PASCAL DestroyRecBuf(
+ int doc,
+ WORD recType);
+
+BOOL FAR PASCAL ResizeRecBuf(
+ int doc,
+ long bytes);
+
+BOOL FAR PASCAL OpenRec(
+ int doc,
+ BYTE action,
+ int col,
+ int line);
+
+void FAR PASCAL CloseRec(
+ int doc,
+ int col,
+ int line,
+ BOOL keepRec);
+
+BOOL FAR PASCAL AppendToRec(int doc, LPSTR chars, int size, BOOL isLine, int *totalSize);
+
+BOOL FAR PASCAL PlayRec(
+ int doc,
+ WORD recType,
+ BOOL untilUserMark,
+ BOOL prompt);
+
+void FAR PASCAL ReadLineFromBuf(NPUNDOREDOREC p, LPSTR dest, int *size, int *expandedLen, LPSTR *charsEnd);
+
+BOOL FAR PASCAL CheckRecBuf(
+ int doc,
+ WORD recType);
+
+void FAR PASCAL DumpRec(
+ int doc,
+ WORD recType);
diff --git a/private/windbg/windbg/include/userctrl.h b/private/windbg/windbg/include/userctrl.h
new file mode 100644
index 000000000..856800557
--- /dev/null
+++ b/private/windbg/windbg/include/userctrl.h
@@ -0,0 +1,79 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+LONG FAR PASCAL EXPORT QCQPCtrlWndProc (HWND, UINT, WPARAM, LONG) ;
+ /*
+ * call - QCQPProc (hWnd, iMessage, wParam, lParam)
+ * hWnd parent's window handle
+ * iMessage window's messages
+ * wParam word parameter
+ * lParam long parameter
+ */
+
+void EnableQCQPCtrl (HWND, int, BOOL) ;
+ /*
+ * call - EnableQCQPCtrl (hWnd, enable) ;
+ * hWnd control's parent handle
+ * id control's id
+ * enable TRUE to enable or FALSE to grayed out the control
+ */
+
+HWND CreateQCQPWindow(LPSTR, DWORD, int, int, int, int, HWND, HMENU, HANDLE, WPARAM) ;
+ /*
+ * call - CreateQCQPWindow (title, style, x, y, dx, dy, hWnd, id, hInst, message) ;
+ * title window's title
+ * style search for "definitions for user control styles"
+ * window's style in low word
+ * window's bitmap reference ID in high word
+ * x left position
+ * y top position
+ * dx width
+ * dy height
+ * hWnd parent's handle
+ * id control's id
+ * hInst parent's instance handle
+ * message message to send back to parent's wParam under WM_COMMAND
+ */
+
+/* definitions for user control styles */
+/* it is important that the following definitions must be in pair and the
+ * latter one must be an incremental of the first by one unit.
+ */
+#define QCQP_CS_SETRECT 1
+
+/* definitions for bitmap button */
+#define QCQP_CS_PUSHBUTTON 2
+#define QCQP_CS_LATCHBUTTON 3
+
+// definitionS for class byte window extra indexes
+#ifdef WIN32
+#define CBWNDEXTRA_STYLE 0 // index to button style
+#define CBWNDEXTRA_STATE 4 // index to button state
+#define CBWNDEXTRA_TEXTFORMAT 8 // index to button text format
+#define CBWNDEXTRA_BITMAP 12 // index to bitmap reference
+#define CBWNDEXTRA_MESSAGE 16 // index to message to send back to parent
+#define CBWNDEXTRA_FONT 16 // index to a font handle
+#define CBWNDEXTRA_QCQPCTRL 32
+#else
+#define CBWNDEXTRA_STYLE 0 // index to button style
+#define CBWNDEXTRA_STATE 2 // index to button state
+#define CBWNDEXTRA_TEXTFORMAT 4 // index to button text format
+#define CBWNDEXTRA_BITMAP 4 // index to bitmap reference
+#define CBWNDEXTRA_MESSAGE 6 // index to message to send back to parent
+#define CBWNDEXTRA_FONT 6 // index to a font handle
+#define CBWNDEXTRA_QCQPCTRL 14
+#endif
+
+// Bitmaps stored in window
+#ifdef WIN32
+#define CBWNDEXTRA_BMAP_NORMAL 20
+#define CBWNDEXTRA_BMAP_PUSHED 24
+#define CBWNDEXTRA_BMAP_GREYED 28
+#else
+#define CBWNDEXTRA_BMAP_NORMAL 8
+#define CBWNDEXTRA_BMAP_PUSHED 10
+#define CBWNDEXTRA_BMAP_GREYED 12
+#endif
+
+void PASCAL FreeRibbonBitmaps(
+ HWND hwndRibbon);
diff --git a/private/windbg/windbg/include/userdll.h b/private/windbg/windbg/include/userdll.h
new file mode 100644
index 000000000..636846eac
--- /dev/null
+++ b/private/windbg/windbg/include/userdll.h
@@ -0,0 +1,77 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ UserDll.h
+
+Abstract:
+
+ Header file for User Dll management
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 26-October-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+VOID
+ModListSetDefaultShe (
+ SHE SheDefault
+ );
+
+BOOL
+ModListGetDefaultShe (
+ CHAR *Name,
+ SHE *She
+ );
+
+VOID
+ModListSetSearchPath(
+ CHAR *Path
+ );
+
+VOID
+ModListAddSearchPath(
+ CHAR *Path
+ );
+
+DWORD
+ModListGetSearchPath(
+ CHAR *Buffer,
+ DWORD Size
+ );
+
+VOID
+ModListInit(
+ VOID
+ );
+
+VOID
+ModListAdd(
+ CHAR *Name,
+ SHE SheDefault
+ );
+
+VOID
+ModListModLoad(
+ CHAR *Name,
+ SHE SheCurrent
+ );
+
+VOID
+ModListModUnload(
+ CHAR *Name
+ );
+
+PVOID
+ModListGetNext(
+ PVOID Previous,
+ CHAR *Name,
+ SHE *SheDefault
+ );
diff --git a/private/windbg/windbg/include/util.h b/private/windbg/windbg/include/util.h
new file mode 100644
index 000000000..47a7f6c58
--- /dev/null
+++ b/private/windbg/windbg/include/util.h
@@ -0,0 +1,558 @@
+/****************************************************************************
+
+ PROTOTYPES DECLARATION FOR UTIL MODULE
+
+****************************************************************************/
+
+#include <commdlg.h>
+
+BOOL RegisterAndMapLocalHotKey(HWND, int, UINT, UINT);
+void UnregisterLocalHotKey(int);
+
+// Function building a pathname derived form the program running
+void MakePathNameFromProg(LPSTR extension, LPSTR pathName);
+void MakeFileNameFromProg(LPSTR extension, LPSTR fileName);
+
+//Checks to see if a file exists with the path/filename
+BOOL FileExist(LPSTR fileName);
+
+//Checks to see if a file exists with the path/filename
+//searching in the path if only filename and extension are provided
+BOOL FileExistCheckingPath(LPSTR fileName);
+
+//Check if file is Valid
+BOOL PASCAL ValidFilename(
+ LPSTR lpszName,
+ BOOL fWildOkay);
+
+// Opens a standard error Dialog Box
+int CDECL ErrorBox(int wErrorFormat, ...);
+
+// Opens a standard error Dialog Box (Parent is hwnd)
+int CDECL ErrorBox2(
+ HWND hwnd,
+ UINT type,
+ WORD wErrorFormat,
+ ...);
+
+// Opens an Internal error Dialog Box
+int CDECL InternalErrorBox(WORD wDescript);
+
+// Opens a standard information Dialog Box
+void CDECL InformationBox(int wInfoFormat, ...);
+
+// Opens a message box with the QCWin title
+int PASCAL MsgBox(HWND hwndParent, LPSTR szText, UINT wType);
+
+// Opens a message box with the QCWin title
+int CDECL VarMsgBox(
+ HWND hwndParent,
+ WORD wFormat,
+ UINT wType,
+ ...);
+
+// Opens a standard error Dialog Box and stop execution
+void FatalErrorBox(
+ WORD line1,
+ LPSTR line2);
+
+// Standard function to prompt an Assertion False
+void ShowAssert(LPSTR condition, UINT line, LPSTR file);
+
+// Loads and execute dialog box 'rcDlgNb' with 'dlgProc' function
+BOOL StartDialog(int rcDlgNb, DLGPROC dlgProc);
+
+// Invalidate the rectangle area of child 'ctlID' in 'hDlg' Dialog Box
+void InvDlgCtlIdRect(HWND hDlg, WPARAM ctlID);
+
+// Loads a resource string from resource file
+void LoadResourceString(
+ WORD wStrId,
+ LPSTR lpszStrBuffer);
+
+//Opens a standard question box containing combination
+//of : Yes, No, Cancel
+int CDECL QuestionBox(
+ WORD wMsgFormat,
+ UINT wType,
+ ...);
+
+//Opens a standard question box containing combination
+//of : Yes, No, Cancel
+int CDECL QuestionBox2(HWND hwnd, WORD wMsgFormat, UINT wType, ...);
+
+//Gets the text associated with the passed environment variable,
+//checking against any internally held environment strings first
+BOOL PASCAL GetQCQPEnvStr(LPSTR lpszVar, LPSTR lpszDestEnv, WORD wDestSize);
+
+// Scans a text string to a long value, checking limits
+// and allowing 0, 0x, and $ representations
+BOOL PASCAL fScanAnyLong(
+ LPSTR lpszSource,
+ WORD wLanguage,
+ long *plDest,
+ long lMin,
+ long lMax);
+
+//Gets sizes of the installed fonts
+void GetFontSizes(
+ HWND hWnd,
+ int currentFont);
+
+//Gets names of the installed fonts
+void LoadFonts(
+ HWND hWnd);
+
+//Opens Cpu, Watch or Locals Window under MDI
+int PASCAL OpenDebugWindow(int winType, LPWININFO lpWinInfo, int Preference);
+
+int GotoLine(int view, int lineNbr, BOOL fDebugger);
+BOOL QueryLineStatus(int doc, int lineNbr, UINT state);
+
+//Change the status of a given line
+void LineStatus(
+ int doc,
+ int lineNbr,
+ WORD state,
+ LINESTATUSACTION action,
+ BOOL positionInFirstView,
+ BOOL redraw);
+
+//Given a file Name, find corresponding doc
+typedef BOOL (* FINDDOC)(LPSTR fileName, int *doc, BOOL docOnly);
+BOOL FindDoc (LPSTR fileName, int *doc, BOOL docOnly);
+BOOL FindDoc1(LPSTR fileName, int *doc, BOOL docOnly);
+
+char *
+GetFileName(
+ char * szPath);
+
+//Clear all visual info of a doc (Tags or BreakPoints or Compile Errors)
+void ClearDocStatus(
+ int doc,
+ WORD state);
+
+//Clear all visual info of all docs (Tags or BreakPoints or Compile Errors)
+void ClearAllDocStatus(
+ WORD state);
+
+//Returns height (in lines) of passed list box
+WORD VisibleListboxLines(
+ HWND hListbox);
+
+//Alloc and lock MOVABLE global memory.
+LPSTR Xalloc(UINT bytes);
+
+//Reallocate memory previously allocated through Xalloc
+LPSTR Xrealloc(LPSTR curblock, UINT bytes);
+
+//Free global memory.
+BOOL Xfree(LPSTR lPtr);
+
+//Hash code for tokens
+void Convert(LPSTR tok);
+
+//Adjust Full Path name to fit in a specified len string
+void AdjustFullPathName(
+ PSTR fullPath,
+ PSTR adjustedPath,
+ int len);
+
+//Read ini file
+BOOL ReadIni(int hFile, LPSTR lpBuffer, int wBytes);
+
+//Write file and add to checksum
+BOOL WriteAndSum(int hFile, LPSTR lpBuffer, int wBytes);
+
+// Utility function
+BOOL FAR PASCAL IsMonoModeProc (void) ;
+
+// Load a DLL (qcqp.exe path tried first)
+HANDLE PASCAL LoadQCQPLibrary(LPSTR LibName, BOOL DoErrorBox);
+
+// WinExec a prog (qcqp.exe path tried first)
+WORD PASCAL WinQCQPExec(LPSTR CmdLine, int nCmdShow, BOOL DoErrorBox);
+
+//Try to lock a global memory handle
+BOOL FailGlobalLock(
+ HANDLE h,
+ LPSTR *p);
+
+//Retrieve in view the word at cursor, or the first line
+//of text if selection is active
+BOOL GetCurrentText(
+ int view,
+ BOOL *lookAround,
+ LPSTR pText,
+ int maxSize,
+ LPINT xLeft,
+ LPINT xRight);
+
+//Checks if a string contains a DOS wildcard : "*" or "?"
+BOOL PASCAL fIsWild(
+ PSTR psz);
+
+#define HUNDREDTHS_IN_A_DAY (((24UL*60)*60)*100)
+
+//Returns current time in 100ths of a second
+ULONG PASCAL TimeIn100ths(
+ void);
+
+//Returns current time + delay time in 100ths of a second
+ULONG PASCAL StopTimeIn100ths(
+ ULONG DelayIn100ths);
+
+// Process a message received by QCQP
+void PASCAL ProcessQCQPMessage(LPMSG lpMsg);
+
+//Initialize files filters for dialog boxes using commonfile DLL
+void InitFilterString(WORD id, LPSTR filter, int maxLen);
+
+//Appends a '\' to a string if none found
+void AppendBackslashIfNone(
+ LPSTR path);
+
+//Get rid of accelerator mark
+void RemoveMnemonic(
+ LPSTR sWith,
+ LPSTR sWithout);
+
+//Status bar operations
+void CDECL StatusText(int newTextId, WORD msgType, BOOL forceUpdate, ...);
+void PASCAL StatusMultiKey(BOOL newValue);
+void PASCAL StatusOvertype(BOOL newValue);
+void PASCAL StatusReadOnly(BOOL newValue);
+void PASCAL StatusNumLock(BOOL newValue);
+void PASCAL StatusCapsLock(BOOL newValue);
+void PASCAL StatusLineColumn(int newLine, int newColumn);
+void PASCAL StatusSrc(BOOL newValue);
+void PASCAL StatusPidTid(UINT ipid, UINT itid);
+
+//Check if keyboard hit is NUMLOCK, CAPSLOCK or INSERT
+LRESULT EXPORT KeyboardHook( int iCode, WPARAM wParam, LPARAM lParam );
+
+//Returns the handle of one of the debug windows
+HWND GetDebugWindowHandle(WORD type);
+
+/****************************************************************************/
+// Set this to 1 to include special code to allow automatic test
+// suites to run.
+#define TESTSUITES 1
+#ifdef DEBUGGING
+//Makes a printf style command for output on debug console
+
+//#define REMOVEAUXPRINTFS TRUE
+#define REMOVEAUXPRINTFS FALSE
+#if REMOVEAUXPRINTFS
+#define AuxPrintf(level, dummy) FALSE
+#else
+BOOL AuxPrintf(int iDebugLevel, LPSTR text, ...);
+#endif //REMOVEAUXPRINTFS
+
+//Swiss Made Chronograph
+void ShowElapsedTime(
+ void);
+void StartTimer(
+ void);
+
+void StopTimer(
+ void);
+
+//Opens a Dialog box with a title and accepting a printf style for text
+int InfoBox(
+ LPSTR text,
+ ...);
+
+PSTR GetWindebugTxt(long lDbg);
+
+#endif
+
+/****************************************************************************
+
+ MACROS:
+
+****************************************************************************/
+// Dbg have to be used for every assertion during Debugging time.
+// If false Dbg Opens a fatal error message Box and Stops program
+
+
+// First, a sanity check
+#ifdef Dbg
+#undef Dbg
+#endif
+
+#if DBG
+#ifdef WIN32
+#ifdef MIPS_C
+#define Dbg(condition) \
+{ \
+ if (!(condition)) { \
+ static char szFileName[] = __FILE__;\
+ static char szExp[] = "condition"; \
+ ShowAssert(szExp, __LINE__, szFileName); \
+ }\
+}
+#else // ! MIPS_C
+#define Dbg(condition) \
+ { \
+ if (!(condition)) \
+ { \
+ static char szFileName[] = __FILE__; \
+ static char szExp[] = #condition; \
+ ShowAssert(szExp, __LINE__, szFileName); \
+ } \
+ }
+#endif
+#else // !WIN32
+#define Dbg(condition) \
+ { \
+ if (!(condition)) \
+ { \
+ static char _based(_segname("SZASSERT")) szFileName[] = __FILE__; \
+ static char _based(_segname("SZASSERT")) szExp[] = #condition; \
+ ShowAssert(szExp,__LINE__,szFileName); \
+ } \
+ }
+#endif
+#else // !DBG
+#define Dbg(condition) condition
+#endif
+
+#ifdef NTBUG
+#define DbgX(condition) Dbg(condition)
+#else
+#define DbgX(condition) condition
+#endif
+
+#ifdef ALIGN
+#define AssertAligned(address) Assert((((long)address) & 3) == 0)
+#else
+#define AssertAligned(address)
+#endif
+
+
+// Assert are assertions that will stay in final Release.
+// If false Assert Opens a fatal error message Box and Stops program
+#ifdef WIN32
+#ifdef MIPS_C
+#define RAssert(condition) \
+{ \
+ if (!(condition)) { \
+ static char szFileName[] = __FILE__;\
+ static char szExp[[] = "condition"; \
+ ShowAssert(szExp, __LINE__, szFileName); \
+ } \
+}
+#else // MIPS_C
+#define RAssert(condition) \
+ { \
+ if (!(condition)) \
+ { \
+ static char szFileName[] = __FILE__; \
+ static char szExp[] = #condition; \
+ ShowAssert(szExp,__LINE__,szFileName); \
+ } \
+ }
+#endif
+#else // WIN32
+#define RAssert(condition) \
+ { \
+ if (!(condition)) \
+ { \
+ static char _based(_segname("SZASSERT")) szFileName[] = __FILE__; \
+ static char _based(_segname("SZASSERT")) szExp[] = #condition; \
+ ShowAssert(szExp,__LINE__,szFileName); \
+ } \
+ }
+#endif
+
+#if DBG
+#define DAssert(cnd) RAssert(cnd)
+#define Assert(cnd) RAssert(cnd)
+#else
+#define DAssert(cnd)
+#define Assert(cnd) RAssert(cnd)
+#endif
+
+
+// Bitwise Operations Macros
+
+// These work on integral operands...
+#define SET(i, mask) ((i) |= (mask))
+#define RESET(i, mask) ((i) &= ~(mask))
+#define TOGGLE(i, mask) ((i) ^= (mask))
+
+// These work on arrays of integral operands...
+// bit_idx is the bit number to set in array a so
+// SET_ARRAY(37, ucBuffer) does a SET(ucBuffer[4], 0x20), whereas
+// SET_ARRAY[37, lBuffer) does a SET(lBuffer[1], 0x20L)
+#define SHIFT_OPERAND(bit_idx, a) ((sizeof(*(a)) > sizeof(int) ? 1L : 1) << (bit_idx%(sizeof(*(a))*8)))
+#define SET_ARRAY(bit_idx, a) SET(a[bit_idx/(sizeof(*(a))*8)], SHIFT_OPERAND(bit_idx, a))
+#define RESET_ARRAY(bit_idx, a) RESET(a[bit_idx/(sizeof(*(a))*8)], SHIFT_OPERAND(bit_idx, a))
+#define TOGGLE_ARRAY(bit_idx, a) TOGGLE(a[bit_idx/(sizeof(*(a))*8)], SHIFT_OPERAND(bit_idx, a))
+#define TEST_ARRAY(bit_idx, a) (a[bit_idx/(sizeof(*(a))*8)] & SHIFT_OPERAND(bit_idx, a))
+
+//To test if a character belong to the C/Pascal Alphanumeric set
+#define CHARINALPHASET(c) (IsCharAlphaNumeric(c) || c == '_')
+#ifdef DBCS
+ #ifdef JAPAN_HANKAKU_KANA_AS_WORD
+ #define CHARINKANASET(c) ((BYTE)(c) >= 0xa6 && (BYTE)(c) <= (BYTE)0xdf)
+ #else // !JAPAN_HANKAKU_KANA_AS_WORD else
+ #define CHARINKANASET(c) (FALSE)
+ #endif // !JAPAN_HANKAKU_KANA_AS_WORD end
+
+#define CHARINWORDCHAR(c) (IsDBCSLeadByte(c) || CHARINALPHASET(c)) || CHARINKANASET(c)
+#endif // DBCS end
+
+void SetVerticalScrollBar(
+ int view,
+ BOOL propagate);
+
+BOOL FAR PASCAL QueryCloseAllDocs(
+ void);
+
+BOOL FAR PASCAL StartFileDlg(HWND hwnd, int titleId, int defExtId,
+ int helpId, int templateId, LPSTR fileName, DWORD *pFlags,
+ LPOFNHOOKPROC lpfnHook);
+
+//Start the Edit Project dialog box
+void PASCAL StartEditProjDlg(
+ HWND hParent);
+
+//Update status bar
+void UpdateStatus(
+ WORD action,
+ NPRECT pClientRect) ;
+
+//Update ribbon
+void UpdateRibbon(
+ WORD action,
+ NPRECT pClientRect);
+
+void AddWindowMenuItem(
+ int doc,
+ int view);
+
+void DeleteWindowMenuItem(
+ int view);
+
+void PASCAL OpenProject(
+ PSTR ProjectName,
+ HWND ParentWnd,
+ BOOL TryForWorkspace);
+
+void PASCAL EditProject(
+ HWND ParentWnd);
+
+void PASCAL CloseProject(
+ void);
+
+int FindWindowMenuId(
+ WORD type,
+ int viewLimit,
+ BOOL sendDocMenuId);
+
+BOOL DestroyView(
+ int view);
+
+#define ERC_COMPILE 0x0002
+#define ERC_BUILD 0x0004
+#define ERC_BREAKPT 0x0008
+#define ERC_QWATCH 0x0010
+#define ERC_TRACESTEP 0x0020
+#define ERC_ALL 0xFFFF
+
+BOOL IntOutOfRange(
+ PSTR text,
+ int far *val,
+ int min,
+ int max,
+ HWND hDlg,
+ int dlgItem,
+ int errMsg);
+
+BOOL LongOutOfRange(
+ PSTR text,
+ long far *val,
+ long min,
+ long max,
+ HWND hDlg,
+ int dlgItem,
+ int errMsg);
+
+int SetLanguage(int doc);
+
+BOOL GetWordAtXY(
+ int view,
+ int x,
+ int y,
+ BOOL selection,
+ BOOL *lookAround,
+ BOOL includeRightSpace,
+ LPSTR pWord,
+ int maxSize,
+ LPINT leftCol,
+ LPINT rightCol);
+
+void PASCAL EnsureScrollBars(
+ int view,
+ BOOL force);
+
+void PASCAL NewFontInView(
+ int view);
+
+void PASCAL EscapeAmpersands(
+ LPSTR AmpStr,
+ int MaxLen);
+
+void PASCAL UnescapeAmpersands(
+ LPSTR AmpStr,
+ int MaxLen);
+
+void PASCAL BuildTitleBar(LPSTR TitleBarStr, UINT MaxLen);
+
+void PASCAL UpdateTitleBar(
+ TITLEBARMODE Mode,
+ BOOL Repaint);
+
+void PASCAL DlgEnsureTitleBar(void);
+
+void PASCAL TimedUpdateTitleBar(TITLEBARMODE Mode, BOOL Repaint);
+
+void FAR PASCAL FileNotSaved(int doc);
+
+int FAR PASCAL ConvertPosX(int x);
+
+void FAR PASCAL FlushKeyboard(void);
+
+void PASCAL EnableRibbonControls(int Updates, BOOL LaunchingDebuggee);
+
+BOOL FindLineStatus(int view, BYTE target, BOOL forward, int *line);
+
+//ANSI/ASCII compatible isspace() test
+#define whitespace(c) (c == ' ' || c == '\t' || c == '\n' || c == '\r')
+
+BOOL SetDriveAndDir(PSTR st);
+VOID GetBaseName( LPSTR , LPSTR );
+LPSTR AllocateMultiString( DWORD );
+BOOLEAN DeallocateMultiString( LPSTR );
+BOOLEAN AddToMultiString( LPSTR *, DWORD *, LPSTR );
+LPSTR GetNextStringFromMultiString( LPSTR, DWORD, DWORD * );
+BOOL FindNameOn(LSZ, UINT, LSZ, LSZ);
+void Egg(void);
+VOID InvalidateAllWindows(VOID);
+
+#ifdef DBCS
+VOID GetDBCSCharWidth(HDC hDC, LPTEXTMETRIC ptm, LPVIEWREC lpv);
+VOID SetReplaceDBCSFlag(LPDOCREC lpd, BOOL bTwoRec);
+#endif // end of DBCS
+
+#ifdef FE_IME
+LRESULT ImeMoveConvertWin(HWND hwnd, INT x, INT y);
+LRESULT ImeSendVkey(HWND hwnd, WORD wVKey);
+BOOL ImeSetFont(HWND hwnd, HFONT hFont);
+BOOL ImeWINNLSEnableIME(HWND hwnd, BOOL bEnable);
+LONG ProccessIMEString(HWND hwnd, LPARAM lParam);
+BOOL ImeInit(void);
+BOOL ImeTerm(void);
+#endif // end of FE_IME
diff --git a/private/windbg/windbg/include/util2.h b/private/windbg/windbg/include/util2.h
new file mode 100644
index 000000000..99a838d77
--- /dev/null
+++ b/private/windbg/windbg/include/util2.h
@@ -0,0 +1,100 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+BOOL FAR PASCAL QueryCloseAllChildren(
+ void);
+
+
+BOOL FAR PASCAL QueryCloseChild(
+ HWND hwnd, BOOL b);
+
+int FAR PASCAL AddFile(
+ WORD mode,
+ WORD type,
+ LPSTR pName,
+ LPWININFO win,
+ HFONT font,
+ BOOL readOnly,
+ int dupView,
+ int Preference
+ );
+
+BOOL FAR PASCAL SaveFile(
+ /*HWND*/ int);
+
+BOOL FAR PASCAL SaveAsFile(
+ /*HWND*/ int);
+
+void FAR PASCAL WindowTitle(
+ int view,
+ int duplicateNbr);
+
+void AddToSearchPath(
+ LPSTR lpstrFile);
+
+int matchExt (char * pTargExt, char * pSrcList);
+
+void RefreshWindowsTitle(
+ int doc);
+
+BOOL FindLineStatus(
+ int view,
+ BYTE target,
+ BOOL forward,
+ int *line);
+
+//Start the Edit Project dialog box
+void PASCAL StartEditProjDlg(
+ HWND hParent);
+
+//Update status bar
+void UpdateStatus(WORD action, NPRECT pClientRect) ;
+
+//Update ribbon
+void UpdateRibbon(WORD action, NPRECT pClientRect);
+
+BOOL FindNext(
+ int startingLine,
+ int startingCol,
+ BOOL startFromSelection,
+ BOOL selectFoundText,
+ BOOL errorIfNotFound);
+
+void Find(
+ void);
+
+void Replace(
+ void);
+
+BOOL MoreFindToDo(
+ void);
+
+void PASCAL OpenProject(
+ PSTR ProjectName,
+ HWND ParentWnd,
+ BOOL TryForWorkspace);
+
+void PASCAL EditProject(
+ HWND ParentWnd);
+
+void PASCAL CloseProject(
+ void);
+
+BOOL DestroyView(
+ int view);
+
+void ResizeEditWindow(
+ int view,
+ int width,
+ int height,
+ int winNbLines,
+ BOOL forceMove);
+
+#define ERC_FONTSPTS 0x0001
+#define ERC_COMPILE 0x0002
+#define ERC_BUILD 0x0004
+#define ERC_BREAKPT 0x0008
+#define ERC_QWATCH 0x0010
+#define ERC_TRACESTEP 0x0020
+#define ERC_ALL 0xFFFF
+#define ERC_ALLBUTFONTSPTS (ERC_ALL & ~ERC_FONTSPTS)
+void PASCAL EnableRibbonControls(int Updates, BOOL LaunchingDebuggee);
diff --git a/private/windbg/windbg/include/vapi.h b/private/windbg/windbg/include/vapi.h
new file mode 100644
index 000000000..8735762c8
--- /dev/null
+++ b/private/windbg/windbg/include/vapi.h
@@ -0,0 +1,50 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+/*** gda_t -- global data area
+ * FIELDS
+ * gda_batflg batch mode compile
+ * gda_wExit VAP exit status
+ * gda_wRet VAP API extra return value
+ * gda_lRet VAP API extra return value
+ * gda_syserr analog to errno for VAPI, etc.
+ * gda_fdErr VIO fd for error 'file'
+ * gda_lpszC1Path pointer to C1.ERR path spec
+ * gda_lpbInclude far pointer to INCLUDE path
+ * gda_lpQcini far pointer to QCINI struct
+ * gda_fAsFeed Feedback from the assembler (flags)
+ *
+ * BUGS
+ * M00WARN gda_s is in vapi.h and vapi.inc.
+ */
+struct gda_s {
+ uint gda_batflg:1; /* batch mode compile */
+ uint gda_CcO1:1; /* -O1 */
+ uint gda_fInVap:1; /* Vap currently active? */
+ uint gda_flg0:13; /* unused */
+ int gda_wExit; /* VAP exit status */
+ ushort gda_wRet; /* VAP API extra return value */
+ ulong gda_lRet; /* VAP API extra return value */
+ int gda_syserr; /* analog to errno */
+ int gda_fdErr; /* error file descriptor */
+ char far * gda_lpszC1Path; /* pointer to C1.ERR path spec */
+ char far * gda_lpbInclude; /* far pointer to INCLUDE path */
+ char far * gda_lpQcini; /* far pointer to QCINI struct */
+ int gda_fsAsFeed; /* Flag feedback from the assembler */
+};
+
+typedef struct gda_s gda_t;
+typedef struct gda_s FAR * gdap_t;
+
+extern gdap_t FAR PASCAL GdaGet( void );
+
+/* VAP (stack-switching, etc.) entry points */
+extern gdap_t FAR PASCAL VapGdaGet( void );
+
+/*
+** These flags are used in the gda_fAsfeed field
+*/
+
+#define ASF_STARTUP 0x1 /* .Startup is present */
+#define ASF_EXIT 0x2 /* .exit is present */
+#define ASF_TINY 0x4 /* .model tiny is present */
+#define ASF_CHECKERRORS 0x8 /* Check for related errors */
diff --git a/private/windbg/windbg/include/vib.h b/private/windbg/windbg/include/vib.h
new file mode 100644
index 000000000..5212f2495
--- /dev/null
+++ b/private/windbg/windbg/include/vib.h
@@ -0,0 +1,189 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+#ifndef _LCLWN_H
+#define _LCLWN_H 1
+
+/************************ Structures And Types *****************************/
+
+typedef enum {
+ vibUndefined = 0, // We don't know what this vib is
+ vibSymbol = 1, // vib is a local
+ vibWatch = 2, // vib is a watch
+ vibChild = 3, // vib is the root of a tree
+ vibGeneric = 4, // vib is a array/structure entry
+ vibPointer = 5, // vib is a pointer
+ vibType = 6 // vib is a type
+} EVIB;
+
+typedef enum {
+ OK = 0,
+ INITLOCSTATUS = 100,
+ INITWATCHSTATUS = 200,
+ CODEVIEWMSG = 1,
+ OUTOFMEMORY = 10,
+ UNABLETOEXPAND = 20,
+ UNABLETOADDWATCH = 30,
+ UNABLETODELETEWATCH = 40,
+ WATCHNOTOPEN = 50,
+ UNABLETOOPEN = 60,
+ NONEDITFIELD = 70,
+ WATCHSYNTAXERROR = 80
+} LTS;
+
+#define OK 0
+#define INITLOCSTATUS ((LTS) 100)
+#define INITWATCHSTATUS ((LTS) 200)
+#define CODEVIEWMSG ((LTS) 1)
+#define OUTOFMEMORY ((LTS) 10)
+#define UNABLETOEXPAND ((LTS) 20)
+#define UNABLETOADDWATCH ((LTS) 30)
+#define UNABLETODELETEWATCH ((LTS) 40)
+#define WATCHNOTOPEN ((LTS) 50)
+#define UNABLETOOPEN ((LTS) 60)
+#define NONEDITFIELD ((LTS) 70)
+#define WATCHSYNTAXERROR ((LTS) 80)
+
+#define EXPAND1ST 0x01;
+
+/*
+**
+*/
+
+#define CLREISACT 0xF0
+#define CLREISVAL 0x0F
+
+
+typedef UCHAR OC; // offset of a character within a line
+typedef ULONG VPI; // vib packet index
+
+typedef struct vib * PTRVIB; // a pointer to a vib
+
+/*
+**
+*/
+
+typedef struct woj {
+ int evalLang; // language of the expression, not used yet
+ USHORT iFormSpec; // offset in szExpStr of the format specifer
+ USHORT ErrNbr;
+ USHORT cbLen;
+ WORD hprc;
+ char szExpStr[1];
+} WOJ;
+
+typedef WOJ * PTRWOJ;
+
+/*
+** CIF - Children information block
+*/
+
+typedef struct cif {
+ PTRVIB pvibChild; // pointer to its children
+ HTM hTMBd; // the TM to be expanded.
+ } CIF; // an expansion info packet
+
+typedef CIF * PTRCIF; // a pointer to a cif
+
+/*
+** VIBFLAGS
+*/
+
+typedef struct vibflags {
+ WORD NoData :1; // Vib contains no data
+ WORD NoBind :1; // Vib not bound (Out of Context)
+ WORD FuncEval :1; // Vib uses Function Evaluation
+ WORD ExpandMe :1; // Needs to be expand at next paint
+ WORD DlgAdd :1; // Dialog Box has added but not done
+ WORD DlgDel :1; // Dialog Box has deleted but not done
+ WORD DlgOrig :1; // Dialog Box tracking but not done
+} VFLAGS;
+
+/*
+** VIBTEXT
+*/
+
+typedef struct vibtext {
+ PSZ pszValueC; // Value (Current Right Pane)
+ PSZ pszValueP; // Value (Current Left Pane)
+ PSZ pszFormat; // Format Override
+ HTM htm;
+ BOOL fChanged; // TRUE if changed on prev step
+} VTEXT;
+
+typedef VTEXT * PVTEXT;
+
+/*
+** Variable Information Block (VIB)
+** This structure describes the information about each
+** expression in the watch window. There is one VIB for every
+** filled line in the window.
+*/
+
+typedef struct vib {
+ short cln; // nbr lines taken by this an all children
+ PTRVIB pvibParent; // pointer to the parent
+ PTRCIF pcif; // pointer to its child info structure
+ PTRVIB pvibSib; // pointer to the next siblings
+ EVIB vibPtr;
+ UCHAR level; // The nesting level
+ VPI vibIndex; // The index into the parents array
+ HPROC hprocCache; // hproc bound under
+ HBLK hblkCache; // hblk bound under
+ HTM hTMBd; // pointer to the bound TM
+ HSYM hSym; // The handle the symbols table
+ VFLAGS flags; // Flags word
+ PTRWOJ pwoj; // Name Information
+
+ PVTEXT pvtext; // Text Descriptions
+ ULONG cText; // Count of Text Descriptions
+
+} VIB; // variable info block
+
+/*
+** VIT
+*/
+
+typedef struct vit * PTRVIT; // pointer to a vit
+
+typedef struct vit {
+ short cln; // Total number of lines in tree
+ PTRVIT * pvitParent; // pointer to the parent, allways NULL
+ PTRVIB pvibChild; // pointer to its children
+ CXF cxf; // the context of the vit
+ } VIT; // variable info block top
+
+
+/**************************** Prototypes *********************************/
+
+LPVOID AllocMem(int cb);
+LPVOID DuplicateMem(PSTR pOld);
+VOID FreeMem(LPVOID lpv);
+
+PTRVIB PASCAL PvibAlloc(PTRVIB, PTRVIB);
+VOID PASCAL FTAgeVibValues(PTRVIB);
+void PASCAL FTclnUpdateParent( PTRVIB pvibParent, int dcln );
+PTRVIB PASCAL FTvibGetAtLine( PTRVIT pvit, ULONG oln );
+VOID PASCAL FTEnsureTextExists( PTRVIB pVib );
+LTS PASCAL FTExpand ( PTRVIT pvit, ULONG oln );
+VOID PASCAL FTExpandOne( PTRVIB pVib);
+VOID PASCAL FTFreeAllSib( PTRVIB pvib );
+BOOL PASCAL FTVerify(PCXF pcxf, PTRVIB pvib);
+int PASCAL FTMakeWatchEntry(void *, void *, char *);
+LTS PASCAL FTError(LTS);
+PSTR PASCAL FTGetVibNames(PTRVIT, BOOL, PLONG);
+PSTR PASCAL FTGetWatchList(PTRVIT);
+PSTR PASCAL FTGetVibResults(PTRVIT, BOOL, PLONG);
+PSTR PASCAL FTGetVibNameString(PTRVIB pVib);
+PSTR PASCAL FTGetVibResultString(PTRVIT pVit, PTRVIB pVib);
+PSTR PASCAL FTGetVibTypeString(PTRVIB pVib);
+BOOL PASCAL FTGetPanelStatus( PTRVIB pVib, UINT PanelNumber);
+PSTR PASCAL FTGetPanelString( PTRVIT pVit, PTRVIB pVib, UINT PanelNumber);
+VOID PASCAL FTSetWatchList(PTRVIT, PSTR);
+PTRVIB PASCAL FTvibGet ( PTRVIB, PTRVIB );
+PTRVIB PASCAL FTvibInit( PTRVIB, PTRVIB );
+PTRVIB PASCAL FTvibGetAtLine( PTRVIT pvit, ULONG oln );
+BOOL PASCAL FTVerifyNew( PTRVIT pvit, ULONG oln);
+#endif /* _LCLWN_H */
+
+
diff --git a/private/windbg/windbg/include/watchwin.h b/private/windbg/windbg/include/watchwin.h
new file mode 100644
index 000000000..f821ac6db
--- /dev/null
+++ b/private/windbg/windbg/include/watchwin.h
@@ -0,0 +1,18 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+---*/
+
+
+// Watch Tree access routines:
+
+PTRVIB AddCVWatch(PTRVIT pvit, PSTR szExpStr);
+BOOL ReplaceCVWatch( PTRVIT pvit, PTRVIB pvib, PSTR newstr);
+LTS DeleteCVWatch( PTRVIT pvit, PTRVIB pvib);
+VOID UpdateCVWatchs(VOID);
+BOOL AcceptWatchUpdate(PTRVIT pVit,PPANE p, WPARAM wParam);
+
+LONG FAR PASCAL LOADDS WatchEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+HWND PASCAL GetWatchHWND(VOID);
+PTRVIT PASCAL GetWatchVit(VOID);
+PTRVIT PASCAL InitWatchVit(void);
+
+
diff --git a/private/windbg/windbg/include/windbg.h b/private/windbg/windbg/include/windbg.h
new file mode 100644
index 000000000..f6cc3c5e0
--- /dev/null
+++ b/private/windbg/windbg/include/windbg.h
@@ -0,0 +1,1272 @@
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Windbg.h
+
+Abstract:
+
+ Main header file for the Windbg debugger.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#if ! defined( _WINDBG_ )
+#define _WINDBG_
+
+#include <windef.h>
+#include "od.h"
+
+#define NOGDICAPMASKS
+#define NOMETAFILE
+#define NOSOUND
+#define NOCOMM
+#define NOKANJI
+#define NOMINMAX
+
+#ifndef WILLOW7
+#define EXPORT LOADDS
+#else
+#ifndef WIN32
+#define EXPORT _export
+#else
+#define EXPORT
+#endif
+#endif
+
+#ifdef WIN32
+#define __FAR
+#define __FASTCALL
+#define _HUGE_
+
+#define _fmemmove memmove
+#define _fstrcmp strcmp
+#define _fstrlen strlen
+#define _fstrncpy strncpy
+#define _fmemset memset
+#define _fstrcpy strcpy
+#define _fstrchr strchr
+#define _fstricmp stricmp
+#define _fstrdup strdup
+
+#define _fmalloc malloc
+#define _ffree free
+#define _frealloc realloc
+
+typedef unsigned short _segment;
+
+#define GetWindowHandle(hWnd, nIndex) (HANDLE) GetWindowLong(hWnd, nIndex)
+#define GetClassHandle(hWnd, nIndex) (HANDLE) GetClassLong(hWnd, nIndex)
+#define SetWindowHandle(hWnd, nIndex, h) SetWindowLong(hWnd, nIndex, h)
+#define MoveToX(a, b, c, d) MoveToEx(a, b, c, d)
+#define SetBrushOrgX(a, b, c, d) SetBrushOrgEx(a, b, c, d)
+
+typedef short * LPSHORT;
+
+#else
+
+#define __FAR far
+#define __FASTCALL
+
+#define GetWindowHandle(hWnd, nIndex) (HANDLE) GetWindowWord(hWnd, nIndex)
+#define GetClassHandle(hWnd, nIndex) (HANDLE) GetClassWord(hWnd, nIndex)
+#define SetWindowHandle(hWnd, nIndex, h) SetWindowWord(hWnd, nIndex, h)
+#define MoveToX(a, b, c, d) MoveTo(a, b, c)
+#define SetBrushOrgX(a, b, c, d) SetBrushOrg(a, b, c)
+
+typedef unsigned short USHORT;
+
+typedef int far * LPSHORT;
+#define WNDPROC FARPROC
+
+#endif
+
+
+//#ifdef WIN32
+//#ifndef NTBUG
+//BOOL IsCharAlphaNumeric(TCHAR cChar);
+//LPTSTR AnsiLower(LPTSTR);
+//LPTSTR AnsiUpper(LPTSTR);
+//#endif
+//#endif
+
+#ifndef _WINDOWS_
+typedef BOOL (FAR PASCAL EXPORT * DLGPROC)(HWND, UINT, WPARAM, LPARAM);
+#endif
+#define Unused(a) (void) a;
+
+//Compilation options
+#define DEBUGGING // Shields all system with assertions
+#undef BRK_IF_ERROR // Issue a BreakPoint after an ErrorBox
+#undef BRK_IF_FATAL_ERROR // Issue a BreakPoint after a FatalErrorBox
+
+/****************************************************************************
+
+ GLOBAL LIMITS CONSTANTS:
+
+****************************************************************************/
+#define MAX_MSG_TXT 4096 //Max text width in message boxes
+#define NB_COLORS 22 //Number of color entries in Palette
+#define NB_COLORED_ITEMS 22 //Number of colorable items
+#define MAX_CMDLINE_TXT 8192 //Max size for command line
+#define MAX_VAR_MSG_TXT 8192 //Max size of a message built at run-time
+#define MAX_ARG_TXT 8192 //Max size for arguments line
+#define ENVSTR_SIZE 1024 //Max size for environment string
+#define MAX_DOCUMENTS 64 //Max number of documents
+#define MAX_VIEWS 64 //Max number of views
+#ifndef NTBUG
+#define DISK_BLOCK_SIZE 2048
+#else
+#define DISK_BLOCK_SIZE 4096 //Cluster size for disks I/O on text files
+#endif
+#define MAX_PICK_LIST 16 //Max of 'old' strings kept in replace and find
+#define MAXFILENAMELEN 260 //Max # of chars in a filename
+#define MAXFILENAMEPREFIX 256 //Prefix part of a filename
+#define DOS_EXT_SIZE 256 //Maximum size of Filename extension
+#define MAX_FILE_TYPE_DESC 25 //Max # of chars in a file type description
+#define MAX_GOTOLINE_KEPT 16 //Max # of lines # kept for View.line
+#define MAX_CLIPBOARD_SIZE 65536*8 //Clipboard limit (512k)
+#define DEFAULT_TAB 8 //Default tabulation size
+#define MAX_TAB_WIDTH 99 //Maximum tab size
+#define TMP_STRING_SIZE 8192 //All purpose strings
+#define MAX_FILTER_LENGTH 256 //Max file names filters length
+#define MAX_STATUS_TXT 60 //Max text size on status line
+#define MAX_EXPRESS_SIZE 1024 //Max text size of an expression (watch etc)
+#define UNDOREDO_DEF_SIZE 4096L //Size of undo/redo buffers
+#define UNDOREDO_MAX_SIZE 65535L //Maximum size of undo/redo buffers
+#define MAX_ADDITIONAL_DLLS 255 //Additional DLLs - Options.Run/Debug
+#define BHD 10 //Size of block header (see BLOCKDEF)
+#define BLOCK_SIZE (8192 - BHD) //Size of block
+#define LHD 4 //Size of line Header (see LINEREC)
+#define MAX_LINE_SIZE 256 //Max inside length of editor line
+#define MAX_USER_LINE (MAX_LINE_SIZE - LHD - 1) //Max length of user line
+#define MAX_LINE_NUMBER 65535 //Maximum line #
+#define MAX_CHARS_IN_FONT 256 //Do you really need a comment ??
+#define TITLEBARTIMERID 200 // ditto
+#define TITLEBARTIMER 250 // Milliseconds
+#define MEMBUF_SIZE 4096 //for memory operations: fi, c, m, s
+#define IDM_FIRSTCHILD 30000 //for mdi default menu handling
+
+
+/****************************************************************************
+
+ GLOBAL TYPES AND DEFINES:
+
+****************************************************************************/
+#ifdef i386
+typedef unsigned long ULONG;
+typedef ULONG *PULONG;
+#endif
+
+//Version conventions
+#define MAX_VERSION_TXT 16 //Version string len (0 included)
+#define MAX_INTERNALVERSION_TXT 10 //Internal Version text len (no 0 included)
+#define MAX_PRODUCTVERSION_TXT 4 //Product Version text len (no 0 included)
+
+#ifndef _WINDOWS_
+//New help engine actions (they will be in windows.h)
+#define HELP_PARTIALKEY 0x105
+#define HELP_FORCEFILE 0x009
+#define HELP_CONTENTS 0x003
+#endif
+
+//Colors : Standard colors for WinDBG
+#define BLACK 0
+#define WHITE 1
+#define RED 2
+#define GREEN 3
+#define BLUE 4
+#define YELLOW 5
+#define MAGENTA 6
+#define CYAN 7
+#define GRAY 8
+#define LIGHTGRAY 9
+#define DARKRED 10
+#define DARKGREEN 11
+#define DARKBLUE 12
+#define LIGHTBROWN 13
+#define DARKMAGENTA 14
+#define DARKCYAN 15
+
+//Colors : Build limits for loops (Update those when changing low and hi values)
+#define COLOR_FIRST BLACK
+#define COLOR_LAST DARKCYAN
+
+//Colors : Array to store items colors
+typedef BYTE ITEMSCOLORS[NB_COLORED_ITEMS];
+typedef ITEMSCOLORS near *NPITEMSCOLORS;
+typedef ITEMSCOLORS far *LPITEMSCOLORS;
+
+//Undo/Redo : Type of action for record
+#define NEXT_HAS_NO_STOP 2
+#define HAS_NO_STOP 1
+#define HAS_STOP 0
+
+//Undo/Redo : Type of Action
+#define INSERTSTREAM 0 // |
+#define INSERTCHAR 1 // |
+#define DELETESTREAM 2 // | bits 0,2
+#define DELETECHAR 3 // |
+#define REPLACECHAR 4 // |
+#define STOPMARK 16 // bit 4
+#define USERMARK 32 // bit 5
+#define CANCELREC 64 // bit 6 CANCELREC should never be on bit 0
+#define ACTIONMASK 7 //To retrieve action
+#ifdef DBCS
+#define REPLACEDBCS 0x08
+#endif
+
+//Undo/Redo : To store Deletsream's col2 and line2
+typedef struct {
+ int line;
+ BYTE col;
+} U_COORD;
+
+//Undo/Redo : To store InsertStream's len and chars
+typedef struct {
+ WORD len; //Actual len (full len)
+ char chars[];
+} STREAM;
+
+//Undo/redo : Variant record
+typedef union {
+ U_COORD c;
+ char ch;
+ STREAM s;
+} X;
+
+//Undo/Redo : Structure of record definition
+typedef struct {
+ WORD prevLen; //MUST BE FIRST FIELD !(Previous rec length (full len))
+ BYTE action; //Type of logical editing action
+ BYTE col;
+ int line;
+ X x; //Variant part
+} STREAMREC;
+typedef STREAMREC near *NPSTREAMREC;
+typedef STREAMREC far *LPSTREAMREC;
+
+//Undo/Redo : Size of variant components
+#define HDR_INSERTSTREAM_SIZE (sizeof(STREAMREC) - sizeof(X) + sizeof(STREAM))
+#define HDR_DELETESTREAM_SIZE (sizeof(STREAMREC) - sizeof(X) + sizeof(U_COORD))
+#define HDR_DELETECHAR_SIZE (sizeof(STREAMREC) - sizeof(X))
+#define HDR_INSERTCHAR_SIZE (sizeof(STREAMREC) - sizeof(X) + sizeof(char))
+
+//Undo/Redo : States of engine
+// - REC_STOPPED no more recording/playing
+// - REC_HADOVERFLOW when buffer went full during an operation
+// - REC_UNDO normal mode where inverse of edit action goes in Undo buffer
+// - REC_REDO during undo, inverse of Undo edit actions will be saved in
+// Redo buffer
+// - REC_CANNOTUNDO when undo buffer is empty
+#define REC_STOPPED 0
+#define REC_HADOVERFLOW 1
+#define REC_UNDO 2
+#define REC_REDO 3
+#define REC_CANNOTUNDO -32767
+
+//Undo/redo : Information in a document
+typedef struct {
+ HANDLE h; //Handle to editor undos/redos
+ long bufferSize; //In bytes
+ long offset; //Current undo/redo rec in buffer
+ LPSTREAMREC pRec; //Pointer to current undo/redo recorded
+} UNDOREDOREC;
+typedef UNDOREDOREC near *NPUNDOREDOREC;
+typedef UNDOREDOREC far *LPUNDOREDOREC;
+
+/*
+** Messages : User messages (See DEBUGGER.H for the other)
+*/
+
+
+#define WU_UPDATE (WM_USER + 0)
+#define WU_CLEAR (WM_USER + 1)
+#define WU_RELOADFILE (WM_USER + 2)
+#define WU_SETWATCH (WM_USER + 3)
+#define WU_EXPANDWATCH (WM_USER + 4)
+#define WU_INFO (WM_USER + 5)
+#define WU_INITDEBUGWIN (WM_USER + 7)
+#define WU_SYNCALL (WM_USER + 8)
+#define WU_DBG_LOADEM (WM_USER + 10)
+#define WU_DBG_UNLOADEM (WM_USER + 11)
+#define WU_AUTORUN (WM_USER + 12)
+#define WU_DBG_LOADEE (WM_USER + 13)
+#define WU_DBG_UNLOADEE (WM_USER + 14)
+#define WU_CLR_FORECHANGE (WM_USER + 15) //next two for windows that need to
+#define WU_CLR_BACKCHANGE (WM_USER + 16) //know about color changes
+#define WU_OPTIONS (WM_USER + 17)
+#define WU_RESAVEFILE (WM_USER + 18)
+#define WU_INVALIDATE (WM_USER + 19)
+#define WU_LOG_REMOTE_MSG (WM_USER + 20)
+#define WU_LOG_REMOTE_CMD (WM_USER + 21)
+
+
+
+// States for autorun engine
+typedef enum _AUTORUN {
+ arNone = 0,
+ arCmdline,
+ arSource,
+ arQuit
+} AUTORUN;
+
+
+//Environment : Structure definition
+typedef struct {
+ int tabStops;
+ BOOL keepTabs;
+ BOOL vertScrollBars;
+ BOOL horizScrollBars;
+ long undoRedoSize; //In bytes
+ BOOL SrchPath;
+} ENVIRONPARAMS;
+typedef ENVIRONPARAMS near *NPENVIRONPARAMS;
+typedef ENVIRONPARAMS far *LPENVIRONPARAMS;
+
+//
+// kernel debugger options
+//
+typedef struct _KDPARAMS {
+ BOOL fInitialBp;
+ BOOL fUseModem;
+ BOOL fGoExit;
+ BOOL fUseCrashDump;
+ DWORD dwBaudRate;
+ DWORD dwPort;
+ DWORD dwCache;
+ DWORD dwPlatform;
+ CHAR szCrashDump[MAX_PATH+1];
+} KDPARAMS, *PKDPARAMS;
+
+//Run/Debug : Structure definition
+typedef struct {
+ char commandLine[MAX_CMDLINE_TXT];
+ BYTE debugMode;
+ BOOL fDebugChildren;
+ BOOL fAttachGo;
+ BOOL fChildGo;
+ BOOL fGoOnThreadTerm;
+ BOOL fNotifyThreadTerm; // FALSE implies GoOnThreadTerm == TRUE
+ BOOL fNotifyThreadCreate;
+ BOOL fCommandRepeat;
+ BOOL fInheritHandles;
+ BOOL fEPIsFirstStep;
+ BOOL fKernelDebugger;
+ BOOL fWowVdm;
+ BOOL fDisconnectOnExit;
+ BOOL fAlternateSS;
+ BOOL fIgnoreAll;
+ BOOL fVerbose;
+ BOOL fShortContext;
+ BOOL fMasmEval;
+ BOOL fShBackground;
+ BOOL fNoVersion;
+ BOOL fUserCrashDump;
+ BYTE RegModeExt : 1;
+ BYTE RegModeMMU : 1;
+ BYTE ShowSegVal : 1;
+ BYTE LfOptAppend : 1;
+ BYTE LfOptAuto : 1;
+ BYTE RegUnused : 3;
+ DOP DisAsmOpts;
+ KDPARAMS KdParams;
+ char szLogFileName[MAX_PATH];
+ char szRemotePipe[MAX_PATH];
+ char szTitle[MAX_PATH];
+ CHAR szUserCrashDump[MAX_PATH+1];
+} RUNDEBUGPARAMS;
+typedef RUNDEBUGPARAMS near *NPRUNDEBUGPARAMS;
+typedef RUNDEBUGPARAMS far *LPRUNDEBUGPARAMS;
+
+//Status Bar : Actions
+#define STATUS_SIZE 1
+#define STATUS_HIDE 2
+#define STATUS_UNHIDE 3
+
+//Status Bar : Display Text type
+#define STATUS_INFOTEXT 0
+#define STATUS_MENUTEXT 1
+#define STATUS_ERRORTEXT 2
+
+
+//Status Bar : Size of strings components
+#define STATUS_MULTIKEY_SIZE 2
+#define STATUS_OVERTYPE_SIZE 3
+#define STATUS_READONLY_SIZE 4
+#define STATUS_CAPSLOCK_SIZE 4
+#define STATUS_NUMLOCK_SIZE 3
+#define STATUS_LINE_SIZE 5
+#define STATUS_COLUMN_SIZE 3
+#define STATUS_SRCMODE_SIZE 3
+#define STATUS_CURPID_SIZE 3
+#define STATUS_CURTID_SIZE 3
+
+//Status Bar : Pens and Brushes colors
+#define GRAYLIGHT 0x00C0C0C0
+#define GRAYDARK 0x00808080
+#define WHITEBKGD 0x00FFFFFF
+
+//Status Bar : Structure definition
+typedef struct {
+ HWND hwndStatus;
+ WNDPROC lpfnOldStatusTextWndProc;
+ BOOL errormsg; // status text is an
+ // error message
+ BOOL hidden; // Hidden or Visible state
+ RECT txtR;
+
+ BOOL fSrcMode; // Source Mode flag
+ RECT rctlSrcMode;
+ char rgchSrcMode[STATUS_SRCMODE_SIZE + 1]; // Source Mode string
+ char rgchSrcMode2[STATUS_SRCMODE_SIZE + 1]; // Source Mode string
+
+ int iCurPid; // Current Pid index
+ RECT rctlCurPid;
+ char rgchCurPid[STATUS_CURPID_SIZE + 1]; // Current Pid String
+
+ int iCurTid; // Current Tid index
+ RECT rctlCurTid;
+ char rgchCurTid[STATUS_CURTID_SIZE + 1]; // Current Tid String
+
+ BOOL multiKey; // MultiKey value
+ RECT multiKeyR;
+ char multiKeyS[STATUS_MULTIKEY_SIZE + 1]; // MultiKey string
+
+ BOOL overtype; // Overtype status
+ RECT overtypeR;
+ char overtypeS[STATUS_OVERTYPE_SIZE + 1]; // Overtype string
+
+ BOOL readOnly; // ReadOnly status
+ RECT readOnlyR;
+ char readOnlyS[STATUS_READONLY_SIZE + 1]; // ReadOnly string
+
+ BOOL capsLock; // CapsLock status
+ RECT capsLockR;
+ char capsLockS[STATUS_CAPSLOCK_SIZE + 1]; // CapsLock string
+
+ BOOL numLock; // NumLock status
+ RECT numLockR;
+ char numLockS[STATUS_NUMLOCK_SIZE + 1]; // NumLock string
+
+ int line; // Current line
+ // Not displayed when
+ // value is 0
+ RECT lineR;
+ char lineS[STATUS_LINE_SIZE + 1]; // Line string
+
+ int column; // Current column
+ // Not displayed when
+ // value is 0
+ RECT columnR;
+ char columnS[STATUS_COLUMN_SIZE + 1]; // Column string
+
+ HFONT font; // Handle to font used in status bar
+ int lastTxt; // Last text ressource # loaded
+ WORD height; // Height of font + some extra
+ WORD charWidth; // Average char width for font
+} STATUS;
+typedef STATUS NEAR *NPSTATUS;
+typedef STATUS FAR *LPSTATUS;
+
+//Ribbon : Actions
+#define RIBBON_SIZE 1
+#define RIBBON_HIDE 2
+#define RIBBON_UNHIDE 3
+
+//Ribbon : Definitions for button's states
+#define STATE_NORMAL 0
+#define STATE_PUSHED 1
+#define STATE_GRAYED 2
+#define STATE_ON 3
+
+//Ribbon : Private messages that can be sent to the ribbon window
+#define WU_RESTOREFOCUS WM_USER+1
+ //Internal to ribbon.c
+ //wParam == ribbon control that sent message
+ //LOWORD(lParam) == OK/Cancel for the control
+#define WU_ENABLERIBBONCONTROL WM_USER+4
+#define WU_DISABLERIBBONCONTROL WM_USER+5
+ //Sent by the environment to enable/disable controls in the ribbon
+ //wParam == ID of control to enable/disable
+#define WU_ESCAPEFROMRIBBON WM_USER+6
+ //Sent by environment to cancel focus from ribbon if its there
+ //wParam == handle to window to escape the focus to (NULL if nowhere)
+
+
+//Ribbon : Structure definition
+typedef struct {
+ HWND hwndRibbon; //Handle to main ribbon window
+ HWND hwndTraceButton; //Handle to "trace into" button
+ HWND hwndStepButton; //Handle to "step over" button
+ HWND hwndBreakButton; //Handle to "set break point" button
+ HWND hwndGoButton; // Handle to "Go" button
+ HWND hwndHaltButton; // Handle to "Halt" button
+ HWND hwndQWatchButton; //Handle to "Quick Watch" button
+ HWND hwndSModeButton; //Handle to "Src Mode" button
+ HWND hwndAModeButton; //Handle to "Asm Mode" button
+ HWND hwndFmtButton; //Handle to "Format" button
+ RECT ribrect; //Rectangle that encompasses the ribbon
+ WORD height; //Ribrect.bottom-ribrect.top+1
+ int hidden; //Ribbon is hidden? (disabled)
+} RIBBON;
+typedef RIBBON near *NPRIBBON;
+typedef RIBBON far *LPRIBBON;
+
+//Workspace : Basic window information
+typedef struct {
+ RECT coord;
+ long style;
+} WININFO;
+typedef WININFO near *NPWININFO;
+typedef WININFO far *LPWININFO;
+
+//Editor & Project: Type of file kept
+#define EDITOR_FILE 0
+#define PROJECT_FILE 1
+
+//Editor : Horizontal scroll ratio (1/5 of the window)
+#define SCROLL_RATIO 5
+
+//Editor : Ascii ctrl chars
+#define CTRL_A 1
+#define CTRL_C 3
+#define CTRL_D 4
+#define CTRL_E 5
+#define CTRL_F 6
+#define CTRL_G 7
+#define CTRL_H 8
+#define CTRL_J 10
+#define CTRL_M 13
+#define CTRL_N 14
+#define CTRL_Q 17
+#define CTRL_R 18
+#define CTRL_S 19
+#define CTRL_T 20
+#define CTRL_U 21
+#define CTRL_V 22
+#define CTRL_W 23
+#define CTRL_X 24
+#define CTRL_Y 25
+#define CTRL_Z 26
+#define CTRL_RIGHTBRACKET 29
+
+//Editor : Escape
+#define ESCAPE 27
+
+//Editor : Scan codes needed
+#define RETURN_SCANCODE 28
+#define BACKSPACE_SCANCODE 14
+
+//Editor : Code for No View
+#define NOVIEW 255
+
+//Editor : Multikey function prefix
+#define MULTIKEY CTRL_Q
+
+//Editor : Standard chars in text files
+#define LF 10
+#define CR 13
+#define TAB 9
+#define BS 8
+
+//Editor : Status of a line
+
+#define COMMENT_LINE 0x1 //This line is fully commented
+#define MULTISTRING_LINE 0x2 //This line is a multiline string
+#define TAGGED_LINE 0x4 //Tagged by the user
+#define BRKPOINT_LINE 0x8 //Brk Point Commited
+#define CURRENT_LINE 0x10 //Current line when debugging
+#define UBP_LINE 0x20 //Uninstaiated BP
+#define DASM_SOURCE_LINE 0x40 //Source line in disasm window
+#define DASM_LABEL_LINE 0x80 //Label line in disasm window
+
+//Editor : State when reading a file
+#define END_OF_LINE 0
+#define END_OF_FILE 1
+#define END_ABORT 2
+
+//Editor : Last line convention
+#define LAST_LINE MAX_LINE_NUMBER + 1
+
+//Color array for screen paint
+typedef struct {
+ int nbChars;
+ COLORREF fore;
+ COLORREF back;
+} COLORINFO;
+
+//Editor : Line status action
+typedef enum
+{
+ LINESTATUS_ON,
+ LINESTATUS_OFF,
+ LINESTATUS_TOGGLE
+}
+LINESTATUSACTION;
+
+//Editor : Line definition
+typedef struct {
+ WORD Status; //Status of line |
+ BYTE PrevLength; //Length of previous line | !! Size in constant LHD
+ BYTE Length; //Length of next line |
+ char Text[1]; //Text of line
+} LINEREC;
+typedef LINEREC NEAR UNALIGNED* NPLINEREC;
+typedef LINEREC FAR UNALIGNED* LPLINEREC;
+
+#ifdef ALIGN
+#pragma pack(4)
+#endif
+
+//Editor : Block definition
+typedef struct tagBD {
+ struct tagBD FAR *PrevBlock; //Previous block or NULL |
+ struct tagBD FAR *NextBlock; //Next block or NULL | !! Size in constant BHD
+ int LastLineOffset; //Size used |
+#ifdef ALIGN
+ int dummy;
+#endif
+ char Data[BLOCK_SIZE];
+} BLOCKDEF;
+typedef BLOCKDEF NEAR * NPBLOCKDEF;
+typedef BLOCKDEF FAR * LPBLOCKDEF;
+
+#ifdef ALIGN
+#pragma pack()
+#endif
+
+//Editor : View definition
+typedef struct {
+ int NextView; //Index of next view or (-1)
+ int Doc; //Index of document
+ HWND hwndFrame; //View Frame Window informations
+ HWND hwndClient; //Client handle
+ RECT rFrame;
+ int X; //Cursor position X
+ int Y; //Cursor position Y
+ BOOL BlockStatus; //Selection On/Off
+ int BlockXL; //Selection X left
+ int BlockXR; //Selection Y left
+ int BlockYL; //Selection X right
+ int BlockYR; //Selection Y right
+ BOOL hScrollBar; //Is there an horizontal scrollbar
+ BOOL vScrollBar; //Is there a vertical scrollbar
+ int scrollFactor; //0-100 Percent of scroll for view
+ HFONT font; //Current font
+ int charWidth[MAX_CHARS_IN_FONT];
+ int charHeight; //Current char height
+ int maxCharWidth;
+ int aveCharWidth;
+ int charSet;
+ int iYTop; /* Current Top line Y iff != -1 */
+ int Tmoverhang;
+#ifdef DBCS
+#define VIEW_PITCH_VARIABLE 0
+#define VIEW_PITCH_DBCS_FIXED 1
+#define VIEW_PITCH_ALL_FIXED 2
+ WORD wViewPitch;
+ WORD wCharSet; //This is for 'Memory Window'.
+#define DBCS_CHAR "\x82\xa0"
+ int charWidthDBCS; //Assume all DBCS char have the same
+ BOOL bDBCSOverWrite; //If TRUE, DBCS char is treated as
+ // two SBCS chars when "OverWrite" mode
+ //This always TRUE now.
+#endif // DBCS end
+} VIEWREC;
+typedef VIEWREC NEAR *NPVIEWREC;
+typedef VIEWREC FAR *LPVIEWREC;
+
+//Document : Type of document (if you change those values, don't be
+//surprise if windows coloring does not work anymore)
+#define DOC_WIN 0
+#define DUMMY_WIN 1
+#define WATCH_WIN 2 // this MUST be here...Our magic # is 1 (-1) !!!!!
+#define LOCALS_WIN 3
+#define CPU_WIN 4
+#define DISASM_WIN 5
+#define COMMAND_WIN 6
+#define FLOAT_WIN 7
+#define MEMORY_WIN 8
+#define QUICKW_WIN 9
+#define CALLS_WIN 10
+
+//Document & Environment : Language kind
+#define NO_LANGUAGE 0
+#define C_LANGUAGE 1
+#define PASCAL_LANGUAGE 2
+#define AUTO_LANGUAGE 3
+
+//Document : Mode when opening files
+#define MODE_OPENCREATE 0
+#define MODE_CREATE 1
+#define MODE_OPEN 2
+#define MODE_DUPLICATE 3
+#define MODE_RELOAD 4
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t;
+#define _TIME_T_DEFINED
+#endif
+
+//Document : Document definition
+typedef struct {
+ WORD docType; // Type of document
+ char FileName[_MAX_PATH]; // File name
+ time_t time; // Time opened, saved
+ BOOL bChangeFileAsk; // is there a dialog up ?
+ int NbLines; // Current number of lines
+ int FirstView; // Index of first view in Views
+ LPBLOCKDEF FirstBlock; // Address of first block
+ LPBLOCKDEF LastBlock; // Address of last block
+ LPBLOCKDEF CurrentBlock; // Address of current block
+ int CurrentLine; // Current line number
+ int CurrentLineOffset; // Current line offset in block
+ int lineTop; // Top line affected by a change
+ int lineBottom; // Buttom line affected by a change
+ WORD language; // C, Pascal or no language document
+ BOOL untitled;
+ BOOL ismodified;
+
+ BOOL readOnly; // Old "entire" doc readonly flag
+
+
+ BOOL RORegionSet; // Do we have a valid RO region?
+ int RoX2;
+ int RoY2; // Region max's-X1,Y1 always 0,0
+
+
+ BOOL forcedOvertype;
+ BOOL forcedReadOnly;
+ int playCount; // 0 in normal edit mode,
+ // counts undos otherwise
+ WORD recType;
+ UNDOREDOREC undo;
+ UNDOREDOREC redo;
+} DOCREC;
+typedef DOCREC near *NPDOCREC;
+typedef DOCREC far *LPDOCREC;
+
+//Find/Replace : Type of pick list
+#define FIND_PICK 0
+#define REPLACE_PICK 1
+
+//Find/Replace : Structure Definition
+typedef struct {
+ BOOL matchCase; //Match Upper/Lower case
+ BOOL regExpr; //Regular expression
+ BOOL wholeWord;
+ BOOL goUp; //Search direction
+ char findWhat[MAX_USER_LINE + 1]; //Input string
+ char replaceWith[MAX_USER_LINE + 1]; //Output string
+ int nbInPick[REPLACE_PICK + 1]; //Number of strings
+ //in picklist
+ HANDLE hPickList[REPLACE_PICK + 1][MAX_PICK_LIST]; //PickList for old
+ int nbReplaced; //Actual number of
+ //replacements
+} _FINDREPLACE;
+
+typedef struct {
+ int leftCol; //Start of string in line
+ int rightCol; //End of string in line
+ int line; //Current line
+ int stopLine; //Where find/replace should end
+ int stopCol; //Where find/replace should end
+ int nbReplaced; //Number of occurences replaced
+ BOOL oneLineDone;
+ BOOL allFileDone;
+ BOOL hadError;
+ BOOL goUpCopy;
+ BOOL allTagged;
+ BOOL replacing;
+ BOOL replaceAll;
+ BOOL exitModelessFind;
+ BOOL exitModelessReplace;
+ HWND hDlgFindNextWnd;
+ HWND hDlgConfirmWnd;
+ WNDPROC lpFindNextProc;
+ WNDPROC lpConfirmProc;
+ BOOL firstFindNextInvoc;
+ BOOL firstConfirmInvoc;
+} _FINDREPLACEMEM;
+
+//Error window : The error node list:
+#define MAX_ERROR_TEXT 256
+#define TRUEERROR 0x0001
+#define SOURCEERROR 0x0002
+
+//Error window : Error node
+typedef struct ERRORNODEtag
+{
+ char Text[MAX_ERROR_TEXT];
+ int ErrorLine;// Line number of error in source file, -1 otherwise
+ WORD flags;
+ struct ERRORNODEtag FAR *Next;
+ struct ERRORNODEtag FAR *Prev;
+} ERRORNODE;
+typedef ERRORNODE FAR *PERRORNODE;
+
+
+//Debugger : Debugging Mode
+#define SOFT_DEBUG 0
+#define HARD_DEBUG 1
+
+//Debugger : Breakpoint buffer sizes
+#define BKPT_LOCATION_SIZE 128
+#define BKPT_WNDPROC_SIZE 128
+#define BKPT_EXPR_SIZE 128
+
+//Degugger : Breakpoints types
+typedef enum
+{
+ BRK_AT_LOC,
+ BRK_AT_LOC_EXPR_TRUE,
+ BRK_AT_LOC_EXPR_CHGD,
+ BRK_EXPR_TRUE,
+ BRK_EXPR_CHGD,
+ BRK_AT_WNDPROC,
+ BRK_AT_WNDPROC_EXPR_TRUE,
+ BRK_AT_WNDPROC_EXPR_CHGD,
+ BRK_AT_WNDPROC_MSG_RECVD
+} BREAKPOINTACTIONS;
+
+
+//Debugger : Message classes
+#define SPECIFICMESSAGE 0x0001
+#define MOUSECLASS 0x0002
+#define WINDOWCLASS 0x0004
+#define INPUTCLASS 0x0008
+#define SYSTEMCLASS 0x0010
+#define INITCLASS 0x0020
+#define CLIPBOARDCLASS 0x0040
+#define DDECLASS 0x0080
+#define NONCLIENTCLASS 0x0100
+#define NOTSELECTED 0x0200
+#define NOTSELECTEDMESSAGE 0xFFFF
+
+//Debugger : Set Breakpoint structure definition
+typedef struct {
+ BREAKPOINTACTIONS nAction;
+ char szLocation[BKPT_LOCATION_SIZE];
+ char szWndProc[BKPT_WNDPROC_SIZE];
+ char szExpression[BKPT_EXPR_SIZE];
+ WORD wLength;
+ WORD MessageClass;
+ WORD Message;
+} BRKPTSTRUC;
+
+//Debugger : Current line in debuggee
+typedef struct {
+ int doc;
+ int CurTraceLine;
+} TRACEINFO;
+
+//Title bar
+typedef enum {TBM_WORK, TBM_RUN, TBM_BREAK} TITLEBARMODE;
+typedef struct _TITLEBAR {
+ char ProgName[30];
+ char UserTitle[30];
+ char ModeWork[20];
+ char ModeRun[20];
+ char ModeBreak[20];
+ TITLEBARMODE Mode;
+ TITLEBARMODE TimerMode;
+} TITLEBAR;
+
+typedef enum {HARDMODE, SOFTMODE, CHECKMODE} DEBUGMODE;
+
+/****************************************************************************
+
+ HOTKEY DEFINES:
+
+****************************************************************************/
+
+#define IDH_CTRLC 100
+
+
+/****************************************************************************
+
+ RESOURCES DEFINES :
+
+****************************************************************************/
+// Windows version
+#define WINDOWS_VERSION 0x300
+
+//Edit control identifier
+#define ID_EDIT 0xCAC
+
+//Position of window menu
+#define WINDOWMENU 7
+
+//Position of file menu
+#define FILEMENU 0
+
+//Position of project menu
+#define PROJECTMENU 3
+
+//Position of workspace sub-menus in Project Menu
+#define LOADWORKSPACEMENU 8
+#define SAVEWORKSPACEMENU 9
+
+//Position of first mdi window in Window Menu
+#define FIRST_DOC_WIN_POS 15
+
+//Standard help id in dialogs
+#define IDWINDBGHELP 100
+
+//Status control identifier
+#define ID_STATUS 100
+
+//Ribbon control identifier
+#define ID_RIBBON 100
+
+//Window word values for child windows
+#define GWW_EDIT 0
+#define GWW_VIEW (GWW_EDIT + sizeof(UINT))
+
+//Size of extra data for MDI child windows
+#define CBWNDEXTRA 6
+
+//Invalid menu Item
+#define IDM_INVALID 16000
+
+//Status Bar : Definitions for status control's IDs
+#define ID_STATUS_TXT 100
+#define ID_STATUS_MULTIKEY 101
+#define ID_STATUS_OVERTYPE 102
+#define ID_STATUS_READONLY 103
+#define ID_STATUS_CAPSLOCK 104
+#define ID_STATUS_NUMLOCK 105
+#define ID_STATUS_LINE 106
+#define ID_STATUS_COLUMN 107
+#define ID_STATUS_SRC 108
+#define ID_STATUS_CURPID 109
+#define ID_STATUS_CURTID 110
+
+//Macro to checks if screen is in CGA, EGA, HGC, or VGA mode [cnv]
+//Mode HGC and EGA is consider the same for now.
+#define IsCGAmode (GetSystemMetrics (SM_CYSCREEN) == 200)
+
+// Herc and EGA are similar.
+#define IsEGAmode ((GetSystemMetrics (SM_CYSCREEN) >= 201) && (GetSystemMetrics (SM_CYSCREEN) <= 350))
+
+// Anything greater is considered VGA for now.
+#define IsVGAmode (GetSystemMetrics (SM_CYSCREEN) >= 480)
+#define IsMONOmode (IsMonoModeProc())
+
+/*
+** Include the defines which are used have numbers for string
+** resources.
+*/
+
+#include "..\include\res_str.h"
+
+#define WM_CREATEX WM_USER+1001
+
+
+char szBrowse[_MAX_PATH]; // for browses
+
+
+/****************************************************************************
+
+ CALL BACKS:
+
+****************************************************************************/
+BOOL InitApplication(HANDLE);
+//BOOL InitInstance(LPSTR, HANDLE, int);
+long FAR PASCAL EXPORT MainWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT StatusWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT StatusTextWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT RibbonWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT MDIChildWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT MDIPaneWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT DLGPaneWndProc(HWND, UINT, WPARAM, LONG);
+long FAR PASCAL EXPORT ChildWndProc(HWND, UINT, WPARAM, LONG);
+
+
+//Call Back to Handle Edit Syntax Dialog BOX
+BOOL FAR PASCAL EXPORT DlgSyntax(HWND, UINT, WPARAM, LONG);
+
+
+//Call Back to Handle Edit Find Dialog BOX
+BOOL FAR PASCAL EXPORT DlgFind(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Edit Replace Dialog BOX
+BOOL FAR PASCAL EXPORT DlgReplace(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle View Line Dialog BOX
+BOOL FAR PASCAL EXPORT DlgLine(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle View Function Dialog BOX
+BOOL FAR PASCAL EXPORT DlgFunction(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle View Function Dialog BOX
+BOOL FAR PASCAL EXPORT DlgTaskList(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Debug Calls Dialog BOX
+BOOL FAR PASCAL EXPORT DlgCalls(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Debug Modify Value Dialog BOX
+BOOL FAR PASCAL EXPORT DlgModify(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Debug QuickWatch Dialog BOX
+BOOL FAR PASCAL EXPORT DlgQuickW(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Debug Watch Value Dialog BOX
+BOOL FAR PASCAL EXPORT DlgWatch(HWND, UINT, WPARAM, LONG);
+
+// Callback to handle memory window dialog box
+BOOL FAR PASCAL EXPORT DlgMemory(HWND, UINT, WPARAM, LONG);
+
+// Callback to handle pane manager options box
+BOOL FAR PASCAL EXPORT DlgPaneOptions(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Debug Set Break Point Message Dialog BOX
+BOOL FAR PASCAL EXPORT DlgMessage(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Debug Set Breakpoint Dialog BOX
+BOOL FAR PASCAL EXPORT DlgSetBreak(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Options Environ Dialog BOX
+BOOL FAR PASCAL EXPORT DlgEnviron(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Options Workspace Dialog BOX
+BOOL FAR PASCAL EXPORT DlgWorkspace(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Options Build Dialog BOX
+BOOL FAR PASCAL EXPORT DlgProject(HWND, UINT, WPARAM, LONG);
+
+//Shells the DlgProject dialog box invocation
+void PASCAL EXPORT DoDlgProject(void);
+
+//Call Back to Handle Option Project C Flags Dialog BOX
+BOOL FAR PASCAL EXPORT DlgCFlags(HWND, UINT, WPARAM, LONG);
+
+//Shells the DlgCFlags dialog box invocation
+void PASCAL EXPORT DoDlgCFlags(int nDebugMode, int nProgType);
+
+//Call Back to Handle Option Project Link Flags Dialog BOX
+BOOL FAR PASCAL EXPORT DlgLnkFlags(HWND, UINT, WPARAM, LONG);
+
+//Shells the DlgLnkFlags dialog box invocation
+void PASCAL EXPORT DoDlgLnkFlags(int nDebugMode, int nProgType);
+
+//Call Back to Handle Option Project Resource Flags Dialog BOX
+BOOL FAR PASCAL EXPORT DlgResFlags(HWND, UINT, WPARAM, LONG);
+
+//Shells the DlgResFlags dialog box invocation
+void PASCAL EXPORT DoDlgResFlags(int nDebugMode, int nProgType);
+
+//Call Back to Handle Debug Options Dialog BOX
+BOOL FAR PASCAL EXPORT DlgRunDebug(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Kernel Debug Options Dialog BOX
+BOOL FAR PASCAL EXPORT DlgKernelDbg(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Calls Window Options Dialog BOX
+BOOL FAR PASCAL EXPORT DlgCallsOptions(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Run Options Dialog BOX
+BOOL FAR PASCAL EXPORT DlgDbugrun(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Debugger DLLS Dialog BOX
+BOOL FAR PASCAL EXPORT DlgDbugdll(HWND, UINT, WPARAM, LONG);
+
+//Call Back to User DLLS Dialog BOX
+BOOL FAR PASCAL EXPORT DlgUserdll(HWND, UINT, WPARAM, LONG);
+
+//Call Back to User DLLS Dialog BOX
+BOOL FAR PASCAL EXPORT DlgUserDllDefaults(HWND, UINT, WPARAM, LONG);
+
+//Call Back to User DLLS Dialog BOX
+BOOL FAR PASCAL EXPORT DlgUserDllAdd(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Debugger exceptions Options Dialog BOX
+BOOL FAR PASCAL EXPORT DlgDbugexcept(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Disassembler Options Dialog BOX
+BOOL FAR PASCAL EXPORT DlgDisasmOpt(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Options Directories Dialog BOX
+BOOL FAR PASCAL EXPORT DlgDirs(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Options Colors Dialog BOX
+BOOL FAR PASCAL EXPORT DlgColors(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Fonts Select Dialog BOX
+BOOL FAR PASCAL EXPORT DlgFonts(HWND, UINT, WPARAM, LONG);
+
+// call back to handle user control buttons
+LONG FAR PASCAL EXPORT QCQPCtrlWndProc (HWND, UINT, WPARAM, LONG) ;
+
+//Call Back to Handle File Open Merge Save and Open Project
+BOOL DlgFile(HWND, UINT, WPARAM, LPARAM);
+BOOL GetOpenFileNameHookProc(HWND, UINT, WPARAM, LPARAM);
+BOOL GetOpenDllNameHookProc(HWND, UINT, WPARAM, LPARAM);
+
+//Call Back to Handle Project Edit Program List Dialog BOX
+BOOL FAR PASCAL EXPORT DlgEditProject(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Edit Confirm Replace Dialog BOX
+BOOL FAR PASCAL EXPORT DlgConfirm(HWND, UINT, WPARAM, LONG);
+
+//Call Back to Handle Edit Find Next Dialog BOX
+BOOL FAR PASCAL EXPORT DlgFindNext(HWND, UINT, WPARAM, LONG);
+
+// Callback Function for Thread dialog
+BOOL FAR PASCAL EXPORT DlgThread(HWND, UINT, WPARAM, LONG);
+
+// Callback Function for Process dialog
+BOOL FAR PASCAL EXPORT DlgProcess(HWND, UINT, WPARAM, LONG);
+
+// Callback Function for BrowseDlg dialog
+BOOL FAR PASCAL EXPORT DlgAskBrowse(HWND, UINT, WPARAM, LONG);
+
+// Callback Function for BrowseDlg dialog
+BOOL FAR PASCAL EXPORT DlgBadSymbols(HWND, UINT, WPARAM, LONG);
+
+
+
+
+
+#define _MAX_CVPATH 255
+#define _MAX_CVDRIVE 3
+#define _MAX_CVDIR 255
+#define _MAX_CVFNAME 255
+#define _MAX_CVEXT 255
+
+/*
+** Describe the set of possible thread and process states.
+*/
+
+typedef enum {
+ tsPreRunning,
+ tsRunning,
+ tsStopped,
+ tsException1,
+ tsException2,
+ tsRipped,
+ tsExited
+} TSTATEX;
+
+typedef enum {
+ psNoProgLoaded,
+ psPreRunning, // haven't hit ldr BP
+ psRunning,
+ psStopped,
+ psExited,
+ psDestroyed, // only used for ipid == 0
+ psError // damaged
+} PSTATE;
+
+
+// See od.h for EFD type
+typedef struct _excpt_node {
+ struct _excpt_node *next;
+ DWORD dwExceptionCode;
+ EXCEPTION_FILTER_DEFAULT efd;
+ LPSTR lpName;
+ LPSTR lpCmd;
+ LPSTR lpCmd2;
+} EXCEPTION_LIST;
+
+
+#define tfStepOver 2
+/*
+** Create structures which will describe the set of processes and
+** threads in the system. These are the Thread Descriptor and
+** Process Descriptor structures.
+*/
+
+typedef struct TD FAR * LPTD;
+typedef struct PD FAR * LPPD;
+
+typedef struct TD {
+ HTID htid; // HTID for this thread
+ LPPD lppd; // Pointer to Process descriptor for thread
+ LPTD lptdNext; // Pointer to sibling threads
+ UINT itid; // Index for this thread
+ UINT cStepsLeft; // Number of steps left to run
+ LPSTR lpszCmdBuffer; // Pointer to buffer containning command to execute
+ LPSTR lpszCmdPtr; // Pointer to next command to be executed.
+ UINT flags; // Flags on thread, used by step
+ TSTATEX tstate; // Thread state - enumeration
+ UINT fInFuncEval:1; // Currently doing function evaluation?
+ UINT fFrozen:1; // Frozen?
+ UINT fGoOnTerm:1; // never stop on termination
+ UINT fRegisters:1; // print registers on stop event?
+ UINT fDisasm:1; // print disasm on stop event?
+ DWORD TebBaseAddress; //
+ LPSTR lpszTname; //
+} TD;
+
+typedef struct PD {
+ HPID hpid; // This is the HPID for this process
+ LPPD lppdNext; // Pointer to next LPPD on list
+ LPTD lptdList; // Pointer to list of threads for process
+ HPDS hpds; // Handle to SH process description structure
+ UINT ctid; // Counter for tids
+ UINT ipid; // Index for this process
+ EXCEPTION_LIST *exceptionList;
+ LPSTR lpBaseExeName; // Name of exe that started process
+ PSTATE pstate; // Process state - enumeration
+ HANDLE hbptSaved; // BP for deferred use
+ UINT fFrozen:1; // Frozen?
+ UINT fPrecious:1; // Don't delete this PD (only for ipid == 0?)
+ UINT fChild:1; // go or don't on ldr BP
+ UINT fHasRun:1; // has run after ldr BP
+ UINT fStopAtEntry:1; // Stop at app entry point?
+ UINT fInitialStep:1; // doing src step before entrypoint event
+} PD;
+
+
+BOOL LoadWorkspaceHeader(void);
+BOOL LoadWorkspace(int wkSpcNb);
+void SetWorkspaceMenuName(WORD menuLoadId, WORD menuSaveId, LPSTR name);
+BOOL CloseWorkspace(void);
+
+// NOTENOTE Davegi Fix when real color support exists.
+
+void RefreshScreenColors(void);
+
+
+#define IDI_WINTMPL 100
+
+#define IDS_SOURCE_WINDOW 100
+#define IDS_DUMMY_WINDOW 101
+#define IDS_WATCH_WINDOW 102
+#define IDS_LOCALS_WINDOW 103
+#define IDS_CPU_WINDOW 104
+#define IDS_DISASSEMBLER_WINDOW 105
+#define IDS_COMMAND_WINDOW 106
+#define IDS_FLOAT_WINDOW 107
+#define IDS_MEMORY_WINDOW 108
+#define IDS_BREAKPOINT_LINE 109
+#define IDS_CURRENT_LINE 110
+#define IDS_CURRENTBREAK_LINE 111
+#define IDS_UNINSTANTIATEDBREAK 112
+#define IDS_TAGGED_LINE 113
+#define IDS_TEXT_SELECTION 114
+#define IDS_KEYWORD 115
+#define IDS_IDENTIFIER 116
+#define IDS_COMMENT 117
+#define IDS_NUMBER 118
+#define IDS_REAL 119
+#define IDS_STRING 120
+#define IDS_ACTIVEEDIT 121
+#define IDS_CHANGEHISTORY 122
+#define IDS_CALLS_WINDOW 123
+
+#define IDS_SELECT_ALL 124
+#define IDS_CLEAR_ALL 125
+
+#endif // _WINDBG_
diff --git a/private/windbg/windbg/include/winpck.h b/private/windbg/windbg/include/winpck.h
new file mode 100644
index 000000000..10830471f
--- /dev/null
+++ b/private/windbg/windbg/include/winpck.h
@@ -0,0 +1,95 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+ * WINPCK.H
+ *
+ * Description of callback packets.
+ *
+ * Module History:
+ * 10-Jan-91 [mannyv] Adapted it from CVPACK
+ * 26-Dec-90 [mannyv] Created it.
+ */
+
+
+/*
+ * Packet header. All packets contain this information at the beginning
+ */
+
+typedef struct
+{
+ short iType; // packet type
+ short cb; // number of bytes in packet (include header)
+
+} PCKHDR;
+
+
+/*
+ * Packet types (values for iType field in header)
+ */
+
+enum
+{
+ QW_VERSION=0, // reports version of app
+ QW_END, // signals end of execution of app
+ QW_ERROR, // signals error
+ QW_WERROR, // signals windows error
+ QW_STATUS // reports progress
+};
+
+
+/*
+ * Version packet
+ */
+
+typedef struct
+{
+ PCKHDR hdr;
+
+ char far * pszTitle;
+ char far * pszCopyright;
+ short Major;
+ short Minor;
+ short Internal;
+
+} PCKVER;
+
+
+/*
+ * Error packet. Note: the string pointed to by pszError in the
+ * packet is only valid during the callback. The callback function
+ * should copy the string if it needs it later.
+ *
+ * This same packe is used for both QW_ERROR and QW_WERROR packets.
+ */
+
+typedef struct
+{
+ PCKHDR hdr;
+
+ char far * pszError;
+
+} PCKERR;
+
+
+/*
+ * End packet
+ */
+
+typedef struct
+{
+ PCKHDR hdr;
+
+ short RetCode;
+
+} PCKEND;
+
+
+/*
+ * Proress report packet.
+ */
+
+typedef struct
+{
+ PCKHDR hdr;
+
+ char far * pszMsg;
+
+} PCKSTS;
diff --git a/private/windbg/windbg/include/wrkspace.h b/private/windbg/windbg/include/wrkspace.h
new file mode 100644
index 000000000..242f7bc31
--- /dev/null
+++ b/private/windbg/windbg/include/wrkspace.h
@@ -0,0 +1,148 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ WrkSpace.h
+
+Abstract:
+
+ Header file for WinDbg WorkSpaces.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 07-July-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+//
+// The WORKSPACE_ITEM enumeration contains all the workspace items
+// that can be load/saved individually.
+//
+typedef enum _WORKSPACE_ITEM {
+
+ //
+ // Miscellaneous
+ //
+ WSI_COMLINE, // Command line arguments
+ WSI_WINDOW, // Frame window
+ WSI_DEFFONT, // Default font
+ WSI_FILEMRU, // File MRU list
+ WSI_RIBBON, // Ribbon state
+ WSI_STATUSBAR, // Status bar state
+ WSI_SRCMODE, // Source mode
+ WSI_BRKPTS, // Breakpoint related info.
+
+ //
+ // Options
+ //
+ WSI_DBGOPT, // Debugger options
+ WSI_DBGDLL, // Debugger DLLs
+ WSI_USRDLL, // User DLLS
+ WSI_ENV, // Environment
+ WSI_ASMOPT, // Disassembler options
+ WSI_EXCPT, // Exceptions
+ WSI_COLORS, // Colors
+
+ //
+ // Windows
+ //
+ WSI_WDWDOC, // Source
+ WSI_WDWWCH, // Watch
+ WSI_WDWLOC, // Locals
+ WSI_WDWCPU, // CPU
+ WSI_WDWASM, // Disassembly
+ WSI_WDWCMD, // Cmd
+ WSI_WDWFLT, // Float
+ WSI_WDWMEM, // Memory
+ WSI_WDWCALLS, // Calls
+
+ WSI_LAST
+
+} WORKSPACE_ITEM, *PWORKSPACE_ITEM;
+
+#define WSI_FIRST WSI_COMLINE
+#define WSI_MISC_FIRST WSI_COMLINE
+#define WSI_MISC_LAST WSI_BRKPTS
+#define WSI_OPTION_FIRST WSI_DBGOPT
+#define WSI_OPTION_LAST WSI_COLORS
+#define WSI_WINDOW_FIRST WSI_WDWDOC
+#define WSI_WINDOW_LAST WSI_WDWMEM
+
+//
+// a mechanism to allow command line options to override
+// workspace settings.
+//
+extern DWORD WorkspaceOverride;
+
+#define WSO_INHERITHANDLES 0x0001
+#define WSO_WINDOW 0x0004
+
+
+
+//
+// name of nameless workspace
+//
+#define UNTITLED "<Attached Process>"
+char UntitledProgramName[];
+char KdProgramName[];
+
+
+//
+// these reserved image names are used to magically identify
+// kernel debugger workspaces
+//
+#define KD_PGM_NAME1 "ntoskrnl.exe"
+#define KD_PGM_NAME2 "osloader.exe"
+
+//
+// Debugger state
+//
+BOOLEAN DebuggerStateChanged( VOID );
+VOID ChangeDebuggerState( VOID );
+LPSTR GetCurrentProgramName( BOOL );
+LPSTR GetCurrentWorkSpace( VOID );
+
+
+
+//
+// Program loading/unloading
+//
+BOOLEAN LoadProgram ( LPSTR );
+BOOLEAN IsProgramLoaded( VOID );
+BOOLEAN UnLoadProgram( VOID );
+
+BOOLEAN LoadProgramMRUList( VOID );
+BOOLEAN SaveProgramMRUList( VOID );
+
+
+
+//
+// WorkSpace operations
+//
+BOOLEAN WorkSpaceExists( LPSTR ProgramName, LPSTR WorkSpace );
+LPSTR GetAllPrograms( DWORD *ListLength );
+LPSTR GetAllWorkSpaces( LPSTR ProgramName, DWORD *ListLength, LPSTR DefaultWorkSpace );
+BOOLEAN GetDefaultWorkSpace( LPSTR ProgramName, LPSTR WorkSpaceName );
+BOOLEAN LoadWorkSpace( LPSTR ProgramName, LPSTR WorkSpaceName, BOOLEAN LoadCommandLine );
+BOOLEAN SaveWorkSpace( LPSTR ProgramName, LPSTR WorkSpaceName, BOOLEAN Default );
+BOOLEAN DeleteWorkSpace( LPSTR ProgramName, LPSTR WorkSpaceName );
+BOOLEAN DeleteProgram( LPSTR ProgramName );
+
+//
+// Option lists
+//
+typedef void (*ENUMOPTIONPROC)(HKEY, LPSTR, LPARAM);
+
+void EnumOptionItems(HKEY hKeyOption, ENUMOPTIONPROC EnumProc, LPARAM lParam);
+BOOL DeleteOptionItem(HKEY hKeyOption, LPSTR lpOptionItemName);
+BOOL SetOptionSubItem(HKEY hKeyOption, LPSTR lpOptionItemName,
+ LPSTR lpOptionSubItemName, LPSTR lpOptionSubItemValue);
+BOOL GetOptionSubItem(HKEY hKeyOption, LPSTR lpOptionItemName,
+ LPSTR lpOptionSubItemName, LPSTR lpOptionSubItemValue, LPDWORD lpcbBuf);
+HKEY GetOptionKey(LPSTR OptionName, BOOLEAN Create);
diff --git a/private/windbg/windbg/init.c b/private/windbg/windbg/init.c
new file mode 100644
index 000000000..de917d0df
--- /dev/null
+++ b/private/windbg/windbg/init.c
@@ -0,0 +1,1681 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Init.c
+
+Abstract:
+
+ This module contains the initialization routines for Windbg.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-1992
+ Griffith Wm. Kadnier (v-griffk) 17-Sep-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include <ntiodump.h>
+
+
+DWORD GetComPorts(VOID);
+
+char DebuggerName[ MAX_PATH ];
+LPSTR LpszCommandLineTransportDll = NULL;
+
+extern char FAR * LpszCommandLine;
+
+extern HMENU hMainMenuSave;
+extern CRITICAL_SECTION csLog;
+
+/*** InitApplication - Initialize the Application specific information
+**
+** Synopsis:
+** bool = InitApplication(hInstance)
+**
+** Entry:
+** hInstance - Instance handle for Win16, Module handle for Win32
+**
+** Returns:
+** TRUE if sucessful and FALSE otherwise
+**
+** Description:
+** Initializes window data and registers window classes.
+**
+*/
+
+BOOL InitApplication(HANDLE hInstance)
+{
+ WNDCLASS wc;
+ char class[MAX_MSG_TXT];
+
+
+ //We use tmp strings as edit buffers
+ Assert(MAX_LINE_SIZE < TMP_STRING_SIZE);
+
+ //Register the main window class
+ //Associates QcQp Icon
+ //Associates Standard Arrow Cursor
+ //Associates QcQp Menu
+
+ wc.style = 0;
+ wc.lpfnWndProc = MainWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(QCQPICON)));
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = MAKEINTRESOURCE(QCQPMAINMENU);
+ Dbg(LoadString(hInstance, SYS_Main_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass (&wc) )
+ return FALSE;
+
+ //Register the MDI child class
+ //Associates Child Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIChildWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(DOCICON)));
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Child_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Cpu child class
+ //Associates Cpu Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIPaneWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(CPUICON)));
+ wc.hbrBackground = (HBRUSH) CreateSolidBrush(GRAYDARK);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Cpu_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Memory child class
+ //Associates Memory Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIChildWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( MEMORYICON )));
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Memory_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Command child class
+ //Associates Command Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIChildWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( CMDICON )));
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Cmd_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Floating Point child class
+ //Associates Floating Point Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIPaneWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( FLOATICON )));
+ wc.hbrBackground = (HBRUSH) CreateSolidBrush(GRAYDARK);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Float_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+ wc.hIcon = NULL;
+ strcpy(LpszCommandLine, wc.lpszClassName);
+ wc.lpszClassName = LpszCommandLine;
+ (*LpszCommandLine) += 1;
+ RegisterClass(&wc);
+
+ //Register the Locals child class
+ //Associates Locals Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIPaneWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( LOCALSICON )));
+ wc.hbrBackground = (HBRUSH) CreateSolidBrush(GRAYDARK);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Locals_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Watch child class
+ //Associates Watch Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIPaneWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( WATCHICON )));
+ wc.hbrBackground = (HBRUSH) CreateSolidBrush(GRAYDARK);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Watch_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the QuickWatch Watch child class
+ //Associates Watch Icon
+
+ wc.style = 0;
+ wc.lpfnWndProc = DLGPaneWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA;
+ wc.hInstance = hInstance;
+ wc.hbrBackground = (HBRUSH) CreateSolidBrush(GRAYDARK);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Quick_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ wc.cbWndExtra = DLGWINDOWEXTRA; // Used by QuickW dialog
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Editor child class
+ //Associates Caret Cursor
+
+ wc.style = CS_DBLCLKS;
+ wc.lpfnWndProc = ChildWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA; // Is this really necessary
+ wc.hInstance = hInstance;
+
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_IBEAM);
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Edit_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Disassembler child class
+
+ wc.style = 0;
+ wc.lpfnWndProc = MDIChildWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA; // Is this really necessary
+ wc.hInstance = hInstance;
+
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( DISASMICON )));
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Disasm_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the Calls child class
+
+ wc.style = 0;
+ wc.lpfnWndProc = CallsWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = CBWNDEXTRA; // Is this really necessary
+ wc.hInstance = hInstance;
+ Dbg(wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(DOCICON)));
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Calls_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the status line class
+
+ wc.style = 0;
+ wc.lpfnWndProc = StatusWndProc;
+ wc.hInstance = hInstance;
+
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+
+ //Only create background with light gray when running under VGA color
+
+ if ( IsVGAmode && !IsMONOmode )
+ wc.hbrBackground = CreateSolidBrush (GRAYLIGHT) ;
+ else
+ wc.hbrBackground = CreateSolidBrush (WHITEBKGD) ;
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Status_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the ribbon line class
+
+ wc.style = 0;
+ wc.lpfnWndProc = RibbonWndProc;
+ wc.hInstance = hInstance;
+
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+
+ // I don't know why but using this line instead of the next line
+ // and Windows will bomb out. !!!!!!!!!!!!!!!!!!!!!!!!!!!!11
+ // only create background with light gray when running under VGA color
+
+ if ( IsVGAmode && !IsMONOmode )
+ wc.hbrBackground = CreateSolidBrush (GRAYLIGHT) ;
+ else
+ wc.hbrBackground = CreateSolidBrush (WHITEBKGD) ;
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_Ribbon_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ //Register the bitmap button
+ // We want double clicks for the error display
+
+ wc.style = 0;
+ wc.lpfnWndProc = QCQPCtrlWndProc;
+ wc.hInstance = hInstance;
+ wc.cbClsExtra = 0 ;
+ wc.cbWndExtra = CBWNDEXTRA_QCQPCTRL ;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+
+ //Only create background with light gray when running under VGA color
+
+ if ( IsVGAmode && !IsMONOmode )
+ wc.hbrBackground = CreateSolidBrush (GRAYLIGHT) ;
+ else
+ wc.hbrBackground = CreateSolidBrush (WHITEBKGD) ;
+ wc.lpszMenuName = NULL;
+ Dbg(LoadString(hInstance, SYS_QCQPCtrl_wClass, class, MAX_MSG_TXT));
+ wc.lpszClassName = class;
+ if (!RegisterClass(&wc))
+ return FALSE ;
+
+ return TRUE;
+} /* InitApplication() */
+
+
+/*** InitInstance
+**
+** Synopsis:
+** WIN32: bool = InitInstance(argc, argv, hModule, nCmdShow)
+** Win16: bool = InitInstance(lpszCmdLine, hInstance, nCmdShow)
+**
+** Entry:
+** argc - Count of command line arguments
+** argv - pointer to array of command line arguement pointers
+** hModule - Handle to current module
+** nCmdShow - Show all windows now?
+**
+** lpszCmdLine - Pointer to the command line
+** hInstance - Handle to current instance of program
+**
+** Returns:
+** TRUE if initialization was successful else FALSE
+**
+** Description:
+** Saves instance handle in global variable and creates main window.
+**
+*/
+
+LPSTR
+GetArg(
+ LPSTR *lpp
+ )
+{
+ static char szStr[1000];
+ int r;
+ LPSTR p1 = *lpp;
+
+ while (*p1 == ' ' || *p1 == '\t') {
+ p1++;
+ }
+
+ *szStr = 0;
+ r = CPCopyString(&p1, szStr, 0, (*p1 == '\'' || *p1 == '"'));
+ if (r >= 0) {
+ *lpp = p1;
+ }
+ return szStr;
+}
+
+
+BOOL
+InitCrashDump(
+ LPSTR CrashDump,
+ LPSTR SymPath
+ )
+{
+ PDUMP_HEADER DumpHeader = NULL;
+ DWORD cb = 0;
+ DWORD fsize = 0;
+ HANDLE File = NULL;
+ HANDLE MemMap = NULL;
+ PCHAR DmpDumpBase = NULL;
+ BOOL rval = FALSE;
+
+
+ File = CreateFile(
+ CrashDump,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (File == INVALID_HANDLE_VALUE) {
+ goto exit;
+ }
+
+ MemMap = CreateFileMapping(
+ File,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ 0,
+ NULL
+ );
+
+ if (MemMap == 0) {
+ goto exit;
+ }
+
+ DmpDumpBase = MapViewOfFile(
+ MemMap,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ 0
+ );
+
+ if (DmpDumpBase == NULL) {
+ goto exit;
+ }
+
+ DumpHeader = (PDUMP_HEADER)DmpDumpBase;
+
+ fsize = GetFileSize( File,NULL );
+ if (strcmp( DmpDumpBase+fsize-8, "DUMPREF" ) == 0) {
+ //
+ // point to the share name
+ //
+ char *p = DmpDumpBase + sizeof(DUMP_HEADER);
+
+ //
+ // point to the file name
+ //
+ p += strlen(p) + 1;
+
+ //
+ // point to the symbol path
+ //
+ p += strlen(p) + 1;
+
+ //
+ // copy into the caller's buffer
+ //
+ strcpy( SymPath, p );
+ }
+
+ if ((DumpHeader->Signature == 'EGAP') &&
+ (DumpHeader->ValidDump == 'PMUD')) {
+
+ runDebugParams.fCommandRepeat = TRUE;
+ runDebugParams.fKernelDebugger = TRUE;
+ runDebugParams.KdParams.fUseCrashDump = TRUE;
+ strcpy( runDebugParams.KdParams.szCrashDump, CrashDump );
+
+ switch( DumpHeader->MachineImageType ) {
+ case IMAGE_FILE_MACHINE_I386:
+ runDebugParams.KdParams.dwPlatform = 0;
+ SetDllKey( DLL_EXEC_MODEL, "emx86" );
+ SetDllKey( DLL_EXPR_EVAL, "x86 c++" );
+ break;
+
+ case IMAGE_FILE_MACHINE_R4000:
+ case IMAGE_FILE_MACHINE_R10000:
+ runDebugParams.KdParams.dwPlatform = 1;
+ SetDllKey( DLL_EXEC_MODEL, "emmip" );
+ SetDllKey( DLL_EXPR_EVAL, "mips c++" );
+ break;
+
+ case IMAGE_FILE_MACHINE_ALPHA:
+ runDebugParams.KdParams.dwPlatform = 2;
+ SetDllKey( DLL_EXEC_MODEL, "emalpha" );
+ SetDllKey( DLL_EXPR_EVAL, "alpha c++" );
+ break;
+
+ case IMAGE_FILE_MACHINE_POWERPC:
+ runDebugParams.KdParams.dwPlatform = 3;
+ SetDllKey( DLL_EXEC_MODEL, "emppc" );
+ SetDllKey( DLL_EXPR_EVAL, "ppc c++" );
+ break;
+ }
+
+ rval = TRUE;
+ }
+
+ if ((DumpHeader->Signature == 'RESU') &&
+ (DumpHeader->ValidDump == 'PMUD')) {
+ //
+ // usermode crash dump
+ //
+ runDebugParams.fUserCrashDump = TRUE;
+ strcpy( runDebugParams.szUserCrashDump, CrashDump );
+ rval = TRUE;
+ }
+
+exit:
+ if (DmpDumpBase) {
+ UnmapViewOfFile( DmpDumpBase );
+ }
+ if (MemMap) {
+ CloseHandle( MemMap );
+ }
+ if (File) {
+ CloseHandle( File );
+ }
+
+ return rval;
+}
+
+
+BOOL
+InitInstance(
+ int argc,
+ char * argv[],
+ HANDLE hInstance,
+ int nCmdShow
+ )
+/*++
+
+Routine Description:
+
+ Finish initializing Windbg, parse and execute the command line.
+
+Arguments:
+
+ argc - Supplies command line arg count
+ argv - Supplies command line args
+ hInstance - Supplies app instance handle (lpBaseOfImage)
+ nCmdShow - Supplies ShowWindow parameter
+
+Return Value:
+
+ TRUE if everything is OK, FALSE if something fails
+
+--*/
+{
+ extern BOOL AutoTest;
+ char ProgramName[ MAX_PATH ] = "";
+ char rgch[ MAX_PATH ] = "";
+ char wTitle[ MAX_MSG_TXT ] = "";
+ char wClass[ MAX_MSG_TXT ] = "";
+ char WorkSpace[ MAX_PATH ] = "";
+ BOOLEAN WorkSpaceSpecified = FALSE;
+ BOOLEAN toRestore = FALSE;
+ BOOLEAN workSpaceLoaded = FALSE;
+ BOOLEAN frameHidden = TRUE;
+ BOOLEAN LoadedDefaultWorkSpace = FALSE;
+ BOOLEAN CreatedNewDefault = FALSE;
+ BOOLEAN WorkSpaceMissed = FALSE;
+ BOOLEAN fJustSource = FALSE;
+ BOOLEAN fGoNow = FALSE;
+ BOOL SwitchK = FALSE;
+ BOOL SwitchH = FALSE;
+ LPSTR WorkSpaceToUse = NULL;
+ LONG lAttachProcess = -2;
+ HANDLE hEventGo = NULL;
+ LPSTR lp1;
+ LPSTR lp2;
+ RUNDEBUGPARAMS rd;
+ BOOL fRemoteServer = FALSE;
+ BOOL fMinimize = FALSE;
+ CHAR PipeName[MAX_PATH+1] = "";
+ BOOL fSymPath = FALSE;
+ BOOL fCrashDump = FALSE;
+ BOOL fIgnoreAll = FALSE;
+ CHAR SymPath[MAX_PATH*2] = "";
+ CHAR CrashDump[MAX_PATH*2] = "";
+ LPSTR lpWindowTitle;
+ BOOL fSetTitle = FALSE;
+ BOOL fVerbose = FALSE;
+ HDESK hDesk;
+
+
+ //
+ // First argument is debugger name
+ //
+ Assert( argc > 0 );
+ strcpy( DebuggerName, argv[0] );
+
+ //
+ // Initialize the debugger state. This state will very probably
+ // be overwritten later on by a workspace from the registry.
+ //
+ hInst = hInstance;
+ winVer = GetVersion();
+ OsVersionInfo.dwOSVersionInfoSize = sizeof(OsVersionInfo);
+ GetVersionEx( &OsVersionInfo );
+
+ InitFileExtensions();
+ InitializeDocument();
+ InitCodemgr();
+
+ InitDefaultRunDebugParams( &rd );
+
+ Dbg(hAccTable = LoadAccelerators(hInst, MAKEINTRESOURCE(QCQPMAINACC)));
+
+ Dbg(LoadString(hInst, SYS_Main_wTitle, wTitle, MAX_MSG_TXT));
+ Dbg(LoadString(hInst, SYS_Main_wClass, wClass, MAX_MSG_TXT));
+
+ hEventIoctl = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+ InitializeCriticalSection( &csLog );
+
+ //
+ // Create the frame
+ //
+ hwndFrame = CreateWindow(wClass, wTitle,
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ NULL, NULL, hInstance, NULL);
+
+ //
+ // Initialize the debugger
+ //
+ if ( !hwndFrame || !FDebInit() || !hwndMDIClient ) {
+ return FALSE;
+ }
+
+ //
+ // Get Handle to main menu and to window submenu
+ //
+ Dbg( hMainMenu = GetMenu(hwndFrame));
+ hMainMenuSave = hMainMenu;
+ Dbg( hWindowSubMenu = GetSubMenu(hMainMenu, WINDOWMENU));
+
+ //
+ // Build Help file path
+ //
+ Dbg(LoadString( hInst, SYS_Help_FileExt, szTmp, _MAX_EXT) );
+ MakePathNameFromProg( (LPSTR)szTmp, szHelpFileName );
+
+ //
+ // Init Items Colors ,Environment and RunDebug params to their default
+ // values 'They will later be overrided by the values in .INI file
+ // but we ensure to have something coherent even if we can't load
+ // the .INI file
+ //
+ InitDefaults();
+
+ //
+ // Initialize Keyboard Hook
+ //
+ hKeyHook = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)KeyboardHook,
+ hInstance, GetCurrentThreadId() );
+
+ //
+ // Parse arguments
+ //
+ ProgramName[0] = '\0';
+ LpszCommandLine = NULL;
+
+ lp1 = GetCommandLine();
+ while (*lp1 == ' ' || *lp1 == '\t') {
+ lp1++;
+ }
+
+ // eat the command:
+ while (*lp1 && *lp1 != ' ' && *lp1 != '\t') {
+#ifdef DBCS
+ lp1 = CharNext(lp1);
+#else
+ lp1++;
+#endif
+ }
+
+
+ while (*lp1) {
+
+ // eat whitespace before arg
+
+ while (*lp1 == ' ' || *lp1 == '\t') {
+ lp1++;
+ }
+
+ if (*lp1 == '-' || *lp1 == '/') {
+
+ // pick up switches
+ BOOL fSwitch = TRUE;
+
+ ++lp1;
+
+ while (*lp1 && fSwitch) {
+
+ switch (*lp1++) {
+
+ case ' ':
+ case '\t':
+ fSwitch = FALSE;
+ break;
+
+ case 'a':
+ fIgnoreAll = TRUE;
+ break;
+
+ case 'd':
+ iDebugLevel = atoi( GetArg(&lp1) );
+ fSwitch = FALSE;
+ break;
+
+ case 'e':
+ // signal an event after process is attached
+ hEventGo = (HANDLE)atol(GetArg(&lp1));
+ fSwitch = FALSE;
+ break;
+
+ case 'g':
+ // go now switch
+ fGoNow = TRUE;
+ break;
+
+ case 'h':
+ SwitchH = TRUE;
+ rd.fInheritHandles = TRUE;
+ WorkspaceOverride |= WSO_INHERITHANDLES;
+ break;
+
+ case 'i':
+ IgnoreDefault = TRUE;
+ break;
+
+ case 'k':
+ //
+ // kernel debugging mode
+ //
+ SwitchK = TRUE;
+ strcpy(ProgramName,"ntoskrnl.exe");
+ rd.fKernelDebugger = TRUE;
+ lp2 = GetArg(&lp1);
+ if (_stricmp(lp2,"i386")==0) {
+ rd.KdParams.dwPlatform = 0;
+ } else if (_stricmp(lp2,"mips")==0) {
+ rd.KdParams.dwPlatform = 1;
+ } else if (_stricmp(lp2,"alpha")==0) {
+ rd.KdParams.dwPlatform = 2;
+ } else if (_stricmp(lp2,"ppc")==0) {
+ rd.KdParams.dwPlatform = 3;
+ }
+ lp2 = GetArg(&lp1);
+ if (strlen(lp2) > 3 && _strnicmp(lp2,"com",3)==0) {
+ lp2 += 3;
+ rd.KdParams.dwPort = strtoul(lp2, NULL, 0);
+ }
+ lp2 = GetArg(&lp1);
+ rd.KdParams.dwBaudRate = strtoul(lp2, NULL, 0);
+ break;
+
+ case 'l':
+ fSetTitle = TRUE;
+ lp2 = GetArg(&lp1);
+ lpWindowTitle = _strdup( lp2 );
+ break;
+
+ case 'm':
+ fMinimize = TRUE;
+ nCmdShow = SW_MINIMIZE;
+ WorkspaceOverride |= WSO_WINDOW;
+ break;
+
+ case 'p':
+ // attach to an active process
+ lAttachProcess = strtoul(GetArg(&lp1), NULL, 0);
+ if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ if (lAttachProcess < -1) {
+ ErrorBox2(hwndFrame, MB_TASKMODAL,
+ ERR_Invalid_Process_Id,
+ lAttachProcess);
+ }
+ }
+ fSwitch = FALSE;
+ break;
+
+ case 'r':
+ AutoRun = arCmdline;
+ NoPopups = TRUE;
+ PszAutoRun = _strdup( GetArg(&lp1) );
+ ShowWindow(hwndFrame, nCmdShow);
+ OpenDebugWindow( COMMAND_WIN, NULL, -1 );
+ fSwitch = FALSE;
+
+ if (CmdAutoRunInit() == FALSE) {
+ ErrorBox( ERR_File_Open, PszAutoRun );
+ exit(1);
+ }
+
+ break;
+
+ case 'R':
+ { // M00KLUDGE this should take quoted strings
+ char * pch = GetArg(&lp1);
+ lp2 = pch;
+ while (*pch != 0) {
+ if (*pch == '_') *pch = ' ';
+#ifdef DBCS
+ pch = CharNext(pch);
+#else
+ pch++;
+#endif
+ }
+ }
+ CmdExecuteLine( lp2 );
+ fSwitch = FALSE;
+ break;
+
+ case 's':
+ fRemoteServer = TRUE;
+ lp2 = GetArg(&lp1);
+ strcpy(PipeName,lp2);
+ break;
+
+ case 't':
+ AutoTest = TRUE;
+ break;
+
+ case 'v':
+ fVerbose = TRUE;
+ break;
+
+ case 'w':
+ WorkSpaceSpecified = TRUE;
+ strcpy( WorkSpace, GetArg(&lp1) );
+ fSwitch = FALSE;
+ break;
+
+ case 'x': // BruceK
+ // Load this transport as the default. For testing.
+ // Must be preceded by -i switch.
+ if (IgnoreDefault) {
+ LpszCommandLineTransportDll = _strdup( GetArg(&lp1) );
+ } else {
+ --lp1;
+ ErrorBox2(hwndFrame, MB_TASKMODAL,
+ ERR_Invalid_Command_Line_File,
+ GetArg(&lp1));
+ }
+ fSwitch = FALSE;
+ break;
+
+ case 'y':
+ fSymPath = TRUE;
+ lp2 = GetArg(&lp1);
+ strcpy(SymPath,lp2);
+ break;
+
+ case 'z':
+ fCrashDump = TRUE;
+ lp2 = GetArg(&lp1);
+ strcpy(CrashDump,lp2);
+ break;
+
+ default:
+ --lp1;
+ ErrorBox2( hwndFrame, MB_TASKMODAL,
+ ERR_Invalid_Command_Line_Option,
+ (LPSTR) GetArg(&lp1));
+ break;
+ }
+ }
+
+ } else {
+
+ // pick up file args. If it is a program name,
+ // keep the tail of the cmd line intact.
+ char *lpSave = lp1;
+
+ AnsiUpper( lp2 = GetArg(&lp1) );
+
+ if (!*lp2) {
+
+ continue;
+
+ } else {
+
+ _fullpath(rgch, lp2, sizeof(rgch));
+ _splitpath(rgch, szDrive, szDir, szFName, szExt);
+
+ if ( !_stricmp( szExt, szStarDotExe+1 ) ||
+ !_stricmp( szExt, szStarDotCom+1 ) ||
+ ( *szExt == '\0' ) )
+ {
+ //
+ // Program name. Get the command line.
+ //
+ strcpy( ProgramName, GetArg(&lpSave));
+ if (*lp1) {
+ // it must be a space or tab...
+ // if it is a tab, we are wrong...
+ ++lp1;
+ }
+ LpszCommandLine = _strdup(lp1);
+ break;
+
+ } else {
+
+ ShowWindow(hwndFrame, SW_SHOWNORMAL);
+
+ //
+ // Source file name
+ //
+ AddFile( MODE_OPENCREATE,
+ DOC_WIN,
+ rgch,
+ NULL,
+ NULL,
+ FALSE,
+ -1,
+ -1
+ );
+ fJustSource = TRUE;
+ IgnoreDefault = TRUE;
+ }
+ }
+ }
+ }
+
+ //
+ // Boost thread priority to improve performance.
+ //
+ if (!AutoTest) {
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+ }
+
+ if ( IgnoreDefault && WorkSpaceSpecified ) {
+ ErrorBox2( hwndFrame, MB_TASKMODAL,
+ ERR_Invalid_Command_Line_File,
+ (LPSTR)"" );
+ }
+
+ if ( fMinimize || IgnoreDefault || !WorkSpaceExists(NULL, NULL)) {
+ ShowWindow(hwndFrame, nCmdShow);
+ UpdateWindow(hwndFrame);
+ }
+
+ //
+ // If there is no default workspace, create a new default.
+ //
+ if ( !IgnoreDefault && !WorkSpaceExists( NULL, NULL ) ) {
+ // force cmdwin
+ OpenDebugWindow( COMMAND_WIN, NULL, -1 );
+ SaveWorkSpace( NULL, NULL, FALSE );
+ CreatedNewDefault = TRUE;
+ }
+
+ LoadProgramMRUList();
+
+ //
+ // If a program was specified, load it.
+ //
+ if ( ProgramName[0] == '\0' && !WorkSpaceSpecified ) {
+
+ if ( !IgnoreDefault ) {
+ //
+ // Load the default workspace. Note that at this
+ // point there MUST exist a default workspace.
+ //
+ Dbg( LoadWorkSpace( NULL, NULL, FALSE ) );
+ }
+
+ } else if ( ProgramName[0] != '\0' && IgnoreDefault ) {
+
+ //
+ // Ignore workspaces in the registry, simply load
+ // the program.
+ //
+ LoadProgram( ProgramName );
+
+ } else {
+
+ //
+ // Determine the workspace to use.
+ //
+ if ( WorkSpaceSpecified ) {
+ if (ProgramName[0] == '\0') {
+ strcpy(ProgramName, GetCurrentProgramName(TRUE));
+ }
+ if ( WorkSpaceExists( ProgramName, WorkSpace ) ) {
+ WorkSpaceToUse = WorkSpace;
+ } else {
+ WorkSpaceMissed = TRUE;
+ }
+ }
+
+ if ( !WorkSpaceToUse ) {
+ if ( !GetDefaultWorkSpace( ProgramName, WorkSpace ) ) {
+ LoadedDefaultWorkSpace = TRUE;
+ } else if ( WorkSpaceExists( ProgramName, WorkSpace ) ) {
+ WorkSpaceToUse = WorkSpace;
+ } else {
+ Dbg(LoadString( hInstance, DLG_DefaultDoesNotExist, rgch, sizeof(rgch)));
+ MsgBox(GetActiveWindow(), rgch, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ LoadedDefaultWorkSpace = TRUE;
+ }
+ }
+
+ if ( !LoadWorkSpace( ProgramName, WorkSpaceToUse, FALSE ) ) {
+ //
+ // Could not load workspace.
+ //
+ LoadProgram( ProgramName );
+ WorkSpaceMissed = TRUE;
+ IgnoreDefault = TRUE;
+ }
+ }
+
+ WorkspaceOverride = 0;
+
+ if (IgnoreDefault || WorkSpaceMissed) {
+ // force cmdwin
+ CmdInsertInit();
+ }
+
+ if (SwitchK) {
+ runDebugParams.KdParams.dwPlatform = rd.KdParams.dwPlatform;
+ runDebugParams.KdParams.dwPort = rd.KdParams.dwPort;
+ runDebugParams.KdParams.dwBaudRate = rd.KdParams.dwBaudRate;
+ runDebugParams.fKernelDebugger = TRUE;
+ switch( runDebugParams.KdParams.dwPlatform ) {
+ case 0:
+ SetDllKey( DLL_EXEC_MODEL, "emx86" );
+ SetDllKey( DLL_EXPR_EVAL, "x86 c++" );
+ break;
+
+ case 1:
+ SetDllKey( DLL_EXEC_MODEL, "emmip" );
+ SetDllKey( DLL_EXPR_EVAL, "mips c++" );
+ break;
+
+ case 2:
+ runDebugParams.KdParams.dwPlatform = 2;
+ SetDllKey( DLL_EXEC_MODEL, "emalpha" );
+ SetDllKey( DLL_EXPR_EVAL, "alpha c++" );
+ break;
+
+ case 3:
+ runDebugParams.KdParams.dwPlatform = 3;
+ SetDllKey( DLL_EXEC_MODEL, "emppc" );
+ SetDllKey( DLL_EXPR_EVAL, "ppc c++" );
+ break;
+ }
+ }
+
+ if (SwitchH) {
+ runDebugParams.fInheritHandles = rd.fInheritHandles;
+ }
+
+ if (fIgnoreAll) {
+ runDebugParams.fIgnoreAll = TRUE;
+ }
+
+ if (fVerbose) {
+ runDebugParams.fVerbose = TRUE;
+ }
+
+ if (fSymPath) {
+ ModListSetSearchPath( SymPath );
+ }
+
+ if (fCrashDump) {
+ if (InitCrashDump( CrashDump, SymPath )) {
+ ModListSetSearchPath( SymPath );
+ fGoNow = TRUE;
+ if (runDebugParams.fUserCrashDump) {
+ strcpy( ProgramName, CrashDump );
+ }
+ }
+ }
+
+ if (runDebugParams.fKernelDebugger) {
+ if (fRemoteServer) {
+ runDebugParams.fCommandRepeat = TRUE;
+ }
+ runDebugParams.fMasmEval = TRUE;
+ }
+
+ if (fSetTitle) {
+ strcpy( runDebugParams.szTitle, lpWindowTitle );
+ SetWindowText( hwndFrame, lpWindowTitle );
+ }
+
+ CheckMenuItem( hMainMenu, IDM_WINDOW_SOURCE_OVERLAY,
+ FSourceOverlay ? MF_CHECKED : MF_UNCHECKED );
+
+ GetComPorts();
+
+
+ if ( WorkSpaceMissed ) {
+ Dbg(LoadString( hInstance, DLG_NoSuchWorkSpace, rgch, sizeof(rgch)));
+ MsgBox(GetActiveWindow(), rgch, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+
+ if (runDebugParams.LfOptAuto) {
+ LogFileOpen(runDebugParams.szLogFileName,runDebugParams.LfOptAppend);
+ }
+
+ if (fRemoteServer) {
+ StartRemoteServer( "stop", FALSE );
+ StartRemoteServer( PipeName, FALSE );
+ }
+
+ if (fGoNow) {
+ if (runDebugParams.KdParams.fUseCrashDump) {
+ char *av[2] = {"ntoskrnl",NULL};
+ RestartDebuggee( 1, av );
+ } else if (lAttachProcess == -2 || *ProgramName) {
+ ExecDebuggee(EXEC_GO);
+ }
+ }
+
+ if (lAttachProcess != -2) {
+ if (!AttachDebuggee(lAttachProcess, hEventGo)) {
+ CmdLogVar(ERR_Attach_Failed);
+ } else {
+
+ // stopped at ldr BP in bogus thread:
+ LptdCur->fGoOnTerm = TRUE;
+
+ if (fGoNow || hEventGo || runDebugParams.fAttachGo) {
+ Go();
+ } else if (!DoStopEvent(NULL)) {
+ CmdLogVar(DBG_Attach_Stopped);
+ }
+
+ if (hEventGo) {
+ hDesk = GetThreadDesktop(GetCurrentThreadId());
+ if (hDesk) {
+ SwitchDesktop(hDesk);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+void
+InitFileExtensions(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Load the standard file extensions into strings
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ // Standard File Extensions
+
+ Dbg(LoadString(hInst, DEF_Ext_C, szStarDotC, DOS_EXT_SIZE));
+ Dbg(LoadString(hInst, DEF_Ext_H, szStarDotH, DOS_EXT_SIZE));
+ Dbg(LoadString(hInst, DEF_Ext_CPP, szStarDotCPP, DOS_EXT_SIZE));
+ Dbg(LoadString(hInst, DEF_Ext_CXX, szStarDotCXX, DOS_EXT_SIZE));
+ Dbg(LoadString(hInst, DEF_Ext_EXE, szStarDotExe, DOS_EXT_SIZE));
+ Dbg(LoadString(hInst, DEF_Ext_COM, szStarDotCom, DOS_EXT_SIZE));
+ Dbg(LoadString(hInst, DEF_Ext_ALL, szStarDotStar, DOS_EXT_SIZE));
+
+ return;
+} /* InitFileExtensions() */
+
+
+void
+InitStatus (
+ HWND hWnd,
+ NPSTATUS st
+ )
+/*++
+
+Routine Description:
+
+ Initialize the Windbg status bar
+
+Arguments:
+
+ hwnd - Supplies handle to frame window
+ st - Supplies pointer to status info structure
+
+Return Value:
+
+ None
+
+--*/
+{
+ TEXTMETRIC metric;
+ PAINTSTRUCT ps;
+ HFONT oldFont;
+ int height ;
+#ifdef DBCS
+ CHARSETINFO csi;
+ DWORD dw = GetACP();
+
+ if (!TranslateCharsetInfo((DWORD*)dw, &csi, TCI_SRCCODEPAGE))
+ csi.ciCharset = ANSI_CHARSET;
+#endif /* DBCS */
+
+ //Initialize status bar information
+ memset(st, 0, sizeof(STATUS)); // Set all to 0 and FALSE
+ st->line = 0;
+ st->column = 0;
+
+ //Set Keyboard States
+
+ st->multiKey = FALSE;
+ st->numLock = (GetKeyState(VK_NUMLOCK) & 1);
+ st->capsLock = (GetKeyState(VK_CAPITAL) & 1);
+
+ //Set status text
+
+ st->lastTxt = 0;
+
+ // Set status bar to initially visible
+
+ st->hidden = FALSE ;
+
+ //VGA mode
+
+#if defined(DBCS)
+ height = 14 ;
+
+ if ( IsCGAmode ) height = 8 ;
+ else if ( IsEGAmode ) height = 10 ;
+#else
+ height = 16 ;
+
+ if ( IsCGAmode ) height = 8 ;
+ else if ( IsEGAmode ) height = 12 ;
+#endif
+
+ //Try to use the ANSI variable system font if we cannot use our Own
+
+#if defined(DBCS)
+ st->font = CreateFont(height, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
+ FALSE, csi.ciCharset, OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ FIXED_PITCH | FF_SWISS, "MS Shell Dlg") ;
+#else // !DBCS
+ st->font = CreateFont(height, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
+ FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ FIXED_PITCH | FF_SWISS, "Helv") ;
+#endif
+
+ if ( !st->font ) {
+#if defined(DBCS)
+ Dbg(st->font = GetStockObject(SYSTEM_FONT)) ;
+#else
+ st->font = GetStockObject(ANSI_VAR_FONT) ;
+ if ( !st->font ) {
+ //No avaible fonts, Use the system Font
+ Dbg(st->font = GetStockObject(SYSTEM_FONT)) ;
+ }
+#endif
+ }
+
+ //Calculate Height of font
+
+ BeginPaint (hWnd, &ps);
+ Dbg(oldFont = SelectObject(ps.hdc, st->font));
+ Dbg(GetTextMetrics(ps.hdc, &metric));
+ st->height = (WORD) (metric.tmHeight + metric.tmExternalLeading + 8);
+ st->charWidth = (WORD) (metric.tmAveCharWidth);
+ EndPaint (hWnd, &ps);
+
+ //Load ressources to init status display strings, speed require
+ //those strings loaded in heap
+
+ Dbg(LoadString(hInst, STS_MESSAGE_MULTIKEY, (LPSTR)status.multiKeyS, STATUS_MULTIKEY_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_OVERTYPE, (LPSTR)status.overtypeS, STATUS_OVERTYPE_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_READONLY, (LPSTR)status.readOnlyS, STATUS_READONLY_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_CAPSLOCK, (LPSTR)status.capsLockS, STATUS_CAPSLOCK_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_NUMLOCK, (LPSTR)status.numLockS, STATUS_NUMLOCK_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_LINE, (LPSTR)status.lineS, STATUS_LINE_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_COLUMN, (LPSTR)status.columnS, STATUS_COLUMN_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_SRC, (LPSTR)status.rgchSrcMode, STATUS_SRCMODE_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_ASM, (LPSTR)status.rgchSrcMode2, STATUS_SRCMODE_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_CURPID, (LPSTR)status.rgchCurPid, STATUS_CURPID_SIZE + 1));
+ Dbg(LoadString(hInst, STS_MESSAGE_CURTID, (LPSTR)status.rgchCurTid, STATUS_CURTID_SIZE + 1));
+
+ return;
+} /* InitStatus() */
+
+
+void
+InitRibbon(
+ HWND hWnd,
+ NPRIBBON rb
+ )
+/*++
+
+Routine Description:
+
+ Initialize the QcQp Ribbon info
+
+Arguments:
+
+ hwnd -
+ rb -
+
+Return Value:
+
+ None
+
+--*/
+{
+ TEXTMETRIC metric;
+ PAINTSTRUCT ps;
+ HFONT sysFont, oldFont;
+
+ //Initialize ribbon information
+ memset(rb, 0, sizeof(RIBBON)); //Set all to 0 and FALSE
+
+ // ribbon height based on size of system font
+
+ Dbg(sysFont = GetStockObject(SYSTEM_FONT));
+ BeginPaint(hWnd, &ps);
+ Dbg(oldFont = SelectObject(ps.hdc, sysFont));
+ Dbg(GetTextMetrics(ps.hdc, &metric));
+
+ // Allow 13 pixels spacing for VGA, 12 for EGA or HGC, and 9 for CGA.
+ // These spacing differences are due to the combobox height.
+
+ if ( IsCGAmode )
+ rb->height = (WORD) (metric.tmHeight + metric.tmExternalLeading + 9);
+ else if ( IsEGAmode )
+ rb->height = (WORD) (metric.tmHeight + metric.tmExternalLeading + 12);
+ else
+ rb->height = (WORD) (metric.tmHeight + metric.tmExternalLeading + 13);
+ EndPaint (hWnd, &ps);
+
+ rb->ribrect.top = 0;
+ rb->ribrect.bottom = rb->ribrect.top + rb->height-1;
+
+ rb->hidden = FALSE;
+ return;
+} /* InitRibbon() */
+
+
+
+VOID
+InitDefaultEnvironParams(
+ LPENVIRONPARAMS pParams
+ )
+/*++
+
+Routine Description:
+
+ Reset the QpQc Environment params to their default values
+
+Arguments:
+
+ pParams -
+
+Return Value:
+
+ None
+
+-*/
+{
+ pParams->tabStops = tabSize = DEFAULT_TAB;
+ pParams->keepTabs = TRUE;
+ pParams->vertScrollBars = TRUE;
+ pParams->horizScrollBars = TRUE;
+ pParams->SrchPath = TRUE;
+ pParams->undoRedoSize = UNDOREDO_DEF_SIZE; //In bytes
+
+ return;
+} /* InitDefaultEnvironParams() */
+
+
+VOID
+InitDefaultRunDebugParams(
+ LPRUNDEBUGPARAMS pParams
+ )
+/*++
+
+Routine Description:
+
+ Reset the QpQc Run/Debug params to their default values
+
+Arguments:
+
+ pParams -
+
+Return Value:
+
+ None
+
+--*/
+{
+ pParams->commandLine[0] = 0;
+ pParams->szTitle[0] = 0;
+ pParams->szRemotePipe[0] = 0;
+ pParams->szLogFileName[0] = 0;
+ pParams->debugMode = SOFT_DEBUG;
+ pParams->RegModeExt = TRUE;
+ pParams->RegModeMMU = 0;
+ pParams->DisAsmOpts = dopSym | dopFlatAddr | dopDemand | dopRaw;
+ pParams->fDebugChildren = TRUE;
+ pParams->fChildGo = TRUE;
+ pParams->fAttachGo = FALSE;
+ pParams->fGoOnThreadTerm = TRUE;
+ pParams->fNotifyThreadTerm = TRUE;
+ pParams->fNotifyThreadCreate = TRUE;
+ pParams->fCommandRepeat = FALSE;
+ pParams->fNoVersion = FALSE;
+ pParams->fInheritHandles = FALSE;
+ pParams->fKernelDebugger = FALSE;
+ pParams->fEPIsFirstStep = FALSE;
+ pParams->fWowVdm = FALSE;
+ pParams->fDisconnectOnExit = FALSE;
+ pParams->fAlternateSS = FALSE;
+ pParams->fIgnoreAll = TRUE;
+ pParams->fVerbose = TRUE;
+ pParams->fShortContext = TRUE;
+ pParams->fMasmEval = FALSE;
+ pParams->fShBackground = FALSE;
+
+ //
+ // setup the default kernel debugger options
+ //
+ pParams->KdParams.fInitialBp = FALSE;
+ pParams->KdParams.fUseModem = FALSE;
+ pParams->KdParams.fGoExit = FALSE;
+ pParams->KdParams.dwBaudRate = 19200;
+ pParams->KdParams.dwPort = 2;
+ pParams->KdParams.dwCache = 102400;
+#if defined(HOST_MIPS)
+ pParams->KdParams.dwPlatform = 1;
+#elif defined(HOST_i386)
+ pParams->KdParams.dwPlatform = 0;
+#elif defined(HOST_ALPHA)
+ pParams->KdParams.dwPlatform = 2;
+#elif defined(HOST_PPC)
+ pParams->KdParams.dwPlatform = 3;
+#endif
+ pParams->KdParams.szCrashDump[0] = 0;
+
+
+ UpdateRadix( 16 );
+ fCaseSensitive = FALSE;
+
+ return;
+} /* InitDefaultRunDebugParams() */
+
+
+VOID
+InitDefaultFont(
+ void
+ )
+{
+ //Set a default font
+
+#ifdef DBCS
+ CHARSETINFO csi;
+ DWORD dw = GetACP();
+
+ if (!TranslateCharsetInfo((DWORD*)dw, &csi, TCI_SRCCODEPAGE))
+ csi.ciCharset = ANSI_CHARSET;
+#endif
+ defaultFont.lfHeight = 10;
+ defaultFont.lfWidth = 0;
+ defaultFont.lfEscapement = 0;
+ defaultFont.lfOrientation = 0;
+ defaultFont.lfWeight = FW_NORMAL;
+ defaultFont.lfItalic = 0;
+ defaultFont.lfUnderline = 0;
+ defaultFont.lfStrikeOut = 0;
+#ifdef DBCS
+ /* use appropriate Character set font as default */
+ defaultFont.lfCharSet = csi.ciCharset;
+
+ /* Set device independent font size */
+ {
+ HDC hDC;
+ int nLogPixY;
+ int nHeight;
+ int nPoints = 100; //Point size * 10
+
+ hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
+ nLogPixY = GetDeviceCaps(hDC, LOGPIXELSY);
+ nHeight = (nPoints / 10) * nLogPixY;
+ if(nPoints % 10){
+ nHeight += MulDiv(nPoints % 10, nLogPixY, 10);
+ }
+ defaultFont.lfHeight = MulDiv(nHeight, -1, 72);
+ DeleteDC(hDC);
+ }
+#else // !DBCS
+ defaultFont.lfCharSet = ANSI_CHARSET;
+#endif // !DBCS end
+ defaultFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ defaultFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ defaultFont.lfQuality = DEFAULT_QUALITY;
+#ifdef DBCS // font facename is hardcoded...
+ defaultFont.lfPitchAndFamily = FIXED_PITCH;
+ lstrcpy((LPSTR) defaultFont.lfFaceName, (LPSTR)"Terminal");
+#else
+ defaultFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
+ lstrcpy((LPSTR) defaultFont.lfFaceName, (LPSTR)"Courier");
+#endif
+
+ return;
+} /* InitDefaultFont() */
+
+
+VOID
+InitDefaultFindReplace(
+ void
+ )
+{
+ int i, j;
+
+ //Initialize Replace/Find structure
+
+ findReplace.matchCase = FALSE;
+ findReplace.regExpr = FALSE;
+ findReplace.wholeWord = FALSE;
+ findReplace.goUp = FALSE;
+ findReplace.findWhat[0] = '\0';
+ findReplace.replaceWith[0] = '\0';
+ for (j = FIND_PICK; j <= REPLACE_PICK; j++) {
+ findReplace.nbInPick[j];
+ for (i = 0; i < MAX_PICK_LIST; i++)
+ findReplace.hPickList[j][i] = 0;
+ }
+ frMem.leftCol = 0;
+ frMem.rightCol = 0;
+ frMem.line = 0;
+ frMem.stopLine = 0;
+ frMem.stopCol = 0;
+ frMem.hDlgFindNextWnd = NULL;
+ frMem.hDlgConfirmWnd = NULL;
+ frMem.allTagged = FALSE;
+ frMem.replacing = FALSE;
+ frMem.replaceAll = FALSE;
+
+ return;
+} /* InitDefaultFindReplace() */
+
+
+void NEAR PASCAL
+InitTitleBar(
+ void
+ )
+{
+ Dbg(LoadString(hInst, SYS_Main_wTitle, (LPSTR)TitleBar.ProgName, sizeof(TitleBar.ProgName)));
+ TitleBar.UserTitle[0] = '\0';
+ TitleBar.ModeWork[0] = '\0';
+ Dbg(LoadString(hInst, TBR_Mode_Run, (LPSTR)TitleBar.ModeRun, sizeof(TitleBar.ModeRun)));
+ Dbg(LoadString(hInst, TBR_Mode_Break, (LPSTR)TitleBar.ModeBreak, sizeof(TitleBar.ModeBreak)));
+ TitleBar.Mode = TBM_WORK;
+}
+
+
+BOOLEAN
+InitDefaultDlls(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initializes the default workspace with some hard-coded values.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if successfully initialized
+
+--*/
+{
+ char szKeyBuf[MAX_PATH];
+
+
+ if (GetDllName(DLL_SYMBOL_HANDLER) == NULL) {
+ GetDefaultDllKey(DLL_SYMBOL_HANDLER, szKeyBuf);
+ SetDllKey(DLL_SYMBOL_HANDLER, szKeyBuf);
+ }
+
+ if (GetDllName(DLL_EXEC_MODEL) == NULL) {
+ GetDefaultDllKey(DLL_EXEC_MODEL, szKeyBuf);
+ SetDllKey(DLL_EXEC_MODEL, szKeyBuf);
+ }
+
+ // If the user specified the -x[transport.dll] switch
+ // on the command line, initialize the default transport to
+ // that string.
+ if (LpszCommandLineTransportDll) {
+
+ SetDllName(DLL_TRANSPORT, LpszCommandLineTransportDll);
+
+ } else if (GetDllName(DLL_TRANSPORT) == NULL) {
+ GetDefaultDllKey(DLL_TRANSPORT, szKeyBuf);
+ SetDllKey(DLL_TRANSPORT, szKeyBuf);
+ }
+
+ if (GetDllName(DLL_EXPR_EVAL) == NULL) {
+ GetDefaultDllKey(DLL_EXPR_EVAL, szKeyBuf);
+ SetDllKey(DLL_EXPR_EVAL, szKeyBuf);
+ }
+
+
+ ModListInit();
+
+ ModListAdd( "NTOSKRNL.EXE", sheNone );
+ ModListAdd( "NTKRNLMP.EXE", sheNone );
+
+ ModListSetDefaultShe( sheDeferSyms );
+ ModListAddSearchPath( "%SystemRoot%\\symbols" );
+
+ SrcFileDirectory[0] = '\0';
+ ExeFileDirectory[0] = '\0';
+ DocFileDirectory[0] = '\0';
+ UserDllDirectory[0] = '\0';
+
+ return TRUE;
+}
+
+
+void FAR PASCAL
+InitDefaults(
+ void
+ )
+{
+ InitDefaultEnvironParams(&environParams);
+ InitDefaultRunDebugParams(&runDebugParams);
+ InitDefaultFindReplace();
+ InitDefaultFont();
+ InitTitleBar();
+
+ status.hidden = 0;
+
+ InitDefaultDlls();
+
+ return;
+} /* InitDefaults() */
diff --git a/private/windbg/windbg/kdopt.c b/private/windbg/windbg/kdopt.c
new file mode 100644
index 000000000..b54751e9e
--- /dev/null
+++ b/private/windbg/windbg/kdopt.c
@@ -0,0 +1,596 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ kdopt.c
+
+Abstract:
+
+
+Author:
+
+ Wesley Witt (wesw) 26-July-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include <ntiodump.h>
+
+typedef struct BROWSESTRUCT {
+ CHAR DefExt[16];
+ CHAR Filter[256];
+ CHAR Title[256];
+ CHAR FileName[256];
+} BROWSESTRUCT, *LPBROWSESTRUCT;
+
+BROWSESTRUCT ImageBrowse =
+ {
+ "dbg",
+ "Image Files(*.exe;*.dll;*.dbg)\0*.exe;*.dll;*.dbg",
+ "Image File Browse",
+ "*.exe;*.dll;*.dbg"
+ };
+
+BROWSESTRUCT DmpBrowse =
+ {
+ "dmp",
+ "Crash Dump Files\0*.dmp",
+ "Crash Dump File Browse",
+ "*.dmp"
+ };
+
+
+typedef struct _KDBAUDRATE {
+ DWORD dwBaudMask;
+ DWORD dwBaudRate;
+} KDBAUDRATE, *LPKDBAUDRATE;
+
+typedef struct _COMPORTINFO {
+ CHAR szSymName[16];
+ DWORD dwNum;
+ DWORD dwSettableBaud;
+} COMPORT_INFO, *LPCOMPORT_INFO;
+
+COMPORT_INFO ComPortInfo[100];
+DWORD MaxComPorts;
+DWORD CurComPort;
+
+LPSTR KdPlatforms[] = { "X86", "MIPS", "ALPHA", "PPC" };
+DWORD KdCacheSizes[] = { 102400, 512000, 1024000, 1024000};
+
+KDBAUDRATE KdBaudRates[] =
+ {
+ BAUD_075, 75,
+ BAUD_110, 110,
+ BAUD_150, 150,
+ BAUD_300, 300,
+ BAUD_600, 600,
+ BAUD_1200, 1200,
+ BAUD_1800, 1800,
+ BAUD_2400, 2400,
+ BAUD_4800, 4800,
+ BAUD_7200, 7200,
+ BAUD_9600, 9600,
+ BAUD_14400, 14400,
+ BAUD_19200, 19200,
+ BAUD_38400, 38400,
+ BAUD_56K, 56000,
+ BAUD_57600, 57600,
+ BAUD_128K, 128000,
+ BAUD_115200, 115200,
+ };
+
+#define KdMaxPlatforms (sizeof(KdPlatforms)/sizeof(LPSTR))
+#define KdMaxBaudRates (sizeof(KdBaudRates)/sizeof(KDBAUDRATE))
+#define KdMaxCacheSizes (sizeof(KdCacheSizes)/sizeof(DWORD))
+
+
+static BOOL KdOptonlyCrashDumpEnabled;
+
+
+static VOID
+KdOptEnableCrashDumpOnly(
+ HWND hDlg
+ )
+{
+ if (KdOptonlyCrashDumpEnabled == FALSE) {
+ EnableWindow (GetDlgItem (hDlg, ID_KD_BAUDRATE), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_PORT), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_CACHE), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_PLATFORM), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_INITIALBP), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_MODEM), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_ENABLE), FALSE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_GOEXIT), FALSE);
+ }
+
+ KdOptonlyCrashDumpEnabled = TRUE;
+
+ return;
+}
+
+static VOID
+KdOptEnableAllChildren(
+ HWND hDlg
+ )
+{
+ if (KdOptonlyCrashDumpEnabled == TRUE) {
+ EnableWindow (GetDlgItem (hDlg, ID_KD_BAUDRATE), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_PORT), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_CACHE), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_PLATFORM), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_INITIALBP), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_MODEM), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_ENABLE), TRUE);
+ EnableWindow (GetDlgItem (hDlg, ID_KD_GOEXIT), TRUE);
+ }
+
+ KdOptonlyCrashDumpEnabled = FALSE;
+
+ return;
+}
+
+
+
+DWORD
+GetComPorts(
+ VOID
+ )
+{
+ FILETIME ft;
+ HKEY hkey;
+ CHAR rgch[256];
+ CHAR szValueName[256];
+ CHAR szValueData[256];
+ DWORD i;
+ DWORD k;
+ DWORD PortNum;
+ DWORD dwSz1, dwSz2;
+ DWORD NumComPorts = 0;
+ DWORD dwType;
+ HANDLE hCommDev;
+ COMMPROP cmmp;
+
+
+ if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "Hardware\\DeviceMap\\SerialComm",
+ 0,
+ KEY_READ,
+ &hkey ) != ERROR_SUCCESS ) {
+ return FALSE;
+ }
+
+ i = sizeof(rgch);
+ if (RegQueryInfoKey( hkey, rgch, &i, NULL, &i, &i, &i,
+ &NumComPorts, &i, &i, &i, &ft ) != ERROR_SUCCESS) {
+ RegCloseKey( hkey );
+ return 0;
+ }
+
+ if (NumComPorts) {
+ k = 0;
+ i = 0;
+ while( TRUE ) {
+ dwSz1 = sizeof(szValueName);
+ dwSz2 = sizeof(szValueData);
+ if (RegEnumValue( hkey, i, szValueName, &dwSz1, NULL, &dwType,
+ szValueData, &dwSz2 ) != ERROR_SUCCESS) {
+ break;
+ }
+
+ sprintf( rgch, "\\\\.\\%s", szValueData );
+ hCommDev = CreateFile(
+ rgch,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ PortNum = strtoul(&szValueData[3], NULL, 0);
+
+ if ((hCommDev != INVALID_HANDLE_VALUE) ||
+ (hCommDev == INVALID_HANDLE_VALUE &&
+ runDebugParams.fKernelDebugger && DebuggeeActive() &&
+ PortNum == runDebugParams.KdParams.dwPort)) {
+ strcpy( ComPortInfo[k].szSymName, szValueData );
+ ComPortInfo[k].dwNum = PortNum;
+ if (hCommDev != INVALID_HANDLE_VALUE) {
+ GetCommProperties( hCommDev, &cmmp );
+ ComPortInfo[k].dwSettableBaud = cmmp.dwSettableBaud;
+ CloseHandle( hCommDev );
+ }
+ k++;
+ }
+ i++;
+ }
+ }
+
+ RegCloseKey( hkey );
+
+ return k;
+}
+
+VOID
+SetupControls(
+ HWND hDlg
+ )
+{
+ CHAR rgch[256];
+ DWORD i;
+ DWORD j;
+ HWND hCtl;
+
+
+ CheckDlgButton( hDlg, ID_KD_ENABLE, runDebugParams.fKernelDebugger );
+ CheckDlgButton( hDlg, ID_KD_GOEXIT, runDebugParams.KdParams.fGoExit );
+ CheckDlgButton( hDlg, ID_KD_INITIALBP, runDebugParams.KdParams.fInitialBp );
+
+ hCtl = GetDlgItem(hDlg,ID_KD_PORT);
+ SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
+ for (i=0,j=0; i<MaxComPorts; i++) {
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)ComPortInfo[i].szSymName);
+ if (ComPortInfo[i].dwNum == runDebugParams.KdParams.dwPort) {
+ CurComPort = i;
+ }
+ }
+ SendMessage(hCtl, CB_SETCURSEL, CurComPort, 0);
+
+ hCtl = GetDlgItem(hDlg,ID_KD_BAUDRATE);
+ SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
+ for (i=0,j=0; i<KdMaxBaudRates; i++) {
+ if (KdBaudRates[i].dwBaudMask & ComPortInfo[CurComPort].dwSettableBaud) {
+ sprintf(rgch,"%d",KdBaudRates[i].dwBaudRate);
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)rgch);
+ j++;
+ }
+ if (runDebugParams.KdParams.dwBaudRate == KdBaudRates[i].dwBaudRate) {
+ SendMessage(hCtl, CB_SETCURSEL, j-1, 0);
+ }
+ }
+
+ hCtl = GetDlgItem(hDlg,ID_KD_CACHE);
+ SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
+ for (i=0; i<KdMaxCacheSizes; i++) {
+ sprintf( rgch, "%d", KdCacheSizes[i] );
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)rgch);
+ if (runDebugParams.KdParams.dwCache == KdCacheSizes[i] ) {
+ SendMessage(hCtl, CB_SETCURSEL, i, 0);
+ }
+ }
+
+ hCtl = GetDlgItem(hDlg,ID_KD_PLATFORM);
+ SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
+ for (i=0; i<KdMaxPlatforms; i++) {
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)KdPlatforms[i]);
+ if (runDebugParams.KdParams.dwPlatform == (DWORD)i) {
+ SendMessage(hCtl, CB_SETCURSEL, i, 0);
+ }
+ }
+
+ SetDlgItemText( hDlg, ID_KD_CRASH, runDebugParams.KdParams.szCrashDump );
+
+ if (runDebugParams.KdParams.szCrashDump[0]) {
+ KdOptEnableCrashDumpOnly( hDlg );
+ } else {
+ KdOptEnableAllChildren( hDlg );
+ }
+}
+
+BOOL
+ValidateCrashDump(
+ HWND hwnd,
+ LPSTR CrashDump
+ )
+{
+ HANDLE hFile;
+ DUMP_HEADER DumpHeader;
+ DWORD cb;
+
+
+ hFile = CreateFile ( CrashDump,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+ if (hFile == INVALID_HANDLE_VALUE) {
+ MessageBox( hwnd,
+ "Crash dump file does not exist",
+ "Kernel Debugger Options Error",
+ MB_ICONSTOP | MB_OK | MB_SETFOREGROUND
+ );
+ return FALSE;
+ }
+
+ ReadFile( hFile, &DumpHeader, sizeof(DUMP_HEADER), &cb, NULL );
+ CloseHandle( hFile );
+
+ if ((DumpHeader.Signature != 'EGAP') ||
+ (DumpHeader.ValidDump != 'PMUD')) {
+ MessageBox( hwnd,
+ "Crash dump file specified is not really a crash dump!",
+ "Kernel Debugger Options Error",
+ MB_ICONSTOP | MB_OK | MB_SETFOREGROUND
+ );
+ return FALSE;
+ }
+
+ runDebugParams.KdParams.fUseCrashDump = TRUE;
+ runDebugParams.fKernelDebugger = TRUE;
+ runDebugParams.KdParams.fGoExit = FALSE;
+ runDebugParams.KdParams.fInitialBp = FALSE;
+ CurComPort = 0;
+
+ switch( DumpHeader.MachineImageType ) {
+ case IMAGE_FILE_MACHINE_I386:
+ runDebugParams.KdParams.dwPlatform = 0;
+ SetDllKey( DLL_EXEC_MODEL, "emx86" );
+ SetDllKey( DLL_EXPR_EVAL, "x86 c++" );
+ break;
+
+ case IMAGE_FILE_MACHINE_R4000:
+ case IMAGE_FILE_MACHINE_R10000:
+ runDebugParams.KdParams.dwPlatform = 1;
+ SetDllKey( DLL_EXEC_MODEL, "emmip" );
+ SetDllKey( DLL_EXPR_EVAL, "mips c++" );
+ break;
+
+ case IMAGE_FILE_MACHINE_ALPHA:
+ runDebugParams.KdParams.dwPlatform = 2;
+ SetDllKey( DLL_EXEC_MODEL, "emalpha" );
+ SetDllKey( DLL_EXPR_EVAL, "alpha c++" );
+ break;
+
+ case IMAGE_FILE_MACHINE_POWERPC:
+ runDebugParams.KdParams.dwPlatform = 3;
+ SetDllKey( DLL_EXEC_MODEL, "emppc" );
+ SetDllKey( DLL_EXPR_EVAL, "ppc c++" );
+ break;
+ }
+
+ strcpy( runDebugParams.KdParams.szCrashDump, CrashDump );
+
+ SetupControls( hwnd );
+
+ return TRUE;
+}
+
+
+BOOL
+BrowseForFile(
+ LPSTR FileName,
+ LPBROWSESTRUCT Browse
+ )
+{
+ OPENFILENAME of;
+ CHAR ftitle [MAX_PATH];
+ CHAR title [MAX_PATH];
+ CHAR fname [MAX_PATH];
+ CHAR filter [1024];
+ DWORD len;
+
+
+ ftitle[0] = 0;
+ strcpy( fname, Browse->FileName );
+ of.lStructSize = sizeof( OPENFILENAME );
+ of.hwndOwner = NULL;
+ of.hInstance = GetModuleHandle( NULL );
+ for (len=sizeof(Browse->Filter)-1; len>0; len--) {
+ if (Browse->Filter[len]) {
+ break;
+ }
+ }
+ memcpy( filter, Browse->Filter, len+2 );
+ of.lpstrFilter = filter;
+ of.lpstrCustomFilter = NULL;
+ of.nMaxCustFilter = 0;
+ of.nFilterIndex = 0;
+ of.lpstrFile = fname;
+ of.nMaxFile = MAX_PATH;
+ of.lpstrFileTitle = ftitle;
+ of.nMaxFileTitle = MAX_PATH;
+ of.lpstrInitialDir = NULL;
+ strcpy( title, Browse->Title );
+ of.lpstrTitle = title;
+ of.Flags = OFN_NOCHANGEDIR;
+ of.nFileOffset = 0;
+ of.nFileExtension = 0;
+ of.lpstrDefExt = Browse->DefExt;
+ of.lCustData = 0;
+ of.lpfnHook = NULL;
+ of.lpTemplateName = NULL;
+ if (GetOpenFileName( &of )) {
+ strcpy( FileName, fname );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+BOOL
+DlgKernelDbg(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ CHAR rgch[256];
+ BOOL b;
+ DWORD i;
+ DWORD j;
+ DWORD k;
+ HWND hCtl;
+ PIOCTLGENERIC pig;
+
+
+ switch (message) {
+ case WM_INITDIALOG:
+ //
+ // Set up the controls to reflect current values
+ //
+ MaxComPorts = GetComPorts();
+ SetupControls( hDlg );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK :
+
+ /*
+ * Transfer the options to global
+ *
+ * Now start looking at the rest and determine what needs to
+ * be updated
+ */
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_ENABLE) != 0);
+ if (b != runDebugParams.fKernelDebugger) {
+ runDebugParams.fKernelDebugger = b;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_GOEXIT) != 0);
+ if (b != runDebugParams.KdParams.fGoExit) {
+ runDebugParams.KdParams.fGoExit = b;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_KD_INITIALBP) != 0);
+ if (b != runDebugParams.KdParams.fInitialBp) {
+ runDebugParams.KdParams.fInitialBp = b;
+ }
+
+ i = SendDlgItemMessage(hDlg, ID_KD_PORT, CB_GETCURSEL, 0, 0);
+ runDebugParams.KdParams.dwPort = ComPortInfo[i].dwNum;
+
+ i = SendDlgItemMessage(hDlg, ID_KD_BAUDRATE, CB_GETCURSEL, 0, 0);
+ SendDlgItemMessage(hDlg, ID_KD_BAUDRATE, CB_GETLBTEXT, i, (LPARAM)rgch);
+ runDebugParams.KdParams.dwBaudRate = strtoul(rgch, NULL, 0);
+
+ i = SendDlgItemMessage(hDlg, ID_KD_CACHE, CB_GETCURSEL, 0, 0);
+ runDebugParams.KdParams.dwCache = KdCacheSizes[i];
+
+ i = SendDlgItemMessage(hDlg, ID_KD_PLATFORM, CB_GETCURSEL, 0, 0);
+ runDebugParams.KdParams.dwPlatform = i;
+
+ GetDlgItemText( hDlg, ID_KD_CRASH, runDebugParams.KdParams.szCrashDump,
+ sizeof( runDebugParams.KdParams.szCrashDump ) );
+
+ if (runDebugParams.KdParams.szCrashDump[0]) {
+ if (!ValidateCrashDump( hDlg, runDebugParams.KdParams.szCrashDump )) {
+ return TRUE;
+ }
+ }
+
+ if (LptdCur && DebuggeeAlive()) {
+ FormatKdParams( rgch, FALSE );
+ pig = (PIOCTLGENERIC) malloc( strlen(rgch) + 1 + sizeof(IOCTLGENERIC) );
+ if (!pig) {
+ return FALSE;
+ }
+ pig->ioctlSubType = IG_DM_PARAMS;
+ pig->length = strlen(rgch) + 1;
+ strcpy((LPSTR)pig->data,rgch);
+ OSDIoctl( LppdCur->hpid,
+ LptdCur->htid,
+ ioctlGeneric,
+ strlen(rgch) + 1 + sizeof(IOCTLGENERIC),
+ (LPV)pig );
+ free( pig );
+ }
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDCANCEL:
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_KDOPT_HELP));
+ return (TRUE);
+
+ default:
+ if (LOWORD(wParam) == ID_KD_PORT &&
+ HIWORD(wParam) == CBN_SELCHANGE) {
+ j = SendDlgItemMessage(hDlg,
+ ID_KD_PORT, CB_GETCURSEL, 0, 0);
+ hCtl = GetDlgItem(hDlg,ID_KD_BAUDRATE);
+ SendMessage(hCtl, CB_RESETCONTENT, 0, 0);
+ for (i=0,k=0; i<KdMaxBaudRates; i++) {
+ if (KdBaudRates[i].dwBaudMask
+ & ComPortInfo[j].dwSettableBaud) {
+ sprintf(rgch,"%d",KdBaudRates[i].dwBaudRate);
+ SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)rgch);
+ k += 1;
+ }
+ if (runDebugParams.KdParams.dwBaudRate
+ == KdBaudRates[i].dwBaudRate) {
+ SendMessage(hCtl, CB_SETCURSEL, k-1, 0);
+ }
+ }
+ CurComPort = j;
+ }
+
+ if (LOWORD(wParam) == ID_KD_CRASH &&
+ HIWORD(wParam) == EN_CHANGE) {
+ if (SendDlgItemMessage( hDlg, ID_KD_CRASH,
+ WM_GETTEXTLENGTH, 0, 0 )) {
+ KdOptEnableCrashDumpOnly( hDlg );
+ } else {
+ KdOptEnableAllChildren( hDlg );
+ }
+ }
+
+ if (LOWORD(wParam) == ID_KD_CRASH &&
+ HIWORD(wParam) == EN_KILLFOCUS) {
+
+ CHAR buf[MAX_PATH];
+
+ GetDlgItemText( hDlg, ID_KD_CRASH, buf, sizeof(buf)-1 );
+ if (buf[0] && ValidateCrashDump( hDlg, buf ) == FALSE) {
+ SendMessage( hDlg,
+ WM_NEXTDLGCTL,
+ (WPARAM)GetDlgItem( hDlg, ID_KD_CRASH ),
+ (LPARAM)TRUE
+ );
+ }
+ }
+
+ if (LOWORD(wParam) == ID_KD_CRASH_BROWSE &&
+ HIWORD(wParam) == BN_CLICKED) {
+ if (BrowseForFile( rgch, &DmpBrowse )) {
+ if (ValidateCrashDump( hDlg, rgch ) == FALSE) {
+ SendMessage( hDlg,
+ WM_NEXTDLGCTL,
+ (WPARAM)GetDlgItem( hDlg, ID_KD_CRASH ),
+ (LPARAM)TRUE
+ );
+ } else {
+ SetDlgItemText( hDlg, ID_KD_CRASH, rgch );
+ KdOptEnableCrashDumpOnly( hDlg );
+ }
+ }
+ }
+
+ break;
+ }
+ break;
+ }
+ return (FALSE);
+}
diff --git a/private/windbg/windbg/line.c b/private/windbg/windbg/line.c
new file mode 100644
index 000000000..ed02eb640
--- /dev/null
+++ b/private/windbg/windbg/line.c
@@ -0,0 +1,70 @@
+#include "precomp.h"
+#pragma hdrstop
+
+/*** DlgLine
+**
+** Synopsis:
+** bool = DlgLine(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to current dialog open
+** message - dialog message to be processed
+** wParam - info about message
+** lParam - info about message
+**
+** Returns:
+**
+** Description:
+** This function processes messages for the "LINE" dialog box.
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT
+DlgLine(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ int y;
+ Unused(lParam);
+
+ switch (message) {
+
+ case WM_COMMAND:
+ switch (wParam) {
+
+ case IDOK:
+ // Retrieve selected item text and compute line nbr
+
+ y = GetDlgItemInt(hDlg, ID_LINE_LINE, NULL, FALSE);
+
+ if (y <= 0) {
+ ErrorBox2(hDlg, MB_TASKMODAL, ERR_Goto_Line);
+ SetFocus(GetDlgItem(hDlg, ID_LINE_LINE));
+ } else {
+ GotoLine(curView, y, FALSE);
+ EndDialog(hDlg, TRUE);
+ }
+
+ return (TRUE);
+
+ case IDCANCEL :
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg,szHelpFileName,HELP_CONTEXT,ID_LINE_HELP));
+ return (TRUE);
+ }
+ break;
+ }
+
+ return (FALSE);
+} /* DlgLine() */
diff --git a/private/windbg/windbg/linklist.c b/private/windbg/windbg/linklist.c
new file mode 100644
index 000000000..a81c7c767
--- /dev/null
+++ b/private/windbg/windbg/linklist.c
@@ -0,0 +1,1245 @@
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define INC_MEMORY
+#define INC_LINKEDLIST
+#define INC_ASSERT
+
+#if 0
+#include "types.h"
+#include "cvinfo.h"
+#include "cvtypes.hxx"
+#include "shapi.hxx"
+#endif
+
+#include "linklist.h"
+
+//
+// Linked List Information
+//
+
+typedef struct _LLI *PLLI;
+typedef struct _LLE *PLLE;
+
+typedef struct _LLI {
+ PLLE plleHead;
+ PLLE plleTail;
+ DWORD chlleMac;
+ DWORD cbUserData; // How big the user data is
+ LLF llf; // LinkList Flags
+ LPFNKILLNODE lpfnKill; // Callback for deletion of node
+ LPFNFCMPNODE lpfnCmp; // Callback for node comparison
+ CRITICAL_SECTION cs;
+} LLI;
+
+//
+// Linked List Entry
+//
+
+// The data is an array of int64's. This is to ensure the data is always aligned on a natural boundary.
+
+typedef struct _LLE {
+#ifdef DEBUGVER
+ DWORD dwTest; // consistency check
+#endif
+ PLLE plleNext;
+#ifdef DBLLINK
+ PLLE pllePrev;
+#endif // DBLLINK
+ DWORDLONG rgdw[1]; // Variable length data
+} LLE;
+
+#ifdef DEBUGTRACE
+char buf[256];
+#endif
+
+//
+// These help keep the code clean
+//
+#define lliAlloc() ((PLLI)MHAlloc(sizeof(LLI)))
+#define lleAllocCb(cb) ((PLLE)MHAlloc(cb))
+#define FreePlli(plli) MHFree(plli)
+#define FreePlle(plle) MHFree((HDEP) (plle))
+//
+// PRIVATE INTERNAL ROUTINES
+//
+static VOID LLInsertPlle( PLLI, PLLE, PLLE, PLLE );
+static VOID LLDeletePlle( PLLI, PLLE, PLLE );
+//
+// Some debug stuff
+//
+#ifdef DEBUGVER
+#define WCONSIST (DWORD)0xfeedbeef
+#endif // DEBUGVER
+
+/*** LLPlliInit
+*
+* Purpose:
+* Create a new list with specified options
+*
+* Input:
+* cbUserData : Number of bytes for user data per node. Must be > 0.
+* llf : List type flags (llfNull, llfAscending, or llfDescending)
+* (indicates wether or not list is sorted)
+* lpfnKill : callback to application for node deletion notification
+* (may be NULL)
+* lpfnCmp : Node comparison callback. May be NULL for non-sorted
+* lists. Otherwise, required.
+*
+* Output:
+* Either returns valid PLLI for newly created list or NULL for failure.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+PLLI
+WINAPI
+LLPlliInit(
+ UINT cbUserData,
+ LLF llf,
+ LPFNKILLNODE lpfnKill,
+ LPFNFCMPNODE lpfnCmp
+ )
+{
+ PLLI plli;
+#ifdef DEBUGTRACE
+ char buf[256];
+#endif
+
+ Assert( cbUserData );
+ Assert( llf == llfNull || lpfnCmp );
+
+#ifdef DEBUGTRACE
+ sprintf(buf,
+ "LLPlliInit\tcbUserData: %d\tllf: %X\tKill: %X\tCmp: %x\n",
+ cbUserData, llf, lpfnKill, lpfnCmp);
+ OutputDebugString(buf);
+#endif
+
+ if ( plli = lliAlloc() ) {
+ memset( plli, 0, sizeof( LLI ) );
+ plli->cbUserData = cbUserData;
+ plli->lpfnKill = lpfnKill;
+ plli->lpfnCmp = lpfnCmp;
+ plli->llf = llf;
+ InitializeCriticalSection(&plli->cs);
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLPlliInit\tlplli: %X\t", lplli);
+ OutputDebugString(buf);
+#endif
+ }
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "plli: %X\n", plli);
+ OutputDebugString(buf);
+#endif
+
+ return plli;
+}
+
+/*** LLPlleCreate
+*
+* Purpose:
+* Allocate and initialize new node for list
+*
+* Input:
+* plli : List to create node for.
+*
+* Output:
+* Returns newly created node (zero filled) if successful, otherwise
+* NULL.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+PLLE
+WINAPI
+LLPlleCreate(
+ PLLI plli
+ )
+{
+ PLLE plle;
+ DWORD cbNode;
+
+ Assert( plli );
+
+ // Ensure that the list is OK
+
+#ifdef DEBUGVER
+ LLFCheckPlli( plli );
+#endif
+
+ // Compute size of node with user data area
+
+ cbNode = sizeof( LLE ) - sizeof( DWORD ) + plli->cbUserData;
+
+#ifdef DEBUGVER
+
+ // Debug version, we're going to stuff a "sentinel" on to the end of the
+ // user's data for consistency checks.
+
+ cbNode += sizeof( DWORD );
+#endif
+
+ // Allocate the node
+
+ if ( plle = (PLLE)MHAlloc( cbNode ) ) {
+ ZeroMemory( plle, cbNode );
+
+#ifdef DEBUGTRACE
+ sprintf(buf,
+ "LLPlleCreate\tplli: %X\tplle: %X\tcbNode: %d\n",
+ plli, plle, cbNode);
+ OutputDebugString(buf);
+#endif
+
+#ifdef DEBUGVER
+ // Stuff in the consistency check stuff
+
+ *(DWORD *)((BYTE *)plle + cbNode - sizeof( DWORD )) = WCONSIST;
+ plle->dwTest = WCONSIST;
+#endif
+ }
+ return plle;
+}
+
+
+/*** LLFAddPlleToLl
+*
+* Purpose:
+* Add a new node to the end of a list.
+*
+* Input:
+* plli : List to add node to.
+* plle : Node to append to list.
+*
+* Output:
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+VOID
+WINAPI
+LLAddPlleToLl(
+ PLLI plli,
+ PLLE plle
+ )
+{
+ Assert( plli );
+ Assert( plle );
+
+ EnterCriticalSection(&plli->cs);
+
+ Assert( plli->llf == llfNull );
+
+ // Initalize node: Since this is to be the last item in the list,
+ // pNext should be null. Also, the pPrev should point to the
+ // currently last item in the list (includes NULL)
+
+ plle->plleNext = NULL;
+#ifdef DBLLINK
+ plle->pllePrev = plli->plleTail;
+#endif
+
+ // Chalk up one more for the list
+
+ plli->chlleMac++;
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLAddPlleToLl\tplle: %X\tplli: %X\n", plle, plli);
+ OutputDebugString(buf);
+ sprintf(buf, "LLAddPlleToLl\tchlleMac: %d\n", plli->chlleMac);
+ OutputDebugString(buf);
+#endif
+
+ // If the pHead is NULL then initialize the pHead and pTail
+ // (you know, like this is the only item in the list)
+
+ if ( plli->plleHead == NULL ) {
+ plli->plleHead = plli->plleTail = plle;
+ } else {
+
+ // Otherwise, update the tail pointer and the pNext for the old tail
+
+ plli->plleTail->plleNext = plle;
+ plli->plleTail = plle;
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+ // Ensure that the list is OK
+
+#ifdef DEBUGVER
+ LLFCheckPlli( plli );
+#endif
+}
+
+/***
+*
+* Purpose:
+*
+* Input:
+*
+* Output:
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+VOID
+WINAPI
+LLInsertPlleInLl(
+ PLLI plli,
+ PLLE plleNew,
+ DWORD lParam
+ )
+{
+ DWORD fNeedPos = TRUE;
+ LPFNFCMPNODE lpfnCmp = plli->lpfnCmp;
+ LPVOID lpv = LLLpvFromPlle( plleNew );
+ PLLE plle = NULL;
+ PLLE pllePrev = NULL;
+ DWORD dwPos = 0;
+
+ Assert( plli );
+ Assert( plli->llf == llfNull || lpfnCmp );
+
+ EnterCriticalSection(&plli->cs);
+
+ switch( plli->llf ) {
+ case llfNull:
+ while( dwPos++ < LOWORD( lParam ) ) {
+ pllePrev = plle;
+ plle = LLPlleFindNext( plli, plle );
+ }
+ break;
+
+ case llfAscending:
+ while( fNeedPos && ( plle = LLPlleFindNext( plli, plle ) ) ) {
+ fNeedPos = lpfnCmp( LLLpvFromPlle( plle ), lpv, lParam ) == fCmpLT;
+ if ( fNeedPos ) {
+ pllePrev = plle;
+ }
+ }
+ break;
+
+ case llfDescending:
+ while( fNeedPos && ( plle = LLPlleFindNext( plli, plle ) ) ) {
+ fNeedPos = lpfnCmp( LLLpvFromPlle( plle ), lpv, lParam ) == fCmpGT;
+ if ( fNeedPos ) {
+ pllePrev = plle;
+ }
+ }
+ break;
+ }
+
+ LLInsertPlle( plli, pllePrev, plleNew, plle );
+ LeaveCriticalSection(&plli->cs);
+}
+
+/*** LLFDeletePlleIndexed
+*
+* Purpose:
+* Delete the ith node from a list.
+*
+* Input:
+* plli : List containing node to delete
+* lPos : zero based index of node to delete.
+*
+* Output:
+* Return TRUE for successful deletion, else FALSE.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+BOOL
+WINAPI
+LLFDeletePlleIndexed(
+ PLLI plli,
+ DWORD lPos
+ )
+{
+ PLLE plleKill;
+ PLLE pllePrev = NULL;
+ DWORD lPosCur = 0L;
+ DWORD fRet = FALSE;
+
+ Assert( plli );
+
+ EnterCriticalSection(&plli->cs);
+
+ plleKill = plli->plleHead;
+
+ // Make sure that we're not deleting past the end of the list!
+
+ if ( lPos < plli->chlleMac ) {
+
+ // Chug through the list until we find the sucker to kill!
+
+ while ( lPos != lPosCur ) {
+ pllePrev = plleKill;
+ plleKill = LLPlleFindNext( plli, plleKill );
+ ++lPosCur;
+ }
+ LLDeletePlle( plli, pllePrev, plleKill );
+ fRet = TRUE;
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+#ifdef DEBUGVER
+ LLFCheckPlli( plli );
+#endif
+
+ return fRet;
+}
+
+/*** LLFDeleteLpvFromLl
+*
+* Purpose:
+* Delete a node from a list containing lpv data.
+*
+* Input:
+* plli : List containing node to delete
+* plle : Node to begin search for delete node at.
+* lpv : far pointer to comparison data. Passed onto compare callback.
+* lParam : Application supplied data. Just passed onto compare callback.
+*
+* Output:
+* Returns TRUE if node has been deleted, else FALSE
+*
+* Exceptions:
+*
+* Notes:
+* There must be a compare routine assiciated with this list!!!
+* For a doubly linked list, this is simple. For singly linked
+* list, we have to go through the list to get the previous node
+* to ensure that the pointers are correct.
+*
+*************************************************************************/
+BOOL
+WINAPI
+LLFDeleteLpvFromLl(
+ PLLI plli,
+ PLLE plle,
+ LPVOID lpv,
+ DWORD lParam
+ )
+{
+#ifdef DBLLINK
+ EnterCriticalSection(&plli->cs);
+
+ plle = LLPlleFindLpv( plli, plle, lpv, lParam );
+ if ( plle ) {
+ LLDeletePlle( plli, LLPlleFindPrev( plli, plle ), plle );
+ }
+
+#ifdef DEBUGVER
+ LLFCheckPlli( plli );
+#endif
+
+ LeaveCriticalSection(&plli->cs);
+
+ return plle != NULL;
+#else
+ PLLE plleNext;
+ LPFNFCMPNODE lpfnCmp = plli->lpfnCmp;
+
+ Assert( lpfnCmp );
+
+ EnterCriticalSection(&plli->cs);
+
+ // We're goint to delete the first occurance AFTER the one specified!
+
+ plleNext = LLPlleFindNext( plli, plle );
+
+ // Look up the data in the list
+
+ while( plleNext &&
+ lpfnCmp( LLLpvFromPlle( plleNext ), lpv, lParam ) != fCmpEQ ) {
+ plle = plleNext;
+ plleNext = LLPlleFindNext( plli, plleNext );
+ }
+
+ // if plleNext is non-null then we've found something to delete!!!
+
+ if ( plleNext ) {
+ LLDeletePlle( plli, plle, plleNext );
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+#ifdef DEBUGVER
+ LLFCheckPlli( plli );
+#endif
+
+ return plleNext != NULL;
+#endif
+}
+
+/*** LLPlleFindNext
+*
+* Purpose:
+* Get the next node in a list.
+*
+* Input:
+* plli : List to search in.
+* plle : Place to begin. If NULL, then return plleHead.
+*
+* Output:
+* Returns a handle to the next item in the list. NULL is returned
+* if the end of the list has been reached.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+PLLE
+WINAPI
+LLPlleFindNext(
+ PLLI plli,
+ PLLE plle
+ )
+{
+ PLLE plleRet;
+
+ EnterCriticalSection(&plli->cs);
+
+ // if plle is non-null, return the next handle
+
+ if ( plle ) {
+ plleRet = plle->plleNext;
+ } else {
+
+ // otherwise, we want the beginning of the list, so return the "head"
+
+ plleRet = plli->plleHead;
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+ return plleRet;
+}
+
+#ifdef DBLLINK
+
+/*** LLPlleFindPrev
+*
+* Purpose:
+* Get the previous node in a list. DOUBLY LINKED LIBRARY ONLY!!!
+*
+* Input:
+* plli : List to search in.
+* plle : Place to beging search at. If NULL, then return the
+* last node in the list.
+*
+* Output:
+* Return a handle to the previous node in the list, NULL if the
+* beginning of the list has been hit.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+PLLE
+WINAPI
+LLPlleFindPrev(
+ PLLI plli,
+ PLLE plle
+ )
+{
+ PLLE plleRet;
+
+ EnterCriticalSection(&plli->cs);
+
+ // if plle is non-null, return the next handle
+
+ if ( plle ) {
+ plleRet = plle->pllePrev;
+ } else {
+
+ // otherwise, we want the beginning of the list, so return the "head"
+
+ plleRet = plli->plleTail;
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+ return plleRet;
+}
+#endif // DBLLINK
+
+/*** LLChlleDestroyList
+*
+* Purpose:
+* Free all memory associated with a specified list. Completely
+* destroys the list. Must call PlliInit() to add new items to list.
+*
+* Input:
+* plli : List to destroy
+*
+* Output:
+* Returns number of nodes destroyed in list.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+DWORD
+WINAPI
+LLChlleDestroyLl(
+ PLLI plli
+ )
+{
+ DWORD cRet = 0;
+
+ Assert( plli );
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLChlleDestroyLl\tplli: %X\n", plli);
+ OutputDebugString(buf);
+#endif
+
+ EnterCriticalSection(&plli->cs);
+
+ while ( LLChlleInLl( plli ) != 0 ) {
+ LLFDeletePlleIndexed( plli, 0 );
+ ++cRet;
+ }
+ LeaveCriticalSection(&plli->cs);
+ DeleteCriticalSection(&plli->cs);
+ FreePlli( plli );
+ return cRet;
+}
+
+/*** LLPlleFindLpv
+*
+* Purpose:
+* Locate a node in a list containing specific data.
+*
+* Input:
+* plli : List to search in.
+* plle : Starting place to begin search. If NULL, start at
+* beginning of list.
+* lpv : Data passed on to compare callback for match.
+* lParam : Application supplied data. Just passed on to callback.
+*
+* Output:
+* Returns handle to node meeting compare criteria or NULL if not found.
+*
+* Exceptions:
+*
+* Notes:
+* Requires that list has a callback function.
+*
+*************************************************************************/
+PLLE
+WINAPI
+LLPlleFindLpv(
+ PLLI plli,
+ PLLE plle,
+ LPVOID lpvFind,
+ DWORD lParam
+ )
+{
+ PLLE plleRet = NULL;
+
+ Assert( plli );
+ Assert( plli->lpfnCmp );
+
+ EnterCriticalSection(&plli->cs);
+
+ plle = LLPlleFindNext( plli, plle );
+
+ while ( plle != NULL && plleRet == NULL ) {
+ if ( plli->lpfnCmp( (LPV)plle->rgdw, lpvFind, lParam ) == fCmpEQ ) {
+ plleRet = plle;
+ }
+ plle = LLPlleFindNext( plli, plle );
+ }
+ LeaveCriticalSection(&plli->cs);
+ return plleRet;
+}
+
+/*** LLFCheckPlli
+*
+* Purpose:
+* Consistency check for a list.
+*
+* Input:
+* plli : List to check.
+*
+* Output:
+* Returns non-null if list is OK, otherwise failure is indicated.
+*
+* Exceptions:
+*
+* Notes:
+* This is a debug only function. We will zip through the entire list
+* and check the head and tail words of EACH node for our magic WCONSIST
+* value. If either one is not correct, someone trashed a node. We also
+* check to see that the last node in the list is actually plleTail for the
+* list.
+*
+*************************************************************************/
+#ifdef DEBUGVER
+BOOL
+WINAPI
+LLFCheckPlli(
+ PLLI plli
+ )
+{
+ PLLE plle = NULL;
+ DWORD cbOffSet;
+ DWORD fRet;
+ PLLE plleLast;
+
+ Assert(plli);
+
+ EnterCriticalSection(&plli->cs);
+
+ cbOffSet = sizeof( LLE ) + plli->cbUserData - sizeof( DWORD );
+ plleLast = LLPlleFindNext( plli, NULL );
+
+ fRet = plli->cbUserData;
+ if ( plli->chlleMac ) {
+ fRet = fRet && plli->plleHead && plli->plleTail;
+ } else {
+ fRet = fRet && !plli->plleHead && !plli->plleTail;
+ }
+ while( fRet && ( plle = LLPlleFindNext( plli, plle ) ) ) {
+ fRet = ((plle->dwTest == WCONSIST &&
+ *((DWORD *)( (BYTE *)plle + cbOffSet )) == WCONSIST ));
+ plleLast = plle;
+ }
+ if ( fRet ) {
+ fRet = plleLast == plli->plleTail;
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+ Assert( fRet );
+ return fRet;
+}
+#endif // DEBUGVER
+
+/*** LLInsertPlle
+*
+* Purpose:
+* INTERNAL utility function to insert a node into a specified place
+* in the list. This will update the pointers and head/tail information
+* for the list.
+*
+* Input:
+* plli : List to insert node into.
+* pllePrev : Node which will appear right before the inserted one.
+* plle : Our newly created node.
+* plleNext : The node which will be immediately after the new one.
+*
+* Output:
+*
+* Exceptions:
+*
+* Notes:
+*
+* The caller must hold the critical section for the list while calling.
+*
+*************************************************************************/
+static
+VOID
+LLInsertPlle(
+ PLLI plli,
+ PLLE pllePrev,
+ PLLE plle,
+ PLLE plleNext
+ )
+{
+#ifdef DEBUGTRACE
+ sprintf(buf,
+ "LLInsertPlle\t plli: %X\tpllePrev: %X\tplle: %X\tplleNext: %x\n",
+ plli, pllePrev, plle, plleNext);
+ OutputDebugString(buf);
+#endif
+
+ // If there is a previous node, update its hnext
+
+ if ( pllePrev ) {
+ pllePrev->plleNext = plle;
+ } else {
+
+ // Otherwise, update the head
+
+ plli->plleHead = plle;
+ }
+
+ // Set the hNext for the new node
+
+ plle->plleNext = plleNext;
+
+ // We're adding to the end of the list, update the plleTail
+
+ if ( plleNext == NULL ) {
+ plli->plleTail = plle;
+ }
+
+#ifdef DBLLINK
+ else {
+ // If there is a next, update its hPrev
+ plleNext->pllePrev = plle;
+ }
+
+ // Set the hPrev for the new node
+
+ plle->pllePrev = pllePrev;
+#endif // DBLLINK
+
+ // Increment the number of items on the list
+
+ ++plli->chlleMac;
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLInsertPlle\t chlleMac: %d\n", plli->chlleMac);
+ OutputDebugString(buf);
+#endif
+
+}
+
+/*** LLFDeletePlleFromLl
+*
+* Purpose:
+* Delete a specified plle. Update head/tail and node pointers.
+*
+* Input:
+* plli : List containing node to delete.
+* plle : The node to destroy.
+*
+* Output:
+* None.
+*
+* Exceptions:
+*
+* Notes:
+* For doubly linked list, we could just use the pllePrev handle,
+* but there's no guarantee that the node is in the list specified.
+* So we do a look up just to make sure.
+*
+*************************************************************************/
+BOOL
+WINAPI
+LLFDeletePlleFromLl(
+ PLLI plli,
+ PLLE plle
+ )
+{
+ PLLE pllePrev = NULL;
+ PLLE plleCur = NULL;
+ DWORD fRet;
+
+ Assert( plli );
+ Assert( plle );
+
+ EnterCriticalSection(&plli->cs);
+
+ while( ( plleCur = LLPlleFindNext( plli, plleCur ) ) && plleCur != plle ) {
+ if (plleCur == plli->plleHead && pllePrev) {
+
+ // for some odd reason we have looped back around to the
+ // head of the list, and will loop endlessly.
+
+ Assert( !"cannot find entry in list, HELP i'm lost" );
+ break;
+ }
+ pllePrev = plleCur;
+ }
+ if ( fRet = ( plle == plleCur ) ) {
+#ifdef DEBUGTRACE
+ OutputDebugString("LLFDeletePlleFromLl calling LLDeletePlle\n");
+#endif
+ LLDeletePlle( plli, pllePrev, plle );
+ }
+
+ LeaveCriticalSection(&plli->cs);
+
+ return fRet;
+}
+
+/*** LLDeletePlle
+*
+* Purpose:
+* INTERNAL utility routine to delete a node. Update head/tail and
+* node pointers.
+*
+* Input:
+* plli : List containing node to delete.
+* pllePrev : Node immediately preceding node to be deleted in the list.
+* plle : The node to destroy.
+*
+* Output:
+* None.
+*
+* Exceptions:
+*
+* Notes:
+* Caller must hold the critical section while calling
+*
+*************************************************************************/
+static
+VOID
+LLDeletePlle(
+ PLLI plli,
+ PLLE pllePrev,
+ PLLE plle
+ )
+{
+ PLLE plleNext = LLPlleFindNext( plli, plle );
+
+#ifdef DEBUGTRACE
+ sprintf(buf,
+ "LLDeletePlle\t plli: %X\tpllePrev: %X\tplle: %X\tplleNext: %x\n",
+ plli, pllePrev, plle, plleNext);
+ OutputDebugString(buf);
+#endif
+
+ // If there is a previous node, update its hnext
+
+ if ( pllePrev ) {
+ pllePrev->plleNext = plleNext;
+#ifdef DEBUGTRACE
+ OutputDebugString("LLDeletePlle\t Removing from middle\n");
+#endif
+ } else {
+
+ // Otherwise, update the head
+
+ plli->plleHead = plleNext;
+#ifdef DEBUGTRACE
+ OutputDebugString("LLDeletePlle\t Removing from head\n");
+#endif
+ }
+
+ // We're adding to the end of the list, update the plleTail
+
+ if ( plleNext == NULL ) {
+#ifdef DEBUGTRACE
+ OutputDebugString("LLDeletePlle\t Removing from tail\n");
+#endif
+ plli->plleTail = pllePrev;
+ }
+
+#ifdef DBLLINK
+ else {
+ // If there is a next, update its hPrev
+ plleNext->pllePrev = pllePrev;
+ }
+#endif // DBLLINK
+
+ // Let the app free up its own mess for the data from this node
+
+ if ( plli->lpfnKill ) {
+ plli->lpfnKill( (LPVOID)plle->rgdw );
+ }
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLDeletePlle\t Kill Function: %X\n"
+ "LLDeletePlle\t Delete plle\n", plli->lpfnKill);
+ OutputDebugString(buf);
+#endif
+
+ FreePlle( plle );
+
+ // Decrement the number of items on the list
+
+ --plli->chlleMac;
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLDeletePlle\t chlleMac: %d\n", plli->chlleMac);
+ OutputDebugString(buf);
+#endif
+
+}
+
+/*** LLChlleInLl
+*
+* Purpose:
+* Return the number of nodes in a list
+*
+* Input:
+* plli : List to get count for
+*
+* Output:
+* Number of nodes in the list.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+DWORD
+WINAPI
+LLChlleInLl(
+ PLLI plli
+ )
+{
+ DWORD lRet;
+
+ Assert( plli );
+
+ EnterCriticalSection(&plli->cs);
+
+ lRet = plli->chlleMac;
+
+ LeaveCriticalSection(&plli->cs);
+
+ return lRet;
+}
+
+/*** LLLpvFromPlle
+*
+* Purpose:
+* Get a far pointer to the user data of a node. This locks the node
+* down. It is the application's responsibility to unlock it!
+*
+* Input:
+* plle : Node to get data for.
+*
+* Output:
+* A far pointer to the data.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+LPVOID
+WINAPI
+LLLpvFromPlle(
+ PLLE plle
+ )
+{
+#ifdef DEBUGVER
+ Assert(plle->dwTest == WCONSIST);
+#endif
+ return (LPVOID)( plle->rgdw );
+}
+
+/*** LLUnlockPlle
+*
+* Purpose:
+* Reverse the effects of LLLpvFromPlle
+*
+* Input:
+* plle : Node to be unlocked
+*
+* Output:
+* void
+*
+* Exceptions:
+*
+* Notes:
+*
+***********************************************************************/
+VOID
+WINAPI
+LLUnlockPlle(
+ PLLE plle
+ )
+{
+ return;
+}
+
+/*** LLPlleGetLast
+*
+* Purpose:
+* Get the last node in the specified list.
+*
+* Input:
+* plli : List to look up last item in.
+*
+* Output:
+* handle to the last item, or NULL if empty list.
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+PLLE
+WINAPI
+LLPlleGetLast(
+ PLLI plli
+ )
+{
+ Assert( plli );
+ return plli->plleTail;
+}
+
+
+/*** LLPlleAddToHeadOfLI
+*
+* Purpose:
+* Add a new node to the head of a list.
+*
+* Input:
+* plli : List to add node to.
+* plle : Node to append to list.
+*
+* Output:
+*
+* Exceptions:
+*
+* Notes:
+*
+*************************************************************************/
+void
+WINAPI
+LLPlleAddToHeadOfLI(
+ PLLI plli,
+ PLLE plle
+ )
+{
+ Assert( plli );
+ Assert( plle );
+
+ EnterCriticalSection(&plli->cs);
+ Assert( plli->llf == llfNull );
+
+ plle->plleNext = plli->plleHead;
+
+ // If the pHead is NULL then initialize the pTail
+ // (you know, like this is the only item in the list)
+
+ if ( plli->plleHead == NULL ) {
+ plli->plleTail = plle;
+ }
+ plli->plleHead = plle;
+
+#ifdef DBLLINK
+ plle->pllePrev = NULL;
+#endif
+
+ // Chalk up one more for the list
+ plli->chlleMac++;
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLPlleAddToHead\t plli: %X\tplleHead: %X\tplle: %X\tplleTail: %X\n",
+ plli, plle->plleNext, plle, plli->plleTail);
+ OutputDebugString(buf);
+ sprintf(buf, "LLPlleAddToHead\t chlleMac: %d\n", plli->chlleMac);
+ OutputDebugString(buf);
+#endif
+
+ LeaveCriticalSection(&plli->cs);
+
+#ifdef DEBUGVER
+ // Ensure that the list is OK
+ LLFCheckPlli( plli );
+#endif
+
+}
+
+/*** LLFRemovePlleFromLl
+*
+* Purpose:
+* Remove a specified plle. Update head/tail and node pointers.
+*
+* Input:
+* plli : List containing node to remove.
+* plle : The node to remove.
+*
+* Output:
+* None.
+*
+* Exceptions:
+*
+* Notes:
+* For doubly linked list, we could just use the pllePrev handle,
+* but there's no guarantee that the node is in the list specified.
+* So we do a look up just to make sure.
+*
+*************************************************************************/
+BOOL
+WINAPI
+LLFRemovePlleFromLl(
+ PLLI plli,
+ PLLE plle
+ )
+{
+ PLLE pllePrev = NULL;
+ PLLE plleCur = NULL;
+ PLLE plleNext;
+ DWORD fRet;
+ Assert( plli );
+ Assert( plle );
+
+ EnterCriticalSection(&plli->cs);
+
+ while( ( plleCur = LLPlleFindNext( plli, plleCur ) ) && plleCur != plle ) {
+ pllePrev = plleCur;
+ }
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLFRemovePlle\t plli: %X\tplle: %X\tplleCur: %X",
+ plli, plle, plleCur);
+ OutputDebugString(buf);
+#endif
+
+ if ( fRet = ( plle == plleCur ) ) {
+
+ plleNext = LLPlleFindNext( plli, plle );
+
+#ifdef DEBUGTRACE
+ sprintf(buf, "\tplleNext: %X\n", plleNext);
+ OutputDebugString(buf);
+ if (plleNext == plleCur) {
+ OutputDebugString("Next == Current!!!!!\n");
+ }
+#endif
+
+ // If there is a previous node, update its hnext
+ if ( pllePrev ) {
+ pllePrev->plleNext = plleNext;
+ } else {
+ // Otherwise, update the head
+ plli->plleHead = plleNext;
+ }
+
+ // We're adding to the end of the list, update the plleTail
+ if ( plleNext == NULL ) {
+ plli->plleTail = pllePrev;
+ }
+
+#ifdef DBLLINK
+ else {
+ // If there is a next, update its hPrev
+ plleNext->pllePrev = pllePrev;
+ }
+#endif // DBLLINK
+
+ // Decrement the number of items on the list
+ --plli->chlleMac;
+#ifdef DEBUGTRACE
+ sprintf(buf, "LLFRemovePlle\t chlleMac: %d\n", plli->chlleMac);
+ OutputDebugString(buf);
+#endif
+ }
+
+ LeaveCriticalSection(&plli->cs);
+#ifdef DEBUGVER
+ LLFCheckPlli( plli );
+#endif
+
+ return fRet;
+}
diff --git a/private/windbg/windbg/localwin.c b/private/windbg/windbg/localwin.c
new file mode 100644
index 000000000..addab2bef
--- /dev/null
+++ b/private/windbg/windbg/localwin.c
@@ -0,0 +1,667 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ localwin.c
+
+Abstract:
+
+ This module contains the routines to manipulate the Locals Window
+
+Author:
+
+ William J. Heaton (v-willhe) 20-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+/*
+ * Preprocessor
+ */
+
+#include "precomp.h"
+#pragma hdrstop
+
+BOOL AcceptValueUpdate(PTRVIT pVit,PPANE p);
+
+
+/*
+ * Global Memory (PROGRAM)
+ */
+
+
+extern CXF CxfIp; // The Current IP Context
+extern LPSHF Lpshf; // Pointer to SH function vector
+
+
+/*
+ * Global Memory (FILE)
+ */
+
+HWND hWndLocal;
+PTRVIT pvitLocal;
+
+/*
+ * Prototypes (Local)
+ */
+
+BOOL PASCAL NEAR GetLocalAtContext ( PTRVIT pvit, PCXF pcxf);
+BOOL UpdateLocalsVit(PCXF pCxf, BOOL Expand1st);
+/*
+ * Start of Code
+ */
+
+
+/*** GetLocalHWND
+**
+** Synopsis:
+** hWnd = GetLocalHWND()
+**
+** Entry:
+** None
+**
+** Returns:
+** Pointer to the current watch window handle.
+**
+*/
+
+HWND GetLocalHWND(VOID)
+{
+ return(hWndLocal);
+}
+
+
+/*** GetLocalAtContext Return a local linked list for the specified context
+**
+** Purpose:
+** Make a locals linked list for a given context
+**
+** Input:
+** pvit - pointer to a vit packet to where the linked list is to start
+** pctxt - pointer to a ctxt of the context.
+**
+** Output:
+** pvit - is filled in and the linked list is allocated and generated.
+**
+** Returns
+** TRUE/FALSE has the context changed.
+**
+**
+** Exceptions:
+**
+**
+*/
+
+BOOL PASCAL NEAR GetLocalAtContext ( PTRVIT pvit, PCXF pcxf )
+{
+ VIB vibT;
+ PTRVIB pvibCur;
+ int RetStatus = FALSE; // Default is context hasn't changed
+ EESTATUS RetErr;
+ CXF cxf;
+ HMEM hsyml = 0;
+ uint strIndex;
+
+ // If no Vit, we can't do anything (and the context has changed!)
+
+ if ( !pvit ) {
+ return(FALSE);
+ }
+
+ // If no Offset or Segment, same treatment
+
+ if ((GetAddrOff (*SHpADDRFrompCXT (SHpCXTFrompCXF (pcxf))) == 0) &&
+ (GetAddrOff (*SHpADDRFrompCXT (SHpCXTFrompCXF (pcxf))) == 0)) {
+ return(FALSE);
+ }
+
+ // copy context and frame and check to see if the context can
+ // handle locals.
+
+ cxf = *pcxf;
+
+ if (!ADDR_IS_LI (*SHpADDRFrompCXT (SHpCXTFrompCXF (&cxf))))
+ SYUnFixupAddr (SHpADDRFrompCXT (SHpCXTFrompCXF (&cxf)));
+
+
+ if( !( cxf.cxt.hBlk && cxf.cxt.hProc && cxf.cxt.hMod) ) {
+ pvit->cxf.cxt.hMod = 0;
+ pvit->cxf.cxt.hGrp = 0;
+ pvit->cxf.cxt.hProc = 0;
+ pvit->cxf.cxt.hBlk = 0;
+ pvit->cln = 0;
+ FTFreeAllSib( pvit->pvibChild );
+ pvit->pvibChild = NULL;
+ return(TRUE);
+ }
+
+
+ if ( pvit->cxf.cxt.hBlk == cxf.cxt.hBlk ) {
+ *SHpFrameFrompCxf(&pvit->cxf) = *SHpFrameFrompCxf(&cxf);
+ return(FALSE);
+ }
+
+
+ // Release the Locals tree
+
+ FTFreeAllSib( pvit->pvibChild );
+ pvit->pvibChild = NULL;
+ RetStatus = TRUE;
+
+ // fill in the Variable Info block Top and clear line count
+
+ pvit->cxf = cxf;
+ pvit->cln = 0;
+
+ // make a dummy Variable Info Block to start the search
+
+ pvibCur = &vibT;
+ pvibCur->pvibSib = pvit->pvibChild;
+
+ // make the linked list
+
+ EEGetHSYMList ( &hsyml, &cxf.cxt, HSYMR_lexical + HSYMR_function,
+ NULL, FALSE );
+
+ if ( hsyml != (HMEM) NULL ) {
+ PHSL_HEAD lphsymhead;
+ PHSL_LIST lphsyml;
+ WORD i = 0;
+ WORD j = 0;
+
+ // get the syms
+ lphsymhead = MMLpvLockMb ( hsyml );
+ lphsyml = (PHSL_LIST)(lphsymhead + 1);
+
+ for ( i = 0; i != lphsymhead->blockcnt; i++ ) {
+ for ( j = 0; j != lphsyml->symbolcnt; j++ ) {
+
+ // is this a displayable sym?
+ if ( SHCanDisplay ( lphsyml->hSym[j] ) ) {
+
+ HSYM hSym = lphsyml->hSym[j];
+
+ // get the new Variable Info Block. To maintain the tree, the old
+ // Variable Info Block is returned if it exists.
+
+ if ( !( pvibCur->pvibSib = FTvibGet ( pvibCur->pvibSib, (PTRVIB) pvit) ) ) {
+ goto nomoresyms;
+ }
+
+ // check to see if this Variable Info Block is an old vib that
+ // isn't correct anymore. We know offset is enough of a check
+ // because we checked the module above. If it is clear the vib chain.
+
+ if( pvibCur->pvibSib->vibPtr != vibUndefined &&
+ pvibCur->pvibSib->hSym != hSym ) {
+ FTvibInit(pvibCur->pvibSib, (PTRVIB) pvit);
+ }
+
+ // if we have a new tree, we must assign stuff
+
+ if ( pvibCur->pvibSib->vibPtr == vibUndefined ) {
+ DAssert (hSym != 0);
+ RetErr = EEGetTMFromHSYM(hSym,&pcxf->cxt,&pvibCur->pvibSib->hTMBd,
+ &strIndex, FALSE);
+
+ if ( RetErr != EENOERROR && RetErr != EECATASTROPHIC ) {
+ pvibCur->pvibSib = NULL;
+ goto nextsym;
+ }
+
+ // assign this stuff only once
+
+ pvibCur->pvibSib->hSym = hSym;
+ pvibCur->pvibSib->vibPtr = vibSymbol;
+
+ }
+
+ // update the parent's (Variable Info block Top) number count
+ // the vit is alway initialized to zero
+
+ pvibCur = pvibCur->pvibSib;
+ pvibCur->pvibParent->cln += pvibCur->cln;
+nextsym:
+ ; // must have a statement after a label
+ }
+ }
+ lphsyml = (PHSL_LIST) &(lphsyml->hSym[j]);
+ }
+
+nomoresyms:
+
+ MMbUnlockMb ( hsyml );
+ }
+
+ EEFreeHSYMList ( &hsyml );
+
+ // free any extra Variable Info Blocks
+
+ FTFreeAllSib ( pvibCur->pvibSib );
+ pvibCur->pvibSib = NULL;
+
+ // load in the child pointer from the dummy vit
+
+ pvit->pvibChild = vibT.pvibSib;
+ return(RetStatus);
+} /* GetLocalAtContext() */
+
+
+
+
+/*
+** void = UpdateLocalsVit(pCxf)
+**
+** Entry:
+** pCxf - pointer to context frame or Null if we are to use the
+** Current IP context frame.
+**
+** Returns:
+** Nothine
+**
+** Description:
+**
+*/
+
+BOOL UpdateLocalsVit(PCXF pCxf, BOOL Expand1st)
+{
+ PTRVIB pvib;
+
+ if ( pCxf == NULL )
+ pCxf = (PCXF)(&CxfIp);
+
+ if ( GetLocalAtContext(pvitLocal, pCxf) ) {
+
+ // Mark all top-level if need b
+ if ( Expand1st ) {
+ pvib = pvitLocal->pvibChild;
+ while ( pvib) {
+ pvib->flags.ExpandMe = TRUE;
+ pvib = pvib->pvibSib;
+ }
+ }
+ return(TRUE);
+ }
+
+ return(FALSE);
+} /* UpdateLocalsVit() */
+
+
+/*** InitLocalsVits
+**
+** Synopsis:
+** bool = InitLocalsVits()
+**
+** Entry:
+** Nothing
+**
+** Returns:
+** TRUE if the initialization was successful else FALSE
+**
+** Description:
+** This routine will allocate the initial structures which are used
+** to contain information describing the contents of the locals window
+*/
+
+
+BOOL NEAR PASCAL InitLocalsVits(void)
+{
+ pvitLocal = calloc(1, sizeof(VIT) );
+ return ( pvitLocal != NULL);
+
+}
+
+
+/*** FreeLocalsVits
+**
+** Synopsis:
+** void = FreeLocalsVits()
+**
+** Entry:
+** Nothing
+**
+** Returns:
+** None
+**
+** Description:
+** This function frees up the structures which describe the contents
+** of the locals window
+**
+*/
+
+void NEAR PASCAL FreeLocalsVits(void)
+{
+ FTFreeAllSib(pvitLocal->pvibChild);
+ pvitLocal->pvibChild = NULL;
+ free(pvitLocal);
+ pvitLocal = NULL;
+}
+
+
+
+/*** LocalEditProc
+**
+** Synopsis:
+** long = LocalEditProc(hwnd, msg, wParam, lParam)
+**
+** Entry:
+** hwnd - handle to window to process message for
+** msg - message to be processed
+** wParam - information about message to be processed
+** lParam - information about message to be processed
+**
+** Returns:
+**
+** Description:
+** MDI function to handle Localwindow messages
+**
+*/
+
+LONG FAR PASCAL LOADDS
+LocalEditProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ PPANE p = (PPANE)lParam;
+ PCXF pCxf = (PCXF)wParam;
+ PPANEINFO pInfo = (PPANEINFO)wParam;
+ LONG Len = 0;
+ LONG lLen = 0;
+ PTRVIB pVib = NULL;
+ PVTEXT pvtext;
+ ULONG i;
+ RECT Rect, tRect;
+ HWND hFoc;
+ HCURSOR hOldCursor, hWaitCursor;
+ CXF CxfLocal;
+
+
+ hFoc = GetFocus();
+
+ __try {
+
+ switch (msg) {
+
+ case WU_INITDEBUGWIN:
+ Dbg(InitLocalsVits());
+ hWndLocal = hwnd;
+ PostMessage(hwnd, WU_UPDATE, 0, 0L);
+ break;
+
+ case WM_DESTROY:
+ hWndLocal = NULL; // Lose the Local Window Handle
+ //
+ // fall thru...
+ //
+
+ case WU_DBG_UNLOADEE:
+ case WU_DBG_UNLOADEM:
+ if ( pvitLocal) {
+ FreeLocalsVits(); // Lose the Local Trees
+ SendMessage(p->hWndLeft, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, 1, 0);
+ p->MaxIdx = (WORD)1;
+ PostMessage(hwnd, WU_UPDATE, 0, 0L);
+ LocalFrameNumber = 0;
+ }
+ break;
+
+ case WU_DBG_LOADEM:
+ case WU_DBG_LOADEE:
+ if (!pvitLocal) {
+ Dbg(InitLocalsVits());
+ hWndLocal = hwnd;
+ PostMessage(hwnd, WU_UPDATE, 0, 0L);
+ }
+ break;
+
+ case WU_OPTIONS:
+ pVib = FTvibGetAtLine( pvitLocal, pInfo->ItemId);
+ if ( pVib == NULL) {
+ return FALSE;
+ }
+
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+
+ if ( pInfo->pFormat && (*(pvtext->pszValueC) != '{')) {
+ FTEnsureTextExists(pVib);
+
+ if ( pvtext->pszFormat) {
+ free(pvtext->pszFormat);
+ }
+ pvtext->pszFormat = _strdup(pInfo->pFormat);
+
+ if ( pvtext->pszValueC) {
+ free(pvtext->pszValueC);
+ }
+ pvtext->pszValueC = NULL;
+
+ PaneInvalidateRow(p);
+
+ } else {
+
+ FTEnsureTextExists(pVib);
+
+ if ( pvtext->pszFormat) {
+ free(pvtext->pszFormat);
+ }
+ pvtext->pszFormat = '\0';
+
+ if ( pvtext->pszValueC) {
+ free(pvtext->pszValueC);
+ }
+ pvtext->pszValueC = NULL;
+
+ PaneInvalidateRow(p);
+ }
+ return TRUE;
+
+ case WU_INFO:
+ //
+ // Default to a reasonable baseline
+ //
+ pInfo->pBuffer = pInfo->pFormat = NULL;
+ pInfo->NewText = FALSE;
+ pInfo->ReadOnly = TRUE;
+
+ pVib = FTvibGetAtLine( pvitLocal, pInfo->ItemId);
+ if ( pVib == NULL) {
+ return(FALSE);
+ }
+
+ FTEnsureTextExists(pVib);
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+
+ pInfo->pFormat = pvtext->pszFormat;
+ pInfo->pBuffer = FTGetPanelString( pvitLocal, pVib, pInfo->CtrlId);
+
+ if ( pInfo->CtrlId == ID_PANE_RIGHT) {
+ pInfo->ReadOnly = FALSE;
+ pInfo->NewText = FTGetPanelStatus( pVib, pInfo->CtrlId);
+ } else {
+ pInfo->ReadOnly = TRUE;
+ pInfo->NewText = FALSE;
+ }
+ return TRUE;
+
+ case WU_SETWATCH:
+ if ( pvitLocal == NULL) {
+ return(FALSE);
+ }
+ if ( p->nCtrlId == ID_PANE_RIGHT) {
+ BOOL retval;
+ fUseFrameContext = TRUE;
+ retval = (AcceptValueUpdate( pvitLocal, p));
+ if (retval == TRUE) {
+ UpdateDebuggerState(UPDATE_DATAWINS);
+ }
+ fUseFrameContext = FALSE;
+ return retval;
+ }
+ break;
+
+
+ case WU_INVALIDATE:
+ if (p == (PPANE)NULL) {
+ p = (PPANE)GetWindowLong(GetLocalHWND(), GWW_EDIT);
+ }
+
+ SendMessage(p->hWndLeft, LB_SETCOUNT, 0, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, 0, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, 0, 0);
+ p->MaxIdx = 0;
+ PostMessage(hwnd, WU_UPDATE, 0, 0L);
+ LocalFrameNumber = 0;
+
+ InvalidateRect(p->hWndButton, NULL, TRUE);
+ InvalidateRect(p->hWndLeft, NULL, TRUE);
+ InvalidateRect(p->hWndRight, NULL, TRUE);
+ UpdateWindow (p->hWndButton);
+ UpdateWindow (p->hWndLeft);
+ UpdateWindow (p->hWndRight);
+ break;
+
+ case WU_EXPANDWATCH:
+ if ( pvitLocal == NULL) {
+ return(FALSE);
+ }
+ if ( FTExpand(pvitLocal, (ULONG)(wParam)) != OK) {
+ return(FALSE);
+ }
+
+ p->LeftOk = p->RightOk = FALSE;
+ pCxf = &pvitLocal->cxf; // Update in vit context
+ //
+ // fall thru...
+ //
+
+ case WU_UPDATE:
+
+ //
+ // Globally indicate usage of Frame CONTEXT registers
+ // for the local window. Disable at end of case.
+ //
+ fUseFrameContext = TRUE;
+
+ if ( pvitLocal == NULL) {
+ return(FALSE);
+ }
+
+ if (LocalFrameNumber) {
+ CxfLocal = *ChangeFrame( LocalFrameNumber );
+ pCxf = &CxfLocal;
+ }
+
+ //
+ // Has the Context Changed?
+ //
+ if ( UpdateLocalsVit(pCxf, p->bFlags.Expand1st) || p->LeftOk == FALSE ) {
+
+ hWaitCursor = LoadCursor ((HANDLE)NULL, IDC_WAIT);
+ hOldCursor = SetCursor (hWaitCursor);
+
+ //
+ // Do we need to expand first level?
+ //
+ if ( p->bFlags.Expand1st) {
+ FTExpandOne(pvitLocal->pvibChild);
+ }
+
+ Len = (LONG)pvitLocal->cln;
+ p->MaxIdx = (WORD)Len;
+ lLen = SendMessage(p->hWndLeft, LB_GETCOUNT, 0, 0L);
+ lLen = (lLen < Len || lLen == 0) ? Len : lLen;
+
+ SendMessage( p->hWndLeft, LB_SETCOUNT, lLen, 0L );
+ SendMessage( p->hWndButton, LB_SETCOUNT, lLen, 0L );
+ SendMessage( p->hWndRight, LB_SETCOUNT, lLen, 0L );
+
+ //
+ // Resetting the count, lost where we were so put us back
+ //
+ if (p->MaxIdx > 0) {
+ PaneResetIdx(p, p->CurIdx);
+ }
+
+ p->LeftOk = TRUE;
+
+ } else {
+
+ // Set hourglass cursor
+ hWaitCursor = LoadCursor ((HANDLE)NULL, IDC_WAIT);
+ hOldCursor = SetCursor (hWaitCursor);
+
+ }
+
+ // Reset the right pane
+
+ FTAgeVibValues(pvitLocal->pvibChild);
+
+ for ( i= (ULONG)p->TopIdx;
+ i < (ULONG)(p->TopIdx + p->PaneLines) ; i++) {
+ if (FTVerifyNew(pvitLocal,i) ) {
+ PaneInvalidateItem( p->hWndRight, (PPANE)p, (SHORT)i);
+ }
+ }
+
+ p->RightOk = TRUE;
+
+ PaneCaretNum(p);
+
+ if ((hFoc == p->hWndButton) ||
+ (hFoc == p->hWndLeft) || (hFoc == p->hWndRight)) {
+ SendMessage(p->hWndButton ,
+ LB_GETITEMRECT,
+ (WPARAM)p->CurIdx,
+ (LPARAM)&Rect);
+ GetClientRect (p->hWndButton, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndButton, &tRect, TRUE);
+
+ SendMessage(p->hWndLeft ,
+ LB_GETITEMRECT,
+ (WPARAM)p->CurIdx,
+ (LPARAM)&Rect);
+ GetClientRect (p->hWndLeft, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndLeft, &tRect, TRUE);
+
+ SendMessage(p->hWndRight ,
+ LB_GETITEMRECT,
+ (WPARAM)p->CurIdx,
+ (LPARAM)&Rect);
+ GetClientRect (p->hWndRight, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndRight, &tRect, TRUE);
+ }
+
+
+ CheckPaneScrollBar( p, (WORD)Len);
+
+ // Set original cursor
+ hOldCursor = SetCursor (hOldCursor);
+
+ fUseFrameContext = FALSE;
+
+ break;
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ return FALSE;
+
+ }
+
+ return FALSE;
+} /* LocalEditProc() */
diff --git a/private/windbg/windbg/makeeng.c b/private/windbg/windbg/makeeng.c
new file mode 100644
index 000000000..74b26adca
--- /dev/null
+++ b/private/windbg/windbg/makeeng.c
@@ -0,0 +1,251 @@
+/*********************************************************************
+
+ File: makeeng.c
+
+ Date created: 27/8/90
+
+ Author: Tim Bell
+
+ Description:
+
+ Windows Make Engine API
+
+ Modified:
+
+*********************************************************************/
+
+#include "precomp.h"
+#pragma hdrstop
+
+BOOL NEAR PASCAL MkEngStartDebuggee(void);
+
+
+/*********************************************************************
+
+ Function: MkEngStartDebuggee
+
+ Description:
+
+*********************************************************************/
+BOOL NEAR PASCAL MkEngStartDebuggee(void)
+{
+ char *argv[2];
+ int argc = 2;
+ char Executable[ MAX_PATH ];
+
+ argv[0] = GetExecutableFilename(Executable, sizeof(Executable));
+
+ //
+ // Must start with space or lose first character
+ //
+ argv[1] = LpszCommandLine;
+
+ if (argv[0] == NULL) {
+ if (runDebugParams.fKernelDebugger) {
+ argv[0] = "ntoskrnl.exe";
+ } else if (runDebugParams.fUserCrashDump) {
+ argv[0] = runDebugParams.szUserCrashDump;
+ } else {
+ ErrorBox(ERR_No_DLL_Caller);
+ return FALSE;
+ }
+ }
+
+ //
+ // Note that RestartDebuggee disables the appropriate
+ // ribbon controls.
+ //
+ if (!RestartDebuggee(argc, argv)) {
+ return FALSE;
+ }
+
+ //
+ // Clear out the current source window view information
+ //
+ TraceInfo.doc = -1;
+
+ Assert( DebuggeeActive());
+
+ return TRUE;
+}
+
+
+
+/*** ExecDebuggee
+**
+** Synopsis:
+** bool = ExecDebuggee(ExecType)
+**
+** Entry:
+** ExecType - type of execution to be done
+**
+** Returns:
+** TRUE on success and FALSE on failure
+**
+** Description:
+** Executes the debuggee in the passed manner. Makes all
+** the necessary tests against the make to see if a
+** build should take place.
+**
+*/
+
+BOOL PASCAL ExecDebuggee(EXECTYPE ExecType)
+{
+ BOOL rVal = TRUE;
+ int View;
+ int line;
+
+ //
+ // If a process is half started, bail out
+ //
+ if (DbgState != ds_normal) {
+ MessageBeep(0);
+ return FALSE;
+ }
+
+ //
+ // For a restart we need to get the system to kill off any debuggee
+ // which may currently be active.
+ //
+ if ((ExecType == EXEC_RESTART) && DebuggeeAlive()) {
+ if (!KillDebuggee()) {
+ MessageBeep(0);
+ return FALSE;
+ }
+ }
+
+ //
+ // remember this before anybody gets a chance to
+ // mess with windows.
+ //
+ if (ExecType == EXEC_TOCURSOR) {
+ View = curView;
+ line = Views[View].Y;
+ }
+
+ //
+ // Check for legal thread and process states for issuing a command
+ // to the debugger. If it is not legal then beep and return.
+ //
+ // If there is not current process descriptor then all commands are
+ // legal.
+ //
+ if (LppdCur != NULL) {
+
+ //
+ // If no thread descriptor then all commands are legal:
+ //
+ if (LptdCur != NULL) {
+
+ //
+ // Check to see if the current thread is actually in a running state
+ // if so then beep and return immeadiately
+ //
+ if (LptdCur->tstate == tsRunning) {
+ MessageBeep(0);
+ return FALSE;
+ }
+ }
+ }
+
+ //
+ // If there is no child process running then we need to play some
+ // games to get it running.
+ //
+ if (!DebuggeeActive()) {
+ //
+ // Start up the child process.
+ //
+ if (!MkEngStartDebuggee()) {
+ //
+ // An error message has been printed out already.
+ //
+ return FALSE;
+ }
+
+ }
+
+ //
+ // Either there was a child running when we first came into this
+ // procedure or we successfully spawned up a child
+ //
+
+ //
+ // check with all windows for their approval about running the
+ // program. This will give then a change to update machine state
+ //
+
+ if (!DbgCommandOk()) {
+ return FALSE;
+ }
+
+ //
+ // Stepping of frozen threads and processes
+ //
+ switch (ExecType) {
+ case EXEC_RESTART:
+ case EXEC_GO:
+ break;
+
+ case EXEC_STEPANDGO:
+ case EXEC_TOCURSOR:
+ case EXEC_TRACEINTO:
+ case EXEC_STEPOVER:
+ if (LppdCur->fFrozen || LptdCur->fFrozen) {
+ MessageBeep(0);
+ return FALSE;
+ }
+ }
+
+ switch (ExecType) {
+
+ case EXEC_RESTART:
+ //
+ // We have gotten the system to get started. Now make sure
+ // that the screen gets updated since we will not be getting
+ // any "funny" messages from the system to get the screen
+ // updated.
+ //
+ UpdateDebuggerState(UPDATE_ALLSTATES & ~UPDATE_SOURCE);
+ break;
+
+ case EXEC_GO:
+ //
+ // Just run the program and be done with it. We will later
+ // get back a message which will case updating of the
+ // screen
+ //
+ Go();
+ break;
+
+ case EXEC_STEPANDGO:
+ break;
+
+ case EXEC_TOCURSOR:
+ if (!ContinueToCursor(View, line)) {
+ MessageBeep(0);
+ return FALSE;
+ }
+ break;
+
+ case EXEC_TRACEINTO:
+ //
+ // Execute the command. If in source mode and the debuggee
+ // is not yet running then these routines will cause the
+ // child to be run to either the main entry point or a
+ // debuggee event which stops execution.
+ //
+ if (Step(FALSE, status.fSrcMode ? ASMSTEPPING : SRCSTEPPING) == FALSE) {
+ return FALSE;
+ }
+ break;
+
+ case EXEC_STEPOVER:
+ if (Step(TRUE, status.fSrcMode ? ASMSTEPPING : SRCSTEPPING) == FALSE) {
+ return FALSE;
+ }
+ break;
+
+ }
+ return TRUE;
+}
diff --git a/private/windbg/windbg/makefile b/private/windbg/windbg/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/windbg/windbg/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/windbg/windbg/makefile.inc b/private/windbg/windbg/makefile.inc
new file mode 100644
index 000000000..42bc3ca51
--- /dev/null
+++ b/private/windbg/windbg/makefile.inc
@@ -0,0 +1,9 @@
+obj\$(TARGET_DIRECTORY)\res_str.i: include\res_str.h
+!IF "$(LANGUAGE)"=="JPN" || "$(LANGUAGE)"=="CHS" || "$(LANGUAGE)"=="CHT" || "$(LANGUAGE)"=="KOR"
+ $(TARGET_CPP) -EP -DRESOURCES -DDBCS -DFE_IME -Tc include\res_str.h > $@
+!ELSE
+ $(TARGET_CPP) -EP -DRESOURCES -Tc include\res_str.h > $@
+!ENDIF
+
+obj\$(TARGET_DIRECTORY)\windbg.res: obj\$(TARGET_DIRECTORY)\res_str.i dialogs.dlg
+
diff --git a/private/windbg/windbg/memory.c b/private/windbg/windbg/memory.c
new file mode 100644
index 000000000..7287b3b38
--- /dev/null
+++ b/private/windbg/windbg/memory.c
@@ -0,0 +1,282 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Memory.c
+
+Abstract:
+
+ This module contains the memory options dialog callback and supporting
+ routines to choose options for memory display.
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 26-Jul-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+
+
+extern EI Ei;
+#define Lpei (&Ei)
+extern CXF CxfIp;
+#define SHpFrameFrompCXF(a) (&(a)->Frame)
+
+
+
+
+/****************************************************************************/
+
+/*** FillFormatListbox
+**
+** Synopsis:
+** void = FillFormatListbox(hDlg)
+**
+** Entry:
+** hDlg - handle to dialog box
+**
+** Returns:
+** nothing
+**
+** Description:
+** Fill in the list box containning the list of formats for
+** the memory display window.
+**
+*/
+
+void PASCAL NEAR FillFormatListbox(HWND hDlg)
+{
+ int i;
+ char* lpsz;
+ UINT cBits;
+ UINT fmtType;
+ UINT uradix;
+ UINT fTwoField;
+ UINT cchMax;
+
+ for (i=0;EEFormatEnumerate(i, &cBits, &fmtType, &uradix, &fTwoField, &cchMax, &lpsz) == xosdNone; i++)
+ {
+ SendDlgItemMessage (hDlg, ID_MEMORY_FORMAT, LB_ADDSTRING, 0, (LPARAM) lpsz);
+ }
+
+ return;
+} /* FillFormatListbox() */
+
+/*** FGetInfo
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+static BOOL PASCAL FGetInfo(HWND hDlg)
+{
+ static char rgch[MAX_MSG_TXT];
+ HTM hTm;
+ uint us ;
+
+ // The expression must be parseable before it can be accepted.
+
+ GetDlgItemText(hDlg, ID_MEMORY_ADDRESS, ( LPSTR ) rgch, sizeof(rgch));
+
+ if (EEParse(rgch, radix, ( SHFLAG ) fCaseSensitive, &hTm, &us) != EENOERROR)
+ {
+ ErrorBox (ERR_Expression_Not_Parsable);
+ return FALSE;
+ }
+
+
+ // If the debugger is alive then it must also be bindable. If it is
+ // not a live expression then we will also get the address.
+
+
+ if (DebuggeeActive())
+ {
+ if ((EEBindTM (&hTm, SHpCXTFrompCXF (&CxfIp), TRUE, FALSE, FALSE) != EENOERROR) ||
+ (EEvaluateTM(&hTm, SHpFrameFrompCXF( &CxfIp), EEHORIZONTAL /* VERTICAL */) != EENOERROR))
+ {
+ ErrorBox (ERR_Expression_Not_Bindable);
+// EEFreeTM(&hTm);
+// return(FALSE);
+ }
+ }
+
+ EEFreeTM(&hTm);
+
+ // Now save the rest of the information
+
+ TempMemWinDesc.fLive = SendDlgItemMessage (hDlg, ID_MEMORY_LIVE, BM_GETCHECK, 0, 0);
+ TempMemWinDesc.fFill = SendDlgItemMessage (hDlg, ID_MEMORY_FILL, BM_GETCHECK, 0, 0);
+
+ if (TempMemWinDesc.atmAddress)
+ {
+ DeleteAtom(TempMemWinDesc.atmAddress);
+ }
+
+ TempMemWinDesc.atmAddress = AddAtom(rgch);
+ TempMemWinDesc.iFormat = SendDlgItemMessage(hDlg, ID_MEMORY_FORMAT, LB_GETCURSEL, 0, 0);
+
+ if (TempMemWinDesc.iFormat == LB_ERR)
+ {
+ TempMemWinDesc.iFormat = 0;
+ }
+
+ return(TRUE);
+} /* FGetInfo() */
+
+
+/*** DlgMemory
+**
+** Synopsis:
+** bool = DlgMemory(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg - handle for the dialog box
+** message - Message number
+** wParam - parameter for message
+** lParam - parameter for message
+**
+** Returns:
+**
+**
+** Description:
+** Processes messages for "memory options" dialog box
+**
+** MESSAGES:
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT DlgMemory(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ char drgch[MAX_MSG_TXT];
+ char trgch[MAX_MSG_TXT];
+ WORD wTitle;
+ BOOL lookAround = FALSE;
+
+ Unused(lParam);
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ *memText = '\0';
+
+ if (curView >= 0)
+ {
+ NPVIEWREC v = &Views[curView];
+
+ if (v->Doc >= 0)
+ {
+ GetSelectedText (curView, &lookAround, (LPSTR)&memText, MAX_MSG_TXT, 0, 0);
+ }
+
+ }
+
+ SendDlgItemMessage(hDlg, ID_MEMORY_LIVE, BM_SETCHECK, TempMemWinDesc.fLive, 0);
+ SendDlgItemMessage(hDlg, ID_MEMORY_FILL, BM_SETCHECK, TempMemWinDesc.fFill, 0);
+ SendDlgItemMessage(hDlg, ID_MEMORY_ADDRESS, EM_LIMITTEXT, MAX_MSG_TXT-1, 0);
+
+ if (TempMemWinDesc.atmAddress)
+ {
+ GetAtomName(TempMemWinDesc.atmAddress, drgch, sizeof(drgch));
+ }
+ else
+ {
+ if (*memText != '\0')
+ {
+ _fmemcpy (drgch, memText, MAX_MSG_TXT);
+ }
+ else
+ {
+ drgch[0] = '\0';
+ }
+
+ }
+ SetDlgItemText(hDlg, ID_MEMORY_ADDRESS, drgch);
+ FillFormatListbox(hDlg);
+ SendDlgItemMessage(hDlg, ID_MEMORY_FORMAT, LB_SETCURSEL,
+ TempMemWinDesc.iFormat, 0);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (wParam == IDOK)
+ {
+ if (FGetInfo(hDlg))
+ {
+ GetDlgItemText(hDlg, ID_MEMORY_ADDRESS, ( LPSTR ) TempMemWinDesc.szAddress, sizeof(TempMemWinDesc.szAddress));
+
+ if (memView != -1)
+ {
+ NPDOCREC d = &Docs[Views[memView].Doc];
+ NPVIEWREC v = &Views[memView];
+ int k = FindWindowMenuId(d->docType, memView, FALSE);
+
+ _fmemcpy (&MemWinDesc[memView], &TempMemWinDesc, sizeof(struct memWinDesc));
+
+ wTitle = SYS_MemoryWin_Title;
+ Dbg(LoadString(hInst, wTitle, trgch, MAX_MSG_TXT));
+ RemoveMnemonic(trgch, d->FileName);
+
+ lstrcat (d->FileName,"(");
+ lstrcat (d->FileName,MemWinDesc[memView].szAddress);
+ lstrcat (d->FileName,")");
+
+ RefreshWindowsTitle(v->Doc);
+
+ DeleteWindowMenuItem(memView);
+ AddWindowMenuItem(v->Doc, memView);
+
+ ViewMem(memView, TRUE);
+ }
+ EndDialog(hDlg, TRUE);
+ }
+ else
+ {
+ MessageBeep(0);
+ SetFocus (GetDlgItem (hDlg, ID_MEMORY_ADDRESS));
+ SendDlgItemMessage(hDlg, ID_MEMORY_ADDRESS, EM_SETSEL, 0, -1);
+ }
+ return (TRUE);
+ }
+ else
+ if (wParam == IDCANCEL)
+ {
+ EndDialog(hDlg, FALSE);
+ return (FALSE);
+ }
+ else
+ {
+ if (wParam == IDWINDBGHELP)
+ {
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_MEMORY_HELP));
+ }
+ }
+
+ break;
+
+ }
+ return (FALSE);
+} /* DlgMemory() */
+
+
+
+/*==========================================================================*/
diff --git a/private/windbg/windbg/memwin.c b/private/windbg/windbg/memwin.c
new file mode 100644
index 000000000..29e0a532a
--- /dev/null
+++ b/private/windbg/windbg/memwin.c
@@ -0,0 +1,1892 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Memwin.c
+
+Abstract:
+
+ This module contains the main line code for display of multiple memory
+ windows and the subclassed win proc to handle editing, display, etc.
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 26-Jul-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef FE_IME
+#include <ime.h>
+#include <winnls32.h>
+#endif
+
+
+
+extern unsigned int _ldused;
+
+extern unsigned int InMemUpdate; // prevent multiple viemem() calls
+
+extern EI Ei;
+#define Lpei (&Ei)
+#define SHpFrameFrompCXF(a) (&(a)->Frame)
+#if defined(DBCS)
+BOOL IsDBCSCharSet(DWORD cs);
+#else
+#define IsDBCSCharSet(c) TRUE // temporary
+#endif
+extern CXF CxfIp;
+
+void FAR * PASCAL MMLpvLockMb(HDEP hmem);
+void PASCAL MMbUnlockMb(HDEP hmem);
+
+static void NEAR GetMemText (void);
+
+int RgbFmts[] = MEM_FORMATS;
+
+struct memWinDesc MemWinDesc[MAX_VIEWS];
+struct memWinDesc TempMemWinDesc;
+char memText[MAX_MSG_TXT];
+char cMem[MAX_MSG_TXT]; //temp for edit/validation
+char cMemTemp[MAX_MSG_TXT]; //temp for edit/validation
+char cDoc[MAX_USER_LINE];
+BOOL fAscii = FALSE; // is memwin edit taking place in an ascii field
+ // with MW_BYTE / twofield representation?
+enum {
+ GOTO_FIRST,
+ GOTO_LAST,
+ GOTO_FIRSTONLINE,
+ GOTO_LASTONLINE,
+ GOTO_NEXT,
+ GOTO_PREVIOUS,
+};
+
+enum {
+ STARTED,
+ INPROGRESS,
+ FINISHED,
+};
+
+
+
+
+/*** UnformatDataItem
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+BOOL
+UnformatDataItem (
+ char * lpch,
+ char * lpb
+ )
+{
+ UINT cBits;
+ UINT fmtType;
+ UINT uradix;
+ UINT fTwoFields;
+ int cchMax;
+ char *lpIndx;
+ EESTATUS eeErr = EENOERROR;
+
+
+ Dbg(EEFormatEnumerate(MemWinDesc[memView].iFormat,
+ &cBits,
+ &fmtType,
+ &uradix,
+ &fTwoFields,
+ &cchMax,
+ NULL) == EENOERROR);
+
+
+ switch (MemWinDesc[memView].iFormat) {
+
+ case MW_ASCII:
+ if ((*lpch > 0x00) && (*lpch < 0x7F)) {
+ *lpb = *lpch;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+
+ case MW_BYTE:
+ if (fAscii == TRUE) {
+ if ((*lpch > 0x00) && (*lpch < 0x7F)) {
+ *lpb = *lpch;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ case MW_SHORT:
+ case MW_SHORT_HEX:
+ case MW_SHORT_UNSIGNED:
+ case MW_LONG:
+ case MW_LONG_HEX:
+ case MW_LONG_UNSIGNED:
+ case MW_QUAD:
+ case MW_QUAD_HEX:
+ case MW_QUAD_UNSIGNED:
+
+ if ((eeErr = EEUnformatMemory (lpb, lpch, cBits,
+ fmtType | fmtOverRide, uradix)) == EENOERROR) {
+ return TRUE;
+ }
+
+ case MW_REAL:
+ case MW_REAL_LONG:
+ case MW_REAL_TEN:
+ lpIndx = lpch;
+ do {
+ if (!(isdigit (*lpIndx))
+ && ((*lpIndx != '.')
+ && (*lpIndx != '+')
+ && (*lpIndx != '-')
+ && (*lpIndx != ' ')
+ && (*lpIndx != 'e')
+ && (*lpIndx != 'E')) )
+ {
+ return (FALSE);
+ }
+ lpIndx++;
+ } while (*lpIndx != '\0');
+ if ((eeErr = EEUnformatMemory (lpb, lpch, cBits,
+ fmtType | fmtOverRide, uradix)) == EENOERROR) {
+ return TRUE;
+ }
+
+ default:
+ return FALSE;
+
+ }
+
+ return FALSE;
+} /* UnformatDataItem() */
+
+
+
+/*** GotoField
+**
+** Synopsis:
+** void = GotoField(action)
+**
+** Entry:
+** action
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+static void NEAR
+GotoField(
+ WORD action
+ )
+{
+ int n;
+ int startX = Views[memView].X;
+ int startY = Views[memView].Y;
+
+
+ if (!DebuggeeActive() || !DebuggeeAlive()) {
+ return;
+ }
+
+
+ if (memView == -1) {
+ return;
+ }
+
+
+ if (MemWinDesc[memView].lpMi == NULL) {
+ PosXY(memView, 0, 0, FALSE);
+ }
+
+ if (startX < MemWinDesc[memView].lpMi[1].iStart) {
+ PosXY(memView, MemWinDesc[memView].lpMi[1].iStart, startY, FALSE);
+ GetMemText ();
+ return;
+ }
+
+ switch (action) {
+
+ case GOTO_FIRST:
+ startY = 0;
+ //fall through to set line element
+
+ case GOTO_FIRSTONLINE:
+ if ((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE)) {
+ n = (MemWinDesc[memView].cMi / 2) + 1;
+ } else {
+ n = 1;
+ }
+ break;
+
+ case GOTO_LAST:
+ startY = (Docs[Views[memView].Doc].NbLines - 1);
+ //fall through to set line element
+
+ case GOTO_LASTONLINE:
+ if ((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == FALSE)) {
+ n = (MemWinDesc[memView].cMi / 2);
+ } else {
+ n = MemWinDesc[memView].cMi - 1;
+ }
+ break;
+
+ case GOTO_NEXT:
+ for (n =
+ ((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE)) ?
+ ((int)((MemWinDesc[memView].cMi / 2) + 1))
+ : 1;
+
+ n < (MemWinDesc[memView].iFormat == MW_BYTE) ?
+ ((fAscii == TRUE) ?
+ ((int)(MemWinDesc[memView].cMi)-1)
+ : ((int)(MemWinDesc[memView].cMi / 2)))
+ : ((int)(MemWinDesc[memView].cMi)-1);
+
+ n++)
+
+ {
+ if (((int)(MemWinDesc[memView].lpMi[n].iStart) <= startX) &&
+ (startX < MemWinDesc[memView].lpMi[n+1].iStart)) {
+ break;
+ }
+ }
+
+ n += 1;
+
+ if ( (n >= ((MemWinDesc[memView].iFormat == MW_BYTE) ?
+ ((fAscii == TRUE) ? ((int)MemWinDesc[memView].cMi)
+ : ((int)(MemWinDesc[memView].cMi / 2) + 1))
+ : (int)MemWinDesc[memView].cMi)
+ )
+ && ((startY + 1) < Docs[Views[memView].Doc].NbLines))
+ {
+ // user moving to next element (in next line of displayed data)
+ startY += 1;
+ if ((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE)) {
+ n = (MemWinDesc[memView].cMi / 2) + 1;
+ } else {
+ n = 1;
+ }
+
+ } else if ((n >= ((MemWinDesc[memView].iFormat == MW_BYTE)
+ ? ((fAscii == TRUE)
+ ? ((int)MemWinDesc[memView].cMi)
+ : ((int)(MemWinDesc[memView].cMi / 2)))
+ : (int)MemWinDesc[memView].cMi))
+ && ((startY + 1) >= Docs[Views[memView].Doc].NbLines))
+ {
+ n = (MemWinDesc[memView].iFormat == MW_BYTE)
+ ? ((fAscii == TRUE)
+ ? MemWinDesc[memView].cMi - 1
+ : ((MemWinDesc[memView].cMi / 2)))
+ //user trying to move beyond last element
+ : MemWinDesc[memView].cMi - 1;
+ }
+ break;
+
+ case GOTO_PREVIOUS:
+ for (n = ((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE))
+ ? ((int)((MemWinDesc[memView].cMi / 2) + 1))
+ : 1;
+ n < (MemWinDesc[memView].iFormat == MW_BYTE)
+ ? ((fAscii == TRUE)
+ ? ((int)MemWinDesc[memView].cMi)
+ : ((int)(MemWinDesc[memView].cMi / 2)))
+ : ((int)MemWinDesc[memView].cMi);
+ n++)
+ {
+ if (((int)(MemWinDesc[memView].lpMi[n].iStart) <= startX) &&
+ (startX < MemWinDesc[memView].lpMi[n].iStart +
+ MemWinDesc[memView].lpMi[n].cch)) {
+ break;
+ }
+ }
+ n -= 1;
+
+ if (n < ((MemWinDesc[memView].iFormat == MW_BYTE)
+ ? ((fAscii == TRUE)
+ ? (int)((MemWinDesc[memView].cMi / 2) + 1) : 1) : 1)) {
+ if (startY == 0) {
+ return; // user trying to move to element before 1st
+ }
+ startY -= 1;
+ n = (MemWinDesc[memView].iFormat == MW_BYTE)
+ ? ((fAscii == TRUE)
+ ? (MemWinDesc[memView].cMi - 1)
+ : ((MemWinDesc[memView].cMi / 2)))
+ : MemWinDesc[memView].cMi - 1;
+ }
+ break;
+
+ }
+
+ //Put the cursor at new location and save the text
+
+ PosXY(memView, MemWinDesc[memView].lpMi[n].iStart, startY, FALSE);
+ GetMemText ();
+
+ return;
+} /* GotoField() */
+
+
+#ifdef DBCS // ***************************************************************
+/*** RecreateAsciiStrings
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** This function will recreate ASCII and Shift JIS strings
+** in the right part of 'Byte Memory Window'.
+*/
+
+VOID RecreateAsciiPart(int doc, UINT cBits, BOOL fTwoFields)
+{
+ UINT cb;
+ int nbLines;
+ int nbPerLine;
+ int x, y;
+ BOOL bDBCS;
+ char FAR * lpb;
+ char FAR * lpb2;
+ char FAR * lpbData;
+ int x1, x2, x3;
+ LPLINEREC pl = NULL;
+ LPBLOCKDEF pb = NULL;
+ HCURSOR hOldCursor;
+ int nHead;
+
+ hOldCursor = SetCursor(LoadCursor((HANDLE)NULL, IDC_WAIT));
+
+ Dbg (OSDSetAddr (LppdCur->hpid, LptdCur->htid, adrCurrent, &MemWinDesc[memView].addr) == xosdNone);
+
+ // Compute number of lines for MAX_CHUNK_TOREAD k of data
+ nbPerLine = MemWinDesc[memView].cPerLine;
+ nbLines = ((MAX_CHUNK_TOREAD / nbPerLine) / (cBits / 8));
+ nHead = fTwoFields ? nbPerLine + 1 : 1;
+
+ // Compute number of bytes to malloc for this space
+ cb = ((nbPerLine * nbLines) * (cBits / 8));
+
+ lpbData = _fmalloc( cb );
+ OSDPtrace( osdReadBuf, cb, lpbData, LppdCur->hpid, LptdCur->htid );
+
+ bDBCS = FALSE;
+
+ for (y = 0, lpb = lpbData; y < nbLines; y++) {
+ lpb2 = lpb;
+
+ // Now deal with the line data
+ for (x = 0; x < nbPerLine; x++) {
+ if (bDBCS) {
+ bDBCS = FALSE;
+ if (x == 0) {
+ //This means that current *lpb is the 2nd byte
+ //of a splited DBCS
+ *lpb = '.';
+ }
+ } else if (IsDBCSLeadByte(*lpb)) {
+ bDBCS = TRUE;
+ }
+#ifdef DBCS
+ else if (!((BYTE)*lpb >= (BYTE)0x20 && (BYTE)*lpb <= (BYTE)0x7E)
+ && !IsDBCSLeadByte(*lpb))
+ //not ascii and 'Hankaku Kana' displayable
+#else
+ else if (*lpb < 0x20 || *lpb > 0x7E) //not ascii displayable
+#endif
+ {
+ *lpb = '.'; // replace with .
+ }
+ lpb++;
+ }
+ x1 = MemWinDesc[memView].lpMi[nHead].iStart;
+ x2 = MemWinDesc[memView].lpMi[nHead + x - 1].iStart;
+ x3 = x2;
+
+ if (FirstLine(doc, &pl, &y, &pb)) {
+ if (elLen > x2 + 1) {
+ //This means that 2nd byte of DBCS has been added.
+ x2++;
+ }
+ CloseLine(doc, &pl, y, &pb);
+ //FirstLine() incremented 'y', so we have to decrement it.
+ y--;
+ if (DeleteBlock(doc, x1, y, x2 + 1, y)) {
+ if (bDBCS) {
+ //If DBC is separated by new line, add 2nd byte.
+ x3++;
+ }
+ InsertBlock(doc, x1, y, x3 - x1 + 1, lpb2);
+ } else {
+ MessageBeep(0);
+ }
+ }
+ }
+ // Free up used space
+ _ffree(lpbData);
+ InvalidateLines(memView, 0, y-1, FALSE);
+ SetCursor (hOldCursor);
+}
+#endif // DBCS end **********************************************************
+
+
+/*** FValidateEdit
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** This function will get the current character stream from the
+** memory window and attempt to convert it a memory pattern and
+** write it back to the users memory. If it is not convertable
+** or is not writable then the function will return FALSE.
+*/
+
+static BOOL PASCAL NEAR
+FValidateEdit(
+ UINT iArea,
+ UINT x,
+ UINT y
+ )
+{
+ int doc = Views[memView].Doc;
+ char rgch[30];
+ char rgb[30];
+ ULONG off;
+ ADDR addr2;
+ int xs, xe, cnt;
+ UINT cBits;
+ UINT fmtType;
+ UINT uradix;
+ UINT fTwoFields;
+ int cchMax;
+ EESTATUS eeErr = EENOERROR;
+ char cMemChar[5];
+
+
+
+ if (!DebuggeeActive() || !DebuggeeAlive()) {
+ return FALSE;
+ }
+
+
+ if (memView == -1) {
+ return FALSE;
+ }
+
+ Dbg(EEFormatEnumerate(MemWinDesc[memView].iFormat,
+ &cBits,
+ &fmtType,
+ &uradix,
+ &fTwoFields,
+ &cchMax,
+ NULL) == EENOERROR);
+
+
+ switch (MemWinDesc[memView].iFormat) {
+ case MW_REAL:
+ case MW_REAL_LONG:
+ xs = x; /* MemWinDesc[memView].lpMi[iArea].iStart; */
+ xe = MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch;
+
+ if ((xs == MemWinDesc[memView].lpMi[iArea].iStart) ||
+ (xs == ((MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch) - 4))) {
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] != '+' && cMemChar[0] != '-' &&
+ cMemChar[0] != ' ') {
+ if (xs == MemWinDesc[memView].lpMi[iArea].iStart) {
+ ReplaceCharInBlock (doc, xs, y, cMem[0]);
+ } else {
+ ReplaceCharInBlock (doc, xs, y,
+ cMem[MemWinDesc[memView].lpMi[iArea].cch - 4]);
+ }
+ PosXY(memView, x, y, FALSE);
+ return(FALSE);
+ }
+ } else if (xs == ((MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch) - 5)) {
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] != 'E' && cMemChar[0] != 'e') {
+ ReplaceCharInBlock (doc, xs, y,
+ cMem[MemWinDesc[memView].lpMi[iArea].cch - 5]);
+ PosXY(memView, x, y, FALSE);
+ return(FALSE);
+ }
+ } else if (xs == (MemWinDesc[memView].lpMi[iArea].iStart + 2)) {
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] != '.') {
+ ReplaceCharInBlock (doc, xs, y, cMem[2]);
+ }
+ } else {
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] < '0' || cMemChar[0] > '9') {
+ ReplaceCharInBlock (doc, xs, y,
+ cMem[xs - MemWinDesc[memView].lpMi[iArea].iStart]);
+ PosXY(memView, x, y, FALSE);
+ return(FALSE);
+ }
+
+ }
+
+ break;
+
+ case MW_REAL_TEN:
+
+ xs = x; /* MemWinDesc[memView].lpMi[iArea].iStart; */
+ xe = MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch;
+
+ if ((xs == MemWinDesc[memView].lpMi[iArea].iStart) ||
+ (xs == ((MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch) - 5))) {
+
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] != '+' && cMemChar[0] != '-' &&
+ cMemChar[0] != ' ') {
+ if (xs == MemWinDesc[memView].lpMi[iArea].iStart) {
+ ReplaceCharInBlock (doc, xs, y, cMem[0]);
+ } else {
+ ReplaceCharInBlock (doc, xs, y,
+ cMem[MemWinDesc[memView].lpMi[iArea].cch - 5]);
+ }
+ PosXY(memView, x, y, FALSE);
+ return(FALSE);
+ }
+ } else if (xs == ((MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch) - 6)) {
+
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] != 'E' && cMemChar[0] != 'e') {
+ ReplaceCharInBlock (doc, xs, y,
+ cMem[MemWinDesc[memView].lpMi[iArea].cch - 6]);
+ PosXY(memView, x, y, FALSE);
+ return(FALSE);
+ }
+ } else if (xs == (MemWinDesc[memView].lpMi[iArea].iStart + 2)) {
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] != '.') {
+ ReplaceCharInBlock (doc, xs, y, cMem[2]);
+ }
+ } else {
+
+ GetTextAtLine(Views[memView].Doc, y, xs,xs+1, cMemChar);
+
+ if (cMemChar[0] < '0' || cMemChar[0] > '9') {
+ ReplaceCharInBlock (doc, xs, y,
+ cMem[xs - MemWinDesc[memView].lpMi[iArea].iStart]);
+ PosXY(memView, x, y, FALSE);
+ return(FALSE);
+ }
+ }
+
+ }
+
+
+ // If no changes have been made then it is a valid edit
+ if (MemWinDesc[memView].fEdit == FALSE) {
+ return TRUE;
+ }
+
+
+ // Get the new buffer from the window/editor
+
+ Assert(MemWinDesc[memView].lpMi[iArea].cch < sizeof(rgch));
+ GetTextAtLine(doc,
+ Views[memView].Y,
+ MemWinDesc[memView].lpMi[iArea].iStart,
+ MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch,
+ rgch);
+ rgch[MemWinDesc[memView].lpMi[iArea].cch] = 0;
+
+ strcpy (cMemTemp, rgch); // make a copy
+
+ // Convert the character buffer into a byte buffer
+
+ Assert(RgbFmts[MemWinDesc[memView].iFormat] <= sizeof(rgb));
+
+
+ if (!UnformatDataItem(rgch, rgb)) {
+ xs = x; /* MemWinDesc[memView].lpMi[iArea].iStart; */
+ xe = MemWinDesc[memView].lpMi[iArea].iStart +
+ MemWinDesc[memView].lpMi[iArea].cch;
+
+ cnt = x - MemWinDesc[memView].lpMi[iArea].iStart; //initialize
+ while (xs < xe) {
+ ReplaceCharInBlock (doc, xs, Views[memView].Y, cMem[cnt++]);
+ xs++;
+ }
+
+ PosXY(memView, x, y, FALSE);
+ return FALSE;
+ } else {
+ // Write the byte buffer back into users memory space
+
+ // Compute the address to write the memory to
+
+ off = (Views[memView].Y * MemWinDesc[memView].cPerLine +
+ (
+ (MemWinDesc[memView].iFormat == MW_BYTE) ?
+ ((fAscii == TRUE)?
+ iArea - (MemWinDesc[memView].cMi / 2)
+ : iArea
+ )
+ : iArea
+ ) - 1
+ ) * RgbFmts[MemWinDesc[memView].iFormat];
+
+ addr2 = MemWinDesc[memView].addr;
+ addr2.addr.off += off;
+
+ Dbg (OSDSetAddr (LppdCur->hpid, LptdCur->htid, adrCurrent, &addr2) ==
+ xosdNone);
+ Dbg (OSDPtrace (osdWriteBuf,
+ RgbFmts[MemWinDesc[memView].iFormat],
+ rgb,
+ LppdCur->hpid,
+ LptdCur->htid) == xosdNone);
+
+ // M00BUG -- highlight the changed area
+
+ // If a two character format then we need to repaint the
+ // window since there are "updates"
+
+ if (MemWinDesc[memView].iFormat == MW_BYTE) {
+
+ Dbg(EEFormatMemory(rgch, 3, rgb, 8, fmtZeroPad| fmtInt, 16) ==
+ EENOERROR);
+
+ if (!fAscii) {
+#ifdef DBCS
+ /********************************************************/
+ /* In this case, we have to recreate ASCII(& Shift JIS) */
+ /* string. But it takes long time to recreate whole */
+ /* string of ASCII side. */
+ /********************************************************/
+ if (IsDBCSCharSet(Views[memView].wCharSet)) {
+ RecreateAsciiPart(doc, cBits, TRUE);
+ }
+#else // !DBCS
+ if (rgb[0] < 0x21 || rgb[0] > 0x7E) { //not ascii displayable
+ rgb[0] = '.'; // replace with .
+ }
+ ReplaceCharInBlock (doc,
+ MemWinDesc[memView].
+ lpMi[((MemWinDesc[memView].cMi / 2))+iArea].
+ iStart,
+ Views[memView].Y,
+ rgb[0]);
+
+ ReplaceCharInBlock (doc,
+ MemWinDesc[memView].lpMi[iArea].iStart,
+ Views[memView].Y,
+ rgch[0]);
+ ReplaceCharInBlock (doc,
+ MemWinDesc[memView].lpMi[iArea].iStart+1,
+ Views[memView].Y,
+ rgch[1]);
+#endif
+
+ } else {
+
+ ReplaceCharInBlock (doc,
+ MemWinDesc[memView].
+ lpMi[iArea - ((MemWinDesc[memView].cMi / 2))].
+ iStart,
+ Views[memView].Y,
+ rgch[0]);
+ ReplaceCharInBlock (doc,
+ MemWinDesc[memView].
+ lpMi[iArea - ((MemWinDesc[memView].cMi / 2))].
+ iStart+1,
+ Views[memView].Y,
+ rgch[1]);
+#ifdef DBCS
+ if (IsDBCSCharSet(Views[memView].wCharSet)) {
+ RecreateAsciiPart(doc, cBits, TRUE);
+ }
+#endif
+ }
+ }
+#ifdef DBCS
+ else if (MemWinDesc[memView].iFormat == MW_ASCII &&
+ IsDBCSCharSet(Views[memView].wCharSet)) {
+ RecreateAsciiPart(doc, cBits, FALSE);
+ }
+#endif
+ }
+
+ return TRUE;
+} /* FValidateEdit() */
+
+
+/*** InEntryArea
+**
+** Synopsis:
+** word = InEntryArea(pui)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+static BOOL NEAR
+InEntryArea(
+ UINT * pui
+ )
+{
+ int startX = Views[memView].X;
+ int n;
+
+ if (!DebuggeeActive() || !DebuggeeAlive()) {
+ return FALSE;
+ }
+
+ if (memView == -1) {
+ return FALSE;
+ }
+
+ for (n=1; n < ((int)(MemWinDesc[memView].cMi)-1); n++) {
+ if (((int)(MemWinDesc[memView].lpMi[n].iStart) <= startX) &&
+ (startX < MemWinDesc[memView].lpMi[n+1].iStart)) {
+ break;
+ }
+ }
+
+ if (startX >= MemWinDesc[memView].lpMi[n].iStart +
+ MemWinDesc[memView].lpMi[n].cch) {
+ return FALSE;
+ }
+
+ if (startX < MemWinDesc[memView].lpMi[1].iStart) {
+ return FALSE;
+ }
+
+ *pui = n;
+ return TRUE;
+} /* InEntryArea() */
+
+#ifdef DBCS // ***************************************************************
+/***
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+*/
+
+BOOL RestoreDBCS(char *pszSrc, char *pszTgt, int x, BOOL bDBCS)
+{
+ if (bDBCS) {
+ if (x == 0) {
+ //This means that current *pszSrc is the 2nd byte
+ //of a splited DBCS
+ pszTgt[x] = '.';
+ } else {
+ //This DBC is changed to '.' by EEFormatMemory().
+ //So I restore it.
+ pszTgt[x - 1] = *(pszSrc - 1);
+ pszTgt[x] = *pszSrc;
+ pszTgt[x + 1] = '\0';
+ }
+ bDBCS = FALSE;
+ } else if (IsDBCSLeadByte(*pszSrc)) {
+ bDBCS = TRUE;
+ }
+#ifdef DBCS
+ else if (IsDBCSLeadByte(*pszSrc)) {
+ //'Hankaku Kana' is changed to '.' by EEFormatMemory().
+ pszTgt[x] = *pszSrc;
+ pszTgt[x + 1] = '\0';
+ }
+#endif
+ return bDBCS;
+}
+#endif // DBCS end **********************************************************
+
+
+/*** ViewMem
+**
+** Synopsis:
+** void = ViewMem(view, fVoidCache)
+**
+** Entry:
+** view - Index of document to update the information in
+**
+** Returns:
+** nothing
+**
+** Description:
+** This function will update the contents of the window to reflect
+** the current memory patterns.
+*/
+
+void
+ViewMem(
+ int view,
+ BOOL fVoidCache
+ )
+{
+ int doc = Views[memView].Doc;
+ int n, x, y;
+ char rgch[MAX_MSG_TXT];
+ char rgchT[MAX_MSG_TXT]; // Temp formatting buffer
+ char rgchT2[MAX_MSG_TXT]; // Temp formatting buffer
+ RECT rc;
+ int cbWindowX; // Number of characters across window
+ int cAddrWidth; // # of characters in address display
+ ADDR addr; // Address for current display
+ ADDR FAR * lpAddr = &addr;
+ RI ri;
+ HTI hti = (HTI) NULL;
+ PTI pTi = (PTI)NULL;
+ HTM hTm = (HTM) NULL;
+ UINT us;
+ char FAR * lpb;
+ char FAR * lpbData;
+ UINT cbt;
+ UINT cb;
+ long cbRead;
+ UINT cBits;
+ UINT fmtType;
+ UINT uradix;
+ UINT fTwoFields;
+ int cchMax;
+ int nbLines, nbPerLine, nNewbPerLine, nPower;
+ NPDOCREC d = &Docs[doc];
+ HCURSOR hOldCursor, hWaitCursor;
+ EESTATUS eeErr = EENOERROR;
+#ifdef DBCS
+ BOOL bDBCS = FALSE;
+ char *psz;
+#endif
+
+
+
+
+ Assert(memView != -1);
+
+ // Keep using GetParent(hwndClient),
+ // instead of hwndFrame (could be not assigned)
+
+ if (IsIconic(GetParent(Views[memView].hwndClient))) {
+ return;
+ }
+
+
+
+ // First clean out all of the information currently in the window
+
+
+ DeleteAll(doc);
+
+
+ if (!DebuggeeActive() || !DebuggeeAlive()) {
+ return;
+ }
+
+
+ // Set hourglass cursor
+ hWaitCursor = LoadCursor ((HANDLE)NULL, IDC_WAIT);
+ hOldCursor = SetCursor (hWaitCursor);
+
+
+ // Get the size of the memory window for sizing
+ GetClientRect(Views[memView].hwndClient, &rc);
+ cbWindowX = Pix2Pos(memView, rc.right, 0) - 1;
+
+ if (cbWindowX > MAX_USER_LINE) {
+ cbWindowX = (MAX_USER_LINE -1);
+ }
+
+ // Get the format information
+ Dbg(EEFormatEnumerate(MemWinDesc[memView].iFormat,
+ &cBits,
+ &fmtType,
+ &uradix,
+ &fTwoFields,
+ &cchMax,
+ NULL) == EENOERROR);
+
+
+ // If necessary compute the address of the expression
+
+ if (!(MemWinDesc[memView].fLive) && (MemWinDesc[memView].fHaveAddr)) {
+
+ addr = MemWinDesc[memView].addr;
+
+ } else {
+
+ GetAtomName(MemWinDesc[memView].atmAddress, rgch, sizeof(rgch));
+
+ if ((EEParse(rgch, radix, fCaseSensitive, &hTm, &us) != EENOERROR) ||
+ (EEBindTM(&hTm, SHpCXTFrompCXF( &CxfIp ), TRUE, FALSE, FALSE) !=
+ EENOERROR) ||
+ (EEvaluateTM(&hTm, SHpFrameFrompCXF( &CxfIp ), EEHORIZONTAL) !=
+ EENOERROR)) {
+
+ LoadString (hInst,ERR_Memory_Context,cDoc,MAX_MSG_TXT);
+ cbt = strlen (cDoc);
+ InsertBlock(doc, 0, 0, cbt, cDoc);
+
+ InvalidateRect(Views[memView].hwndClient, (LPRECT)NULL, TRUE);
+ SendMessage(Views[memView].hwndClient, WM_PAINT, 0, 0L);
+ return;
+ }
+
+ memset( &ri, 0, sizeof(ri));
+ ri.fAddr = TRUE;
+
+
+ eeErr = EEInfoFromTM(&hTm, &ri, &hti);
+
+ // Extract the desired information
+
+ if (eeErr == EENOERROR) {
+
+ if ((hti == 0) || (pTi = (PTI) MMLpvLockMb( hti )) == 0) {
+
+ return;
+
+ } else {
+
+ if (pTi->fResponse.fAddr) {
+ *lpAddr = pTi->u2.AI;
+ } else if (pTi->fResponse.fValue &&
+ pTi->fResponse.fSzBytes &&
+ pTi->cbValue >= sizeof(WORD)) {
+
+ switch( pTi->cbValue ) {
+ case sizeof(WORD):
+ SetAddrOff( lpAddr, *((WORD FAR *) pTi->Value));
+ break;
+
+ case sizeof(DWORD):
+ SetAddrOff( lpAddr, *((DWORD FAR *) pTi->Value));
+ break;
+ }
+
+ // set the segment
+
+ if ((pTi->u.SegType & EEDATA) == EEDATA) {
+ ADDR addrData = {0};
+
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, adrData,
+ &addrData );
+ SetAddrSeg( lpAddr, (SEGMENT) GetAddrSeg( addrData ));
+ ADDR_IS_FLAT(*lpAddr) = ADDR_IS_FLAT(addrData);
+ SYUnFixupAddr ( lpAddr );
+
+ } else if ((pTi->u.SegType & EECODE) == EECODE) {
+
+ ADDR addrPC = {0};
+
+ OSDGetAddr(LppdCur->hpid,LptdCur->htid, adrPC, &addrPC);
+ SetAddrSeg( lpAddr, (SEGMENT) GetAddrSeg( addrPC ));
+ ADDR_IS_FLAT(*lpAddr) = ADDR_IS_FLAT(addrPC);
+ SYUnFixupAddr( lpAddr );
+
+ } else {
+
+ ADDR addrData = {0};
+
+ OSDGetAddr(LppdCur->hpid, LptdCur->htid, adrData,
+ &addrData );
+ SetAddrSeg( lpAddr, (SEGMENT) GetAddrSeg( addrData ));
+ ADDR_IS_FLAT(*lpAddr) = ADDR_IS_FLAT(addrData);
+ SYUnFixupAddr ( lpAddr );
+ }
+ }
+ MMbUnlockMb( hti );
+ }
+ }
+
+
+ // Free up any handles
+ if (hTm) {
+ EEFreeTM (&hTm);
+ }
+ if (hti) {
+ EEFreeTI (&hti);
+ }
+
+ SYFixupAddr(&addr);
+
+ MemWinDesc[memView].addr = addr;
+
+ MemWinDesc[memView].fHaveAddr = TRUE;
+
+ // save orig address
+ _fmemcpy (&MemWinDesc[memView].orig_addr, &addr, sizeof(struct ADDR));
+ }
+
+
+ // Now compute how many memory locations will fit on one line
+ EEFormatAddr(&MemWinDesc[memView].addr, rgchT, 20,
+ (runDebugParams.ShowSegVal != FALSE) ? EEFMT_SEG : 0);
+ cAddrWidth = strlen(rgchT);
+
+
+ if (fmtType != fmtAscii) {
+ nbPerLine = (int)((cbWindowX - cAddrWidth) /
+ (cchMax + 1 + (fTwoFields ? 1 : 0)));
+ } else {
+ nbPerLine = (int)((cbWindowX - cAddrWidth) / cchMax);
+ }
+
+
+ if (nbPerLine < 1) {
+ // Force at least one memory item to be displayed on the line
+ return;
+ }
+
+
+ if (MemWinDesc[memView].fFill == FALSE) {
+ // now we hold the number of items per line to a power of 2
+
+ nNewbPerLine = nbPerLine / 2; // normalize and round
+
+ nPower = 1;
+
+ while (nNewbPerLine >= 1) {
+ nNewbPerLine /= 2;
+ nPower++;
+ }
+
+ nbPerLine = (int) pow (2.0, ((double)nPower - 1.0));
+
+ }
+
+ MemWinDesc[memView].cPerLine = nbPerLine;
+
+ // Now read in the new memory space
+ Assert((cBits % 8) == 0); // Only display evenly divisable items
+
+ // Compute number of lines for MAX_CHUNK_TOREAD k of data
+ nbLines = ((MAX_CHUNK_TOREAD / nbPerLine) / (cBits / 8));
+
+ if ((nbPerLine * nbLines) < MAX_CHUNK_TOREAD) {
+ nbLines++;
+ }
+
+ // Compute number of bytes to malloc for this space
+ cb = ((nbPerLine * nbLines) * (cBits / 8));
+ lpbData = _fmalloc( cb );
+
+ Dbg(OSDSetAddr(LppdCur->hpid, LptdCur->htid, adrCurrent, &addr)==xosdNone);
+ cbRead =
+ (long)OSDPtrace( osdReadBuf, cb, lpbData, LppdCur->hpid, LptdCur->htid );
+
+ if (cbRead > 0) {
+ MemWinDesc[memView].cbRead = cbRead; // save for VK_PRIOR;
+ MemWinDesc[memView].fBadRead = FALSE;
+ } else {
+ MemWinDesc[memView].cbRead = cb;
+ MemWinDesc[memView].fBadRead = TRUE;
+ }
+
+ // If necessary clean up the formatted area and re-compute
+ if (MemWinDesc[memView].lpMi)
+ _ffree(MemWinDesc[memView].lpMi);
+ MemWinDesc[memView].cMi = nbPerLine + 1;
+
+ if (MemWinDesc[memView].iFormat == MW_BYTE) {
+ MemWinDesc[memView].cMi += nbPerLine;
+ }
+
+ MemWinDesc[memView].lpMi =
+ _fmalloc( sizeof(struct memItem) * MemWinDesc[memView].cMi);
+
+ /*
+ ** Now, we know exactly the layout, display memory
+ */
+
+ if (fVoidCache) {
+ DeleteAll (doc); // void the window first
+ }
+
+#ifdef DBCS
+ //Initialize
+ bDBCS = FALSE;
+#endif
+ for (y=0, lpb = lpbData; y < nbLines; y++) {
+ x = 0;
+
+ // Place the current address out
+ EEFormatAddr(&addr, rgchT, 20,
+ (runDebugParams.ShowSegVal != FALSE) ? EEFMT_SEG : 0);
+
+ cb = strlen(rgchT);
+
+ strcpy (cDoc,rgchT);
+
+ if (y == 0) {
+ MemWinDesc[memView].lpMi[0].iStart = (char)x;
+ MemWinDesc[memView].lpMi[0].cch = (char) cb;
+ MemWinDesc[memView].lpMi[0].iFmt = -1;
+ }
+
+ x += cb;
+
+ if (fmtType == fmtAscii) {
+ strcat (cDoc," ");
+ x += 1;
+ }
+#ifdef DBCS
+ psz = cDoc + x;
+#endif
+
+
+ // Now deal with the line data
+ for (n=0; n<nbPerLine; n++) {
+
+ // Format the data
+
+
+ if ((cbRead >= (long)RgbFmts[MemWinDesc[memView].iFormat]) &&
+ (MemWinDesc[memView].fBadRead == FALSE)) {
+ Dbg(EEFormatMemory(rgchT, cchMax + 1, lpb, cBits,
+ fmtType|fmtZeroPad, uradix) == EENOERROR);
+
+ if (fTwoFields) {
+ Dbg(EEFormatMemory(&rgchT2[n], 2, lpb, 8, fmtAscii, 10) ==
+ EENOERROR);
+#ifdef DBCS
+ if (IsDBCSCharSet(Views[memView].wCharSet)) {
+ bDBCS = RestoreDBCS(lpb, rgchT2, n, bDBCS);
+ }
+#endif
+ }
+#ifdef DBCS
+ else if (MemWinDesc[memView].iFormat == MW_ASCII &&
+ IsDBCSCharSet(Views[memView].wCharSet)) {
+ psz[n] = rgchT[0];
+ psz[n+1] = '\0';
+ bDBCS = RestoreDBCS(lpb, psz, n, bDBCS);
+ rgchT[0] = psz[n];
+ psz[n] = '\0';
+ }
+#endif
+
+ cb = strlen( rgchT );
+ } else {
+ memset(rgchT, '?', cchMax);
+ rgchT[cchMax] = '\0';
+ cb = cchMax;
+
+ if (fTwoFields) {
+ rgchT2[n] = '.';
+ rgchT2[n+1] = '\0';
+ }
+
+ }
+
+ if (cb < (UINT)cchMax) {
+ strncat (cDoc," ",(cchMax-cb));
+ x += cchMax - cb;
+ }
+
+ if (fmtType != fmtAscii) {
+ strcat (cDoc," ");
+ x++;
+ }
+
+ strcat (cDoc,rgchT);
+
+ if (y == 0) {
+ MemWinDesc[memView].lpMi[1+n].iStart = (char)x;
+ MemWinDesc[memView].lpMi[1+n].cch = (char) cb;
+ MemWinDesc[memView].lpMi[1+n].iFmt = (char) fmtType;
+ }
+
+ // Update the loop variables
+ x += cb;
+ lpb += RgbFmts[MemWinDesc[memView].iFormat];
+ addr.addr.off += RgbFmts[MemWinDesc[memView].iFormat];
+ cbRead -= (long)(min((UINT)RgbFmts[MemWinDesc[memView].iFormat],
+ (UINT)cbRead));
+ }
+
+ if (fTwoFields) {
+#ifdef DBCS
+ if (bDBCS && IsDBCSCharSet(Views[memView].wCharSet)) {
+ //If DBC is separated by new line, add 2nd byte.
+ //This DBC is changed to '.' by EEFormatMemory().
+ //So I restore it.
+ rgchT2[n - 1] = *(lpb - 1);
+ rgchT2[n] = *lpb;
+ rgchT2[n + 1] = '\0';
+ }
+#endif
+ strcat (cDoc," ");
+ x++;
+ strcat (cDoc,rgchT2);
+
+ if (y == 0) {
+ for (n=0; n<nbPerLine; n++) {
+ MemWinDesc[memView].lpMi[1+n+nbPerLine].iStart =
+ (char)(x+n);
+ MemWinDesc[memView].lpMi[1+n+nbPerLine].cch = 1;
+ MemWinDesc[memView].lpMi[1+n+nbPerLine].iFmt =
+ (char)MemWinDesc[memView].iFormat;
+ }
+ }
+
+ x += n;
+ }
+#ifdef DBCS
+ else if (MemWinDesc[memView].iFormat == MW_ASCII &&
+ IsDBCSCharSet(Views[memView].wCharSet)) {
+ if (bDBCS) {
+ //If DBC is separated by new line, add 2nd byte.
+ //This DBC is changed to '.' by EEFormatMemory().
+ //So I restore it.
+ psz[n-1] = *(lpb - 1);
+ psz[n ] = *lpb;
+ psz[n+1] = '\0';
+ }
+ }
+#endif
+
+
+ // Now add the CR/LF at the end of all lines except last line
+ if (y < (nbLines - 1)) {
+ strcat (cDoc,"\r\n");
+ }
+ cbt = strlen (cDoc);
+ InsertBlock(doc, 0, y, cbt, cDoc);
+
+ }
+
+ // Set original cursor
+ hOldCursor = SetCursor (hOldCursor);
+
+ //Now everything is ready, so refresh the screen.
+ //PosXY(memView, MemWinDesc[memView].lpMi[1].iStart, 0, FALSE);
+
+ PosXY(memView, Views[memView].X, Views[memView].Y, FALSE);
+ InvalidateLines(memView, 0, LAST_LINE, FALSE);
+ EnsureScrollBars(memView,TRUE);
+ SetVerticalScrollBar(memView, FALSE);
+
+ // update address in struct
+ _fmemcpy (&MemWinDesc[memView].old_addr, &addr, sizeof (struct ADDR));
+
+ // Free up used space
+ _ffree(lpbData);
+
+ GetMemText ();
+
+ return;
+} /* ViewMem() */
+
+
+/*** CheckByteFields
+**
+** Synopsis:
+** void CheckByteFields (void)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Makes sure of which field the caret is in when MW_BYTE
+**
+*/
+
+
+static void NEAR
+CheckByteFields (
+ void
+ )
+{
+ UINT iArea2;
+ BOOL fInEntry;
+
+
+ if (!DebuggeeActive() || !DebuggeeAlive() || (memView == -1)) {
+ return;
+ }
+
+ if (MemWinDesc[memView].iFormat == MW_BYTE) {
+ if ((fInEntry = InEntryArea(&iArea2)) == FALSE) {
+ while ((fInEntry = InEntryArea(&iArea2)) == FALSE) {
+ if (Views[memView].X > MemWinDesc[memView].lpMi[1].iStart) {
+ PosXY(memView, (Views[memView].X)-1, Views[memView].Y,
+ FALSE);
+ GetMemText ();
+ } else {
+ GotoField ((WORD) GOTO_NEXT);
+ break;
+ }
+ }
+ }
+
+ fInEntry = InEntryArea(&iArea2);
+
+ if ((fAscii == TRUE) && (iArea2 < (MemWinDesc[memView].cMi / 2) + 1)) {
+ fAscii = FALSE;
+ } else if ((fAscii == FALSE) &&
+ (iArea2 > (MemWinDesc[memView].cMi / 2))) {
+ fAscii = TRUE;
+ }
+ }
+}
+
+/*** GetMemText
+**
+** Synopsis:
+** void GetMemText (void)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Gets text of memory item
+**
+*/
+
+
+static void NEAR
+GetMemText (
+ void
+ )
+{
+ UINT iArea2;
+ BOOL fInEntry;
+ int memY = Views[memView].Y;
+
+
+ if (!DebuggeeActive() || !DebuggeeAlive() || (memView == -1)) {
+ return;
+ }
+
+ fInEntry = InEntryArea(&iArea2); //got the area
+
+ if (fInEntry) {
+ GetTextAtLine(Views[memView].Doc,
+ memY,
+ MemWinDesc[memView].lpMi[iArea2].iStart,
+ MemWinDesc[memView].lpMi[iArea2].iStart +
+ MemWinDesc[memView].lpMi[iArea2].cch,
+ cMem);
+ }
+
+}
+
+
+LONG FAR PASCAL LOADDS
+MemoryEditProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ hwnd - window handle to CPU window
+
+ message - message to be processed
+
+ wParam - info about message
+
+ lParam - info about message
+
+Return Value:
+
+
+--*/
+{
+ UINT iArea;
+ UINT x, y;
+ BOOL fInEntry = FALSE;
+ SHORT isShiftDown;
+ SHORT isCtrlDown;
+#ifdef FE_IME
+ static BOOL bOldImeStatus;
+#endif
+
+
+ switch (message) {
+
+ case WU_INITDEBUGWIN:
+
+ // WARNING : lParam is NOT a pointer to a Valid CREATESTRUCT,
+ // but holds the view number.
+
+ Assert(lParam >= 0 && lParam < MAX_VIEWS);
+
+
+ // Set Doc to forced overtype
+
+ Docs[Views[(WORD)lParam].Doc].forcedOvertype = TRUE;
+
+ // Set cursor on First mem item
+
+ _fmemcpy (&MemWinDesc[(WORD)lParam],
+ &TempMemWinDesc,
+ sizeof(struct memWinDesc));
+
+ PostMessage(hwnd, WM_KEYDOWN, VK_HOME, 0L);
+
+ return FALSE; //Never call original proc or you are Dead...
+
+ case WM_KEYDOWN:
+
+
+ if (!DebuggeeActive() ||
+ !DebuggeeAlive() ||
+ !(MemWinDesc[memView].fHaveAddr)) {
+
+ // First clean out all of the information currently in the window
+
+ InvalidateRect(hwnd, (LPRECT)NULL, TRUE);
+ SendMessage(hwnd, WM_PAINT, 0, 0L);
+ return CallWindowProc(lpfnEditProc, hwnd, message, wParam, lParam);
+ }
+
+ isShiftDown = (GetKeyState(VK_SHIFT) < 0);
+ isCtrlDown = (GetKeyState(VK_CONTROL) < 0);
+
+
+ if ((memView != -1) && (MemWinDesc[memView].fHaveAddr)) {
+ GetMemText ();
+
+ if (!isShiftDown) {
+ CheckByteFields ();
+ fInEntry = InEntryArea(&iArea);
+ }
+
+ switch (wParam) {
+ case VK_F6:
+ if (MemWinDesc[memView].iFormat == MW_BYTE) {
+ if (fAscii == FALSE) {
+ fAscii = TRUE;
+ } else {
+ fAscii = FALSE;
+ }
+ GotoField(GOTO_FIRSTONLINE);
+ }
+ return FALSE;
+
+
+ case VK_NEXT:
+
+ //if we had a bad read, return now-no mem movement allowed
+ if (MemWinDesc[memView].fBadRead == TRUE) {
+ return FALSE;
+ }
+
+
+ if (hwnd == Views[memView].hwndClient) {
+ MemWinDesc[memView].addr.addr.seg =
+ MemWinDesc[memView].old_addr.addr.seg;
+ // set for NEXT
+ MemWinDesc[memView].addr.addr.off =
+ MemWinDesc[memView].old_addr.addr.off;
+ ViewMem(memView, FALSE);
+ }
+
+ InvalidateRect(hwnd, (LPRECT)NULL, TRUE);
+ return FALSE;
+
+
+ case VK_PRIOR:
+
+ //if we had a bad read, return now-no mem movement allowed
+ if (MemWinDesc[memView].fBadRead == TRUE) {
+ return FALSE;
+ }
+
+ if (hwnd == Views[memView].hwndClient) {
+ if ((MemWinDesc[memView].addr.addr.off -
+ MemWinDesc[memView].cbRead)
+ >= MemWinDesc[memView].orig_addr.addr.off)
+ {
+ MemWinDesc[memView].addr.addr.off -=
+ MemWinDesc[memView].cbRead;
+ ViewMem(memView, FALSE);
+ }
+
+ }
+
+ InvalidateRect(hwnd, (LPRECT)NULL, TRUE);
+ return FALSE;
+
+
+ case VK_RETURN:
+ case VK_TAB:
+ if (fInEntry) {
+ GotoField ((WORD)((GetKeyState (VK_SHIFT) >= 0) ?
+ GOTO_NEXT : GOTO_PREVIOUS));
+ }
+ return FALSE;
+
+
+ case VK_BACK:
+ if (fInEntry &&
+ (Views[memView].X > MemWinDesc[memView].lpMi[1].iStart)) {
+ PosXY(memView,
+ (Views[memView].X)-1,
+ Views[memView].Y, FALSE);
+ GetMemText ();
+ } else if (fInEntry &&
+ (Views[memView].X <= MemWinDesc[memView].lpMi[1].iStart)) {
+ if (Views[memView].Y <= 0) {
+ PosXY(memView,
+ (MemWinDesc[memView].lpMi[1].iStart),
+ (Views[memView].Y),
+ FALSE);
+ GetMemText ();
+ } else {
+
+ PosXY(memView,
+ (MemWinDesc[memView].iFormat == MW_BYTE) ?
+ (fAscii == TRUE) ?
+ ((MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi].iStart) + MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi].cch)
+ : ((MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi / 2].iStart) + MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi / 2].cch)
+ : ((MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi - 1].iStart) + MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi - 1].cch),
+ (Views[memView].Y) - 1,
+ FALSE);
+
+ GetMemText ();
+ }
+ }
+
+ if ((fInEntry = InEntryArea(&iArea)) == FALSE) {
+ while ((fInEntry = InEntryArea(&iArea)) == FALSE) {
+ if (Views[memView].X >
+ MemWinDesc[memView].lpMi[1].iStart) {
+ PosXY(memView,
+ (Views[memView].X)-1,
+ Views[memView].Y,
+ FALSE);
+ GetMemText ();
+ } else {
+ GotoField ((WORD) GOTO_NEXT);
+ break;
+ }
+ }
+ }
+
+ return FALSE;
+
+
+
+ case VK_END:
+ if (fInEntry) {
+ if (GetKeyState(VK_CONTROL) < 0) {
+ GotoField(GOTO_LAST);
+ } else {
+ GotoField(GOTO_LASTONLINE);
+ }
+ }
+ return FALSE;
+
+ case VK_HOME:
+ if (!fInEntry) {
+ GotoField(GOTO_FIRST);
+ } else if (GetKeyState(VK_CONTROL) < 0) {
+ GotoField(GOTO_FIRST);
+ } else {
+ GotoField(GOTO_FIRSTONLINE);
+ }
+ return FALSE;
+
+ //case VK_SPACE:
+ case VK_RIGHT:
+ if ((wParam == VK_RIGHT) && isShiftDown) {
+ KeyDown((WORD) GetWindowWord(hwnd, GWW_VIEW), wParam,
+ isShiftDown, isCtrlDown);
+ return(FALSE);
+ }
+
+ if (fInEntry) {
+ PosXY(memView,
+ (Views[memView].X)+1,
+ Views[memView].Y,
+ FALSE);
+ GetMemText ();
+ }
+
+ fInEntry = InEntryArea(&iArea);
+
+ if (!fInEntry) {
+ ClearSelection(memView);
+ GotoField ((WORD) GOTO_NEXT);
+ }
+
+ return FALSE;
+
+
+ case VK_LEFT:
+ if (isShiftDown) {
+ KeyDown((WORD) GetWindowWord(hwnd, GWW_VIEW), wParam,
+ isShiftDown, isCtrlDown);
+ return(FALSE);
+ }
+
+
+ if (fInEntry &&
+ (Views[memView].X >
+ (((MemWinDesc[memView].iFormat == MW_BYTE) &&
+ (fAscii == TRUE)) ?
+ MemWinDesc[memView].lpMi[(MemWinDesc[memView].cMi / 2) + 1].iStart
+ : MemWinDesc[memView].lpMi[1].iStart)))
+ {
+ PosXY(memView,
+ (Views[memView].X)-1,
+ Views[memView].Y,
+ FALSE);
+ GetMemText ();
+ } else {
+ if (fInEntry && (Views[memView].X <= (((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE)) ? MemWinDesc[memView].lpMi[(MemWinDesc[memView].cMi / 2) + 1].iStart : MemWinDesc[memView].lpMi[1].iStart)))
+ {
+ if (Views[memView].Y > 0) {
+ PosXY(memView, (MemWinDesc[memView].iFormat == MW_BYTE)
+ ? (fAscii == TRUE)
+ ? ((MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi - 1].iStart) + MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi - 1].cch)
+ : ((MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi / 2].iStart) + MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi / 2].cch)
+ : ((MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi - 1].iStart) + MemWinDesc[memView].lpMi[MemWinDesc[memView].cMi - 1].cch)
+ , (Views[memView].Y) - 1, FALSE);
+
+ GetMemText ();
+
+ } else {
+
+ PosXY(memView,
+ (((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE)) ? MemWinDesc[memView].lpMi[(MemWinDesc[memView].cMi / 2) + 1].iStart : MemWinDesc[memView].lpMi[1].iStart),
+ (Views[memView].Y),
+ FALSE);
+
+ GetMemText ();
+ }
+ }
+ }
+
+ if ((fInEntry = InEntryArea(&iArea)) == FALSE) {
+ ClearSelection(memView);
+ while ((fInEntry = InEntryArea(&iArea)) == FALSE) {
+
+ if (Views[memView].X > (((MemWinDesc[memView].iFormat == MW_BYTE) && (fAscii == TRUE)) ? MemWinDesc[memView].lpMi[(MemWinDesc[memView].cMi / 2) + 1].iStart : MemWinDesc[memView].lpMi[1].iStart))
+ {
+ PosXY(memView, (Views[memView].X)-1, Views[memView].Y, FALSE);
+ GetMemText ();
+
+ } else {
+ GotoField ((WORD) GOTO_NEXT);
+ break;
+ }
+ }
+ }
+ return FALSE;
+
+ case VK_DELETE:
+ case VK_INSERT:
+ return (FALSE);
+
+ }
+ }
+ break;
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ return TRUE;
+ break;
+
+ case WM_SETFOCUS:
+ bOldImeStatus = ImeWINNLSEnableIME(NULL, FALSE);
+ break;
+
+ case WM_KILLFOCUS:
+ ImeWINNLSEnableIME(NULL, bOldImeStatus);
+ break;
+#endif
+
+ case WM_CHAR:
+
+ if (!DebuggeeActive() ||
+ !DebuggeeAlive() ||
+ !(MemWinDesc[memView].fHaveAddr)) {
+ return FALSE;
+ }
+
+ //if we had a bad read, return now-no edits allowed
+ if (MemWinDesc[memView].fBadRead == TRUE) {
+ return FALSE;
+ }
+
+ CheckByteFields ();
+
+ if (Views[memView].X < MemWinDesc[memView].lpMi[1].iStart) {
+ // keep user out of mem address display
+ return FALSE;
+ }
+
+
+ switch (wParam) {
+ //case VK_F6:
+ case VK_RETURN:
+ case VK_TAB:
+ case VK_BACK:
+ //case VK_SPACE:
+ return FALSE;
+ default:
+ break;
+ }
+
+ // See if we are at a cursor position where entry is allowed
+
+ if (InEntryArea(&iArea)) {
+ // Now perform validation on the character about to be replaced
+ // based upon what is present and type of field
+
+ x = Views[memView].X;
+ y = Views[memView].Y;
+
+ Docs[Views[memView].Doc].ismodified = FALSE;
+
+ CallWindowProc(lpfnEditProc, hwnd, message, wParam, lParam);
+
+ if (Docs[Views[memView].Doc].ismodified) {
+ MemWinDesc[memView].fEdit = TRUE;
+ }
+
+ if (FValidateEdit(iArea, x, y)) {
+///// if (MemWinDesc[memView].iFormat != MW_ASCII) {
+ if (!InEntryArea(&iArea)) {
+ GotoField ((WORD) GOTO_NEXT);
+ }
+///// }
+ }
+
+ }
+ return FALSE;
+
+
+ case WM_LBUTTONDBLCLK:
+ CallWindowProc(lpfnEditProc, hwnd, message, wParam, lParam);
+
+ fInEntry = InEntryArea(&iArea);
+
+ if (fInEntry) {
+ BOOL lookAround = FALSE;
+ char memField[MAX_MSG_TXT];
+
+ *memField = '\0';
+
+ if (GetSelectedText (curView, &lookAround, (LPSTR)&memField,
+ MAX_MSG_TXT, 0, 0)) {
+ // hmm. there's nothing here...
+ }
+
+ }
+ return FALSE;
+
+ case WM_FONTCHANGE:
+
+ if (!DebuggeeActive() || !DebuggeeAlive()) {
+ return FALSE;
+ }
+ ViewMem(memView, TRUE);
+
+ return FALSE;
+
+ case WM_SIZE:
+ if (wParam != SIZEICONIC) {
+ if (!DebuggeeActive() || !DebuggeeAlive()) {
+ return FALSE;
+ }
+
+ if ((hwnd == Views[memView].hwndClient) &&
+ (InMemUpdate == STARTED)) {
+ InMemUpdate = INPROGRESS;
+ ViewMem(memView, TRUE);
+ }
+
+ InvalidateRect(hwnd, (LPRECT)NULL, TRUE);
+ }
+ WindowTitle( memView, 0 );
+ return FALSE;
+
+ case WM_DESTROY:
+ MemWinDesc[memView].fHaveAddr = FALSE;
+
+ //Destroy the instance of this window proc
+ FreeProcInstance((FARPROC)SetWindowLong(hwnd, GWL_WNDPROC,
+ (DWORD)lpfnEditProc));
+ break;
+ }
+
+ return CallWindowProc(lpfnEditProc, hwnd, message, wParam, lParam);
+} /* MemoryEditProc() */
+
+
+
+#ifdef DBCS
+BOOL IsDBCSCharSet ( DWORD cs )
+/* cs is charset to check for dbcs-ness */
+{
+ switch(cs) {
+ case SHIFTJIS_CHARSET:
+ case HANGEUL_CHARSET:
+ case GB2312_CHARSET:
+ case CHINESEBIG5_CHARSET:
+ case JOHAB_CHARSET:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+#endif /* DBCS */
diff --git a/private/windbg/windbg/menu.c b/private/windbg/windbg/menu.c
new file mode 100644
index 000000000..99cb8b3e1
--- /dev/null
+++ b/private/windbg/windbg/menu.c
@@ -0,0 +1,820 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Menu.c
+
+Abstract:
+
+ This module contains the support for Windbg's menu.
+
+Author:
+
+ David J. Gilman (davegi) 16-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+HWND GetCpuHWND(void);
+HWND GetFloatHWND(void);
+HWND GetLocalHWND(void);
+HWND GetWatchHWND(void);
+HWND GetCallsHWND(void);
+
+
+
+
+//Keep the 4 most recently used files (editor and project)
+HANDLE hFileKept[PROJECT_FILE + 1][MAX_MRU_FILES_KEPT] = {
+ {0, 0, 0, 0}, {0, 0, 0, 0}
+};
+int nbFilesKept[PROJECT_FILE + 1] = {0, 0};
+
+//Last menu id & id state
+IWORD FAR lastMenuId;
+IWORD FAR lastMenuIdState;
+
+//Window submenu
+HMENU hWindowSubMenu;
+
+//
+// Handle to main window menu.
+//
+
+HMENU hMainMenu;
+HMENU hMainMenuSave;
+
+
+
+//
+// EnableMenuItemTable contains the menu IDs for all menu items whose
+// enabled state needs to be determined dynamically i.e. based on the state
+// of Windbg.
+//
+// This table must be kept in sync with the switch statement in
+// CommandIdEnabled in order for the state of the menu id to be determined.
+//
+
+UINT
+EnableMenuItemTable[ ] = {
+ IDM_FILE_NEW,
+ IDM_FILE_OPEN,
+ IDM_FILE_MERGE,
+ IDM_FILE_CLOSE,
+ IDM_FILE_SAVE,
+ IDM_FILE_SAVEAS,
+ IDM_FILE_SAVEALL,
+
+ IDM_EDIT_UNDO,
+ IDM_EDIT_REDO,
+ IDM_EDIT_CUT,
+ IDM_EDIT_COPY,
+ IDM_EDIT_PASTE,
+ IDM_EDIT_DELETE,
+ IDM_EDIT_FIND,
+ IDM_EDIT_REPLACE,
+ IDM_EDIT_READONLY,
+
+ IDM_VIEW_LINE,
+ IDM_VIEW_FUNCTION,
+ IDM_VIEW_TOGGLETAG,
+ IDM_VIEW_NEXTTAG,
+ IDM_VIEW_PREVIOUSTAG,
+ IDM_VIEW_CLEARALLTAGS,
+
+ IDM_PROGRAM_OPEN,
+ IDM_PROGRAM_CLOSE,
+ IDM_PROGRAM_SAVE,
+ IDM_PROGRAM_SAVEAS,
+ IDM_PROGRAM_DELETE,
+ IDM_PROGRAM_SAVE_DEFAULTS,
+
+ IDM_RUN_RESTART,
+ IDM_RUN_STOPDEBUGGING,
+ IDM_RUN_GO,
+ IDM_RUN_TOCURSOR,
+ IDM_RUN_TRACEINTO,
+ IDM_RUN_STEPOVER,
+ IDM_RUN_HALT,
+ IDM_RUN_SET_THREAD,
+ IDM_RUN_SET_PROCESS,
+ IDM_RUN_GO_HANDLED,
+ IDM_RUN_GO_UNHANDLED,
+ IDM_RUN_ATTACH,
+
+ IDM_DEBUG_CALLS,
+ IDM_DEBUG_SETBREAK,
+ IDM_DEBUG_QUICKWATCH,
+ IDM_DEBUG_MODIFY,
+
+ IDM_OPTIONS_RUN,
+ IDM_OPTIONS_WATCH,
+ IDM_OPTIONS_LOCAL,
+ IDM_OPTIONS_CPU,
+ IDM_OPTIONS_FLOAT,
+ IDM_OPTIONS_CALLS,
+
+ IDM_OPTIONS_MEMORY,
+ IDM_OPTIONS_FONTS,
+
+ IDM_OPTIONS_KD,
+
+ IDM_WINDOW_NEWWINDOW,
+ IDM_WINDOW_CASCADE,
+ IDM_WINDOW_TILE,
+ IDM_WINDOW_ARRANGE,
+ IDM_WINDOW_ARRANGE_ICONS
+};
+
+#define ELEMENTS_IN_ENABLE_MENU_ITEM_TABLE \
+ ( sizeof( EnableMenuItemTable ) / sizeof( EnableMenuItemTable[ 0 ] ))
+
+UINT
+CommandIdEnabled(
+ IN UINT MenuID
+ )
+
+/*++
+
+Routine Description:
+
+ Determines if a menu item is enabled/disabled based on the current
+ state of the debugger.
+
+Arguments:
+
+ MenuID - Supplies a menu id whose state is to be determined.
+
+Return Value:
+
+ UINT - Returns ( MF_ENABLED | MF_BYCOMMAND ) if the supplied menu ID
+ is enabled, ( MF_GRAYED | MF_BYCOMMAND) otherwise.
+
+--*/
+
+{
+ BOOL Enabled;
+ NPVIEWREC v;
+ NPDOCREC d;
+ BOOL normalWin;
+ UINT uFormat;
+ int i;
+ int dtype;
+ PPANE p;
+ LPSTR List;
+ DWORD ListLength;
+ HWND hwnd;
+
+
+ //
+ // Determine the state of the debugger.
+ //
+
+ //
+ // If there is an active edit control, remember the current view,
+ // document and whether or not the active window is an icon.
+ //
+
+ if (curView >= 0) {
+ v = &Views[ curView ];
+ }
+
+ d = NULL;
+ p = NULL;
+ normalWin = FALSE;
+
+ if ( hwndActiveEdit ) {
+ if (v->Doc > -1) {
+ d = &Docs[ v->Doc ];
+ dtype = d->docType;
+ } else if (v->Doc < -1) {
+ p = (PPANE)GetWindowLong( hwndActive, GWW_EDIT);
+ dtype = -(v->Doc);
+ }
+ normalWin = ! IsIconic( hwndActive );
+ }
+
+ //
+ // Assume menu item is not enabled.
+ //
+
+ Enabled = FALSE;
+
+ switch( MenuID ) {
+
+ case IDM_FILE_NEW:
+ case IDM_FILE_OPEN:
+ Enabled = (DbgState == ds_normal);
+ break;
+
+ case IDM_FILE_CLOSE:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = (d->docType == DOC_WIN) && (DbgState == ds_normal);
+ }
+ break;
+
+ case IDM_FILE_MERGE:
+ case IDM_FILE_SAVE:
+ case IDM_FILE_SAVEAS:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = (d->docType == DOC_WIN) &&
+ !(d->readOnly) &&
+ (DbgState == ds_normal);
+ }
+ break;
+
+ case IDM_FILE_SAVEALL:
+ for (i = 0; i < MAX_VIEWS; i++) {
+ if ((Docs[Views[i].Doc].docType == DOC_WIN)) {
+ Enabled = TRUE && (DbgState == ds_normal);
+ break;
+ }
+ }
+ break;
+
+
+
+
+ case IDM_EDIT_UNDO:
+
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin
+ && !d->readOnly
+ && d->playCount >= 0
+ && d->recType != REC_STOPPED;
+ }
+ break;
+
+ case IDM_EDIT_REDO:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = hwndActiveEdit
+ && !d->readOnly
+ && d->playCount != 0
+ && d->playCount != REC_CANNOTUNDO
+ && d->recType != REC_STOPPED;
+ }
+ break;
+
+ case IDM_EDIT_CUT:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin
+ && v->BlockStatus
+ && ( v->BlockXL != v->BlockXR || v->BlockYL != v->BlockYR )
+ && !d->readOnly
+ && d->docType == DOC_WIN;
+ }
+ break;
+
+ case IDM_EDIT_COPY:
+ {
+ BOOL Enable1 = FALSE;
+ BOOL Enable2 = FALSE;
+
+
+ Enabled = FALSE;
+
+ if (d == NULL) {
+ Enable1 = FALSE;
+ if (p) {
+ Enable2 = (p->SelLen != 0);
+ }
+ } else {
+ Enable1 = normalWin &&
+ ((v->BlockStatus &&
+ ( v->BlockXL != v->BlockXR || v->BlockYL != v->BlockYR )));
+
+ if (p == NULL) {
+ Enable2 = FALSE;
+ } else {
+ Enable2 = (p->SelLen != 0);
+ }
+ }
+
+ Enabled = Enable1 || Enable2;
+ break;
+ }
+
+ case IDM_EDIT_PASTE:
+ {
+ Enabled = FALSE;
+
+ //
+ // If the window is normal, is not read only and is a document
+ // or cmdwin, determine if the clipboard contains pastable data
+ // (i.e. clipboard format CF_TEXT).
+ //
+
+ if (d == NULL) {
+ if (p != NULL) {
+ if (!p->ReadOnly && (OpenClipboard( hwndFrame ))) {
+ uFormat = 0;
+ while( uFormat = EnumClipboardFormats( uFormat )) {
+ if( uFormat == CF_TEXT ) {
+ Enabled = TRUE;
+ break;
+ }
+ }
+ CloseClipboard();
+ }
+ }
+ } else if (normalWin &&
+ ((((d->docType == DOC_WIN && !d->readOnly) ||
+ (d->docType == COMMAND_WIN && !(d->RORegionSet &&
+ ((v->Y < d->RoY2) || (v->Y == d->RoY2 && v->X < d->RoX2))))
+ ))) && OpenClipboard( hwndFrame ))
+ {
+ uFormat = 0;
+ while( uFormat = EnumClipboardFormats( uFormat )) {
+ if ( uFormat == CF_TEXT ) {
+ Enabled = TRUE;
+ break;
+ }
+ }
+ CloseClipboard();
+ } else if (p != NULL) {
+ if (!p->ReadOnly && (OpenClipboard( hwndFrame ))) {
+ uFormat = 0;
+ while ( uFormat = EnumClipboardFormats( uFormat )) {
+ if ( uFormat == CF_TEXT ) {
+ Enabled = TRUE;
+ break;
+ }
+ }
+ CloseClipboard();
+ }
+ }
+ }
+ break;
+
+
+ case IDM_EDIT_DELETE:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin
+ && ! d->readOnly
+ && (d->docType == DOC_WIN);
+ }
+ break;
+
+ case IDM_EDIT_FIND:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin
+ &&
+ ((d->docType == DOC_WIN) || (d->docType == COMMAND_WIN))
+ &&
+ frMem.hDlgFindNextWnd == 0
+ &&
+ frMem.hDlgConfirmWnd == 0;
+ }
+ break;
+
+ case IDM_EDIT_REPLACE:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin
+ &&
+ (d->docType == DOC_WIN) && (!d->readOnly)
+ &&
+ frMem.hDlgFindNextWnd == 0
+ &&
+ frMem.hDlgConfirmWnd == 0;
+ }
+ break;
+
+ case IDM_EDIT_READONLY:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = hwndActiveEdit && (d->docType == DOC_WIN);
+ }
+ break;
+
+
+
+
+ case IDM_VIEW_LINE:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin && (d->docType == DOC_WIN);
+ }
+ break;
+
+ case IDM_VIEW_FUNCTION:
+
+ Enabled = DebuggeeActive();
+ break;
+
+ case IDM_VIEW_TOGGLETAG:
+ case IDM_VIEW_NEXTTAG:
+ case IDM_VIEW_PREVIOUSTAG:
+ case IDM_VIEW_CLEARALLTAGS:
+ if (d == NULL) {
+ Enabled = FALSE;
+ } else {
+ Enabled = normalWin && d->docType == DOC_WIN;
+ }
+ break;
+
+
+
+ case IDM_PROGRAM_OPEN:
+ Enabled = !(LptdCur && LptdCur->tstate == tsRunning);
+ break;
+
+ case IDM_PROGRAM_CLOSE:
+ Enabled = IsProgramLoaded() &&
+ !(LptdCur && LptdCur->tstate == tsRunning);
+ break;
+
+ case IDM_PROGRAM_SAVE:
+ case IDM_PROGRAM_SAVEAS:
+ Enabled = TRUE;
+ break;
+
+
+ case IDM_PROGRAM_DELETE:
+ List = GetAllPrograms( &ListLength );
+ Enabled = (List != NULL);
+ if ( List ) {
+ DeallocateMultiString( List );
+ }
+ break;
+
+ case IDM_PROGRAM_SAVE_DEFAULTS:
+ Enabled = TRUE;
+ break;
+
+ case IDM_RUN_RESTART:
+
+ Enabled = !IsProcRunning( LppdCur );
+ break;
+
+ case IDM_RUN_ATTACH:
+ if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ if (runDebugParams.fKernelDebugger) {
+ Enabled = FALSE;
+ } else {
+ Enabled = TRUE;
+ }
+ } else {
+ Enabled = FALSE;
+ }
+ break;
+
+ case IDM_RUN_STOPDEBUGGING:
+ if (runDebugParams.fKernelDebugger) {
+ Enabled = FALSE;
+ } else {
+ Enabled = DebuggeeAlive();
+ }
+ break;
+
+ case IDM_RUN_HALT:
+
+ Enabled = DebuggeeActive() && IsProcRunning(LppdCur);
+ break;
+
+ case IDM_RUN_TRACEINTO:
+ case IDM_RUN_STEPOVER:
+
+ if (DbgState != ds_normal) {
+ Enabled = FALSE;
+ } else if (DebuggeeActive()) {
+ Enabled = StepOK(LppdCur, LptdCur);
+ } else {
+ Enabled = (GetLppdHead() == (LPPD)0);
+ }
+ break;
+
+ case IDM_RUN_GO:
+
+ if (DbgState != ds_normal) {
+ Enabled = FALSE;
+ } else if (DebuggeeActive()) {
+ Enabled = GoOK(LppdCur, LptdCur);
+ } else {
+ Enabled = (GetLppdHead() == (LPPD)0);
+ }
+ break;
+
+ case IDM_RUN_GO_HANDLED:
+ case IDM_RUN_GO_UNHANDLED:
+
+ if (DbgState != ds_normal) {
+ Enabled = FALSE;
+ } else if (DebuggeeActive()) {
+ Enabled = GoExceptOK(LppdCur, LptdCur);
+ } else {
+ Enabled = FALSE;
+ }
+ break;
+
+
+ case IDM_RUN_TOCURSOR:
+
+ //
+ // In addition, for IDM_RUN_CONTINUE_TO_CURSOR, caret must be in a
+ // document or the disassembler window.
+ //
+ if (DbgState != ds_normal) { // not ready?
+ Enabled = FALSE;
+ } else if (d == NULL || !hwndActiveEdit) { // no window?
+ Enabled = FALSE;
+ } else if (!DebuggeeAlive()) { // not started?
+ Enabled = (d->docType == DOC_WIN);
+ } else if (d->docType == DOC_WIN // src or asm win?
+ || d->docType == DISASM_WIN) {
+ Enabled = GoOK(LppdCur, LptdCur);
+ } else { // other.
+ Enabled = FALSE;
+ }
+
+ break;
+
+ case IDM_RUN_SET_THREAD:
+ case IDM_RUN_SET_PROCESS:
+ Enabled = DebuggeeActive();
+ break;
+
+
+ case IDM_DEBUG_CALLS:
+ Enabled = DebuggeeActive() && !IsProcRunning(LppdCur);
+ break;
+
+ case IDM_DEBUG_SETBREAK:
+ Enabled = TRUE;
+ break;
+
+
+ case IDM_DEBUG_QUICKWATCH:
+ case IDM_DEBUG_MODIFY:
+ Enabled = DebuggeeActive() && !IsProcRunning(LppdCur);
+ break;
+
+ case IDM_OPTIONS_RUN:
+ Enabled = (GetCurrentProgramName(FALSE) != NULL);
+ break;
+
+ case IDM_OPTIONS_KD:
+ Enabled = TRUE;
+ break;
+
+ case IDM_OPTIONS_WATCH:
+ Enabled = DebuggeeActive() &&
+ (hwnd = GetWatchHWND()) &&
+ (!IsIconic(hwnd)) &&
+ (dtype == WATCH_WIN);
+ break;
+
+ case IDM_OPTIONS_LOCAL:
+ Enabled = DebuggeeActive() &&
+ (hwnd = GetLocalHWND()) &&
+ (!IsIconic(hwnd)) &&
+ (dtype == LOCALS_WIN);
+ break;
+
+ case IDM_OPTIONS_CALLS:
+ Enabled = DebuggeeActive() &&
+ (hwnd = GetCallsHWND()) &&
+ (!IsIconic(hwnd)) &&
+ (dtype == CALLS_WIN);
+ break;
+
+ case IDM_OPTIONS_CPU:
+ Enabled = FALSE;
+ break;
+
+ case IDM_OPTIONS_FLOAT:
+ Enabled = FALSE;
+ break;
+
+
+ case IDM_OPTIONS_MEMORY:
+ if ( IsWindow( hwndActiveEdit ) ) {
+ // memcurView may change during loop:
+ int memcurView = GetWindowWord(hwndActiveEdit, GWW_VIEW);
+ int curDoc = Views[memcurView].Doc;
+
+ if (Docs[curDoc].docType == MEMORY_WIN) {
+ Enabled = DebuggeeActive();
+ }
+ }
+ break;
+
+
+ case IDM_OPTIONS_FONTS:
+ Enabled = hwndActiveEdit != NULL;
+ break;
+
+
+ case IDM_WINDOW_NEWWINDOW:
+
+ if (d != NULL) {
+ Enabled = hwndActiveEdit && d->docType == DOC_WIN;
+ }
+ break;
+
+
+ case IDM_WINDOW_CASCADE:
+ case IDM_WINDOW_TILE:
+ case IDM_WINDOW_ARRANGE:
+ Enabled = hwndActiveEdit != NULL;
+ break;
+
+ case IDM_WINDOW_ARRANGE_ICONS:
+ if ((hwnd = GetCpuHWND()) && IsIconic (hwnd)) {
+ Enabled = TRUE;
+ } else if ((hwnd = GetFloatHWND()) && IsIconic (hwnd)) {
+ Enabled = TRUE;
+ } else if ((hwnd = GetLocalHWND()) && IsIconic (hwnd)) {
+ Enabled = TRUE;
+ } else if ((hwnd = GetWatchHWND()) && IsIconic (hwnd)) {
+ Enabled = TRUE;
+ } else {
+ for (i = 0; i < MAX_VIEWS; i++) {
+ if (Views[i].hwndClient &&
+ IsIconic(GetParent(Views[i].hwndClient))) {
+ Enabled = TRUE;
+ break;
+ }
+ }
+ }
+ break;
+
+
+ case IDM_FILE:
+ case IDM_EDIT:
+ case IDM_VIEW:
+ case IDM_RUN:
+ case IDM_DEBUG:
+ case IDM_OPTIONS:
+ case IDM_WINDOW:
+ case IDM_HELP:
+ case IDM_PROGRAM:
+ Enabled = TRUE;
+ break;
+
+ default:
+
+ if ( MenuID > IDM_PROGRAM_LAST &&
+ MenuID <= ((UINT) IDM_PROGRAM_LAST + nbFilesKept[PROJECT_FILE])) {
+
+ Enabled = !(LptdCur && LptdCur->tstate == tsRunning);
+ break;
+ }
+
+ Enabled = FALSE;
+ break;
+ }
+
+ return (( Enabled ) ? MF_ENABLED : MF_GRAYED ) | MF_BYCOMMAND;
+}
+
+UINT
+GetPopUpMenuID(
+ IN HMENU hMenu
+ )
+
+/*++
+
+Routine Description:
+
+ Map the supplied menu handle to a menu ID.
+
+Arguments:
+
+ hMenu - Supplies a handle to a pop-up menu.
+
+Return Value:
+
+ UINT - Returns the menu ID corresponsing to the supplied menu handle.
+
+--*/
+
+{
+ INT i;
+ INT menus;
+
+ DAssert( hMainMenu != NULL );
+
+ //
+ // Loop through the menu bar for each pop-up menu.
+ //
+
+ menus = GetActualMenuCount( );
+ DAssert( menus != -1 );
+
+ for( i = 0; i < menus; i++ ) {
+
+ //
+ // If the current pop-up is the supplied pop-up, return its ID.
+ //
+
+ if( hMenu == GetSubMenu( hMainMenu, i )) {
+ return ((( i + 1 ) * IDM_BASE ) | MENU_SIGNATURE );
+ }
+ }
+
+ //
+ // The supplied menu handle wasn't found, assume it was actually a
+ // menu ID.
+ //
+
+ return ( UINT ) hMenu;
+}
+
+VOID
+InitializeMenu(
+ IN HANDLE hMenu
+ )
+
+/*++
+
+Routine Description:
+
+ InitializeMenu sets the enabled/disabled state of all menu items whose
+ state musr be determined dynamically.
+
+Arguments:
+
+ hMenu - Supplies a handle to the menu bar.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ INT i;
+ UINT checked;
+
+ //
+ // Iterate thrrough the table, enabling/disabling menu items
+ // as appropriate.
+ //
+
+ for( i = 0; i < ELEMENTS_IN_ENABLE_MENU_ITEM_TABLE; i++ ) {
+
+ EnableMenuItem(
+ hMenu,
+ EnableMenuItemTable[ i ],
+ CommandIdEnabled( EnableMenuItemTable[ i ])
+ );
+ }
+
+ //
+ // Enable/disable project files
+ //
+ for (i= IDM_PROGRAM_LAST+1; i <= IDM_PROGRAM_LAST + nbFilesKept[PROJECT_FILE]; i++ ) {
+ EnableMenuItem(
+ hMenu,
+ i,
+ CommandIdEnabled( i )
+ );
+
+ }
+
+
+ //
+ // If the document in the active window is read only,
+ // check the read only menu item.
+ //
+
+ if( hwndActiveEdit ) {
+
+ checked = ((Views[curView].Doc < 0) ||
+ (Docs[Views[curView].Doc].readOnly))
+ ? MF_CHECKED
+ : MF_UNCHECKED;
+ } else {
+
+ checked = MF_UNCHECKED;
+ }
+
+ CheckMenuItem( hMainMenu, IDM_EDIT_READONLY, checked );
+}
diff --git a/private/windbg/windbg/panemgr.c b/private/windbg/windbg/panemgr.c
new file mode 100644
index 000000000..65c25e0d7
--- /dev/null
+++ b/private/windbg/windbg/panemgr.c
@@ -0,0 +1,2339 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ panemgr.c
+
+Abstract:
+
+ This module contains the panel manager for the debug windows.
+
+Author:
+
+ William J. Heaton (v-willhe) 20-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef FE_IME
+//#include <windowsx.h>
+#ifndef GET_WM_COMMAND_HWND
+#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
+#endif
+#ifndef GET_WM_COMMAND_CMD
+#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
+#endif
+#include <winnls32.h>
+#include <ime.h>
+#endif // end of FE_IME
+
+#define PAGE (p->PaneLines-1)
+
+#define TOP_OFFSET 4
+#define BOTTOM_OFFSET 1
+#define LEFT_OFFSET 4
+#define BUTTON_SIZE 12
+#define SIZER_HANDLE 4
+#define RIGHT_OFFSET 4
+#define TOTAL_WIDTH (LEFT_OFFSET + BUTTON_SIZE + LEFT_OFFSET + SIZER_HANDLE + RIGHT_OFFSET)
+
+#define WS_STYLE WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS
+#define LBS_STYLE LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOTIFY | LBS_DISABLENOSCROLL | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT
+
+#define BUTTON_STYLE LBS_STYLE | WS_STYLE
+#define PANE_STYLE LBS_STYLE | WS_STYLE | WS_HSCROLL
+#define SCROLL_STYLE WS_CHILD | SBS_VERT
+
+#define PTEXT DT_LEFT | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER
+
+extern HMENU hMainMenuSave;
+#define PrintMenu() {char tmp[32];sprintf(tmp,"menu=%08x\n",hMainMenu); OutputDebugString(tmp);}
+#define CheckMenu() if ((DWORD)hMainMenu != (DWORD)hMainMenuSave) DebugBreak()
+
+
+
+extern void PaneSetPos( PPANE p, SHORT NewPos);
+
+/*
+* Global Storage (FILE)
+*/
+
+WNDPROC lpfnButtonEditProc = NULL; // Original Button WndProc (Plus/Minus)
+WNDPROC lpfnEditEditProc = NULL; // Original Edit Window Proc (Panes)
+WNDPROC lpfnSizerEditProc = NULL; // Original Sizer Window Proc (bar)
+
+HDC hdcSpace = NULL;
+HDC hdcPlus = NULL;
+HDC hdcMinus = NULL;
+
+
+int nLineHt = 13;
+
+char szBuffer[MAX_USER_LINE+1]; // Buffer for dealing with pane lines
+
+/*
+ * Local Structures
+ */
+
+typedef struct INFODEF *PINFO;
+typedef struct INFODEF INFO;
+
+struct INFODEF {
+ LONG Length; // Length of the Status Area
+ PFLAGS Flags; // Panel flags
+ WORD PerCent; // Pane Percent
+ char Text[1]; // Text Area (Watch Window)
+};
+
+
+/*
+ * Function Prototypes
+ */
+
+
+extern int PaneCaretNum( PPANE p);
+
+
+LONG CreatePaneWindow( HWND hWnd, WPARAM wParam, LPARAM lParam);
+void DrawPaneButton(HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis );
+void DrawPaneFormat(HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis, UCHAR * pBuff, UCHAR * pFmt);
+void DrawPaneSelection(HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis, UCHAR * pBuff);
+void PaintPane(HWND hWnd);
+void PaintSizer(HWND hWnd);
+void ResetSplitter(HWND hWndCntl, LPARAM lParam);
+void ScrollPanes( PPANE p,WPARAM wParam, LPARAM lParam);
+void SetPaneFont( HWND hWnd, PPANE p, LPLOGFONT LogFont );
+void SizePanels( PPANE p, int cx, int cy);
+void CheckHorizontalScroll (PPANE p);
+
+LONG FAR PASCAL LOADDS PaneButtonWndProc(HWND,UINT,WPARAM,LPARAM);
+LONG FAR PASCAL LOADDS PaneLeftWndProc(HWND,UINT,WPARAM,LPARAM);
+LONG FAR PASCAL LOADDS PaneRightWndProc(HWND,UINT,WPARAM,LPARAM);
+LONG FAR PASCAL LOADDS PaneSizerWndProc(HWND,UINT,WPARAM,LPARAM);
+
+
+
+
+
+/*** MDIPaneWndProc
+**
+** Synopsis:
+** LONG MDIPaneWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+**
+** Entry:
+** Standard WNDPROC (MDI flavor)
+**
+** Returns:
+** Standard WNDPROC
+**
+** Description:
+** Base WNDPROC for the Pane Manager controlled windows.
+*/
+
+LONG FAR PASCAL EXPORT MDIPaneWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+
+ PPANE p = (PPANE)GetWindowLong(hWnd, GWW_EDIT);
+ LPCHOOSEFONT Cf;
+ LONG lRet;
+
+
+
+ CheckMenu();
+
+ __try {
+
+ switch (message) {
+
+ case WM_CREATE:
+ lRet = CreatePaneWindow( hWnd, wParam, lParam);
+ return(lRet);
+
+ case WM_MDIACTIVATE:
+
+ //
+ // Activating a Window
+ //
+
+ if (hWnd == (HWND) lParam) {
+
+ hwndActive = hWnd;
+ hwndActiveEdit = hWnd;
+ curView = p->iView;
+ EnableRibbonControls(ERC_ALL, FALSE);
+ }
+
+ //
+ // Deactivating A Window
+ //
+
+ else {
+ hwndActive = NULL;
+ hwndActiveEdit = NULL;
+ curView = -1;
+ }
+ break;
+
+ case WM_DESTROY:
+ (*p->fnEditProc)(hWnd, message, 0, (LONG)p);
+ DeleteWindowMenuItem (p->iView);
+ Views[p->iView].Doc = -1; /* Clear the view out */
+ goto CallClient;
+
+ case WM_SIZE:
+
+ SizePanels( p, LOWORD(lParam), HIWORD(lParam) );
+
+ // Button pane may have changed its top index, so
+ // make sure that we resync
+
+ SyncPanes(p,(WORD)-1);
+
+ WindowTitle( p->iView, 0 );
+
+ // No Break Intended
+
+
+ case WM_PAINT:
+
+ if ( !IsIconic(hWnd) ) {
+ PaintSizer(p->hWndSizer);
+ PaintPane(hWnd);
+ }
+ goto CallClient;
+
+
+ case WM_MEASUREITEM:
+ ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = p->LineHeight;
+ return(TRUE);
+
+ case WM_DRAWITEM:
+ DrawPaneItem( hWnd, p, (LPDRAWITEMSTRUCT)lParam );
+ return(TRUE);
+
+
+ case WM_SETCURSOR:
+
+ if ( (HWND)wParam == p->hWndSizer) {
+ SetCursor(LoadCursor(NULL,IDC_SIZEWE));
+ return(TRUE);
+ }
+ goto CallClient;
+
+ case WM_SETFONT:
+ Cf = (LPCHOOSEFONT)lParam;
+ SetPaneFont( hWnd, p, Cf->lpLogFont);
+ InvalidateRect(hWnd, NULL, TRUE);
+ return(TRUE);
+
+ case WU_CLR_BACKCHANGE:
+ DeleteObject((HGDIOBJ)p->hbrBackground);
+ p->hbrBackground = CreateSolidBrush(StringColors[p->Type].BkgndColor);
+ return (TRUE);
+
+ case WM_CTLCOLORLISTBOX:
+ return ((LRESULT)(p->hbrBackground));
+
+ case WM_CLOSE:
+
+ (*p->fnEditProc)(hWnd, WM_CLOSE, 0, (LONG)p);
+ goto CallClient;
+
+
+ case WM_SETFOCUS:
+ curView = p->iView; // Make sure the doc's know we have it
+
+ if ( p->hWndFocus == NULL)
+ {
+ p->hWndFocus = p->hWndLeft;
+ p->nCtrlId = ID_PANE_LEFT;
+ }
+ else
+ if ((p->hWndFocus == p->hWndLeft))
+ p->nCtrlId = ID_PANE_LEFT;
+ else
+ if ((p->hWndFocus == p->hWndLeft))
+ p->nCtrlId = ID_PANE_RIGHT;
+ else
+ if (p->hWndFocus == p->hWndButton)
+ p->nCtrlId = ID_PANE_BUTTON;
+
+ SetFocus(p->hWndFocus);
+
+ return(FALSE);
+
+ case WM_KILLFOCUS:
+
+ HideCaret(p->hWndFocus);
+ DestroyCaret();
+ return FALSE;
+
+ case WM_VSCROLL:
+
+ switch (LOWORD(wParam))
+ {
+ case SB_LINEDOWN:
+ if (p->CurIdx < p->MaxIdx)
+ {
+ PaneSetIdx(p,(SHORT)(p->CurIdx+1));
+ PaneCaretNum(p);
+ }
+ break;
+
+ case SB_LINEUP:
+ if (p->CurIdx != 0xFFFF)
+ {
+ PaneSetIdx(p,(SHORT)(p->CurIdx-1));
+ PaneCaretNum(p);
+ }
+
+ break;
+
+ case SB_PAGEDOWN:
+ PaneSetIdx(p,(SHORT)(p->CurIdx+PAGE));
+ PaneCaretNum(p);
+
+ break;
+
+ case SB_PAGEUP:
+ PaneSetIdx(p,(SHORT)(p->CurIdx-PAGE));
+ PaneCaretNum(p);
+
+
+ break;
+
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ PaneSetIdx(p,(SHORT)((int)HIWORD(wParam)));
+ PaneCaretNum(p);
+
+ break;
+
+
+ }
+
+ return(FALSE);
+
+
+ case WM_COMMAND:
+#ifdef FE_IME
+ {
+ static BOOL bOldImeStatus;
+ TCHAR szClass[64];
+ WORD wNotice1;
+ WORD wNotice2;
+
+ if (0 < GetClassName(
+ GET_WM_COMMAND_HWND(wParam, lParam),
+ szClass, sizeof(szClass)-1)) {
+ if (lstrcmpi(szClass, TEXT("ListBox")) == 0) {
+ wNotice1 = LBN_SETFOCUS;
+ wNotice2 = LBN_KILLFOCUS;
+ } else if (lstrcmpi(szClass, TEXT("Edit")) == 0) {
+ wNotice1 = EN_SETFOCUS;
+ wNotice2 = EN_KILLFOCUS;
+ } else if (lstrcmpi(szClass, TEXT("Combobox")) == 0) {
+ wNotice1 = CBN_SETFOCUS;
+ wNotice2 = CBN_KILLFOCUS;
+ } else {
+ szClass[0] = TEXT('\0');
+ }
+ if (szClass[0]) {
+ if (GET_WM_COMMAND_CMD(wParam, lParam) == wNotice1) {
+ ImeSendVkey(
+ GET_WM_COMMAND_HWND(wParam, lParam),
+ VK_DBE_FLUSHSTRING);
+ bOldImeStatus = ImeWINNLSEnableIME(NULL, FALSE);
+ } else
+ if (GET_WM_COMMAND_CMD(wParam, lParam) == wNotice2) {
+ ImeWINNLSEnableIME(NULL, bOldImeStatus);
+ }
+ }
+ }
+ }
+ goto CallClient;
+#endif // FE_IME end
+
+ case WM_COPY:
+ case WM_PASTE:
+ PaneKeyboardHandler(p->hWndFocus, message, wParam, lParam);
+ return(TRUE);
+
+ case WU_INVALIDATE:
+
+ (*p->fnEditProc)(hWnd, message, wParam, (LONG)p);
+
+ CheckHorizontalScroll (p);
+ return(FALSE);
+
+ case WU_UPDATE:
+
+ (*p->fnEditProc)(hWnd, message, wParam, (LONG)p);
+
+ if ( p->ScrollBarUp ) {
+ SetScrollRange(p->hWndScroll, SB_CTL, 0, p->MaxIdx - 1, FALSE);
+ SetScrollPos( p->hWndScroll, SB_CTL, (INT)p->CurIdx, FALSE);
+ }
+ ShowScrollBar( p->hWndScroll, SB_CTL, p->ScrollBarUp);
+
+ if (!p->ScrollBarUp)
+ {
+ p->TopIdx = 0; //reset top if no scrolling
+ }
+
+ SyncPanes(p,(WORD)-1);
+
+ CheckHorizontalScroll (p);
+ return(FALSE);
+
+ case WU_DBG_LOADEM:
+ case WU_DBG_LOADEE:
+ case WU_DBG_UNLOADEM:
+ case WU_DBG_UNLOADEE:
+ (*p->fnEditProc)(hWnd, message, wParam, (LONG)p);
+ return(FALSE);
+
+ default:
+ CallClient:
+
+ // Call MDI client for default actions.
+ return DefMDIChildProc(hWnd, message, wParam, lParam);
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ return FALSE;
+
+ }
+
+ return FALSE;
+} /* MDIPaneWndProc() */
+
+/*** DlgPaneWndProc
+**
+** Synopsis:
+** LONG DlgPaneWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+**
+** Entry:
+** Standard WNDPROC (DLG flavor)
+**
+** Returns:
+** Standard WNDPROC
+**
+** Description:
+** Base WNDPROC for the Pane Manager controlled windows when called from a
+** dialog box
+*/
+
+LONG FAR PASCAL EXPORT DLGPaneWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ PPANE p = (PPANE)GetWindowLong(hWnd, GWW_EDIT);
+
+ CheckMenu();
+
+ __try {
+
+ switch (message) {
+
+ case WM_CREATE:
+ return( CreatePane( hWnd, 0, QUICKW_WIN) );
+ break;
+
+
+ case WM_DESTROY:
+
+ (*p->fnEditProc)(hWnd, message, 0, (LONG)p);
+ goto CallClient;
+
+ case WM_SIZE:
+
+ SizePanels( p, LOWORD(lParam), HIWORD(lParam) );
+ SyncPanes(p,(WORD)-1);
+
+ // No Break Intended
+
+
+ case WM_PAINT:
+
+ if ( !IsIconic(hWnd) ) {
+ PaintSizer(p->hWndSizer);
+ PaintPane(hWnd);
+ }
+ goto CallClient;
+
+
+ case WM_MEASUREITEM:
+ ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = p->LineHeight;
+ return(TRUE);
+
+ case WM_DRAWITEM:
+ DrawPaneItem( hWnd, p, (LPDRAWITEMSTRUCT)lParam );
+ return(TRUE);
+
+
+ case WM_SETCURSOR:
+
+ if ( (HWND)wParam == p->hWndSizer) {
+ SetCursor(LoadCursor(NULL,IDC_SIZEWE));
+ return(TRUE);
+ }
+ goto CallClient;
+
+ case WM_SETFONT:
+ SetPaneFont(hWnd, p, &defaultFont);
+ return(TRUE);
+
+ case WM_CLOSE:
+
+ (*p->fnEditProc)(hWnd, WM_CLOSE, 0, (LONG)p);
+ goto CallClient;
+
+
+ case WM_SETFOCUS:
+
+ if ((p->hWndFocus != p->hWndLeft) && (p->hWndFocus != p->hWndRight) && (p->hWndFocus != p->hWndButton))
+ {
+ p->hWndFocus = p->hWndButton;
+ p->nCtrlId = ID_PANE_BUTTON;
+ }
+ CreateCaret( p->hWndFocus, 0, 3, p->LineHeight);
+ PaneSwitchFocus(p, NULL, FALSE);
+ ShowCaret (p->hWndFocus);
+ break;
+
+
+ case WM_KILLFOCUS:
+ HideCaret(hWnd);
+ DestroyCaret();
+ break;
+
+ case WM_VSCROLL:
+ switch (LOWORD(wParam))
+ {
+
+ case SB_LINEDOWN:
+ if (p->CurIdx < p->MaxIdx)
+ {
+ PaneSetIdx(p,(SHORT)(p->CurIdx+1));
+ PaneCaretNum(p);
+ }
+ break;
+
+ case SB_LINEUP:
+ if (p->CurIdx >= 0)
+ {
+ PaneSetIdx(p,(SHORT)(p->CurIdx-1));
+ PaneCaretNum(p);
+ }
+
+ break;
+
+ case SB_PAGEDOWN:
+ PaneSetIdx(p,(SHORT)(p->CurIdx+PAGE));
+ PaneCaretNum(p);
+
+ break;
+
+ case SB_PAGEUP:
+ PaneSetIdx(p,(SHORT)(p->CurIdx-PAGE));
+ PaneCaretNum(p);
+
+
+ break;
+
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ PaneSetIdx(p,(SHORT)((int)HIWORD(wParam)));
+ PaneCaretNum(p);
+
+ break;
+
+
+ }
+ return(FALSE);
+
+
+ case WM_COMMAND:
+#ifdef FE_IME
+ {
+ static BOOL bOldImeStatus;
+ TCHAR szClass[64];
+ WORD wNotice1;
+ WORD wNotice2;
+
+ if (0 < GetClassName(
+ GET_WM_COMMAND_HWND(wParam, lParam),
+ szClass, sizeof(szClass)-1)) {
+ if (lstrcmpi(szClass, TEXT("ListBox")) == 0) {
+ wNotice1 = LBN_SETFOCUS;
+ wNotice2 = LBN_KILLFOCUS;
+ } else if (lstrcmpi(szClass, TEXT("Edit")) == 0) {
+ wNotice1 = EN_SETFOCUS;
+ wNotice2 = EN_KILLFOCUS;
+ } else if (lstrcmpi(szClass, TEXT("Combobox")) == 0) {
+ wNotice1 = CBN_SETFOCUS;
+ wNotice2 = CBN_KILLFOCUS;
+ } else {
+ szClass[0] = '\0';
+ }
+ if (szClass[0]) {
+ if (GET_WM_COMMAND_CMD(wParam, lParam) == wNotice1) {
+ ImeSendVkey(
+ GET_WM_COMMAND_HWND(wParam, lParam),
+ VK_DBE_FLUSHSTRING);
+ bOldImeStatus = ImeWINNLSEnableIME(NULL, FALSE);
+ } else
+ if (GET_WM_COMMAND_CMD(wParam, lParam) == wNotice2) {
+ ImeWINNLSEnableIME(NULL, bOldImeStatus);
+ }
+ }
+ }
+ }
+#endif // FE_IME end
+ goto CallClient;
+
+
+ case WU_INVALIDATE:
+
+ (*p->fnEditProc)(hWnd, message, wParam, (LONG)p);
+
+ CheckHorizontalScroll (p);
+ return(FALSE);
+
+ case WU_UPDATE:
+ (*p->fnEditProc)(hWnd, message, wParam, (LONG)p);
+
+ if ( p->ScrollBarUp ) {
+ SetScrollRange(p->hWndScroll, SB_CTL, 0, p->MaxIdx - 1, FALSE);
+ SetScrollPos( p->hWndScroll, SB_CTL, (INT)p->CurIdx, FALSE);
+ }
+ ShowScrollBar( p->hWndScroll, SB_CTL, p->ScrollBarUp);
+
+ if (!p->ScrollBarUp)
+ {
+ p->TopIdx = 0; //reset top if no scrolling
+ }
+
+ SyncPanes(p,(WORD)-1);
+
+ return(FALSE);
+
+ case WU_DBG_LOADEM:
+ case WU_DBG_LOADEE:
+ case WU_DBG_UNLOADEM:
+ case WU_DBG_UNLOADEE:
+
+ (*p->fnEditProc)(hWnd, message, wParam, (LONG)p);
+ return(FALSE);
+
+ default:
+ CallClient:
+
+ // Call the default dialog proc
+ return ( DefWindowProc(hWnd, message, wParam, lParam) );
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ return FALSE;
+
+ }
+
+ return FALSE;
+} /* DLGPaneWndProc() */
+
+
+/*** PaneSizerWndProc
+**
+** Synopsis:
+** LONG PASCAL PaneSizerWndProc( hWnd, Msg, wParam, lParam);
+**
+** Entry:
+** Standard Window Proc
+**
+** Returns:
+** Standard Window Proc
+**
+** Description:
+** Windows Proc for the Sizer Bar, Allows us to intercept a button
+** down message and handle moving the bar.
+**
+*/
+
+
+LONG FAR PASCAL EXPORT PaneSizerWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+
+ CheckMenu();
+
+ __try {
+
+ switch (message) {
+
+ case WM_LBUTTONDOWN:
+ ResetSplitter( hWnd, lParam );
+ return(FALSE);
+
+ default:
+
+ DAssert(lpfnSizerEditProc);
+ return(CallWindowProc(lpfnSizerEditProc,hWnd,message,wParam,lParam));
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ return 0;
+
+ }
+}
+
+
+
+/*** PaneButtonWndProc
+**
+** Synopsis:
+** LONG PaneButtonWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+**
+** Entry:
+** Standard Window Proc
+**
+** Returns:
+** Standard Window Prod
+**
+** Description:
+** The subclassed window proc for the button pane. Allow us to interscept
+** the keyboard.
+**
+*/
+
+
+LONG FAR PASCAL EXPORT PaneButtonWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+
+ PPANE p = (PPANE)GetWindowLong(GetParent(hWnd), GWW_EDIT);
+
+
+
+ CheckMenu();
+
+ __try {
+
+ switch (message) {
+
+
+ case WM_SETFOCUS:
+ CreateCaret(hWnd, 0, 3, p->LineHeight);
+ HideCaret(hWnd);
+ return FALSE;
+ break;
+
+
+ case WM_KILLFOCUS:
+ DestroyCaret();
+ return FALSE;
+ break;
+
+
+
+
+ case WM_KEYDOWN:
+ case WM_CHAR:
+ if (wParam == VK_SHIFT)
+ return(0);
+
+ PaneKeyboardHandler(hWnd, message, wParam, lParam);
+ return(0);
+
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ PaneKeyboardHandler(hWnd, message, wParam, lParam);
+ return(0);
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ if (IR_STRING == wParam) {
+ return TRUE;
+ }
+ DAssert(lpfnButtonEditProc);
+ return(lpfnButtonEditProc(hWnd,message,wParam,lParam));
+ break;
+#endif
+
+ default:
+ DAssert(lpfnButtonEditProc);
+ return(lpfnButtonEditProc(hWnd,message,wParam,lParam));
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ return 0;
+
+ }
+}
+
+
+
+/*** PaneLeftWndProc
+**
+** Synopsis:
+** LONG PASCAL PaneLeftWndProc(HWND hWnd, UINT msg, WPARAM wParam, LONG lParam)
+**
+** Entry:
+** Standard WNDPROC
+**
+** Returns:
+** Standard WNDPROC
+**
+** Description:
+** The WNDPROC for the Left Pane control. We intercept deletes and
+** backspaces and don't allow them to cross line bountries. We use
+** tab to switch between panes. We Also monitor what the top line
+** that is visible so that we can keep all the panes in sync.
+**
+*/
+
+
+LONG FAR PASCAL EXPORT PaneLeftWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+
+ PPANE p = (PPANE)GetWindowLong(GetParent(hWnd), GWW_EDIT);
+ POINT pnt;
+
+
+
+ CheckMenu();
+
+ __try {
+
+ switch (message) {
+
+
+ case WM_SETFOCUS:
+ CreateCaret(hWnd, 0, 3, p->LineHeight);
+ SetCaretPos (p->X, p->Y);
+ ShowCaret (hWnd);
+ return FALSE;
+ break;
+
+
+ case WM_KILLFOCUS:
+ GetCaretPos(&pnt);
+ p->X = pnt.x;
+ p->Y = pnt.y;
+ HideCaret(hWnd);
+ DestroyCaret();
+ return FALSE;
+ break;
+
+
+
+ case WM_KEYDOWN:
+ case WM_CHAR:
+ if (wParam == VK_SHIFT)
+ return(0);
+ PaneKeyboardHandler(hWnd, message, wParam, lParam);
+ return(0);
+
+
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ PaneKeyboardHandler(hWnd, message, wParam, lParam);
+ CheckMenu();
+ return(0);
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ if (IR_STRING == wParam) {
+ return TRUE;
+ }
+ DAssert(lpfnEditEditProc);
+ return(lpfnEditEditProc(hWnd,message,wParam,lParam));
+ break;
+#endif
+
+ default:
+ DAssert(lpfnEditEditProc);
+ return(lpfnEditEditProc(hWnd,message,wParam,lParam));
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ CheckMenu();
+ return FALSE;
+
+ }
+
+ CheckMenu();
+ return(FALSE);
+}
+
+/*** PaneRightWndProc
+**
+** Synopsis:
+** LONG PASCAL PaneRightWndProc(HWND hWnd, UINT msg, WPARAM wParam, LONG lParam)
+**
+** Entry:
+** Standard WNDPROC
+**
+** Returns:
+** Standard WNDPROC
+**
+** Description:
+** The WNDPROC for the Right Pane. We intercept deletes and
+** backspaces and don't allow them to cross line bountries. We use
+** tab to switch between panes. We Also monitor what the top line
+** that is visible so that we can keep all the panes in sync.
+**
+**
+*/
+
+
+LONG FAR PASCAL EXPORT PaneRightWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+
+ PPANE p = (PPANE)GetWindowLong(GetParent(hWnd), GWW_EDIT);
+ POINT pnt;
+
+ CheckMenu();
+
+ __try {
+
+ switch (message) {
+
+ case WM_SETFOCUS:
+ CreateCaret(hWnd, 0, 3, p->LineHeight);
+ SetCaretPos (p->X, p->Y);
+ ShowCaret (hWnd);
+ return FALSE;
+ break;
+
+
+ case WM_KILLFOCUS:
+ GetCaretPos(&pnt);
+ p->X = pnt.x;
+ p->Y = pnt.y;
+ HideCaret(hWnd);
+ DestroyCaret();
+ return FALSE;
+ break;
+
+
+ case WM_KEYDOWN:
+ case WM_CHAR:
+ if (wParam == VK_SHIFT)
+ return(0);
+ PaneKeyboardHandler(hWnd, message, wParam, lParam);
+ return(0);
+
+
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ PaneKeyboardHandler(hWnd, message, wParam, lParam);
+ CheckMenu();
+ return(0);
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ if (IR_STRING == wParam) {
+ return TRUE;
+ }
+ DAssert(lpfnEditEditProc);
+ return(lpfnEditEditProc(hWnd,message,wParam,lParam));
+ break;
+#endif
+
+ default:
+ DAssert(lpfnEditEditProc);
+ return(lpfnEditEditProc(hWnd,message,wParam,lParam));
+ }
+
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ CheckMenu();
+ return FALSE;
+
+ }
+
+ CheckMenu();
+ return(FALSE);
+}
+/*** OpenPanedWindow
+**
+** Synopsis:
+** void OpenPanedWindow(WORD type);
+**
+** Entry:
+** type - The Type of Window to Open (WATCH_WIN, LOCALS_WIN...)
+**
+** Returns:
+** None
+**
+** Description:
+** Creates (or makes visible the type of window needed.
+*/
+
+
+void OpenPanedWindow(int type, LPWININFO lpWinInfo, int Preference)
+{
+ WORD classId;
+ WORD winTitle;
+ HWND hWnd;
+ int view;
+ BOOL fZoomed;
+
+ MDICREATESTRUCT mcs;
+ char class[MAX_MSG_TXT];
+ char title[MAX_MSG_TXT];
+ char final[MAX_MSG_TXT+4];
+
+ if (hwndActive != NULL)
+ fZoomed = IsZoomed(hwndActive) || IsZoomed(GetParent(hwndActive));
+ else
+ fZoomed = FALSE;
+
+ // Figure out the details of what we're to do
+
+ switch ( type ) {
+ case WATCH_WIN:
+ classId = SYS_Watch_wClass;
+ winTitle = SYS_WatchWin_Title;
+ hWnd = GetWatchHWND();
+ break;
+
+ case LOCALS_WIN:
+ classId = SYS_Locals_wClass;
+ winTitle = SYS_LocalsWin_Title;
+ hWnd = GetLocalHWND();
+ break;
+
+ case CPU_WIN:
+ classId = SYS_Cpu_wClass;
+ winTitle = SYS_CpuWin_Title;
+ hWnd = GetCpuHWND();
+ break;
+
+ case FLOAT_WIN:
+ classId = SYS_Float_wClass;
+ winTitle = SYS_FloatWin_Title;
+ hWnd = GetFloatHWND();
+ break;
+
+ default:
+ DAssert(FALSE);
+ return;
+ }
+
+ // If we don't have one yet, create it
+
+ if ( hWnd == NULL) {
+
+ /*
+ * Determine which view index we are going to use
+ */
+
+ if ( (Preference != -1) && (Views[Preference].Doc == -1) ) {
+ view = Preference;
+ }
+
+ else {
+ for (view=0; (view < MAX_VIEWS) && (Views[view].Doc != -1); view++);
+ }
+
+ if (view == MAX_VIEWS) {
+ ErrorBox(ERR_Too_Many_Opened_Views);
+ return;
+ }
+
+ // Get the Window Title and Window Class
+
+ Dbg(LoadString(hInst, classId, class, MAX_MSG_TXT));
+ Dbg(LoadString(hInst, winTitle, title, MAX_MSG_TXT));
+ RemoveMnemonic(title,title);
+ sprintf(final,"<%d> %s",view+1,title);
+
+ // Make sure the Menu gets setup
+ AddWindowMenuItem(-type, view);
+
+ // Have MDI Client create the Child
+
+ mcs.szTitle = final;
+ mcs.szClass = class;
+ mcs.hOwner = hInst;
+ if (lpWinInfo) {
+ mcs.x = lpWinInfo->coord.left;
+ mcs.y = lpWinInfo->coord.top;
+ mcs.cx = lpWinInfo->coord.right - lpWinInfo->coord.left;
+ mcs.cy = lpWinInfo->coord.bottom - lpWinInfo->coord.top;
+ mcs.style = (lpWinInfo->style & ~(WS_MAXIMIZE));
+ } else {
+ mcs.x = mcs.cx = CW_USEDEFAULT;
+ mcs.y = mcs.cy = CW_USEDEFAULT;
+ mcs.style = 0L;
+ }
+ mcs.lParam = (ULONG) (type | (view << 16));
+
+ Views[view].hwndClient = hwndMDIClient;
+ Views[view].NextView = -1; /* No next view */
+ Views[view].Doc = -type;
+
+ hWnd = (HANDLE)SendMessage(hwndMDIClient, WM_MDICREATE, 0,
+ (LPARAM)(LPMDICREATESTRUCT)&mcs);
+
+ SetWindowWord(hWnd, GWW_VIEW, (WORD)view);
+ Views[view].hwndFrame = hWnd;
+ }
+
+
+ // Child already exists, reactivate the previous one.
+
+ else {
+
+ if (IsIconic(hWnd))
+ OpenIcon(hWnd);
+
+ SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM)hWnd, (ULONG)type);
+ }
+
+ // Set the style of the window to maximized if the
+ // active window is currently maximized, to nothing otherwise
+
+ if (fZoomed) {
+ ShowWindow(hWnd, SW_MAXIMIZE);
+ }
+
+ return;
+}
+
+
+/*** PaintPane
+**
+** Synopsis:
+** PaintPane( HWND hWnd);
+**
+** Entry:
+** hWnd - Handle to the base window of the pane
+**
+** Returns:
+** None
+**
+** Description:
+** Paints the accents for the base window to give it a 3D look
+**
+*/
+
+
+void PaintPane(HWND hWnd)
+{
+ PAINTSTRUCT ps;
+ HPEN blackPen, whitePen;
+
+ BeginPaint (hWnd, &ps);
+
+ //Prepare the pens
+ Dbg(whitePen = GetStockObject(WHITE_PEN));
+ Dbg(blackPen = GetStockObject(BLACK_PEN));
+
+ //Draw a top white line
+ Dbg(SelectObject(ps.hdc, whitePen));
+ MoveToX(ps.hdc, ps.rcPaint.left, 0, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, 0);
+
+ EndPaint (hWnd, &ps);
+}
+
+/*** PaintSizer
+**
+** Synopsis:
+** PaintSizer( HWND hWnd );
+**
+** Entry:
+** hWnd - Handle to the sizer window.
+**
+** Returns:
+** None
+**
+** Description:
+** Paints the accents on the sizer control to give it a 3D look.
+*/
+
+
+void PaintSizer(HWND hWnd)
+{
+ PAINTSTRUCT ps;
+ HPEN blackPen, grayPen;
+ int cx;
+
+ BeginPaint (hWnd, &ps);
+ cx = ps.rcPaint.right - ps.rcPaint.left - 1;
+
+ //Prepare the pens
+ Dbg(blackPen = GetStockObject(BLACK_PEN));
+ Dbg(grayPen = CreatePen(PS_SOLID, cx, GRAYDARK));
+
+ // Background to gray
+ Dbg(SelectObject(ps.hdc, grayPen));
+ MoveToX(ps.hdc, ps.rcPaint.left + (cx/2),ps.rcPaint.top, NULL);
+ LineTo(ps.hdc, ps.rcPaint.left + (cx/2), ps.rcPaint.bottom);
+
+ // Left side to white
+ Dbg(SelectObject(ps.hdc, blackPen));
+ MoveToX(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, NULL);
+ LineTo(ps.hdc, ps.rcPaint.left, ps.rcPaint.bottom);
+
+ // Right side to black
+ Dbg(SelectObject(ps.hdc, blackPen));
+ MoveToX(ps.hdc, ps.rcPaint.right, ps.rcPaint.top, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, ps.rcPaint.bottom);
+
+ // Lose the Pen and release the paint
+ Dbg(DeleteObject (grayPen));
+ EndPaint (hWnd, &ps);
+
+}
+
+
+/*** SyncPanes
+**
+** Synopsis:
+** SyncPanes(PPANE p, WORD Index);
+**
+** Entry:
+** p - Pointer to the Pane structure.
+** Index - Index to Sync to
+**
+** Returns:
+** None
+**
+** Description:
+** Checks each of the pane controls (Button Pane, Left Pane, Right Pane)
+** makes sure that the index of the top line is the same.
+*/
+
+void SyncPanes(PPANE p, WORD NewTop)
+{
+ if ( NewTop != (WORD)-1)
+ p->TopIdx = NewTop;
+
+
+ if ( p->ScrollBarUp)
+ {
+ SetScrollRange(p->hWndScroll, SB_CTL, 0, (p->MaxIdx - 1), FALSE);
+ SetScrollPos(p->hWndScroll, SB_CTL, (WPARAM)p->CurIdx, TRUE);
+ }
+
+
+ SendMessage(p->hWndButton, LB_SETTOPINDEX, (WPARAM)p->TopIdx,0);
+ SendMessage(p->hWndLeft , LB_SETTOPINDEX, (WPARAM)p->TopIdx,0);
+ SendMessage(p->hWndRight , LB_SETTOPINDEX, (WPARAM)p->TopIdx,0);
+
+}
+
+
+/*** SizePanels
+**
+** Synopsis:
+** SizePanels(PPANE p, int cx, int cy);
+**
+** Entry:
+** p - Pointer to the Pane structure.
+** cx - The New width of the base window
+** cy - The New height of the base window
+**
+** Returns:
+** None
+**
+** Description:
+** Sizes the panes in the window to fit the new size of the base.
+*/
+
+void SizePanels( PPANE p, int cx, int cy)
+{
+ int bar_width;
+ int bar_height;
+ int height, left_pane, right_pane, left_start, right_start;
+
+
+ //
+ // Calculate where things should go
+ //
+
+ bar_width = GetSystemMetrics(SM_CXVSCROLL);
+ bar_height = GetSystemMetrics(SM_CXHSCROLL);
+ height = cy - TOP_OFFSET - BOTTOM_OFFSET + 2;
+ left_start = LEFT_OFFSET + BUTTON_SIZE + LEFT_OFFSET + 1;
+ left_pane = ((cx - TOTAL_WIDTH ) * p->PanePerCent ) / 1000;
+ right_start = left_start + left_pane + SIZER_HANDLE + 1;
+ right_pane = cx - TOTAL_WIDTH - left_pane;
+
+ p->PaneLines = (height - bar_height)/p->LineHeight;
+ p->ScrollBarUp = p->MaxIdx > p->PaneLines;
+
+
+ //
+ // Move the Pane components into their new positions
+ //
+
+ MoveWindow(p->hWndButton,LEFT_OFFSET,TOP_OFFSET,BUTTON_SIZE,height - bar_height ,TRUE);
+ MoveWindow(p->hWndLeft,left_start,TOP_OFFSET,left_pane,height,TRUE);
+ MoveWindow(p->hWndSizer,left_start+left_pane,TOP_OFFSET,SIZER_HANDLE,height,TRUE);
+
+ // Do Scroll bar first, it may adjust the right pane size
+
+
+ if ( p->ScrollBarUp ) {
+ right_pane -= bar_width;
+
+ SetScrollRange(p->hWndScroll, SB_CTL, 0, p->MaxIdx - 1, FALSE);
+
+ SetScrollPos( p->hWndScroll, SB_CTL, (INT)p->CurIdx, TRUE);
+
+ MoveWindow(p->hWndScroll, cx - bar_width - RIGHT_OFFSET + 2, TOP_OFFSET,
+ bar_width, height - bar_height, TRUE);
+ }
+ ShowScrollBar( p->hWndScroll, SB_CTL, p->ScrollBarUp);
+
+ if (!p->ScrollBarUp)
+ {
+ p->TopIdx = 0; //reset top if no scrolling
+ }
+ // Now do the right pane
+
+ MoveWindow(p->hWndRight,right_start,TOP_OFFSET,right_pane,height,TRUE);
+
+ //InvalidateRect (p->hWndButton,NULL,TRUE);
+ //InvalidateRect (p->hWndLeft,NULL,TRUE);
+ //InvalidateRect (p->hWndRight,NULL,TRUE);
+
+
+ UpdateWindow (p->hWndButton);
+ UpdateWindow (p->hWndLeft);
+ UpdateWindow (p->hWndRight);
+
+
+ CheckHorizontalScroll (p);
+}
+
+
+void CheckHorizontalScroll (PPANE p)
+{
+ int Max, i, MaxLen, nItems;
+ PANEINFO Info = {0,0,0,0,NULL};
+ SIZE Size;
+ HDC hDC;
+
+
+ if (p->hWndLeft) {
+ Max = 0;
+ Info.CtrlId = ID_PANE_LEFT;
+ nItems = min(p->PaneLines,p->MaxIdx);
+ if (nItems > 0) {
+ for (i = 0;i < nItems ;i++) {
+ Info.ItemId = i;
+ (*p->fnEditProc)(p->hWndLeft,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ if (Info.pBuffer) {
+ MaxLen = strlen (Info.pBuffer);
+ hDC = GetDC(p->hWndLeft);
+ SelectObject(hDC, p->hFont);
+ GetTextExtentPoint(hDC, Info.pBuffer, MaxLen, &Size);
+ ReleaseDC(p->hWndLeft,hDC);
+ }
+ if (Size.cx > Max) {
+ Max = Size.cx;
+ }
+ }
+ SendMessage(p->hWndLeft, LB_SETHORIZONTALEXTENT, (WPARAM)(Max + p->CharWidth), 0);
+ }
+ }
+
+ if (p->hWndRight) {
+ Max = 0;
+ Info.CtrlId = ID_PANE_RIGHT;
+ nItems = min(p->PaneLines,p->MaxIdx);
+ if (nItems > 0) {
+ for (i = 0;i < nItems ;i++) {
+ Info.ItemId = i;
+ (*p->fnEditProc)(p->hWndRight,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ if (Info.pBuffer != NULL) {
+ MaxLen = strlen (Info.pBuffer);
+ hDC = GetDC(p->hWndRight);
+ SelectObject(hDC, p->hFont);
+ GetTextExtentPoint(hDC, Info.pBuffer, MaxLen, &Size);
+ ReleaseDC(p->hWndRight,hDC);
+ }
+ if (Size.cx > Max) {
+ Max = Size.cx;
+ }
+ }
+ SendMessage(p->hWndRight, LB_SETHORIZONTALEXTENT, (WPARAM)(Max + p->CharWidth), 0);
+ }
+ }
+}
+
+
+/*** CreatePaneWindow
+**
+** Synopsis:
+** CreatePaneWindow( WPARAM wParam, LPARAM lParam)
+**
+** Entry:
+** hWnd - hWnd from the WM_CREATE message
+** wParam - wParam from the WM_CREATE message
+** lParam - lParam from the WM_CREATE message
+**
+** Returns:
+** None
+**
+** Description:
+** Create the Pane manager information, and windows and
+** in general gets everything setup for operations.
+*/
+
+LONG CreatePaneWindow( HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+ MDICREATESTRUCT FAR *mdi;
+ int iView;
+ int iType;
+
+ // Get the MDICREATE struct
+
+ mdi = (MDICREATESTRUCT FAR *)
+ (((CREATESTRUCT FAR *)lParam)->lpCreateParams);
+
+ iView = (mdi->lParam >> 16) & 0xffff;
+ iType = (WORD)(mdi->lParam & 0xffff);
+ return( CreatePane( hWnd, iView, iType) );
+}
+
+/*** CreatePane
+**
+** Synopsis:
+** CreatePane( HWND hWnd, int iView, int iType)
+**
+** Entry:
+** hWnd - hWnd from the WM_CREATE message
+** iView - View number for this window (zero if dialog)
+** lType - Window Type
+**
+** Returns:
+** TRUE/FALSE
+**
+** Description:
+** Create the Pane manager information, and windows and
+** in general gets everything setup for operations.
+*/
+
+LONG CreatePane( HWND hWnd, int iView, int iType )
+{
+ PPANE p;
+ HDC hdc;
+ HBITMAP hBitmap;
+
+ // Allocate the Pane data and store it in the class data
+
+ if ( (p = calloc(1,sizeof(PANE))) == NULL) {
+ return(FALSE);
+ }
+
+ SetWindowLong(hWnd, GWW_EDIT, (LONG)p);
+ p->iView = iView;
+ p->Type = iType;
+
+ // Set the Window Specific Details
+
+ switch ( p->Type ) {
+
+ case WATCH_WIN:
+ p->ColorItem = WatchWindow;
+ p->fnEditProc = WatchEditProc;
+ if (Views[iView].Doc < 0)
+ Views[iView].hwndFrame = hWnd;
+ break;
+
+
+ case LOCALS_WIN:
+ p->ColorItem = LocalsWindow;
+ p->fnEditProc = LocalEditProc;
+ if (Views[iView].Doc < 0)
+ Views[iView].hwndFrame = hWnd;
+ break;
+
+ case CPU_WIN:
+ p->ColorItem = RegistersWindow;
+ p->fnEditProc = CPUEditProc;
+ if (Views[iView].Doc < 0)
+ Views[iView].hwndFrame = hWnd;
+ break;
+
+ case FLOAT_WIN:
+ p->ColorItem = FloatingPointWindow;
+ p->fnEditProc = CPUEditProc;
+ if (Views[iView].Doc < 0)
+ Views[iView].hwndFrame = hWnd;
+ break;
+
+ case QUICKW_WIN:
+ p->ColorItem = WatchWindow;
+ p->fnEditProc = QuickEditProc;
+ break;
+
+ default:
+ DAssert(FALSE);
+ return(FALSE);
+ }
+
+
+ // Setup the default info
+
+ p->PanePerCent = 300; // Default to 30.0%
+ p->ScrollBarUp = FALSE; // Default to no-scroll bar
+ p->LeftOk = FALSE; // Left Pane needs painting
+ p->RightOk = FALSE; // Right Pane needs painting
+ p->nXoffLeft = 0;
+ p->nXoffRight = 0;
+ p->X = 0;
+ p->Y = 0;
+
+ //Initialize font information for Pane Windows
+ SetPaneFont(hWnd, p, &defaultFont);
+
+ // Initialize background brush for Pane Windows
+ p->hbrBackground = CreateSolidBrush(StringColors[iType].BkgndColor);
+
+ // Create Buttons, subclass the editproc
+ p->hWndButton = CreateWindow( "ListBox" , "", BUTTON_STYLE,
+ 0, 0, 0, 0, hWnd,(HMENU)ID_PANE_BUTTON,hInst,NULL);
+ lpfnButtonEditProc = (WNDPROC)GetWindowLong(p->hWndButton, GWL_WNDPROC);
+ SetWindowLong(p->hWndButton, GWL_WNDPROC, (LONG)PaneButtonWndProc);
+
+
+ // Create Expression Pane and Subclass the edit proc
+ p->hWndLeft = CreateWindow("ListBox", "", PANE_STYLE,
+ 0, 0, 0, 0, hWnd, (HMENU)ID_PANE_LEFT, hInst,NULL);
+ lpfnEditEditProc = (WNDPROC)GetWindowLong(p->hWndLeft, GWL_WNDPROC);
+ SetWindowLong(p->hWndLeft, GWL_WNDPROC, (LONG)PaneLeftWndProc);
+
+
+ // Create Sizer Handle
+ p->hWndSizer = CreateWindow("Edit", "", WS_CHILD | WS_VISIBLE,
+ 0, 0, 0, 0, hWnd, (HMENU)ID_PANE_SIZER, hInst,NULL);
+ lpfnSizerEditProc = (WNDPROC)GetWindowLong(p->hWndSizer, GWL_WNDPROC);
+ SetWindowLong(p->hWndSizer, GWL_WNDPROC, (LONG)PaneSizerWndProc);
+
+
+ // Create Results Pane, reference our editproc
+ p->hWndRight = CreateWindow("ListBox", "", PANE_STYLE,
+ 0, 0, 0, 0, hWnd, (HMENU)ID_PANE_RIGHT, hInst,NULL);
+ SetWindowLong(p->hWndRight, GWL_WNDPROC, (LONG)PaneRightWndProc);
+
+
+ // Create Scroll Bar
+ p->hWndScroll = CreateWindow("ScrollBar",NULL, SCROLL_STYLE,
+ 0, 0, 0, 0, hWnd, (HMENU)ID_PANE_SCROLL, hInst, NULL);
+
+ // Once again now that we have the children windows
+ SetPaneFont(hWnd, p, &defaultFont);
+
+ // If we don't have the BITMAP hdc's get them
+ if ( hdcSpace == NULL) {
+ Dbg(hdc = GetDC(p->hWndButton));
+
+ Dbg(hdcSpace = CreateCompatibleDC(hdc));
+ Dbg(hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(VGA_PANE_BLANK)));
+ Dbg(SelectObject(hdcSpace, hBitmap));
+
+ Dbg(hdcPlus = CreateCompatibleDC(hdc));
+ Dbg(hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(VGA_PANE_PLUS)));
+ Dbg(SelectObject(hdcPlus, hBitmap));
+
+ Dbg(hdcMinus = CreateCompatibleDC(hdc));
+ Dbg(hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(VGA_PANE_MINUS)));
+ Dbg(SelectObject(hdcMinus, hBitmap));
+
+ ReleaseDC(p->hWndButton, hdc);
+ }
+
+ // Initilize the Window
+ (*p->fnEditProc)(hWnd, WU_INITDEBUGWIN, 0, (LONG)p);
+
+ PaneSwitchFocus(p, NULL, FALSE);
+ return((LONG)hWnd);
+}
+
+/*** SetPaneFont
+**
+** Synopsis:
+** void SetPaneFont( HWND hWnd, PPANE p, HFONT hFont);
+**
+** Entry:
+** hWnd - Handle of the Pane Managed Window
+** p - Pointer to the Pane Manager Info
+** hFont - Handle to the New Font
+**
+** Returns:
+** None
+**
+** Description:
+** Sets a new font to be used in the pane manager window.
+*/
+
+
+void SetPaneFont( HWND hWnd, PPANE p, LPLOGFONT LogFont )
+{
+ HDC hDC;
+ TEXTMETRIC tm;
+ int Max;
+
+ p->hFont = CreateFontIndirect(LogFont);
+ Views[p->iView].font = p->hFont;
+
+
+ hDC = GetDC(hWnd);
+ SelectObject(hDC, p->hFont);
+ GetTextMetrics(hDC, &tm);
+ GetCharWidth(hDC, 0, MAX_CHARS_IN_FONT - 1, (LPINT)(Views[p->iView].charWidth));
+ ReleaseDC(hWnd, hDC);
+
+ p->LineHeight = (WORD)tm.tmHeight;
+ nLineHt = tm.tmHeight;
+ p->CharWidth = (WORD)tm.tmMaxCharWidth;
+ Max = tm.tmMaxCharWidth * 256;
+
+
+ if ( p->hWndButton) {
+ SendMessage(p->hWndButton,WM_SETFONT,(WPARAM)p->hFont,(LPARAM)FALSE);
+ SendMessage(p->hWndButton,LB_SETITEMHEIGHT, 0, MAKELPARAM(p->LineHeight,0));
+ SendMessage(p->hWndButton,WM_SETFOCUS,0,0L);
+
+ }
+
+ if ( p->hWndLeft ) {
+ SendMessage(p->hWndLeft, WM_SETFONT,(WPARAM)p->hFont,(LPARAM)FALSE);
+ SendMessage(p->hWndLeft, LB_SETITEMHEIGHT, 0, MAKELPARAM(p->LineHeight,0));
+ SendMessage(p->hWndLeft, LB_SETHORIZONTALEXTENT, (WPARAM)Max, 0);
+ SendMessage(p->hWndLeft, WM_SETFOCUS,0,0L);
+ }
+
+ if ( p->hWndRight) {
+ SendMessage(p->hWndRight, WM_SETFONT,(WPARAM)p->hFont,(LPARAM)FALSE);
+ SendMessage(p->hWndRight, LB_SETITEMHEIGHT, 0, MAKELPARAM(p->LineHeight,0));
+ SendMessage(p->hWndRight, LB_SETHORIZONTALEXTENT, (WPARAM)Max, 0);
+ SendMessage(p->hWndRight, WM_SETFOCUS,0,0L);
+
+ }
+
+ if ( p->hWndLeft)
+ SendMessage (p->hWndLeft,WM_SETFOCUS,0,0L);
+
+ return;
+}
+
+
+/*** ResetSplitter
+**
+** Synopsis:
+** ResetSplitter( hWndCntrl )
+**
+** Entry:
+** hWnd - hWnd from the WM_LBUTTONDOWN message
+** lParam - lParam from WM_BUTTONDOWN message
+**
+** Returns:
+** None
+**
+** Description:
+** Allows the user to move the splitter control.
+*/
+
+void ResetSplitter(HWND hWndCntl, LPARAM lParam)
+{
+ HWND hWnd = GetParent(hWndCntl);
+ PPANE p = (PPANE)GetWindowLong(hWnd, GWW_EDIT);
+ RECT rc;
+ HDC hdc;
+ MSG msg;
+ INT x, y, dx, dy;
+ HCURSOR hOldCursor;
+ int PerCent;
+ BOOL Hit = FALSE;
+
+ hOldCursor = SetCursor(LoadCursor(NULL, IDC_SIZEWE));
+
+ // Get the Size of splitter bar
+ GetClientRect(hWndCntl, &rc);
+ x = LOWORD(lParam);
+ y = rc.top;
+ dx = rc.right - rc.left;
+ dy = rc.bottom - rc.top;
+
+ // Grap the device context and the mouse, then invert a vertical bar
+ hdc = GetDC(hWnd);
+ SetCapture(hWnd);
+ PatBlt(hdc, x - dx / 2, y, dx, dy, PATINVERT);
+
+ // Track the mouse for a while
+ while (GetMessage(&msg, NULL, 0, 0)) {
+
+ if ( msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST ) {
+
+ if (msg.message == WM_LBUTTONUP ||
+ msg.message == WM_LBUTTONDOWN)
+ break;
+
+
+ if (msg.message == WM_MOUSEMOVE) {
+
+ // erase old
+ PatBlt(hdc, x - dx / 2, y, dx, dy, PATINVERT);
+ ScreenToClient(hWnd, &msg.pt);
+ x = msg.pt.x;
+
+ // put down new
+ PatBlt(hdc, x - dx / 2, y, dx, dy, PATINVERT);
+ Hit = TRUE;
+ }
+ }
+
+ else {
+ DispatchMessage(&msg);
+ }
+ }
+
+ // Clean-up the track clutter
+
+ ReleaseCapture();
+ PatBlt(hdc, x - dx / 2, y, dx, dy, PATINVERT);
+ ReleaseDC(hWnd, hdc);
+ SetCursor(hOldCursor);
+
+ // Calculate the new percentage
+
+ GetClientRect(hWnd, &rc);
+
+ //PerCent = ((x-TOTAL_WIDTH) * 1000)/(WORD)(rc.right-rc.left - TOTAL_WIDTH);
+ if ( Hit ) {
+ PerCent = ((x-TOTAL_WIDTH+SIZER_HANDLE+RIGHT_OFFSET) * 1000)/(WORD)(rc.right-rc.left - TOTAL_WIDTH);
+
+ if ( PerCent < 10) {
+ p->PanePerCent = 10;
+ } else if ( PerCent > 990) {
+ p->PanePerCent = 990;
+ } else {
+ p->PanePerCent = (WORD)PerCent;
+ }
+
+ PostMessage(hWnd, WM_SIZE, 0, MAKELONG(rc.right,rc.bottom));
+ }
+}
+
+/*** CheckPaneScrollBar
+**
+** Synopsis:
+** void CheckPaneScrollBar( pInfo, NewCount)
+**
+** Entry:
+** PPANE pInfo - Pointer to the Pane Information
+** WORD NewCount - New Count of Lines in the controls
+**
+** Returns:
+** None
+**
+** Description:
+** Called when the number of items in the controls changed (or that
+** size of the panes changed). Determines if we need a scroll bar
+** or not, and then makes it visible or not as needed.
+*/
+
+void CheckPaneScrollBar( PPANE p, WORD Count)
+{
+ int nHeight;
+ int nWidth;
+ RECT Rect;
+
+ int nBar = GetSystemMetrics(SM_CXHSCROLL);
+ BOOL fNeedBar = ((WORD)Count > p->PaneLines);
+
+
+
+ // Exit if what we need is what we have
+ if ( fNeedBar == p->ScrollBarUp) {
+ if ( p->PaneLines ) {
+ SetScrollRange(p->hWndScroll, SB_CTL, 0, p->MaxIdx - 1, FALSE);
+ CheckHorizontalScroll (p);
+ }
+ return;
+ }
+
+ // Get size of Right Pane
+ GetClientRect( GetParent(p->hWndRight), &Rect);
+ nHeight = Rect.bottom - Rect.top;
+ nWidth = Rect.right - Rect.left;
+
+
+ // Get Current Size Pane Windows Client Area and resize the panels.
+
+ GetClientRect( GetParent(p->hWndRight), &Rect);
+ nHeight = Rect.bottom - Rect.top;
+ nWidth = Rect.right - Rect.left;
+ SizePanels( p, nWidth, nHeight);
+ CheckHorizontalScroll (p);
+ return;
+}
+
+
+/*** ScrollPanes
+**
+** Synopsis:
+** void ScrollPanes( PPANE pPane, WPARAM wParam, LPARAM lParam);
+**
+** Entry:
+** PPANE pPane - Pointer to the pane information
+** WPARAM wParam - The wParam from the WM_VSCROLL
+** LPARAM lPAram - The lParam from the WM_VSCROLL
+**
+** Returns:
+** None
+**
+** Description:
+** Services the WM_VSCROLL message. Determines the type of scroll
+** and then does it.
+*/
+
+void ScrollPanes( PPANE p,WPARAM wParam, LPARAM lParam)
+{
+ int nScroll = (int) LOWORD(wParam);
+ int nPos = (int) HIWORD(wParam);
+ int nNewPos = (int)p->TopIdx;
+
+ Unreferenced(lParam);
+
+ switch ( nScroll ) {
+ case SB_LINEDOWN:
+ nNewPos++;
+ break;
+
+ case SB_LINEUP:
+ nNewPos--;
+ break;
+
+ case SB_PAGEDOWN:
+ nNewPos += (p->PaneLines-1);
+ break;
+
+ case SB_PAGEUP:
+ nNewPos -= (p->PaneLines-1);
+ break;
+
+ case SB_THUMBTRACK:
+ case SB_THUMBPOSITION:
+ nNewPos = (WORD)nPos;
+ break;
+
+ case SB_TOP:
+ nNewPos = 0;
+ break;
+
+ case SB_BOTTOM:
+ nNewPos = p->MaxIdx-1;
+ break;
+ }
+
+ // Range check the result
+
+ if ( nNewPos < 0 ) {
+ nNewPos = 0;
+ }
+
+ else if ( nNewPos > p->MaxIdx-1) {
+ nNewPos = p->MaxIdx-1;
+ }
+
+
+
+ // And Sync the Pane
+
+ StatusLineColumn(p->CurIdx+1, 1);
+ SyncPanes(p, (WORD)nNewPos);
+ return;
+}
+
+
+
+/*** GetPaneStatus
+**
+** Synopsis:
+** PLONG GetPaneStatus( ViewNo );
+**
+** Entry:
+** int ViewNo - The View number we need status for
+**
+** Returns:
+** Returns a pointer to status area.
+**
+** Description:
+** Returns a buffer with status information for a given view number.
+** The first long in the buffer is the length of the buffer (including
+** this field). When you are done with the status area use
+** FreePaneStatus() to clean up.
+*/
+
+PLONG GetPaneStatus( int nView )
+{
+ int length;
+ HWND hWnd = Views[nView].hwndFrame;
+ PPANE p = (PPANE)GetWindowLong(hWnd, GWW_EDIT);
+ PINFO pStatus = NULL;
+ char *pWatchs = NULL;
+
+ DAssert( p );
+ DAssert( p->Type == (WORD)(-Views[nView].Doc) );
+
+ pStatus = calloc(1, sizeof(INFO));
+
+ if ( pStatus ) {
+ pStatus->Length = sizeof(INFO);
+ pStatus->PerCent = p->PanePerCent;
+ pStatus->Flags = p->bFlags;
+ pStatus->Text[0] = 0;
+
+ if ( p->Type == WATCH_WIN) {
+ pWatchs = FTGetWatchList( GetWatchVit() );
+
+ if (pWatchs != NULL)
+ {
+ length = strlen(pWatchs);
+ pStatus = realloc(pStatus, sizeof(INFO) + length);
+ pStatus->Length = sizeof(INFO) + length;
+ strcpy( pStatus->Text, pWatchs);
+ }
+ }
+ }
+
+ return((PLONG)pStatus);
+}
+
+/*** FreePaneStatus
+**
+** Synopsis:
+** void FreePaneStatus( ViewNo, Status );
+**
+** Entry:
+** int ViewNo - View number
+** PLONG Status - Status area returned by GetPaneStatus()
+**
+** Returns:
+** None
+**
+** Description:
+** Release any buffers needed to creat the status area.
+*/
+
+void FreePaneStatus( int nView, PLONG pStatus )
+{
+ Unreferenced(nView);
+ free(pStatus);
+ return;
+}
+
+/*** SetPaneStatus
+**
+** Synopsis:
+** void SetPaneStatus( ViewNo, Status );
+**
+** Entry:
+** int ViewNo - The View number we need status for
+** PLONG Status - Status area returned by GetPaneStatus()
+**
+** Returns:
+** None
+**
+** Description:
+** Restores the pane status information to the indicated view.
+*/
+
+void SetPaneStatus( int nView, PLONG Status )
+{
+ HWND hWnd = Views[nView].hwndFrame;
+ PPANE p = (PPANE)GetWindowLong(hWnd, GWW_EDIT);
+ PINFO pStatus = (PINFO)Status;
+ RECT rc;
+
+ DAssert( p );
+ DAssert( p->Type == (WORD)(-Views[nView].Doc) );
+ DAssert( pStatus );
+
+ p->PanePerCent = pStatus->PerCent;
+ if ( p->PanePerCent < 10 ) p->PanePerCent = 10;
+ if ( p->PanePerCent > 990) p->PanePerCent = 990;
+
+ p->bFlags = pStatus->Flags;
+
+ if ( p->Type == WATCH_WIN) {
+ FTSetWatchList( GetWatchVit(), pStatus->Text );
+ p->LeftOk = FALSE;
+ }
+
+ SendMessage( hWnd, WU_UPDATE, 0, 0l);
+ GetClientRect(hWnd, &rc);
+ PostMessage(hWnd, WM_SIZE, 0, MAKELONG(rc.right,rc.bottom));
+
+ return;
+}
+
+
+/*** DrawPaneItem
+**
+** Synopsis:
+** void DrawPaneItem( hWnd, p, lpDis);
+**
+** Entry:
+** HWND hWnd - Handle to the Window
+** PPANE p - The pane information for the draw request
+** int xOrigin - The X origin of the horz. Scroll bar
+** LPDRAWITEMSTRUCT lpDis - Draw Info from WM_DRAWITEM message
+**
+** Returns:
+** None
+**
+** Description:
+** Paint an item in the pane manager.
+*/
+
+VOID DrawPaneItem( HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis )
+{
+ PANEINFO Info = {0,0,0,0,NULL,NULL};
+ PSTR pBuff= NULL;
+ COLORREF cfBack;
+ COLORREF cfFore;
+
+ /*
+ * Draw Logic
+ */
+
+
+ if ( lpDis->itemAction & ODA_DRAWENTIRE) {
+
+ /*
+ * Button pane gets a bitmap
+ */
+
+ if ( lpDis->CtlID == ID_PANE_BUTTON) {
+ DrawPaneButton(hWnd, p, lpDis);
+ return;
+ }
+
+ /*
+ * Is the pane the one we editing?
+ */
+
+ else if ( lpDis->CtlID == p->nCtrlId &&
+ lpDis->itemID == (UINT)p->CurIdx && p->Edit) {
+ pBuff = p->EditBuf;
+ cfFore = StringColors[ActiveEdit].FgndColor;
+ cfBack = StringColors[ActiveEdit].BkgndColor;
+
+ }
+
+
+ /*
+ * Otherwise get the buffer from the low level and set the color
+ * either to the ChangeHistory color if its changed, or the default
+ * color it its hasn't.
+ */
+
+ else {
+ Info.CtrlId = lpDis->CtlID;
+ Info.ItemId = lpDis->itemID;
+ (PSTR)(*p->fnEditProc)(hWnd,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ pBuff = Info.pBuffer;
+
+ if ( Info.NewText ) {
+ cfFore = StringColors[ChangeHistory].FgndColor;
+ cfBack = StringColors[ChangeHistory].BkgndColor;
+ }
+
+ else {
+ cfFore = StringColors[p->ColorItem].FgndColor;
+ cfBack = StringColors[p->ColorItem].BkgndColor;
+ }
+ }
+
+ /*
+ * Make sure we ended up with a buffer and if so paint it
+ */
+
+ if (pBuff != NULL) {
+
+ int iLen;
+
+ iLen = strlen (pBuff);
+
+ SetTextColor(lpDis->hDC, cfFore);
+ SetBkColor (lpDis->hDC, cfBack);
+
+ DrawText(lpDis->hDC, pBuff, iLen, &lpDis->rcItem, PTEXT);
+
+ if ( lpDis->CtlID == p->nCtrlId
+ && lpDis->itemID == (UINT)p->CurIdx
+ && p->SelLen != 0 ) {
+ DrawPaneSelection( hWnd, p, lpDis, (UCHAR *)pBuff);
+ return;
+
+ }
+
+ if ( lpDis->CtlID == ID_PANE_LEFT && Info.pFormat && !p->Edit) {
+ DrawPaneFormat( hWnd, p, lpDis, (UCHAR *)pBuff, (UCHAR *)Info.pFormat);
+ }
+
+ }
+ }
+
+} /* DrawPaneItem() */
+
+
+/*** DrawPaneFormat
+**
+** Synopsis:
+** void DrawPaneFormat( hWnd, p, lpDis, pBuff, pFmt);
+**
+** Entry:
+** HWND hWnd - Handle to the Window
+** PPANE p - The pane information for the draw request
+** LPDRAWITEMSTRUCT lpDis - Draw Info from WM_DRAWITEM message
+** UCHAR * pBuff - The original buffer
+** UCHAR * pFmt - The format string to add
+**
+** Returns:
+** None
+**
+** Description:
+** Paint a format string after the current string
+*/
+
+void DrawPaneFormat(HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis, UCHAR * pBuff, UCHAR * pFmt)
+{
+ SIZE Size = { 0, 0 };
+ RECT Rect = lpDis->rcItem;
+ int iLen;
+
+ if (pFmt == NULL)
+ {
+ return;
+ }
+
+ iLen = strlen (pFmt);
+
+ SelectObject(lpDis->hDC, p->hFont);
+ GetTextExtentPoint(lpDis->hDC, pBuff, strlen(pBuff), &Size);
+ Rect.left = Size.cx;
+
+ SetTextColor( lpDis->hDC, StringColors[ChangeHistory].FgndColor);
+ SetBkColor ( lpDis->hDC, StringColors[ChangeHistory].BkgndColor);
+ DrawText( lpDis->hDC, pFmt, iLen, &Rect, PTEXT);
+
+
+} /* DrawPaneFormat() */
+
+
+/*** DrawPaneSelection
+**
+** Synopsis:
+** void DrawPaneSelection( hWnd, p, lpDis, pBuff);
+**
+** Entry:
+** HWND hWnd - Handle to the Window
+** PPANE p - The pane information for the draw request
+** LPDRAWITEMSTRUCT lpDis - Draw Info from WM_DRAWITEM message
+** UCHAR * pBuff - The original buffer
+**
+** Returns:
+** None
+**
+** Description:
+** Paints the portion of the string that is selected
+*/
+
+void DrawPaneSelection(HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis, UCHAR * pBuff)
+{
+ WORD x;
+ WORD i;
+ RECT Rect;
+ WORD Begin;
+ WORD Len;
+ WORD Available;
+ WORD Size;
+ int iLen;
+ TEXTMETRIC tm;
+
+ if (pBuff == NULL)
+ {
+ return;
+ }
+
+ if ( p->SelLen > 0 ) {
+ Begin = p->SelPos;
+ Len = p->SelLen;
+ } else {
+ Begin = (WORD)(p->SelPos + p->SelLen);
+ Len = -(p->SelLen);
+ }
+
+ SelectObject(lpDis->hDC, p->hFont);
+ GetTextMetrics(lpDis->hDC, &tm);
+ GetCharWidth(lpDis->hDC, 0, MAX_CHARS_IN_FONT - 1, (LPINT)(Views[p->iView].charWidth));
+
+ x = 0;
+ Rect.left = lpDis->rcItem.left;
+
+ while ( x < Begin ) {
+ Rect.left += Views[p->iView].charWidth[ pBuff[x] ];
+ x++;
+ }
+
+ Rect.right = Rect.left;
+ Available = (WORD)(lpDis->rcItem.right - Rect.left);
+
+ for ( i = 0; i < Len; i++ ) {
+
+ Size = Views[p->iView].charWidth[ pBuff[x] ];
+
+ if ( Available < Size ) {
+ Rect.right += Available;
+ break;
+ }
+
+ Rect.right += Size;
+ Available -= Size;
+ x++;
+ }
+
+ Rect.top = lpDis->rcItem.top;
+ Rect.bottom = lpDis->rcItem.bottom;
+
+ iLen = strlen ((pBuff+Begin));
+
+ SetTextColor( lpDis->hDC, StringColors[TextSelection].FgndColor);
+ SetBkColor ( lpDis->hDC, StringColors[TextSelection].BkgndColor);
+ DrawText( lpDis->hDC, pBuff+Begin, iLen, &Rect, PTEXT);
+} /* DrawPaneSelection */
+
+
+/*** DrawPaneButton
+**
+** Synopsis:
+** void DrawPaneButton( hWnd, p, lpDis);
+**
+** Entry:
+** HWND hWnd - Handle to the Window
+** PPANE p - The pane information for the draw request
+** LPDRAWITEMSTRUCT lpDis - Draw Info from WM_DRAWITEM message
+**
+** Returns:
+** None
+**
+** Description:
+** Draw a button in the button pane.
+*/
+
+void DrawPaneButton(HWND hWnd, PPANE p, LPDRAWITEMSTRUCT lpDis )
+ {
+ LPRECT r;
+ LONG dx, dy;
+ LONG d;
+ PANEINFO Info = {0,0,0,0,NULL};
+
+ Info.CtrlId = lpDis->CtlID;
+ Info.ItemId = lpDis->itemID;
+
+ (PSTR)(*p->fnEditProc)(hWnd,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ r = &lpDis->rcItem;
+ dx = ( r->right - r->left) + 1;
+ dy = ( r->bottom - r->top) +1;
+
+ d = (p->LineHeight - BUTTON_SIZE)/2;
+ r->top += d;
+ dy -= d;
+
+ // Paint the pretty picture
+ switch( Info.pBuffer ? *Info.pBuffer : ' ') {
+
+ case '~': // Don't want a button
+ break;
+
+ case '+':
+ BitBlt (lpDis->hDC, r->left, r->top, dx, dy,
+ hdcPlus, 0, 0, SRCCOPY);
+ break;
+
+ case '-':
+ BitBlt (lpDis->hDC, r->left, r->top, dx, dy,
+ hdcMinus, 0, 0, SRCCOPY);
+ break;
+
+ default:
+ break;
+ }
+
+ // If its the current item, invert it.
+ if ( lpDis->CtlID == p->nCtrlId && lpDis->itemID == (UINT)p->CurIdx ) {
+ InvertButton( p );
+ }
+
+ return; // Return Early (No Text to Paint)
+}
+
+/*** InvertButton
+**
+** Synopsis:
+** void InvertButton( PPANE p)
+**
+** Entry:
+** PPANE p - The pane information for the draw request
+**
+** Returns:
+** None
+**
+** Description:
+**
+*/
+
+void InvertButton( PPANE p )
+{
+ RECT Rect;
+ HDC hDC;
+ HGDIOBJ hBrush;
+ RECT rc;
+
+ hDC = GetDC(p->hWndFocus);
+ hBrush = GetStockObject(BLACK_BRUSH);
+
+ Rect.left = 0;
+ Rect.top = (p->CurIdx - p->TopIdx) * p->LineHeight + (p->LineHeight - BUTTON_SIZE)/2 ;
+ Rect.right = BUTTON_SIZE;
+ Rect.bottom = Rect.top + BUTTON_SIZE;
+
+
+ GetClientRect(p->hWndFocus, &rc);
+
+ if ( Rect.bottom < rc.bottom ) {
+ FrameRect( hDC, &Rect, hBrush );
+
+ Rect.left++;
+ Rect.top++;
+ Rect.right--;
+ Rect.bottom--;
+ FrameRect( hDC, &Rect, hBrush );
+ }
+
+ DeleteObject(hBrush);
+ ReleaseDC(p->hWndFocus,hDC);
+}
+
+
diff --git a/private/windbg/windbg/paneopt.c b/private/windbg/windbg/paneopt.c
new file mode 100644
index 000000000..55da9edd4
--- /dev/null
+++ b/private/windbg/windbg/paneopt.c
@@ -0,0 +1,209 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ PANEOPT.C
+
+Abstract:
+
+ This file contains the code for dealing with the Pane Manager Options
+
+Author:
+
+ Bill Heaton (v-willhe)
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define MAXFMT 512
+
+BOOL FAR PASCAL EXPORT DlgPaneOptInit(HWND hDlg, UINT message, WPARAM wParam, LONG lParam);
+BOOL FAR PASCAL EXPORT DlgPaneOptCommand(HWND hDlg, UINT message, WPARAM wParam, LONG lParam);
+
+extern void CheckHorizontalScroll (PPANE p);
+
+
+WORD DialogType;
+HWND hWnd;
+PPANE p;
+PANEINFO Info;
+char format[MAXFMT];
+char tformat[MAXFMT];
+
+/*** DlgQuickW
+**
+** Synopsis:
+** bool = DlgQuickW(hwnd, message, wParam, lParam)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes messages for "xxx Options" dialog box
+** (Edit Find Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT DlgPaneOptions(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ Unused(lParam);
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ return ( DlgPaneOptInit( hDlg, message, wParam, lParam) );
+
+ case WM_COMMAND:
+ return ( DlgPaneOptCommand( hDlg, message, wParam, lParam) );
+
+ }
+ return (FALSE);
+
+} /* DlgPaneOptions() */
+
+
+
+BOOL FAR PASCAL EXPORT DlgPaneOptInit(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+
+
+ switch( DialogType ) {
+ case WATCH_WIN:
+ SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)"Watch Window Options");
+ hWnd = GetWatchHWND();
+ break;
+
+ case LOCALS_WIN:
+ SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)"Locals Window Options");
+ hWnd = GetLocalHWND();
+ break;
+
+ case CPU_WIN:
+ SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)"CPU Window Options");
+ hWnd = GetCpuHWND();
+ break;
+
+ case FLOAT_WIN:
+ SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)"Float Window Options");
+ hWnd = GetFloatHWND();
+ break;
+
+ default:
+ DAssert(FALSE);
+
+ }
+
+ // Get the Options for the Window
+ p = (PPANE)GetWindowLong(hWnd, GWW_EDIT);
+ DAssert(p);
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(hWnd,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+
+ // Set the Format string if it exists
+ if ( Info.pFormat) {
+ SendDlgItemMessage(hDlg, ID_PANEMGR_FORMAT, WM_SETTEXT, 0, (LPARAM)Info.pFormat);
+ }
+
+ // Set the Expand button if true
+ if ( p->bFlags.Expand1st )
+ SendDlgItemMessage(hDlg, ID_PANEMGR_EXPAND_1ST, BM_SETCHECK, 1, 0);
+ else
+ SendDlgItemMessage(hDlg, ID_PANEMGR_EXPAND_NONE, BM_SETCHECK, 1, 0);
+
+ return(TRUE);
+}
+
+
+BOOL FAR PASCAL EXPORT DlgPaneOptCommand(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ PTRVIT pVit = NULL;
+ PCHAR pFmt = &format[0];
+
+ switch (wParam) {
+
+ case ID_PANEMGR_FORMAT:
+ break;
+
+ case ID_PANEMGR_EXPAND_1ST:
+ p->bFlags.Expand1st = TRUE;
+ break;
+
+ case ID_PANEMGR_EXPAND_NONE:
+ p->bFlags.Expand1st = FALSE;
+ break;
+
+ case IDOK:
+ SendDlgItemMessage(hDlg, ID_PANEMGR_FORMAT, WM_GETTEXT, MAXFMT, (LPARAM)&format[0]);
+ while ( isspace(*pFmt) ) pFmt++;
+
+ if ( strlen (pFmt) == 0) {
+ Info.pFormat = NULL;
+ }
+
+ else {
+ // Ensure a leading comma
+ if ( *pFmt != ',') {
+
+ strcpy (tformat,",");
+ strcat (tformat,pFmt);
+ pFmt = &tformat[0];
+ }
+
+ Info.pFormat = pFmt;
+ }
+
+ (PSTR)(*p->fnEditProc)(hWnd,WU_OPTIONS,(WPARAM)&Info,(LPARAM)p);
+ CheckHorizontalScroll (p);
+
+ // No break intended
+ case IDCANCEL:
+ p = NULL;
+ hWnd = 0;
+ memset( &Info, 0, sizeof(PANEINFO));
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDWINDBGHELP :
+ switch (DialogType)
+ {
+ case WATCH_WIN:
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_WATCH_HELP));
+ break;
+
+ case LOCALS_WIN:
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_LOCAL_HELP));
+ break;
+
+ case CPU_WIN:
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_CPU_HELP));
+ break;
+
+ case FLOAT_WIN:
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_FLOAT_HELP));
+ break;
+
+
+ }
+ return TRUE;
+
+ }
+}
+
+
diff --git a/private/windbg/windbg/paneuser.c b/private/windbg/windbg/paneuser.c
new file mode 100644
index 000000000..4141c8c85
--- /dev/null
+++ b/private/windbg/windbg/paneuser.c
@@ -0,0 +1,1583 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ paneuser.c
+
+Abstract:
+
+ This module contains the code for handling the keyboard and mouse
+ for the panel manager windows.
+
+Author:
+
+ William J. Heaton (v-willhe) 25-Nov-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+#include "precomp.h"
+#pragma hdrstop
+
+void PaneClearEdit( PPANE p);
+void PaneDeleteChar( PPANE p, SHORT Idx);
+void PaneEditMode( PPANE p);
+void PaneInsertChar( PPANE p, CHAR wParam );
+void PaneKeyboardHandler(HWND hWnd, UINT message, WPARAM wParam, LONG lParam);
+void PaneCopyClipBoard( PPANE p );
+void PanePasteClipBoard( PPANE p );
+void PaneSetPos( PPANE p, SHORT NewPos);
+void PaneSetPosXY( HWND hWnd, int X, int Y, BOOL Select);
+void PaneSelectWord( PPANE p );
+void PaneCutSelection( PPANE p );
+int PaneCaretNum( PPANE p);
+
+
+extern LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+extern void CheckHorizontalScroll (PPANE p);
+
+BOOL inMouseMove=FALSE;
+
+/*** PaneKeyboardHandler
+**
+** Synopsis:
+** LONG PASCAL PaneKeyboardHandler( hWnd, msg, wParam, lParam)
+**
+** Entry:
+** Standard WNDPROC
+**
+** Returns:
+** Standard WNDPROC
+**
+** Description:
+** The Standard Keyboard Handler for all of the Panemanager Panes.
+**
+*/
+
+#define PAGE (p->PaneLines-1)
+
+void PaneKeyboardHandler(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ PPANE p = (PPANE)GetWindowLong(GetParent(hWnd), GWW_EDIT);
+ BOOL isShiftDown;
+ BOOL isCtrlDown;
+
+
+ if (!IsIconic(GetParent(hWnd))) {
+ isShiftDown = (GetKeyState(VK_SHIFT) < 0);
+ isCtrlDown = (GetKeyState(VK_CONTROL) < 0);
+ }
+ else
+ return;
+
+ if ((message == WM_KEYDOWN) && ((wParam == VK_CONTROL) || (wParam == VK_SHIFT)))
+ {
+ return; // don't care if it is just the ctrl/shift key
+ }
+
+ switch (message) {
+
+ case WM_COPY:
+ PaneCopyClipBoard( p );
+ break;
+
+ case WM_PASTE:
+ PanePasteClipBoard( p );
+ break;
+
+ case WM_MOUSEMOVE:
+ if ( wParam & MK_LBUTTON ) {
+ inMouseMove = TRUE;
+ PaneSetPosXY( hWnd, LOWORD(lParam), HIWORD(lParam), TRUE );
+ inMouseMove = FALSE;
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ PaneSetPosXY( hWnd, LOWORD(lParam), HIWORD(lParam), FALSE );
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ if ( p->hWndFocus != p->hWndButton ) {
+ PaneSelectWord( p );
+ }
+ break;
+
+ case WM_RBUTTONDOWN:
+ if (p->SelLen) {
+ PaneCopyClipBoard( p );
+ } else {
+ PanePasteClipBoard( p );
+ }
+ return;
+
+ case WM_CHAR:
+ switch(wParam) {
+
+ // Handled by WM_KEYDOWN
+ case TAB:
+ case CTRL_H:
+ case CTRL_M:
+ case ESCAPE:
+ break;
+
+ default:
+ if ( p->hWndFocus != p->hWndButton && wParam >= ' ')
+ PaneInsertChar(p, (CHAR)wParam );
+ else
+ MessageBeep(0);
+ }
+ break;
+
+ case WM_KEYDOWN:
+
+ if (hWnd != p->hWndButton) {
+ MSG msg;
+
+ // if text has been highlighted, a cut may be necessary
+ // in preparing for an insert
+
+ if (p->SelLen != 0 &&
+ PeekMessage(&msg, hWnd, WM_KEYDOWN, WM_CHAR, PM_NOREMOVE))
+ if (msg.message == WM_CHAR)
+ switch (msg.wParam) {
+ // there will not be any insert for these four cases
+ case TAB:
+ case CTRL_H:
+ case CTRL_M:
+ case ESCAPE:
+ break;
+ default:
+ if (msg.wParam >= ' ') {
+ PaneCutSelection(p);
+ p->SelLen = 0;
+ return;
+ }
+ }
+
+ // removes any highlighting if necessary
+ // except the following key combinations:
+ // DELETE, BACKSPACE
+ // Shift+(Ctrl)+Left/Right Arrow
+ // Shift+Home/End Key
+
+ if (wParam != VK_DELETE &&
+ wParam != VK_BACK &&
+ !(isShiftDown &&
+ (wParam == VK_LEFT || wParam == VK_RIGHT ||
+ (!isCtrlDown && (wParam == VK_HOME || wParam == VK_END)))
+ )
+ ) {
+ POINT cPos;
+ GetCaretPos (&cPos);
+ PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, FALSE);
+ }
+ }
+
+ switch ( wParam ) {
+
+ case VK_DELETE:
+ case VK_BACK:
+ if (p->SelLen != 0) {
+ PaneCutSelection(p);
+ p->SelLen = 0;
+ } else if (wParam == VK_BACK)
+ PaneDeleteChar(p, (SHORT)(p->CurPos-1)); // backspace
+ else
+ PaneDeleteChar(p, (SHORT)p->CurPos);
+ break;
+
+ case VK_LEFT:
+ case VK_RIGHT:
+ if (isShiftDown) {
+ POINT cPos;
+ if (p->SelLen == 0)
+ p->SelPos = p->CurPos;
+ PaneSetPos(p,(SHORT)(p->CurPos+((wParam == VK_LEFT)?-1:1)));
+ GetCaretPos (&cPos);
+ PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, TRUE );
+ } else
+ PaneSetPos(p,(SHORT)(p->CurPos+((wParam == VK_LEFT)?-1:1)));
+ break;
+
+ case VK_UP:
+ case VK_DOWN:
+ PaneInvalidateCurrent(p->hWndFocus, p, -1);
+ PaneSetIdx(p,(SHORT)(p->CurIdx + ((wParam == VK_UP) ?-1:1)));
+ if (isShiftDown) {
+ POINT cPos;
+ GetCaretPos (&cPos);
+ PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, FALSE);
+ }
+ p->SelLen = 0;
+ p->SelPos = 0;
+ PaneCaretNum(p);
+ break;
+
+ case VK_PRIOR:
+ case VK_NEXT:
+ PaneSetIdx(p,(SHORT)(p->CurIdx+((wParam == VK_PRIOR) ?-PAGE:PAGE)));
+ if (isShiftDown) {
+ POINT cPos;
+ GetCaretPos (&cPos);
+ PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, FALSE );
+ }
+ p->SelLen = 0;
+ p->SelPos = 0;
+ PaneCaretNum(p);
+ break;
+
+ case VK_HOME:
+ case VK_END:
+ {
+ SHORT tmp;
+ POINT cPos;
+
+ tmp = (wParam == VK_HOME) ? 0 : 0x7fff; // first or last
+ if (isCtrlDown) {
+ PaneSetIdx(p, (SHORT)tmp);
+ } else if (isShiftDown) {
+ if (p->SelLen == 0)
+ p->SelPos = p->CurPos;
+ PaneSetPos(p, (SHORT)tmp);
+ GetCaretPos (&cPos);
+ PaneSetPosXY( hWnd, (WORD)cPos.x, (WORD)cPos.y, TRUE);
+ } else {
+ PaneSetPos(p, (SHORT)tmp);
+ p->SelLen = p->SelPos = 0; // why?
+ }
+ PaneCaretNum(p);
+ }
+ break;
+
+ case VK_TAB:
+ PaneSwitchFocus(p, NULL, (BOOL)(((GetKeyState (VK_SHIFT) >= 0)) ? FALSE : TRUE));
+ break;
+
+ case VK_INSERT:
+ if (isShiftDown) {
+ PanePasteClipBoard( p );
+ } else if (isCtrlDown) {
+ PaneCopyClipBoard( p );
+ } else {
+ PaneEditMode(p);
+ }
+ break;
+
+ case VK_ESCAPE:
+ PaneClearEdit(p);
+ break;
+
+ case VK_RETURN:
+ if (p->nCtrlId == ID_PANE_BUTTON) {
+ (*p->fnEditProc)(p->hWndFocus, WU_EXPANDWATCH, (WPARAM)p->CurIdx, (LONG)p);
+ CheckHorizontalScroll (p);
+ } else {
+ PaneCloseEdit(p);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ DAssert(FALSE);
+ }
+} /* PaneKeyboardHandler() */
+
+
+ /*** PaneCopyClipBoard
+ **
+ ** Synopsis:
+ ** void PaneCopyClipBoard( PPANE p);
+ **
+ ** Entry:
+ ** p - pointer to Pane Information Strucure
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Copy the current selection (If any to the clipboard)
+ **
+ */
+
+void
+PaneCopyClipBoard(
+ PPANE p
+ )
+{
+
+ PSTR pBuf = NULL;
+ int nLen = 0;
+ PANEINFO Info = {0,0,0,0,NULL};
+ HANDLE hData;
+ LPSTR pData;
+ LPSTR pSrc;
+
+ if ( p->SelLen != 0 ) {
+
+ if ( p->Edit ) {
+
+ pBuf = p->EditBuf;
+
+ } else {
+
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ pBuf = Info.pBuffer;
+ }
+
+ if ( p->SelLen > 0 ) {
+ pSrc = pBuf + p->SelPos;
+ nLen = p->SelLen;
+ } else {
+ pSrc = pBuf + p->SelPos + p->SelLen;
+ nLen = -(p->SelLen);
+ }
+
+ Dbg(hData = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, nLen + 1));
+ if ( hData ) {
+
+ Dbg((pData = GlobalLock( hData )) != NULL);
+ if ( pData ) {
+
+ while ( nLen-- ) {
+ *pData++ = *pSrc++;
+ }
+ *pData = '\0';
+
+ DbgX(GlobalUnlock(hData) == 0);
+
+ if (OpenClipboard (hwndFrame)) {
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, hData);
+ CloseClipboard();
+ p->SelLen = 0;
+ }
+ }
+
+ }
+ }
+ } /* PaneCopyClipBoard() */
+
+
+ /*** PanePasteClipBoard
+ **
+ ** Synopsis:
+ ** void PanePasteClipBoard( PPANE p);
+ **
+ ** Entry:
+ ** p - pointer to Pane Information Strucure
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Copy the clipboard to the current pane item
+ **
+ */
+
+void PanePasteClipBoard( PPANE p )
+ {
+
+ HANDLE hData;
+ DWORD size;
+ LPSTR p1;
+ LPSTR pData;
+
+ if ( !p->ReadOnly ) {
+
+ if (OpenClipboard(hwndFrame)) {
+
+ hData = GetClipboardData(CF_TEXT);
+
+ if (hData && (size = GlobalSize (hData))) {
+
+ if (size >= MAX_CLIPBOARD_SIZE) {
+
+ ErrorBox(ERR_Clipboard_Overflow);
+
+ } else if ( pData = GlobalLock(hData) ) {
+
+ p1 = pData;
+ while (size && *p1) {
+ size--;
+ if (*p1 == '\r' || *p1 == '\n') {
+ break;
+ }
+
+ PaneInsertChar(p, (CHAR)*p1 );
+
+ p1++;
+ }
+ DbgX(GlobalUnlock (hData) == FALSE);
+ }
+ CloseClipboard();
+ }
+ }
+ }
+ } /* PanePasteClipBoard() */
+
+
+
+/*** PaneCutSelection
+**
+** Synopsis:
+** void PaneCutSelection( PPANE p);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+**
+** Returns:
+** None
+**
+** Description:
+** Cut the current selection (delete)
+**
+*/
+
+void
+PaneCutSelection(
+ PPANE p
+ )
+{
+
+ PSTR pBuf = NULL;
+ int nLen = 0;
+ PANEINFO Info = {0,0,0,0,NULL};
+ SHORT Indx;
+
+ if ( p->SelLen != 0 ) {
+
+ if ( p->Edit ) {
+ pBuf = p->EditBuf;
+ } else {
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ pBuf = Info.pBuffer;
+ }
+
+ if ( p->SelLen > 0 ) {
+ Indx = p->SelPos;
+ nLen = p->SelLen;
+ } else {
+ Indx = p->CurPos;
+ nLen = -(p->SelLen);
+ }
+
+ while ( nLen-- ) {
+ PaneDeleteChar(p, Indx);
+ }
+
+ }
+
+} /* PaneCutSelection() */
+
+
+/*** PaneSetPos
+**
+** Synopsis:
+** void PaneSetPos( PPANE p, SHORT NewPos);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+** NewPos - The index of the position to set on the current pane item
+**
+** Returns:
+** None
+**
+** Description:
+** This routine is used to set the x coordinate on a pane item
+**
+*/
+
+void
+PaneSetPos(
+ PPANE p,
+ SHORT NewPos
+ )
+{
+ SIZE Size = { 0, 0 };
+ PANEINFO Info = {0,0,0,0,NULL};
+ RECT Rect = {0,0,0,0};
+ PSTR pBuf = NULL;
+ int nLen = 0;
+ HDC hDC = 0;
+
+ if ( p->nCtrlId == ID_PANE_BUTTON ) {
+ InvertButton( p );
+ } else {
+
+ // Figure out which buffer we're using and it's max
+ if ( p->Edit ) {
+ pBuf = &p->EditBuf[0];
+ nLen = p->CurLen;
+ } else {
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ pBuf = Info.pBuffer;
+ if ( pBuf ) {
+ nLen = strlen(pBuf);
+ }
+ }
+
+#ifdef DBCS
+ if(NewPos > p->CurPos) { /* move right */
+ if(IsDBCSLeadByte((BYTE)*(pBuf + p->CurPos))) {
+ NewPos++;
+ }
+ }
+ else if(NewPos < p->CurPos) { /* move left */
+ if(IsDBCSLeadByte((BYTE)(*CharPrev(pBuf, pBuf + p->CurPos)))) {
+ NewPos--;
+ }
+ }
+#endif
+
+ // If the New position is out of range, put it back in range
+ if ( NewPos < 0 ) {
+ NewPos = 0;
+ }
+ if ( (WORD)NewPos > nLen ) {
+ NewPos = nLen;
+ }
+ p->CurPos = NewPos;
+
+ // Figure out the offset to the new caret
+ if ( NewPos <= 0) {
+ Size.cx = 0;
+ } else {
+ hDC = GetDC(p->hWndFocus);
+ SelectObject(hDC, p->hFont);
+ GetTextExtentPoint(hDC, pBuf, NewPos, &Size);
+ ReleaseDC(p->hWndFocus,hDC);
+ }
+
+ PaneSetCaret(p, Size.cx, TRUE);
+ }
+
+ // Set the Status Bar
+ StatusLineColumn(p->CurIdx+1, p->CurPos+1);
+
+} /* PaneSetPos() */
+
+
+/*** PaneSetPosXY
+**
+** Synopsis:
+** void PaneSetPosXY( HWND hWnd, int X, int Y, BOOL Select)
+**
+** Entry:
+** hWnd - The Window
+** x - The X coordinate
+** y - The Y coordinate
+** Select -
+**
+** Returns:
+** None
+**
+** Description:
+**
+**
+*/
+
+void
+PaneSetPosXY(
+ HWND hWnd,
+ int X,
+ int Y,
+ BOOL Select
+ )
+{
+ PPANE p = (PPANE)GetWindowLong(GetParent(hWnd), GWW_EDIT);
+ SHORT NewIdx;
+ SHORT NewPos;
+ PSTR pBuf = NULL;
+ int nLen = 0;
+ int Offset = 0;
+ PANEINFO Info = {0,0,0,0,NULL};
+ HDC hDC = 0;
+ BOOL isShiftDown = (GetKeyState(VK_SHIFT) < 0);
+ SIZE Size;
+ POINT point;
+
+ //
+ // Calculate what index the mouse hit was on, If we're selecting
+ // we ignore anything off our pane and/or index
+ //
+
+ if ( hWnd != p->hWndButton) {
+ HideCaret(hWnd);
+ }
+
+ NewIdx = p->TopIdx + Y/p->LineHeight;
+ if ( Select ) {
+ if ( hWnd != p->hWndFocus || NewIdx != p->CurIdx ) {
+ if ( hWnd != p->hWndButton) {
+ ShowCaret(hWnd);
+ }
+ return;
+ }
+ }
+
+ //
+ // Dialog boxes (quickwatch) can't select
+ //
+
+ if (( p->Type == QUICKW_WIN) || (!isShiftDown && !inMouseMove)) {
+ Select = FALSE;
+ }
+
+
+
+ //
+ // Switch pane if necessary
+ //
+
+ if ( hWnd != p->hWndFocus ) {
+ PaneSwitchFocus(p, hWnd, FALSE);
+ Select = FALSE;
+
+ // Buttons are special, Expand/Contract the item and get out
+ if ( hWnd == p->hWndButton) {
+ p->CurIdx = NewIdx;
+ (*p->fnEditProc)(p->hWndFocus, WU_EXPANDWATCH, (WPARAM)NewIdx, (LONG)p);
+ CheckHorizontalScroll (p);
+ return;
+ }
+ }
+
+
+
+ if ( NewIdx < p->MaxIdx ) {
+
+ //
+ // Calculate new position
+ //
+ if ( NewIdx == p->CurIdx && p->Edit ) {
+
+ pBuf = &p->EditBuf[0];
+ nLen = p->CurLen;
+
+ } else {
+
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = NewIdx;
+
+ (PSTR)(*p->fnEditProc)( p->hWndFocus,
+ WU_INFO,
+ (WPARAM)&Info,
+ (LPARAM)p);
+
+ if ( pBuf = Info.pBuffer ) {
+ nLen = strlen(pBuf);
+ }
+ }
+
+ if ( p->nCtrlId == ID_PANE_BUTTON) {
+ (*p->fnEditProc)(p->hWndFocus,
+ WU_EXPANDWATCH,
+ (WPARAM)NewIdx,
+ (LONG)p);
+
+
+ if ( p->ScrollBarUp ) {
+ SetScrollRange(p->hWndScroll, SB_CTL, 0, p->MaxIdx - 1, FALSE);
+ SetScrollPos( p->hWndScroll, SB_CTL, (INT)p->CurIdx, FALSE);
+ }
+ ShowScrollBar( p->hWndScroll, SB_CTL, p->ScrollBarUp);
+
+ if (!p->ScrollBarUp) {
+ p->TopIdx = 0; //reset top if no scrolling
+ }
+
+ SyncPanes(p,(WORD)-1);
+
+ CheckHorizontalScroll (p);
+ }
+
+ if ( pBuf ) {
+
+ NewPos = -1;
+
+ if (p->nCtrlId == ID_PANE_LEFT) {
+ Offset = p->nXoffLeft;
+ } else if (p->nCtrlId == ID_PANE_RIGHT) {
+ Offset = p->nXoffRight;
+ }
+
+ X += Offset;
+
+ hDC = GetDC(p->hWndFocus);
+ SelectObject(hDC, p->hFont);
+ GetTextExtentPoint(hDC, pBuf, 1, &Size);
+ ReleaseDC(p->hWndFocus,hDC);
+
+
+ if (X < Size.cx) {
+ NewPos = 0;
+ } else {
+ hDC = GetDC(p->hWndFocus);
+ SelectObject(hDC, p->hFont);
+ do {
+#ifdef DBCS
+ if(NewPos >=0 && IsDBCSLeadByte((BYTE)*(pBuf+NewPos)))
+ NewPos++;
+#endif
+ NewPos++;
+ GetTextExtentPoint(hDC, pBuf, NewPos, &Size);
+ } while (Size.cx < X);
+ ReleaseDC(p->hWndFocus,hDC);
+ }
+
+ if ( NewPos > nLen ) {
+ NewPos = nLen;
+ }
+
+ if ( p->CurIdx != NewIdx ) {
+ Select = FALSE;
+ p->SelLen = 0;
+ PaneInvalidateCurrent( p->hWndFocus, p, -1);
+ PaneSetIdx( p, NewIdx );
+ }
+
+ if ( Select ) {
+ p->SelLen = NewPos - p->SelPos;
+ } else {
+ p->SelPos = NewPos;
+ p->SelLen = 0;
+ }
+#ifdef DBCS
+ p->CurPos = NewPos;
+#endif
+
+ PaneSetPos( p, NewPos );
+ PaneInvalidateCurrent( p->hWndFocus, p, -1);
+ } else {
+ NewPos = 0;
+
+ PaneInvalidateCurrent( p->hWndFocus, p, -1);
+
+ PaneSetPos( p, NewPos );
+ PaneSetIdx( p, NewIdx );
+ }
+ }
+
+ if ( hWnd != p->hWndButton) {
+ GetCaretPos(&point);
+ p->X = point.x;
+ p->Y = point.y;
+ ShowCaret(hWnd);
+ }
+
+} /* PaneSetPosXY() */
+
+
+/*** PaneSelectWord
+**
+** Synopsis:
+** void PaneSelectWord( PPANE p );
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+**
+** Returns:
+** None
+**
+** Description:
+** Selects the word around the current selection point
+**
+*/
+
+void
+PaneSelectWord(
+ PPANE p
+ )
+{
+ WORD Start = p->CurPos;
+ WORD End = p->CurPos;
+ PSTR pBuf = NULL;
+ int nLen = 0;
+ PANEINFO Info = {0,0,0,0,NULL};
+
+ if ( p->Edit ) {
+
+ pBuf = p->EditBuf;
+ nLen = p->CurLen;
+
+ } else {
+
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ pBuf = Info.pBuffer;
+ if ( pBuf ) {
+ nLen = strlen(pBuf);
+ }
+ }
+
+ if ( pBuf && pBuf[Start] != ' ' && pBuf[Start] != '\t' ) {
+
+#ifdef DBCS
+ if(!IsDBCSLeadByte((BYTE)pBuf[Start])) {
+#endif
+ while ( Start > 0 && pBuf[Start] != ' ' && pBuf[Start] != '\t' ) {
+ Start--;
+ }
+
+ if ( pBuf[Start] == ' ' || pBuf[Start] == '\t' ) {
+ Start++;
+ }
+#ifdef DBCS
+ }
+#endif
+
+ while ( End < nLen
+ && pBuf[End]
+ && pBuf[End] != ' '
+ && pBuf[End] != '\t' ) {
+#ifdef DBCS
+ if(IsDBCSLeadByte((BYTE)pBuf[End])) {
+ End++;
+ break;
+ }
+#endif
+ End++;
+ }
+
+ if ( pBuf[End] == ' ' || pBuf[End] == '\t' || !pBuf[End] ) {
+ End--;
+ }
+
+ p->SelPos = Start;
+ p->SelLen = End - Start + 1;
+
+ PaneInvalidateCurrent( p->hWndFocus, p, -1);
+ }
+} /* PaneSelectWord */
+
+/*** PaneSetIdx
+**
+** Synopsis:
+** void PaneSetIdx( PPANE p, SHORT NewIdx);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+** NewIdx - The index (Line) to set the current pane item to.
+**
+** Returns:
+** None
+**
+** Description:
+** This routine is used to set the y coordinate on a pane item
+**
+*/
+
+void
+PaneSetIdx(
+ PPANE p,
+ SHORT NewIdx
+ )
+{
+ // If we're in edit mode and can't close edit, bail out.
+ if ( !PaneCloseEdit(p) ) {
+ PaneClearEdit(p);
+ }
+
+ PaneResetIdx(p, NewIdx);
+} /* PaneSetIdx */
+
+
+/*** PaneResetIdx
+**
+** Synopsis:
+** void PaneResetIdx( PPANE p, SHORT NewIdx);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+** NewIdx - The index (Line) to set the current pane item to.
+**
+** Returns:
+** None
+**
+** Description:
+** This routine is used to set the y coordinate on a pane item
+**
+*/
+
+void
+PaneResetIdx(
+ PPANE p,
+ SHORT NewIdx
+ )
+{
+
+ PANEINFO Info = {0,0,0,0,NULL};
+
+ if ( p->nCtrlId == ID_PANE_BUTTON ) {
+ PaneInvalidateCurrent( p->hWndFocus, p, -1);
+ }
+
+ // If the New index is out of range, put it back in range
+ if ( NewIdx < 0 ) {
+ NewIdx = 0;
+ }
+ if ( (WORD)NewIdx > p->MaxIdx-1) {
+ NewIdx = (SHORT)p->MaxIdx-1;
+ }
+
+ p->CurIdx = (WORD)NewIdx;
+
+ SyncPanes(p, (WORD)-1);
+
+ if ( p->nCtrlId != ID_PANE_BUTTON ) {
+ PaneSetPos(p, 0);
+ } else {
+ InvertButton(p);
+ }
+
+ // Set the Status Bar
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+
+ p->ReadOnly = Info.ReadOnly;
+ StatusReadOnly(Info.ReadOnly);
+ StatusLineColumn(p->CurIdx+1, p->CurPos+1);
+
+} /* PaneResetIdx */
+
+
+/*** PaneSetCaret
+**
+** Synopsis:
+** void PaneSetCaret( PPANE p, LONG cx, BOOL Scroll);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+** cx - The pixel address of where the caret should be
+** Scroll - Scroll the pane to show the insertion point
+**
+** Returns:
+** None
+**
+** Description:
+** Set the caret (if in view) on the current pane item
+**
+*/
+
+void
+PaneSetCaret(
+ PPANE p,
+ LONG cx,
+ BOOL Scroll
+ )
+{
+ RECT Rect = {0,0,0,0};
+ RECT cRect = {0,0,0,0};
+ LONG Offset;
+ LONG PerCent;
+ LONG Max;
+ HWND hFoc;
+ POINT point;
+ double dMax, dCx;
+
+
+ if (p->CurIdx > p->MaxIdx) {
+ return; //window is empty or bad indx
+ }
+
+ if (p->hWndFocus) {
+ SendMessage( p->hWndFocus, LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect( p->hWndFocus, &cRect);
+ Offset = Rect.right - cRect.right;
+ } else
+ Offset = 0;
+
+
+ if (p->nCtrlId == ID_PANE_LEFT) {
+ p->nXoffLeft = Offset;
+ } else if (p->nCtrlId == ID_PANE_RIGHT) {
+ p->nXoffRight = Offset;
+ }
+
+ p->nCaretPos = cx;
+
+ if ((hFoc = GetFocus ()) == p->hWndFocus) {
+ HideCaret (p->hWndFocus);
+ }
+
+ if (p->CurPos == 0) {
+ PaneInvalidateItem( p->hWndFocus, p, p->CurIdx);
+ }
+
+
+ // Is the caret in range?
+ if ((p->nCaretPos < Offset || p->nCaretPos > (Rect.right -1))
+ && ((hFoc = GetFocus ()) == p->hWndFocus)) {
+ if (!Scroll) {
+ ShowCaret(p->hWndFocus);
+ GetCaretPos(&point);
+ p->X = point.x;
+ return;
+ } else {
+
+ // Note: Listbox scrollbars are a percentage 1-100
+ Max = (SendMessage( p->hWndFocus, LB_GETHORIZONTALEXTENT, 0,0))
+ - p->CharWidth;
+
+ DestroyCaret();
+ CreateCaret( p->hWndFocus, 0, 3, p->LineHeight);
+
+ SetCaretPos(cx - Offset, Rect.top);
+ GetCaretPos(&point);
+ p->X = point.x;
+ ShowCaret(p->hWndFocus);
+
+ if (Max != 0) {
+ dMax = (double) Max;
+ dCx = (double) cx;
+ PerCent = ((long)((dCx /dMax) * 100.0));
+ SendMessage( p->hWndFocus,
+ WM_HSCROLL,
+ MAKELONG(SB_THUMBPOSITION,PerCent),
+ 0);
+ }
+
+ SendMessage( p->hWndFocus, LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect( p->hWndFocus, &cRect);
+ Offset = Rect.right - cRect.right;
+
+ if (p->nCtrlId == ID_PANE_LEFT) {
+ p->nXoffLeft = Offset;
+ } else if (p->nCtrlId == ID_PANE_RIGHT) {
+ p->nXoffRight = Offset;
+ }
+
+ PaneInvalidateItem( p->hWndFocus, p, p->CurIdx);
+
+ return;
+ }
+ }
+
+ if ((hFoc = GetFocus ()) == p->hWndFocus) {
+ SetCaretPos(cx - Offset, Rect.top);
+ GetCaretPos(&point);
+ p->X = point.x;
+ ShowCaret(p->hWndFocus);
+ }
+}
+/* PaneSetCaret() */
+
+
+
+/*** PaneCaretNum
+**
+** Synopsis:
+** int PaneCaretNum( PPANE p);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+**
+** Returns:
+** Number of Items visible
+**
+**
+*/
+
+int
+PaneCaretNum(
+ PPANE p
+ )
+{
+ RECT Rect = {0,0,0,0};
+ RECT tRect = {0,0,0,0};
+ RECT cRect = {0,0,0,0};
+ const RECT zeroRect = {0,0,0,0};
+ int nNum, nMin, nMax, nScrollPos;
+ HWND hPane;
+ BOOL fRedo = TRUE;
+ LRESULT rst;
+
+ GetScrollRange (p->hWndScroll,SB_CTL,&nMin, &nMax);
+
+ do {
+ hPane = (p->hWndFocus != p->hWndButton) ?
+ p->hWndFocus
+ :p->hWndLeft;
+ rst = SendMessageNZ(hPane,
+ LB_GETITEMRECT,
+ (WPARAM)p->CurIdx,
+ (LPARAM)&Rect);
+ if (rst == LB_ERR)
+ return 0;
+ rst = SendMessageNZ(hPane,
+ LB_GETITEMRECT,
+ (WPARAM)p->TopIdx,
+ (LPARAM)&tRect);
+ if (rst == LB_ERR)
+ return 0;
+
+ nScrollPos = GetScrollPos (p->hWndScroll,SB_CTL);
+
+ // Is the caret in range?
+
+ if (hPane != NULL) {
+
+ int nRct;
+
+ GetClientRect(hPane, &cRect);
+ nRct = (cRect.bottom - cRect.top);
+ if ((Rect.bottom - Rect.top) > nRct)
+ nNum = 0;
+ else if ((Rect.bottom - Rect.top) != 0)
+ nNum = (nRct / (Rect.bottom - Rect.top));
+ else
+ nNum = 0;
+ }
+
+ if ((Rect.bottom > cRect.bottom)
+ && (p->CurIdx < p->MaxIdx)
+ && (nNum > 0)) {
+
+ ScrollPanes (p,
+ MAKEWPARAM (SB_THUMBTRACK,(p->CurIdx - PAGE)),
+ 0);
+
+ } else if ((Rect.top < tRect.top)
+ && (p->CurIdx != 0xFFFF)
+ && (nNum > 0)) {
+
+ ScrollPanes (p,
+ MAKEWPARAM (SB_THUMBTRACK,p->CurIdx),
+ 0);
+
+ } else {
+
+ fRedo = FALSE;
+
+ }
+
+ } while (fRedo == TRUE);
+
+ return(nNum);
+
+}
+/* PaneCaretNum() */
+
+
+
+
+/*** PaneDeleteChar
+**
+** Synopsis:
+** void PaneDeleteChar( PPANE p, SHORT Idx);
+**
+** Entry:
+** p - pointer to Pane Information Strucure
+** Idx - The index of the character to delete
+**
+** Returns:
+** None
+**
+** Description:
+** Deletes the character at the specified index from the current
+** pane item.
+**
+*/
+
+void PaneDeleteChar( PPANE p, SHORT Idx)
+ {
+ RECT Rect = {0,0,0,0};
+ PANEINFO Info = {0,0,0,0,NULL};
+ PSTR pBuf = NULL;
+ int nLen = 0;
+
+ // Can't delete on a readonly panel (Catchs Button Pane too!)
+ if ( p->ReadOnly ) {
+ MessageBeep(0);
+ return;
+ }
+
+ // Get the Buffer Information
+ if ( p->Edit ) {
+ pBuf = &p->EditBuf[0];
+ nLen = p->CurLen;
+ }
+
+ else {
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ pBuf = Info.pBuffer;
+ if ( pBuf)
+ nLen = strlen(pBuf);
+ }
+
+
+ // If the New position is out of range, we can't delete
+ if ( nLen == 0 || Idx < 0 || Idx > nLen-1) {
+ MessageBeep(0);
+ return;
+ }
+
+ // If no Edit open, Start it up
+ if ( !p->Edit ) {
+ strcpy(p->EditBuf,pBuf);
+ p->CurLen = nLen;
+ p->Edit = TRUE;
+ }
+
+ // Let do the Delete
+
+ if ( Idx < p->CurLen ) { // If not at end, shift the string over
+ memmove( &p->EditBuf[Idx],
+ &p->EditBuf[Idx+1], p->CurLen - Idx);
+ }
+ p->CurLen--; // One Less char to worry about
+ p->EditBuf[p->CurLen] = 0; // But make sure it goes away
+
+
+ PaneInvalidateCurrent( p->hWndFocus, p, Idx);
+ } /* PaneDeleteChar() */
+
+
+ /*** PaneInsertChar
+ **
+ ** Synopsis:
+ ** void PaneDeleteChar( PPANE p, CHAR c);
+ **
+ ** Entry:
+ ** p - pointer to Pane Information Strucure
+ ** c - The character to be inserted.
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Insert the character passed into the buffer at the current
+ ** insert point.
+ **
+ */
+
+void PaneInsertChar( PPANE p, CHAR c)
+ {
+ PANEINFO Info = {0,0,0,0,NULL};
+
+ // Can't insert on Readonly Pane (Catches Buttons too!)
+ // Don't Insert into null at end of buffer
+ if ( p->ReadOnly || p->CurPos == EDITMAX-1) {
+ MessageBeep(0);
+ return;
+ }
+
+ // If no Edit open, Start it up
+ if ( !p->Edit ) {
+ Info.CtrlId = p->nCtrlId;
+ Info.ItemId = p->CurIdx;
+ (PSTR)(*p->fnEditProc)(p->hWndFocus,WU_INFO,(WPARAM)&Info,(LPARAM)p);
+ if ( Info.pBuffer) {
+ strcpy(p->EditBuf,Info.pBuffer);
+ p->CurLen = strlen(p->EditBuf);
+ }
+ p->Edit = TRUE;
+ }
+
+ // OverStrike Mode
+ if ( p->OverType ) {
+
+
+ if ( p->EditBuf[p->CurPos] == 0)
+ p->CurLen++;
+ p->EditBuf[p->CurPos] = c;
+ }
+
+ // Insert Mode
+ else {
+
+ // Insert at end of line is a no brainer
+ if ( p->EditBuf[p->CurPos] == 0) {
+ p->CurLen++;
+ p->EditBuf[p->CurPos] = c;
+ }
+
+ // Insert into the Middle
+ else {
+ memmove( &p->EditBuf[p->CurPos+1], &p->EditBuf[p->CurPos], p->CurLen - p->CurPos);
+ p->EditBuf[p->CurPos] = c;
+ p->CurLen++;
+ }
+ }
+
+ // Repaint the Line
+ PaneInvalidateCurrent( p->hWndFocus, p,(SHORT)(p->CurPos+1));
+ } /* PaneInsertChar() */
+
+
+ /*** PaneEditMode
+ **
+ ** Synopsis:
+ ** void PaneEditMode( PPANE p)
+ **
+ ** Entry:
+ ** p - The Pane info for the window
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Set insert/overstrike mode.
+ */
+
+void PaneEditMode( PPANE p)
+ {
+ p->OverType = !p->OverType;
+ StatusOvertype(p->OverType);
+
+ } /* PaneEditMode */
+
+
+ /*** PaneClearEdit
+ **
+ ** Synopsis:
+ ** void PaneClearEdit( PPANE p)
+ **
+ ** Entry:
+ ** p - The Pane info for the window
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Aborts the current edit and repaints the item
+ */
+
+void PaneClearEdit( PPANE p)
+ {
+ p->Edit = FALSE;
+ p->CurLen = 0;
+ memset(p->EditBuf,0,EDITMAX);
+ PaneInvalidateCurrent( p->hWndFocus, p, 0);
+
+ } /* PaneClearEdit */
+
+
+ /*** PaneCloseEdit
+ **
+ ** Synopsis:
+ ** BOOL PaneCloseEdit( PPANE p)
+ **
+ ** Entry:
+ ** p - The Pane info for the window
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Attempts to close the edit and update the item.
+ */
+
+BOOL PaneCloseEdit( PPANE p)
+{
+ // If no Edit open, we're done
+ if ( !p->Edit ) {
+ PaneInvalidateCurrent( p->hWndRight, p, -1);
+ return(TRUE);
+ }
+
+ if ( (*p->fnEditProc)(p->hWndFocus, WU_SETWATCH, 0, (LONG)p) ) {
+ PaneClearEdit(p);
+ return(TRUE);
+ }
+
+ PaneClearEdit(p);
+ MessageBeep(0);
+ return(FALSE);
+ } /* PaneCloseEdit */
+
+
+ /*** PaneInvalidateRow
+ **
+ ** Synopsis:
+ ** void PaneInvalidateRow(PPANE p)
+ **
+ ** Entry:
+ ** p - The Pane info for the window
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Invalidate all panes on the current index.
+ */
+
+void PaneInvalidateRow( PPANE p )
+ {
+ PaneInvalidateCurrent( p->hWndButton, p, -1);
+ PaneInvalidateCurrent( p->hWndLeft, p, -1);
+ PaneInvalidateCurrent( p->hWndRight, p, -1);
+ }
+
+
+ /*** PaneInvalidateCurrent
+ **
+ ** Synopsis:
+ ** void PaneInvalidateCurrent( HWND hWnd, PPANE p, SHORT pos)
+ **
+ ** Entry:
+ ** hWnd - The handle to the current window
+ ** p - The Pane info for the window
+ ** pos - A optional position to set the caret to
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Invalidate the current item that has the focus causing it to be
+ ** repainted
+ */
+
+
+void PaneInvalidateCurrent( HWND hWnd, PPANE p, SHORT pos)
+ {
+
+ PaneInvalidateItem( hWnd, p, p->CurIdx);
+
+ if ( pos >= 0) {
+ PaneSetPos(p,pos);
+ }
+
+ } /* PaneInvalidateCurrent */
+
+ /*** PaneInvalidateItem
+ **
+ ** Synopsis:
+ ** void PaneInvalidateItem( HWND hWnd, PPANE p, WORD Item)
+ **
+ ** Entry:
+ ** hWnd - The handle to the current window
+ ** p - The Pane info for the window
+ ** pos - Item number to invalidate
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Invalidate the a given item and cause it to be repainted
+ */
+
+
+void PaneInvalidateItem( HWND hWnd, PPANE p, SHORT item)
+ {
+ RECT Rect;
+
+ if ( hWnd && p->PaneLines > 0 ) {
+ SendMessage( hWnd, LB_GETITEMRECT, (WPARAM)item, (LPARAM)&Rect);
+ InvalidateRect( hWnd, &Rect, TRUE);
+ }
+
+ } /* PaneInvalidateItem */
+
+ /*** PaneSwitchFocus
+ **
+ ** Synopsis:
+ ** PaneSwitchFocus(PPANE p, HWND hwnd, BOOL fPrev);
+ **
+ ** Entry:
+ ** p - Pointer to the Pane structure.
+ ** hWnd - Handle to the New pane (NULL if we get to pick)
+ ** Prev - flag to force a switch to reverse order
+ **
+ ** Returns:
+ ** None
+ **
+ ** Description:
+ ** Switchs to the next logical pane in the panemanager.
+ */
+
+void PaneSwitchFocus(PPANE p, HWND hWnd, BOOL fPrev)
+ {
+
+ if ( !PaneCloseEdit(p) ) {
+ MessageBeep(0);
+ return;
+ }
+
+ // We're not selecting, need to lose the caret
+ // and are going to repaint the current item (Caret may
+ // have left junk on screen.
+
+ p->SelPos = 0;
+ p->SelLen = 0;
+
+ PaneInvalidateCurrent( p->hWndFocus, p, -1);
+
+ // If we got a hWnd to set use that one
+ if (hWnd != NULL) {
+ p->hWndFocus = hWnd;
+ }
+ else
+ if (p->hWndFocus == NULL) // If we don't have one, default to left pane
+ p->hWndFocus = p->hWndLeft;
+
+ //
+ // Other wise move to the right one
+ //
+ else
+ if ( p->hWndFocus == p->hWndLeft )
+ {
+ if (fPrev == FALSE)
+ p->hWndFocus = p->hWndRight;
+ else
+ p->hWndFocus = p->hWndButton;
+ }
+ else
+ if ( p->hWndFocus == p->hWndRight)
+ {
+ if (fPrev == FALSE)
+ p->hWndFocus = p->hWndButton;
+ else
+ p->hWndFocus = p->hWndLeft;
+ }
+ else
+ if ( p->hWndFocus == p->hWndButton)
+ {
+ if (fPrev == FALSE)
+ p->hWndFocus = p->hWndLeft;
+ else
+ p->hWndFocus = p->hWndRight;
+
+ }
+ else
+ p->hWndFocus = p->hWndLeft;
+
+ //
+ // Make sure we have the right control number
+ //
+
+ if ( p->hWndFocus == p->hWndLeft )
+ p->nCtrlId = ID_PANE_LEFT;
+
+ else if ( p->hWndFocus == p->hWndRight )
+ p->nCtrlId = ID_PANE_RIGHT;
+
+ else
+ p->nCtrlId = ID_PANE_BUTTON;
+
+ SetFocus(p->hWndFocus);
+ PaneResetIdx( p, p->CurIdx);
+
+ } /* PaneSwitch */
+
diff --git a/private/windbg/windbg/pidtid.c b/private/windbg/windbg/pidtid.c
new file mode 100644
index 000000000..58c2c5f8f
--- /dev/null
+++ b/private/windbg/windbg/pidtid.c
@@ -0,0 +1,530 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ pidtid.c
+
+Abstract:
+
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk)
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/****************************** DATA **************************************/
+
+static LPPD LppdHead = NULL;
+static int ipid = 0;
+
+/****************************** CODE **************************************/
+
+VOID PASCAL
+SetIpid(
+ int i
+ )
+{
+ ipid = i;
+}
+
+VOID PASCAL
+RecycleIpid1(
+ void
+ )
+{
+ if (LppdHead
+ && LppdHead->pstate != psDestroyed
+ && !LppdHead->lppdNext
+ && ipid == 2)
+ {
+ ipid = 1;
+ }
+}
+
+LPPD PASCAL
+GetLppdHead(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Retrieves head of LPPD chain.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Pointer to first PD in chain
+
+--*/
+{
+ return LppdHead;
+}
+
+
+LPPD PASCAL
+CreatePd(
+ HPID hpid
+ )
+/*++
+
+Routine Description:
+
+ This function will create a process descriptor block, fill in
+ the defaults for the fields and return a pointer to the descriptor
+ block. No attempts are made to verify that the hpid (handle to
+ process identifier) passed in is correct in any way.
+
+Arguments:
+
+ hpid - Handle to process in the OSDebug world
+
+Return Value:
+
+ NULL on failure or a pointer to a PD structure
+
+--*/
+{
+ LPPD lppd;
+ LPPD lppdT;
+
+ /*
+ ** first allocate and verify the allocation succeeded
+ */
+
+ lppd = (LPPD) _fmalloc(sizeof(PD));
+ if (lppd == NULL) {
+ return lppd;
+ }
+ memset(lppd, 0, sizeof(PD));
+
+ /*
+ ** Now fill in the default set of values for the structure
+ **
+ ** hpid == passed in value
+ ** state == no program has yet been loaded here.
+ ** lptdNext == No threads currently linked on this process.
+ */
+
+ lppd->hpid = hpid;
+ lppd->pstate = psNoProgLoaded;
+ lppd->lptdList = NULL;
+ lppd->ctid = 0;
+ lppd->ipid = ipid++;
+ lppd->exceptionList=NULL;
+ lppd->lpBaseExeName = NULL;
+ lppd->fPrecious = FALSE;
+ lppd->fChild = FALSE;
+ lppd->fFrozen = FALSE;
+
+ /*
+ ** Now append it to the list of process descriptors
+ */
+
+ lppd->lppdNext = NULL;
+ lppdT = LppdHead;
+ if (lppdT == NULL) {
+ LppdHead = lppd;
+ } else {
+ while (lppdT->lppdNext) {
+ lppdT = lppdT->lppdNext;
+ }
+ lppdT->lppdNext = lppd;
+ }
+
+ /*
+ ** Return the pointer to the process descriptor block allocated
+ */
+
+ return(lppd);
+} /* CreatePd() */
+
+
+VOID PASCAL
+DestroyPd(
+ LPPD lppd,
+ BOOL fDestroyPrecious
+ )
+/*++
+
+Routine Description:
+
+ Remove a PD from the list and free it.
+
+Arguments:
+
+ lppd - Supplies pointer to PD to be destroyed
+
+Return Value:
+
+ None.
+
+--*/
+{
+ LPPD *lplppd;
+
+ /*
+ * Remove it from the chain
+ */
+ for (lplppd = &LppdHead; *lplppd; lplppd = &((*lplppd)->lppdNext) ) {
+ if (*lplppd == lppd) {
+ if (lppd->lpBaseExeName) {
+ free(lppd->lpBaseExeName);
+ lppd->lpBaseExeName = NULL;
+ }
+ if (lppd->fPrecious && !fDestroyPrecious) {
+ lppd->pstate = psDestroyed;
+ } else {
+ *lplppd = lppd->lppdNext;
+ free(lppd);
+ }
+ break;
+ }
+ }
+} /* DestroyPd() */
+
+
+/*** LppdOfHpid
+**
+** Synopsis:
+** lppd = LppdOfHpid(hpid)
+**
+** Entry:
+** hpid - Process id handle to be found
+**
+** Returns:
+** pointer to PD if hpid is found and NULL otherwise
+**
+** Description:
+** This routine looks down the list of PDS looking for the specific
+** hpid. If it is found then a pointer to that pd will be returned
+** otherwise NULL is returned
+*/
+
+LPPD PASCAL LppdOfHpid(HPID hpid)
+{
+ LPPD lppd = LppdHead;
+
+ while (lppd != NULL) {
+ if (lppd->hpid == hpid) {
+ break;
+ }
+ lppd = lppd->lppdNext;
+ }
+
+ return(lppd);
+} /* LppdOfHpid() */
+
+
+/*** LppdOfIpid
+**
+** Synopsis:
+** lppd = LppdOfIpid(ipid)
+**
+** Entry:
+** ipid - Internal index number of the process
+**
+** Returns:
+** Pointer to process structure if one exists else NULL
+**
+** Description:
+**
+*/
+
+LPPD PASCAL LppdOfIpid(UINT ipid)
+{
+ LPPD lppd = LppdHead;
+
+ while (lppd != NULL) {
+ if (lppd->ipid == ipid) {
+ break;
+ }
+
+ lppd = lppd->lppdNext;
+ }
+
+ return lppd;
+} /* LppdOfIpid() */
+
+
+LPPD FAR PASCAL
+ValidLppdOfIpid(
+ UINT ipid
+ )
+/*++
+
+Routine Description:
+
+ Look up LPPD by its index #, ignoring destroyed lppd's
+
+Arguments:
+
+ ipid - ordinal number of process
+
+Return Value:
+
+ LPPD or NULL
+
+--*/
+{
+ LPPD lppd;
+
+ for (lppd = LppdHead; lppd != NULL; lppd = lppd->lppdNext) {
+ if (lppd->pstate != psDestroyed && lppd->ipid == ipid) {
+ break;
+ }
+ }
+ return lppd;
+}
+
+
+BOOL FAR PASCAL
+GetFirstValidPDTD(
+ LPPD *plppd,
+ LPTD *plptd
+ )
+/*++
+
+Routine Description:
+
+ Find first non-destroyed LPPD/LPTD pair in list
+
+Arguments:
+
+ plppd - returns lppd
+ plptd - returns lptd
+
+Return Value:
+
+ TRUE for success, FALSE of none found. Values pointed to by
+ args are not modified if search fails.
+
+--*/
+{
+ LPPD lppd;
+
+ for (lppd = LppdHead; lppd; lppd = lppd->lppdNext) {
+ if (lppd->pstate != psDestroyed && lppd->lptdList) {
+ *plppd = lppd;
+ *plptd = lppd->lptdList;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/*** CreateTd
+**
+** Synopsis:
+** lptd = CreateTd(lppd, htid)
+**
+** Entry:
+** lppd - Pointer to process descriptor block to create thread in
+** htid - OSDebug thread handle to be added to process
+**
+** Returns:
+** pointer to thread descriptor block on success, NULL on failure
+**
+** Description:
+** This function will create a thread descriptor block for the
+** osdebug handle to a thread. It will be added to the list of
+** threads for the specified process descriptor block.
+*/
+
+
+LPTD PASCAL CreateTd(LPPD lppd, HTID htid)
+{
+ LPTD lptd;
+ LPTD lptd2;
+
+
+ /*
+ ** First allocate and verify success
+ */
+
+ lptd = (LPTD) _fmalloc(sizeof(TD));
+ if (lptd == NULL)
+ return lptd;
+ memset(lptd, 0, sizeof(TD));
+
+ /*
+ ** Now fill in the default set of values for a thread descriptor
+ **
+ */
+
+ lptd->htid = htid;
+ lptd->lppd = lppd;
+ lptd->tstate = tsPreRunning;
+ lptd->itid = lppd->ctid++;
+
+ /*
+ ** Now insert it in the thread list for the process
+ */
+
+ lptd->lptdNext = NULL;
+ lptd2 = lppd->lptdList;
+ if (lptd2 == NULL) {
+ lppd->lptdList = lptd;
+ } else {
+ while (lptd2->lptdNext != NULL) {
+ lptd2 = lptd2->lptdNext;
+ }
+ lptd2->lptdNext = lptd;
+ }
+
+ /*
+ **
+ */
+
+ return lptd;
+} /* CreateTd() */
+
+
+VOID PASCAL SetTdInfo(LPTD lptd)
+{
+ BYTE buf[sizeof(IOCTLGENERIC)+sizeof(DWORD)];
+ PIOCTLGENERIC pig = (PIOCTLGENERIC)&buf[0];
+ LPTD lptdSave;
+
+
+ if (runDebugParams.fKernelDebugger) {
+ lptd->lpszTname = NULL;
+ lptd->TebBaseAddress = 0;
+ } else {
+ if (lptd->TebBaseAddress == 0) {
+ lptdSave = LptdCur;
+ LptdCur = lptd;
+ pig->ioctlSubType = IG_THREAD_INFO;
+ pig->length = sizeof(DWORD);
+ OSDIoctl( LppdCur->hpid, lptd->htid, ioctlGeneric, pig->length + sizeof(IOCTLGENERIC), (LPV)pig );
+ lptd->TebBaseAddress = *(LPDWORD)pig->data;
+ lptd->lpszTname = GetLastFrameFuncName();
+ LptdCur = lptdSave;
+ }
+ }
+}
+
+
+
+/*** DestroyTd
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+VOID PASCAL DestroyTd(LPTD lptd)
+{
+ LPPD lppd = lptd->lppd;
+ LPTD lptdT;
+
+ if (lppd->lptdList == lptd) {
+ lppd->lptdList = lptd->lptdNext;
+ } else {
+ lptdT = lppd->lptdList;
+ while (lptdT->lptdNext != lptd) {
+ lptdT = lptdT->lptdNext;
+ Assert(lptdT != NULL);
+ }
+ lptdT->lptdNext = lptd->lptdNext;
+ }
+
+ free(lptd);
+ return;
+} /* DestroyTd() */
+
+/*** LptdOfLppdHtid
+**
+** Synopsis:
+** lppd = LptdOfLppdHtid(lppd, htid)
+**
+** Entry:
+** lppd - Process descripter table to look in for thread descriptor
+** htid - thread id handle to be found
+**
+** Returns:
+** pointer to TD if htid is found and NULL otherwise
+**
+** Description:
+** This routine looks down the list of TDs looking for the specific
+** htid. If it is found then a pointer to that td will be returned
+** otherwise NULL is returned
+*/
+
+LPTD PASCAL
+LptdOfLppdHtid(
+ LPPD lppd,
+ HTID htid
+ )
+{
+ LPTD lptd;
+
+ if (!lppd) {
+ return NULL;
+ }
+
+ lptd = lppd->lptdList;
+
+ while (lptd != NULL) {
+ if (lptd->htid == htid) {
+ return lptd;
+ }
+ lptd = lptd->lptdNext;
+ }
+
+ return(lptd);
+} /* LptdOfLppdHtid() */
+
+
+/*** LptdOfLppdItid
+**
+** Synopsis:
+** lptd = LptdOfLppdItid(lppd, itid)
+**
+** Entry:
+** lppd - pointer to process
+** itid - index of thread
+**
+** Returns:
+** pointer to thread if found else NULL
+**
+** Description:
+** This function will locate a thread within the given process which
+** has the correct thread id. This thread id is local to the shell
+** of the debugger and is not the same as a Htid. If no such thread
+** is found then NULL will be returned
+*/
+
+LPTD PASCAL LptdOfLppdItid(LPPD lppd, UINT itid)
+{
+ LPTD lptd = lppd->lptdList;
+
+ while (lptd != NULL) {
+ if (lptd->itid == itid)
+ return lptd;
+ lptd = lptd->lptdNext;
+ }
+
+ return lptd;
+} /* LptdOfLppdItid() */
diff --git a/private/windbg/windbg/precomp.h b/private/windbg/windbg/precomp.h
new file mode 100644
index 000000000..4272eeecd
--- /dev/null
+++ b/private/windbg/windbg/precomp.h
@@ -0,0 +1,90 @@
+/*--
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ Header file that is pre-compiled into a .pch file
+
+Author:
+
+ Wesley Witt (wesw) 21-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#define OEMRESOURCE
+
+#include "global.h"
+#include "apisupp.h"
+#include "debugger.h"
+#include "util.h"
+#include "userdll.h"
+#include "dbugdll.h"
+#include "cvinfo.h"
+#include "shapi.hxx"
+#include "eeapi.h"
+#include "types.h"
+#include "cvtypes.hxx"
+#include "cp.h"
+#include "menu.h"
+#include "breakpts.h"
+#include "cvextras.h"
+#include "disasm.h"
+#include "codemgr.h"
+#include "pidtid.h"
+#include "wrkspace.h"
+#include "bptypes.h"
+#include "bpprotos.h"
+#include "localwin.h"
+#include "od.h"
+#include "document.h"
+#include "edit.h"
+#include "cmdexec.h"
+#include "cmdwin.h"
+#include "makeeng.h"
+#include "util2.h"
+#include "memwin.h"
+#include "dbgver.h"
+#include <dlgs.h>
+#include "colors.h"
+#include "findrep.h"
+#include "panemgr.h"
+#include "cpuwin.h"
+#include "vib.h"
+#include <stdio.h>
+#include <string.h>
+#include "docfile.h"
+#include "undoredo.h"
+#include "editutil.h"
+#include "fonts.h"
+#include "init.h"
+#include "userctrl.h"
+#include "watchwin.h"
+#include "quickw.h"
+#include "program.h"
+#include "remi.h"
+#include "ribbon.h"
+#include "status.h"
+#include <search.h>
+#include <windows.h>
+#include <imagehlp.h>
+#define NOEXTAPI
+#include <wdbgexts.h>
+#include <winver.h>
+#include <stddef.h>
+#include "remote.h"
+#include "callswin.h"
+#include "heap.h"
+
+#ifdef DBCS
+#include <mbstring.h>
+#define strchr _mbschr
+#endif
diff --git a/private/windbg/windbg/process.c b/private/windbg/windbg/process.c
new file mode 100644
index 000000000..29497d99c
--- /dev/null
+++ b/private/windbg/windbg/process.c
@@ -0,0 +1,357 @@
+#include "precomp.h"
+#pragma hdrstop
+
+
+/********************* Structs & Defines ************************************/
+
+typedef struct {
+ LPPD lppd;
+ BOOL fSet;
+} A, *PA;
+
+/**************************** DATA ******************************************/
+
+static PA Pa;
+static int Ca;
+
+static int iTabs[] = { 14, 28, 68, 100, 120 };
+static char szPrFmt[] = "%s\t%2d\t%s\t%s";
+
+/**************************** CODE ******************************************/
+
+
+static BOOL PASCAL
+PrFormatInfo(
+ PA pa,
+ LPSTR lpTarget,
+ UINT cch
+ )
+/*++
+
+Routine Description:
+
+ This routine will format the data associated with a process for
+ displaying to the user.
+
+Arguments:
+
+ lppd - Supplies internal handle to process to be formatted
+ lpTarget - Supplies where to place the formatted string
+ cch - Supplies count of characters in buffer
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise
+
+--*/
+{
+
+
+ PST pst;
+
+ Unreferenced(cch);
+
+ OSDGetProcessStatus(pa->lppd->hpid, &pst);
+
+ sprintf(lpTarget, szPrFmt,
+ (pa->lppd == LppdCur)? " * " : (pa->fSet ? "(*)" : " "),
+ pa->lppd->ipid,
+ pst.rgchProcessID,
+ pst.rgchProcessState);
+
+#if 0
+ long cbPid;
+ char rgb[10];
+ char szStr[100];
+ LPSTR lpstr;
+
+ Unreferenced(cch);
+
+ OSDGetDebugMetric(mtrcPidSize, pa->lppd->hpid, 0, &cbPid );
+ OSDGetDebugMetric(mtrcPidValue, pa->lppd->hpid, 0, (long *) &rgb);
+ EEFormatMemory(szStr, cbPid*2+1, rgb, cbPid*8, fmtUInt|fmtZeroPad, 16);
+
+ OSDPtrace(osdProcStatus, 0, &lpstr, pa->lppd->hpid, 0);
+
+ sprintf(lpTarget, szPrFmt,
+ (pa->lppd == LppdCur)? " * " : (pa->fSet ? "(*)" : " "),
+ pa->lppd->ipid,
+ cbPid*2, cbPid*2, szStr,
+ lpstr);
+#endif
+
+ return TRUE;
+} /* PrFormatInfo() */
+
+
+static VOID PASCAL
+PrEmptyList(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Destructor for process list box
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ if (Pa) {
+ free( Pa );
+ Pa = NULL;
+ }
+ Ca = 0;
+} /* PrEmptyList() */
+
+
+static int PASCAL
+PrSetupDlg(
+ HWND hDlg,
+ BOOL fFirstTime
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ char rgch[256];
+ LPPD lppd;
+ LPPD lppdSelect;
+ int i;
+ int cc;
+ HWND h = GetDlgItem(hDlg, ID_PROCESS_LIST);
+
+
+ Assert( h != NULL);
+
+ i = SendMessage(h, LB_GETCURSEL, 0, 0L);
+ SendMessage(h, LB_RESETCONTENT, 0, 0L);
+
+ if (lppd = GetLppdHead()) {
+
+ /*
+ ** Count the processes.
+ */
+ for (cc=0; lppd; lppd = lppd->lppdNext) {
+ if (lppd->pstate != psDestroyed) {
+ ++cc;
+ }
+ }
+ if (cc != Ca) {
+ Ca = 0;
+ }
+
+ if (!fFirstTime && Ca > 0 && i != LB_ERR) {
+
+ lppdSelect = Pa[i].lppd;
+
+ } else if (cc) {
+
+ lppdSelect = LppdCur;
+ PrEmptyList();
+
+ Ca = cc;
+ Pa = (PA) malloc(sizeof(A)*Ca);
+ Assert(Pa);
+ memset(Pa, 0, sizeof(A)*Ca);
+
+ /*
+ ** Fill it in with initial information.
+ */
+
+ for (i=0, lppd=GetLppdHead(); lppd; i++, lppd=lppd->lppdNext) {
+ if (lppd->pstate == psDestroyed) {
+ continue;
+ }
+ Pa[i].lppd = lppd;
+ Pa[i].fSet = (lppd == LppdCur);
+ }
+ }
+
+ for (i = 0; i < Ca; i++) {
+ PrFormatInfo(&Pa[i], rgch, sizeof(rgch));
+ SendMessage(h, LB_ADDSTRING, 0, (LONG)(LPSTR) rgch);
+
+ if (Pa[i].lppd == lppdSelect) {
+ SendMessage( h, LB_SETCURSEL, i, 0L);
+ }
+ }
+
+ }
+ return Ca;
+} /* PrSetupDlg() */
+
+
+
+/*** DlgProcess
+**
+** Synopsis:
+** bool = DlgProcess(hDlg, msg, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to dialog window
+** msg - Message to be processed
+** wParam - Info about the mesage
+** lParam - Info about the message
+**
+** Returns:
+** TRUE if the message was deal with here and FALSE otherwise
+**
+** Description:
+** This function is the dialog procecdure for the Set Process dialog
+** box. It allows the user to look at the current status of
+** all threads in the current process and manuipulate them
+*/
+
+BOOL PASCAL FAR EXPORT
+DlgProcess(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ int i;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+
+ //
+ // set tabs for listbox
+ //
+ SendMessage(GetDlgItem(hDlg, ID_PROCESS_LIST),
+ LB_SETTABSTOPS, sizeof(iTabs)/sizeof(*iTabs), (LPARAM)iTabs);
+
+ //
+ // now fill listbox and update freeze/thaw button
+ //
+
+ if (PrSetupDlg( hDlg, TRUE ) > 0) {
+ EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
+ return TRUE;
+ } else {
+ // Gray everything
+ EnableWindow(GetDlgItem(hDlg, ID_PROCESS_SELECT), FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
+ SetFocus(GetDlgItem(hDlg, IDCANCEL));
+ return FALSE;
+ }
+
+
+ case WM_COMMAND:
+
+ switch ( wParam ) {
+
+ case IDOK:
+
+ for (i = 0; i < Ca; i++) {
+ if (Pa[i].fSet && Pa[i].lppd != LppdCur) {
+ LppdCur = Pa[i].lppd;
+ LptdCur = LppdCur->lptdList;
+ UpdateDebuggerState(UPDATE_WINDOWS);
+ break;
+ }
+ }
+
+ EndDialog(hDlg, TRUE);
+ PrEmptyList();
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog( hDlg, FALSE );
+ PrEmptyList();
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_PROCESS_HELP ));
+ return TRUE;
+
+
+#ifdef AKENTF
+ case ID_PROCESS_FREEZE:
+
+ i = SendMessage( GetDlgItem( hDlg, ID_PROCESS_LIST), LB_GETCURSEL, 0, 0);
+ Assert( i != LB_ERR);
+
+ if (Pa[i].fFrozen) {
+ if (OSDPtrace(osdFreezeState, FALSE, 0, LppdCur->hpid, htidNull)
+ == xosdNone) {
+ Pa[i].fFrozen = FALSE;
+ Pa[i].lppd->fFrozen = FALSE;
+ }
+ } else {
+ if (OSDPtrace(osdFreezeState, TRUE, 0, LppdCur->hpid, htidNull)
+ == xosdNone) {
+ Pa[i].fFrozen = TRUE;
+ Pa[i].lppd->fFrozen = TRUE;
+ }
+ }
+
+ PrSetupDlg(hDlg, FALSE);
+ return TRUE;
+
+
+ case ID_PROCESS_FREEZEALL:
+
+ for (i=0; i<Ca; i++) {
+ if (!Pa[i].fFrozen
+ && OSDPtrace(osdFreezeState, TRUE, 0, LppdCur->hpid, htidNull)
+ == xosdNone) {
+ Pa[i].fFrozen = TRUE;
+ Pa[i].lppd->fFrozen = TRUE;
+ }
+ }
+ PrSetupDlg(hDlg, FALSE);
+ return TRUE;
+
+
+ case ID_PROCESS_THAWALL:
+
+ for (i=0; i<Ca; i++) {
+ if (Pa[i].fFrozen
+ && OSDPtrace(osdFreezeState, FALSE, 0, LppdCur->hpid, htidNull)
+ == xosdNone) {
+ Pa[i].fFrozen = FALSE;
+ Pa[i].lppd->fFrozen = FALSE;
+ }
+ }
+ PrSetupDlg(hDlg, FALSE);
+ return TRUE;
+#endif
+
+ case ID_PROCESS_SELECT: // Make current
+
+ // clear old current process
+ for (i=0; i<Ca; i++) {
+ Pa[i].fSet = FALSE;
+ }
+
+ i = SendMessage( GetDlgItem( hDlg, ID_PROCESS_LIST), LB_GETCURSEL, 0, 0);
+ Pa[i].fSet = TRUE;
+
+ PrSetupDlg(hDlg, FALSE);
+ EnableWindow( GetDlgItem(hDlg, IDOK), Pa[i].lppd != LppdCur );
+ return TRUE;
+
+ }
+ break;
+ }
+
+ return FALSE;
+} /* DlgProcess() */
diff --git a/private/windbg/windbg/program.c b/private/windbg/windbg/program.c
new file mode 100644
index 000000000..0258ec11e
--- /dev/null
+++ b/private/windbg/windbg/program.c
@@ -0,0 +1,1609 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Program.c
+
+Abstract:
+
+ This module contains the support for Windbg's program menu.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 07-July-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+
+#define DEFAULT_WORKSPACE "Common Workspace"
+#define CURRENT_WORKSPACE "Current Workspace"
+
+
+//
+// Workspace marked to be deleted.
+//
+typedef struct _WORKSPACE_TO_DELETE *PWORKSPACE_TO_DELETE;
+typedef struct _WORKSPACE_TO_DELETE {
+ PWORKSPACE_TO_DELETE Next;
+ char WorkSpace[ MAX_PATH ];
+} WORKSPACE_TO_DELETE;
+
+
+//
+// Program marked to be deleted.
+//
+typedef struct _PROGRAM_TO_DELETE *PPROGRAM_TO_DELETE;
+typedef struct _PROGRAM_TO_DELETE {
+ PPROGRAM_TO_DELETE Next;
+ PWORKSPACE_TO_DELETE WorkSpaceToDelete;
+ BOOLEAN DeleteAll;
+ char ProgramName[ MAX_PATH ];
+} PROGRAM_TO_DELETE;
+
+
+//
+// External variables
+//
+extern BOOL AutoTest;
+
+
+//
+// Exported variables
+//
+BOOLEAN ExitingDebugger = FALSE;
+BOOLEAN AskToSave = FALSE;
+
+//
+// Global variables, for communication with dialogs.
+//
+BOOLEAN DialogCancelled;
+PPROGRAM_TO_DELETE ProgramToDeleteHead = NULL;
+
+
+
+
+//
+// Local prototypes
+//
+BOOL FAR PASCAL EXPORT DlgProgramOpen(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL FAR PASCAL EXPORT DlgProgramClose(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL FAR PASCAL EXPORT DlgProgramSaveAs(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL FAR PASCAL EXPORT DlgProgramDelete(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL FillWorkSpaceBox( HWND hWnd, LPSTR ProgramName, BOOLEAN IncludeDefault, BOOLEAN ComboBox, PPROGRAM_TO_DELETE ProgramToDelete, BOOLEAN );
+VOID FreeProgramToDelete ( VOID );
+BOOL ProgramHookProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+
+
+
+
+
+
+VOID
+ProgramOpen(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handles the processing of Program.Open
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ Assert( !(LptdCur && LptdCur->tstate == tsRunning));
+ StartDialog( DLG_PROGRAM_OPEN, DlgProgramOpen);
+}
+
+
+
+VOID
+ProgramOpenPath(
+ char *Path
+ )
+/*++
+
+Routine Description:
+
+ Opens the specified program
+
+Arguments:
+
+ Path - Supplies the name of the program to open
+
+Return Value:
+
+ None
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+
+ Assert( !(LptdCur && LptdCur->tstate == tsRunning));
+
+ DialogCancelled = FALSE;
+
+ //
+ // If a program is currently loaded and its workspace is
+ // not up-to-date in the registry, give the user a chance
+ // to save it.
+ //
+ if ( DebuggeeAlive() ||
+ (IsProgramLoaded() && DebuggerStateChanged()) ) {
+ if ( AskToSave ) {
+ StartDialog( DLG_PROGRAM_CLOSE, DlgProgramClose );
+ } else {
+ UnLoadProgram();
+ }
+ }
+
+ //
+ // If the user did not cancel the Close of the current
+ // program, load the new program.
+ //
+ if ( !DialogCancelled ) {
+ if ( !GetDefaultWorkSpace( Path, Buffer ) ||
+ !LoadWorkSpace( Path, Buffer, TRUE ) ) {
+
+ //
+ // Program has no workspace, load default instead.
+ //
+ LoadWorkSpace( Path, NULL, TRUE );
+ }
+ }
+}
+
+
+
+
+
+
+BOOLEAN
+ProgramClose(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handles the processing of Program.Close
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - FALSE if cancelled, TRUE otherwise
+
+--*/
+{
+ BOOLEAN Ok = TRUE;
+
+ Assert( ExitingDebugger || !(LptdCur && LptdCur->tstate == tsRunning));
+
+ //
+ // If a program is loaded, close it.
+ //
+ if ( IsProgramLoaded() ) {
+
+ //
+ // If the state has changed, use the close dialog so the
+ // user can save the workspace. Otherwise simply unload
+ // the program.
+ //
+ DialogCancelled = FALSE;
+ if ( DebuggerStateChanged() && !AutoTest ) {
+ if ( AskToSave ) {
+ StartDialog(DLG_PROGRAM_CLOSE, DlgProgramClose);
+ } else {
+ UnLoadProgram();
+ }
+ Ok = !DialogCancelled;
+ } else {
+ UnLoadProgram();
+ }
+
+ //
+ // Load default workspace
+ //
+ if ( !DialogCancelled && !ExitingDebugger ) {
+ LoadWorkSpace( NULL, NULL, TRUE );
+ }
+ }
+
+ return Ok;
+}
+
+
+
+VOID
+ProgramSave(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handles the processing of Program.Save
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ if ( *(GetCurrentWorkSpace()) != '\0' ) {
+ SaveWorkSpace( GetCurrentProgramName(TRUE), GetCurrentWorkSpace(), FALSE );
+ } else {
+ ProgramSaveAs();
+ }
+}
+
+
+
+VOID
+ProgramSaveAs(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handles the processing of Program.Save
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ //Assert( IsProgramLoaded() );
+ StartDialog( DLG_PROGRAM_SAVEAS, DlgProgramSaveAs );
+}
+
+
+
+VOID
+ProgramDelete(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Handles the processing of Program.New
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ StartDialog( DLG_PROGRAM_DELETE, DlgProgramDelete);
+}
+
+
+
+VOID
+ProgramSaveDefaults(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ None
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+
+ if ( SaveWorkSpace( NULL, NULL, FALSE ) ) {
+ //Dbg(LoadString( hInst, DLG_DefaultSaved, Buffer, sizeof(Buffer)));
+ //MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ } else {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_DefaultNotSaved, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+}
+
+
+
+
+
+// **********************************************************
+// DIALOGS
+// **********************************************************
+
+
+
+
+
+
+
+BOOL FAR PASCAL EXPORT
+DlgProgramOpen(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ Code for the Program.Open dialog
+
+Arguments:
+
+ Std. dialog args.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+ char Buffer2[ MAX_PATH ];
+ char FileName[ MAX_PATH ];
+ char Filter[ MAX_PATH ];
+ ULONG i;
+ ULONG MruIndex;
+ BOOLEAN MruFound;
+ WORD Items;
+ OPENFILENAME OpenFileName;
+ LPSTR s;
+ LPSTR List;
+ DWORD ListLength;
+ DWORD Next = 0;
+ LPSTR ProgramName;
+ static int LargestString;
+ int StringLength;
+ SIZE Size;
+ HDC hdc;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+
+ LargestString = 0;
+
+ //
+ // Fill the program list with all the programs in the registry
+ //
+ if ( List = GetAllPrograms( &ListLength ) ) {
+
+ char Name1[ MAX_PATH ];
+ char Name2[ MAX_PATH ];
+
+ strcpy( FileName, GetCurrentProgramName(TRUE) );
+
+ hdc = GetDC( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ) );
+ while ( ProgramName = GetNextStringFromMultiString( List,
+ ListLength,
+ &Next ) ) {
+
+ //
+ // If the program is the current program, preserve the
+ // current path.
+ //
+ Name1[0] = '\0';
+ Name2[0] = '\0';
+
+ _splitpath( FileName, NULL, NULL, Name1, NULL );
+ _splitpath( ProgramName, NULL, NULL, Name2, NULL );
+
+ if ( !_stricmp( Name1, Name2 ) ) {
+ strcpy( Buffer, FileName );
+ } else {
+ strcpy( Buffer, ProgramName );
+ }
+
+ GetTextExtentPoint(hdc, Buffer, strlen(Buffer), &Size );
+ StringLength = Size.cx;
+
+ if ( StringLength > LargestString ) {
+
+ LargestString = StringLength;
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_ADDSTRING, 0, (LONG)(LPSTR)Buffer );
+
+ }
+
+ ReleaseDC( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ), hdc );
+ DeallocateMultiString( List );
+ }
+
+ //
+ // The default program to open will be the first we
+ // find from the MRU list, or the first in the program
+ // list.
+ //
+ Items = (WORD)SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETCOUNT, 0, 0L );
+
+ if ( Items > 0 ) {
+
+ MruFound = FALSE;
+ for ( MruIndex = 0;
+ !MruFound && (MruIndex < (ULONG)nbFilesKept[PROJECT_FILE]);
+ MruIndex++ ) {
+
+ //
+ // Look for the MRU program in the list.
+ //
+ Dbg(s = (LPSTR)GlobalLock(hFileKept[PROJECT_FILE][MruIndex]));
+ strcpy(Buffer2, s);
+ Dbg(GlobalUnlock (hFileKept[PROJECT_FILE][MruIndex]) == FALSE);
+
+ for ( i=0; !MruFound && (i < (ULONG)Items); i++ ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETTEXT, i, (LONG)(LPSTR)Buffer );
+
+ if ( !_stricmp( Buffer, Buffer2 )) {
+ MruFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ //
+ // Select the program
+ //
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_SETCURSEL, MruFound ? i : 0, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETTEXT, MruFound ? i : 0, (LONG)(LPSTR)Buffer );
+
+ if ( *Buffer ) {
+ FillWorkSpaceBox( GetDlgItem(hDlg, ID_PROGOPEN_WORKSPACES ),
+ Buffer,
+ TRUE,
+ FALSE,
+ NULL,
+ FALSE
+ );
+ }
+
+ i = SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_WORKSPACES ),
+ LB_GETCOUNT, 0, 0L );
+
+ EnableWindow(GetDlgItem(hDlg, IDOK ), (i > 0) );
+ SetFocus(GetDlgItem( hDlg, IDOK ) );
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+ case ID_PROGOPEN_PROGRAMS:
+ switch (HIWORD(wParam)) {
+ case LBN_SETFOCUS:
+ case LBN_SELCHANGE:
+ *Buffer = '\0';
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETTEXT,
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETCURSEL, 0, 0L ),
+ (LONG)(LPSTR)Buffer );
+ if ( *Buffer ) {
+ FillWorkSpaceBox( GetDlgItem(hDlg, ID_PROGOPEN_WORKSPACES ),
+ Buffer,
+ TRUE, FALSE, NULL, FALSE );
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+
+ case IDOK:
+ //
+ // If a program is currently loaded, invoke the
+ // close dialog.
+ //
+ // If the user cancells the close, then continue,
+ // otherwise go ahead with the open.
+ //
+ DialogCancelled = FALSE;
+
+ if ( DebuggeeAlive() ||
+ (IsProgramLoaded() && DebuggerStateChanged()) ) {
+ if ( AskToSave ) {
+ StartDialog( DLG_PROGRAM_CLOSE, DlgProgramClose );
+ } else {
+ UnLoadProgram();
+ }
+ }
+
+ if ( !DialogCancelled ) {
+
+ //
+ // Get program & workspace and open it.
+ //
+ Buffer[0] = '\0';
+ Buffer2[0] = '\0';
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETTEXT,
+ SendMessage(GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_GETCURSEL, 0, 0L ),
+ (LONG)(LPSTR)Buffer );
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_WORKSPACES ),
+ LB_GETTEXT,
+ SendMessage(GetDlgItem(hDlg, ID_PROGOPEN_WORKSPACES ),
+ LB_GETCURSEL, 0, 0L ),
+ (LONG)(LPSTR)Buffer2 );
+
+
+ if ( !_stricmp( Buffer2, CURRENT_WORKSPACE ) ) {
+ //
+ // Load new program using current workspace.
+ //
+ LoadProgram( Buffer );
+ FileName[0] = '\0';
+ strcpy( GetCurrentWorkSpace(), FileName );
+
+ } else {
+ if ( !_stricmp( Buffer2, DEFAULT_WORKSPACE) ) {
+ Buffer2[0] = '\0';
+ }
+
+ LoadWorkSpace( Buffer, Buffer2, TRUE );
+ }
+
+ DialogCancelled = FALSE;
+ EndDialog( hDlg, TRUE );
+ }
+ break;
+
+ case ID_PROGOPEN_NEW:
+
+ GetCurrentDirectory( sizeof( Buffer ), Buffer );
+
+ FileName[0] = '\0';
+
+/***
+ s = Filter;
+ strcpy( s, szStarDotExe );
+ s += strlen(s)+1;
+ strcpy( s, szStarDotExe );
+ s += strlen(s)+1;
+ strcpy( s, szStarDotCom );
+ s += strlen(s)+1;
+ strcpy( s, szStarDotCom );
+ s += strlen(s)+1;
+ strcpy( s, szStarDotStar );
+ s += strlen(s)+1;
+ strcpy( s, szStarDotStar );
+ s += strlen(s)+1;
+ *s++ = '\0';
+***/
+ {
+ char* nextStr = Filter;
+ int remaining = sizeof(Filter);
+ int loadCount;
+
+ Dbg(loadCount = LoadString(hInst, TYP_File_EXE_COM, nextStr, remaining));
+ nextStr += loadCount+1;
+ remaining -= loadCount - 1;
+
+ Dbg(loadCount = LoadString(hInst, DEF_Ext_EXE_COM, nextStr, remaining));
+ nextStr += loadCount+1;
+ remaining -= loadCount - 1;
+
+ Dbg(loadCount = LoadString(hInst, TYP_File_ALL, nextStr, remaining));
+ nextStr += loadCount+1;
+ remaining -= loadCount - 1;
+
+ Dbg(loadCount = LoadString(hInst, DEF_Ext_ALL, nextStr, remaining));
+ nextStr += loadCount+1;
+
+ *nextStr = 0;
+ }
+
+
+
+ OpenFileName.lStructSize = sizeof( OpenFileName );
+ OpenFileName.hwndOwner = hDlg;
+ OpenFileName.hInstance = (HANDLE)0;
+ OpenFileName.lpstrFilter = Filter;
+ OpenFileName.lpstrCustomFilter = NULL;
+ OpenFileName.nMaxCustFilter = 0;
+ OpenFileName.nFilterIndex = 1;
+ OpenFileName.lpstrFile = FileName;
+ OpenFileName.nMaxFile = sizeof( FileName );
+ OpenFileName.lpstrFileTitle = Buffer2;
+ OpenFileName.nMaxFileTitle = sizeof( Buffer2 );
+ OpenFileName.lpstrInitialDir = Buffer;
+ OpenFileName.lpstrTitle = NULL;
+ OpenFileName.Flags = OFN_ENABLEHOOK
+ | OFN_SHOWHELP
+ | OFN_HIDEREADONLY;
+ OpenFileName.nFileOffset = 0;
+ OpenFileName.nFileExtension = 0;
+ OpenFileName.lpstrDefExt = NULL;
+ OpenFileName.lCustData = 0;
+ OpenFileName.lpfnHook = ( LPOFNHOOKPROC )ProgramHookProc;
+ OpenFileName.lpTemplateName = NULL;
+
+ if ( GetOpenFileName( &OpenFileName ) ) {
+
+ int Index;
+
+ //
+ // If program name is not in list, add new entry
+ //
+ Index = SendMessage( GetDlgItem(hDlg,ID_PROGOPEN_PROGRAMS), LB_SELECTSTRING, 0, (LONG)OpenFileName.lpstrFile );
+ if ( Index == LB_ERR ) {
+
+ hdc = GetDC( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ) );
+ GetTextExtentPoint(hdc, OpenFileName.lpstrFile , strlen(OpenFileName.lpstrFile), &Size );
+ ReleaseDC( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ), hdc );
+ StringLength = Size.cx;
+
+ if ( StringLength > LargestString ) {
+
+ LargestString = StringLength;
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ Index = SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_ADDSTRING, 0, (LONG)(LPSTR)OpenFileName.lpstrFile );
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGOPEN_PROGRAMS ),
+ LB_SETCURSEL, Index, 0L );
+ }
+ SetFocus(GetDlgItem( hDlg, ID_PROGOPEN_PROGRAMS ) );
+ }
+ break;
+
+ case IDCANCEL:
+ DialogCancelled = TRUE;
+ EndDialog( hDlg, TRUE );
+ break;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_PROGOPEN_HELP));
+ return TRUE;
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+
+
+BOOL ProgramHookProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static LPCHOOSEFONT Cf;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam )) {
+
+ case IDWINDBGHELP:
+ case pshHelp:
+
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_PROGOPEN_NEW_HELP));
+ return TRUE;
+
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+
+BOOL FAR PASCAL EXPORT
+DlgProgramClose(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ Code for the Program.Close dialog
+
+Arguments:
+
+ Std. dialog args.
+
+Return Value:
+
+ None
+
+--*/
+{
+
+ char Buffer[ MAX_PATH ];
+ char Buffer2[ MAX_PATH ];
+ char Buffer3[ MAX_PATH ];
+ char *ProgramName;
+ char *WorkSpace;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+
+ ProgramName = GetCurrentProgramName(TRUE);
+ GetBaseName( ProgramName, Buffer );
+ Dbg(LoadString( hInst, DLG_CloseText1, Buffer2, sizeof(Buffer2)));
+ sprintf( Buffer3, Buffer2, Buffer );
+ SendMessage(GetDlgItem(hDlg, ID_PROGCLOSE_TEXT1), WM_SETTEXT, 0, (DWORD)(LPSTR)Buffer3);
+
+ WorkSpace = GetCurrentWorkSpace();
+ Dbg(LoadString( hInst, DLG_CloseText2, Buffer2, sizeof(Buffer2)));
+ if ( *WorkSpace != '\0' ) {
+ sprintf( Buffer3, Buffer2, WorkSpace );
+ } else {
+ sprintf( Buffer3, Buffer2, DEFAULT_WORKSPACE );
+ }
+ SendMessage(GetDlgItem(hDlg, ID_PROGCLOSE_TEXT2), WM_SETTEXT, 0, (DWORD)(LPSTR)Buffer3);
+
+ //if ( ExitingDebugger ) {
+ // EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
+ //}
+ SetFocus(GetDlgItem( hDlg, IDYES ) );
+
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+ case ID_PROGCLOSE_TEXT1:
+ break;
+
+ case ID_PROGCLOSE_TEXT2:
+ break;
+
+ case IDYES:
+
+ //
+ // If the program has a workspace, just save it.
+ // Otherwise the user has to give it a name.
+ //
+ if ( *(GetCurrentWorkSpace()) == '\0' ) {
+ DialogCancelled = FALSE;
+ StartDialog( DLG_PROGRAM_SAVEAS, DlgProgramSaveAs );
+ if ( !DialogCancelled ) {
+ if ( UnLoadProgram() ) {
+ EndDialog( hDlg, TRUE );
+ } else {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_CannotUnload, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+ }
+ } else {
+ if ( SaveWorkSpace( GetCurrentProgramName(TRUE), GetCurrentWorkSpace(), FALSE ) ) {
+ //Dbg(LoadString( hInst, DLG_WorkSpaceSaved, Buffer, sizeof(Buffer)));
+ //MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ if ( UnLoadProgram() ) {
+ DialogCancelled = FALSE;
+ EndDialog( hDlg, TRUE );
+ } else {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_CannotUnload, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+ } else {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_WorkSpaceNotSaved, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+ }
+ break;
+
+ case IDNO:
+
+ if ( UnLoadProgram() ) {
+ DialogCancelled = FALSE;
+ EndDialog( hDlg, TRUE );
+ } else {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_CannotUnload, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+ break;
+
+ case IDCANCEL:
+ DialogCancelled = TRUE;
+ EndDialog( hDlg, TRUE );
+ break;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_PROGCLOSE_HELP) );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+BOOL FAR PASCAL EXPORT
+DlgProgramSaveAs(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ Code for the Program.Load Work Space dialog
+
+Arguments:
+
+ Std. dialog args.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+ char Buffer1[ MAX_PATH ];
+ BOOLEAN MakeDefault;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+
+ case WM_INITDIALOG:
+
+ if (FillWorkSpaceBox( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ GetCurrentProgramName(TRUE),
+ FALSE,
+ TRUE,
+ NULL,
+ FALSE )) {
+
+ if ( GetCurrentWorkSpace() ) {
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ CB_SELECTSTRING, (WPARAM)-1,
+ (LPARAM)GetCurrentWorkSpace() );
+ }
+
+ Buffer[0] = '\0';
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ WM_GETTEXT, sizeof( Buffer ), (LONG)(LPSTR)Buffer );
+
+ if ( GetDefaultWorkSpace( GetCurrentProgramName(TRUE), Buffer1 ) ) {
+ MakeDefault = !_stricmp( Buffer, Buffer1 );
+ } else {
+ MakeDefault = TRUE;
+ }
+
+ } else {
+
+ //
+ // No workspaces, set default to "Untitled"
+ //
+ Dbg(LoadString(hInst, SYS_Untitled_Workspace, Buffer, MAX_MSG_TXT));
+ SendMessage( GetDlgItem(hDlg,ID_PROGSAVEAS_WORKSPACES), CB_ADDSTRING, 0, (LONG)Buffer );
+ SendMessage( GetDlgItem(hDlg,ID_PROGSAVEAS_WORKSPACES), CB_SETCURSEL, 0, (LONG)0 );
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_MAKEDEFAULT),
+ BM_SETCHECK, FALSE, 0L );
+
+ MakeDefault = TRUE;
+ }
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_MAKEDEFAULT),
+ BM_SETCHECK, MakeDefault, 0L );
+
+ SetFocus(GetDlgItem( hDlg, IDOK ) );
+
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+ case ID_PROGSAVEAS_WORKSPACES:
+ switch (HIWORD(wParam)) {
+ case LBN_SELCHANGE:
+ //SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ // WM_GETTEXT, sizeof( Buffer ), (LONG)(LPSTR)Buffer );
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ CB_GETLBTEXT,
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ CB_GETCURSEL, 0, 0L ),
+ (LONG)(LPSTR)Buffer );
+
+ if ( GetDefaultWorkSpace( GetCurrentProgramName(TRUE), Buffer1 ) ) {
+ MakeDefault = !_stricmp( Buffer, Buffer1 );
+ } else {
+ MakeDefault = TRUE;
+ }
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_MAKEDEFAULT),
+ BM_SETCHECK, MakeDefault, 0L );
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case IDOK:
+
+ Buffer[0] = '\0';
+ SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_WORKSPACES ),
+ WM_GETTEXT, sizeof( Buffer ), (LONG)(LPSTR)Buffer );
+
+ if ( Buffer[0] != '\0' ) {
+
+ MakeDefault = (SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_MAKEDEFAULT),
+ BM_GETCHECK, 0, 0L ) == 1);
+
+ if ( SaveWorkSpace( GetCurrentProgramName(TRUE), Buffer, MakeDefault ) ) {
+ //Dbg(LoadString( hInst, DLG_WorkSpaceSaved, Buffer, sizeof(Buffer)));
+ //MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ DialogCancelled = FALSE;
+ EndDialog( hDlg, TRUE );
+ } else {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_WorkSpaceNotSaved, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ DialogCancelled = TRUE;
+ EndDialog( hDlg, TRUE );
+ break;
+
+ case ID_PROGSAVEAS_MAKEDEFAULT:
+
+ //MakeDefault = !(SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_MAKEDEFAULT),
+ // BM_GETCHECK, 0, 0L ) == 1);
+ //
+ //SendMessage( GetDlgItem(hDlg, ID_PROGSAVEAS_MAKEDEFAULT),
+ // BM_SETCHECK, MakeDefault ? 1 : 0, 0L );
+ break;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_PROGSAVEAS_HELP) );
+ return TRUE;
+ }
+
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+BOOL FAR PASCAL EXPORT
+DlgProgramDelete(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ Code for the Program.Delete dialog
+
+Arguments:
+
+ Std. dialog args.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+ char Buffer2[ MAX_PATH ];
+ ULONG i;
+ BOOLEAN MruFound;
+ ULONG MruIndex;
+ char * s;
+ WORD Items;
+ WORD DeletedItems;
+ WORD ProgramIdx;
+ PPROGRAM_TO_DELETE ProgramToDelete;
+ PWORKSPACE_TO_DELETE WorkSpaceToDelete;
+ LPSTR List=0;
+ DWORD ListLength;
+ DWORD Next = 0;
+ LPSTR ProgramName;
+ int LargestString = 0;
+ int StringLength;
+ SIZE Size;
+ HDC hdc;
+
+ Unreferenced( lParam );
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+
+ //
+ // Fill the program list with all the programs in the registry
+ //
+ if ( List = GetAllPrograms( &ListLength ) ) {
+
+ while ( ProgramName = GetNextStringFromMultiString( List,
+ ListLength,
+ &Next ) ) {
+
+ hdc = GetDC( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ) );
+ GetTextExtentPoint(hdc, ProgramName , strlen(ProgramName), &Size );
+ ReleaseDC( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ), hdc );
+ StringLength = Size.cx;
+
+ if ( StringLength > LargestString ) {
+
+ LargestString = StringLength;
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_ADDSTRING, 0, (LONG)(LPSTR)ProgramName );
+
+ }
+
+ DeallocateMultiString( List );
+ }
+
+
+ //
+ // The default program to delete will be the first we
+ // find from the MRU list, or the first in the program
+ // list.
+ //
+ Items = (WORD)SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETCOUNT, 0, 0L );
+
+ if ( Items > 0 ) {
+
+ MruFound = FALSE;
+ for ( MruIndex = 0;
+ !MruFound && (MruIndex < (ULONG)nbFilesKept[PROJECT_FILE]);
+ MruIndex++ ) {
+
+ //
+ // Look for the MRU program in the list.
+ //
+ Dbg(s = (LPSTR)GlobalLock(hFileKept[PROJECT_FILE][MruIndex]));
+ strcpy(Buffer2, s);
+ Dbg(GlobalUnlock (hFileKept[PROJECT_FILE][MruIndex]) == FALSE);
+
+ for ( i=0; !MruFound && (i < (ULONG)Items); i++ ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETTEXT, i, (LONG)(LPSTR)Buffer );
+
+ if ( !_stricmp( Buffer, Buffer2 )) {
+ MruFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETTEXT, MruFound ? i : 0, (LONG)(LPSTR)Buffer );
+
+
+ FillWorkSpaceBox( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ Buffer,
+ FALSE, FALSE, NULL, TRUE );
+
+ //
+ // Select the program
+ //
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_SETCURSEL, MruFound ? i : 0, 0L );
+
+ }
+
+ ProgramToDeleteHead = NULL;
+
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam ) ) {
+
+ case ID_PROGDELETE_PROGRAMS:
+
+ switch (HIWORD(wParam)) {
+ case LBN_SETFOCUS:
+ case LBN_SELCHANGE:
+
+ //
+ // A new program was selected, fill the workspace
+ // list with all the workspaces for the selected
+ // program.
+ //
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETTEXT,
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETCURSEL, 0, 0L ),
+ (LONG)(LPSTR)Buffer );
+
+ ProgramToDelete = ProgramToDeleteHead;
+ while ( ProgramToDelete ) {
+ if ( !_stricmp( ProgramToDelete->ProgramName,
+ Buffer ) ) {
+ break;
+ }
+ ProgramToDelete = ProgramToDelete->Next;
+ }
+
+ FillWorkSpaceBox( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ Buffer,
+ FALSE, FALSE, ProgramToDelete, TRUE );
+
+ EnableWindow( GetDlgItem(hDlg,ID_PROGDELETE_DELETE), Buffer != NULL);
+
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case ID_PROGDELETE_WORKSPACES:
+ switch (HIWORD(wParam)) {
+ case LBN_SELCHANGE:
+ Items = (WORD)SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES),
+ LB_GETCOUNT, 0, 0L );
+
+ for (i=0; i < (ULONG)Items; i++ ) {
+ if ( SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES),
+ LB_GETSEL, i, 0L ) ) {
+ break;
+ }
+ }
+ EnableWindow( GetDlgItem(hDlg,ID_PROGDELETE_DELETE), i < Items );
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case IDOK:
+ //
+ // Delete whatever is selected for deletion
+ //
+ ProgramToDelete = ProgramToDeleteHead;
+ while ( ProgramToDelete ) {
+ if ( ProgramToDelete->DeleteAll ) {
+ DeleteProgram( ProgramToDelete->ProgramName );
+ } else {
+
+ WorkSpaceToDelete = ProgramToDelete->WorkSpaceToDelete;
+ while ( WorkSpaceToDelete ) {
+
+ DeleteWorkSpace( ProgramToDelete->ProgramName,
+ WorkSpaceToDelete->WorkSpace );
+
+ WorkSpaceToDelete = WorkSpaceToDelete->Next;
+ }
+ }
+ ProgramToDelete = ProgramToDelete->Next;
+ }
+
+ FreeProgramToDelete();
+ EndDialog( hDlg, TRUE );
+ break;
+
+ case ID_PROGDELETE_DELETE:
+ //
+ // Add selections to deletion data.
+ //
+ ProgramIdx = (WORD)SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETCURSEL, 0, 0L );
+
+ if ( ProgramIdx != LB_ERR ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_GETTEXT, ProgramIdx, (LONG)(LPSTR)Buffer );
+
+ //
+ // If we already deleted something from this program reuse
+ // its deletion structure, otherwise create a new one.
+ //
+ ProgramToDelete = ProgramToDeleteHead;
+ while ( ProgramToDelete ) {
+ if ( !_stricmp( ProgramToDelete->ProgramName, Buffer ) ) {
+ break;
+ }
+ ProgramToDelete = ProgramToDelete->Next;
+ }
+
+ if ( !ProgramToDelete ) {
+ Assert( ProgramToDelete = (PPROGRAM_TO_DELETE)malloc( sizeof( PROGRAM_TO_DELETE ) ) );
+ strcpy( ProgramToDelete->ProgramName, Buffer );
+ ProgramToDelete->WorkSpaceToDelete = NULL;
+ ProgramToDelete->DeleteAll = FALSE;
+ ProgramToDelete->Next = ProgramToDeleteHead;
+ ProgramToDeleteHead = ProgramToDelete;
+ }
+
+ //
+ // Add the workspaces to the deletion structure.
+ //
+ Items = (WORD)SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ LB_GETCOUNT, 0, 0L );
+
+ if ( Items == 0 ) {
+ //ProgramToDelete->DeleteAll = TRUE;
+ } else {
+ DeletedItems = 0;
+ for ( i=0; i < (ULONG)Items; i++ ) {
+
+ if ( SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ LB_GETSEL, i, 0L ) ) {
+
+ Assert( WorkSpaceToDelete = (PWORKSPACE_TO_DELETE)malloc( sizeof( WORKSPACE_TO_DELETE ) ) );
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ LB_GETTEXT, i, (LONG)(LPSTR)WorkSpaceToDelete->WorkSpace );
+
+ WorkSpaceToDelete->Next = ProgramToDelete->WorkSpaceToDelete;
+ ProgramToDelete->WorkSpaceToDelete = WorkSpaceToDelete;
+ DeletedItems++;
+
+ }
+ }
+
+ if ( DeletedItems == Items ) {
+ ProgramToDelete->DeleteAll = TRUE;
+ }
+ }
+
+ if ( ProgramToDelete->DeleteAll ) {
+ SendMessage( GetDlgItem( hDlg, ID_PROGDELETE_WORKSPACES ),
+ LB_RESETCONTENT, 0, 0L );
+
+ } else {
+ FillWorkSpaceBox( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ ProgramToDelete->ProgramName,
+ FALSE, FALSE, ProgramToDelete, TRUE );
+
+ }
+
+ Items = (WORD)SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_WORKSPACES ),
+ LB_GETCOUNT, 0, 0L );
+
+ if ( Items == 0 ) {
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_DELETESTRING, ProgramIdx, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS ),
+ LB_SETCURSEL, 0, 0L );
+
+ SetFocus( GetDlgItem(hDlg, ID_PROGDELETE_PROGRAMS) );
+ }
+ }
+ break;
+
+ case IDCANCEL:
+ FreeProgramToDelete();
+ DialogCancelled = TRUE;
+ EndDialog( hDlg, TRUE );
+ break;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_PROGDELETE_HELP) );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+
+// **********************************************************
+// HELPER FUNCTIONS
+// **********************************************************
+
+
+BOOL
+FillWorkSpaceBox(
+ HWND hWnd,
+ LPSTR ProgramName,
+ BOOLEAN IncludeDefault,
+ BOOLEAN ComboBox,
+ PPROGRAM_TO_DELETE ProgramToDelete,
+ BOOLEAN SelectAll
+ )
+/*++
+
+Routine Description:
+
+ Fills a workspace box with the workspaces for a given
+ program.
+
+Arguments:
+
+ hWnd - Supplies handle to combo box
+ List - Supplies multistring with workspace names
+ ListLength - Supplies the size of the list
+ IncludeDefault - Supplies flag which if TRUE means that
+ the default is to be included in the list.
+ ComboBox - Supplies flag which if TRUE means that
+ the handle is to a combo box.
+ ProgramToDelete - Supplies structure with workspaces not to be
+ included in the list.
+
+Return Value:
+
+ None
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+ ULONG i;
+ WORD Items;
+ BOOLEAN Selected = FALSE;
+ PWORKSPACE_TO_DELETE WorkSpaceToDelete;
+ BOOLEAN Add;
+ DWORD Next = 0;
+ LPSTR WorkSpace;
+ int LargestString = 0;
+ int StringLength;
+ SIZE Size;
+ HDC hdc;
+ LPSTR List;
+ DWORD ListLength;
+ char Default[ MAX_PATH ];
+ BOOL rv = TRUE;
+
+
+ List = GetAllWorkSpaces( ProgramName, &ListLength, Default );
+ if (!List) {
+ rv = FALSE;
+ }
+
+ SendMessage( hWnd, CB_RESETCONTENT, 0, 0L );
+
+ if ( ProgramToDelete && ProgramToDelete->DeleteAll ) {
+ return FALSE;
+ }
+
+ SendMessage( hWnd, ComboBox ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0L );
+
+ if ( IncludeDefault ) {
+
+ hdc = GetDC( hWnd );
+ GetTextExtentPoint(hdc, DEFAULT_WORKSPACE, strlen(DEFAULT_WORKSPACE), &Size );
+ LargestString = Size.cx;
+ GetTextExtentPoint(hdc, CURRENT_WORKSPACE, strlen(CURRENT_WORKSPACE), &Size );
+ ReleaseDC( hWnd, hdc );
+ if ( Size.cx > LargestString ) {
+ LargestString = Size.cx;
+ }
+
+ SendMessage( hWnd,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+
+ SendMessage( hWnd, LB_ADDSTRING, 0, (LONG)(LPSTR)DEFAULT_WORKSPACE );
+ SendMessage( hWnd, LB_ADDSTRING, 0, (LONG)(LPSTR)CURRENT_WORKSPACE );
+ }
+
+
+ if ( List ) {
+ while ( WorkSpace = GetNextStringFromMultiString( List,
+ ListLength,
+ &Next ) ) {
+ Add = TRUE;
+
+ if ( ProgramToDelete ) {
+ WorkSpaceToDelete = ProgramToDelete->WorkSpaceToDelete;
+ while ( WorkSpaceToDelete ) {
+ if ( !_stricmp( WorkSpaceToDelete->WorkSpace,
+ WorkSpace ) ) {
+ Add = FALSE;
+ break;
+ }
+ WorkSpaceToDelete = WorkSpaceToDelete->Next;
+ }
+ }
+
+ if ( Add ) {
+
+ hdc = GetDC( hWnd );
+ GetTextExtentPoint(hdc, WorkSpace, strlen(WorkSpace), &Size );
+ ReleaseDC( hWnd, hdc );
+ StringLength = Size.cx;
+
+ if ( StringLength > LargestString ) {
+
+ LargestString = StringLength;
+
+ SendMessage( hWnd,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ SendMessage( hWnd,
+ ComboBox ? CB_ADDSTRING : LB_ADDSTRING,
+ 0,
+ (LONG)(LPSTR)WorkSpace ) ;
+ }
+ }
+ }
+
+ if ( SelectAll ) {
+
+ SendMessage( hWnd, LB_SETSEL, TRUE, -1L );
+
+ } else {
+
+ //
+ // If there is a default workspace, select it.
+ //
+ if ( Default && (*Default != '\0') ) {
+ Items = (WORD)SendMessage( hWnd,
+ ComboBox ? CB_GETCOUNT : LB_GETCOUNT,
+ 0, 0L );
+
+ for (i=0; i < (ULONG)Items; i++ ) {
+
+ SendMessage( hWnd, ComboBox ? CB_GETLBTEXT : LB_GETTEXT, i, (LONG)(LPSTR)Buffer );
+
+ if ( !_stricmp( Buffer, Default ) ) {
+
+ SendMessage( hWnd, ComboBox ? CB_SETCURSEL : LB_SETCURSEL, i, 0L );
+ Selected = TRUE;
+ break;
+ }
+ }
+ }
+
+ //
+ // If no default, select the first one.
+ //
+ if ( !Selected && !ProgramToDelete ) {
+
+ Items = (WORD)SendMessage( hWnd, ComboBox ? CB_GETCOUNT : LB_GETCOUNT, 0, 0L );
+
+ if ( Items > 0 ) {
+ SendMessage( hWnd, ComboBox ? CB_SETCURSEL : LB_SETCURSEL, 0, 0L );
+ }
+ }
+ }
+
+ if (List) {
+ DeallocateMultiString( List );
+ }
+
+ return rv;
+}
+
+
+
+VOID
+FreeProgramToDelete (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Frees up memory used by the ProgramToDelete list
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ PPROGRAM_TO_DELETE ProgramToDelete;
+ PPROGRAM_TO_DELETE ProgramToDeleteTmp;
+ PWORKSPACE_TO_DELETE WorkSpaceToDelete;
+ PWORKSPACE_TO_DELETE WorkSpaceToDeleteTmp;
+
+ //
+ // Free all memory used by the deletion structures.
+ //
+ ProgramToDelete = ProgramToDeleteHead;
+ while ( ProgramToDelete ) {
+ //
+ // Free all workspace memory
+ //
+ WorkSpaceToDelete = ProgramToDelete->WorkSpaceToDelete;
+ while ( WorkSpaceToDelete ) {
+ WorkSpaceToDeleteTmp = WorkSpaceToDelete;
+ WorkSpaceToDelete = WorkSpaceToDelete->Next;
+ free( WorkSpaceToDeleteTmp );
+ }
+
+ ProgramToDeleteTmp = ProgramToDelete;
+ ProgramToDelete = ProgramToDelete->Next;
+ free( ProgramToDeleteTmp );
+ }
+}
+
diff --git a/private/windbg/windbg/quickw.c b/private/windbg/windbg/quickw.c
new file mode 100644
index 000000000..54552fc70
--- /dev/null
+++ b/private/windbg/windbg/quickw.c
@@ -0,0 +1,466 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ QUICKW.C
+
+Abstract:
+
+ This file contains the code for dealing with the Quickwatch Dialog box
+
+Author:
+
+ Bill Heaton (v-willhe)
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32 - User
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#define QWButtonStyle(Id) (WORD)GetWindowLong(GetDlgItem(hDlg, Id), GWL_STYLE)
+
+/*
+ * Global Memory (PROGRAM)
+ */
+
+extern CXF CxfIp;
+
+/*
+ * Global Memory (FILE)
+ */
+
+PTRVIT pvitQuick;
+HWND hWndQuick;
+char WatchVar[MAX_USER_LINE + 1];
+PSTR pWatchVar;
+
+PTRVIT pVit = NULL;
+PTRVIB pVib = NULL;
+
+
+
+/*
+ * Function Prototypes
+ */
+
+BOOL FAR PASCAL EXPORT DlgQuickInit(HWND hDlg, UINT message, WPARAM wParam, LONG lParam);
+BOOL FAR PASCAL EXPORT DlgQuickCommand(HWND hDlg, UINT message, WPARAM wParam, LONG lParam);
+VOID UpdateQuickWatch(PPANE p, WPARAM wParam);
+PTRVIT PASCAL InitQuickVit(void);
+
+/*** DlgQuickW
+**
+** Synopsis:
+** bool = DlgQuickW(hwnd, message, wParam, lParam)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes messages for "QUICKWATCH" dialog box
+** (Edit Find Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT DlgQuickW(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ Unused(lParam);
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ pVit = NULL;
+ return ( DlgQuickInit( hDlg, message, wParam, lParam) );
+
+ case WM_COMMAND:
+ return ( DlgQuickCommand( hDlg, message, wParam, lParam) );
+
+ case WM_SYSCOMMAND:
+
+ if (wParam == SC_CLOSE)
+ {
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+
+
+
+ }
+ return (FALSE);
+
+} /* DlgQuickW() */
+
+
+
+BOOL FAR PASCAL EXPORT DlgQuickInit(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ BOOL lookAround = TRUE;
+
+ // First, is there something to try and watch
+
+ *WatchVar = '\0';
+
+ if (Views[curView].Doc > -1)
+ {
+ if (hwndActiveEdit && GetCurrentText(curView,
+ &lookAround, (LPSTR)WatchVar,
+ MAX_USER_LINE, NULL, NULL) )
+ {
+ // Is what we got interesting?
+ pWatchVar = WatchVar;
+ while (whitespace(*pWatchVar)) pWatchVar++;
+ if (strlen(pWatchVar) > 0)
+ {
+ SetDlgItemText( hDlg, ID_QUICKW_MODIFY, pWatchVar);
+ AddCVWatch( pvitQuick, pWatchVar);
+ SendDlgItemMessage( hDlg, ID_QUICKW_LIST, WU_UPDATE, 0, 0);
+ }
+
+ }
+
+ }
+ else
+ {
+ SetDlgItemText( hDlg, ID_QUICKW_MODIFY, pWatchVar);
+ SetFocus (GetDlgItem (hDlg,ID_QUICKW_MODIFY));
+ }
+
+ EnableWindow (GetDlgItem (hDlg, ID_QUICKW_REM_LAST), FALSE);
+
+ return (TRUE);
+}
+
+
+BOOL FAR PASCAL EXPORT DlgQuickCommand(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ switch (wParam) {
+
+ case WM_KEYDOWN:
+ if (wParam == VK_RETURN)
+ {
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SETSEL,0,-1);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SCROLLCARET,0,-1);
+ SetFocus (GetDlgItem (hDlg,ID_QUICKW_MODIFY));
+ return(FALSE);
+ }
+ break;
+
+ case ID_QUICKW_MODIFY:
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SETSEL,0,-1);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SCROLLCARET,0,-1);
+ SetFocus (GetDlgItem (hDlg,ID_QUICKW_MODIFY));
+ break;
+
+
+ case ID_QUICKW_ZOOM:
+ if (pvitQuick == NULL)
+ return(FALSE);
+
+ pWatchVar = WatchVar;
+ GetDlgItemText( hDlg, ID_QUICKW_MODIFY, pWatchVar, MAX_USER_LINE);
+ while (whitespace(*pWatchVar)) pWatchVar++;
+ if (strlen(pWatchVar) == 0)
+ return(TRUE);
+
+ if ( pvitQuick->cln == 0)
+ pVib = AddCVWatch( pvitQuick, pWatchVar);
+ else
+ ReplaceCVWatch( pvitQuick, pvitQuick->pvibChild, pWatchVar);
+
+ SendDlgItemMessage( hDlg, ID_QUICKW_LIST, WU_UPDATE, 0, 0);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SETSEL,0,-1);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SCROLLCARET,0,-1);
+ SetFocus (GetDlgItem (hDlg,ID_QUICKW_MODIFY));
+ break;
+
+ case ID_QUICKW_ADD:
+
+ pWatchVar = WatchVar;
+ GetDlgItemText( hDlg, ID_QUICKW_MODIFY, pWatchVar, MAX_USER_LINE);
+ while (whitespace(*pWatchVar)) pWatchVar++;
+ if (strlen(pWatchVar) == 0) return(TRUE);
+
+ pVit = InitWatchVit();
+ pVib = AddCVWatch( pVit, pWatchVar);
+
+ if (GetWatchHWND() == NULL) {
+ SendMessage(hwndFrame, WM_COMMAND, IDM_WINDOW_WATCH, 0L);
+ }
+ else {
+ PostMessage( GetWatchHWND(), WU_UPDATE, 0, 0L);
+ }
+
+ SendDlgItemMessage( hDlg, ID_QUICKW_LIST, WU_UPDATE, 0, 0);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SETSEL,0,-1);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SCROLLCARET,0,-1);
+
+ EnableWindow (GetDlgItem (hDlg, ID_QUICKW_REM_LAST), TRUE);
+
+ SetFocus (GetDlgItem (hDlg,ID_QUICKW_MODIFY));
+
+ break;
+
+ case ID_QUICKW_REM_LAST:
+ if ( pVit != NULL)
+ {
+ DeleteCVWatch( pVit, pVib);
+ pVit = (PTRVIT) NULL;
+ PostMessage( GetWatchHWND(), WU_UPDATE, (WPARAM) TRUE, 0L);
+ SendDlgItemMessage( hDlg, ID_QUICKW_LIST, WU_DBG_UNLOADEE, 0, 0);
+ SendDlgItemMessage( hDlg, ID_QUICKW_LIST, WU_UPDATE, 0, 0);
+ Dbg(InitQuickVit());
+
+ pWatchVar = WatchVar;
+ GetDlgItemText( hDlg, ID_QUICKW_MODIFY, pWatchVar, MAX_USER_LINE);
+ while (whitespace(*pWatchVar)) pWatchVar++;
+ if (strlen(pWatchVar) == 0) return(TRUE);
+
+ if ( pvitQuick->cln == 0) {
+ pVib = AddCVWatch( pvitQuick, pWatchVar);
+ }
+ else {
+ ReplaceCVWatch( pvitQuick, pvitQuick->pvibChild, pWatchVar);
+ }
+
+ SendDlgItemMessage( hDlg, ID_QUICKW_LIST, WU_UPDATE, 0, 0);
+
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SETSEL,0,-1);
+ SendDlgItemMessage (hDlg,ID_QUICKW_MODIFY,EM_SCROLLCARET,0,-1);
+
+ EnableWindow (GetDlgItem (hDlg, ID_QUICKW_REM_LAST), FALSE);
+ SetFocus (GetDlgItem (hDlg,ID_QUICKW_MODIFY));
+ }
+ break;
+
+
+ case IDCANCEL:
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_QUICKW_HELP));
+ return TRUE;
+
+ }
+ return(FALSE);
+}
+
+
+/*** InitQuickVit
+**
+** Synopsis:
+** pVit = InitQuickVit()
+**
+** Entry:
+** None
+**
+** Returns:
+** Returns a pointer to the current vit (Allocating one if needed).
+** return NULL if can't
+**
+** Description:
+**
+** Creates the Vit (Variable Information Top) block for the
+** watch window
+**
+*/
+
+PTRVIT PASCAL InitQuickVit(void)
+{
+ if (pvitQuick == NULL) {
+ pvitQuick = calloc(1, sizeof(VIT));
+ }
+ return (pvitQuick);
+} /* InitWatchVit() */
+
+
+/*** QuickEditProc
+**
+** Synopsis:
+** long = QuickEditProc(hwnd, msg, wParam, lParam)
+**
+** Entry:
+** hwnd - handle to window to process message for
+** msg - message to be processed
+** wParam - information about message to be processed
+** lParam - information about message to be processed
+**
+** Returns:
+**
+** Description:
+** MDI function to handle Watch window messages
+**
+*/
+
+LONG FAR PASCAL LOADDS QuickEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HCURSOR hOldCursor = 0;
+
+ PPANE p = (PPANE)lParam;
+ PPANEINFO pInfo = (PPANEINFO)wParam;
+ PTRVIB pVib = NULL;
+
+ switch (msg) {
+
+ case WU_INITDEBUGWIN:
+
+ Dbg(InitQuickVit());
+ hWndQuick = hwnd;
+ UpdateQuickWatch(p, wParam);
+ break;
+
+ case WM_DESTROY:
+
+ hWndQuick = NULL; // Lose the Watch Window Handle
+ // No Break Intended
+
+ case WU_DBG_UNLOADEE:
+
+ if (pvitQuick != NULL)
+ {
+ // Lose the Watch Tree
+ if ( pvitQuick->pvibChild ) {
+ FTFreeAllSib(pvitQuick->pvibChild);
+ pvitQuick->pvibChild = NULL;
+ free(pvitQuick);
+ pvitQuick=NULL;
+ }
+
+ }
+ break;
+
+ case WU_INFO:
+ pInfo->NewText = FALSE;
+ pInfo->ReadOnly = TRUE;
+ pInfo->pFormat = NULL;
+
+ pVib = FTvibGetAtLine( pvitQuick, pInfo->ItemId);
+ if ( pVib == NULL) return(FALSE);
+
+ pInfo->pBuffer = FTGetPanelString( pvitQuick, pVib, pInfo->CtrlId);
+ return(TRUE);
+
+ case WU_EXPANDWATCH:
+
+ if ( FTExpand(pvitQuick, (ULONG)(wParam)) == OK) {
+ UpdateQuickWatch(p, wParam); // Watch Count changed
+ }
+ break;
+
+ case WU_UPDATE:
+ UpdateQuickWatch(p, wParam);
+ break;
+ }
+
+ return 0L;
+} /* WatchEditProc() */
+
+
+VOID UpdateQuickWatch(PPANE p, WPARAM wParam)
+{
+ LONG Len = 0;
+ LONG lLen = 0;
+ RECT Rect, tRect;
+ HWND hFoc;
+ HCURSOR hOldCursor, hWaitCursor;
+
+
+
+ // Set hourglass cursor
+ hWaitCursor = LoadCursor ((HANDLE)NULL, IDC_WAIT);
+ hOldCursor = SetCursor (hWaitCursor);
+
+
+ hFoc = GetFocus();
+
+
+ if ( pvitQuick == NULL )
+ {
+ InvalidateRect(p->hWndLeft, NULL, TRUE);
+ InvalidateRect(p->hWndButton, NULL, TRUE);
+ InvalidateRect(p->hWndRight, NULL, TRUE);
+ // Set original cursor
+ hOldCursor = SetCursor (hOldCursor);
+ return;
+ }
+ FTVerify(&CxfIp, pvitQuick->pvibChild);
+ pvitQuick->cxf = CxfIp;
+
+ Len = (LONG)pvitQuick->cln;
+
+ lLen = SendMessage(p->hWndLeft, LB_GETCOUNT, 0, 0L);
+ if ((lLen < Len) || (lLen == 0))
+ {
+ SendMessage(p->hWndLeft, LB_SETCOUNT, Len, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, Len, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, Len, 0);
+ }
+ else
+ {
+ SendMessage(p->hWndLeft, LB_SETCOUNT, (WPARAM) ((int)lLen), 0L);
+ SendMessage(p->hWndButton, LB_SETCOUNT, (WPARAM) ((int)lLen), 0L);
+ SendMessage(p->hWndRight, LB_SETCOUNT, (WPARAM) ((int)lLen), 0L);
+ }
+
+
+ p->MaxIdx = (WORD)Len;
+
+ // Reseting the count, lost where we were so put us back
+ PaneResetIdx(p, p->CurIdx);
+
+ PaneCaretNum(p);
+
+
+ if ((hFoc == p->hWndButton) || (hFoc == p->hWndLeft) || (hFoc == p->hWndRight))
+ {
+ SendMessage(p->hWndButton , LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect (p->hWndButton, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndButton, &tRect, TRUE);
+
+
+
+ SendMessage(p->hWndLeft , LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect (p->hWndLeft, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndLeft, &tRect, TRUE);
+
+
+ SendMessage(p->hWndRight , LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect (p->hWndRight, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndRight, &tRect, TRUE);
+
+
+ }
+
+
+ // Set original cursor
+ hOldCursor = SetCursor (hOldCursor);
+
+
+ CheckPaneScrollBar( p, (WORD)Len);
+
+
+
+
+}
+
+
+
+
diff --git a/private/windbg/windbg/re_mi.c b/private/windbg/windbg/re_mi.c
new file mode 100644
index 000000000..46469c9bb
--- /dev/null
+++ b/private/windbg/windbg/re_mi.c
@@ -0,0 +1,1110 @@
+/* re_mi.c - machine independent regular expression compiler
+ * cl /c /Zep /AM /NT RE /Gs /G2 /Oa /D LINT_ARGS /Fc re_mi.c
+ *
+ * Modifications:
+ * 09-Mar-1988 mz Add check in fREMtch for pat == NULL
+ * 15-Sep-1988 bw Change fREMatch to REMatch. New parameters and
+ * return type.
+ * 23-Nov-1989 bp Use relative adresses: OFST and PNTR macros
+ * 05-Feb-1991 mz Merge in KANJI changes
+ *
+ */
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#ifdef DBCS
+typedef unsigned short int CHAR_DBCS;
+#endif
+#if 0
+typedef unsigned short int DBCS;
+extern unsigned char REKTab[];
+extern unsigned char REBTab[];
+
+unsigned char *MovePBackwards (unsigned char *bos, unsigned char *P);
+#endif
+
+/* The following are dependent on the low-level representation of the compiled
+ * machine. The cases that have been implemented are:
+ *
+ * Simple interpreted machine
+ */
+
+/* pseudo-instruction definitions */
+
+#define I_CALL 0
+#define I_RETURN 1
+#define I_LETTER 2
+#define I_ANY 3
+#define I_EOL 4
+#define I_BOL 5
+#define I_CCL 6
+#define I_NCCL 7
+#define I_MATCH 8
+#define I_JMP 9
+#define I_SPTOM 10
+#define I_PTOM 11
+#define I_MTOP 12
+#define I_MTOSP 13
+#define I_FAIL 14
+#define I_PUSHP 15
+#define I_PUSHM 16
+#define I_POPP 17
+#define I_POPM 18
+#define I_PNEQM 19
+#define I_ITOM 20
+#define I_PREV 21
+
+/* instruction templates and lengths */
+
+#if defined(DBCS)
+#define LLETTER 3
+#else
+#define LLETTER 2
+#endif
+#define LANY 1
+#define LBOL 1
+#define LEOL 1
+
+/* address part of instruction */
+
+#define ADDR(ip) (*(RE_OPCODE **)(ip+sizeof(RE_OPCODE)))
+
+/* conversion macros for adresses */
+
+#define OFST(p) ((RE_OPCODE *) (((char *) p) - ((char *) REPat)))
+#define PNTR(p) ((RE_OPCODE *) (((char *) REPat) + ((unsigned) p)))
+
+#define IMM(ip) (*(RE_OPCODE **)(ip+sizeof(RE_OPCODE)+sizeof(RE_OPCODE *)))
+
+#if defined(DBCS)
+#define LRANGE (sizeof(RE_OPCODE)+sizeof(RE_OPCODE)+sizeof(RE_OPCODE)+sizeof(RE_OPCODE))
+#define LCCL (sizeof(RE_OPCODE))
+#define LNCCL (sizeof(RE_OPCODE))
+#else
+#define LCCL (sizeof(RE_OPCODE)+(256/8))
+#define LNCCL (sizeof(RE_OPCODE)+(256/8))
+#endif
+
+#define LOFFSET sizeof(RE_OPCODE *)
+#define LCALL (sizeof(RE_OPCODE)+LOFFSET)
+#define LJMP (sizeof(RE_OPCODE)+LOFFSET)
+#define LSPTOM (sizeof(RE_OPCODE)+LOFFSET)
+#define LPTOM (sizeof(RE_OPCODE)+LOFFSET)
+#define LMTOP (sizeof(RE_OPCODE)+LOFFSET)
+#define LMTOSP (sizeof(RE_OPCODE)+LOFFSET)
+#define LRETURN sizeof(RE_OPCODE)
+#define LMATCH sizeof(RE_OPCODE)
+#define LFAIL sizeof(RE_OPCODE)
+#define LPUSHM (sizeof(RE_OPCODE)+LOFFSET)
+#define LPOPM (sizeof(RE_OPCODE)+LOFFSET)
+#define LPUSHP sizeof(RE_OPCODE)
+#define LPOPP sizeof(RE_OPCODE)
+#define LPNEQM (sizeof(RE_OPCODE)+LOFFSET)
+#define LITOM (sizeof(RE_OPCODE)+LOFFSET+LOFFSET)
+#define LPREV (sizeof(RE_OPCODE)+sizeof(RE_OPCODE))
+
+/* action templates */
+
+typedef struct {
+ RE_OPCODE i1[LCALL]; /* CALL pattern */
+ RE_OPCODE i2[LFAIL]; /* FAIL */
+ } T_PROLOG; /* pattern: */
+
+typedef struct {
+ RE_OPCODE i1[LPTOM]; /* PTOM ArgBeg[cArg] */
+ RE_OPCODE i2[LCALL]; /* CALL x */
+ RE_OPCODE i3[LITOM]; /* ITOM ArgBeg[cArg],-1 */
+ RE_OPCODE i4[LRETURN]; /* RETURN */
+ } T_LEFTARG; /* x: */
+
+typedef struct {
+ RE_OPCODE i1[LPTOM]; /* PTOM ArgEnd[cArg] */
+ } T_RIGHTARG;
+
+typedef struct {
+ RE_OPCODE i1[LPUSHM]; /* PUSHM tmp */
+ RE_OPCODE i2[LCALL]; /* CALL l1 */
+ RE_OPCODE i3[LPOPM]; /* POPM tmp */
+ RE_OPCODE i4[LRETURN]; /* RETURN */
+ RE_OPCODE tmp[LOFFSET]; /* tmp DW */
+ RE_OPCODE i6[LPUSHP]; /* l1: PUSHP */
+ RE_OPCODE i7[LCALL]; /* CALL y */
+ RE_OPCODE i8[LPOPP]; /* POPP */
+ RE_OPCODE i9[LPTOM]; /* PTOM tmp */
+ } T_SMSTAR; /* x: ... */
+
+typedef struct {
+ RE_OPCODE i1[LPNEQM]; /* PNEQM tmp */
+ RE_OPCODE i2[LJMP]; /* JMP l1 */
+ } T_SMSTAR1; /* y: ... */
+
+typedef struct {
+ RE_OPCODE i1[LPUSHM]; /* l1: PUSHM tmp */
+ RE_OPCODE i2[LPTOM]; /* PTOM tmp */
+ RE_OPCODE i3[LPUSHP]; /* PUSHP */
+ RE_OPCODE i4[LCALL]; /* CALL x */
+ RE_OPCODE i5[LPOPP]; /* POPP */
+ RE_OPCODE i6[LPOPM]; /* POPM tmp */
+ RE_OPCODE i7[LJMP]; /* JMP y */
+ RE_OPCODE tmp[LOFFSET]; /* tmp DW */
+ } T_STAR; /* x: ... */
+
+typedef struct {
+ RE_OPCODE i1[LPNEQM]; /* PNEQM tmp */
+ RE_OPCODE i2[LPTOM]; /* PTOM tmp */
+ RE_OPCODE i3[LJMP]; /* JMP l1 */
+ } T_STAR1; /* y: ... */
+
+typedef struct {
+ RE_OPCODE i1[LANY]; /* ANY */
+ } T_ANY;
+
+typedef struct {
+ RE_OPCODE i1[LBOL]; /* BOL */
+ } T_BOL;
+
+typedef struct {
+ RE_OPCODE i1[LEOL]; /* EOL */
+ } T_EOL;
+
+typedef struct {
+ RE_OPCODE i1[LSPTOM]; /* SPTOM tmp */
+ RE_OPCODE i2[LPTOM]; /* PTOM tmp1 */
+ RE_OPCODE i3[LCALL]; /* CALL x */
+ RE_OPCODE i4[LMTOP]; /* MTOP tmp1 */
+ RE_OPCODE i5[LJMP]; /* JMP y */
+ RE_OPCODE tmp[LOFFSET]; /* tmp DW */
+ RE_OPCODE tmp1[LOFFSET]; /* tmp1 DW */
+ } T_NOTSIGN; /* x: ... */
+
+typedef struct {
+ RE_OPCODE i1[LMTOSP]; /* MTOSP tmp */
+ RE_OPCODE i2[LMTOP]; /* MTOP tmp1 */
+ RE_OPCODE i3[LRETURN]; /* RETURN */
+ } T_NOTSIGN1; /* y: ... */
+
+typedef struct {
+ RE_OPCODE i1[LLETTER]; /* LETTER c */
+ } T_LETTER;
+
+typedef struct {
+ RE_OPCODE i1[LPUSHP]; /* ln: PUSHP */
+ RE_OPCODE i2[LCALL]; /* CALL cn */
+ RE_OPCODE i3[LPOPP]; /* POPP */
+ RE_OPCODE i4[LJMP]; /* JMP ln+1 */
+ } T_LEFTOR; /* cn: ... */
+
+typedef struct {
+ RE_OPCODE i1[LJMP]; /* JMP y */
+ } T_ORSIGN;
+
+typedef struct {
+ RE_OPCODE i1[LRETURN]; /* cn+1:RETURN */
+ } T_RIGHTOR; /* y: ... */
+
+typedef struct {
+ RE_OPCODE i1[LCCL]; /* CCL <bits> */
+ } T_CCL;
+
+typedef struct {
+ RE_OPCODE i1[LMATCH]; /* MATCH */
+ } T_EPILOG;
+
+typedef struct {
+ RE_OPCODE i1[LPREV]; /* PREV n */
+ } T_PREV;
+
+#if defined(DBCS)
+typedef struct {
+ RE_OPCODE i1[LRANGE]; /* x1:x2 - y1:y2 */
+ } T_RANGE;
+#endif
+
+typedef union {
+ T_PROLOG U_PROLOG;
+ T_LEFTARG U_LEFTARG;
+ T_RIGHTARG U_RIGHTARG;
+ T_SMSTAR U_SMSTAR;
+ T_SMSTAR1 U_SMSTAR1;
+ T_STAR U_STAR;
+ T_STAR1 U_STAR1;
+ T_ANY U_ANY;
+ T_BOL U_BOL;
+ T_EOL U_EOL;
+ T_NOTSIGN U_NOTSIGN;
+ T_NOTSIGN1 U_NOTSIGN1;
+ T_LETTER U_LETTER;
+ T_LEFTOR U_LEFTOR;
+ T_ORSIGN U_ORSIGN;
+ T_RIGHTOR U_RIGHTOR;
+ T_CCL U_CCL;
+ T_EPILOG U_EPILOG;
+ T_PREV U_PREV;
+#if defined(DBCS)
+ T_RANGE U_RANGE;
+#endif
+ } template ;
+
+/* size of each compiled action */
+
+int cbIns[] = {
+/* PROLOG 0 */ sizeof (T_PROLOG ),
+/* LEFTARG 1 */ sizeof (T_LEFTARG ),
+/* RIGHTARG 2 */ sizeof (T_RIGHTARG ),
+/* SMSTAR 3 */ sizeof (T_SMSTAR ),
+/* SMSTAR1 4 */ sizeof (T_SMSTAR1 ),
+/* STAR 5 */ sizeof (T_STAR ),
+/* STAR1 6 */ sizeof (T_STAR1 ),
+/* ANY 7 */ sizeof (T_ANY ),
+/* BOL 8 */ sizeof (T_BOL ),
+/* EOL 9 */ sizeof (T_EOL ),
+/* NOTSIGN 10 */ sizeof (T_NOTSIGN ),
+/* NOTSIGN1 11 */ sizeof (T_NOTSIGN1 ),
+/* LETTER 12 */ sizeof (T_LETTER ),
+/* LEFTOR 13 */ sizeof (T_LEFTOR ),
+/* ORSIGN 14 */ sizeof (T_ORSIGN ),
+/* RIGHTOR 15 */ sizeof (T_RIGHTOR ),
+/* CCLBEG 16 */ sizeof (T_CCL ),
+/* CCLNOT 17 */ sizeof (T_CCL ),
+/* RANGE 18 */ 0,
+/* EPILOG 19 */ sizeof (T_EPILOG ),
+/* PREV 20 */ sizeof (T_PREV ),
+#if defined(DBCS)
+/* RANGEDBCS1 21 */ sizeof (T_RANGE ),
+/* RANGEDBCS2 22 */ 0,
+#endif
+ 0
+ };
+
+#if DEBUG
+#define DEBOUT(x) printf x;
+#else
+#define DEBOUT(x)
+#endif
+
+
+
+#if defined (DBCS)
+/* MovePBackwards - Move P backwards
+ *
+ *
+ */
+unsigned char *MovePBackwards (bos, P)
+unsigned char *bos;
+unsigned char *P;
+{
+ unsigned char *P1;
+
+ if (P - 1 <= bos)
+ return bos;
+
+ P1 = P - 2;
+ while (TRUE) {
+ if ( P1 == bos || !IsDBCSLeadByte(*P1) )
+ break;
+ P1--;
+ }
+
+ if (IsDBCSLeadByte(*P1))
+ P1--;
+
+ return P - 1 - ((P - P1) % 2);
+}
+
+#endif
+
+
+/* REMatch - enumerate all matches of a pattern onto a string
+ *
+ * pat compiled pattern (gotten from RECompile)
+ * bos pointer to beginning of string to scan
+ * str pointer to into bos of place to begin scan
+ * fFor direction to move on unsuccessful compares (for <msearch> in Z)
+ *
+ * REMatch returns 0 if a match was found. Otherwise it returns a non-zero
+ * error code.
+ *
+ * REMatch interprets the compiled patching machine in the pattern.
+ */
+int REMatch (pat, bos, str, Stack, MaxREStack, fFor)
+struct patType *pat;
+char *bos;
+char *str;
+RE_OPCODE *Stack[]; /* simulated stack */
+unsigned MaxREStack;
+flagType fFor;
+{
+ RE_OPCODE **SP; /* top of stack */
+ register RE_OPCODE *IP; /* current instruction to execute */
+ register unsigned char *P; /* pointer to next char to match */
+ RE_OPCODE C;
+#if defined(DBCS)
+ unsigned short U;
+ int fMatched;
+#endif
+ int i, n;
+ RE_OPCODE **StackEnd = & Stack[MaxREStack-sizeof(Stack[0])];
+ int (_CRTAPI1 * pfncomp) (const char *, const char *, size_t);
+
+ if ((REPat = pat) == NULL)
+ return REM_INVALID;
+
+ pfncomp = REPat->fCase ? strncmp : _strnicmp;
+
+ /* initialize the machine */
+ Fill ((char far *) REPat->pArgBeg, -1, sizeof (REPat->pArgBeg));
+ REPat->pArgBeg[0] = P = str;
+
+ /* begin this instance of the machine */
+ SP = &Stack[-1];
+ IP = REPat->code;
+
+ while (TRUE) {
+ DEBOUT (("%04x/%04x/%04x ", IP, SP-&Stack[0], P));
+ /* execute instruction */
+ switch (*IP) {
+ /* call a subroutine */
+ case I_CALL:
+ if (SP >= StackEnd)
+ return REM_STKOVR;
+ *++SP = IP + LCALL;
+ IP = PNTR (ADDR (IP));
+ DEBOUT (("CALL %04x\n", IP));
+ break;
+
+ /* return from a subroutine */
+ case I_RETURN:
+ DEBOUT (("RETURN\n"));
+ IP = *SP--;
+ break;
+
+ /* match a character, fail if no match */
+ case I_LETTER:
+#if defined(DBCS)
+ if (IsDBCSLeadByte(*P)) {
+ if (*(CHAR_DBCS *)P == *(CHAR_DBCS *)(IP+1))
+ IP += LLETTER;
+ else
+ IP = *SP--;
+ P += 2;
+ }
+ else {
+ C = REPat->fCase ? *P++ : XLTab[*P++];
+ if (C == IP[1])
+ IP += LLETTER;
+ else
+ IP = *SP--;
+ }
+#else
+
+ C = REPat->fCase ? *P++ : XLTab[*P++];
+ DEBOUT (("LETTER %c\n", IP[1]));
+ if (C == IP[1])
+ IP += LLETTER;
+ else
+ IP = *SP--;
+#endif
+ break;
+
+ /* match any character, fail if no match */
+ case I_ANY:
+ DEBOUT (("ANY\n"));
+#if defined(DBCS)
+ if (*P != '\0') {
+ if (IsDBCSLeadByte(*P))
+ P++;
+ IP += LANY;
+ }
+ else
+ IP = *SP--;
+ P++;
+#else
+ if (*P++ != '\0')
+ IP += LANY;
+ else
+ IP = *SP--;
+#endif
+ break;
+
+ /* match end of line, fail if no match */
+ case I_EOL:
+ DEBOUT (("EOL\n"));
+ if (*P == '\0')
+ IP += LEOL;
+ else
+ IP = *SP--;
+ break;
+
+ /* match beginning of line, fail if no match */
+ case I_BOL:
+ DEBOUT (("BOL\n"));
+ if (P == bos)
+ IP += LBOL;
+ else
+ IP = *SP--;
+ break;
+
+ /* handle character class, fail if no match */
+ case I_CCL:
+#if defined(DBCS)
+ IP += LCCL;
+ fMatched = FALSE;
+ U = REPat->fCase ? *P++ : (unsigned char)XLTab[*P++];
+ if (IsDBCSLeadByte((BYTE)U))
+ U = (U << 8) + *P++;
+ if (C == '\0') {
+ IP = *SP--;
+ break;
+ }
+#define USIP ((unsigned short *)IP)
+#define CLOW (USIP[0])
+#define CHIGH (USIP[1])
+ while (CLOW != 0) {
+ fMatched |= (CLOW <= U) && (U <= CHIGH);
+ IP += LRANGE;
+ }
+ IP += LRANGE;
+#undef USIP
+#undef CLOW
+#undef CHIGH
+ if (!fMatched)
+ IP = *SP--;
+
+#else
+ C = REPat->fCase ? *P++ : XLTab[*P++];
+ DEBOUT (("CCL %c\n", C));
+ if (C != '\0' && (IP[1 + (C >> 3)] & (1 << (C & 7))) != 0)
+ IP += LCCL;
+ else
+ IP = *SP--;
+#endif
+ break;
+
+ /* handle not character class, fail if match */
+ case I_NCCL:
+#if defined(DBCS)
+ IP += LCCL;
+ fMatched = FALSE;
+ U = REPat->fCase ? *P++ : (unsigned char)XLTab[*P++];
+ if (IsDBCSLeadByte((BYTE)U))
+ U = (U << 8) + *P++;
+ if (C == '\0') {
+ IP = *SP--;
+ break;
+ }
+#define USIP ((unsigned short *)IP)
+#define CLOW (USIP[0])
+#define CHIGH (USIP[1])
+ while (CLOW != 0) {
+ fMatched |= (CLOW <= U) && (U <= CHIGH);
+ IP += LRANGE;
+ }
+ IP += LRANGE;
+#undef USIP
+#undef CLOW
+#undef CHIGH
+ if (fMatched)
+ IP = *SP--;
+
+#else
+ DEBOUT (("NCCL %c\n", C));
+ C = REPat->fCase ? *P++ : XLTab[*P++];
+ if (C != '\0' && (IP[1 + (C >> 3)] & (1 << (C & 7))) == 0)
+ IP += LNCCL;
+ else
+ IP = *SP--;
+#endif
+ break;
+
+ /* signal a match */
+ case I_MATCH:
+ DEBOUT (("MATCH\n"));
+ REPat->pArgEnd[0] = P;
+ return REM_MATCH;
+
+ /* jump to an instruction */
+ case I_JMP:
+ IP = PNTR (ADDR (IP));
+ DEBOUT (("JMP %04x\n", IP));
+ break;
+
+ /* save the character pointer in a memory location */
+ case I_PTOM:
+ DEBOUT (("PTOM %04x\n", PNTR (ADDR(IP))));
+ * ((unsigned char **) PNTR (ADDR (IP))) = P;
+ IP += LPTOM;
+ break;
+
+ /* restore the character pointer from a memory location */
+ case I_MTOP:
+ DEBOUT (("MTOP %04x\n", PNTR (ADDR(IP))));
+ P = * ((unsigned char **) PNTR (ADDR (IP)));
+ IP += LMTOP;
+ break;
+
+ /* save the stack pointer in a memory location */
+ case I_SPTOM:
+ DEBOUT (("SPTOM %04x\n", PNTR (ADDR(IP))));
+ * ((RE_OPCODE ***) PNTR (ADDR (IP))) = SP;
+ IP += LSPTOM;
+ break;
+
+ /* restore the stack pointer from a memory location */
+ case I_MTOSP:
+ DEBOUT (("MTOSP %04x\n", PNTR (ADDR (IP))));
+ SP = * ((RE_OPCODE ***) PNTR (ADDR (IP)));
+ IP += LMTOSP;
+ break;
+
+ /* push the char pointer */
+ case I_PUSHP:
+ DEBOUT (("PUSHP\n"));
+ if (SP >= StackEnd)
+ return REM_STKOVR;
+ *++SP = (RE_OPCODE *) P;
+ IP++;
+ break;
+
+ /* pop the char pointer */
+ case I_POPP:
+ DEBOUT (("POPP\n"));
+ P = (unsigned char *) (*SP--);
+ IP ++;
+ break;
+
+ /* push memory */
+ case I_PUSHM:
+ DEBOUT (("PUSHM %04x\n", PNTR (ADDR (IP))));
+ if (SP >= StackEnd)
+ return REM_STKOVR;
+ *++SP = * ((RE_OPCODE **) PNTR (ADDR (IP)));
+ IP += LPUSHM;
+ break;
+
+ /* pop memory */
+ case I_POPM:
+ DEBOUT (("POPM %04x\n", PNTR (ADDR (IP))));
+ * ((RE_OPCODE **) PNTR (ADDR (IP))) = *SP--;
+ IP += LPOPM;
+ break;
+
+ /* make sure that the char pointer P is != memory, fail if necessary */
+ case I_PNEQM:
+ DEBOUT (("PNEQM %04x\n", PNTR (ADDR (IP))));
+ if (P != * ((unsigned char **) PNTR (ADDR (IP))))
+ IP += LPNEQM;
+ else
+ IP = *SP--;
+ break;
+
+ /* move an immediate value to memory */
+ case I_ITOM:
+ DEBOUT (("ITOM %04x,%04x\n", PNTR (ADDR (IP)), IMM(IP)));
+ * ((RE_OPCODE **) PNTR (ADDR (IP))) = IMM (IP);
+ IP += LITOM;
+ break;
+
+ /* indicate a fail on the total match */
+ case I_FAIL:
+ DEBOUT (("FAIL\n"));
+ P = REPat->pArgBeg[0];
+#if defined(DBCS)
+ if (fFor) {
+ if (IsDBCSLeadByte(*P))
+ P++;
+ if (*P++ == '\0')
+ return REM_NOMATCH;
+ else
+ ;
+ }
+ else
+ if (P == bos)
+ return REM_NOMATCH;
+ else
+ P = MovePBackwards (bos, P);
+
+#else
+ if (fFor)
+ if (*P++ == '\0')
+ return REM_NOMATCH;
+ else
+ ;
+ else
+ if (P-- == bos)
+ return REM_NOMATCH;
+#endif
+
+ REPat->pArgBeg[0] = P;
+ SP = &Stack[-1];
+ IP = REPat->code;
+ break;
+
+ /* perform a match with a previously matched item */
+ case I_PREV:
+ i = IP[1];
+ n = REPat->pArgEnd[i] - REPat->pArgBeg[i];
+ DEBOUT (("PREV %04x\n", i));
+ if (REPat->pArgBeg[i] == (char *) -1)
+ IP = *SP--;
+ else
+ if ((*pfncomp) (REPat->pArgBeg[i], P, n))
+ IP = *SP--;
+ else {
+ IP += LPREV;
+ P += n;
+ }
+ break;
+ default:
+ return REM_UNDEF;
+
+ }
+ }
+}
+
+void pascal INTERNAL REStackOverflow ()
+{
+ InternalErrorBox(SYS_RegExpr_StackOverflow);
+}
+
+/* CompileAction - drop in the compilation template at a particular node
+ * in the tree. Continuation appropriate to a node occurs by relying on
+ * passed input and past input (yuk, yuk).
+ *
+ * type type of action being performed
+ * u previous return value. Typically points to a previous
+ * template that needs to be linked together.
+ * x low byte of a range
+ * y high range of a range.
+ *
+ * Returns variable depending on action required.
+ *
+ */
+unsigned INTERNAL CompileAction (type, u, x, y)
+OPTYPE type;
+register unsigned int u;
+unsigned char x, y;
+{
+ register template *t = (template *) REip;
+ unsigned u1, u2, u3;
+
+ DEBOUT (("%04x CompileAction %04x\n", REip, type));
+
+ REip += cbIns[type];
+
+ switch (type) {
+
+ case PROLOG:
+#define ip (&(t->U_PROLOG))
+ ip->i1[0] = I_CALL; ADDR(ip->i1) = OFST (REip);
+ ip->i2[0] = I_FAIL;
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case LEFTARG:
+#define ip (&(t->U_LEFTARG))
+ ip->i1[0] = I_PTOM;
+ ADDR(ip->i1) = OFST ((RE_OPCODE *) &(REPat->pArgBeg[REArg]));
+ ip->i2[0] = I_CALL; ADDR(ip->i2) = OFST (REip);
+ ip->i3[0] = I_ITOM;
+ ADDR(ip->i3) = OFST ((RE_OPCODE *) &(REPat->pArgBeg[REArg]));
+ IMM(ip->i3) = (RE_OPCODE *) -1;
+ ip->i4[0] = I_RETURN;
+ return (unsigned) REArg++;
+#undef ip
+ break;
+
+ case RIGHTARG:
+#define ip (&(t->U_RIGHTARG))
+ ip->i1[0] = I_PTOM;
+ ADDR(ip->i1) = OFST ((RE_OPCODE *) &(REPat->pArgEnd[u]));
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case SMSTAR:
+#define ip (&(t->U_SMSTAR))
+ return (unsigned) ip;
+#undef ip
+ break;
+
+ case SMSTAR1:
+#define ip ((T_SMSTAR *)u)
+#define ip2 (&(t->U_SMSTAR1))
+ ip->i1[0] = I_PUSHM; ADDR(ip->i1) = OFST (ip->tmp);
+ ip->i2[0] = I_CALL; ADDR(ip->i2) = OFST (ip->i6);
+ ip->i3[0] = I_POPM; ADDR(ip->i3) = OFST (ip->tmp);
+ ip->i4[0] = I_RETURN;
+ /* DW */
+ ip->i6[0] = I_PUSHP;
+ ip->i7[0] = I_CALL; ADDR(ip->i7) = OFST (REip);
+ ip->i8[0] = I_POPP;
+ ip->i9[0] = I_PTOM; ADDR(ip->i9) = OFST (ip->tmp);
+
+ ip2->i1[0] = I_PNEQM; ADDR(ip2->i1) = OFST (ip->tmp);
+ ip2->i2[0] = I_JMP; ADDR(ip2->i2) = OFST (ip->i6);
+ return (unsigned) NULL;
+#undef ip
+#undef ip2
+ break;
+
+ case STAR:
+#define ip (&(t->U_STAR))
+ return (unsigned) ip;
+#undef ip
+ break;
+
+ case STAR1:
+#define ip ((T_STAR *)u)
+#define ip2 (&(t->U_STAR1))
+ ip->i1[0] = I_PUSHM; ADDR(ip->i1) = OFST (ip->tmp);
+ ip->i2[0] = I_PTOM; ADDR(ip->i2) = OFST (ip->tmp);
+ ip->i3[0] = I_PUSHP;
+ ip->i4[0] = I_CALL; ADDR(ip->i4) = OFST (((RE_OPCODE *)ip) + sizeof (*ip));
+ ip->i5[0] = I_POPP;
+ ip->i6[0] = I_POPM; ADDR(ip->i6) = OFST (ip->tmp);
+ ip->i7[0] = I_JMP; ADDR(ip->i7) = OFST (REip);
+
+ ip2->i1[0] = I_PNEQM; ADDR(ip2->i1) = OFST (ip->tmp);
+ ip2->i2[0] = I_PTOM; ADDR(ip2->i2) = OFST (ip->tmp);
+ ip2->i3[0] = I_JMP; ADDR(ip2->i3) = OFST (ip->i1);
+ return (unsigned) NULL;
+#undef ip
+#undef ip2
+ break;
+
+ case ANY:
+#define ip (&(t->U_ANY))
+ ip->i1[0] = I_ANY;
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case BOL:
+#define ip (&(t->U_BOL))
+ ip->i1[0] = I_BOL;
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case EOL:
+#define ip (&(t->U_EOL))
+ ip->i1[0] = I_EOL;
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case NOTSIGN:
+#define ip (&(t->U_NOTSIGN))
+ return (unsigned) ip;
+#undef ip
+ break;
+
+ case NOTSIGN1:
+#define ip ((T_NOTSIGN *)u)
+#define ip2 (&(t->U_NOTSIGN1))
+ ip->i1[0] = I_SPTOM; ADDR(ip->i1) = OFST (ip->tmp);
+ ip->i2[0] = I_PTOM; ADDR(ip->i2) = OFST (ip->tmp1);
+ ip->i3[0] = I_CALL; ADDR(ip->i3) = OFST (((RE_OPCODE *)ip) + sizeof (*ip));
+ ip->i4[0] = I_MTOP; ADDR(ip->i4) = OFST (ip->tmp1);
+ ip->i5[0] = I_JMP; ADDR(ip->i5) = OFST (REip);
+
+ ip2->i1[0] = I_MTOSP; ADDR(ip2->i1) = OFST (ip->tmp);
+ ip2->i2[0] = I_MTOP; ADDR(ip2->i2) = OFST (ip->tmp1);
+ ip2->i3[0] = I_RETURN;
+ return (unsigned) NULL;
+#undef ip
+#undef ip2
+ break;
+
+ case LETTER:
+#define ip (&(t->U_LETTER))
+ if (!REPat->fCase)
+ x = XLTab[x];
+ ip->i1[0] = I_LETTER; ip->i1[1] = (RE_OPCODE) x;
+#if defined(DBCS)
+ ip->i1[2] = (RE_OPCODE) y;
+#endif
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case LEFTOR:
+#define ip (&(t->U_LEFTOR))
+ * (unsigned *) ip = u;
+ return (unsigned) ip;
+#undef ip
+ break;
+
+ case ORSIGN:
+#define ip (&(t->U_ORSIGN))
+ * (unsigned *) ip = u;
+ return (unsigned) ip;
+#undef ip
+ break;
+
+ case RIGHTOR:
+ u1 = u;
+ u2 = (unsigned int) t;
+ u = * (unsigned *) u1;
+ while (u1 != (unsigned) NULL) {
+ u3 = * (unsigned *) u;
+ /* u points to leftor
+ * u1 points to orsign
+ * u2 points to next leftor
+ * u3 points to previous orsign
+ */
+#define ip (&(((template *)u)->U_LEFTOR))
+ ip->i1[0] = I_PUSHP;
+ ip->i2[0] = I_CALL; ADDR (ip->i2) = OFST (((RE_OPCODE *)ip) + sizeof (*ip));
+ ip->i3[0] = I_POPP;
+ ip->i4[0] = I_JMP; ADDR (ip->i4) = OFST ((RE_OPCODE *) u2);
+#undef ip
+#define ip (&(((template *)u1)->U_ORSIGN))
+ ip->i1[0] = I_JMP; ADDR (ip->i1) = OFST (REip);
+#undef ip
+ u2 = u;
+ u1 = u3;
+ u = * (unsigned *) u1;
+ }
+#define ip (&(t->U_RIGHTOR))
+ ip->i1[0] = I_RETURN;
+#undef ip
+ return (unsigned) NULL;
+ break;
+
+ case CCLBEG:
+#define ip (&(t->U_CCL))
+#if defined(DBCS)
+ ip->i1[0] = I_CCL;
+ return (unsigned) NULL;
+
+#else
+ Fill ((char far *) ip->i1, 0, sizeof (ip->i1));
+ ip->i1[0] = I_CCL;
+ return (unsigned) ip;
+#endif
+#undef ip
+ break;
+
+
+ case CCLNOT:
+#define ip (&(t->U_CCL))
+#if defined(DBCS)
+ ip->i1[0] = I_NCCL;
+ return (unsigned) ip;
+#else
+ Fill ((char far *) ip->i1, 0, sizeof (ip->i1));
+ ip->i1[0] = I_NCCL;
+ return (unsigned) ip;
+#endif
+#undef ip
+ break;
+
+#if defined(DBCS)
+ case RANGEDBCS1:
+#define ip (&(t->U_RANGE))
+ ip->i1[0] = (REPat->fCase || x) ? y : XLTab[y];
+ ip->i1[1] = x;
+ return (unsigned) ip;
+#undef ip
+ break;
+
+ case RANGEDBCS2:
+#define ip ((T_RANGE *)u)
+ ip->i1[2] = (REPat->fCase || x) ? y : XLTab[y];
+ ip->i1[3] = x;
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+#else
+ case RANGE:
+#define ip ((T_CCL *)u)
+ {
+ unsigned char ch;
+
+ for (ch = x; ch <= y; ch++) {
+ x = REPat->fCase ? (unsigned char) ch : XLTab[ch];
+ ip->i1[1 + (x >> 3)] |= 1 << (x & 7);
+ }
+ return (unsigned) NULL;
+ }
+#undef ip
+ break;
+
+#endif
+
+ case EPILOG:
+#define ip (&(t->U_EPILOG))
+ ip->i1[0] = I_MATCH;
+ return (unsigned) NULL;
+#undef ip
+ break;
+
+ case PREV:
+#define ip (&(t->U_PREV))
+ ip->i1[0] = I_PREV;
+ ip->i1[1] = (RE_OPCODE) u;
+ return (unsigned) NULL;
+#undef ip
+
+ default:
+ InternalErrorBox(SYS_RegExpr_CompileAction);
+ return (unsigned) NULL;
+ }
+}
+
+#if DEBUG
+void INTERNAL REDump (p)
+struct patType *p;
+{
+ RE_OPCODE *REip = p->code;
+
+ while (TRUE) {
+ printf ("%04x ", REip);
+ switch (*REip) {
+ case I_CALL:
+ printf ("CALL %04x\n", ADDR(REip));
+ REip += LCALL;
+ break;
+ case I_RETURN:
+ printf ("RETURN\n");
+ REip += LRETURN;
+ break;
+ case I_LETTER:
+ printf ("LETTER %c", REip[1]);
+ REip += LLETTER;
+ break;
+ case I_ANY:
+ printf ("ANY\n");
+ REip += LANY;
+ break;
+ case I_EOL:
+ printf ("EOL\n");
+ REip += LEOL;
+ break;
+ case I_BOL:
+ printf ("BOL\n");
+ REip += LBOL;
+ break;
+ case I_CCL:
+ printf ("CCL\n");
+ REip += LCCL;
+ break;
+ case I_NCCL:
+ printf ("NCCL\n");
+ REip += LNCCL;
+ break;
+ case I_MATCH:
+ printf ("MATCH\n");
+ return;
+ break;
+ case I_JMP:
+ printf ("JMP %04x\n", ADDR(REip));
+ REip += LJMP;
+ break;
+ case I_SPTOM:
+ printf ("SPTOM %04x\n", ADDR(REip));
+ REip += LSPTOM;
+ break;
+ case I_PTOM:
+ printf ("PTOM %04x\n", ADDR(REip));
+ REip += LPTOM;
+ break;
+ case I_MTOP:
+ printf ("MTOP %04x\n", ADDR(REip));
+ REip += LMTOP;
+ break;
+ case I_MTOSP:
+ printf ("MTOSP %04x\n", ADDR(REip));
+ REip += LMTOSP;
+ break;
+ case I_FAIL:
+ printf ("FAIL\n");
+ REip += LFAIL;
+ break;
+ case I_PUSHP:
+ printf ("PUSHP\n");
+ REip += LPUSHP;
+ break;
+ case I_PUSHM:
+ printf ("PUSHM %04x\n", ADDR(REip));
+ REip += LPUSHM;
+ break;
+ case I_POPP:
+ printf ("POPP\n");
+ REip += LPOPP;
+ break;
+ case I_POPM:
+ printf ("POPM %04x\n", ADDR(REip));
+ REip += LPOPM;
+ break;
+ case I_PNEQM:
+ printf ("PNEQM %04x\n", ADDR(REip));
+ REip += LPNEQM;
+ break;
+ case I_ITOM:
+ printf ("ITOM %04x,%04x\n", ADDR(REip), IMM(REip));
+ REip += LITOM;
+ break;
+ default:
+ printf ("%04x ???\n", *REip);
+ REip += LOFFSET;
+ return;
+ }
+ }
+}
+#endif
+
+/* EstimateAction - sum up the number of bytes required by each individual
+ * parsing action in the tree. Take the input action and add it up to the
+ * running total.
+ *
+ * type type of action being performed
+ * u dummy parm
+ * x dummy parm
+ * y dummy parm
+ *
+ * Returns 0 always
+ *
+ */
+unsigned INTERNAL EstimateAction (type, u, x, y)
+OPTYPE type;
+unsigned int u;
+unsigned char x, y;
+{
+ u; x; y;
+
+ DEBOUT (("%04x EstimateAction %04x\n", RESize, type));
+
+ if (type < ACTIONMIN || type > ACTIONMAX)
+ InternalErrorBox(SYS_RegExpr_EstimateAction);
+ RESize += cbIns[type];
+ return (unsigned) 0;
+}
+
+/* REEstimate - estimates the number of bytes required to
+ * compile a specified pattern.
+ *
+ * REEstimate sets RESize to the number of bytes required to compile
+ * a pattern. If there is a syntax error in the pattern, RESize is set
+ * to -1.
+ *
+ * p character pointer to pattern that will be compiled
+ */
+void pascal INTERNAL REEstimate (p)
+char *p;
+{
+ RESize = sizeof (struct patType) - 1;
+ REArg = 1;
+
+ EstimateAction (PROLOG, (unsigned int) 0, '\0', '\0');
+
+ if (REParseRE (EstimateAction, p, NULL) == NULL || REArg > MAXPATARG)
+ RESize = -1;
+ else
+ EstimateAction (EPILOG, (unsigned int) 0, '\0', '\0');
+}
diff --git a/private/windbg/windbg/remote.c b/private/windbg/windbg/remote.c
new file mode 100644
index 000000000..6b148b914
--- /dev/null
+++ b/private/windbg/windbg/remote.c
@@ -0,0 +1,1039 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ remote.c
+
+Abstract:
+
+ This file implements a remote server for REMOTE.EXE that services
+ the windbg command window. This provides a "NTSD/KD" style debugging
+ from a REMOTE.EXE client to WINDBG.EXE.
+
+Author:
+
+ Wesley Witt (wesw) 5-Dec-1993
+
+Environment:
+
+ Win32, User Mode
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+extern HANDLE hFileLog;
+extern CRITICAL_SECTION csLog;
+
+#define MAX_SESSION 10
+#define BUFFSIZE 256
+
+SESSION_TYPE ClientList[MAX_SESSION];
+
+HANDLE RemoteServerThreadH;
+HANDLE hEventRemoteTerm;
+CHAR HostName[MAX_PATH];
+CHAR PipeName[MAX_PATH];
+CHAR Server[MAX_PATH];
+
+
+
+DWORD
+RemoteServerThread(
+ char* pipe
+ );
+
+DWORD
+NewSession(
+ SESSION_TYPE* Client
+ );
+
+BOOL
+FilterCommand(
+ LPSESSION_TYPE cl,
+ LPSTR buf,
+ DWORD cb
+ );
+
+DWORD
+RemoteSessionThread(
+ SESSION_TYPE* Client
+ );
+
+VOID
+SendStatus(
+ LPSESSION_TYPE cl
+ );
+
+DWORD
+ShowPopupThread(
+ char *mssg
+ );
+
+VOID
+CloseClient(
+ SESSION_TYPE *Client
+ );
+
+VOID
+InitClientList(
+ );
+
+DWORD
+ReadFixBytes(
+ LPSESSION_TYPE MyClient,
+ LPSTR lpBuf,
+ DWORD cbRead
+ );
+
+VOID
+PrintDebuggerMsg(
+ BOOL fInsert,
+ BOOL fLog,
+ LPSTR lpFmt,
+ ...
+ );
+
+VOID
+PrintCmdMsg(
+ LPSESSION_TYPE MyClient,
+ BOOL fInsert,
+ BOOL fLog,
+ LPSTR InpBuf
+ );
+
+
+
+VOID
+StartRemoteServer(
+ LPSTR szPipeName,
+ BOOL fAppend
+ )
+{
+ DWORD ThreadID;
+ DWORD i;
+ DWORD j;
+
+
+ if (_stricmp(szPipeName,"stop")==0) {
+ if (!RemoteRunning) {
+ CmdLogFmt( "Remote server is not running\r\n" );
+ return;
+ }
+
+ for (i=0;i<MAX_SESSION;i++) {
+ if (ClientList[i].Active) {
+
+ SetEvent( ClientList[i].hEventTerm );
+ if (WaitForSingleObject( ClientList[i].hThread, 10 * 10000 ) == WAIT_TIMEOUT) {
+ TerminateThread( ClientList[i].hThread, 0 );
+ }
+ CloseHandle( ClientList[i].hEventTerm );
+
+ CloseHandle( ClientList[i].PipeWriteH );
+ CloseHandle( ClientList[i].PipeReadH );
+ CloseHandle( ClientList[i].OverlappedRead.hEvent );
+ CloseHandle( ClientList[i].OverlappedWrite.hEvent );
+ CloseHandle( ClientList[i].hThread );
+ }
+ }
+
+ SetEvent( hEventRemoteTerm );
+ if (WaitForSingleObject( RemoteServerThreadH, 10 * 1000 ) == WAIT_TIMEOUT) {
+ TerminateThread( RemoteServerThreadH, 0 );
+ }
+ CloseHandle( hEventRemoteTerm );
+
+ CmdLogFmt( "Remote server stopped for %s\r\n", PipeName );
+ RemoteRunning = FALSE;
+ runDebugParams.szRemotePipe[0] = 0;
+ NoPopups = FALSE;
+
+ return;
+ }
+
+ if (RemoteRunning) {
+ CmdLogFmt( "Remote server running for pipe <%s>\r\n", PipeName );
+ for (i=0,j=0;i<MAX_SESSION;i++) {
+ if (ClientList[i].Active) {
+ j++;
+ }
+ }
+ if (j) {
+ CmdLogFmt( "%d remote connections:\r\n", j );
+ for (i=0;i<MAX_SESSION;i++) {
+ if (ClientList[i].Active) {
+ CmdLogFmt( "\tClient: %s\r\n", ClientList[i].Name );
+ }
+ }
+ }
+ return;
+ }
+
+ if (!*szPipeName) {
+ CmdLogFmt( "Remote server is not running\r\n" );
+ return;
+ }
+
+
+ InitClientList();
+
+ runDebugParams.fIgnoreAll = TRUE;
+ NoPopups = TRUE;
+ strcpy( PipeName, szPipeName );
+ strcpy( runDebugParams.szRemotePipe, szPipeName );
+ HostName[0]='\0';
+ Server[0]='\0';
+
+ if (hFileLog == INVALID_HANDLE_VALUE) {
+ HANDLE hMap;
+ LPBYTE lpBase, lpb;
+ CHAR buf[MAX_PATH];
+ char szLogFileName[MAX_PATH];
+ strncpy( szLogFileName, szPipeName, 8 );
+ szLogFileName[min(strlen(szPipeName),8)] = 0;
+ strcat( szLogFileName, ".log" );
+ LogFileOpen( szLogFileName, fAppend );
+ if (fAppend) {
+ hMap = CreateFileMapping( hFileLog, NULL, PAGE_READONLY, 0, 0, NULL );
+ if (hMap) {
+ lpb = lpBase = MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 );
+ i = GetFileSize( hFileLog, NULL );
+ while( i ) {
+ j = 0;
+ while( (*lpb != '\n') && (i) ) {
+ buf[j++] = *lpb++;
+ i--;
+ }
+ if (*lpb == '\n') {
+ i--;
+ buf[j++] = *lpb++;
+ }
+ buf[j] = 0;
+ CmdLogFmt( "%s", buf );
+ }
+ UnmapViewOfFile( lpBase );
+ CloseHandle( lpb );
+ }
+ }
+ }
+
+ hEventRemoteTerm = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+
+ RemoteServerThreadH = CreateThread(
+ NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)RemoteServerThread,
+ (LPVOID)PipeName,
+ 0,
+ &ThreadID
+ );
+
+ if (!RemoteServerThreadH) {
+ CmdLogFmt( "Cannot start remote server for %s\r\n", szPipeName );
+ return;
+ }
+
+ CmdLogFmt( "Remote server started for %s\r\n", szPipeName );
+
+ RemoteRunning = TRUE;
+
+ return;
+}
+
+BOOL
+PipeConnect(
+ HANDLE hPipe,
+ LPOVERLAPPED OverlappedPipe,
+ DWORD dwTimeout
+ )
+{
+ DWORD ec;
+ DWORD status;
+
+
+ ResetEvent( OverlappedPipe->hEvent );
+ status = ConnectNamedPipe( hPipe, OverlappedPipe);
+
+ if (!status) {
+ ec = GetLastError();
+ switch( ec ) {
+ case ERROR_PIPE_CONNECTED:
+ goto connected;
+
+ case ERROR_IO_PENDING:
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ status = WaitForSingleObject( OverlappedPipe->hEvent, dwTimeout );
+ switch ( status ) {
+ case WAIT_OBJECT_0:
+ goto connected;
+
+ case WAIT_TIMEOUT:
+ default:
+ return FALSE;
+ }
+ }
+
+connected:
+
+ return TRUE;
+}
+
+DWORD
+PipeRead(
+ LPSESSION_TYPE MyClient,
+ PUCHAR pch,
+ DWORD cch
+ )
+{
+ DWORD cb;
+
+
+ ResetEvent( MyClient->OverlappedRead.hEvent );
+
+ if (ReadFile(MyClient->PipeReadH, pch, cch, &cb, &MyClient->OverlappedRead)) {
+ //
+ // Read was successful and finished return packet size and exit.
+ //
+ return cb;
+ }
+
+ //
+ // We got a failure case -- there are now two possibities.
+ // 1. -- we have overlapped I/O, or
+ // 2. -- we are messed up.
+ //
+
+ if (GetLastError() == ERROR_IO_PENDING) {
+
+ cb = 0;
+
+ } else {
+
+ return 0;
+
+ }
+
+ while (TRUE) {
+ if (GetOverlappedResult(MyClient->PipeReadH,
+ &MyClient->OverlappedRead,
+ &cb,
+ FALSE)) {
+ //
+ // Read has successfully completed
+ //
+ return cb;
+ }
+ if (GetLastError() == ERROR_BROKEN_PIPE) {
+ break;
+ }
+ if (WaitForSingleObject( MyClient->hEventTerm, 0 ) == WAIT_OBJECT_0) {
+ break;
+ }
+ Sleep( 100 );
+ }
+
+ return 0;
+}
+
+DWORD
+PipeWrite(
+ LPSESSION_TYPE MyClient,
+ PUCHAR pch,
+ DWORD cch,
+ BOOL fAsynch
+ )
+{
+ DWORD cb;
+
+
+ if (WriteFile(MyClient->PipeWriteH, pch, cch, &cb, &MyClient->OverlappedWrite )) {
+ //
+ // Write was successful and finished
+ //
+ return cb;
+ }
+
+ //
+ // We got a failure case -- there are now two possiblities.
+ // 1. -- we have overlapped I/O or
+ // 2. -- we are messed up
+ //
+
+ if (GetLastError() == ERROR_IO_PENDING) {
+
+ cb = 0;
+
+ } else {
+
+ return 0;
+
+ }
+
+ if (GetOverlappedResult(MyClient->PipeWriteH, &MyClient->OverlappedWrite, &cb, !fAsynch)) {
+ //
+ // Write has successfully completed
+ //
+ return cb;
+ }
+
+ return 0;
+}
+
+DWORD
+RemoteServerThread(
+ LPSTR pipename
+ )
+{
+ int i;
+ DWORD ThreadID;
+ HANDLE PipeH[2];
+ OVERLAPPED OverlappedPipe[2];
+ SECURITY_DESCRIPTOR SecurityDescriptor;
+ HANDLE TokenHandle;
+ TOKEN_DEFAULT_DACL DefaultDacl;
+ SECURITY_ATTRIBUTES lsa;
+ char fullnameIn[BUFFSIZE];
+ char fullnameOut[BUFFSIZE];
+
+
+ sprintf( fullnameIn, SERVER_READ_PIPE, ".", pipename );
+ sprintf( fullnameOut, SERVER_WRITE_PIPE, ".", pipename );
+
+ //
+ // Initialize the security descriptor that we're going to
+ // use.
+ //
+
+ InitializeSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
+
+ SetSecurityDescriptorDacl( &SecurityDescriptor, TRUE, NULL, FALSE );
+
+ DefaultDacl.DefaultDacl = NULL;
+
+ if (OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_DEFAULT, &TokenHandle )) {
+ //
+ // Remove the default DACL on the token
+ //
+ SetTokenInformation( TokenHandle,
+ TokenDefaultDacl,
+ &DefaultDacl,
+ sizeof( TOKEN_DEFAULT_DACL )
+ );
+
+ }
+
+ lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
+ lsa.lpSecurityDescriptor=&SecurityDescriptor;
+ lsa.bInheritHandle=TRUE;
+
+ OverlappedPipe[0].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ OverlappedPipe[1].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ while(TRUE) {
+ PipeH[0] = CreateNamedPipe( fullnameIn ,
+ PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE,
+ PIPE_UNLIMITED_INSTANCES,
+ 0,
+ 0,
+ 1000,
+ &lsa
+ );
+
+ PipeH[1] = CreateNamedPipe( fullnameOut,
+ PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE,
+ PIPE_UNLIMITED_INSTANCES,
+ 0,
+ 0,
+ 1000,
+ &lsa
+ );
+
+ if (!PipeConnect( PipeH[0], &OverlappedPipe[0], 1000 )) {
+ CloseHandle(PipeH[0]);
+ CloseHandle(PipeH[1]);
+ if (WaitForSingleObject( hEventRemoteTerm, 0 ) == WAIT_OBJECT_0) {
+ return 0;
+ }
+ continue;
+ }
+
+ if (!PipeConnect( PipeH[1], &OverlappedPipe[1], INFINITE )) {
+ CloseHandle(PipeH[0]);
+ CloseHandle(PipeH[1]);
+ continue;
+ }
+
+ //
+ //Look For a Free Slot & if not- then terminate connection
+ //
+
+ for (i=1;i<MAX_SESSION;i++) {
+ //
+ // Locate a Free Client block
+ //
+ if (!ClientList[i].Active)
+ break;
+ }
+
+ if (i<MAX_SESSION) {
+
+ //
+ // Initialize the Client
+ //
+ ClientList[i].PipeReadH=PipeH[0];
+ ClientList[i].PipeWriteH=PipeH[1];
+ ClientList[i].Active=TRUE;
+ ClientList[i].SendOutput=TRUE;
+ ClientList[i].CommandRcvd=FALSE;
+ ClientList[i].OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ ClientList[i].OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ ClientList[i].hEventTerm = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ } else {
+
+ PrintDebuggerMsg( TRUE, FALSE, "Remote:Closing New Session - No more slots\n");
+ CloseHandle(PipeH[0]);
+ CloseHandle(PipeH[1]);
+ continue;
+
+ }
+
+ //
+ //start new thread for this connection
+ //
+
+ ClientList[i].hThread = CreateThread(
+ NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)RemoteSessionThread,
+ &ClientList[i],
+ 0,
+ &ThreadID
+ );
+
+ if (!ClientList[i].hThread) {
+ CloseClient(&ClientList[i]);
+ continue;
+ }
+ }
+
+ return 0;
+}
+
+
+BOOL
+DeliverHistory(
+ LPSESSION_TYPE MyClient,
+ DWORD MaxLines
+ )
+{
+ HANDLE LogMap;
+ LPBYTE lpLog;
+ LPBYTE p;
+ DWORD i;
+ DWORD cb;
+ DWORD lines;
+
+
+ if (hFileLog == INVALID_HANDLE_VALUE) {
+ return FALSE;
+ }
+
+ EnterCriticalSection( &csLog );
+ SetFilePointer( hFileLog, 0, NULL, FILE_BEGIN );
+
+ LogMap = CreateFileMapping(
+ hFileLog,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ 0,
+ NULL
+ );
+
+ if (LogMap == 0) {
+ LeaveCriticalSection( &csLog );
+ return FALSE;
+ }
+
+ lpLog = MapViewOfFile(
+ LogMap,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ 0
+ );
+
+ if (lpLog == NULL) {
+ LeaveCriticalSection( &csLog );
+ return FALSE;
+ }
+
+ cb = GetFileSize( hFileLog, NULL );
+ p = lpLog + cb - 1;
+ i = 0;
+ lines = 0;
+ while (i < cb) {
+ if (*p == '\n') {
+ ++lines;
+ }
+ if (lines == MaxLines) {
+ break;
+ }
+ --p;
+ ++i;
+ }
+
+ PipeWrite( MyClient, p+1, i, FALSE );
+ SetFilePointer( hFileLog, 0, NULL, FILE_END );
+ UnmapViewOfFile( lpLog );
+ CloseHandle( LogMap );
+ LeaveCriticalSection( &csLog );
+
+ return TRUE;
+}
+
+
+DWORD
+RemoteSessionThread(
+ LPSESSION_TYPE MyClient
+ )
+{
+ DWORD cb;
+ DWORD ReadCnt;
+ SESSION_STARTUPINFO ssi;
+ LPSTR headerbuff;
+ CHAR msg[BUFFSIZE];
+ SESSION_STARTREPLY ssr;
+ SYSTEMTIME st;
+ DWORD reply=0;
+ LPSTR ptr;
+ LPSTR pPacket;
+
+
+ GetLocalTime( &st );
+ ZeroMemory( &ssi, sizeof(ssi) );
+
+ ReadFixBytes( MyClient, (LPSTR)MyClient->Name, HOSTNAMELEN-1 );
+
+ //
+ //Last four Bytes contains a code
+ //
+ memcpy((LPSTR)&reply,(LPSTR)&(MyClient->Name[11]),4);
+
+ if (reply!=MAGICNUMBER) {
+ //
+ // Unknown client
+ //
+ CloseClient(MyClient);
+ return 1;
+ }
+
+ ssr.MagicNumber = MAGICNUMBER;
+ ssr.Size = sizeof(ssr);
+ ssr.FileSize = 0;
+
+ PipeWrite( MyClient, (char *)&ssr, sizeof(ssr), FALSE );
+
+ if (ReadFixBytes(MyClient,(char *)&(ssi.Size),sizeof(ssi.Size))!=0) {
+ CloseClient(MyClient);
+ return 1;
+ }
+
+ if (ssi.Size>1024) {
+ sprintf(msg,"%s","Server:Unknown Header..Terminating session\n");
+ PipeWrite(MyClient,msg,strlen(msg), FALSE );
+ CloseClient(MyClient);
+ return 1;
+ }
+
+ if ((headerbuff=(char *)calloc(ssi.Size,1))==NULL) {
+ sprintf(msg,"%s","Server:Not Enough Memory..Terminating session\n");
+ PipeWrite(MyClient,msg,strlen(msg), FALSE );
+ CloseClient(MyClient);
+ return 1;
+ }
+
+ ReadCnt=ssi.Size-sizeof(ssi.Size);
+ if (ReadFixBytes(MyClient,(char *)headerbuff,ReadCnt)!=0) {
+ CloseClient(MyClient);
+ return 1;
+ }
+
+ memcpy((char *)&ssi+sizeof(ssi.Size),headerbuff,sizeof(ssi)-sizeof(ssi.Size));
+ free(headerbuff);
+
+ //
+ // Version
+ //
+ if (ssi.Version!=VERSION) {
+ sprintf(msg,"Remote Warning:Server Version=%d Client Version=%d\n",VERSION,ssi.Version);
+ PipeWrite(MyClient,msg,strlen(msg), FALSE );
+ }
+
+ //
+ // Name
+ //
+ memcpy(MyClient->Name,ssi.ClientName,15);
+ MyClient->Name[14]=0;
+
+ DeliverHistory( MyClient, ssi.LinesToSend );
+
+ PrintDebuggerMsg(TRUE, FALSE, "Remote:Connected To %s [%02d:%02d]\n",MyClient->Name,st.wHour,st.wMinute);
+
+ MyClient->lpBuf = malloc( BUFFSIZE );
+
+ CmdExecutePrompt( TRUE, FALSE );
+
+ while( TRUE ) {
+
+ cb = PipeRead( MyClient, MyClient->lpBuf, BUFFSIZE );
+ if (!cb) {
+ break;
+ }
+
+ MyClient->lpBuf[cb]=0;
+ MyClient->CommandRcvd=TRUE;
+
+ if (FilterCommand( MyClient, MyClient->lpBuf, cb)) {
+ continue;
+ }
+
+ ptr = &MyClient->lpBuf[strlen(MyClient->lpBuf) - 1];
+ while ( *ptr == '\n' || *ptr == '\r') {
+ *ptr-- = '\0';
+ }
+
+ PrintCmdMsg( MyClient, FALSE, FALSE, (LPSTR)MyClient->lpBuf );
+
+ pPacket = malloc(strlen(MyClient->lpBuf) + 1);
+ strcpy(pPacket, MyClient->lpBuf);
+ PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_CMD, TRUE,
+ (LPARAM)pPacket );
+ }
+
+ PrintDebuggerMsg( TRUE, FALSE, "Remote:Disconnected From %s [%02d:%02d]\n",MyClient->Name,st.wHour,st.wMinute);
+
+ CloseClient( MyClient );
+ return 0;
+}
+
+
+VOID
+SendClientOutput(
+ LPSTR lpBuf,
+ DWORD cbBuf
+ )
+{
+ DWORD i;
+
+ for (i=0;i<MAX_SESSION;i++) {
+ if (ClientList[i].Active) {
+ PipeWrite( &ClientList[i], lpBuf, cbBuf, TRUE );
+ }
+ }
+}
+
+BOOL
+FilterCommand(
+ LPSESSION_TYPE cl,
+ LPSTR buf,
+ DWORD cb
+ )
+{
+ SYSTEMTIME st;
+ char inp_buf[4096];
+ DWORD ThreadID;
+ LPSTR mssg;
+ LPSTR ack;
+ BOOL ret = FALSE;
+
+
+ if (!cb) {
+ return FALSE;
+ }
+
+ buf[cb]=0;
+
+ GetLocalTime( &st );
+
+ if (buf[0] == COMMANDCHAR) {
+ switch(tolower(buf[1])) {
+ case 'o':
+ cl->SendOutput = !cl->SendOutput;
+ break;
+
+ case 's':
+ SendStatus( cl );
+ break;
+
+ case 'p':
+ mssg = (LPSTR) calloc( 4096, 1 );
+ ack = "Remote:Popup Shown..\n";
+
+ if (!mssg) {
+ break;
+ }
+
+ sprintf( mssg, "From %s [%d:%d]\n\n%s\n",
+ cl->Name,
+ st.wHour,
+ st.wMinute,
+ &buf[2]
+ );
+ CreateThread( NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)ShowPopupThread,
+ mssg,
+ 0,
+ &ThreadID
+ );
+ PipeWrite( cl, ack, strlen(ack), FALSE );
+ break;
+
+ case 'm':
+ buf[cb-2]=0;
+ PrintCmdMsg( cl, TRUE, TRUE, buf );
+ break;
+
+ case '@':
+ buf[cb-2]=0;
+ PrintCmdMsg( cl, TRUE, TRUE, buf );
+ //
+ // Remove the first @ sign
+ //
+ MoveMemory( buf, &buf[1], cb-1 );
+ buf[cb-1]=' ';
+ return FALSE;
+ break;
+
+ default :
+ sprintf( inp_buf, "%s","** Unknown Command **\n" );
+ PipeWrite( cl, inp_buf, strlen(inp_buf), FALSE );
+ //
+ // fall through
+ //
+
+ case 'h':
+ case 'H':
+ sprintf( inp_buf, "%cM: To Send Message\n", COMMANDCHAR );
+ PipeWrite( cl, inp_buf, strlen(inp_buf), FALSE );
+ sprintf( inp_buf, "%cP: To Generate popup\n", COMMANDCHAR );
+ PipeWrite( cl, inp_buf, strlen(inp_buf), FALSE );
+ sprintf( inp_buf,"%cK: To kill the server\n", COMMANDCHAR );
+ PipeWrite( cl, inp_buf, strlen(inp_buf), FALSE );
+ sprintf( inp_buf, "%cH: This Help\n", COMMANDCHAR );
+ PipeWrite( cl, inp_buf, strlen(inp_buf), FALSE );
+ break;
+ }
+ return TRUE;
+ }
+
+ if (buf[0]<26) {
+ if (buf[0] == CTRLC) {
+ cl->CommandRcvd = FALSE;
+ DispatchCtrlCEvent();
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+VOID
+SendStatus(
+ LPSESSION_TYPE cl
+ )
+{
+ CHAR buf[1024];
+ DWORD i;
+ LPSTR env;
+ DWORD ver;
+
+
+ env = GetEnvironmentStrings();
+ ver = GetVersion();
+
+ sprintf(buf,"Server = %s PIPE=%s\n",HostName,PipeName);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+
+ sprintf(buf,"Build = %d \n",((WORD *)&ver)[1]);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+
+ for (i=1;i<MAX_SESSION;i++) {
+ if (ClientList[i].Active) {
+ sprintf(buf,"ACTIVE SESSION=%s\n",ClientList[i].Name);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+ }
+ }
+
+ sprintf(buf,"====================\n",Server,PipeName);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+
+ sprintf(buf,"ENVIRONMENT VARIABLES\n",Server,PipeName);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+
+ sprintf(buf,"====================\n",Server,PipeName);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+
+
+ __try {
+ while (*env!=0) {
+ sprintf(buf,"%s\n",env);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+
+ while(*(env++)!=0);
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+ sprintf(buf,"Exception Generated Getting Environment Block\n",env);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+ }
+
+ sprintf(buf,"====================\n",Server,PipeName);
+ PipeWrite(cl,buf,strlen(buf), FALSE);
+ return;
+}
+
+DWORD
+ShowPopupThread(
+ LPSTR mssg
+ )
+{
+ MessageBox( GetActiveWindow(), mssg, "***WinDbg Remote***", MB_OK | MB_SETFOREGROUND );
+ free( mssg );
+ return 0;
+}
+
+VOID
+InitClientList(
+ )
+{
+ int i;
+
+ for (i=0;i<MAX_SESSION;i++) {
+ ZeroMemory( ClientList[i].Name, HOSTNAMELEN );
+ ClientList[i].PipeReadH = INVALID_HANDLE_VALUE;
+ ClientList[i].PipeWriteH = INVALID_HANDLE_VALUE;
+ ClientList[i].Active = FALSE;
+ ClientList[i].CommandRcvd = FALSE;
+ ClientList[i].SendOutput = FALSE;
+ ClientList[i].hThread = NULL;
+ }
+
+ return;
+}
+
+DWORD
+ReadFixBytes(
+ LPSESSION_TYPE MyClient,
+ LPSTR lpBuf,
+ DWORD cbRead
+ )
+{
+ DWORD cb;
+ DWORD xyzBytesRead=0;
+ DWORD xyzBytesToRead=cbRead;
+ LPSTR xyzbuf=lpBuf;
+
+ while(xyzBytesToRead!=0) {
+ cb = PipeRead(MyClient, xyzbuf, xyzBytesToRead );
+
+ if (!cb) {
+ return xyzBytesToRead;
+ }
+
+ xyzBytesToRead -= cb;
+ xyzbuf += cb;
+ }
+
+ return 0;
+}
+
+VOID
+CloseClient(
+ SESSION_TYPE *Client
+ )
+{
+ ZeroMemory(Client->Name,HOSTNAMELEN);
+
+ if (Client->PipeReadH!=INVALID_HANDLE_VALUE) {
+ CloseHandle(Client->PipeReadH);
+ Client->PipeReadH=INVALID_HANDLE_VALUE;
+ }
+
+ if (Client->PipeWriteH!=INVALID_HANDLE_VALUE) {
+ CloseHandle(Client->PipeWriteH);
+ Client->PipeWriteH=INVALID_HANDLE_VALUE;
+ }
+
+
+ Client->Active=FALSE; //Keep it last else synch problem.
+ return;
+}
+
+
+VOID
+PrintCmdMsg(
+ LPSESSION_TYPE MyClient,
+ BOOL fInsert,
+ BOOL fLog,
+ LPSTR InpBuf
+ )
+{
+ SYSTEMTIME st;
+
+ GetLocalTime( &st );
+
+ PrintDebuggerMsg(
+ fInsert,
+ fLog,
+ "%-15s [%-15s %2d:%02d %2d/%2d/%4d]\n" ,
+ InpBuf,
+ MyClient->Name,
+ st.wHour,
+ st.wMinute,
+ st.wMonth,
+ st.wDay,
+ st.wYear
+ );
+}
+
+
+VOID
+PrintDebuggerMsg(
+ BOOL fInsert,
+ BOOL fLog,
+ LPSTR lpFmt,
+ ...
+ )
+{
+ LPSTR lpText;
+ va_list vargs;
+
+ lpText = malloc( MAX_VAR_MSG_TXT );
+
+ va_start(vargs, lpFmt);
+ _vsnprintf( lpText, MAX_VAR_MSG_TXT, lpFmt, vargs);
+ va_end(vargs);
+
+ if (fLog) {
+ LogFileWrite( lpText, strlen(lpText) );
+ }
+
+ PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, fInsert, (LPARAM)lpText );
+}
diff --git a/private/windbg/windbg/reparse.c b/private/windbg/windbg/reparse.c
new file mode 100644
index 000000000..fc36cad3c
--- /dev/null
+++ b/private/windbg/windbg/reparse.c
@@ -0,0 +1,1364 @@
+/* reparse.c - parse a regular expression
+ *
+ * cl /c /Zep /AM /NT RE /Gs /G2 /Oa /D LINT_ARGS /Fc reparse.c
+ *
+ * Modifications:
+ *
+ * 22-Jul-1986 mz Hookable allocator (allow Z to create enough free space)
+ * 19-Nov-1986 mz Add RETranslateLength for Z to determine overflows
+ * 18-Aug-1987 mz Add field width and justification in translations
+ * 01-Mar-1988 mz Add in UNIX-like syntax
+ * 14-Jun-1988 mz Fix file parts allowing backslashes
+ * 04-Dec-1989 bp Let :p accept uppercase drive names
+ * 20-Dec-1989 ln capture trailing periods in :p
+ * 23-Jan-1990 ln Handle escaped characters & invalid trailing \ in
+ * RETranslate.
+ * 05-Feb-1991 mz Merged in KANJI stuff
+ *
+ */
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include <string.h> // Move(): memmove()
+ // Fill(): memset()
+
+
+#if DEBUG
+#define DEBOUT(x) printf x; fflush (stdout)
+#else
+#define DEBOUT(x)
+#endif
+
+
+/* regular expression compiler. A regular expression is compiled into pseudo-
+ * machine code. The principle is portable to other machines and is outlined
+ * below. We parse by recursive descent.
+ *
+ * The pseudo-code is fairly close to normal assembler and can be easily
+ * converted to be real machine code and has been done for the 80*86
+ * processor family.
+ *
+ * The basic regular expressions handled are:
+ *
+ * letter matches a single letter
+ * [class] matches a single character in the class
+ * [~class] matches a single character not in the class
+ * ^ matches the beginning of the line
+ * $ matches the end of the line
+ * ? matches any character (except previous two)
+ * \x literal x
+ * \n matches the previously tagged/matched expression (n digit)
+ *
+ * Regular expressions are now build from the above via:
+ *
+ * x* matches 0 or more x, matching minimal number
+ * x+ matches 1 or more x, matching minimal number
+ * x@ matches 0 or more x, matching maximal number
+ * x# matches 1 or more x, matching maximal number
+ * (x1!x2!...) matches x1 or x2 or ...
+ * ~x matches 0 characters but prevents x from occuring
+ * {x} identifies an argument
+ *
+ * The final expression that is matched by the compiler is:
+ *
+ * xy matches x then y
+ *
+ *
+ * The actual grammar used is: Parsing action:
+ *
+ * TOP -> re PROLOG .re. EPILOG
+ *
+ *
+ * re -> { re } re | LEFTARG .re. RIGHTARG
+ * e re |
+ * empty
+ *
+ * e -> se * | SMSTAR .se. SMSTAR1
+ * se + |
+ * se @ | STAR .se. STAR1
+ * se # |
+ * se
+ *
+ * se -> ( alt ) |
+ * [ ccl ] |
+ * ? | ANY
+ * ^ | BOL
+ * $ | EOL
+ * ~ se | NOTSIGN .se. NOTSIGN1
+ * :x |
+ * \n | PREV
+ * letter LETTER x
+ *
+ * alt -> re ! alt | LEFTOR .re. ORSIGN
+ * re LEFTOR .re. ORSIGN RIGHTOR
+ *
+ * ccl -> ~ cset | CCLBEG NOTSIGN .cset. CCLEND
+ * cset CCLBEG NULL .cset. CCLEND
+ *
+ * cset -> item cset |
+ * item
+ *
+ * item -> letter - letter | RANGE x y
+ * letter RANGE x x
+ *
+ * Abbreviations are introduced by :.
+ *
+ * :a [a-zA-Z0-9] alphanumeric
+ * :b ([<space><tab>]#) whitespace
+ * :c [a-zA-Z] alphabetic
+ * :d [0-9] digit
+ * :f ([~/\\ "\[\]\:<|>+=;,.]#) file part
+ * :h ([0-9a-fA-F]#) hex number
+ * :i ([a-zA-Z_$][a-zA-Z0-9_$]@) identifier
+ * :n ([0-9]#.[0-9]@![0-9]@.[0-9]#![0-9]#) number
+ * :p (([A-Za-z]\:!)(\\!)(:f(.:f!)(\\!/))@:f(.:f!.!)) path
+ * :q ("[~"]@"!'[~']@') quoted string
+ * :w ([a-zA-Z]#) word
+ * :z ([0-9]#) integer
+ *
+ */
+
+extern char XLTab[256]; /* lower-casing table */
+
+static BOOL RE__hasBeenInitialized = 0;
+static void RE__ModuleInitialize (void);
+
+/* There are several classes of characters:
+ *
+ * Closure characters are suffixes that indicate repetition of the previous
+ * RE.
+ *
+ * Simple RE chars are characters that indicate a particular type of match
+ *
+ */
+
+/* Closure character equates
+ */
+#define CC_SMPLUS 0 /* plus closure */
+#define CC_SMCLOSURE 1 /* star closure */
+#define CC_POWER 2 /* n repetitions of previous pattern */
+#define CC_CLOSURE 3 /* greedy closure */
+#define CC_PLUS 4 /* greedy plus */
+#define CC_EMPTY 5
+#define CC_ERROR -1
+
+/* Simple RE character equates */
+#define SR_BOL 0
+#define SR_EOL 1
+#define SR_ANY 2
+#define SR_CCLBEG 3
+#define SR_LEFTOR 4
+#define SR_CCLEND 5
+#define SR_ABBREV 6
+#define SR_RIGHTOR 7
+#define SR_ORSIGN 8
+#define SR_NOTSIGN 9
+#define SR_LEFTARG 10
+#define SR_RIGHTARG 11
+#define SR_LETTER 12
+#define SR_PREV 13
+
+int EndAltRE[] = { SR_ORSIGN, SR_RIGHTOR, -1 };
+int EndArg[] = { SR_RIGHTARG, -1 };
+
+char *pAbbrev[] = {
+ "a[a-zA-Z0-9]",
+ "b([ \t]#)",
+ "c[a-zA-Z]",
+ "d[0-9]",
+ "f([~/\\\\ \\\"\\[\\]\\:<|>+=;,.]#!..!.)",
+ "h([0-9a-fA-F]#)",
+ "i([a-zA-Z_$][a-zA-Z0-9_$]@)",
+ "n([0-9]#.[0-9]@![0-9]@.[0-9]#![0-9]#)",
+ "p(([A-Za-z]\\:!)(\\\\!/!)(:f(.:f!)(\\\\!/))@:f(.:f!.!))",
+ "q(\"[~\"]@\"!'[~']@')",
+ "w([a-zA-Z]#)",
+ "z([0-9]#)",
+ NULL
+};
+
+static char *digits = "0123456789";
+
+static flagType fZSyntax = TRUE; /* TRUE => use Z syntax for things */
+
+static int cArg;
+
+#if defined(KANJI)
+
+/* Lead byte test for KANJI. Since Kanji has a lead byte in the range
+ * 0x81-0xA0 and 0xE0-0xFC we have a bit table to test for presence in these
+ * ranges.
+ */
+unsigned char REKTab[32] = { 0x00, 0x00, /* 0 .. F */
+ 0x00, 0x00, /* 10 .. 1F */
+ 0x00, 0x00, /* 20 .. 2F */
+ 0x00, 0x00, /* 30 .. 3F */
+ 0x00, 0x00, /* 40 .. 4F */
+ 0x00, 0x00, /* 50 .. 5F */
+ 0x00, 0x00, /* 60 .. 6F */
+ 0x00, 0x00, /* 70 .. 7F */
+ 0x7f, 0xff, /* 80 .. 8F */
+ 0xff, 0xff, /* 90 .. 9F */
+ 0x00, 0x00, /* A0 .. AF */
+ 0x00, 0x00, /* B0 .. BF */
+ 0x00, 0x00, /* C0 .. CF */
+ 0x00, 0x00, /* D0 .. DF */
+ 0xff, 0xff, /* E0 .. EF */
+ 0xff, 0xf8 /* F0 .. FF */
+ };
+
+unsigned char REBTab[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+#endif
+
+/* RECharType - classify a character type
+ *
+ * p character pointer
+ *
+ * returns type of character (SR_xx)
+ */
+int pascal INTERNAL RECharType (p)
+char *p;
+{
+ if (fZSyntax)
+ /* Zibo syntax
+ */
+ switch (*p) {
+ case '^':
+ return SR_BOL;
+ case '$':
+ if (isdigit (p[1]))
+ return SR_PREV;
+ else
+ return SR_EOL;
+ case '?':
+ return SR_ANY;
+ case '[':
+ return SR_CCLBEG;
+ case '(':
+ return SR_LEFTOR;
+ case ']':
+ return SR_CCLEND;
+ case ':':
+ return SR_ABBREV;
+ case ')':
+ return SR_RIGHTOR;
+ case '!':
+ return SR_ORSIGN;
+ case '~':
+ return SR_NOTSIGN;
+ case '{':
+ return SR_LEFTARG;
+ case '}':
+ return SR_RIGHTARG;
+ default:
+ return SR_LETTER;
+ }
+ else
+ /* UNIX syntax
+ */
+ switch (*p) {
+ case '^':
+ return SR_BOL;
+ case '$':
+ return SR_EOL;
+ case '.':
+ return SR_ANY;
+ case '[':
+ return SR_CCLBEG;
+ case ']':
+ return SR_CCLEND;
+ case '\\':
+ switch (p[1]) {
+ case ':': /* \:C */
+ return SR_ABBREV;
+ case '(': /* \( */
+ return SR_LEFTARG;
+ case ')': /* \) */
+ return SR_RIGHTARG;
+ case '~': /* \~ */
+ return SR_NOTSIGN;
+ case '{': /* \{ */
+ return SR_LEFTOR;
+ case '}': /* \} */
+ return SR_RIGHTOR;
+ case '!': /* \! */
+ return SR_ORSIGN;
+ }
+ if (isdigit (p[1])) /* \N */
+ return SR_PREV;
+ default:
+ return SR_LETTER;
+ }
+}
+
+/* RECharLen - length of character type
+ *
+ * p character pointer to type
+ *
+ * returns length in chars of type
+ */
+int pascal INTERNAL RECharLen (p)
+char *p;
+{
+ if (fZSyntax)
+ if (RECharType (p) == SR_PREV) /* $N */
+ return 2;
+ else
+ if (RECharType (p) == SR_ABBREV) /* :N */
+ return 2;
+ else
+ return 1;
+ else {
+ if (*p == '\\')
+ switch (p[1]) {
+ case '{':
+ case '}':
+ case '~':
+ case '(':
+ case ')':
+ case '!':
+ return 2; /* \C */
+ case ':': /* \:C */
+ return 3;
+ default:
+ if (isdigit (p[1]))
+ return 2; /* \N */
+ else
+ return 1;
+ }
+ return 1;
+ }
+}
+
+/* REClosureLen - length of character type
+ *
+ * p character pointer to type
+ *
+ * returns length in chars of type
+ */
+int pascal INTERNAL REClosureLen (p)
+char *p;
+{
+ p;
+
+ return 1;
+}
+
+/* REParseRE - parse a general RE up to but not including the pEnd set
+ * of chars. Apply a particular action to each node in the parse tree.
+ *
+ * pAction Parse action routine to call at particluar points in the
+ * parse tree. This routine returns an unsigned quantity that
+ * is expected to be passed on to other action calls within the
+ * same node.
+ * p character pointer to string being parsed
+ * pEnd pointer to set of char types that end the current RE.
+ * External callers will typically use NULL for this value.
+ * Internally, however, we need to break on the ALT-terminating
+ * types or on arg-terminating types.
+ *
+ * Returns: pointer to delimited character if successful parse
+ * NULL if unsuccessful parse (syntax error).
+ *
+ */
+char * pascal INTERNAL REParseRE (pAction, p, pEnd)
+PACT pAction;
+register char *p;
+int *pEnd;
+{
+ int *pe;
+ unsigned u;
+
+ DEBOUT (("REParseRE (%04x, %s)\n", pAction, p));
+
+ while (TRUE) {
+ /* If we're at end of input
+ */
+ if (*p == '\0')
+ /* If we're not in the midst of an open expression
+ */
+ if (pEnd == NULL)
+ /* return the current parse position
+ */
+ return p;
+ else {
+ /* End of input, but expecting more, ERROR
+ */
+ DEBOUT (("REParse expecting more, ERROR\n"));
+ return NULL;
+ }
+
+ /* If there is an open expression
+ */
+ if (pEnd != NULL)
+ /* Find a matching character
+ */
+ for (pe = pEnd; *pe != -1; pe++)
+ if (RECharType (p) == *pe)
+ return p;
+
+ /* If we are looking at a left argument
+ */
+ if (RECharType (p) == SR_LEFTARG) {
+ /* Parse LEFTARG .re. RIGHTARG
+ */
+ u = (*pAction) (LEFTARG, 0, 0, 0);
+ if ((p = REParseRE (pAction, p + RECharLen (p), EndArg)) == NULL)
+ return NULL;
+ (*pAction) (RIGHTARG, u, 0, 0);
+ cArg++;
+ p += RECharLen (p);
+ }
+ else
+ /* Parse .e.
+ */
+ if ((p = REParseE (pAction, p)) == NULL)
+ return NULL;
+ }
+}
+
+/* REParseE - parse a simple regular expression with potential closures.
+ *
+ * pAction Action to apply at special parse nodes
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseE (pAction, p)
+PACT pAction;
+register char *p;
+{
+ DEBOUT (("REParseE (%04x, %s)\n", pAction, p));
+
+ switch (REClosureChar (p)) {
+ case CC_SMPLUS:
+ if (REParseSE (pAction, p) == NULL)
+ return NULL;
+ case CC_SMCLOSURE:
+ return REParseClosure (pAction, p);
+
+ case CC_PLUS:
+ if (REParseSE (pAction, p) == NULL)
+ return NULL;
+ case CC_CLOSURE:
+ return REParseGreedy (pAction, p);
+
+ case CC_POWER:
+ return REParsePower (pAction, p);
+
+ case CC_EMPTY:
+ return REParseSE (pAction, p);
+
+ default:
+ return NULL;
+ }
+}
+
+/* REParseSE - parse a simple regular expression
+ *
+ * pAction Action to apply at special parse nodes
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseSE (pAction, p)
+register PACT pAction;
+register char *p;
+{
+ DEBOUT (("REParseSE (%04x, %s)\n", pAction, p));
+
+ switch (RECharType (p)) {
+ case SR_CCLBEG:
+ return REParseClass (pAction, p);
+ case SR_ANY:
+ return REParseAny (pAction, p);
+ case SR_BOL:
+ return REParseBOL (pAction, p);
+ case SR_EOL:
+ return REParseEOL (pAction, p);
+ case SR_PREV:
+ return REParsePrev (pAction, p);
+ case SR_LEFTOR:
+ return REParseAlt (pAction, p);
+ case SR_NOTSIGN:
+ return REParseNot (pAction, p);
+ case SR_ABBREV:
+ return REParseAbbrev (pAction, p);
+ default:
+ return REParseChar (pAction, p);
+ }
+}
+
+/* REParseClass - parse a class membership match
+ *
+ * pAction Action to apply at beginning of parse and at each range
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseClass (pAction, p)
+PACT pAction;
+register char *p;
+{
+ char c;
+#if defined(DBCS)
+ char c2, c3, c4;
+#endif
+ unsigned u;
+
+ DEBOUT (("REParseClass (%04x, %s)\n", pAction, p));
+
+ p += RECharLen (p);
+ if ((fZSyntax && *p == '~') || (!fZSyntax && *p == '^')) {
+ u = (*pAction) (CCLNOT, 0, 0, 0);
+ p += RECharLen (p);
+ }
+ else
+ u = (*pAction) (CCLBEG, 0, 0, 0);
+
+ while (RECharType (p) != SR_CCLEND) {
+ if (*p == '\\')
+ p++;
+ if (*p == '\0') {
+ DEBOUT (("REParseClass expecting more, ERROR\n"));
+ return NULL;
+ }
+ c = *p++;
+
+#if defined(DBCS)
+ if (IsDBCSLeadByte((BYTE)c))
+ c2 = *p++;
+ else {
+ c2 = c;
+ c = 0;
+ }
+#endif
+ if (*p == '-') {
+ p++;
+ if (*p == '\\')
+ p++;
+ if (*p == '\0') {
+ DEBOUT (("REParseClass expecting more, ERROR\n"));
+ return NULL;
+ }
+#if defined(DBCS)
+ c3 = *p;
+ if (IsDBCSLeadByte(*(unsigned char *)p))
+ c4 = *++p;
+ else {
+ c4 = c3;
+ c3 = 0;
+ }
+ if ( (c == 0 && c3 == 0) || (c != 0 && c3 != 0) ) {
+ u = (*pAction) (RANGEDBCS1, 0, c, c2);
+ (*pAction) (RANGEDBCS2, u, c3, c4);
+ }
+ else
+ return NULL;
+#else
+ (*pAction) (RANGE, u, c, *p);
+#endif
+ p++;
+ }
+ else
+#if defined(KANJI)
+ {
+ u = (*pAction) (RANGEJ1, 0, c, c2);
+ (*pAction) (RANGEJ2, u, c, c2);
+ }
+#else
+ (*pAction) (RANGE, u, c, c);
+#endif
+ }
+#if defined(DBCS)
+ c = 0;
+ u = (*pAction) (RANGEDBCS1, 0, c, c);
+ (*pAction) (RANGEDBCS2, u, c, c);
+#endif
+ return p + RECharLen (p);
+}
+
+/* REParseAny - parse a match-any-character expression
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseAny (pAction, p)
+PACT pAction;
+char *p;
+{
+ DEBOUT (("REParseAny (%04x, %s)\n", pAction, p));
+
+ (*pAction) (ANY, 0, 0, 0);
+ return p + RECharLen (p);
+}
+
+/* REParseBOL - parse a beginning-of-line match
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseBOL (pAction, p)
+PACT pAction;
+char *p;
+{
+ DEBOUT (("REParseBOL (%04x, %s)\n", pAction, p));
+
+ (*pAction) (BOL, 0, 0, 0);
+ return p + RECharLen (p);
+}
+
+/* REParsePrev - parse a previous-match item
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParsePrev (pAction, p)
+PACT pAction;
+char *p;
+{
+ unsigned int i = *(p + 1) - '0';
+
+ DEBOUT (("REParsePrev (%04x, %s)\n", pAction, p));
+
+ if (i < 1 || i > (unsigned) cArg) {
+ DEBOUT (("REParsePrev invalid previous number, ERROR\n"));
+ return NULL;
+ }
+
+ (*pAction) (PREV, i, 0, 0);
+ return p + RECharLen (p);
+}
+
+/* REParseEOL - parse an end-of-line match
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseEOL (pAction, p)
+PACT pAction;
+char *p;
+{
+ DEBOUT (("REParseEOL (%04x, %s)\n", pAction, p));
+
+ (*pAction) (EOL, 0, 0, 0);
+ return p + RECharLen (p);
+}
+
+/* REParseAlt - parse a series of alternatives
+ *
+ * pAction Action to apply before and after each alternative
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseAlt (pAction, p)
+PACT pAction;
+register char *p;
+{
+ unsigned u = 0;
+
+ DEBOUT (("REParseAlt (%04x, %s)\n", pAction, p));
+
+ while (RECharType (p) != SR_RIGHTOR) {
+ p += RECharLen (p);
+ u = (*pAction) (LEFTOR, u, 0, 0);
+ if ((p = REParseRE (pAction, p, EndAltRE)) == NULL)
+ return NULL;
+ u = (*pAction) (ORSIGN, u, 0, 0);
+ }
+ (*pAction) (RIGHTOR, u, 0, 0);
+ return p + RECharLen (p);
+}
+
+/* REParseNot - parse a guard-against match
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseNot (pAction, p)
+PACT pAction;
+register char *p;
+{
+ unsigned u;
+
+ DEBOUT (("REParseNot (%04x, %s)\n", pAction, p));
+
+ p += RECharLen (p);
+ if (*p == '\0') {
+ DEBOUT (("REParseNot expecting more, ERROR\n"));
+ return NULL;
+ }
+ u = (*pAction) (NOTSIGN, 0, 0, 0);
+ p = REParseSE (pAction, p);
+ (*pAction) (NOTSIGN1, u, 0, 0);
+ return p;
+}
+
+/* REParseAbbrev - parse and expand an abbreviation
+ *
+ * Note that since the abbreviations are in Z syntax, we must change syntax
+ * temporarily to Z. We are careful to do this so that we do not mess up
+ * advancign the pointers.
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseAbbrev (pAction, p)
+PACT pAction;
+register char *p;
+{
+ int i;
+ flagType fZSTmp;
+
+ DEBOUT (("REParseAbbrev (%04x, %s)\n", pAction, p));
+
+ p += RECharLen (p);
+
+ fZSTmp = fZSyntax;
+ fZSyntax = TRUE;
+ if (p[-1] == '\0') {
+ DEBOUT (("REParseAbbrev expecting abbrev char, ERROR\n"));
+ fZSyntax = fZSTmp;
+ return NULL;
+ }
+
+ for (i = 0; pAbbrev[i]; i++)
+ if (p[-1] == *pAbbrev[i])
+ if (REParseSE (pAction, pAbbrev[i] + 1) == NULL) {
+ fZSyntax = fZSTmp;
+ return NULL;
+ }
+ else {
+ fZSyntax = fZSTmp;
+ return p;
+ }
+ DEBOUT (("REParseAbbrev found invalid abbrev char %s, ERROR\n", p - 1));
+ fZSyntax = fZSTmp;
+ return NULL;
+}
+
+/* REParseChar - parse a single character match
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseChar (pAction, p)
+PACT pAction;
+register char *p;
+{
+ DEBOUT (("REParseChar (%04x, %s)\n", pAction, p));
+
+ if (*p == '\\')
+ p++;
+ if (*p == '\0') {
+ DEBOUT (("REParseChar expected more, ERROR\n"));
+ return NULL;
+ }
+#if defined(DBCS)
+ if ( IsDBCSLeadByte ((BYTE)*p) ) {
+ (*pAction) (LETTER, 0, *p, *(p+1));
+ return p+2;
+ }
+ else {
+ (*pAction) (LETTER, 0, *p, 0);
+ return p+1;
+ }
+#else
+ (*pAction) (LETTER, 0, *p, 0);
+ return p+1;
+#endif
+}
+
+/* REParseClosure - parse a minimal match closure. The match occurs by
+ * matching none, then one, ...
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseClosure (pAction, p)
+PACT pAction;
+register char *p;
+{
+ unsigned u;
+
+ DEBOUT (("REParseaClosure (%04x, %s)\n", pAction, p));
+
+ u = (*pAction) (SMSTAR, 0, 0, 0);
+ if ((p = REParseSE (pAction, p)) == NULL)
+ return NULL;
+ (*pAction) (SMSTAR1, u, 0, 0);
+ return p + REClosureLen (p);
+}
+
+/* REParseGreedy - parse a maximal-match closure. The match occurs by
+ * matching the maximal number and then backing off as failures occur.
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParseGreedy (pAction, p)
+PACT pAction;
+register char *p;
+{
+ unsigned u;
+
+ DEBOUT (("REParseGreedy (%04x, %s)\n", pAction, p));
+
+ u = (*pAction) (STAR, 0, 0, 0);
+ if ((p = REParseSE (pAction, p)) == NULL)
+ return NULL;
+ (*pAction) (STAR1, u, 0, 0);
+ return p + REClosureLen (p);
+}
+
+/* REParsePower - parse a power-closure. This is merely the simple pattern
+ * repeated the number of times specified by the exponent.
+ *
+ * pAction Action to apply
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns pointer past parsed text if successful
+ * NULL otherwise (syntax error)
+ */
+char * pascal INTERNAL REParsePower (pAction, p)
+PACT pAction;
+char *p;
+{
+ register char *p1;
+ int exp;
+
+ DEBOUT (("REParsePower (%04x, %s)\n", pAction, p));
+
+ /* We have .se. POWER something. Skip over the .se. and POWER
+ * to make sure that what follows is a valid number
+ */
+ p1 = REParseSE (NullAction, p);
+
+ if (p1 == '\0')
+ /* Parse of .se. failed
+ */
+ return NULL;
+
+ /* skip POWER
+ */
+ p1 += REClosureLen (p1);
+
+ if (*p1 == '\0') {
+ DEBOUT (("REParsePower expecting more, ERROR\n"));
+ return NULL;
+ }
+
+ /* try to parse off number */
+ if (sscanf (p1, "%d", &exp) != 1) {
+ DEBOUT (("REParsePower expecting number, ERROR\n"));
+ return NULL;
+ }
+
+ p1 = strbskip (p1, digits);
+
+ /* iterate the pattern the exponent number of times */
+ while (exp--)
+ if (REParseSE (pAction, p) == NULL)
+ return NULL;
+ return p1;
+}
+
+/* NullAction - a do-nothing action. Used for stubbing out the action
+ * during a parse.
+ */
+unsigned INTERNAL NullAction (type, u, x, y)
+OPTYPE type;
+unsigned int u;
+unsigned char x, y;
+{
+ type; u; x; y;
+ return 0;
+}
+
+/* REClosureChar - return the character that corresponds to the next
+ * closure to be parsed. We call REParseSE with a null action to merely
+ * advance the character pointer to point just beyond the current simple
+ * regular expression.
+ *
+ * p character pointer to spot where parsing occurs
+ *
+ * Returns closure character if appropriate
+ * CC_EMPTY if no closure character found.
+ */
+char pascal INTERNAL REClosureChar (p)
+char *p;
+{
+ p = REParseSE (NullAction, p);
+ if (p == NULL)
+ return CC_ERROR;
+
+ if (fZSyntax)
+ /* Zibo syntax
+ */
+ switch (*p) {
+ case '^':
+ return CC_POWER;
+ case '+':
+ return CC_SMPLUS;
+ case '#':
+ return CC_PLUS;
+ case '*':
+ return CC_SMCLOSURE;
+ case '@':
+ return CC_CLOSURE;
+ default:
+ return CC_EMPTY;
+ }
+ else
+ /* UNIX syntax
+ */
+ switch (*p) {
+ case '+':
+ return CC_SMPLUS;
+ case '*':
+ return CC_SMCLOSURE;
+ default:
+ return CC_EMPTY;
+ }
+}
+
+/* RECompile - compile a pattern into the internal machine. Return a
+ * pointer to the match machine.
+ *
+ * p character pointer to pattern being compiled
+ *
+ * Returns: pointer to the internal machine if compilation was successful
+ * NULL if syntax error or not enough memory for malloc
+ */
+struct patType *RECompile (p, fCase, fZS)
+char *p;
+flagType fCase;
+flagType fZS;
+{
+ if (!RE__hasBeenInitialized) { RE__ModuleInitialize(); }
+
+ fZSyntax = fZS;
+
+ REEstimate (p);
+
+ DEBOUT (("Length is %04x\n", RESize));
+ if (RESize == -1)
+ return NULL;
+
+ if ((REPat = (struct patType *) (*tools_alloc) (RESize)) == NULL)
+ return NULL;
+
+ Fill ((char far *) REPat, -1, RESize);
+ Fill ((char far *) REPat->pArgBeg, 0, sizeof (REPat->pArgBeg));
+ Fill ((char far *) REPat->pArgEnd, 0, sizeof (REPat->pArgEnd));
+
+ REip = REPat->code;
+ REArg = 1;
+ REPat->fCase = fCase;
+ REPat->fUnix = (flagType) !fZS;
+
+ cArg = 0;
+
+ CompileAction (PROLOG, 0, 0, 0);
+
+ if (REParseRE (CompileAction, p, NULL) == NULL)
+ return NULL;
+
+ CompileAction (EPILOG, 0, 0, 0);
+
+#if DEBUG
+ REDump (REPat);
+#endif
+ return REPat;
+}
+
+/* Escaped - translate an escaped character ala UNIX C conventions.
+ *
+ * \t => tab \e => ESC char \h => backspace \g => bell
+ * \n => lf \r => cr \\ => \
+ *
+ * c character to be translated
+ *
+ * Returns: character as per above
+ */
+char pascal INTERNAL Escaped (c)
+char c;
+{
+ switch (c) {
+ case 't':
+ return '\t';
+ case 'e':
+ return 0x1B;
+ case 'h':
+ return 0x08;
+ case 'g':
+ return 0x07;
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case '\\':
+ return '\\';
+ default:
+ return c;
+ }
+}
+
+/* REGetArg - copy argument string out from match.
+ *
+ * pat matched pattern
+ * i index of argument to fetch, 0 is entire pattern
+ * p destination of argument
+ *
+ * Returns: TRUE if successful, FALSE if i is out of range.
+ */
+flagType REGetArg (pat, i, p)
+struct patType *pat;
+int i;
+char *p;
+{
+ int l = 0;
+
+ if (i > MAXPATARG)
+ return FALSE;
+ else
+ if (pat->pArgBeg[i] != (char *)-1)
+ Move ((char far *)pat->pArgBeg[i], (char far *)p, l = RELength (pat, i));
+ p[l] = '\0';
+ return TRUE;
+}
+
+/* RETranslate - translate a pattern string and match structure into an
+ * output string. During pattern search-and-replace, RETranslate is used
+ * to generate an output string based on an input match pattern and a template
+ * that directs the output.
+ *
+ * The input match is any patType returned from RECompile that has been passed
+ * to fREMatch and that causes fREMatch to return TRUE. The template string
+ * is any set of ascii chars. The $ character leads in arguments:
+ *
+ * $$ is replaced with $
+ * $0 is replaced with the entire match string
+ * $1-$9 is replaced with the corresponding tagged (by {}) item from
+ * the match.
+ *
+ * An alternative method is to specify the argument as:
+ *
+ * $([w,]a) where a is the argument number (0-9) and w is an optional field
+ * width that will be used in a printf %ws format.
+ *
+ * buf pattern matched
+ * src template for the match
+ * dst destination of the translation
+ *
+ * Returns: TRUE if translation was successful, FALSE otherwise
+ */
+flagType RETranslate (buf, src, dst)
+struct patType *buf;
+register char *src;
+register char *dst;
+{
+ int i, w;
+ char *work;
+ char chArg = (char) (buf->fUnix ? '\\' : '$');
+
+ work = (*tools_alloc) (MAXLINELEN);
+ if (work == NULL)
+ return FALSE;
+
+ *dst = '\0';
+
+ while (*src != '\0') {
+ /* Process tagged substitutions first
+ */
+ if (*src == chArg && (isdigit (src[1]) || src[1] == '(')) {
+ /* presume 0-width field */
+ w = 0;
+
+ /* skip $ and char */
+ src += 2;
+
+ /* if we saw $n */
+ if (isdigit (src[-1]))
+ i = src[-1] - '0';
+ /* else we saw $( */
+ else {
+ /* get tagged expr number */
+ i = atoi (src);
+
+ /* skip over number */
+ if (*src == '-')
+ src++;
+ src = strbskip (src, digits);
+
+ /* was there a comma? */
+ if (*src == ',') {
+ /* We saw field width, parse off expr number */
+ w = i;
+ i = atoi (++src);
+ src = strbskip (src, digits);
+ }
+
+ /* We MUST end with a close paren */
+ if (*src++ != ')') {
+ free (work);
+ return FALSE;
+ }
+ }
+ /* w is field width
+ * i is selected argument
+ */
+ if (!REGetArg (buf, i, work)) {
+ free (work);
+ return FALSE;
+ }
+ sprintf (dst, "%*s", w, work);
+ dst += strlen (dst);
+ }
+ else
+ /* process escaped characters */
+ if (*src == '\\') {
+ src++;
+ if (!*src) {
+ free (work);
+ return FALSE;
+ }
+ *dst++ = Escaped (*src++);
+ }
+ else
+ /* chArg quotes itself */
+ if (*src == chArg && src[1] == chArg) {
+ *dst++ = chArg;
+ src += 2;
+ }
+ else
+#ifdef DBCS
+ if (IsDBCSLeadByte(*src) && *(src+1)) {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ }
+ else
+#endif
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ free (work);
+ return TRUE;
+}
+
+/* RETranslateLength - given a matched pattern and a replacement string
+ * return the length of the final replacement
+ *
+ * The inputs have the same syntax/semantics as in RETranslate.
+ *
+ * buf pattern matched
+ * src template for the match
+ *
+ * Returns: number of bytes in total replacement, -1 if error
+ */
+int RETranslateLength (buf, src)
+struct patType *buf;
+register char *src;
+{
+ int i, w;
+ int length = 0;
+ char chArg = (char) (buf->fUnix ? '\\' : '$');
+
+ while (*src != '\0') {
+ /* Process tagged substitutions first
+ */
+ if (*src == chArg && (isdigit (src[1]) || src[1] == '(')) {
+ w = 0;
+ src += 2;
+ if (isdigit (src[-1]))
+ i = src[-1] - '0';
+ else {
+ i = atoi (src);
+ if (*src == '-')
+ src++;
+ src = strbskip (src, digits);
+ if (*src == ',') {
+ w = i;
+ i = atoi (++src);
+ src = strbskip (src, digits);
+ }
+ if (*src++ != ')')
+ return -1;
+ }
+ /* w is field width
+ * i is selected argument
+ */
+ i = RELength (buf, i);
+ length += max (i, abs(w));
+ }
+ else
+ /* process escaped characters */
+ if (*src == '\\') {
+ src += 2;
+ length++;
+ }
+ else
+ /* chArg quotes itself */
+ if (*src == chArg && src[1] == chArg) {
+ src += 2;
+ length++;
+ }
+#ifdef DBCS
+ else
+ if (IsDBCSLeadByte(*src) && *(src+1)) {
+ length += 2;
+ src += 2;
+ }
+#endif
+ else {
+ length++;
+ src++;
+ }
+ }
+ return length;
+}
+
+/* RELength - return length of argument in match.
+ *
+ * pat matched pattern
+ * i index of argument to examine, 0 is entire pattern
+ *
+ * Returns: length of ith argument, -1 if i is out-of-range.
+ */
+int RELength (pat, i)
+struct patType *pat;
+int i;
+{
+ if (i > MAXPATARG)
+ return -1;
+ else
+ if (pat->pArgBeg[i] == (char *)-1)
+ return 0;
+ else
+ return pat->pArgEnd[i] - pat->pArgBeg[i];
+}
+
+/* REStart - return pointer to beginning of match.
+ *
+ * ppat matched pattern
+ *
+ * Returns: character pointer to beginning of match
+ */
+char *REStart (pat)
+struct patType *pat;
+{
+ return pat->pArgBeg[0] == (char *)-1 ? NULL : pat->pArgBeg[0];
+}
+
+
+// void Fill(void FAR * a, char b, unsigned int c) {;}
+// void Move(void FAR * a, void FAR * b, unsigned int c) {;}
+char XLTab[256];
+char * strbskip(char const * a, char const * b) {return (char *) a;}
+
+
+void Fill(void FAR * a, char b, unsigned int c)
+{
+ (void) memset (a, (int)b, c);
+ return;
+}
+
+
+void Move(void FAR * a, void FAR * b, unsigned int c)
+{
+ (void) memmove (b, a, c);
+ return;
+}
+
+
+
+/****************************************************************************
+*
+* void RE__ModuleInitialize (void)
+*
+* "Initialize the Regular Expression module. Presently, this comprises
+* loading lowercase information into the global(!) array 'XLTab[]'."
+*
+* Answers: <nothing>
+*
+* Requires: true
+*
+* Ensures: The global array 'XLTab[]' has, for each index, the ASCII
+* lowercase equivalent of that index (as defined by invoking
+* 'tolower()' on each index value).
+*
+* Only the *first* invocation of this method will do the
+* initialization procedure; subsequent invocations are legal
+* but have no effect.
+*
+* Modifies: XLTab[]
+* RE__hasBeenInitialized
+*
+* Raises: <nothing>
+*
+* COMMENTS: There is a companion array 'XUTab[]' which we ignore because
+* the entire system ignores it, also.
+*
+* We #include <ctype.h> just to be sure, even though it may
+* have already been pulled in somewhere else (surely *all*
+* header files watch for mulitple inclusions...).
+*
+* In keeping with windbg philosophy, we do *not* pay attention
+* to Unicode stuff.
+*
+\***************************************************************************/
+
+#include <ctype.h> // RE__ModuleInitialize(): tolower()
+
+static
+void
+RE__ModuleInitialize (void)
+{
+ int idxChar;
+
+ if (!RE__hasBeenInitialized)
+ {
+ for (idxChar = 0; idxChar != sizeof(XLTab); idxChar++)
+ {
+ XLTab[idxChar] = tolower (idxChar);
+ }
+
+ RE__hasBeenInitialized = TRUE;
+ }
+
+ return;
+}
diff --git a/private/windbg/windbg/replace.c b/private/windbg/windbg/replace.c
new file mode 100644
index 000000000..d42c36805
--- /dev/null
+++ b/private/windbg/windbg/replace.c
@@ -0,0 +1,175 @@
+#include "precomp.h"
+#pragma hdrstop
+
+#define extraPick (*((BOOL *)&wGeneric1))
+
+/*** DlgReplace
+**
+**
+** Description:
+** Processes messages for "REPLACE" dialog box
+** (Edit Replace menu Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND - Input received
+*/
+
+BOOL FAR PASCAL EXPORT DlgReplace(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ Unused( lParam );
+
+ switch (message) {
+
+ case WM_INITDIALOG: {
+
+ BOOL lookAround = TRUE;
+ int i;
+ LPSTR s;
+
+ frMem.replaceAll = FALSE;
+ frMem.oneLineDone = FALSE;
+ frMem.replacing = TRUE;
+ SetStopLimit();
+ StatusMultiKey(FALSE);
+
+ //Retrieve text from document, blank string if nothing found
+ //and send string to dialog box
+ if (GetCurrentText(curView, &lookAround,
+ (LPSTR)findReplace.findWhat,
+ MAX_USER_LINE, &frMem.leftCol, NULL)) {
+
+ //Temporarly put the string in the picklist
+ extraPick = InsertInPickList(FIND_PICK);
+
+ }
+ else
+ extraPick = FALSE;
+
+ frMem.rightCol = frMem.leftCol;
+ SendDlgItemMessage(hDlg, ID_REPLACE_WHAT,
+ CB_LIMITTEXT, MAX_USER_LINE, (LPARAM) NULL);
+ SendDlgItemMessage(hDlg, ID_REPLACE_WHAT, WM_SETTEXT, 0,
+ (DWORD)((LPSTR)findReplace.findWhat));
+
+ //Put back last replaced value
+ SendDlgItemMessage(hDlg, ID_REPLACE_REPLACEWITH,
+ CB_LIMITTEXT, MAX_USER_LINE, (LPARAM) NULL);
+ SendDlgItemMessage(hDlg, ID_REPLACE_REPLACEWITH, WM_SETTEXT, 0,
+ (DWORD)((LPSTR)findReplace.replaceWith));
+
+ //Transfer boolean values to Dialog Box
+ SendDlgItemMessage(hDlg, ID_REPLACE_MATCHUPLO, BM_SETCHECK,
+ findReplace.matchCase, 0L);
+ SendDlgItemMessage(hDlg, ID_REPLACE_WHOLEWORD, BM_SETCHECK,
+ !findReplace.regExpr & findReplace.wholeWord, 0L);
+ SendDlgItemMessage(hDlg, ID_REPLACE_REGEXP, BM_SETCHECK,
+ findReplace.regExpr, 0L);
+ EnableWindow(GetDlgItem(hDlg, ID_REPLACE_WHOLEWORD),
+ !findReplace.regExpr);
+
+ frMem.goUpCopy = findReplace.goUp;
+ findReplace.goUp = FALSE;
+
+ //Set the line to start find
+ frMem.line = Views[curView].Y;
+
+ //Set number of replaced occurences to 0
+ frMem.nbReplaced = 0;
+
+ //Fill find pick list
+ for (i = 0 ; i < findReplace.nbInPick[FIND_PICK]; i++) {
+ Dbg(s = (LPSTR)GlobalLock(findReplace.hPickList[FIND_PICK][i]));
+ SendDlgItemMessage(hDlg, ID_REPLACE_WHAT, CB_INSERTSTRING, (WPARAM) -1,
+ (LONG)(LPSTR)s);
+ Dbg(GlobalUnlock (findReplace.hPickList[FIND_PICK][i]) == FALSE);
+ }
+
+ //Fill replace pick list
+ for (i = 0 ; i < findReplace.nbInPick[REPLACE_PICK]; i++) {
+ Dbg(s = (LPSTR)GlobalLock(findReplace.hPickList[REPLACE_PICK][i]));
+ SendDlgItemMessage(hDlg, ID_REPLACE_REPLACEWITH, CB_INSERTSTRING, (WPARAM) -1,
+ (LONG)(LPSTR)s);
+ Dbg(GlobalUnlock (findReplace.hPickList[REPLACE_PICK][i]) == FALSE);
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMMAND: {
+
+ switch (wParam) {
+
+ case ID_REPLACE_FINDNEXT:
+ case ID_REPLACE_REPLACEALL:
+
+ if (SendDlgItemMessage(hDlg, ID_REPLACE_WHAT, WM_GETTEXT,
+ MAX_USER_LINE,
+ (DWORD)((LPSTR)findReplace.findWhat))) {
+
+
+ SendDlgItemMessage(hDlg, ID_REPLACE_REPLACEWITH,
+ WM_GETTEXT, MAX_USER_LINE,
+ (DWORD)((LPSTR)findReplace.replaceWith));
+
+ if (extraPick)
+ RemoveFromPick(FIND_PICK);
+
+ frMem.replaceAll = (wParam == ID_REPLACE_REPLACEALL);
+ InsertInPickList(FIND_PICK);
+ InsertInPickList(REPLACE_PICK);
+ if (FindNext(Views[curView].Y, Views[curView].X,
+ TRUE, TRUE, TRUE)) {
+ if (frMem.hadError)
+ findReplace.goUp = frMem.goUpCopy;
+ frMem.replacing = !frMem.hadError;
+ frMem.firstConfirmInvoc = TRUE;
+ EndDialog(hDlg, !frMem.hadError);
+ }
+ else {
+ SetStopLimit();
+ SetFocus(GetDlgItem(hDlg, ID_REPLACE_WHAT));
+ }
+
+ }
+ return TRUE;
+
+ case ID_REPLACE_WHOLEWORD:
+ findReplace.wholeWord = !findReplace.wholeWord;
+ return TRUE;
+
+ case ID_REPLACE_MATCHUPLO:
+ findReplace.matchCase = !findReplace.matchCase;
+ return TRUE;
+
+ case ID_REPLACE_REGEXP:
+ findReplace.regExpr = !findReplace.regExpr;
+ SendDlgItemMessage(hDlg, ID_REPLACE_WHOLEWORD, BM_SETCHECK,
+ !findReplace.regExpr & findReplace.wholeWord, 0L);
+ EnableWindow(GetDlgItem(hDlg, ID_REPLACE_WHOLEWORD),
+ !findReplace.regExpr);
+ return TRUE;
+
+ case IDCANCEL :
+
+ //Remove the extra pick we inserted
+ if (extraPick)
+ RemoveFromPick(FIND_PICK);
+
+ findReplace.goUp = frMem.goUpCopy;
+ frMem.replacing = FALSE;
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDWINDBGHELP :
+ Dbg(WinHelp(hDlg,szHelpFileName,HELP_CONTEXT,ID_REPLACE_HELP));
+ return TRUE;
+ }
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
diff --git a/private/windbg/windbg/ribbon.c b/private/windbg/windbg/ribbon.c
new file mode 100644
index 000000000..5fc2ffd5b
--- /dev/null
+++ b/private/windbg/windbg/ribbon.c
@@ -0,0 +1,573 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Ribbon.c
+
+Abstract:
+
+ This module contains the support code for ribbon/toolbar routines
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 26-Jul-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+extern BOOL bChildFocus; // module wide flag for swallowing mouse messages
+extern BOOL bOffRibbon; // module wide ribbon/MDI focus flag
+
+
+
+LONG FAR PASCAL EXPORT RibbonWndProc (HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ PAINTSTRUCT ps;
+
+ switch (message) {
+ case WM_CREATE:
+ {
+ int c_top, c_left, c_height, c_width, c_center, c_tmp;
+ HDC hDC ;
+
+ hDC = GetDC (hWnd) ;
+
+ // Allow 2 pixels spacing for VGA, 2 for EGA or HGC, and 1 for CGA.
+
+ if (IsCGAmode)
+ c_tmp = 1;
+ else
+ c_tmp = 2;
+
+ //Set up values for the top and bottom of static controls
+ c_top = c_tmp;
+ c_left = ribbon.height / 2;
+ c_height = ribbon.height - (2 * c_tmp) - 1;
+ c_center = ribbon.height / 2;
+
+ // readjust the c_top and c_bottom to make sure that the bitmap
+ // for the buttons are not being stretched (Cosmetic reason).
+
+ if (IsCGAmode) {
+ c_top = c_center - (RIBBON_CGA_HEIGHT / 2) ;
+ c_height = RIBBON_CGA_HEIGHT ;
+ c_width = RIBBON_CGA_WIDTH ;
+ } else if (IsEGAmode) {
+ c_top = c_center - (RIBBON_EGA_HEIGHT / 2) ;
+ c_height = RIBBON_EGA_HEIGHT ;
+ c_width = RIBBON_EGA_WIDTH ;
+ }
+
+ //Default to VGA for VGA or higher resolution
+ else {
+ c_top = c_center - (RIBBON_VGA_HEIGHT / 2) ;
+ c_height = RIBBON_VGA_HEIGHT ;
+ c_width = RIBBON_VGA_WIDTH ;
+ }
+
+ //Space the first button out to the left for about the width of a button
+
+ c_left += c_width ;
+ ribbon.hwndGoButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG(QCQP_CS_PUSHBUTTON, IDS_CTRL_GONORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_GO,
+ hInst,
+ ID_RIBBON_GO);
+
+ //Position the next button as a pair without gap
+
+ c_left += c_width ; // pair with CompileFile button
+ ribbon.hwndHaltButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_HALTNORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_HALT,
+ hInst,
+ ID_RIBBON_HALT) ;
+
+ //Don't pair with Halt button, so skip 1/2 extra space
+
+ c_left += (c_width + (c_width/2)) ;
+ ribbon.hwndBreakButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_BREAKNORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_BREAK,
+ hInst,
+ ID_RIBBON_BREAK);
+
+ //Pair with BreakPoint button
+
+ c_left += c_width ;
+ ribbon.hwndQWatchButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_QWATCHNORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_QWATCH,
+ hInst,
+ ID_RIBBON_QWATCH) ;
+
+ // don't pair with Build button, so skip extra space
+
+ c_left += (c_width + (c_width/2)) ;
+ ribbon.hwndTraceButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_TRACENORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_TRACE,
+ hInst,
+ ID_RIBBON_TRACE) ;
+
+ c_left += c_width ; // pair with Trace button
+ ribbon.hwndStepButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_STEPNORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_STEP,
+ hInst,
+ ID_RIBBON_STEP) ;
+
+ /*
+ ** This is the SOURCE mode button so space it over
+ */
+
+ c_left += (c_width + (c_width/2));
+ ribbon.hwndSModeButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_SMODENORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_SMODE,
+ hInst,
+ ID_RIBBON_SMODE);
+
+ c_left += c_width ; // ASM pair with Src button
+ ribbon.hwndAModeButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_AMODENORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_AMODE,
+ hInst,
+ ID_RIBBON_AMODE) ;
+
+
+
+ /*
+ ** The format button is placed by itself
+ */
+
+ c_left += (c_width + (c_width/2));
+ ribbon.hwndFmtButton = CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_PUSHBUTTON, IDS_CTRL_FORMATNORMAL),
+ c_left, c_top,
+ c_width, c_height,
+ hWnd,
+ (HMENU) ID_RIBBON_FORMAT,
+ hInst,
+ ID_RIBBON_FORMAT);
+
+
+
+
+ // initialize these controls' states appropriately
+
+ EnableQCQPCtrl(hWnd, ID_RIBBON_GO, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_HALT, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_BREAK, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_QWATCH, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_TRACE, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_STEP, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_SMODE, FALSE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_AMODE, TRUE);
+ EnableQCQPCtrl(hWnd, ID_RIBBON_FORMAT, TRUE);
+ ReleaseDC (hWnd, hDC) ;
+ break;
+ }
+
+
+ case WM_MOUSEACTIVATE:
+ bChildFocus = FALSE;
+ bOffRibbon = TRUE;
+ return FALSE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case ID_RIBBON_GO:
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_GO, 0L));
+ Dbg(PostMessage(hwndFrame, WM_COMMAND, IDM_RUN_GO, 0L));
+ break;
+
+ case ID_RIBBON_HALT:
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_HALT, 0L));
+ Dbg(PostMessage(hwndFrame, WM_COMMAND, IDM_RUN_HALT, 0L));
+ break;
+
+ case ID_RIBBON_TRACE:
+ //Give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_TRACE, 0L));
+
+ //Send quick watch message to the main menu bar window
+ Dbg(PostMessage(hwndFrame, WM_COMMAND, IDM_RUN_TRACEINTO, 0L)) ;
+ break;
+
+ case ID_RIBBON_STEP:
+ //Give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_STEP, 0L));
+ //Send quick watch message to the main menu bar window
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_RUN_STEPOVER, 0L)) ;
+ break;
+
+ case ID_RIBBON_SMODE:
+ //Give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_SMODE, 0L));
+ //Send quick watch message to the main menu bar window
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_RUN_SOURCE_MODE, 0L)) ;
+ break;
+
+ case ID_RIBBON_AMODE:
+ //Give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_AMODE, 0L));
+ //Send quick watch message to the main menu bar window
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_RUN_SOURCE_MODE, 1L)) ;
+ break;
+
+
+ case ID_RIBBON_BREAK:
+ //Give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_BREAK, 0L));
+ // Send quick watch message to the main menu bar window
+
+#ifdef WIN32
+ // Make this message look like an accelerator (HIWORD(wParam) == 1)
+ Dbg (PostMessage (hwndFrame, WM_COMMAND, MAKELONG(IDM_DEBUG_SETBREAK, 1), 0)) ;
+#else
+ // Make this message look like an accelerator (HIWORD(lParam) == 1)
+ Dbg (PostMessage (hwndFrame, WM_COMMAND, IDM_DEBUG_SETBREAK, MAKELONG(0, 1))) ;
+#endif
+ break;
+
+
+ case ID_RIBBON_QWATCH:
+ // give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,
+ ID_RIBBON_QWATCH, 0L));
+ // Send quick watch message to the main menu bar window
+ Dbg(PostMessage(hwndFrame, WM_COMMAND, IDM_DEBUG_QUICKWATCH, 0L)) ;
+ break;
+
+ case ID_RIBBON_FORMAT:
+ //Give back focus to who used to have it
+ Dbg(PostMessage(ribbon.hwndRibbon, WU_RESTOREFOCUS,ID_RIBBON_FORMAT, 0L));
+ //Send options to the main menu bar window
+
+ {
+ NPVIEWREC v = &Views[curView];
+ NPDOCREC d;
+ UINT uSwitch;
+
+ if (v->Doc < -1)
+ {
+ uSwitch = -(v->Doc);
+ }
+ else
+ {
+ d = &Docs[v->Doc]; //Views[indx].Doc
+ uSwitch = d->docType;
+ }
+
+ switch (uSwitch)
+ {
+ case WATCH_WIN:
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_OPTIONS_PANE, WATCH_WIN)) ;
+ break;
+
+ case LOCALS_WIN:
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_OPTIONS_PANE, LOCALS_WIN)) ;
+ break;
+
+ case CALLS_WIN:
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_OPTIONS_CALLS, 0L)) ;
+ break;
+
+ case MEMORY_WIN:
+ Dbg(PostMessage (hwndFrame, WM_COMMAND, IDM_OPTIONS_MEMORY, 0L)) ;
+ break;
+
+ case CPU_WIN:
+ break;
+
+ case FLOAT_WIN:
+ break;
+
+ case DOC_WIN:
+ break;
+
+ case DISASM_WIN:
+ break;
+
+ case COMMAND_WIN:
+ break;
+
+ default:
+ break;
+
+
+ }
+ }
+
+ break; // Nothing for now
+
+
+ }
+
+ break;
+
+ case WU_RESTOREFOCUS:
+ //!Let the mdi decide where the actual focus should go
+ //!If something is done to block the editor when the ribbon
+ //!gets control this might need re-thinking
+ SetFocus(hwndFrame);
+
+ break;
+
+ case WU_ENABLERIBBONCONTROL:
+ // Sent by anyone wanting to enable
+ // any of the ribbon controls.
+ switch (wParam)
+ {
+
+ case ID_RIBBON_TRACE:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_TRACE, TRUE);
+ break;
+
+ case ID_RIBBON_STEP:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_STEP, TRUE);
+ break;
+
+ case ID_RIBBON_BREAK:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_BREAK, TRUE);
+ break;
+
+ case ID_RIBBON_GO:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_GO, TRUE);
+ break;
+
+ case ID_RIBBON_HALT:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_HALT, TRUE);
+ break;
+
+ case ID_RIBBON_QWATCH:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_QWATCH, TRUE);
+ break;
+
+ case ID_RIBBON_SMODE:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_SMODE, TRUE);
+ break;
+
+ case ID_RIBBON_AMODE:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_AMODE, TRUE);
+ break;
+
+ case ID_RIBBON_FORMAT:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_FORMAT, TRUE);
+ break;
+
+ }
+ break;
+
+
+ case WU_DISABLERIBBONCONTROL:
+ // Sent by anyone wanting to disable
+ // any of the ribbon controls.
+ switch (wParam)
+ {
+ case ID_RIBBON_TRACE:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_TRACE, FALSE);
+ break;
+
+ case ID_RIBBON_STEP:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_STEP, FALSE);
+ break;
+
+ case ID_RIBBON_BREAK:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_BREAK, FALSE);
+ break;
+
+ case ID_RIBBON_GO:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_GO, FALSE);
+ break;
+
+ case ID_RIBBON_HALT:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_HALT, FALSE);
+ break;
+
+ case ID_RIBBON_QWATCH:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_QWATCH, FALSE);
+ break;
+
+ case ID_RIBBON_SMODE:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_SMODE, FALSE);
+ break;
+
+ case ID_RIBBON_AMODE:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_AMODE, FALSE);
+ break;
+
+
+ case ID_RIBBON_FORMAT:
+ EnableQCQPCtrl(hWnd, ID_RIBBON_FORMAT, FALSE);
+ break;
+
+
+ }
+ break;
+
+ case WU_ESCAPEFROMRIBBON:
+ {
+ /*
+ ** Sent from elsewhere to cancel the usage of the ribbon
+ ** wParam contains the handle of window to whom we should
+ ** set the focus.
+ **
+ ** If either we have the focus or if one of our children
+ ** has the focus then we need to reset it. Otherwise ignore
+ ** the message
+ */
+
+ HWND CurFocus;
+
+ CurFocus = GetFocus();
+
+ if ((CurFocus != NULL) &&
+ ((CurFocus == ribbon.hwndRibbon) ||
+ (IsChild(ribbon.hwndRibbon, CurFocus)))) {
+
+ if (wParam)
+ SetFocus((HWND) wParam);
+ }
+ }
+ break;
+
+ case WM_PAINT:
+ {
+ HPEN blackPen, whitePen, grayPen;
+
+ BeginPaint (hWnd, &ps);
+
+ //Prepare the pens
+ Dbg(whitePen = GetStockObject(WHITE_PEN));
+ Dbg(blackPen = GetStockObject(BLACK_PEN));
+ Dbg(grayPen = CreatePen(PS_SOLID, 1, GRAYDARK));
+
+ //Draw a top white line
+
+ Dbg(SelectObject(ps.hdc, whitePen));
+ MoveToX(ps.hdc, ps.rcPaint.left, 0, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, 0);
+
+ //Draw a bottom black line
+
+ Dbg(SelectObject(ps.hdc, blackPen));
+ MoveToX(ps.hdc, ps.rcPaint.left, ribbon.height-1, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, ribbon.height-1);
+
+ //Restore previous font and Delete allocated ojects
+
+ Dbg(DeleteObject (grayPen));
+ EndPaint (hWnd, &ps);
+
+ }
+ break;
+
+#ifdef WIN32
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ goto DefProcessing;
+
+
+ case WM_CTLCOLORSTATIC:
+ {
+ POINT point;
+ HANDLE hRibbonBrush;
+#else
+ case WM_CTLCOLOR:
+ {
+
+ POINT point;
+ HANDLE hRibbonBrush;
+
+ // We need to set the colors up for
+ // CS_DROPDOWN style combo boxes
+ if (HIWORD(lParam) == CTLCOLOR_STATIC) {
+#endif
+ // Use light gray for VGA mode with color monitor only.
+ if ( IsVGAmode && !IsMONOmode )
+ SetBkColor((HDC) wParam, GRAYLIGHT);
+ else
+ SetBkColor((HDC) wParam, WHITEBKGD);
+
+ SetTextColor((HDC) wParam, GetSysColor(COLOR_WINDOWTEXT));
+
+ // Handle patterns in background colours - see Child Window Controls in Petzold
+#ifdef WIN32
+ hRibbonBrush = (HANDLE) GetClassHandle(hWnd, GCL_HBRBACKGROUND);
+#else
+ hRibbonBrush = (HANDLE) GetClassHandle(hWnd, GCW_HBRBACKGROUND);
+#endif
+#ifdef WIN16
+ UnrealizeObject(hRibbonBrush);
+#endif
+ point.x = 0; point.y = 0;
+ ClientToScreen(hWnd, &point);
+ SetBrushOrgX((HDC) wParam, point.x, point.y, NULL);
+ return (DWORD)hRibbonBrush;
+#ifdef WIN16
+ }
+ goto DefProcessing;
+#endif
+ }
+
+
+ case WM_DESTROY:
+ // Free the bitmaps stored in ribbon
+ FreeRibbonBitmaps(hWnd);
+
+ PostQuitMessage(0);
+ break;
+
+ DefProcessing:
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return FALSE;
+} /* RibbonWndProc() */
diff --git a/private/windbg/windbg/rundebug.c b/private/windbg/windbg/rundebug.c
new file mode 100644
index 000000000..1a09748b4
--- /dev/null
+++ b/private/windbg/windbg/rundebug.c
@@ -0,0 +1,501 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ rundebug.c
+
+Abstract:
+
+
+Author:
+
+ David J. Gilman (davegi) 16-May-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#define DEFAULT_LFOPT_FNAME "windbg.log"
+
+extern LRESULT SendMessageNZ(HWND,UINT,WPARAM,LPARAM);
+
+void SetOkButtonToDefault( HWND hDlg );
+
+BOOL FAR PASCAL EXPORT
+DlgRunDebug(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+)
+
+/*** DlgRunDebug
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes messages for "RUNDEBUG" dialog box
+** (Options RunDebug menu Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+** WM_DESTROY- Restore memory
+**
+*/
+
+{
+ UINT newradix;
+ char rgch[256];
+ BOOL b;
+ BOOL fUpdateCpu = FALSE;
+ int disAsmOpts;
+ BOOL fChange = FALSE;
+ char ch;
+ int bUpdate = UPDATE_NONE;
+ LPSTR lp;
+
+ Unused(lParam);
+
+ switch (message) {
+ case WM_INITDIALOG:
+
+ /*
+ * Set up the controls to reflect current values
+ */
+
+ if (runDebugParams.fDebugChildren) {
+ CheckDlgButton(hDlg,ID_DBUGOPT_CHILDREN,1);
+ }
+
+ if (runDebugParams.RegModeExt) {
+ CheckRadioButton(hDlg, ID_DBUGOPT_REGREG, ID_DBUGOPT_REGEXT,
+ ID_DBUGOPT_REGEXT);
+ } else {
+ CheckRadioButton(hDlg, ID_DBUGOPT_REGREG, ID_DBUGOPT_REGEXT,
+ ID_DBUGOPT_REGREG);
+ }
+
+ if (runDebugParams.RegModeMMU) {
+ CheckDlgButton(hDlg,ID_DBUGOPT_REGMMU,1);
+ }
+
+ if (runDebugParams.ShowSegVal) {
+ CheckDlgButton(hDlg,ID_DBUGOPT_DISPSEG,1);
+ }
+
+ if (runDebugParams.fGoOnThreadTerm) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_EXITGO, 1);
+ }
+
+ if (runDebugParams.fAttachGo) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_ATTACHGO, 1);
+ }
+
+ if (runDebugParams.fChildGo) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_CHILDGO, 1);
+ }
+
+ if (runDebugParams.fCommandRepeat) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_COMMANDREPEAT, 1);
+ }
+
+ if (runDebugParams.fDisconnectOnExit) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_DISCONNECT, 1);
+ }
+
+ if (runDebugParams.fVerbose) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_VERBOSE, 1);
+ }
+
+ if (runDebugParams.fIgnoreAll) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_IGNOREALL, 1);
+ }
+
+ if (runDebugParams.fShortContext) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_CONTEXT, 1);
+ }
+
+ if (runDebugParams.fAlternateSS) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_ALTSS, 1);
+ }
+
+ if (runDebugParams.fWowVdm) {
+ CheckDlgButton(hDlg, ID_DBUGOPT_WOWVDM, 1);
+ }
+
+ if (!(runDebugParams.DisAsmOpts & dopFlatAddr)) {
+ CheckDlgButton(hDlg,ID_DISASMOPT_SHOWSEG,1);
+ }
+
+ if (runDebugParams.DisAsmOpts & dopRaw) {
+ CheckDlgButton(hDlg,ID_DISASMOPT_SHOWBYTE,1);
+ }
+
+ if (runDebugParams.DisAsmOpts & dopUpper) {
+ CheckDlgButton(hDlg,ID_DISASMOPT_CASE,1);
+ }
+
+ if (runDebugParams.DisAsmOpts & 0x800) {
+ CheckDlgButton(hDlg,ID_DISASMOPT_SHOWSOURCE,1);
+ }
+
+ if (runDebugParams.DisAsmOpts & dopSym) {
+ CheckDlgButton(hDlg,ID_DISASMOPT_SHOWSYMB,1);
+ }
+
+ if (runDebugParams.DisAsmOpts & dopDemand) {
+ CheckDlgButton(hDlg,ID_DISASMOPT_DEMAND,1);
+ }
+
+ if (runDebugParams.LfOptAppend) {
+ CheckDlgButton(hDlg,ID_LFOPT_APPEND,1);
+ }
+
+ if (runDebugParams.LfOptAuto) {
+ CheckDlgButton(hDlg,ID_LFOPT_AUTO,1);
+ }
+
+ SetDlgItemText(hDlg, ID_LFOPT_FNAME, runDebugParams.szLogFileName);
+
+ /*
+ *
+ */
+
+ lp = GetDllName(DLL_SOURCE_PATH);
+ SetDlgItemText(hDlg, ID_DBUGOPT_SRCHPATH, lp ? lp : "");
+
+ CheckRadioButton(
+ hDlg,
+ ID_DBUGOPT_RADIXOCT,
+ ID_DBUGOPT_RADIXHEX,
+ radix == 8 ? ID_DBUGOPT_RADIXOCT
+ : radix == 10 ? ID_DBUGOPT_RADIXDEC
+ : ID_DBUGOPT_RADIXHEX);
+
+ /*
+ * Set check box for case matching
+ */
+
+ if (!fCaseSensitive) {
+ CheckDlgButton( hDlg, ID_DBUGOPT_CASESENSITIVE, 1);
+ }
+
+
+ CheckRadioButton(
+ hDlg,
+ ID_DBUGOPT_SUFFIXA,
+ ID_DBUGOPT_SUFFIXNONE,
+ (SuffixToAppend == 'A') ? ID_DBUGOPT_SUFFIXA :
+ (SuffixToAppend == 'W') ? ID_DBUGOPT_SUFFIXW :
+ ID_DBUGOPT_SUFFIXNONE );
+
+
+ return TRUE;
+
+
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK :
+
+ /*
+ * Transfer the options to global
+ *
+ * Now start looking at the rest and determine what needs to
+ * be updated
+ */
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_REGMMU) != 0);
+ if (b != runDebugParams.RegModeMMU) {
+ runDebugParams.RegModeMMU = b;
+ fChange = TRUE;
+ fUpdateCpu = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_REGEXT) != 0);
+ if (b != runDebugParams.RegModeExt) {
+ runDebugParams.RegModeExt = b;
+ fChange = TRUE;
+ fUpdateCpu = TRUE;
+ }
+
+ /*
+ * If the register options changed then we need to get
+ * it to refresh the list of registers in the windows
+ */
+
+ if (fUpdateCpu && HModEM) {
+ SendMessageNZ( GetCpuHWND(), WU_DBG_LOADEM, 0, 0);
+ SendMessageNZ( GetFloatHWND(), WU_DBG_LOADEM, 0, 0);
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_DISPSEG) != 0);
+ if (b != runDebugParams.ShowSegVal) {
+ runDebugParams.ShowSegVal = b;
+ bUpdate = UPDATE_WATCH|UPDATE_LOCALS|UPDATE_MEMORY;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_CHILDREN) != 0);
+ if (b != runDebugParams.fDebugChildren) {
+ runDebugParams.fDebugChildren = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked( hDlg, ID_DBUGOPT_CASESENSITIVE) == 0);
+ if (b != fCaseSensitive) {
+ fCaseSensitive = b;
+ fChange = TRUE;
+ bUpdate = UPDATE_WATCH|UPDATE_LOCALS|UPDATE_MEMORY;
+ }
+
+ b = (IsDlgButtonChecked( hDlg, ID_DBUGOPT_EXITGO) != 0);
+ if (b != runDebugParams.fGoOnThreadTerm) {
+ runDebugParams.fGoOnThreadTerm = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_CHILDGO) != 0);
+ if (b != runDebugParams.fChildGo) {
+ runDebugParams.fChildGo = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_ATTACHGO) != 0);
+ if (b != runDebugParams.fAttachGo) {
+ runDebugParams.fAttachGo = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_COMMANDREPEAT) != 0);
+ if (b != runDebugParams.fCommandRepeat) {
+ runDebugParams.fCommandRepeat = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_ALTSS) != 0);
+ if (b != runDebugParams.fAlternateSS) {
+ runDebugParams.fAlternateSS = b;
+ fChange = TRUE;
+ if (LppdCur) {
+ if (b) {
+ strcpy(rgch, "slowstep");
+ } else {
+ strcpy(rgch, "faststep");
+ }
+ OSDIoctl(LppdCur->hpid,0,ioctlCustomCommand,8,rgch);
+ }
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_DISCONNECT) != 0);
+ if (b != runDebugParams.fDisconnectOnExit) {
+ runDebugParams.fDisconnectOnExit = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_VERBOSE) != 0);
+ if (b != runDebugParams.fVerbose) {
+ runDebugParams.fVerbose = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_IGNOREALL) != 0);
+ if (b != runDebugParams.fIgnoreAll) {
+ runDebugParams.fIgnoreAll = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_CONTEXT) != 0);
+ if (b != runDebugParams.fShortContext) {
+ runDebugParams.fShortContext = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_DBUGOPT_WOWVDM) != 0);
+ if (b != runDebugParams.fWowVdm) {
+ runDebugParams.fWowVdm = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_LFOPT_APPEND) != 0);
+ if (b != runDebugParams.LfOptAppend) {
+ runDebugParams.LfOptAppend = b;
+ fChange = TRUE;
+ }
+
+ b = (IsDlgButtonChecked(hDlg,ID_LFOPT_AUTO) != 0);
+ if (b != runDebugParams.LfOptAuto) {
+ runDebugParams.LfOptAuto = b;
+ fChange = TRUE;
+ }
+
+ GetDlgItemText(hDlg, ID_LFOPT_FNAME, rgch, sizeof(rgch));
+ if (strlen(rgch) == 0) {
+ strcpy( runDebugParams.szLogFileName, DEFAULT_LFOPT_FNAME );
+ }
+ else {
+ strcpy( runDebugParams.szLogFileName, rgch );
+ }
+
+ /*
+ * Get the correct value for the new radix. The routine
+ * UpdateRadix will conditionally update the global radix
+ */
+
+ if (IsDlgButtonChecked(hDlg, ID_DBUGOPT_RADIXOCT)) {
+ newradix = 8;
+ } else if (IsDlgButtonChecked(hDlg, ID_DBUGOPT_RADIXDEC)) {
+ newradix = 10;
+ } else {
+ newradix = 16;
+ }
+
+ UpdateRadix(newradix);
+
+ /*
+ *
+ */
+
+ if (IsDlgButtonChecked(hDlg, ID_DBUGOPT_SUFFIXA)) {
+ ch = 'A';
+ } else if (IsDlgButtonChecked(hDlg, ID_DBUGOPT_SUFFIXW)) {
+ ch = 'W';
+ } else {
+ ch = '\0';
+ }
+
+ if (ch != SuffixToAppend) {
+ if ( HModEE ) {
+ EESetSuffix( ch );
+ }
+ SuffixToAppend = ch;
+ fChange = TRUE;
+ bUpdate = UPDATE_WATCH|UPDATE_LOCALS|UPDATE_MEMORY;
+ }
+
+ /*
+ * Check to see what disassembler options have changed
+ * and update the disasm window if necessary.
+ */
+
+ disAsmOpts = 0;
+ if (!IsDlgButtonChecked(hDlg,ID_DISASMOPT_SHOWSEG)) {
+ disAsmOpts |= dopFlatAddr;
+ }
+
+ if (IsDlgButtonChecked(hDlg,ID_DISASMOPT_SHOWBYTE)) {
+ disAsmOpts |= dopRaw;
+ }
+
+ if (IsDlgButtonChecked(hDlg,ID_DISASMOPT_CASE)) {
+ disAsmOpts |= dopUpper;
+ }
+
+ if (IsDlgButtonChecked(hDlg,ID_DISASMOPT_SHOWSOURCE)) {
+ disAsmOpts |= 0x800;
+ }
+
+ if (IsDlgButtonChecked(hDlg,ID_DISASMOPT_SHOWSYMB)) {
+ disAsmOpts |= dopSym;
+ }
+
+ if (IsDlgButtonChecked(hDlg,ID_DISASMOPT_DEMAND)) {
+ disAsmOpts |= dopDemand;
+ }
+
+ if (disAsmOpts != runDebugParams.DisAsmOpts) {
+ runDebugParams.DisAsmOpts = disAsmOpts;
+ if (disasmView != -1) {
+ ViewDisasm(NULL, disasmRefresh);
+ }
+ fChange = TRUE;
+ }
+
+ /*
+ *
+ */
+
+ GetDlgItemText(hDlg, ID_DBUGOPT_SRCHPATH, rgch, sizeof(rgch));
+ lp = GetDllName(DLL_SOURCE_PATH);
+ if (!lp || strcmp(rgch, lp)) {
+ SetDllName(DLL_SOURCE_PATH, rgch);
+ fChange = TRUE;
+ }
+
+ /*
+ * See if we have changed any options.
+ */
+
+ if (fChange) {
+ ChangeDebuggerState();
+ }
+
+ if (bUpdate != UPDATE_NONE) {
+ UpdateDebuggerState(bUpdate);
+ }
+
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case IDCANCEL:
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+
+ case ID_DBUGOPT_RADIXOCT:
+ case ID_DBUGOPT_RADIXDEC:
+ case ID_DBUGOPT_RADIXHEX:
+ return (TRUE);
+
+ case ID_DBUGOPT_SUFFIXA:
+ case ID_DBUGOPT_SUFFIXW:
+ case ID_DBUGOPT_SUFFIXNONE:
+ return TRUE;
+
+ case IDWINDBGHELP: /* User Help */
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_DBUGOPT_HELP));
+ SetOkButtonToDefault( hDlg );
+ return (TRUE);
+ }
+ break;
+ }
+ return (FALSE);
+} /* DlgRunDebug() */
+
+void
+ResetButtonDefault( HWND hWnd )
+{
+ DWORD dwStyle;
+
+
+ dwStyle = GetWindowLong( hWnd, GWL_STYLE );
+ dwStyle &= ~BS_DEFPUSHBUTTON;
+ dwStyle = SetWindowLong( hWnd, GWL_STYLE, dwStyle );
+ InvalidateRect( hWnd, NULL, FALSE );
+
+ return;
+}
+
+void
+SetOkButtonToDefault( HWND hDlg )
+{
+ SendMessage(hDlg,
+ WM_NEXTDLGCTL,
+ (WPARAM)GetDlgItem(hDlg, IDOK),
+ (LPARAM)TRUE);
+ return;
+}
diff --git a/private/windbg/windbg/setbreak.c b/private/windbg/windbg/setbreak.c
new file mode 100644
index 000000000..0de66df4f
--- /dev/null
+++ b/private/windbg/windbg/setbreak.c
@@ -0,0 +1,2092 @@
+/*--Author:
+
+ Griffith Wm. Kadnier (v-griffk) 01-Aug-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/**********************************************************************/
+
+#define MAX_LOCATION 255
+#define MAX_EXPRESSION 255
+#define MAX_COMMAND 255
+
+extern CXF CxfIp;
+
+#define WNDPROC_HISTORY_SIZE 32
+
+/**********************************************************************/
+
+static char rgchT[255];
+ char FAR WndProcHistory[WNDPROC_HISTORY_SIZE][MAX_LOCATION];
+ int FAR NumHistoricalWndProcs = 0;
+ char MsgBuffer[255];
+ char szLocation[255];
+ char szExpression[255];
+ char szLength[20];
+ char szWndProc[255];
+ char szPass[20];
+ char szPassLeft[20];
+ char szProcess[20];
+ char szThread[20];
+ char szCommand[255];
+
+static int TopIndex;
+
+
+VOID
+EnableBPButtons(
+ HWND hDlg,
+ int iBP
+ );
+
+VOID
+SetChooseClass(
+ HWND,
+ BOOL
+ );
+
+VOID
+FillMsgCombo(
+ HWND
+ );
+
+BOOL
+WINAPI
+DlgMessage(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ );
+
+HBPT
+BPLB_HbptOfI(
+ int iBP
+ );
+
+
+
+/*** FillWndProcCombo
+**
+** Synopsis:
+** void = FillWndProcCombo(hDlg)
+**
+** Entry:
+** hDlg - handle to dialog box for combo box
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function is used to fill in the combo box which contains the
+** list of window procedures which are known to the system. This is
+** based on the last N items which had a breakpoint of a window proc
+** type. (i.e. on message)
+*/
+
+VOID
+FillWndProcCombo(
+ HWND hDlg
+ )
+{
+ int i;
+
+ for (i = 0; i < NumHistoricalWndProcs; i++) {
+ SendDlgItemMessage(hDlg, ID_SETBREAK_WNDPROC,
+ CB_ADDSTRING, 0, (DWORD)WndProcHistory[i]);
+ }
+ return;
+} /* FillWndProcCombo() */
+
+/*** StoreWndProcHistory
+**
+** Synopsis:
+** void = StoreWndProcHistory(hDlg)
+**
+** Entry:
+** hDlg - handle to current breakpoint dialog
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function is used to retreive the strings which contain the
+** names of the latest window procedure names back from the dialog
+** box and store them into the array
+*/
+
+VOID
+StoreWndProcHistory(
+ HWND hDlg
+ )
+{
+ int i;
+
+ NumHistoricalWndProcs = (int)SendDlgItemMessage(hDlg, ID_SETBREAK_WNDPROC,
+ CB_GETCOUNT, 0, 0L);
+
+ NumHistoricalWndProcs = min(WNDPROC_HISTORY_SIZE,
+ NumHistoricalWndProcs);
+
+ for (i = 0; i < NumHistoricalWndProcs; i++) {
+ SendDlgItemMessage(hDlg, ID_SETBREAK_WNDPROC,
+ CB_GETLBTEXT, i, (DWORD)WndProcHistory[i]);
+ }
+ return;
+} /* StoreWndProcHistory() */
+
+
+
+BOOL
+ClearWndProcHistory (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Clears the WndProc history
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOL - TRUE if cleared
+
+--*/
+{
+ int i;
+
+ for (i = 0; i < NumHistoricalWndProcs; i++) {
+ WndProcHistory[i][0] = '\0';
+ }
+
+ NumHistoricalWndProcs = 0;
+
+ return TRUE;
+}
+
+
+
+
+BOOL
+SetWndProcHistory (
+ LPSTR List,
+ DWORD ListLength
+ )
+/*++
+
+Routine Description:
+
+ Adds the WndProcs from a multistring to the end of the current
+ WndProc history.
+
+Arguments:
+
+ List - Supplies the multistring of WndProcs
+ ListLength - Supplies length of multistring
+
+Return Value:
+
+ BOOL - TRUE if ALL WndProcs in the list were added.
+
+--*/
+{
+ LPSTR WndProc;
+ DWORD Next = 0;
+ BOOL Ok = FALSE;
+
+ while ( NumHistoricalWndProcs < WNDPROC_HISTORY_SIZE ) {
+
+ if ( WndProc = GetNextStringFromMultiString( List, ListLength, &Next ) ) {
+
+ _fstrcpy( WndProcHistory[ NumHistoricalWndProcs++ ], WndProc );
+
+ } else {
+
+ Ok = TRUE;
+ break;
+ }
+ }
+
+ return Ok;
+}
+
+
+
+LPSTR
+GetWndProcHistory (
+ DWORD *ListLength
+ )
+/*++
+
+Routine Description:
+
+ Generates a multistring with the WndProc history. MRU WndProc goes
+ first.
+
+Arguments:
+
+ ListLength - Supplies pointer to length of multistring
+
+Return Value:
+
+ LPSTR - Multistring with WndProc history. May be NULL if
+ no history.
+
+--*/
+{
+ LPSTR List = NULL;
+ DWORD Length = 0;
+ int i;
+
+ for (i = 0; i < NumHistoricalWndProcs; i++) {
+ AddToMultiString( &List, &Length, WndProcHistory[i] );
+ }
+
+ *ListLength = Length;
+ return List;
+}
+
+
+
+#define BreakButtonStyle(Id) (WORD)GetWindowLong(GetDlgItem(hDlg, Id), GWL_STYLE)
+
+#define BreakSelection wGeneric1
+
+/*** BreakDefPushButton
+**
+** Synopsis:
+** void = BreakDefPushButton(hDlg, ButtonId)
+**
+** Entry:
+** hDlg - handle to breakpoint dialog box
+** ButtonId - Button to set as the default button
+**
+** Returns:
+** nothing
+**
+** Description:
+** This function is used to set the default button in the breakpoint
+** dialog box. Which button is to be the default is passed in as
+** ButtonId.
+*/
+
+VOID
+BreakDefPushButton(
+ HWND hDlg,
+ INT ButtonId
+ )
+{
+ SendMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg,ButtonId), (LPARAM)TRUE );
+ return;
+} /* BreakDefPushButton() */
+
+/*** SetbreakControls
+**
+** Synopsis:
+** void = SetbreakControls(hDlg, bpType)
+**
+** Entry:
+** hDlg
+** bpType
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Initialize the controls according to the
+** value of bpType. (CB_ERR means no Action selected.)
+**
+*/
+
+VOID
+SetbreakControls(
+ HWND hDlg,
+ int bpType
+ )
+{
+ BOOL fEnableLocation, fEnableWndProc,
+ fEnableExpression, fEnableLength,
+ fEnableMessages;
+
+ fEnableLocation = FALSE;
+ fEnableWndProc = FALSE;
+ fEnableExpression = FALSE;
+ fEnableLength = FALSE;
+ fEnableMessages = FALSE;
+
+ switch (bpType)
+ {
+ case BPLOC:
+ // Break at Location
+ fEnableLocation = TRUE;
+ break;
+
+ case BPLOCEXPRTRUE:
+ // Break at Location if Expression true
+ fEnableLocation = TRUE;
+ fEnableExpression = TRUE;
+ break;
+
+ case BPLOCEXPRCHGD:
+ // Break at Location if Expression changed
+ fEnableLocation = TRUE;
+ fEnableExpression = TRUE;
+ fEnableLength = TRUE;
+ break;
+
+ case BPEXPRTRUE:
+ // Break when Expression true
+ fEnableExpression = TRUE;
+ break;
+
+ case BPEXPRCHGD:
+ // Break when Expression changed
+ fEnableExpression = TRUE;
+ fEnableLength = TRUE;
+ break;
+
+ case BPWNDPROC:
+ // Break at Wnd Proc
+ fEnableWndProc = TRUE;
+ break;
+
+ case BPWNDPROCEXPRTRUE:
+ // Break at Wnd Proc if Expression true
+ fEnableWndProc = TRUE;
+ fEnableExpression = TRUE;
+ break;
+
+ case BPWNDPROCEXPRCHGD:
+ // Break at Wnd Proc if Expression changed
+ fEnableWndProc = TRUE;
+ fEnableExpression = TRUE;
+ fEnableLength = TRUE;
+ break;
+
+ case BPWNDPROCMSGRCVD:
+ // Break at Wnd Proc if Message Received
+ fEnableWndProc = TRUE;
+ fEnableMessages = TRUE;
+ break;
+
+ case CB_ERR:
+ // no action selected - all controls disabled
+ break;
+
+ default:
+ Dbg(FALSE);
+ }
+
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_SLOCATION), fEnableLocation);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_LOCATION), fEnableLocation);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_SWNDPROC), fEnableWndProc);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_WNDPROC), fEnableWndProc);
+ EnableWindow(GetWindow(GetDlgItem(hDlg, ID_SETBREAK_WNDPROC), GW_CHILD),
+ fEnableWndProc);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_SEXPRESSION), fEnableExpression);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_EXPRESSION), fEnableExpression);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_SLENGTH), fEnableLength);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_LENGTH), fEnableLength);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_MESSAGES), fEnableMessages);
+
+ return;
+} /* SetbreakControls() */
+
+/*** fGetSetbreakControls
+**
+** Synopsis:
+** bool = fGetSetbreakControls( hDlg )
+**
+** Entry:
+** hDlg - handle to current dialog box
+**
+** Returns:
+** TRUE on success and FALSE otherwise
+**
+** Description:
+** Retrieve and validate what's in the controls.
+** Return TRUE if ok, FALSE otherwise.
+*/
+
+BOOL
+fGetSetbreakControls(
+ HWND hDlg
+ )
+{
+ int type;
+ HWND hAction, hLocation, hWndProc, hExpression, hLength, hMessages;
+ char * pch;
+ BOOL fLoc = FALSE;
+ BOOL fWndProc = FALSE;
+ char BigBuffer[255];
+ char Buffer[255];
+ int i;
+
+ hAction = GetDlgItem(hDlg, ID_SETBREAK_ACTION);
+ hLocation = GetDlgItem(hDlg, ID_SETBREAK_LOCATION);
+ hWndProc = GetDlgItem(hDlg, ID_SETBREAK_WNDPROC);
+ hExpression = GetDlgItem(hDlg, ID_SETBREAK_EXPRESSION);
+ hLength = GetDlgItem(hDlg, ID_SETBREAK_LENGTH);
+ hMessages = GetDlgItem(hDlg, ID_SETBREAK_MESSAGES);
+
+ /*
+ ** Step 1. clean out the string
+ */
+
+ rgchT[0] = 0;
+
+ /*
+ ** Step 2. Determine the breakpoint type. This tells us which
+ ** fields we need to get information from. If no type has been
+ ** selected then error.
+ */
+
+ type = (int)SendMessage(hAction, CB_GETCURSEL, 0, 0L);
+ if (type == CB_ERR)
+ {
+ // no action specified
+ MessageBeep(0);
+ SetFocus(hAction);
+ return FALSE;
+ }
+
+ /*
+ ** Step 3. If a location field can be specified get the location field.
+ */
+
+ rgchT[0] = 0;
+ *BigBuffer = '\0';
+
+ if ((type == BPLOC) || (type == BPLOCEXPRTRUE) || (type == BPLOCEXPRCHGD)) {
+
+ fLoc = TRUE;
+ GetDlgItemText(hDlg, ID_SETBREAK_LOCATION,
+ BigBuffer, sizeof(BigBuffer)-1);
+
+ } else if ((type == BPWNDPROC) || (type == BPWNDPROCEXPRTRUE) || (type == BPWNDPROCEXPRCHGD) ||
+ (type == BPWNDPROCMSGRCVD) ) {
+
+ fWndProc = TRUE;
+ SendMessage( hWndProc, WM_GETTEXT, sizeof( BigBuffer ),
+ (LONG)(LPSTR)BigBuffer );
+ }
+
+ if ( fLoc || fWndProc ) {
+
+ //
+ // It can not be an empty string and it and a trailing space
+ // must fit into the command string buffer.
+ //
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if (*pch == 0 || (strlen(pch) > sizeof(rgchT)-2)) {
+ MessageBeep(0);
+ SetFocus(hLocation);
+ return FALSE;
+ }
+
+ _fstrcpy(rgchT, pch);
+ _fstrcat(rgchT, " ");
+
+ if ( fWndProc ) {
+
+ //
+ // Add the WndProc to the list
+ //
+
+ //
+ // If the WndProc is already in the list, remove it.
+ //
+ i = SendMessage( hWndProc, CB_SELECTSTRING, (WPARAM)-1, (LONG)BigBuffer );
+ if ( i != CB_ERR ) {
+ SendMessage( hWndProc, CB_GETLBTEXT, i, (LONG)Buffer );
+ if ( !strcmp( Buffer, BigBuffer )) {
+ SendMessage( hWndProc,
+ CB_DELETESTRING,
+ i,
+ 0L ) ;
+
+ }
+ }
+
+ //
+ // Insert the WndProc at the top of the list
+ //
+ SendMessage( hWndProc,
+ CB_INSERTSTRING,
+ 0,
+ (LONG)(LPSTR)BigBuffer ) ;
+
+ //
+ // We only keep track of the last WNDPROC_HISTORY_SIZE
+ // strings.
+ //
+ while ( SendMessage(hWndProc, CB_GETCOUNT, 0, 0L) > WNDPROC_HISTORY_SIZE ) {
+ SendMessage( hWndProc,
+ CB_DELETESTRING,
+ WNDPROC_HISTORY_SIZE-1,
+ 0L ) ;
+ }
+
+
+ //
+ // Add message (or message class) if one specified.
+ //
+ if (type == BPWNDPROCMSGRCVD ) {
+ if ( *MsgBuffer == '\0' ) {
+ MessageBeep(0);
+ SetFocus(hLocation);
+ return FALSE;
+ }
+ _fstrcat(rgchT, "/M");
+ _fstrcat(rgchT, MsgBuffer );
+ _fstrcat(rgchT, " " );
+ }
+ }
+ }
+
+ /*
+ ** Grab a memory expression if one should exist
+ */
+
+ if ((type == BPLOCEXPRTRUE) || (type == BPEXPRTRUE) ||
+ (type == BPWNDPROCEXPRTRUE)) {
+ *BigBuffer = 0;
+ GetDlgItemText(hDlg, ID_SETBREAK_EXPRESSION, BigBuffer, sizeof(BigBuffer)-1);
+
+ /*
+ ** It can not be empty and it must fix in the buffer
+ */
+
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if ((*pch == 0) || (strlen(pch) > sizeof(rgchT)-2)) {
+ MessageBeep(0);
+ SetFocus(hExpression);
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "?\"");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, "\" ");
+ }
+
+ /*
+ ** Grab a change memory expression if one should exist
+ */
+
+ if ((type == BPLOCEXPRCHGD) || (type == BPEXPRCHGD)) {
+ *BigBuffer = 0;
+ GetDlgItemText(hDlg, ID_SETBREAK_EXPRESSION, BigBuffer, sizeof(BigBuffer)-1);
+
+ /*
+ ** It can not be empty and it must fix in the buffer
+ */
+
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if ((*pch == 0) || (strlen(pch) > sizeof(rgchT)-2)) {
+ MessageBeep(0);
+ SetFocus(hExpression);
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "=\"");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, "\" ");
+
+ /*
+ ** Now get the length
+ */
+
+ *BigBuffer = 0;
+ GetDlgItemText(hDlg, ID_SETBREAK_LENGTH, BigBuffer, sizeof(BigBuffer)-1);
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if (*pch != 0) {
+ if (strlen(pch) > sizeof(rgchT)-4) {
+ MessageBeep(0);
+ SetFocus(hLength);
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "/R");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, " ");
+ }
+ }
+
+
+ /*
+ ** Grab a pass count if it exists
+ */
+
+ *BigBuffer = 0;
+ GetDlgItemText(hDlg, ID_SETBREAK_PASS, BigBuffer, sizeof(BigBuffer)-1);
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if (*pch != 0) {
+ if (strlen(pch) > sizeof(rgchT)-4) {
+ MessageBeep(0);
+ SetFocus(hLocation); //M00QUEST
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "/P");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, " ");
+ }
+
+ /*
+ ** Grab a process if it exists
+ */
+
+ *BigBuffer = 0;
+ GetDlgItemText(hDlg, ID_SETBREAK_PROCESS, BigBuffer, sizeof(BigBuffer)-1);
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if (*pch != 0) {
+ if (strlen(pch) > sizeof(rgchT)-4) {
+ MessageBeep(0);
+ SetFocus(hLocation); //M00QUEST
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "/H");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, " ");
+ }
+
+ /*
+ ** Grab a thread if it exists
+ */
+
+ *BigBuffer = 0;
+ GetDlgItemText(hDlg, ID_SETBREAK_THREAD, BigBuffer, sizeof(BigBuffer)-1);
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if (*pch != 0) {
+ if (strlen(pch) > sizeof(rgchT)-4) {
+ MessageBeep(0);
+ SetFocus(hLocation); //M00QUEST
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "/T");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, " ");
+ }
+
+ /*
+ ** Grab a set of commands if exist
+ */
+
+ *BigBuffer = 0;
+ GetDlgItemText( hDlg, ID_SETBREAK_CMDS, BigBuffer, sizeof(BigBuffer)-1);
+ pch = BigBuffer;
+ while (*pch == ' ') pch++;
+ if (*pch != 0) {
+ if (strlen(pch) > sizeof(rgchT)-6) {
+ MessageBeep(0);
+ SetFocus(hLocation); // M00QUEST
+ return FALSE;
+ }
+
+ _fstrcat(rgchT, "/C\"");
+ _fstrcat(rgchT, pch);
+ _fstrcat(rgchT, "\" ");
+ }
+
+
+ //
+ // If WndProc, add WndProc switch
+ //
+ if ( fWndProc ) {
+ _fstrcat(rgchT, "/W ");
+ }
+
+
+ // If get to here the Breakpoint action has necessary data
+ return TRUE;
+} /* fGetSetbreakControls() */
+
+/*** FillBPListbox
+**
+** Synopsis:
+** void = FillBPListbox(hDlg)
+**
+** Entry:
+** hDlg - handle to dialog box
+**
+** Returns:
+** nothing
+**
+** Description:
+** Fill the breakpoint list box with the current breakpoints.
+**
+*/
+
+VOID
+FillBPListbox(
+ HWND hDlg
+ )
+{
+ HBPT hBpt = 0;
+ HBPT hBpt2;
+ char szBigBuffer[256];
+ int LargestString = 0;
+ SIZE Size;
+ HDC hdc;
+ int Count;
+
+
+ Dbg(BPNextHbpt(&hBpt, bptNext) == BPNOERROR);
+
+ if (hBpt == NULL) {
+ /*
+ ** No breakpoints so grey out the Clear All button
+ */
+
+ EnableWindow( GetDlgItem(hDlg, ID_SETBREAK_CLEARALL), FALSE);
+ } else {
+
+ hdc = GetDC(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT) );
+ Count = 0;
+
+ while (hBpt != NULL) {
+ /*
+ ** M00BUG: check to see if it is marked as deleted and
+ ** if not then display it
+ ** Fix with DeleteBPListbox
+ */
+
+ Dbg(BPGetFinalHbpt( hBpt, &hBpt2 ) == BPNOERROR);
+ Dbg(BPFormatHbpt( hBpt2, szBigBuffer, sizeof(szBigBuffer), BPFCF_ADD_DELETE|BPFCF_ITEM_COUNT) == BPNOERROR);
+
+ GetTextExtentPoint(hdc, szBigBuffer, strlen(szBigBuffer), &Size );
+
+ if ( Size.cx > LargestString ) {
+
+ LargestString = Size.cx;
+
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestString,
+ 0 );
+ }
+
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_ADDSTRING, 0, (LONG)(LPSTR)szBigBuffer);
+
+ Count++;
+
+ /*
+ ** Get the next breakpoint
+ */
+
+ Dbg(BPNextHbpt(&hBpt, bptNext) == BPNOERROR);
+ }
+
+ ReleaseDC(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT), hdc );
+
+ if ( TopIndex != LB_ERR && TopIndex <= Count ) {
+ SendMessage( GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_SETTOPINDEX, TopIndex, 0L);
+ }
+ }
+
+ return;
+} /* FillBPListbox() */
+
+
+/*** AddBPToListBox
+**
+** Synopsis:
+** void = AddBPToListBox( hDlg, hBpt )
+**
+** Entry:
+** hDlg - handle of dialog box containning listbox
+** hBpt - handle of breakpoint to be added
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Updates the breakpoint list box with the just added breakpoint.
+*/
+
+VOID
+AddBPToListBox(
+ HWND hDlg,
+ HBPT hBpt
+ )
+{
+ char szBigBuffer[255];
+ WORD wRet;
+
+ Unused(wRet);
+
+ Dbg(BPFormatHbpt( hBpt, szBigBuffer, sizeof(szBigBuffer), BPFCF_ADD_DELETE) == BPNOERROR);
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_RESETCONTENT, 0, 0L);
+ FillBPListbox(hDlg);
+
+ // When a BP has been added the OK button becomes the default
+
+ BreakDefPushButton(hDlg, IDOK);
+
+ // Clear All must be valid
+
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_CLEARALL), TRUE);
+
+ return;
+} /* AddBPToListBox() */
+
+
+/*** DeleteBPListbox
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Mark the passed bp as deleted and update the breakpoint list box.
+*/
+
+VOID
+DeleteBPListbox(
+ HWND hDlg,
+ int BPNum
+ )
+{
+ HBPT hBpt = 0;
+
+ Dbg(BPNextHbpt( & hBpt, bptNext) == BPNOERROR);
+
+ Assert(hBpt != NULL); // Must be something or we should not
+ // attempt to delete anything
+
+ do {
+ /**** M00BUG -- Need to do a filter for previously delete breakpoints
+ **
+ ** Force refill of listbox
+ */
+
+ if (BPNum == 0) {
+
+ BPDelete( hBpt );
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_RESETCONTENT, 0, 0L);
+
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_ADDSTRING, 0, (LONG)(LPSTR)"");
+
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_RESETCONTENT, 0, 0L);
+
+ FillBPListbox(hDlg);
+ return;
+ }
+ /*
+ ** Move to the next breakpoint
+ */
+
+ BPNum -= 1;
+ BPNextHbpt( &hBpt, bptNext);
+ } while (hBpt != NULL);
+
+ Assert(FALSE); /* Should never get here */
+
+ return;
+Unused(hDlg);
+} /* DeleteBPListbox() */
+
+/*** ClearAllBP
+**
+** Synopsis:
+** void = ClearAllBP( hDlg )
+**
+** Entry:
+** hDlg - handle to dialog box
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Mark all the bps as deleted and clear the listbox
+*/
+
+VOID
+ClearAllBP(
+ HWND hDlg
+ )
+{
+ BPDeleteAll();
+
+ /*
+ ** update the breakpoint list box
+ */
+
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT), LB_RESETCONTENT, 0, 0L);
+ FillBPListbox(hDlg);
+
+ SetFocus(GetDlgItem(hDlg, ID_SETBREAK_ACTION));
+
+ /*
+ ** Grey Delete and Clear All
+ */
+
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_CLEARALL), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_DELETE), FALSE);
+
+ return;
+} /* ClearAllBP() */
+
+/*** EnableBPListbox
+**
+** Synopsis:
+** void = EnableBPListbox(hDlg, iBP, fEnable)
+**
+** Entry:
+** hDlg - handle to the dialog box
+** iBP - Index of breakpoint to be enabled/disabled
+** fEnable - enable (TRUE) or diable (FALSE)
+**
+** Return:
+** Nothing
+**
+** Description:
+** This function is used to either enable or diable an item in the
+** listbox.
+**
+*/
+
+VOID
+EnableBPListbox(
+ HWND hDlg,
+ int iBP,
+ BOOL fEnable
+ )
+{
+ HBPT hBpt = BPLB_HbptOfI(iBP);
+
+ if (hBpt != NULL) {
+ if (fEnable) {
+ BPEnable( hBpt );
+ } else {
+ BPDisable( hBpt );
+ }
+ }
+
+ return;
+} /* EnableBPListbox() */
+
+/*** BPLB_HbptOfI
+**
+** Synopsis:
+** hbpt = BPLB_HbptOfI(iBP)
+**
+** Entry:
+** iBP - index of the breakpoint in the listbox to be retrieved
+**
+** Returns:
+** Handle of the iBP-th breakpoint in the list of breakpoints -- it is
+** assumed that the list box and the list of breakpoints has a one-to-
+** one correspondence.
+**
+*/
+
+HBPT
+BPLB_HbptOfI(
+ int iBP
+ )
+{
+ HBPT hbpt = 0;
+
+ // THere must be some record or we should never have been called.
+
+ Dbg(BPNextHbpt(&hbpt, bptNext) == BPNOERROR);
+ Assert( hbpt != NULL);
+
+ for (;(iBP > 0) && (hbpt != NULL); iBP-= 1) {
+ Dbg( BPNextHbpt( &hbpt, bptNext ) == BPNOERROR );
+ Assert( hbpt != NULL);
+ }
+
+ return hbpt;
+} /* BPLB_HbptOfI() */
+
+/*** OKBP
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Delete any BPs marked for deletion, and reset the BP
+** editing flags. Update the editor screen to reflect any
+** changes.
+*/
+
+VOID
+OKBP(void)
+{
+ ChangeDebuggerState();
+ BPCommit();
+} /* OKBP() */
+
+/*** CancelBP
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Delete any BPs marked as added and reset the BP editing flags.
+*/
+
+VOID
+CancelBP(
+ VOID
+ )
+{
+ BPUnCommit();
+
+ return;
+} /* CancelBP() */
+
+
+BOOL
+BreakFieldsChanged(
+ HWND hDlg
+ )
+{
+ HWND hLocation;
+ HWND hWndProc;
+ HWND hExpression;
+ HWND hLength;
+ HWND hPass;
+ HWND hThread;
+ HWND hProcess;
+ HWND hCommand;
+ char szLocation1[255];
+ char szExpression1[255];
+ char szWndProc1[255];
+ char szPass1[20];
+ char szProcess1[20];
+ char szThread1[20];
+ char szCommand1[255];
+ BOOL Ok = FALSE;
+
+ //
+ // Get the handles to the dialog actions
+ //
+ hLocation = GetDlgItem(hDlg, ID_SETBREAK_LOCATION);
+ hWndProc = GetDlgItem(hDlg, ID_SETBREAK_WNDPROC);
+ hExpression = GetDlgItem(hDlg, ID_SETBREAK_EXPRESSION);
+ hLength = GetDlgItem(hDlg, ID_SETBREAK_LENGTH);
+ hPass = GetDlgItem(hDlg, ID_SETBREAK_PASS);
+ hProcess = GetDlgItem(hDlg, ID_SETBREAK_PROCESS);
+ hThread = GetDlgItem(hDlg, ID_SETBREAK_THREAD);
+ hCommand = GetDlgItem(hDlg, ID_SETBREAK_CMDS);
+
+ SendMessage( hLocation, WM_GETTEXT, sizeof(szLocation1 ), (DWORD)(LPSTR)szLocation1 );
+ SendMessage( hExpression, WM_GETTEXT, sizeof(szExpression1), (DWORD)(LPSTR)szExpression1 );
+ SendMessage( hWndProc, WM_GETTEXT, sizeof(szWndProc1 ), (DWORD)(LPSTR)szWndProc1 );
+ SendMessage( hPass, WM_GETTEXT, sizeof(szPass1 ), (DWORD)(LPSTR)szPass1 );
+ SendMessage( hProcess, WM_GETTEXT, sizeof(szProcess1 ), (DWORD)(LPSTR)szProcess1 );
+ SendMessage( hThread, WM_GETTEXT, sizeof(szThread1 ), (DWORD)(LPSTR)szThread1 );
+ SendMessage( hCommand, WM_GETTEXT, sizeof(szCommand1 ), (DWORD)(LPSTR)szCommand1 );
+
+ if ( strcmp( szLocation ,szLocation1 ) ||
+ strcmp( szExpression,szExpression1 ) ||
+ strcmp( szWndProc ,szWndProc1 ) ||
+ strcmp( szPass ,szPass1 ) ||
+ strcmp( szProcess ,szProcess1 ) ||
+ strcmp( szThread ,szThread1 ) ||
+ strcmp( szCommand ,szCommand1 )
+ ) {
+
+ Ok = TRUE;
+ }
+
+ return Ok;
+}
+
+
+
+/*** SetbreakFields
+**
+** Synopsis:
+** void = SetbreakFields( hDlg, bpIndex );
+**
+** Entry:
+** hDlg - handle to breakpoint dialog box
+** bpIndex - index of breakpoint to have its fields displayed
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Set the contents of the various fields to match the passed bpIndex.
+*/
+
+VOID
+SetbreakFields(
+ HWND hDlg,
+ int bpIndex
+ )
+{
+ HWND hAction;
+ HWND hLocation;
+ HWND hWndProc;
+ HWND hExpression;
+ HWND hLength;
+ HWND hPass;
+ HWND hThread;
+ HWND hProcess;
+ HWND hPassLeft;
+ HWND hCommand;
+ int bpType;
+ HBPT hBpt;
+ HBPT hBpt2;
+ char *pWndProc;
+ int Index;
+
+ //
+ // Get the handles to the dialog actions
+ //
+ hAction = GetDlgItem(hDlg, ID_SETBREAK_ACTION);
+ hLocation = GetDlgItem(hDlg, ID_SETBREAK_LOCATION);
+ hWndProc = GetDlgItem(hDlg, ID_SETBREAK_WNDPROC);
+ hExpression = GetDlgItem(hDlg, ID_SETBREAK_EXPRESSION);
+ hLength = GetDlgItem(hDlg, ID_SETBREAK_LENGTH);
+ hPass = GetDlgItem(hDlg, ID_SETBREAK_PASS);
+ hPassLeft = GetDlgItem(hDlg, ID_SETBREAK_PASSESLEFTCOUNT);
+ hProcess = GetDlgItem(hDlg, ID_SETBREAK_PROCESS);
+ hThread = GetDlgItem(hDlg, ID_SETBREAK_THREAD);
+ hCommand = GetDlgItem(hDlg, ID_SETBREAK_CMDS);
+
+ //
+ // Initialize strings
+ //
+ *szLocation = '\0';
+ *szExpression = '\0';
+ *szLength = '\0';
+ *szWndProc = '\0';
+ *szPass = '\0';
+ *szPassLeft = '\0';
+ *szProcess = '\0';
+ *szThread = '\0';
+ *szCommand = '\0';
+
+ if ( bpIndex == LB_ERR ) {
+
+ //
+ // Nothing selected, clear all and set default action
+ //
+ bpType = BPLOC;
+
+ SendMessage( hAction, CB_SETCURSEL, bpType, 0L );
+
+ SendMessage( hLocation, WM_SETTEXT, 0, (DWORD)(LPSTR)szLocation );
+ SendMessage( hExpression, WM_SETTEXT, 0, (DWORD)(LPSTR)szExpression );
+ SendMessage( hLength, WM_SETTEXT, 0, (DWORD)(LPSTR)szLength );
+ SendMessage( hWndProc, WM_SETTEXT, 0, (DWORD)(LPSTR)szWndProc );
+ SendMessage( hPass, WM_SETTEXT, 0, (DWORD)(LPSTR)szPass );
+ SendMessage( hPassLeft, WM_SETTEXT, 0, (DWORD)(LPSTR)szPassLeft );
+ SendMessage( hProcess, WM_SETTEXT, 0, (DWORD)(LPSTR)szProcess );
+ SendMessage( hThread, WM_SETTEXT, 0, (DWORD)(LPSTR)szThread );
+ SendMessage( hCommand, WM_SETTEXT, 0, (DWORD)(LPSTR)szCommand );
+
+ } else {
+
+ //
+ // Get the i-th breakpoint from the breakpoint list
+ //
+ Dbg( BPNextHbpt( &hBpt2, bptFirst) == BPNOERROR);
+ while ( bpIndex-- ) {
+ Dbg( BPNextHbpt( &hBpt2, bptNext) == BPNOERROR);
+ }
+
+ Assert( hBpt2 != NULL );
+
+ Dbg(BPGetFinalHbpt( hBpt2, &hBpt ) == BPNOERROR);
+ BPQueryBPTypeOfHbpt( hBpt2, &bpType );
+
+ //
+ // Set the action field:
+ //
+ SendMessage(hAction, CB_SETCURSEL, bpType, 0L);
+
+ //
+ // Set the other fields depending on the type:
+ //
+ switch ( bpType ) {
+ case BPLOC:
+ BPQueryLocationOfHbpt( hBpt, szLocation, sizeof(szLocation));
+ break;
+
+ case BPLOCEXPRTRUE:
+ BPQueryLocationOfHbpt( hBpt, szLocation, sizeof(szLocation));
+ BPQueryExprOfHbpt( hBpt, szExpression, sizeof(szExpression));
+ break;
+
+ case BPLOCEXPRCHGD:
+ BPQueryLocationOfHbpt( hBpt, szLocation, sizeof(szLocation));
+ BPQueryMemoryOfHbpt( hBpt, szExpression, sizeof(szExpression));
+ BPQueryMemorySizeOfHbpt( hBpt, szLength, sizeof(szLength));
+ break;
+
+ case BPEXPRTRUE:
+ BPQueryExprOfHbpt( hBpt, szExpression, sizeof(szExpression));
+ break;
+
+ case BPEXPRCHGD:
+ BPQueryMemoryOfHbpt( hBpt, szExpression, sizeof(szExpression));
+ BPQueryMemorySizeOfHbpt( hBpt, szLength, sizeof(szLength));
+ break;
+
+ case BPWNDPROC:
+ BPQueryLocationOfHbpt( hBpt, szWndProc, sizeof(szWndProc));
+ break;
+
+ case BPWNDPROCEXPRTRUE:
+ BPQueryLocationOfHbpt( hBpt, szWndProc, sizeof(szWndProc));
+ BPQueryExprOfHbpt( hBpt, szExpression, sizeof(szExpression));
+ break;
+
+ case BPWNDPROCEXPRCHGD:
+ BPQueryLocationOfHbpt( hBpt, szWndProc, sizeof(szWndProc));
+ BPQueryMemoryOfHbpt( hBpt, szExpression, sizeof(szExpression));
+ BPQueryMemorySizeOfHbpt( hBpt, szLength, sizeof(szLength));
+ break;
+
+ case BPWNDPROCMSGRCVD:
+ BPQueryLocationOfHbpt( hBpt, szWndProc, sizeof(szWndProc));
+ BPQueryMessageOfHbpt( hBpt, MsgBuffer, sizeof( MsgBuffer ));
+ break;
+ }
+
+ if ( *szWndProc ) {
+ if ( pWndProc = strchr( szWndProc, '}' ) ) {
+ pWndProc++;
+ } else {
+ pWndProc = szWndProc;
+ }
+ Index = SendMessage( hWndProc, CB_SELECTSTRING, 0, (LPARAM)pWndProc );
+ if ( Index == LB_ERR ) {
+ SendMessage( hWndProc, CB_ADDSTRING, 0, (DWORD)pWndProc );
+ SendMessage( hWndProc, CB_SELECTSTRING, 0, (LPARAM)pWndProc );
+ }
+ } else {
+ SendMessage( hWndProc, WM_SETTEXT, 0, (DWORD)(LPSTR)szWndProc );
+ }
+
+ BPQueryPassCntOfHbpt( hBpt, szPass, sizeof(szPass));
+ BPQueryPassLeftOfHbpt( hBpt, szPassLeft, sizeof(szPassLeft));
+ BPQueryProcessOfHbpt( hBpt, szProcess, sizeof(szProcess));
+ BPQueryThreadOfHbpt( hBpt, szThread, sizeof(szThread));
+ BPQueryCmdOfHbpt( hBpt, szCommand, sizeof(szCommand) );
+
+ SendMessage( hLocation, WM_SETTEXT, 0, (DWORD)(LPSTR)szLocation );
+ SendMessage( hExpression, WM_SETTEXT, 0, (DWORD)(LPSTR)szExpression );
+ SendMessage( hLength, WM_SETTEXT, 0, (DWORD)(LPSTR)szLength );
+ SendMessage( hPass, WM_SETTEXT, 0, (DWORD)(LPSTR)szPass );
+ SendMessage( hPassLeft, WM_SETTEXT, 0, (DWORD)(LPSTR)szPassLeft );
+ SendMessage( hProcess, WM_SETTEXT, 0, (DWORD)(LPSTR)szProcess );
+ SendMessage( hThread, WM_SETTEXT, 0, (DWORD)(LPSTR)szThread );
+ SendMessage( hCommand, WM_SETTEXT, 0, (DWORD)(LPSTR)szCommand );
+ }
+
+ SetbreakControls(hDlg, bpType );
+
+ return;
+}
+
+
+
+VOID
+FillMsgCombo(
+ HWND hCombo
+ )
+{
+ XOSD xosd;
+ LPMSGMAP MsgMap = NULL;
+ LPMSGINFO MsgInfo;
+
+ xosd = OSDGetMsgMap( LppdCur->hpid, LptdCur->htid, &MsgMap );
+
+ if ( xosd == xosdNone ) {
+
+ DWORD Msg = 0;
+
+ //
+ // Check that messages are sorted
+ //
+ //MsgInfo = MsgMap->MsgInfo;
+ //while ( MsgInfo && MsgInfo->MsgText ) {
+ //
+ // if ( Msg > MsgInfo->Msg ) {
+ // sprintf( "Msg %s is out of sequence!", MsgInfo->MsgText );
+ // MsgBox(GetActiveWindow(), Bf, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ // }
+ // Msg = MsgInfo->Msg;
+ // MsgInfo++;
+ //}
+
+ SendMessage( hCombo, CB_RESETCONTENT, 0, 0L );
+
+ MsgInfo = MsgMap->MsgInfo;
+ while ( MsgInfo && MsgInfo->MsgText ) {
+ SendMessage( hCombo, CB_ADDSTRING, 0, (LONG)MsgInfo->MsgText );
+ MsgInfo++;
+ }
+ }
+}
+
+
+VOID
+SetChooseClass(
+ HWND hDlg,
+ BOOL Enable
+ )
+{
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CHOOSEMESSAGE),
+ BM_SETCHECK, !Enable, 0L );
+
+ EnableWindow(GetDlgItem(hDlg, ID_MESSAGE_MESSAGE), !Enable);
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CHOOSECLASS),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSMOUSE),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSWINDOW),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSINPUT),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSSYSTEM),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSINIT),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSCLIPBOARD),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSDDE),
+ BM_SETCHECK, Enable, 0L );
+
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_CLASSNONCLIENT),
+ BM_SETCHECK, Enable, 0L );
+}
+
+
+BOOL
+WINAPI
+DlgMessage(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+/*++
+
+Routine Description:
+
+ Processes mesages for the "Message" dialog box
+
+Arguments:
+
+ The usual
+
+Return Value:
+
+ The usual
+
+--*/
+{
+ char Buffer[ MAX_PATH ];
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ MsgBuffer[0] = '\0';
+ //
+ // Fill the message combo box
+ //
+ FillMsgCombo( GetDlgItem(hDlg, ID_MESSAGE_MESSAGE) );
+
+ //
+ // Enable/disable the appropriate stuff.
+ //
+ SetChooseClass( hDlg, TRUE );
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam)) {
+
+ case ID_MESSAGE_CHOOSEMESSAGE:
+ SetChooseClass( hDlg, FALSE );
+ SendMessage( GetDlgItem(hDlg,ID_MESSAGE_MESSAGE), CB_SETCURSEL, 0, (LONG)0 );
+ break;
+
+ case ID_MESSAGE_CHOOSECLASS:
+ SetChooseClass( hDlg, TRUE );
+ break;
+
+ case IDOK:
+
+ //
+ // Fill the global MsgBuffer with the
+ // appropriate message/class string
+ //
+ MsgBuffer[0] = '\0';
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CHOOSEMESSAGE ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ //
+ // Single message, make sure that a message was selected
+ // from the message combo.
+ //
+ SendMessage( GetDlgItem(hDlg, ID_MESSAGE_MESSAGE ),
+ WM_GETTEXT, sizeof( MsgBuffer ), (LONG)(LPSTR)MsgBuffer );
+
+ if ( MsgBuffer[0] == '\0' ) {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, DLG_NoMsg, Buffer, sizeof(Buffer)));
+ MsgBox(GetActiveWindow(), Buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ break;
+ }
+
+ } else {
+
+ //
+ // Message class. Check all checkboxes and form
+ // a class string.
+ //
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSMOUSE ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "M" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSWINDOW ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "W" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSINPUT ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "N" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSSYSTEM ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "S" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSINIT ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "I" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSCLIPBOARD ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "C" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSDDE ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "D" );
+ }
+
+ if ( SendMessage( GetDlgItem( hDlg, ID_MESSAGE_CLASSNONCLIENT ),
+ BM_GETCHECK, 0, 0L ) ) {
+
+ strcat( MsgBuffer, "Z" );
+ }
+ }
+
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_MESSAGE_HELP) );
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+VOID
+EnableButtons(
+ HWND hDlg,
+ DWORD LastSelected
+ )
+{
+ EnableWindow( GetDlgItem(hDlg, ID_SETBREAK_DELETE), FALSE );
+ EnableWindow( GetDlgItem(hDlg, ID_SETBREAK_ENABLE), FALSE );
+ EnableWindow( GetDlgItem(hDlg, ID_SETBREAK_DISABLE), FALSE );
+ EnableWindow( GetDlgItem(hDlg, ID_SETBREAK_ADD), TRUE );
+ EnableWindow( GetDlgItem(hDlg, ID_SETBREAK_CHANGE), LastSelected != LB_ERR);
+}
+
+
+/*** DlgSetBreak
+**
+** Synopsis:
+** long = DlgSetBreak(hWnd, msg, wParam, lParam);
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes messages for "SETBREAK" dialog box
+** (Debug Setbreakpoint menu Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+
+BOOL
+WINAPI
+DlgSetBreak(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ char szBuffer[MAX_MSG_TXT];
+ int LastAction;
+ int i;
+ DWORD dwRetVal;
+ HWND hAction = GetDlgItem(hDlg, ID_SETBREAK_ACTION);
+ HWND hWndProc = GetDlgItem(hDlg, ID_SETBREAK_WNDPROC);
+ int NumItems;
+ BOOL Ok;
+ static int LastSelected;
+ static BOOL fEdited;
+ int bpType;
+ HBPT hbpt;
+ BPSTATUS bpstat;
+ int BPNum;
+ int ibp;
+
+
+ switch (message) {
+ case WM_INITDIALOG:
+
+ LastSelected = LB_ERR;
+ TopIndex = LB_ERR;
+ fEdited = FALSE;
+
+ //
+ // Initialise Action combobox
+ //
+ LastAction = DebuggeeActive() ? DBG_Brk_End_Actions : DBG_Brk_End_Actions - 1;
+ for (i = DBG_Brk_Start_Actions; i <= LastAction; i++) {
+ Dbg(LoadString(hInst, i, (LPSTR)szBuffer, sizeof(szBuffer)));
+ dwRetVal = SendMessage(hAction, CB_ADDSTRING, 0, (LONG)(LPSTR)szBuffer);
+ Dbg((dwRetVal!=CB_ERR)||(dwRetVal!=CB_ERRSPACE));
+ }
+
+ //
+ // Initialise WndProc combobox
+ //
+ FillWndProcCombo(hDlg);
+
+ //
+ // Set edit control limits
+ //
+ Dbg(SendDlgItemMessage(hDlg, ID_SETBREAK_LOCATION, EM_LIMITTEXT, MAX_LOCATION-1, 0L));
+ Dbg(SendDlgItemMessage(hDlg, ID_SETBREAK_EXPRESSION, EM_LIMITTEXT, MAX_EXPRESSION-1, 0L));
+ Dbg(SendDlgItemMessage(hDlg, ID_SETBREAK_WNDPROC, CB_LIMITTEXT, MAX_LOCATION-1, 0L));
+ Dbg(SendDlgItemMessage(hDlg, ID_SETBREAK_CMDS, EM_LIMITTEXT, MAX_COMMAND-1, 0L));
+
+ //
+ // Initialise control contents:
+ //
+ // Location field is set to current line number in current
+ // editor file
+ //
+ if (hwndActiveEdit != NULL)
+ if (Views[curView].Doc >= 0)
+ if (Docs[Views[curView].Doc].docType == DOC_WIN)
+ {
+
+ char rgch[MAX_PATH];
+
+ sprintf( rgch, "{,%s,}@", Docs[Views[curView].Doc].FileName );
+
+ _itoa( Views[curView].Y+1, rgch + strlen(rgch), 10);
+ SetDlgItemText(hDlg, ID_SETBREAK_LOCATION, rgch);
+ }
+
+ SendDlgItemMessage(hDlg, ID_SETBREAK_WNDPROC, CB_SETCURSEL, 0, 0L);
+
+ //
+ // Length
+ //
+ _itoa((int)(sizeof(BYTE)), szTmp, 10);
+ SetDlgItemText(hDlg, ID_SETBREAK_LENGTH, szTmp);
+
+ //
+ // Initialise the breakpoint listbox
+ //
+ FillBPListbox(hDlg);
+ NumItems = SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETCOUNT, 0, 0L);
+ if ( NumItems == 0 ) {
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT), FALSE );
+ }
+
+
+
+ //
+ // Initialise message and message class specifier
+ //
+
+ //
+ // Initialise controls according to current selection
+ // in action list box. We start with Break At
+ // Location as default.
+ //
+ SendMessage(hAction, CB_SETCURSEL, BPLOC, 0L);
+
+ SetbreakControls(hDlg, BPLOC);
+
+ SetFocus(hAction);
+
+ PostMessage(hDlg, WU_INFO, ERR_Cant_Modify_BP_While_Running, 0);
+
+ return TRUE;
+
+ case WM_DESTROY:
+ return TRUE;
+
+ case WU_INFO:
+ InformationBox(wParam);
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam)) {
+ case ID_SETBREAK_ACTION:
+ switch (HIWORD(wParam)) {
+ case CBN_SETFOCUS:
+ EnableButtons( hDlg, LastSelected );
+ break;
+
+ case CBN_SELCHANGE:
+ //
+ // Initialise other controls depending on what
+ // action is selected
+ //
+ bpType = SendMessage(hAction, CB_GETCURSEL, 0, 0L);
+ SetbreakControls(hDlg, bpType);
+ //BreakDefPushButton(hDlg, ID_SETBREAK_ADD);
+ fEdited = TRUE;
+ break;
+ }
+ break;
+
+ case ID_SETBREAK_LOCATION:
+ case ID_SETBREAK_EXPRESSION:
+ case ID_SETBREAK_LENGTH:
+ case ID_SETBREAK_PASS:
+ case ID_SETBREAK_PROCESS:
+ case ID_SETBREAK_THREAD:
+ case ID_SETBREAK_CMDS:
+ switch (HIWORD(wParam)) {
+ case EN_SETFOCUS:
+ EnableButtons( hDlg, LastSelected );
+ break;
+
+ case EN_CHANGE:
+ EnableButtons( hDlg, LastSelected );
+ fEdited = TRUE;
+ break;
+ }
+ break;
+
+
+ case ID_SETBREAK_WNDPROC:
+ switch (HIWORD(wParam)) {
+ case CBN_SETFOCUS:
+ EnableButtons( hDlg, LastSelected );
+ break;
+
+ case CBN_SELCHANGE:
+ case CBN_EDITCHANGE:
+ EnableButtons( hDlg, LastSelected );
+ fEdited = TRUE;
+ break;
+ }
+ break;
+
+ case ID_SETBREAK_ADD:
+SetbreakAdd:
+ if (fGetSetbreakControls(hDlg)) {
+ bpstat = BPParse( &hbpt, rgchT, NULL, NULL,
+ (LppdCur != NULL) ? LppdCur->hpid : 0);
+
+ if (bpstat != BPNOERROR) {
+ MessageBeep(0);
+ } else {
+
+ if (DebuggeeActive()) {
+ bpstat = BPBindHbpt( hbpt, NULL );
+ } else {
+ bpstat = BPError;
+ }
+
+ if ( bpstat == BPCancel ) {
+ MessageBeep(0);
+ Dbg(LoadString( hInst, ERR_Breakpoint_Not_Set, szBuffer, sizeof(szBuffer)));
+ MsgBox(GetActiveWindow(), szBuffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ } else {
+ Dbg(BPAddToList( hbpt, -1 ) == BPNOERROR);
+ if ( (bpstat != BPNOERROR) && DebuggeeActive() ) {
+ MessageBeep(0);
+ Dbg(LoadString(hInst,
+ ERR_Breakpoint_Not_Instantiated,
+ szBuffer,
+ sizeof(szBuffer)));
+ MsgBox(GetActiveWindow(),
+ szBuffer,
+ MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+
+ AddBPToListBox( hDlg, hbpt );
+ }
+
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ TRUE );
+ LastSelected = LB_ERR;
+ SetbreakFields(hDlg, LastSelected);
+ SetFocus(hAction);
+
+ }
+ }
+
+ fEdited = FALSE;
+
+ if (LOWORD(wParam) == IDOK) {
+ goto OKPressed;
+ }
+
+ return TRUE;
+
+ case ID_SETBREAK_DELETE:
+SetbreakDelete:
+ BPNum = LastSelected;
+
+ if (BPNum != LB_ERR) {
+
+ TopIndex = SendMessage( GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETTOPINDEX, 0, 0L);
+ DeleteBPListbox(hDlg, BPNum);
+ NumItems = SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETCOUNT, 0, 0L);
+ if ( NumItems == 0 ) {
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT), FALSE );
+ }
+
+ //
+ // After deleting the breakpoint, we must change
+ // the focus and enable the appropriate buttons.
+ //
+ LastSelected = LB_ERR;
+ SetbreakFields(hDlg, LastSelected);
+ SetFocus(hAction);
+
+ } else {
+
+ MessageBeep(0);
+ }
+
+ fEdited = FALSE;
+ return TRUE;
+
+ case ID_SETBREAK_CLEARALL:
+ LastSelected = LB_ERR;
+ ClearAllBP(hDlg);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT), FALSE );
+ fEdited = FALSE;
+ return TRUE;
+
+ case ID_SETBREAK_ENABLE:
+ if (LastSelected != LB_ERR) {
+ TopIndex = SendMessage( GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETTOPINDEX, 0, 0L);
+ EnableBPListbox(hDlg, LastSelected, TRUE);
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_RESETCONTENT, 0, 0L);
+ FillBPListbox(hDlg);
+ LastSelected = LB_ERR;
+ SetbreakFields(hDlg, LastSelected);
+ SetFocus(hAction);
+ } else {
+ MessageBeep(0);
+ }
+ fEdited = FALSE;
+ return TRUE;
+
+ case ID_SETBREAK_DISABLE:
+ if (LastSelected != LB_ERR) {
+ TopIndex = SendMessage( GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETTOPINDEX, 0, 0L);
+ EnableBPListbox(hDlg, LastSelected, FALSE);
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_RESETCONTENT, 0, 0L);
+ FillBPListbox(hDlg);
+ LastSelected = LB_ERR;
+ SetbreakFields(hDlg, LastSelected);
+ SetFocus(hAction);
+ } else {
+ MessageBeep(0);
+ }
+ fEdited = FALSE;
+ return TRUE;
+
+
+ case ID_SETBREAK_CHANGE:
+ if ( (LastSelected != LB_ERR) && fGetSetbreakControls(hDlg)) {
+ bpstat = BPParse( &hbpt, rgchT, NULL, NULL, (LppdCur != NULL) ? LppdCur->hpid : 0);
+ if (bpstat == BPNOERROR) {
+ BPIFromHbpt(&ibp, BPLB_HbptOfI(LastSelected));
+
+ Dbg(BPChange( hbpt, ibp ) == BPNOERROR);
+
+ if (DebuggeeActive()) {
+ bpstat = BPBindHbpt( hbpt, NULL );
+ } else {
+ bpstat = BPError;
+ }
+
+ if ( (bpstat != BPNOERROR) && DebuggeeActive() ) {
+ MessageBeep(0);
+ MsgBox(GetActiveWindow(), "Breakpoint not instantiated", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ }
+
+ TopIndex = SendMessage( GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETTOPINDEX, 0, 0L);
+ SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_RESETCONTENT, 0, 0L);
+
+ FillBPListbox(hDlg);
+ LastSelected = LB_ERR;
+ SetbreakFields(hDlg, LastSelected);
+ SetFocus(hAction);
+
+ } else {
+ MessageBeep(0);
+ }
+ }
+ fEdited = FALSE;
+ return TRUE;
+
+
+ case ID_SETBREAK_BREAKPOINT:
+ switch (HIWORD(wParam)) {
+ case LBN_SETFOCUS:
+
+ LastSelected = SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETCURSEL, 0, 0L);
+
+ if ( LastSelected == LB_ERR ) {
+ NumItems = SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT),
+ LB_GETCOUNT, 0, 0L);
+ if ( NumItems > 0 ) {
+ LastSelected = 0;
+ }
+ }
+
+ if ( LastSelected != LB_ERR ) {
+ EnableBPButtons( hDlg, LastSelected );
+ }
+ break;
+
+
+ case LBN_DBLCLK:
+ //
+ // Try to delete
+ //
+ goto SetbreakDelete;
+
+ case LBN_SELCHANGE:
+ LastSelected = SendMessage(GetDlgItem(hDlg, ID_SETBREAK_BREAKPOINT), LB_GETCURSEL, 0, 0L);
+ if ((LastSelected != LB_ERR)) {
+ SetbreakFields(hDlg, LastSelected);
+ }
+ EnableBPButtons( hDlg, LastSelected );
+ break;
+ }
+ return TRUE;
+
+ //
+ // Important. The tests are done in this order to
+ // get around a bug in Windows whereby more than
+ // button can be set as the default. In our case
+ // this always the OK button that can be set by
+ // mistake so we test this case last.
+ //
+ case IDOK:
+ if ((HWND)lParam == GetDlgItem(hDlg, IDOK)) {
+ goto OKPressed;
+
+ } else if (LOWORD(GetWindowLong(GetDlgItem(hDlg, ID_SETBREAK_DELETE),
+ GWL_STYLE)) == LOWORD(BS_DEFPUSHBUTTON)) {
+
+ //
+ // Take the focus out of the list box and set it
+ // to the breakpoint dialog box.
+ //
+ SetFocus( hDlg );
+ goto SetbreakDelete;
+
+ } else if (LOWORD(GetWindowLong(GetDlgItem(hDlg, ID_SETBREAK_ADD),
+ GWL_STYLE)) == LOWORD(BS_DEFPUSHBUTTON)) {
+ goto SetbreakAdd;
+
+ } else if (LOWORD(GetWindowLong(GetDlgItem(hDlg, IDOK),
+ GWL_STYLE)) == LOWORD(BS_DEFPUSHBUTTON)) {
+OKPressed:
+
+ //
+ // If Edited fields, confirm before ending the dialog
+ //
+ if ( fEdited && BreakFieldsChanged( hDlg ) ) {
+ goto SetbreakAdd;
+ //Ok = (QuestionBox(ERR_BP_Edited,MB_YESNO) == IDYES);
+ } else {
+ Ok = TRUE;
+ }
+
+ if ( Ok ) {
+ OKBP();
+ StoreWndProcHistory(hDlg);
+ EndDialog(hDlg, TRUE);
+ }
+ }
+ return TRUE;
+
+ case IDCANCEL:
+ CancelBP();
+ EndDialog(hDlg, FALSE);
+ fEdited = FALSE;
+ return TRUE;
+
+ case ID_SETBREAK_MESSAGES:
+ StartDialog( DLG_MESSAGES, DlgMessage );
+ break;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, HELP_CONTEXT, ID_SETBREAK_HELP));
+ return TRUE;
+ }
+ break;
+ }
+ }
+
+ return FALSE;
+} /* DlgSetBreak() */
+
+VOID
+EnableBPButtons(
+ IN HWND hDlg,
+ IN int iBP
+ )
+/*++
+
+Routine Description:
+
+ Enables/disables the "Clear", "Enable" and "Disable" windows
+ depending on whether a breakpoint has been marked for deletion
+ or not.
+
+Arguments:
+
+ hDlg - Supplies the dialog handle
+ iBP - Supplies the breakpoint index
+
+Return Value:
+
+ None.
+
+
+--*/
+{
+ HBPT hBpt = 0;
+ BOOL Deleted;
+
+ Dbg(BPNextHbpt( &hBpt, bptNext ) == BPNOERROR);
+
+ do {
+ if (iBP == 0) {
+
+ Deleted = BPIsMarkedForDeletion( hBpt );
+
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_DELETE), !Deleted);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_ENABLE), !Deleted);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_DISABLE), !Deleted);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_CHANGE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_SETBREAK_ADD), FALSE);
+ return;
+ }
+
+ iBP -= 1;
+ Dbg( BPNextHbpt( &hBpt, bptNext ) == BPNOERROR );
+
+ } while (hBpt != NULL);
+}
diff --git a/private/windbg/windbg/sources b/private/windbg/windbg/sources
new file mode 100644
index 000000000..7be69ffce
--- /dev/null
+++ b/private/windbg/windbg/sources
@@ -0,0 +1,122 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Jim Schaad (jimsch)
+
+!ENDIF
+
+MAJORCOMP=windbg
+MINORCOMP=windbg
+
+TARGETNAME=windbg
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+
+SOURCES= \
+ windbg.rc \
+ apisupp.c \
+ arrange.c \
+ breakpts.c \
+ brkpt0.c \
+ callswin.c \
+ cmdexec0.c \
+ cmdexec1.c \
+ cmdexec2.c \
+ cmdwin.c \
+ codemgr.c \
+ colors.c \
+ confirm.c \
+ cp.c \
+ cpuwin.c \
+ cvextras.c \
+ data.c \
+ dbgext.c \
+ dbugdll.c \
+ dbugexcp.c \
+ dbugrun.c \
+ disasm.c \
+ docfile.c \
+ document.c \
+ edit.c \
+ editutil.c \
+ environ.c \
+ find.c \
+ findnext.c \
+ findrep.c \
+ fonts.c \
+ function.c \
+ init.c \
+ line.c \
+ linklist.c \
+ kdopt.c \
+ localwin.c \
+ makeeng.c \
+ memory.c \
+ memwin.c \
+ menu.c \
+ panemgr.c \
+ paneopt.c \
+ paneuser.c \
+ pidtid.c \
+ process.c \
+ program.c \
+ quickw.c \
+ re_mi.c \
+ remote.c \
+ reparse.c \
+ replace.c \
+ ribbon.c \
+ rundebug.c \
+ setbreak.c \
+ status.c \
+ tasklist.c \
+ thread.c \
+ undoredo.c \
+ userctrl.c \
+ userdll.c \
+ util.c \
+ util2.c \
+ vib.c \
+ watch.c \
+ watchwin.c \
+ windbg.c \
+ wrkspace.c
+
+UMTYPE=windows
+
+INCLUDES=..\osdebug\include;include;obj\$(TARGET_DIRECTORY)
+
+!include ..\common.src
+
+C_DEFINES = $(C_DEFINES) -DOSDEBUG
+
+UMLIBS= $(MORE_LIBS) \
+ ..\osdebug\obj\*\osdebug.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\version.lib \
+ $(BASEDIR)\public\sdk\lib\*\mpr.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib \
+ $(BASEDIR)\public\sdk\lib\*\crashlib.lib
+
+NTTARGETFILES=
+NTKEEPRESOURCETMPFILES=1
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
diff --git a/private/windbg/windbg/status.c b/private/windbg/windbg/status.c
new file mode 100644
index 000000000..cf4353ecb
--- /dev/null
+++ b/private/windbg/windbg/status.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright Microsoft 1991
+ *
+ * Date Jan 08, 1991
+ *
+ * Project Asterix/Obelix
+ *
+ * History
+ * Date Initial Description
+ * ---- ------- -----------
+ * - NatSys created
+ * 01-08-91 ChauV completely redesigned
+ * 01-10-91 ChauV changed the width determination algorithm so
+ * the status little windows can be recalculated
+ * according to their text length.
+ *
+ */
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+
+// colors for Textout()
+
+#define FORCOLOR(colorRef) ( StringColors[ colorRef ].FgndColor )
+#define BAKCOLOR(colorRef) ( StringColors[ colorRef ].BkgndColor )
+
+
+/*** StatusTextWndProc
+**
+**
+** Description:
+** WndProc for the StatusText portion of the status bar.
+**
+*/
+LONG FAR PASCAL EXPORT StatusTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ switch (message) {
+ case WM_LBUTTONDBLCLK:
+ if (!(status.errormsg))
+ break;
+
+ }
+ return CallWindowProc(status.lpfnOldStatusTextWndProc, hWnd,
+ message, wParam, lParam);
+} /* StatusTextWndProc() */
+
+
+
+/*** StatusWndProc
+**
+** Synopsis:
+** long = StatusWndProc(hWnd, message, wParam, lParam)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+LONG FAR PASCAL EXPORT
+StatusWndProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ PAINTSTRUCT ps;
+
+ switch (message) {
+ case WM_CREATE:
+ {
+ HWND hwndStatusText;
+ FARPROC lpfnStatusTextWndProc;
+
+ // at creation, the sizes of these buttons are not important
+ // so they all can be zero to save code space.
+ // create status message control
+
+ hwndStatusText = CreateQCQPWindow(
+ (LPSTR)szNull, // Window's title
+ MAKELONG (QCQP_CS_SETRECT, DT_LEFT),// window style + text justification
+ 0, // x position
+ 0, // y position
+ 0, // width
+ 0, // height
+ hWnd, // Parent window's handle
+ (HMENU) ID_STATUS_TXT, // child id
+ hInst, // Instance of window
+ (WPARAM)status.font); // wParam for message WM_COMMAND
+
+ // Sub-class the Status Text window
+
+
+ //lpfnStatusTextWndProc = MakeProcInstance((FARPROC)StatusTextWndProc, hInst);
+
+ lpfnStatusTextWndProc = (FARPROC)StatusTextWndProc;
+
+ status.lpfnOldStatusTextWndProc =
+ (WNDPROC)SetWindowLong(hwndStatusText, GWL_WNDPROC,
+ (LONG)lpfnStatusTextWndProc);
+
+ // create ASM/SRC control
+
+ CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd, (HMENU) ID_STATUS_SRC, hInst, (WPARAM) status.font);
+
+ // create PID control
+
+ CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd, (HMENU) ID_STATUS_CURPID, hInst, (WPARAM) status.font);
+
+ // create TID control
+
+ CreateQCQPWindow((LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd, (HMENU) ID_STATUS_CURTID, hInst, (WPARAM) status.font);
+
+
+ // create multiKey control
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_MULTIKEY,
+ hInst,
+ (WPARAM)status.font);
+
+ // create overtype control
+
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_OVERTYPE,
+ hInst,
+ (WPARAM)status.font);
+
+ // create readOnly control
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_READONLY,
+ hInst,
+ (WPARAM)status.font);
+
+ // create capsLock control
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_CAPSLOCK,
+ hInst,
+ (WPARAM)status.font);
+
+ // create numLock control
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_NUMLOCK,
+ hInst,
+ (WPARAM)status.font);
+
+ // create line control
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_LINE,
+ hInst,
+ (WPARAM)status.font);
+
+ // create column control
+ CreateQCQPWindow(
+ (LPSTR)szNull,
+ MAKELONG (QCQP_CS_SETRECT, DT_CENTER),
+ 0, 0, 0, 0,
+ hWnd,
+ (HMENU) ID_STATUS_COLUMN,
+ hInst,
+ (WPARAM)status.font);
+
+ }
+ break;
+
+ case WM_PAINT:
+ {
+ HPEN blackPen, whitePen, grayPen;
+
+ BeginPaint (hWnd, &ps);
+
+ if ( IsVGAmode && !IsMONOmode ) {
+ //Prepare the pens
+ Dbg(whitePen = GetStockObject(WHITE_PEN));
+ Dbg(grayPen = CreatePen(PS_SOLID, 1, GRAYDARK));
+
+ //Prepare a brush for Status Bar background
+
+ //Draw a top gray line
+
+ Dbg(SelectObject(ps.hdc, grayPen));
+ MoveToX(ps.hdc, ps.rcPaint.left, 0, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, 0);
+
+ //Draw a white line just under
+
+ Dbg(SelectObject(ps.hdc, whitePen));
+ MoveToX(ps.hdc, ps.rcPaint.left, 1, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, 1);
+
+ //%%%To Change (WINDOW background is now in class definition)
+ //Set text background
+ //SetBkColor(ps.hdc, GRAYLIGHT);
+
+ Dbg(DeleteObject(grayPen));
+ } else {
+ // draw the top black line
+
+ Dbg(blackPen = GetStockObject(BLACK_PEN));
+ Dbg(SelectObject(ps.hdc, blackPen));
+ MoveToX(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, NULL);
+ LineTo(ps.hdc, ps.rcPaint.right, ps.rcPaint.top);
+ }
+
+ EndPaint(hWnd, &ps);
+
+ }
+ break;
+
+
+ case WM_DESTROY:
+ {
+ FARPROC lpfnStatusTextWndProc;
+
+ // Unsub-class the StatusText window
+
+ lpfnStatusTextWndProc =
+ (FARPROC)SetWindowLong(
+ GetDlgItem(status.hwndStatus, ID_STATUS_TXT),
+ GWL_WNDPROC,
+ (DWORD)(status.lpfnOldStatusTextWndProc));
+ //FreeProcInstance(lpfnStatusTextWndProc);
+ break;
+ }
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+
+ return FALSE;
+} /* StatusWndProc() */
+
+/*** ResizeStatusLine
+**
+** Synopsis:
+** void = ResizeStatusLine(r)
+**
+** Entry:
+** r -
+**
+** Returns:
+**
+** Description:
+** Recalculate the sizes of the status windows.
+*/
+
+void ResizeStatusLine(
+ LPRECT r)
+{
+ int spacing;
+ HDC hDC;
+ HFONT hFont;
+ SIZE size;
+
+
+ // Force spacing to avoid text being clipped
+
+ spacing = 2;
+
+ //Initialize rectangle's heights
+
+ status.txtR.top =
+ status.rctlSrcMode.top =
+ status.rctlCurPid.top =
+ status.rctlCurTid.top =
+ status.multiKeyR.top =
+ status.overtypeR.top =
+ status.readOnlyR.top =
+ status.capsLockR.top =
+ status.numLockR.top =
+ status.lineR.top =
+ status.columnR.top =
+ // New spacing
+ r->top + spacing + 1;
+
+ status.txtR.bottom =
+ status.rctlSrcMode.bottom =
+ status.rctlCurPid.bottom =
+ status.rctlCurTid.bottom =
+ status.multiKeyR.bottom =
+ status.overtypeR.bottom =
+ status.readOnlyR.bottom =
+ status.capsLockR.bottom =
+ status.numLockR.bottom =
+ status.lineR.bottom =
+ status.columnR.bottom =
+ r->bottom - (spacing - 1);
+
+ // IMPORTANT !!!!
+ // From here on, the width of these windows are determined by its strings
+ // load from the string table plus one extra for spacing and cosmetic reason.
+ // This is done so the width can be easily changed when we decide to go
+ // with a different text. It will be done on the fly.
+ // Also localization don't have to worry about it either.
+ //
+ // Items are adjusted from right to left.
+
+ hDC = GetDC (status.hwndStatus);
+
+ // select new font and save current font handle.
+
+ Dbg(hFont = SelectObject(hDC, status.font));
+
+ //Re-adjust the status bar Column rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.columnS, strlen(status.columnS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.columnS, strlen(status.columnS)));
+#endif
+ status.columnR.right = r->right - 8;
+ status.columnR.left = status.columnR.right - spacing;
+ MoveWindow(GetDlgItem(status.hwndStatus, ID_STATUS_COLUMN),
+ status.columnR.left,
+ status.columnR.top,
+ status.columnR.right - status.columnR.left,
+ status.columnR.bottom - status.columnR.top,
+ FALSE);
+
+ //Re-adjust the status bar Line rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.lineS, strlen(status.lineS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.lineS, strlen(status.lineS)));
+#endif
+ status.lineR.right = status.columnR.left - 1;
+ status.lineR.left = status.lineR.right - spacing ;
+ MoveWindow(GetDlgItem(status.hwndStatus, ID_STATUS_LINE),
+ status.lineR.left,
+ status.lineR.top,
+ status.lineR.right - status.lineR.left,
+ status.lineR.bottom - status.lineR.top,
+ FALSE);
+
+ //Re-adjust the status bar Num Lock rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.numLockS, strlen(status.numLockS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.numLockS, strlen(status.numLockS)));
+#endif
+ status.numLockR.right = status.lineR.left - 6;
+ status.numLockR.left = status.numLockR.right - spacing ;
+ MoveWindow(GetDlgItem(status.hwndStatus, ID_STATUS_NUMLOCK),
+ status.numLockR.left,
+ status.numLockR.top,
+ status.numLockR.right - status.numLockR.left,
+ status.numLockR.bottom - status.numLockR.top,
+ FALSE);
+
+ //Re-adjust the status bar Caps Lock rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.capsLockS, strlen(status.capsLockS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.capsLockS, strlen(status.capsLockS)));
+#endif
+ status.capsLockR.right = status.numLockR.left - 2;
+ status.capsLockR.left = status.capsLockR.right - spacing;
+ MoveWindow(GetDlgItem(status.hwndStatus, ID_STATUS_CAPSLOCK),
+ status.capsLockR.left,
+ status.capsLockR.top,
+ status.capsLockR.right - status.capsLockR.left,
+ status.capsLockR.bottom - status.capsLockR.top,
+ FALSE);
+
+ //Re-adjust the status bar Read Only rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.readOnlyS, strlen(status.readOnlyS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.readOnlyS, strlen(status.readOnlyS)));
+#endif
+ status.readOnlyR.right = status.capsLockR.left - 2;
+ status.readOnlyR.left = status.readOnlyR.right - spacing;
+ MoveWindow (GetDlgItem (status.hwndStatus, ID_STATUS_READONLY),
+ status.readOnlyR.left,
+ status.readOnlyR.top,
+ status.readOnlyR.right - status.readOnlyR.left,
+ status.readOnlyR.bottom - status.readOnlyR.top,
+ FALSE);
+
+ //Re-adjust the status bar Overtype rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.overtypeS, strlen(status.overtypeS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.overtypeS, strlen(status.overtypeS)));
+#endif
+ status.overtypeR.right = status.readOnlyR.left - 2;
+ status.overtypeR.left = status.overtypeR.right - spacing;
+ MoveWindow(GetDlgItem(status.hwndStatus, ID_STATUS_OVERTYPE),
+ status.overtypeR.left,
+ status.overtypeR.top,
+ status.overtypeR.right - status.overtypeR.left,
+ status.overtypeR.bottom - status.overtypeR.top,
+ FALSE);
+
+ //Re-adjust the status bar Multi Key rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.multiKeyS, strlen(status.multiKeyS), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.multiKeyS, strlen(status.multiKeyS)));
+#endif
+ status.multiKeyR.right = status.overtypeR.left - 6;
+ status.multiKeyR.left = status.multiKeyR.right - spacing;
+ MoveWindow (GetDlgItem (status.hwndStatus, ID_STATUS_MULTIKEY),
+ status.multiKeyR.left,
+ status.multiKeyR.top,
+ status.multiKeyR.right - status.multiKeyR.left,
+ status.multiKeyR.bottom - status.multiKeyR.top,
+ FALSE);
+
+ //Re-adjust the status bar Current Tid rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.rgchCurTid, strlen(status.rgchCurTid), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.rgchCurTid, strlen(status.rgchCurTid)));
+#endif
+ status.rctlCurTid.right = status.multiKeyR.left - 6;
+ status.rctlCurTid.left = status.rctlCurTid.right - spacing;
+ MoveWindow (GetDlgItem (status.hwndStatus, ID_STATUS_CURTID),
+ status.rctlCurTid.left,
+ status.rctlCurTid.top,
+ status.rctlCurTid.right - status.rctlCurTid.left,
+ status.rctlCurTid.bottom - status.rctlCurTid.top,
+ FALSE);
+
+ //Re-adjust the status bar PID rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.rgchCurPid, strlen(status.rgchCurPid), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.rgchCurPid, strlen(status.rgchCurPid)));
+#endif
+ status.rctlCurPid.right = status.rctlCurTid.left - 2;
+ status.rctlCurPid.left = status.rctlCurPid.right - spacing;
+ MoveWindow (GetDlgItem (status.hwndStatus, ID_STATUS_CURPID),
+ status.rctlCurPid.left,
+ status.rctlCurPid.top,
+ status.rctlCurPid.right - status.rctlCurPid.left,
+ status.rctlCurPid.bottom - status.rctlCurPid.top,
+ FALSE);
+
+ //Re-adjust the status bar Multi Key rectangle and move it
+
+#ifdef WIN32
+ GetTextExtentPoint(hDC, (LPSTR)status.rgchSrcMode, strlen(status.rgchSrcMode), &size);
+ spacing = 4 + size.cx;
+#else
+ spacing = 4 + LOWORD(GetTextExtent(hDC, (LPSTR)status.rgchSrcMode, strlen(status.rgchSrcMode)));
+#endif
+ status.rctlSrcMode.right = status.rctlCurPid.left - 6;
+ status.rctlSrcMode.left = status.rctlSrcMode.right - spacing;
+ MoveWindow (GetDlgItem (status.hwndStatus, ID_STATUS_SRC),
+ status.rctlSrcMode.left,
+ status.rctlSrcMode.top,
+ status.rctlSrcMode.right - status.rctlSrcMode.left,
+ status.rctlSrcMode.bottom - status.rctlSrcMode.top,
+ FALSE);
+
+ //Set width of message area to left width and move it
+
+ status.txtR.left = 8;
+ status.txtR.right = status.rctlSrcMode.left - 6;
+ MoveWindow (GetDlgItem (status.hwndStatus, ID_STATUS_TXT),
+ status.txtR.left,
+ status.txtR.top,
+ status.txtR.right - status.txtR.left,
+ status.txtR.bottom - status.txtR.top,
+ FALSE);
+
+ // restore the old font
+
+ Dbg(SelectObject(hDC, hFont));
+ ReleaseDC(status.hwndStatus, hDC);
+
+ return;
+} /* ResizeStatusLine() */
diff --git a/private/windbg/windbg/tasklist.c b/private/windbg/windbg/tasklist.c
new file mode 100644
index 000000000..54a67c42f
--- /dev/null
+++ b/private/windbg/windbg/tasklist.c
@@ -0,0 +1,155 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ callswin.c
+
+Abstract:
+
+ This module contains the main line code for display of calls window.
+
+Author:
+
+ Wesley Witt (wesw) 6-Sep-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+#define MAX_TASKS ((1024-sizeof(IOCTLGENERIC))/sizeof(TASK_LIST))
+
+
+
+
+BOOL FAR PASCAL EXPORT
+DlgTaskList(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog procedure for the calls stack options dialog.
+
+Arguments:
+
+ hwnd - window handle
+ msg - message number
+ wParam - first message parameter
+ lParam - second message parameter
+
+Return Value:
+
+ TRUE - did not process the message
+ FALSE - did process the message
+
+--*/
+
+{
+ DWORD i;
+ CHAR buf[80];
+ LPSTR p;
+ PIOCTLGENERIC pig;
+ PTASK_LIST pTask;
+ HANDLE hEvent = NULL;
+ LPSTR fmt;
+
+
+ switch (message) {
+ case WM_INITDIALOG:
+ SendDlgItemMessage( hDlg, ID_TL_TASK_LIST, WM_SETFONT,
+ (WPARAM)GetStockObject( SYSTEM_FIXED_FONT ), (LPARAM)FALSE );
+ if (ConnectDebugger() &&
+ NULL != (pig = (PIOCTLGENERIC) malloc((sizeof(TASK_LIST)*MAX_TASKS) +
+ sizeof(IOCTLGENERIC)))) {
+ ZeroMemory( pig, (sizeof(TASK_LIST)*MAX_TASKS) + sizeof(IOCTLGENERIC) );
+ pig->ioctlSubType = IG_TASK_LIST;
+ pig->length = sizeof(TASK_LIST)*MAX_TASKS;
+ pTask = (PTASK_LIST)pig->data;
+ pTask->dwProcessId = MAX_TASKS;
+ OSDIoctl( LppdCur->hpid, NULL, ioctlGeneric, pig->length + sizeof(IOCTLGENERIC), (LPV)pig );
+ for (i=0; i<MAX_TASKS; i++) {
+ if (pTask[i].dwProcessId == 0) {
+ break;
+ }
+ if (pTask[i].dwProcessId == (DWORD)-2) {
+ pTask[i].dwProcessId = 0;
+ }
+ if ((radix == 10) || (pTask[i].dwProcessId == (DWORD)-1)) {
+ fmt = "%4d %s";
+ } else if (radix == 16) {
+ fmt = "%4x %s";
+ } else {
+ fmt = "%4d %s";
+ }
+ sprintf(buf, fmt, pTask[i].dwProcessId, pTask[i].ProcessName );
+ SendDlgItemMessage( hDlg, ID_TL_TASK_LIST, LB_ADDSTRING, 0, (LPARAM)buf );
+ }
+ if (i) {
+ --i;
+ }
+ SendDlgItemMessage( hDlg, ID_TL_TASK_LIST, LB_SETCURSEL, i, 0 );
+ free( pig );
+ } else {
+ EndDialog( hDlg, TRUE );
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam) {
+ case IDOK :
+ i = SendDlgItemMessage( hDlg, ID_TL_TASK_LIST, LB_GETCURSEL, 0, 0 );
+ SendDlgItemMessage( hDlg, ID_TL_TASK_LIST, LB_GETTEXT, i, (LPARAM)buf );
+
+ buf[4] = 0;
+ i = strtoul( buf, NULL, radix );
+
+ if (i == (DWORD)-1) {
+ if (MessageBox( hDlg,
+ "Are you sure that you want to attach to CSR?",
+ "WinDbg Process Attach",
+ MB_ICONASTERISK | MB_YESNO ) == IDNO) {
+
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+ }
+ }
+
+ sprintf( buf, ".attach 0x%x", i );
+ p = malloc( strlen(buf)+16 );
+ strcpy( p, buf );
+
+ PostMessage(
+ Views[cmdView].hwndClient,
+ WU_LOG_REMOTE_CMD,
+ TRUE,
+ (LPARAM)p
+ );
+
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog( hDlg, TRUE );
+ return TRUE;
+
+ case IDWINDBGHELP:
+ WinHelp( hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)IDM_RUN_ATTACH );
+ return (TRUE);
+ }
+ }
+
+ return FALSE;
+}
diff --git a/private/windbg/windbg/thread.c b/private/windbg/windbg/thread.c
new file mode 100644
index 000000000..676907e5d
--- /dev/null
+++ b/private/windbg/windbg/thread.c
@@ -0,0 +1,402 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Thread.c
+
+Abstract:
+
+ This module contains the functions needed for the Run.Set Thread dialog
+ box.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/********************* Structs & Defines ************************************/
+
+typedef struct {
+ LPTD lptd;
+ BOOL fFreeze;
+ BOOL fSet;
+} A, *PA;
+
+/**************************** DATA ******************************************/
+
+static PA pa = NULL;
+static int ca = 0;
+static char lpstrFreeze[ MAX_MSG_TXT ];
+static char lpstrThaw[ MAX_MSG_TXT ];
+
+static int iTabs[] = { 12, 30, 70, 90, 110, 130 };
+static char szThFmt[] = "%s\t%2d\t%s\t%c %3s\t%s";
+
+/**************************** CODE ******************************************/
+
+static BOOL PASCAL
+ThFormatInfo(
+ PA pa,
+ LPSTR lpTarget,
+ UINT cch,
+ LPTST ptst
+ )
+/*++
+
+Routine Description:
+
+ This routine will format the data associated with a thread for
+ displaying to the user.
+
+Arguments:
+
+ lptd - Supplies internal handle to thread to be formatted
+ lpTarget - Supplies where to place the formatted string
+ cch - Supplies count of characters in buffer
+ ptst - Returns thread state info in structure pointed to
+
+Return Value:
+
+ TRUE if successful and FALSE otherwise
+
+--*/
+{
+
+ XOSD xosd;
+
+ Unreferenced(cch);
+
+ xosd = OSDGetThreadStatus(pa->lptd->lppd->hpid, pa->lptd->htid, ptst);
+
+ if (xosd != xosdNone) {
+ return FALSE;
+ } else {
+ sprintf(lpTarget, szThFmt,
+ (pa->lptd == LptdCur)? " * " : (pa->fSet ? "(*)" : " "),
+ pa->lptd->itid,
+ ptst->rgchThreadID,
+ pa->lptd->fFrozen? 'F' : 'T',
+ pa->fFreeze ? "(F)" : "(T)",
+ ptst->rgchState);
+ }
+
+ return TRUE;
+} /* ThFormatInfo() */
+
+
+static VOID PASCAL
+ThEmptyList(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Destructor for thread list box
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ if (pa) {
+ free( pa );
+ pa = NULL;
+ }
+ ca = 0;
+}
+
+
+static int PASCAL
+ThSetupDlg(
+ HWND hDlg,
+ BOOL fFirsttime
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ HWND h = GetDlgItem(hDlg, ID_THREAD_LIST);
+ char rgch[256];
+ LPTD lptd;
+ LPTD lptdSelect;
+ TST tst;
+ int i, cc;
+
+
+ Assert( h != NULL);
+
+ i = SendMessage(h, LB_GETCURSEL, 0, 0L);
+ SendMessage(h, LB_RESETCONTENT, 0, 0L);
+
+ if (LppdCur) {
+
+ /*
+ * Count the threads in the process.
+ */
+ for (cc=0,lptd=LppdCur->lptdList; lptd; cc++, lptd=lptd->lptdNext) {
+ ;
+ }
+ if (cc != ca) {
+ ca = 0;
+ }
+
+ if (!fFirsttime && ca > 0 && i != LB_ERR) {
+
+ lptdSelect = pa[i].lptd;
+
+ } else if (cc) {
+
+ lptdSelect = LptdCur;
+ ThEmptyList();
+
+ /*
+ * allocate an array to hold state information
+ */
+ ca = cc;
+ pa = (A *) malloc(sizeof(A)*ca);
+ Assert( pa );
+ memset(pa, 0, sizeof(A)*ca);
+
+ /*
+ * Fill it in with initial information.
+ */
+
+ for (i = 0, lptd = LppdCur->lptdList; lptd; i++, lptd = lptd->lptdNext) {
+ pa[i].lptd = lptd;
+ pa[i].fFreeze = lptd->fFrozen;
+ pa[i].fSet = (lptd == LptdCur);
+ }
+ }
+
+ for (i = 0; i < ca; i++) {
+
+ ThFormatInfo(&pa[i], rgch, sizeof(rgch), &tst);
+ SendMessage(h, LB_ADDSTRING, 0, (LONG)(LPSTR) rgch);
+
+ if (pa[i].lptd == lptdSelect) {
+ SetDlgItemText(hDlg,
+ ID_THREAD_FREEZE,
+ pa[i].fFreeze ? lpstrThaw : lpstrFreeze);
+ SendMessage( h, LB_SETCURSEL, i, 0L);
+ }
+ }
+ }
+
+ return ca;
+} /* ThSetupDlg */
+
+
+
+
+BOOL PASCAL FAR EXPORT
+DlgThread(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LONG lParam
+ )
+/*++
+
+Routine Description:
+
+ This function is the dialog procedure for the Thread dialog
+ box. It allows the user to look at the current status of
+ all threads in the current process and manuipulate them.
+
+Arguments:
+
+ hDlg - Handle to dialog window
+ msg - Message to be processed
+ wParam - Info about the mesage
+ lParam - Info about the message
+
+Return Value:
+
+ TRUE if the message was dealt with here and FALSE otherwise
+
+--*/
+{
+ int i;
+
+ UNREFERENCED_PARAMETER( lParam );
+
+ switch ( msg ) {
+
+ case WM_INITDIALOG:
+
+ //
+ // Load the text strings for the Thaw/Freeze button once.
+ //
+
+ if( lpstrFreeze[ 0 ] == 0 ) {
+
+ Dbg( LoadString(
+ GetModuleHandle( NULL ),
+ DLG_Cols_Thaw,
+ lpstrThaw,
+ MAX_MSG_TXT
+ )
+ );
+
+ Dbg( LoadString(
+ GetModuleHandle( NULL ),
+ DLG_Cols_Freeze,
+ lpstrFreeze,
+ MAX_MSG_TXT
+ )
+ );
+ }
+
+ //
+ // set tabs for listbox
+ //
+ SendMessage(GetDlgItem(hDlg, ID_THREAD_LIST),
+ LB_SETTABSTOPS, sizeof(iTabs)/sizeof(*iTabs), (LPARAM)iTabs);
+
+ //
+ // now fill listbox and update freeze/thaw button
+ //
+
+ if (ThSetupDlg( hDlg, TRUE ) > 0) {
+ return TRUE;
+ } else {
+ // Gray everything
+ EnableWindow(GetDlgItem(hDlg, ID_THREAD_FREEZE), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_THREAD_FREEZEALL), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_THREAD_THAWALL), FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_THREAD_SELECT), FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
+ SetFocus(GetDlgItem(hDlg, IDCANCEL));
+ return FALSE;
+ }
+
+
+ case WM_COMMAND:
+
+ switch ( LOWORD(wParam) ) {
+
+ case IDOK:
+
+ //
+ // Lock it all in
+ //
+ for (i = 0; i < ca; i++) {
+
+ if (pa[i].lptd->fFrozen && !pa[i].fFreeze) {
+
+ if (OSDPtrace( osdThaw, 0, 0,
+ LppdCur->hpid,
+ pa[ i ].lptd->htid ) == xosdNone)
+ {
+ pa[i].lptd->fFrozen = FALSE;
+ }
+
+ } else if (!pa[i].lptd->fFrozen && pa[i].fFreeze) {
+
+ if (OSDPtrace(osdFreeze, 0, 0,
+ LppdCur->hpid,
+ pa[ i ].lptd->htid) == xosdNone)
+ {
+ pa[i].lptd->fFrozen = TRUE;
+ }
+ }
+ }
+
+ for (i = 0; i < ca; i++) {
+ if (pa[i].fSet && pa[i].lptd != LptdCur) {
+ LptdCur = pa[i].lptd;
+ LppdCur = LptdCur->lppd;
+ UpdateDebuggerState(UPDATE_WINDOWS);
+ break;
+ }
+ }
+
+ EndDialog( hDlg, TRUE );
+ ThEmptyList();
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog( hDlg, FALSE );
+ ThEmptyList();
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg( WinHelp( hDlg, szHelpFileName, HELP_CONTEXT, ID_THREAD_HELP ));
+ return TRUE;
+
+ case ID_THREAD_FREEZE:
+ i = SendMessage( GetDlgItem( hDlg, ID_THREAD_LIST), LB_GETCURSEL, 0, 0);
+ Assert(i != LB_ERR);
+
+ // this could be a freeze or a thaw:
+ pa[i].fFreeze = !pa[i].fFreeze;
+
+ ThSetupDlg(hDlg, FALSE);
+ return TRUE;
+
+ case ID_THREAD_FREEZEALL:
+ for (i=0; i<ca; i++) {
+ pa[i].fFreeze = TRUE;
+ }
+ ThSetupDlg(hDlg, FALSE);
+ return TRUE;
+
+ case ID_THREAD_THAWALL:
+ for (i=0; i<ca; i++) {
+ pa[i].fFreeze = FALSE;
+ }
+ ThSetupDlg(hDlg, FALSE);
+ return TRUE;
+
+ case ID_THREAD_SELECT:
+ // clear old current thread
+ for (i=0; i<ca; i++) {
+ pa[i].fSet = FALSE;
+ }
+
+ i = SendMessage( GetDlgItem( hDlg, ID_THREAD_LIST), LB_GETCURSEL, 0, 0);
+ pa[i].fSet = TRUE;
+
+ ThSetupDlg(hDlg, FALSE);
+ return TRUE;
+
+ case ID_THREAD_LIST:
+ if (HIWORD(wParam) == LBN_SELCHANGE) {
+ ThSetupDlg(hDlg, FALSE);
+ return TRUE;
+ }
+ break;
+
+ }
+
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/private/windbg/windbg/undoredo.c b/private/windbg/windbg/undoredo.c
new file mode 100644
index 000000000..458744429
--- /dev/null
+++ b/private/windbg/windbg/undoredo.c
@@ -0,0 +1,1199 @@
+/*--Author:
+
+ Griffith Wm. Kadnier (v-griffk) 01-Aug-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+//Prototypes
+
+void NEAR PASCAL LowLevelReadBuf (LPSTR source, long offset, LPSTR dest, WORD size, long limit);
+void NEAR PASCAL LowLevelWriteBuf (LPSTR dest, long offset, LPSTR source, WORD size, long limit);
+void NEAR PASCAL ReadFromBuf (NPUNDOREDOREC p, LPSTR dest, WORD size);
+char NEAR PASCAL ReadCharFromStreamBuf (NPUNDOREDOREC p, WORD disp);
+BOOL NEAR PASCAL WriteToBuf (int doc, NPUNDOREDOREC p, WORD disp, LPSTR source, WORD size, BOOL expanding);
+BOOL NEAR PASCAL InitRecBuf (NPUNDOREDOREC p, long size, BOOL allocateMem);
+
+
+/*** LowLevelReadBuf
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void NEAR PASCAL LowLevelReadBuf(LPSTR source, long offset, LPSTR dest, WORD size, long limit)
+{
+ Assert(offset + size <= limit);
+ _fmemmove(dest, source + offset, size);
+ return;
+} /* LowLevelReadBuf() */
+
+/*** LowLevelWriteBuf
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void NEAR PASCAL LowLevelWriteBuf(LPSTR dest, long offset, LPSTR source, WORD size, long limit)
+{
+ Assert(offset + size <= limit);
+ _fmemmove(dest + offset, source, size);
+ return;
+} /* LowLevelWriteBuf() */
+
+/*** ReadFileFromBuf
+*/
+
+void NEAR PASCAL ReadFromBuf(NPUNDOREDOREC p, LPSTR dest, WORD size)
+{
+ LPSTR source =(LPSTR)p->pRec + p->offset;
+
+ //If read goes beyond buffer end, split in two moves
+ Assert(p->offset + size <= p->bufferSize);
+ _fmemmove(dest, source, size);
+
+ return;
+} /* ReadFromBuf() */
+
+
+/*** ReadLineFromBuf
+*/
+
+void FAR PASCAL ReadLineFromBuf(NPUNDOREDOREC p, LPSTR dest, int *size,
+ int *expandedLen, LPSTR *charsEnd)
+{
+ STREAMREC st;
+ long pos;
+
+ //Read this record header using a safe way (header could spread
+ //over the end and the start of the buf)
+ LowLevelReadBuf((LPSTR)p->pRec, p->offset,
+ (LPSTR)&st, HDR_INSERTSTREAM_SIZE, p->bufferSize);
+ Assert((st.action & ACTIONMASK) == INSERTSTREAM);
+
+ pos = p->offset + HDR_INSERTSTREAM_SIZE + st.x.s.len - (*size);
+
+ //Read sequentially buffer until size == 0 or char is a CR, rewind
+ //to beginning of buffer if we reach end of buffer
+ *charsEnd = dest;
+ while (*size && *((LPSTR)p->pRec + pos) != CR) {
+ if (*((LPSTR)p->pRec + pos) == TAB)
+ *expandedLen += (tabSize - (*expandedLen % tabSize));
+ else
+ (*expandedLen)++;
+ *(*charsEnd)++ = *((LPSTR)p->pRec + pos);
+ pos++;
+ (*size)--;
+ }
+
+ //Append a CR + LF in dest if there is a line
+ if (*size && *((LPSTR)p->pRec + pos) == CR) {
+ (*charsEnd)[0] = CR;
+ (*charsEnd)[1] = LF;
+ }
+
+ return;
+} /* ReadLineFromBuf() */
+
+/*** ReadCharFromStreamBuf
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+char NEAR PASCAL ReadCharFromStreamBuf(NPUNDOREDOREC p, WORD disp)
+{
+ return *((LPSTR)p->pRec + p->offset + HDR_INSERTSTREAM_SIZE + disp);
+} /* ReadCharFromStreamBuf() */
+
+/*** WriteToBuf
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL NEAR PASCAL WriteToBuf(int doc, NPUNDOREDOREC p, WORD disp, LPSTR source,
+ WORD size, BOOL expanding)
+{
+ long oldPos = p->offset + disp;
+ long newPos = p->offset + disp + size;
+ STREAMREC st;
+ BOOL more;
+
+ //This should allways be true
+ Assert((long)size <= p->bufferSize);
+
+ if (expanding && newPos > p->bufferSize) {
+
+ WORD k = 0, len = 0;
+
+ recordBufferOverflow = 0;
+
+ do {
+
+ //Read the record header
+ LowLevelReadBuf((LPSTR)p->pRec, k,
+ (LPSTR)&st, sizeof(st), p->bufferSize);
+
+ //Compute len of the first record
+ switch(st.action & ACTIONMASK) {
+ case DELETESTREAM:
+ len += HDR_DELETESTREAM_SIZE;
+ break;
+ case DELETECHAR:
+ len += HDR_DELETECHAR_SIZE;
+ break;
+ case INSERTSTREAM:
+ len += (WORD) (HDR_INSERTSTREAM_SIZE + st.x.s.len);
+ break;
+ case INSERTCHAR:
+ case REPLACECHAR:
+ len += HDR_INSERTCHAR_SIZE;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ k = len;
+ more = (newPos - len > p->bufferSize);
+
+ if (Docs[doc].recType == REC_REDO && !(st.action & CANCELREC)) {
+
+ //Increment the global record buffer overflow count
+ recordBufferOverflow++;
+
+ return InternalErrorBox(SYS_RedoBufferOverflow);
+ }
+
+ } while (more);
+
+ //Make the move
+ _fmemmove((LPSTR)p->pRec,
+ (LPSTR)p->pRec + len,
+ (WORD)p->offset + disp - len);
+ oldPos -= len;
+ p->offset -= len;
+
+ //The current record is now the first one, set it's previous length
+ //to 0 and write it back (we just write the first word, to avoid
+ //erasing other fields). CAUTION : If prevLen is not first field
+ //of STREAMREC. The guy changing it will have surprises....
+ st.prevLen = 0;
+ LowLevelWriteBuf((LPSTR)p->pRec, 0,
+ (LPSTR)&st, sizeof(st.prevLen), p->bufferSize);
+
+ }
+
+ //Now we can safely write data in buffer
+ LowLevelWriteBuf((LPSTR)p->pRec, oldPos, source, size, p->bufferSize);
+
+ return TRUE;
+} /* WriteToBuf() */
+
+/*** InitRecBuf
+**
+** Synopsis:
+** bool = InitRecBuf(p, size, allocateMem)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL NEAR PASCAL
+InitRecBuf(
+ NPUNDOREDOREC p,
+ long size,
+ BOOL allocateMem
+ )
+{
+ WORD nbRecs;
+ STREAMREC st;
+
+ nbRecs = (WORD) max(2, (WORD)(size / HDR_DELETESTREAM_SIZE));
+ p->bufferSize = nbRecs * HDR_DELETESTREAM_SIZE;
+
+ if (allocateMem) {
+
+ //Allocate record buffer, it is important to be zero inited !
+ if (!(p->h = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
+ p->bufferSize))) {
+ return ErrorBox(SYS_Allocate_Memory);
+ }
+ AuxPrintf(1, "%lu bytes allocated", p->bufferSize);
+
+ //Lock buffer
+ if (FailGlobalLock(p->h, (LPSTR *)&(p->pRec))) {
+ return InternalErrorBox(SYS_Lock_Memory);
+ }
+ }
+
+ //Put a DELETESTREAM + CANCEL in buffer so OpenRec won't try to
+ //alloc a new rec, and to initiate the circular buffer process
+ st.action = DELETESTREAM + CANCELREC;
+ st.prevLen = 0;
+ st.col = 0;
+ st.line = 0;
+ st.x.c.col = 1;
+ st.x.c.line = 0;
+ _fmemmove((LPSTR)p->pRec, (LPSTR)&st, HDR_DELETESTREAM_SIZE);
+
+ //First record
+ p->offset = 0;
+
+ return TRUE;
+}
+
+
+/*** CreateRecBuf
+**
+** Synopsis:
+** bool = CreateRecBuf(doc, recType, bytes)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL CreateRecBuf(int doc, BYTE recType, long bytes)
+{
+ NPDOCREC docs = &Docs[doc];
+ UNDOREDOREC p;
+
+ if (docs->recType == REC_STOPPED)
+ return TRUE;
+
+ switch(recType) {
+ case REC_UNDO :
+ p = docs->undo;
+ docs->playCount = REC_CANNOTUNDO; //Normal editing mode for now
+ break;
+
+ case REC_REDO :
+ {
+ struct tm *lt;
+
+ p = docs->redo;
+
+ //Redo Buffer needs to be bigger than undo buf, to potentially
+ //contain the characters in the existing text, so we allocate
+ //the size of undo buffer + size of text.
+
+ bytes = min(docs->undo.bufferSize + CountCharsInDocument(doc),
+ UNDOREDO_MAX_SIZE);
+
+ lt = localtime(&docs->time);
+ mC = lt->tm_mon;
+ dL = lt->tm_mday - 1;
+ }
+ break;
+
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ //Allocates and initialize buffer
+ if (!InitRecBuf(&p, bytes, TRUE))
+ return FALSE;
+
+ DbgX(GlobalUnlock(p.h) == 0);
+
+ //Set document record pointer to new record
+ switch(recType) {
+ case REC_UNDO :
+ docs->undo = p;
+ break;
+ case REC_REDO :
+ docs->redo = p;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+} /* CreateRecBuf() */
+
+/*** DestroyRecBuf
+**
+*/
+
+BOOL FAR PASCAL DestroyRecBuf(int doc, WORD recType)
+{
+ NPDOCREC docs = &Docs[doc];
+ HANDLE h;
+
+ if (docs->recType == REC_STOPPED)
+ return TRUE;
+
+ switch(recType) {
+ case REC_UNDO :
+ h = docs->undo.h;
+ break;
+ case REC_REDO :
+ h = docs->redo.h;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ if ((h != 0) && (GlobalFree (h) != NULL))
+ return InternalErrorBox(SYS_Free_Memory);
+
+ switch(recType) {
+ case REC_UNDO :
+ docs->undo.h = 0;
+ break;
+ case REC_REDO :
+ docs->redo.h = 0;
+ docs->playCount = 0;
+ docs->recType = REC_UNDO;
+ break;
+ case REC_STOPPED :
+ return TRUE;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+} /* DestroyRecBuf() */
+
+
+/*** ResizeRecBuf
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL ResizeRecBuf(int doc, long bytes)
+{
+
+ NPDOCREC docs = &Docs[doc];
+
+ if (docs->recType == REC_STOPPED)
+ return TRUE;
+
+ //Destroy Redo Buffer if any
+ if (docs->redo.h)
+ DestroyRecBuf(doc, REC_REDO);
+
+ if (docs->undo.h) {
+
+ //Destroy Undo Buffer
+ DestroyRecBuf(doc, REC_UNDO);
+ return CreateRecBuf(doc, REC_UNDO, bytes);
+ }
+ else
+ //Create Undo Buffer
+ return CreateRecBuf(doc, REC_UNDO, bytes);
+} /* ResizeRecBuf() */
+
+
+/*** OpenRec
+**
+*/
+
+BOOL FAR PASCAL OpenRec(int doc, BYTE action, int col, int line)
+{
+ NPDOCREC docs = &Docs[doc];
+ UNDOREDOREC p;
+ WORD hdrSize;
+ STREAMREC st;
+
+ switch(docs->recType) {
+ case REC_UNDO :
+ p = docs->undo;
+ break;
+ case REC_REDO :
+ p = docs->redo;
+ break;
+ case REC_STOPPED :
+ case REC_HADOVERFLOW :
+ return TRUE;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ //Lock buffer, will stay used and locked until CloseRec
+ if (FailGlobalLock(p.h, (LPSTR *)&(p.pRec)))
+ return InternalErrorBox(SYS_Lock_Memory);
+
+ //Get last rec to compute new rec address
+ ReadFromBuf(&p, (LPSTR)&st, (WORD)sizeof(st));
+
+ //First rec is or not a existing rec
+ switch(st.action & ACTIONMASK) {
+ case DELETESTREAM:
+ hdrSize = HDR_DELETESTREAM_SIZE;
+ break;
+ case DELETECHAR:
+ hdrSize = HDR_DELETECHAR_SIZE;
+ break;
+ case INSERTSTREAM:
+ hdrSize = (WORD) (HDR_INSERTSTREAM_SIZE + st.x.s.len);
+ break;
+ case INSERTCHAR:
+ case REPLACECHAR:
+ hdrSize = HDR_INSERTCHAR_SIZE;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ //If type is CANCEL then don't change offset in buf
+ if (!(st.action & CANCELREC)) {
+ p.offset += hdrSize;
+ st.prevLen = hdrSize;
+ }
+
+ st.action = (BYTE)action;
+ if (stopMarkStatus == HAS_STOP)
+ st.action += STOPMARK;
+ else if (stopMarkStatus == NEXT_HAS_NO_STOP) {
+ st.action += STOPMARK;
+ stopMarkStatus = HAS_NO_STOP;
+ }
+ st.col = (BYTE)col;
+ st.line = line;
+
+
+ //Adjust buffer to chars start if we insert a block
+ if ((action & ACTIONMASK) == INSERTSTREAM
+ || (action & ACTIONMASK) == REPLACECHAR)
+ st.x.s.len = 0;
+
+ //Update last rec in buffer
+ if (!WriteToBuf(doc, &p, 0, (LPSTR)&st, (WORD)sizeof(st), TRUE))
+ return FALSE;
+
+ //Set document record pointer to new record
+ switch(docs->recType) {
+ case REC_UNDO :
+ docs->undo = p;
+ break;
+ case REC_REDO :
+ docs->redo = p;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+ return TRUE;
+} /* OpenRec() */
+
+/*** CloseRec
+**
+*/
+
+void FAR PASCAL CloseRec(int doc, int col, int line, BOOL keepRec)
+{
+ NPDOCREC docs = &Docs[doc];
+ UNDOREDOREC p;
+ STREAMREC st;
+
+ switch(docs->recType) {
+ case REC_UNDO :
+ p = docs->undo;
+ break;
+ case REC_REDO :
+ p = docs->redo;
+ break;
+ case REC_STOPPED :
+ case REC_HADOVERFLOW :
+ return;
+ default:
+ Assert(FALSE);
+ return;
+ break;
+ }
+
+ //Get last rec from buffer
+ ReadFromBuf(&p, (LPSTR)&st, (WORD)sizeof(st));
+
+ if (keepRec) {
+
+ if ((st.action & ACTIONMASK) == DELETESTREAM) {
+
+ //Cancel if we delete 0 chars and check if we delete 1 char
+ if (col == st.col +1 && line == st.line)
+ st.action += (DELETECHAR - DELETESTREAM);
+ else if (col == (int)st.col && line == st.line)
+ st.action += CANCELREC;
+ else {
+ //Deleting a stream, save ending coordinates
+ st.x.c.col = (BYTE)col;
+ st.x.c.line = line;
+ }
+ }
+ else {
+
+ //Replacing char
+ if ((st.action & ACTIONMASK) == REPLACECHAR)
+ st.x.ch = st.x.s.chars[0];
+ else {
+
+ //Inserting : If length of chars == 0 then cancel record, if
+ //it's one char, put it in the special stucture
+ if (st.x.s.len == 1) {
+ st.action += (INSERTCHAR - INSERTSTREAM);
+ st.x.ch = st.x.s.chars[0];
+ }
+ else if (st.x.s.len == 0)
+ st.action += CANCELREC;
+ }
+ }
+ }
+ else
+ //Tells OpenRec to cancel this record
+ st.action += CANCELREC;
+
+ //Update last rec in buffer
+ WriteToBuf(doc, &p, 0, (LPSTR)&st, (WORD)sizeof(st), FALSE);
+
+ //%if (docs->recType == REC_UNDO)
+ //% AuxPrintf(1, "CloseRec REC_UNDO First = %lu", p.first);
+ //%else
+ //% AuxPrintf(1, "CloseRec REC_REDO First = %lu", p.first);
+
+ DbgX(GlobalUnlock(p.h) == 0);
+
+ return;
+} /* CloseRec() */
+
+/*** AppendToRec
+**
+*/
+
+BOOL FAR PASCAL AppendToRec(int doc, LPSTR chars, int size, BOOL isLine, int *totalSize)
+{
+ NPDOCREC docs = &Docs[doc];
+ UNDOREDOREC p;
+ STREAMREC st;
+
+ if (docs->recType == REC_STOPPED
+ || docs->recType == REC_HADOVERFLOW)
+ return TRUE;
+
+ switch(docs->recType) {
+ case REC_UNDO :
+ p = docs->undo;
+ break;
+ case REC_REDO :
+ p = docs->redo;
+ break;
+ case REC_STOPPED :
+ return TRUE;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ //Get last rec from buffer
+ ReadFromBuf(&p, (LPSTR)&st, (WORD)sizeof(st));
+
+ Assert((st.action & ACTIONMASK) == INSERTSTREAM
+ || (st.action & ACTIONMASK) == REPLACECHAR);
+
+ //Updates total size
+ if (totalSize) {
+ *totalSize += size;
+ if (isLine)
+ *totalSize += 2;
+
+ //Before to write data, check for a possible buffer overflow
+ if ((long)(*totalSize + HDR_INSERTSTREAM_SIZE) > p.bufferSize)
+ return FALSE;
+ }
+
+ if (size) {
+ if (!WriteToBuf(doc, &p, (WORD)(HDR_INSERTSTREAM_SIZE + st.x.s.len), chars,
+ (WORD) size, TRUE))
+ return FALSE;
+ st.x.s.len += (WORD) size;
+
+ //Update last rec in buffer (but only the x.s.len field)
+ WriteToBuf(doc, &p, HDR_INSERTSTREAM_SIZE - sizeof(STREAM),
+ (LPSTR)&st.x.s, sizeof(WORD), FALSE);
+
+ }
+
+ if (isLine) {
+ if (!WriteToBuf(doc, &p, (WORD)(HDR_INSERTSTREAM_SIZE + st.x.s.len),
+ (LPSTR)CrLf, 2, TRUE))
+ return FALSE;
+ st.x.s.len += 2;
+
+ //Update last rec in buffer (but only the x.s.len field)
+ WriteToBuf(doc, &p, HDR_INSERTSTREAM_SIZE - sizeof(STREAM),
+ (LPSTR)&st.x.s, sizeof(WORD), FALSE);
+ }
+
+ //Set document record pointer to new record
+ switch(docs->recType) {
+ case REC_UNDO :
+ docs->undo = p;
+ break;
+ case REC_REDO :
+ docs->redo = p;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/*** PlayRec
+**
+**
+*/
+
+BOOL FAR PASCAL PlayRec(int doc, WORD recType, BOOL untilUserMark, BOOL prompt)
+{
+
+ NPDOCREC docs = &Docs[doc];
+ int j = 0;
+ BOOL endOfRec = FALSE;
+ UNDOREDOREC p;
+ STREAMREC st;
+ WORD action;
+ int line;
+ int col;
+ BOOL more;
+ BOOL pass1 = TRUE;
+
+ if (docs->recType == REC_STOPPED) {
+ return FALSE;
+ }
+
+ Assert(curView >= 0 && curView < MAX_VIEWS);
+
+ switch(recType) {
+
+ case REC_UNDO :
+ //%AuxPrintf(1, "PLAY AN UNDO");
+ docs->recType = REC_REDO;
+
+ p = docs->undo;
+ //If we start replay, we lock undo buffer and we create redo buffer
+ if (docs->playCount == 0) {
+ CreateRecBuf(doc, REC_REDO, p.bufferSize);
+ }
+
+ ClearSelection(curView);
+
+ break;
+
+ case REC_REDO :
+ //%AuxPrintf(1, "PLAY A REDO");
+
+ //Were we at end of undos ?
+ if (docs->playCount < 0)
+ docs->playCount = -docs->playCount;
+
+ p = docs->redo;
+ docs->recType = REC_UNDO;
+ ClearSelection(curView);
+ break;
+
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ if (FailGlobalLock(p.h, (LPSTR *)&(p.pRec))) {
+ InternalErrorBox(SYS_Lock_Memory);
+ return FALSE;
+ }
+
+ //Tells the editor that we are playing
+
+ playingRecords = TRUE;
+
+ //We will stop playing when find a record with required
+ //stop condition, but at least, we play one
+ more = TRUE;
+ while (more) {
+#ifdef DBCS
+ STREAMREC *pstSave = (STREAMREC *)((LPSTR)p.pRec + p.offset);
+#endif
+
+ //Get rec from buffer
+ ReadFromBuf(&p, (LPSTR)&st, (WORD)sizeof(st));
+
+ action = st.action;
+
+ //Test if we will stop after this replay
+ if (untilUserMark) {
+ more = !(action & USERMARK);
+ } else {
+ more = !(action & STOPMARK);
+ }
+ endOfRec = (st.prevLen == 0);
+ if (endOfRec) {
+ more = FALSE;
+ }
+
+ //If we are in a multiple replay, we insert the STOP in opposite
+ //record buffer only if we replay the first one
+ if (!pass1) {
+ stopMarkStatus = HAS_NO_STOP;
+ }
+
+ if (!(action & CANCELREC)) {
+ col = st.col;
+ line = st.line;
+
+ switch(action & ACTIONMASK) {
+
+ case DELETESTREAM :
+ //%AuxPrintf(1, "DELETESTREAM from (%i,%i) to (%i,%i)",
+ //% col, line, st.x.c.col, st.x.c.line);
+ //DeleteStream(doc, col, line,
+ //st.x.c.col, st.x.c.line, FALSE);
+ DeleteBlock(doc, col, line,
+ st.x.c.col, st.x.c.line);
+ break;
+
+ case DELETECHAR :
+ //%AuxPrintf(1, "DELETECHAR at (%i,%i)", col, line);
+ //DeleteStream(doc, col, line, st.col + 1,
+ //st.line, FALSE);
+ DeleteBlock(doc, col, line, st.col + 1, st.line);
+ break;
+
+ case INSERTSTREAM :
+ //InsertStream(doc, col, line, st.x.s.len, NULL, FALSE);
+ InsertBlock(doc, col, line, st.x.s.len, NULL);
+
+ //If stream is a CR+LF, we need to reposition
+ //cursor at begin of next line
+
+ if (st.x.s.len == 2
+ && ReadCharFromStreamBuf(&p, 1) == LF) {
+ line++;
+ col = 0;
+ }
+#ifdef DBCS
+ if (action & REPLACEDBCS) {
+ col += st.x.s.len;
+ }
+#endif
+ break;
+
+ case INSERTCHAR :
+ //%AuxPrintf(1, "INSERTCHAR at (%i,%i) '%c'",
+ //% col, line, st.x.ch);
+ //InsertStream(doc, col, line, 1, (LPSTR)&st.x.ch, FALSE);
+ InsertBlock(doc, col, line, 1, (LPSTR)&st.x.ch);
+
+ //Reposition cursor after char
+ col++;
+
+ break;
+
+ case REPLACECHAR :
+ //%AuxPrintf(1, "REPLACECHAR at (%i,%i) '%c'",
+ //% col, line, st.x.ch);
+ //ReplaceChar(doc, col, line, st.x.ch, FALSE);
+ ReplaceCharInBlock(doc, col, line, st.x.ch);
+ col++;
+ break;
+
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ //Reposition Cursor taking care of tabs
+
+ PosXY(curView, col, line, FALSE);
+
+ //%AuxPrintf(1, "Cursor at (%i,%i)", col, line);
+
+ //Update tape counter
+ if (recType == REC_UNDO) {
+ docs->playCount += 1 - recordBufferOverflow;
+ if (prompt)
+ StatusText(STA_Undo, STATUS_INFOTEXT, TRUE,
+ abs(docs->playCount));
+ }
+ else {
+ docs->playCount--;
+ if (prompt)
+ StatusText(STA_Redo, STATUS_INFOTEXT, TRUE,
+ abs(docs->playCount));
+ }
+ }
+
+ //Prepare next play for the next record (going backward in buffer)
+ if (!endOfRec)
+ p.offset -= st.prevLen;
+ else {
+
+ if (recType == REC_UNDO) {
+ if (prompt)
+ StatusText(STA_End_Of_Undo, STATUS_INFOTEXT, FALSE);
+ } else {
+ if (prompt)
+ StatusText(STA_End_Of_Redo, STATUS_INFOTEXT, FALSE);
+ }
+ }
+
+#ifdef DBCS
+ // Restore "REPLACEDBCS" flag.
+ // Because some action can modify this flag.
+ pstSave = (STREAMREC *)((LPSTR)p.pRec + p.offset);
+ if (action & REPLACEDBCS) {
+ pstSave->action |= REPLACEDBCS;
+ } else {
+ pstSave->action &= ~(REPLACEDBCS);
+ }
+#endif
+ pass1 = FALSE;
+ if (recType == REC_UNDO)
+ docs->undo = p;
+ else
+ docs->redo = p;
+ }
+
+ stopMarkStatus = HAS_STOP;
+ playingRecords = FALSE;
+
+ switch(recType) {
+
+ case REC_UNDO :
+
+ //See if we have not played the first record
+ if (endOfRec) {
+
+ //Convention to know we are at end of undos
+ docs->playCount = -docs->playCount;
+
+ //Reinitialize undo buffer
+ InitRecBuf(&p, p.bufferSize, FALSE);
+ }
+
+ DbgX(GlobalUnlock(docs->undo.h) == 0);
+
+ break;
+
+ case REC_REDO :
+ DbgX(GlobalUnlock(docs->redo.h) == 0);
+ break;
+
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+ return TRUE;
+} /* PlayRec() */
+
+/*** CheckRecBuf
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL FAR PASCAL CheckRecBuf(int doc, WORD recType)
+{
+ NPDOCREC docs = &Docs[doc];
+ UNDOREDOREC p;
+ STREAMREC st;
+ int i = 0;
+ BOOL endOfRec;
+ WORD action, hdrSize;
+ long size = 0;
+
+ if (docs->recType == REC_STOPPED)
+ return TRUE;
+
+ switch(recType) {
+ case REC_UNDO :
+ //%AuxPrintf(1, "Checking Undo Buffer for document #%i", doc);
+ p = docs->undo;
+ break;
+ case REC_REDO :
+ //%AuxPrintf(1, "Checking Redo Buffer for document #%i", doc);
+ p = docs->redo;
+ break;
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ if (p.h == 0) {
+ AuxPrintf(1, "No buffer");
+ return TRUE;
+ }
+
+ if (FailGlobalLock(p.h, (LPSTR *)&(p.pRec))) {
+ InternalErrorBox(SYS_Lock_Memory);
+ return TRUE;
+ }
+
+ endOfRec = FALSE;
+ while (!endOfRec) {
+
+ //Get rec from buffer
+ ReadFromBuf(&p, (LPSTR)&st, (WORD)sizeof(st));
+
+ action = st.action;
+ if (action > REPLACECHAR + STOPMARK + USERMARK + CANCELREC)
+ return AuxPrintf(1, "Record #%i Offset:%lu Bad Header\a", i, p.offset);
+
+ if (p.offset == 0 && st.prevLen !=0)
+ return AuxPrintf(1, "Record #%i Offset:%lu First has a non zero len\a", i, p.offset);
+
+ switch(action & ACTIONMASK) {
+
+ case DELETESTREAM :
+ if (st.line == st.x.c.line) {
+ if (st.col >= st.x.c.col)
+ return AuxPrintf(1, "Record #%i Offset:%lu Bad columns numbers\a", i, p.offset);
+ }
+ else {
+ if (st.line > st.x.c.line)
+ return AuxPrintf(1, "Record #%i Offset:%lu Bad lines numbers\a", i, p.offset);
+ }
+ hdrSize = HDR_DELETESTREAM_SIZE;
+ break;
+
+ case DELETECHAR:
+ hdrSize = HDR_DELETECHAR_SIZE;
+ break;
+
+ case INSERTSTREAM:
+ hdrSize = (WORD) (HDR_INSERTSTREAM_SIZE + st.x.s.len);
+ break;
+
+ case INSERTCHAR:
+ case REPLACECHAR:
+ hdrSize = HDR_INSERTCHAR_SIZE;
+ break;
+
+ default:
+ return AuxPrintf(1, "Record #%i Offset:%lu Unknow action\a", i, p.offset);
+ break;
+ }
+
+ endOfRec = (st.prevLen == 0);
+ if (!endOfRec)
+ p.offset -= st.prevLen;
+ i++;
+ size += hdrSize;
+
+ if (size > p.bufferSize)
+ return AuxPrintf(1, "Record #%i Offset:%lu Bad pointers\a", i, p.offset);
+ }
+
+ DbgX(GlobalUnlock(p.h) == 0);
+
+} /* CheckRecBuf() */
+
+/*** DumpRec
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void FAR PASCAL DumpRec(int doc, WORD recType)
+{
+
+ NPDOCREC docs = &Docs[doc];
+ char s[512], t[50];
+ int j, i = 0;
+ UNDOREDOREC p;
+ STREAMREC st;
+ BOOL endOfRec;
+ WORD action;
+
+ if (docs->recType == REC_STOPPED)
+ return;
+
+ switch(recType) {
+ case REC_UNDO :
+ AuxPrintf(1, "Dumping Undo Buffer");
+ p = docs->undo;
+ break;
+ case REC_REDO :
+ AuxPrintf(1, "Dumping Redo Buffer");
+ p = docs->redo;
+ break;
+ default:
+ Assert(FALSE);
+ return;
+ break;
+ }
+
+ if (p.h == 0) {
+ AuxPrintf(1, "No buffer");
+ return;
+ }
+
+ if (FailGlobalLock(p.h, (LPSTR *)&(p.pRec))) {
+ InternalErrorBox(SYS_Lock_Memory);
+ return;
+ }
+
+ endOfRec = FALSE;
+ while (!endOfRec) {
+
+ //Get rec from buffer
+ ReadFromBuf(&p, (LPSTR)&st, (WORD)sizeof(st));
+
+ action = st.action;
+
+ t[0] = '\0';
+ if (action & STOPMARK)
+ strcat(t, "STOP ");
+ if (action & USERMARK)
+ strcat(t, "USER ");
+ if (action & CANCELREC)
+ strcat(t, "CANCEL ");
+
+ switch(action & ACTIONMASK) {
+
+ case DELETESTREAM :
+ AuxPrintf(1, "%3i : DELETESTREAM from (%i,%i) to (%i,%i) %s",
+ i, st.col, st.line, st.x.c.col, st.x.c.line, (LPSTR)t);
+ break;
+
+ case DELETECHAR :
+ AuxPrintf(1, "%3i : DELETECHAR at (%i,%i) %s",
+ i, st.col, st.line, (LPSTR)t);
+ break;
+
+ case INSERTSTREAM :
+ if (st.x.s.len < 512) {
+ if ((long) (p.offset + HDR_INSERTSTREAM_SIZE) >= p.bufferSize)
+ p.offset -= p.bufferSize;
+ LowLevelReadBuf((LPSTR)p.pRec,
+ p.offset + HDR_INSERTSTREAM_SIZE,
+ (LPSTR)s, st.x.s.len, p.bufferSize);
+ s[st.x.s.len] = '\0';
+ for (j = 0; j < (int)strlen(s); j++) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(s[j]) && s[j+1]) {
+ j++;
+ continue;
+ }
+#endif
+ if (s[j] == CR)
+ s[j] = 'Ä';
+ if (s[j] == LF)
+ s[j] = '¿';
+ }
+ }
+ else
+ strcpy(s,"too long");
+ AuxPrintf(1, "%3i : INSERTSTREAM at (%i,%i) '%s' [%i] %s",
+ i, st.col, st.line, (LPSTR)s, strlen(s), (LPSTR)t);
+ break;
+
+ case INSERTCHAR :
+ AuxPrintf(1, "%3i : INSERTCHAR at (%i,%i) '%c' %s",
+ i, st.col, st.line, st.x.ch, (LPSTR)t);
+ break;
+
+ case REPLACECHAR :
+ AuxPrintf(1, "%3i : REPLACECHAR at (%i,%i) '%c' %s",
+ i, st.col, st.line, st.x.ch, (LPSTR)t);
+ break;
+
+ default:
+ Assert(FALSE);
+ return;
+ break;
+ }
+
+ endOfRec = (st.prevLen == 0);
+ if (!endOfRec)
+ p.offset -= st.prevLen;
+
+ i++;
+
+ }
+
+ DbgX(GlobalUnlock(p.h) == 0);
+
+ return;
+} /* DumpRec() */
diff --git a/private/windbg/windbg/userctrl.c b/private/windbg/windbg/userctrl.c
new file mode 100644
index 000000000..27238d2ab
--- /dev/null
+++ b/private/windbg/windbg/userctrl.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright Microsoft 1991
+ *
+ * Date Jan 09, 1991
+ *
+ * Project Asterix/Obelix
+ *
+ * History
+ * Date Initial Description
+ * ---- ------- -----------
+ * 01-09-91 ChauV Created for use with Tools and Status bars.
+ *
+ */
+
+#include "precomp.h"
+#pragma hdrstop
+
+// colors for Textout()
+
+#define FORCOLOR(colorRef) ( StringColors[ colorRef ].FgndColor )
+#define BAKCOLOR(colorRef) ( StringColors[ colorRef ].BkgndColor )
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
+/* begin definitions ********************************************************/
+
+// definitions for brush & pen colors
+#define GRAYBRUSH RGB (192, 192, 192)
+#define WHITEBRUSH RGB (255, 255, 255)
+#define BLACKBRUSH RGB ( 0, 0, 0)
+#define DARKGRAYBRUSH RGB (132, 132, 132)
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
+/* begin static function prototypes *****************************************/
+
+/* user defined Rectangular box */
+/*static*/ void DrawSetRect(HWND, LPRECT, LPSTR);
+
+void DrawBitmapButton (HWND, LPRECT) ;
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
+/* begin variable definitions ***********************************************/
+
+static BOOL bTrack = FALSE ; // mouse down flag
+static WORD wOldState ; // preserve the control state just before
+ // a button is being pushed.
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
+/*** EnableQCQPCtrl
+**
+** Synopsis:
+** void = EnableQCQPCtrl(hWnd, id, fEnable)
+**
+** Entry:
+** hWnd - parent's handle
+** id - control's ID
+** fEnable - FALSE for disable
+**
+** Returns:
+** nothing
+**
+** Description:
+** This function enable or disable a control identified by the the
+** parent's handle and the control's ID. If enable is FALSE, the control
+** is grayed, otherwise it is activated. This function is only valid to
+** pushbutton style (QCQP_CS_PUSHBUTTON).
+**
+*/
+
+void EnableQCQPCtrl(HWND hWnd, int id, BOOL enable)
+{
+ HWND hwndControl;
+
+ hwndControl = GetDlgItem(hWnd, id);
+
+ if (!enable)
+ {
+ if ((id == ID_RIBBON_SMODE) || (id == ID_RIBBON_AMODE))
+ {
+ SetWindowWord(hwndControl, CBWNDEXTRA_STATE, STATE_PUSHED);
+ }
+ else
+ {
+ SetWindowWord(hwndControl, CBWNDEXTRA_STATE, STATE_GRAYED);
+ }
+
+ }
+ else
+ SetWindowWord(hwndControl, CBWNDEXTRA_STATE, STATE_NORMAL);
+
+ InvalidateRect(hwndControl, (LPRECT)NULL, FALSE);
+
+ return;
+} /* EnableQCQPCtrl() */
+
+/*** GetBitmapIndex
+**
+** Synopsis:
+** word = GetBitmapIndex(state)
+**
+** Entry:
+** state -
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+WORD NEAR PASCAL GetBitmapIndex(WORD State)
+{
+ switch (State) {
+ case STATE_NORMAL:
+ return CBWNDEXTRA_BMAP_NORMAL;
+
+ case STATE_PUSHED:
+ return CBWNDEXTRA_BMAP_PUSHED;
+
+ case STATE_GRAYED:
+ return CBWNDEXTRA_BMAP_GREYED;
+
+ default:
+ Assert(FALSE);
+ }
+} /* GetBitmapIndex() */
+
+
+/*** CreateQCQPWindow
+**
+** Synopsis:
+** hwnd = CreateQCQPWindow(lpszWindowName, dwStyle, x, y, dx, dy
+** hParent, hMenu, hInstance, wMessage)
+**
+** Entry:
+** lpszWindowName -
+** dwStyle -
+** x -
+** y -
+** dx -
+** dy -
+** hParent -
+** hMenu -
+** hInstance -
+** wMessage -
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+HWND CreateQCQPWindow(LPSTR lpWindowName,
+ DWORD dwStyle,
+ int x,
+ int y,
+ int dx,
+ int dy,
+ HWND hParent,
+ HMENU hMenu,
+ HANDLE hInstance,
+ WPARAM wMessage)
+{
+ HWND hTemp ;
+ char class[MAX_MSG_TXT] ;
+ WORD BaseId;
+ WORD State;
+ HBITMAP hBitmap;
+
+ Dbg(LoadString(hInstance, SYS_QCQPCtrl_wClass, class, MAX_MSG_TXT)) ;
+ hTemp = CreateWindow(
+ (LPSTR)class, // Window class name
+ lpWindowName, // Window's title
+ WS_CHILD | WS_VISIBLE, // window created visible
+ x, y, // X, Y
+ dx, dy, // Width, Height of window
+ hParent, // Parent window's handle
+ hMenu, // child's id
+ hInstance, // Instance of window
+ NULL); // Create struct for WM_CREATE
+
+ if (hTemp != NULL) {
+ SetWindowWord (hTemp, CBWNDEXTRA_STYLE, LOWORD(dwStyle)) ;
+ SetWindowWord (hTemp, CBWNDEXTRA_BITMAP, HIWORD(dwStyle)) ;
+ SetWindowWord (hTemp, CBWNDEXTRA_STATE, STATE_NORMAL) ;
+ SetWindowHandle (hTemp, CBWNDEXTRA_MESSAGE, wMessage) ;
+
+ if (LOWORD(dwStyle) == QCQP_CS_PUSHBUTTON) {
+ // Load the bitmaps and store the handles
+ switch (HIWORD(dwStyle)) {
+ case IDS_CTRL_TRACENORMAL:
+ case IDS_CTRL_TRACEPUSHED:
+ case IDS_CTRL_TRACEGRAYED:
+ BaseId = VGA_TRACE_NORMAL;
+ break;
+
+ case IDS_CTRL_STEPNORMAL:
+ case IDS_CTRL_STEPPUSHED:
+ case IDS_CTRL_STEPGRAYED:
+ BaseId = VGA_STEP_NORMAL;
+ break;
+
+ case IDS_CTRL_BREAKNORMAL:
+ case IDS_CTRL_BREAKPUSHED:
+ case IDS_CTRL_BREAKGRAYED:
+ BaseId = VGA_BREAK_NORMAL;
+ break;
+
+ case IDS_CTRL_GONORMAL:
+ case IDS_CTRL_GOPUSHED:
+ case IDS_CTRL_GOGRAYED:
+ BaseId = VGA_GO_NORMAL;
+ break;
+
+ case IDS_CTRL_HALTNORMAL:
+ case IDS_CTRL_HALTPUSHED:
+ case IDS_CTRL_HALTGRAYED:
+ BaseId = VGA_HALT_NORMAL;
+ break;
+
+ case IDS_CTRL_QWATCHNORMAL:
+ case IDS_CTRL_QWATCHPUSHED:
+ case IDS_CTRL_QWATCHGRAYED:
+ BaseId = VGA_QWATCH_NORMAL;
+ break;
+
+ case IDS_CTRL_SMODENORMAL:
+ case IDS_CTRL_SMODEPUSHED:
+ case IDS_CTRL_SMODEGRAYED:
+ BaseId = VGA_SMODE_NORMAL;
+ break;
+
+ case IDS_CTRL_AMODENORMAL:
+ case IDS_CTRL_AMODEPUSHED:
+ case IDS_CTRL_AMODEGRAYED:
+ BaseId = VGA_AMODE_NORMAL;
+ break;
+
+
+ case IDS_CTRL_FORMATNORMAL:
+ case IDS_CTRL_FORMATPUSHED:
+ case IDS_CTRL_FORMATGRAYED:
+ BaseId = VGA_FORMAT_NORMAL;
+ break;
+
+
+ default:
+
+
+ Assert(FALSE);
+ }
+
+ // Load the bitmaps for each state for the button
+ for (State = STATE_NORMAL; State <= STATE_GRAYED; State++) {
+
+ Dbg(hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE( BaseId + State )));
+
+ SetWindowHandle(hTemp, GetBitmapIndex(State), (WPARAM)hBitmap);
+ }
+ }
+ }
+
+ return hTemp ;
+} /* CreateQCQPWindow() */
+
+
+/*** QCQPCtrlWndProc
+**
+** Synopsis:
+** long = QCQPCtrlWndProc(hWnd, iMessage, wParam, lParam)
+**
+** Entry:
+** hWnd
+** iMessage
+** wParam
+** lParam
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+LONG FAR PASCAL EXPORT QCQPCtrlWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LONG lParam)
+{
+ PAINTSTRUCT ps ;
+ char szText [128] ;
+ WPARAM wStyle ;
+ RECT r ;
+
+ wStyle = GetWindowWord (hWnd, CBWNDEXTRA_STYLE) ;
+ switch ( iMessage ) {
+ case WM_CREATE:
+ bTrack = FALSE ;
+ break ;
+
+ case WM_PAINT:
+ GetClientRect (hWnd, (LPRECT)&r) ;
+
+ BeginPaint (hWnd, &ps) ;
+
+ switch ( wStyle ) {
+ case QCQP_CS_SETRECT:
+ GetWindowText (hWnd, (LPSTR)szText, sizeof (szText)) ;
+ DrawSetRect(hWnd, (LPRECT)&r, (LPSTR)szText);
+ break ;
+
+ case QCQP_CS_PUSHBUTTON:
+ case QCQP_CS_LATCHBUTTON:
+ DrawBitmapButton (hWnd, (LPRECT)&r) ;
+ break ;
+
+ default:
+ break ;
+ }
+
+ EndPaint (hWnd, &ps) ;
+ break ;
+
+ case WM_LBUTTONUP:
+ if ( GetWindowWord (hWnd, CBWNDEXTRA_STATE) != STATE_GRAYED ) {
+ bTrack = FALSE ;
+ ReleaseCapture () ;
+ switch (wStyle) {
+ case QCQP_CS_PUSHBUTTON:
+ // Only change the state and send message back to parent
+ // if state is not normal. This prevent user from clicking
+ // the mouse on the button then dragging it outside of
+ // the button.
+
+ if (GetWindowWord (hWnd, CBWNDEXTRA_STATE) != STATE_NORMAL) {
+ SetWindowWord (hWnd, CBWNDEXTRA_STATE, STATE_NORMAL) ;
+ InvalidateRect (hWnd, (LPRECT)NULL, FALSE) ;
+
+ // Send information back to where the function key is being
+ // used for the same purpose.
+
+ SendMessage (GetParent (hWnd),
+ WM_COMMAND,
+ (WPARAM) GetWindowHandle (hWnd, CBWNDEXTRA_MESSAGE),
+ MAKELONG(0, GetDlgCtrlID (hWnd))) ;
+ }
+ break ;
+
+ case QCQP_CS_LATCHBUTTON:
+ if (GetWindowWord (hWnd, CBWNDEXTRA_STATE) != wOldState) {
+ if (wOldState == STATE_NORMAL)
+ SetWindowWord (hWnd, CBWNDEXTRA_STATE, STATE_ON) ;
+ else
+ SetWindowWord (hWnd, CBWNDEXTRA_STATE, STATE_NORMAL) ;
+
+ InvalidateRect (hWnd, (LPRECT)NULL, FALSE) ;
+
+ // Send information back to where the function key is being
+ // used for the same purpose.
+
+ SendMessage (GetParent (hWnd),
+ WM_COMMAND,
+ (WPARAM) GetWindowHandle (hWnd, CBWNDEXTRA_MESSAGE),
+ MAKELONG(0, GetDlgCtrlID (hWnd))) ;
+ }
+ break ;
+ }
+ }
+ break ;
+
+ case WM_LBUTTONDOWN:
+ if ( GetWindowWord (hWnd, CBWNDEXTRA_STATE) != STATE_GRAYED ) {
+ bTrack = TRUE ;
+ wOldState = GetWindowWord (hWnd, CBWNDEXTRA_STATE) ;
+ switch (wStyle) {
+ case QCQP_CS_PUSHBUTTON:
+ case QCQP_CS_LATCHBUTTON:
+ SetWindowWord (hWnd, CBWNDEXTRA_STATE, STATE_PUSHED) ;
+ InvalidateRect (hWnd, (LPRECT)NULL, FALSE) ;
+ break ;
+ }
+ SetCapture (hWnd) ;
+ }
+ break ;
+
+ case WM_MOUSEMOVE:
+ if ( GetWindowWord (hWnd, CBWNDEXTRA_STATE) != STATE_GRAYED ) {
+ if ( bTrack ) {
+ int x, y ;
+
+ x = LOWORD (lParam) ; // get x position
+ y = HIWORD (lParam) ; // get y position
+ GetClientRect (hWnd, &r) ;
+
+ // if mouse position is outside of button area, bring it
+ // back to its old state stored in wOldState.
+
+ if ( ((x < r.left) || (x > r.right)) ||
+ ((y < r.top) || (y > r.bottom)) ) {
+ // redraw the button only if it's not in normal position.
+ if ( GetWindowWord (hWnd, CBWNDEXTRA_STATE) != wOldState ) {
+ SetWindowWord (hWnd, CBWNDEXTRA_STATE, wOldState) ;
+ InvalidateRect (hWnd, (LPRECT)NULL, FALSE) ;
+ }
+ } else {
+ // redraw the button only if it's not in pushed position.
+
+ if ( GetWindowWord (hWnd, CBWNDEXTRA_STATE) != STATE_PUSHED ) {
+ SetWindowWord (hWnd, CBWNDEXTRA_STATE, STATE_PUSHED) ;
+ InvalidateRect (hWnd, (LPRECT)NULL, FALSE) ;
+ }
+ }
+ }
+ }
+ break ;
+
+ default:
+ return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
+ break ;
+ }
+ return 0L ;
+} /* QCQPCtrlWndProc() */
+
+/*** DrawSetRect
+**
+** Synopsis:
+** void = DrawSetRect(hWnd, rect, lpsz)
+**
+** Entry:
+** hWnd
+** r
+** text
+**
+** Returns:
+** nothing
+**
+** Description:
+**
+*/
+
+void DrawSetRect(HWND hWnd, LPRECT r, LPSTR text)
+{
+ HDC hDC;
+ HBRUSH OurBrush; // Brush for this rectangle
+ BOOL DeleteOurBrush; // TRUE if must delete OurBrush after use
+ HBRUSH OldBrush; // Save previous brush
+ HPEN OldPen; // Save previous pen
+ COLORREF OldTextColour; // Save previous text color
+ int OldBkMode; // Save previous background mode
+ HFONT OldFont; // Save previous font handle
+ COLORREF DarkShadow; // shadow box colors for left & top lines
+ COLORREF LightShadow; // shadow box colors for bottom & right lines
+ RECT OurRect;
+ HDC hMemDC;
+ HBITMAP hBitmap;
+ HBITMAP OldBitmap;
+ POINT BitMapSize;
+ HDC hUseDC;
+
+ OurRect = *r;
+
+ Dbg(hDC = GetDC(hWnd));
+
+ hMemDC = CreateCompatibleDC(hDC);
+
+ BitMapSize.x = OurRect.right-OurRect.left+1;
+ BitMapSize.y = OurRect.bottom-OurRect.top+1;
+ hBitmap = CreateCompatibleBitmap(
+ hDC,
+ BitMapSize.x,
+ BitMapSize.y);
+
+ if (hMemDC && hBitmap) {
+ OldBitmap = SelectObject(hMemDC, hBitmap);
+ hUseDC = hMemDC;
+ } else {
+ // Can't do it in memory, so do it direct to the screen
+ hUseDC = hDC;
+ }
+
+
+ if (IsVGAmode && !IsMONOmode) {
+ // VGA mode has 3-D effects
+
+ DarkShadow = DARKGRAYBRUSH;
+ LightShadow = WHITEBRUSH;
+ } else {
+ // other modes including VGA mono has 2-D effects
+
+ DarkShadow = BLACKBRUSH;
+ LightShadow = BLACKBRUSH;
+ }
+
+ // First we draw the two-tone border:
+
+ OurRect.bottom--;
+ OurRect.right--;
+
+ Dbg(OldPen = SelectObject(hUseDC, CreatePen(PS_SOLID, 1, DarkShadow)));
+ MoveToX(hUseDC, OurRect.left, OurRect.bottom, NULL);
+ LineTo(hUseDC, OurRect.left, OurRect.top);
+ LineTo(hUseDC, OurRect.right, OurRect.top);
+
+ // This deletes the pen we just created too
+
+ Dbg(DeleteObject(SelectObject(hUseDC, CreatePen(PS_SOLID, 1, LightShadow))));
+ LineTo(hUseDC, OurRect.right, OurRect.bottom);
+ LineTo(hUseDC, OurRect.left, OurRect.bottom);
+
+ // Put old pen back
+
+ Dbg(DeleteObject(SelectObject(hUseDC, OldPen)));
+
+
+ // Set up foreground/background according to message type
+
+ if ((hWnd == GetDlgItem(status.hwndStatus, ID_STATUS_TXT)) &&
+ (status.errormsg)) {
+ // Background is the colour same as ErrorLine
+
+ Dbg(OurBrush = CreateSolidBrush(/*BAKCOLOR(DLG_Cols_ErrorLine)*/GRAYBRUSH));
+ DeleteOurBrush = TRUE;
+ OldTextColour = SetTextColor(hUseDC, /*FORCOLOR(DLG_Cols_ErrorLine)*/ BLACKBRUSH);
+ } else {
+ // Background is the same colour as main status window
+
+#ifdef WIN32
+ DbgX(OurBrush = (HBRUSH) GetClassHandle(status.hwndStatus, GCL_HBRBACKGROUND));
+#else
+ Dbg(OurBrush = (HBRUSH) GetClassWord(status.hwndStatus, GCW_HBRBACKGROUND));
+#endif
+ DeleteOurBrush = FALSE;
+ OldTextColour = SetTextColor(hUseDC, BLACKBRUSH);
+ }
+
+// OurBrush = (HBRUSH) CreateSolidBrush( 0x0000ff );
+
+#ifdef NTBUG
+ Dbg(OldBrush = SelectObject(hUseDC, OurBrush));
+#else
+ OldBrush = SelectObject(hUseDC, OurBrush);
+#endif
+
+ // FillRect fills from (top, left) to (bottom-1, right-1) so...
+
+ OurRect.top++;
+ OurRect.left++;
+
+ FillRect(hUseDC, &OurRect, OurBrush);
+#ifndef NTBUG
+if (OldBrush)
+#endif
+ Dbg(SelectObject(hUseDC, OldBrush));
+ if (DeleteOurBrush) {
+ Dbg(DeleteObject(OurBrush));
+ }
+
+ // Draw the text:
+
+ // First choose our font
+
+ Dbg(OldFont = SelectObject(hUseDC, GetWindowHandle(hWnd, CBWNDEXTRA_FONT)));
+
+ OldBkMode = SetBkMode(hUseDC, TRANSPARENT);
+
+ // Finally output the text
+
+ DrawText(hUseDC,
+ text,
+ lstrlen(text),
+ &OurRect,
+ (WORD) (GetWindowWord(hWnd, CBWNDEXTRA_TEXTFORMAT) | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP));
+
+ if (hUseDC == hMemDC) {
+ // Now blt it onto the screen
+
+ DPtoLP(hDC, &BitMapSize, 1);
+ BitBlt(hDC, r->left, r->top, BitMapSize.x, BitMapSize.y,
+ hMemDC, 0, 0, SRCCOPY);
+
+ SelectObject(hMemDC, OldBitmap);
+ DeleteObject(hBitmap);
+ }
+
+ // Put everything back as it was before:
+
+ SetTextColor(hUseDC, OldTextColour);
+ SetBkMode(hUseDC, OldBkMode);
+ Dbg(SelectObject(hUseDC, OldFont));
+ if (hMemDC) {
+ DeleteDC(hMemDC);
+ }
+ ReleaseDC(hWnd, hDC);
+} /* DrawSetRect() */
+
+/*** DrawBitmapButton
+**
+** Synopsis:
+** void = DrawBitmapButton(hWnd, r)
+**
+** Entry:
+** hWnd
+** r
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+**
+*/
+
+void DrawBitmapButton (HWND hWnd, LPRECT r)
+{
+ HDC hDC, hMemoryDC ;
+ HBITMAP hBitmap, hTempBitmap ;
+ int OldStretchMode ;
+ BITMAP Bitmap ;
+ WORD State;
+
+ State = (WORD) GetWindowWord(hWnd, CBWNDEXTRA_STATE);
+ hBitmap = GetWindowHandle(hWnd, GetBitmapIndex(State));
+
+ hDC = GetDC (hWnd) ;
+ Dbg(hMemoryDC = CreateCompatibleDC (hDC));
+ Dbg(GetObject (hBitmap, sizeof(BITMAP), (LPSTR) &Bitmap));
+
+ // save the current bitmap handle.
+ Dbg(hTempBitmap = SelectObject (hMemoryDC, hBitmap));
+
+ OldStretchMode = SetStretchBltMode (hDC, COLORONCOLOR);
+ StretchBlt (hDC, r->left, r->top,
+ r->right, r->bottom,
+ hMemoryDC, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY);
+
+ SetStretchBltMode(hDC, OldStretchMode);
+
+ // restore the old bitmap back into DC
+
+ SelectObject(hMemoryDC, hTempBitmap);
+ Dbg(DeleteDC(hMemoryDC));
+ Dbg(ReleaseDC(hWnd, hDC));
+
+ return;
+} /* DrawBitmapButton() */
+
+/*** FreeBitmaps
+**
+** Synopsis:
+** void = FreeBitmaps(hwnd, ctrlId)
+**
+** Entry:
+** hwnd -
+** ctrlId -
+**
+** Returns:
+** nothing
+**
+** Description;
+**
+*/
+
+void NEAR PASCAL FreeBitmaps(HWND hwndRibbon, int CtrlId)
+{
+ HWND hwndCtrl;
+ WORD State;
+ HBITMAP hBitmap;
+
+ hwndCtrl = GetDlgItem(hwndRibbon, CtrlId);
+
+ for (State = STATE_NORMAL; State <= STATE_GRAYED; State++) {
+ hBitmap = (HBITMAP)GetWindowHandle(hwndCtrl, GetBitmapIndex(State));
+ Dbg(DeleteObject(hBitmap));
+ }
+} /* FreeBitmaps() */
+
+/*** FreeRibbonBitmaps
+**
+** Synopsis:
+** void = FreeRibbonBitmaps(hwnd)
+**
+** Entry:
+** hwnd
+**
+** Returns:
+** nothing
+**
+** Description:
+**
+*/
+
+void PASCAL FreeRibbonBitmaps(HWND hwndRibbon)
+{
+ FreeBitmaps(hwndRibbon, ID_RIBBON_GO);
+ FreeBitmaps(hwndRibbon, ID_RIBBON_HALT);
+
+ FreeBitmaps(hwndRibbon, ID_RIBBON_BREAK);
+ FreeBitmaps(hwndRibbon, ID_RIBBON_QWATCH);
+
+ FreeBitmaps(hwndRibbon, ID_RIBBON_TRACE);
+ FreeBitmaps(hwndRibbon, ID_RIBBON_STEP);
+
+ FreeBitmaps(hwndRibbon, ID_RIBBON_SMODE);
+ FreeBitmaps(hwndRibbon, ID_RIBBON_AMODE);
+
+
+ FreeBitmaps(hwndRibbon, ID_RIBBON_FORMAT);
+
+
+
+} /* FreeRibbonBitmaps() */
diff --git a/private/windbg/windbg/userdll.c b/private/windbg/windbg/userdll.c
new file mode 100644
index 000000000..2eef04653
--- /dev/null
+++ b/private/windbg/windbg/userdll.c
@@ -0,0 +1,1462 @@
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// Externals
+//
+extern LPSHF Lpshf;
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// Module List stuff
+//
+// This list contains the default symbol load actions for all
+// modules. It is kept in the shell so it can be saved and loaded
+// from a workspace and modified by the user before loading any
+// debugger DLL.
+//
+///////////////////////////////////////////////////////////////////////
+
+//
+// How to search for a module
+//
+typedef enum _MATCHKIND {
+ MATCH_FULLPATH,
+ MATCH_FILENAME,
+ MATCH_BASENAME
+} MATCHKIND;
+
+//
+// These flags tell us what to do with the module
+//
+#define MOD_FLAG_NONE 0x00000000
+#define MOD_FLAG_TO_ADD 0x00000001
+#define MOD_FLAG_TO_DELETE 0x00000002
+#define MOD_FLAG_TO_MODIFY 0x00000004
+
+//
+// Node in the Module load list
+//
+typedef struct _MOD_NODE *PMOD_NODE;
+typedef struct _MOD_NODE {
+ PMOD_NODE Prev;
+ PMOD_NODE Next;
+ CHAR Name[ MAX_PATH ];
+ SHE SheDefault;
+ SHE SheCurrent;
+ SHE SheNew;
+ DWORD Flags;
+ BOOL fLoaded;
+} MOD_NODE;
+
+static PMOD_NODE ModListHead = NULL;
+static SHE SheDefault = sheNone;
+
+
+INT ModMatch( CHAR *, CHAR *, MATCHKIND );
+PMOD_NODE ModFind( CHAR *, MATCHKIND, BOOL );
+PMOD_NODE ModFindIndex( DWORD, BOOL );
+INT ModIndex( PMOD_NODE );
+VOID ModAdd( PMOD_NODE );
+PMOD_NODE ModNameAdd( CHAR *, SHE );
+VOID ModDel( PMOD_NODE );
+
+
+
+
+INT
+ModMatch (
+ CHAR *Name1,
+ CHAR *Name2,
+ MATCHKIND MatchKind
+ )
+{
+ INT Match;
+ char Base1[ _MAX_FNAME ];
+ char Base2[ _MAX_FNAME ];
+ char Ext1[ _MAX_EXT ];
+ char Ext2[ _MAX_EXT ];
+
+ Assert( Name1 );
+ Assert( Name2 );
+
+ if ( MatchKind == MATCH_FULLPATH ) {
+
+ Match = _stricmp( Name1, Name2 );
+
+ } else {
+
+ _splitpath( Name1, NULL, NULL, Base1, Ext1 );
+ _splitpath( Name2, NULL, NULL, Base2, Ext2 );
+
+ Match = _stricmp( Base1, Base2 );
+
+ if ( !Match && MatchKind == MATCH_FILENAME ) {
+ Match = _stricmp( Ext1, Ext2 );
+ }
+ }
+
+ return Match;
+}
+
+
+PMOD_NODE
+ModFind(
+ CHAR *Name,
+ MATCHKIND MatchKind,
+ BOOL IgnoreFlags
+ )
+{
+ PMOD_NODE ModNode = ModListHead;
+
+ while( ModNode ) {
+ if ( IgnoreFlags || !(ModNode->Flags & MOD_FLAG_TO_ADD) ) {
+ if ( !ModMatch( ModNode->Name, Name, MatchKind ) ) {
+ break;
+ }
+ }
+ ModNode = ModNode->Next;
+ }
+
+ return ModNode;
+}
+
+
+PMOD_NODE
+ModFindIndex(
+ DWORD Index,
+ BOOL UseFlag
+ )
+{
+ PMOD_NODE ModNode;
+ DWORD i;
+
+ ModNode = ModListHead;
+ i = 0;
+
+ while ( ModNode ) {
+ if ( !UseFlag || !(ModNode->Flags & MOD_FLAG_TO_DELETE) ) {
+ i++;
+ }
+
+ if ( i > Index ) {
+ break;
+ }
+
+ ModNode = ModNode->Next;
+ }
+
+ return ModNode;
+}
+
+
+INT
+ModIndex(
+ PMOD_NODE ModNode
+ )
+{
+ PMOD_NODE ModNodeTmp;
+ INT Index;
+
+ Index = 0;
+ ModNodeTmp = ModListHead;
+
+ while ( ModNodeTmp ) {
+
+ if ( ModNodeTmp == ModNode ) {
+ break;
+ }
+
+ Index++;
+ ModNodeTmp = ModNodeTmp->Next;
+ }
+
+ if ( !ModNodeTmp ) {
+ Index = -1;
+ }
+
+ return Index;
+}
+
+
+VOID
+ModAdd(
+ PMOD_NODE ModNode
+ )
+{
+ PMOD_NODE Mod = ModListHead;
+ PMOD_NODE ModPrev = NULL;
+
+ while ( Mod && ModMatch( ModNode->Name, Mod->Name, MATCH_FILENAME ) > 0 ) {
+ ModPrev = Mod;
+ Mod = Mod->Next;
+ }
+
+ ModNode->Prev = ModPrev;
+ ModNode->Next = Mod;
+
+ if ( ModPrev ) {
+ ModPrev->Next = ModNode;
+ } else {
+ ModListHead = ModNode;
+ }
+
+ if ( Mod ) {
+ Mod->Prev = ModNode;
+ }
+}
+
+PMOD_NODE
+ModNameAdd(
+ CHAR *Name,
+ SHE SheDefault
+ )
+{
+ PMOD_NODE ModNode;
+
+ Assert( Name );
+
+ ModNode = (PMOD_NODE)malloc(sizeof(MOD_NODE));
+
+ if ( ModNode ) {
+ strcpy(ModNode->Name, Name );
+ ModNode->Prev = NULL;
+ ModNode->Next = NULL;
+ ModNode->SheDefault = SheDefault;
+ ModNode->SheCurrent = sheNone;
+ ModNode->Flags = MOD_FLAG_NONE;
+ ModNode->fLoaded = FALSE;
+
+ ModAdd( ModNode );
+ }
+
+ return ModNode;
+}
+
+
+
+VOID
+ModDel(
+ PMOD_NODE ModNode
+ )
+{
+ if ( ModNode->Prev ) {
+ ModNode->Prev->Next = ModNode->Next;
+ } else {
+ ModListHead = ModNode->Next;
+ }
+
+ if ( ModNode->Next ) {
+ ModNode->Next->Prev = ModNode->Prev;
+ }
+
+ free( ModNode );
+}
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// External interface
+//
+///////////////////////////////////////////////////////////////////////
+
+
+static CHAR *SrchPath = NULL;
+
+
+
+
+VOID
+ModListSetDefaultShe (
+ SHE She
+ )
+{
+ SheDefault = She;
+}
+
+
+BOOL
+ModListGetDefaultShe(
+ CHAR *Name,
+ SHE *She
+ )
+{
+ BOOL Ret = FALSE;
+ PMOD_NODE ModNode;
+
+ Assert( She );
+
+ if ( Name ) {
+
+ ModNode = ModFind( Name, MATCH_FULLPATH, FALSE );
+ if ( !ModNode ) {
+ ModNode = ModFind( Name, MATCH_FILENAME, FALSE );
+ if ( !ModNode ) {
+ ModNode = ModFind( Name, MATCH_BASENAME, FALSE );
+ }
+ }
+
+ if ( ModNode ) {
+ *She = ModNode->SheDefault;
+ Ret = TRUE;
+ }
+
+ } else {
+
+ *She = SheDefault;
+ Ret = TRUE;
+ }
+
+ return Ret;
+}
+
+
+VOID
+ModListInit(
+ VOID
+ )
+{
+ PMOD_NODE ModNode;
+ PMOD_NODE ModNodeTmp;
+
+ ModNode = ModListHead;
+ while( ModNode ) {
+ ModNodeTmp = ModNode;
+ ModNode = ModNode->Next;
+ ModDel( ModNodeTmp );
+ }
+
+ ModListHead = NULL;
+
+ if ( SrchPath ) {
+ free( SrchPath );
+ SrchPath = NULL;
+ }
+}
+
+
+VOID
+ModListAdd(
+ CHAR *Name,
+ SHE SheDefault
+ )
+{
+ ModNameAdd( Name, SheDefault );
+}
+
+
+VOID
+ModListModLoad(
+ CHAR *Name,
+ SHE SheCurrent
+ )
+{
+ PMOD_NODE ModNode;
+
+ ModNode = ModFind( Name, MATCH_FULLPATH, FALSE );
+ if ( !ModNode ) {
+ ModNode = ModFind( Name, MATCH_FILENAME, FALSE );
+ if ( !ModNode ) {
+ ModNode = ModFind( Name, MATCH_BASENAME, FALSE );
+ }
+ }
+
+ if ( !ModNode ) {
+ ModNode = ModNameAdd( Name, SheDefault );
+ }
+
+ if ( ModNode ) {
+ ModNode->SheCurrent = SheCurrent;
+ ModNode->fLoaded = TRUE;
+ }
+}
+
+VOID
+ModListModUnload(
+ CHAR *Name
+ )
+{
+ PMOD_NODE ModNode;
+
+ ModNode = ModFind( Name, MATCH_FULLPATH, FALSE );
+ if ( ModNode ) {
+ ModNode->SheCurrent = sheNone;
+ ModNode->fLoaded = TRUE;
+ }
+}
+
+PVOID
+ModListGetNext(
+ PVOID Previous,
+ CHAR *Name,
+ SHE *SheDefault
+ )
+{
+ PMOD_NODE ModNode;
+
+ if ( !Previous ) {
+ ModNode = ModListHead;
+ } else {
+ ModNode = ((PMOD_NODE)Previous)->Next;
+ }
+
+ if ( ModNode ) {
+ strcpy( Name, ModNode->Name );
+ *SheDefault = ModNode->SheDefault;
+ }
+
+ return (PVOID)ModNode;
+}
+
+
+VOID
+ModListSetSearchPath(
+ CHAR *Path
+ )
+{
+ if ( SrchPath ) {
+ free( SrchPath );
+ SrchPath = NULL;
+ }
+
+ ModListAddSearchPath( Path );
+}
+
+VOID
+ModListAddSearchPath(
+ CHAR *Path
+ )
+{
+ size_t Len;
+
+ Assert( Path );
+
+ Len = strlen( Path );
+
+ if ( !SrchPath ) {
+ SrchPath = (CHAR *)malloc( Len + 1 );
+ if ( SrchPath ) {
+ *SrchPath = '\0';
+ }
+ } else {
+ SrchPath = (CHAR*)realloc( SrchPath, strlen(SrchPath) + Len + 1 );
+ }
+
+ if ( SrchPath ) {
+ strcat( SrchPath, Path );
+ }
+}
+
+DWORD
+ModListGetSearchPath(
+ CHAR *Buffer,
+ DWORD Size
+ )
+{
+ DWORD Len = 0;
+
+ if ( SrchPath ) {
+
+ Len = (DWORD)strlen(SrchPath);
+
+ if ( Buffer ) {
+
+ if ( Size > Len ) {
+ strcpy( Buffer, SrchPath );
+ Len++;
+ } else {
+ strncpy( Buffer, SrchPath, Size-1 );
+ Buffer[Size-1] = '\0';
+ Len = Size;
+ }
+
+ } else {
+
+ Len++;
+ }
+ }
+
+ return Len;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// User DLL Dialog stuff
+//
+///////////////////////////////////////////////////////////////////////
+
+
+#define TEXT_LOAD "Load"
+#define TEXT_DEFER "Defer"
+#define TEXT_SUPPRESS "Suppress"
+#define TEXT_LOCAL "Local"
+#define TEXT_REMOTE "Remote"
+#define TEXT_UNKNOWN "Unknown"
+#define TEXT_NOTLOADED "< Not loaded >"
+#define TEXT_NULL ""
+
+
+typedef enum _DEFBUTTON {
+ DEF_OK,
+ DEF_ADD,
+ DEF_CHANGE
+} DEFBUTTON;
+
+static DEFBUTTON DefButton;
+static BOOL SheChanged;
+
+
+DWORD FormatUserDll ( PMOD_NODE, CHAR *, DWORD );
+VOID UserDllInsert( HWND, PMOD_NODE, INT );
+VOID UserDllInit( HWND );
+VOID UserDllListInit( HWND );
+VOID UserDllAdd( HWND );
+VOID UserDllBrowse( HWND );
+BOOL UserDllBrowseHookProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+VOID UserDllShowDef( HWND );
+VOID UserDllDef( HWND );
+VOID UserDllDel( HWND );
+SHE UserDllGetShe( HWND, HWND, HWND );
+VOID UserDllSetShe( SHE, HWND, HWND, HWND );
+VOID UserDllModify( HWND );
+VOID UserDllOk( HWND );
+VOID UserDllCancel( HWND );
+VOID UserDllDllList( HWND );
+VOID UserDllAddName( HWND );
+HWND DefButtonToHwnd( HWND, DEFBUTTON );
+VOID UserDllSym( HWND );
+VOID UserDllEnableButtons( HWND );
+VOID UserDllSetDefButton( HWND );
+
+
+
+//
+// Largest string in Module list
+//
+static DWORD LargestModListString;
+
+//
+// Tabs in list box
+//
+INT Tabs[] = { 20, 26, 40, 46, 52 };
+#define MAX_NAME_LEN 14
+
+DWORD
+FormatUserDll (
+ PMOD_NODE ModNode,
+ CHAR *Buffer,
+ DWORD BufferSize
+ )
+{
+ CHAR Name[ MAX_PATH ];
+ CHAR Ext[ MAX_PATH ];
+ LSZ DefLoc;
+ LSZ DefLoad;
+ LSZ LoadMsg;
+
+ _splitpath( ModNode->Name, NULL, NULL, Name, Ext );
+ strcat( Name, Ext );
+ if ( strlen( Name ) > MAX_NAME_LEN ) {
+ Name[MAX_NAME_LEN] = '\0';
+ Name[MAX_NAME_LEN-1] = '.';
+ Name[MAX_NAME_LEN-2] = '.';
+ Name[MAX_NAME_LEN-3] = '.';
+ }
+
+ DefLoc = TEXT_LOCAL;
+ switch ( ModNode->Flags & MOD_FLAG_TO_MODIFY ? ModNode->SheNew : ModNode->SheDefault ) {
+ case sheNone:
+ DefLoad = TEXT_LOAD;
+ break;
+ case sheDeferSyms:
+ DefLoad = TEXT_DEFER;
+ break;
+ case sheSuppressSyms:
+ DefLoad = TEXT_SUPPRESS;
+ break;
+ default:
+ DefLoad = TEXT_UNKNOWN;
+ break;
+ }
+
+ if ( ModNode->fLoaded ) {
+ LoadMsg = SHLszGetErrorText( ModNode->SheCurrent );
+ } else {
+ LoadMsg = TEXT_NOTLOADED;
+ }
+ sprintf( Buffer, "%-s\t%-s\t%-s\t%-s", Name, DefLoc, DefLoad, LoadMsg );
+
+ return Tabs[3] + strlen( LoadMsg ) + 1;
+}
+
+
+VOID
+UserDllInsert(
+ HWND hList,
+ PMOD_NODE ModNode,
+ INT Index
+ )
+{
+ HDC hdc;
+ DWORD StringLength;
+ SIZE Size;
+ CHAR Buffer[ MAX_PATH * 2];
+
+ StringLength = FormatUserDll( ModNode, Buffer, (DWORD)sizeof( Buffer ) );
+
+ hdc = GetDC( hList );
+ GetTextExtentPoint( hdc, Buffer, StringLength, &Size );
+ ReleaseDC( hList, hdc );
+
+ if ( Size.cx > (LONG)LargestModListString ) {
+ LargestModListString = Size.cx;
+
+ SendMessage( hList,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)LargestModListString,
+ 0 );
+ }
+
+ if ( Index < 0 ) {
+ SendMessage( hList, LB_ADDSTRING, 0, (LONG)(LPSTR)Buffer );
+ } else {
+ SendMessage( hList, LB_INSERTSTRING, Index, (LONG)(LPSTR)Buffer );
+ }
+}
+
+VOID
+UserDllListInit(
+ HWND hDlg
+ )
+{
+ HWND hList;
+ PMOD_NODE ModNode;
+ INT i;
+ INT wTabs[5];
+ long BaseUnit;
+
+ LargestModListString = 0;
+ hList = GetDlgItem( hDlg, ID_USERDLL_LIST );
+ SendMessage( hList, LB_RESETCONTENT, 0, 0L );
+
+ BaseUnit = GetDialogBaseUnits();
+ for ( i=0; i < 5; i++ ) {
+ wTabs[i] = Tabs[i] * HIWORD(BaseUnit)/4;
+ }
+
+ SendMessage(GetDlgItem(hDlg, ID_USERDLL_LIST),
+ LB_SETTABSTOPS, 5, (LPARAM)wTabs);
+
+ //
+ // Fill the module list
+ //
+ for ( ModNode = ModListHead;
+ ModNode;
+ ModNode = ModNode->Next ) {
+
+ if ( !(ModNode->Flags & MOD_FLAG_TO_DELETE) ) {
+ UserDllInsert( hList, ModNode, -1 );
+ }
+ }
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_NAME),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL );
+}
+
+VOID
+UserDllInit(
+ HWND hDlg
+ )
+{
+ INT Len;
+ LSZ Buffer;
+
+ UserDllListInit( hDlg );
+
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_ADD ), FALSE );
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_REMOTE ), FALSE );
+ UserDllSetShe( SheDefault,
+ GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ );
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_LOCAL ), BM_SETCHECK, TRUE, 0 );
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME), WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL);
+
+ Len = ModListGetSearchPath( NULL, 0 );
+
+ if ( Len ) {
+ Buffer = (LSZ)malloc( Len );
+ if ( Buffer ) {
+ ModListGetSearchPath( Buffer, Len );
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_SRCHPATH),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)Buffer );
+ free( Buffer );
+ } else {
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_SRCHPATH),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL );
+ }
+ }
+
+ UserDllShowDef( hDlg );
+ DefButton = DEF_OK;
+ SheChanged = FALSE;
+ SetFocus( GetDlgItem( hDlg, ID_USERDLL_LIST ) );
+}
+
+
+VOID
+UserDllAdd(
+ HWND hDlg
+ )
+{
+ INT Len;
+ CHAR *Buffer;
+ SHE She;
+ INT Index = -2;
+ PMOD_NODE ModNode;
+ INT Selected;
+
+ She = UserDllGetShe(
+ GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ );
+
+ Len = SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME ), WM_GETTEXTLENGTH, 0, 0 );
+
+ if ( Len > 0 ) {
+
+ Buffer = (CHAR *)malloc( Len + 1 );
+
+ if ( Buffer ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME ),
+ WM_GETTEXT, Len+1, (LONG)(LPSTR)Buffer );
+
+ ModNode = ModFind( Buffer, MATCH_FULLPATH, TRUE );
+
+ if ( ModNode ) {
+
+ if ( ModNode->Flags & MOD_FLAG_TO_DELETE ) {
+
+ ModNode->Flags &= ~(MOD_FLAG_TO_DELETE);
+ }
+
+ ModNode->Flags |= MOD_FLAG_TO_MODIFY;
+ ModNode->SheNew = She;
+
+ } else {
+
+ ModNode = ModNameAdd( Buffer, She );
+
+ if ( ModNode ) {
+ ModNode->Flags |= MOD_FLAG_TO_ADD;
+ }
+ }
+
+ if ( ModNode ) {
+ Index = ModIndex( ModNode );
+ }
+
+ free( Buffer );
+ }
+ }
+
+ if ( Index >= 0 ) {
+ UserDllListInit( hDlg );
+ SendMessage( GetDlgItem( hDlg, ID_USERDLL_LIST), LB_SETTOPINDEX, Index, 0 );
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME), WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL);
+ Selected = SendMessage( GetDlgItem( hDlg, ID_USERDLL_LIST ), LB_GETSELCOUNT, 0, 0 );
+ if ( Selected <= 0 ) {
+ SheChanged = FALSE;
+ }
+ }
+}
+
+
+VOID
+UserDllBrowse(
+ HWND hDlg
+ )
+{
+ char CurrentDirectory[ MAX_PATH ];
+ char Buffer[ MAX_PATH ];
+ char Buffer2[ MAX_PATH ];
+ char FileName[ MAX_PATH ];
+ char Filter[ MAX_PATH ];
+ LPSTR s;
+ OPENFILENAME OpenFileName;
+
+
+ GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory );
+
+ if ( *UserDllDirectory ) {
+ SetCurrentDirectory( UserDllDirectory );
+ strcpy( Buffer, UserDllDirectory );
+ } else {
+ strcpy( Buffer, CurrentDirectory );
+ }
+
+ strcpy(FileName, "*.DLL" );
+
+ s = Filter;
+ strcpy( s, "*.DLL" );
+ s += strlen(s)+1;
+ *s++ = '\0';
+
+ OpenFileName.lStructSize = sizeof( OpenFileName );
+ OpenFileName.hwndOwner = hDlg;
+ OpenFileName.hInstance = (HANDLE)0;
+ OpenFileName.lpstrFilter = Filter;
+ OpenFileName.lpstrCustomFilter = NULL;
+ OpenFileName.nMaxCustFilter = 0;
+ OpenFileName.nFilterIndex = 1;
+ OpenFileName.lpstrFile = FileName;
+ OpenFileName.nMaxFile = sizeof( FileName );
+ OpenFileName.lpstrFileTitle = Buffer2;
+ OpenFileName.nMaxFileTitle = sizeof( Buffer2 );
+ OpenFileName.lpstrInitialDir = Buffer;
+ OpenFileName.lpstrTitle = NULL;
+ OpenFileName.Flags = OFN_ENABLEHOOK | OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
+ OpenFileName.nFileOffset = 0;
+ OpenFileName.nFileExtension = 0;
+ OpenFileName.lpstrDefExt = NULL;
+ OpenFileName.lCustData = 0;
+ OpenFileName.lpfnHook = ( LPOFNHOOKPROC )UserDllBrowseHookProc;
+ OpenFileName.lpTemplateName = NULL;
+
+ if ( GetOpenFileName( &OpenFileName ) ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME), WM_SETTEXT, 0, (DWORD)(LPSTR)OpenFileName.lpstrFile);
+
+ SetFocus( GetDlgItem( hDlg, ID_USERDLL_ADD_NAME ) );
+
+ GetCurrentDirectory( sizeof( UserDllDirectory ), UserDllDirectory );
+ }
+
+ SetCurrentDirectory( CurrentDirectory );
+}
+
+BOOL UserDllBrowseHookProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static LPCHOOSEFONT Cf;
+
+ switch( message ) {
+
+ case WM_COMMAND:
+
+ switch( LOWORD( wParam )) {
+
+ case IDWINDBGHELP:
+ case pshHelp:
+
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_USERDLL_HELP));
+ return TRUE;
+
+ }
+ }
+
+ return FALSE;
+}
+
+
+VOID
+UserDllDef(
+ HWND hDlg
+ )
+{
+ SHE She;
+ INT Selected;
+
+ She = UserDllGetShe(GetDlgItem(hDlg, ID_USERDLL_LOAD),
+ GetDlgItem(hDlg, ID_USERDLL_DEFER),
+ GetDlgItem(hDlg, ID_USERDLL_SUPPRESS));
+
+ Assert(She != sheMax);
+ ModListSetDefaultShe(She);
+ UserDllShowDef(hDlg);
+
+ Selected = SendMessage(GetDlgItem(hDlg, ID_USERDLL_LIST), LB_GETSELCOUNT, 0, 0);
+
+ if (Selected <= 0) {
+ SheChanged = FALSE;
+ }
+}
+
+
+VOID
+UserDllShowDef (
+ HWND hDlg
+ )
+{
+ CHAR Buffer[ MAX_PATH ];
+ LSZ DefLoc;
+ LSZ DefLoad;
+
+ DefLoc = TEXT_LOCAL;
+
+ switch ( SheDefault ) {
+ case sheNone:
+ DefLoad = TEXT_LOAD;
+ break;
+ case sheDeferSyms:
+ DefLoad = TEXT_DEFER;
+ break;
+ case sheSuppressSyms:
+ DefLoad = TEXT_SUPPRESS;
+ break;
+ default:
+ DefLoad = TEXT_UNKNOWN;
+ break;
+ }
+
+ sprintf( Buffer, "%-s %-s", DefLoc, DefLoad );
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_DEFAULT), WM_SETTEXT, 0, (DWORD)(LPSTR)Buffer);
+}
+
+VOID
+UserDllDel(
+ HWND hDlg
+ )
+{
+ HWND hList;
+ INT MaxIndex;
+ INT Selected;
+ INT i;
+ INT Deleted;
+ INT TopIndex;
+ PMOD_NODE ModNode;
+ PMOD_NODE ModNodeTmp;
+
+ hList = GetDlgItem( hDlg, ID_USERDLL_LIST );
+
+ Selected = SendMessage( hList, LB_GETSELCOUNT, 0, 0 );
+
+ if ( Selected > 0 ) {
+
+ TopIndex = SendMessage( hList, LB_GETTOPINDEX, 0, 0 );
+ MaxIndex = SendMessage( hList, LB_GETCOUNT, 0, 0 );
+ Deleted = 0;
+
+ for ( i=0; i < MaxIndex; i++ ) {
+
+ Selected = SendMessage( hList, LB_GETSEL, i, 0 );
+
+ if ( Selected ) {
+ ModNode = ModFindIndex( i - Deleted, TRUE );
+ if ( ModNode ) {
+ Deleted++;
+ ModNode->Flags |= MOD_FLAG_TO_DELETE;
+ }
+ }
+ }
+
+ ModNode = ModListHead;
+ while ( ModNode ) {
+ ModNodeTmp = ModNode;
+ ModNode = ModNode->Next;
+ if ( ModNodeTmp->Flags & MOD_FLAG_TO_ADD &&
+ ModNodeTmp->Flags & MOD_FLAG_TO_DELETE ) {
+ ModDel( ModNodeTmp );
+ }
+ }
+
+ if ( Deleted > 0 ) {
+ UserDllListInit( hDlg );
+ SendMessage( hList, LB_SETTOPINDEX, TopIndex, 0 );
+ }
+ }
+}
+
+
+SHE
+UserDllGetShe(
+ HWND hLoad,
+ HWND hDefer,
+ HWND hSuppress
+ )
+{
+ SHE She;
+
+ if (SendMessage( hLoad, BM_GETCHECK, 0, 0L ) == 1) {
+ She = sheNone;
+ } else if (SendMessage( hDefer, BM_GETCHECK, 0, 0L ) == 1) {
+ She = sheDeferSyms;
+ } else if (SendMessage( hSuppress, BM_GETCHECK, 0, 0L ) == 1) {
+ She = sheSuppressSyms;
+ } else {
+ She = sheMax;
+ }
+
+ return She;
+
+}
+
+VOID
+UserDllSetShe(
+ SHE She,
+ HWND hLoad,
+ HWND hDefer,
+ HWND hSuppress
+ )
+{
+ HWND hwnd;
+
+ SendMessage( hLoad, BM_SETCHECK, FALSE, 0 );
+ SendMessage( hDefer, BM_SETCHECK, FALSE, 0 );
+ SendMessage( hSuppress, BM_SETCHECK, FALSE, 0 );
+
+ switch ( She ) {
+
+ case sheNone:
+ hwnd = hLoad;
+ break;
+ case sheDeferSyms:
+ hwnd = hDefer;
+ break;
+ case sheSuppressSyms:
+ hwnd = hSuppress;
+ break;
+ default:
+ hwnd = (HWND)0;
+ break;
+ }
+
+ if ( hwnd ) {
+ SendMessage( hwnd, BM_SETCHECK, TRUE, 0 );
+ }
+}
+
+
+VOID
+UserDllModify(
+ HWND hDlg
+ )
+{
+ HWND hList;
+ INT MaxIndex;
+ INT Selected;
+ INT i;
+ INT Modified;
+ PMOD_NODE ModNode;
+ SHE She;
+
+ Modified = 0;
+ hList = GetDlgItem( hDlg, ID_USERDLL_LIST );
+ Selected = SendMessage( hList, LB_GETSELCOUNT, 0, 0 );
+
+ if ( Selected > 0 ) {
+
+ She = UserDllGetShe(
+ GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ );
+
+ MaxIndex = SendMessage( hList, LB_GETCOUNT, 0, 0 );
+ Modified = 0;
+
+ for ( i=0; i < MaxIndex; i++ ) {
+
+ Selected = SendMessage( hList, LB_GETSEL, i, 0 );
+
+ if ( Selected ) {
+ ModNode = ModFindIndex( i, TRUE );
+ if ( ModNode ) {
+ ModNode->Flags |= MOD_FLAG_TO_MODIFY;
+ ModNode->SheNew = She;
+
+ SendMessage( hList, LB_DELETESTRING, i, 0 );
+ UserDllInsert( hList, ModNode, i );
+ }
+ }
+ }
+
+ //UserDllSetShe( SheDefault,
+ // GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ // GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ // GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ // );
+ }
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_NAME),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL );
+ SheChanged = FALSE;
+}
+
+
+VOID
+UserDllOk(
+ HWND hDlg
+ )
+{
+ PMOD_NODE ModNode;
+ PMOD_NODE ModNodeTmp;
+ INT Len;
+ CHAR *Buffer;
+
+ ModNode = ModListHead;
+
+ while ( ModNode ) {
+ ModNodeTmp = ModNode;
+ ModNode = ModNode->Next;
+
+ if ( ModNodeTmp->Flags & MOD_FLAG_TO_DELETE ) {
+ ModDel( ModNodeTmp );
+ } else {
+ if ( ModNodeTmp->Flags & MOD_FLAG_TO_MODIFY ) {
+ ModNodeTmp->SheDefault = ModNodeTmp->SheNew;
+ }
+ ModNodeTmp->Flags = MOD_FLAG_NONE;
+ }
+ }
+
+ Len = SendMessage( GetDlgItem(hDlg, ID_USERDLL_SRCHPATH ), WM_GETTEXTLENGTH, 0, 0 );
+
+ if ( Len > 0 ) {
+ Buffer = (CHAR *)malloc( Len + 1 );
+
+ if ( Buffer ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_SRCHPATH ),
+ WM_GETTEXT, Len+1, (LONG)(LPSTR)Buffer );
+
+ ModListSetSearchPath( Buffer );
+
+ free( Buffer );
+ }
+ }
+}
+
+
+VOID
+UserDllCancel(
+ HWND hDlg
+ )
+{
+ PMOD_NODE ModNode;
+ PMOD_NODE ModNodeTmp;
+
+ ModNode = ModListHead;
+
+ while ( ModNode ) {
+ ModNodeTmp = ModNode;
+ ModNode = ModNode->Next;
+
+ if ( ModNodeTmp->Flags & MOD_FLAG_TO_ADD ) {
+ ModDel( ModNodeTmp );
+ }
+ ModNodeTmp->Flags = MOD_FLAG_NONE;
+ }
+}
+
+
+VOID
+UserDllDllList(
+ HWND hDlg
+ )
+{
+ HWND hList;
+ INT Selected;
+ INT MaxIndex;
+ INT i;
+ PMOD_NODE ModNode;
+ SHE She;
+ SHE SheLast;
+ BOOL First = TRUE;
+
+ hList = GetDlgItem( hDlg, ID_USERDLL_LIST );
+ Selected = SendMessage( hList, LB_GETSELCOUNT, 0, 0 );
+
+ if ( Selected <= 0 ) {
+
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_NAME),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL );
+ } else {
+
+ if ( Selected > 1 ) {
+
+ MaxIndex = SendMessage( hList, LB_GETCOUNT, 0, 0 );
+
+ for ( i=0; i < MaxIndex; i++ ) {
+
+ Selected = SendMessage( hList, LB_GETSEL, i, 0 );
+
+ if ( Selected ) {
+ ModNode = ModFindIndex( i, TRUE );
+ if ( ModNode ) {
+ if ( ModNode->Flags & MOD_FLAG_TO_MODIFY ) {
+ She = ModNode->SheNew;
+ } else {
+ She = ModNode->SheDefault;
+ }
+
+ if ( !First && She != SheLast ) {
+ break;
+ }
+ First = FALSE;
+ SheLast = She;
+ }
+ }
+ }
+
+ if ( !SheChanged ) {
+ UserDllSetShe( She == SheLast ? She : sheMax,
+ GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ );
+ }
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_NAME),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)TEXT_NULL );
+
+ } else {
+
+ MaxIndex = SendMessage( hList, LB_GETCOUNT, 0, 0 );
+
+ for ( i=0; i < MaxIndex; i++ ) {
+
+ Selected = SendMessage( hList, LB_GETSEL, i, 0 );
+
+ if ( Selected ) {
+ ModNode = ModFindIndex( i, TRUE );
+ if ( ModNode ) {
+ if ( !SheChanged ) {
+ UserDllSetShe( ModNode->Flags & MOD_FLAG_TO_MODIFY ?
+ ModNode->SheNew : ModNode->SheDefault,
+ GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ );
+ }
+ SendMessage( GetDlgItem(hDlg, ID_USERDLL_NAME),
+ WM_SETTEXT, 0, (DWORD)(LPSTR)ModNode->Name );
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+VOID
+UserDllAddName(
+ HWND hDlg
+ )
+{
+ UNREFERENCED_PARAMETER( hDlg );
+}
+
+HWND
+DefButtonToHwnd(
+ HWND hDlg,
+ DEFBUTTON Button
+ )
+{
+ HWND Hwnd;
+
+ switch( Button ) {
+ case DEF_OK:
+ Hwnd = GetDlgItem( hDlg, IDOK );
+ break;
+
+ case DEF_ADD:
+ Hwnd = GetDlgItem( hDlg, ID_USERDLL_ADD );
+ break;
+
+ case DEF_CHANGE:
+ Hwnd = GetDlgItem( hDlg, ID_USERDLL_CHANGE );
+ break;
+
+ }
+ return Hwnd;
+}
+
+
+VOID
+UserDllSym(
+ HWND hDlg
+ )
+{
+ UNREFERENCED_PARAMETER( hDlg );
+
+ SheChanged = TRUE;
+}
+
+VOID
+UserDllEnableButtons(
+ HWND hDlg
+ )
+{
+ INT Selected;
+ INT NewDllLen;
+ SHE She;
+
+ She = UserDllGetShe(
+ GetDlgItem( hDlg, ID_USERDLL_LOAD ),
+ GetDlgItem( hDlg, ID_USERDLL_DEFER ),
+ GetDlgItem( hDlg, ID_USERDLL_SUPPRESS )
+ );
+
+ Selected = SendMessage( GetDlgItem( hDlg, ID_USERDLL_LIST ), LB_GETSELCOUNT, 0, 0 );
+
+ if ( Selected > 0 ) {
+
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_DEFAULT), She != sheMax );
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_ADD), FALSE );
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_CHANGE), She != sheMax );
+/*! ==v==(-) !**
+/*! --*-- !*/
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_DELETE), She != sheMax );
+/*! ==^==(+) !*/
+
+ } else {
+
+ //
+ // Nothing selected
+ //
+ NewDllLen = SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME ), WM_GETTEXTLENGTH, 0, 0 );
+
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_DEFAULT), She != sheMax );
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_ADD), NewDllLen > 0 && She != sheMax );
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_CHANGE), FALSE );
+/*! ==v==(-) !**
+/*! --*-- !*/
+ EnableWindow( GetDlgItem( hDlg, ID_USERDLL_DELETE), FALSE );
+/*! ==^==(+) !*/
+ }
+}
+
+
+VOID
+UserDllSetDefButton(
+ HWND hDlg
+ )
+{
+ DEFBUTTON Button;
+ INT Len;
+
+ Len = SendMessage( GetDlgItem(hDlg, ID_USERDLL_ADD_NAME ), WM_GETTEXTLENGTH, 0, 0 );
+
+ if ( Len > 0 ) {
+ Button = DEF_ADD;
+ } else {
+ Len = SendMessage( GetDlgItem(hDlg,ID_USERDLL_LIST), LB_GETSELCOUNT, 0, 0 );
+ if ( Len > 0 ) {
+ Button = DEF_CHANGE;
+ } else {
+ Button = DEF_OK;
+ }
+ }
+
+ if ( Button != DefButton ) {
+ PostMessage(DefButtonToHwnd(hDlg, DefButton), BM_SETSTYLE, (WORD)BS_PUSHBUTTON, (DWORD)TRUE);
+ PostMessage(DefButtonToHwnd(hDlg, Button), BM_SETSTYLE, (WORD)BS_DEFPUSHBUTTON, (DWORD)TRUE);
+ DefButton = Button;
+ }
+}
+
+
+BOOL FAR PASCAL EXPORT
+DlgUserdll(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LONG lParam
+ )
+{
+ BOOL Ret = FALSE;
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ UserDllInit( hDlg );
+ Ret = TRUE;
+ break;
+
+ case WM_COMMAND:
+ switch ( LOWORD(wParam ) ) {
+
+ case ID_USERDLL_LIST:
+ UserDllDllList( hDlg );
+ break;
+
+ case ID_USERDLL_LOCAL:
+ case ID_USERDLL_REMOTE:
+ break;
+
+ case ID_USERDLL_LOAD:
+ case ID_USERDLL_DEFER:
+ case ID_USERDLL_SUPPRESS:
+ UserDllSym( hDlg );
+ break;
+
+ case ID_USERDLL_ADD_NAME:
+ UserDllAddName( hDlg );
+ break;
+
+ case ID_USERDLL_ADD:
+ UserDllAdd( hDlg );
+ break;
+
+ case ID_USERDLL_BROWSE:
+ UserDllBrowse( hDlg );
+ break;
+
+ case ID_USERDLL_DEFAULT:
+ UserDllDef( hDlg );
+ break;
+
+ case ID_USERDLL_DELETE:
+ UserDllDel( hDlg );
+ break;
+
+ case ID_USERDLL_CHANGE:
+ UserDllModify( hDlg );
+ break;
+
+ case IDOK:
+ switch( DefButton ) {
+ case DEF_OK:
+ UserDllOk( hDlg );
+ EndDialog(hDlg, TRUE);
+ break;
+ case DEF_ADD:
+ UserDllAdd( hDlg );
+ break;
+ case DEF_CHANGE:
+ UserDllModify( hDlg );
+ break;
+ }
+ break;
+
+ case IDCANCEL:
+ UserDllCancel( hDlg );
+ EndDialog(hDlg, TRUE);
+ break;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)ID_USERDLL_HELP));
+ break;
+
+ }
+ UserDllEnableButtons(hDlg);
+ UserDllSetDefButton(hDlg);
+ Ret = TRUE;
+ break;
+ }
+
+ return Ret;
+}
diff --git a/private/windbg/windbg/util.c b/private/windbg/windbg/util.c
new file mode 100644
index 000000000..8f9fde213
--- /dev/null
+++ b/private/windbg/windbg/util.c
@@ -0,0 +1,3329 @@
+/*--Author:
+
+ Griffith Wm. Kadnier (v-griffk) 01-Aug-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include "direct.h"
+
+LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+static BOOL CompareFileName(LPSTR, LPSTR);
+static BOOL CompareFileNameWithPath(LPSTR, LPSTR);
+
+#ifdef FE_IME
+
+#include <ime.h>
+
+static BOOL (WINAPI *lpfnWINNLSEnableIME)(HWND, BOOL) = NULL;
+static LRESULT (WINAPI *lpfnSendIMEMessageEx)(HWND, LPARAM) = NULL;
+static HINSTANCE hModUser32 = NULL;
+
+#endif
+
+extern BOOL bOffRibbon;
+
+
+typedef struct _HK {
+ struct _HK * next;
+ int idHotKey;
+ HWND hwnd;
+} HK, *LPHK;
+
+static LPHK LpHKHead = NULL;
+
+
+static LPHK
+FindLocalHotKey(
+ int idHotKey
+ )
+{
+ LPHK lpHK;
+ for (lpHK = LpHKHead; lpHK; lpHK = lpHK->next) {
+ if (lpHK->idHotKey == idHotKey) {
+ return lpHK;
+ }
+ }
+ return NULL;
+}
+
+
+static void
+MapLocalHotKey(
+ MSG *lpMsg
+ )
+{
+ LPHK lpHK;
+ if (lpMsg->message == WM_HOTKEY
+ && lpMsg->hwnd == NULL
+ && (lpHK = FindLocalHotKey(lpMsg->wParam)) != NULL)
+ {
+ lpMsg->hwnd = lpHK->hwnd;
+ }
+}
+
+BOOL
+RegisterAndMapLocalHotKey(
+ HWND hwnd,
+ int idHotKey,
+ UINT fuModifiers,
+ UINT uVirtKey
+ )
+/*++
+
+Routine Description:
+
+ Register a non-global hotkey, and put its window in a map so it
+ can be directed to the right window when it happens.
+
+Arguments:
+
+ hwnd
+ idHotKey
+ fuModifiers
+ uVirtKey
+
+Return Value:
+
+ return val from RegisterHotKey
+
+--*/
+{
+ LPHK lpHK;
+ BOOL r;
+
+ r = RegisterHotKey(NULL, idHotKey, fuModifiers, uVirtKey);
+
+ if (r) {
+ lpHK = FindLocalHotKey(idHotKey);
+ if (!lpHK) {
+ lpHK = malloc(sizeof(HK));
+ }
+ if (!lpHK) {
+ r = FALSE;
+ UnregisterHotKey(NULL, idHotKey);
+ } else {
+ lpHK->idHotKey = idHotKey;
+ lpHK->hwnd = hwnd;
+ lpHK->next = LpHKHead;
+ LpHKHead = lpHK;
+ }
+ }
+
+ return r;
+}
+
+
+void
+UnregisterLocalHotKey(
+ int idHotKey
+ )
+{
+ LPHK lpHK, *lppHK;
+ for (lppHK = &LpHKHead; *lppHK; lppHK = &(*lppHK)->next) {
+ if ((*lppHK)->idHotKey == idHotKey) {
+ UnregisterHotKey(NULL, idHotKey);
+ lpHK = *lppHK;
+ *lppHK = lpHK->next;
+ free(lpHK);
+ break;
+ }
+ }
+}
+
+/*** FileExist
+**
+** Synopsis:
+** bool = FileExist(szFileName)
+**
+** Entry:
+** szFileName - Name of file to check for
+**
+** Returns:
+** TRUE if file exists and FALSE otherwise
+**
+** Description:
+** Checks to see if a file exists with the path/filename
+** described by the string pointed to by 'fileName'.
+*/
+
+BOOL FileExist(LPSTR fileName)
+{
+ int fh;
+#ifdef WIN32
+ OFSTRUCT of;
+
+ if ((fh = OpenFile(fileName, &of, OF_READ)) == -1)
+ return(FALSE);
+
+ CloseHandle((HANDLE) fh);
+#else
+
+ if ((fh = _lopen((LPSTR) fileName, OF_READ)) < 0)
+ return(FALSE);
+
+ _lclose(fh);
+#endif
+ return(TRUE);
+} /* FileExist() */
+
+/*** FileExistCheckingPath
+**
+** Synopis:
+** bool = FileExistCheckingPath(fileName)
+**
+** Entry:
+** fileName - Name of file and path to check for existance
+**
+** Returns;
+** TRUE if the file exists, FALSE otherwise
+**
+** Description:
+** Checks to see if a file exists with the path/filename
+** described by the string pointed to by 'fileName'.
+** If 'fileName' is only filename and extension, the search
+** will be done in windows dirs and in current path.
+**
+*/
+
+BOOL FileExistCheckingPath(LPSTR fileName)
+{
+ OFSTRUCT ofT;
+
+ return (OpenFile(fileName, (LPOFSTRUCT)&ofT, OF_EXIST) != -1);
+}
+
+
+/*** hGetBoxParent
+**
+** Synopsis:
+** hwnd = hGetBoxParent()
+**
+** Entry:
+** none
+**
+** Returns:
+**
+** Description:
+** Gets a suitable parent window handle for an
+** invocation of a message or dialog box.
+** Helper function to util.c functions so declared
+** near.
+**
+*/
+
+HWND NEAR hGetBoxParent(void)
+{
+ HWND hCurWnd;
+ int i=0;
+
+ hCurWnd = GetFocus();
+ if (hCurWnd) {
+ while (GetWindowLong(hCurWnd, GWL_STYLE) & WS_CHILD) {
+
+ hCurWnd = GetParent(hCurWnd);
+ Dbg(++i < 100);
+ }
+ } else {
+ hCurWnd = hwndFrame;
+ }
+
+ return hCurWnd;
+} /* hGetBoxParent() */
+
+/****************************************************************************
+
+ FUNCTION: MsgBox
+
+ PURPOSE: General purpose message box routine which takes
+ a pointer to the message text. Provides
+ program title as caption.
+
+****************************************************************************/
+
+int PASCAL
+MsgBox(
+ HWND hwndParent,
+ LPSTR szText,
+ UINT wType
+ )
+/*++
+
+Routine Description:
+
+ Generial purpose message box routine which takes a pointer to a message
+ text and prvoides the program title for the caption of the message box.
+
+Arguments:
+
+ hwndParament - Supplies the parent window handle for the message box
+ szText - Supplies a pointer to the message box text.
+ wType - Supplies the message box type (to specify buttons)
+
+Return Value:
+
+ Returns the message box return code
+
+--*/
+
+{
+ int MsgBoxRet = IDOK;
+
+ if (NoPopups) {
+ //
+ // log the string to the command win in case testing
+ // or when the remote server is running
+ //
+ CmdLogFmt ("%s\r\n", szText);
+ } else {
+ BoxCount++;
+ MsgBoxRet = MessageBox(hwndParent, szText, (LPSTR)MainTitleText, wType);
+ BoxCount--;
+ }
+
+ return MsgBoxRet;
+} /* MsgBox() */
+
+/****************************************************************************
+
+ FUNCTION: VarMsgBox
+
+ PURPOSE: As MsgBox but takes resource id as text and performs
+ a vsprintf on the variable parameters.
+
+****************************************************************************/
+int CDECL
+VarMsgBox(
+ HWND hwndParent,
+ WORD wFormat,
+ UINT wType,
+ ...)
+{
+ char szFormat[MAX_MSG_TXT];
+ char szText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
+ va_list vargs;
+
+ // load format string from resource file
+ Dbg(LoadString(hInst, wFormat, (LPSTR)szFormat, MAX_MSG_TXT));
+
+ va_start(vargs, wType);
+ vsprintf(szText, szFormat, vargs);
+ va_end(vargs);
+
+ return MsgBox(hwndParent, szText, wType);
+} /* VarMsgBox() */
+
+/*** ErrorBox
+**
+** Synopsis:
+** int = ErrorBox(wErrorFormat, ...)
+**
+** Entry:
+** wErrorFormat
+** ...
+**
+** Returns:
+** FALSE
+**
+** Description:
+** Display an error message box with an "Error" title, an OK
+** button and a Exclamation Icon. First parameter is a
+** reference string in the ressource file. The string
+** can contain printf formatting chars, the arguments
+** follow from the second parameter onwards.
+**
+*/
+
+int CDECL
+ErrorBox(
+ int wErrorFormat,
+ ...
+ )
+{
+ char szErrorFormat[MAX_MSG_TXT];
+ char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
+ va_list vargs;
+
+ // load format string from resource file
+ Dbg(LoadString(hInst, wErrorFormat, (LPSTR)szErrorFormat, MAX_MSG_TXT));
+
+ va_start(vargs, wErrorFormat);
+ vsprintf(szErrorText, szErrorFormat, vargs);
+ va_end(vargs);
+
+ MsgBox(hwndFrame, (LPSTR)szErrorText, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+ return FALSE; //Keep it always FALSE please
+} /* ErrorBox() */
+
+/*** ErrorBox2
+**
+** Synopsis:
+** int = ErrorBox2(hwnd, type, wErrorFormat, ...)
+**
+** Entry:
+**
+** Return:
+** FALSE
+**
+** Description:
+** Display an error message box with an "Error" title, an OK
+** button and a Exclamation Icon. First is the window handle
+** of the parent window. Second is the extra types given
+** to the message box.Third parameter is a reference string
+** in the ressource file. The string can contain printf
+** formatting chars, the arguments follow from the fourth
+** parameter onwards.
+**
+*/
+
+int CDECL
+ErrorBox2(
+ HWND hwnd,
+ UINT type,
+ WORD wErrorFormat,
+ ...
+ )
+{
+ char szErrorFormat[MAX_MSG_TXT];
+ char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
+ va_list vargs;
+
+ // load format string from resource file
+ Dbg(LoadString(hInst, wErrorFormat, (LPSTR)szErrorFormat, MAX_MSG_TXT));
+
+ // set up szErrorText from passed parameters
+ va_start(vargs, wErrorFormat);
+ vsprintf(szErrorText, szErrorFormat, vargs);
+ va_end(vargs);
+
+ MsgBox(hwnd, (LPSTR)szErrorText, type | MB_OK | MB_ICONINFORMATION);
+ return FALSE; //Keep it always FALSE please
+} /* ErrorBox2() */
+
+/*** InternalErrorBox
+**
+** Synopsis:
+** int = InternalErrorBox(wDescript,...)
+**
+** Entry:
+**
+** Returns:
+** FALSE
+**
+** Description:
+**
+*/
+
+int
+InternalErrorBox(
+ WORD wDescript
+ )
+{
+ char szErrorFormat[MAX_MSG_TXT];
+ char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
+ char szArgument[MAX_MSG_TXT];
+
+ //Load format and argument strings from resource file
+ Dbg(LoadString(hInst, ERR_Internal_Error, (LPSTR)szErrorFormat, MAX_MSG_TXT));
+ Dbg(LoadString(hInst, wDescript, (LPSTR)szArgument, MAX_MSG_TXT));
+
+ sprintf(szErrorText, szErrorFormat, (LPSTR)szArgument);
+
+ MsgBox(hwndFrame, (LPSTR)szErrorText, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
+
+ DebugBreak();
+ return FALSE;
+} /* InternalErrorBox() */
+
+/*** InformationBox
+**
+** Synopsis:
+** void = InformationBox(wInfoFormat, ...)
+**
+** Entry:
+** wInfoFormat - Resource index of format string
+** ... - Additional informationto be displayed
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Display an information message box with an "Information"
+** title, an OK button and an Information Icon. First
+** parameter is a reference string in the ressource file.
+** The string can contain printf formatting chars, the
+** arguments follow from the second parameter onwards.
+**
+*/
+
+void CDECL
+InformationBox(
+ int wInfoFormat,
+ ...
+ )
+{
+ char szInfoFormat[MAX_MSG_TXT];
+ char szInfoText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
+ va_list vargs;
+
+ // load format string from resource file
+ Dbg(LoadString(hInst, wInfoFormat, (LPSTR)szInfoFormat, MAX_MSG_TXT));
+
+ // set up szInfoText from passed parameters
+ va_start(vargs, wInfoFormat);
+ vsprintf(szInfoText, szInfoFormat, vargs);
+ va_end(vargs);
+
+ MsgBox(hwndFrame, (LPSTR)szInfoText, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+
+ return;
+} /* InformationBox() */
+
+/*** QuestionBox
+**
+** Synopsis:
+** int = QuestionBox(wCaptionId, wMsgFormat, wType, ...)
+**
+** Entry:
+**
+** Returns:
+** The result of the message box call
+**
+** Description:
+** Display an query box with combination of YES, NO and
+** CANCEL buttons and a question mark Icon.
+** See ErrorBox for discussion.
+**
+*/
+
+int CDECL
+QuestionBox(
+ WORD wMsgFormat,
+ UINT wType,
+ ...
+ )
+{
+ char szMsgFormat[MAX_MSG_TXT];
+ char szMsgText[MAX_VAR_MSG_TXT];
+ va_list vargs;
+
+ //Load format string from resource file
+ Dbg(LoadString(hInst, wMsgFormat, (LPSTR)szMsgFormat, MAX_MSG_TXT));
+
+ //Set up szMsgText from passed parameters
+ va_start(vargs, wType);
+ vsprintf(szMsgText, szMsgFormat, vargs);
+ va_end(vargs);
+
+ return MsgBox(hwndFrame, szMsgText,
+ wType | MB_ICONEXCLAMATION | MB_TASKMODAL);
+} /* QuestionBox() */
+
+/****************************************************************************
+
+ FUNCTION: QuestionBox2
+
+ PURPOSE: Display an query box with combination of YES, NO and
+ CANCEL buttons and a question mark Icon. The type and
+ the parent window are adjustable.
+
+ RETURNS: MessageBox result
+
+****************************************************************************/
+int CDECL
+QuestionBox2(
+ HWND hwnd,
+ WORD wMsgFormat,
+ UINT wType,
+ ...
+ )
+{
+ char szMsgFormat[MAX_MSG_TXT];
+ char szMsgText[MAX_VAR_MSG_TXT];
+ va_list vargs;
+
+ //Load format string from resource file
+ Dbg(LoadString(hInst, wMsgFormat, (LPSTR)szMsgFormat, MAX_MSG_TXT));
+
+ //Set up szMsgText from passed parameters
+ va_start(vargs, wType);
+ vsprintf(szMsgText, szMsgFormat, vargs);
+ va_end(vargs);
+
+ return MsgBox(hwnd, szMsgText, wType | MB_ICONEXCLAMATION);
+} /* QuestionBox2() */
+
+/*** FatalErrorBox
+**
+** Synopsis:
+** void = FatalErrorBox(iLine, szText)
+**
+** Entry:
+** iLine -
+** szText -
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function will display an error message in a message box
+** which has the title of "Error". The first paramter is an index
+** of a string in the resource file and the second parameter is
+** a literal which is displayed in the box.
+**
+*/
+
+typedef struct _febargs {
+ LPSTR lpLine2;
+ WORD wLine1;
+} FEBARGS;
+
+DWORD
+FatalErrorBoxThread(
+ LPVOID lpArgs
+ )
+{
+ char text[MAX_MSG_TXT], buffer[MAX_VAR_MSG_TXT];
+ FEBARGS *pfa = (FEBARGS *)lpArgs;
+
+ if (pfa->wLine1 == 0) {
+ *text = 0;
+ } else {
+ Dbg(LoadString(hInst, pfa->wLine1, text, MAX_MSG_TXT));
+ }
+
+ Dbg(strlen(text) < sizeof(buffer));
+
+ if (pfa->lpLine2) {
+ sprintf(buffer, "%s %s",text, pfa->lpLine2);
+ } else {
+ sprintf(buffer, "%s",text);
+ }
+
+#if DBG
+ OutputDebugString(buffer);
+ OutputDebugString("\n\r");
+#endif
+
+ strcat(buffer, "\r\nOK to ignore, CANCEL to break");
+
+ return MessageBox(NULL,
+ buffer,
+ MainTitleText,
+ MB_OKCANCEL | MB_ICONHAND | MB_TASKMODAL | MB_SETFOREGROUND);
+} /* FatalErrorBoxThread() */
+
+void
+FatalErrorBox(
+ WORD wLine1,
+ LPSTR lpLine2
+ )
+{
+ FEBARGS fa;
+ HANDLE hThread;
+ DWORD dw;
+ fa.wLine1 = wLine1;
+ fa.lpLine2 = lpLine2;
+ hThread = CreateThread(NULL, 0, FatalErrorBoxThread, &fa, 0, &dw);
+ WaitForSingleObject(hThread, INFINITE);
+ GetExitCodeThread(hThread, &dw);
+ CloseHandle(hThread);
+ if (dw == IDCANCEL) {
+ DebugBreak();
+ }
+} /* FatalErrorBox() */
+
+
+/*** ShowAssert
+**
+** Synopsis:
+** void = ShowAssert(szCond, iLine, szFile)
+**
+** Entry:
+** szCond - tokenized form of the failed condition
+** iLine - Line number for the assertion
+** szFile - File for the assertion
+**
+** Returns:
+** void
+**
+** Description:
+** Prepare and display a Message Box with szCondition, iLine and
+** szFile as fields.
+**
+*/
+
+void
+ShowAssert(
+ LPSTR condition,
+ UINT line,
+ LPSTR file
+ )
+{
+ char text[MAX_VAR_MSG_TXT];
+
+ //Build line, show assertion and exit program
+
+ sprintf(text, "- Line:%u, File:%Fs, Condition:%Fs",
+ (WPARAM) line, file, condition);
+
+ if (!AutoTest) {
+ FatalErrorBox(ERR_Assertion_Failed, text);
+ } else {
+ char szBuffer[_MAX_PATH];
+ PSTR pszBuffer;
+ PSTR szAssertFile = "assert.qcw";
+ int fd;
+ OFSTRUCT OFStruct;
+
+ fd = OpenFile(szAssertFile, (LPOFSTRUCT)&OFStruct, OF_CREATE|OF_WRITE);
+ Unreferenced( szBuffer );
+ Unreferenced( pszBuffer );
+
+ if (fd != -1) {
+ // write the text
+
+ _lwrite(fd, text, (WORD)strlen(text));
+ _lclose(fd);
+ }
+ CmdLogFmt( text );
+ emergency = TRUE;
+ exit(3);
+ }
+
+ return;
+} /* ShowAssert() */
+
+/*** MakePathNameFromProg
+**
+** Synopsis:
+** void = MakePathName(extension, fileName)
+**
+** Entry:
+** extension - Pointer to string containing the extension to be used
+** fileName - pointer to buffer for the resulting file name
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function will take the module name, the passed in extension
+** and the current path to construct a full path name. An example of
+** how this is used is in getting the ini file name.
+*/
+
+void
+MakePathNameFromProg(
+ LPSTR extension,
+ LPSTR fileName
+ )
+{
+ LPSTR pcFileName;
+ int nFileNameLen;
+
+ /*
+ ** Get the file name for the base module.
+ */
+
+ nFileNameLen = GetModuleFileName(hInst, fileName, _MAX_PATH);
+ pcFileName = fileName + nFileNameLen;
+
+ /*
+ ** Strip off any extensions found. Assume that atleast .exe exists
+ **
+ ** M00BUG -- no extension on file name but a dot in the path.
+ */
+
+#ifdef DBCS
+ while (pcFileName > fileName) {
+ pcFileName = CharPrev(fileName, pcFileName);
+ if (*pcFileName == '.') {
+ *(++pcFileName) = '\0';
+ break;
+ }
+ nFileNameLen -= (IsDBCSLeadByte(*pcFileName) ? 2 : 1);
+ }
+#else
+ while (pcFileName > fileName) {
+ if (*pcFileName == '.') {
+ *(++pcFileName) = '\0';
+ break;
+ }
+
+ nFileNameLen--;
+ pcFileName--;
+ }
+#endif
+
+ /*
+ ** Make sure that the name is really an ansi string and that
+ ** it is not too long.
+ */
+
+ OemToAnsi(fileName, fileName);
+ if ((nFileNameLen+lstrlen(extension)) < _MAX_PATH)
+ lstrcat(fileName, extension);
+ else
+ ErrorBox(ERR_File_Name_Too_Long, fileName);
+
+ Assert(_fstrlen(fileName) < _MAX_PATH);
+ return;
+} /* MakePathNameFromProg() */
+
+/*** MakeFileNameFromProg
+**
+** Synopsis:
+** void = MakeFileNameFromProg(extension, fileName)
+**
+** Entry:
+** extension - Pointer to string containing the extension to be used
+** fileName - pointer to buffer for the resulting file name
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function will take the module name, the passed in extension
+** and the current path to construct a full path name. An example of
+** how this is used is in getting the ini file name.
+*/
+
+void MakeFileNameFromProg(LPSTR extension, LPSTR fileName)
+{
+ int nFileNameLen;
+
+ /*
+ ** Get the file name for the base module.
+ */
+
+ nFileNameLen = GetModuleFileName(hInst, szPath, _MAX_PATH);
+ _splitpath(szPath, szDrive, szDir, szFName, szExt);
+
+
+ /*
+ ** Make sure that the name is really an ansi string and that
+ ** it is not too long.
+ */
+
+ OemToAnsi(szFName, fileName);
+ if ((_fstrlen(fileName)+_fstrlen(extension)) < _MAX_FNAME) {
+ _fstrcat(fileName, extension);
+ } else
+ ErrorBox(ERR_File_Name_Too_Long, fileName);
+
+ Assert(_fstrlen(fileName) < _MAX_FNAME);
+ return;
+} /* MakePathNameFromProg() */
+
+
+/*** StartDialog
+**
+** Synopsis:
+** bool = StartDialog(rcDlgNb, dlgProc)
+**
+** Entry:
+** rcDlgNb - Resource number of dialog to be openned
+** dlgProc - Filter procedure for the dialog
+**
+** Returns:
+** Result of the dialog box call
+**
+** Description:
+** Loads and execute the dialog box 'rcDlgNb' (ressource
+** file string number) associated with the dialog
+** function 'dlgProc'
+**
+*/
+
+BOOL StartDialog(int rcDlgNb, DLGPROC dlgProc)
+{
+ DLGPROC lpDlgProc;
+ int result;
+
+ //TestRoutine();
+
+ lpDlgProc = (DLGPROC)dlgProc;
+
+ /*
+ * M00NOTE: If you are running on a non-vga system then you need
+ * add modifications to add an offset to the resource number.
+ * i.e. VGA == += 0
+ * EGA == += 1
+ * CGA == += 2
+ */
+
+ /*
+ * Execute Dialog Box
+ */
+
+ DlgEnsureTitleBar();
+ BoxCount++;
+ Dbg((result = DialogBox(hInst, MAKEINTRESOURCE(rcDlgNb), hGetBoxParent(), lpDlgProc)) != -1);
+ BoxCount--;
+
+ return (result);
+} /* StartDialog() */
+
+/****************************************************************************
+
+ FUNCTION: InvDlgCtlIdRect
+
+ PURPOSE: Invalidate the rectangle area of child 'ctlID' in
+ 'hDlg' Dialog Box
+
+****************************************************************************/
+void InvDlgCtlIdRect(HWND hDlg, WPARAM ctlID)
+{
+ HWND win;
+
+ Dbg(win = GetDlgItem(hDlg, ctlID));
+ InvalidateRect(win, (LPRECT)NULL, 1);
+ return;
+} /* InvDlgCtlIdRect() */
+
+/****************************************************************************
+
+ FUNCTION: RemoveMnemonic
+
+ PURPOSE: Get rid of accelerator mark
+
+****************************************************************************/
+void RemoveMnemonic(
+ LPSTR sWith,
+ LPSTR sWithout)
+{
+ int k, j = 0;
+
+ for (k = 0; k <= (int)lstrlen(sWith); k++)
+#ifdef DBCS
+ if (IsDBCSLeadByte(sWith[k]) && sWith[k+1]) {
+ sWithout[j++] = sWith[k++];
+ sWithout[j++] = sWith[k];
+ } else
+#endif
+ if (sWith[k] != '&')
+ {
+ sWithout[j++] = sWith[k];
+ }
+ else if (sWith[k+1] == '&')
+ {
+ sWithout[j++] = sWith[k++];
+ }
+ return;
+} /* RemoveMnomonic() */
+
+/****************************************************************************
+
+ FUNCTION: StatusText, StatusMultiKey, StatusOverType, StatusNumLock
+ StatusCapsLock, StatusLineColumn
+
+ PURPOSE: Functions to change elements values of the status bar
+
+****************************************************************************/
+void CDECL StatusText(int newTextId, WORD msgType, BOOL forceUpdate, ...)
+{
+ #define BETWEEN(inf, sup) (newTextId >= inf && newTextId <= sup)
+
+ char szStatusFormat[MAX_MSG_TXT];
+ char szStatusText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
+ va_list vargs;
+
+ if (forceUpdate || (newTextId != status.lastTxt)) {
+
+ //Load status text format
+
+ if (msgType == STATUS_MENUTEXT) {
+
+ int menuAdjust, j = 0;
+
+ newTextId = (int) GetPopUpMenuID(( HMENU ) newTextId );
+
+ if (BETWEEN(IDM_FILE_FIRST, IDM_FILE_LAST)
+ || BETWEEN(IDM_EDIT_FIRST, IDM_EDIT_LAST)
+ || BETWEEN(IDM_VIEW_FIRST, IDM_VIEW_LAST)
+ || BETWEEN(IDM_PROGRAM_FIRST, IDM_PROGRAM_LAST)
+ || BETWEEN(IDM_RUN_FIRST, IDM_RUN_LAST)
+ || BETWEEN(IDM_DEBUG_FIRST, IDM_DEBUG_LAST)
+ || BETWEEN(IDM_OPTIONS_FIRST, IDM_OPTIONS_LAST)
+ || BETWEEN(IDM_WINDOW_FIRST, IDM_WINDOW_LAST)
+ || BETWEEN(IDM_HELP_FIRST, IDM_HELP_LAST)) {
+
+ if(!LoadString(hInst,
+ newTextId, (LPSTR)szStatusFormat, MAX_MSG_TXT))
+
+ {
+ wsprintf(szStatusFormat,
+ "LoadString failed in %s, %ld: hInst == %ld, Id == %ld\r\n",
+ __FILE__, (LONG)__LINE__, (LONG)hInst, (LONG)newTextId);
+ OutputDebugString(szStatusFormat);
+
+ lstrcpy(szStatusFormat, "--Bogus Bogus--");
+ }
+
+ goto show;
+ }
+
+ //See if we have a maximized Mdi Window
+ //(A system menu will be added) to standard menu bar
+
+ if (GetMenuItemCount(hMainMenu) > NUMBER_OF_MENUS)
+ menuAdjust = 1;
+ else
+ menuAdjust = 0;
+ //See if it's a MRU file item
+
+ if (newTextId > IDM_FILE_EXIT
+ && newTextId <= IDM_FILE_EXIT + MAX_MRU_FILES_KEPT) {
+ Dbg(LoadString(hInst, STA_Open_MRU_File, (LPSTR)szStatusFormat, MAX_MSG_TXT));
+ if (GetMenuString(GetSubMenu(hMainMenu, FILEMENU + menuAdjust),
+ newTextId, (LPSTR)szTmp,
+ MAX_MSG_TXT, MF_BYCOMMAND) > 2) {
+ UnescapeAmpersands(szTmp + 2, sizeof(szTmp)-2);
+ strcat(szStatusFormat, szTmp + 2);
+ }
+ goto show;
+ }
+
+ //See if it's a MRU project item
+
+ if (newTextId > IDM_PROGRAM_LAST
+ && newTextId <= IDM_PROGRAM_LAST + MAX_MRU_FILES_KEPT) {
+ Dbg(LoadString(hInst, STA_Open_MRU_Project, (LPSTR)szStatusFormat, MAX_MSG_TXT));
+ if (GetMenuString(GetSubMenu(hMainMenu, PROJECTMENU + menuAdjust),
+ newTextId, (LPSTR)szTmp,
+ MAX_MSG_TXT, MF_BYCOMMAND) > 2) {
+ UnescapeAmpersands(szTmp + 2, sizeof(szTmp)-2);
+ strcat(szStatusFormat, szTmp + 2);
+ }
+ goto show;
+ }
+
+ //See if it's a MDI window item
+
+ if (newTextId >= IDM_WINDOWCHILD
+ && newTextId < IDM_WINDOWCHILD + MAX_DOCUMENTS) {
+
+ PSTR pStr;
+
+ Dbg(LoadString(hInst, STA_Open_MDI_Window, (LPSTR)szStatusFormat, MAX_MSG_TXT));
+ if (GetMenuString(hWindowSubMenu, newTextId, (LPSTR)szTmp,
+ MAX_MSG_TXT, MF_BYCOMMAND) > 2) {
+
+ //Search and get rid of accelerator
+
+ Dbg((pStr = strchr(szTmp, '\t' - 1)) != NULL);
+ *pStr = '\0';
+ UnescapeAmpersands(szTmp + 2, sizeof(szTmp)-2);
+ strcat(szStatusFormat, szTmp + 2);
+ }
+ goto show;
+ }
+
+ //It's system menu or unknown, Clear status Bar
+
+ Dbg(LoadString(hInst, SYS_StatusClear, (LPSTR)szStatusFormat, MAX_MSG_TXT));
+ } else
+ //Load Info text or Error Message
+ Dbg(LoadString(hInst, newTextId, (LPSTR)szStatusFormat, MAX_MSG_TXT));
+
+
+ show:
+
+ //Build the status text with the var parameters
+
+ va_start(vargs, forceUpdate);
+ vsprintf(szStatusText, szStatusFormat, vargs);
+ va_end(vargs);
+
+ //Save whether this is an error message
+
+ status.errormsg = (msgType == STATUS_ERRORTEXT);
+
+ //Save last status Text
+
+ status.lastTxt = newTextId;
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_TXT), szStatusText);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_TXT),
+ (LPRECT)NULL, FALSE);
+ }
+ return;
+} /* StatusText() */
+
+
+/*** StatusMultiKey
+**
+** Synopsis:
+** void = StatusMultiKey(fNewVal)
+**
+** Entry:
+** fNewVal -
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+*/
+
+void PASCAL StatusMultiKey(
+ BOOL newValue)
+{
+ LPSTR s;
+
+ if (newValue != status.multiKey) {
+ status.multiKey = newValue;
+ if (newValue)
+ s = status.multiKeyS;
+ else
+ s = szNull;
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_MULTIKEY), s);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_MULTIKEY),
+ (LPRECT)NULL, FALSE);
+ }
+} /* StatusMultiKey() */
+
+void PASCAL StatusOvertype(
+ BOOL newValue)
+{
+ LPSTR s;
+
+ if (newValue != status.overtype) {
+ status.overtype = newValue;
+ if (newValue)
+ s = status.overtypeS;
+ else
+ s = szNull;
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_OVERTYPE), s);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_OVERTYPE),
+ (LPRECT)NULL, FALSE);
+ }
+} /* StatusOvertype() */
+
+/*** StatusReadOnly
+**
+** Synopsis:
+** void = StatusReadOnly(fReadOnly)
+**
+** Entry:
+** fReadOnly - New read only state
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+*/
+
+void PASCAL StatusReadOnly(
+ BOOL newValue)
+{
+ LPSTR s;
+
+ if (newValue != status.readOnly) {
+ status.readOnly = newValue;
+ if (newValue)
+ s = status.readOnlyS;
+ else
+ s = szNull;
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_READONLY), s);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_READONLY),
+ (LPRECT)NULL, FALSE);
+ }
+} /* StatusReadOnly() */
+
+void PASCAL StatusNumLock(
+ BOOL newValue)
+{
+ LPSTR s;
+
+ if (newValue != status.numLock) {
+ status.numLock = newValue;
+ if (newValue)
+ s = status.numLockS;
+ else
+ s = szNull;
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_NUMLOCK), s);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_NUMLOCK),
+ (LPRECT)NULL, FALSE);
+ }
+} /* StatusNumLock() */
+
+void PASCAL StatusCapsLock(
+ BOOL newValue)
+{
+ LPSTR s;
+
+ if (newValue != status.capsLock) {
+ status.capsLock = newValue;
+ if (newValue)
+ s = status.capsLockS;
+ else
+ s = szNull;
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_CAPSLOCK), s);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_CAPSLOCK),
+ (LPRECT)NULL, FALSE);
+ }
+} /* StatusCapsLock() */
+
+void PASCAL StatusLineColumn(
+ int newLine,
+ int newColumn)
+{
+ char s[15], tmp[15];
+
+ //Handle line
+ if (newLine != status.line) {
+ status.line = newLine;
+
+ if (newLine == 0)
+ tmp[0] = '\0';
+ else {
+ _itoa(newLine, s, 10);
+
+ //Fill tmp with 0
+ strcpy(tmp, status.lineS);
+
+ //Insert our string at the right place (tmp must be bigger of 1 char)
+ memmove(tmp + STATUS_LINE_SIZE - strlen(s), s, strlen(s));
+ }
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_LINE), tmp);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_LINE),
+ (LPRECT)NULL, FALSE);
+ }
+
+ //Handle column
+ if (newColumn != status.column) {
+ status.column = newColumn;
+
+ if (newColumn == 0)
+ tmp[0] = '\0';
+ else {
+ _itoa((int)newColumn, s, 10);
+
+ //Fill tmp with 0
+ strcpy(tmp, status.columnS);
+
+ //Insert our string at the right place
+ memmove(tmp + STATUS_COLUMN_SIZE - strlen(s), s, strlen(s));
+ }
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_COLUMN), (LPSTR)tmp);
+
+ if (!status.hidden)
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_COLUMN),
+ (LPRECT)NULL, FALSE);
+ }
+ return;
+} /* StatusLineColumn() */
+
+/*** StatusSrc
+**
+** Synopsis:
+** void = StatusSrc(newValue)
+**
+*/
+
+void PASCAL StatusSrc(BOOL newValue)
+{
+ LPSTR s;
+
+ if (newValue != status.fSrcMode) {
+ status.fSrcMode = newValue;
+ if (newValue)
+ s = status.rgchSrcMode2;
+ else
+ s = status.rgchSrcMode;
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_SRC), s);
+
+ if (status.hidden)
+ return;
+
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_SRC),
+ (LPRECT)NULL, FALSE);
+ }
+
+ if ((newValue == TRUE) && (disasmView == -1))
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+} /* StatusSrc() */
+
+/*** StatusPidTid
+**
+*/
+
+void PASCAL StatusPidTid(UINT ipid, UINT itid)
+{
+ LPSTR s;
+
+ if (ipid != (UINT) status.iCurPid) {
+ status.iCurPid = ipid;
+ if (ipid == -1) {
+ s = NULL;
+ } else {
+ sprintf(status.rgchCurPid, "%d", ipid);
+ s = status.rgchCurPid;
+ }
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_CURPID), s);
+
+ if (!status.hidden) {
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_CURPID),
+ (LPRECT)NULL, FALSE);
+ }
+ }
+
+ if (itid != (UINT) status.iCurTid) {
+ status.iCurTid = itid;
+ if (itid == -1) {
+ s = NULL;
+ } else {
+ sprintf(status.rgchCurTid, "%d", itid);
+ s = status.rgchCurTid;
+ }
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_CURTID), s);
+
+ if (!status.hidden) {
+ InvalidateRect(GetDlgItem(status.hwndStatus, ID_STATUS_CURTID),
+ (LPRECT)NULL, FALSE);
+ }
+ }
+
+ return;
+} /* StatusPidTid() */
+
+
+/*** fScanAnyLong
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+/****************************************************************************
+
+ FUNCTION: fScanAnyLong
+
+ PURPOSE: Converts the text form of a long value in
+ to the binary representation. The language
+ parameter specifies the expected format of the
+ number. If it is C then decimal, octal (leading 0)
+ and hex (leading 0x) are supported. If it is
+ Pascal then decimal and hex (leading $) are
+ handled. If it is AUTO then C is tried first
+ and Pascal if the conversion is unsuccessful.
+
+ RETURNS: TRUE if conversion is successful, FALSE if
+ not. To return TRUE a number must be successfully
+ scanned AND it must fall within the passed max and
+ min values.
+
+****************************************************************************/
+BOOL PASCAL fScanAnyLong(LPSTR lpszSource, WORD wLanguage,
+ long *plDest, long lMin, long lMax)
+{
+ long lLong;
+ PSTR pszTmp;
+ BOOL fGotANumber = FALSE;
+ char szSource[80];
+
+ _fstrncpy(szSource, lpszSource, sizeof(szSource)-1);
+ szSource[sizeof(szSource)-1] = '\0';
+
+ if ((wLanguage == PASCAL_LANGUAGE) || (wLanguage == AUTO_LANGUAGE))
+ {
+ // look for '$' first
+ // skip whitespace
+ pszTmp = szSource;
+ while (whitespace(*pszTmp)) pszTmp++;
+ if (*pszTmp == '$')
+ {
+ pszTmp++;
+ lLong = strtol(pszTmp, (PSTR *)NULL, 16);
+ fGotANumber = TRUE;
+ }
+ else if (wLanguage == PASCAL_LANGUAGE)
+ {
+ // Try and read a decimal
+ lLong = strtol(pszTmp, (PSTR *)NULL, 10);
+ fGotANumber = TRUE;
+ }
+ }
+
+ if (!fGotANumber)
+ {
+ lLong = strtol(szSource, (PSTR *)NULL, 0);
+ }
+
+ if ((lLong >= lMin) && (lLong <= lMax))
+ {
+ *plDest = lLong;
+ return TRUE;
+ }
+
+ return FALSE;
+} /* fScanAnyLong() */
+
+/*** QCQPEnumFonts
+**
+** Synopsis:
+** int = QCQPEnumFonts(lf, mtr, type, data)
+**
+** Entry:
+** lf
+** mtr
+** type
+** data
+**
+** Returns:
+**
+** Description:
+** Enumerates fonts faces names or font chars sizes
+**
+*/
+
+int FAR PASCAL LOADDS QCQPEnumFonts(LPLOGFONT pLf, LPTEXTMETRIC mtr, DWORD fontType, LPARAM data)
+{
+ #define NBOFSIZES 20
+
+ switch (LOWORD(data)) {
+ case 0:
+
+ //Just count the fonts, but skip the Decoratives
+
+ if (pLf->lfCharSet != SYMBOL_CHARSET
+ && (pLf->lfPitchAndFamily & 0xF0) != FF_DECORATIVE)
+ fontsNb++;
+ return 1;
+
+ case 1:
+ if (pLf->lfCharSet != SYMBOL_CHARSET
+ && (pLf->lfPitchAndFamily & 0xF0) != FF_DECORATIVE) {
+
+ fonts[fontsNb] = *pLf;
+ fonts[fontsNb].lfWidth = 0;
+ fontsNb++;
+ }
+ return 1;
+
+ case 2:
+ //Just count the sizes for that font
+
+ if (fontType & RASTER_FONTTYPE)
+ fontSizesNb++;
+ else
+ fontSizesNb = NBOFSIZES;
+ return 1;
+
+ case 3:
+ {
+ int i = 0;
+
+ if (fontType & RASTER_FONTTYPE) {
+
+ //Insert the new element sorted in the array
+
+ while (i < fontSizesNb && pLf->lfHeight > fontSizes[i])
+ i++;
+
+ if (i < fontSizesNb) {
+
+ //We don't insert the duplicates
+
+ if (pLf->lfHeight == fontSizes[i])
+ return 1;
+
+ //Insert element
+
+ _fmemmove(fontSizes + i + 1, fontSizes + i,
+ (fontSizesNb - i) * sizeof(int));
+ _fmemmove(fontSizesPoint + i + 1, fontSizesPoint + i,
+ (fontSizesNb - i) * sizeof(int));
+ }
+
+ //Store size in pixels
+
+ fontSizes[i] = pLf->lfHeight;
+
+ //Store pixels converted into points
+
+ fontSizesPoint[i] =
+ (int)((72L * (pLf->lfHeight - mtr->tmInternalLeading)
+ + (HIWORD((DWORD)data) / 2)) / (HIWORD((DWORD)data)));
+
+ fontSizesNb++;
+ } else {
+ int k = 6;
+
+ fontSizesNb = NBOFSIZES;
+
+ //Put a set of sizes in the array
+
+ for (i = 0 ; i < fontSizesNb; i++) {
+ fontSizesPoint[i] = k;
+ fontSizes[i] = (int)((k * (HIWORD((DWORD)data)) + 72L / 2) / 72L);
+ k +=2;
+ }
+ }
+ return 1;
+ }
+ }
+} /* QCQPEnumFonts() */
+
+/*** GetFontSizes
+**
+** Synopsis:
+** void = GetFontSizes(hWnd, currentFont)
+**
+** Entry:
+** hWnd -
+** currentFont -
+**
+** Returns:
+** nothing
+**
+** Description
+**
+*/
+
+void GetFontSizes(HWND hWnd, int currentFont)
+{
+ HDC hDC;
+ FONTENUMPROC EnumProc;
+
+ hDC = GetDC(hWnd);
+
+ //Dbg((LONG) (EnumProc = (FONTENUMPROC) MakeProcInstance((FARPROC)QCQPEnumFonts, hInst)));
+
+
+ EnumProc = (FONTENUMPROC)QCQPEnumFonts;
+
+ //First query the number of sizes for this font
+
+ fontSizesNb = 0;
+ EnumFonts(hDC, fonts[currentFont].lfFaceName, EnumProc, 2);
+
+ //Allocates the array to store the sizes and query the sizes
+
+ if (fontSizes != NULL) {
+ Xfree((LPSTR)fontSizes);
+ Xfree((LPSTR)fontSizesPoint);
+ }
+
+ fontSizes = (LPINT)Xalloc(fontSizesNb * sizeof(*fontSizes));
+ fontSizesPoint = (LPINT)Xalloc(fontSizesNb * sizeof(*fontSizesPoint));
+ fontSizesNb = 0;
+ EnumFonts(hDC, fonts[currentFont].lfFaceName, EnumProc,
+ MAKELONG(3, GetDeviceCaps(hDC, LOGPIXELSY)));
+ //FreeProcInstance(EnumProc);
+ ReleaseDC(hWnd, hDC);
+ return;
+} /* GetFontSizes() */
+
+/*** LoadFonts
+**
+** Synopsis:
+** void = LoadFonts(hWnd)
+**
+** Entry:
+** hWnd -
+**
+** Returns:
+** nothing
+**
+** Description:
+** Load available fonts
+**
+*/
+
+void LoadFonts(HWND hWnd)
+{
+
+ HDC hDC;
+ FONTENUMPROC EnumProc;
+
+ hDC = GetDC(hWnd);
+
+ //Dbg((LONG) (EnumProc = (FONTENUMPROC) MakeProcInstance((FARPROC)QCQPEnumFonts, hInst)));
+
+ EnumProc = (FONTENUMPROC)QCQPEnumFonts;
+
+
+ //First count the number of fonts
+ fontsNb = 0;
+ EnumFonts(hDC, NULL, EnumProc, 0);
+
+ //Allocates the array to store the fonts and query the fonts
+ if (fonts != NULL)
+ Xfree((LPSTR)fonts);
+ fonts = (LPLOGFONT)Xalloc(fontsNb * sizeof(*fonts));
+ fontsNb = 0;
+ EnumFonts(hDC, NULL, EnumProc, 1);
+ fontCur = 0;
+ //FreeProcInstance(EnumProc);
+ ReleaseDC(hWnd, hDC);
+ return;
+} /* LoadFonts() */
+
+
+int PASCAL
+OpenDebugWindow(
+ int winType,
+ LPWININFO lpWinInfo,
+ int Preference
+ )
+/*++
+
+Routine Description:
+
+ Opens Cpu, Watch, Locals, Calls, or Memory Window under MDI
+ Handles special case for memory win's
+
+Arguments:
+
+ winType - Supplies Type of debug window to be openned
+
+Return Value:
+
+ View number on success and -1 on failures
+
+--*/
+
+{
+ HWND win = NULL;
+ int view = -1;
+
+ switch (winType) {
+
+ case WATCH_WIN:
+ case LOCALS_WIN:
+ case CPU_WIN:
+ case FLOAT_WIN:
+ /*
+ * Let the Pane Manager handle openning the window (it will
+ * check for prior existance), get the view number and
+ * return without using the document manager.
+ */
+
+ OpenPanedWindow(winType, lpWinInfo, Preference);
+ for (view=0; view < MAX_VIEWS; view++) {
+ if (Views[view].Doc == -winType) {
+ break;
+ }
+ }
+ if (view == MAX_VIEWS) {
+ view = -1;
+ }
+ return view;
+
+ case CALLS_WIN:
+ OpenCallsWindow(winType, lpWinInfo, Preference);
+ for (view=0; view < MAX_VIEWS; view++) {
+ if (Views[view].Doc == -winType) {
+ break;
+ }
+ }
+ if (view == MAX_VIEWS) {
+ view = -1;
+ }
+ return view;
+
+ case DOC_WIN:
+ case DISASM_WIN:
+ case COMMAND_WIN:
+ win = GetDebugWindowHandle((WORD) winType);
+ break;
+
+ case MEMORY_WIN:
+
+ if (DebuggeeActive())
+ {
+ if (StartDialog(DLG_MEMORY, DlgMemory) != TRUE)
+ {
+ MessageBeep (0);
+ return -1; // No Debuggee or User Cancel out.
+ }
+ }
+ break;
+
+ default:
+ Assert(FALSE);
+ return -1;
+ }
+
+
+ //
+ // Open the Debug Windows to standard size or to previous
+ // size if already opened
+ //
+
+ if (win == NULL) {
+ view = AddFile(MODE_CREATE, (WORD) winType, (LPSTR)szNull, lpWinInfo,
+ NULL, FALSE, -1, Preference);
+ }
+
+ else {
+
+ HWND MDIWin = GetParent(win);
+
+ if (IsIconic(MDIWin))
+ OpenIcon(MDIWin);
+
+ SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM) MDIWin, 0L);
+
+ for (view=0; view < MAX_VIEWS; view++) {
+ if (Views[view].Doc < 0) {
+ continue;
+ }
+
+ if (Docs[Views[view].Doc].docType == winType)
+ {
+ break;
+ }
+ }
+ if (view == MAX_VIEWS) {
+ view = -1;
+ }
+ }
+
+ bOffRibbon = TRUE; // module wide flag for ribbon/MDI focus
+ return view;
+}
+
+ /* OpenDebugWindow() */
+
+
+int
+GotoLine(
+ int view,
+ int lineNbr,
+ BOOL fDebugger
+ )
+/*++
+
+Routine Description:
+
+ Move to the passed line in the passed view - returns
+ line actually hit in case of adjustment.
+ (NB lines are passed in range 1 => N)
+
+Arguments:
+
+ view - Supplies the index of document window to do the goto in
+ lineNbr - Supplies the line number to go to
+ fDebugger - Supplies TRUE if debugger is doing the goto
+
+Return Value:
+
+ lineNbr - Actual line nubmer we went to
+
+--*/
+
+{
+ Assert( Views[view].Doc >= 0);
+
+ lineNbr = min(max(1, (int)lineNbr), (int)Docs[Views[view].Doc].NbLines) - 1;
+ PosXYCenter(view, 0, lineNbr, fDebugger);
+ return lineNbr;
+} /* GotoLine() */
+
+
+void
+LineStatus(
+ int doc,
+ int lineNbr,
+ WORD state,
+ LINESTATUSACTION action,
+ BOOL positionInFirstView,
+ BOOL redraw
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to change the highlighting done on a per line
+ basis. This include tags, current line, breakpoints, errors.
+
+Arguments:
+
+ doc - Supplies the document index
+ lineNbr - Supplies the 0 based line number to be changed
+ state - Supplies the state to be changed.
+ action - Supplies the TRUE/FALSE of the state to be set
+ positionInFirstView - Supplies TRUE if the focues is to be changed to
+ the first view for the document in question
+ redraw - Supplies TRUE if a redraw is to be forced now
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+
+ y = lineNbr = min(max(1, (int)lineNbr), (int)Docs[doc].NbLines) - 1;
+
+ if (!FirstLine (doc, &pl, &y, &pb)) {
+ Assert(FALSE);
+ return;
+ }
+
+ switch (action) {
+ case LINESTATUS_ON:
+ SET(pl->Status, state);
+ break;
+
+ case LINESTATUS_OFF:
+ RESET(pl->Status, state);
+ break;
+
+ case LINESTATUS_TOGGLE:
+ TOGGLE(pl->Status, state);
+ break;
+ }
+
+ CloseLine(doc, &pl, y, &pb);
+
+ if (positionInFirstView) {
+ PosXY(Docs[doc].FirstView, Views[Docs[doc].FirstView].X, lineNbr, TRUE);
+ }
+
+ if (redraw) {
+ InvalidateLines(Docs[doc].FirstView, lineNbr, lineNbr, FALSE);
+
+ if (! (IsIconic(GetParent(Views[Docs[doc].FirstView].hwndClient)) ||
+ IsZoomed(GetParent(Views[Docs[doc].FirstView].hwndClient))))
+ {
+ ShowWindow (GetParent(Views[Docs[doc].FirstView].hwndClient), SW_SHOWNORMAL); //re-activate the iconized window gaining
+ //current focus
+ }
+
+
+ ClearSelection (Docs[doc].FirstView);
+
+
+ // SendMessage (GetParent(Views[Docs[doc].FirstView].hwndClient), WM_MDIACTIVATE,0,0L);
+
+ }
+
+ return;
+} /* LineStatus() */
+
+/*** QueryLineStatus
+**
+** Synopsis:
+** bool = QueryLineStatus(doc, lineNbr, state)
+**
+** Entry:
+** doc - which document to look in
+** lineNbr - which line to number look at the status for
+** state - which status flags we are looking at
+**
+** Returns:
+** TRUE if any of the flags are set and FALSE otherwise
+**
+** Description:
+** This function is used to find out if any status flags are current
+** set on a line
+*/
+
+BOOL QueryLineStatus(int doc, int lineNbr, UINT state)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+
+ /*
+ ** If we are not looking at a valid line then no status flags
+ ** are ever set.
+ */
+
+ if ((lineNbr < 1) || (lineNbr > Docs[doc].NbLines-1)) {
+ return FALSE;
+ }
+
+ y = lineNbr - 1;
+
+ if (!FirstLine (doc, &pl, &y, &pb)) {
+ Assert(FALSE);
+ return FALSE;
+ }
+
+ CloseLine(doc, &pl, y, &pb);
+
+ return (pl->Status & state) ? TRUE : FALSE;
+} /* QueryLineStatus() */
+
+/*** FindDoc
+**
+** Synopsis:
+** bool = FindDoc(fileName, doc, docOnly)
+**
+** Entry:
+**
+** Returns:
+** TRUE if document was found FALSE otherwise
+**
+** Description:
+** Given a file Name, find doc #, if docOnly == TRUE then
+** the Debug windows are not included
+**
+** Updates the location pointed to by doc with the document number
+*/
+
+BOOL FindDoc(
+ LPSTR fileName,
+ int *doc,
+ BOOL docOnly)
+{
+ LPSTR SrcFile = GetFileName( fileName );
+
+ if ( SrcFile ) {
+ if (docOnly) {
+ for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
+ if (Docs[*doc].docType == DOC_WIN && Docs[*doc].FirstView != -1
+ && _stricmp(GetFileName(Docs[*doc].FileName), SrcFile) == 0) {
+ return TRUE;
+ }
+ }
+ }
+ else {
+ for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
+ if (Docs[*doc].FirstView != -1
+ && _stricmp(GetFileName(Docs[*doc].FileName), SrcFile) == 0) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/*** FindDoc1
+**
+** Synopsis:
+** bool = FindDoc1(fileName, doc, docOnly)
+**
+** Entry:
+**
+** Returns:
+** TRUE if document was found FALSE otherwise
+**
+** Description:
+** Given a file Name, find doc #, if docOnly == TRUE then
+** the Debug windows are not included
+**
+** Updates the location pointed to by doc with the document number
+*/
+
+BOOL FindDoc1(
+ LPSTR fileName,
+ int *doc,
+ BOOL docOnly)
+{
+ BOOL (*lpCompareFileName)(LPSTR, LPSTR);
+ LPSTR SrcFile = GetFileName( fileName );
+
+ if ( SrcFile ) {
+#if 1
+ if (strlen(SrcFile) == strlen(fileName)) {
+ lpCompareFileName = CompareFileName;
+ } else {
+ lpCompareFileName = CompareFileNameWithPath;
+ SrcFile = fileName;
+ }
+#else
+ lpCompareFileName = CompareFileName;
+#endif
+ if (docOnly) {
+ for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
+ if (Docs[*doc].docType == DOC_WIN && Docs[*doc].FirstView != -1
+ && (*lpCompareFileName)(Docs[*doc].FileName, SrcFile)) {
+ return TRUE;
+ }
+ }
+ }
+ else {
+ for (*doc = 0; *doc < MAX_DOCUMENTS; (*doc)++) {
+ if (Docs[*doc].FirstView != -1
+ && (*lpCompareFileName)(Docs[*doc].FileName, SrcFile)) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+static
+BOOL
+CompareFileName(
+ LPSTR szName1,
+ LPSTR szName2
+)
+{
+ return (_stricmp(GetFileName(szName1), szName2) == 0);
+}
+
+static
+BOOL
+CompareFileNameWithPath(
+ LPSTR szName1,
+ LPSTR szName2
+)
+{
+ return (_stricmp(szName1, szName2) == 0);
+}
+
+
+char *
+GetFileName(
+ IN char * szPath
+ )
+
+/*++
+
+Routine Description:
+
+ Returns a pointer to the filename portion of a path
+
+Arguments:
+
+ szPath - Supplies the path
+
+Return Value:
+
+ char * - Pointer to the filename portion of the path.
+
+--*/
+{
+ char *p = NULL;
+
+ if ( *szPath ) {
+
+ p = szPath + strlen(szPath );
+#ifdef DBCS
+ while (p > szPath) {
+ p = CharPrev(szPath, p);
+ if (*p == '\\' || *p == '/') {
+ break;
+ }
+ }
+#else
+ while ( (*p != '\\') && (*p != '/') && (p != szPath ) ) {
+ p--;
+ }
+#endif
+ if ((*p == '\\' ) || (*p == '/' )) {
+ p++;
+ }
+ }
+
+ return p;
+}
+
+
+
+
+
+/****************************************************************************
+
+ FUNCTION: ClearDocStatus
+
+ PURPOSE: Given a doc, clear all visual breakpoints, tags or
+ compile errors in the views in that doc.
+
+****************************************************************************/
+void ClearDocStatus(
+ int doc,
+ WORD state)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ int y;
+
+ y = 0;
+
+ if (!FirstLine(doc, &pl, &y, &pb))
+ return;
+ while (TRUE) {
+ if (pl->Status & state) {
+ pl->Status &= ~state;
+ InvalidateLines(Docs[doc].FirstView, y - 1, y - 1, FALSE);
+ }
+ if (y >= Docs[doc].NbLines)
+ break;
+ else
+ if (!NextLine(doc, &pl, &y, &pb))
+ return;
+ }
+ CloseLine(doc, &pl, y, &pb);
+ return;
+} /* ClearDocStatus() */
+
+
+/****************************************************************************
+
+ FUNCTION: ClearAllDocStatus
+
+ PURPOSE: Clear all visual breakpoints, tags or compile errors
+ that in all docs.
+
+****************************************************************************/
+void ClearAllDocStatus(
+ WORD state)
+{
+ int d;
+
+ for (d = 0; d < MAX_DOCUMENTS; d++)
+ if (Docs[d].FirstView != -1)
+ ClearDocStatus(d, state);
+
+ return;
+} /* ClearAllDocStatus() */
+
+
+/****************************************************************************
+
+ FUNCTION: VisibleListboxLines
+
+ PURPOSE: Return the number of visible lines in the list box
+ associated with the passed handle.
+ Note that this function assumes that each list box item
+ is the same height.
+
+****************************************************************************/
+WORD VisibleListboxLines(HWND hListbox)
+{
+ RECT ListRect; // Dims of client area of listbox
+ RECT ItemRect; // Dims of an item within listbox
+
+ GetClientRect(hListbox, (LPRECT)&ListRect);
+ Dbg(SendMessage(hListbox, LB_GETITEMRECT, 0, (LONG)(LPRECT)&ItemRect)!=LB_ERR);
+
+ return ((WORD)((ListRect.bottom - ListRect.top + 1) /
+ (ItemRect.bottom - ItemRect.top)));
+} /* VisibleListboxLines() */
+
+/****************************************************************************
+
+ FUNCTION: IsMonoModeProc
+
+ PURPOSE: Checks for what kind of monitor is present.
+ Returns a TRUE if it is Monochrome and FALSE otherwise.
+
+****************************************************************************/
+BOOL FAR PASCAL IsMonoModeProc ()
+{
+ return FALSE;
+} /* IsMonoModeProc() */
+
+/*** AjustFullPathName
+**
+** Synopsis:
+** void = AdjustFullPathName(fullPath, adjustedPath, len
+**
+** Entry:
+**
+** Returns:
+** nothing
+**
+** Description:
+** Adjust Full Path name to fit in a specified len string
+** Priority rules for reduction are :
+** - FileName.extension
+** - Drive
+** - Nth dir
+** - (N-1)th dir
+** - ...
+** - 1st dir
+*/
+
+void AdjustFullPathName(
+ PSTR fullPath,
+ PSTR adjustedPath,
+ int len)
+{
+ int remain = len;
+ PSTR cur;
+
+ //Assert(len >= MAXFILENAMELEN);
+
+ if ((int)strlen(fullPath) <= len) {
+ strcpy(adjustedPath, fullPath);
+ return;
+ }
+
+ *adjustedPath = '\0';
+
+ _splitpath(fullPath, szDrive, szDir, szFName, szExt);
+
+ remain -= (strlen(szFName) + strlen(szExt));
+
+ //Try to add the drive
+ if (szDrive) {
+ if (remain >= (int)strlen(szDrive)) {
+ strcat(adjustedPath, szDrive);
+ remain -= strlen(szDrive);
+ } else {
+
+ //No space, try to add some "." templates
+ while (remain-- > 0) {
+ strcat(adjustedPath, ".");
+ }
+ goto rebuild;
+ }
+ }
+
+ //Extract dirs until we have no more space left
+ if (szDir) {
+ cur = szDir + strlen(szDir) - remain;
+
+ if (cur <= szDir ) {
+ //We have space to copy all dirs
+ strcat(adjustedPath, szDir);
+ } else if (remain < 5) {
+ //If we had the drive and there is a dir, better get rid
+ //of the drive to avoid to return a wrong pathName.
+ if (szDrive && strlen(szDrive) >= 2) {
+ strcpy(adjustedPath, "..");
+ }
+ } else {
+ //Add "\..\" template, if we have space left
+
+ strcat(adjustedPath, "\\...");
+ remain -= 4;
+
+ if (remain == 1) {
+ //Just space to add a "\"
+ strcat(adjustedPath, "\\");
+ } else {
+ //We have no space to copy all dirs, synchronize to next
+ //dir beginning and add it to reduced path name
+ cur = szDir + strlen(szDir) - remain;
+ while (*cur && *cur != '\\') {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*cur) && *(cur+1))
+ cur += 2;
+ else
+#endif
+ cur++;
+ }
+ if (*cur) {
+ strcat(adjustedPath, cur);
+ } else {
+ strcat(adjustedPath, "\\");
+ }
+ }
+ }
+ }
+
+rebuild:
+
+ //Rebuild FileName.extension
+ remain = len - strlen(adjustedPath);
+ strncat(adjustedPath, szFName, remain);
+ remain -= strlen(szFName);
+ if (remain > 0) {
+ strncat(adjustedPath, szExt, remain);
+ }
+} /* AdjustFullPathName() */
+
+/*** ReadIni
+**
+** Synopsis:
+** bool = ReadIni(hFile, lpBuffer, wBytes)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** ReadIni to file and add to checksum
+**
+*/
+
+BOOL ReadIni(int hFile, LPSTR lpBuffer, int wBytes)
+{
+ //Read File Buffer
+
+ if (_lread(hFile, lpBuffer, wBytes) != (UINT) wBytes)
+ return ErrorBox2(hwndFrame, MB_TASKMODAL, ERR_Ini_File_Read, (LPSTR)iniFileName);
+
+ return TRUE;
+} /* ReadIni() */
+
+/*** WriteAndSum
+**
+** Synopsis:
+** bool = WriteAndSum(hFile, lpBuffer, wBytes)
+**
+** Entry:
+** hFile - Handle to file to do the write on
+** lpBuffer - Buffer containning bytes to be written
+** wBytes - count of bytes to be written
+**
+** Returns:
+** TRUE on a sucessful write and FALSE on failure
+**
+** Description:
+** This function will write data out to the file connected to the
+** file handle and to compute a checksum on the data being written
+** out. The checksum is a sum of all bytes written.
+**
+*/
+
+BOOL WriteAndSum(int hFile, LPSTR lpBuffer, int wBytes)
+{
+ register int i;
+
+ //Add buffer bytes to checksum
+
+ for (i = 0; i < wBytes; i++)
+ checkSum += (BYTE)lpBuffer[i];
+
+ //Write File Buffer
+
+ if (_lwrite(hFile, lpBuffer, wBytes) != (UINT) wBytes)
+ return ErrorBox2(hwndFrame, MB_TASKMODAL, ERR_Ini_File_Write, (LPSTR)iniFileName);
+
+ return TRUE;
+} /* WriteAndSum() */
+
+
+/*** FailGlobalLock
+**
+** Synopsis:
+** bool = FailGlobalLoc(h, p)
+**
+** Entry:
+**
+** Returns:
+** TRUE if locked and FALSE if failed to lock
+**
+** Description:
+** Try to lock a global memory handle
+*/
+
+BOOL FailGlobalLock(
+ HANDLE h,
+ LPSTR *p)
+{
+ if ((*p = GlobalLock (h)) == 0) {
+ Dbg(GlobalFree (h) == NULL);
+ return TRUE;
+ }
+ return FALSE;
+} /* FailGlobalLock() */
+
+/*** GetCurrentText
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+** FALSE if there is a problem or nothing to get
+**
+** Description:
+** Retrieve in view the word at cursor, or the first line
+** of text if selection is active. If not NULL, beginOffset
+** and endOffset return number of chars relative to cursor
+** position. If a selection is active and is over several
+** lines and cursor in selection is not above a word and
+** lookAround is TRUE, the word at left is returned and
+** 'lookAround' is TRUE, otherwise lookAround is FALSE.
+**
+*/
+
+BOOL GetCurrentText(
+ int view,
+ BOOL *lookAround,
+ LPSTR pText,
+ int maxSize,
+ LPINT xLeft,
+ LPINT xRight)
+{
+ NPVIEWREC v = &Views[view];
+
+ //If selection active
+ if (v->BlockStatus)
+
+ //Returns selected text
+ return GetSelectedText(view, lookAround, (LPSTR)pText,
+ maxSize, xLeft, xRight);
+ else {
+
+ //No selection, send word at cursor
+ return GetWordAtXY(view, v->X, v->Y, FALSE, lookAround, TRUE,
+ (LPSTR)pText, maxSize, xLeft, xRight);
+ }
+} /* GetCurrentText() */
+
+
+/*** TimeIn100ths
+**
+** Synopsis:
+** ulong = TimeIn100ths()
+**
+** Entry:
+** None
+**
+** Return:
+** the current time in 100ths of a second
+**
+** Description:
+** This function will look at the clock and return the current time
+** routined to 100ths of a second
+*/
+
+ULONG PASCAL TimeIn100ths(void)
+{
+#ifdef WIN32
+ return GetTickCount();
+#else
+ struct _dostime_t time;
+
+ _dos_gettime(&time);
+ return (((((time.hour*60UL)+time.minute)*60)+time.second)*100)+time.hsecond;
+#endif
+} /* TimeIn100ths() */
+
+
+/****************************************************************************
+
+ FUNCTION: StopTimeIn100ths
+
+ PURPOSE: Returns the current time + the passed delay in 100ths
+ of a second. NB takes into account the time period
+ crossing midnight.
+
+ RETURNS: See above.
+
+****************************************************************************/
+/*** StopTimeIn100ths
+**
+** Synopsis:
+** ulong = StopTimeIn100ths( DelayIn100ths)
+**
+** Entry:
+** DelayIn100ths - delay to add to current time
+**
+** Return:
+** Current time plus the delay request in 100ths of a second
+**
+** Description:
+** This routine will take the current system time and add the requested
+** delay to it. The result in 100ths of a second will then be returned
+*/
+
+ULONG PASCAL StopTimeIn100ths(ULONG DelayIn100ths)
+{
+ return (TimeIn100ths() + DelayIn100ths) % HUNDREDTHS_IN_A_DAY;
+}
+
+/*** ProcessQCQPMessage
+**
+** Synopsis:
+** void = ProcessQCQPMessage(lpmsg)
+**
+** Entry:
+** lpmsg - The message to be processed and forwarded as appropriate
+**
+** Returns:
+** nothing:
+**
+** Description:
+** Performs translation and dispatching of a message
+** received by QCQP. Should be called by anyone that
+** does a Get/Peek etc Message.
+**
+*/
+
+void PASCAL ProcessQCQPMessage(LPMSG lpMsg)
+{
+ //If a keyboard message is for the MDI , let the MDI client
+ //take care of it. Otherwise, check to see if it's a normal
+ //accelerator key (like F3 = find next). Otherwise, just handle
+ //the message as usual.
+ if (!TranslateMDISysAccel(hwndMDIClient, lpMsg) &&
+ !TranslateAccelerator(hwndFrame, hAccTable, lpMsg))
+ {
+ TranslateMessage(lpMsg);
+ MapLocalHotKey(lpMsg);
+ DispatchMessage(lpMsg);
+ }
+} /* ProcessQCQPMessage() */
+
+/*** AppendFilter
+**
+**
+** Description:
+** Append a filter to an existing filters string.
+**
+*/
+
+void NEAR PASCAL AppendFilter(WORD filterTextId, int filterExtId,
+ LPSTR filterString, int *len, int maxLen)
+{
+ int size;
+
+ //Append filter text
+
+ Dbg(LoadString(hInst, filterTextId, (LPSTR)szTmp, MAX_MSG_TXT));
+ size = strlen(szTmp) + 1;
+ Assert(*len + size <= maxLen);
+ _fmemmove(filterString + *len, szTmp, size);
+ *len += size;
+
+ //Append filter extension
+
+ Dbg(LoadString(hInst, filterExtId, (LPSTR)szTmp, MAX_MSG_TXT));
+ size = strlen(szTmp) + 1;
+ Assert(*len + size < maxLen);
+ _fmemmove(filterString + *len, szTmp, size);
+ *len += size;
+
+ return;
+} /* AppendFilter() */
+
+/*** InitFilterString
+**
+** Description:
+** Initialize file filters for file dialog boxes.
+*/
+
+void InitFilterString(WORD titleId, LPSTR filter, int maxLen)
+{
+ int len = 0;
+
+ switch (titleId) {
+ case DLG_SaveAs_Filebox_Title:
+ case DLG_Open_Filebox_Title:
+ case DLG_Merge_Filebox_Title:
+ case DLG_Browse_Filebox_Title:
+ AppendFilter(TYP_File_SOURCE, DEF_Ext_SOURCE, filter, &len, maxLen);
+ AppendFilter(TYP_File_INCLUDE, DEF_Ext_INCLUDE, filter, &len, maxLen);
+ AppendFilter(TYP_File_ASMSRC, DEF_Ext_ASMSRC, filter, &len, maxLen);
+ AppendFilter(TYP_File_INC, DEF_Ext_INC, filter, &len, maxLen);
+ AppendFilter(TYP_File_RC, DEF_Ext_RC, filter, &len, maxLen);
+ AppendFilter(TYP_File_DLG, DEF_Ext_DLG, filter, &len, maxLen);
+ AppendFilter(TYP_File_DEF, DEF_Ext_DEF, filter, &len, maxLen);
+ AppendFilter(TYP_File_MAK, DEF_Ext_MAK, filter, &len, maxLen);
+ break ;
+
+ case DLG_Browse_DbugDll_Title:
+ AppendFilter(TYP_File_DLL, DEF_Ext_DLL, filter, &len, maxLen);
+ break;
+
+ case DLG_Browse_UserDll_Title:
+ AppendFilter(TYP_File_SYM, DEF_Ext_SYM, filter, &len, maxLen);
+ AppendFilter(TYP_File_SYMS, DEF_Ext_SYMS, filter, &len, maxLen);
+ break;
+
+ default:
+ DAssert(FALSE);
+ break;
+ }
+
+ AppendFilter(TYP_File_ALL, DEF_Ext_ALL, filter, &len, maxLen);
+ filter[len] = '\0';
+ return;
+} /* InitFilterString() */
+
+
+/****************************************************************************
+
+ FUNCTION: KeyboardHook
+
+ PURPOSE: Check if keyboard hit is NUMLOCK, CAPSLOCK or INSERT
+
+****************************************************************************/
+
+LRESULT EXPORT KeyboardHook( int iCode, WPARAM wParam, LPARAM lParam )
+{
+ if (iCode == HC_ACTION) {
+
+ //See if NUMLOCK is hit and refresh status if so
+
+ if (wParam == VK_NUMLOCK
+ && HIWORD(lParam) & 0x8000 //Key up
+ && GetKeyState(VK_CONTROL) >= 0) //No Ctrl
+ StatusNumLock(!status.numLock);
+ else
+ //See if CAPSLOCK is hit and refresh status if so
+ if (wParam == VK_CAPITAL
+ && HIWORD(lParam) & 0x8000 //Key up
+ && GetKeyState(VK_CONTROL) >= 0) //No Ctrl
+ StatusCapsLock(!status.capsLock);
+ else
+ //See if INSERT is hit and refresh status if so
+ if (wParam == VK_INSERT
+ && ((HIWORD(lParam) & 0xE000) == 0x0000) //Key down was up before and No Alt
+ && GetKeyState(VK_SHIFT) >= 0 //No Shift
+ && GetKeyState(VK_CONTROL) >= 0 //No Ctrl
+ && IsChild(hwndMDIClient, GetFocus()) //Only editor windows
+ && curView != -1
+ && (Views[curView].Doc != -CPU_WIN)) // But not registers
+
+ StatusOvertype(!status.overtype);
+ }
+
+ return CallNextHookEx( hKeyHook, iCode, wParam, lParam );
+} /* KeyboardHook() */
+
+
+/*** GetDebugWindowHandle
+**
+** Synopsis:
+** hwnd = GetDebugWindowHandle(type)
+**
+** Entry:
+** type - Debug window type to get the handle for
+**
+** Returns:
+** The handle for this type of debug window if one exists, otherwise
+** it returns NULL
+**
+** Description:
+** This function is used to obtain the window handle for the
+** single instance of the debug window of class type.
+**
+*/
+
+HWND
+GetDebugWindowHandle(
+ WORD type
+ )
+{
+ int v;
+
+ if ((type == CPU_WIN) || (type == FLOAT_WIN) || (type == WATCH_WIN) ||
+ (type == LOCALS_WIN) || (type == CALLS_WIN)) {
+ type = -type;
+ }
+
+ for (v = 0; v < MAX_VIEWS; v++) {
+ if (type < -1) {
+ if (Views[v].Doc == (int) type) {
+ return Views[v].hwndClient;
+ }
+ } else if ((Views[v].Doc != -1) &&
+ (Docs[Views[v].Doc].docType == type)) {
+ return Views[v].hwndClient;
+ }
+ }
+ return NULL;
+} /* GetDebugWindowHandle() */
+
+/*** SetVerticalScrollBar
+**
+** Synopsis:
+** void = SetScrollBar(view, propagate)
+**
+** Entry:
+** view - document to set scroll bars for
+** propagate - Modify just this view or all other views on same document
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function is used to adjust the range of the vertical scroll bar
+** for a document. It will be set according to the number of lines in
+** the document. If desired then all views of the same document may have
+** their scroll bars adjusted at the same time. If so then the cursor
+** for the other windows will be verified as within the current line
+** count.
+*/
+
+void
+SetVerticalScrollBar(int view, BOOL propagate)
+{
+ int n = Docs[Views[view].Doc].NbLines - 1;
+
+ DAssert(Views[view].Doc >= 0);
+
+ // Need to work out disasmbler scroll bars later
+ if (view == disasmView) {
+ return;
+ }
+
+ // Only handle multiple views for DOC_WIN
+
+ if (!propagate || Docs[Views[view].Doc].docType != DOC_WIN) {
+
+ SetScrollRange(Views[view].hwndClient, SB_VERT, 0, max(n,1), TRUE);
+
+ } else {
+
+ int k = Docs[Views[view].Doc].FirstView;
+ NPVIEWREC v;
+
+ while (k != -1) {
+ v = &Views[k];
+
+ //Possibly adjust cursor position
+
+ if (v->Y > n) {
+ v->Y = n;
+ if (v->BlockYR > n) {
+ v->BlockYR = n;
+ }
+ if (v->BlockYL > n) {
+ v->BlockYL = n;
+ }
+ }
+ k = v->NextView;
+ SetScrollRange(v->hwndClient, SB_VERT, 0, max(n,1), TRUE);
+
+ }
+ }
+
+ return;
+} /* SetVerticalScrollBar() */
+
+/*** AuxPrintf
+**
+** Synopsis:
+** bool = AuxPrintf(iReqDebLevel, sz, ...)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Makes a printf style command for output on debug console
+*/
+
+#undef AuxPrintf
+BOOL AuxPrintf(int iReqDebLevel, LPSTR text, ...)
+{
+#if !REMOVEAUXPRINTFS
+ char buffer[MAX_MSG_TXT];
+ int fdComm;
+ va_list vargs;
+
+ if (iReqDebLevel > iDebugLevel)
+ return(FALSE);
+
+ va_start(vargs, text);
+ vsprintf(buffer, text, vargs);
+ va_end(vargs);
+ lstrcat(buffer,"\r\n");
+
+ // By-pass OutputDebugString, otherwise we'll get notifications
+ // about these things when debugging (DBG_N_InfoAvail)
+ //!OutputDebugString(buffer);
+ if ((fdComm = _lopen("com1", OF_WRITE)) != -1)
+ {
+ _lwrite(fdComm, buffer, _fstrlen(buffer));
+ _lclose(fdComm);
+ }
+
+ OutputDebugString(buffer);
+#endif
+ return FALSE;
+} /* AuxPrintf() */
+
+
+BOOL
+FindNameOn(
+ LSZ lszDest,
+ UINT cchDest,
+ LSZ lszPaths,
+ LSZ lszFile
+ )
+/*++
+
+Routine Description:
+
+ This function will look in each of the directories specified in
+ the lszPaths variable for the relative path lszFile. If the file
+ if fond to exist then the resulting name will be returned in
+ lszDest and TRUE is returned.
+
+Arguments:
+
+ lszDest - Supplies a buffer to place resulting name
+ cchDest - Supplies the number of bytes in buffer
+ lszPaths - Supplies a semi-colon seperated list of directories to search
+ lszFile - Supplies a file name to look for
+
+Return Value:
+
+ TRUE if file was found and FALSE otherwise.
+
+--*/
+{
+ char * lpch1;
+ char * lpch2;
+ char ch;
+ char rgchT[MAX_PATH*2];
+
+ lpch1 = lszPaths;
+
+ if (lpch1 == NULL)
+ return FALSE;
+
+ while (*lpch1 != 0) {
+ lpch2 = lpch1;
+ while ((*lpch2) && (*lpch2 != ';')) {
+#ifdef DBCS
+ lpch2 = CharNext(lpch2);
+#else
+ lpch2++;
+#endif
+ }
+
+ strncpy(rgchT, lpch1, lpch2-lpch1);
+ rgchT[lpch2-lpch1] = 0;
+ strcat(rgchT, "\\");
+ strcat(rgchT, lszFile);
+
+ if (_fullpath(lszDest, rgchT, cchDest) != NULL) {
+ if (FileExist(lszDest)) {
+ return TRUE;
+ }
+ }
+
+ lpch1 = lpch2;
+
+ if (*lpch1 == ';') {
+ lpch1++;
+ }
+ }
+
+ return FALSE;
+} /* FindNameOn() */
+
+
+BOOL
+SetDriveAndDir(
+ PSTR st
+ )
+{
+ int dirLen;
+ char sTmp[_MAX_PATH];
+
+ //Set current drive and dir
+ strcpy(sTmp, st);
+ _splitpath(sTmp, szDrive, szDir, szFName, szExt);
+ if (szDrive[0] != 0) {
+ if (_chdrive((int)(toupper(szDrive[0]) - 'A' + 1)) != 0)
+ return ErrorBox(ERR_Change_Drive, (LPSTR)szDrive);
+ }
+ dirLen = strlen(szDir);
+ AnsiToOem(szDir, sTmp);
+ if (dirLen > 0) {
+#ifdef DBCS
+ if (strlen(sTmp) > 1 && *CharPrev(sTmp, sTmp + dirLen - 1) == '\\')
+ sTmp[--dirLen] = 0;
+#else
+ if (strlen(sTmp) > 1 && sTmp[--dirLen] == '\\')
+ sTmp[dirLen] = 0;
+#endif
+ if (_chdir(sTmp) != 0) {
+ OemToAnsi(sTmp, szDir);
+ return ErrorBox(ERR_Change_Directory, (LPSTR)szDir);
+ }
+ }
+
+ return TRUE;
+}
+
+
+//*******************************************************************
+//*******************************************************************
+#ifdef DEBUGGING
+
+struct _timeb startTime;
+struct _timeb stopTime;
+
+void ShowElapsedTime(
+ void)
+{
+ int millisecs, secs;
+
+ secs = (int)(stopTime.time - startTime.time);
+ if (startTime.millitm > stopTime.millitm) {
+ secs--;
+ millisecs = (1000 + stopTime.millitm - startTime.millitm) / 10;
+ }
+ else
+ millisecs = (stopTime.millitm - startTime.millitm) / 10;
+ AuxPrintf(1, "%u' %u''", secs, millisecs);
+}
+
+void StartTimer(
+ void)
+{
+ _ftime(&startTime);
+}
+
+void StopTimer(
+ void)
+{
+ _ftime(&stopTime);
+}
+
+/****************************************************************************
+
+ FUNCTION: InfoBox
+
+ PURPOSE: Opens a Dialog box with a title and accepting
+ a printf style for text. It's for DEBUGGING USE ONLY
+
+ RETURNS: MessageBox result
+
+****************************************************************************/
+int InfoBox(
+ LPSTR text,
+ ...)
+{
+ char buffer[MAX_MSG_TXT];
+ va_list vargs;
+
+ va_start(vargs, text);
+ vsprintf(buffer, text, vargs);
+ va_end(vargs);
+ return MsgBox(GetActiveWindow(), buffer, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
+}
+
+#endif //debugging
+
+
+VOID
+InvalidateAllWindows(
+ VOID
+ )
+{
+ SendMessageNZ( GetCpuHWND(), WU_INVALIDATE, 0, 0L);
+ SendMessageNZ( GetFloatHWND(), WU_INVALIDATE, 0, 0l);
+ SendMessageNZ( GetLocalHWND(), WU_INVALIDATE, 0, 0L);
+ SendMessageNZ( GetWatchHWND(), WU_INVALIDATE, 0, 0L);
+ SendMessageNZ( GetCallsHWND(), WU_INVALIDATE, 0, 0L);
+}
+
+
+#ifdef DBCS
+/***************************************************************************
+
+
+
+***************************************************************************/
+VOID GetDBCSCharWidth(
+ HDC hDC,
+ LPTEXTMETRIC ptm,
+ LPVIEWREC lpv)
+{
+ SIZE Size;
+
+#ifdef DBCS
+ if (ptm->tmCharSet == SHIFTJIS_CHARSET) {
+ if (0 == (ptm->tmPitchAndFamily & TMPF_FIXED_PITCH)
+ && ptm->tmMaxCharWidth == ptm->tmAveCharWidth * 2) {
+ lpv->wViewPitch = VIEW_PITCH_ALL_FIXED;
+ } else {
+ lpv->wViewPitch = VIEW_PITCH_DBCS_FIXED;
+ }
+ } else {
+ if (0 == (ptm->tmPitchAndFamily & TMPF_FIXED_PITCH)) {
+ lpv->wViewPitch = VIEW_PITCH_ALL_FIXED;
+ } else {
+ lpv->wViewPitch = VIEW_PITCH_VARIABLE;
+ }
+ }
+#endif
+ GetTextExtentPoint((hDC), DBCS_CHAR, 2, &Size);
+ lpv->charWidthDBCS = Size.cx - ptm->tmOverhang;
+ lpv->wCharSet = ptm->tmCharSet;
+}
+#endif
+
+#ifdef DBCS
+/***************************************************************************
+
+ Modify UndoRedo record
+
+***************************************************************************/
+VOID SetReplaceDBCSFlag(
+ LPDOCREC lpd,
+ BOOL bTwoRec)
+{
+ STREAMREC *pst;
+
+ if (DOC_WIN != lpd->docType) {
+ return;
+ }
+
+ //It is bad to update undo information directly...
+ pst = (STREAMREC *)((LPSTR)lpd->undo.pRec + lpd->undo.offset);
+
+ if (bTwoRec) {
+ // This is because lpd->undo.offset points the undo record
+ // for inserted chars. Previous record is for deleted chars.
+ pst = (STREAMREC *)((LPSTR)pst - pst->prevLen);
+ }
+ pst->action |= REPLACEDBCS;
+}
+#endif
+
+#ifdef FE_IME
+/***************************************************************************
+
+ Set position of IME conversion window
+
+***************************************************************************/
+LRESULT ImeMoveConvertWin(
+ HWND hwnd,
+ INT x,
+ INT y)
+{
+ HANDLE hIME;
+ LPIMESTRUCT lpIme;
+ LRESULT lrRet;
+
+ if (NULL == lpfnSendIMEMessageEx) {
+ return FALSE;
+ }
+
+ if(!(hIME = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)sizeof(IMESTRUCT)))){
+ return FALSE;
+ }
+ if(!(lpIme = (LPIMESTRUCT)GlobalLock(hIME))){
+ return FALSE;
+ }
+
+ // Set IME_SETCONVERSIONWINDOW as a sub-function number
+ lpIme->fnc = IME_SETCONVERSIONWINDOW;
+
+ // if x == -1 && y == -1 then set default conversion ID
+ if (x == -1 && y == -1) {
+ lpIme->wParam = MCW_DEFAULT;
+ } else {
+ RECT rRect;
+
+ GetClientRect(hwnd, &rRect);
+ // Set spot conversion ID, and a position of a conversion window
+ lpIme->wParam = MCW_WINDOW | MCW_RECT;
+ lpIme->lParam1 = MAKELONG(LOWORD(x), LOWORD(y));
+ lpIme->lParam2 = MAKELONG(LOWORD(rRect.left), LOWORD(rRect.top));
+ lpIme->lParam3 = MAKELONG(LOWORD(rRect.right), LOWORD(rRect.bottom));
+ }
+ GlobalUnlock(hIME);
+
+ lrRet = (*lpfnSendIMEMessageEx)(hwnd, (LPARAM)hIME);
+ GlobalFree(hIME);
+ return lrRet;
+}
+#endif
+
+#ifdef FE_IME
+/***************************************************************************
+
+ Send virtial key message to IME
+
+***************************************************************************/
+LRESULT ImeSendVkey(
+ HWND hwnd,
+ WORD wVKey)
+{
+ HANDLE hIME;
+ LPIMESTRUCT lpIme;
+ LRESULT lrRet;
+
+ if (NULL == lpfnSendIMEMessageEx) {
+ return FALSE;
+ }
+
+ if(!(hIME = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)sizeof(IMESTRUCT)))){
+ return FALSE;
+ }
+ if(!(lpIme = (LPIMESTRUCT)GlobalLock(hIME))){
+ return FALSE;
+ }
+ lpIme->fnc = IME_SENDVKEY;
+ lpIme->wParam = wVKey;
+ GlobalUnlock(hIME);
+
+ lrRet = (*lpfnSendIMEMessageEx)(hwnd, (LPARAM)hIME);
+ GlobalFree(hIME);
+ return lrRet;
+}
+#endif
+
+#ifdef FE_IME
+/****************************************************************************
+
+ FUNCTION : ImeSetFont
+
+ PURPOSE : Specify the font which is used in IME conversion window
+
+****************************************************************************/
+BOOL ImeSetFont(
+ HWND hwnd,
+ HFONT hFont)
+{
+ HANDLE hIME;
+ LPIMESTRUCT lpIme;
+ HANDLE hLF;
+ LPLOGFONT lpLF;
+
+ if (NULL == lpfnSendIMEMessageEx) {
+ return FALSE;
+ }
+
+ if(!(hIME = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)sizeof(IMESTRUCT)))){
+ return FALSE;
+ }
+ if(!(lpIme = (LPIMESTRUCT)GlobalLock(hIME))){
+ return FALSE;
+ }
+
+ if (!(hLF = GlobalAlloc(GHND | GMEM_SHARE, sizeof(LOGFONT)))){
+ GlobalUnlock(hIME);
+ GlobalFree(hIME);
+ return FALSE;
+ }
+
+ if (!(lpLF = (LPLOGFONT)GlobalLock(hLF))){
+ GlobalFree(hLF);
+ GlobalUnlock(hIME);
+ GlobalFree(hIME);
+ return FALSE;
+ }
+
+ if (!GetObject(hFont, sizeof(LOGFONT), lpLF)) {
+ GlobalUnlock(hLF);
+ GlobalFree(hLF);
+ GlobalUnlock(hIME);
+ GlobalFree(hIME);
+ return FALSE;
+ }
+
+ GlobalUnlock(hLF);
+
+ // Set IME sub-function number
+ lpIme->fnc = IME_SETCONVERSIONFONTEX;
+
+ lpIme->lParam1 = (LPARAM)hLF;
+
+ GlobalUnlock(hIME);
+
+ (*lpfnSendIMEMessageEx)(hwnd, (LPARAM)hIME);
+
+ GlobalFree(hLF);
+ GlobalFree(hIME);
+
+ return TRUE;
+}
+#endif
+
+#ifdef FE_IME
+/****************************************************************************
+
+ FUNCTION : ImeWINNLSEnableIME
+
+ PURPOSE :
+
+****************************************************************************/
+BOOL ImeWINNLSEnableIME(
+ HWND hwnd,
+ BOOL bEnable)
+{
+ if (lpfnWINNLSEnableIME) {
+ (*lpfnWINNLSEnableIME)(hwnd, bEnable);
+ } else {
+ return FALSE;
+ }
+}
+#endif
+
+#ifdef FE_IME
+/***************************************************************************
+
+ Proccess WM_IME_REPORT:IR_STRING message
+
+***************************************************************************/
+LONG ProccessIMEString(HWND hwnd, LPARAM lParam)
+{
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ NPVIEWREC v = &Views[view];
+ NPDOCREC d = &Docs[v->Doc];
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ LPTSTR lpsz;
+ int nLen1;
+ BOOL bRet;
+
+ if (!(lpsz = GlobalLock((HANDLE)lParam))) {
+ return FALSE;
+ }
+
+ if (!FirstLine(v->Doc, &pl, &(v->Y), &pb)) {
+ GlobalUnlock ((HANDLE)lParam);
+ return FALSE;
+ }
+ CloseLine(v->Doc, &pl, v->Y, &pb);
+ v->Y--;
+
+ nLen1 = lstrlen(lpsz);
+
+ if ((v->X < elLen - 1)
+ && (status.overtype || d->forcedOvertype) && !v->BlockStatus) {
+ /**********************************************/
+ /* if over-write mode and no text is selected */
+ /**********************************************/
+ v->BlockStatus = TRUE;
+ v->BlockXL = v->X;
+ v->BlockYL = v->Y;
+ v->BlockYR = v->Y;
+
+ if (v->X + nLen1 >= elLen) {
+ v->BlockXR = elLen - 1;
+ } else if (v->bDBCSOverWrite) {
+ int i;
+
+ for (i = 0; i < nLen1; i++) {
+ if (IsDBCSLeadByte(el[v->X + i])) {
+ i++;
+ }
+ }
+ if (i > nLen1) {
+ HGLOBAL hmemTmp;
+
+ GlobalUnlock ((HANDLE)lParam);
+ if (!(hmemTmp = GlobalReAlloc((HGLOBAL)lParam,
+ nLen1+2, GMEM_MOVEABLE | GMEM_SHARE))) {
+ return FALSE;
+ }
+ if (!(lpsz = GlobalLock((HANDLE)lParam = hmemTmp))) {
+ return FALSE;
+ }
+ lpsz[nLen1] = ' ';
+ nLen1++;
+ }
+ v->BlockXR = v->X + nLen1;
+ } else {
+ int nNum1;
+ int nNum2;
+ int i;
+
+ for (i = 0, nNum1 = 0; i < nLen1; i++, nNum1++) {
+ if (IsDBCSLeadByte(lpsz[i])) {
+ i++;
+ }
+ }
+ for (i = 0, nNum2 = 0; nNum2 < nNum1; i++, nNum2++) {
+ if (IsDBCSLeadByte(el[v->X + i])) {
+ i++;
+ }
+ }
+ v->BlockXR = v->X + i;
+ }
+ }
+ bRet = InsertStream(view, v->X, v->Y, nLen1, lpsz, TRUE);
+ GlobalUnlock ((HANDLE)lParam);
+
+ if (bRet) {
+ SetReplaceDBCSFlag(d, v->BlockStatus ? TRUE : FALSE);
+ PosXY(view, v->X + nLen1, v->Y, TRUE);
+ }
+ return TRUE;
+}
+#endif
+
+#ifdef FE_IME
+/***************************************************************************
+
+ Initialize pointers of IME APIs
+
+***************************************************************************/
+BOOL ImeInit(void)
+{
+ if (NULL == hModUser32) {
+ hModUser32 = LoadLibrary("IMM32");
+ }
+ if (NULL == hModUser32) {
+#ifdef DEBUG
+ MessageBox(NULL, "Failed to load IMM32.DLL",
+ NULL, MB_APPLMODAL | MB_OK);
+#endif
+ return FALSE;
+ }
+ if (NULL == lpfnWINNLSEnableIME) {
+ (FARPROC)lpfnWINNLSEnableIME
+ = GetProcAddress(hModUser32, "ImmWINNLSEnableIME");
+#ifdef DEBUG
+ if (NULL == lpfnWINNLSEnableIME) {
+ MessageBox(NULL, "Failed to get address of ImmWINNLSEnableIME",
+ NULL, MB_APPLMODAL | MB_OK);
+ }
+#endif
+ }
+ if (NULL == lpfnSendIMEMessageEx) {
+ (FARPROC)lpfnSendIMEMessageEx
+ = GetProcAddress(hModUser32, "ImmSendIMEMessageExA");
+#ifdef DEBUG
+ if (NULL == lpfnSendIMEMessageEx) {
+ MessageBox(NULL, "Failed to get address of ImmSendIMEMessageExA",
+ NULL, MB_APPLMODAL | MB_OK);
+ }
+#endif
+ }
+
+ return TRUE;
+}
+/***************************************************************************
+
+ Terminate proccess of IME
+
+***************************************************************************/
+BOOL ImeTerm(void)
+{
+ if (NULL != hModUser32) {
+ if (FreeLibrary(hModUser32)) {
+ hModUser32 = NULL;
+ lpfnWINNLSEnableIME = NULL;
+ lpfnSendIMEMessageEx = NULL;
+ }
+ }
+ return TRUE;
+}
+#endif // FE_IME
+
diff --git a/private/windbg/windbg/util2.c b/private/windbg/windbg/util2.c
new file mode 100644
index 000000000..cd9039e9b
--- /dev/null
+++ b/private/windbg/windbg/util2.c
@@ -0,0 +1,4224 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Util2.c
+
+Abstract:
+
+ This module contains the support code for debuggerwide routines
+
+Author:
+
+ Griffith Wm. Kadnier (v-griffk) 26-Jul-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+extern LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+
+static BOOL FAddToSearchPath = FALSE;
+static BOOL FAddToRootMap = FALSE;
+
+
+/*** BuildWindowItemString
+**
+** Synopsis:
+** void = BuildWindowItemString(dest, type, mnemo, text, accel)
+**
+** Entry:
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Prepare a menu item string (mnemonic, text, accelerator) for Window Menu
+**
+*/
+
+void BuildWindowItemString(PSTR dest, int type, int mnemo, PSTR text, int accel)
+{
+ char szAccel[20];
+ char szMnemo[15];
+ char fName[MAX_MSG_TXT];
+ int winTitle;
+
+ //Build Accelerator string
+
+ if (accel >= 0) {
+
+ szAccel[0] = (char)('\t' - 1);
+ szAccel[1] = '\0';
+ Dbg(LoadString(hInst, SYS_Alt, szAccel + strlen(szAccel), MAX_MSG_TXT));
+ if (accel > 9) {
+ strcat(szAccel, "+");
+ Dbg(LoadString(hInst, SYS_Shift, szAccel + strlen(szAccel), MAX_MSG_TXT));
+ }
+ strcat(szAccel,"+x");
+ if (accel < 9)
+ szAccel[strlen(szAccel) - 1] = (char)('1' + accel);
+ else if (accel > 9)
+ szAccel[strlen(szAccel) - 1] = (char)('1' + accel - 10);
+ else
+ szAccel[strlen(szAccel) - 1] = '0';
+ }
+ else
+ szAccel[0] = '\0';
+
+ //Appends mnemonic to text if it's a document
+
+ if (type == DOC_WIN) {
+
+ if (mnemo < 9) {
+ strcpy(szMnemo, "& ");
+ szMnemo[1] = (char)(mnemo + '1');
+ }
+ else {
+ strcpy(szMnemo, "1& ");
+ szMnemo[2] = (char)(mnemo + '1' - 10);
+ }
+
+
+ //Reduce filename to acceptable menu width
+
+ AdjustFullPathName(text, fName, FILES_MENU_WIDTH);
+
+ //NB fname should be kept a lot (2* ?) bigger than
+ //FILES_MENU_WIDTH as the added chars don't add to the width
+
+ EscapeAmpersands(fName, sizeof(fName));
+ strcpy(dest, szMnemo);
+ strcat(dest, fName);
+ strcat(dest, szAccel);
+
+ }
+ else {
+
+ switch( type ) {
+ case DISASM_WIN: winTitle = SYS_DisasmWin_Title; break;
+ case COMMAND_WIN: winTitle = SYS_CmdWin_Title; break;
+ case MEMORY_WIN: winTitle = SYS_MemoryWin_Title; break;
+ case LOCALS_WIN: winTitle = SYS_LocalsWin_Title; break;
+ case WATCH_WIN: winTitle = SYS_WatchWin_Title; break;
+ case CPU_WIN: winTitle = SYS_CpuWin_Title; break;
+ case FLOAT_WIN: winTitle = SYS_FloatWin_Title; break;
+ case CALLS_WIN: winTitle = SYS_CallsWin_Title; break;
+ default: DAssert(FALSE); winTitle = SYS_MemoryWin_Title; break;
+ }
+
+ Dbg(LoadString(hInst, winTitle, fName, MAX_MSG_TXT));
+ strcpy(dest, fName);
+
+ if (type == MEMORY_WIN)
+ {
+ lstrcat (dest," (");
+ lstrcat (dest,TempMemWinDesc.szAddress);
+ lstrcat (dest,")");
+ }
+
+ strcat(dest, szAccel);
+ }
+ return;
+} /* BuildWindowItemString() */
+
+BOOL NEAR PASCAL IsLastView(
+ int doc)
+{
+ DAssert(Docs[doc].FirstView != -1);
+ return (Views[Docs[doc].FirstView].NextView == -1);
+}
+
+void FAR PASCAL FileNotSaved(
+ int doc)
+{
+ //User doesn't want file to be saved
+ if (!CheckDocument(doc))
+ ErrorBox(ERR_Document_Corrupted);
+
+}
+
+BOOL FAR PASCAL QueryCloseAllDocs()
+{
+ int doc;
+
+ for (doc = 0; doc < MAX_DOCUMENTS; doc++) {
+
+ if (Docs[doc].FirstView != -1)
+ if (!QueryCloseChild(Views[Docs[doc].FirstView].hwndClient,
+ TRUE))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL FAR PASCAL QueryCloseChild(
+ HWND hwnd,
+ BOOL allViews)
+{
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ int doc = Views[view].Doc;
+ BOOL doNotQuery;
+
+ DAssert(doc >= 0);
+
+ if (allViews)
+ doNotQuery = !Docs[doc].ismodified;
+ else
+ doNotQuery = !IsLastView(doc) || !Docs[doc].ismodified;
+
+ //Return TRUE if text was not modified, or window type is not a document
+ if (Docs[doc].docType != DOC_WIN || doNotQuery)
+ {
+ if (IsZoomed (hwnd))
+ {
+ ShowWindow (hwnd, SW_RESTORE);
+ }
+ return TRUE;
+ }
+
+
+ //Ask user whether to save / not save / cancel
+ switch (QuestionBox(SYS_Save_Changes_To,
+ MB_YESNOCANCEL , (LPSTR)Docs[doc].FileName)) {
+ case IDYES:
+
+ if (IsZoomed (hwnd))
+ {
+ ShowWindow (hwnd, SW_RESTORE);
+ }
+ //User wants file saved
+ return SaveFile(doc);
+
+ case IDNO:
+ FileNotSaved(doc);
+ return TRUE;
+
+ default:
+
+ //We couldn't do the messagebox, or not ok to close
+ if (!CheckDocument(doc))
+ ErrorBox(ERR_Document_Corrupted);
+ return FALSE;
+ }
+} /* QueryCloseChild() */
+
+/*** AddFile
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+** View number of the window added, -1 on failure
+**
+** Description:
+** Creates a new MDI window. If the lpName parameter is not
+** NULL, it loads a file into the window. If "win" provided,
+** size, pos and style are taken from "win". If "font" provided,
+** we use it. Update status line upon readOnly value
+**
+*/
+
+int FAR PASCAL
+AddFile(
+ WORD mode,
+ WORD type,
+ LPSTR pName,
+ LPWININFO win,
+ HFONT font,
+ BOOL readOnly,
+ int dupView,
+ int Preference
+ )
+{
+ int view;
+
+ MDICREATESTRUCT mcs;
+ NPDOCREC d;
+ char class[MAX_MSG_TXT];
+ WORD classId;
+ BOOL maximize = FALSE;
+
+ if ((view = OpenDocument(mode, type, 0, pName, dupView, Preference)) == -1)
+ return -1;
+
+ DAssert(Views[view].Doc >= 0);
+ d = &Docs[Views[view].Doc];
+
+ //If opening file, insert file in Most recently used files names list
+
+ if ((d->docType == DOC_WIN) &&
+ ((mode == MODE_OPENCREATE) || (mode == MODE_OPEN))) {
+ InsertKeptFileNames(EDITOR_FILE, FILEMENU, IDM_FILE_EXIT,
+ (LPSTR)d->FileName);
+ }
+
+ //Change status bar
+
+ d->readOnly |= readOnly;
+ StatusMultiKey(FALSE);
+
+ mcs.szTitle = d->FileName;
+
+ //Get class name according to window type
+
+ switch(d->docType) {
+ case DOC_WIN:
+ classId = SYS_Child_wClass;
+ break;
+ case DISASM_WIN:
+ classId = SYS_Disasm_wClass;
+ disasmView = view;
+ break;
+ case COMMAND_WIN:
+ classId = SYS_Cmd_wClass;
+ cmdView = view;
+ break;
+ case MEMORY_WIN:
+ classId = SYS_Memory_wClass;
+ memView = view;
+ break;
+ default:
+ DAssert(FALSE);
+ return -1;
+ break;
+ }
+ Dbg(LoadString(hInst, classId, class, MAX_MSG_TXT));
+
+ mcs.szClass = class;
+ mcs.hOwner = hInst;
+
+ //The window structure already exist
+
+ if (win) {
+ mcs.x = win->coord.left;
+ mcs.y = win->coord.top;
+ mcs.cx = win->coord.right - win->coord.left;
+ mcs.cy = win->coord.bottom - win->coord.top;
+
+ //Get rid of MAXIMIZE style, one more MDI Bug...
+
+ mcs.style = (win->style & ~(WS_MAXIMIZE));
+
+ } else {
+ //Use the default size for the window
+
+ mcs.x = mcs.cx = CW_USEDEFAULT;
+ mcs.y = mcs.cy = CW_USEDEFAULT;
+ mcs.style = WS_VISIBLE;
+
+ //Set the style of the window to maximized if the
+ //active window is currently maximized, to nothing otherwise
+
+ maximize = hwndActive && (GetWindowLong(hwndActive, GWL_STYLE) & WS_MAXIMIZE);
+
+ }
+
+ //Font will be initialized when WM_CREATE msg received for this view
+
+ Views[view].font = font;
+ mcs.lParam = (ULONG)view;
+
+ //Tell the MDI Client to create the child and keep window handle for Workspace functions
+
+ Views[view].hwndFrame = (HANDLE)SendMessage(hwndMDIClient, WM_MDICREATE,
+ 0, (LONG)(LPMDICREATESTRUCT)&mcs);
+
+ if (!IsIconic(Views[view].hwndFrame))
+ {
+ if (maximize)
+ ShowWindow(Views[view].hwndFrame, SW_SHOWMAXIMIZED);
+ else
+ ShowWindow(Views[view].hwndFrame, SW_SHOWNORMAL);
+ }
+ //Set vertical scrollbar range
+
+ SetVerticalScrollBar(view, FALSE);
+
+ //Dont pos the cursor after the setdebug lines
+
+ if (mode == MODE_DUPLICATE)
+ PosXY(view, Views[dupView].X, Views[dupView].Y, FALSE);
+ else if (d->docType != COMMAND_WIN)
+ PosXY(view, 0, 0, FALSE);
+
+ //Display any debug/error tags/lines
+
+ if (type == DOC_WIN && (mode == MODE_OPEN || mode == MODE_OPENCREATE))
+ {
+ SetDebugLines(Views[view].Doc, FALSE);
+ }
+
+ return view;
+} /* AddFile() */
+
+BOOL FAR PASCAL SaveFile(int doc)
+{
+
+ if (Docs[doc].readOnly)
+ return (!ErrorBox(ERR_File_Is_ReadOnly));
+
+ if (!CheckDocument(doc)) {
+ ErrorBox(ERR_Modified_Document_Corrupted);
+ return SaveAsFile(doc);
+ }
+ else {
+ if (Docs[doc].untitled)
+ return SaveAsFile(doc);
+ else {
+ BOOL ok = SaveDocument(doc, (LPSTR)Docs[doc].FileName);
+ if (ok)
+ CompactDocument(doc);
+ return ok;
+ }
+ }
+}
+
+BOOL FAR PASCAL SaveAsFile(int doc)
+{
+ NPDOCREC d = &Docs[doc];
+ DWORD dwFlags;
+ char savedChar;
+ char CurrentDirectory[ MAX_PATH ];
+
+ //Careful when it's not a doc window, the filename could be
+ //invalid
+
+ if (d->docType != DOC_WIN) {
+ savedChar = d->FileName[MAXFILENAMEPREFIX];
+ d->FileName[MAXFILENAMEPREFIX] = '\0';
+ }
+
+//
+// Hack, hack, hack.
+// When the Save As dialog box runs, the name of the file being saved is
+// entered into the file name text control and selected. However, if this is
+// a new document that has no title, then we enter only some extensions, but
+// there is no indication of what new file is actually being saved: UNTITLED 1,
+// UNTITLED 2, etc. So, we *kludge* (repeat, KLUDGE!!!) the "UNTITLED n" file name
+// onto the back of the initial szPath[] null. Then, down in StartFileDlg(),
+// we have the complementary *kludge* (repeat KLUDGE!!!) which first handles the
+// initial null in szPath[] as ususal, then, and *only* for the Save As dialog,
+// reads the back end of the szPath[] array to get the "UNTITLED n" file name.
+// Finally, this file name is placed in the title bar for the dialog.
+// Did I mention that I find this to be a *kludge* (repeat KLUDGE!!!)?
+//
+
+ if (d->untitled)
+ {
+ szPath[0] = '\0';
+ sprintf (szPath+1, "<<%s>>", d->FileName);
+ }
+ else
+ {
+ strcpy(szPath, d->FileName);
+ }
+
+ GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory );
+ if ( *DocFileDirectory ) {
+ SetCurrentDirectory( DocFileDirectory );
+ }
+
+ dwFlags = OFN_SHOWHELP | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
+ if (StartFileDlg(hwndFrame, DLG_SaveAs_Filebox_Title, DEF_Ext_C, ID_SAVEAS_HELP,
+ 0, (LPSTR)szPath, &dwFlags, DlgFile)) {
+
+ int k;
+
+ //Check if the user has not given a file name of an opened document
+
+ for (k = 0 ; k < MAX_DOCUMENTS; k++) {
+ if (Docs[k].FirstView != -1 && Docs[k].docType == DOC_WIN
+ && k != doc && _stricmp(Docs[k].FileName, szPath) == 0) {
+ return ErrorBox(ERR_Duplicate_File_Name);
+ }
+ }
+
+
+ if (!SaveDocument(doc, (LPSTR)szPath)) {
+
+ if (d->docType != DOC_WIN)
+ d->FileName[MAXFILENAMEPREFIX] = savedChar;
+
+ return FALSE;
+ }
+
+ //Do some operations only on documents
+
+ if (d->docType == DOC_WIN) {
+
+ int n = 0, k = 0;
+
+ //Change the file name
+
+ strcpy(d->FileName, szPath);
+ d->untitled = FALSE;
+
+ //Set the language and refresh the views
+
+ d->language = (WORD) SetLanguage(doc);
+ if (d->language == C_LANGUAGE) {
+ d->lineTop = 0;
+ d->lineBottom = d->NbLines - 1;
+ CheckSyntax(doc);
+ }
+
+ InvalidateLines(d->FirstView, 0, LAST_LINE, TRUE);
+
+ //Change the window title in all views of this doc
+
+ RefreshWindowsTitle(doc);
+
+ //Insert file in Most recently used files names list
+
+ InsertKeptFileNames(EDITOR_FILE, FILEMENU, IDM_FILE_EXIT,
+ (LPSTR)d->FileName);
+
+ // Finally re-do debug highlights
+
+ ClearDocStatus(doc, BRKPOINT_LINE|CURRENT_LINE);
+ SetDebugLines(doc, TRUE);
+
+ // File type (extension) may have changed
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ GetCurrentDirectory( sizeof( DocFileDirectory ), DocFileDirectory );
+
+ }
+
+ SetCurrentDirectory( CurrentDirectory );
+
+ return TRUE;
+ }
+ else {
+
+ if (d->docType != DOC_WIN)
+ d->FileName[MAXFILENAMEPREFIX] = savedChar;
+
+ return FALSE;
+ }
+} /* SaveAsFile() */
+
+void FAR PASCAL InsertKeptFileNames(
+ WORD type,
+ int menuPos,
+ WORD menuId,
+ LPSTR newName)
+{
+ int i, j;
+ LPSTR s[MAX_MRU_FILES_KEPT];
+ char tmp[_MAX_PATH];
+ BOOL found = FALSE;
+ HMENU hMenu;
+ int nb = nbFilesKept[type];
+
+
+ //sprintf(tmp,"menu=%08x\n",hMainMenu); OutputDebugString(tmp); return;
+
+ //First lock memory for existing kept files
+ for (i = 0; i < nb; i++)
+ Dbg(s[i] = (LPSTR)GlobalLock (hFileKept[type][i]));
+
+ //See if we have a maximized Mdi Window
+ //(A system menu will be added) to standard menu bar
+ if (GetMenuItemCount(hMainMenu) > NUMBER_OF_MENUS)
+ menuPos++;
+
+ //Get a handle to the File menu.
+ Dbg(hMenu = GetSubMenu (hMainMenu, menuPos));
+
+ //First put a separator if we already have no files names kept
+ if (nb == 0)
+ Dbg(AppendMenu(hMenu, MF_SEPARATOR, 0, NULL));
+
+ //Remove old menu items
+ for (i = 1; i <= nb; i++)
+ Dbg(RemoveMenu(hMenu, menuId + i, MF_BYCOMMAND));
+
+ //First check if file is not already in list
+ i = 0;
+ while (i < nb && !found) {
+ found = (_strcmpi(s[i], newName) == 0);
+ if (!found)
+ i++;
+ }
+
+ if (found) {
+
+ //File name already exist, move it to first place
+ if (i > 0) {
+ lstrcpy((LPSTR)szTmp, s[i]);
+ for (j = i; j > 0; j--)
+ lstrcpy(s[j], s[j - 1]);
+ lstrcpy(s[0], (LPSTR)szTmp);
+ }
+ }
+ else {
+
+ //File name not found, do we have a new space to create ?
+ if (nb < MAX_MRU_FILES_KEPT) {
+ Dbg(hFileKept[type][nb] = GlobalAlloc(GMEM_MOVEABLE, _MAX_PATH));
+ Dbg(s[nb] = (LPSTR)GlobalLock(hFileKept[type][nb]));
+ nb++;
+ }
+
+ //Shift list
+ for (i = nb - 1; i >= 1; i--)
+ lstrcpy(s[i], s[i - 1]);
+ lstrcpy(s[0], newName);
+ }
+
+ //Now list is Most Recently Used sorted, change file menu
+ for (i = 0 ; i < nb; i++) {
+
+ lstrcpy((LPSTR)szTmp, s[i]);
+
+ //Adjust path file name to width
+ AdjustFullPathName(szTmp, tmp, FILES_MENU_WIDTH);
+ EscapeAmpersands(tmp, sizeof(tmp));
+
+ //Set accelerator mark
+ szTmp[0] = '&';
+
+ //Convert counter to string and append reduced path name
+ _itoa(i + 1, szTmp + 1, 10);
+ strcat(szTmp, " ");
+ strcat(szTmp, tmp);
+
+ //Fill the corresponding menu option
+ Dbg(AppendMenu(hMenu, MF_ENABLED, menuId + i + 1, (LPSTR)szTmp));
+
+ //Unlocks the current element
+ Dbg(GlobalUnlock (hFileKept[type][i]) == FALSE);
+ }
+
+ nbFilesKept[type] = nb;
+ DrawMenuBar(hwndFrame);
+} /* InsertKeptFileNames() */
+
+
+
+void FAR PASCAL
+WindowTitle(
+ int view,
+ int duplicateNbr
+ )
+
+/*++
+
+Routine Description:
+
+ This function constructs the actual title for a document window.
+
+Arguments:
+
+ view - Supplies the view number for the document
+ duplicateNbr - Supplies the count of views on the current document
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int wPix;
+ TEXTMETRIC tm;
+ int n;
+ int winTitle = 0;
+ char title[MAX_MSG_TXT];
+ char trail[9];
+ NPDOCREC d;
+ HANDLE hwnd;
+ RECT r;
+ HDC hDC;
+ SIZE size;
+ int dep;
+ PSTR cur;
+
+ /*
+ * Must have some view and it can not be a view on a pane window
+ */
+
+ DAssert(view != -1);
+ DAssert(view >= 0);
+
+ /*
+ * We might be in a situation where the view structure is not
+ * totally filled (Ex : If duplicating a window from a maximized
+ * original, MDI will send a Resize command to the maximized window
+ * in the middle of the processing of WM_MDICREATE, and we don't
+ * control that), we will get the handle of mdi window through the
+ * edit control cause at this time Views[view].win.hwnd may also not be
+ * ready
+ */
+
+ if (Views[view].Doc < 0) {
+ //
+ // its NOT a doc window
+ //
+ d = NULL;
+ hwnd = Views[view].hwndFrame;
+ } else {
+ d = &Docs[Views[view].Doc];
+ hwnd = Views[view].hwndClient;
+ if (hwnd == NULL) {
+ return;
+ }
+ hwnd = GetParent(hwnd);
+ }
+
+ if (hwnd == NULL) {
+ return;
+ }
+
+
+ /*
+ * Special handling for Iconic and Maximized windows
+ */
+
+ if (IsIconic(hwnd) || IsZoomed(hwnd)) {
+ if (d) {
+ cur = d->FileName + strlen(d->FileName);
+ szTmp[0] = '<';
+ _itoa(view + 1, szTmp + 1, 10);
+ strcat(szTmp, ">");
+
+ /*
+ * Add an extra space when maximizing window
+ */
+
+ if (IsZoomed(hwnd)) {
+ strcat(szTmp, " ");
+ }
+
+#ifdef DBCS
+ if (IsDBCSLeadByte(d->FileName[0])) {
+ dep = strlen(szTmp);
+ } else {
+ dep = strlen(szTmp) + 1;
+ }
+ while (cur > d->FileName) {
+ cur = CharPrev(d->FileName, cur);
+ if (*cur == '\\') {
+ break;
+ }
+ }
+ if (*cur == '\\') {
+ cur++;
+ }
+#else // !DBCS
+ dep = strlen(szTmp) + 1;
+
+ while ((cur >= d->FileName) && (*cur != '\\')) {
+ cur--;
+ }
+ cur++;
+#endif
+ strcat(szTmp, cur);
+ if (Views[view].Doc == DISASM_WIN) {
+ Dbg(LoadString( hInst, SYS_DisasmWin_Title, title, MAX_MSG_TXT ));
+ for (cur=&szTmp[strlen(szTmp)],n=0; n<(int)strlen(title); n++) {
+ if (title[n] != '&') {
+ *cur++ = title[n];
+ }
+ }
+ *cur = '\0';
+ }
+ if (d->docType == DOC_WIN && d->ismodified) {
+ strcat(szTmp, "*");
+ }
+ } else {
+ szTmp[0] = '<';
+ _itoa(view + 1, szTmp + 1, 10);
+ strcat(szTmp, ">");
+
+ /*
+ * Add an extra space when maximizing window
+ */
+
+ if (IsZoomed(hwnd)) {
+ strcat(szTmp, " ");
+ }
+
+ dep = strlen(szTmp) + 1;
+
+ switch( abs(Views[view].Doc) ) {
+ case DISASM_WIN: winTitle = SYS_DisasmWin_Title; break;
+ case MEMORY_WIN: winTitle = SYS_MemoryWin_Title; break;
+ case LOCALS_WIN: winTitle = SYS_LocalsWin_Title; break;
+ case WATCH_WIN: winTitle = SYS_WatchWin_Title; break;
+ case CPU_WIN: winTitle = SYS_CpuWin_Title; break;
+ case FLOAT_WIN: winTitle = SYS_FloatWin_Title; break;
+ case CALLS_WIN: winTitle = SYS_CallsWin_Title; break;
+ }
+
+ if (winTitle) {
+ Dbg(LoadString( hInst, winTitle, title, MAX_MSG_TXT ));
+ for (cur=&szTmp[strlen(szTmp)],n=0; n<(int)strlen(title); n++) {
+ if (title[n] != '&') {
+ *cur++ = title[n];
+ }
+ }
+ *cur = '\0';
+
+ if (abs(Views[view].Doc) == MEMORY_WIN) {
+ strcat ( szTmp, " (" );
+ strcat ( szTmp, TempMemWinDesc.szAddress );
+ strcat ( szTmp, ")" );
+ }
+ }
+ }
+
+ TitleBar.UserTitle[0] = 0;
+
+ SetWindowText(hwnd, (LPSTR)szTmp);
+ return;
+ }
+
+ Dbg(hDC = GetDC(hwnd));
+ szTmp[0] = '<';
+ _itoa(view + 1, szTmp + 1, 10);
+ strcat(szTmp, "> ");
+
+ /*
+ * Compute actual width of caption title
+ */
+
+ GetWindowRect(hwnd, (LPRECT)&r);
+ wPix = r.right - r.left - 3 * GetSystemMetrics(SM_CXSIZE)
+ - 2 * GetSystemMetrics(SM_CXFRAME);
+
+ /*
+ * Add a '*' if document is modified
+ */
+
+ if ((d) && (d->docType == DOC_WIN && d->ismodified)) {
+ strcpy(trail, "*");
+ } else {
+ trail[0] = '\0';
+ }
+
+ if (duplicateNbr > 0) {
+ strcat(trail, " : ");
+ _itoa(duplicateNbr, trail + strlen(trail), 10);
+ }
+
+ /*
+ * Get font metrics
+ */
+
+ GetTextMetrics(hDC, &tm);
+
+ /*
+ * Can we display the full title, or do we have to reduce it
+ */
+
+ if (d && d->docType == DOC_WIN) {
+ int i;
+
+ Dbg(GetTextExtentPoint(hDC, (LPSTR)szTmp, strlen(szTmp), &size));
+ i = size.cx;
+ Dbg(GetTextExtentPoint(hDC, (LPSTR)d->FileName,
+ strlen(d->FileName), &size));
+ i += size.cx;
+ Dbg(GetTextExtentPoint(hDC, (LPSTR)trail, strlen(trail), &size));
+ i += size.cx;
+ if (wPix >= i) {
+ strcat(szTmp, d->FileName);
+ strcat(szTmp, trail);
+ } else {
+
+ /*
+ * Reduce file name len to fit in caption title
+ */
+
+ n = (wPix / (tm.tmAveCharWidth)) - strlen(szTmp) - strlen(trail);
+ if (n <= MAXFILENAMELEN) {
+ AdjustFullPathName(d->FileName,
+ szTmp + strlen(szTmp),
+ n /*MAXFILENAMELEN*/);
+ } else {
+ AdjustFullPathName(d->FileName,
+ szTmp + strlen(szTmp),
+ n);
+ strcat(szTmp, trail);
+ }
+ }
+
+ } else {
+
+ if (d) {
+ strcat( szTmp, d->FileName );
+ } else {
+ switch( abs(Views[view].Doc) ) {
+ case DISASM_WIN: winTitle = SYS_DisasmWin_Title; break;
+ case MEMORY_WIN: winTitle = SYS_MemoryWin_Title; break;
+ case LOCALS_WIN: winTitle = SYS_LocalsWin_Title; break;
+ case WATCH_WIN: winTitle = SYS_WatchWin_Title; break;
+ case CPU_WIN: winTitle = SYS_CpuWin_Title; break;
+ case FLOAT_WIN: winTitle = SYS_FloatWin_Title; break;
+ case CALLS_WIN: winTitle = SYS_CallsWin_Title; break;
+ }
+
+ if (winTitle) {
+ Dbg(LoadString( hInst, winTitle, title, MAX_MSG_TXT ));
+ for (cur=&szTmp[strlen(szTmp)],n=0; n<(int)strlen(title); n++) {
+ if (title[n] != '&') {
+ *cur++ = title[n];
+ }
+ }
+ *cur = '\0';
+
+ if (abs(Views[view].Doc) == MEMORY_WIN) {
+ strcat ( szTmp, " (" );
+ strcat ( szTmp, TempMemWinDesc.szAddress );
+ strcat ( szTmp, ")" );
+ }
+ }
+ }
+
+ strcat(szTmp, trail);
+
+ }
+
+ Dbg(ReleaseDC(hwnd, hDC));
+ SetWindowText(hwnd, (LPSTR)szTmp);
+ TitleBar.UserTitle[0] = 0;
+ SendMessage(hwndFrame, WM_SETTEXT, 0, (LONG)(LPSTR)szNull);
+ return;
+} /* WindowTitle() */
+
+
+
+void
+RefreshWindowsTitle(
+ int doc
+ )
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ doc - Supplies the document number to refresh the title for
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int view;
+ int n;
+ int duplicateNb = 1;
+
+
+
+ view = Docs[doc].FirstView;
+ if (Views[view].NextView == -1) {
+
+ /*
+ * Single view, refresh title
+ */
+
+ WindowTitle(view, 0);
+
+ } else {
+ /*
+ * For each view of this document, display title with view copy
+ */
+
+ if (Views[view].Doc == -1) {
+ WindowTitle( view, duplicateNb );
+ } else {
+ n = Docs[Views[view].Doc].FirstView;
+ while (n != -1) {
+ WindowTitle(n, duplicateNb);
+ duplicateNb++;
+ n = Views[n].NextView;
+ }
+ DAssert(duplicateNb <= MAX_VIEWS + 1);
+ }
+ }
+ return;
+} /* RefreshWindowsTItle() */
+
+BOOL FindLineStatus(int view, BYTE target, BOOL forward, int *line)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ NPVIEWREC v = &Views[view];
+ BOOL found = FALSE;
+ int curLine = *line;
+
+ DAssert(v->Doc >= 0);
+
+ if (forward) {
+ (*line)++;
+
+ //Scan text from current line + 1 till end of file
+ if (*line < Docs[v->Doc].NbLines) {
+ if (!
+ FirstLine(v->Doc, &pl, line, &pb))
+ goto err;
+ while (*line < Docs[v->Doc].NbLines) {
+ if ((pl->Status) & target) {
+ found = TRUE;
+ break;
+ }
+ if (!NextLine(v->Doc, &pl, line, &pb))
+ goto err;
+ }
+ if ((pl->Status) & target)
+ found = TRUE;
+ }
+
+ //Scan text from beginning till current line
+ if (!found) {
+
+ *line = 0;
+ if (!FirstLine(v->Doc, &pl, line, &pb))
+ goto err;
+ while (*line <= curLine) {
+ if ((pl->Status) & target) {
+ found = TRUE;
+ break;
+ }
+ if (!NextLine(v->Doc, &pl, line, &pb))
+ goto err;
+ }
+ }
+
+ CloseLine(v->Doc, &pl, *line, &pb);
+ (*line)--;
+
+ }
+ else {
+
+ (*line)--;
+
+ //Scan text from current line - 1 till begin of file
+ if (*line >= 0) {
+ if (!FirstLine(v->Doc, &pl, line, &pb))
+ goto err;
+ (*line) -= 2;
+ while (*line >= 0) {
+ if ((pl->Status) & target) {
+ found = TRUE;
+ break;
+ }
+ if (!PreviousLine(v->Doc, &pl, *line, &pb))
+ goto err;
+ (*line)--;
+ }
+ if ((pl->Status) & target)
+ found = TRUE;
+ }
+
+ //Scan text from end of file till current line
+ if (!found) {
+
+ *line = Docs[v->Doc].NbLines - 1;
+ if (!FirstLine(v->Doc, &pl, line, &pb))
+ goto err;
+ (*line) -= 2;
+ while (*line >= curLine) {
+ if ((pl->Status) & target) {
+ found = TRUE;
+ break;
+ }
+ if (!PreviousLine(v->Doc, &pl, *line, &pb))
+ goto err;
+ (*line)--;
+ }
+ }
+
+ (*line)++;
+ CloseLine(v->Doc, &pl, (*line) + 1, &pb);
+ }
+
+ return found;
+
+ err: {
+ DAssert(FALSE);
+ return FALSE;
+ }
+} /* FindLineStatus() */
+
+/*** StartFileDlg
+**
+** Synopsis:
+** bool = StartFileDlg(hwnd, titleId, defExtId, helpId, templateId,
+** fileName, pFlags, lpfnHook)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+
+BOOL
+StartFileDlg(
+ HWND hwnd,
+ int titleId,
+ int defExtId,
+ int helpId,
+ int templateId,
+ LPSTR fileName,
+ DWORD* pFlags,
+ LPOFNHOOKPROC lpfnHook
+ )
+
+/*++
+
+Routine Description:
+
+ This function is used by windbg to open the set of common file handling
+ dialog boxes.
+
+Arguments:
+
+ hwnd - Supplies the wnd to hook the dialog box to
+
+ titleId - Supplies the string resource of the title
+
+ defExtId - Supplies The default extension resource string
+
+ helpId - Supplies the help number for the dialog box
+
+ templateId - Supplies the dialog resource number if non-zero
+
+ fileName - Supplies the default file name
+
+ pFiles - Supplies a pointer to flags
+
+ lpfnHook - Supplies the address of a hook procedure for the dialog
+
+Return Value:
+
+ The result of the dialog box call (usually TRUE for OK and FALSE for
+ cancel)
+
+--*/
+
+{
+ #define filtersMaxSize 350
+
+ OPENFILENAME OpenFileName;
+ char title[MAX_MSG_TXT];
+ char defExt[MAX_MSG_TXT];
+ BOOL result;
+ char filters[filtersMaxSize];
+ LPOFNHOOKPROC lpDlgHook;
+ HCURSOR hSaveCursor;
+ char files[_MAX_PATH + 8];
+ char szExt[_MAX_EXT + 8];
+ char szBase[_MAX_PATH + 8];
+ int indx;
+ char ch;
+ CHAR fname[_MAX_FNAME];
+ CHAR ext[_MAX_EXT];
+ static char * szInitialDir = NULL;
+
+ *pFlags |= OFN_NOCHANGEDIR;
+
+
+ if (DLG_Browse_Filebox_Title == titleId) {
+ _splitpath( fileName, NULL, NULL, fname, ext );
+ _makepath( files, NULL, NULL, fname, ext );
+ } else
+ strcpy (files,fileName);
+
+ /*
+ * Disable frame client
+ */
+
+ EnableWindow(hwndMDIClient, FALSE);
+
+ /*
+ * Set the Hour glass cursor
+ */
+
+ hSaveCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ InitFilterString((WORD)titleId, (LPSTR)filters, (int)filtersMaxSize);
+ Dbg(LoadString(hInst, titleId, (LPSTR)title, MAX_MSG_TXT));
+ Dbg(LoadString(hInst, defExtId, (LPSTR)defExt, MAX_MSG_TXT));
+ if (templateId) {
+
+ /*
+ * Build dialog box Name
+ */
+
+ *pFlags |= OFN_ENABLETEMPLATE;
+ OpenFileName.lpTemplateName = MAKEINTRESOURCE(templateId);
+ }
+
+ /*
+ * Make instance for 'dlgProc'
+ */
+
+ if (lpfnHook) {
+
+ lpDlgHook = (LPOFNHOOKPROC)lpfnHook;
+
+ *pFlags |= OFN_ENABLEHOOK;
+ }
+
+ curHelpId = helpId;
+ OpenFileName.lStructSize = sizeof(OPENFILENAME);
+ OpenFileName.hwndOwner = hwnd;
+ OpenFileName.hInstance = hInst;
+ OpenFileName.lpstrFilter = (LPSTR)filters;
+ OpenFileName.lpstrCustomFilter = NULL;
+ OpenFileName.nMaxCustFilter = 0;
+ OpenFileName.nFilterIndex = 1;
+ OpenFileName.lpstrFile = files;
+ OpenFileName.nMaxFile = _MAX_PATH;
+ OpenFileName.lpstrFileTitle = NULL;
+ OpenFileName.lpstrInitialDir = szInitialDir;
+ OpenFileName.lpstrTitle = (LPSTR)title;
+ OpenFileName.Flags = *pFlags;
+ OpenFileName.lpstrDefExt = (LPSTR)NULL;
+ OpenFileName.lCustData = 0L;
+ OpenFileName.lpfnHook = lpDlgHook;
+
+ DlgEnsureTitleBar();
+ BoxCount++;
+
+ switch (titleId) {
+
+ case DLG_SaveAs_Filebox_Title:
+//
+// Here we have the second half of a *kludge* (repeat, KLUDGE!!!) that
+// began back up in the SaveAsFile() routine. If the 'fileName' parameter
+// is a null string, then we know (magic!) that we are Save As'ing a new file
+// that has no name as yet. But the user's window shows a title of "UNTITLED n",
+// and that has been stuck in 'fileName' after the initial null. So we find
+// it and then add that to the dialog box's title, eh?
+//
+ if (!*fileName)
+ {
+ sprintf (title+strlen(title), " %s", fileName+1);
+ }
+
+ result = GetSaveFileName((LPOPENFILENAME)&OpenFileName) ;
+ break ;
+
+ case DLG_Open_Filebox_Title:
+ strcpy(OpenFileName.lpstrFile, defExt);
+ result = GetOpenFileName((LPOPENFILENAME)&OpenFileName) ;
+ break ;
+
+ case DLG_Browse_DbugDll_Title:
+ case DLG_Merge_Filebox_Title:
+ *(OpenFileName.lpstrFile) = '\0';
+ result = GetOpenFileName((LPOPENFILENAME)&OpenFileName) ;
+ break ;
+
+ case DLG_Browse_Filebox_Title:
+ _splitpath (files, (char *)NULL, (char *)NULL, (char *)szBase, szExt);
+ indx = matchExt (szExt, filters);
+
+ if (indx != -1) {
+ OpenFileName.nFilterIndex = indx;
+ }
+
+ strcat(title, szBase);
+ if (*szExt) {
+ strcat(title, szExt);
+ }
+
+ FAddToSearchPath = FALSE;
+ FAddToRootMap = FALSE;
+
+ result = GetOpenFileName((LPOPENFILENAME)&OpenFileName) ;
+
+ /*
+ * Check to see if the use said to add a file to the browse path.
+ * If so then add it to the fromt of the path
+ */
+
+ if (FAddToSearchPath) {
+ AddToSearchPath(OpenFileName.lpstrFile);
+ } else if (FAddToRootMap) {
+ RootSetMapped(fileName, OpenFileName.lpstrFile);
+ }
+ break ;
+
+ case DLG_Browse_UserDll_Title:
+ _splitpath (files, (char *)NULL, (char *)NULL, (char *)szBase, szExt);
+ indx = matchExt (szExt, filters);
+
+ if (indx != -1) {
+ OpenFileName.nFilterIndex = indx;
+ }
+
+ strcat(title, szBase);
+ if (*szExt) {
+ strcat(title, szExt);
+ }
+
+ FAddToSearchPath = FALSE;
+
+ result = GetOpenFileName((LPOPENFILENAME)&OpenFileName) ;
+
+ /*
+ * Check to see if the use said to add a file to the browse path.
+ * If so then add it to the front of the path
+ */
+
+ if (FAddToSearchPath) {
+ char szSearchPath[4000];
+ char *p1;
+
+ strcpy(szSearchPath, OpenFileName.lpstrFile);
+ p1 = strrchr(szSearchPath, '\\');
+ if (p1) {
+#ifdef DBCS
+ if (p1 == szSearchPath || *(CharPrev(szSearchPath,p1))==':') {
+#else
+ if (p1 == szSearchPath || *(p1-1) == ':') {
+#endif
+ p1++;
+ }
+ *p1++ = ';';
+
+ ModListGetSearchPath( p1,
+ sizeof(szSearchPath) - (p1 - szSearchPath) );
+ // if there wasn't a string there, lose the ';'
+ if (p1 > szSearchPath && !*p1) {
+ *--p1 = '\0';
+ }
+
+ ModListSetSearchPath(szSearchPath);
+ }
+ }
+ break ;
+
+ default:
+ DAssert(FALSE);
+ return FALSE;
+ break;
+ }
+
+
+ BoxCount--;
+
+ if (result)
+ {
+ _fstrcpy(fileName, OpenFileName.lpstrFile);
+
+ /*
+ * Save directory for next time
+ */
+
+#ifdef DBCS // to fix mskkbug#3909
+ if (result) {
+#endif
+ ch = fileName[OpenFileName.nFileOffset-1];
+ fileName[OpenFileName.nFileOffset-1] = 0;
+ if ((szInitialDir == NULL) || (strcmp(szInitialDir, fileName) != 0)) {
+ if (szInitialDir != NULL) {
+ free(szInitialDir);
+ }
+ szInitialDir = _strdup(fileName);
+ }
+ fileName[OpenFileName.nFileOffset-1] = ch;
+#ifdef DBCS // to fix mskkbug#3909
+ }
+#endif
+
+ /*
+ * Get the output of flags
+ */
+
+ *pFlags = OpenFileName.Flags ;
+
+ }
+
+ /*
+ * Restore cursor
+ */
+
+ SetCursor(hSaveCursor);
+
+ /*
+ * Enable edit window (WM_INITDIALOG of the hook may not run)
+ */
+
+
+ EnableWindow(hwndMDIClient, TRUE);
+
+ return result;
+} /* StartFileDlg() */
+
+
+void
+AddToSearchPath(
+ LPSTR lpstrFile
+)
+{
+ char * sz = GetDllName( DLL_SOURCE_PATH);
+ int i;
+ char * pch;
+ char ch;
+
+ pch = lpstrFile + strlen(lpstrFile);
+ while (*pch != '\\') {
+ pch--;
+ DAssert(pch >= lpstrFile);
+ }
+
+ i = pch - lpstrFile;
+ pch = malloc( i + 2 + (sz?strlen(sz):0) );
+ ch = lpstrFile[i];
+ lpstrFile[i] = 0;
+ strcpy(pch, lpstrFile);
+ lpstrFile[i] = ch;
+ if (sz) {
+ *(pch + i) = ';';
+ *(pch + i + 1) = 0;
+ strcat(pch, sz );
+ }
+
+ SetDllName(DLL_SOURCE_PATH, pch);
+
+ free(pch);
+}
+
+/*** matchExt
+**
+** Synopsis:
+** int = matchExt (queryExtension, sourceList)
+**
+** Entry:
+**
+** Returns: 1-based index of pairwise substring for which the second
+** element (i.e., the extension list), contains the target
+** extension. If there is no match, we return -1.
+**
+** Description:
+** Searches extension lists for the Open/Save/Browse common
+** dialogs to try to match a filter to the input filename's
+** extension.
+** (Open File, Save File, Merge File and Open Project)
+**
+** Implementation note: Our thinking looks like this:
+**
+** We are given a sequence of null-terminated strings which
+** are text/extension pairs. We return the pairwise 1-based
+** index of the first pair for which the second element has an
+** exact match for the target extension. (Everything, by the
+** way, is compared without case sensitivity.) We picture the
+** source sequence, then, to be an array whose elements are pairs
+** of strings (we will call the pairs 'left' and 'right').
+**
+** Just to complicate things, we allow the '.right' pair elements to
+** be strings like "*.c;*.cpp;*.cxx", where we our query might be
+** any one of the three (minus the leading asterisk). Fortunately,
+** strtok() will break things apart for us (see the 'delims[]' array
+** in the code for the delimiters we have chosen).
+**
+** Assuming there is a match in there somewhere, our invariant
+** for locating the first one will be:
+**
+** Exists(k):
+** ForAll(i) : 0 <= i < k
+** : queryExtension \not IS_IN source[i].right
+** \and
+** queryExtension IS_IN source[k].right
+**
+** where we define IS_IN to be a membership predicate (using strtok()
+** and _stricmp() in the implementation, eh?):
+**
+** x IS_IN y
+** <=>
+** Exists (t:token) : (t \in y) \and (x == t).
+**
+** The guard for our main loop, then, comes from the search for the
+** queryExtension within the tokens inside successive '.right' elements.
+** We choose to continue as long as there is no current token in the
+** pair's right side that contains the query.
+**
+** (We have the pragmatic concern that the value may not be there, so we
+** augment the loop guard with the condition that we have not yet
+** exhausted the source. This is straightforward to add to the
+** invariant, but it causes a lot of clutter that does help our
+** comprehension at all, so we just stick it in the guard without
+** formal justification.)
+*/
+
+int matchExt (char* queryExtension, char* sourceList)
+{
+ int answer;
+ int idxPair = 1; // a 1-based index!
+ char* tokenMatch = 0;
+
+ char delims[] = "*,; " ; // Given a typical string: "*.c;*.cpp;*.cxx",
+ // strtok() would produce three tokens:
+ // ".c", ".cpp", and ".cxx".
+
+ while (*sourceList != 0 && tokenMatch == 0)
+ {
+ while (*sourceList != '\0')
+ { sourceList++; } // skip first string of pair
+ sourceList++; // and increment beyond NULL
+
+ if (*sourceList != '\0')
+ {
+ char* work = _strdup (sourceList); // copy to poke holes in
+
+ tokenMatch = strtok (work, delims);
+
+ while (tokenMatch && _stricmp (tokenMatch, queryExtension))
+ {
+ tokenMatch = strtok (0, delims);
+ }
+
+ free (work);
+ }
+
+ if (tokenMatch == 0) // no match: need to move to next pair
+ {
+ while (*sourceList != '\0')
+ { sourceList++; } // skip second string of pair
+ sourceList++; // and increment beyond NULL
+
+ idxPair++;
+ }
+ }
+
+ answer = (tokenMatch != 0) ? idxPair : (-1);
+
+ return (answer);
+}
+
+
+
+
+
+/*** DlgFile
+**
+** Synopsis:
+** bool = DlgFile(hDlg, message, wParam, lParam)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes messages for file dialog boxes
+** Those dialogs are not called directly but are called
+** by the DlgFile function which contains all basic
+** elements for Dialogs Files Operations Handling.
+** (Open File, Save File, Merge File and Open Project)
+**
+*/
+
+BOOL
+DlgFile(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+)
+
+{
+ Unused(lParam);
+
+ switch (message) {
+
+ case WM_INITDIALOG:
+ {
+ char fileFilter[MAX_MSG_TXT];
+
+ // We don't like this standard title
+
+ Dbg(LoadString(hInst, SYS_File_Filter, (LPSTR)fileFilter,
+ MAX_MSG_TXT));
+ SetWindowText(GetDlgItem(hDlg, stc2), (LPSTR)fileFilter);
+
+ //Send input to dialog box and re-enable back frame client
+
+ SetFocus(hDlg);
+ EnableWindow(hwndMDIClient, TRUE);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch (wParam) {
+
+ //Help button
+
+ case psh15:
+ Dbg(WinHelp(hDlg,szHelpFileName, HELP_CONTEXT, curHelpId));
+ return TRUE;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return FALSE;
+} /* DlgFile() */
+
+
+BOOL
+GetOpenFileNameHookProc(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is handle the Add Directory To radio buttons in the
+ browser source file dialog box.
+
+Arguments:
+
+ hDlg - Supplies the handle to current dialog
+ msg - Supplies the message to be processed
+ wParam - Supplies info about the message
+ lParam - Supplies info about the message
+
+Return Value:
+
+ TRUE if we replaced default processing of the message, FALSE otherwise
+
+--*/
+
+{
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+ CheckRadioButton(hDlg, ID_BROWSE_ADDNONE, ID_BROWSE_ADDSOURCE,
+ ID_BROWSE_ADDNONE);
+ break;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam )) {
+ case IDOK:
+ FAddToSearchPath = IsDlgButtonChecked( hDlg, ID_BROWSE_ADDSOURCE );
+ FAddToRootMap = IsDlgButtonChecked(hDlg, ID_BROWSE_ADDROOT);
+ if (FAddToSearchPath || FAddToRootMap) {
+ Assert(FAddToSearchPath != FAddToRootMap);
+ Assert(IsDlgButtonChecked(hDlg, ID_BROWSE_ADDNONE) == FALSE);
+ } else
+ Assert(IsDlgButtonChecked(hDlg, ID_BROWSE_ADDNONE));
+ break;
+ }
+ }
+ return DlgFile(hDlg, msg, wParam, lParam);
+
+} /* GetOpenFileNameHookProc() */
+
+
+BOOL
+GetOpenDllNameHookProc(
+ HWND hDlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to handle the Add Directory To radio
+ buttons in the browse Exe and Sym file dialog box.
+
+Arguments:
+
+ hDlg - Supplies the handle to current dialog
+ msg - Supplies the message to be processed
+ wParam - Supplies info about the message
+ lParam - Supplies info about the message
+
+Return Value:
+
+ TRUE if we replaced default processing of the message, FALSE otherwise
+
+--*/
+
+{
+
+ switch( msg ) {
+ case WM_INITDIALOG:
+ CheckRadioButton(hDlg, ID_BROWSE_ADDNONE, ID_BROWSE_ADDSOURCE,
+ ID_BROWSE_ADDNONE);
+ EnableWindow(GetDlgItem(hDlg, ID_BROWSE_ADDROOT), FALSE);
+ break;
+
+ case WM_COMMAND:
+ switch( LOWORD( wParam )) {
+ case IDOK:
+ FAddToSearchPath = IsDlgButtonChecked( hDlg, ID_BROWSE_ADDSOURCE );
+ break;
+ }
+ }
+ return DlgFile(hDlg, msg, wParam, lParam);
+
+} /* GetOpenFileNameHookProc() */
+
+
+/*** UpdateStatus
+**
+** Synopsis:
+** void = UpdateStatus(action, pClientRec)
+**
+** Entry:
+** action -
+** pClientRec -
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+void UpdateStatus(
+ WORD action,
+ NPRECT pClientRec)
+{
+ RECT rect;
+
+ switch (action)
+ {
+ case STATUS_SIZE:
+ if (status.hidden)
+ break;
+ else
+ {
+ // don't recalculate the size if the rectangle is null
+ if ( pClientRec != NULL )
+ ResizeStatusLine((LPRECT)pClientRec) ;
+ InvalidateRect (status.hwndStatus, (LPRECT)NULL, TRUE) ;
+ }
+ break;
+
+ case STATUS_HIDE: {
+ // Disable all windows/controls in the status
+ SendMessage(status.hwndStatus, WM_SETREDRAW, FALSE, 0L);
+ EnableWindow(status.hwndStatus, FALSE);
+
+ //Ask the frame to redraw
+ GetClientRect(hwndFrame, (LPRECT)&rect);
+ SendMessage(hwndFrame, WM_SIZE, SIZENORMAL,
+ MAKELONG(rect.right + 1, rect.bottom + 1));
+ }
+ break;
+
+ case STATUS_UNHIDE: {
+ // Enable everything
+ SendMessage(status.hwndStatus, WM_SETREDRAW, TRUE, 0L);
+ EnableWindow(status.hwndStatus, TRUE);
+
+ //Ask the frame to redraw
+ GetClientRect(hwndFrame, (LPRECT)&rect);
+ SendMessage(hwndFrame, WM_SIZE, SIZENORMAL,
+ MAKELONG(rect.right + 1, rect.bottom + 1));
+ }
+ break;
+ }
+} /* UpdateStatus() */
+
+/****************************************************************************
+
+ FUNCTION: UpdateRibbon
+
+****************************************************************************/
+void
+UpdateRibbon(
+ WORD action,
+ NPRECT pClientRec
+ )
+{
+ RECT rect;
+
+ switch (action) {
+
+ case RIBBON_SIZE:
+
+ if (ribbon.hidden) {
+
+ break;
+
+ } else if ( pClientRec == NULL ) {
+
+ InvalidateRect (ribbon.hwndRibbon, (LPRECT)NULL, TRUE) ;
+
+ } else {
+ // only update the part that is not intersected
+ // between old and new sizes.
+ if ( pClientRec->right > ribbon.ribrect.right ) {
+ RECT r ;
+
+ r.left = ribbon.ribrect.right ;
+ r.top = ribbon.ribrect.top ;
+ r.right = pClientRec->right ;
+ r.bottom = ribbon.ribrect.bottom + 1 ;
+ InvalidateRect (ribbon.hwndRibbon, (LPRECT)&r, TRUE) ;
+ }
+ // always update the right even if the new width is not
+ // greater than the old width.
+ ribbon.ribrect.right = pClientRec->right ;
+ }
+ break;
+
+ case RIBBON_HIDE:
+
+ // Disable all windows/controls in the ribbon
+ SendMessage(ribbon.hwndRibbon, WM_SETREDRAW, FALSE, 0L);
+ EnableWindow(ribbon.hwndRibbon, FALSE);
+
+ //Ask the frame to redraw
+ GetClientRect(hwndFrame, (LPRECT)&rect);
+ SendMessage(hwndFrame, WM_SIZE, SIZENORMAL,
+ MAKELONG(rect.right + 1, rect.bottom + 1));
+ break;
+
+ case RIBBON_UNHIDE:
+
+ // Enable everything
+ SendMessage(ribbon.hwndRibbon, WM_SETREDRAW, TRUE, 0L);
+ EnableWindow(ribbon.hwndRibbon, TRUE);
+
+ //Ask the frame to redraw
+ GetClientRect(hwndFrame, (LPRECT)&rect);
+ SendMessage(hwndFrame, WM_SIZE, SIZENORMAL,
+ MAKELONG(rect.right + 1, rect.bottom + 1));
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ // invalidate the bar so it can be redrawn entirely
+ InvalidateRect(ribbon.hwndRibbon, (LPRECT)NULL, TRUE) ;
+ break;
+ }
+} /* UpdateRibbon() */
+
+/*** FindWindowMenuId
+**
+** Synopsis:
+** int = FindWindowMenuId(type, viewLimit, sendDocMenuId)
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Find an Id number window menu if window is not a document,
+** return offset in window menu otherwise
+*/
+
+int
+FindWindowMenuId(
+ WORD type,
+ int viewLimit,
+ BOOL sendDocMenuId)
+{
+
+ int k;
+
+ switch (type) {
+ case DOC_WIN:
+
+ if (sendDocMenuId) {
+ k = IDM_WINDOWCHILD + viewLimit;
+ } else {
+
+ int n;
+
+ for (n=0, k=0; n < viewLimit; n += 1) {
+ if (Views[n].Doc > -1)
+ if (Docs[Views[n].Doc].docType == DOC_WIN) {
+ k++;
+ }
+ }
+ }
+ break;
+
+ case CPU_WIN:
+ k = IDM_WINDOW_CPU;
+ break;
+ case DISASM_WIN:
+ k = IDM_WINDOW_DISASM;
+ break;
+ case COMMAND_WIN:
+ k = IDM_WINDOW_COMMAND;
+ break;
+ case FLOAT_WIN:
+ k = IDM_WINDOW_FLOAT;
+ break;
+ case MEMORY_WIN:
+ if (sendDocMenuId)
+ {
+ k = IDM_WINDOWCHILD + viewLimit;
+ } else
+ {
+ int n;
+ for (n=0, k=0; n <= viewLimit; n += 1)
+ {
+ if (Views[n].Doc > -1)
+ {
+ if ((Docs[Views[n].Doc].docType == MEMORY_WIN))
+ {
+ k++;
+ }
+
+ }
+ }
+ }
+ break;
+ case WATCH_WIN:
+ k = IDM_WINDOW_WATCH;
+ break;
+ case LOCALS_WIN:
+ k = IDM_WINDOW_LOCALS;
+ break;
+ case CALLS_WIN:
+ k = IDM_WINDOW_CALLS;
+ break;
+ default:
+ DAssert(FALSE);
+ k = 0;
+ break;
+ }
+
+ return k;
+} /* FindWindowMenuId() */
+
+/*** AddWindowMenuItem
+**
+** Synopsis:
+** void = AddWindowMenuItem(doc, view)
+**
+** Entry:
+** doc
+** view
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Add an Item in Window menu
+**
+*/
+
+void AddWindowMenuItem(int doc, int view)
+{
+ int n;
+ int i;
+ int k;
+
+ if (doc < 0) {
+ k = FindWindowMenuId((WORD)-doc, view, FALSE);
+ BuildWindowItemString(szTmp, -doc, 0, NULL, view);
+ Dbg(ModifyMenu(hWindowSubMenu, k, MF_BYCOMMAND, k, (LPSTR)szTmp));
+/*! ==v==(+) !*/
+/*! --*-- !**
+ if (view < 0)
+ {
+ CheckMenuItem (hWindowSubMenu, k, MF_CHECKED);
+ }
+/*! ==^==(-) !*/
+ }
+
+ //Special behaviour if it's first view of one of the debugging windows
+
+ else {
+
+ NPDOCREC d = &Docs[doc];
+ k = FindWindowMenuId(d->docType, view, FALSE);
+ if ((d->docType != DOC_WIN) && (d->docType != MEMORY_WIN)) {
+ BuildWindowItemString(szTmp, d->docType, 0, d->FileName, view);
+ Dbg(ModifyMenu(hWindowSubMenu, k, MF_BYCOMMAND, k, (LPSTR)szTmp));
+ }
+
+ else {
+ //if (GetMenuItemCount(hWindowSubMenu) < FIRST_DOC_WIN_POS)
+ // Dbg(AppendMenu(hWindowSubMenu, MF_SEPARATOR, 0, NULL));
+
+ /*
+ ** Get mnemonic number counting the window menu items
+ */
+
+ BuildWindowItemString(szTmp, d->docType, k, d->FileName, view);
+
+ for (n=0, i=0; i < view; i++) {
+ if ((Views[n].Doc != -1) &&
+ (Views[n].Doc >= 0) &&
+ ((Docs[Views[n].Doc].docType == DOC_WIN) ||
+ (Docs[Views[n].Doc].docType == MEMORY_WIN))) {
+ n += 1;
+ }
+ }
+
+ // Dbg(InsertMenu(hWindowSubMenu, n + FIRST_DOC_WIN_POS,
+ // MF_ENABLED | MF_BYPOSITION, IDM_WINDOWCHILD + view,
+ // (LPSTR)szTmp));
+ }
+ }
+ return;
+} /* AddWindowMenuItem() */
+
+/*** DeleteWindowMenuItem
+**
+** Synopsis:
+** void = DeleteWindowMenuItem(view)
+**
+** Entry:
+** view
+**
+** Returns:
+**
+** Description:
+** Delete an Item from Window menu
+**
+*/
+
+void DeleteWindowMenuItem(int view)
+{
+ NPDOCREC d;
+ int k;
+ int doc = Views[view].Doc;
+
+ if ( doc < 0) {
+ k = FindWindowMenuId((WORD)-doc, view, FALSE);
+ BuildWindowItemString(szTmp, -doc, 0, NULL, -1);
+ ModifyMenu(hWindowSubMenu, k, MF_BYCOMMAND, k, (LPSTR)szTmp);
+/*! ==v==(+) !*/
+/*! --*-- !**
+ CheckMenuItem (hWindowSubMenu, k, MF_CHECKED);
+/*! ==^==(-) !*/
+ }
+
+
+ else {
+ d = &Docs[Views[view].Doc];
+ k = FindWindowMenuId(d->docType, view, FALSE);
+ if ((d->docType != DOC_WIN) && (d->docType != MEMORY_WIN)) {
+ BuildWindowItemString(szTmp, d->docType, 0, d->FileName, -1);
+ ModifyMenu(hWindowSubMenu, k, MF_BYCOMMAND, k, (LPSTR)szTmp);
+ }
+
+ }
+ return;
+} /* DeleteWindowMenuItem() */
+
+
+/*** DestroyView
+**
+** Synopsis:
+** bool = DestroyView(view)
+**
+** Entry:
+** view - view index of document to be destroyed
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL DestroyView(int view)
+{
+ NPVIEWREC v = &Views[view];
+ HCURSOR hSaveCursor;
+
+ //Set the Hour glass cursor
+
+ hSaveCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ DAssert(view >= 0 && view < MAX_VIEWS);
+
+ if (v->Doc < 0)
+ {
+ return(FALSE);
+ }
+
+
+ //Delete title from window menu list
+
+ DeleteWindowMenuItem(view);
+
+ switch(Docs[v->Doc].docType) {
+
+ case DISASM_WIN:
+ disasmView = -1;
+ break;
+
+ case COMMAND_WIN:
+ cmdView = -1;
+ break;
+
+ case MEMORY_WIN:
+ {
+ int n;
+ BOOL fMem;
+
+ fMem = FALSE;
+
+ for (n=0; n < MAX_VIEWS; n++) {
+ if (Views[n].Doc > -1)
+ {
+ if ((Docs[Views[n].Doc].docType == MEMORY_WIN))
+ {
+ fMem = TRUE;
+ }
+ }
+ }
+
+ if (fMem == FALSE)
+ {
+ memView = -1; // only reset if no other memwins
+ }
+
+ }
+ break;
+ }
+
+ //Suppress the view from the list of views. If it was the last
+ //view of the document, suppress the document from the list of
+ //documents and free all memory blocks associated with it
+
+ if (Docs[v->Doc].FirstView == view && v->NextView == -1) {
+
+ if (!TerminatedApp) {
+ EnableRibbonControls(ERC_ALL, FALSE);
+ }
+
+ Docs[v->Doc].FirstView = -1;
+ DestroyDocument(v->Doc);
+
+ } else {
+
+ int *pV;
+
+ //At least one more view, suppress view from list of views
+
+ pV = &Docs[v->Doc].FirstView;
+ while (*pV != -1 && *pV != view)
+ pV = &Views[*pV].NextView;
+ DAssert (*pV == view);
+ *pV = Views[view].NextView;
+
+ //We have 1 view, or more, refresh title(s)
+
+ RefreshWindowsTitle(v->Doc);
+
+ }
+
+ Dbg(DeleteObject(v->font));
+
+ memset ( v, 0, sizeof (VIEWREC));
+ v->Doc = -1;
+
+ //Reset Cursor
+
+ SetCursor(hSaveCursor);
+
+ return TRUE;
+} /* DestroyView() */
+
+/*** EnableRibbonControls
+**
+** Synopsis:
+** void = EnableRibbonControls(Updates, LaunchingDebuggee)
+**
+** Entry:
+** Updates - Mask of which set of controls to udpate
+** LaunchingDebuggee - TRUE if debugging is about to be started
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Enables/disables the controls in the ribbon according
+** to the current state of the system.
+**
+*/
+
+void PASCAL
+EnableRibbonControls(int Updates, BOOL LaunchingDebuggee)
+{
+ NPDOCREC d;
+ NPVIEWREC v;
+ int EnableMsg;
+ int memcurView = 0;
+ int curDoc = 0;
+
+
+#define ControlOk(id) ((CommandIdEnabled(id)&(MF_DISABLED|MF_ENABLED|MF_GRAYED))==MF_ENABLED)
+
+
+
+ if (hwndActiveEdit != NULL) // case just loading from registry
+ {
+ memcurView = GetWindowWord(hwndActiveEdit, GWW_VIEW);
+ curDoc = Views[memcurView].Doc; //memcurView may change during loop
+ }
+
+ d = NULL;
+ if (curView != -1) {
+ v = &Views[curView];
+ d = &Docs[v->Doc];
+ }
+
+ /*
+ ** Breakpoint: The breakpoint toggle button is enabled if:
+ ** 1. There is an active document,
+ ** 2. The document is a source document,
+ ** 3. The document is NOT untitled, and
+ ** 4. The Debug.Set Breakpoint menu item is not disabled
+ */
+
+ if (Updates & ERC_BREAKPT) {
+ EnableMsg = (((d != NULL) &&
+ ((d->docType == DOC_WIN) ||
+ ((d->docType == DISASM_WIN) && DebuggeeActive())) &&
+ !(d->untitled) &&
+ ControlOk(IDM_DEBUG_SETBREAK)) ?
+ WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL);
+ SendMessageNZ(ribbon.hwndRibbon, EnableMsg, ID_RIBBON_BREAK, 0L);
+ }
+
+
+ /*
+ ** QuickWatch: The quickwatch button is enabled if:
+ ** 1. The Quickwatch menu item is not disabled, and
+ ** 2. the debuggee is not about to be run
+ */
+
+ if (Updates & ERC_QWATCH) {
+ EnableMsg = ((ControlOk(IDM_DEBUG_QUICKWATCH)) ?
+ WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL);
+ SendMessageNZ(ribbon.hwndRibbon, EnableMsg, ID_RIBBON_QWATCH, 0L);
+ }
+
+ /*
+ ** Trace/StepGo: The trace, step and go buttons follow the
+ ** corresponding menu items.
+ */
+
+ if (Updates & ERC_TRACESTEP) {
+
+ SendMessageNZ(ribbon.hwndRibbon,
+ (!LaunchingDebuggee && ControlOk(IDM_RUN_TRACEINTO)) ?
+ WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL,
+ ID_RIBBON_TRACE,
+ 0L);
+
+ SendMessageNZ(ribbon.hwndRibbon,
+ (!LaunchingDebuggee && ControlOk(IDM_RUN_STEPOVER)) ?
+ WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL,
+ ID_RIBBON_STEP,
+ 0L);
+
+ SendMessageNZ(ribbon.hwndRibbon,
+ (!LaunchingDebuggee && ControlOk(IDM_RUN_GO)) ?
+ WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL,
+ ID_RIBBON_GO,
+ 0L);
+
+ SendMessageNZ(ribbon.hwndRibbon,
+ (!LaunchingDebuggee && ControlOk(IDM_RUN_HALT)) ?
+ WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL,
+ ID_RIBBON_HALT,
+ 0L);
+ }
+
+ if (!status.fSrcMode)
+ {
+ SendMessageNZ(ribbon.hwndRibbon,WU_DISABLERIBBONCONTROL,ID_RIBBON_SMODE,0L);
+ SendMessageNZ(ribbon.hwndRibbon,WU_ENABLERIBBONCONTROL, ID_RIBBON_AMODE,0L);
+ }
+ else
+ {
+ SendMessageNZ(ribbon.hwndRibbon,WU_ENABLERIBBONCONTROL,ID_RIBBON_SMODE,0L);
+ SendMessageNZ(ribbon.hwndRibbon,WU_DISABLERIBBONCONTROL, ID_RIBBON_AMODE,0L);
+ }
+
+
+ if (hwndActiveEdit != NULL) {
+
+ NPVIEWREC v = &Views[curView];
+ NPDOCREC d;
+ UINT uSwitch;
+ UINT Msg = WU_DISABLERIBBONCONTROL;
+
+ if (v->Doc < -1) {
+
+ uSwitch = -(v->Doc);
+
+ } else {
+
+ d = &Docs[v->Doc]; //Views[indx].Doc
+ uSwitch = d->docType;
+ }
+
+ switch (uSwitch) {
+
+ case WATCH_WIN:
+ case LOCALS_WIN:
+ case CALLS_WIN:
+ Msg = WU_ENABLERIBBONCONTROL;
+ break;
+
+ case MEMORY_WIN:
+ Msg = (DebuggeeActive()) ? WU_ENABLERIBBONCONTROL : WU_DISABLERIBBONCONTROL;
+ break;
+
+ default:
+ break;
+ }
+
+ SendMessage(ribbon.hwndRibbon,
+ Msg,
+ ID_RIBBON_FORMAT,
+ 0L);
+
+ }
+
+ return;
+
+#undef ControlOk
+} /* EnableRibbonControls() */
+
+BOOL IntOutOfRange(PSTR text, int FAR *val, int min, int max, HWND hDlg,
+ int dlgItem, int errMsg)
+{
+ BOOL outOfRange = FALSE;
+
+ *val = atoi(text);
+ if (*val < min) {
+ _itoa(min, text, 10);
+ *val = min;
+ outOfRange = TRUE;
+ } else {
+ if (*val > max) {
+ _itoa(max, text, 10);
+ *val = max;
+ outOfRange = TRUE;
+ }
+ }
+
+ //If out of range, prompt the error and give focus to the item
+
+ if (outOfRange) {
+ InformationBox(errMsg, min, max);
+ SendDlgItemMessage(hDlg, dlgItem,
+ WM_SETTEXT, 0, (LONG)(LPSTR)text);
+ SendDlgItemMessage(hDlg, dlgItem,
+ EM_SETSEL, 0, MAKELONG(0, 32767));
+ SetFocus(GetDlgItem(hDlg, dlgItem));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LongOutOfRange(
+ PSTR text,
+ long far *val,
+ long min,
+ long max,
+ HWND hDlg,
+ int dlgItem,
+ int errMsg)
+{
+ BOOL outOfRange = FALSE;
+
+ *val = atol(text);
+ if (*val < min) {
+ _ltoa(min, text, 10);
+ *val = min;
+ outOfRange = TRUE;
+ }
+ else {
+ if (*val > max) {
+ _ltoa(max, text, 10);
+ *val = max;
+ outOfRange = TRUE;
+ }
+ }
+
+ //If out of range, prompt the error and give focus to the item
+ if (outOfRange) {
+ InformationBox(errMsg, min, max);
+ SendDlgItemMessage(hDlg, dlgItem,
+ WM_SETTEXT, 0, (LONG)(LPSTR)text);
+ SendDlgItemMessage(hDlg, dlgItem,
+ EM_SETSEL, 0, MAKELONG(0, 32767));
+ SetFocus(GetDlgItem(hDlg, dlgItem));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*** SetLanguage
+**
+** Synopsis:
+** int = SetLanguage(doc)
+**
+** Entry:
+** doc - index of document to check for language specific extenstion
+**
+** Returns:
+** Language type index, currently C_LANGUAGE or NO_LANGUAGE
+**
+** Description:
+** Examine the extension on the filename for a document and check to
+** see if it matches a language specific extension. If so return
+** the parameter for that language.
+*/
+
+int SetLanguage(int doc)
+{
+ _splitpath(Docs[doc].FileName, szDrive, szDir, szFName, szExt);
+ _strupr(szExt);
+ if (_strcmpi(szExt , szStarDotC + 1) == 0
+ || strcmp(szExt, szStarDotH + 1) == 0
+ || strcmp(szExt, szStarDotCPP + 1) == 0
+ || strcmp(szExt, szStarDotCXX + 1) == 0
+ )
+ return C_LANGUAGE;
+ else
+ return NO_LANGUAGE;
+} /* SetLanguage() */
+
+BOOL GetWordAtXY(
+ int view,
+ int x,
+ int y,
+ BOOL selection,
+ BOOL *lookAround,
+ BOOL includeRightSpace,
+ LPSTR pWord,
+ int maxSize,
+ LPINT leftCol,
+ LPINT rightCol)
+{
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ NPVIEWREC v = &Views[view];
+ int xl, xr;
+
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return FALSE;
+
+#ifdef DBCS // ***************************************************************
+ //Line empty or cursor beyond line
+ if (pl->Length == LHD)
+ goto endFalse;
+
+ else if (x >= elLen) {
+ int iLastChar = -1;
+ int i;
+
+ //We could be one char after a word
+ if (x == elLen) {
+ for (i = 0 ; i < elLen ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ iLastChar = i;
+ i++;
+ } else if (CHARINKANASET(el[i])) {
+ iLastChar = i;
+ } else if (IsCharAlphaNumeric(el[i])) {
+ iLastChar = i;
+ } else {
+ iLastChar = -1;
+ }
+ }
+ }
+ if (iLastChar >= 0) {
+ x = iLastChar;
+ } else if (lookAround && *lookAround) {
+ //If caller wants to look around, look left
+ for (i = 0, x = -1 ; i < elLen ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ x = i;
+ i++;
+ } else if (el[i] != ' ') {
+ x = i;
+ }
+ }
+ if (x < 0)
+ goto endFalse;
+ *lookAround = TRUE;
+ } else {
+ goto endFalse;
+ }
+ } else {
+ int i;
+
+ //make sure if the cursor isn't on middle of DBCS char
+ for (i = 0 ; i < elLen && i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ if (x == i + 1) {
+ x = i;
+ break;
+ }
+ i++;
+ }
+ }
+ }
+
+#else // !DBCS *************************************************************
+
+ //Line empty or cursor beyond line
+ if (pl->Length == LHD)
+ goto endFalse;
+ else {
+
+ if (x >= elLen) {
+
+ //We could be one char after a word
+ if (x == elLen && IsCharAlphaNumeric(el[x - 1]))
+ x--;
+ else {
+
+ //If caller wants to look around, look left
+ if (lookAround && *lookAround) {
+
+ x = elLen - 1;
+ while (x >= 0 && el[x] == ' ')
+ x--;
+ if (x < 0)
+ goto endFalse;
+ *lookAround = TRUE;
+ }
+ else
+ goto endFalse;
+ }
+ }
+ }
+#endif // !DBCS end *********************************************************
+
+#ifdef DBCS // ***************************************************************
+ //Cursor on a space
+ if (el[x] == ' ') {
+ int iLastChar = -1;
+ int i;
+
+ //Cursor on a space but just after a word
+ if (includeRightSpace) {
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ iLastChar = i;
+ i++;
+ } else if (CHARINKANASET(el[i])) {
+ iLastChar = i;
+ } else if (CHARINALPHASET(el[i])) {
+ iLastChar = i;
+ } else {
+ iLastChar = -1;
+ }
+ }
+ }
+ if (iLastChar >= 0 && includeRightSpace) {
+ x = iLastChar;
+ } else if (lookAround && *lookAround) {
+ xl = x;
+
+ //We are on a space but the caller want to look first if
+ //there is a word on the right and then on the left
+ while (x < elLen && el[x] == ' '
+ && !IsDBCSLeadByte((BYTE)el[x])) {
+ x++;
+ }
+
+ //Nothing at right, try left
+ if (x >= elLen) {
+ x = xl;
+ iLastChar = -1;
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ iLastChar = i;
+ i++;
+ } else if (CHARINKANASET(el[i])) {
+ iLastChar = i;
+ } else if (CHARINALPHASET(el[i])) {
+ iLastChar = i;
+ } else {
+ iLastChar = -1;
+ }
+ }
+ if (iLastChar < 0) {
+ goto endFalse;
+ }
+ x = iLastChar;
+ }
+ *lookAround = TRUE;
+ }
+ else {
+ //We are going to return FALSE, but set right word to last space
+ if (rightCol) {
+ while (x < elLen && el[x] == ' '
+ && !IsDBCSLeadByte((BYTE)el[x])) {
+ x++;
+ }
+ *rightCol = x;
+ }
+ goto endFalse;
+ }
+
+ }
+ else {
+
+ //Cursor was already on a word
+ if (lookAround)
+ *lookAround = FALSE;
+ }
+
+#else // !DBCS *************************************************************
+
+ //Cursor on a space
+ if (el[x] == ' ') {
+
+ //Cursor on a space but just after a word
+ if (x > 0 && CHARINALPHASET(el[x - 1]) && includeRightSpace)
+ x--;
+ else {
+
+ if (lookAround && *lookAround) {
+
+ xl = x;
+
+ //We are on a space but the caller want to look first if
+ //there is a word on the right and then on the left
+ while (x < elLen && el[x] == ' ')
+ x++;
+
+ //Nothing at right, try left
+ if (x >= elLen) {
+ x = xl;
+ while (x >= 0 && el[x] == ' ')
+ x--;
+ if (x < 0)
+ goto endFalse;
+ }
+ *lookAround = TRUE;
+ }
+ else {
+ //We are going to return FALSE, but set right word to last space
+ if (rightCol) {
+ while (x < elLen && el[x] == ' ')
+ x++;
+ *rightCol = x;
+ }
+ goto endFalse;
+ }
+ }
+ }
+ else {
+
+ //Cursor was already on a word
+ if (lookAround)
+ *lookAround = FALSE;
+ }
+
+#endif // !DBCS end *********************************************************
+
+#ifdef DBCS // ***************************************************************
+
+ xl = xr = x;
+
+ if (IsDBCSLeadByte((BYTE)el[x])) {
+#ifdef DBCS_WORD_MULTI
+ int iLeftChar = -1;
+ int i;
+
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ if (-1 == iLeftChar) {
+ iLeftChar = i;
+ }
+ i++;
+ } else {
+ iLeftChar = -1;
+ }
+ }
+ if (-1 != iLeftChar) {
+ xl = iLeftChar;
+ }
+ while (xr < elLen && IsDBCSLeadByte((BYTE)el[xr])) {
+ xr += 2;
+ }
+#else
+ // Suppose one DBCS char is one word.
+ xr += 2;
+#endif
+ } else if (CHARINKANASET(el[x])) {
+ int iLeftChar = -1;
+ int i;
+
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ iLeftChar = -1;
+ i++;
+ } else if (CHARINKANASET(el[i])) {
+ if (-1 == iLeftChar) {
+ iLeftChar = i;
+ }
+ } else {
+ iLeftChar = -1;
+ }
+ }
+ if (-1 != iLeftChar) {
+ xl = iLeftChar;
+ }
+ while (xr < elLen
+ && !IsDBCSLeadByte((BYTE)el[xr])
+ && CHARINKANASET(el[xr])) {
+ xr++;
+ }
+
+ //Extract all alphanumerics characters
+ } else if (CHARINALPHASET(el[x])) {
+ int iLeftChar = -1;
+ int i;
+
+ for (i = 0 ; i < x ; i++) {
+ if (IsDBCSLeadByte((BYTE)el[i])) {
+ iLeftChar = -1;
+ i++;
+ } else if (CHARINALPHASET(el[i])) {
+ if (-1 == iLeftChar) {
+ iLeftChar = i;
+ }
+ } else {
+ iLeftChar = -1;
+ }
+ }
+ if (-1 != iLeftChar) {
+ xl = iLeftChar;
+ }
+ while (xr < elLen
+ && !IsDBCSLeadByte((BYTE)el[xr])
+ && CHARINALPHASET(el[xr])) {
+ xr++;
+ }
+ }
+ else
+ //Separator
+ xr++;
+
+#else // !DBCS *************************************************************
+
+ xl = xr = x;
+
+ //Extract all alphanumerics characters
+ if (CHARINALPHASET(el[x])) {
+
+ while (xl >= 0 && CHARINALPHASET(el[xl]))
+ xl--;
+ xl++;
+
+ while (xr < elLen && CHARINALPHASET(el[xr]))
+ xr++;
+ }
+ else
+
+ //Separator
+ xr++;
+
+#endif // !DBCS end *********************************************************
+
+ //Send back cursor positions containing word
+ if (leftCol)
+ *leftCol = xl;
+ if (rightCol)
+ *rightCol = xr;
+
+ //Extract word in a string, if a word return is wanted
+ maxSize = min(maxSize, xr - xl);
+ if (maxSize > 0) {
+ _fmemmove(pWord, (LPSTR)(el + xl), maxSize);
+ pWord[maxSize] = '\0';
+ }
+
+ //Highlight word if selection wanted
+ y--;
+ if (selection) {
+ ClearSelection(view);
+ v->BlockStatus = TRUE;
+ v->BlockYL = y;
+ v->BlockYR = y;
+ v->BlockXL = xl;
+ v->BlockXR = xr;
+ InvalidateLines(view, y, y, FALSE);
+ PosXY(view, xr, y, FALSE);
+ }
+
+ CloseLine (v->Doc, &pl, y + 1, &pb);
+ return TRUE;
+
+ endFalse: {
+ CloseLine (v->Doc, &pl, y, &pb);
+ return FALSE;
+ }
+
+}
+
+int NEAR PASCAL GetMaxLineWidth(
+ int view)
+{
+ NPVIEWREC v = &Views[view];
+ LPLINEREC pl;
+ LPBLOCKDEF pb;
+ RECT rc;
+ int y, lastY;
+ int maxX = 0;
+
+ //Get first line of view's window
+ y = v->iYTop;
+ if (y == -1) {
+ y = GetScrollPos(v->hwndClient, SB_VERT);
+ }
+
+ //Get last line of view's window
+ GetClientRect(v->hwndClient, &rc);
+
+ lastY = y + (rc.bottom / v->charHeight);
+ if (rc.bottom % v->charHeight)
+ lastY++;
+
+ //This function is for the debugging windows, so we won't find tabs
+ if (y < Docs[v->Doc].NbLines) {
+
+ lastY = min(lastY, Docs[v->Doc].NbLines - 1);
+ if (!FirstLine(v->Doc, &pl, &y, &pb))
+ return 0;
+ maxX = pl->Length - LHD;
+
+ while (y < lastY) {
+
+ if (!NextLine(v->Doc, &pl, &y, &pb))
+ return 0;
+
+ if (pl->Length - LHD > maxX)
+ maxX = pl->Length - LHD;
+ }
+
+ CloseLine (v->Doc, &pl, y, &pb);
+ }
+ return maxX * v->aveCharWidth;
+}
+
+/*** EnsureScrollBars
+**
+** Synopsis:
+** void = EnsureScrollBars(view, force)
+**
+** Entry:
+** view - Which view to play with the scroll bars of
+** force -
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+*/
+
+void PASCAL EnsureScrollBars(int view, BOOL force)
+{
+ int sbWidth, sbHeight;
+ NPVIEWREC v = &Views[view];
+ BOOL hScrollBar, vScrollBar;
+ RECT rc;
+
+ /*
+ ** Get the current rectangle description for the client window
+ */
+
+ GetClientRect(v->hwndClient, &rc);
+
+ /*
+ ** Check if we want a vertical scrollbar. Yes if
+ ** 1. The user said ok to vertical scroll bar, and
+ ** 1a. The view is not of the disassembler window
+ ** 2. The document height is greater than the window size, or
+ ** 3. The scroll bar is not at the top
+ */
+
+ if (environParams.vertScrollBars &&
+ ((Docs[v->Doc].NbLines - 1 >= rc.bottom / v->charHeight) ||
+ (GetScrollPos(v->hwndClient, SB_VERT) != 0) ||
+ (view == disasmView))) {
+
+ vScrollBar = TRUE;
+ sbWidth = 0;
+ } else {
+ vScrollBar = FALSE;
+ sbWidth = GetSystemMetrics(SM_CXVSCROLL);
+ }
+
+ /*
+ ** Check if we want an horizontal scrollbar. No if
+ ** 1. The use said no horizontal scrollbar, or
+ ** 2. Not a document window and the widest line in the
+ ** document fits in the window.
+ */
+
+ if (environParams.horizScrollBars) {
+ if (Docs[v->Doc].docType != DOC_WIN
+ && GetMaxLineWidth(view) < rc.right
+ && GetScrollPos(v->hwndClient, SB_HORZ) == 0) {
+ hScrollBar = FALSE;
+ sbHeight = GetSystemMetrics(SM_CYHSCROLL);
+ } else {
+ hScrollBar = TRUE;
+ sbHeight = 0;
+ }
+ } else {
+ hScrollBar = FALSE;
+ sbHeight = GetSystemMetrics(SM_CYHSCROLL);
+ }
+
+ /*
+ ** See if we have to hide or show the scrollbars
+ */
+
+ GetClientRect(GetParent(v->hwndClient), &rc); //v->hwndFrame may not exist
+ if (force || vScrollBar != v->vScrollBar || hScrollBar != v->hScrollBar)
+ MoveWindow(v->hwndClient, 0, 0, rc.right + sbWidth, rc.bottom + sbHeight, TRUE);
+
+ //Save current state of scroll bars
+
+ v->vScrollBar = vScrollBar;
+ v->hScrollBar = hScrollBar;
+
+ return;
+} /* EnsureScrollBars() */
+
+
+/****************************************************************************
+
+ FUNCTION: Xalloc
+
+ PURPOSE: Alloc and lock MOVABLE global memory. Extra bytes are
+ allocated to spare Handle returned by GlobalAlloc
+
+ CHANGED: Now uses _fmalloc() in the new Windows C libraries
+ which contains a memory manager.
+
+****************************************************************************/
+LPSTR Xalloc(UINT bytes)
+{
+ LPSTR lPtr;
+
+ lPtr = (LPSTR)_fmalloc(bytes);
+ if (lPtr != NULL)
+ _fmemset(lPtr, 0, bytes);
+ return lPtr;
+}
+
+
+/****************************************************************************
+
+ FUNCTION: Xrealloc
+
+ PURPOSE: Rellocate a block of memory that was previously allocated
+ through Xalloc
+
+****************************************************************************/
+LPSTR Xrealloc(LPSTR curBlock, UINT newBytes)
+{
+ LPSTR lPtr;
+ UINT curBytes;
+
+#ifdef WIN32
+ curBytes = _msize(curBlock);
+ lPtr = (LPSTR) realloc(curBlock, newBytes);
+ if ((lPtr != NULL) && (newBytes > curBytes))
+ memset(lPtr+curBytes, 0, newBytes-curBytes);
+ return lPtr;
+#else
+ curBytes = _fmsize(curBlock);
+ lPtr = (LPSTR)_frealloc(curBlock, newBytes);
+ if ((lPtr != NULL) && (newBytes > curBytes))
+ _fmemset(lPtr+curBytes, 0, newBytes-curBytes);
+ return lPtr;
+#endif
+}
+
+
+/****************************************************************************
+
+ FUNCTION: Xfree
+
+ PURPOSE: Free global memory. The handle is stored at beginning
+ of lPtr
+
+****************************************************************************/
+BOOL Xfree(
+ LPSTR lPtr)
+{
+ _ffree(lPtr);
+ return TRUE;
+}
+
+
+/****************************************************************************
+
+ FUNCTION: NewFontInView
+
+ PURPOSE: Does the necessary things for updating the view when
+ its font has been changed
+
+****************************************************************************/
+void PASCAL NewFontInView(int view)
+{
+ NPVIEWREC v = &Views[view];
+ TEXTMETRIC tm;
+ HDC hDC;
+ LOGFONT tmpFont;
+
+ Dbg(hDC = GetDC(v->hwndClient));
+ tmpFont = fonts[fontCur];
+ tmpFont.lfHeight = fontSizes[fontSizeCur];
+ tmpFont.lfWidth = 0;
+ Dbg(v->font = CreateFontIndirect(&tmpFont));
+ Dbg(SelectObject(hDC, v->font));
+ Dbg(GetTextMetrics (hDC, &tm));
+ v->charHeight = tm.tmHeight;
+ v->maxCharWidth =tm.tmMaxCharWidth;
+ v->aveCharWidth =tm.tmAveCharWidth;
+ v->charSet = tm.tmCharSet;
+ GetCharWidth(hDC, 0, MAX_CHARS_IN_FONT - 1, (LPINT)v->charWidth);
+#ifdef DBCS
+ GetDBCSCharWidth(hDC, &tm, v);
+#endif
+ Dbg(ReleaseDC(v->hwndClient, hDC));
+
+
+ //Refresh display to print text with new font
+ InvalidateRect(v->hwndClient, (LPRECT)NULL, FALSE);
+
+ //Update scrollbars status
+ EnsureScrollBars(curView, FALSE);
+}
+
+/****************************************************************************
+
+ FUNCTION: EscapeAmpersands
+
+ PURPOSE: Convert any '&'s in a string to '&''&' sequences
+ (To avoid Windows taking it to be an accelerator
+ char. The conversion is done in place.
+
+****************************************************************************/
+void PASCAL EscapeAmpersands(LPSTR AmpStr, int MaxLen)
+{
+ char szBuffer[255];
+ int i = 0, j = 0;
+
+ // Escape into szBuffer...
+ while (AmpStr[i] && (j < sizeof(szBuffer)-2))
+ {
+ szBuffer[j] = AmpStr[i];
+
+ if (AmpStr[i] == '&')
+ {
+ szBuffer[++j] = '&';
+ }
+
+ i++;
+ j++;
+#ifdef DBCS
+ if (IsDBCSLeadByte(AmpStr[i])
+ && AmpStr[i+1] && j < sizeof(szBuffer)-2) {
+ szBuffer[j] = AmpStr[i];
+ i++;
+ j++;
+ }
+#endif
+ }
+ szBuffer[j] = '\0';
+
+ // ...and copy back into AmpStr
+ _fstrncpy(AmpStr, szBuffer, MaxLen-1);
+ AmpStr[MaxLen-1] = '\0';
+}
+
+/****************************************************************************
+
+ FUNCTION: UnescapeAmpersands
+
+ PURPOSE: Opposite of EscapeAmpersands. (Isn't Windows fun?)
+
+****************************************************************************/
+void PASCAL UnescapeAmpersands(LPSTR AmpStr, int MaxLen)
+{
+ char szBuffer[255];
+ int i = 0, j = 0;
+
+ // Unescape into szBuffer...
+ while (AmpStr[i] && (j < sizeof(szBuffer)-1))
+ {
+ szBuffer[j] = AmpStr[i];
+
+ j++;
+#ifdef DBCS
+ if (IsDBCSLeadByte(AmpStr[i])
+ && AmpStr[i+1] && j < sizeof(szBuffer)-2) {
+ i++;
+ szBuffer[j] = AmpStr[i];
+ i++;
+ j++;
+ }
+#endif
+ if (AmpStr[++i] == '&')
+ {
+ i++;
+ }
+ }
+ szBuffer[j] = '\0';
+
+ // ...and copy back into AmpStr
+ _fstrncpy(AmpStr, szBuffer, MaxLen-1);
+ AmpStr[MaxLen-1] = '\0';
+}
+
+/*** BuildTitleBar
+**
+** Synopsis:
+** void = BuildTitleBar(lpbTitleBar, cb)
+**
+** Entry:
+** lpbTitleBar - Buffer to place the title bar string into
+** cb - count of bytes for the buffer
+**
+** Returns:
+** Nothing
+**
+** Description:
+** This function will constuct the title bar for the frame window.
+** The values in the variable TitleBar are used to contruct the title
+** bar string.
+*/
+
+void PASCAL BuildTitleBar(LPSTR TitleBarStr, UINT MaxLen)
+{
+ char szBuffer[255];
+ char szFilePath[_MAX_PATH];
+ char szExeName[_MAX_PATH];
+ PSTR CopyPtr;
+ HWND MDIGetActive;
+ int winTitle = 0;
+ int n;
+ char title[MAX_MSG_TXT];
+
+
+
+ strcpy( szBuffer, TitleBar.ProgName );
+
+ if (*szBuffer == '\0') {
+ return;
+ }
+
+ if (runDebugParams.szTitle[0]) {
+ sprintf( &szBuffer[strlen(szBuffer)], " <%s>", runDebugParams.szTitle );
+ }
+
+ // And the mode
+
+ switch (TitleBar.Mode) {
+ case TBM_RUN:
+ CopyPtr = TitleBar.ModeRun;
+ break;
+
+ case TBM_BREAK:
+ CopyPtr = TitleBar.ModeBreak;
+ break;
+
+ case TBM_WORK:
+ CopyPtr = TitleBar.ModeWork;
+ break;
+
+ default:
+ DAssert(FALSE);
+ return;
+ }
+
+ strcat(szBuffer, CopyPtr);
+
+ // Current project/debuggee
+
+ CopyPtr = NULL;
+ if (TitleBar.Mode != TBM_WORK) {
+
+ // Show current program name
+ GetExecutableFilename(szExeName, sizeof(szExeName));
+ _fullpath(szFilePath, szExeName, sizeof(szFilePath));
+ _splitpath(szFilePath, szDrive, szDir, szFName, szExt);
+ CopyPtr = szFilePath;
+
+ // Show current project, if any
+ } else if (GetExecutableFilename(szFilePath, sizeof(szFilePath))) {
+ _splitpath(szFilePath, szDrive, szDir, szFName, szExt);
+ CopyPtr = szFilePath;
+ }
+
+ if (CopyPtr) {
+ szFilePath[0] = ' ';
+ szFilePath[1] = '-';
+ szFilePath[2] = ' ';
+ _makepath(szFilePath+3, szNull, szNull, szFName, szExt);
+ strcat(szBuffer, szFilePath);
+ }
+
+ // Current editor file, if maximized NB curView is not
+ // always reliable when this is called
+
+ MDIGetActive = (HWND) SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L);
+
+ if (MDIGetActive && (GetWindowLong(MDIGetActive, GWL_STYLE) & WS_MAXIMIZE)) {
+ // Find window in Views
+
+ int view = 0;
+
+ while (view < MAX_VIEWS) {
+ if ((Views[view].Doc != -1) &&
+ (Views[view].hwndFrame == MDIGetActive)) {
+ break;
+ }
+
+ view++;
+ }
+
+ if (view < MAX_VIEWS) {
+ size_t len;
+
+ if (CopyPtr) {
+ // Already have the project file in title
+
+ szFilePath[0] = ' ';
+ szFilePath[1] = '<';
+ _itoa(view+1, szFilePath + 2, 10);
+ } else {
+ // File on his own
+
+ szFilePath[0] = ' ';
+ szFilePath[1] = '-';
+ szFilePath[2] = ' ';
+ szFilePath[3] = '<';
+ _itoa(view+1, szFilePath + 4, 10);
+ }
+
+ len = strlen(szFilePath);
+ szFilePath[len] = '>';
+ szFilePath[len+1] = ' ';
+
+
+ if (Views[view].Doc >= 0) {
+
+ _splitpath(Docs[Views[view].Doc].FileName,
+ szDrive, szDir, szFName, szExt);
+ _makepath(szFilePath+len+2, szNull, szNull, szFName, szExt);
+ strcat(szBuffer, szFilePath);
+
+ } else {
+
+ szFilePath[len+2] = '\0';
+ strcat(szBuffer, szFilePath);
+
+ switch( abs(Views[view].Doc) ) {
+ case DISASM_WIN: winTitle = SYS_DisasmWin_Title; break;
+ case MEMORY_WIN: winTitle = SYS_MemoryWin_Title; break;
+ case LOCALS_WIN: winTitle = SYS_LocalsWin_Title; break;
+ case WATCH_WIN: winTitle = SYS_WatchWin_Title; break;
+ case CPU_WIN: winTitle = SYS_CpuWin_Title; break;
+ case FLOAT_WIN: winTitle = SYS_FloatWin_Title; break;
+ case CALLS_WIN: winTitle = SYS_CallsWin_Title; break;
+ }
+
+ if (winTitle) {
+ Dbg(LoadString( hInst, winTitle, title, MAX_MSG_TXT ));
+ for (CopyPtr=&szBuffer[strlen(szBuffer)],n=0; n<(int)strlen(title); n++) {
+ if (title[n] != '&') {
+ *CopyPtr++ = title[n];
+ }
+ }
+ *CopyPtr = '\0';
+
+ if (abs(Views[view].Doc) == MEMORY_WIN) {
+ strcat ( szBuffer, " (" );
+ strcat ( szBuffer, TempMemWinDesc.szAddress );
+ strcat ( szBuffer, ")" );
+ }
+ }
+ }
+ }
+ }
+
+ // Finally copy over to passed buffer
+
+ MaxLen = min(strlen(szBuffer), MaxLen-1);
+ _fmemcpy(TitleBarStr, szBuffer, MaxLen);
+ TitleBarStr[MaxLen] = '\0';
+ return;
+} /* BuildTitleBar() */
+
+
+/****************************************************************************
+
+ FUNCTION: UpdateTitleBar
+
+ PURPOSE: Refresh the title bar
+
+****************************************************************************/
+void PASCAL UpdateTitleBar(
+ TITLEBARMODE Mode,
+ BOOL Repaint)
+{
+ BOOL SetTheText;
+
+ // Always reset the TimerMode
+ TitleBar.TimerMode = -1;
+
+ SetTheText = (Repaint || ((Mode != -1) && (TitleBar.Mode != Mode)));
+
+ if (Mode != -1)
+ {
+ TitleBar.Mode = Mode;
+ }
+
+ if (SetTheText)
+ {
+ // NB WM_SETTEXT handles all title bar builds
+ SendMessage(hwndFrame, WM_SETTEXT, 0, (LONG)(LPSTR)szNull);
+ }
+}
+
+/****************************************************************************
+
+ FUNCTION: DlgEnsureTitleBar
+
+ PURPOSE: Ensure the frame is set with our title text
+ when a dialog/message box is open.
+
+ (Don't receive WM_GETTEXT's when Alt-tabbing)
+
+****************************************************************************/
+void PASCAL DlgEnsureTitleBar(
+ void)
+{
+ if (BoxCount == 0)
+ {
+ UpdateTitleBar(-1, TRUE);
+ }
+}
+
+/****************************************************************************
+
+ FUNCTION: TimedUpdateTitleBar
+
+ PURPOSE: Refresh the title bar - called from the timer
+
+****************************************************************************/
+void PASCAL TimedUpdateTitleBar(
+ TITLEBARMODE Mode,
+ BOOL Repaint)
+{
+ // Charge the timer version of the title bar mode
+ TitleBar.TimerMode = Mode;
+
+ if (SetTimer(hwndFrame, TITLEBARTIMERID, TITLEBARTIMER, (TIMERPROC)NULL) == 0)
+ {
+ // No timers available so call UpdateTitleBar directly
+ UpdateTitleBar(Mode, Repaint);
+ }
+}
+
+int FAR PASCAL ConvertPosX(
+ int x)
+{
+ register int i = 0;
+ register int j = 0;
+ int len = pcl->Length - LHD;
+
+ while (i < x) {
+ if (i >= len) {
+ j += (x - len);
+ break;
+ }
+#ifdef DBCS
+ if (IsDBCSLeadByte((BYTE)pcl->Text[i])) {
+ j += 2;
+ i++;
+ } else
+#endif
+ if (pcl->Text[i] == TAB)
+ j += tabSize - (j % tabSize);
+ else
+ j++;
+ i++;
+ }
+
+ DAssert(j <= MAX_USER_LINE);
+ return j;
+}
+
+
+void FAR PASCAL FlushKeyboard(
+ void)
+{
+ MSG msg;
+
+ //Flush keyboard buffer
+ while (!TerminatedApp && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)
+ && (msg.message != WM_KEYDOWN || msg.message != WM_CHAR))
+ ProcessQCQPMessage(&msg);
+}
+
+
+
+LPSTR
+AllocateMultiString(
+ DWORD Length
+ )
+/*++
+
+Routine Description:
+
+ Allocates A Multistring
+
+Arguments:
+
+ Length - Supplies the length of the multistring
+
+Return Value:
+
+ LPSTR - String
+
+--*/
+{
+ return (LPSTR)malloc( Length );
+}
+
+
+
+BOOLEAN
+DeallocateMultiString(
+ LPSTR String
+ )
+/*++
+
+Routine Description:
+
+ Deallocates A Multistring
+
+Arguments:
+
+ String - Supplies the multistring
+
+Return Value:
+
+ LPSTR - String
+
+--*/
+{
+ free( String );
+ return TRUE;
+}
+
+
+
+
+BOOLEAN
+AddToMultiString(
+ LPSTR *String,
+ DWORD *Length,
+ LPSTR NewString
+ )
+/*++
+
+Routine Description:
+
+ Adds a string to a multistring
+
+Arguments:
+
+ String - Supplies the multistring
+ Length - Supplies the length of the multistring
+ NewString - Supplies the string to be added
+
+Return Value:
+
+ BOOLEAN - TRUE if string added
+
+--*/
+{
+ LPSTR Str = *String;
+ DWORD CurrentLength = *Length;
+ DWORD ThisLength = strlen( NewString ) + 1;
+ BOOLEAN Ok = FALSE;
+ LPSTR Tmp;
+
+ if (Tmp = (LPSTR)realloc( Str, CurrentLength + ThisLength ) ) {
+
+ Str = Tmp;
+ strcpy(Str+CurrentLength, NewString);
+ CurrentLength += ThisLength;
+
+ *String = Str;
+ *Length = CurrentLength;
+
+ Ok = TRUE;
+ }
+
+ return Ok;
+}
+
+
+
+LPSTR
+GetNextStringFromMultiString(
+ LPSTR String,
+ DWORD Length,
+ DWORD *Next
+ )
+/*++
+
+Routine Description:
+
+ Iterates thru the strings of a multistring
+
+Arguments:
+
+ String - Supplies the multistring
+ Length - Supplies the length of the multistring
+ Next - Supplies next index
+
+Return Value:
+
+ LPSTR - Next string, NULL if end.
+
+--*/
+{
+ LPSTR Str = NULL;
+
+ if ( *Next < Length ) {
+
+ Str = String + *Next;
+ *Next += strlen( Str ) + 1;
+ }
+
+ return Str;
+}
+
+
+
+VOID
+GetBaseName (
+ LPSTR Path,
+ LPSTR Base
+ )
+/*++
+
+Routine Description:
+
+ Given a Path, determines the base portion of the name, i.e.
+ the file name without the extension.
+
+Arguments:
+
+ Path - Supplies path
+ Base - Supplies buffer to put base
+
+Return Value:
+
+ None
+
+--*/
+{
+ LPSTR p;
+
+ if ( Base ) {
+
+ if ( Path ) {
+ p = Path + strlen( Path );
+#ifdef DBCS
+ while (p > Path) {
+ p = CharPrev(Path, p);
+ if (*p == '\\' || *p == ':') {
+ p++;
+ break;
+ }
+ }
+#else
+ while ( (p >= Path) && (*p != '\\') && (*p != ':')) {
+ p--;
+ }
+ p++;
+#endif
+
+ strcpy( Base, p);
+
+ p = Base;
+ while ( (*p != '.') && (*p != '\0') ) {
+#ifdef DBCS
+ p = CharNext(p);
+#else
+ p++;
+#endif
+ }
+
+ } else {
+ p = Base;
+ }
+
+ *p = '\0';
+ }
+}
+
+
+
+void
+HashBfr(
+ LPSTR lps,
+ int nSize
+ )
+{
+ int i;
+ for (i = 0; i < nSize; i++) {
+ *lps++ += (i & 0xff);
+ }
+}
+
+static
+DibNumColors (LPVOID pv)
+{
+ int bits;
+ LPBITMAPINFOHEADER lpbi;
+ LPBITMAPCOREHEADER lpbc;
+
+ lpbi = ((LPBITMAPINFOHEADER)pv);
+ lpbc = ((LPBITMAPCOREHEADER)pv);
+
+ /*
+ * With the BITMAPINFO format headers, the size of the palette
+ * is in biClrUsed, whereas in the BITMAPCORE - style headers,
+ * it is dependent on the bits per pixel ( = 2 raised to the
+ * power of bits/pixel).
+ */
+
+ if (lpbi->biSize == sizeof(BITMAPCOREHEADER)){
+ bits = lpbc->bcBitCount;
+ } else {
+ if (lpbi->biClrUsed != 0) {
+ return (WORD)lpbi->biClrUsed;
+ }
+ bits = lpbi->biBitCount;
+ }
+
+ switch (bits){
+ case 1:
+ return 2;
+ case 4:
+ return 16;
+ case 8:
+ return 256;
+ default:
+ /* A 24 bitcount DIB has no color table */
+ return 0;
+ }
+}
+
+static
+PaletteSize (LPVOID pv)
+{
+ LPBITMAPINFOHEADER lpbi;
+ int NumColors;
+
+ lpbi = (LPBITMAPINFOHEADER)pv;
+ NumColors = DibNumColors(lpbi);
+
+ if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) {
+ return NumColors * sizeof(RGBTRIPLE);
+ } else {
+ return NumColors * sizeof(RGBQUAD);
+ }
+}
+
+
+HPALETTE
+CreateBIPalette (
+ LPBITMAPINFOHEADER lpbi
+ )
+{
+ LOGPALETTE *pPal;
+ HPALETTE hpal = NULL;
+ UINT nNumColors;
+ BYTE red;
+ BYTE green;
+ BYTE blue;
+ int i;
+ RGBQUAD *pRgb;
+
+ if (!lpbi) {
+ return NULL;
+ }
+
+ if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) {
+ return NULL;
+ }
+
+ /* Get a pointer to the color table and the number of colors in it */
+ pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (UINT)lpbi->biSize);
+ nNumColors = DibNumColors(lpbi);
+
+ if (nNumColors) {
+ /* Allocate for the logical palette structure */
+ pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE)
+ + nNumColors * sizeof(PALETTEENTRY));
+ if (!pPal) {
+ return NULL;
+ }
+
+ pPal->palNumEntries = nNumColors;
+ pPal->palVersion = 0x300;
+
+ /* Fill in the palette entries from the DIB color table and
+ * create a logical color palette.
+ */
+ for (i = 0; (unsigned)i < nNumColors; i++){
+ pPal->palPalEntry[i].peRed = pRgb[i].rgbRed;
+ pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
+ pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue;
+ pPal->palPalEntry[i].peFlags = (BYTE)0;
+ }
+ hpal = CreatePalette(pPal);
+ LocalFree((HANDLE)pPal);
+
+ } else if (lpbi->biBitCount == 24) {
+
+ /* A 24 bitcount DIB has no color table entries so, set the number of
+ * to the maximum value (256).
+ */
+ nNumColors = 256;
+ pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE)
+ + nNumColors * sizeof(PALETTEENTRY));
+ if (!pPal) {
+ return NULL;
+ }
+
+ pPal->palNumEntries = nNumColors;
+ pPal->palVersion = 0x300;
+
+ red = green = blue = 0;
+
+ /* Generate 256 (= 8*8*4) RGB combinations to fill the palette
+ * entries.
+ */
+ for (i = 0; (unsigned)i < pPal->palNumEntries; i++){
+ pPal->palPalEntry[i].peRed = red;
+ pPal->palPalEntry[i].peGreen = green;
+ pPal->palPalEntry[i].peBlue = blue;
+ pPal->palPalEntry[i].peFlags = (BYTE)0;
+
+ if (!(red += 32))
+ if (!(green += 32)) {
+ blue += 64;
+ }
+ }
+
+ // make sure WHITE is in the palette! ACT
+ pPal->palPalEntry[--i].peRed =
+ pPal->palPalEntry[i].peGreen =
+ pPal->palPalEntry[i].peBlue = 0xFF;
+
+ hpal = CreatePalette(pPal);
+ LocalFree((HANDLE)pPal);
+ }
+ return hpal;
+}
+
+
+#ifdef INTERNAL
+
+static char szEgg[] = "Egg";
+
+LRESULT APIENTRY
+MDIEggWndProc(HWND hwnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ LPBITMAPFILEHEADER lpbf;
+ LPBITMAPINFOHEADER lpbi;
+ HRSRC hRes;
+ HANDLE hPict;
+ HGDIOBJ hgdiobj;
+ HFONT hFont;
+ LPSTR lps;
+ PALETTEENTRY ape[16];
+ HBRUSH ahbr[16];
+ PAINTSTRUCT ps;
+ HPALETTE hPalT;
+ int i;
+
+#define SCROLLBITS 5
+#define NLIGHTS 2
+#define TICKS 100
+#define PAUSETIME 10
+
+ static char szWas[] = {
+ 'I' - 0,'s' - 1,' ' - 2,'b' - 3,'r' - 4,'o' - 5,'u' - 6, 'g' - 7,
+ 'h' - 8,'t' - 9,' ' - 10,'t' - 11,'o' - 12,' ' - 13,'y' - 14, 'o' - 15,
+ 'u' - 16,' ' - 17,'b' - 18,'y' - 19,'.' - 20,'.' - 21,'.' - 22,
+ 0};
+ static HDC hdc;
+ static COLORREF crBk;
+ static int cxWnd;
+ static int cyWnd;
+
+ static HDC hdcPict;
+ static HBITMAP hbmPict;
+ static HPALETTE hPalPict;
+ static HPALETTE hPalOld;
+ static int cxPict;
+ static int cyPict;
+
+ static int nPhase;
+
+ static int idxPict;
+ static RECT rcScroll;
+ static int cxScroll;
+ static int cyScroll;
+ static RECT rcText;
+ static int nppi;
+ static BOOL fMono;
+
+ static HDC hdcHLights;
+ static HDC hdcVLights;
+ static HBITMAP hbmHLights;
+ static HBITMAP hbmVLights;
+ static HBITMAP hbmHLtmp;
+ static HBITMAP hbmVLtmp;
+ static int cxLights = 8;
+ static int nTime;
+ static int nDelay;
+ static int nCycle;
+
+
+ switch (message) {
+ case WM_CREATE:
+
+ hdc = GetDC(hwnd);
+
+ nppi = GetDeviceCaps(hdc, LOGPIXELSX);
+ crBk = GetBkColor(hdc);
+
+ // get picture bitmap
+
+ hRes = FindResource(NULL, szEgg, szEgg);
+ hPict = LoadResource(NULL, hRes);
+ lpbf = LockResource(hPict);
+ HashBfr((LPSTR)lpbf, SizeofResource(NULL, hRes));
+
+ lpbi = (LPBITMAPINFOHEADER)(((LPSTR)lpbf) + sizeof(BITMAPFILEHEADER));
+
+ // now lpbi is a DIB.
+
+ cxPict = lpbi->biWidth;
+ cyPict = lpbi->biHeight;
+
+ fMono = (DibNumColors(lpbi) == 2);
+
+ // if there aren't enough colors in the display driver,
+ // make a halftone version of the bitmap
+
+ hdcPict = CreateCompatibleDC(hdc);
+
+ if ( ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+ && (GetDeviceCaps(hdc, SIZEPALETTE) >= 64))
+ || (GetDeviceCaps(hdc, BITSPIXEL)
+ * GetDeviceCaps(hdc, PLANES)
+ >= 8) ) {
+
+
+ hPalPict = CreateBIPalette(lpbi);
+ hPalOld = SelectPalette(hdc, hPalPict, 0);
+ RealizePalette(hdc);
+
+ hbmPict = CreateDIBitmap(hdc,
+ lpbi,
+ CBM_INIT,
+ (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
+ (LPBITMAPINFO)lpbi,
+ DIB_RGB_COLORS);
+
+ SelectPalette(hdcPict, hPalPict, 0);
+ SelectObject(hdcPict, hbmPict);
+
+ } else {
+
+ hbmPict = CreateCompatibleBitmap(hdc,
+ lpbi->biWidth,
+ lpbi->biHeight);
+ SelectObject(hdcPict, hbmPict);
+
+ hPalPict = CreateHalftonePalette(hdc);
+ SelectPalette(hdcPict, hPalPict, 0);
+ RealizePalette(hdcPict);
+
+ SetStretchBltMode(hdcPict, HALFTONE);
+
+ StretchDIBits(hdcPict,
+ 0, 0, lpbi->biWidth, lpbi->biHeight,
+ 0, 0, lpbi->biWidth, lpbi->biHeight,
+ (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
+ (LPBITMAPINFO)lpbi,
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ DeleteObject(hPalPict);
+ hPalPict = 0;
+ }
+
+ UnlockResource(hPict);
+
+
+ // make light DC's
+
+ hdcHLights = CreateCompatibleDC(hdc);
+ hdcVLights = CreateCompatibleDC(hdc);
+
+ return 0;
+
+ case WM_DESTROY:
+
+ KillTimer(hwnd, 1);
+ DeleteDC(hdcPict);
+ DeleteObject(hbmPict);
+ DeleteDC(hdcHLights);
+ DeleteDC(hdcVLights);
+ if (hbmHLights) {
+ DeleteObject(hbmHLights);
+ hbmHLights = NULL;
+ }
+ if (hbmVLights) {
+ DeleteObject(hbmVLights);
+ hbmVLights = NULL;
+ }
+ SetBkColor(hdc, crBk);
+
+ if (hPalOld) {
+ SelectPalette(hdc, hPalOld, 0);
+ RealizePalette(hdc);
+ }
+ ReleaseDC(hwnd, hdc);
+
+ break;
+
+ case WM_CLOSE:
+ break;
+
+ case WM_PALETTECHANGED:
+ if (hwnd == (HWND)wParam) {
+ return 0L;
+ }
+
+ case WM_QUERYNEWPALETTE:
+ if (!hPalPict || IsIconic(hwnd)) {
+ return 0L;
+ }
+ hPalT = SelectPalette(hdc, hPalPict, 0);
+ i = RealizePalette(hdc);
+ SelectPalette(hdc, hPalT, 0);
+
+ return i;
+
+
+ case WM_SIZE:
+
+ // calc sizes
+
+ cxWnd = LOWORD(lParam);
+ cyWnd = HIWORD(lParam);
+ rcScroll.left = 2 * cxLights;
+ rcScroll.right = cxWnd - 2 * cxLights + 1;
+ if (cyPict > cyWnd / 2) {
+ rcScroll.top = cyWnd / 2 - 2 * cxLights;
+ rcScroll.bottom = cyWnd + 1 - 2 * cxLights;
+ } else {
+ rcScroll.top = (cyWnd + cyWnd/2 - cyPict) / 2 - 2 * cxLights;
+ rcScroll.bottom = rcScroll.top + cyPict;
+ }
+
+ cxScroll = rcScroll.right - rcScroll.left;
+ cyScroll = rcScroll.bottom - rcScroll.top;
+
+ SetBkColor(hdc, crBk);
+
+ // create lights
+
+ if (hbmHLights) {
+ DeleteObject(SelectObject(hdcHLights, hbmHLtmp));
+ }
+ if (hbmVLights) {
+ DeleteObject(SelectObject(hdcVLights, hbmVLtmp));
+ }
+ hbmHLights = CreateCompatibleBitmap(hdc, cxWnd+16*cxLights, cxLights);
+ hbmHLtmp = SelectObject(hdcHLights, hbmHLights);
+ hbmVLights = CreateCompatibleBitmap(hdc, cxLights, cyWnd+16*cxLights);
+ hbmVLtmp = SelectObject(hdcVLights, hbmVLights);
+
+ i = GetSystemPaletteEntries(hdc, 0, 0, NULL);
+ GetSystemPaletteEntries(hdc, 0, 8, ape);
+ GetSystemPaletteEntries(hdc, i-9, 8, ape+8);
+
+ for (i = 0; i < 16; i++) {
+ ahbr[i] = CreateSolidBrush(RGB(ape[i].peRed, ape[i].peGreen, ape[i].peBlue));
+ }
+
+ for (i = 0; i < cxWnd + 16*cxLights; i += cxLights) {
+ SelectObject(hdcHLights, ahbr[ (i / cxLights) % 16 ]);
+ PatBlt(hdcHLights, i, 0, cxLights, cxLights, PATCOPY);
+ }
+
+ for (i = 0; i < cyWnd + 16*cxLights; i += cxLights) {
+ SelectObject(hdcVLights, ahbr[ (i / cxLights) % 16 ]);
+ PatBlt(hdcVLights, 0, i, cxLights, cxLights, PATCOPY);
+ }
+
+ for (i = 0; i < 16; i++) {
+ DeleteObject(ahbr[i]);
+ }
+
+
+ // start machine
+
+ nPhase = 0;
+ nTime = 0;
+ nCycle = 0;
+ idxPict = 0;
+
+ SetTimer(hwnd, 1, TICKS, NULL);
+
+ break;
+
+
+ case WM_PAINT:
+
+ BeginPaint(hwnd, &ps);
+
+ SetBkColor(hdc, crBk);
+
+ if (nPhase > 0) {
+
+ // phase 0 text
+
+ rcText.left = rcScroll.left;
+ rcText.top = cxLights;
+ rcText.right = rcText.left + cxScroll;
+ rcText.bottom = rcText.top + cyScroll/2;
+
+ hFont = CreateFont((4 * cyWnd * 72)/(5 * 4 * nppi), 0, 0, 0,
+ FW_DONTCARE, TRUE, FALSE, FALSE,
+ ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE | 0x04,
+ "Lucida Handwriting");
+ hgdiobj = SelectObject(hdc, hFont);
+ DrawText(hdc, "WinDBG", 6, &rcText,
+ DT_CENTER | DT_NOCLIP | DT_SINGLELINE | DT_VCENTER);
+ DeleteObject(SelectObject(hdc, hgdiobj));
+
+ }
+
+ if (nPhase > 2) {
+
+ // phase 2 text
+
+ rcText.top = rcText.bottom;
+ rcText.bottom += cyScroll/2;
+
+ lps = malloc(sizeof(szWas));
+ memcpy(lps, szWas, sizeof(szWas));
+ HashBfr(lps, sizeof(szWas)-1);
+ hFont = CreateFont((3 * cyWnd * 72)/(5 * 4 * nppi), 0, 0, 0,
+ FW_DONTCARE, TRUE, FALSE, FALSE,
+ ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE | 0x04,
+ "Lucida Handwriting");
+ hgdiobj = SelectObject(hdc, hFont);
+ DrawText(hdc, lps, strlen(lps), &rcText,
+ DT_CENTER | DT_NOCLIP | DT_SINGLELINE | DT_TOP);
+ DeleteObject(SelectObject(hdc, hgdiobj));
+ free(lps);
+
+ }
+
+ if (fMono) {
+ SetBkColor(hdc, RGB(0,0,0));
+ }
+
+ EndPaint(hwnd, &ps);
+ return 0;
+
+
+ case WM_TIMER:
+
+
+ // move the lights:
+
+ if ((nTime++ % NLIGHTS) == 0) {
+ BitBlt(hdc, 0, 0, cxWnd - cxLights, cxLights,
+ hdcHLights, nCycle * cxLights, 0, SRCCOPY);
+ BitBlt(hdc, cxLights, cyWnd-cxLights, cxWnd - cxLights, cxLights,
+ hdcHLights, (16 - nCycle) * cxLights, 0, SRCCOPY);
+ BitBlt(hdc, cxWnd - cxLights, 0, cxLights, cyWnd - cxLights,
+ hdcVLights, 0, nCycle * cxLights, SRCCOPY);
+ BitBlt(hdc, 0, cxLights, cxLights, cyWnd - cxLights,
+ hdcVLights, 0, (16 - nCycle) * cxLights, SRCCOPY);
+ nCycle = (nCycle + 1) % 16;
+ }
+
+ switch (nPhase) {
+
+ case 0: // text drawing
+
+ nDelay = nTime;
+ nPhase++;
+ InvalidateRect(hwnd, NULL, FALSE);
+ break;
+
+ case 1:
+
+ if (nTime > nDelay + PAUSETIME) {
+ nPhase++;
+ }
+ break;
+
+ case 2: // more text
+
+ nDelay = nTime;
+ nPhase++;
+ InvalidateRect(hwnd, NULL, FALSE);
+ break;
+
+ case 3: // wait...
+ if (nTime > nDelay + 2*PAUSETIME) {
+ nPhase++;
+ }
+ break;
+
+ case 4: // pictures
+
+ BitBlt(hdc,
+ rcScroll.left, rcScroll.top,
+ cxScroll, cyScroll,
+ hdcPict,
+ idxPict - cxScroll, 0,
+ SRCCOPY);
+
+ idxPict += SCROLLBITS;
+
+ if (idxPict >= cxPict) {
+ idxPict = 0;
+ nPhase++;
+ }
+ break;
+
+ case 5:
+
+ if (idxPict < cxScroll) {
+ // blt right edge of bmp to left of window
+ BitBlt(hdc,
+ rcScroll.left, rcScroll.top,
+ cxScroll - idxPict, cyScroll,
+ hdcPict,
+ cxPict - cxScroll + idxPict, 0,
+ SRCCOPY);
+ // blt left edge of bmp to right of window
+ BitBlt(hdc,
+ rcScroll.left + cxScroll - idxPict, rcScroll.top,
+ idxPict, cyScroll,
+ hdcPict,
+ 0, 0,
+ SRCCOPY);
+ } else {
+ BitBlt(hdc, rcScroll.left, rcScroll.top,
+ cxScroll, cyScroll,
+ hdcPict,
+ idxPict - cxScroll, 0,
+ SRCCOPY);
+ }
+
+ idxPict += SCROLLBITS;
+ if (idxPict >= cxPict) {
+ idxPict = 0;
+ }
+
+ break;
+
+ }
+
+ return 0;
+
+ }
+
+ return DefMDIChildProc(hwnd, message, wParam, lParam);
+}
+
+void
+Egg(
+ void
+ )
+{
+ // Create an mdi child, maximized, on top.
+ extern HWND hwndMDIClient;
+ static BOOL fReg = FALSE;
+ WNDCLASS wc;
+ HWND hwndEgg;
+ DWORD dwStyle = WS_CAPTION | WS_CHILD | WS_VISIBLE;
+ char szC[8];
+ szC[0]='C'; szC[1]='r'; szC[2]='e'; szC[3]='d'; szC[4]='i';
+ szC[5]='t'; szC[6]='s'; szC[7]=0;
+
+ if (!fReg) {
+ fReg = TRUE;
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = MDIEggWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = NULL;
+ wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szEgg;
+
+ RegisterClass(&wc);
+ }
+
+ hwndEgg = CreateMDIWindow(szEgg, szC, dwStyle,
+ 0, 0, 0, 0, hwndMDIClient, NULL, 0);
+
+}
+#endif
+
diff --git a/private/windbg/windbg/vib.c b/private/windbg/windbg/vib.c
new file mode 100644
index 000000000..a4b666a3b
--- /dev/null
+++ b/private/windbg/windbg/vib.c
@@ -0,0 +1,1894 @@
+/*++
+
+
+
+Copyright 1992 Microsoft Corporation
+
+Module Name:
+
+ vib.c
+
+Abstract:
+
+ This module contains the VIB (Variable Information Block) support
+ routines used by the watch and local windows.
+
+Author:
+
+ William J. Heaton (v-willhe) 20-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+typedef struct {
+ USHORT cb;
+ LPVOID lpv;
+} MEMLINK, * PTRMEMLINK;
+
+#define NAMES_BUFFER 2048
+#define BUFFERMAX 1024
+
+//
+// Global Storage (PROGRAM)
+//
+
+extern CXF CxfIp;
+
+//
+// Global Storage (FILE)
+//
+
+
+char szBuffer[BUFFERMAX+1];
+
+//
+// Prototypes (LOCAL)
+//
+
+PTRCIF PASCAL FTGetCif( VOID );
+VOID PASCAL FTFreeVib( PTRVIB );
+VOID PASCAL FTFreeVibChildren( PTRVIB );
+VOID PASCAL FTFreeAllCif( PTRCIF );
+LTS PASCAL FTExpandVib( PTRVIB pvib );
+VOID PASCAL FTInvalidateVib( PTRVIB pvib);
+VOID PASCAL FTResetVib( PTRVIB pvib);
+BOOL PASCAL FTSetupWoj( PTRVIB pvib, PSTR pName, UINT cbSize);
+
+
+/*** FTMakeWatchEntry
+*
+* Purpose: To make a watchentry
+*
+* Input:
+* ppvib - A pointer to a vib pointer of where to place the new vib
+* pvit - The vit tree that the watchentry is to be added to.
+* szExpStr- A string containing the expression
+*
+* Output:
+* Returns FALSE is ok, TRUE if errors
+*
+* Exceptions:
+*
+* Notes:
+*
+*/
+int PASCAL FTMakeWatchEntry ( void *ppvibVoid, void *pvit, char *szExpStr)
+{
+ EESTATUS Err;
+ UINT cbszExpStr;
+ char * pch;
+ UINT iLast;
+
+ PTRVIB * ppvib = ppvibVoid;
+
+ // get a new vib
+
+ if( !(*ppvib = PvibAlloc ( NULL, (PTRVIB) pvit )) ) {
+ FTError ( OUTOFMEMORY );
+ return TRUE;
+ }
+
+ // take out leading and trailing spaces
+
+ while( *szExpStr == ' ' ) szExpStr++;
+ if ( !*szExpStr ) return TRUE;
+#ifdef DBCS
+ pch = szExpStr + strlen(szExpStr);
+ while (pch > szExpStr) {
+ if (*(pch = CharPrev(szExpStr, pch)) != ' ') {
+ break;
+ }
+ }
+ pch += (IsDBCSLeadByte(*pch) ? 2 : 1);
+#else
+ pch = szExpStr + strlen(szExpStr) - 1;
+ while ( *pch == ' ' ) pch--;
+ pch++;
+#endif
+ strcpy(szBuffer,szExpStr);
+
+ // do a parse
+ if( (Err = EEParse(szBuffer, radix, fCaseSensitive, &(*ppvib)->hTMBd, &iLast)) ) {
+// (*ppvib) = (PTRVIB)NULL;
+// return(TRUE);
+ }
+
+
+ // Setup the Woj
+
+ cbszExpStr = pch - szExpStr;
+ if ( !FTSetupWoj( *ppvib, szExpStr, cbszExpStr) ) {
+ (*ppvib) = (PTRVIB) NULL;
+ FTError ( OUTOFMEMORY );
+ return TRUE;
+ }
+
+ (*ppvib)->vibPtr = vibWatch;
+
+ return FALSE;
+} /* WTMakeWatchEntry() */
+
+/*** FTSetupWoj
+*
+* Purpose: Add a Woj (Watch Object?) to a vib
+*
+* Input:
+* pvib - Pointer to the vib
+* pName - Pointer to the Name
+* cbSize - Size of Name
+*
+* Output:
+* TRUE/FALSE if memory alloc failed
+*
+* Exceptions:
+*
+* Notes:
+*
+*/
+
+BOOL PASCAL FTSetupWoj( PTRVIB pvib, PSTR pName, UINT cbSize)
+{
+ // If we already have one, lose it
+
+ if ( pvib->pwoj ) {
+ free( pvib->pwoj );
+ }
+
+ // Allocate the Woj
+
+ pvib->pwoj = malloc( sizeof(WOJ) + cbSize + 1 );
+ if ( pvib->pwoj == NULL ) return(FALSE);
+
+ // copy over the string
+
+ strncpy ( pvib->pwoj->szExpStr, pName, cbSize);
+ pvib->pwoj->szExpStr[cbSize] = '\0';
+
+ // Fill out the other info
+
+ pvib->pwoj->iFormSpec = (WORD)cbSize;
+ pvib->pwoj->ErrNbr = 0;
+ pvib->pwoj->cbLen = (unsigned char)cbSize;
+
+ return(TRUE);
+}
+
+/*** FTVerify
+ *
+ * Purpose: To verify the watch tree
+ *
+ * Input:
+ * pcxf - A pointer to the current CXF
+ * pvib - A pointer to the vib to verify
+ *
+ * Output:
+ * Returns:
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+
+BOOL PASCAL FTVerify ( PCXF pcxf, PTRVIB pvib )
+{
+ EEPDTYP ExpTyp;
+ BOOL fBind = FALSE;
+ HTYPE hType;
+ HTI hti;
+ RI rti = {0};
+ PTI pti;
+ BOOL fStatus = FALSE;
+
+ /*
+ * If we're in a function evaluation get out fast
+ */
+
+ if ( (LptdCur != NULL) && (LptdCur->fInFuncEval)) {
+ return(fStatus);
+ }
+
+ /*
+ * only while the Variable Info Block is valid
+ */
+
+ for (; pvib; pvib = pvib->pvibSib ) {
+ /*
+ * Don't rebind this items
+ */
+
+ if (pvib->vibPtr == vibGeneric) {
+ continue;
+ }
+
+ /*
+ * rebind, the error will be displayed during evaluation
+ */
+
+ hType = EEGetHtypeFromTM (&pvib->hTMBd);
+
+ fBind = ((pvib->hprocCache != ( SHpCXTFrompCXF ( pcxf ) )->hProc) ||
+ (pvib->hblkCache != ( SHpCXTFrompCXF ( pcxf ) )->hBlk));
+
+ if ( fBind ) {
+ pvib->hprocCache = ( SHpCXTFrompCXF ( pcxf ) )->hProc;
+ pvib->hblkCache = ( SHpCXTFrompCXF ( pcxf ) )->hBlk;
+ fStatus = TRUE;
+ }
+
+ /*
+ * Make sure we can still Bind
+ */
+
+ if ( pvib->hTMBd &&
+ EEBindTM(&pvib->hTMBd, SHpCXTFrompCXF(pcxf),fBind,FALSE, FALSE) == EENOERROR ) {
+
+ /*
+ * Reset the NoBind Flag because it back in context
+ */
+
+ FTResetVib(pvib);
+
+ /*
+ * Make sure the Function Evaluation gets updated
+ */
+
+ if (EEInfoFromTM ( &pvib->hTMBd, &rti, &hti ) == EENOERROR) {
+ DAssert(hti != (HTI)NULL);
+ pti = MMLpvLockMb (hti);
+ if (pti->u.fFunction) pvib->flags.FuncEval = 1;
+ if ( pti != NULL ) MMbUnlockMb ( hti );
+ }
+
+ if (hti != (HTI) NULL) {
+ EEFreeTI(&hti);
+ }
+
+ /*
+ * Has the Type changed for a Watch or a Type
+ */
+
+ if (((pvib->vibPtr == vibWatch) || (pvib->vibPtr == vibType)) &&
+ (hType != EEGetHtypeFromTM(&pvib->hTMBd))) {
+ /*
+ * remove the rest of the tree
+ */
+
+ FTFreeAllCif(pvib->pcif);
+ pvib->pcif = NULL;
+ FTclnUpdateParent ( pvib, (1-pvib->cln) );
+ fStatus = TRUE;
+
+ /*
+ * Make sure VibPtr is reset
+ */
+
+ if ( pvib->vibPtr == vibWatch || pvib->vibPtr == vibType ) {
+ ExpTyp = EEIsExpandable(&pvib->hTMBd);
+ if ( ExpTyp == EETYPE || ExpTyp == EETYPENOTEXP ) {
+ pvib->vibPtr = vibType;
+ } else {
+ pvib->vibPtr = vibWatch;
+ }
+ }
+ }
+
+ /*
+ * Update any children
+ */
+
+ if (pvib->pcif) {
+ if ( pvib->pcif->hTMBd ) {
+ EEBindTM( &pvib->pcif->hTMBd, SHpCXTFrompCXF(pcxf),
+ fBind, FALSE, FALSE);
+ }
+
+ /*
+ * If a child had a signicant change, so did we
+ */
+
+ if ( FTVerify ( pcxf, pvib->pcif->pvibChild ) ) {
+ fStatus = TRUE;
+ }
+ }
+ }
+
+ /*
+ * Couldn't Bind, Invalidate any children
+ */
+
+ else if ( pvib->pcif ) {
+ FTInvalidateVib(pvib->pcif->pvibChild);
+ }
+ }
+ return(fStatus);
+} /* FTVerify() */
+
+/*** FTVerifyNew
+ *
+ * Purpose: Determine if a vib's result have changed since
+ * the last time a user saw it
+ *
+ * Input:
+ * pvit - A pointer to the vit
+ * oln - Item number of interest
+ *
+ * Output:
+ * Returns:
+ * TRUE/FALSE the item has changed
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+BOOL PASCAL FTVerifyNew( PTRVIT pVit, ULONG oln)
+{
+ PTRVIB pVib = FTvibGetAtLine( pVit, oln);
+ VPI i;
+
+ // No Vib, No change
+ if ( pVib == 0) return(FALSE);
+ i = pVib->vibIndex;
+
+ // Give EE a chance to fill out the result
+ FTEnsureTextExists( pVib );
+ FTGetPanelString( pVit, pVib, ID_PANE_RIGHT);
+
+ // Do we have a string at all?
+ if ( pVib->pvtext[i].pszValueP || pVib->pvtext[i].pszValueC) {
+
+ // Do we have both strings?
+ if ( pVib->pvtext[i].pszValueP && pVib->pvtext[i].pszValueC ) {
+ if ((!_strcmpi(pVib->pvtext[i].pszValueC,pVib->pvtext[i].pszValueP)) && (pVib->pvtext[i].fChanged == FALSE))
+ {
+ return(FALSE);
+ }
+ else
+ if ((!_strcmpi(pVib->pvtext[i].pszValueC,pVib->pvtext[i].pszValueP)) && (pVib->pvtext[i].fChanged == TRUE))
+ {
+ pVib->pvtext[i].fChanged = FALSE;
+ return(TRUE);
+ }
+ }
+
+ // Nope, It changed
+ pVib->pvtext[i].fChanged = TRUE;
+ return(TRUE);
+ }
+
+ // Nope, No change
+ return(FALSE);
+
+} /* FTVerifyNew() */
+
+
+/*** FTvibGetAtLine Get the vib starting at the line specified.
+ *
+ * Purpose: Given a vit, and a line, return the vib packet discribing that line.
+ *
+ * Input:
+ * pvit - A valid Variable Info block Top describing a Variable Info
+ * Block list
+ * oln - The line of interest
+ *
+ * Output:
+ * Returns
+ * pvib - A pointer to a vib that describes the requested line
+ *
+ * Exceptions:
+ *
+ * Notes: Make sure the Variable Info block Top list is valid!
+ *
+*/
+
+
+PTRVIB PASCAL FTvibGetAtLine( PTRVIT pvit, ULONG oln )
+{
+ ULONG olnCur = 0;
+ VPI vpiT = 0;
+ PTRVIB pvib;
+ uint strIndex;
+ HTI hti;
+ RI rti = {0};
+ PTI pti;
+
+ if ( pvit )
+ pvib = pvit->pvibChild;
+ else
+ return(NULL);
+
+ /*
+ * Loop through the vib tree looking for the correct vib. Do this
+ * by adding the count of lines in a pvib structure until we get
+ * to the correct vib.
+ */
+
+ while( pvib && olnCur != oln ) {
+
+ /*
+ * Is the line number we are looking for in the current vib?
+ *
+ * YES -- move to the child of this vib (expanded item)
+ * NO -- skip to the next vib in this list
+ */
+
+ if( oln < olnCur + (WORD)pvib->cln ) {
+ olnCur++;
+ vpiT = 0;
+ pvib = pvib->pcif->pvibChild; // go into the expanded item.
+ }
+
+ else { // skip this vib, go on to the next
+ olnCur += pvib->cln;
+ pvib = pvib->pvibSib;
+ }
+
+ if ( pvib == NULL ) {
+ break;
+ }
+
+
+ /*
+ * Move to the i-th element of the current vib, where i is the
+ * distance between the first line in the vib and the
+ * actual line desired.
+ *
+ * If the current vib is a vibGeneric then we need to get the
+ * i-th element in this vib.
+ * If the current vib is a vibChild -????
+ * ELSE -- no action needs to be taken -- use the current vib
+ * since it is a one line item.
+ */
+
+ if ( pvib->vibPtr == vibGeneric || pvib->vibPtr == vibChild ) {
+ HTM hTM;
+
+ if ((!pvib->pvibSib) ||
+ (oln < olnCur + pvib->vibIndex - vpiT) ) {
+
+ EESTATUS Err;
+
+ /*
+ * search for the generic vib
+ */
+
+ while( pvib->pvibSib ) {
+ pvib = pvib->pvibSib;
+ }
+
+ /*
+ * OK -- now if we have some data for this item then we
+ * can get information about it.
+ */
+
+ DAssert(pvib->hTMBd == 0);
+
+ if ( !pvib->flags.NoData ) {
+
+ // get the index and TM
+ pvib->vibIndex = (unsigned short) (vpiT + oln - olnCur);
+
+ /*
+ * Make sure the structure we are about to index into
+ * already exitsts.
+ */
+
+ FTEnsureTextExists( pvib );
+
+ /*
+ * Now see if we have already created a TM for this, if
+ * so then we can just use it.
+ */
+
+ if (pvib->pvtext[pvib->vibIndex].htm) {
+ ;
+ } else {
+ /*
+ * get the TM to expand.
+ */
+
+ if( pvib->pvibParent->pcif->hTMBd ) {
+ hTM = pvib->pvibParent->pcif->hTMBd;
+ } else {
+ hTM = pvib->pvibParent->hTMBd;
+ }
+
+ Err = EEGetChildTM ( &hTM, pvib->vibIndex,
+ &pvib->pvtext[pvib->vibIndex].htm,
+ &strIndex, fCaseSensitive, radix );
+
+ if (Err) {
+ CVExprErr ( Err, MSGGERRSTR, &hTM, NULL);
+ pvib->flags.NoBind;
+ } else {
+ if (!EEInfoFromTM(&pvib->pvtext[pvib->vibIndex].htm,
+ &rti, &hti)) {
+ DAssert(hti != (HTI) NULL);
+ pti = MMLpvLockMb( hti );
+ if (pti != NULL) {
+ if (pti->u.fFunction) {
+ pvib->flags.FuncEval = 1;
+ }
+ MMbUnlockMb( hti );
+ }
+ }
+ if (hti != (HTI) NULL) {
+ EEFreeTI(&hti);
+ }
+ }
+
+ }
+ olnCur = oln;
+ }
+ }
+ else {
+ // check out this Variable Info Block, it cannot be
+ // the generic Variable Info Block!
+ // we must advance by the preceeding blank space
+
+ olnCur += pvib->vibIndex - vpiT;
+ vpiT = pvib->vibIndex + 1;
+ }
+ }
+ }
+
+ return( pvib );
+} /* FTvibGetAtLine() */
+
+
+/*** PvibAlloc
+ *
+ * Purpose: To get a new Variable Info Block. If the list has a Variable
+ * Info Block after it, choose that as the next Variable Info Block,
+ * but don't alter the current Variable Info Block. If a new Variable
+ * Info Block must be allocated, all fields are initialized. This
+ * does not update anything in the parent!
+ *
+ * Input:
+ * pvib - A pointer to the potential next vib. This may be NULL;
+ * pvibParent - A pointer to the parent vib, This may not be NULL;
+ *
+ * Output:
+ *
+ * Returns
+ * A pointer to the next vib. The new vib will be unchanged if it
+ * already existed, otherwise it will be initialized.
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+
+PTRVIB PASCAL PvibAlloc ( PTRVIB pvib, PTRVIB pvibParent )
+{
+ if ( !pvib ) {
+ pvib = malloc( sizeof(VIB) );
+
+ if ( !( pvib ) ) {
+ return ( NULL );
+ }
+
+ memset ( pvib, 0, sizeof( VIB ) );
+ pvib->cln = 1;
+ pvib->pvibParent = pvibParent;
+ pvib->vibPtr = vibUndefined;
+
+ // if the parent has a parent, then it must not be a Variable
+ // Info block Top, get one more than the parents level
+
+ if ( pvibParent->pvibParent ) {
+ pvib->level = (unsigned char) (pvibParent->level + 1);
+ }
+ else {
+ pvib->level = 0;
+ }
+ }
+
+ return ( pvib );
+} /* PvibAlloc() */
+
+
+/*** FTvibGet
+ *
+ * Purpose: To get a new Variable Info Block. If the list has a Variable
+ * Info Block after it, choose that as the next Variable Info Block,
+ * but don't alter the current Variable Info Block. If a new Variable
+ * Info Block must be allocated, all fields are initialized. This
+ * does not update anything in the parent!
+ *
+ * Input:
+ * pvib - A pointer to the potential next vib. This may be NULL;
+ * pvibParent - A pointer to the parent vib, This may not be NULL;
+ *
+ * Output:
+ *
+ * Returns
+ * A pointer to the next vib. The new vib will be unchanged if it
+ * already existed, otherwise it will be initialized.
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+PTRVIB PASCAL FTvibGet ( PTRVIB pvib, PTRVIB pvibParent )
+{
+ if ( !pvib ) {
+ pvib = malloc( sizeof(VIB) );
+ if ( !( pvib ) ) {
+ return ( NULL );
+ }
+
+ memset ( pvib, 0, sizeof( VIB ) );
+ pvib->cln = 1;
+ pvib->pvibParent = pvibParent;
+ pvib->vibPtr = vibUndefined;
+
+ // if the parent has a parent, then it must not be a Variable
+ // Info block Top, get one more than the parents level
+
+ if ( pvibParent->pvibParent ) {
+ pvib->level = (unsigned char) (pvibParent->level + 1);
+ }
+ else {
+ pvib->level = 0;
+ }
+ }
+
+ return ( pvib );
+}
+
+
+
+
+/*** FTvibInit
+ *
+ * Purpose: To clear out an existing Variable Info Block, freeing all of
+ * its children and sibilings.
+ *
+ * Input:
+ * pvib - A pointer to the vib to be initialized
+ * pvibParent - A pointer to the parent, this may not be NULL
+ *
+ * Output:
+ * Returns pvib
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+
+PTRVIB PASCAL FTvibInit( PTRVIB pvib, PTRVIB pvibParent )
+{
+
+ // Free all of the children. Don't use FTFreeVibChildren() because it may
+ // merge this vibif it is an array
+
+ FTFreeAllCif ( pvib->pcif );
+
+ // free all remaining sibiling
+
+ FTFreeAllSib ( pvib->pvibSib );
+ pvib->pvibSib = (PTRVIB) NULL;
+
+ // reinitialize the packet
+ if ( pvib->vibPtr != vibGeneric && pvib->vibPtr != vibUndefined && pvib->hTMBd )
+ EEFreeTM (&pvib->hTMBd);
+
+ if ( pvib->pwoj ) {
+ free( pvib->pwoj );
+ pvib->pwoj = (PTRWOJ)NULL;
+ }
+
+ memset ( pvib, 0, sizeof( VIB ) );
+ pvib->cln = 1;
+ pvib->pvibParent = pvibParent;
+ pvib->vibPtr = vibUndefined;
+
+ // if the parent has a parent, then it must not be a Variable Info
+ // block Top, get one more than the parent's level
+
+ if( pvibParent->pvibParent )
+ pvib->level = (unsigned char) (pvibParent->level + 1);
+ else
+ pvib->level = 0;
+
+ return(pvib);
+
+} /* FTvibInit() */
+
+
+
+/*** FTGetCif
+ *
+ * Purpose: To allocate a full Child InFo packet.
+ *
+ * Input: NONE
+ *
+ * Output:
+ * Returns A pointer to a new Child InFo packet.
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+PTRCIF PASCAL FTGetCif( void )
+{
+ PTRCIF pcif;
+
+ if ( (pcif = malloc( sizeof(CIF) )) )
+ memset(pcif, 0, sizeof(CIF));
+
+ return ( pcif );
+
+} /* FTGetCif() */
+
+
+/*** FTFreeVib
+ *
+ * Purpose: To free a Variable Info Block and all of its associated memory
+ *
+ * Input:
+ * pvib - A pointer to the Variable Info Block that is to be freed
+ *
+ * Output:
+ * Returns .....
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+VOID PASCAL FTFreeVib ( PTRVIB pvib )
+{
+ ULONG i;
+ if ( pvib ) {
+
+ // free the TM if it is appropriate
+ //
+ // For child TMS -- this is a copy of the item in the vibGeneric
+ //
+
+ if ( pvib->vibPtr == vibChild) {
+ pvib->hTMBd = 0;
+ }
+ if ( pvib->vibPtr != vibUndefined && pvib->hTMBd ) {
+ EEFreeTM ( &pvib->hTMBd );
+ }
+
+ // Free the watch information
+ if ( pvib->pwoj )
+ free(pvib->pwoj );
+
+ // free any text strings
+ if ( pvib->cText ) {
+ for (i=0; i<pvib->cText ; i++ ) {
+
+ if ( pvib->pvtext[i].pszValueC)
+ free(pvib->pvtext[i].pszValueC);
+
+ if ( pvib->pvtext[i].pszValueP)
+ free(pvib->pvtext[i].pszValueP);
+
+ if ( pvib->pvtext[i].pszFormat)
+ free(pvib->pvtext[i].pszFormat);
+
+ if ( pvib->pvtext[i].htm) {
+ EEFreeTM(&pvib->pvtext[i].htm);
+ }
+ }
+ free(pvib->pvtext);
+ }
+
+
+ // now free the Variable Info Block itself
+
+ free(pvib);
+ }
+ return;
+} /* FTFreeVib() */
+
+
+/*** FTFreeVibChildren
+ *
+ * Purpose: Given a Variable Info Block, clear out all child structures.
+ * The pcif (Pointer to Child Info) field will be NULL on return.
+ *
+ * Input:
+ * pvib - A pointer to the Variable Info Block that is to be cleared
+ *
+ * Output:
+ * Returns .....
+ *
+ * Exceptions:
+ *
+ * Notes: If the vib is of type vibArray, the vib itself may be merged in
+ * with the genaric array vib.
+ *
+*/
+
+
+VOID PASCAL FTFreeVibChildren ( PTRVIB pvib )
+{
+ PTRVIB pvibCur;
+ VIB vibT;
+
+ // free all of its Child InFo packets
+
+ FTFreeAllCif ( pvib->pcif );
+ pvib->pcif = NULL;
+
+ // if the Variable Info Block is expanded, merge it back into the
+ // the generic element by eliminating it from the child list
+ if( pvib->vibPtr != vibChild ) return;
+
+ // search the list
+ pvibCur = &vibT;
+
+ // This should never be at level 0 of the chain,
+ // the parent should never be a Variable Info block Top
+
+ pvibCur->pvibSib = pvib->pvibParent->pcif->pvibChild;
+ while( pvibCur->pvibSib != pvib ) pvibCur = pvibCur->pvibSib;
+
+ pvibCur->pvibSib = pvib->pvibSib;
+ pvib->pvibParent->pcif->pvibChild = vibT.pvibSib;
+
+ // Don't free the hTM since it is a copy of the one being saved in
+ // the generic structure rather than a duplicate handle.
+
+ pvib->hTMBd = 0;
+// if ( pvib->hTMBd ) {
+// EEFreeTM ( &pvib->hTMBd );
+// }
+
+ FTFreeVib ( pvib );
+ return;
+} /* FTFreeVibChildren() */
+
+/*** FTFreeAllSib
+ *
+ * Purpose: Starting at the point specifed in the tree, all following children
+ * and sibilings are freed. The Variable Info Block specified is also freed.
+ *
+ * Input:
+ * pvib - The first Variable Info Block in the list to be freed.
+ *
+ * Output:
+ * Returns .....
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+
+void PASCAL FTFreeAllSib( PTRVIB pvib )
+{
+ while ( pvib ) {
+ if( pvib->pcif )FTFreeAllCif( pvib->pcif );
+
+
+ if( pvib->pvibSib ) {
+ pvib->pvibSib->pvibParent = pvib;
+ pvib = pvib->pvibSib;
+ FTFreeVib ( pvib->pvibParent );
+ }
+
+ else {
+ FTFreeVib( pvib ); // free the last vib and get out
+ break;
+ }
+ }
+ return;
+} /* FTFreeAllSib() */
+
+/*** FTFreeAllCif
+ *
+ * Purpose: To free all children blocks and the Child InFo.
+ *
+ * Input:
+ * pcif A pointer to the Child InFo.
+ *
+ * Output:
+ * Returns .....
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+*/
+
+VOID PASCAL FTFreeAllCif( PTRCIF pcif )
+{
+ if( pcif ) {
+ FTFreeAllSib ( pcif->pvibChild );
+ pcif->pvibChild = (PTRVIB) NULL;
+
+ if ( pcif->hTMBd ) EEFreeTM ( &pcif->hTMBd );
+
+ free ( pcif );
+ }
+ return;
+} /* FTFreeAllCif() */
+
+
+/*** FTExpandOne(PTRVIB pvib)
+ *
+ * Purpose:
+ * Expand all vibs at this level in the tree (All siblings)
+ *
+ *
+ * Input:
+ * pVib - Pointer to a VIB
+ *
+ * Output:
+ * None
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+VOID PASCAL FTExpandOne( PTRVIB pvib )
+{
+ while ( pvib) {
+
+ // Don't Collapse if it's already open!
+ if ( !pvib->pcif && pvib->flags.ExpandMe ) {
+ FTExpandVib(pvib);
+ }
+
+ // Now take care of the siblings
+ pvib = pvib->pvibSib;
+ }
+}
+
+
+/*** FTExpand
+ *
+ * Purpose: To expand the structure at the line pointed to by oln. oln is
+ * the offset from the start of the locals, not the start of the
+ * window.
+ *
+ * Input:
+ * pvit - A Pointer to the Variable Information Top
+ * oln - The offset from the first local
+ *
+ * Output:
+ * Returns a LTS
+ *
+ * Exceptions:
+ *
+ *
+*/
+
+
+LTS PASCAL FTExpand ( PTRVIT pvit, ULONG oln )
+{
+ PTRVIB pvib;
+
+ if ( pvit && (pvib = FTvibGetAtLine( pvit, oln)) ) {
+ return( FTExpandVib(pvib) );
+ }
+
+ return(UNABLETOEXPAND);
+}
+
+
+/*** FTExpand
+ *
+ * Purpose: To expand the structure at a particular vib.
+ *
+ * Input:
+ * PTR pvib - Pointer to a VIB
+ *
+ * Output:
+ * Returns a LTS
+ *
+ * Exceptions:
+ *
+ *
+*/
+
+LTS PASCAL FTExpandVib( PTRVIB pvib )
+{
+ EESTATUS Err;
+ HTM hTM;
+ long cChild;
+ EEPDTYP ExpTyp;
+ SHFLAG shflag;
+ uint strIndex;
+ HTI hti;
+ RI rti = {0};
+ HTM hTMParent;
+
+ //
+ // If its already expand, collasse it
+ //
+
+ if ( pvib->pcif ) {
+ FTclnUpdateParent ( pvib, (1-pvib->cln) );
+ FTFreeVibChildren ( pvib );
+ return ( OK );
+ }
+
+ //
+ // Can we Expand?
+ //
+
+ if ( pvib->flags.NoData || pvib->flags.NoBind ) {
+ return(UNABLETOEXPAND);
+ }
+
+ if (pvib->vibPtr == vibGeneric) {
+ hTMParent = pvib->pvtext[pvib->vibIndex].htm;
+ } else {
+ hTMParent = pvib->hTMBd;
+ }
+
+ if ( EEInfoFromTM ( &hTMParent, &rti, &hti ) != EENOERROR) {
+ return(UNABLETOEXPAND);
+ }
+
+ if (hti != (HTI) 0) {
+ EEFreeTI(&hti);
+ }
+ ExpTyp = EEIsExpandable ( &hTMParent );
+ if ( ExpTyp == EENOTEXP || ExpTyp == EETYPENOTEXP ) {
+ return ( UNABLETOEXPAND );
+ }
+
+ // here is the nasty, if we are currently an expandable, we don't
+ // want to update the generic vib, but rather make a new one
+
+ if( pvib->vibPtr == vibGeneric ) {
+ PTRVIB *ppvib;
+ PTRVIB pvibNew;
+
+ // get a new vib
+ if ( !(pvibNew = PvibAlloc ( NULL, pvib->pvibParent )) ) return ( OUTOFMEMORY );
+
+ // copy the generic vib
+ *pvibNew = *pvib;
+ pvibNew->cln = 1; // put in the count
+
+ // Copy over the correct hTM
+
+ pvibNew->hTMBd = pvib->pvtext[pvib->vibIndex].htm;
+
+ // put this vib in the list, this should alway be at least two down
+ // from the root vit. A sym must be in between
+
+ ppvib = &pvib->pvibParent->pcif->pvibChild;
+ pvib = *ppvib;
+ while ( pvib->pvibSib && pvib->vibIndex < pvibNew->vibIndex ) {
+ ppvib = &pvib->pvibSib;
+ pvib = pvib->pvibSib;
+ }
+
+ // fixup the link list
+ *ppvib = pvibNew;
+ pvibNew->pvibSib = pvib;
+
+ // now select this vib
+ pvib = pvibNew;
+ pvib->vibPtr = vibChild;
+ pvib->pvtext = NULL; // Make sure that Text Info isn't dup'd
+ pvib->cText = 0; // because of the copy above.
+ }
+
+ // now expand it
+ if( !(pvib->pcif = FTGetCif()) || !(pvib->pcif->pvibChild = PvibAlloc ( NULL, pvib )) ) {
+ FTFreeVibChildren( pvib );
+ return ( UNABLETOEXPAND );
+ }
+
+ // if it is a pointer and I can't dereference, get out
+
+ hTM = hTMParent;
+ if( ExpTyp == EEPOINTER &&
+ EEDereferenceTM ( &hTMParent, &hTM, &strIndex, fCaseSensitive ) != EENOERROR ) {
+
+ FTFreeVibChildren( pvib );
+ return ( UNABLETOEXPAND );
+ }
+
+ // get the count
+ Err = EEcChildrenTM ( &hTM, &cChild, &shflag );
+
+ // set up the new Variable Info Block after expansion
+ switch(ExpTyp) {
+
+ case EEAGGREGATE:
+ if ( !cChild ) {
+ pvib->pcif->pvibChild->flags.NoData;
+ cChild = 1;
+ }
+
+ case EETYPE:
+ pvib->pcif->pvibChild->vibPtr = vibGeneric;
+ break;
+
+ case EEPOINTER:
+ if( cChild ) {
+ pvib->pcif->pvibChild->vibPtr = vibGeneric;
+ pvib->pcif->hTMBd = hTM;
+ }
+
+ else {
+ pvib->pcif->pvibChild->vibPtr = vibPointer;
+ pvib->pcif->pvibChild->hTMBd = hTM;
+ cChild = 1;
+ }
+ break;
+ }
+
+ // say we are expanded, and put the expand count in the tree.
+ FTclnUpdateParent( pvib, (short) cChild );
+ pvib->flags.ExpandMe = FALSE;
+ return(OK);
+} /* FTExpand() */
+
+
+/*** FTclnUpdateParent
+ *
+ * Purpose: To Go up the tree and update all of the parent's cln fields
+ *
+ * Input:
+ * pvibParent - The first parent to update
+ * dcln - The difference to update them by
+ *
+ * Output:
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+void PASCAL FTclnUpdateParent( PTRVIB pvibParent, int dcln )
+{
+ while ( pvibParent ) { // Walk up the tree
+ pvibParent->cln += dcln;
+ pvibParent = pvibParent->pvibParent;
+ }
+} /* FTclnUpdateParent() */
+
+
+/*** FTGetVibTypeString
+ *
+ * Purpose:
+ * Get a pointer to a vib return a string that contains the
+ * text for its expansion button.
+ *
+ * Input:
+ * pVib - Pointer to the Vib
+ *
+ * Output:
+ * Returns a pointer to the String o rNULL
+ *
+ * Exceptions:
+ *
+ *
+*/
+
+PSTR PASCAL FTGetVibTypeString(PTRVIB pVib)
+{
+ EEPDTYP ExpTyp;
+
+ // If we don't have any data, return a space
+
+ if ( pVib->flags.NoData || pVib->flags.NoBind ) {
+ return( " " );
+ }
+
+ /*
+ * If EE says we can't expand, return a space
+ */
+
+ if (pVib->vibPtr == vibGeneric) {
+ ExpTyp = EEIsExpandable( &pVib->pvtext[pVib->vibIndex].htm );
+ } else {
+ ExpTyp = EEIsExpandable ( &pVib->hTMBd );
+ }
+
+ if ( (ExpTyp == EENOTEXP) || (ExpTyp == EETYPENOTEXP)) {
+ return( " " );
+
+ // If we have a child info block, we're already expanded
+
+ } else if ( pVib->pcif ) {
+ return( "-" );
+ }
+
+ // Else we are expandable
+ return( "+" );
+} /* FTGetVibTypeString() */
+
+
+
+/*** FTGetVibResultString
+ *
+ * Purpose:
+ * Get a pointer to a vib return a string that contains the
+ * text for the evaluated result.
+ *
+ * Input:
+ * pVit - Pointer to the VIT (Variable Information Top)
+ * pVib - Pointer to the VIB (Variable Information Block)
+ *
+ * Output:
+ * Returns a pointer to the String o rNULL
+ *
+ * Exceptions:
+ *
+ *
+*/
+
+PSTR PASCAL FTGetVibResultString(PTRVIT pVit, PTRVIB pVib)
+{
+ EEHSTR hValue = 0;
+ PCXF pCxf;
+ PSTR szValue;
+ EESTATUS Err;
+ PSTR pszFormat = NULL;
+ PVTEXT pvtext;
+ HTM hTM;
+
+
+ pCxf = (pVib->vibPtr == vibWatch) ? &CxfIp : &pVit->cxf;
+
+ if ( pVib->flags.NoBind) {
+ szBuffer[0] = 0;
+ return(szBuffer);
+ }
+
+ if (pVib->vibPtr == vibGeneric) {
+ hTM = pVib->pvtext[pVib->vibIndex].htm;
+ } else {
+ hTM = pVib->hTMBd;
+ }
+
+ if ( pVib->flags.NoData ) {
+ LoadString(hInst, ERR_Expclass_No_Members, szBuffer, BUFFERMAX);
+ return(szBuffer);
+ }
+
+ if ( pVib->flags.FuncEval) {
+ LoadString(hInst, ERR_No_Funcs_In_Watch, szBuffer, BUFFERMAX);
+ return(szBuffer);
+ }
+
+ // If we have a format override, make sure it passed
+ if ( pVib->pvtext) {
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+ if ( pvtext->pszFormat ) pszFormat = pvtext->pszFormat;
+ }
+
+ if ( (Err = EEvaluateTM ( &hTM, SHpFrameFrompCXF(pCxf),EEVERTICAL )) ||
+ (Err = EEGetValueFromTM ( &hTM, radix, pszFormat, &hValue)) ) {
+ CVExprErr ( Err, MSGSTRING, &hTM, szBuffer );
+ return(szBuffer);
+ }
+
+ szValue = MMLpvLockMb( (HDEP)hValue );
+ strncpy(szBuffer,szValue,BUFFERMAX);
+ MMbUnlockMb ( (HDEP)hValue );
+ EEFreeStr(hValue);
+
+ // If we have a new line in the string then terminate there
+ //pszBuffer = strchr(szBuffer,'\n');
+ //if (pszBuffer) *pszBuffer = 0;
+
+
+ return(szBuffer);
+}
+
+
+/*** FTGetVibNameString
+ *
+ * Purpose:
+ * Get a pointer to a vib return a string that contains the
+ * text for the name portion.
+ *
+ * Input:
+ * pVib - Pointer to the VIB (Variable Information Block)
+ *
+ * Output:
+ * Returns a pointer to the String o rNULL
+ *
+ * Exceptions:
+ *
+ *
+*/
+
+PSTR PASCAL FTGetVibNameString(PTRVIB pVib)
+{
+ PSTR pszBuffer = szBuffer;
+ PSTR szValue;
+ HDEP hType = 0;
+ EEHSTR hName = 0;
+ int i;
+ int len = 0;
+ EESTATUS Err;
+
+ /*
+ * put in indent
+ */
+
+
+ if ((int)pVib->level < 128) {
+ for(i=0; i<(int)pVib->level; i++) {
+ *pszBuffer++ = '|';
+ *pszBuffer++ = ' ';
+ len += 2;
+ }
+ }
+
+ /*
+ * Get the Name
+ */
+
+ switch(pVib->vibPtr) {
+ /*
+ * Case 1:
+ *
+ * This implies that the item is a real variable and we can
+ * know its name from what was typed in to the system. So
+ * get it from the typed in expression.
+ */
+
+ case vibWatch:
+ strncpy(pszBuffer,pVib->pwoj->szExpStr,BUFFERMAX-len);
+ break;
+
+ /*
+ * Get the Name from the Type info
+ */
+
+ case vibType:
+ if ((pVib->pwoj != NULL) && (pVib->pwoj->szExpStr != NULL)) {
+ strncpy(pszBuffer, pVib->pwoj->szExpStr, BUFFERMAX-len);
+ } else if ( pVib->flags.NoBind ) {
+ /*
+ * Out of Context, no info
+ */
+
+ *pszBuffer = 0;
+ } else {
+ /*
+ * Get the Type String
+ */
+
+ if (((Err = EEGetNameFromTM(&pVib->hTMBd, &hName)) != EENOERROR) ||
+ ((Err = EEGetTypeFromTM(&pVib->hTMBd, hName,
+ (PEEHSTR)&hType, TRUE) != EENOERROR))) {
+ CVExprErr ( Err, MSGSTRING, &pVib->hTMBd, szBuffer );
+ if (hName) {
+ EEFreeStr(hName);
+ }
+ if (hType) {
+ EEFreeStr(hType);
+ }
+ return(szBuffer);
+ }
+
+ /*
+ * Lock it down and copy to the woj
+ */
+
+ szValue = MMLpvLockMb ( hType );
+ strncpy(pszBuffer,szValue + sizeof(HDR_TYPE),BUFFERMAX-len);
+ MMbUnlockMb ( hType );
+ EEFreeStr ( (EEHSTR)hType );
+ }
+ break;
+
+ /*
+ * Case 3:
+ * We are doing deverivations from a base item. In this
+ * case we are hopless about getting the string correct
+ * on our own so let the EE get the string for use. It
+ * will still be wrong sometimes but mostly correct.
+ */
+
+ case vibGeneric:
+ if (pVib->flags.NoBind) {
+ /*
+ * Expression is out of context so return NULL string
+ */
+ *pszBuffer = 0;
+ } else {
+ /*
+ * Get the name from the TM
+ */
+
+ Err = EEGetNameFromTM( &pVib->pvtext[pVib->vibIndex].htm,
+ &hName );
+
+ if ( Err != EENOERROR ) {
+ CVExprErr( Err, MSGSTRING,
+ &pVib->pvtext[pVib->vibIndex].htm, szBuffer);
+ if (hName) {
+ EEFreeStr( hName );
+ }
+ return szBuffer;
+ }
+
+ szValue = MMLpvLockMb( (HDEP) hName );
+ strncpy( pszBuffer, szValue, BUFFERMAX-len );
+ pszBuffer[BUFFERMAX-len] = 0;
+ MMbUnlockMb( (HDEP) hName );
+ EEFreeStr( hName );
+ }
+ break;
+
+ /*
+ * Case 4:
+ *
+ * Get the Name from the Evaluation tree
+ */
+ default:
+ if ( pVib->flags.NoBind ) {
+ /*
+ * Out of Context, no info
+ */
+
+ *pszBuffer = 0;
+ } else {
+ /*
+ * Get the Name from the tm
+ */
+
+ if ( Err = EEGetNameFromTM ( &pVib->hTMBd, &hName) ) {
+ CVExprErr ( Err, MSGSTRING, &pVib->hTMBd, szBuffer );
+ if ( hName ) {
+ EEFreeStr(hName);
+ }
+ return(szBuffer);
+ }
+
+ szValue = MMLpvLockMb( (HDEP)hName );
+ strncpy(pszBuffer,szValue,BUFFERMAX-len);
+ pszBuffer[BUFFERMAX-len] = 0;
+ MMbUnlockMb ( (HDEP)hName );
+ EEFreeStr(hName);
+ }
+ break;
+ }
+
+ return(szBuffer);
+}
+
+/*** FTGetWatchList
+ *
+ * Purpose:
+ * Return a buffer that has a list of all the Toplevel watchs
+ * for the given vit.
+ *
+ * Input:
+ * pVit - Pointer to the Variable Information Top
+ *
+ * Output:
+ * Returns a pointer to the formatted buffer or NULL if there
+ * was an error.
+ *
+ * Exceptions:
+ *
+ * Notes:
+ * The Buffer was malloced and needs to be free'd by the caller.
+ * The first character of each line is the expansion type.
+ *
+ */
+
+
+PSTR PASCAL FTGetWatchList( PTRVIT pVit)
+{
+ PTRVIB pVib;
+ PSTR pBuffer; // Pointer to start of buffer
+ PSTR pCh; // Pointer to End of buffer
+ PSTR pName; // Pointer to next string
+ PSTR pType; // Pointer to the expansion string
+
+ ULONG Size = NAMES_BUFFER; // Size of Buffer
+ ULONG Cnt = 0; // Count of Lines
+ ULONG Len = 1; // Lenth of filled buffer
+
+
+ //
+ // If we can't get a buffer, give up
+ //
+
+ if ( !pVit || (pBuffer = malloc(NAMES_BUFFER)) == NULL) {
+ return(NULL);
+ }
+ pCh = pBuffer;
+ *pCh = 0;
+
+ //
+ // Loop through the VIT
+ //
+
+ pVib = pVit->pvibChild;
+ while ( pVib ) {
+
+ // Get the values
+
+ pName = FTGetVibNameString(pVib);
+ pType = FTGetVibTypeString(pVib);
+
+ // Make sure we fit in the buffer
+
+ if ( Len + strlen(pName) + 3 > Size ) {
+ Size += NAMES_BUFFER;
+ pBuffer = realloc(pBuffer, Size);
+ pCh = pBuffer + Len - 1 ; // Reposition to the same offset
+ }
+
+ // Copy the string and point to the end
+
+ *pCh++ = *pType;
+ strcpy(pCh, pName);
+ pCh += strlen(pName);
+
+ // Copy in the carriage return/linefeed
+
+ *pCh++ = '\r';
+ *pCh++ = '\n';
+
+ // Increment the length and get next vib
+
+ Len += strlen(pName) + 3;
+ pVib = pVib->pvibSib;
+ }
+
+ *pCh = 0;
+ return(pBuffer);
+}
+
+/*** FTSetWatchList
+ *
+ * Purpose:
+ * Restore a watch list that was generated by FTGetWatchList()
+ * for a given vit.
+ *
+ * Input:
+ * pVit - Pointer to the Variable Information Top
+ * List - Save area generated by FTGetWatchList()
+ *
+ * Output:
+ * None
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+VOID PASCAL FTSetWatchList( PTRVIT pVit, PSTR list)
+{
+ PSTR pWatch;
+ PTRVIB pVib;
+ char cType;
+
+ // While we have line with \r\n
+
+ pWatch = strtok(list, "\r\n");
+ while ( pWatch ) {
+
+#ifdef DBCS
+ if (IsDBCSLeadByte(*pWatch)) {
+ pWatch = strtok( NULL, "\r\n"); // Get the Next Watch
+ continue;
+ }
+#endif
+ cType = *pWatch++; // Get the Expansion Type
+ pVib = AddCVWatch(pVit, pWatch); // Add the Watch
+
+
+#if V-WILLHE
+ //
+ // NOTENOTE - V-Willhe If we do this we get free() areas. The
+ // vib is ok....check for corruption in
+ // FTExpandVib.
+ //
+
+ if ( pVib && cType == '-') { // If it was expanded,
+ FTExpandVib( pVib); // Make it so...
+ }
+#endif
+ pWatch = strtok( NULL, "\r\n"); // Get the Next Watch
+ }
+ return;
+}
+
+/*** FTInvalidateVib
+ *
+ * Purpose:
+ * To invalidate the entire tree starting at a given node.
+ *
+ * Input:
+ * pVib - Pointer to a VIB
+ *
+ * Output:
+ * None
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+VOID PASCAL FTInvalidateVib( PTRVIB pvib)
+{
+ while ( pvib) {
+
+ // Make sure this one is invalidated
+ pvib->flags.NoBind = TRUE;
+
+ // If we have any children, invalidate them
+ if ( pvib->pcif ) FTInvalidateVib( pvib->pcif->pvibChild);
+
+ // Now take care of the siblings
+ pvib = pvib->pvibSib;
+ }
+}
+
+/*** FTResetVib
+ *
+ * Purpose:
+ * Reset any NoBind flags from this vib down
+ *
+ * Input:
+ * pVib - Pointer to a VIB
+ *
+ * Output:
+ * None
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+VOID PASCAL FTResetVib( PTRVIB pvib)
+{
+ while ( pvib) {
+
+ // Make sure this one is turned off
+ pvib->flags.NoBind = FALSE;
+
+ // If we have any children, reset them
+ if ( pvib->pcif ) FTResetVib( pvib->pcif->pvibChild);
+
+ // Now take care of the siblings
+ pvib = pvib->pvibSib;
+ }
+}
+
+
+/*** FTAgeVibValues
+ *
+ * Purpose:
+ * Age the Vib's value strings by moving it to the previous value.
+ * If we have a previous value free it. Null the current value.
+ *
+ * Input:
+ * pVib - Pointer to a VIB
+ *
+ * Output:
+ * None
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+VOID PASCAL FTAgeVibValues( PTRVIB pvib)
+{
+ ULONG i;
+
+ while ( pvib) {
+
+ FTEnsureTextExists( pvib );
+ if ( pvib->cText ) {
+
+ // For each text segment
+
+ for ( i=0; i < pvib->cText ; i++) {
+
+ // Free the Prev. If it exists
+ if ( pvib->pvtext[i].pszValueP )
+ free(pvib->pvtext[i].pszValueP);
+
+ // Move Current to Prev. and Null current
+ pvib->pvtext[i].pszValueP = pvib->pvtext[i].pszValueC;
+ pvib->pvtext[i].pszValueC = NULL;
+ }
+ }
+
+ // If we have any children, Age them
+
+ if ( pvib->pcif )
+ FTAgeVibValues( pvib->pcif->pvibChild);
+
+ // Now take care of the siblings
+ pvib = pvib->pvibSib;
+ }
+}
+
+
+/*** FTGetPanelString
+ *
+ * Purpose:
+ * Get the String associated with a vib index.
+ *
+ * Input:
+ * UINT PanelNumber - Panel whos string we need (BUTTON, LEFT, RIGHT)
+ * UINT VibINdex - Index of the Vib we need
+ *
+ * Output:
+ * PSTR Pointer to the buffer containing the string.
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+PSTR PASCAL FTGetPanelString( PTRVIT pVit, PTRVIB pVib, UINT PanelNumber)
+{
+ PVTEXT pvtext;
+
+ FTEnsureTextExists( pVib );
+
+ // Focus in on the one we want
+ switch (PanelNumber) {
+
+ case ID_PANE_BUTTON:
+ return(FTGetVibTypeString(pVib));
+
+ case ID_PANE_LEFT:
+ return(FTGetVibNameString(pVib));
+
+ case ID_PANE_RIGHT:
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+ if ( pvtext->pszValueC == NULL)
+ pvtext->pszValueC = _strdup(FTGetVibResultString(pVit,pVib));
+ return(pvtext->pszValueC);
+
+ default:
+ return(NULL);
+ }
+
+}
+
+/*** FTGetPanelStatus
+ *
+ * Purpose:
+ * Has the text for a panel id changed?
+ *
+ * Input:
+ * UINT PanelNumber - Panel whos string we need (BUTTON, LEFT, RIGHT)
+ * UINT VibINdex - Index of the Vib we need
+ *
+ * Output:
+ * TRUE/FALSE
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+
+BOOL PASCAL FTGetPanelStatus( PTRVIB pVib, UINT PanelNumber)
+{
+ PVTEXT pvtext;
+
+ if ( PanelNumber == ID_PANE_RIGHT) {
+ FTEnsureTextExists( pVib );
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+ if ( pvtext->pszValueC && pvtext->pszValueP)
+ return ( strcmp( pvtext->pszValueC, pvtext->pszValueP) );
+ else
+ return(FALSE);
+ }
+
+ else
+ return(FALSE);
+}
+
+
+/*** FTEnsureTextExists
+ *
+ * Purpose:
+ * Ensure that the Text segment for a vib exists
+ *
+ * Input:
+ * PRTVIB pVib - Pointer to the vib to check
+ *
+ * Output:
+ *
+ * Exceptions:
+ *
+ * Notes:
+ *
+ */
+
+VOID PASCAL FTEnsureTextExists( PTRVIB pVib )
+{
+ int count;
+ int slack;
+
+ // Make sure we have a text segment
+ if ( pVib->pvtext == NULL) {
+ pVib->pvtext = malloc( sizeof(VTEXT) );
+ RAssert(pVib->pvtext);
+ memset(pVib->pvtext,0, sizeof(VTEXT));
+ pVib->cText = 1;
+ }
+
+ // Make sure the Indicated index has text associated
+ // with it, if not expand in 10 entry increments
+
+ if ( pVib->vibIndex + 1 > pVib->cText) {
+ count = pVib->vibIndex + 11;
+ slack = count - pVib->cText;
+ pVib->pvtext = realloc(pVib->pvtext, count * sizeof(VTEXT) );
+ RAssert(pVib->pvtext);
+ memset(&pVib->pvtext[pVib->cText], 0, slack * sizeof(VTEXT) );
+ pVib->cText = count;
+ }
+
+}
diff --git a/private/windbg/windbg/watch.c b/private/windbg/windbg/watch.c
new file mode 100644
index 000000000..1e9a9aed2
--- /dev/null
+++ b/private/windbg/windbg/watch.c
@@ -0,0 +1,704 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ watch.c
+
+Abstract:
+
+ This module contains the routines to deal with the watch
+ dialog box.
+
+Author:
+
+ William J. Heaton (v-willhe) 20-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+//
+// Preprocessor Macros
+//
+
+#define STYLE(Id) ((WORD)GetWindowLong(GetDlgItem(hDlg, Id), GWL_STYLE))
+#define ITEM(val) (GetDlgItem(hDlg, val))
+#define ISITEMDEFAULT(i) ( (LOWORD(GetWindowLong(ITEM(i),GWL_STYLE)) == LOWORD(BS_DEFPUSHBUTTON)) )
+#define WatchSelection wGeneric1
+
+//
+// Function Prototypes (LOCAL)
+
+VOID AddWatchExpression(HWND);
+VOID DeleteWatchExpression(HWND);
+VOID WatchExpressionHandler( HWND hDlg, WPARAM wParam, LPARAM lParam);
+VOID WatchListHandler( HWND hDlg, WPARAM wParam, LPARAM lParam);
+VOID OkButtonHandler( HWND hDlg, WPARAM wParam, LPARAM lParam);
+
+/*** WatchDefPushButton
+**
+** Synopsis:
+** void = WatchDefPushButton(hDlg, ButtonId)
+**
+** Entry:
+** HWND hDlg Dialog Window Handle
+** int Id Button Id
+**
+** Returns:
+** Nothing
+**
+** Description:
+**
+*/
+
+void NEAR PASCAL WatchDefPushButton(HWND hDlg, int Id)
+{
+ // Undo the current default push button
+
+ if ( Id != IDOK && STYLE(IDOK) == BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(IDOK), BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
+ }
+
+ if ( Id != IDCANCEL && STYLE(IDCANCEL) == BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(IDCANCEL), BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
+ }
+
+ if ( Id != IDWINDBGHELP && STYLE(IDWINDBGHELP) == (WORD)BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(IDWINDBGHELP), BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
+ }
+
+ if ( Id != ID_WATCH_ADD && STYLE(ID_WATCH_ADD) == BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(ID_WATCH_ADD), BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
+ }
+
+ if ( Id != ID_WATCH_DELETE && STYLE(ID_WATCH_DELETE) == BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(ID_WATCH_DELETE), BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
+ }
+
+ if ( Id != ID_WATCH_CLEARALL && STYLE(ID_WATCH_CLEARALL) == BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(ID_WATCH_CLEARALL), BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
+ }
+
+ if (STYLE(Id) != BS_DEFPUSHBUTTON) {
+ PostMessage(ITEM(Id), BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
+ }
+
+ return;
+} /* WatchDefPushButton() */
+
+/*** FillWatchListbox
+**
+** Synopsis:
+** void = FillWatchListbox(hDlg)
+**
+** Entry:
+** hDlg - handle to dialog box containning the list box
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Fill the watch list box with the current watches
+**
+*/
+
+void PASCAL NEAR FillWatchListbox(HWND hDlg)
+{
+ PTRVIT pVit = InitWatchVit();
+ PTRVIB pVib;
+
+ DAssert(pVit);
+
+ // If no VIB'S, No Clear All Button
+
+ pVib = pVit->pvibChild;
+ if (pVib == NULL) {
+ EnableWindow(ITEM(ID_WATCH_CLEARALL), FALSE);
+ }
+
+ // While we have a vib, add the expression to the listbox
+ // and mark it as a original.
+
+ while (pVib) {
+ SendMessage( ITEM(ID_WATCH_CUREXPRESSION), LB_ADDSTRING,
+ 0,(LONG)(LPSTR)pVib->pwoj->szExpStr);
+
+ pVib->flags.DlgOrig = TRUE;
+ pVib->flags.DlgAdd = FALSE;
+ pVib->flags.DlgDel = FALSE;
+
+ pVib = pVib->pvibSib;
+ }
+ return;
+} /* FillWatchListbox() */
+
+
+/*** AddWatchListbox
+**
+** Synopsis:
+** void = AddWatchListbox(hDlg, szExp)
+**
+** Entry:
+** HWND hDlg - handle of dialog containning the list box
+** PSTR szExp - Pointer to the Expression to be added
+**
+** Returns:
+** nothing
+**
+** Description:
+** Creates the Vib, Makrs it as an add, and updates the Watch
+** listbox. Also a sucessful add turns on the clear all button
+**
+*/
+
+void PASCAL NEAR AddWatchListbox(HWND hDlg, PSTR szExpress)
+{
+ PTRVIB pVib;
+ PTRVIT pVit = GetWatchVit();
+
+ pVib = AddCVWatch( pVit, szExpress);
+
+ if ( pVib) {
+ pVib->flags.DlgAdd = TRUE;
+
+ SendMessage(ITEM(ID_WATCH_CUREXPRESSION),LB_ADDSTRING, 0, (LONG)szExpress);
+ EnableWindow(ITEM(ID_WATCH_CLEARALL), TRUE);
+ }
+
+ return;
+}
+
+/*** DeleteWatchListbox
+**
+** Synopsis:
+** void = DeleteWatchListbox(hDlg, WatchNum)
+**
+** Entry:
+** hDlg - Dialog containning the listbox
+** WatchNum -
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Mark the passed watch as deleted and update the watch list box.
+*/
+
+void PASCAL NEAR DeleteWatchListbox(HWND hDlg, int WatchNum)
+{
+ PTRVIT pVit = GetWatchVit();
+ PTRVIB pVib = pVit->pvibChild;
+ LONG NumItems;
+ int i = 0;
+
+ //
+ // Find the Nth Vib
+ //
+
+ while (pVib) {
+
+ // If it isn't a pending delete, check if its the
+ // target otherwise bump the count
+
+ if ( !pVib->flags.DlgDel ) {
+ if ( i == WatchNum ) break;
+ i++;
+ }
+ pVib = pVib->pvibSib;
+ }
+ if ( !pVib ) return;
+
+ //
+ // Mark it as deleted and remove it from listbox
+ //
+
+ pVib->flags.DlgDel = TRUE;
+ SendMessage(ITEM(ID_WATCH_CUREXPRESSION), LB_DELETESTRING, WatchNum, 0L);
+
+ //
+ // Reset the highlights and buttons if needed
+ //
+
+ NumItems = SendMessage(ITEM(ID_WATCH_CUREXPRESSION),LB_GETCOUNT,0,0L);
+
+ if (NumItems > 0) {
+ if (WatchNum == NumItems) WatchNum--;
+ SendMessage( ITEM(ID_WATCH_CUREXPRESSION),LB_SETCURSEL,WatchNum,0L);
+ }
+
+ else {
+ SetFocus(ITEM(ID_WATCH_EXPRESSION));
+ EnableWindow(ITEM(ID_WATCH_CLEARALL), FALSE);
+ EnableWindow(ITEM(ID_WATCH_DELETE), FALSE);
+ }
+ return;
+} /* DeleteWatchListbox() */
+
+
+/*** ClearAllWatch
+**
+** Synopsis:
+** void = ClearAllWatch(hDlg)
+**
+** Entry:
+** hDlg - Handle to dialog containning list box
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Mark all the watches as deleted and clear the listbox
+**
+*/
+
+void PASCAL NEAR ClearAllWatch(HWND hDlg)
+{
+ PTRVIT pVit = GetWatchVit();
+ PTRVIB pVib = pVit->pvibChild;
+
+ // Set the Pending Delete on all vibs
+ while (pVib) {
+ pVib->flags.DlgDel = TRUE;
+ pVib = pVib->pvibSib;
+ }
+
+ // Clear the watch list box
+ SendMessage(ITEM(ID_WATCH_CUREXPRESSION),LB_RESETCONTENT, 0, 0L);
+ SetFocus(ITEM(ID_WATCH_EXPRESSION));
+
+ // Grey Delete and Clear All
+ EnableWindow(ITEM(ID_WATCH_CLEARALL), FALSE);
+ EnableWindow(ITEM(ID_WATCH_DELETE), FALSE);
+
+ return;
+} /* ClearAllWatch() */
+
+/*** OKWatch
+**
+** Synopsis:
+** void = OKWatch()
+**
+** Entry:
+** None
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Delete any watches marked for deletion, and reset the
+** watch editing flags. Update the watch window to reflect
+** any changes.
+**
+*/
+
+void PASCAL NEAR OKWatch(void)
+{
+ PTRVIT pVit = GetWatchVit();
+ PTRVIB pVib = pVit->pvibChild;
+ PTRVIB pVibTemp;
+ BOOL fChanged = FALSE;
+
+
+ while (pVib) {
+
+ if ( pVib->flags.DlgDel ) {
+ pVibTemp = pVib->pvibSib;
+ DeleteCVWatch(pVit, pVib);
+ pVib = pVibTemp;
+ fChanged = TRUE;
+ }
+
+ else {
+ if ( pVib->flags.DlgAdd ) fChanged = TRUE;
+ pVib->flags.DlgAdd = FALSE;
+ pVib->flags.DlgOrig = FALSE;
+ pVib = pVib->pvibSib;
+ }
+ }
+
+ // If we have watchs, but no watchwindow, create one
+
+ if ( pVit->pvibChild && GetWatchHWND() == NULL) {
+ PostMessage(hwndFrame, WM_COMMAND, IDM_WINDOW_WATCH, 0L);
+ return;
+ }
+
+ // Refresh watch window
+
+ if ( fChanged ) {
+ UpdateCVWatchs();
+ }
+
+ return;
+} /* OKWatch() */
+
+/*** CancelWatch
+**
+** Synopsis:
+** void = CancelWatch()
+**
+** Entry:
+** none
+**
+** Returns:
+** Nothing
+**
+** Description:
+** Delete any watches marked as added and reset the watch
+** editing flags.
+**
+*/
+
+void PASCAL NEAR CancelWatch(void)
+{
+ PTRVIT pVit = GetWatchVit();
+ PTRVIB pVib = pVit->pvibChild;
+ PTRVIB pVibTemp;
+ BOOL fChanged = FALSE;
+
+ while (pVib) {
+
+ if ( !pVib->flags.DlgOrig ) {
+ pVibTemp = pVib->pvibSib;
+ DeleteCVWatch(pVit, pVib);
+ pVib = pVibTemp;
+ fChanged = TRUE;
+ }
+
+ else {
+ pVib->flags.DlgAdd = FALSE;
+ pVib->flags.DlgDel = FALSE;
+ pVib->flags.DlgOrig = FALSE;
+ pVib = pVib->pvibSib;
+ }
+
+ }
+ return;
+} /* CancelWatch() */
+
+
+/*** DlgWatch
+**
+** Synopsis:
+** bool = DlgWatch(hDlg, message, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to dialog for which to process the message
+** message - message to be processed
+** wParam - info about the message
+** lParam - info about the message
+**
+** Returns:
+**
+** Description:
+** Processes messages for "WATCH" dialog box
+** (Debug Watch Value menu Option)
+**
+** MESSAGES:
+**
+** WM_INITDIALOG - Initialize dialog box
+** WM_COMMAND- Input received
+**
+*/
+
+BOOL FAR PASCAL EXPORT DlgWatch(HWND hDlg, UINT message, WPARAM wParam, LONG lParam)
+{
+ HWND hExp = ITEM(ID_WATCH_EXPRESSION);
+ char szExpr[MAX_EXPRESS_SIZE];
+
+ switch (message) {
+ case WM_INITDIALOG:
+
+ FillWatchListbox(hDlg);
+ Dbg(SendMessage(hExp, EM_LIMITTEXT, MAX_EXPRESS_SIZE-1, 0L));
+ *szExpr = '\0';
+ SetFocus(hExp);
+ WatchSelection = 0;
+ return TRUE;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam)) {
+
+ case ID_WATCH_ADD:
+ AddWatchExpression(hDlg);
+ return TRUE;
+
+ case ID_WATCH_DELETE:
+ DeleteWatchExpression(hDlg);
+ return TRUE;
+
+ case ID_WATCH_CLEARALL:
+ ClearAllWatch(hDlg);
+ return TRUE;
+
+ case ID_WATCH_EXPRESSION:
+ WatchExpressionHandler(hDlg, wParam, lParam);
+ return TRUE;
+
+ case ID_WATCH_CUREXPRESSION:
+ WatchListHandler( hDlg, wParam, lParam);
+ return TRUE;
+
+ case IDOK:
+ OkButtonHandler( hDlg, wParam, lParam);
+ return TRUE;
+
+ case IDCANCEL:
+ CancelWatch();
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDWINDBGHELP:
+ Dbg(WinHelp(hDlg,szHelpFileName,HELP_CONTEXT,ID_WATCH_HELP));
+ return (TRUE);
+ }
+ break;
+ }
+
+ return (FALSE);
+} /* DlgWatch() */
+
+/*** AddWatchExpression
+**
+** Synopsis:
+** void AddWatchExpression(hDlg);
+**
+** Entry:
+** hDlg - Handle to dialog for which to process the message
+**
+** Returns:
+**
+** Description:
+** Addes a watch to the watch list
+**
+**
+*/
+
+
+VOID AddWatchExpression( HWND hDlg )
+{
+ HWND hExp = ITEM(ID_WATCH_EXPRESSION);
+ char szExpr[MAX_EXPRESS_SIZE];
+
+ // get the input expression
+ *szExpr = '\0';
+ GetDlgItemText(hDlg, ID_WATCH_EXPRESSION, (LPSTR)szExpr, sizeof(szExpr)-1);
+
+ if (CheckExpression(szExpr, radix, TRUE)) {
+ AddWatchListbox(hDlg, szExpr );
+ }
+
+ else
+ MessageBeep(0);
+
+ // Either way put focus back in the edit field
+ SendMessage(hExp, WM_SETTEXT, 0, (DWORD)(LPSTR)szNull);
+ SetFocus(hExp);
+}
+
+/*** DeleteWatchExpression
+**
+** Synopsis:
+** void DeleteWatchExpression(hDlg);
+**
+** Entry:
+** hDlg - Handle to dialog for which to process the message
+**
+** Returns:
+**
+** Description:
+** Delete the current line in the watch list box.
+**
+**
+*/
+
+VOID DeleteWatchExpression( HWND hDlg )
+{
+ WORD WatchNum;
+ HWND hList = ITEM(ID_WATCH_CUREXPRESSION);
+
+ WatchNum = (WORD)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+ if (WatchNum != LB_ERR) {
+ DeleteWatchListbox(hDlg, WatchNum);
+ }
+
+ else{
+ MessageBeep(0);
+ }
+}
+
+/*** WatchExpressionHandler
+**
+** Synopsis:
+** WatchExpressionHandler(hDlg, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to dialog for which to process the message
+** wParam - info about the message
+** lParam - info about the message
+**
+** Returns:
+**
+** Description:
+** Handles the messages that orginated from the Watch Expression
+** edit control.
+**
+*/
+
+
+VOID WatchExpressionHandler( HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ char szExpr[MAX_EXPRESS_SIZE];
+ BOOL fHasText = GetDlgItemText(hDlg, ID_WATCH_EXPRESSION, (LPSTR)szExpr, sizeof(szExpr)-1);
+
+ switch (HIWORD(wParam)) {
+
+ case EN_SETFOCUS:
+ SendMessage((HWND) lParam, EM_SETSEL, 0, 0xffffffff);
+ SendMessage(ITEM(ID_WATCH_CUREXPRESSION),LB_SETCURSEL, 0xffffffff, 0L);
+
+ EnableWindow(ITEM(ID_WATCH_DELETE), FALSE);
+
+ if ( fHasText ) {
+ EnableWindow(ITEM(ID_WATCH_ADD), TRUE);
+ WatchDefPushButton(hDlg, ID_WATCH_ADD);
+
+ PostMessage(ITEM(IDOK),BM_SETSTYLE, (WORD)BS_PUSHBUTTON, TRUE);
+ PostMessage(ITEM(ID_WATCH_ADD),BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
+ }
+
+ else {
+ EnableWindow(ITEM(ID_WATCH_ADD), FALSE);
+ WatchDefPushButton(hDlg, IDOK);
+ }
+ break;
+
+ case EN_CHANGE:
+
+ if ( fHasText ) {
+ EnableWindow(ITEM(ID_WATCH_ADD), TRUE);
+ WatchDefPushButton(hDlg, ID_WATCH_ADD);
+ }
+
+ else {
+ EnableWindow(ITEM(ID_WATCH_ADD), FALSE);
+ WatchDefPushButton(hDlg, IDOK);
+ }
+ break;
+ }
+ return;
+}
+
+/*** WatchExpressionHandler
+**
+** Synopsis:
+** WatchListHandler(hDlg, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to dialog for which to process the message
+** wParam - info about the message
+** lParam - info about the message
+**
+** Returns:
+**
+** Description:
+** Handles the messages that orginated from the Watch Expression
+** List box.
+**
+*/
+
+VOID WatchListHandler( HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hList = ITEM(ID_WATCH_CUREXPRESSION);
+ BOOL Enabled;
+
+ switch (HIWORD(wParam)) {
+
+ case LBN_SETFOCUS:
+ EnableWindow(ITEM(ID_WATCH_ADD), FALSE);
+
+ SendMessage((HWND) lParam, LB_SETCURSEL, WatchSelection, 0L);
+ Enabled = (SendMessage((HWND) lParam, LB_GETCURSEL, 0, 0L) != LB_ERR);
+ EnableWindow(ITEM(ID_WATCH_DELETE), Enabled);
+ if (Enabled){
+ WatchDefPushButton(hDlg, ID_WATCH_DELETE);
+
+ // KLUGE to stop Windows making the OK button
+ // default when coming from buttons
+ PostMessage(ITEM(IDOK),BM_SETSTYLE, (WORD)BS_PUSHBUTTON, TRUE);
+ PostMessage(ITEM(ID_WATCH_DELETE),BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
+ }
+ break;
+
+ case LBN_DBLCLK:
+ DeleteWatchExpression(hDlg);
+ break;
+
+ case LBN_SELCHANGE:
+ WatchSelection = (WORD)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+ EnableWindow(ITEM(ID_WATCH_DELETE), (WatchSelection != -1));
+ if ((WatchSelection != -1)){
+ WatchDefPushButton(hDlg, ID_WATCH_DELETE);
+ }
+ break;
+ }
+ return;
+}
+
+/*** OkButtonHandler
+**
+** Synopsis:
+** OkButtonHandler(hDlg, wParam, lParam)
+**
+** Entry:
+** hDlg - Handle to dialog for which to process the message
+** wParam - info about the message
+** lParam - info about the message
+**
+** Returns:
+**
+** Description:
+** Handles the messages that orginated from the Watch Expression
+** buttons.
+**
+*/
+
+VOID OkButtonHandler( HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ // Important. The tests are done in this order to get around a
+ // bug in Windows whereby more than button can be set as the
+ // default. In our case this always the OK button that can be
+ // set by mistake so we test this case last.
+
+ if ((HWND)LOWORD(lParam) == ITEM(IDOK)) {
+ OKWatch();
+ EndDialog(hDlg, TRUE);
+ }
+
+ else if ( ISITEMDEFAULT(ID_WATCH_ADD) ) {
+ AddWatchExpression(hDlg);
+ }
+
+ else if ( ISITEMDEFAULT(ID_WATCH_DELETE) ) {
+ DeleteWatchExpression(hDlg);
+ }
+
+ else if ( ISITEMDEFAULT(IDOK) ) {
+ OKWatch();
+ EndDialog(hDlg, TRUE);
+ }
+
+ return;
+}
+
+
diff --git a/private/windbg/windbg/watchwin.c b/private/windbg/windbg/watchwin.c
new file mode 100644
index 000000000..f1fe02146
--- /dev/null
+++ b/private/windbg/windbg/watchwin.c
@@ -0,0 +1,817 @@
+/*++
+
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ watchwin.c
+
+Abstract:
+
+ This module contains the routines to manipulate the Watch Window
+
+Author:
+
+ William J. Heaton (v-willhe) 20-Jul-1992
+ Griffith Wm. Kadnier (v-griffk) 10-Mar-1993
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+/*
+ * Global Memory (PROGRAM)
+ */
+
+extern PTRVIT pvitEdit;
+extern CXF CxfIp;
+char output[512];
+/*
+ * Global Memory (FILE)
+ */
+
+PTRVIT pvitWatch;
+HWND hWndWatch;
+
+
+VOID WatchUpdate( PPANE p, BOOL fClear, WPARAM wParam);
+BOOL AcceptValueUpdate(PTRVIT pVit,PPANE p);
+
+/*** InitWatchVit
+**
+** Synopsis:
+** pVit = InitWatchVit()
+**
+** Entry:
+** None
+**
+** Returns:
+** Returns a pointer to the current vit (Allocating one if needed).
+** return NULL if can't
+**
+** Description:
+**
+** Creates the Vit (Variable Information Top) block for the
+** watch window
+**
+*/
+
+PTRVIT PASCAL InitWatchVit(void)
+{
+ if (pvitWatch == NULL) {
+ pvitWatch = calloc(1, sizeof(VIT));
+ }
+ return (pvitWatch);
+} /* InitWatchVit() */
+
+/*** GetWatchVit
+**
+** Synopsis:
+** pVit = GetWatchVit()
+**
+** Entry:
+** None
+**
+** Returns:
+** Pointer to the current watch vit.
+**
+*/
+
+PTRVIT GetWatchVit(VOID)
+{
+ return(pvitWatch);
+}
+
+/*** GetWatchHWND
+**
+** Synopsis:
+** hWnd = GetWatchHWND()
+**
+** Entry:
+** None
+**
+** Returns:
+** Pointer to the current watch window handle.
+**
+*/
+
+HWND GetWatchHWND(VOID)
+{
+ return(hWndWatch);
+}
+
+/*** UpdateCVWatchs
+**
+** Synopsis:
+** UpdateCVWatchs()
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Forces the WatchWindow (If Present) to update ALL of its
+** Panels.
+**
+*/
+VOID UpdateCVWatchs()
+{
+ PPANE p;
+
+ if ( hWndWatch ) {
+ p = (PPANE)GetWindowLong(hWndWatch, GWW_EDIT);
+ p->LeftOk = p->RightOk = FALSE;
+ }
+
+ UpdateDebuggerState( UPDATE_WATCH );
+ return;
+}
+
+/*** AddCVWatch
+**
+** Synopsis:
+** pVib = AddCVWatch(PSTR szExpStr)
+**
+** Entry:
+** szExpStr - A pointer to the string containing the entry to
+** be added.
+**
+** Returns:
+** Return a pointer to the vib created or NULL;
+**
+** Description:
+**
+** Adds a expression to the watch window. Returns the VIB created.
+**
+*/
+
+PTRVIB AddCVWatch(PTRVIT pVit, PSTR szExpStr)
+{
+ VIB vibT = {0};
+ PTRVIB pvib;
+
+ // check to see if the watch vit is there yet or not
+ // this is for the state file.
+
+ if ( pVit == (PTRVIT)NULL) {
+ FTError(UNABLETOADDWATCH);
+ return(NULL);
+ }
+
+ // make a dummy vib
+ vibT.pvibSib = pVit->pvibChild;
+ pvib = &vibT;
+
+ // find the end of the chain
+ while( pvib->pvibSib != NULL) {
+ pvib = pvib->pvibSib;
+ }
+
+ // set the current context
+ if( FTMakeWatchEntry(&pvib->pvibSib, pVit, szExpStr) ) {
+ return(NULL);
+ }
+
+ // add this entry to the vit
+ FTclnUpdateParent(pvib->pvibSib->pvibParent, 1);
+
+ // restore the vit
+ pVit->pvibChild = vibT.pvibSib;
+ return(pvib->pvibSib);
+} /* AddCVWatch() */
+
+
+/*** DeleteCVWatch
+**
+** Synopsis:
+** LTS = DeleveCVWatch(PTRVIT pVit, PTRVIB pvib)
+**
+** Entry:
+** pVib - Pointer to the VIB that contains the watch to
+** delete.
+**
+** Returns:
+** Returns a LTS status code (defined in vib.h)
+**
+** Description:
+** Given a pointer to a vib, find it and delete it from the
+** watch tree.
+**
+*/
+
+LTS DeleteCVWatch(PTRVIT pVit, PTRVIB pvib)
+{
+ VIB vibT;
+ PTRVIB pvibPrev;
+
+ // make sure this is a watch to be deleted
+ if (!(pvib && (pvib->vibPtr == vibWatch ||
+ pvib->vibPtr == vibType))) {
+ return UNABLETODELETEWATCH;
+ }
+
+ // starting at the head of the list, find the previous vib
+ vibT.pvibSib = pVit->pvibChild;
+ pvibPrev = &vibT;
+
+ while (pvibPrev->pvibSib != pvib) {
+ pvibPrev = pvibPrev->pvibSib;
+ }
+
+ // remove this the deleted one from the chain
+ pvibPrev->pvibSib = pvib->pvibSib;
+ pvib->pvibSib = NULL;
+
+ // update the the vit with the new chain
+ pVit->pvibChild = vibT.pvibSib;
+
+ // delete all members of this vib from the parent count
+ FTclnUpdateParent(pvib->pvibParent, -pvib->cln );
+
+ // delete this vib, and all children
+ FTFreeAllSib(pvib);
+ pvib = NULL;
+
+ return OK;
+} /* DeleteCVWatch() */
+
+
+
+/*** ReplaceCVWatch
+**
+** Synopsis:
+** bool = ReplaceCVWatch( pvit, pvib, szStr)
+**
+** Entry:
+** pvib - Pointer to the VIB whos expression is changing
+** szStr - Pointer to the New expression string.
+**
+** Returns:
+** TRUE or FALSE
+**
+** Description:
+** Replaces the expression strings of the indicated watch
+** entry with the new string.
+*/
+
+BOOL ReplaceCVWatch(PTRVIT pVit, PTRVIB pvib, PSTR szStr)
+{
+ PTRVIB *ppvib;
+
+ //
+ // Find The parent VIB
+ //
+
+ ppvib = &pVit->pvibChild;
+ while ( *ppvib && *ppvib != pvib ) {
+ ppvib = &(*ppvib)->pvibSib;
+ }
+
+
+ //
+ // Make a New child for the parent
+ //
+
+ if ( ! FTMakeWatchEntry ( ppvib, pVit, szStr) ) {
+
+ // New Child gets the Old Child's siblings
+ FTVerify(&pVit->cxf,*ppvib);
+ (*ppvib)->pvibSib = pvib->pvibSib;
+ FTclnUpdateParent( (*ppvib)->pvibParent, (*ppvib)->cln );
+
+
+ // Remove the Old Child
+ FTclnUpdateParent(pvib->pvibParent, -pvib->cln);
+ pvib->pvibSib = NULL;
+ FTFreeAllSib(pvib);
+ pvib = (PTRVIB) NULL;
+ return(TRUE);
+ }
+
+ //
+ // Couldn't add the new watch, make sure the old stays around
+
+ else {
+ *ppvib = pvib;
+ return(FALSE);
+ }
+}
+
+
+/*** AcceptWatchUpdate
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL AcceptWatchUpdate(PTRVIT pVit,PPANE p, WPARAM wParam)
+{
+ PSTR pszBuffer;
+ PTRVIB EditVib;
+ HWND hWnd = p->hWndLeft;
+ ULONG Line = (LONG)p->CurIdx;
+ BOOL retVal = FALSE;
+
+
+ //
+ // Get the current line number, and contents, find its vib
+ //
+
+ pszBuffer = p->EditBuf;
+ while ( isspace(*pszBuffer) )
+ pszBuffer++;
+
+ EditVib = FTvibGetAtLine(pVit,Line);
+
+
+ //
+ // Does a Vib exist for this line, if so we're deleting or changing it
+ //
+
+ if ( EditVib ) {
+
+ //
+ // It only makes sense to modify level zero things.
+ //
+ if (EditVib->level == 0 ) {
+
+ if ( *pszBuffer ) {
+ retVal = ReplaceCVWatch( pVit, EditVib, pszBuffer);
+
+ if (p->bFlags.Expand1st)
+ EditVib->flags.ExpandMe = TRUE;
+
+ p->LeftOk = p->RightOk = FALSE;
+ WatchUpdate(p, FALSE, wParam);
+ }
+ else {
+
+ // Blanking the name means remove the watch
+ DeleteCVWatch(pVit, EditVib);
+
+ // We Need to repaint, watch count changed
+ p->LeftOk = p->RightOk = FALSE;
+ WatchUpdate(p, FALSE, wParam);
+ retVal = TRUE;
+ }
+ }
+ }
+
+ //
+ // Vib doesn't exist for this line create it.
+ //
+
+ else
+ if (*pszBuffer && (EditVib = AddCVWatch(pVit, pszBuffer)) != NULL) {
+ p->CurIdx++;
+
+ if (p->bFlags.Expand1st)
+ EditVib->flags.ExpandMe = TRUE;
+
+ // We Need to repaint, watch count changed
+ p->LeftOk = p->RightOk = FALSE;
+ WatchUpdate(p, FALSE, wParam);
+ retVal = TRUE;
+ }
+
+
+ return retVal;
+} /* AcceptWatchUpdate() */
+
+
+/*** AcceptValueUpdate
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL AcceptValueUpdate(PTRVIT pVit,PPANE p)
+{
+ PSTR pszBuffer;
+ PTRVIB pVib;
+ EESTATUS eeErr;
+ HTM hTm;
+ UINT strIndex;
+ VPI i;
+ EEHSTR hstr;
+ ushort cb;
+ char * lpsz;
+
+ // If we're not editing, we're done (sucessfully)
+ if ( !p->Edit )
+ return(TRUE);
+
+#if 0
+ // Get the variable name
+ pVib = FTvibGetAtLine(pVit,p->CurIdx);
+ pszBuffer = FTGetPanelString( pVit, pVib, ID_PANE_LEFT);
+ DAssert(pszBuffer);
+ memset(output, 0, sizeof(output));
+ strncpy(output, pszBuffer, sizeof(output));
+ strncat(output, " = ", sizeof(output));
+
+#else
+ /*
+ * Get the expression represented by the left pane
+ */
+
+ pVib = FTvibGetAtLine(pVit,p->CurIdx);
+ if (pVib->hTMBd == 0) {
+ hTm = pVib->pvtext[pVib->vibIndex].htm;
+ } else {
+ hTm = pVib->hTMBd;
+ }
+
+ if (EEGetExprFromTM(&hTm, &radix, &hstr, &cb) != EENOERROR) {
+ return FALSE;
+ }
+ if (cb >= sizeof(output)-3) {
+ return FALSE;
+ }
+ lpsz = MMLpvLockMb( hstr );
+ output[0] = '(';
+ strncpy(&output[1], lpsz, cb);
+ strcpy(&output[cb+1], ")=");
+ MMbUnlockMb( hstr );
+ EEFreeStr( hstr );
+#endif
+
+ // Get the New values
+ pszBuffer = p->EditBuf;
+ DAssert(pszBuffer);
+
+ while ( isspace(*pszBuffer) ) {
+ pszBuffer++;
+ }
+
+ if ((strlen(pszBuffer) + cb + 3) > sizeof(output)) {
+ return FALSE;
+ }
+
+ strcat(output, pszBuffer);
+
+ // Parse, Bind, and Evaluate
+ eeErr = EEParse(output, radix, fCaseSensitive, &hTm, &strIndex);
+ if (eeErr == EENOERROR)
+ eeErr = EEBindTM(&hTm, SHpCXTFrompCXF(&CxfIp), TRUE, FALSE, FALSE);
+ if (eeErr == EENOERROR)
+ eeErr = EEvaluateTM(&hTm, SHpFrameFrompCXF(&CxfIp), EEHORIZONTAL);
+ if (hTm)
+ EEFreeTM( &hTm );
+
+ if (eeErr == EENOERROR) {
+ i = pVib->vibIndex;
+
+ FTEnsureTextExists(pVib);
+
+ if(pVib->pvtext[i].pszValueP)
+ free(pVib->pvtext[i].pszValueP);
+
+ pVib->pvtext[i].pszValueP = pVib->pvtext[i].pszValueC;
+ pVib->pvtext[i].pszValueC = NULL;
+ return(TRUE);
+ }
+
+ MessageBeep(0);
+ return(FALSE);
+} /* AcceptValueUpdate() */
+
+
+/*** WatchEditProc
+**
+** Synopsis:
+** long = WatchEditProc(hwnd, msg, wParam, lParam)
+**
+** Entry:
+** hwnd - handle to window to process message for
+** msg - message to be processed
+** wParam - information about message to be processed
+** lParam - information about message to be processed
+**
+** Returns:
+**
+** Description:
+** MDI function to handle Watch window messages
+**
+*/
+
+LONG FAR PASCAL LOADDS WatchEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ PPANE p = (PPANE)lParam;
+ PPANEINFO pInfo = (PPANEINFO)wParam;
+ PTRVIB pVib = NULL;
+ PVTEXT pvtext;
+
+
+ __try {
+
+ switch (msg) {
+ case WU_INITDEBUGWIN:
+ Dbg(InitWatchVit());
+ hWndWatch = hwnd;
+
+ SendMessage(p->hWndLeft, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, 1, 0);
+ p->MaxIdx = (WORD)1;
+ WatchUpdate(p, FALSE, wParam);
+ break;
+
+ case WM_DESTROY:
+ hWndWatch = NULL;
+ //
+ // Fall thru...
+ //
+
+ case WU_DBG_UNLOADEE:
+ case WU_DBG_UNLOADEM:
+ //
+ // Lose the Watch Tree
+ //
+ if ( pvitWatch && pvitWatch->pvibChild ) {
+ FTFreeAllSib(pvitWatch->pvibChild);
+ pvitWatch->pvibChild = NULL;
+ free(pvitWatch);
+ pvitWatch = NULL;
+ SendMessage(p->hWndLeft, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, 1, 0);
+ p->MaxIdx = (WORD)1;
+ WatchUpdate(p, FALSE, wParam);
+ }
+ break;
+
+ case WU_DBG_LOADEM:
+ case WU_DBG_LOADEE:
+ if (!pvitWatch) {
+ Dbg(InitWatchVit());
+ hWndWatch = hwnd;
+
+ SendMessage(p->hWndLeft, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, 1, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, 1, 0);
+ p->MaxIdx = (WORD)1;
+ WatchUpdate(p, FALSE, wParam);
+ }
+ break;
+
+ case WU_INVALIDATE:
+ if (p == (PPANE)NULL) {
+ p = (PPANE)GetWindowLong(GetWatchHWND(), GWW_EDIT);
+ }
+
+ SendMessage(p->hWndLeft, LB_SETCOUNT, 0, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, 0, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, 0, 0);
+ p->MaxIdx = 0;
+ WatchUpdate(p, FALSE, wParam);
+
+ InvalidateRect(p->hWndButton, NULL, TRUE);
+ InvalidateRect(p->hWndLeft, NULL, TRUE);
+ InvalidateRect(p->hWndRight, NULL, TRUE);
+ UpdateWindow (p->hWndButton);
+ UpdateWindow (p->hWndLeft);
+ UpdateWindow (p->hWndRight);
+ break;
+
+ case WU_OPTIONS:
+ pVib = FTvibGetAtLine( pvitWatch, pInfo->ItemId);
+ if ( pVib == NULL) {
+ return(FALSE);
+ }
+
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+
+ if ( pInfo->pFormat && (*(pvtext->pszValueC) != '{') ) {
+ FTEnsureTextExists(pVib);
+
+ if ( pvtext->pszFormat) {
+ free(pvtext->pszFormat);
+ }
+ pvtext->pszFormat = _strdup(pInfo->pFormat);
+
+ if ( pvtext->pszValueC) {
+ free(pvtext->pszValueC);
+ }
+ pvtext->pszValueC = NULL;
+
+ PaneInvalidateRow(p);
+ } else {
+ FTEnsureTextExists(pVib);
+
+ if (pvtext->pszFormat) {
+ free(pvtext->pszFormat);
+ }
+ pvtext->pszFormat = '\0';
+
+ if ( pvtext->pszValueC) {
+ free(pvtext->pszValueC);
+ }
+ pvtext->pszValueC = NULL;
+
+ PaneInvalidateRow(p);
+ }
+ return TRUE;
+
+ case WU_INFO:
+ pInfo->pBuffer = pInfo->pFormat = NULL;
+ pInfo->NewText = FALSE;
+ pInfo->ReadOnly = (pInfo->CtrlId == ID_PANE_LEFT) ? FALSE : TRUE;
+
+ pVib = FTvibGetAtLine( pvitWatch, pInfo->ItemId);
+
+ if ( pVib == NULL) {
+ return(FALSE);
+ }
+
+ FTEnsureTextExists(pVib);
+ pvtext = &pVib->pvtext[pVib->vibIndex];
+ pInfo->pFormat = pvtext->pszFormat;
+
+ pInfo->pBuffer = FTGetPanelString( pvitWatch, pVib, pInfo->CtrlId);
+ pInfo->ReadOnly = (pInfo->ItemId == (UINT) p->MaxIdx);
+
+ if ( pInfo->CtrlId == ID_PANE_LEFT ) {
+ pInfo->NewText = FALSE;
+ } else if ( pInfo->CtrlId == ID_PANE_RIGHT) {
+ pInfo->NewText = FTGetPanelStatus( pVib, pInfo->CtrlId);
+ } else {
+ pInfo->ReadOnly = TRUE;
+ pInfo->NewText = FALSE;
+ }
+ return TRUE;
+
+ case WU_SETWATCH:
+ if (pvitWatch == NULL) {
+ return(FALSE);
+ }
+
+ if (p->nCtrlId == ID_PANE_LEFT) {
+ return(AcceptWatchUpdate( pvitWatch, p, wParam));
+ } else {
+ BOOL retval;
+ retval = (AcceptValueUpdate( pvitWatch, p));
+ if (retval == TRUE) {
+ UpdateDebuggerState(UPDATE_DATAWINS);
+ }
+ return retval;
+ }
+ break;
+
+ case WU_EXPANDWATCH:
+ if (pvitWatch == NULL) {
+ return(FALSE);
+ }
+ if ( FTExpand(pvitWatch, (ULONG)(wParam)) == OK) {
+ p->LeftOk = p->RightOk = FALSE;
+ WatchUpdate(p, FALSE, wParam); // Watch Count changed
+ }
+ break;
+
+ case WU_UPDATE:
+ WatchUpdate(p, (BOOL)wParam, wParam);
+ break;
+ }
+ } __except(EXCEPTION_EXECUTE_HANDLER) {
+
+ return FALSE;
+
+ }
+
+ return FALSE;
+}
+
+
+VOID
+WatchUpdate(
+ PPANE p,
+ BOOL fClear,
+ WPARAM wParam
+ )
+{
+ LONG Len = 0;
+ LONG lLen = 0;
+ WORD i;
+ RECT Rect, tRect;
+ HWND hFoc;
+ HCURSOR hOldCursor, hWaitCursor;
+
+
+ if ( pvitWatch == NULL)
+ return;
+
+ // Set hourglass cursor
+ hWaitCursor = LoadCursor ((HANDLE)NULL, IDC_WAIT);
+ hOldCursor = SetCursor (hWaitCursor);
+
+ hFoc = GetFocus();
+
+
+ if ( FTVerify(&CxfIp, pvitWatch->pvibChild) ) {
+ p->LeftOk = FALSE;
+ }
+
+ pvitWatch->cxf = CxfIp;
+
+
+ // Redo the Left pane if needed
+
+ if ( !p->LeftOk || fClear ) {
+
+ if ( p->bFlags.Expand1st) {
+ FTExpandOne(pvitWatch->pvibChild);
+ }
+
+ Len = (LONG)pvitWatch->cln + 1;
+
+
+ lLen = SendMessage(p->hWndLeft, LB_GETCOUNT, 0, 0L);
+ if ((lLen < Len) || (lLen == 0))
+ {
+ SendMessage(p->hWndLeft, LB_SETCOUNT, Len, 0);
+ SendMessage(p->hWndButton, LB_SETCOUNT, Len, 0);
+ SendMessage(p->hWndRight, LB_SETCOUNT, Len, 0);
+ }
+ else
+ {
+ SendMessage(p->hWndLeft, LB_SETCOUNT, (WPARAM) ((int)lLen), 0L);
+ SendMessage(p->hWndButton, LB_SETCOUNT, (WPARAM) ((int)lLen), 0L);
+ SendMessage(p->hWndRight, LB_SETCOUNT, (WPARAM) ((int)lLen), 0L);
+ }
+
+
+ p->MaxIdx = (WORD)Len;
+
+ // Reseting the count, lost where we were so put us back
+
+ if (p->MaxIdx > 0)
+ {
+ PaneResetIdx(p,p->CurIdx);
+ }
+
+ p->LeftOk = TRUE;
+ }
+
+ // Reset the right pane
+
+ FTAgeVibValues(pvitWatch->pvibChild);
+
+
+ for ( i= p->TopIdx; i < (p->TopIdx + p->PaneLines) ; i++) {
+ if ( FTVerifyNew(pvitWatch,i) ) {
+ PaneInvalidateItem( p->hWndRight, p, i);
+ }
+ }
+
+ p->RightOk = TRUE;
+
+
+ PaneCaretNum(p);
+
+
+ if ((hFoc == p->hWndButton) || (hFoc == p->hWndLeft) || (hFoc == p->hWndRight))
+ {
+ SendMessage(p->hWndButton , LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect (p->hWndButton, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndButton, &tRect, TRUE);
+
+
+ SendMessage(p->hWndLeft , LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect (p->hWndLeft, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndLeft, &tRect, TRUE);
+
+
+ SendMessage(p->hWndRight , LB_GETITEMRECT, (WPARAM)p->CurIdx, (LPARAM)&Rect);
+ GetClientRect (p->hWndRight, &tRect);
+ tRect.top = Rect.top;
+ InvalidateRect(p->hWndRight, &tRect, TRUE);
+ }
+
+
+ CheckPaneScrollBar( p, (WORD)Len);
+
+ // Set original cursor
+ hOldCursor = SetCursor (hOldCursor);
+
+ }
diff --git a/private/windbg/windbg/windbg.c b/private/windbg/windbg/windbg.c
new file mode 100644
index 000000000..ed58b3125
--- /dev/null
+++ b/private/windbg/windbg/windbg.c
@@ -0,0 +1,2545 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Windbg.c
+
+Abstract:
+
+ This module contains the main program, main window proc and MDICLIENT
+ window proc for Windbg.
+
+Author:
+
+ David J. Gilman (davegi) 21-Apr-1992
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+#ifdef FE_IME
+#include <ime.h>
+#include <winnls32.h>
+#endif
+
+extern HWND GetLocalHWND(void);
+extern HWND GetFloatHWND(void);
+extern HWND GetWatchHWND(void);
+extern HWND GetCpuHWND(void);
+extern LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+
+
+
+extern PASCAL FAR arrange (void); //IDM_WINDOW_ARRANGE
+
+BOOL bOffRibbon = FALSE; // module wide flag for ribbon/MDI focus
+BOOL bChildFocus = FALSE; // module wide flag for swallowing mouse messages
+
+
+enum {
+ STARTED,
+ INPROGRESS,
+ FINISHED,
+};
+
+HWND
+GetCallsHWND(
+ VOID
+ );
+
+unsigned int InMemUpdate = FINISHED; // prevent multiple viemem() calls
+extern WORD DialogType;
+
+int
+MainExceptionFilter(
+ LPEXCEPTION_POINTERS lpep
+ )
+{
+ char sz[1000];
+ int r;
+ PEXCEPTION_RECORD per = lpep->ExceptionRecord;
+ switch (per->ExceptionCode) {
+
+ default:
+ r = EXCEPTION_CONTINUE_SEARCH;
+ break;
+
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_INT_OVERFLOW:
+
+ sprintf(sz,
+ "Exception 0x%08X occurred at address 0x%08X.\nHit OK to exit, CANCEL to hit a breakpoint.",
+ per->ExceptionCode,
+ per->ExceptionAddress);
+
+ r = MsgBox(NULL,
+ sz,
+ MB_OKCANCEL | MB_ICONSTOP | MB_SETFOREGROUND | MB_TASKMODAL);
+
+ if (r == IDOK) {
+ r = EXCEPTION_CONTINUE_SEARCH;
+ } else {
+ DebugBreak();
+ r = EXCEPTION_CONTINUE_EXECUTION;
+ }
+ break;
+ }
+ return r;
+}
+
+
+int _CRTAPI1
+main(
+ int argc,
+ char* argv[ ],
+ char* envp[]
+ )
+
+/*++
+
+Routine Description:
+
+ description-of-function.
+
+Arguments:
+
+ argc - Supplies the count of arguments on command line.
+ argv - Supplies a pointer to an array of string pointers.
+
+Return Value:
+
+ int - Returns the wParam from the WM_QUIT message.
+ None.
+
+--*/
+
+{
+ #define RST_DONTJOURNALATTACH 0x00000002
+ typedef VOID (WINAPI * RST)(DWORD,DWORD);
+
+ MSG msg;
+ int i, nCmdShow;
+ HMODULE hInstance = GetModuleHandle(NULL);
+ STARTUPINFO Startup;
+ RST Rst;
+
+ #define hPrevInstance 0
+
+
+ SetErrorMode( SEM_NOALIGNMENTFAULTEXCEPT );
+
+ Rst = (RST)GetProcAddress( GetModuleHandle( "user32.dll" ), "RegisterSystemThread" );
+ if (Rst) {
+ (Rst) (RST_DONTJOURNALATTACH, 0);
+ }
+
+ GetStartupInfo (&Startup);
+
+ nCmdShow = Startup.wShowWindow;
+
+ // First of all, load the title and our standard low memory message
+
+ if (!LoadString(hInstance, SYS_Main_wTitle, MainTitleText, sizeof(MainTitleText)) ||
+ !LoadString(hInstance, ERR_Memory_Is_Low, LowMemoryMsg, sizeof(LowMemoryMsg)) ||
+ !LoadString(hInstance, ERR_Memory_Is_Low_2, LowMemoryMsg2, sizeof(LowMemoryMsg2))) {
+ return FALSE;
+ }
+
+ //Clear the terminal screen
+ for (i = 0; i < 12; i++)
+ AuxPrintf(1, (LPSTR)"");
+
+ if (!hPrevInstance)
+ if (!InitApplication(hInstance)) {
+ FatalErrorBox(ERR_Init_Application, NULL);
+ return FALSE;
+ }
+
+ if (!InitInstance(argc, argv, hInstance, nCmdShow)) {
+ FatalErrorBox(ERR_Init_Application, NULL);
+ return FALSE;
+ }
+
+ PostMessage((HWND) -1, RegisterWindowMessage("XXXYYY"), 0, 0);
+
+ __try {
+ //Enter main message loop
+ while (GetMessage (&msg, NULL, 0, 0)) {
+ ProcessQCQPMessage(&msg);
+ }
+ } __except(MainExceptionFilter(GetExceptionInformation())) {
+ DAssert(FALSE);
+ }
+
+ ExitProcess (msg.wParam);
+}
+
+/*** TerminateApplication
+**
+** Synopsis:
+** bool = TerminateApplication(hWnd, wParam)
+**
+** Entry:
+** hWnd
+** wParam
+**
+** Returns:
+**
+** Description:
+**
+*/
+
+BOOL NEAR
+TerminateApplication(
+ HWND hwnd,
+ WPARAM wParam
+ )
+{
+ if (runDebugParams.fDisconnectOnExit) {
+
+ if (LppdCur) {
+ OSDDisconnect( LppdCur->hpid, LptdCur->htid );
+ }
+
+ } else {
+
+ /*
+ ** Unload and clean out the debugger. Don't do exit if the
+ ** debugger is in the "loading an exe" state.
+ */
+
+ if (DbgState != ds_normal) {
+ MessageBeep(0);
+ return FALSE;
+ }
+
+ if (!emergency) {
+ if (DebuggeeActive() && !AutoTest) {
+ CmdInsertInit();
+ CmdLogFmt("Debuggee still active on Exit\r\n");
+ }
+ }
+
+ ExitingDebugger = TRUE;
+
+ /*
+ * Frightfully sleazy hack:
+ */
+
+ if (DebuggeeActive()) {
+ KillDebuggee();
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return FALSE;
+ }
+
+ if (!ProgramClose()) {
+ ExitingDebugger = FALSE;
+ return FALSE;
+ }
+
+ }
+
+ //Destroy modeless find/replace dialog boxes
+ frMem.exitModelessFind = TRUE;
+ frMem.exitModelessReplace = TRUE;
+
+ // don't fetch more commands
+ SetAutoRunSuppress(TRUE);
+
+ //For Microsoft Tests suites
+ if (wParam != (WPARAM)-1) {
+
+ //Don't close if any children cancel the operation
+ if (!QueryCloseAllDocs()) {
+ if (!emergency) {
+ return FALSE;
+ }
+ }
+ }
+
+ /*
+ * Kill off all debuggee processes, process all notifications,
+ * and generally clean up.
+ */
+
+ if (!runDebugParams.fDisconnectOnExit) {
+ FDebTerm();
+ }
+
+ //Stop Help Engine
+ Dbg(WinHelp(hwnd, szHelpFileName, HELP_QUIT, (DWORD) 0L));
+
+ TerminatedApp = TRUE;
+
+ return TRUE;
+} /* TerminateApplication() */
+
+
+/*** MainWndProc
+**
+** Synopsis:
+**
+** Entry:
+**
+** Returns:
+**
+** Description:
+** Processes window messages.
+**
+*/
+
+long FAR PASCAL EXPORT
+MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ NPVIEWREC v;
+ static UINT menuID;
+#ifdef FE_IME
+ static BOOL bOldImeStatus;
+#endif
+
+ switch (message) {
+
+ case WM_CREATE:
+ {
+ CLIENTCREATESTRUCT ccs;
+ char class[MAX_MSG_TXT];
+
+#ifdef FE_IME
+ ImeInit();
+#endif
+
+ //Find window menu where children will be listed
+ ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), WINDOWMENU);
+ ccs.idFirstChild = IDM_FIRSTCHILD;
+
+ //Create the MDI client filling the client area
+ hwndMDIClient = CreateWindow((LPSTR)"mdiclient",
+ NULL,
+ WS_CHILD | WS_CLIPCHILDREN,
+ 0, 0, 0, 0,
+ hwnd, (HMENU) 0xCAC, hInst, (LPSTR)&ccs);
+
+ LoadFonts(hwnd);
+
+ //Create the Ribbon
+ InitRibbon(hwnd, &ribbon);
+ Dbg(LoadString(hInst, SYS_Ribbon_wClass, class, MAX_MSG_TXT));
+ ribbon.hwndRibbon = CreateWindow ((LPSTR)class,
+ NULL,
+ WS_CHILD | WS_CLIPSIBLINGS,
+ 0, 0, 0, 0,
+ hwnd,
+ (HMENU) ID_RIBBON,
+ hInst,
+ NULL);
+
+ //Create Status Bar
+ InitStatus(hwnd, &status) ;
+ Dbg(LoadString(hInst, SYS_Status_wClass, class, MAX_MSG_TXT));
+ status.hwndStatus = CreateWindow ((LPSTR)class,
+ NULL,
+ WS_CHILD | WS_CLIPSIBLINGS,
+ 0, 0, 0, 0,
+ hwnd,
+ (HMENU) ID_STATUS,
+ hInst,
+ NULL);
+
+ SetWindowText(GetDlgItem(status.hwndStatus, ID_STATUS_SRC), status.rgchSrcMode);
+
+ ShowWindow(hwndMDIClient,SW_SHOW);
+ ShowWindow(status.hwndStatus,SW_SHOW);
+ ShowWindow(ribbon.hwndRibbon,SW_SHOW);
+
+ break;
+ }
+
+ case WM_QUERYOPEN:
+ if (checkFileDate) {
+ checkFileDate = FALSE;
+ PostMessage(hwndFrame, WM_ACTIVATEAPP, 1, 0L);
+ }
+ goto DefProcessing;
+
+ case WM_GETTEXT:
+ BuildTitleBar((LPSTR)lParam, wParam);
+ return _fstrlen((LPSTR)lParam);
+
+ case WM_SETTEXT:
+ {
+ char szTitleBar[256];
+
+ if (lParam && *(LPSTR)lParam) {
+ strcpy( TitleBar.UserTitle, (LPSTR)lParam );
+ }
+
+ BuildTitleBar(szTitleBar, sizeof(szTitleBar));
+ return DefWindowProc(hwnd, message, wParam, (LONG)(LPSTR)szTitleBar);
+ }
+
+ case WM_TIMER:
+ if (wParam == TITLEBARTIMERID)
+ {
+ KillTimer(hwndFrame, TITLEBARTIMERID);
+ UpdateTitleBar(TitleBar.TimerMode, FALSE);
+ }
+ goto DefProcessing;
+
+ case WM_COMMAND:
+ // Deactivate ribbon
+ SendMessage(ribbon.hwndRibbon, WU_ESCAPEFROMRIBBON, (WPARAM) hwndFrame, 0L);
+
+ if (hwndActiveEdit) {
+ v = &Views[curView];
+ }
+
+ switch (LOWORD(wParam)) {
+
+ case IDM_INVALID:
+ break;
+
+ case IDM_FILE_NEW:
+ //Add a new, empty MDI child
+ AddFile(MODE_CREATE, DOC_WIN, NULL, NULL, NULL, FALSE, -1, -1);
+ break;
+
+ case IDM_FILE_OPEN:
+ {
+ DWORD dwFlags;
+ char CurrentDirectory[ MAX_PATH ];
+
+ dwFlags = OFN_SHOWHELP | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
+ GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory );
+ if ( *DocFileDirectory ) {
+ SetCurrentDirectory( DocFileDirectory );
+ }
+
+ if (StartFileDlg(hwnd, DLG_Open_Filebox_Title, DEF_Ext_SOURCE,
+ IDM_FILE_OPEN, 0, (LPSTR) szPath, &dwFlags, DlgFile)) {
+
+ AddFile(MODE_OPENCREATE,
+ DOC_WIN,
+ (LPSTR)szPath,
+ NULL,
+ NULL,
+ (dwFlags & OFN_READONLY) == OFN_READONLY,
+ -1, -1) ;
+
+ GetCurrentDirectory( sizeof( DocFileDirectory ), DocFileDirectory );
+
+ if (FSourceOverlay) {
+ int iView;
+ WINDOWPLACEMENT wp;
+ int doc;
+
+ Dbg(FindDoc(szPath, &doc, TRUE));
+
+ for (iView=0; iView < MAX_VIEWS; iView++) {
+ if ((Views[iView].Doc > -1) &&
+ (Docs[Views[iView].Doc].docType == DOC_WIN) &&
+ (Views[iView].Doc != doc)) {
+ GetWindowPlacement( Views[iView].hwndFrame, &wp );
+ SetWindowPlacement(Views[Docs[doc].FirstView].hwndFrame,&wp);
+ break;
+ }
+ }
+ }
+
+
+ }
+ SetCurrentDirectory( CurrentDirectory );
+ break;
+ }
+
+ case IDM_FILE_CLOSE: {
+
+ int i;
+ int curDoc = Views[curView].Doc; //curView may change during loop
+ BOOL closeIt = TRUE;
+ struct _stat fileStat;
+
+ if (curDoc >= 0 &&
+ Docs[curDoc].docType == DOC_WIN && Docs[curDoc].ismodified) {
+
+ //Ask user whether to save / not save / cancel
+ switch (QuestionBox(SYS_Save_Changes_To,
+ MB_YESNOCANCEL ,
+ (LPSTR)Docs[curDoc].FileName)) {
+ case IDYES:
+
+ //User wants file saved
+ if (SaveFile(curDoc)) {
+ //Reset file creation/load/save time
+ _stat(Docs[curDoc].FileName, &fileStat);
+ Docs[curDoc].time = fileStat.st_mtime;
+ Docs[curDoc].ismodified = FALSE;
+ } else {
+ closeIt = FALSE;
+ }
+ break;
+
+ case IDNO:
+
+ FileNotSaved(curDoc);
+ Docs[curDoc].ismodified = FALSE;
+ break;
+
+ default:
+
+ //We couldn't do the messagebox, or not ok to close
+ if (!CheckDocument(curDoc)) {
+ ErrorBox(ERR_Document_Corrupted);
+ }
+ closeIt = FALSE;
+ break;
+ }
+
+ }
+ if (closeIt) {
+ for (i = 0; i < MAX_VIEWS; i++) {
+ if (Views[i].Doc == curDoc) {
+ if (IsZoomed (Views[i].hwndFrame))
+ {
+ ShowWindow (Views[i].hwndFrame, SW_RESTORE);
+ }
+
+
+ SendMessage(Views[i].hwndFrame, WM_CLOSE, 0, 0L);
+ }
+ }
+ }
+ }
+
+
+ break;
+
+ case IDM_FILE_SAVE:
+ {
+ struct _stat fileStat;
+
+ SaveFile(Views[curView].Doc);
+ //Reset file creation/load/save time
+ _stat(Docs[Views[curView].Doc].FileName, &fileStat);
+ Docs[Views[curView].Doc].time = fileStat.st_mtime;
+ }
+ break;
+
+ case IDM_FILE_SAVEAS:
+ {
+ struct _stat fileStat;
+
+ if (!CheckDocument(v->Doc)) {
+ ErrorBox(ERR_Modified_Document_Corrupted);
+ }
+ SaveAsFile(Views[curView].Doc);
+ //Reset file creation/load/save time
+ _stat(Docs[Views[curView].Doc].FileName, &fileStat);
+ Docs[Views[curView].Doc].time = fileStat.st_mtime;
+ }
+ break;
+
+ case IDM_FILE_SAVEALL:
+ {
+ int d;
+ struct _stat fileStat;
+
+ for (d = 0; d < MAX_DOCUMENTS; d++)
+ {
+ if (Docs[d].FirstView != -1
+ && Docs[d].docType == DOC_WIN)
+ {
+ if (Docs[d].untitled)
+ {
+ SaveAsFile (d);
+ //Reset file creation/load/save time
+ _stat(Docs[d].FileName, &fileStat);
+ Docs[d].time = fileStat.st_mtime;
+ }
+ else if (Docs[d].ismodified)
+ {
+ SaveFile(d);
+ //Reset file creation/load/save time
+ _stat(Docs[d].FileName, &fileStat);
+ Docs[d].time = fileStat.st_mtime;
+ }
+ }
+ }
+
+ }
+ break;
+
+ case IDM_FILE_MERGE:
+ {
+
+ DWORD dwFlags ;
+ BOOL doIt = TRUE;
+ char CurrentDirectory[ MAX_PATH ];
+
+ if (Docs[v->Doc].recType != REC_STOPPED) {
+ doIt = (QuestionBox(ERR_Merge_Destroy_UndoRedo,
+ MB_YESNOCANCEL) == IDYES);
+ }
+
+ if (doIt) {
+ dwFlags = OFN_SHOWHELP | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
+ GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory );
+ if ( *DocFileDirectory ) {
+ SetCurrentDirectory( DocFileDirectory );
+ }
+ if (StartFileDlg(hwnd, DLG_Merge_Filebox_Title, DEF_Ext_C,
+ IDM_FILE_MERGE, 0,
+ (LPSTR)szPath, &dwFlags, DlgFile)) {
+
+ MergeFile((LPSTR)szPath, curView);
+
+ //Resize undo buffer (to clear it)
+ ResizeRecBuf(v->Doc, environParams.undoRedoSize);
+ GetCurrentDirectory( sizeof( DocFileDirectory ), DocFileDirectory );
+ }
+ SetCurrentDirectory( CurrentDirectory );
+ }
+ break;
+ }
+
+ case IDM_FILE_EXIT:
+ SendMessage(hwnd, WM_CLOSE, 0, 0L);
+ break;
+
+ case IDM_EDIT_UNDO:
+ if (PlayRec(v->Doc, REC_UNDO, FALSE, TRUE)) {
+ InvalidateRect(v->hwndClient, NULL, FALSE);
+ }
+ break;
+
+ case IDM_EDIT_REDO:
+ if (PlayRec(v->Doc, REC_REDO, FALSE, TRUE)) {
+ InvalidateRect(v->hwndClient, NULL, FALSE);
+ }
+ break;
+
+ case IDM_EDIT_COPY:
+ {
+
+ int XL,XR;
+ int YL,YR;
+
+ if ( v->Doc < -1 ) {
+ if ( hwndActiveEdit ) {
+ SendMessage(hwndActiveEdit, WM_COPY, 0, 0L);
+ }
+ } else if (v->BlockStatus) {
+ GetBlockCoord(curView, &XL, &YL, &XR, &YR);
+ PasteStream(curView, XL, YL, XR, YR);
+ }
+ break;
+ }
+
+ case IDM_EDIT_PASTE:
+ if (hwndActiveEdit) {
+ SendMessage(hwndActiveEdit, WM_PASTE, 0, 0L);
+ } else {
+ Assert(FALSE);
+ }
+ break;
+
+ case IDM_EDIT_CUT:
+ if (v->BlockStatus) {
+
+ int XL,XR;
+ int YL,YR;
+
+ GetBlockCoord(curView, &XL, &YL, &XR, &YR);
+ PasteStream(curView, XL, YL, XR, YR);
+
+ DeleteStream(curView, XL, YL, XR, YR, TRUE);
+ if (!status.readOnly)
+ PosXY(curView, XL, YL, FALSE);
+ }
+ break;
+
+ case IDM_EDIT_DELETE:
+ DeleteKey(curView);
+ break;
+
+ case IDM_EDIT_READONLY:
+ {
+ int doc = v->Doc;
+
+ Docs[doc].readOnly = !Docs[doc].readOnly;
+ StatusReadOnly(Docs[doc].readOnly);
+
+ if (IsWindow(frMem.hDlgConfirmWnd))
+ {
+ SetFocus(frMem.hDlgConfirmWnd);
+ }
+
+
+ break;
+ }
+
+ case IDM_EDIT_FIND:
+ //FindNext box may already be there
+
+ if (frMem.hDlgFindNextWnd)
+ SetFocus(frMem.hDlgFindNextWnd);
+ else {
+ if (StartDialog(DLG_FIND, DlgFind))
+ Find();
+ }
+ break;
+
+ case IDM_EDIT_REPLACE:
+ //Replace box may already be there
+
+ if (frMem.hDlgConfirmWnd) {
+ SetFocus(frMem.hDlgConfirmWnd);
+ }
+ else {
+ if (StartDialog(DLG_REPLACE, DlgReplace))
+ Replace();
+ }
+ break;
+
+ case IDM_VIEW_TOGGLETAG:
+ LineStatus(Views[curView].Doc, v->Y + 1, TAGGED_LINE,
+ LINESTATUS_TOGGLE, FALSE, TRUE);
+ break;
+
+ case IDM_VIEW_NEXTTAG:
+ {
+ int y = v->Y;
+
+ //Search forward in text
+ if (FindLineStatus(curView, TAGGED_LINE, TRUE, &y)) {
+ ClearSelection(curView);
+ PosXY(curView, 0, y, FALSE);
+ } else
+ MessageBeep(0);
+
+ break;
+ }
+
+ case IDM_VIEW_PREVIOUSTAG:
+ {
+ int y = v->Y;
+
+ //Search backward in text
+ if (FindLineStatus(curView, TAGGED_LINE, FALSE, &y)) {
+ ClearSelection(curView);
+ PosXY(curView, 0, y, FALSE);
+ } else
+ MessageBeep(0);
+
+ break;
+ }
+
+ case IDM_VIEW_CLEARALLTAGS:
+ ClearDocStatus(Views[curView].Doc, TAGGED_LINE);
+ break;
+
+ case IDM_VIEW_LINE:
+ StartDialog(DLG_LINE, DlgLine);
+ break;
+
+ case IDM_VIEW_FUNCTION:
+ StartDialog(DLG_FUNCTION, DlgFunction);
+ break;
+
+ case IDM_VIEW_RIBBON:
+ ribbon.hidden = !ribbon.hidden;
+ CheckMenuItem(hMainMenu, IDM_VIEW_RIBBON,
+ ribbon.hidden ? MF_UNCHECKED : MF_CHECKED);
+ UpdateRibbon((WORD) (ribbon.hidden ? RIBBON_HIDE : RIBBON_UNHIDE), NULL);
+ ChangeDebuggerState();
+ break;
+
+ case IDM_VIEW_STATUS:
+ status.hidden = !status.hidden;
+ CheckMenuItem(hMainMenu, IDM_VIEW_STATUS,
+ status.hidden ? MF_UNCHECKED : MF_CHECKED);
+ UpdateStatus((WORD) (status.hidden ? STATUS_HIDE : STATUS_UNHIDE), NULL) ;
+ ChangeDebuggerState();
+ break;
+
+ case IDM_PROGRAM_OPEN:
+ ProgramOpen();
+ break;
+
+ case IDM_PROGRAM_CLOSE:
+ ProgramClose();
+ break;
+
+ case IDM_PROGRAM_SAVE:
+ ProgramSave();
+ break;
+
+ case IDM_PROGRAM_SAVEAS:
+ ProgramSaveAs();
+ break;
+
+ case IDM_PROGRAM_DELETE:
+ ProgramDelete();
+ break;
+
+ case IDM_PROGRAM_SAVE_DEFAULTS:
+ ProgramSaveDefaults();
+ break;
+
+ case IDM_RUN_RESTART:
+ ExecDebuggee(EXEC_RESTART);
+ return TRUE;
+
+ case IDM_RUN_ATTACH:
+ if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ StartDialog(DLG_TASKLIST, DlgTaskList);
+ }
+ return TRUE;
+
+ case IDM_RUN_GO:
+ case IDM_RUN_GO2:
+ CmdExecuteCmd("g");
+ return TRUE;
+
+ case IDM_RUN_GO_HANDLED:
+ CmdExecuteCmd("gh");
+ break;
+
+ case IDM_RUN_GO_UNHANDLED:
+ CmdExecuteCmd("gn");
+ break;
+
+
+ case IDM_RUN_TOCURSOR:
+ case IDM_RUN_TOCURSOR2:
+ if (IsCallsInFocus()) {
+ SendMessage( GetCallsHWND(), WM_COMMAND,
+ MAKELONG( IDM_RUN_TOCURSOR, 0 ), 0 );
+ return TRUE;
+ }
+
+ // DON'T force the command window open before
+ // calling ExecDebuggee()
+ if (DebuggeeActive() && !GoOK(LppdCur, LptdCur)) {
+ CmdInsertInit();
+ NoRunExcuse(LppdCur, LptdCur);
+ } else if (!DebuggeeActive() && DebuggeeAlive()) {
+ CmdInsertInit();
+ NoRunExcuse(GetLppdHead(), NULL);
+ } else if (LptdCur && LptdCur->fFrozen) {
+ CmdInsertInit();
+ CmdLogVar(DBG_Go_When_Frozen);
+ } else if (!ExecDebuggee(EXEC_TOCURSOR)) {
+ CmdInsertInit();
+ CmdLogVar(ERR_Go_Failed);
+ }
+ return TRUE;
+
+ case IDM_RUN_TRACEINTO:
+ CmdInsertInit();
+ if (DebuggeeActive() && !StepOK(LppdCur, LptdCur)) {
+ NoRunExcuse(LppdCur, LptdCur);
+ } else if (!DebuggeeActive() && DebuggeeAlive()) {
+ NoRunExcuse(GetLppdHead(), NULL);
+ } else if (LptdCur && LptdCur->fFrozen) {
+ CmdLogVar(DBG_Go_When_Frozen);
+ } else if (!ExecDebuggee(EXEC_TRACEINTO)) {
+ CmdLogVar(ERR_Go_Failed);
+ }
+ return TRUE;
+
+ case IDM_RUN_STEPOVER:
+ CmdInsertInit();
+ if (DebuggeeActive() && !StepOK(LppdCur, LptdCur)) {
+ NoRunExcuse(LppdCur, LptdCur);
+ } else if (!DebuggeeActive() && DebuggeeAlive()) {
+ NoRunExcuse(GetLppdHead(), NULL);
+ } else if (LptdCur && LptdCur->fFrozen) {
+ CmdLogVar(DBG_Go_When_Frozen);
+ } else if (!ExecDebuggee(EXEC_STEPOVER)) {
+ CmdLogVar(ERR_Go_Failed);
+ }
+ return TRUE;
+
+ case IDM_RUN_HALT:
+ AsyncStop();
+ return TRUE;
+
+ case IDM_RUN_STOPDEBUGGING:
+ ClearDebuggee();
+ EnableRibbonControls( ERC_ALL, FALSE );
+ return TRUE;
+
+ case IDM_DEBUG_SETBREAK:
+
+ if (HIWORD(wParam) == 0) {
+
+ // menu got us here
+ StartDialog(DLG_BREAKPOINTS, DlgSetBreak);
+
+ } else if (!hwndActiveEdit
+ || v->Doc < 0
+ || ( Docs[v->Doc].docType != DISASM_WIN
+ && Docs[v->Doc].docType != DOC_WIN)) {
+
+ // accelerator, but not in a valid window
+ StartDialog(DLG_BREAKPOINTS, DlgSetBreak);
+
+ } else if (!ToggleLocBP()) {
+
+ MessageBeep(0);
+ ErrorBox(ERR_NoCodeForFileLine);
+
+ }
+ break;
+
+ case IDM_DEBUG_QUICKWATCH:
+ StartDialog(DLG_QUICKWATCH, DlgQuickW);
+ break;
+
+ case IDM_DEBUG_WATCH:
+ StartDialog(DLG_WATCH, DlgWatch);
+ break;
+
+ case IDM_DEBUG_MODIFY:
+ // StartDialog(DLG_MODIFY, DlgModify);
+ break;
+
+
+ case IDM_OPTIONS_MEMORY:
+ {
+ int memcurView = GetWindowWord(hwndActiveEdit, GWW_VIEW);
+ int curDoc = Views[memcurView].Doc; //memcurView may change during loop
+
+ if (Docs[curDoc].docType == MEMORY_WIN)
+ {
+ memView = memcurView;
+ _fmemcpy (&TempMemWinDesc,&MemWinDesc[memView],sizeof(struct memWinDesc));
+ TempMemWinDesc.fHaveAddr = FALSE; //force re-evaluation
+ TempMemWinDesc.cMi = 0; //force re-evaluation
+ TempMemWinDesc.cPerLine = 0; //force re-evaluation
+ StartDialog(DLG_MEMORY, DlgMemory);
+ }
+ }
+ break;
+
+
+ case IDM_OPTIONS_WATCH:
+ DialogType = WATCH_WIN;
+ StartDialog( DLG_PANEOPTIONS, DlgPaneOptions);
+ break;
+
+ case IDM_OPTIONS_LOCAL:
+ DialogType = LOCALS_WIN;
+ StartDialog( DLG_PANEOPTIONS, DlgPaneOptions);
+ break;
+
+ case IDM_OPTIONS_CPU:
+ DialogType = CPU_WIN;
+ StartDialog( DLG_PANEOPTIONS, DlgPaneOptions);
+ break;
+
+ case IDM_OPTIONS_FLOAT:
+ DialogType = FLOAT_WIN;
+ StartDialog( DLG_PANEOPTIONS, DlgPaneOptions);
+ break;
+
+ case IDM_OPTIONS_PANE:
+ DialogType = (WORD)lParam;
+ StartDialog( DLG_PANEOPTIONS, DlgPaneOptions);
+ break;
+
+ case IDM_RUN_SET_THREAD:
+
+ StartDialog(DLG_THREAD, DlgThread);
+ break;
+
+ case IDM_RUN_SET_PROCESS:
+ StartDialog(DLG_PROCESS, DlgProcess);
+ break;
+
+ case IDM_OPTIONS_DEBUG:
+ StartDialog(DLG_RUNDEBUG, DlgRunDebug);
+ break;
+
+ case IDM_OPTIONS_USERDLL:
+ StartDialog(DLG_USERDLL, DlgUserdll);
+ break;
+
+ case IDM_OPTIONS_DBGDLL:
+ StartDialog(DLG_DEBUGDLL, DlgDbugdll);
+ break;
+
+ case IDM_OPTIONS_EXCEPTIONS:
+ StartDialog(DLG_DEBUGEXCP, DlgDbugexcept);
+ break;
+
+ case IDM_OPTIONS_KD:
+ StartDialog(DLG_KERNELDBG, DlgKernelDbg);
+ break;
+
+ case IDM_OPTIONS_ENVIRON:
+ StartDialog(DLG_ENVIRONMENT, DlgEnviron);
+ break;
+
+ case IDM_OPTIONS_RUN:
+ StartDialog(DLG_RUNOPT, DlgDbugrun);
+ break;
+
+ case IDM_OPTIONS_COLOR:
+ SelectColor (hwnd);
+ break;
+
+ case IDM_OPTIONS_FONTS:
+ SelectFont (hwnd);
+ break;
+
+ case IDM_OPTIONS_CALLS:
+ StartDialog( DLG_CALLSWINOPTIONS, DlgCallsOptions);
+ break;
+
+ case IDM_WINDOW_TILE:
+ SendMessage(hwndMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0L);
+ // It does not seem like the updating is necessary either.
+ if (DebuggeeActive()) {
+ UpdateDebuggerState (UPDATE_MEMORY);
+ }
+ // commented out the line below for ntbug #27745
+ // InvalidateAllWindows();
+ break;
+
+ case IDM_WINDOW_CASCADE:
+ SendMessage(hwndMDIClient, WM_MDICASCADE, 0, 0L);
+ // It does not seem like the updating is necessary either.
+ if (DebuggeeActive()) {
+ UpdateDebuggerState (UPDATE_MEMORY);
+ }
+ // commented out the line below for ntbug #27745
+ // InvalidateAllWindows();
+ break;
+
+ case IDM_WINDOW_ARRANGE_ICONS:
+ SendMessage(hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
+ break;
+
+ case IDM_WINDOW_ARRANGE:
+ arrange ();
+ {
+ BOOL Active;
+
+ Active = DebuggeeActive();
+ if (Active)
+ {
+ UpdateDebuggerState (UPDATE_WINDOWS);
+ }
+ }
+ break;
+
+ case IDM_WINDOW_NEWWINDOW:
+ AddFile(MODE_DUPLICATE, DOC_WIN, NULL, NULL, NULL, FALSE, curView, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_SOURCE_OVERLAY:
+ FSourceOverlay = !FSourceOverlay;
+ CheckMenuItem(hMainMenu, IDM_WINDOW_SOURCE_OVERLAY,
+ FSourceOverlay ? MF_CHECKED : MF_UNCHECKED);
+ break;
+
+ case IDM_WINDOW_CPU:
+ OpenDebugWindow(CPU_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_WATCH:
+ OpenDebugWindow(WATCH_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_LOCALS:
+ OpenDebugWindow(LOCALS_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_DISASM:
+ OpenDebugWindow(DISASM_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_COMMAND:
+ OpenDebugWindow(COMMAND_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_FLOAT:
+ OpenDebugWindow(FLOAT_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_MEMORY:
+ memView = -1;
+ _fmemset (&TempMemWinDesc,0,sizeof(struct memWinDesc));
+ TempMemWinDesc.iFormat = MW_BYTE; //default to byte display
+ OpenDebugWindow(MEMORY_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_WINDOW_CALLS:
+ OpenDebugWindow(CALLS_WIN, NULL, -1);
+ EnableRibbonControls( 0, FALSE );
+ break;
+
+ case IDM_HELP_CONTENTS:
+ Dbg(WinHelp(hwnd, szHelpFileName, HELP_CONTENTS, 0L));
+ break;
+
+ case IDM_HELP_SEARCH:
+
+ Dbg(WinHelp(hwnd, szHelpFileName, HELP_FORCEFILE, 0L));
+ Dbg(WinHelp(hwnd, szHelpFileName, HELP_PARTIALKEY,
+ (DWORD)(LPSTR)szNull));
+ break;
+
+ case IDM_HELP_ABOUT:
+
+ ShellAbout( hwnd, MainTitleText, NULL, NULL );
+ break;
+
+ //**************************************************
+ //Those following commands are not accessible via menus
+
+ case IDA_FINDNEXT:
+ if(hwndActiveEdit && !IsIconic(hwndActive)
+ && (curView != -1) && (Views[curView].Doc >= 0))
+ {
+ if (findReplace.findWhat[0] == '\0') {
+ if (StartDialog(DLG_FIND, DlgFind))
+ Find();
+ } else {
+ if (frMem.hDlgFindNextWnd) {
+
+ SetFocus(frMem.hDlgFindNextWnd);
+ SendMessage(frMem.hDlgFindNextWnd, WM_COMMAND, IDOK, 0L);
+ } else {
+ if (frMem.hDlgConfirmWnd) {
+
+ SetFocus(frMem.hDlgConfirmWnd);
+ SendMessage(frMem.hDlgConfirmWnd, WM_COMMAND, ID_CONFIRM_FINDNEXT, 0L);
+ }
+ else
+ FindNext(v->Y, v->X, v->BlockStatus, TRUE, TRUE);
+ }
+ }
+ } else
+ MessageBeep(0);
+ break;
+
+
+ case IDM_RUN_SOURCE_MODE:
+
+ //if (!status.fSrcMode && (lParam == 1L))
+ // {
+ // SendMessage(ribbon.hwndRibbon,WU_DISABLERIBBONCONTROL,ID_RIBBON_SMODE,0L);
+ // SendMessage(ribbon.hwndRibbon,WU_ENABLERIBBONCONTROL, ID_RIBBON_AMODE,0L);
+ // StatusSrc(!status.fSrcMode);
+ // }
+ // else
+ // {
+ // if (status.fSrcMode && (lParam == 0L))
+ // {
+ // SendMessage(ribbon.hwndRibbon,WU_ENABLERIBBONCONTROL,ID_RIBBON_SMODE,0L);
+ // SendMessage(ribbon.hwndRibbon,WU_DISABLERIBBONCONTROL,ID_RIBBON_AMODE,0L);
+ // StatusSrc(!status.fSrcMode);
+ // }
+ // }
+
+ SendMessage(ribbon.hwndRibbon,WU_DISABLERIBBONCONTROL,ID_RIBBON_SMODE,0L);
+ SendMessage(ribbon.hwndRibbon,WU_ENABLERIBBONCONTROL, ID_RIBBON_AMODE,0L);
+ StatusSrc(!status.fSrcMode);
+
+ ChangeDebuggerState();
+ EnableRibbonControls(ERC_ALL, FALSE);
+ break;
+
+ default:
+
+ //Check if user does not want to open one file from
+ //editor kept file names list
+ if (LOWORD(wParam) > IDM_FILE_EXIT
+ && LOWORD(wParam) <= (WORD)(IDM_FILE_EXIT + nbFilesKept[EDITOR_FILE])) {
+
+ LPSTR s;
+ int fileNb = LOWORD(wParam) - IDM_FILE_EXIT -1;
+
+ //Lock file name, copy it, and unlock it
+ Dbg(s = (LPSTR)GlobalLock(hFileKept[EDITOR_FILE][fileNb]));
+ lstrcpy(szPath, s);
+ Dbg(GlobalUnlock (hFileKept[EDITOR_FILE][fileNb]) == FALSE);
+
+ //Change to file dir and opens file
+
+ if (SetDriveAndDir(szPath))
+ AddFile(MODE_OPENCREATE, DOC_WIN, (LPSTR)szPath, NULL, NULL, FALSE, -1, -1);
+
+ break;
+ }
+
+ //Check if user does not want to open one file from
+ //project kept file names list
+ if (LOWORD(wParam) > IDM_PROGRAM_LAST
+ && LOWORD(wParam) <= (WORD)(IDM_PROGRAM_LAST
+ + nbFilesKept[PROJECT_FILE])) {
+
+ LPSTR s;
+ int fileNb = LOWORD(wParam) - IDM_PROGRAM_LAST - 1;
+
+ //Lock file name, copy it, and unlock it
+ Dbg(s = (LPSTR)GlobalLock(hFileKept[PROJECT_FILE][fileNb]));
+ lstrcpy(szPath, s);
+ Dbg(GlobalUnlock (hFileKept[PROJECT_FILE][fileNb]) == FALSE);
+
+ ProgramOpenPath( szPath );
+
+ break;
+ }
+
+ //Check if user does not want to open one file from
+ //windows menu list
+ if (LOWORD(wParam) >= IDM_WINDOWCHILD
+ && LOWORD(wParam) < (WORD)(IDM_WINDOWCHILD + MAX_VIEWS)) {
+
+ int view = LOWORD(wParam) - IDM_WINDOWCHILD;
+
+ if (Views[view].Doc != -1) {
+
+ //Restore window if necessary
+ if (IsIconic(Views[view].hwndFrame))
+ OpenIcon(Views[view].hwndFrame);
+
+ //Reactivate window
+ SendMessage(hwndMDIClient, WM_MDIACTIVATE,
+ (WPARAM) Views[view].hwndFrame, 0L);
+ } else
+ MessageBeep(0);
+ break;
+ }
+
+ goto DefProcessing;
+ }
+ break;
+
+ case WM_COMPACTING: {
+
+ int i;
+
+ if (!editorIsCritical) {
+ for (i = 0; i < MAX_DOCUMENTS; i++) {
+ if(Docs[i].FirstView != -1)
+ CompactDocument(i);
+ }
+ }
+
+ // Completely arbitrarily, try and decide whether we
+ // have enough memory to do a "soft" system-modal or not
+ if (GlobalCompact(0UL) > (30*1024UL))
+ {
+ // Soft
+ MsgBox(hwndFrame, LowMemoryMsg,
+ MB_OK|MB_TASKMODAL|MB_ICONINFORMATION);
+ }
+ else
+ {
+ // Hard
+ MsgBox(hwndFrame, LowMemoryMsg2,
+ MB_OK|MB_TASKMODAL|MB_ICONHAND);
+ }
+ }
+ return TRUE;
+
+ case WM_FONTCHANGE: {
+
+ int i, j, k;
+ HDC hDC;
+ HFONT font;
+ int fontPb = 0;
+ char faceName[LF_FACESIZE];
+
+ LoadFonts(hwnd);
+
+ //Check to see if the default font still exist
+
+ font = CreateFontIndirect(&defaultFont);
+ Dbg(hDC = GetDC(hwndFrame));
+ Dbg(SelectObject(hDC, font));
+ GetTextFace(hDC, LF_FACESIZE, faceName);
+ if (_strcmpi(faceName, (char FAR *) defaultFont.lfFaceName) != 0) {
+
+ TEXTMETRIC tm;
+
+ ErrorBox2(hwndFrame, MB_TASKMODAL, ERR_Lost_Default_Font, (LPSTR)defaultFont.lfFaceName, (LPSTR)faceName);
+
+ //Change characteristics of default font
+
+ GetTextMetrics(hDC, &tm);
+ defaultFont.lfHeight = tm.tmHeight;
+ defaultFont.lfWeight = tm.tmWeight;
+ defaultFont.lfPitchAndFamily = tm.tmPitchAndFamily;
+ lstrcpy((LPSTR) defaultFont.lfFaceName, faceName);
+ }
+ ReleaseDC(hwndFrame, hDC);
+ Dbg(DeleteObject(font));
+
+ //Ensure that each view still has an existing font, warn the
+ //user and load the closest font otherwise
+
+ for (i = 0; i < MAX_VIEWS; i++) {
+ if (Views[i].Doc != -1) {
+ k = 0;
+
+ //Get Face name of view
+
+ Dbg(hDC = GetDC(Views[i].hwndClient));
+ SelectObject(hDC, Views[i].font);
+ GetTextFace(hDC, LF_FACESIZE, faceName);
+ Dbg(ReleaseDC(Views[i].hwndClient, hDC));
+
+ //See if this font still exist
+
+ for (j = 0; j < fontsNb; j++)
+ if (_strcmpi((LPSTR) fonts[j].lfFaceName, (LPSTR) faceName) == 0)
+ k++;
+
+ //Substitute with default font if not found
+
+ if (k == 0) {
+ fontPb++;
+ Dbg(DeleteObject(Views[i].font));
+ Views[i].font = CreateFontIndirect(&defaultFont);
+ SetVerticalScrollBar(i, FALSE);
+ PosXY(i, Views[i].X, Views[i].Y, FALSE);
+ InvalidateLines(i, 0, LAST_LINE, TRUE);
+ }
+ }
+
+ }
+#ifdef FE_IME
+ // This is to let the edit window set new font
+ if (IsWindow(hwndActiveEdit)) {
+ SendMessage(hwndActiveEdit, message, wParam, lParam);
+ }
+#endif
+ if (fontPb > 0)
+ ErrorBox2(hwndFrame, MB_TASKMODAL, ERR_Lost_Font);
+ }
+ return TRUE;
+
+ case WM_INITMENU:
+
+ // RIBBON handling - a menu item has been selected.
+ // Catches keyboard menu selecting.
+ SendMessage(ribbon.hwndRibbon, WU_ESCAPEFROMRIBBON,
+ (WPARAM) hwndFrame, 0L);
+
+ if (GetWindowLong(hwnd, GWL_STYLE) & WS_ICONIC)
+ break;
+
+ //Set up the menu states and the filenames in menus for Project
+ LoadProgramMRUList();
+ InitializeMenu((HMENU)wParam);
+ return TRUE;
+
+
+ case WM_MENUSELECT:
+
+ // NOTENOTE Davegi MAKELPARAM is only defined in windowsx.h.
+
+ lastMenuId = LOWORD(wParam);
+
+ if( MAKELONG( 0, -1 ) == wParam ) {
+
+ //
+ // Menu is closed, clear the Status Bar.
+ //
+
+ menuID = 0;
+ StatusText( SYS_StatusClear, STATUS_INFOTEXT, FALSE );
+
+ } else if( HIWORD( wParam ) & MF_POPUP ) {
+
+ //
+ // Get the menuID for the pop-up menu.
+ //
+
+ menuID = GetPopUpMenuID(( HMENU ) lParam );
+
+ } else {
+
+ //
+ // Get the menuID for the menu item.
+ //
+
+ menuID = LOWORD( wParam );
+ }
+ return 0;
+
+ case WM_ENTERIDLE:
+ #define BETWEEN(inf, sup) (lastMenuId >= inf && lastMenuId <= sup)
+
+
+ if ((wParam == MSGF_MENU)
+ && (GetKeyState(VK_F1) & 0x8000)
+ && (lastMenuIdState == 0)) {
+
+ if (BETWEEN(IDM_FILE_FIRST, IDM_FILE_LAST)
+ || BETWEEN(IDM_EDIT_FIRST, IDM_EDIT_LAST)
+ || BETWEEN(IDM_VIEW_FIRST, IDM_VIEW_LAST)
+ || BETWEEN(IDM_PROGRAM_FIRST, IDM_PROGRAM_LAST)
+ || BETWEEN(IDM_RUN_FIRST, IDM_RUN_LAST)
+ || BETWEEN(IDM_DEBUG_FIRST, IDM_DEBUG_LAST)
+ || BETWEEN(IDM_OPTIONS_FIRST, IDM_OPTIONS_LAST)
+ || BETWEEN(IDM_WINDOW_FIRST, IDM_WINDOW_LAST)
+ || BETWEEN(IDM_HELP_FIRST, IDM_HELP_LAST)) {
+
+ bHelp = TRUE;
+ Dbg(WinHelp(hwnd, szHelpFileName, (DWORD) HELP_CONTEXT,(DWORD)lastMenuId));
+ }
+ else
+ MessageBeep(0);
+
+ } else if ((wParam == MSGF_DIALOGBOX) && (GetKeyState(VK_F1) & 0x8000)) {
+
+ //Is it one of our dialog boxes
+
+ if (GetDlgItem((HANDLE) lParam, IDWINDBGHELP)) {
+ Dbg(PostMessage((HANDLE) lParam, WM_COMMAND, IDWINDBGHELP, 0L));
+ } else {
+
+ // The only dialog boxes having special help id
+ // are from COMMDLG module (Files pickers)
+
+ if (GetDlgItem((HANDLE) lParam, psh15)) {
+ Dbg(PostMessage((HANDLE) lParam, WM_COMMAND, psh15, 0L));
+ } else {
+ MessageBeep(0);
+ }
+ }
+
+ }
+
+ StatusText( menuID, STATUS_MENUTEXT, FALSE );
+ break;
+
+ case WM_CLOSE:
+ TerminateApplication(hwnd, wParam);
+ ExitProcess(0);
+ break;
+
+ case WM_QUERYENDSESSION:
+ //Are we re-entering ?
+ if (BoxCount != 0) {
+ ErrorBox2(GetActiveWindow(), MB_TASKMODAL, ERR_Cannot_Quit);
+ return 0;
+ } else {
+
+ //Before session ends, check that all files are saved
+ //And that it is ok to quit when debugging
+
+ if (DebuggeeActive() &&
+ (QuestionBox(ERR_Close_When_Debugging, MB_YESNO) != IDYES))
+ {
+ return 0;
+ }
+ return QueryCloseAllDocs();
+ }
+
+ case WM_DESTROY:
+#ifdef FE_IME
+ ImeTerm();
+#endif
+ PostQuitMessage(0);
+ QuitTheSystem = TRUE;
+ break;
+
+#ifdef FE_IME
+ case WM_SETFOCUS:
+ if (!hwndActive) {
+ ImeSendVkey(hwnd, VK_DBE_FLUSHSTRING);
+ bOldImeStatus = ImeWINNLSEnableIME(NULL, FALSE);
+ }
+ goto DefProcessing;
+
+ case WM_KILLFOCUS:
+ if (!hwndActive) {
+ ImeWINNLSEnableIME(NULL, bOldImeStatus);
+ }
+ goto DefProcessing;
+
+ case WM_MOVE:
+ // This is to let the edit window
+ // set a position of IME conversion window
+ if (hwndActive) {
+ SendMessage(hwndActive, WM_MOVE, 0, 0);
+ }
+ break;
+#endif
+
+ case WM_SIZE:
+ {
+ RECT rc;
+ WORD rib_height = 0;
+ WORD sta_height = 0 ; // do what ribbon does
+
+ GetClientRect (hwnd, &rc);
+
+ //On creation or resize, size the MDI client,
+ //status line and ribbon.
+
+ if (!status.hidden) {
+
+ RECT r;
+
+ r.left = rc.left ;
+ r.top = rc.bottom - status.height ;
+ r.right = rc.right - rc.left ;
+ r.bottom = rc.bottom ;
+
+ sta_height = status.height;
+
+ MoveWindow(status.hwndStatus,
+ r.left, r.top,
+ r.right - r.left, r.bottom - r.top,
+ FALSE) ;
+ GetClientRect(status.hwndStatus, &r) ;
+ UpdateStatus(STATUS_SIZE, &r) ;
+ }
+ if (!ribbon.hidden) {
+
+ RECT r;
+
+ r.left = rc.left;
+ r.top = rc.top;
+ r.right = rc.right - rc.left;
+ r.bottom = rc.top + ribbon.height;
+
+ rib_height = ribbon.height;
+
+ MoveWindow(ribbon.hwndRibbon,
+ r.left, r.top,
+ r.right - r.left, r.bottom - r.top,
+ FALSE);
+ GetClientRect(ribbon.hwndRibbon, &r) ;
+ UpdateRibbon(RIBBON_SIZE, &r);
+ }
+ MoveWindow(hwndMDIClient,
+ rc.left, rc.top + rib_height,
+ rc.right - rc.left,
+ rc.bottom - rc.top - sta_height - rib_height,
+ TRUE);
+
+ SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
+#ifdef FE_IME
+ // This is to let the edit window
+ // set a position of IME conversion window
+ if (hwndActive) {
+ SendMessage(hwndActive, WM_MOVE, 0, 0);
+ }
+#endif
+ }
+ ChangeDebuggerState();
+ return TRUE;
+
+ case WM_SYSCOMMAND:
+ {
+ LONG ret;
+
+
+ //RIBBON handing - catches mouse clicks in
+ //system menu area which won't activate a menu
+
+ SendMessage(ribbon.hwndRibbon, WU_ESCAPEFROMRIBBON, (WPARAM) hwndFrame, 0L);
+
+ // Handle title bar
+
+ if ((wParam == SC_NEXTWINDOW) ||
+ (wParam == SC_PREVWINDOW))
+ {
+ UpdateTitleBar(-1, TRUE);
+ }
+
+ ret = DefFrameProc(hwnd, hwndMDIClient, message, wParam, lParam);
+
+ // Handle title bar
+
+ if ((wParam == SC_MAXIMIZE) ||
+ (wParam == SC_MINIMIZE) ||
+ (wParam == SC_RESTORE))
+ {
+ UpdateTitleBar(-1, TRUE);
+ }
+
+ return ret;
+ }
+
+ case WM_MOUSEACTIVATE:
+ if (HIWORD(lParam) == WM_RBUTTONDOWN) {
+ return MA_ACTIVATE;
+ }
+ SendMessage(ribbon.hwndRibbon, WU_ESCAPEFROMRIBBON, (WPARAM) hwndFrame, 0L);
+ if (bChildFocus == TRUE) {
+ bChildFocus = FALSE;
+ if (LOWORD(lParam) == HTCLIENT) {
+ return MA_ACTIVATEANDEAT;
+ }
+ }
+ goto DefProcessing;
+
+ case WM_ACTIVATEAPP:
+
+ if (IsIconic(hwndFrame)) {
+
+ checkFileDate = TRUE;
+
+ } else if (wParam == 0) {
+
+ //
+ // RIBBON handling - our app might be deactivated
+ //
+
+ SendMessage(ribbon.hwndRibbon, WU_ESCAPEFROMRIBBON, 0, 0L);
+
+ } else {
+ int k, fst;
+ struct _stat fileStat;
+
+ // Check the opened files to see if files has been changed
+ // by another App
+
+ for (k = 0; k < MAX_DOCUMENTS; k++) {
+
+ if ((Docs[k].FirstView != -1) &&
+ (Docs[k].docType == DOC_WIN)) {
+
+ if ((fst=_stat(Docs[k].FileName, &fileStat)) == 0) {
+
+ //
+ // Compare our internal date and file's date,
+ // if changed ask (later) the user what he
+ // thinks about it.
+ //
+
+ if ((fileStat.st_mtime > Docs[k].time) &&
+ (!Docs[k].bChangeFileAsk)) {
+
+ Docs[k].bChangeFileAsk = TRUE;
+ PostMessage(hwndFrame,
+ WU_RELOADFILE,
+ k,
+ SYS_File_Changed);
+ }
+
+ } else if (fst == -1 &&
+ errno == ENOENT &&
+ !Docs[k].untitled) {
+
+ PostMessage(hwndFrame,
+ WU_RESAVEFILE,
+ 0,
+ (LONG)(LPSTR)Docs[k].FileName);
+ }
+ }
+ }
+ }
+
+ goto DefProcessing;
+
+
+ /*
+ ** Somebody requeseted that the screen be updated
+ */
+ case DBG_REFRESH:
+ CmdExecNext(wParam, lParam);
+ break;
+
+ case WU_RELOADFILE:
+ {
+ NPDOCREC docs = &Docs[wParam];
+ WORD modalType;
+
+ Assert(docs->docType == DOC_WIN);
+
+ //
+ // User may have clicked in the editing window, clear timer
+ // and release mouse capture
+ //
+
+ if (curView != -1) {
+ KillTimer(Views[curView].hwndClient, 100);
+ ReleaseCapture();
+ }
+
+ if (AutoTest) {
+ modalType = MB_TASKMODAL;
+ } else {
+ modalType = MB_TASKMODAL;
+ }
+
+ //Ask user for doc reloading
+
+ if (QuestionBox2(hwndFrame,
+ LOWORD(lParam),
+ (WORD)(MB_YESNO | modalType),
+ (LPSTR)docs->FileName) == IDYES) {
+ int *pV;
+
+ editorIsCritical = TRUE;
+
+ //Refresh contents
+
+ if (OpenDocument(MODE_RELOAD, DOC_WIN, wParam, docs->FileName,
+ -1, -1) != -1) {
+
+ StatusReadOnly(docs->readOnly);
+
+ //Clear selection and move up the cursor if text is smaller
+ //(for each view)
+
+ pV = &docs->FirstView;
+ while (*pV != -1) {
+ ClearSelection(*pV);
+ if (Views[*pV].Y >= docs->NbLines) {
+ Views[*pV].Y = docs->NbLines - 1;
+ }
+ SetVerticalScrollBar(*pV, FALSE);
+ PosXY(*pV, 0, Views[*pV].Y, FALSE);
+ EnsureScrollBars(*pV, FALSE);
+ pV = &Views[*pV].NextView;
+ }
+
+ //Display any debug/error tags/lines
+
+ SetDebugLines(wParam, TRUE);
+
+ //Refresh possible views of changed documents
+
+ InvalidateLines(docs->FirstView, 0, LAST_LINE, TRUE);
+
+ editorIsCritical = FALSE;
+ }
+ } else {
+ struct _stat sfileStat;
+
+ //Set the opened doc file struct timewise
+
+ _stat(docs->FileName, &sfileStat);
+ docs->time = sfileStat.st_mtime;
+ }
+
+ docs->bChangeFileAsk = FALSE;
+ }
+ break;
+
+
+ case WU_RESAVEFILE:
+ {
+ WORD modalType;
+
+
+ //User may have clicked in the editing window, clear timer
+ //and release mouse capture
+ if (curView != -1) {
+
+ KillTimer(Views[curView].hwndClient, 100);
+ ReleaseCapture();
+ }
+
+
+ //Are we in test mode or not
+
+ if (AutoTest)
+ modalType = MB_TASKMODAL;
+ else
+ modalType = MB_TASKMODAL;
+
+ //Ask user for doc reloading
+
+ ErrorBox (ERR_File_Deleted,(LPSTR)lParam);
+
+ }
+ break;
+
+
+
+
+ DefProcessing:
+ default:
+ return DefFrameProc(hwnd, hwndMDIClient, message, wParam, lParam);
+ }
+ return (0l);
+} /* MainWndProc() */
+
+
+/****************************************************************************
+
+ FUNCTION : MDIChildWndProc
+
+ PURPOSE : The window function for the individual document windows,
+ each of which has a "note". Each of these windows contain
+ one multi-line edit control filling their client area.
+
+****************************************************************************/
+LONG FAR PASCAL EXPORT MDIChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LONG lParam)
+{
+ HWND hwndEdit;
+
+ switch (message) {
+ case WM_CREATE:
+ {
+ MDICREATESTRUCT FAR *p;
+ TEXTMETRIC tm;
+ HDC hDC;
+ DWORD style;
+ char class[MAX_MSG_TXT];
+ int newView;
+ NPVIEWREC v;
+
+ //Remember the window handle and initialize some window attributes
+ p = (MDICREATESTRUCT FAR *)(((CREATESTRUCT FAR *)lParam)->lpCreateParams);
+ newView = (int)p->lParam;
+ Assert(newView >= 0 && newView < MAX_VIEWS && Views[newView].hwndClient == 0);
+ v = &Views[newView];
+
+ style = WS_CHILD | WS_MAXIMIZE | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL;
+
+ Dbg(LoadString(hInst, SYS_Edit_wClass, class, MAX_MSG_TXT));
+
+ hwndEdit = CreateWindow((LPSTR)class, NULL, style, 0, 0, 0, 0,
+ hwnd, (HMENU) ID_EDIT, hInst, (LPSTR)p->lParam);
+
+ //Remember the window handle
+
+ SetWindowHandle(hwnd, GWW_EDIT, (WPARAM)hwndEdit);
+ v->hwndClient = hwndEdit;
+#ifdef DBCS
+ v->bDBCSOverWrite = TRUE;
+#endif
+
+ //Remember the window view
+
+ SetWindowWord(hwnd, GWW_VIEW, (WORD)newView);
+
+ //Initialize font information for window
+
+ hDC = GetDC(hwndEdit);
+
+ //If we open the file from workspace, font is already
+ //created
+
+ if (v->font == NULL)
+ v->font = CreateFontIndirect((LPLOGFONT)&defaultFont);
+
+ //Store all information about fonts
+
+ SelectObject(hDC, v->font);
+ GetTextMetrics(hDC, &tm);
+ v->BlockStatus = FALSE;
+ v->charHeight = tm.tmHeight;
+ v->maxCharWidth =tm.tmMaxCharWidth;
+ v->aveCharWidth =tm.tmAveCharWidth;
+ v->charSet = tm.tmCharSet;
+ GetCharWidth(hDC, 0, MAX_CHARS_IN_FONT - 1, (LPINT)v->charWidth);
+#ifdef DBCS
+ GetDBCSCharWidth(hDC, &tm, v);
+#endif
+ ReleaseDC(hwndEdit, hDC);
+
+
+
+
+ // initialize DOC structure readonly flags/values
+
+ Docs[Views[p->lParam].Doc].RORegionSet = FALSE;
+ Docs[Views[p->lParam].Doc].RoX2 = 0;
+ Docs[Views[p->lParam].Doc].RoY2 = 0;
+
+
+ //Set vertical scroll-bar position
+
+ SetScrollPos(hwndEdit, SB_VERT, 0, TRUE);
+
+ //Set horizontal scroll-bar position
+
+ SetScrollRange(hwndEdit, SB_HORZ, 0, MAX_USER_LINE, FALSE);
+ SetScrollPos(hwndEdit, SB_HORZ, 0, TRUE);
+
+ if (Docs[Views[p->lParam].Doc].docType != DOC_WIN) {
+
+ WNDPROC lpfnNewEditProc, NewEditProc;
+
+ switch (Docs[Views[p->lParam].Doc].docType) {
+
+ case DISASM_WIN:
+ NewEditProc = (WNDPROC) DisasmEditProc;
+ break;
+
+ case COMMAND_WIN:
+ NewEditProc = (WNDPROC) CmdEditProc;
+ break;
+
+ case MEMORY_WIN:
+ NewEditProc = (WNDPROC) MemoryEditProc;
+ break;
+
+ default:
+ Assert(FALSE);
+ return FALSE;
+ break;
+ }
+
+ //Sub-class the editor proc for the specialized windows
+ lpfnEditProc = (WNDPROC)GetWindowLong(Views[p->lParam].hwndClient, GWL_WNDPROC);
+
+
+ lpfnNewEditProc = (WNDPROC)NewEditProc;
+
+ SetWindowLong(Views[p->lParam].hwndClient, GWL_WNDPROC, (LONG)lpfnNewEditProc);
+
+ //Init the new subclassed proc window
+ SendMessage(Views[p->lParam].hwndClient, WU_INITDEBUGWIN, 0, p->lParam);
+ }
+
+ SetFocus(hwndEdit);
+ ChangeDebuggerState();
+ break;
+ }
+
+
+ case WM_MDIACTIVATE:
+
+ //If we're activating this child, remember it
+
+ if (hwnd == (HWND) lParam) // activating
+ {
+
+ int curDoc;
+ NPDOCREC d;
+
+ hwndActive = hwnd;
+ hwndActiveEdit = (HWND)GetWindowHandle(hwnd, GWW_EDIT);
+
+ //Get global current view
+ curView = GetWindowWord(hwndActiveEdit, GWW_VIEW);
+ curDoc = Views[curView].Doc;
+ Assert (curView >= 0 && curView < MAX_VIEWS && curDoc != -1);
+
+ d = &Docs[Views[curView].Doc];
+
+
+
+ if (Views[curView].Doc > -1)
+ {
+ d = &Docs[Views[curView].Doc];
+
+ if (d->docType == MEMORY_WIN)
+ {
+ int memcurView = GetWindowWord((HWND)GetWindowHandle(hwnd, GWW_EDIT), GWW_VIEW);
+ int curDoc = Views[memcurView].Doc; //memcurView may change during loop
+
+ if (Docs[curDoc].docType == MEMORY_WIN)
+ {
+ memView = memcurView;
+ _fmemcpy (&MemWinDesc,&MemWinDesc[memView],sizeof(struct memWinDesc));
+ ViewMem (memView, FALSE);
+ }
+ }
+
+ }
+
+
+
+
+
+ //Change Status Bar ReadOnly
+
+ StatusReadOnly(Docs[curDoc].readOnly);
+
+ // Update ribbon for new document
+
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ //To avoid problem of focus lost when an MDI window is
+ //reactivated and when the previous activated window was
+ //minimized. (Could be a bug in MDI or in my brain, seems
+ //to be linked with the fact that our MdiClientChildClient
+ //is not a standard class window)
+
+
+ if (!IsIconic(hwnd))
+ {
+ SetFocus(hwndActiveEdit);
+
+ if (bOffRibbon == TRUE)
+ {
+ bOffRibbon = FALSE; //resets
+ }
+ else
+ {
+ bChildFocus = TRUE;
+ }
+
+ }
+ } else {
+ //Unselect previous window view menu item
+
+ CheckMenuItem(hWindowSubMenu,
+ (WORD) FindWindowMenuId(Docs[Views[curView].Doc].docType, curView, TRUE),
+ MF_UNCHECKED);
+
+ //Updates status bar.
+
+ StatusReadOnly(FALSE);
+ StatusLineColumn(0, 0);
+
+ hwndActive = NULL;
+ hwndActiveEdit = NULL;
+ curView = -1;
+ }
+ break;
+
+
+ case WM_CLOSE:
+
+ {
+
+
+ int i;
+ int curDoc = Views[curView].Doc; //curView may change during loop
+ BOOL closeIt = TRUE;
+ struct _stat fileStat;
+
+ if (curDoc >= 0 &&
+ Docs[curDoc].docType == DOC_WIN && Docs[curDoc].ismodified) {
+
+ //Ask user whether to save / not save / cancel
+ switch (QuestionBox(SYS_Save_Changes_To,
+ MB_YESNOCANCEL ,
+ (LPSTR)Docs[curDoc].FileName)) {
+ case IDYES:
+
+ //User wants file saved
+ if (SaveFile(curDoc)) {
+ //Reset file creation/load/save time
+ _stat(Docs[curDoc].FileName, &fileStat);
+ Docs[curDoc].time = fileStat.st_mtime;
+ Docs[curDoc].ismodified = FALSE;
+ } else {
+ closeIt = FALSE;
+ }
+ break;
+
+ case IDNO:
+
+ FileNotSaved(curDoc);
+ Docs[curDoc].ismodified = FALSE;
+ break;
+
+ default:
+
+ //We couldn't do the messagebox, or not ok to close
+ if (!CheckDocument(curDoc)) {
+ ErrorBox(ERR_Document_Corrupted);
+ }
+ closeIt = FALSE;
+ break;
+ }
+
+ }
+ if (closeIt)
+ {
+ for (i = 0; i < MAX_VIEWS; i++)
+ {
+ if (Views[i].Doc == curDoc)
+ {
+ if (IsZoomed (Views[i].hwndFrame))
+ {
+ ShowWindow (Views[i].hwndFrame, SW_RESTORE);
+
+ break;
+
+ }
+ }
+ }
+ }
+ }
+
+
+ //If its OK to close the child, do so, else ignore
+
+ if (QueryCloseChild(GetWindowHandle(hwnd, GWW_EDIT), FALSE))
+ goto CallDCP;
+ else
+ break;
+
+ case WM_ERASEBKGND:
+ //Do nothing, paint will handle it
+
+ break;
+
+ case WM_MOVE: {
+
+ int view;
+
+ view = GetWindowWord(GetWindowHandle(hwnd, GWW_EDIT), GWW_VIEW);
+ Assert(view >=0 && view < MAX_VIEWS);
+
+ //Save the window size (not when maximized or minimized)
+
+ if (!IsIconic(hwnd) && !IsZoomed(hwnd))
+ GetWindowRect(hwnd, (LPRECT)&Views[view].rFrame);
+ ChangeDebuggerState();
+#ifdef FE_IME
+ // This is to let the edit window
+ // set a position of IME conversion window
+ if (GetWindowHandle(hwnd, GWW_EDIT)) {
+ SendMessage(GetWindowHandle(hwnd, GWW_EDIT), WM_MOVE, 0, 0);
+ }
+ break;
+#endif
+ goto CallDCP;
+ }
+
+ case WM_SIZE: {
+
+ int view;
+ NPVIEWREC v;
+ NPDOCREC d;
+
+ view = GetWindowWord(GetWindowHandle(hwnd, GWW_EDIT), GWW_VIEW);
+ Assert(view >=0 && view < MAX_VIEWS);
+ v = &Views[view];
+ d = &Docs[Views[view].Doc];
+
+
+ if (Views[view].Doc > 0)
+ {
+ if (d->docType == MEMORY_WIN)
+ {
+ InMemUpdate = STARTED; // prevent multiple viemem() calls
+ }
+ }
+
+
+ //Adjust and display window titlebar text
+
+ RefreshWindowsTitle(v->Doc);
+
+ //Save the window size (not when maximized or minimized)
+
+ if (wParam != SIZEICONIC && wParam != SIZEFULLSCREEN)
+ GetWindowRect(hwnd, (LPRECT)&v->rFrame);
+
+ //Also resize the edit control
+
+ if (wParam != SIZEICONIC) {
+
+ //Set client to it's new size
+
+ MoveWindow(v->hwndClient, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
+
+ //Update scrollbars status and resize the window
+
+ EnsureScrollBars(view, TRUE);
+
+ // Make sure that the caret is visible...(this needs more thought!)
+
+ PostMessage (v->hwndClient, EM_SCROLLCARET, 0, 0);
+ }
+
+ ChangeDebuggerState();
+
+
+ if (Views[view].Doc > 0) {
+ if (d->docType == MEMORY_WIN) {
+ InMemUpdate = FINISHED; // prevent multiple viemem() calls
+ }
+ }
+
+
+ goto CallDCP;
+ }
+
+ case WM_INITMENU:
+ // RIBBON handling - a menu item has been selected in
+ // a child (especially via the keyboard).
+
+ SendMessage(ribbon.hwndRibbon, WU_ESCAPEFROMRIBBON,
+ (WPARAM) hwndFrame, 0L);
+ goto CallDCP;
+
+ case WM_SETFOCUS:
+ SetFocus(GetWindowHandle(hwnd, GWW_EDIT));
+ break;
+
+ default:
+ CallDCP:
+
+ //MDI default behaviour is different, call DefMDIChildProc
+ //instead of DefWindowProc()
+
+ return DefMDIChildProc(hwnd, message, wParam, lParam);
+ }
+ return FALSE;
+} /* MDIChildWndProc() */
+
+LONG FAR PASCAL EXPORT
+ChildWndProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ PAINTSTRUCT ps;
+#ifdef FE_IME
+ static BOOL bOldImeStatus;
+#endif
+
+
+ switch (message) {
+
+ case WM_CREATE:
+ {
+ //WARNING : lParam is NOT a pointer to a Valid CREATESTRUCT
+ //but holds the view number.
+ long l;
+
+ l = (long)((CREATESTRUCT FAR *)lParam)->lpCreateParams;
+ Assert (l >= 0 && l < MAX_VIEWS);
+
+ //Remember the window handle
+
+ SetWindowWord(hwnd, GWW_VIEW, (WORD)l);
+
+ break;
+ }
+
+ case WM_RBUTTONDOWN:
+ {
+ int XL,XR;
+ int YL,YR;
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ if (Views[view].BlockStatus) {
+ GetBlockCoord(view, &XL, &YL, &XR, &YR);
+ PasteStream(view, XL, YL, XR, YR);
+ ClearSelection(view);
+ if (view == cmdView) {
+ PosXY(view,
+ GetLineLength(view, FALSE, Docs[Views[view].Doc].NbLines - 1),
+ Docs[Views[view].Doc].NbLines - 1, FALSE);
+ }
+ } else {
+ SendMessage(hwnd, WM_PASTE, 0, 0L);
+ }
+ }
+ break;
+
+ case WM_SETFOCUS:
+ //Set cursor position
+ if (!emergency && !editorIsCritical) {
+
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ NPVIEWREC v = &Views[view];
+ NPDOCREC d;
+
+
+ curView = view;
+ CreateCaret(hwnd, 0, 3, v->charHeight);
+ SetCaret(view, v->X, v->Y, -1);
+ ShowCaret(hwnd);
+ StatusLineColumn(v->Y + 1, v->X + 1);
+#ifdef FE_IME
+ d = &Docs[Views[view].Doc];
+
+ if (d->docType == DOC_WIN
+ || d->docType == MEMORY_WIN
+ || d->docType == COMMAND_WIN) {
+ bOldImeStatus = ImeWINNLSEnableIME(NULL, TRUE);
+ ImeSetFont(hwnd, v->font);
+ if (!IsWindowVisible(hwnd)) {
+ ImeMoveConvertWin(hwnd, -1, -1);
+ }
+ } else {
+ ImeSendVkey(hwnd, VK_DBE_FLUSHSTRING);
+ bOldImeStatus = ImeWINNLSEnableIME(NULL, FALSE);
+ }
+#endif
+
+ if (Views[curView].Doc > -1) {
+ d = &Docs[Views[curView].Doc];
+
+ if (d->docType == MEMORY_WIN) {
+ int memcurView, curDoc;
+ HWND hwndEdit = (HWND)GetWindowHandle(hwnd, GWW_EDIT);
+ if (hwndEdit != NULL)
+ memcurView = GetWindowWord(hwndEdit, GWW_VIEW);
+ else
+ memcurView = 0;
+ //memcurView may change during loop
+ curDoc = Views[memcurView].Doc;
+
+ if (Docs[curDoc].docType == MEMORY_WIN) {
+ memView = memcurView;
+ _fmemcpy (&MemWinDesc,
+ &MemWinDesc[memView],
+ sizeof(struct memWinDesc));
+ ViewMem (memView, FALSE);
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_KILLFOCUS:
+ //Set cursor position
+ if (!emergency && !editorIsCritical) {
+ //Remember the window view
+
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ NPVIEWREC v = &Views[view];
+
+ SetWindowWord(hwnd, GWW_VIEW, (WORD)view);
+ HideCaret(hwnd);
+#ifdef FE_IME
+ {
+ NPDOCREC d;
+ d = &Docs[Views[view].Doc];
+
+ if (d->docType == DOC_WIN
+ || d->docType == MEMORY_WIN
+ || d->docType == COMMAND_WIN) {
+ ImeSetFont(hwnd, NULL);
+ ImeMoveConvertWin(hwnd, -1, -1);
+ }
+ ImeWINNLSEnableIME(NULL, bOldImeStatus);
+ }
+#endif
+ DestroyCaret();
+ }
+ break;
+
+#ifdef FE_IME
+ case WM_MOVE:
+ case WM_SIZE:
+ if (GetFocus() == hwnd
+ && !emergency && !editorIsCritical) {
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ NPVIEWREC v = &Views[view];
+
+ // This is to set the position of IME conversion window
+ SetCaret(view, v->X, v->Y, -1);
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ break;
+#endif
+
+#ifdef FE_IME
+ case WM_FONTCHANGE:
+ // This message is sent only from MainWndProc
+ // (not from system)
+ if (!emergency && !editorIsCritical) {
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+ NPVIEWREC v = &Views[view];
+
+ ImeSetFont(hwnd, v->font);
+ }
+ break;
+#endif
+
+ case WM_LBUTTONDBLCLK:
+ {
+ int view = GetWindowWord(hwnd, GWW_VIEW);
+
+ ButtonDown(view, wParam, LOWORD(lParam), HIWORD(lParam));
+ ButtonUp(view, wParam, LOWORD(lParam), HIWORD(lParam));
+ GetWordAtXY(view, Views[view].X, Views[view].Y,
+ TRUE, NULL, TRUE, NULL, 0, NULL, NULL);
+ break;
+ }
+
+ case WM_PAINT:
+ BeginPaint(hwnd, &ps);
+ if (!editorIsCritical) {
+ PaintText(GetWindowWord(hwnd, GWW_VIEW), ps.hdc, &ps.rcPaint);
+ } else {
+ AuxPrintf(1, "WM_PAINT editorWasCritical");
+ }
+ EndPaint(hwnd, &ps);
+ break;
+
+ case WM_TIMER:
+ if (wParam == 100) {
+ TimeOut(GetWindowWord(hwnd, GWW_VIEW));
+ } else {
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ ButtonDown(GetWindowWord(hwnd, GWW_VIEW), wParam, LOWORD(lParam), HIWORD(lParam));
+ break;
+
+ case WM_LBUTTONUP:
+ ButtonUp(GetWindowWord(hwnd, GWW_VIEW), wParam, (int)(signed short)LOWORD(lParam), (int)(signed short)HIWORD(lParam));
+ break;
+
+
+ case WM_MOUSEMOVE:
+ MouseMove(GetWindowWord(hwnd, GWW_VIEW), wParam, (int)(signed short)LOWORD(lParam), (int)(signed short)HIWORD(lParam));
+ break;
+
+ case WM_VSCROLL:
+ VertScroll((WORD) GetWindowWord(hwnd, GWW_VIEW), wParam, lParam);
+ break;
+
+ case WM_HSCROLL:
+ HorzScroll((WORD) GetWindowWord(hwnd, GWW_VIEW), wParam, lParam);
+ break;
+
+ case WM_KEYDOWN:
+ if (!IsIconic(GetParent(hwnd))) {
+ isShiftDown = (GetKeyState(VK_SHIFT) < 0);
+ isCtrlDown = (GetKeyState(VK_CONTROL) < 0);
+ KeyDown((WORD) GetWindowWord(hwnd, GWW_VIEW), wParam,
+ isShiftDown, isCtrlDown);
+ }
+ break;
+
+ case WM_CHAR:
+
+ if (!IsIconic(GetParent(hwnd))) {
+ //Key is being pressed
+ PressChar(hwnd, wParam, lParam);
+ }
+ break;
+
+#ifdef FE_IME
+ case WM_IME_REPORT:
+ if (IR_STRING == wParam) {
+ return(ProccessIMEString(hwnd, lParam));
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ break;
+#endif
+
+ case WM_ERASEBKGND:
+
+ //Let WM_PAINT do the job
+ return FALSE;
+
+ case WM_PASTE:
+
+ if (OpenClipboard(hwnd)) {
+ HANDLE hData;
+ DWORD size;
+ LPSTR p1;
+ LPSTR p;
+ int nLines, cCol;
+ int x, y;
+ int XL,XR;
+ int YL,YR;
+ int pos;
+
+
+
+ hData = GetClipboardData(CF_TEXT);
+
+ if (hData && (size = GlobalSize (hData))) {
+ if (size >= MAX_CLIPBOARD_SIZE) {
+ ErrorBox(ERR_Clipboard_Overflow);
+ } else if ( p = GlobalLock(hData) ) {
+
+ x = Views[curView].X;
+ y = Views[curView].Y;
+ p1 = p;
+ nLines = 0;
+
+ if (Views[curView].BlockStatus)
+ {
+ GetBlockCoord(curView, &XL, &YL, &XR, &YR);
+ cCol = XL;
+ pos = y - (YR - YL);
+ }
+ else
+ {
+ cCol = x;
+ pos = y;
+ }
+ while (size && *p1) {
+#ifdef DBCS
+ if (IsDBCSLeadByte(*p1) && size > 1) {
+ size -= 2;
+ p1 += 2;
+ continue;
+ } else
+#endif
+ if (*p1 == '\n') {
+ ++nLines;
+ cCol = 0;
+ } else if (*p1 != '\r') {
+ ++cCol;
+ } else {
+ ++nLines;
+ cCol = 0;
+ if (p1[1] == '\n') {
+ ++p1;
+ --size;
+ }
+ }
+ --size;
+ ++p1;
+ }
+ InsertStream(curView, x, y, p1-p, p, TRUE);
+ DbgX(GlobalUnlock (hData) == FALSE);
+ PosXY(curView, cCol, pos+nLines, TRUE);
+ }
+ }
+ CloseClipboard();
+ }
+ return 0;
+
+ case WM_DESTROY:
+ DestroyView(GetWindowWord(hwnd, GWW_VIEW));
+ break;
+
+ default:
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ return FALSE;
+}
+
+#ifdef PROFILER_HACK
+
+/************ Profiler hacks ******************/
+
+int EMFunc(int, int, int, int, int);
+int TLFunc( int, int, int, int);
+int DMFunc(int, int);
+int EEInitializeExpr(int, int);
+int SHInit(int, int);
+
+Profile()
+{
+ EMFunc(0, 0, 0, 0, 0);
+ TLFunc(0, 0, 0, 0);
+ DMFunc(0, 0);
+ EEInitializeExpr(0, 0);
+ SHInit(0, 0);
+}
+
+#endif
diff --git a/private/windbg/windbg/windbg.rc b/private/windbg/windbg/windbg.rc
new file mode 100644
index 000000000..9b35e0711
--- /dev/null
+++ b/private/windbg/windbg/windbg.rc
@@ -0,0 +1,296 @@
+#undef DEBUGGING
+
+
+
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Windows NT GUI symbolic debugger"
+#define VER_INTERNALNAME_STR "windbg.exe\0"
+#define VER_ORIGINALFILENAME_STR "windbg.exe\0"
+
+#include <common.ver>
+#include "dlgs.h"
+#include "windbg.h"
+#include "dialogs.h"
+#include "menu.h"
+#include "dialogs.dlg"
+#include "resource.h"
+
+QCQPICON ICON "bitmaps/windbg.ico"
+HELPCURSOR CURSOR "bitmaps/help.cur"
+DOCICON ICON "bitmaps/source.ico"
+CPUICON ICON "bitmaps/qcreg.ico"
+LOCALSICON ICON "bitmaps/qclocal.ico"
+WATCHICON ICON "bitmaps/qcwatch.ico"
+DISASMICON ICON "bitmaps/asm.ico"
+CMDICON ICON "bitmaps/qcsource.ico"
+FLOATICON ICON "bitmaps/qcfloat.ico"
+MEMORYICON ICON "bitmaps/memory.ico"
+
+//
+// Bitmaps for Windbg buttons.
+//
+
+VGA_FORMAT_NORMAL BITMAP "bitmaps/opt-up.bmp"
+VGA_FORMAT_PUSHED BITMAP "bitmaps/opt-dn.bmp"
+VGA_FORMAT_GRAYED BITMAP "bitmaps/opt-da.bmp"
+VGA_TRACE_NORMAL BITMAP "bitmaps/trace-up.bmp"
+VGA_TRACE_PUSHED BITMAP "bitmaps/trace-dn.bmp"
+VGA_TRACE_GRAYED BITMAP "bitmaps/trace-da.bmp"
+VGA_STEP_NORMAL BITMAP "bitmaps/step-up.bmp"
+VGA_STEP_PUSHED BITMAP "bitmaps/step-dn.bmp"
+VGA_STEP_GRAYED BITMAP "bitmaps/step-da.bmp"
+VGA_BREAK_NORMAL BITMAP "bitmaps/brkpt-up.bmp"
+VGA_BREAK_PUSHED BITMAP "bitmaps/brkpt-dn.bmp"
+VGA_BREAK_GRAYED BITMAP "bitmaps/brkpt-da.bmp"
+VGA_GO_NORMAL BITMAP "bitmaps/runup.bmp"
+VGA_GO_PUSHED BITMAP "bitmaps/rundn.bmp"
+VGA_GO_GRAYED BITMAP "bitmaps/runda.bmp"
+VGA_HALT_NORMAL BITMAP "bitmaps/stpup.bmp"
+VGA_HALT_PUSHED BITMAP "bitmaps/stpdn.bmp"
+VGA_HALT_GRAYED BITMAP "bitmaps/stpda.bmp"
+VGA_QWATCH_NORMAL BITMAP "bitmaps/wtch-up.bmp"
+VGA_QWATCH_PUSHED BITMAP "bitmaps/wtch-dn.bmp"
+VGA_QWATCH_GRAYED BITMAP "bitmaps/wtch-da.bmp"
+VGA_SMODE_NORMAL BITMAP "bitmaps/src-up.bmp"
+VGA_SMODE_PUSHED BITMAP "bitmaps/src-dn.bmp"
+VGA_SMODE_GRAYED BITMAP "bitmaps/src-da.bmp"
+VGA_AMODE_NORMAL BITMAP "bitmaps/asmup.bmp"
+VGA_AMODE_PUSHED BITMAP "bitmaps/asmdn.bmp"
+VGA_AMODE_GRAYED BITMAP "bitmaps/asmda.bmp"
+VGA_PANE_BLANK BITMAP "bitmaps/blank.bvg"
+VGA_PANE_MINUS BITMAP "bitmaps/minus.bvg"
+VGA_PANE_PLUS BITMAP "bitmaps/plus.bvg"
+#ifdef MS_INTERNAL_DONT_COMPILE_THIS_DAMMIT
+Egg Egg "bitmaps/buildp.bvm"
+#endif
+
+QCQPMAINMENU MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New", IDM_FILE_NEW
+ MENUITEM "&Open...\aCtrl+F12", IDM_FILE_OPEN
+ MENUITEM "&Merge...", IDM_FILE_MERGE
+ MENUITEM "&Close", IDM_FILE_CLOSE
+ MENUITEM "&Save\aShift+F12", IDM_FILE_SAVE
+ MENUITEM "Save &As...\aF12", IDM_FILE_SAVEAS
+ MENUITEM "Sa&ve All", IDM_FILE_SAVEALL
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit\aAlt+F4", IDM_FILE_EXIT
+ END
+
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Undo\tAlt+Bksp", IDM_EDIT_UNDO
+ MENUITEM "&Redo\tCtrl+Bksp", IDM_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t\tShift+Del", IDM_EDIT_CUT
+ MENUITEM "&Copy\tCtrl+Ins", IDM_EDIT_COPY
+ MENUITEM "&Paste\tShift+Ins", IDM_EDIT_PASTE
+ MENUITEM "&Delete\tDel", IDM_EDIT_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "&Find...\tShift+F3", IDM_EDIT_FIND
+ MENUITEM "R&eplace...", IDM_EDIT_REPLACE
+ MENUITEM SEPARATOR
+ MENUITEM "Read &Only", IDM_EDIT_READONLY
+ END
+
+ POPUP "&View"
+ BEGIN
+ MENUITEM "Goto &Line...", IDM_VIEW_LINE
+ MENUITEM "&Goto Address...", IDM_VIEW_FUNCTION
+ MENUITEM SEPARATOR
+ MENUITEM "&Toggle Tag\tCtrl+F2", IDM_VIEW_TOGGLETAG
+ MENUITEM "Ne&xt Tag\tF2", IDM_VIEW_NEXTTAG
+ MENUITEM "Pre&vious Tag\tShift+F2", IDM_VIEW_PREVIOUSTAG
+ MENUITEM "&Clear All Tags", IDM_VIEW_CLEARALLTAGS
+ MENUITEM SEPARATOR
+ MENUITEM "Tool&bar", IDM_VIEW_RIBBON, CHECKED
+ MENUITEM "&Status Bar", IDM_VIEW_STATUS, CHECKED
+ END
+
+ POPUP "&Program",
+ BEGIN
+ MENUITEM "&Open...", IDM_PROGRAM_OPEN
+ MENUITEM "&Close", IDM_PROGRAM_CLOSE
+ MENUITEM "&Save", IDM_PROGRAM_SAVE
+ MENUITEM "Save &As...", IDM_PROGRAM_SAVEAS
+ MENUITEM "&Delete...", IDM_PROGRAM_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "Save Co&mmon", IDM_PROGRAM_SAVE_DEFAULTS
+ END
+
+ POPUP "&Run"
+ BEGIN
+ MENUITEM "&Restart\tShift+F5", IDM_RUN_RESTART
+ MENUITEM "Stop &Debugging\tAlt+F5", IDM_RUN_STOPDEBUGGING
+ MENUITEM SEPARATOR
+ MENUITEM "&Go\tF5", IDM_RUN_GO
+ MENUITEM "&Attach\tF6", IDM_RUN_ATTACH,
+ MENUITEM "&Continue to Cursor\tF7", IDM_RUN_TOCURSOR
+ MENUITEM "&Trace Into\tF8", IDM_RUN_TRACEINTO
+ MENUITEM "&Step Over\tF10", IDM_RUN_STEPOVER
+ MENUITEM "&Halt", IDM_RUN_HALT
+ MENUITEM SEPARATOR
+ MENUITEM "Go Handled", IDM_RUN_GO_HANDLED
+ MENUITEM "Go Unhandled", IDM_RUN_GO_UNHANDLED
+ MENUITEM SEPARATOR
+ MENUITEM "S&et Thread...", IDM_RUN_SET_THREAD
+ MENUITEM "Set &Process...", IDM_RUN_SET_PROCESS, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "T&oggle Source/Asm Mode", IDM_RUN_SOURCE_MODE
+ END
+
+ POPUP "&Debug"
+ BEGIN
+ MENUITEM "&Breakpoints...", IDM_DEBUG_SETBREAK
+ MENUITEM "&Quickwatch...\tShift+F9", IDM_DEBUG_QUICKWATCH, GRAYED
+ MENUITEM "&Watch Expression...", IDM_DEBUG_WATCH
+ END
+
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Run...", IDM_OPTIONS_RUN
+ MENUITEM "De&bug...", IDM_OPTIONS_DEBUG,
+ MENUITEM "&User Dlls...", IDM_OPTIONS_USERDLL,
+ MENUITEM "&Debugger Dlls...", IDM_OPTIONS_DBGDLL,
+ MENUITEM "&Exceptions...", IDM_OPTIONS_EXCEPTIONS,
+ MENUITEM "&Kernel Debugger...", IDM_OPTIONS_KD,
+ MENUITEM "En&vironment..." IDM_OPTIONS_ENVIRON,
+ MENUITEM SEPARATOR
+ MENUITEM "&Memory...", IDM_OPTIONS_MEMORY,GRAYED
+ MENUITEM "&Watch...", IDM_OPTIONS_WATCH, GRAYED
+ MENUITEM "&Local...", IDM_OPTIONS_LOCAL, GRAYED
+ MENUITEM "&Calls...", IDM_OPTIONS_CALLS, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "C&olor...", IDM_OPTIONS_COLOR
+ MENUITEM "&Font...", IDM_OPTIONS_FONTS, GRAYED
+ END
+
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&New Window", IDM_WINDOW_NEWWINDOW
+ MENUITEM "C&ascade", IDM_WINDOW_CASCADE
+ MENUITEM "&Tile", IDM_WINDOW_TILE
+ MENUITEM "Arran&ge", IDM_WINDOW_ARRANGE
+ MENUITEM "Arrange &Icons", IDM_WINDOW_ARRANGE_ICONS
+ MENUITEM "Overlay &Source", IDM_WINDOW_SOURCE_OVERLAY
+ MENUITEM SEPARATOR
+ MENUITEM "&Watch", IDM_WINDOW_WATCH
+ MENUITEM "&Locals", IDM_WINDOW_LOCALS
+ MENUITEM "&Registers", IDM_WINDOW_CPU
+ MENUITEM "&Disassembly", IDM_WINDOW_DISASM
+ MENUITEM "C&ommand", IDM_WINDOW_COMMAND
+ MENUITEM "&Floating Point", IDM_WINDOW_FLOAT
+ MENUITEM "&Memory...", IDM_WINDOW_MEMORY
+ MENUITEM "&Calls", IDM_WINDOW_CALLS
+ END
+
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Contents", IDM_HELP_CONTENTS
+ MENUITEM "&Search", IDM_HELP_SEARCH
+ MENUITEM SEPARATOR
+ MENUITEM "&About...", IDM_HELP_ABOUT
+ END
+END
+
+//
+// Default accelerators
+//
+
+QCQPMAINACC ACCELERATORS
+BEGIN
+
+ //
+ // File Menu
+ //
+
+ VK_F12, IDM_FILE_OPEN, VIRTKEY, CONTROL
+ VK_F12, IDM_FILE_SAVE, VIRTKEY, SHIFT
+ VK_F12, IDM_FILE_SAVEAS, VIRTKEY
+ VK_F2, IDM_FILE_OPEN, VIRTKEY, CONTROL, ALT
+ VK_F2, IDM_FILE_SAVE, VIRTKEY, SHIFT, ALT
+ VK_F2, IDM_FILE_SAVEAS, VIRTKEY, ALT
+ VK_F4, IDM_FILE_EXIT, VIRTKEY, ALT
+
+ //
+ // Edit Menu
+ //
+
+ VK_BACK, IDM_EDIT_UNDO, VIRTKEY, ALT
+ VK_BACK, IDM_EDIT_REDO, VIRTKEY, CONTROL
+ VK_DELETE, IDM_EDIT_CUT, VIRTKEY, SHIFT
+ VK_INSERT, IDM_EDIT_COPY, VIRTKEY, CONTROL
+ VK_INSERT, IDM_EDIT_PASTE, VIRTKEY, SHIFT
+ VK_F3, IDM_EDIT_FIND, VIRTKEY, SHIFT
+
+ //
+ // Search Menu
+ //
+
+ VK_F2, IDM_VIEW_TOGGLETAG, VIRTKEY, CONTROL
+ VK_F2, IDM_VIEW_NEXTTAG, VIRTKEY
+ VK_F2, IDM_VIEW_PREVIOUSTAG, VIRTKEY, SHIFT
+
+ VK_F3, IDA_FINDNEXT, VIRTKEY
+
+ //
+ // Program Menu
+ //
+
+ // 0x31, IDM_PROGRAM_LOAD_WORKSPACE, VIRTKEY, CONTROL
+ // 0x31, IDM_PROGRAM_SAVE_WORKSPACE, VIRTKEY, SHIFT, CONTROL
+
+ //
+ // Run Menu
+ //
+
+ VK_F5, IDM_RUN_RESTART, VIRTKEY, SHIFT
+ VK_F5, IDM_RUN_GO2, VIRTKEY
+ VK_F5, IDM_RUN_STOPDEBUGGING, VIRTKEY, ALT
+ VK_F6, IDM_RUN_ATTACH, VIRTKEY
+ VK_F7, IDM_RUN_TOCURSOR2, VIRTKEY
+ VK_F8, IDM_RUN_TRACEINTO, VIRTKEY
+ VK_F10, IDM_RUN_STEPOVER, VIRTKEY
+
+
+ //
+ // Debug Menu
+ //
+
+ VK_F9, IDM_DEBUG_SETBREAK, VIRTKEY
+ VK_F9, IDM_DEBUG_QUICKWATCH, VIRTKEY, SHIFT
+ VK_F9, IDM_DEBUG_MODIFY, VIRTKEY, CONTROL
+
+ //
+ // Extra accelerators
+ //
+
+ VK_F3, IDA_FINDNEXT, VIRTKEY
+ 0x31, IDM_WINDOWCHILD, VIRTKEY, ALT
+ 0x32, IDM_WINDOWCHILD + 1, VIRTKEY, ALT
+ 0x33, IDM_WINDOWCHILD + 2, VIRTKEY, ALT
+ 0x34, IDM_WINDOWCHILD + 3, VIRTKEY, ALT
+ 0x35, IDM_WINDOWCHILD + 4, VIRTKEY, ALT
+ 0x36, IDM_WINDOWCHILD + 5, VIRTKEY, ALT
+ 0x37, IDM_WINDOWCHILD + 6, VIRTKEY, ALT
+ 0x38, IDM_WINDOWCHILD + 7, VIRTKEY, ALT
+ 0x39, IDM_WINDOWCHILD + 8, VIRTKEY, ALT
+ 0x30, IDM_WINDOWCHILD + 9, VIRTKEY, ALT
+ 0x31, IDM_WINDOWCHILD + 10, VIRTKEY, ALT, SHIFT
+ 0x32, IDM_WINDOWCHILD + 11, VIRTKEY, ALT, SHIFT
+ 0x33, IDM_WINDOWCHILD + 12, VIRTKEY, ALT, SHIFT
+ 0x34, IDM_WINDOWCHILD + 13, VIRTKEY, ALT, SHIFT
+ 0x35, IDM_WINDOWCHILD + 14, VIRTKEY, ALT, SHIFT
+ 0x36, IDM_WINDOWCHILD + 15, VIRTKEY, ALT, SHIFT
+END
+
+// Define the string table
+
+#include "res_str.i"
+ \ No newline at end of file
diff --git a/private/windbg/windbg/wrkspace.c b/private/windbg/windbg/wrkspace.c
new file mode 100644
index 000000000..5928b1f9a
--- /dev/null
+++ b/private/windbg/windbg/wrkspace.c
@@ -0,0 +1,5923 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ WrkSpace.c
+
+Abstract:
+
+ This module contains the support for Windbg's workspaces.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 07-July-1992
+ Griffith Wm. Kadnier (v-griffk) 15-Jan-1993
+
+
+Environment:
+
+ Win32, User Mode
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#include "dbugexcp.h"
+
+
+
+
+
+//
+// The following constants determine the location of the
+// debugger information in the registry.
+//
+#define WINDBG_KEY "Software\\Microsoft\\"
+#define PROGRAMS "Programs"
+#define OPTIONS "Options"
+#define DEFAULT_WORKSPACE "Default Workspace"
+#define COMMON_WORKSPACE "Common Workspace"
+#define WORKSPACE_PREFIX "WorkSpace_"
+
+//
+// The following strings identify key/values in the registry.
+//
+#define WS_STR_MRU_LIST "MRU List"
+#define WS_STR_MISC "Misc"
+#define WS_STR_PATH "Path"
+#define WS_STR_COMLINE "Command Line"
+#define WS_STR_FRAME_WINDOW "Frame Window"
+#define WS_STR_DEFFONT "Default font"
+#define WS_STR_FILEMRU "File MRU List"
+#define WS_STR_RIBBON "Tool Bar"
+#define WS_STR_STATUSBAR "Status Bar"
+#define WS_STR_SRCMODE "Source Mode"
+#define WS_STR_BRKPTS "Breakpoints"
+#define WS_STR_WNDPROCHIST "WndProc History"
+#define WS_STR_OPTIONS "Options"
+#define WS_STR_DBGCHLD "Debug Child Process"
+#define WS_STR_CHILDGO "Go on Child Start"
+#define WS_STR_ATTACHGO "Go on Attach"
+#define WS_STR_EXITGO "Go on Thread Exit"
+#define WS_STR_EPSTEP "Entry Point is First Step"
+#define WS_STR_COMMANDREPEAT "Command Repeat"
+#define WS_STR_NOVERSION "NoVersion"
+#define WS_STR_EXTENSION_NAMES "Extension Names"
+#define WS_STR_MASMEVAL "Masm Evaluation"
+#define WS_STR_BACKGROUND "Background Symbol Loads"
+#define WS_STR_ALTSS "Alternate SS"
+#define WS_STR_WOWVDM "WOW Vdm"
+#define WS_STR_DISCONNECT "Disconnect Exit"
+#define WS_STR_IGNOREALL "Ignore All"
+#define WS_STR_VERBOSE "Verbose"
+#define WS_STR_CONTEXT "Abbreviated Context"
+#define WS_STR_INHERITHANDLES "Inherit Handles"
+#define WS_STR_LFOPT_APPEND "Logfile Append"
+#define WS_STR_LFOPT_AUTO "Logfile Auto"
+#define WS_STR_LFOPT_FNAME "Logfile Name"
+#define WS_STR_KERNELDEBUGGER "Kernel Debugger"
+#define WS_STR_KD_INITIALBP "Initial Break Point"
+#define WS_STR_KD_MODEM "Use Modem Controls"
+#define WS_STR_KD_PORT "Port"
+#define WS_STR_KD_BAUDRATE "Baudrate"
+#define WS_STR_KD_CACHE "Cache Size"
+#define WS_STR_KD_PLATFORM "Platform"
+#define WS_STR_KD_ENABLE "Enable"
+#define WS_STR_KD_GOEXIT "Go On Exit"
+#define WS_STR_KD_CRASH "Crash Dump"
+#define WS_STR_KD_KERNEL_NAME "Kernel Name"
+#define WS_STR_KD_HAL_NAME "HAL Name"
+#define WS_STR_RADIX "Radix"
+#define WS_STR_REG "Registers"
+#define WS_STR_REGULAR "Regular"
+#define WS_STR_EXTENDED "Extended"
+#define WS_STR_REGMMU "Register MMU"
+#define WS_STR_DISPSEG "Display Segment"
+#define WS_STR_IGNCASE "Ignore Case"
+#define WS_STR_SUFFIX "Suffix"
+#define WS_STR_ENV "Environment"
+#define WS_STR_ASMOPT "Disassembler Options"
+#define WS_STR_SHOWSEG "Show Segment"
+#define WS_STR_SHOWRAW "Show Raw Bytes"
+#define WS_STR_UPPERCASE "Uppercase"
+#define WS_STR_SHOWSRC "Show Source"
+#define WS_STR_SHOWSYM "Show Symbols"
+#define WS_STR_DEMAND "Demand"
+#define WS_STR_COLORS "Colors"
+#define WS_STR_DBGDLL "Debugger DLLs"
+#define WS_STR_SYMHAN "Symbol Handler"
+#define WS_STR_EXPEVAL "Expression Evaluator"
+#define WS_STR_TRANSLAY "Transport Layer"
+#define WS_STR_EXECMOD "Execution model"
+#define WS_STR_VIEWS "Views"
+#define WS_STR_TYPE "Type"
+#define WS_STR_PANE "Pane Data"
+#define WS_STR_PLACEMENT "Placement"
+#define WS_STR_FONT "Font"
+#define WS_STR_FILENAME "File Name"
+#define WS_STR_LINE "Line"
+#define WS_STR_COLUMN "Column"
+#define WS_STR_READONLY "ReadOnly"
+#define WS_STR_EXPRESSION "Expression"
+#define WS_STR_FORMAT "Format"
+#define WS_STR_LIVE "Live"
+#define WS_STR_X "X"
+#define WS_STR_Y "Y"
+#define WS_STR_WIDTH "Width"
+#define WS_STR_HEIGHT "Height"
+#define WS_STR_STATE "State"
+#define WS_STR_ICONIC "Iconized"
+#define WS_STR_NORMAL "Normal"
+#define WS_STR_MAXIMIZED "Maximized"
+#define WS_STR_ORDER "Order"
+#define WS_STR_VIEWKEY_TEMPLATE "%.3d"
+#define WS_STR_TABSTOPS "Tab Stops"
+#define WS_STR_KEEPTABS "Keep tabs"
+#define WS_STR_HORSCROLL "Horizontal Scroll Bar"
+#define WS_STR_VERSCROLL "Vertical Scroll Bar"
+#define WS_STR_SRCHPATH "PATH search"
+#define WS_STR_REDOSIZE "Undo-Redo buffer size"
+#define WS_STR_SRCPATH "Source search path"
+#define WS_STR_ROOTPATH "Root Mapping Pairs"
+#define WS_STR_USERDLL "User DLLs"
+#define WS_STR_USERDLLNAME "Name"
+#define WS_STR_USERDLL_TEMPLATE "UserDll_%.4d"
+#define WS_STR_LOCATION "Location"
+#define WS_STR_LOADTIME "Load time"
+#define WS_STR_DEFLOCATION "Default location"
+#define WS_STR_DEFLOADTIME "Default load time"
+#define WS_STR_DEFSRCHPATH "Default search path"
+#define WS_STR_EXCPT "Exceptions"
+#define WS_STR_ASKSAVE "Ask to save"
+#define WS_STR_CALLS "Calls Options"
+#define WS_STR_TITLE "Window Title"
+#define WS_STR_REMOTE_PIPE "Remote Pipe"
+
+//
+// Location of symbols
+//
+typedef enum _LOCATION {
+ SYMBOL_LOCATION_IGNORE, // Ignore
+ SYMBOL_LOCATION_LOCAL, // Load local symbols
+ SYMBOL_LOCATION_REMOTE // Load remote symbols
+} LOCATION, *PLOCATION;
+
+//
+// When to load the symbols
+//
+typedef enum _LOADTIME {
+ LOAD_SYMBOLS_IGNORE, // Ignore
+ LOAD_SYMBOLS_NOW, // Load symbols immediately after loading DLL
+ LOAD_SYMBOLS_LATER, // Defer symbol loading
+ LOAD_SYMBOLS_NEVER // Suppress symbol loading
+} LOADTIME, *PLOADTIME;
+
+
+//
+// Window state
+//
+typedef enum _WINDOW_STATE {
+ WSTATE_ICONIC, // Iconized
+ WSTATE_NORMAL, // Normal
+ WSTATE_MAXIMIZED // Maximized
+} WINDOW_STATE, *PWINDOW_STATE;
+
+//
+// Window information structure
+//
+typedef struct _WINDOW_DATA {
+ DWORD X;
+ DWORD Y;
+ DWORD Width;
+ DWORD Height;
+ WINDOW_STATE State;
+} WINDOW_DATA, *PWINDOW_DATA;
+
+
+//
+// View ordering structure
+typedef struct _VIEW_ORDER {
+ int View; // View index
+ int Order; // Order
+} VIEW_ORDER, *PVIEW_ORDER;
+
+
+
+
+
+//
+// External variables
+//
+extern char DebuggerName[];
+extern LPSTR LpszCommandLine;
+extern CXF CxfIp;
+extern LPSTR LpszCommandLineTransportDll;
+extern BOOLEAN AskToSave;
+
+//
+// External functions
+//
+extern HWND GetLocalHWND(void);
+extern HWND GetFloatHWND(void);
+extern HWND GetWatchHWND(void);
+extern HWND GetCpuHWND(void);
+extern HWND GetCallsHWND(void);
+extern LRESULT SendMessageNZ (HWND,UINT,WPARAM,LPARAM);
+
+//
+// Global variables
+//
+BOOLEAN StateCurrent = FALSE;
+BOOLEAN ProgramLoaded = FALSE;
+char CurrentWorkSpaceName[ MAX_PATH ];
+char CurrentProgramName[ MAX_PATH ];
+char UntitledProgramName[] = UNTITLED;
+VS_FIXEDFILEINFO *FixedFileInfo = NULL;
+DWORD WorkspaceOverride;
+
+char SrcFileDirectory[ MAX_PATH ];
+char ExeFileDirectory[ MAX_PATH ];
+char DocFileDirectory[ MAX_PATH ];
+char UserDllDirectory[ MAX_PATH ];
+
+EXCEPTION_LIST *DefaultExceptionList = NULL;
+
+
+//
+// Local prototypes
+//
+HKEY GetDebuggerKey( void );
+HKEY OpenRegistryKey( HKEY, LPSTR , BOOLEAN );
+
+HKEY GetWorkSpaceKey( HKEY, LPSTR , LPSTR , BOOLEAN, LPSTR );
+BOOLEAN LoadWorkSpaceFromKey( HKEY, BOOLEAN );
+BOOLEAN SaveWorkSpaceToKey( HKEY, BOOLEAN );
+BOOLEAN SetDefaultWorkSpace( HKEY, LPSTR , LPSTR );
+
+BOOLEAN LoadWorkSpaceItem ( HKEY, WORKSPACE_ITEM, BOOLEAN );
+BOOLEAN SaveWorkSpaceItem ( HKEY, WORKSPACE_ITEM, BOOLEAN );
+
+BOOLEAN LoadWorkSpaceMiscItem ( HKEY, WORKSPACE_ITEM, BOOLEAN );
+BOOLEAN SaveWorkSpaceMiscItem ( HKEY, WORKSPACE_ITEM, BOOLEAN );
+
+BOOLEAN LoadWorkSpaceOptionItem ( HKEY, WORKSPACE_ITEM, BOOLEAN );
+BOOLEAN SaveWorkSpaceOptionItem ( HKEY, WORKSPACE_ITEM, BOOLEAN );
+
+BOOLEAN LoadWorkSpaceWindowItem ( HKEY, WORKSPACE_ITEM, BOOLEAN, BOOLEAN );
+BOOLEAN SaveWorkSpaceWindowItem ( HKEY, WORKSPACE_ITEM, BOOLEAN, BOOLEAN );
+
+BOOLEAN LoadWindowType ( HKEY, DWORD, BOOLEAN, BOOLEAN );
+BOOLEAN SaveWindowType ( HKEY, DWORD, BOOLEAN, BOOLEAN );
+
+BOOLEAN LoadView ( HKEY, int, DWORD );
+BOOLEAN SaveView ( HKEY, int, int, BOOLEAN );
+
+BOOLEAN LoadWindowData ( HKEY, char*, PWINDOW_DATA );
+BOOLEAN SaveWindowData ( HKEY, char*, PWINDOW_DATA );
+
+BOOLEAN LoadFont( HKEY, char*, LPLOGFONT );
+BOOLEAN SaveFont( HKEY, char*, LPLOGFONT );
+
+BOOLEAN LoadMRUList ( HKEY, char*, DWORD, DWORD, DWORD );
+BOOLEAN SaveMRUList( HKEY, char*, DWORD );
+
+BOOLEAN DeleteKeyRecursive( HKEY, LPSTR );
+
+BOOLEAN GetWindowMetrics ( HWND, PWINDOW_DATA, BOOLEAN );
+
+LPSTR LoadMultiString( HKEY, LPSTR , DWORD * );
+
+BOOLEAN GetProgramPath( HKEY, LPSTR, LPSTR );
+BOOLEAN SetProgramPath( HKEY, LPSTR );
+
+
+int _CRTAPI1 CompareViewOrder(const void *, const void *);
+SHE LoadTimeToShe ( LOADTIME );
+LOADTIME SheToLoadTime( SHE );
+LPSTR GetExtensionDllNames(LPDWORD);
+VOID SetExtensionDllNames(LPSTR);
+
+
+
+
+// **********************************************************
+// EXPORTED FUNCTIONS
+// **********************************************************
+
+
+BOOLEAN
+DebuggerStateChanged(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Determines if the debugger state has changed since the last state
+ save.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if state has changed.
+
+--*/
+{
+ return !StateCurrent;
+}
+
+
+
+VOID
+ChangeDebuggerState(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Sets the global flag indicating that the debugger state has changed.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ StateCurrent = FALSE;
+}
+
+
+
+LPSTR
+GetCurrentProgramName(
+ BOOL fReturnUntitled
+ )
+/*++
+
+Routine Description:
+
+ Returns current program name
+
+Arguments:
+
+ None
+
+Return Value:
+
+ LPSTR - Current program Name
+
+--*/
+{
+ if ( *CurrentProgramName != '\0' ) {
+ return CurrentProgramName;
+ }
+ else
+ if (fReturnUntitled) {
+ return UntitledProgramName;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+
+LPSTR
+GetCurrentWorkSpace(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Returns current workspace
+
+Arguments:
+
+ None
+
+Return Value:
+
+ LPSTR - Current workspace
+
+--*/
+{
+ return CurrentWorkSpaceName;
+}
+
+
+
+
+BOOLEAN
+IsProgramLoaded(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Determines if a program is loaded or not.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if a program is loaded
+
+--*/
+{
+ return ProgramLoaded;
+}
+
+
+
+
+BOOLEAN
+UnLoadProgram(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Unloads the current program.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if a program is unloaded
+
+--*/
+{
+ if ( IsProgramLoaded() ) {
+ ClearDebuggee();
+ }
+
+ ProgramLoaded = FALSE;
+ StateCurrent = FALSE;
+ CurrentWorkSpaceName[0] = '\0';
+ CurrentProgramName[0] = '\0';
+
+ return TRUE;
+}
+
+
+
+LPSTR
+GetAllPrograms(
+ DWORD *ListLength
+ )
+/*++
+
+Routine Description:
+
+ Gets all the programs in the registry
+
+Arguments:
+
+ ListLength - Supplies pointer to multistring length
+
+Return Value:
+
+ LPSTR - Multistring with the names of the programs
+
+--*/
+{
+ LPSTR List = NULL;
+ HKEY DbgKey;
+ HKEY PgmKey;
+ DWORD SubKeys;
+ DWORD DataSize;
+ FILETIME FileTime;
+ DWORD Error;
+ int i;
+ char Buffer[ MAX_PATH ];
+ char Buffer2[ MAX_PATH ];
+
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+
+ if ( PgmKey = OpenRegistryKey( DbgKey, Buffer, FALSE ) ) {
+
+ DataSize = 0;
+ Error = RegQueryInfoKey( PgmKey,
+ NULL,
+ &DataSize,
+ NULL,
+ &SubKeys,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &FileTime );
+
+ if ( (Error == NO_ERROR) || (Error == ERROR_INSUFFICIENT_BUFFER) ) {
+
+ *ListLength = 0;
+ for (i=0; i < (int)SubKeys; i++ ) {
+ if ( RegEnumKey( PgmKey, i, Buffer, sizeof( Buffer ) ) ) {
+ break;
+ } else {
+
+ //
+ // If the program has a path, use it, otherwise use
+ // only the program name.
+ //
+ AddToMultiString( &List, ListLength, GetProgramPath( PgmKey, Buffer, Buffer2 ) ? Buffer2 : Buffer );
+ }
+ }
+ }
+
+ RegCloseKey( PgmKey );
+ }
+
+ RegCloseKey( DbgKey );
+ }
+
+ return List;
+}
+
+
+
+LPSTR
+GetAllWorkSpaces(
+ LPSTR ProgramName,
+ DWORD *ListLength,
+ LPSTR DefaultWorkSpace
+ )
+/*++
+
+Routine Description:
+
+ Gets the names of all the workspaces for a given program
+
+Arguments:
+
+ ProgramName - Supplies the name of the program
+ ListLength - Supplies pointer to multistring length
+ DefaultWorkSpace - Supplies an optional buffer where the
+ name of the default workspace is placed.
+
+Return Value:
+
+ LPSTR - Multistring with the names of the workspaces
+
+--*/
+{
+ LPSTR List = NULL;
+ HKEY DbgKey;
+ HKEY PgmKey;
+ DWORD SubKeys;
+ DWORD DataSize;
+ FILETIME FileTime;
+ DWORD Error;
+ int i;
+ char Buffer[ MAX_PATH ];
+
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ GetBaseName( ProgramName, Buffer + strlen(Buffer) );
+ if ( PgmKey = OpenRegistryKey( DbgKey, Buffer, FALSE ) ) {
+
+ DataSize = 0;
+ Error = RegQueryInfoKey( PgmKey,
+ NULL,
+ &DataSize,
+ NULL,
+ &SubKeys,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &FileTime );
+
+ if ( (Error == NO_ERROR) || (Error == ERROR_INSUFFICIENT_BUFFER) ) {
+
+ *ListLength = 0;
+ for (i=0; i < (int)SubKeys; i++ ) {
+ if ( RegEnumKey( PgmKey, i, Buffer, sizeof( Buffer ) ) ) {
+ break;
+ } else {
+ if ( !_strnicmp( Buffer, WORKSPACE_PREFIX, strlen( WORKSPACE_PREFIX ) ) ) {
+ AddToMultiString( &List, ListLength, Buffer + strlen( WORKSPACE_PREFIX ) );
+ }
+ }
+ }
+ }
+
+ if ( DefaultWorkSpace ) {
+ GetDefaultWorkSpace( ProgramName, DefaultWorkSpace );
+ }
+
+ RegCloseKey( PgmKey );
+ }
+
+ RegCloseKey( DbgKey );
+
+ }
+
+ return List;
+}
+
+
+
+BOOLEAN
+GetDefaultWorkSpace(
+ LPSTR ProgramName,
+ LPSTR WorkSpaceName
+ )
+/*++
+
+Routine Description:
+
+ Gets the name of the default workspace for a program.
+
+Arguments:
+
+ ProgramName - Supplies the name of the program,
+ can be NULL or empty.
+
+ WorkSpaceName - Supplies buffer where the name of the
+ default workspace is placed.
+
+Return Value:
+
+ BOOLEAN - TRUE if program has a default workspace
+
+--*/
+{
+ HKEY DbgKey;
+ HKEY PgmKey;
+ char Buffer[ MAX_PATH ];
+ DWORD DataSize;
+ BOOLEAN Ok = FALSE;
+
+
+ //
+ // Get registry key for the debugger.
+ //
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ //
+ // Program Name provided. Look for the key corresponding
+ // to it.
+ //
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ GetBaseName( ProgramName, Buffer + strlen(Buffer) );
+ if ( PgmKey = OpenRegistryKey( DbgKey, Buffer, FALSE ) ) {
+
+ DataSize = MAX_PATH;
+ Ok = ( RegQueryValueEx( PgmKey,
+ DEFAULT_WORKSPACE,
+ NULL,
+ NULL,
+ WorkSpaceName,
+ &DataSize ) == NO_ERROR );
+
+ RegCloseKey( PgmKey );
+ }
+
+ RegCloseKey( DbgKey );
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadProgramMRUList(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Loads the MRU list from the registry.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if MRU list loaded
+
+--*/
+{
+
+ HKEY DbgKey;
+ BOOLEAN Ok = FALSE;
+
+ //
+ // Get the MRU list from the registry
+ //
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ Ok = LoadMRUList( DbgKey, WS_STR_MRU_LIST, PROJECT_FILE,
+ PROJECTMENU, IDM_PROGRAM_LAST );
+
+ RegCloseKey( DbgKey );
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+SaveProgramMRUList(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Saves the MRU list to the registry.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if MRU list loaded
+
+--*/
+{
+
+ HKEY DbgKey;
+ BOOLEAN Ok = FALSE;
+
+ //
+ // Get the MRU list from the registry
+ //
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ Ok = SaveMRUList( DbgKey, WS_STR_MRU_LIST, PROJECT_FILE );
+
+ RegCloseKey( DbgKey );
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadWorkSpace(
+ LPSTR ProgramName,
+ LPSTR WorkSpaceName,
+ BOOLEAN LoadCommandLine
+ )
+/*++
+
+Routine Description:
+
+ Loads a workspace from the registry.
+
+Arguments:
+
+ ProgramName - Supplies the name of the program,
+ can be NULL or empty.
+
+ WorkSpaceName - Supplies the name of the workspace,
+ NULL if loading the default workspace.
+
+ LoadCommandLine - Supplies flag which if TRUE will cause
+ command line to be loaded from workspace.
+ If FALSE the command line is NOT loaded.
+
+
+Return Value:
+
+ BOOLEAN - TRUE if workspace loaded.
+
+--*/
+{
+ HKEY DbgKey;
+ HKEY PgmKey;
+ HKEY WspKey;
+ BOOLEAN Ok = FALSE;
+ char Buffer[ MAX_PATH ];
+ char *w;
+ HCURSOR hOldCursor;
+ HCURSOR hWaitCursor;
+
+ //
+ // Get registry key for the debugger.
+ //
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ if ( ProgramName && (*ProgramName != '\0') ) {
+
+ //
+ // Load the workspace for the specified program.
+ //
+ w = ( WorkSpaceName && (*WorkSpaceName != '\0') ) ? WorkSpaceName : NULL;
+
+ WspKey = GetWorkSpaceKey( DbgKey, w ? ProgramName : NULL, w, FALSE, CurrentWorkSpaceName );
+
+ if ( WspKey ) {
+
+ //
+ // Try to use the given name. If that fails, use the path
+ // stored in the workspace.
+ //
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ if ( PgmKey = OpenRegistryKey( DbgKey, Buffer, FALSE ) ) {
+ GetProgramPath( PgmKey, ProgramName, Buffer );
+ RegCloseKey( PgmKey );
+ }
+
+ if ( LoadProgram( ProgramName ) || LoadProgram( Buffer ) ) {
+
+ //
+ // Update the MRU list.
+ //
+ //Dbg(w = (LPSTR)GlobalLock(hFileKept[PROJECT_FILE][0]));
+ //strcpy(Buffer, w);
+ //Dbg(GlobalUnlock (hFileKept[PROJECT_FILE][0]) == FALSE);
+ //
+ //if ( _stricmp( ProgramName, Buffer ) ) {
+ // InsertKeptFileNames( PROJECT_FILE, PROJECTMENU,
+ // IDM_PROGRAM_LAST, (LPSTR)ProgramName );
+ //}
+ //
+ //SaveProgramMRUList();
+ }
+ }
+
+ } else {
+
+ //
+ // No program name provided. Load the default workspace.
+ //
+ Assert( (!WorkSpaceName || *WorkSpaceName == '\0') );
+ WspKey = GetWorkSpaceKey( DbgKey, NULL, NULL, FALSE, CurrentWorkSpaceName );
+ }
+
+ //
+ // If got the workspace key, load the workspace.
+ //
+ if ( WspKey ) {
+
+ if ( LpszCommandLine && LoadCommandLine ) {
+ free( LpszCommandLine );
+ LpszCommandLine = FALSE;
+ }
+
+ hWaitCursor = LoadCursor( (HANDLE)NULL, IDC_WAIT );
+ hOldCursor = SetCursor( hWaitCursor );
+
+ StatusText(STA_Loading_Workspace, STATUS_INFOTEXT, FALSE, NULL);
+
+ Ok = LoadWorkSpaceFromKey( WspKey, TRUE );
+
+ StatusText(STA_Empty, STATUS_INFOTEXT, FALSE, NULL);
+
+ hOldCursor = SetCursor (hOldCursor);
+
+ RegCloseKey( WspKey );
+
+ }
+
+ RegCloseKey( DbgKey );
+ }
+
+ SrcFileDirectory[0] = '\0';
+ ExeFileDirectory[0] = '\0';
+ DocFileDirectory[0] = '\0';
+ UserDllDirectory[0] = '\0';
+
+ if (ProgramName) {
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+ char pname[MAX_PATH];
+ _splitpath( ProgramName, NULL, NULL, fname, ext );
+ if (_stricmp(ext,"exe") != 0) {
+ strcpy(ext, "exe" );
+ }
+ _makepath( pname, NULL, NULL, fname, ext );
+ if (_stricmp(pname,KD_PGM_NAME1)==0 ||
+ _stricmp(pname,KD_PGM_NAME2)==0) {
+
+ runDebugParams.fKernelDebugger = TRUE;
+
+ }
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+SaveWorkSpace(
+ char *ProgramName,
+ char *WorkSpaceName,
+ BOOLEAN MakeDefault
+ )
+/*++
+
+Routine Description:
+
+ Saves the current state to a workspace.
+
+Arguments:
+
+ ProgramName - Supplies the name of the program, NULL
+ for default workspace.
+
+ WorkSpaceName - Supplies the name of the workspace,
+ NULL for the default.
+
+ MakeDefault - Supplies flag which if TRUE means that
+ this workspace will be the new default for
+ the program.
+
+Return Value:
+
+ BOOLEAN - TRUE if workspace saved.
+
+--*/
+{
+ HKEY DbgKey;
+ HKEY PgmKey;
+ HKEY WspKey = NULL;
+ BOOLEAN Ok = FALSE;
+ BOOLEAN SaveDefault;
+ HCURSOR hOldCursor;
+ HCURSOR hWaitCursor;
+ char Buffer[ MAX_PATH ];
+
+ //
+ // Get registry key for the debugger.
+ //
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ if ( WorkSpaceName && (*WorkSpaceName != '\0') ) {
+
+ //
+ // A workspace name was given, get the key for the
+ // workspace.
+ //
+ Assert( ProgramName && (*ProgramName != '\0') );
+ SaveDefault = FALSE;
+ DeleteWorkSpace( ProgramName, WorkSpaceName );
+ WspKey = GetWorkSpaceKey( DbgKey,
+ ProgramName,
+ WorkSpaceName,
+ TRUE,
+ NULL );
+
+ } else {
+
+ //
+ // No workspace name given, save the default workspace
+ //
+ Assert( !ProgramName || (*ProgramName == '\0') );
+ SaveDefault = TRUE;
+ DeleteWorkSpace( NULL, NULL );
+ WspKey = GetWorkSpaceKey( DbgKey,
+ NULL,
+ NULL,
+ TRUE,
+ NULL );
+
+ }
+
+ if ( WspKey ) {
+
+ hWaitCursor = LoadCursor( (HANDLE)NULL, IDC_WAIT );
+ hOldCursor = SetCursor( hWaitCursor );
+
+ StatusText(STA_Saving_Workspace, STATUS_INFOTEXT, FALSE, NULL);
+
+ //
+ // If the workspace key is saved successfully and we
+ // want to make it the current default, do so.
+ //
+ if ( Ok = SaveWorkSpaceToKey( WspKey, SaveDefault ) ) {
+
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+
+ if (ProgramName && *ProgramName) {
+ if ( PgmKey = OpenRegistryKey( DbgKey, Buffer, FALSE ) ) {
+ SetProgramPath( PgmKey, ProgramName );
+ RegCloseKey( PgmKey );
+ }
+ }
+
+ if ( WorkSpaceName && (*WorkSpaceName != '\0') ) {
+ if ( !_stricmp( WorkSpaceName, GetCurrentWorkSpace() ) ) {
+ StateCurrent = TRUE;
+ }
+ }
+ if ( MakeDefault ) {
+
+ Assert( ProgramName );
+
+ SetDefaultWorkSpace( DbgKey,
+ ProgramName,
+ WorkSpaceName );
+ }
+
+ }
+
+ StatusText(STA_Empty, STATUS_INFOTEXT, FALSE, NULL);
+
+ hOldCursor = SetCursor (hOldCursor);
+
+ RegCloseKey( WspKey );
+ }
+
+ RegCloseKey( DbgKey );
+ }
+
+ if ( Ok && WorkSpaceName && (*WorkSpaceName != '\0') ) {
+ strcpy( CurrentWorkSpaceName, WorkSpaceName );
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+WorkSpaceExists (
+ LPSTR ProgramName,
+ LPSTR WorkSpace
+ )
+/*++
+
+Routine Description:
+
+ Determines if a workspace exists
+
+Arguments:
+
+ ProgramName - Supplies name of program. NULL for debugger default
+
+ WorkSpace - Supplies name of workspace. NULL ONLY for the
+ debugger default (NOT for program default)
+
+Return Value:
+
+ BOOLEAN - TRUE if default exists
+
+--*/
+{
+ HKEY DbgKey;
+ HKEY WspKey;
+ BOOLEAN Ok = FALSE;
+
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ if ( WspKey = GetWorkSpaceKey( DbgKey, ProgramName, WorkSpace, FALSE, NULL ) ) {
+
+ Ok = TRUE;
+ RegCloseKey( WspKey );
+ }
+
+ RegCloseKey( DbgKey );
+ }
+
+ return Ok;
+}
+
+
+// **********************************************************
+// WORKSPACE FUNCTIONS
+// **********************************************************
+
+
+
+
+HKEY
+OpenRegistryKey(
+ HKEY Key,
+ char *KeyName,
+ BOOLEAN Create
+ )
+/*++
+
+Routine Description:
+
+ Opens or creates a registry key.
+
+Arguments:
+
+ Key - Supplies Key handle
+
+ KeyName - Supplies Name of subkey to open/create (relative to Key)
+
+ Create - Supplies flag which if TRUE causes the function to
+ create the key if if does not already exist.
+
+Return Value:
+
+ HKEY - handle to key opened/created.
+
+--*/
+
+{
+
+ HKEY KeyHandle = NULL;
+
+ if ( RegOpenKey( Key,
+ KeyName,
+ &KeyHandle
+ ) ) {
+
+ //
+ // No such key, create it if requested.
+ //
+ KeyHandle = NULL;
+ if ( Create ) {
+ if ( RegCreateKey( Key,
+ KeyName,
+ &KeyHandle
+ ) ) {
+ KeyHandle = NULL;
+ }
+ }
+ }
+
+ return KeyHandle;
+}
+
+
+
+HKEY
+GetDebuggerKey(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Gets the registry key for the debugger. Will create the
+ key if it does not exist in the registry.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ HKEY - Registry key to be used.
+
+--*/
+{
+ char KeyName[ MAX_PATH ];
+ char VersionString[ MAX_MSG_TXT ];
+ char *p;
+ char *Version;
+ HKEY KeyHandle = NULL;
+ HKEY KeyTmp;
+
+ //
+ // Get the base portion of the key name
+ //
+ strcpy( KeyName, WINDBG_KEY );
+ p = KeyName + strlen( KeyName );
+ GetBaseName( DebuggerName, p );
+ strcat( KeyName, "\\" );
+ Version = p + strlen(p);
+
+ //
+ // Use the current version
+ //
+ Dbg(LoadString(hInst, DLG_VersionIni, VersionString, MAX_VERSION_TXT));
+ strcpy( Version, VersionString );
+
+ if ( RegOpenKey( HKEY_CURRENT_USER,
+ KeyName,
+ &KeyHandle
+ ) ) {
+
+ //
+ // No debugger key in the registry, create new one.
+ //
+ if ( RegCreateKey( HKEY_CURRENT_USER,
+ KeyName,
+ &KeyHandle
+ ) ) {
+
+ KeyHandle = NULL;
+
+ } else {
+
+ //
+ // Make the Programs and Options keys
+ //
+ if ( !RegCreateKey( KeyHandle, PROGRAMS, &KeyTmp ) ) {
+ RegCloseKey( KeyTmp );
+ } else if (!RegCreateKey( KeyHandle, OPTIONS, &KeyTmp) ) {
+ RegCloseKey( KeyTmp );
+ }
+ }
+ }
+
+ return KeyHandle;
+}
+
+
+
+HKEY
+GetWorkSpaceKey(
+ HKEY DebuggerKey,
+ LPSTR ProgramName,
+ LPSTR WorkSpaceName,
+ BOOLEAN Create,
+ LPSTR WorkSpaceUsed
+ )
+
+/*++
+
+Routine Description:
+
+ Gets the registry key for the specified workspace.
+
+Arguments:
+
+ DebuggerKey - Supplies the registry key for the debugger
+
+ ProgramName - Supplies the program name
+
+ WorkSpaceName - Supplies the workspace name
+
+ Create - Supplies flag which if TRUE means that the
+ workspace must be created if it does not
+ exist.
+
+ WorkSpaceUsed - Supplies an optional pointer to the name of
+ the workspace that was actually used.
+
+
+Return Value:
+
+ HKEY - Registry key for the workspace
+
+--*/
+
+{
+ char Buffer[ MAX_PATH ];
+ HKEY PgmKey;
+ HKEY KeyHandle = NULL;
+
+ if ( ProgramName && (*ProgramName != '\0' ) ) {
+
+ //
+ // Program Name provided. Look for the key corresponding
+ // to it.
+ //
+ Assert( WorkSpaceName && (*WorkSpaceName != '\0') );
+
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ GetBaseName( ProgramName, Buffer + strlen(Buffer) );
+
+ if ( PgmKey = OpenRegistryKey( DebuggerKey, Buffer, Create ) ) {
+
+ //
+ // Get the workspace.
+ //
+ strcpy( Buffer, WORKSPACE_PREFIX );
+ strcat( Buffer, WorkSpaceName );
+
+ KeyHandle = OpenRegistryKey( PgmKey, Buffer, Create );
+
+ if ( KeyHandle && WorkSpaceUsed ) {
+ strcpy( WorkSpaceUsed, WorkSpaceName );
+ }
+
+ RegCloseKey( PgmKey );
+ }
+
+ } else {
+
+ //
+ // No program, use the common workspace.
+ //
+ Assert( !WorkSpaceName || (*WorkSpaceName == '\0'));
+
+ KeyHandle = OpenRegistryKey( DebuggerKey, COMMON_WORKSPACE, Create );
+
+ //
+ // The common workspace is indicated by an
+ // empty name.
+ //
+ if ( KeyHandle && WorkSpaceUsed ) {
+ *WorkSpaceUsed = '\0';
+ }
+ }
+
+ return KeyHandle;
+}
+
+
+
+BOOLEAN
+SetDefaultWorkSpace(
+ HKEY DbgKey,
+ char *ProgramName,
+ char *WorkSpaceName
+ )
+/*++
+
+Routine Description:
+
+ Sets the default workspace for a program
+
+Arguments:
+
+ DbgKey - Supplies the registry key for the debugger
+
+ ProgramName - Supplies the program name
+
+ WorkSpaceName - Supplies the name of the default workspace
+
+Return Value:
+
+ BOOLEAN - TRUE if default workspace set.
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY PgmKey;
+ char Buffer[ MAX_PATH ];
+
+ if ( ProgramName && (*ProgramName != '\0' ) ) {
+
+ //
+ // Program Name provided. Look for the key corresponding
+ // to it.
+ //
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ GetBaseName( ProgramName, Buffer + strlen(Buffer) );
+
+ if ( PgmKey = OpenRegistryKey( DbgKey, Buffer, FALSE ) ) {
+
+ if ( RegSetValueEx( PgmKey,
+ DEFAULT_WORKSPACE,
+ 0,
+ REG_SZ,
+ WorkSpaceName,
+ strlen( WorkSpaceName )+1
+ ) == NO_ERROR ) {
+ Ok = TRUE;
+ }
+
+ RegCloseKey( PgmKey );
+ }
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+DeleteWorkSpace(
+ char *ProgramName,
+ char *WorkSpaceName
+ )
+/*++
+
+Routine Description:
+
+ Deletes a workspace
+
+Arguments:
+
+ ProgramName - Supplies the program name
+
+ WorkSpaceName - Supplies the name of the workspace
+
+Return Value:
+
+ BOOLEAN - TRUE if workspace deleted
+
+--*/
+{
+ HKEY DbgKey;
+ BOOLEAN Ok = FALSE;
+ char Buffer[ MAX_PATH ];
+
+ //
+ // Get registry key for the debugger.
+ //
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ if ( ProgramName && *ProgramName != '\0' ) {
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ GetBaseName( ProgramName, Buffer + strlen(Buffer) );
+ strcat( Buffer, "\\" );
+ strcat( Buffer, WORKSPACE_PREFIX );
+ strcat( Buffer, WorkSpaceName );
+ } else {
+ strcpy( Buffer, COMMON_WORKSPACE );
+ }
+ Ok = DeleteKeyRecursive( DbgKey, Buffer );
+
+ RegCloseKey ( DbgKey );
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+DeleteProgram(
+ char *ProgramName
+ )
+/*++
+
+Routine Description:
+
+ Deletes a program (and all its workspaces )
+
+Arguments:
+
+ ProgramName - Supplies the program name
+
+Return Value:
+
+ BOOLEAN - TRUE if program deleted
+
+--*/
+{
+ HKEY DbgKey;
+
+ char Buffer[ MAX_PATH ];
+ BOOLEAN Ok = FALSE;
+
+ //
+ // Get registry key for the debugger.
+ //
+ if (ProgramName && *ProgramName) {
+ if ( DbgKey = GetDebuggerKey() ) {
+
+ strcpy( Buffer, PROGRAMS );
+ strcat( Buffer, "\\" );
+ GetBaseName( ProgramName, Buffer + strlen(Buffer) );
+
+ Ok = DeleteKeyRecursive( DbgKey, Buffer );
+
+ RegCloseKey( DbgKey );
+ }
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+LoadWorkSpaceFromKey(
+ HKEY WspKey,
+ BOOLEAN Replace
+ )
+/*++
+
+Routine Description:
+
+ Loads a workspace from the given registry key. The registry
+ key must correspond to a workspace key.
+
+Arguments:
+
+ WspKey - Supplies the registry key from which to
+ load the workspace.
+ Replace - Supplies flag which if TRUE means that new
+ settings must replace current ones.
+
+Return Value:
+
+ BOOLEAN - TRUE if workspace loaded.
+
+--*/
+
+{
+ WORKSPACE_ITEM Item;
+
+ for ( Item = WSI_OPTION_FIRST; Item <= WSI_OPTION_LAST; Item++ ) {
+ LoadWorkSpaceOptionItem( WspKey, Item, Replace );
+ }
+
+ for ( Item = WSI_MISC_FIRST; Item <= WSI_MISC_LAST; Item++ ) {
+ LoadWorkSpaceMiscItem( WspKey, Item, Replace );
+ }
+
+ LoadWorkSpaceWindowItem( WspKey, WSI_WINDOW_FIRST, Replace, TRUE );
+
+ return TRUE;
+}
+
+
+
+
+BOOLEAN
+SaveWorkSpaceToKey(
+ HKEY WspKey,
+ BOOLEAN Default
+ )
+/*++
+
+Routine Description:
+
+ Saves a workspace to the given workspace key.
+
+Arguments:
+
+ WspKey - Supplies the registry key to which the workspace
+ is to be saved.
+
+ Default - Supplies flag which if TRUE means that we are
+ saving the default workspace.
+
+Return Value:
+
+ BOOLEAN - TRUE if workspace saved.
+
+--*/
+
+{
+ WORKSPACE_ITEM Item;
+
+ for ( Item = WSI_OPTION_FIRST; Item <= WSI_OPTION_LAST; Item++ ) {
+ SaveWorkSpaceOptionItem( WspKey, Item, Default );
+ }
+
+ for ( Item = WSI_MISC_FIRST; Item <= WSI_MISC_LAST; Item++ ) {
+ SaveWorkSpaceMiscItem( WspKey, Item, Default );
+ }
+
+ SaveWorkSpaceWindowItem( WspKey, WSI_WINDOW_FIRST, Default, TRUE );
+
+ return TRUE;
+}
+
+
+
+BOOLEAN
+LoadWorkSpaceItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Replace
+ )
+/*++
+
+Routine Description:
+
+ Loads a particular workspace item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Replace - Supplies replace flag
+
+Return Value:
+
+ BOOLEAN - TRUE if item loaded
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+
+ Assert( Item >= WSI_FIRST && Item < WSI_LAST );
+
+ if ( Item >= WSI_MISC_FIRST && Item <= WSI_MISC_LAST ) {
+ Ok = LoadWorkSpaceMiscItem( KeyHandle, Item, Replace );
+ } else if ( Item >= WSI_OPTION_FIRST && Item <= WSI_OPTION_LAST ) {
+ Ok = LoadWorkSpaceOptionItem( KeyHandle, Item, Replace );
+ } else if ( Item >= WSI_WINDOW_FIRST && Item <= WSI_WINDOW_LAST ) {
+ Ok = LoadWorkSpaceWindowItem( KeyHandle, Item, Replace, FALSE );
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+SaveWorkSpaceItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Default
+ )
+/*++
+
+Routine Description:
+
+ Saves a particular workspace item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Default - Supplies default flag
+
+Return Value:
+
+ BOOLEAN - TRUE if item saved
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+
+ Assert( Item >= WSI_FIRST && Item < WSI_LAST );
+
+ if ( Item >= WSI_MISC_FIRST && Item <= WSI_MISC_LAST ) {
+ Ok = SaveWorkSpaceMiscItem( KeyHandle, Item, Default );
+ } else if ( Item >= WSI_OPTION_FIRST && Item <= WSI_OPTION_LAST ) {
+ Ok = SaveWorkSpaceOptionItem( KeyHandle, Item, Default );
+ } else if ( Item >= WSI_WINDOW_FIRST && Item <= WSI_WINDOW_LAST ) {
+ Ok = SaveWorkSpaceWindowItem( KeyHandle, Item, Default, FALSE );
+ }
+
+ return Ok;
+}
+
+
+
+
+
+BOOLEAN
+LoadWorkSpaceMiscItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Replace
+ )
+/*++
+
+Routine Description:
+
+ Loads a particular workspace misc item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Replace - Supplies replace flag
+
+Return Value:
+
+ BOOLEAN - TRUE if item loaded
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY Key;
+ DWORD Dword;
+ DWORD DataSize;
+ WINDOW_DATA WindowData;
+ char Buffer[ TMP_STRING_SIZE ];
+ BPSTATUS bpstatus;
+ HBPT hBpt;
+ LPSTR List = NULL;
+ DWORD Next = 0;
+ LPSTR Brkpt;
+ BOOLEAN Disabled;
+ LPSTR String;
+
+ Assert( Item >= WSI_MISC_FIRST && Item <= WSI_MISC_LAST );
+
+ Key = OpenRegistryKey( KeyHandle, WS_STR_MISC, FALSE );
+
+ if ( Key ) {
+
+ switch ( Item ) {
+
+ case WSI_COMLINE:
+ if ( !LpszCommandLine ) {
+ DataSize = TMP_STRING_SIZE;
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_COMLINE,
+ NULL,
+ NULL,
+ Buffer,
+ &DataSize ) == NO_ERROR )) {
+ LpszCommandLine = realloc( LpszCommandLine, strlen( Buffer ) + 1 );
+ strcpy( LpszCommandLine, Buffer );
+ }
+ }
+ break;
+
+ case WSI_WINDOW:
+
+ if (WorkspaceOverride & WSO_WINDOW) {
+ break;
+ }
+ if ( Ok = LoadWindowData( Key, WS_STR_FRAME_WINDOW, &WindowData ) ) {
+ if ( IsZoomed( hwndFrame ) ) {
+ ShowWindow( hwndFrame, SW_NORMAL );
+ }
+ if ( Ok = MoveWindow( hwndFrame,
+ WindowData.X,
+ WindowData.Y,
+ WindowData.Width,
+ WindowData.Height,
+ TRUE ) ) {
+ switch ( WindowData.State ) {
+ case WSTATE_ICONIC:
+ ShowWindow( hwndFrame, SW_SHOWMINIMIZED );
+ break;
+ case WSTATE_MAXIMIZED:
+ ShowWindow( hwndFrame, SW_SHOWMAXIMIZED );
+ break;
+ default:
+ ShowWindow( hwndFrame, SW_NORMAL );
+ break;
+ }
+ }
+ }
+ break;
+
+ case WSI_DEFFONT:
+ Ok = LoadFont( Key, WS_STR_DEFFONT, &defaultFont );
+ break;
+
+ case WSI_FILEMRU:
+ Ok = LoadMRUList( Key, WS_STR_FILEMRU,
+ EDITOR_FILE, FILEMENU, IDM_FILE_EXIT );
+
+ break;
+
+ case WSI_RIBBON:
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_RIBBON,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ ribbon.hidden = !Dword;
+ CheckMenuItem(hMainMenu, IDM_VIEW_RIBBON,
+ ribbon.hidden ? MF_UNCHECKED : MF_CHECKED);
+ UpdateRibbon((WORD) (ribbon.hidden ? RIBBON_HIDE : RIBBON_UNHIDE), NULL);
+ }
+ break;
+
+ case WSI_STATUSBAR:
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_STATUSBAR,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ status.hidden = !Dword;
+ CheckMenuItem(hMainMenu, IDM_VIEW_STATUS,
+ status.hidden ? MF_UNCHECKED : MF_CHECKED);
+ UpdateStatus((WORD) (status.hidden ? STATUS_HIDE : STATUS_UNHIDE), NULL) ;
+ }
+ break;
+
+ case WSI_SRCMODE:
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_SRCMODE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ StatusSrc( Dword );
+ }
+ break;
+
+ case WSI_BRKPTS:
+ if ( Replace ) {
+ //
+ // Remove all the current breakpoints
+ //
+ BPDeleteAll();
+ ClearWndProcHistory();
+ BPCommit();
+ }
+
+ //
+ // Load breakpoints
+ //
+ if ( List = LoadMultiString( Key, WS_STR_BRKPTS, &DataSize ) ) {
+ while ( String = GetNextStringFromMultiString( List,
+ DataSize,
+ &Next ) ) {
+
+ Disabled = FALSE;
+
+ Brkpt = strchr( String, ' ' )+1;
+
+ while ( *String != ' ' ) {
+ if ( *String == 'D' ) {
+ Disabled = TRUE;
+ break;
+ }
+#ifdef DBCS
+ String = CharNext(String);
+#else
+ String++;
+#endif
+ }
+
+ bpstatus = BPParse( &hBpt, Brkpt, NULL, NULL,
+ LppdCur ? LppdCur->hpid : 0);
+
+ if ( (bpstatus != BPNOERROR) ||
+ (BPAddToList(hBpt, -1) != BPNOERROR ) ) {
+ Ok = FALSE;
+ break;
+ }
+
+ if ( Disabled ) {
+ BPDisable(hBpt);
+ } else if ( DebuggeeActive() ) {
+ BPBindHbpt( hBpt, NULL );
+ }
+ Dbg(BPCommit() == BPNOERROR);
+ }
+ DeallocateMultiString( List );
+ }
+
+ //
+ // Load WndProc list
+ //
+ if ( List = LoadMultiString( Key, WS_STR_WNDPROCHIST, &DataSize ) ) {
+ Ok |= SetWndProcHistory( List, DataSize );
+ DeallocateMultiString( List );
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ RegCloseKey( Key );
+ }
+ return Ok;
+}
+
+
+
+BOOLEAN
+SaveWorkSpaceMiscItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Default
+ )
+/*++
+
+Routine Description:
+
+ Saves a particular workspace misc item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Default - Supplies default flag
+
+Return Value:
+
+ BOOLEAN - TRUE if item saved
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY Key;
+ DWORD Dword;
+ WINDOW_DATA WindowData;
+ HBPT hBpt = 0;
+ char Buffer[ TMP_STRING_SIZE ];
+ LPSTR List = NULL;
+ DWORD ListLength = 0;
+
+
+ Assert( Item >= WSI_MISC_FIRST && Item <= WSI_MISC_LAST );
+
+ Key = OpenRegistryKey( KeyHandle, WS_STR_MISC, TRUE );
+
+ if ( Key ) {
+
+ switch ( Item ) {
+
+ case WSI_COMLINE:
+ if ( !Default ) {
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_COMLINE,
+ 0,
+ REG_SZ,
+ LpszCommandLine ? LpszCommandLine : "",
+ (LpszCommandLine ? strlen( LpszCommandLine ) : strlen( "" ) )+1
+ ) == NO_ERROR );
+ }
+ break;
+
+ case WSI_WINDOW:
+ Ok = FALSE;
+ if ( GetWindowMetrics( hwndFrame, &WindowData, FALSE ) ) {
+
+ Ok = SaveWindowData( Key,
+ WS_STR_FRAME_WINDOW,
+ &WindowData );
+ }
+ break;
+
+ case WSI_DEFFONT:
+ Ok = SaveFont( Key, WS_STR_DEFFONT, &defaultFont );
+ break;
+
+ case WSI_FILEMRU:
+ if ( Default ) {
+ Ok = TRUE;
+ } else {
+ Ok = SaveMRUList( Key, WS_STR_FILEMRU, EDITOR_FILE );
+ }
+ break;
+
+ case WSI_RIBBON:
+ Dword = !ribbon.hidden;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_RIBBON,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+ break;
+
+ case WSI_STATUSBAR:
+ Dword = !status.hidden;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_STATUSBAR,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+ break;
+
+ case WSI_SRCMODE:
+ Dword = status.fSrcMode;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_SRCMODE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+ break;
+
+ case WSI_BRKPTS:
+ Ok = TRUE;
+ if ( !Default ) {
+
+ //
+ // Save Breakpoints
+ //
+ hBpt = 0;
+ Dbg(BPNextHbpt(&hBpt, bptNext) == BPNOERROR);
+ while (Ok && (hBpt != NULL) ) {
+ Dbg(BPFormatHbpt( hBpt, Buffer, sizeof(Buffer), BPFCF_WNDPROC | BPFCF_WRKSPACE ) == BPNOERROR);
+ //String = strchr( Buffer, '{' );
+ //Ok = AddToMultiString( &List, &ListLength, String );
+ Ok = AddToMultiString( &List, &ListLength, Buffer );
+ Dbg(BPNextHbpt(&hBpt, bptNext) == BPNOERROR);
+ }
+
+ if ( Ok && List ) {
+
+ if ( RegSetValueEx( Key,
+ WS_STR_BRKPTS,
+ 0,
+ REG_MULTI_SZ,
+ List,
+ ListLength
+ ) != NO_ERROR ) {
+
+ Ok = FALSE;
+ }
+ }
+
+ if ( List ) {
+ DeallocateMultiString( List );
+ }
+
+ //
+ // Save WndProc History
+ //
+ if ( List = GetWndProcHistory( &ListLength ) ) {
+ if ( RegSetValueEx( Key,
+ WS_STR_WNDPROCHIST,
+ 0,
+ REG_MULTI_SZ,
+ List,
+ ListLength
+ ) != NO_ERROR ) {
+ Ok = FALSE;
+ }
+ DeallocateMultiString( List );
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ RegCloseKey( Key );
+ }
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadWorkSpaceOptionItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Replace
+ )
+/*++
+
+Routine Description:
+
+ Loads a particular workspace "options" item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Replace - Supplies replace flag
+
+Return Value:
+
+ BOOLEAN - TRUE if item loaded
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY Key;
+ HKEY SubKey;
+ HKEY DllKey;
+ DWORD Dword;
+ DWORD DataSize;
+ DWORD SubKeys;
+ FILETIME FileTime;
+ DWORD Error;
+ DWORD i;
+ char Buffer[ MAX_PATH ];
+ LPSTR String;
+ LPSTR List = NULL;
+ DWORD Next = 0;
+ EXCEPTION_LIST *ExceptionList;
+ EXCEPTION_LIST *Exception;
+ BOOLEAN fException;
+ BOOLEAN fEfd;
+ BOOLEAN fName;
+ BOOLEAN fCmd;
+ BOOLEAN fCmd2;
+ BOOLEAN fInvalid;
+ LPSTR lpName;
+ LPSTR lpCmd;
+ LPSTR lpCmd2;
+ LOGERR rVal;
+ DWORD ExceptionCode;
+ EXCEPTION_FILTER_DEFAULT efd;
+
+ Assert( Item >= WSI_OPTION_FIRST && Item <= WSI_OPTION_LAST );
+
+ Key = OpenRegistryKey( KeyHandle, WS_STR_OPTIONS, FALSE );
+
+ if ( Key ) {
+
+ switch ( Item ) {
+
+ case WSI_DBGOPT:
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_DBGCHLD,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fDebugChildren = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_CHILDGO,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fChildGo = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_ATTACHGO,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fAttachGo = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_IGNOREALL,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fIgnoreAll = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_VERBOSE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fVerbose = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_CONTEXT,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fShortContext = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_EXITGO,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fGoOnThreadTerm = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_EPSTEP,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fEPIsFirstStep = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_COMMANDREPEAT,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fCommandRepeat = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_NOVERSION,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fNoVersion = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_MASMEVAL,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fMasmEval = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_BACKGROUND,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fShBackground = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_ALTSS,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fAlternateSS = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_WOWVDM,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fWowVdm = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_DISCONNECT,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fDisconnectOnExit = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_LFOPT_APPEND,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.LfOptAppend = (BYTE)Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_LFOPT_AUTO,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.LfOptAuto = (BYTE)Dword;
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_LFOPT_FNAME,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ strcpy( runDebugParams.szLogFileName, Buffer );
+ } else {
+ runDebugParams.szLogFileName[0] = '\0';
+ }
+
+ if (runDebugParams.LfOptAuto) {
+ LogFileClose(NULL,0);
+ LogFileOpen(runDebugParams.szLogFileName,runDebugParams.LfOptAppend);
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_TITLE,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ strcpy( runDebugParams.szTitle, Buffer );
+ SetWindowText( hwndFrame, runDebugParams.szTitle );
+ } else {
+ runDebugParams.szTitle[0] = '\0';
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_REMOTE_PIPE,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ strcpy( runDebugParams.szRemotePipe, Buffer );
+ if (RemoteRunning) {
+ StartRemoteServer( "stop", FALSE );
+ }
+ if (runDebugParams.szRemotePipe[0]) {
+ StartRemoteServer( runDebugParams.szRemotePipe, FALSE );
+ }
+ } else {
+ runDebugParams.szRemotePipe[0] = '\0';
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( Key,
+ WS_STR_INHERITHANDLES,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ if (!(WorkspaceOverride & WSO_INHERITHANDLES)) {
+ runDebugParams.fInheritHandles = Dword;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_RADIX,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ radix = Dword;
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_REG,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ if ( !_stricmp( Buffer, WS_STR_REGULAR ) ) {
+ runDebugParams.RegModeExt = FALSE;
+ } else if ( !_stricmp( Buffer, WS_STR_EXTENDED ) ) {
+ runDebugParams.RegModeExt = TRUE;
+ } else {
+ Ok = FALSE;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_REGMMU,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.RegModeMMU = (BYTE)Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_DISPSEG,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.ShowSegVal = (BYTE)Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_IGNCASE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ fCaseSensitive = !Dword;
+ }
+
+ if ( List = LoadMultiString( Key, WS_STR_ROOTPATH, &DataSize ) ) {
+ SetRootNameMappings(List, DataSize);
+ DeallocateMultiString( List );
+ } else
+ SetRootNameMappings(NULL, 0);
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_SRCPATH,
+ NULL,
+ NULL,
+ (LPBYTE) Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+ SetDllName( DLL_SOURCE_PATH, Buffer);
+ }
+
+
+
+ DataSize = MAX_PATH;
+ ZeroMemory( Buffer, sizeof(Buffer) );
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_EXTENSION_NAMES,
+ NULL,
+ NULL,
+ (LPBYTE) Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+ SetExtensionDllNames( Buffer );
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( Key,
+ WS_STR_SUFFIX,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ SuffixToAppend = *Buffer;
+ } else {
+ SuffixToAppend = '\0';
+ }
+ if ( HModEE ) {
+ EESetSuffix( SuffixToAppend );
+ }
+
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_KERNELDEBUGGER, FALSE ) ) {
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_ENABLE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.fKernelDebugger = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_GOEXIT,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.fGoExit = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_INITIALBP,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.fInitialBp = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_MODEM,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.fUseModem = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_PORT,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.dwPort = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_BAUDRATE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.dwBaudRate = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_CACHE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.dwCache = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_KD_PLATFORM,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+
+ runDebugParams.KdParams.dwPlatform = Dword;
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_KD_CRASH,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ strcpy( runDebugParams.KdParams.szCrashDump, Buffer );
+ } else {
+ runDebugParams.KdParams.szCrashDump[0] = 0;
+ }
+
+ RegCloseKey( SubKey );
+ }
+
+ break;
+
+ case WSI_DBGDLL:
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_DBGDLL, FALSE ) ) {
+
+ DataSize = MAX_PATH;
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_SYMHAN,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ SetDllKey( DLL_SYMBOL_HANDLER, Buffer);
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_EXPEVAL,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ SetDllKey( DLL_EXPR_EVAL, Buffer);
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_TRANSLAY,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+ SetDllKey( DLL_TRANSPORT, Buffer);
+ }
+
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_EXECMOD,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR ) ) {
+
+
+ SetDllKey( DLL_EXEC_MODEL, Buffer );
+ }
+
+ RegCloseKey( SubKey );
+ }
+ break;
+
+
+ case WSI_USRDLL:
+
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_USERDLL, FALSE ) ) {
+
+ LOCATION Location;
+ LOADTIME LoadTime;
+ LSZ SrchPath;
+
+ ModListInit();
+
+ //
+ // Get defaults
+ //
+ DataSize = sizeof( LOCATION );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_DEFLOCATION,
+ NULL,
+ NULL,
+ (LPBYTE)&Location,
+ &DataSize ) != NO_ERROR ) ) {
+
+ Location = SYMBOL_LOCATION_IGNORE;
+ }
+
+ DataSize = sizeof( LOADTIME );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_DEFLOADTIME,
+ NULL,
+ NULL,
+ (LPBYTE)&LoadTime,
+ &DataSize ) != NO_ERROR ) ) {
+
+ LoadTime = LOAD_SYMBOLS_IGNORE;
+ }
+
+ Buffer[0] = '\0';
+ DataSize = MAX_PATH;
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_DEFSRCHPATH,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) != NO_ERROR ) ) {
+ SrchPath = NULL;
+
+ } else {
+
+ SrchPath = Buffer;
+ }
+
+ ModListSetDefaultShe( LoadTimeToShe( LoadTime ) );
+ ModListSetSearchPath( SrchPath );
+
+ //
+ // Get DLLs
+ //
+ DataSize = 0;
+ Error = RegQueryInfoKey( SubKey,
+ NULL,
+ &DataSize,
+ NULL,
+ &SubKeys,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &FileTime );
+
+ if ( (Error == NO_ERROR) || (Error == ERROR_INSUFFICIENT_BUFFER) ) {
+
+ for ( i=0; i < SubKeys; i++ ) {
+
+ if ( RegEnumKey( SubKey, i, Buffer, sizeof( Buffer ) ) ) {
+ break;
+ }
+
+ if ( DllKey = OpenRegistryKey(SubKey, Buffer, FALSE ) ) {
+
+ DataSize = MAX_PATH;
+ if ( Ok = ( RegQueryValueEx( DllKey,
+ WS_STR_USERDLLNAME,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) != NO_ERROR ) ) {
+
+ Buffer[0] = '\0';
+ }
+
+ DataSize = sizeof( LOCATION );
+ if ( Ok = ( RegQueryValueEx( DllKey,
+ WS_STR_LOCATION,
+ NULL,
+ NULL,
+ (LPBYTE)&Location,
+ &DataSize ) != NO_ERROR ) ) {
+
+ Location = SYMBOL_LOCATION_IGNORE;
+ }
+
+ DataSize = sizeof( LOADTIME );
+ if ( Ok = ( RegQueryValueEx( DllKey,
+ WS_STR_LOADTIME,
+ NULL,
+ NULL,
+ (LPBYTE)&LoadTime,
+ &DataSize ) != NO_ERROR ) ) {
+
+ LoadTime = LOAD_SYMBOLS_IGNORE;
+ }
+
+ ModListAdd( Buffer, LoadTimeToShe( LoadTime ) );
+
+ RegCloseKey( DllKey );
+ }
+ }
+ }
+
+ RegCloseKey( SubKey );
+ }
+
+ break;
+
+
+
+ case WSI_ENV:
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_ENV, FALSE ) ) {
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_TABSTOPS,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ environParams.tabStops = Dword;
+ tabSize = environParams.tabStops;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_KEEPTABS,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ environParams.keepTabs = Dword ? TRUE : FALSE;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_HORSCROLL,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ environParams.horizScrollBars = Dword ? TRUE : FALSE;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_VERSCROLL,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ environParams.vertScrollBars = Dword ? TRUE : FALSE;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_REDOSIZE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ environParams.undoRedoSize = Dword;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_SRCHPATH,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ environParams.SrchPath = Dword ? TRUE : FALSE;
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_ASKSAVE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ AskToSave = Dword ? TRUE : FALSE;
+ }
+
+ RegCloseKey( SubKey );
+ }
+ break;
+
+ case WSI_ASMOPT:
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_ASMOPT, FALSE ) ) {
+
+ runDebugParams.DisAsmOpts = 0;
+ DataSize = sizeof( Dword );
+ if ( Ok = ( RegQueryValueEx( SubKey,
+ WS_STR_SHOWSEG,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ if ( Dword ) {
+ runDebugParams.DisAsmOpts |= dopFlatAddr;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_SHOWRAW,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ if ( Dword ) {
+ runDebugParams.DisAsmOpts |= dopRaw;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_UPPERCASE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ if ( Dword ) {
+ runDebugParams.DisAsmOpts |= dopUpper;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_SHOWSRC,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ if ( Dword ) {
+ runDebugParams.DisAsmOpts |= 0x800;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_SHOWSYM,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ if ( Dword ) {
+ runDebugParams.DisAsmOpts |= dopSym;
+ }
+ }
+
+ DataSize = sizeof( Dword );
+ if ( Ok &= ( RegQueryValueEx( SubKey,
+ WS_STR_DEMAND,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) ) {
+ if ( Dword ) {
+ runDebugParams.DisAsmOpts |= dopDemand;
+ }
+ }
+
+ RegCloseKey( SubKey );
+ }
+
+ break;
+
+
+ case WSI_EXCPT:
+
+ //
+ // Free current default exception list
+ //
+ ExceptionList = DefaultExceptionList;
+ while( ExceptionList ) {
+
+ Exception = ExceptionList;
+ ExceptionList = ExceptionList->next;
+
+ if ( Exception->lpName ) {
+ free( Exception->lpName );
+ }
+
+ if ( Exception->lpCmd ) {
+ free( Exception->lpCmd );
+ }
+
+ if ( Exception->lpCmd2 ) {
+ free( Exception->lpCmd2 );
+ }
+
+ free( Exception );
+ }
+
+ DefaultExceptionList = ExceptionList = NULL;
+
+ if ( List = LoadMultiString( Key, WS_STR_EXCPT, &DataSize ) ) {
+
+ //
+ // Workspace has exception list, use it as default
+ //
+ while ( String = GetNextStringFromMultiString( List,
+ DataSize,
+ &Next ) ) {
+
+ rVal = ParseException( String,
+ 16,
+ &fException,
+ &fEfd,
+ &fName,
+ &fCmd,
+ &fCmd2,
+ &fInvalid,
+ &ExceptionCode,
+ &efd,
+ &lpName,
+ &lpCmd,
+ &lpCmd2 );
+
+ if ( rVal == LOGERROR_NOERROR ) {
+
+ Exception = (EXCEPTION_LIST *)
+ malloc( sizeof( EXCEPTION_LIST) );
+ if ( !Exception ) {
+ Ok = FALSE;
+ break;
+ }
+
+ Exception->dwExceptionCode = ExceptionCode;
+ Exception->efd = fEfd? efd : efdStop;
+ Exception->lpName = lpName;
+ Exception->lpCmd = lpCmd;
+ Exception->lpCmd2 = lpCmd2;
+
+ DefaultExceptionList =
+ InsertException( DefaultExceptionList, Exception );
+
+ } else if ( !HModSH || !HModEE) {
+ //
+ // We could not parse the exception because the
+ // SH or EE failed to load, there's no point in
+ // trying to parse the rest of them.
+ //
+ break;
+ }
+ }
+
+ DeallocateMultiString( List );
+ }
+
+ break;
+
+ case WSI_COLORS:
+
+ DataSize = sizeof( StringColors[0] ) * MAX_STRINGS;
+ Ok = ( RegQueryValueEx( Key,
+ WS_STR_COLORS,
+ NULL,
+ NULL,
+ (LPBYTE)StringColors,
+ &DataSize ) == NO_ERROR );
+ break;
+
+ default:
+ break;
+ }
+
+ RegCloseKey( Key );
+ }
+ return Ok;
+}
+
+
+
+BOOLEAN
+SaveWorkSpaceOptionItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Default
+ )
+/*++
+
+Routine Description:
+
+ Saves a particular workspace option item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Default - Supplies default flag
+
+Return Value:
+
+ BOOLEAN - TRUE if item saved
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY Key;
+ HKEY SubKey;
+ HKEY DllKey;
+ DWORD Dword;
+ char * String;
+ int i;
+ char Buffer[ 2000 ];
+ char KeyName[ 128 ];
+ EXCEPTION_LIST *ExceptionList;
+ LPSTR List = NULL;
+ DWORD ListLength = 0;
+
+ Assert( Item >= WSI_OPTION_FIRST && Item <= WSI_OPTION_LAST );
+
+ Key = OpenRegistryKey( KeyHandle, WS_STR_OPTIONS, TRUE );
+
+ if ( Key ) {
+
+ switch ( Item ) {
+
+ case WSI_DBGOPT:
+ Dword = runDebugParams.fDebugChildren;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_DBGCHLD,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fChildGo;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_CHILDGO,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fAttachGo;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_ATTACHGO,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fIgnoreAll;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_IGNOREALL,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fVerbose;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_VERBOSE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fShortContext;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_CONTEXT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fGoOnThreadTerm;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_EXITGO,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fEPIsFirstStep;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_EPSTEP,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fCommandRepeat;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_COMMANDREPEAT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fNoVersion;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_NOVERSION,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fMasmEval;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_MASMEVAL,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fShBackground;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_BACKGROUND,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fWowVdm;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_WOWVDM,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fDisconnectOnExit;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_DISCONNECT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fAlternateSS;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_ALTSS,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.LfOptAppend;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_LFOPT_APPEND,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.LfOptAuto;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_LFOPT_AUTO,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ String = runDebugParams.szLogFileName;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_LFOPT_FNAME,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen( "")) + 1
+ ) == NO_ERROR );
+
+ String = runDebugParams.szTitle;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_TITLE,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen( "")) + 1
+ ) == NO_ERROR );
+
+ String = runDebugParams.szRemotePipe;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_REMOTE_PIPE,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen( "")) + 1
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.fInheritHandles;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_INHERITHANDLES,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = radix;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_RADIX,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ if ( runDebugParams.RegModeExt ) {
+ String = WS_STR_EXTENDED;
+ } else {
+ String = WS_STR_REGULAR;
+ }
+
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_REG,
+ 0,
+ REG_SZ,
+ String,
+ strlen( String ) + 1
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.RegModeMMU;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_REGMMU,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.ShowSegVal;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_DISPSEG,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = !fCaseSensitive;
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_IGNCASE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ String = GetDllName(DLL_SOURCE_PATH);
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_SRCPATH,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen( "")) + 1
+ ) == NO_ERROR );
+
+ ListLength = 0;
+ List = NULL;
+ if (GetRootNameMappings(&List, &ListLength)) {
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_ROOTPATH,
+ 0,
+ REG_MULTI_SZ,
+ List,
+ ListLength
+ ) == ERROR_SUCCESS );
+
+ }
+ if (List)
+ DeallocateMultiString(List);
+
+ String = GetExtensionDllNames(&i);
+ if (String) {
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_EXTENSION_NAMES,
+ 0,
+ REG_MULTI_SZ,
+ String,
+ i
+ ) == NO_ERROR );
+ free( String );
+ }
+
+ Buffer[0] = SuffixToAppend;
+ Buffer[1] = '\0';
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_SUFFIX,
+ 0,
+ REG_SZ,
+ Buffer,
+ strlen( Buffer )+1
+ ) == NO_ERROR );
+
+ if (SubKey = OpenRegistryKey( Key, WS_STR_KERNELDEBUGGER, TRUE)) {
+
+ Dword = runDebugParams.fKernelDebugger;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_ENABLE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.fGoExit;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_GOEXIT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.fInitialBp;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_INITIALBP,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.fUseModem,
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_MODEM,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.dwBaudRate,
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_BAUDRATE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.dwPort,
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_PORT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.dwCache;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_CACHE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = runDebugParams.KdParams.dwPlatform;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_PLATFORM,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ strcpy( Buffer, runDebugParams.KdParams.szCrashDump );
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_KD_CRASH,
+ 0,
+ REG_SZ,
+ (LPBYTE)&Buffer,
+ strlen(Buffer)+1
+ ) == NO_ERROR );
+
+ RegCloseKey( SubKey );
+ }
+
+ break;
+
+
+ case WSI_DBGDLL:
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_DBGDLL, TRUE ) ) {
+
+ String = GetDllKey(DLL_SYMBOL_HANDLER);
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_SYMHAN,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen("")) + 1
+ ) == NO_ERROR );
+
+ String = GetDllKey(DLL_EXPR_EVAL);
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_EXPEVAL,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen("")) + 1
+ ) == NO_ERROR );
+
+ String = GetDllKey(DLL_TRANSPORT);
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_TRANSLAY,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen("")) + 1
+ ) == NO_ERROR );
+
+ String = GetDllKey(DLL_EXEC_MODEL);
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_EXECMOD,
+ 0,
+ REG_SZ,
+ String ? String : "",
+ (String ? strlen( String ) : strlen("")) + 1
+ ) == NO_ERROR );
+ RegCloseKey( SubKey );
+ }
+ break;
+
+
+ case WSI_USRDLL:
+
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_USERDLL, TRUE ) ) {
+
+ LOCATION Location;
+ LOADTIME LoadTime;
+ PVOID Next;
+ SHE She;
+
+ //
+ // Write defaults
+ //
+ ModListGetSearchPath( Buffer, sizeof( Buffer ) );
+ ModListGetDefaultShe( NULL, &She );
+ LoadTime = SheToLoadTime( She );
+ Location = SYMBOL_LOCATION_LOCAL;
+
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_DEFLOCATION,
+ 0,
+ REG_BINARY,
+ (LPBYTE)&Location,
+ sizeof(LOCATION)
+ ) == NO_ERROR );
+
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_DEFLOADTIME,
+ 0,
+ REG_BINARY,
+ (LPBYTE)&LoadTime,
+ sizeof(LOADTIME)
+ ) == NO_ERROR );
+
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_DEFSRCHPATH,
+ 0,
+ REG_SZ,
+ (LPBYTE)&Buffer,
+ strlen(Buffer)+1
+ ) == NO_ERROR );
+
+
+ //
+ // Write DLLs
+ //
+ Next = NULL;
+ i = 0;
+
+ while ( Next = ModListGetNext( Next, Buffer, &She ) ) {
+
+ LoadTime = SheToLoadTime( She );
+ Location = SYMBOL_LOCATION_LOCAL;
+
+ sprintf( KeyName, WS_STR_USERDLL_TEMPLATE, i++ );
+
+ if ( DllKey = OpenRegistryKey( SubKey, KeyName, TRUE ) ) {
+
+ Ok = ( RegSetValueEx( DllKey,
+ WS_STR_USERDLLNAME,
+ 0,
+ REG_SZ,
+ (LPBYTE)Buffer,
+ strlen( Buffer )+1
+ ) == NO_ERROR );
+
+ Ok = ( RegSetValueEx( DllKey,
+ WS_STR_LOCATION,
+ 0,
+ REG_BINARY,
+ (LPBYTE)&Location,
+ sizeof(LOCATION)
+ ) == NO_ERROR );
+
+ Ok = ( RegSetValueEx( DllKey,
+ WS_STR_LOADTIME,
+ 0,
+ REG_BINARY,
+ (LPBYTE)&LoadTime,
+ sizeof(LOADTIME)
+ ) == NO_ERROR );
+
+ RegCloseKey( DllKey );
+ }
+ }
+
+ RegCloseKey( SubKey );
+ }
+
+ break;
+
+
+ case WSI_ENV:
+
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_ENV, TRUE ) ) {
+ Dword = environParams.tabStops;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_TABSTOPS,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = environParams.keepTabs ? 1 : 0;
+ Ok |= ( RegSetValueEx( SubKey,
+ WS_STR_KEEPTABS,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = environParams.horizScrollBars ? 1 : 0;
+ Ok |= ( RegSetValueEx( SubKey,
+ WS_STR_HORSCROLL,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = environParams.vertScrollBars ? 1 : 0;
+ Ok |= ( RegSetValueEx( SubKey,
+ WS_STR_VERSCROLL,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = environParams.undoRedoSize;
+ Ok |= ( RegSetValueEx( SubKey,
+ WS_STR_REDOSIZE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = environParams.SrchPath ? 1 : 0;
+ Ok |= ( RegSetValueEx( SubKey,
+ WS_STR_SRCHPATH,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = AskToSave ? 1 : 0;
+ Ok |= ( RegSetValueEx( SubKey,
+ WS_STR_ASKSAVE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ RegCloseKey( SubKey );
+
+ }
+ break;
+
+
+ case WSI_ASMOPT:
+ if ( SubKey = OpenRegistryKey( Key, WS_STR_ASMOPT, TRUE ) ) {
+
+ Dword = (runDebugParams.DisAsmOpts & dopFlatAddr) ? 1 : 0;
+ Ok = ( RegSetValueEx( SubKey,
+ WS_STR_SHOWSEG,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = (runDebugParams.DisAsmOpts & dopRaw) ? 1 : 0;
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_SHOWRAW,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = (runDebugParams.DisAsmOpts & dopUpper) ? 1 : 0;
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_UPPERCASE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = (runDebugParams.DisAsmOpts & 0x800) ? 1 : 0;
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_SHOWSRC,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = (runDebugParams.DisAsmOpts & dopSym) ? 1 : 0;
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_SHOWSYM,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Dword = (runDebugParams.DisAsmOpts & dopDemand) ? 1 : 0;
+ Ok &= ( RegSetValueEx( SubKey,
+ WS_STR_DEMAND,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+
+ RegCloseKey( SubKey );
+ }
+
+ break;
+
+
+ case WSI_EXCPT:
+
+ //
+ // Note that we only save one exception list: The default
+ // exception list. This exception list corresponds to
+ // process 0. If other processes have different exception
+ // lists, they will be lost.
+ //
+ ExceptionList = DefaultExceptionList;
+
+ while ( ExceptionList ) {
+
+ FormatException( ExceptionList->efd,
+ ExceptionList->dwExceptionCode,
+ ExceptionList->lpName,
+ ExceptionList->lpCmd,
+ ExceptionList->lpCmd2,
+ " ",
+ Buffer );
+
+ Ok &= AddToMultiString( &List, &ListLength, Buffer );
+
+ ExceptionList = ExceptionList->next;
+ }
+
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_EXCPT,
+ 0,
+ REG_MULTI_SZ,
+ List,
+ ListLength
+ ) != NO_ERROR );
+
+ if ( List ) {
+ DeallocateMultiString( List );
+ }
+
+ break;
+
+
+
+ case WSI_COLORS:
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_COLORS,
+ 0,
+ REG_BINARY,
+ (LPBYTE)StringColors,
+ sizeof( StringColors[0] ) * MAX_STRINGS
+ ) == NO_ERROR );
+ break;
+
+ default:
+ break;
+ }
+
+ RegCloseKey( Key );
+ }
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadWorkSpaceWindowItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Replace,
+ BOOLEAN LoadAll
+ )
+/*++
+
+Routine Description:
+
+ Loads a particular workspace window item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Replace - Supplies replace flag
+ LoadAll - Supplies flag which if TRUE loads all
+ windows, ignoring Item
+
+Return Value:
+
+ BOOLEAN - TRUE if item loaded
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY Key;
+
+ Assert( Item >= WSI_WINDOW_FIRST && Item <= WSI_WINDOW_LAST );
+
+ Key = OpenRegistryKey( KeyHandle, WS_STR_VIEWS, FALSE );
+
+ if ( Key ) {
+
+ if ( LoadAll ) {
+ Ok = LoadWindowType( Key, 0, Replace, TRUE );
+ } else {
+ switch ( Item ) {
+
+ case WSI_WDWDOC:
+ Ok = LoadWindowType( Key, DOC_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWWCH:
+ Ok = LoadWindowType( Key, WATCH_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWLOC:
+ Ok = LoadWindowType( Key, LOCALS_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWCALLS:
+ Ok = LoadWindowType( Key, CALLS_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWCPU:
+ Ok = LoadWindowType( Key, CPU_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWASM:
+ Ok = LoadWindowType( Key, DISASM_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWCMD:
+ Ok = LoadWindowType( Key, COMMAND_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWFLT:
+ Ok = LoadWindowType( Key, FLOAT_WIN, Replace, FALSE );
+ break;
+
+ case WSI_WDWMEM:
+ Ok = LoadWindowType( Key, MEMORY_WIN, Replace, FALSE );
+ break;
+
+ default:
+ break;
+ }
+ }
+ RegCloseKey( Key );
+ }
+ return Ok;
+}
+
+
+
+
+
+BOOLEAN
+SaveWorkSpaceWindowItem (
+ HKEY KeyHandle,
+ WORKSPACE_ITEM Item,
+ BOOLEAN Default,
+ BOOLEAN SaveAll
+ )
+/*++
+
+Routine Description:
+
+ Saves a particular workspace window item
+
+Arguments:
+
+ KeyHandle - Supplies the handle to the workspace
+ Item - Supplies the item to load
+ Default - Supplies default flag
+ SaveAll - Supplies flag which if TRUE saves all
+ windows and ignores Item.
+
+Return Value:
+
+ BOOLEAN - TRUE if item saved
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ HKEY Key;
+
+ Assert( Item >= WSI_WINDOW_FIRST && Item <= WSI_WINDOW_LAST );
+
+ Key = OpenRegistryKey( KeyHandle, WS_STR_VIEWS, TRUE );
+
+ if ( Key ) {
+
+ if ( SaveAll ) {
+ Ok = SaveWindowType( Key, 0, Default, TRUE );
+ } else {
+ switch ( Item ) {
+
+ case WSI_WDWDOC:
+ Ok = SaveWindowType( Key, DOC_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWWCH:
+ Ok = SaveWindowType( Key, WATCH_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWLOC:
+ Ok = SaveWindowType( Key, LOCALS_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWCALLS:
+ Ok = SaveWindowType( Key, CALLS_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWCPU:
+ Ok = SaveWindowType( Key, CPU_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWASM:
+ Ok = SaveWindowType( Key, DISASM_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWCMD:
+ Ok = SaveWindowType( Key, COMMAND_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWFLT:
+ Ok = SaveWindowType( Key, FLOAT_WIN, Default, FALSE );
+ break;
+
+ case WSI_WDWMEM:
+ Ok = SaveWindowType( Key, MEMORY_WIN, Default, FALSE );
+ break;
+
+ default:
+ break;
+ }
+ }
+ RegCloseKey( Key );
+ }
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadWindowType (
+ HKEY Hkey,
+ DWORD Type,
+ BOOLEAN Replace,
+ BOOLEAN LoadAll
+ )
+/*++
+
+Routine Description:
+
+ Loads all windows of a certain type
+
+Arguments:
+
+ Hkey - Supplies registry key
+ Type - Supplies window type (i.e. document type)
+ Replace - Supplies replace flag
+ LoadAll - Supplies LoadAll flag (ignores Type)
+
+Return Value:
+
+ BOOLEAN - TRUE if windows loaded
+
+--*/
+{
+ int View;
+ HKEY Key;
+ DWORD Dword;
+ DWORD DataSize;
+ FILETIME FileTime;
+ DWORD SubKeys;
+ DWORD Error;
+ int Order;
+ char Buffer[ MAX_PATH ];
+ DWORD i = 0;
+ BOOLEAN Ok = TRUE;
+ VIEW_ORDER ViewOrder[ MAX_VIEWS ];
+
+ //
+ // If replacing, get rid of all the current windows of this particular
+ // type.
+ //
+ if ( Replace ) {
+ for ( View = 0; View < MAX_VIEWS; View++ ) {
+ int Doc = Views[View].Doc;
+ if ( Doc > -1 ) {
+ if (LoadAll || (Docs[ Doc ].docType == (WORD)Type)) {
+ SendMessage( Views[ View ].hwndFrame,
+ WM_SYSCOMMAND,
+ SC_CLOSE,
+ 0L );
+ }
+ } else if ( Doc != -1 ) {
+ if (LoadAll || (Doc == -(int)Type)) {
+ SendMessage( Views[ View ].hwndFrame,
+ WM_SYSCOMMAND,
+ SC_CLOSE,
+ 0L );
+ }
+ }
+ }
+ }
+
+ //
+ // Load the views from the registry
+ //
+
+ DataSize = 0;
+ Error = RegQueryInfoKey( Hkey,
+ NULL,
+ &DataSize,
+ NULL,
+ &SubKeys,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &FileTime );
+
+ if ( (Error == NO_ERROR) || (Error == ERROR_INSUFFICIENT_BUFFER) ) {
+
+
+ //
+ // If loading all, determine the view ordering and load the views
+ // in the appropriate order.
+ //
+ if ( LoadAll ) {
+
+ //
+ // Determine view ordering
+ //
+ for ( View = 0; View < MAX_VIEWS; View++ ) {
+ ViewOrder[View].View = -1;
+ ViewOrder[View].Order = MAX_VIEWS+1;
+ }
+
+ for ( i=0; i < SubKeys; i++ ) {
+
+ if ( RegEnumKey( Hkey, i, Buffer, sizeof( Buffer ) ) ) {
+ Ok = FALSE;
+ break;
+ }
+
+ if ( Key = OpenRegistryKey(Hkey, Buffer, FALSE ) ) {
+
+ View = atoi( Buffer );
+
+ DataSize = sizeof( Dword );
+ if ( (RegQueryValueEx( Key,
+ WS_STR_ORDER,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR) &&
+ (Dword < MAX_VIEWS) ) {
+ Order = MAX_VIEWS - Dword;
+ } else {
+ Order = View;
+ }
+
+
+ ViewOrder[View].View = View;
+ ViewOrder[View].Order = Order;
+
+ RegCloseKey( Key );
+ }
+ }
+
+ qsort( ViewOrder, sizeof( ViewOrder )/sizeof( ViewOrder[0] ), sizeof( ViewOrder[0] ), CompareViewOrder );
+
+ //
+ // Now load the views in order
+ //
+ for ( View = 0;
+ View < MAX_VIEWS && ViewOrder[View].View != -1;
+ View++ ) {
+
+ sprintf(Buffer, WS_STR_VIEWKEY_TEMPLATE, ViewOrder[View].View);
+
+ if ( Key = OpenRegistryKey(Hkey, Buffer, FALSE ) ) {
+
+ DataSize = sizeof( Dword );
+ if ( RegQueryValueEx( Key,
+ WS_STR_TYPE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) {
+
+ Ok = LoadView( Key, ViewOrder[View].View, Dword );
+ }
+ RegCloseKey( Key );
+ }
+ }
+
+ } else {
+
+ for ( i=0; i < SubKeys; i++ ) {
+
+ if ( RegEnumKey( Hkey, i, Buffer, sizeof( Buffer ) ) ) {
+ Ok = FALSE;
+ break;
+ }
+
+ if ( Key = OpenRegistryKey(Hkey, Buffer, FALSE ) ) {
+
+ DataSize = sizeof( Dword );
+ if ( RegQueryValueEx( Key,
+ WS_STR_TYPE,
+ NULL,
+ NULL,
+ (LPBYTE)&Dword,
+ &DataSize ) == NO_ERROR ) {
+
+ //if ( LoadAll || (Dword == Type) ) {
+ if ( Dword == Type ) {
+ View = atoi( Buffer );
+ Ok = LoadView( Key, View, Dword );
+ }
+ } else {
+ Ok = FALSE;
+ }
+
+ RegCloseKey( Key );
+ }
+ }
+ }
+ }
+
+ return Ok;
+}
+
+
+
+
+
+BOOLEAN
+SaveWindowType (
+ HKEY Hkey,
+ DWORD Type,
+ BOOLEAN Default,
+ BOOLEAN SaveAll
+ )
+/*++
+
+Routine Description:
+
+ Saves all windows of a certain type
+
+Arguments:
+
+ Hkey - Supplies registry key
+ Type - Supplies window type (i.e. document type)
+ Default - Supplies Default flag
+ SaveAll - Supplies SaveAll flag (Type is ignored)
+
+Return Value:
+
+ BOOLEAN - TRUE if windows saved
+
+--*/
+{
+ int View;
+ BOOLEAN Ok = TRUE;
+ HWND hwnd;
+ int Order = 0;
+ VIEW_ORDER ViewOrder[ MAX_VIEWS ];
+
+
+ //
+ // If saving all, determine the view ordering.
+ //
+ if ( SaveAll ) {
+
+ for ( View = 0; View < MAX_VIEWS; View++ ) {
+ ViewOrder[View].View = View;
+ ViewOrder[View].Order = -1;
+ }
+
+ //hwnd = GetWindow( hwndMDIClient, GW_CHILD );
+
+ hwnd = GetTopWindow (hwndMDIClient);
+ while ( hwnd ) {
+
+ View = GetWindowWord( hwnd, GWW_VIEW );
+
+ if ( View >= 0 && View < MAX_VIEWS ) {
+ ViewOrder[View].Order = Order++;
+ }
+
+ hwnd = GetNextWindow( hwnd, GW_HWNDNEXT );
+ }
+ }
+
+
+ for ( View = 0; Ok && (View < MAX_VIEWS); View++ ) {
+ int Doc = Views[View].Doc;
+ if ( Doc > -1 ) {
+ if (SaveAll || (Docs[ Doc ].docType == (WORD)Type)) {
+ if (!Default || (Docs[ Doc ].docType != MEMORY_WIN)) {
+ Ok &= SaveView( Hkey,
+ View,
+ ViewOrder[View].Order,
+ Default );
+ }
+ }
+ } else if (Doc != -1) {
+ if (SaveAll || (Doc == -(int)Type)) {
+ Ok &= SaveView( Hkey, View, ViewOrder[View].Order, Default );
+ }
+ }
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+LoadView (
+ HKEY Key,
+ int WantedView,
+ DWORD Type
+ )
+/*++
+
+Routine Description:
+
+ Loads a view
+
+Arguments:
+
+ key - Supplies registry key
+ WantedView - Supplies desired view
+ Type - Supplies type of window
+
+Return Value:
+
+ BOOLEAN - TRUE if view loaded
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ WORD Mode = MODE_CREATE;
+ char *FileName = NULL;
+ HFONT Font = 0;
+ LOGFONT LogFont;
+ DWORD DataSize;
+ char Buffer[ MAX_PATH ];
+ WINDOW_DATA WindowData;
+ WININFO WinInfo;
+ int View;
+ DWORD iFormat = MW_BYTE;
+ DWORD Live = FALSE;
+ LPSTR List = NULL;
+ DWORD Next = 0;
+ NPDOCREC Doc;
+ DWORD Line;
+ DWORD Column;
+ DWORD ReadOnly = (DWORD)FALSE;
+ PLONG Pane;
+ PLONG CallsOpt;
+ CHOOSEFONT Cf;
+ UINT uSwitch;
+ NPVIEWREC v;
+ HDC hDC;
+ TEXTMETRIC tm;
+
+ //
+ // Get window placement
+ //
+ if ( Ok = LoadWindowData( Key, WS_STR_PLACEMENT, &WindowData ) ) {
+
+ WinInfo.coord.left = WindowData.X;
+ WinInfo.coord.top = WindowData.Y;
+ WinInfo.coord.right = WindowData.X + WindowData.Width;
+ WinInfo.coord.bottom = WindowData.Y + WindowData.Height;
+
+ WinInfo.style = 0;
+
+ Ok &= LoadFont( Key,
+ WS_STR_FONT,
+ &LogFont );
+
+ if ( Ok ) {
+ Ok &= ( (Font = CreateFontIndirect( &LogFont )) != 0 );
+ }
+
+ switch ( Type ) {
+
+ case DOC_WIN:
+ DataSize = MAX_PATH;
+ if ( RegQueryValueEx( Key,
+ WS_STR_FILENAME,
+ NULL,
+ NULL,
+ Buffer,
+ &DataSize ) == NO_ERROR ) {
+ FileName = Buffer;
+ Mode = MODE_OPENCREATE;
+ }
+
+ DataSize = sizeof(ReadOnly);
+ RegQueryValueEx( Key,
+ WS_STR_READONLY,
+ NULL,
+ NULL,
+ (LPBYTE)&ReadOnly,
+ &DataSize );
+ break;
+
+ default:
+ break;
+ }
+
+ if (Type == DOC_WIN) {
+
+ View = AddFile( Mode,
+ (WORD)Type,
+ FileName,
+ &WinInfo,
+ Font,
+ (BOOL)ReadOnly,
+ -1,
+ WantedView );
+
+ Ok = (BOOLEAN)( View != -1 );
+
+ } else {
+ View = OpenDebugWindow( Type, &WinInfo, WantedView );
+ Ok = (View != -1);
+ if ( Ok ) {
+
+ v = &Views[View];
+
+ Cf.lStructSize = sizeof (CHOOSEFONT);
+ Cf.hwndOwner = v->hwndClient;
+ Cf.hDC = NULL;
+ Cf.lpLogFont = &LogFont;
+
+ if (v->Doc < -1) {
+ uSwitch = -(v->Doc);
+ } else {
+ uSwitch = Docs[ v->Doc ].docType;
+ }
+
+ switch (uSwitch) {
+
+ case WATCH_WIN:
+ SendMessageNZ( GetWatchHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case LOCALS_WIN:
+ SendMessageNZ( GetLocalHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case CALLS_WIN:
+ SendMessageNZ( GetCallsHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case CPU_WIN:
+ SendMessageNZ( GetCpuHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ case FLOAT_WIN:
+ SendMessageNZ( GetFloatHWND(), WM_SETFONT, 0, (LONG)&Cf);
+ break;
+
+ default:
+ Dbg(hDC = GetDC(v->hwndClient));
+ v->font = Font;
+ Dbg(SelectObject(hDC, v->font));
+ Dbg(GetTextMetrics (hDC, &tm));
+ v->charHeight = tm.tmHeight;
+ v->maxCharWidth = tm.tmMaxCharWidth;
+ v->aveCharWidth = tm.tmAveCharWidth;
+ v->charSet = tm.tmCharSet;
+ GetCharWidth(hDC,
+ 0,
+ MAX_CHARS_IN_FONT - 1,
+ (LPINT)v->charWidth);
+ Dbg(ReleaseDC (v->hwndClient, hDC));
+ DestroyCaret ();
+ CreateCaret(v->hwndClient, 0, 3, v->charHeight);
+ PosXY(View, v->X, v->Y, FALSE);
+ ShowCaret(v->hwndClient);
+ SendMessage(v->hwndClient, WM_FONTCHANGE, 0, 0L);
+ InvalidateRect(v->hwndClient, (LPRECT)NULL, FALSE);
+ }
+ }
+ }
+
+ if (Ok) {
+
+ if ( Type == CALLS_WIN ) {
+
+ DataSize = 0;
+ RegQueryValueEx( Key,
+ WS_STR_CALLS,
+ NULL,
+ NULL,
+ NULL,
+ &DataSize );
+
+ if ( DataSize > 0 ) {
+ if ( CallsOpt = (PLONG)malloc( DataSize ) ) {
+ if ( RegQueryValueEx( Key,
+ WS_STR_CALLS,
+ NULL,
+ NULL,
+ (LPBYTE)CallsOpt,
+ &DataSize ) == NO_ERROR) {
+
+ SetCallsStatus( View, CallsOpt );
+
+ Ok |= TRUE;
+ free( CallsOpt );
+ }
+ }
+ }
+
+ }
+
+ if ( Type == WATCH_WIN ||
+ Type == LOCALS_WIN ||
+ Type == CPU_WIN ||
+ Type == FLOAT_WIN ) {
+
+ DataSize = 0;
+ RegQueryValueEx( Key,
+ WS_STR_PANE,
+ NULL,
+ NULL,
+ NULL,
+ &DataSize );
+
+ if ( DataSize > 0 ) {
+ if ( Pane = (PLONG)malloc( DataSize ) ) {
+ if ( RegQueryValueEx( Key,
+ WS_STR_PANE,
+ NULL,
+ NULL,
+ (LPBYTE)Pane,
+ &DataSize ) == NO_ERROR) {
+
+
+ SetPaneStatus( View, Pane );
+
+ Ok |= TRUE;
+ free( Pane );
+ }
+ }
+ }
+ }
+
+
+ switch ( WindowData.State ) {
+ case WSTATE_ICONIC:
+ ShowWindow( Views[View].hwndFrame, SW_SHOWMINIMIZED );
+ break;
+ case WSTATE_MAXIMIZED:
+ ShowWindow( Views[View].hwndFrame, SW_SHOWMAXIMIZED );
+ default:
+ break;
+ }
+
+ switch ( Type ) {
+
+ case DOC_WIN:
+ if ( FileName ) {
+ DataSize = sizeof( Line );
+ RegQueryValueEx( Key,
+ WS_STR_LINE,
+ NULL,
+ NULL,
+ (LPBYTE)&Line,
+ &DataSize );
+
+ DataSize = sizeof( Column );
+ RegQueryValueEx( Key,
+ WS_STR_COLUMN,
+ NULL,
+ NULL,
+ (LPBYTE)&Column,
+ &DataSize );
+
+ Line = min(max(1, (int)Line), (int)Docs[Views[View].Doc].NbLines) - 1;
+ PosXY(View, Column, Line, FALSE);
+ }
+ break;
+
+ case MEMORY_WIN:
+ DataSize = sizeof( Buffer );
+ if ( RegQueryValueEx( Key,
+ WS_STR_EXPRESSION,
+ NULL,
+ NULL,
+ Buffer,
+ &DataSize ) == NO_ERROR ) {
+
+ DataSize = sizeof( iFormat );
+ RegQueryValueEx( Key,
+ WS_STR_FORMAT,
+ NULL,
+ NULL,
+ (LPBYTE)&iFormat,
+ &DataSize );
+
+ DataSize = sizeof( Live );
+ RegQueryValueEx( Key,
+ WS_STR_LIVE,
+ NULL,
+ NULL,
+ (LPBYTE)&Live,
+ &DataSize );
+
+ MemWinDesc[ View ].iFormat = iFormat;
+ MemWinDesc[ View ].fLive = Live;
+ MemWinDesc[ View ].atmAddress = AddAtom( Buffer );
+ strcpy( MemWinDesc[ View ].szAddress, Buffer );
+
+ Doc = &Docs[ Views[ View].Doc ];
+ Dbg(LoadString(hInst, SYS_MemoryWin_Title, Buffer, sizeof( Buffer )));
+ RemoveMnemonic(Buffer, Doc->FileName);
+ lstrcat (Doc->FileName,"(");
+ lstrcat (Doc->FileName, MemWinDesc[ View ].szAddress);
+ lstrcat (Doc->FileName,")");
+
+ RefreshWindowsTitle( Views[ View].Doc );
+ }
+
+ ViewMem( View, FALSE );
+ break;
+
+ case WATCH_WIN:
+ /*
+ //
+ // NOTENOTE Ramonsa - Add watch expressions when new
+ // watch window code is on-line.
+ //
+ if ( Ok && (List = LoadMultiString( Key, WS_STR_EXPRESSION, &DataSize )) ) {
+ while ( Ok && (String = GetNextStringFromMultiString( List,
+ DataSize,
+ &Next )) ) {
+ Ok &= (AddWatchNode( String ) != NULL );
+ }
+ DeallocateMultiString( List );
+ }
+ */
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+SaveView (
+ HKEY Hkey,
+ int View,
+ int Order,
+ BOOLEAN Default
+ )
+/*++
+
+Routine Description:
+
+ Saves a view
+
+Arguments:
+
+ Hkey - Supplies registry key
+ View - Supplies index of view
+ Order - Supplies view order
+ Default - Supplies Default flag
+
+Return Value:
+
+ BOOLEAN - TRUE if view saved
+
+--*/
+{
+ HKEY Key;
+ WINDOW_DATA WindowData;
+ LOGFONT LogFont;
+ DWORD Dword;
+ DWORD Type;
+ char Buffer[ MAX_PATH ];
+ LPSTR List = NULL;
+ DWORD ListLength = 0;
+ BOOLEAN Ok = FALSE;
+ PLONG Pane;
+ PLONG CallsOpt;
+
+ sprintf( Buffer, WS_STR_VIEWKEY_TEMPLATE, View );
+
+ if ( Key = OpenRegistryKey(Hkey, Buffer, TRUE ) ) {
+
+ //
+ // Save view type
+ //
+
+ if (Views[ View ].Doc < -1) {
+ Type = - Views[ View ].Doc;
+ } else {
+ Type = Docs[ Views[ View ].Doc ].docType;
+ }
+ Ok = (RegSetValueEx( Key,
+ WS_STR_TYPE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Type,
+ sizeof( Type )
+ ) == NO_ERROR );
+
+ if ( Type == CALLS_WIN ) {
+
+ if ( CallsOpt = GetCallsStatus( View ) ) {
+
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_CALLS,
+ 0,
+ REG_BINARY,
+ (LPBYTE)CallsOpt,
+ *CallsOpt
+ ) == NO_ERROR );
+
+ FreeCallsStatus( View, CallsOpt );
+ }
+
+ }
+
+ if ( Type == WATCH_WIN ||
+ Type == LOCALS_WIN ||
+ Type == CPU_WIN ||
+ Type == FLOAT_WIN ) {
+
+ if ( Pane = GetPaneStatus( View ) ) {
+
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_PANE,
+ 0,
+ REG_BINARY,
+ (LPBYTE)Pane,
+ *Pane
+ ) == NO_ERROR );
+
+ FreePaneStatus( View, Pane );
+ }
+ }
+
+ //
+ // Save window placement
+ //
+ if ( GetWindowMetrics( Views[ View ].hwndFrame, &WindowData, TRUE ) ) {
+
+ Ok &= SaveWindowData( Key,
+ WS_STR_PLACEMENT,
+ &WindowData );
+
+ GetObject( Views[ View ].font, sizeof( LogFont ), &LogFont );
+
+ Ok &= SaveFont( Key,
+ WS_STR_FONT,
+ &LogFont );
+
+ Dword = Order;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_ORDER,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof( Dword )
+ ) == NO_ERROR );
+
+ //
+ // Save extra stuff according to type
+ //
+
+ switch ( Type ) {
+
+ case DOC_WIN:
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_FILENAME,
+ 0,
+ REG_SZ,
+ Docs[ Views[ View].Doc ].FileName,
+ strlen( Docs[ Views[ View].Doc ].FileName )+1
+ ) == NO_ERROR );
+
+ Dword = Docs[ Views[ View].Doc ].readOnly;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_READONLY,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof( Dword )
+ ) == NO_ERROR );
+
+ Dword = Views[ View].Y + 1;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_LINE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof( Dword )
+ ) == NO_ERROR );
+
+ Dword = Views[ View].X;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_COLUMN,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof( Dword )
+ ) == NO_ERROR );
+
+ break;
+
+
+ case MEMORY_WIN:
+ GetAtomName( MemWinDesc[ View ].atmAddress, Buffer, sizeof( Buffer ) );
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_EXPRESSION,
+ 0,
+ REG_SZ,
+ Buffer,
+ strlen( Buffer )+1
+ ) == NO_ERROR );
+
+
+ Dword = MemWinDesc[ View ].iFormat;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_FORMAT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof( Dword )
+ ) == NO_ERROR );
+
+ Dword = MemWinDesc[ View ].fLive;
+ Ok &= ( RegSetValueEx( Key,
+ WS_STR_LIVE,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Dword,
+ sizeof( Dword )
+ ) == NO_ERROR );
+
+ break;
+
+
+ case WATCH_WIN:
+ /*
+ //
+ // NOTENOTE Ramonsa - Save watch expressions when new
+ // watch window code is on-line.
+ //
+ if ( !Default ) {
+ //
+ // Save all the watch expressions
+ //
+ WatchNode = GetFirstWatchNode();
+ while ( Ok && WatchNode ) {
+ Ok &= AddToMultiString( &List, &ListLength, WatchNode->Expr );
+ WatchNode = WatchNode->Next;
+ }
+
+ if ( Ok && List ) {
+
+ if ( RegSetValueEx( Key,
+ WS_STR_EXPRESSION,
+ 0,
+ REG_MULTI_SZ,
+ List,
+ ListLength
+ ) != NO_ERROR ) {
+ Ok = FALSE;
+ }
+ }
+
+ if ( List ) {
+ DeallocateMultiString( List );
+ }
+ }
+ */
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ RegCloseKey( Key );
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadWindowData (
+ HKEY Hkey,
+ char *WindowName,
+ PWINDOW_DATA WindowData
+ )
+/*++
+
+Routine Description:
+
+ Loads window data
+
+Arguments:
+
+ Hkey - Supplies registry key under which the data is to be saved
+ WindowName - Supplies window name
+ WindowData - Supplies window data
+
+Return Value:
+
+ BOOLEAN - TRUE if window data saved
+
+--*/
+{
+ HKEY WdwKey;
+ DWORD DataSize;
+ char Buffer[ MAX_PATH ];
+ BOOLEAN Ok = FALSE;
+
+ if ( WdwKey = OpenRegistryKey(Hkey, WindowName, FALSE ) ) {
+
+
+ DataSize = sizeof( DWORD );
+ Ok = ( RegQueryValueEx( WdwKey,
+ WS_STR_X,
+ NULL,
+ NULL,
+ (LPBYTE)&(WindowData->X),
+ &DataSize ) == NO_ERROR );
+
+ Ok &= ( RegQueryValueEx( WdwKey,
+ WS_STR_Y,
+ NULL,
+ NULL,
+ (LPBYTE)&(WindowData->Y),
+ &DataSize ) == NO_ERROR );
+
+ Ok &= ( RegQueryValueEx( WdwKey,
+ WS_STR_WIDTH,
+ NULL,
+ NULL,
+ (LPBYTE)&(WindowData->Width),
+ &DataSize ) == NO_ERROR );
+
+ Ok &= ( RegQueryValueEx( WdwKey,
+ WS_STR_HEIGHT,
+ NULL,
+ NULL,
+ (LPBYTE)&(WindowData->Height),
+ &DataSize ) == NO_ERROR );
+
+ DataSize = MAX_PATH;
+ Ok &= ( RegQueryValueEx( WdwKey,
+ WS_STR_STATE,
+ NULL,
+ NULL,
+ (LPBYTE)Buffer,
+ &DataSize ) == NO_ERROR );
+
+ if ( !_stricmp( Buffer, WS_STR_ICONIC ) ) {
+ WindowData->State = WSTATE_ICONIC;
+ } else if ( !_stricmp( Buffer, WS_STR_NORMAL ) ) {
+ WindowData->State = WSTATE_NORMAL;
+ } else if ( !_stricmp( Buffer, WS_STR_MAXIMIZED ) ) {
+ WindowData->State = WSTATE_MAXIMIZED;
+ } else {
+ Ok = FALSE;
+ }
+
+ RegCloseKey( WdwKey );
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+SaveWindowData (
+ HKEY Hkey,
+ char *WindowName,
+ PWINDOW_DATA WindowData
+ )
+/*++
+
+Routine Description:
+
+ Saves window data
+
+Arguments:
+
+ Hkey - Supplies registry key under which the data is to be saved
+ WindowName - Supplies window name
+ WindowData - Supplies window data
+
+Return Value:
+
+ BOOLEAN - TRUE if window data saved
+
+--*/
+{
+ HKEY WdwKey;
+ char *StateString;
+ BOOLEAN Ok = FALSE;
+
+ if ( WdwKey = OpenRegistryKey(Hkey, WindowName, TRUE ) ) {
+
+ Ok = ( RegSetValueEx( WdwKey,
+ WS_STR_X,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&(WindowData->X),
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Ok &= ( RegSetValueEx( WdwKey,
+ WS_STR_Y,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&(WindowData->Y),
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Ok &= ( RegSetValueEx( WdwKey,
+ WS_STR_WIDTH,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&(WindowData->Width),
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ Ok &= ( RegSetValueEx( WdwKey,
+ WS_STR_HEIGHT,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&(WindowData->Height),
+ sizeof(DWORD)
+ ) == NO_ERROR );
+
+ switch ( WindowData->State ) {
+ case WSTATE_ICONIC:
+ StateString = WS_STR_ICONIC;
+ break;
+ case WSTATE_NORMAL:
+ StateString = WS_STR_NORMAL;
+ break;
+ case WSTATE_MAXIMIZED:
+ StateString = WS_STR_MAXIMIZED;
+ break;
+ default:
+ Ok = FALSE;
+ break;
+ }
+
+ if ( Ok ) {
+ Ok &= ( RegSetValueEx( WdwKey,
+ WS_STR_STATE,
+ 0,
+ REG_SZ,
+ StateString,
+ strlen( StateString ) + 1
+ ) == NO_ERROR );
+ }
+
+ RegCloseKey( WdwKey );
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+LoadFont (
+ HKEY Hkey,
+ char *Name,
+ LPLOGFONT LogFont
+ )
+/*++
+
+Routine Description:
+
+ Loads a font
+
+Arguments:
+
+ Hkey - Supplies registry key under which the data is to be saved
+ Name - Supplies name
+ LogFont - Supplies pointer to font
+
+Return Value:
+
+ BOOLEAN - TRUE if data saved
+
+--*/
+{
+ DWORD DataSize;
+ BOOLEAN Ok = FALSE;
+
+ DataSize = sizeof( LOGFONT );
+ Ok = ( RegQueryValueEx( Hkey,
+ Name,
+ NULL,
+ NULL,
+ (LPBYTE)LogFont,
+ &DataSize ) == NO_ERROR );
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+SaveFont (
+ HKEY Hkey,
+ char *Name,
+ LPLOGFONT LogFont
+ )
+/*++
+
+Routine Description:
+
+ Saves a font
+
+Arguments:
+
+ Hkey - Supplies registry key under which the data is to be saved
+ Name - Supplies name
+ LogFont - Supplies font
+
+Return Value:
+
+ BOOLEAN - TRUE if data saved
+
+--*/
+{
+
+ BOOLEAN Ok = FALSE;
+
+ Ok = ( RegSetValueEx( Hkey,
+ Name,
+ 0,
+ REG_BINARY,
+ (LPBYTE)LogFont,
+ sizeof( LOGFONT )
+ ) == NO_ERROR );
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadMRUList(
+ HKEY Hkey,
+ char *MruName,
+ DWORD WhatFile,
+ DWORD WhatMenu,
+ DWORD WhatPosition
+ )
+/*++
+
+Routine Description:
+
+ Loads an MRU list from the registry.
+
+Arguments:
+
+ Hkey - Supplies the registry key
+ MruName - Supplies the MRU name
+ WhatFile - Supplies the kind of file (Editor/Project)
+ WhatMenu - Supplies the kind of menu
+ WhatPosition- Supplies the position
+
+Return Value:
+
+ BOOLEAN - TRUE if MRU list loaded
+
+--*/
+{
+
+ LPSTR Name;
+ LPSTR List;
+ DWORD DataSize;
+ BOOLEAN Ok = FALSE;
+ DWORD Next = 0;
+
+ if ( List = LoadMultiString( Hkey, MruName, &DataSize ) ) {
+
+ while ( Name = GetNextStringFromMultiString( List,
+ DataSize,
+ &Next ) ) {
+ //
+ // Add the entries to the MRU list
+ //
+ InsertKeptFileNames( (WORD)WhatFile,
+ (int)WhatMenu,
+ (WORD)WhatPosition,
+ Name );
+ }
+
+ Ok = TRUE;
+
+ DeallocateMultiString( List );
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+SaveMRUList(
+ HKEY Hkey,
+ char *MruName,
+ DWORD WhatFile
+ )
+/*++
+
+Routine Description:
+
+ Saves the MRU list to the registry.
+
+Arguments:
+
+ Hkey - Supplies the registry key
+ MruName - Supplies the MRU name
+ WhatFile - Supplies the kind of file (Editor/Project)
+
+Return Value:
+
+ BOOLEAN - TRUE if MRU list loaded
+
+--*/
+{
+ char *s;
+ ULONG i;
+ LPSTR List = NULL;
+ DWORD ListLength = 0;
+ BOOLEAN Ok = TRUE;
+
+ //
+ // Get current MRU list
+ //
+ for ( i = nbFilesKept[ WhatFile ]; Ok && (i > 0); i-- ) {
+
+ Dbg(s = (LPSTR)GlobalLock( hFileKept[ WhatFile ][ i-1 ] ) );
+
+ Ok = AddToMultiString( &List, &ListLength, s );
+
+ Dbg(GlobalUnlock ( hFileKept[ WhatFile ][ i-1 ] ) == FALSE);
+ }
+
+ //
+ // Save the List in the registry
+ //
+ if ( Ok && List ) {
+
+ if ( RegSetValueEx( Hkey,
+ MruName,
+ 0,
+ REG_MULTI_SZ,
+ List,
+ ListLength
+ ) != NO_ERROR ) {
+
+ Ok = FALSE;
+ }
+ }
+
+ if ( List ) {
+ DeallocateMultiString( List );
+ }
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+LoadProgram (
+ char *ProgramName
+ )
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ ProgramName - Supplies the name of the program
+
+Return Value:
+
+ BOOLEAN - TRUE if program loaded.
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+
+
+ if (strcmp(ProgramName, UntitledProgramName) == 0) {
+ CurrentProgramName[0] = '\0';
+ EnableRibbonControls(ERC_ALL, FALSE);
+ ProgramLoaded = TRUE;
+ return TRUE;
+ }
+
+ strcpy(szPath, ProgramName);
+ strcpy( CurrentProgramName, szPath );
+
+ //
+ // Insert project in menu MRU project
+ //
+ InsertKeptFileNames(PROJECT_FILE, PROJECTMENU,
+ IDM_PROGRAM_LAST,
+ (LPSTR)szPath);
+
+ SaveProgramMRUList();
+
+ AdjustFullPathName(szPath, szTmp, FILES_MENU_WIDTH);
+ StatusText(STA_Program_Opened, STATUS_INFOTEXT, FALSE, (LPSTR)szTmp);
+
+ //
+ // Update ribbon status
+ //
+ EnableRibbonControls(ERC_ALL, FALSE);
+
+ Ok = TRUE;
+
+ ProgramLoaded = Ok;
+
+ return Ok;
+}
+
+
+
+
+BOOLEAN
+DeleteKeyRecursive (
+ HKEY Hkey,
+ char *KeyName
+ )
+/*++
+
+Routine Description:
+
+ Deletes a key in the registry
+
+Arguments:
+
+ Hkey - Supplies a key
+ KeyName - Supplies name of subkey relative to Hkey to
+ be deleted.
+
+Return Value:
+
+ BOOLEAN - TRUE if key deleted.
+
+--*/
+{
+ BOOLEAN Ok = TRUE;
+ HKEY Handle;
+ DWORD SubKeys;
+ DWORD DataSize;
+ FILETIME FileTime;
+ DWORD Error;
+ DWORD i;
+ char Buffer[ MAX_PATH ];
+
+ if ( (Error = RegOpenKey( Hkey,
+ KeyName,
+ &Handle
+ )) == NO_ERROR ) {
+
+ DataSize = 0;
+ Error = RegQueryInfoKey( Handle,
+ NULL,
+ &DataSize,
+ NULL,
+ &SubKeys,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &DataSize,
+ &FileTime );
+
+ if ( (Error == NO_ERROR) || (Error == ERROR_INSUFFICIENT_BUFFER) ) {
+
+ //
+ // Enumerate all the subkeys and recursively delete them
+ //
+ for (i=0; i < SubKeys; i++ ) {
+ if (Error = RegEnumKey( Handle, 0, Buffer, sizeof( Buffer ))) {
+ Ok = FALSE;
+ } else {
+ Ok = DeleteKeyRecursive( Handle, Buffer );
+ }
+ }
+ }
+
+ RegCloseKey( Handle );
+
+ if ( Ok ) {
+ Ok = ((Error = RegDeleteKey( Hkey, KeyName )) == NO_ERROR);
+ }
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+GetWindowMetrics (
+ HWND Hwnd,
+ PWINDOW_DATA WindowData,
+ BOOLEAN Client
+ )
+/*++
+
+Routine Description:
+
+ Fills out the WindowData structure with the data that can
+ be obtained from a window handle.
+
+Arguments:
+
+ Hwnd - Supplies the window handle
+ WindowData - Supplies window data structure
+ Client - Supplies flag which if TRUE means that
+ we want Client metrics
+
+Return Value:
+
+ BOOLEAN - TRUE if data filled out
+
+--*/
+{
+ BOOLEAN Ok = FALSE;
+ WINDOWPLACEMENT WindowPlacement;
+ RECT Rect;
+
+
+ WindowPlacement.length = sizeof(WINDOWPLACEMENT);
+
+ if ( Client ) {
+
+ if ( GetWindowPlacement( Hwnd, &WindowPlacement ) ) {
+
+ WindowData->X = WindowPlacement.rcNormalPosition.left;
+ WindowData->Y = WindowPlacement.rcNormalPosition.top;
+ WindowData->Width = WindowPlacement.rcNormalPosition.right -
+ WindowPlacement.rcNormalPosition.left;
+ WindowData->Height = WindowPlacement.rcNormalPosition.bottom -
+ WindowPlacement.rcNormalPosition.top;
+
+ if ( WindowPlacement.showCmd == SW_SHOWMAXIMIZED ) {
+ WindowData->State = WSTATE_MAXIMIZED;
+ } else if ( WindowPlacement.showCmd == SW_SHOWMINIMIZED ) {
+ WindowData->State = WSTATE_ICONIC;
+ } else {
+ WindowData->State = WSTATE_NORMAL;
+ }
+
+ Ok = TRUE;
+ }
+
+ } else {
+
+ if ( GetWindowPlacement( Hwnd, &WindowPlacement ) &&
+ GetWindowRect( Hwnd, &Rect ) ) {
+
+ WindowData->X = WindowPlacement.rcNormalPosition.left;
+ WindowData->Y = WindowPlacement.rcNormalPosition.top;
+ WindowData->Width = WindowPlacement.rcNormalPosition.right -
+ WindowPlacement.rcNormalPosition.left;
+ WindowData->Height = WindowPlacement.rcNormalPosition.bottom -
+ WindowPlacement.rcNormalPosition.top;
+
+ if ( IsIconic( Hwnd ) ) {
+ WindowData->State = WSTATE_ICONIC;
+ } else if ( IsZoomed( Hwnd ) ) {
+ WindowData->State = WSTATE_MAXIMIZED;
+ } else {
+ WindowData->State = WSTATE_NORMAL;
+ }
+
+ Ok = TRUE;
+ }
+ }
+
+ return Ok;
+}
+
+
+
+
+LPSTR
+LoadMultiString(
+ HKEY Key,
+ char *Name,
+ DWORD *Length
+ )
+/*++
+
+Routine Description:
+
+ Loads a Multistring from the registry
+
+Arguments:
+
+ Key - Supplies registry key
+ Name - Supplies value name
+ Length - Supplies pointer to length
+
+Return Value:
+
+ LPSTR - String
+
+--*/
+{
+ DWORD Error;
+ DWORD DataSize = 0;
+ LPSTR String = NULL;
+
+ Error = RegQueryValueEx( Key,
+ Name,
+ NULL,
+ NULL,
+ NULL,
+ &DataSize );
+
+ if ( DataSize > 0 ) {
+ if ( String = AllocateMultiString( DataSize) ) {
+
+ if ( RegQueryValueEx( Key,
+ Name,
+ NULL,
+ NULL,
+ String,
+ &DataSize ) != NO_ERROR ) {
+
+ DeallocateMultiString( String );
+ String = NULL;
+
+ } else {
+
+ *Length = DataSize - 1;
+ }
+ }
+ }
+
+ return String;
+}
+
+
+
+
+
+BOOLEAN
+GetProgramPath(
+ HKEY PgmKey,
+ LPSTR ProgramName,
+ LPSTR Buffer
+ )
+/*++
+
+Routine Description:
+
+ Gets the recorded path for the program
+
+Arguments:
+
+ PgmKey - Supplies key to PROGRAMS
+
+ ProgramName - Supplies program name
+
+ Buffer - Supplies buffer where path is placed
+
+Return Value:
+
+ BOOLEAN - TRUE if path obtained
+
+--*/
+{
+ HKEY Key;
+ DWORD DataSize;
+ BOOLEAN Ok = FALSE;
+
+ if (ProgramName && *ProgramName) {
+ if ( Key = OpenRegistryKey( PgmKey, ProgramName, FALSE ) ) {
+
+ DataSize = MAX_PATH;
+ Ok = ( RegQueryValueEx( Key,
+ WS_STR_PATH,
+ NULL,
+ NULL,
+ Buffer,
+ &DataSize ) == NO_ERROR );
+
+ RegCloseKey( Key );
+ }
+ }
+
+ return Ok;
+}
+
+
+
+BOOLEAN
+SetProgramPath(
+ HKEY PgmKey,
+ LPSTR ProgramName
+ )
+/*++
+
+Routine Description:
+
+ Gets the recorded path for the program
+
+Arguments:
+
+ PgmKey - Supplies key to PROGRAMS
+
+ ProgramName - Supplies program name
+
+ Buffer - Supplies buffer where path is placed
+
+Return Value:
+
+ BOOLEAN - TRUE if path obtained
+
+--*/
+{
+ HKEY Key;
+ BOOLEAN Ok = FALSE;
+ char Buffer[ MAX_PATH ];
+
+ if (!ProgramName) {
+ ProgramName = "";
+ }
+
+ GetBaseName( ProgramName, Buffer );
+
+ if ( Key = OpenRegistryKey( PgmKey, Buffer, FALSE ) ) {
+
+ Ok = ( RegSetValueEx( Key,
+ WS_STR_PATH,
+ 0,
+ REG_SZ,
+ ProgramName,
+ strlen( ProgramName )+1
+ ) == NO_ERROR );
+
+ RegCloseKey( Key );
+ }
+
+ return Ok;
+}
+
+
+int _CRTAPI1
+CompareViewOrder (
+ const void *p1,
+ const void *p2
+ )
+/*++
+
+Routine Description:
+
+ Compares two VIEW_ORDER structures. Called by qsort
+
+Arguments:
+
+ See qsort()
+
+Return Value:
+
+ See qsort()
+
+--*/
+{
+ int Order1 = ((PVIEW_ORDER)p1)->Order;
+ int Order2 = ((PVIEW_ORDER)p2)->Order;
+
+ if ( Order1 == Order2 ) {
+ return 0;
+ } else if ( Order1 < Order2 ) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+
+
+
+// **********************************************************
+// OPTION FUNCTIONS
+// **********************************************************
+
+
+
+
+
+void
+EnumOptionItems(
+ HKEY hKeyOption,
+ ENUMOPTIONPROC EnumProc,
+ LPARAM lParam
+ )
+/*++
+
+Routine Description:
+
+ Enumerate the items found under an option name, calling
+ EnumProc for each one.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ FILETIME filetime;
+ char szBuf[MAX_PATH];
+ DWORD dwSub;
+ DWORD cbBuf;
+ LONG lError;
+
+ lError = ERROR_SUCCESS;
+ for (dwSub = 0; lError == ERROR_SUCCESS; dwSub++) {
+ cbBuf = sizeof(szBuf);
+ lError = RegEnumKeyEx(hKeyOption,
+ dwSub,
+ szBuf, &cbBuf,
+ NULL,
+ NULL, NULL,
+ &filetime);
+ if (lError == ERROR_SUCCESS) {
+ (*EnumProc)(hKeyOption, szBuf, lParam);
+ }
+ }
+}
+
+
+BOOL
+DeleteOptionItem(
+ HKEY hKeyOption,
+ LPSTR lpOptionItemName
+ )
+/*++
+
+Routine Description:
+
+ Delete an option item and all of its sub-items
+
+ Example:
+ DeleteOptionItem(hKey, "EMx86");
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ return (RegDeleteKey(hKeyOption, lpOptionItemName) == ERROR_SUCCESS);
+}
+
+
+BOOL
+SetOptionSubItem(
+ HKEY hKeyOption,
+ LPSTR lpOptionItemName,
+ LPSTR lpOptionSubItemName,
+ LPSTR lpOptionSubItemValue
+ )
+/*++
+
+Routine Description:
+
+ Save a sub-item for an option - these are values of the
+ key OPTIONS\option\item
+
+ Example:
+ SaveOptionSubItem(hKey,
+ "EMx86",
+ "Description",
+ "EM for x86 CPU");
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ LONG lError;
+ DWORD dwDisp;
+ HKEY hKeyItem;
+
+ lError = RegCreateKeyEx(hKeyOption,
+ lpOptionItemName,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hKeyItem,
+ &dwDisp
+ );
+
+ if (lError == ERROR_SUCCESS) {
+ lError = RegSetValueEx(hKeyItem, lpOptionSubItemName, 0, REG_SZ,
+ lpOptionSubItemValue, strlen(lpOptionSubItemValue)+1);
+ RegCloseKey(hKeyItem);
+ }
+
+ return (lError == ERROR_SUCCESS);
+}
+
+
+BOOL
+GetOptionSubItem(
+ HKEY hKeyOption,
+ LPSTR lpOptionItemName,
+ LPSTR lpOptionSubItemName,
+ LPSTR lpOptionSubItemValue,
+ LPDWORD lpcbBuf
+ )
+{
+ LONG lError;
+ DWORD dwType;
+ HKEY hKeyItem;
+
+ lError = RegOpenKeyEx(hKeyOption,
+ lpOptionItemName,
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hKeyItem);
+
+ if (lError == ERROR_SUCCESS) {
+ lError = RegQueryValueEx(hKeyItem, lpOptionSubItemName, 0,
+ &dwType, lpOptionSubItemValue, lpcbBuf);
+
+ RegCloseKey(hKeyItem);
+
+ }
+
+ if (dwType != REG_SZ) {
+ return FALSE;
+ }
+
+ return (lError == ERROR_SUCCESS);
+}
+
+
+HKEY
+GetOptionKey(
+ LPSTR OptionName,
+ BOOLEAN Create
+ )
+/*++
+
+Routine Description:
+
+ Gets the registry key for the specified option
+
+Arguments:
+
+ OptionName - Supplies the option name
+ Create - Supplies flag which if TRUE means that the
+ option must be created if it does not
+ exist.
+
+Return Value:
+
+ HKEY - Registry key for the option
+
+--*/
+
+{
+ char Buffer[ MAX_PATH ];
+ HKEY hKeyOption = NULL;
+ HKEY hKeyDebugger = GetDebuggerKey();
+
+ if (hKeyDebugger) {
+
+ strcpy( Buffer, OPTIONS );
+ strcat( Buffer, "\\" );
+ strcat( Buffer, OptionName );
+
+ hKeyOption = OpenRegistryKey( hKeyDebugger, Buffer, Create );
+
+ RegCloseKey(hKeyDebugger);
+ }
+
+ return hKeyOption;
+}
+
+SHE
+LoadTimeToShe (
+ LOADTIME LoadTime
+ )
+{
+ SHE She;
+
+ switch( LoadTime ) {
+
+ case LOAD_SYMBOLS_LATER:
+ She = sheDeferSyms;
+ break;
+
+ case LOAD_SYMBOLS_NEVER:
+ She = sheSuppressSyms;
+ break;
+
+ case LOAD_SYMBOLS_IGNORE:
+ case LOAD_SYMBOLS_NOW:
+ default:
+ She = sheNone;
+ break;
+ }
+
+ return She;
+}
+
+LOADTIME
+SheToLoadTime (
+ SHE She
+ )
+{
+ LOADTIME LoadTime;
+
+ switch ( She ) {
+
+ case sheDeferSyms:
+ LoadTime = LOAD_SYMBOLS_LATER;
+ break;
+
+ case sheSuppressSyms:
+ LoadTime = LOAD_SYMBOLS_NEVER;
+ break;
+
+ default:
+ LoadTime = LOAD_SYMBOLS_NOW;
+ break;
+ }
+
+ return LoadTime;
+}