Expect

Changes On Branch telco-tec-win32-take2-branch
Login

Changes On Branch telco-tec-win32-take2-branch

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch telco-tec-win32-take2-branch Excluding Merge-Ins

This is equivalent to a diff from 3b3b7d3e33 to e86ae14031

2003-08-26
20:46
titleblock comment changes and removal of the Detours library usage. Leaf check-in: e86ae14031 user: davygrvy tags: trunk, telco-tec-win32-take2-branch
00:14
ConsoleDebugger::OnXBreakpoint(): sometimes a breakpoint is not set. Don't crash, just punt.. Unknown for why... td32.exe can cause this by launching a new command shell that will launch a seperate console (ie. File->OS Shell) check-in: 8500ec0ed0 user: davygrvy tags: trunk, telco-tec-win32-take2-branch
2002-03-22
05:26
new "follow the mouse" test case. check-in: 8a18d3f5f5 user: davygrvy tags: trunk, telco-tec-win32-take2-branch
2002-03-16
00:38
no message Leaf check-in: 3b3b7d3e33 user: davygrvy tags: trunk, win32-jump-point-1
00:37
fixed a nasty bug in the SetArgv() function that was all my fault. check-in: abce3fafb9 user: davygrvy tags: trunk, win32-jump-point-1

Changes to ChangeLog.win32.

































































































































































































































































1
2
3
4
5
6
7
































































































































































































































































2002-03-16  davygrvy
	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinMessage.cpp:
	* win/expWinMessage.hpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinUtils.cpp:
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
2002-06-28  davygrvy
	* win/expWinInjectorIPC.hpp:
		fixed comments.

	* win/Mcl/Mcl.dsp:
		exceptions truned off.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinMessage.hpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinSlaveTrapDbg.cpp:
	* win/expWinTestClient.hpp:
	* win/expWinTestClientConio.cpp:
	* win/expWinTestClientInteract.cpp:
	* win/expWinTestClientStdio.cpp:
		The ClientInteract class has been created.  It's empty, though.

2002-06-27  davygrvy
	* win/expWinClientTransport.hpp:
	* win/expWinClientTransportConio.cpp:
	* win/expWinClientTransportStdio.cpp:
	* win/expWinSlave.hpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinTestClient.hpp:
	* win/expWinTestClientConio.cpp:
	* win/expWinTestClientStdio.cpp:
	* win/slavedrv.dsp:
		renamed ClientTransport* to be TestClient* as the name is more
		descriptive.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinInjectorIPC.hpp:
	* win/expWinInjectorMain.cpp:
	* win/injector.dsp:
	* win/slavedrv.dsp:
		slot and slot sizes are shared on both sides.  This ensures there won't be
		any errors from different info.

	* win/expWinClientTransport.hpp:
	* win/expWinClientTransportConio.cpp:
	* win/expWinConsoleDebugger.cpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinSlaveTrap.hpp:
		closing of the test application is more thorough and controlled.

2002-06-26  davygrvy
	* win/expWinConsoleDebugger.cpp:
		small stuff

2002-06-25  davygrvy
	* win/expWinClientTransport.hpp:
	* win/expWinClientTransportConio.cpp:
	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinInjectorMain.cpp:
	* win/expWinSlaveMain.cpp:
	* win/test1.dsp:
		We can now write to the slave console.  Debugged and working.
		slavedrv1.1 was released today from the code of this commit.

	* win/Mcl/Mcl.dsp:
		Changed all builds to not throw C++ exceptions.  there's some exe size
		savings for doing this.  I would prefer to check the Status() member after
		the constructor instead.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/slavedrvmc.mc:
		Added RIP events to the debugger and better error reporting for bad trap
		and transport methods on the commandline.

	* win/Mcl/include/CMclGlobal.h:
		another bug squashed.

2002-06-24  davygrvy
	* win/Mcl/src/CMclMailbox.cpp:
		Nasty bug found and fixed.  Talked to Mike Woodring about it
		yesterday.

2002-06-23  davygrvy
	* win/expWinSlaveMain.cpp:
		small variable naming changes to help the reader.

	* win/expWinInjectorMain.cpp:
		Upped the mailbox size to 80 slots from 10.  An INPUT_RECORD can't be
		too much more that 24 bytes, so this shouldn't hurt active memory.

	* win/expWinConsoleKeyMap.cpp:
		more good stuff

	* win/expWinClientStdio.cpp:
	* win/expWinClientTransport.hpp:
	* win/expWinClientTransportConio.cpp:
	* win/expWinClientTransportStdio.cpp:
	* win/slavedrv.dsp:
		yet more filename changes.

	* win/expWinMessage.cpp:
		Changed the destructor to use the array modifier.  I don't know if it serves a
		purpose, though.

	* win/expWinClientTransport.hpp:
	* win/expWinSpawnClient.hpp:
	* win/slavedrv.dsp:
		filename changed to be more obvious/meaningful.

	* win/expWinSlaveMain.cpp:
		matches the class name changes

	* win/expWinSlave.hpp:
		matches the class name changes and added a proto for the new
		MapToKeys() function.

	* win/expWinConsoleDebugger.cpp:
		hMasterConsole now properly closed in destructor.

	* win/expWinClientStdio.cpp:
	* win/expWinSpawnStdioClient.cpp:
	* win/slavedrv.dsp:
		another filename changed to be more obvious/meaningful.

2002-06-22  davygrvy
	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinConsoleDebuggerBreakPoints.cpp:
	* win/expWinInjectorMain.cpp:
	* win/expWinMessage.cpp:
	* win/expWinMessage.hpp:
	* win/expWinSlave.hpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinSlaveTrap.hpp:
	* win/expWinSlaveTrapDbg.cpp:
	* win/expWinSpawnStdioClient.cpp:
		More new good stuff.

	* win/expWinConsoleKeyMap.cpp:
		New file.  Contains the mapping routines for converting characters into
		keypress events.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
		IPC connection to the injector dll, done.  Write() added, but does nothing yet.
		I have to think this through...

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinInjectorMain.cpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinSpawnStdioClient.cpp:
	* win/injector.dsp:
		Big crash big fixed.  I was restarting the thread AFTER the breakpoint rather
		than on top of it.  OutputDebugString() is now passing through, too.  No
		connection has been made yet to the IPC server the injector dll is providing.

2002-06-21  davygrvy
	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinConsoleDebuggerBreakPoints.cpp:
	* win/expWinInjectorMain.cpp:
	* win/expWinMessage.cpp:
	* win/expWinMessage.hpp:
	* win/expWinSlaveTrapDbg.cpp:
	* win/expWinSpawnClient.hpp:
	* win/expWinSpawnStdioClient.cpp:
		Injector code hook-in, but doesn't yet work.  I don't know why.
		The opcodes for loading the DLL are correct.  The opcodes are
		written to the sub process memory and run.  I just don't know.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinInjectorMain.cpp:
		The injector DLL is now loading into the process.  That's the good news.
		The bad news is that it's crashing the process.  I decided to commit the
		changes anyways with the hope someone can assist.  Even with the
		injector doing nothing, we still crash for some unknown reason.

2002-06-20  davygrvy
	* win/expWinInjectorMain.cpp:
		better error handling.  I think I'll use OutputDebugString()
		for sending warnings back to the ConsoleDebugger class.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinInjectorMain.cpp:
	* win/expWinMessage.hpp:
	* win/expWinSpawnStdioClient.cpp:
		Added OnXDebugString() to the ConsoleDebugger class to handle the
		OUTPUT_DEBUG_STRING_EVENT debugger event.  This sends a new
		message type called TYPE_WARNING to the output client.  Changed the
		stdio client to just send this out on stderr.

	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/slavedrv.dsp:
		small refactoring.

	* win/expWinInjectorMain.cpp:
		one must open the console INPUT buffer to write console events
		to it, not the SCREEN buffer.

	* win/expWinInjectorMain.cpp:
		small changes, but still untested.

2002-06-19  davygrvy
	* win/slavedrv.rc:
		small app type error fixed.  I had been calling this a dll. 
		Oops.

	* win/expWinInjectorMain.cpp:
	* win/injector.dsp:
	* win/injector.dsw:
		minimal starting point for the console event injector dll (the
		write portion of the ConsoleDebugger class)

	* win/expWinInjectorMain.cpp:
	* win/inject.rc:
	* win/injector.dsp:
		added an RC script for version info.

	* win/expWinInjectorMain.cpp:
	* win/injector.dsp:
	* win/injector.dsw:
		Injector idea more formalized from thought into some code.

2002-06-18  davygrvy
	* generic/exp.h:
	* generic/expDecls.h:
	* generic/expIntDecls.h:
	* generic/expIntPlatDecls.h:
	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinConsoleDebuggerBreakPoints.cpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinUtils.cpp:
	* win/expWinUtils.hpp:
	* win/expect.rc:
	* win/slavedrv.rc:
	* win/slavedrvmc.mc:
	* win/test1.cpp:
		these changes perfect the debugger code under Win98 and have
		been sitting in my workspace for quite some time now.

	* win/expWinConsoleDebugger.cpp:
		oops. fixed a compiling bug.

2002-03-22  davygrvy
	* win/slavedrv.dsp:
	* win/slavedrv.dsw:
	* win/test1.cpp:
	* win/test1.dsp:
		new "follow the mouse" test case.

	* win/TclHash.hpp:
		new Extract() functions.

2002-03-16  davygrvy
	* win/expWinConsoleDebugger.cpp:
	* win/expWinConsoleDebugger.hpp:
	* win/expWinMessage.cpp:
	* win/expWinMessage.hpp:
	* win/expWinSlaveMain.cpp:
	* win/expWinUtils.cpp:

Changes to generic/exp.h.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: exp.h,v 1.1.4.8 2002/03/06 02:18:20 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXP
#define _EXP









|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: exp.h,v 1.1.4.9 2002/03/07 02:49:36 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXP
#define _EXP


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#	define EXP_PATCH_LEVEL \
		STRINGIFY( \
			JOIN(JOIN(EXP_MAJOR_VERSION, \
			JOIN(., EXP_MINOR_VERSION)), \
			JOIN(., EXP_RELEASE_SERIAL)))

#else
#	include "bad/release/level/used"
#endif

/*
 * The windows resource compiler defines this by default.  Skip the rest of this
 * file when included from an rc script.
 */
#ifndef RC_INVOKED







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#	define EXP_PATCH_LEVEL \
		STRINGIFY( \
			JOIN(JOIN(EXP_MAJOR_VERSION, \
			JOIN(., EXP_MINOR_VERSION)), \
			JOIN(., EXP_RELEASE_SERIAL)))

#else
#	error bad release level used.
#endif

/*
 * The windows resource compiler defines this by default.  Skip the rest of this
 * file when included from an rc script.
 */
#ifndef RC_INVOKED
91
92
93
94
95
96
97
98

99
100
101
102
103

104
105
106
107


108
109
110
111
112
113
114
115
116
117

118
119

120
121

122
123
124
125
126
127
128
#endif


/* Fix the Borland bug in tcl.h */
#ifndef TCL_EXTERN
#   undef DLLIMPORT
#   undef DLLEXPORT
#   if (defined(__WIN32__) &&  (defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) \

	    || (defined(__GNUC__) && defined(__DECLSPEC_SUPPORTED)))) \
	    || (defined(MAC_TCL) && FUNCTION_DECLSPEC)
#	define DLLIMPORT __declspec(dllimport)
#	define DLLEXPORT __declspec(dllexport)
#   elif defined(__BORLANDC__)

#	define OLD_BORLAND 1
#	define DLLIMPORT __import
#	define DLLEXPORT __export
#   else


#	define DLLIMPORT
#	define DLLEXPORT
#   endif
    /* Avoid name mangling. */
#   ifdef __cplusplus
#	define TCL_CPP "C"
#   else
#	define TCL_CPP
#   endif
    /* Pre 5.5 Borland requires the attributes be placed after the return type. */

#   if OLD_BORLAND
#	define TCL_EXTERN(rtnType) extern TCL_CPP rtnType TCL_STORAGE_CLASS

#   else
#	define TCL_EXTERN(rtnType) extern TCL_CPP TCL_STORAGE_CLASS rtnType

#   endif
#endif


/* needed by some exports */
#ifdef TIME_WITH_SYS_TIME
#   include <sys/time.h>







|
>





>




>
>



|





|
>

|
>

|
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#endif


/* Fix the Borland bug in tcl.h */
#ifndef TCL_EXTERN
#   undef DLLIMPORT
#   undef DLLEXPORT
#   if (defined(__WIN32__) &&  \
		(defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) \
	    || (defined(__GNUC__) && defined(__DECLSPEC_SUPPORTED)))) \
	    || (defined(MAC_TCL) && FUNCTION_DECLSPEC)
#	define DLLIMPORT __declspec(dllimport)
#	define DLLEXPORT __declspec(dllexport)
#   elif defined(__BORLANDC__)
	/* Pre 5.5 Borland */
#	define OLD_BORLAND 1
#	define DLLIMPORT __import
#	define DLLEXPORT __export
#   else
	/* Systems that don't support keywords for exporting/importing
	 * functions from dynamic libraries. */
#	define DLLIMPORT
#	define DLLEXPORT
#   endif
    /* Avoid C++ name mangling. */
#   ifdef __cplusplus
#	define TCL_CPP "C"
#   else
#	define TCL_CPP
#   endif
    /* Pre 5.5 Borland requires the attributes be placed after the return
     * type. */
#   if OLD_BORLAND
#	define TCL_EXTERN(rtnType) \
	    extern TCL_CPP rtnType TCL_STORAGE_CLASS
#   else
#	define TCL_EXTERN(rtnType) \
	    extern TCL_CPP TCL_STORAGE_CLASS rtnType
#   endif
#endif


/* needed by some exports */
#ifdef TIME_WITH_SYS_TIME
#   include <sys/time.h>

Changes to generic/expDecls.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expDecls.h,v 1.1.4.2 2002/02/10 12:04:22 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPDECLS
#define _EXPDECLS

/*
 * WARNING: This file is automatically generated by the $(TCLROOT)/tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the generic/exp.decls script.
 */

/* !BEGIN!: Do not edit below this line. */

/*
 * Exported function declarations:
 */

/* 0 */
TCL_EXTERN(int)		Expect_Init _ANSI_ARGS_((Tcl_Interp * interp));
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* 3 */
TCL_EXTERN(int)		Exp_ExpInternalCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* Slot 4 is reserved */
/* 5 */
TCL_EXTERN(int)		Exp_ExitCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 6 */
TCL_EXTERN(int)		Exp_ExpContinueCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* Slot 7 is reserved */
/* 8 */
TCL_EXTERN(int)		Exp_ExpPidCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 9 */
TCL_EXTERN(int)		Exp_GetpidDeprecatedCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* Slot 10 is reserved */
/* 11 */
TCL_EXTERN(int)		Exp_LogFileCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 12 */
TCL_EXTERN(int)		Exp_LogUserCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 13 */
TCL_EXTERN(int)		Exp_OpenCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* Slot 14 is reserved */
/* Slot 15 is reserved */
/* Slot 16 is reserved */
/* 17 */
TCL_EXTERN(int)		Exp_SendLogCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 18 */
TCL_EXTERN(int)		Exp_SleepCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 19 */
TCL_EXTERN(int)		Exp_SpawnCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 20 */
TCL_EXTERN(int)		Exp_StraceCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 21 */
TCL_EXTERN(int)		Exp_WaitCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 22 */
TCL_EXTERN(int)		Exp_ExpVersionCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 23 */
TCL_EXTERN(int)		Exp_Prompt1Cmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 24 */
TCL_EXTERN(int)		Exp_Prompt2Cmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 25 */
TCL_EXTERN(int)		Exp_TrapCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 26 */
TCL_EXTERN(int)		Exp_SttyCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 27 */
TCL_EXTERN(int)		Exp_SystemCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 28 */
TCL_EXTERN(int)		Exp_ExpectCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int objc, 
				Tcl_Obj *CONST objv[]));
/* 29 */
TCL_EXTERN(int)		Exp_ExpectGlobalCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, Tcl_Obj *CONST objv[]));
/* 30 */
TCL_EXTERN(int)		Exp_MatchMaxCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 31 */
TCL_EXTERN(int)		Exp_RemoveNullsCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* 32 */
TCL_EXTERN(int)		Exp_ParityCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 33 */
TCL_EXTERN(int)		Exp_TimestampCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 34 */
TCL_EXTERN(int)		Exp_CloseCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 35 */
TCL_EXTERN(int)		Exp_InterpreterCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* 36 */
TCL_EXTERN(int)		Exp_SendCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 37 */
TCL_EXTERN(int)		Exp_KillCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* Slot 38 is reserved */
/* Slot 39 is reserved */
/* 40 */
TCL_EXTERN(char *)	exp_printify _ANSI_ARGS_((char * s));
/* Slot 41 is reserved */
/* Slot 42 is reserved */
/* Slot 43 is reserved */
/* Slot 44 is reserved */
/* Slot 45 is reserved */
/* Slot 46 is reserved */
/* Slot 47 is reserved */
/* Slot 48 is reserved */
/* Slot 49 is reserved */
/* 50 */
TCL_EXTERN(void)	exp_errorlog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
/* 51 */
TCL_EXTERN(void)	exp_log _ANSI_ARGS_(TCL_VARARGS(int,force_stdout));
/* 52 */
TCL_EXTERN(void)	exp_debuglog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
/* 53 */
TCL_EXTERN(void)	exp_nflog _ANSI_ARGS_((char * buf, int force_stdout));
/* 54 */
TCL_EXTERN(void)	exp_nferrorlog _ANSI_ARGS_((char * buf, 
				int force_stdout));
/* 55 */
TCL_EXTERN(void)	exp_error _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));
/* Slot 56 is reserved */
/* Slot 57 is reserved */
/* Slot 58 is reserved */
/* Slot 59 is reserved */
/* 60 */
TCL_EXTERN(void)	exp_parse_argv _ANSI_ARGS_((Tcl_Interp * interp, 
				int argc, char ** argv));
/* 61 */
TCL_EXTERN(int)		exp_interpreter _ANSI_ARGS_((Tcl_Interp * interp));
/* 62 */
TCL_EXTERN(int)		exp_interpret_cmdfile _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Channel cmdfile));
/* 63 */
TCL_EXTERN(int)		exp_interpret_cmdfilename _ANSI_ARGS_((
				Tcl_Interp * interp, char * filename));
/* 64 */
TCL_EXTERN(void)	exp_interpret_rcfiles _ANSI_ARGS_((
				Tcl_Interp * interp, int my_rc, int sys_rc));
/* 65 */
TCL_EXTERN(char *)	exp_cook _ANSI_ARGS_((CONST char * s, int * len));
/* Slot 66 is reserved */
/* 67 */
TCL_EXTERN(int)		exp_getpidproc _ANSI_ARGS_((void));
/* 68 */
TCL_EXTERN(Tcl_Channel)	 ExpCreateSpawnChannel _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Channel chan));
/* 69 */
TCL_EXTERN(int)		ExpPlatformSpawnOutput _ANSI_ARGS_((
				ClientData instanceData, CONST char * bufPtr, 
				int toWrite, int * errorPtr));
/* 70 */
TCL_EXTERN(void)	exp_init_main_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* 71 */
TCL_EXTERN(void)	exp_init_expect_cmds _ANSI_ARGS_((
				Tcl_Interp * interp));
/* 72 */
TCL_EXTERN(void)	exp_init_most_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* 73 */
TCL_EXTERN(void)	exp_init_trap_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* 74 */
TCL_EXTERN(void)	exp_init_interact_cmds _ANSI_ARGS_((
				Tcl_Interp * interp));
/* 75 */
TCL_EXTERN(int)		exp_init_tty_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* Slot 76 is reserved */
/* Slot 77 is reserved */
/* 78 */
TCL_EXTERN(Tcl_Channel)	 ExpCreatePairChannel _ANSI_ARGS_((
				Tcl_Interp * interp, CONST char * chanInId, 
				CONST char * chanOutId, 
				CONST char * chanName));
/* 79 */
TCL_EXTERN(int)		ExpSpawnOpen _ANSI_ARGS_((Tcl_Interp * interp, 
				char * chanId, int leaveopen));
/* 80 */
TCL_EXTERN(struct exp_f *) exp_update_master _ANSI_ARGS_((
				Tcl_Interp * interp, int opened, int adjust));
/* 81 */
TCL_EXTERN(CONST char *) exp_get_var _ANSI_ARGS_((Tcl_Interp * interp, 
				char * var));
/* 82 */
TCL_EXTERN(void)	exp_exit _ANSI_ARGS_((Tcl_Interp * interp, 
				int status));
/* 83 */
TCL_EXTERN(int)		exp_dsleep _ANSI_ARGS_((Tcl_Interp * interp, 
				double sec));
/* 84 */
TCL_EXTERN(void)	exp_init_event _ANSI_ARGS_((void));
/* Slot 85 is reserved */
/* 86 */
TCL_EXTERN(void)	exp_background_filehandler _ANSI_ARGS_((
				ClientData clientData, int mask));
/* 87 */
TCL_EXTERN(void)	exp_exit_handlers _ANSI_ARGS_((ClientData clientData));
/* 88 */
TCL_EXTERN(void)	exp_close_on_exec _ANSI_ARGS_((int fd));
/* 89 */
TCL_EXTERN(int)		exp_flageq_code _ANSI_ARGS_((char * flag, 
				char * string, int minlen));
/* 90 */
TCL_EXTERN(void)	exp_close_tcl_files _ANSI_ARGS_((void));
/* 91 */
TCL_EXTERN(void)	exp_lowmemcpy _ANSI_ARGS_((char * dest, 
				CONST char * src, int n));
/* 92 */
TCL_EXTERN(void)	exp_timestamp _ANSI_ARGS_((Tcl_Interp * interp, 
				time_t * timeval, char * array));

typedef struct ExpStubHooks {
    struct ExpPlatStubs *expPlatStubs;
    struct ExpIntStubs *expIntStubs;
    struct ExpIntPlatStubs *expIntPlatStubs;
} ExpStubHooks;







|



















|



|




|


|




|


|




|


|


|





|


|


|


|


|


|


|


|


|


|


|


|



|



|


|



|


|


|


|



|


|




|










|

|

|

|

|


|





|


|

|


|


|


|


|

|


|



|

|


|

|

|


|



|




|


|
|

|


|


|


|


|


|

|

|


|

|


|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expDecls.h,v 1.1.4.3 2002/02/10 13:40:47 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPDECLS
#define _EXPDECLS

/*
 * WARNING: This file is automatically generated by the $(TCLROOT)/tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the generic/exp.decls script.
 */

/* !BEGIN!: Do not edit below this line. */

/*
 * Exported function declarations:
 */

/* 0 */
EXTERN int		Expect_Init _ANSI_ARGS_((Tcl_Interp * interp));
/* Slot 1 is reserved */
/* Slot 2 is reserved */
/* 3 */
EXTERN int		Exp_ExpInternalCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* Slot 4 is reserved */
/* 5 */
EXTERN int		Exp_ExitCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 6 */
EXTERN int		Exp_ExpContinueCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* Slot 7 is reserved */
/* 8 */
EXTERN int		Exp_ExpPidCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 9 */
EXTERN int		Exp_GetpidDeprecatedCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* Slot 10 is reserved */
/* 11 */
EXTERN int		Exp_LogFileCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 12 */
EXTERN int		Exp_LogUserCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 13 */
EXTERN int		Exp_OpenCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* Slot 14 is reserved */
/* Slot 15 is reserved */
/* Slot 16 is reserved */
/* 17 */
EXTERN int		Exp_SendLogCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 18 */
EXTERN int		Exp_SleepCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 19 */
EXTERN int		Exp_SpawnCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 20 */
EXTERN int		Exp_StraceCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 21 */
EXTERN int		Exp_WaitCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 22 */
EXTERN int		Exp_ExpVersionCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 23 */
EXTERN int		Exp_Prompt1Cmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 24 */
EXTERN int		Exp_Prompt2Cmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 25 */
EXTERN int		Exp_TrapCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 26 */
EXTERN int		Exp_SttyCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 27 */
EXTERN int		Exp_SystemCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 28 */
EXTERN int		Exp_ExpectCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int objc, 
				Tcl_Obj *CONST objv[]));
/* 29 */
EXTERN int		Exp_ExpectGlobalCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, Tcl_Obj *CONST objv[]));
/* 30 */
EXTERN int		Exp_MatchMaxCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 31 */
EXTERN int		Exp_RemoveNullsCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* 32 */
EXTERN int		Exp_ParityCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 33 */
EXTERN int		Exp_TimestampCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 34 */
EXTERN int		Exp_CloseCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 35 */
EXTERN int		Exp_InterpreterCmd _ANSI_ARGS_((
				ClientData clientData, Tcl_Interp * interp, 
				int argc, char * argv[]));
/* 36 */
EXTERN int		Exp_SendCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* 37 */
EXTERN int		Exp_KillCmd _ANSI_ARGS_((ClientData clientData, 
				Tcl_Interp * interp, int argc, char * argv[]));
/* Slot 38 is reserved */
/* Slot 39 is reserved */
/* 40 */
EXTERN char *		exp_printify _ANSI_ARGS_((char * s));
/* Slot 41 is reserved */
/* Slot 42 is reserved */
/* Slot 43 is reserved */
/* Slot 44 is reserved */
/* Slot 45 is reserved */
/* Slot 46 is reserved */
/* Slot 47 is reserved */
/* Slot 48 is reserved */
/* Slot 49 is reserved */
/* 50 */
EXTERN void		exp_errorlog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
/* 51 */
EXTERN void		exp_log _ANSI_ARGS_(TCL_VARARGS(int,force_stdout));
/* 52 */
EXTERN void		exp_debuglog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
/* 53 */
EXTERN void		exp_nflog _ANSI_ARGS_((char * buf, int force_stdout));
/* 54 */
EXTERN void		exp_nferrorlog _ANSI_ARGS_((char * buf, 
				int force_stdout));
/* 55 */
EXTERN void		exp_error _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));
/* Slot 56 is reserved */
/* Slot 57 is reserved */
/* Slot 58 is reserved */
/* Slot 59 is reserved */
/* 60 */
EXTERN void		exp_parse_argv _ANSI_ARGS_((Tcl_Interp * interp, 
				int argc, char ** argv));
/* 61 */
EXTERN int		exp_interpreter _ANSI_ARGS_((Tcl_Interp * interp));
/* 62 */
EXTERN int		exp_interpret_cmdfile _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Channel cmdfile));
/* 63 */
EXTERN int		exp_interpret_cmdfilename _ANSI_ARGS_((
				Tcl_Interp * interp, char * filename));
/* 64 */
EXTERN void		exp_interpret_rcfiles _ANSI_ARGS_((
				Tcl_Interp * interp, int my_rc, int sys_rc));
/* 65 */
EXTERN char *		exp_cook _ANSI_ARGS_((CONST char * s, int * len));
/* Slot 66 is reserved */
/* 67 */
EXTERN int		exp_getpidproc _ANSI_ARGS_((void));
/* 68 */
EXTERN Tcl_Channel	ExpCreateSpawnChannel _ANSI_ARGS_((
				Tcl_Interp * interp, Tcl_Channel chan));
/* 69 */
EXTERN int		ExpPlatformSpawnOutput _ANSI_ARGS_((
				ClientData instanceData, CONST char * bufPtr, 
				int toWrite, int * errorPtr));
/* 70 */
EXTERN void		exp_init_main_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* 71 */
EXTERN void		exp_init_expect_cmds _ANSI_ARGS_((
				Tcl_Interp * interp));
/* 72 */
EXTERN void		exp_init_most_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* 73 */
EXTERN void		exp_init_trap_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* 74 */
EXTERN void		exp_init_interact_cmds _ANSI_ARGS_((
				Tcl_Interp * interp));
/* 75 */
EXTERN int		exp_init_tty_cmds _ANSI_ARGS_((Tcl_Interp * interp));
/* Slot 76 is reserved */
/* Slot 77 is reserved */
/* 78 */
EXTERN Tcl_Channel	ExpCreatePairChannel _ANSI_ARGS_((
				Tcl_Interp * interp, CONST char * chanInId, 
				CONST char * chanOutId, 
				CONST char * chanName));
/* 79 */
EXTERN int		ExpSpawnOpen _ANSI_ARGS_((Tcl_Interp * interp, 
				char * chanId, int leaveopen));
/* 80 */
EXTERN struct exp_f *	exp_update_master _ANSI_ARGS_((Tcl_Interp * interp, 
				int opened, int adjust));
/* 81 */
EXTERN CONST char *	exp_get_var _ANSI_ARGS_((Tcl_Interp * interp, 
				char * var));
/* 82 */
EXTERN void		exp_exit _ANSI_ARGS_((Tcl_Interp * interp, 
				int status));
/* 83 */
EXTERN int		exp_dsleep _ANSI_ARGS_((Tcl_Interp * interp, 
				double sec));
/* 84 */
EXTERN void		exp_init_event _ANSI_ARGS_((void));
/* Slot 85 is reserved */
/* 86 */
EXTERN void		exp_background_filehandler _ANSI_ARGS_((
				ClientData clientData, int mask));
/* 87 */
EXTERN void		exp_exit_handlers _ANSI_ARGS_((ClientData clientData));
/* 88 */
EXTERN void		exp_close_on_exec _ANSI_ARGS_((int fd));
/* 89 */
EXTERN int		exp_flageq_code _ANSI_ARGS_((char * flag, 
				char * string, int minlen));
/* 90 */
EXTERN void		exp_close_tcl_files _ANSI_ARGS_((void));
/* 91 */
EXTERN void		exp_lowmemcpy _ANSI_ARGS_((char * dest, 
				CONST char * src, int n));
/* 92 */
EXTERN void		exp_timestamp _ANSI_ARGS_((Tcl_Interp * interp, 
				time_t * timeval, char * array));

typedef struct ExpStubHooks {
    struct ExpPlatStubs *expPlatStubs;
    struct ExpIntStubs *expIntStubs;
    struct ExpIntPlatStubs *expIntPlatStubs;
} ExpStubHooks;

Changes to generic/expIntDecls.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expIntDecls.h,v 1.1.4.4 2002/02/10 13:40:47 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPINTDECLS
#define _EXPINTDECLS

/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the exp.decls script.
 */

/* !BEGIN!: Do not edit below this line. */

/*
 * Exported function declarations:
 */

/* Slot 0 is reserved */
/* 1 */
TCL_EXTERN(int)		Exp_StringMatch _ANSI_ARGS_((CONST char * string, 
				CONST char * pattern, int * offset));
/* 2 */
TCL_EXTERN(int)		Exp_StringMatch2 _ANSI_ARGS_((CONST char * string, 
				CONST char * pattern));
/* Slot 3 is reserved */
/* 4 */
TCL_EXTERN(struct exp_i *) exp_new_i_complex _ANSI_ARGS_((
				Tcl_Interp * interp, char * arg, 
				int duration, Tcl_VarTraceProc * updateproc, 
				CONST char * msg));
/* 5 */
TCL_EXTERN(struct exp_i *) exp_new_i_simple _ANSI_ARGS_((struct exp_f * fd, 
				int duration));
/* 6 */
TCL_EXTERN(struct exp_fs_list *) exp_new_fs _ANSI_ARGS_((struct exp_f * f));
/* 7 */
TCL_EXTERN(void)	exp_free_i _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_i * i, 
				Tcl_VarTraceProc * updateproc));
/* 8 */
TCL_EXTERN(void)	exp_free_fs _ANSI_ARGS_((
				struct exp_fs_list * fs_first));
/* 9 */
TCL_EXTERN(void)	exp_free_fs_single _ANSI_ARGS_((
				struct exp_fs_list * fs));
/* 10 */
TCL_EXTERN(void)	exp_i_update _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_i * i));
/* 11 */
TCL_EXTERN(void)	exp_pty_exit _ANSI_ARGS_((void));
/* 12 */
TCL_EXTERN(void)	exp_init_spawn_ids _ANSI_ARGS_((Tcl_Interp * interp));
/* 13 */
TCL_EXTERN(void)	exp_init_pty _ANSI_ARGS_((Tcl_Interp * interp));
/* 14 */
TCL_EXTERN(void)	exp_init_tty _ANSI_ARGS_((Tcl_Interp * interp));
/* 15 */
TCL_EXTERN(void)	exp_init_stdio _ANSI_ARGS_((void));
/* 16 */
TCL_EXTERN(void)	exp_init_sig _ANSI_ARGS_((void));
/* 17 */
TCL_EXTERN(void)	exp_init_trap _ANSI_ARGS_((void));
/* 18 */
TCL_EXTERN(void)	exp_init_unit_random _ANSI_ARGS_((void));
/* 19 */
TCL_EXTERN(void)	exp_init_spawn_id_vars _ANSI_ARGS_((
				Tcl_Interp * interp));
/* 20 */
TCL_EXTERN(void)	exp_adjust _ANSI_ARGS_((struct exp_f * f));
/* 21 */
TCL_EXTERN(void)	exp_ecmd_remove_f_direct_and_indirect _ANSI_ARGS_((
				Tcl_Interp * interp, struct exp_f * f));
/* 22 */
TCL_EXTERN(void)	exp_rearm_sigchld _ANSI_ARGS_((Tcl_Interp * interp));
/* 23 */
TCL_EXTERN(struct exp_f *) exp_chan2f _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * chan, int opened, int adjust, 
				CONST char * msg));
/* 24 */
TCL_EXTERN(int)		exp_fcheck _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f * f, int opened, int adjust, 
				CONST char * msg));
/* 25 */
TCL_EXTERN(int)		exp_close _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f * f));
/* 26 */
TCL_EXTERN(void)	exp_strftime _ANSI_ARGS_((char * format, 
				const struct tm * timeptr, 
				Tcl_DString * dstring));
/* 27 */
TCL_EXTERN(void)	exp_create_commands _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_cmd_data * c));
/* 28 */
TCL_EXTERN(void)	exp_tty_break _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f * f));
/* 29 */
TCL_EXTERN(void)	exp_event_disarm _ANSI_ARGS_((struct exp_f * f));
/* 30 */
TCL_EXTERN(void)	exp_arm_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 31 */
TCL_EXTERN(void)	exp_disarm_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 32 */
TCL_EXTERN(void)	exp_disarm_background_filehandler_force _ANSI_ARGS_((
				struct exp_f * f));
/* 33 */
TCL_EXTERN(void)	exp_unblock_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 34 */
TCL_EXTERN(void)	exp_block_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 35 */
TCL_EXTERN(int)		exp_get_next_event _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f ** masters, int n, 
				struct exp_f ** master_out, int timeout, 
				int key));
/* 36 */
TCL_EXTERN(int)		exp_get_next_event_info _ANSI_ARGS_((
				Tcl_Interp * interp, struct exp_f * fd, 
				int ready_mask));
/* 37 */
TCL_EXTERN(struct exp_f *) exp_f_find _ANSI_ARGS_((Tcl_Interp * interp, 
				char * spawnId));
/* 38 */
TCL_EXTERN(struct exp_f *) exp_f_new _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Channel chan, char * spawnId, int pid));
/* 39 */
TCL_EXTERN(int)		exp_f_new_platform _ANSI_ARGS_((struct exp_f * f));
/* 40 */
TCL_EXTERN(void)	exp_f_free _ANSI_ARGS_((struct exp_f * f));
/* 41 */
TCL_EXTERN(void)	exp_f_free_platform _ANSI_ARGS_((struct exp_f * f));
/* 42 */
TCL_EXTERN(int)		exp_exact_write _ANSI_ARGS_((struct exp_f * f, 
				char * buffer, int rembytes));

typedef struct ExpIntStubs {
    int magic;
    struct ExpIntStubHooks *hooks;

    void *reserved0;







|




















|


|



|
|
|


|


|

|



|


|


|


|

|

|

|

|

|

|

|

|


|

|


|

|



|



|


|



|


|


|

|


|


|


|


|


|




|



|


|


|

|

|

|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expIntDecls.h,v 1.1.4.5 2002/02/13 02:39:41 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPINTDECLS
#define _EXPINTDECLS

/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script.  Any modifications to the function declarations below should be made
 * in the exp.decls script.
 */

/* !BEGIN!: Do not edit below this line. */

/*
 * Exported function declarations:
 */

/* Slot 0 is reserved */
/* 1 */
EXTERN int		Exp_StringMatch _ANSI_ARGS_((CONST char * string, 
				CONST char * pattern, int * offset));
/* 2 */
EXTERN int		Exp_StringMatch2 _ANSI_ARGS_((CONST char * string, 
				CONST char * pattern));
/* Slot 3 is reserved */
/* 4 */
EXTERN struct exp_i *	exp_new_i_complex _ANSI_ARGS_((Tcl_Interp * interp, 
				char * arg, int duration, 
				Tcl_VarTraceProc * updateproc, 
				CONST char * msg));
/* 5 */
EXTERN struct exp_i *	exp_new_i_simple _ANSI_ARGS_((struct exp_f * fd, 
				int duration));
/* 6 */
EXTERN struct exp_fs_list * exp_new_fs _ANSI_ARGS_((struct exp_f * f));
/* 7 */
EXTERN void		exp_free_i _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_i * i, 
				Tcl_VarTraceProc * updateproc));
/* 8 */
EXTERN void		exp_free_fs _ANSI_ARGS_((
				struct exp_fs_list * fs_first));
/* 9 */
EXTERN void		exp_free_fs_single _ANSI_ARGS_((
				struct exp_fs_list * fs));
/* 10 */
EXTERN void		exp_i_update _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_i * i));
/* 11 */
EXTERN void		exp_pty_exit _ANSI_ARGS_((void));
/* 12 */
EXTERN void		exp_init_spawn_ids _ANSI_ARGS_((Tcl_Interp * interp));
/* 13 */
EXTERN void		exp_init_pty _ANSI_ARGS_((Tcl_Interp * interp));
/* 14 */
EXTERN void		exp_init_tty _ANSI_ARGS_((Tcl_Interp * interp));
/* 15 */
EXTERN void		exp_init_stdio _ANSI_ARGS_((void));
/* 16 */
EXTERN void		exp_init_sig _ANSI_ARGS_((void));
/* 17 */
EXTERN void		exp_init_trap _ANSI_ARGS_((void));
/* 18 */
EXTERN void		exp_init_unit_random _ANSI_ARGS_((void));
/* 19 */
EXTERN void		exp_init_spawn_id_vars _ANSI_ARGS_((
				Tcl_Interp * interp));
/* 20 */
EXTERN void		exp_adjust _ANSI_ARGS_((struct exp_f * f));
/* 21 */
EXTERN void		exp_ecmd_remove_f_direct_and_indirect _ANSI_ARGS_((
				Tcl_Interp * interp, struct exp_f * f));
/* 22 */
EXTERN void		exp_rearm_sigchld _ANSI_ARGS_((Tcl_Interp * interp));
/* 23 */
EXTERN struct exp_f *	exp_chan2f _ANSI_ARGS_((Tcl_Interp * interp, 
				CONST char * chan, int opened, int adjust, 
				CONST char * msg));
/* 24 */
EXTERN int		exp_fcheck _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f * f, int opened, int adjust, 
				CONST char * msg));
/* 25 */
EXTERN int		exp_close _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f * f));
/* 26 */
EXTERN void		exp_strftime _ANSI_ARGS_((char * format, 
				const struct tm * timeptr, 
				Tcl_DString * dstring));
/* 27 */
EXTERN void		exp_create_commands _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_cmd_data * c));
/* 28 */
EXTERN void		exp_tty_break _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f * f));
/* 29 */
EXTERN void		exp_event_disarm _ANSI_ARGS_((struct exp_f * f));
/* 30 */
EXTERN void		exp_arm_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 31 */
EXTERN void		exp_disarm_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 32 */
EXTERN void		exp_disarm_background_filehandler_force _ANSI_ARGS_((
				struct exp_f * f));
/* 33 */
EXTERN void		exp_unblock_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 34 */
EXTERN void		exp_block_background_filehandler _ANSI_ARGS_((
				struct exp_f * f));
/* 35 */
EXTERN int		exp_get_next_event _ANSI_ARGS_((Tcl_Interp * interp, 
				struct exp_f ** masters, int n, 
				struct exp_f ** master_out, int timeout, 
				int key));
/* 36 */
EXTERN int		exp_get_next_event_info _ANSI_ARGS_((
				Tcl_Interp * interp, struct exp_f * fd, 
				int ready_mask));
/* 37 */
EXTERN struct exp_f *	exp_f_find _ANSI_ARGS_((Tcl_Interp * interp, 
				char * spawnId));
/* 38 */
EXTERN struct exp_f *	exp_f_new _ANSI_ARGS_((Tcl_Interp * interp, 
				Tcl_Channel chan, char * spawnId, int pid));
/* 39 */
EXTERN int		exp_f_new_platform _ANSI_ARGS_((struct exp_f * f));
/* 40 */
EXTERN void		exp_f_free _ANSI_ARGS_((struct exp_f * f));
/* 41 */
EXTERN void		exp_f_free_platform _ANSI_ARGS_((struct exp_f * f));
/* 42 */
EXTERN int		exp_exact_write _ANSI_ARGS_((struct exp_f * f, 
				char * buffer, int rembytes));

typedef struct ExpIntStubs {
    int magic;
    struct ExpIntStubHooks *hooks;

    void *reserved0;

Changes to generic/expIntPlatDecls.h.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expIntPlatDecls.h,v 1.1.4.4 2002/03/07 02:49:36 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPPLATINTDECLS
#define _EXPPLATINTDECLS

/* !BEGIN!: Do not edit below this line. */

/*
 * Exported function declarations:
 */

#ifdef __WIN32__
/* 0 */
TCL_EXTERN(DWORD)	ExpWinApplicationType _ANSI_ARGS_((
				const char * originalName, 
				Tcl_DString * fullPath));
/* 1 */
TCL_EXTERN(DWORD)	ExpWinCreateProcess _ANSI_ARGS_((int argc, 
				char *const * argv, HANDLE inputHandle, 
				HANDLE outputHandle, HANDLE errorHandle, 
				int allocConsole, int hideConsole, int debug, 
				int newProcessGroup, HANDLE * processPtr, 
				PDWORD globalPidPtr));
/* 2 */
TCL_EXTERN(void)	ExpWinSyslog _ANSI_ARGS_(TCL_VARARGS(DWORD,errId));
/* 3 */
TCL_EXTERN(char *)	ExpSyslogGetSysMsg _ANSI_ARGS_((DWORD errId));
/* 4 */
TCL_EXTERN(Tcl_Pid)	Exp_WaitPid _ANSI_ARGS_((Tcl_Pid pid, int * statPtr, 
				int options));
/* 5 */
TCL_EXTERN(void)	Exp_KillProcess _ANSI_ARGS_((Tcl_Pid pid));
/* 6 */
TCL_EXTERN(void)	ExpWinInit _ANSI_ARGS_((void));
/* 7 */
TCL_EXTERN(void)	BuildCommandLine _ANSI_ARGS_((
				CONST char * executable, int argc, 
				char *const * argv, Tcl_DString * linePtr));
#endif /* __WIN32__ */

typedef struct ExpIntPlatStubs {
    int magic;
    struct ExpIntPlatStubHooks *hooks;







|














|



|






|

|

|


|

|

|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expIntPlatDecls.h,v 1.1.4.5 2002/03/11 06:52:53 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPPLATINTDECLS
#define _EXPPLATINTDECLS

/* !BEGIN!: Do not edit below this line. */

/*
 * Exported function declarations:
 */

#ifdef __WIN32__
/* 0 */
EXTERN DWORD		ExpWinApplicationType _ANSI_ARGS_((
				const char * originalName, 
				Tcl_DString * fullPath));
/* 1 */
EXTERN DWORD		ExpWinCreateProcess _ANSI_ARGS_((int argc, 
				char *const * argv, HANDLE inputHandle, 
				HANDLE outputHandle, HANDLE errorHandle, 
				int allocConsole, int hideConsole, int debug, 
				int newProcessGroup, HANDLE * processPtr, 
				PDWORD globalPidPtr));
/* 2 */
EXTERN void		ExpWinSyslog _ANSI_ARGS_(TCL_VARARGS(DWORD,errId));
/* 3 */
EXTERN char *		ExpSyslogGetSysMsg _ANSI_ARGS_((DWORD errId));
/* 4 */
EXTERN Tcl_Pid		Exp_WaitPid _ANSI_ARGS_((Tcl_Pid pid, int * statPtr, 
				int options));
/* 5 */
EXTERN void		Exp_KillProcess _ANSI_ARGS_((Tcl_Pid pid));
/* 6 */
EXTERN void		ExpWinInit _ANSI_ARGS_((void));
/* 7 */
EXTERN void		BuildCommandLine _ANSI_ARGS_((
				CONST char * executable, int argc, 
				char *const * argv, Tcl_DString * linePtr));
#endif /* __WIN32__ */

typedef struct ExpIntPlatStubs {
    int magic;
    struct ExpIntPlatStubHooks *hooks;

Changes to win/.gitignore.

1
2
3
4
5
6
7
*.ncb
*.opt
*.plg
Debug
DebugU
Release
ReleaseU




<

|
1
2
3
4

5
6
*.ncb
*.opt
*.plg
Debug

Release
Detours

Changes to win/Mcl/ChangeLog.






1
2
3
4
5
6
7





2001-11-18  David Gravereaux <[email protected]>

	* src/CMclMailbox.cpp:  2001-11-07 eratta change.  See
	http://www.bearcanyon.com/mtbook/errata.htm#source

2000-09-16  davidg
	* include/CMclLinkedLists.h:
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
2002-06-24  David Gravereaux <[email protected]>

	* src/CMclMailbox.cpp: A nasty bug found and fixed.  Author knows
	of it, too.

2001-11-18  David Gravereaux <[email protected]>

	* src/CMclMailbox.cpp:  2001-11-07 eratta change.  See
	http://www.bearcanyon.com/mtbook/errata.htm#source

2000-09-16  davidg
	* include/CMclLinkedLists.h:

Changes to win/Mcl/Mcl.dsp.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\ReleaseA"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo/out:".\lib\mcl.lib"







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\ReleaseA"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX- /O2 /I ".\include" /D "NDEBUG" /D "_MBCS" /D __CMCL_THROW_EXCEPTIONS__=0 /D "WIN32" /D "_WINDOWS" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo/out:".\lib\mcl.lib"
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\DebugA"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c

# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mcld.lib"







|
>







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\DebugA"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MDd /W3 /GX- /Z7 /Od /I ".\include" /D "_DEBUG" /D "_MBCS" /D __CMCL_THROW_EXCEPTIONS__=0 /D "WIN32" /D "_WINDOWS" /YX /FD /c
# SUBTRACT CPP /Fr
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mcld.lib"
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\DebugU"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mclud.lib"







|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\DebugU"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD CPP /nologo /MDd /W3 /GX- /Z7 /Od /I ".\include" /D "_DEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D __CMCL_THROW_EXCEPTIONS__=0 /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mclud.lib"
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\ReleaseU"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mclu.lib"







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\ReleaseU"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX- /O2 /I ".\include" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_WINDOWS" /D __CMCL_THROW_EXCEPTIONS__=0 /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mclu.lib"
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\ReleaseAS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G5 /MT /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo







|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\ReleaseAS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G5 /MT /W3 /GX- /O2 /I ".\include" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D __CMCL_THROW_EXCEPTIONS__=0 /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\DebugAS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G5 /MTd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mcld.lib"







|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\lib"
# PROP Intermediate_Dir ".\DebugAS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I ".\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G5 /MTd /W3 /GX- /Z7 /Od /I ".\include" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D __CMCL_THROW_EXCEPTIONS__=0 /YX /FD /c
# ADD BASE RSC /l 0x409
# ADD RSC /l 0x409
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:".\lib\mcld.lib"

Changes to win/Mcl/include/CMclGlobal.h.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#else
#define CMCL_CHECK_AUTOPTR_OBJECT(PTR,STATUS) if ((PTR).IsNull()) { (STATUS) = ERROR_OUTOFMEMORY; return; }
#endif

// SCODE is the return value to check,
// STATUS is the variable in which to store an error code if an error is detected...
#if __CMCL_THROW_EXCEPTIONS__
#define CMCL_CHECK_CREATION_STATUS(SCODE,STATUS) {}
#else
#define CMCL_CHECK_CREATION_STATUS(SCODE,STATUS) if (((SCODE)!=NO_ERROR)&&((SCODE)!=ERROR_ALREADY_EXISTS)) { STATUS = (SCODE); return; }
#endif

// error handling macro and function...
#ifdef UNICODE
#define ASUNICODE(_str) L#_str







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#else
#define CMCL_CHECK_AUTOPTR_OBJECT(PTR,STATUS) if ((PTR).IsNull()) { (STATUS) = ERROR_OUTOFMEMORY; return; }
#endif

// SCODE is the return value to check,
// STATUS is the variable in which to store an error code if an error is detected...
#if __CMCL_THROW_EXCEPTIONS__
#define CMCL_CHECK_CREATION_STATUS(SCODE,STATUS) if (((SCODE)!=NO_ERROR)&&((SCODE)!=ERROR_ALREADY_EXISTS)) { CMclThrowError(SCODE); }
#else
#define CMCL_CHECK_CREATION_STATUS(SCODE,STATUS) if (((SCODE)!=NO_ERROR)&&((SCODE)!=ERROR_ALREADY_EXISTS)) { STATUS = (SCODE); return; }
#endif

// error handling macro and function...
#ifdef UNICODE
#define ASUNICODE(_str) L#_str

Changes to win/Mcl/src/CMclMailbox.cpp.

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
    return (CMclWaitSucceeded(dwStatus, 1));
}

BOOL CMclMailbox::PostAlertable( const void *lpMsg, CMclEvent *pInterrupt, DWORD dwTimeout) {
    BOOL bStatus = FALSE;
    DWORD dwStatus = pInterrupt->WaitForTwo( *m_cFreeCountSemaphoreAPtr, FALSE, dwTimeout);
    if (CMclWaitSucceeded( dwStatus, 2)
            && (CMclWaitSucceededIndex(dwStatus) == (WAIT_OBJECT_0 + 1))) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( GetTailPtr(), lpMsg, m_pHdr->cbMsgSize);
            IncrementTail();
            m_cGuardMutexAPtr->Release();
            bStatus = TRUE;








|







230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
    return (CMclWaitSucceeded(dwStatus, 1));
}

BOOL CMclMailbox::PostAlertable( const void *lpMsg, CMclEvent *pInterrupt, DWORD dwTimeout) {
    BOOL bStatus = FALSE;
    DWORD dwStatus = pInterrupt->WaitForTwo( *m_cFreeCountSemaphoreAPtr, FALSE, dwTimeout);
    if (CMclWaitSucceeded( dwStatus, 2)
            && (CMclWaitSucceededIndex(dwStatus) == 1)) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( GetTailPtr(), lpMsg, m_pHdr->cbMsgSize);
            IncrementTail();
            m_cGuardMutexAPtr->Release();
            bStatus = TRUE;

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    return bStatus;
}

BOOL CMclMailbox::GetAlertable( void *lpMsg, CMclEvent *pInterrupt, DWORD dwTimeout) {
    BOOL bStatus = FALSE;
    DWORD dwStatus = pInterrupt->WaitForTwo( *m_cPendingCountSemaphoreAPtr, FALSE, dwTimeout);    
    if (CMclWaitSucceeded( dwStatus, 2)
            && (CMclWaitSucceededIndex(dwStatus) == (WAIT_OBJECT_0 + 1))) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( lpMsg, GetHeadPtr(), m_pHdr->cbMsgSize);
            IncrementHead();
            m_cGuardMutexAPtr->Release();
            bStatus = TRUE;








|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    return bStatus;
}

BOOL CMclMailbox::GetAlertable( void *lpMsg, CMclEvent *pInterrupt, DWORD dwTimeout) {
    BOOL bStatus = FALSE;
    DWORD dwStatus = pInterrupt->WaitForTwo( *m_cPendingCountSemaphoreAPtr, FALSE, dwTimeout);    
    if (CMclWaitSucceeded( dwStatus, 2)
            && (CMclWaitSucceededIndex(dwStatus) == 1)) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( lpMsg, GetHeadPtr(), m_pHdr->cbMsgSize);
            IncrementHead();
            m_cGuardMutexAPtr->Release();
            bStatus = TRUE;

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
    cCollection.AddObject(*m_cFreeCountSemaphoreAPtr);
    cCollection.AddCollection(rCollection);
    int nObjects = cCollection.GetCount();

    DWORD dwStatus = cCollection.Wait( FALSE, dwTimeout);
 
    if (CMclWaitSucceeded( dwStatus, nObjects)
            && (CMclWaitSucceededIndex(dwStatus) == WAIT_OBJECT_0)) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( GetTailPtr(), lpMsg, m_pHdr->cbMsgSize);
            IncrementTail();
            m_cGuardMutexAPtr->Release();
            dwStatus = WAIT_OBJECT_0;








|







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
    cCollection.AddObject(*m_cFreeCountSemaphoreAPtr);
    cCollection.AddCollection(rCollection);
    int nObjects = cCollection.GetCount();

    DWORD dwStatus = cCollection.Wait( FALSE, dwTimeout);
 
    if (CMclWaitSucceeded( dwStatus, nObjects)
            && (CMclWaitSucceededIndex(dwStatus) == 0)) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( GetTailPtr(), lpMsg, m_pHdr->cbMsgSize);
            IncrementTail();
            m_cGuardMutexAPtr->Release();
            dwStatus = WAIT_OBJECT_0;

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    cCollection.AddObject(*m_cPendingCountSemaphoreAPtr);
    cCollection.AddCollection(rCollection);
    int nObjects = cCollection.GetCount();

    DWORD dwStatus = cCollection.Wait( FALSE, dwTimeout);
 
    if (CMclWaitSucceeded( dwStatus, nObjects)
            && (CMclWaitSucceededIndex(dwStatus) == WAIT_OBJECT_0)) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( lpMsg, GetHeadPtr(), m_pHdr->cbMsgSize);
            IncrementHead();
            m_cGuardMutexAPtr->Release();
            dwStatus = WAIT_OBJECT_0;








|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    cCollection.AddObject(*m_cPendingCountSemaphoreAPtr);
    cCollection.AddCollection(rCollection);
    int nObjects = cCollection.GetCount();

    DWORD dwStatus = cCollection.Wait( FALSE, dwTimeout);
 
    if (CMclWaitSucceeded( dwStatus, nObjects)
            && (CMclWaitSucceededIndex(dwStatus) == 0)) {
        dwStatus = m_cGuardMutexAPtr->Wait(dwTimeout);
        if (CMclWaitSucceeded(dwStatus, 1) || CMclWaitAbandoned(dwStatus, 1)) {
            CopyMemory( lpMsg, GetHeadPtr(), m_pHdr->cbMsgSize);
            IncrementHead();
            m_cGuardMutexAPtr->Release();
            dwStatus = WAIT_OBJECT_0;

Changes to win/MsvcDbgControl.cpp.

19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.sf.net/
 *	    http://expect.nist.gov/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: MsvcDbgControl.cpp,v 1.1.2.6 2002/03/12 04:37:39 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include <initguid.h>







>







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.sf.net/
 *	    http://expect.nist.gov/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: MsvcDbgControl.cpp,v 1.1.2.7 2002/03/12 23:12:59 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include <initguid.h>

Changes to win/MsvcDbgControl.h.

16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: MsvcDbgControl.h,v 1.1.2.4 2002/03/09 01:17:29 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_MsvcDbgControl_h__
#define INC_MsvcDbgControl_h__

#include <windows.h>

extern TCL_CPP int	MsvcDbg_Launch(const CHAR *wrkspace, Tcl_DString *cmdline,
			void **token);
#endif







>







|








|


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: MsvcDbgControl.h,v 1.1.2.6 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_MsvcDbgControl_h__
#define INC_MsvcDbgControl_h__

#include <windows.h>

TCL_EXTRNC int	MsvcDbg_Launch(const CHAR *wrkspace, Tcl_DString *cmdline,
			void **token);
#endif

Deleted win/TclAdapter.hpp.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 ------------------------------------------------------------------------------
 * TclAdapter.hpp --
 *
 *	Defines one templated class for doing the grunt work for making
 *	C++ extensions.
 *
 * Copyright (c) 1999-2001 TomaSoft Engineering
 *
 * See the file "license.txt" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: TclAdapter.hpp,v 1.1.2.1 2002/03/11 00:31:56 davygrvy Exp $
 ------------------------------------------------------------------------------
 */
#ifndef INC_TclAdapter_hpp__
#define INC_TclAdapter_hpp__

#include "tcl.h"

// We need at least the Tcl_Obj interface that was started in 8.0
#if TCL_MAJOR_VERSION < 8
#   error "we need Tcl 8.0 or greater to build this"

// Check for Stubs compatibility when asked for it.
#elif defined(USE_TCL_STUBS) && TCL_MAJOR_VERSION == 8 && \
	(TCL_MINOR_VERSION == 0 || \
        (TCL_MINOR_VERSION == 1 && TCL_RELEASE_LEVEL != TCL_FINAL_RELEASE))
#   error "Stubs interface doesn't work in 8.0 and alpha/beta 8.1; only 8.1.0+"
#endif

#ifdef _MSC_VER
    // Only do this when MSVC++ is compiling us.
#   ifdef USE_TCL_STUBS
	// Mark this .obj as needing tcl's Stubs library.
#	pragma comment(lib, "tclstub" \
	    STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
#	if !defined(_MT) || !defined(_DLL) || defined(_DEBUG)
	    // This fixes a bug with how the Stubs library was compiled.
	    // The requirement for msvcrt.lib from tclstubXX.lib should
	    // be removed.
#	    pragma comment(linker, "-nodefaultlib:msvcrt.lib")
#	endif
#   else
    // Mark this .obj needing the import library
#   pragma comment(lib, "tcl" \
	STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
#   endif
#endif

// We only need one Win32 API in here so we can be super defensive
// with the destructor.
#ifdef __WIN32__
#   include <windows.h>
#   ifdef _MSC_VER
#	pragma comment (lib, "kernel32.lib")
#   endif
#endif


// short cut
#define NewTclCmd(a,b,c) \
	Tcl_CreateObjCommand((a), (b), CmdDemux, CmdInfo((c), this), CmdDelete)


namespace Tcl {
    template <class T>
	class Adapter
    {
	typedef struct {
	    T *ext;
	    int (T::*cmd)(int, struct Tcl_Obj * CONST []);
	} MPLEXDATA, *LPMPLEXDATA;

    protected:
	Adapter(Tcl_Interp *_interp);
	~Adapter();

	Tcl_Interp *interp;

	virtual void DoCleanup(void) = 0;

	// Create the multiplexor data that we save in the ClientData portion
	// of the Tcl command.
	ClientData CmdInfo(int (T::*cmd)(int, struct Tcl_Obj * CONST []), T *that)
	{
	    LPMPLEXDATA mplex = new MPLEXDATA;
	    
	    mplex->ext = that;
	    mplex->cmd = cmd;
	    return static_cast <ClientData>(mplex);
	}
	static Tcl_InterpDeleteProc InterpDeleting;
	static Tcl_ExitProc Exiting;
	static Tcl_ObjCmdProc CmdDemux;
	static Tcl_CmdDeleteProc CmdDelete;
    };


    template <class T>
	Adapter<T>::Adapter(Tcl_Interp *_interp)
	: interp(_interp)
    {
	Tcl_CallWhenDeleted(interp, InterpDeleting, this);
	Tcl_CreateExitHandler(Exiting, this);
    }


    template <class T>
	Adapter<T>::~Adapter()
    {
	Tcl_DeleteExitHandler(Exiting, this);
    }


    template <class T> void
	Adapter<T>::InterpDeleting (ClientData clientData, Tcl_Interp *)
    {
	T *adapt = static_cast <T *>(clientData);
	adapt->DoCleanup();
	delete adapt;
    }


    template <class T> void
	Adapter<T>::Exiting (ClientData clientData)
    {
#ifdef __WIN32__
	// It can happen that the HEAP could have already been unloaded from an
	// awkward teardown caused by a Ctrl+C or other.  Win32 seems to do a
	// teardown in reverse order and by the time Tcl knows what's going on
	// and Tcl_Finalize calls the exit handlers, this extension's data has
	// already been unloaded by the OS.  Do a quick legal check on the
	// pointer first.
	if (IsBadReadPtr(clientData, sizeof(T *))) return;
#endif
	delete static_cast <T *>(clientData);
    }


    template <class T> int
	Adapter<T>::CmdDemux (ClientData clientData, Tcl_Interp *, int objc,
			      struct Tcl_Obj * CONST objv[])
    {
	LPMPLEXDATA demux = static_cast <LPMPLEXDATA>(clientData);
	// We aleady know what the interp pointer is (saved in the class
	// instance), so don't bother with it here. Call the member function
	// of the extension instance as saved in the MPLEXDATA struct when we
	// created this command using the somewhat obscure C++ pointer-to-
	// member method.
	//
	// This is a demultiplexor or 'demux' for short.
	return ((demux->ext) ->* (demux->cmd)) (objc,objv);
    }


    template <class T> void
	Adapter<T>::CmdDelete (ClientData clientData)
    {
	// clean-up the MPLEXDATA structure from the commands.
	delete static_cast <LPMPLEXDATA>(clientData);
    }
}
#endif
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































































































































































































































































Added win/TclAdaptor.hpp.

























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 ------------------------------------------------------------------------------
 * TclAdaptor.hpp --
 *
 *	Defines one templated class for doing the grunt work of making
 *	C++ extensions for Tcl.
 *
 * Copyright (c) 1999-2001 TomaSoft Engineering
 *
 * See the file "license.txt" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: TclAdaptor.hpp,v 1.6 2002/08/26 23:48:20 davygrvy Exp $
 ------------------------------------------------------------------------------
 */
#ifndef INC_TclAdaptor_hpp__
#define INC_TclAdaptor_hpp__

#ifndef INC_config_hpp__
#   include "config.hpp"
#endif

#include "tcl.h"

// We need at least the Tcl_Obj interface that was started in 8.0
#if TCL_MAJOR_VERSION < 8
#   error "we need Tcl 8.0 or greater to build this"

// Check for Stubs compatibility when asked for it.
#elif defined(USE_TCL_STUBS) && TCL_MAJOR_VERSION == 8 && \
	(TCL_MINOR_VERSION == 0 || \
        (TCL_MINOR_VERSION == 1 && TCL_RELEASE_LEVEL != TCL_FINAL_RELEASE))
#   error "Stubs interface doesn't work in 8.0 and alpha/beta 8.1; only 8.1.0+"
#endif

#ifdef _MSC_VER
    // Only do this when MSVC++ is compiling us.
#   ifdef USE_TCL_STUBS
	// Mark this .obj as needing tcl's Stubs library.
#	pragma comment(lib, "tclstub" \
	    STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
#	if !defined(_MT) || !defined(_DLL) || defined(_DEBUG)
	    // This fixes a bug with how the Stubs library was compiled.
	    // The requirement for msvcrt.lib from tclstubXX.lib should
	    // be removed.
#	    pragma comment(linker, "-nodefaultlib:msvcrt.lib")
#	endif
#   else
    // Mark this .obj needing the import library
#   pragma comment(lib, "tcl" \
	STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
#   endif
#endif

// We only need one Win32 API in here so we can be super defensive
// with the destructor.
#ifdef __WIN32__
#   include <windows.h>
#   ifdef _MSC_VER
#	pragma comment (lib, "kernel32.lib")
#   endif
#endif


// short cut
#define NewTclCmd(a,b) \
	Tcl_CreateObjCommand(interp, (a), CmdDemux, CmdInfo((b), this), CmdDelete)


CPPTCL_BEGIN_NAMESPACE(Tcl)

template <class T>
    class Adaptor
{
    typedef struct {
	T *ext;
	int (T::*cmd)(int, struct Tcl_Obj * const []);
    } MPLEXDATA, *LPMPLEXDATA;

public:
    Tcl_Interp *interp;

protected:
    Adaptor(Tcl_Interp *_interp);
    Adaptor();
    virtual ~Adaptor();

    virtual void DoInterpDataCleanup(void) {};
    virtual void DoCommandCleanup(void) {};

    void InitBase();    // delay start entry when the interp isn't
			// known for the constructor.

    // Create the multiplexor data that we save in the ClientData
    // portion of the Tcl command.
    //
    ClientData CmdInfo(int (T::*cmd)(int, struct Tcl_Obj * const []), T *that)
    {
	LPMPLEXDATA mplex = new MPLEXDATA;
	
	mplex->ext = that;
	mplex->cmd = cmd;
	return static_cast <ClientData>(mplex);
    }
    static Tcl_InterpDeleteProc InterpDeleting;
    static Tcl_ExitProc Exiting;
    static Tcl_ObjCmdProc CmdDemux;
    static Tcl_CmdDeleteProc CmdDelete;
};


template <class T>
    Adaptor<T>::Adaptor(Tcl_Interp *_interp)
    : interp(_interp)
{
    InitBase();
}

template <class T>
    Adaptor<T>::Adaptor()
    : interp(0L)
{
}

template <class T> void
    Adaptor<T>::InitBase()
{
    Tcl_CallWhenDeleted(interp, InterpDeleting, this);
    Tcl_CreateExitHandler(Exiting, this);
}

template <class T>
    Adaptor<T>::~Adaptor()
{
    if (interp != 0L) DoCommandCleanup();
    Tcl_DeleteExitHandler(Exiting, this);
}


template <class T> void
    Adaptor<T>::InterpDeleting (ClientData clientData, Tcl_Interp *)
{
    T *adapt = reinterpret_cast <T *>(clientData);
    adapt->DoInterpDataCleanup();

    // The use of the interp* is not allowed from the context of the
    // destructor.  Ensure that it can't be used by removing it now.
    //
    adapt->interp = 0L;
    delete adapt;
}


template <class T> void
    Adaptor<T>::Exiting (ClientData clientData)
{
    T *adapt = reinterpret_cast <T *>(clientData);
#ifdef __WIN32__
    // It can happen that the HEAP could have already been unloaded
    // from an awkward teardown caused by a Ctrl+C or other.  Win32
    // seems to do a teardown in reverse order and by the time Tcl
    // knows what's going on and Tcl_Finalize calls the exit
    // handlers, this extension's data (heap?) has already been
    // unloaded by the OS.  Do a quick legal check on the pointer
    // first.
    //
    if (IsBadReadPtr(adapt, sizeof(T *))) return;
#endif
    // The use of the interp* is not allowed from the context of an
    // exit handler, so make sure it can't be used by removing it.
    //
    adapt->interp = 0L;
    delete adapt;
}


template <class T> int
    Adaptor<T>::CmdDemux (ClientData clientData, Tcl_Interp *, int objc,
			  struct Tcl_Obj * const objv[])
{
    LPMPLEXDATA demux = static_cast <LPMPLEXDATA>(clientData);
    // We aleady know what the interp pointer is (saved in the class
    // instance), so don't bother with it here. Call the member function
    // of the extension instance as saved in the MPLEXDATA struct when we
    // created this command using the somewhat obscure C++ pointer-to-
    // member method.
    //
    // This is a demultiplexor or 'demux' for short.
    //
    return ((demux->ext) ->* (demux->cmd)) (objc,objv);
}


template <class T> void
    Adaptor<T>::CmdDelete (ClientData clientData)
{
    // clean-up the MPLEXDATA structure from the commands.
    //
    delete static_cast <LPMPLEXDATA>(clientData);
}

CPPTCL_END_NAMESPACE

#endif

Changes to win/TclHash.hpp.

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

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123



124
125
126




127













128
129
/*
 ------------------------------------------------------------------------------
 * TclHash.hpp --
 *
 *   Tcl's hash table done as a template.
 *
 * Copyright (c) 1999-2001 David Gravereaux
 *
 * See the file "license.txt" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: TclHash.hpp,v 1.1.2.1 2002/03/12 16:42:07 davygrvy Exp $
 ------------------------------------------------------------------------------
 */

#ifndef INC_tclhash_hpp__
#define INC_tclhash_hpp__





#include "tcl.h"

namespace Tcl {

    template <class T, int keytype = TCL_STRING_KEYS>
	class Hash
    {
    public:
	Hash () { Tcl_InitHashTable(&HashTbl, keytype); }
	~Hash () { Tcl_DeleteHashTable(&HashTbl); }
	Tcl_Obj *Stats ();
	int Add (void *key, T result);
	int Find (void *key, T *result);

	int Delete (void *key);
	int Top (T *result);
	int Next (T *result);

    protected:
	Tcl_HashSearch HashSrch;
	Tcl_HashTable HashTbl;
    };

    template <class T, int keytype>
	Tcl_Obj *Hash<T, keytype>::Stats ()
    {
	char *stats;
	Tcl_Obj *oStats;

	stats = Tcl_HashStats(&HashTbl);
	oStats = Tcl_NewStringObj(stats, -1);
	ckfree(stats);
	return oStats;
    }

    template <class T, int keytype>
	int Hash<T, keytype>::Add (void *key, T result)
    {
	int created;
	Tcl_HashEntry *entryPtr;

	entryPtr = Tcl_CreateHashEntry(&HashTbl, static_cast<const char *>(key),
	    &created);

	if (!created) {
	    return TCL_ERROR;
	}
	Tcl_SetHashValue(entryPtr, result);
	return TCL_OK;
    }

    template <class T, int keytype>
	int Hash<T, keytype>::Find (void *key, T *result)
    {
	Tcl_HashEntry *entryPtr;

	entryPtr = Tcl_FindHashEntry(&HashTbl, static_cast<const char *>(key));
	if (entryPtr == 0L) {
	    return TCL_ERROR;
	}
	if (result != 0L) {
	    *result = static_cast<T>(Tcl_GetHashValue(entryPtr));
	}
	return TCL_OK;
    }

    template <class T, int keytype>
	int Hash<T, keytype>::Delete (void *key)
    {
	Tcl_HashEntry *entryPtr;

	entryPtr = Tcl_FindHashEntry(&HashTbl, static_cast<const char *>(key));
	if (entryPtr == 0L) {
	    return TCL_ERROR;
	}
	Tcl_DeleteHashEntry(entryPtr);
	return TCL_OK;
    }

    template <class T, int keytype>
	int Hash<T, keytype>::Top (T *result)
    {
	Tcl_HashEntry *entryPtr;

	entryPtr = Tcl_FirstHashEntry(&HashTbl, &HashSrch);
	if (entryPtr == 0L) {
	    return TCL_ERROR;
	}
	if (result != 0L) {
	    *result = static_cast<T>(Tcl_GetHashValue(entryPtr));
	}



	return TCL_OK;
    }

    template <class T, int keytype>
	int Hash<T, keytype>::Next (T *result)
    {
	Tcl_HashEntry *entryPtr;

	entryPtr = Tcl_NextHashEntry(&HashSrch);
	if (entryPtr == 0L) {
	    return TCL_ERROR;
	}
	if (result != 0L) {
	    *result = static_cast<T>(Tcl_GetHashValue(entryPtr));
	}



	return TCL_OK;
    }





};	// namespace Tcl













#endif	// #ifndef INC_tclhash_hpp__







|




|





>
>
>
>



|

|
|
|
|
|
|
|
|
|
>
|
|
|

|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|

|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
>
>
>
|
|

|
|
|
|

|
|
|
|
|
|
|
>
>
>
|
|

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 ------------------------------------------------------------------------------
 * TclHash.hpp --
 *
 *   Tcl's hash table done as a template.
 *
 * Copyright (c) 1999-2001 TomaSoft Engineering
 *
 * See the file "license.txt" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: TclHash.hpp,v 1.15 2002/08/27 01:27:44 davygrvy Exp $
 ------------------------------------------------------------------------------
 */

#ifndef INC_tclhash_hpp__
#define INC_tclhash_hpp__

#ifndef INC_config_hpp__
#   include "config.hpp"
#endif

#include "tcl.h"

CPPTCL_BEGIN_NAMESPACE(Tcl)

template <class T, int keytype = TCL_STRING_KEYS>
    class Hash
{
public:
    Hash () { Tcl_InitHashTable(&HashTbl, keytype); }
    ~Hash () { Tcl_DeleteHashTable(&HashTbl); }
    Tcl_Obj *Stats ();
    int Add (const void *key, T result);
    int Find (const void *key, T *result);
    int Extract (const void *key, T *result);
    int Delete (const void *key);
    int Top (T *result, const void **key = 0L);
    int Next (T *result, const void **key = 0L);

protected:
    Tcl_HashSearch HashSrch;
    Tcl_HashTable HashTbl;
};

template <class T, int keytype>
    Tcl_Obj *Hash<T, keytype>::Stats ()
{
    const char *stats;
    Tcl_Obj *oStats;

    stats = Tcl_HashStats(&HashTbl);
    oStats = Tcl_NewStringObj(stats, -1);
    ckfree((char *)stats);
    return oStats;
}

template <class T, int keytype>
    int Hash<T, keytype>::Add (const void *key, T result)
{
    int created;
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_CreateHashEntry(&HashTbl, static_cast<const char *>(key),
	&created);

    if (!created) {
	return TCL_ERROR;
    }
    Tcl_SetHashValue(entryPtr, result);
    return TCL_OK;
}

template <class T, int keytype>
    int Hash<T, keytype>::Find (const void *key, T *result)
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FindHashEntry(&HashTbl, static_cast<const char *>(key));
    if (entryPtr == 0L) {
	return TCL_ERROR;
    }
    if (result != 0L) {
	*result = reinterpret_cast<T>(Tcl_GetHashValue(entryPtr));
    }
    return TCL_OK;
}

template <class T, int keytype>
    int Hash<T, keytype>::Delete (const void *key)
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FindHashEntry(&HashTbl, static_cast<const char *>(key));
    if (entryPtr == 0L) {
	return TCL_ERROR;
    }
    Tcl_DeleteHashEntry(entryPtr);
    return TCL_OK;
}

template <class T, int keytype>
    int Hash<T, keytype>::Top (T *result, const void **key)
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FirstHashEntry(&HashTbl, &HashSrch);
    if (entryPtr == 0L) {
	return TCL_ERROR;
    }
    if (result != 0L) {
	*result = reinterpret_cast<T>(Tcl_GetHashValue(entryPtr));
    }
    if (key != 0L) {
	*key = Tcl_GetHashKey(&HashTbl, entryPtr);
    }
    return TCL_OK;
}

template <class T, int keytype>
    int Hash<T, keytype>::Next (T *result, const void **key)
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_NextHashEntry(&HashSrch);
    if (entryPtr == 0L) {
	return TCL_ERROR;
    }
    if (result != 0L) {
	*result = reinterpret_cast<T>(Tcl_GetHashValue(entryPtr));
    }
    if (key != 0L) {
	*key = Tcl_GetHashKey(&HashTbl, entryPtr);
    }
    return TCL_OK;
}

template <class T, int keytype>
    int Hash<T, keytype>::Extract (const void *key, T *result)
{
    Tcl_HashEntry *entryPtr;

    entryPtr = Tcl_FindHashEntry(&HashTbl, static_cast<const char *>(key));
    if (entryPtr == 0L) {
	return TCL_ERROR;
    }
    if (result != 0L) {
	*result = reinterpret_cast<T>(Tcl_GetHashValue(entryPtr));
    }
    Tcl_DeleteHashEntry(entryPtr);
    return TCL_OK;
}

CPPTCL_END_NAMESPACE

#endif	// #ifndef INC_tclhash_hpp__

Added win/config.hpp.











































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#ifndef INC_config_hpp__
#define INC_config_hpp__

// Just a simple configuration file to adjust between
// various compiler quirks.


/*******************************************
 *   Microsoft Visual C++
 *******************************************/
#if defined(_MSC_VER) && !defined(__ICL) && !defined(__MWERKS__)
    // we don't care to know about name trucation in the debug data.
#   pragma warning (disable:4786)
#endif


/*******************************************
 * Intel C++ Compiler
 *******************************************/
#if defined(__ICL)
#endif


/*******************************************
 * Mingw32 (gcc)
 *   (egcs compiler using the M$ C runtime)
 *******************************************/
#if defined(__MINGW32__)
#endif


/*******************************************
 * Cygwin32 (gcc)
 *   (egcs cross-compiler on M$ Windows)
 *******************************************/
#if defined(__CYGWIN__)
#endif


#if defined(__sgi) && !defined(__GNUC__)
#   if (_COMPILER_VERSION >= 721) && !defined(_NAMESPACES)
#	define CPPTCL_NO_NAMESPACES
#   endif
#endif

/*******************************************
 * SunPro Compiler
 *     (Using OBJECTSPACE STL)
 *******************************************/
#ifdef __SUNPRO_CC
#   if (__SUNPRO_CC == 0x420)
#	define CPPTCL_NO_NAMESPACES
#   endif
#endif


/*******************************************
 * SCO UDK 7 compiler
 *     (UnixWare 7x, OSR 5, UnixWare 2x)
 *******************************************/
#if defined(__USLC__)
#endif


/*******************************************
 *   Inprise (Borland) C++ Builder 3.0
 *******************************************/
#ifdef __BCPLUSPLUS__
#endif


/*******************************************
 * IBM VisualAge C++ 
 *   ( uses the Dinkumware C++ Library )
 *******************************************/
#ifdef __IBMCPP__
#endif


/*******************************************
 * Metrowerks Codewarrior
 *******************************************/
#ifdef __MWERKS__
#endif



#if !defined(CPPTCL_NO_NAMESPACES)
#   define CPPTCL_USE_NAMESPACE(_x_)	    _x_::
#   define CPPTCL_USING_NAMESPACE(_x_)	    using namespace _x_;
#   define CPPTCL_BEGIN_NAMESPACE(_x_)	    namespace _x_ {
#   define CPPTCL_END_NAMESPACE 	    }
#else
#   define CPPTCL_USE_NAMESPACE(_x_)
#   define CPPTCL_USING_NAMESPACE(_x_)
#   define CPPTCL_BEGIN_NAMESPACE(_x_)
#   define CPPTCL_END_NAMESPACE
#endif


#endif // #ifndef INC_config_hpp__

Changes to win/expWinCommand.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinCommand.c,v 1.1.2.1.2.10 2002/02/10 12:03:30 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

#ifdef TCL_DEBUGGER
#include "Dbg.h"







>







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinCommand.c,v 1.1.2.1.2.12 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

#ifdef TCL_DEBUGGER
#include "Dbg.h"
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
 *	of stuff popping up.
 *----------------------------------------------------------------------
 */
/* arguments are passed verbatim to execvp() */
/*ARGSUSED*/

int
Exp_SpawnCmd(ClientData clientData,Tcl_Interp *interp,int argc,char **argv)
{
    HANDLE hSlaveDrv = INVALID_HANDLE_VALUE;	/* Handle to communicate with slave driver */
    Tcl_Pid slaveDrvPid;	/* Process id of the slave */
    BOOL bRet;
    DWORD dwRet;
    DWORD count;
    int echo = TRUE;
    char **a;
    char *argv0 = argv[0];
    char slaveName[50];		/* Used to set 'spawn_out(slave,name)' */
    static int slaveId = 1;	/* Start at one because console0 is expect's */
    UCHAR buf[8];		/* enough space for child status info */
    WCHAR execPath[MAX_PATH];   /* needed for unicode space. */
    Tcl_DString slavePath;
    Tcl_DString slaveDrvPath;
    struct exp_f *f;
    HANDLE hEvent = NULL;
    OVERLAPPED over;
    DWORD globalPid;
    Tcl_Channel channel = NULL;
    Tcl_Channel channel2 = NULL;
    Tcl_Channel spawnChan = NULL;
    TclFile masterRFile;
    TclFile masterWFile;
    char *openarg = NULL;
    int leaveopen = 0;
    CONST char *val;
    int hide;
    int debug;
    char **nargv = NULL;
    int i, j;
    int usePipes = 0;
    int useSocket = 0;

    char pipeName[100];
    static int pipeNameId = 0;
    char sockPort[10];







|







|
|















|




|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
 *	of stuff popping up.
 *----------------------------------------------------------------------
 */
/* arguments are passed verbatim to execvp() */
/*ARGSUSED*/

int
Exp_SpawnCmd(ClientData clientData,Tcl_Interp *interp,int argc, CONST char **argv)
{
    HANDLE hSlaveDrv = INVALID_HANDLE_VALUE;	/* Handle to communicate with slave driver */
    Tcl_Pid slaveDrvPid;	/* Process id of the slave */
    BOOL bRet;
    DWORD dwRet;
    DWORD count;
    int echo = TRUE;
    CONST char **a;
    CONST char *argv0 = argv[0];
    char slaveName[50];		/* Used to set 'spawn_out(slave,name)' */
    static int slaveId = 1;	/* Start at one because console0 is expect's */
    UCHAR buf[8];		/* enough space for child status info */
    WCHAR execPath[MAX_PATH];   /* needed for unicode space. */
    Tcl_DString slavePath;
    Tcl_DString slaveDrvPath;
    struct exp_f *f;
    HANDLE hEvent = NULL;
    OVERLAPPED over;
    DWORD globalPid;
    Tcl_Channel channel = NULL;
    Tcl_Channel channel2 = NULL;
    Tcl_Channel spawnChan = NULL;
    TclFile masterRFile;
    TclFile masterWFile;
    CONST char *openarg = NULL;
    int leaveopen = 0;
    CONST char *val;
    int hide;
    int debug;
    CONST char **nargv = NULL;
    int i, j;
    int usePipes = 0;
    int useSocket = 0;

    char pipeName[100];
    static int pipeNameId = 0;
    char sockPort[10];
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
 *
 *----------------------------------------------------------------------
 */

/*ARGSUSED*/

int
Exp_KillCmd(ClientData clientData,Tcl_Interp *interp,int argc,char **argv)
{
    struct exp_f *f;
    char *chanId = NULL;
    char *argv0 = argv[0];
    int signal = 9;
    char buf[2];
    int msg;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {







|


|
|







638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
 *
 *----------------------------------------------------------------------
 */

/*ARGSUSED*/

int
Exp_KillCmd(ClientData clientData,Tcl_Interp *interp,int argc, CONST char **argv)
{
    struct exp_f *f;
    CONST char *chanId = NULL;
    CONST char *argv0 = argv[0];
    int signal = 9;
    char buf[2];
    int msg;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {

Changes to win/expWinConsoleDebugger.cpp.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31




32
33
34
35











36
37




38






39



40






















41
42
43
44
45
46
47
48
49
50
51
52
53
54
55




56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154



































155
156
157
158
159
160
161
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleDebugger.cpp,v 1.1.2.13 2002/03/15 07:51:56 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <stddef.h>
#include <assert.h>
#include "expWinConsoleDebugger.hpp"




#ifdef _MSC_VER
#   pragma comment (lib, "imagehlp.lib")
#endif












//  Constructor.
ConsoleDebugger::ConsoleDebugger (int _argc, char * const *_argv, CMclQueue<Message *> &_mQ)




    : argc(_argc), argv(_argv), ProcessList(0L), CursorKnown(FALSE),






    ShowExceptionBacktraces(FALSE), SymbolPath(0L), mQ(_mQ)



{






















    //  Until further notice, assume this.
    //
    ConsoleSize.X = 80;
    ConsoleSize.Y = 25;

    //  Until further notice, assume this, too.
    //
    CursorPosition.X = 0;
    CursorPosition.Y = 0;

    //  Set all our breakpoint info.  We have to do this the long way, here in
    //  the constructor, because we need to have the this pointer already
    //  set because we refer to ourselves by needing the address to member
    //  functions.
    //




    BreakArrayKernel32[0].funcName = "Beep";
    BreakArrayKernel32[0].nargs = 2;
    BreakArrayKernel32[0].breakProc = OnBeep;
    BreakArrayKernel32[0].dwFlags = BREAK_OUT|BREAK_IN;

    BreakArrayKernel32[1].funcName = "FillConsoleOutputCharacterA";
    BreakArrayKernel32[1].nargs = 5;
    BreakArrayKernel32[1].breakProc = OnFillConsoleOutputCharacter;
    BreakArrayKernel32[1].dwFlags = BREAK_OUT;

    BreakArrayKernel32[2].funcName = "FillConsoleOutputCharacterW";
    BreakArrayKernel32[2].nargs = 5;
    BreakArrayKernel32[2].breakProc = OnFillConsoleOutputCharacter;
    BreakArrayKernel32[2].dwFlags = BREAK_OUT;

    BreakArrayKernel32[3].funcName = "GetStdHandle";
    BreakArrayKernel32[3].nargs = 1;
    BreakArrayKernel32[3].breakProc = OnGetStdHandle;
    BreakArrayKernel32[3].dwFlags = BREAK_OUT;

    BreakArrayKernel32[4].funcName = "OpenConsoleW";
    BreakArrayKernel32[4].nargs = 4;
    BreakArrayKernel32[4].breakProc = OnOpenConsoleW;
    BreakArrayKernel32[4].dwFlags = BREAK_OUT;

    BreakArrayKernel32[5].funcName = "ReadConsoleInputA";
    BreakArrayKernel32[5].nargs = 4;
    BreakArrayKernel32[5].breakProc = OnReadConsoleInput;
    BreakArrayKernel32[5].dwFlags = BREAK_OUT;

    BreakArrayKernel32[6].funcName = "ReadConsoleInputW";
    BreakArrayKernel32[6].nargs = 4;
    BreakArrayKernel32[6].breakProc = OnReadConsoleInput;
    BreakArrayKernel32[6].dwFlags = BREAK_OUT;

    BreakArrayKernel32[7].funcName = "ScrollConsoleScreenBufferA";
    BreakArrayKernel32[7].nargs = 5;
    BreakArrayKernel32[7].breakProc = OnScrollConsoleScreenBuffer;
    BreakArrayKernel32[7].dwFlags = BREAK_OUT;

    BreakArrayKernel32[8].funcName = "ScrollConsoleScreenBufferW";
    BreakArrayKernel32[8].nargs = 5;
    BreakArrayKernel32[8].breakProc = OnScrollConsoleScreenBuffer;
    BreakArrayKernel32[8].dwFlags = BREAK_OUT;

    BreakArrayKernel32[9].funcName = "SetConsoleMode";
    BreakArrayKernel32[9].nargs = 2;
    BreakArrayKernel32[9].breakProc = OnSetConsoleMode;
    BreakArrayKernel32[9].dwFlags = BREAK_OUT;

    BreakArrayKernel32[10].funcName = "SetConsoleActiveScreenBuffer";
    BreakArrayKernel32[10].nargs = 1;
    BreakArrayKernel32[10].breakProc = OnSetConsoleActiveScreenBuffer;
    BreakArrayKernel32[10].dwFlags = BREAK_OUT;

    BreakArrayKernel32[11].funcName = "SetConsoleCursorPosition";
    BreakArrayKernel32[11].nargs = 2;
    BreakArrayKernel32[11].breakProc = OnSetConsoleCursorPosition;
    BreakArrayKernel32[11].dwFlags = BREAK_OUT;

    BreakArrayKernel32[12].funcName = "SetConsoleWindowInfo";
    BreakArrayKernel32[12].nargs = 2;
    BreakArrayKernel32[12].breakProc = OnSetConsoleWindowInfo;
    BreakArrayKernel32[12].dwFlags = BREAK_OUT;

    BreakArrayKernel32[13].funcName = "WriteConsoleA";
    BreakArrayKernel32[13].nargs = 5;
    BreakArrayKernel32[13].breakProc = OnWriteConsoleA;
    BreakArrayKernel32[13].dwFlags = BREAK_OUT;

    BreakArrayKernel32[14].funcName = "WriteConsoleW";
    BreakArrayKernel32[14].nargs = 5;
    BreakArrayKernel32[14].breakProc = OnWriteConsoleW;
    BreakArrayKernel32[14].dwFlags = BREAK_OUT;

    BreakArrayKernel32[15].funcName = "WriteConsoleOutputA";
    BreakArrayKernel32[15].nargs = 5;
    BreakArrayKernel32[15].breakProc = OnWriteConsoleOutputA;
    BreakArrayKernel32[15].dwFlags = BREAK_OUT;

    BreakArrayKernel32[16].funcName = "WriteConsoleOutputW";
    BreakArrayKernel32[16].nargs = 5;
    BreakArrayKernel32[16].breakProc = OnWriteConsoleOutputW;
    BreakArrayKernel32[16].dwFlags = BREAK_OUT;

    BreakArrayKernel32[17].funcName = "WriteConsoleOutputCharacterA";
    BreakArrayKernel32[17].nargs = 5;
    BreakArrayKernel32[17].breakProc = OnWriteConsoleOutputCharacterA;
    BreakArrayKernel32[17].dwFlags = BREAK_OUT;

    BreakArrayKernel32[18].funcName = "WriteConsoleOutputCharacterW";
    BreakArrayKernel32[18].nargs = 5;
    BreakArrayKernel32[18].breakProc = OnWriteConsoleOutputCharacterW;
    BreakArrayKernel32[18].dwFlags = BREAK_OUT;

    BreakArrayKernel32[19].funcName = 0L;
    BreakArrayKernel32[19].nargs = 0;
    BreakArrayKernel32[19].breakProc = 0L;
    BreakArrayKernel32[19].dwFlags = 0;




































    BreakArrayUser32[0].funcName = "IsWindowVisible";
    BreakArrayUser32[0].nargs = 1;
    BreakArrayUser32[0].breakProc = OnIsWindowVisible;
    BreakArrayUser32[0].dwFlags = BREAK_OUT;

    BreakArrayUser32[1].funcName = 0L;







>







|






>
>
>
>




>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>

>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|



>
>
>
>
|
|
|
|

|
|
|
|

|

|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|


|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleDebugger.cpp,v 1.1.2.33 2003/08/26 00:14:38 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <stddef.h>
#include <assert.h>
#include "expWinConsoleDebugger.hpp"
#include "expWinInjectorIPC.hpp"
#include <vdmdbg.h>
#pragma comment (lib, "vdmdbg.lib")

#ifdef _MSC_VER
#   pragma comment (lib, "imagehlp.lib")
#endif

#ifdef _M_IX86
    // Breakpoint opcode on i386
#   define BRK_OPCODE	    0xCC
    // Single step flag
#   define SINGLE_STEP_BIT  0x100
#else
#   error need opcodes for this hardware.
#endif



//  Constructor.
ConsoleDebugger::ConsoleDebugger (
	int _argc,
	char * const *_argv,
	CMclQueue<Message *> &_mQ
    )
    : argc(_argc), argv(_argv), ProcessList(0L), CursorKnown(FALSE),
    ConsoleOutputCP(0), ConsoleCP(0), mQ(_mQ), pStartAddress(0L),
    originalExeEntryPointOpcode(0), pInjectorStub(0), injectorIPC(0L),
    interacting(false), interactingConsole(0L)
{
    OSVERSIONINFO osvi;
    DWORD n, i;

    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&osvi);
    dwPlatformId = osvi.dwPlatformId;

    if (dwPlatformId == VER_PLATFORM_WIN32_NT) {
	pfnVirtualAllocEx = (PFNVIRTUALALLOCEX) GetProcAddress(
		GetModuleHandle("KERNEL32.DLL"),"VirtualAllocEx");
	pfnVirtualFreeEx = (PFNVIRTUALFREEEX) GetProcAddress(
		GetModuleHandle("KERNEL32.DLL"),"VirtualFreeEx");
    }

    n = GetEnvironmentVariable("Path", NULL, 0);
    n += GetEnvironmentVariable("_NT_SYMBOL_PATH", NULL, 0) + 1;
    n += GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", NULL, 0) + 1;
    n += GetEnvironmentVariable("SystemRoot", NULL, 0) + 1;

    SymbolPath = new char [n];

    i = GetEnvironmentVariable("Path", SymbolPath, n);
    SymbolPath[i++] = ';';
    i += GetEnvironmentVariable("_NT_SYMBOL_PATH", &SymbolPath[i], n-i);
    SymbolPath[i++] = ';';
    i += GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", &SymbolPath[i], n-i);
    SymbolPath[i++] = ';';
    i += GetEnvironmentVariable("SystemRoot", &SymbolPath[i], n-i);

    //  Until further notice, assume this.
    //
    ConsoleSize.X = 80;
    ConsoleSize.Y = 25;

    //  Until further notice, assume this, too.
    //
    CursorPosition.X = 0;
    CursorPosition.Y = 0;

    //  Set all our breakpoint info.  We have to do this the long way, here in
    //  the constructor, because we need to have the 'this' pointer already
    //  set because we refer to ourselves by needing the address to member
    //  functions.
    //

    // interesting ones I might want to add:
    // DuplicateConsoleHandle

    BreakArrayKernel32[0].funcName = "AllocConsole";
    BreakArrayKernel32[0].nargs = 0;
    BreakArrayKernel32[0].breakProc = OnAllocConsole;
    BreakArrayKernel32[0].dwFlags = BREAK_OUT;

    BreakArrayKernel32[1].funcName = "Beep";
    BreakArrayKernel32[1].nargs = 2;
    BreakArrayKernel32[1].breakProc = OnBeep;
    BreakArrayKernel32[1].dwFlags = BREAK_OUT|BREAK_IN;

    BreakArrayKernel32[2].funcName = "CreateConsoleScreenBuffer";
    BreakArrayKernel32[2].nargs = 5;
    BreakArrayKernel32[2].breakProc = OnCreateConsoleScreenBuffer;
    BreakArrayKernel32[2].dwFlags = BREAK_OUT;

    BreakArrayKernel32[3].funcName = "FillConsoleOutputAttribute";
    BreakArrayKernel32[3].nargs = 5;
    BreakArrayKernel32[3].breakProc = OnFillConsoleOutputAttribute;
    BreakArrayKernel32[3].dwFlags = BREAK_OUT;

    BreakArrayKernel32[4].funcName = "FillConsoleOutputCharacterA";
    BreakArrayKernel32[4].nargs = 5;
    BreakArrayKernel32[4].breakProc = OnFillConsoleOutputCharacterA;
    BreakArrayKernel32[4].dwFlags = BREAK_OUT;

    BreakArrayKernel32[5].funcName = "FillConsoleOutputCharacterW";
    BreakArrayKernel32[5].nargs = 5;
    BreakArrayKernel32[5].breakProc = OnFillConsoleOutputCharacterW;
    BreakArrayKernel32[5].dwFlags = BREAK_OUT;

    BreakArrayKernel32[6].funcName = "FreeConsole";
    BreakArrayKernel32[6].nargs = 0;
    BreakArrayKernel32[6].breakProc = OnFreeConsole;
    BreakArrayKernel32[6].dwFlags = BREAK_OUT;

    BreakArrayKernel32[7].funcName = "GetStdHandle";
    BreakArrayKernel32[7].nargs = 1;
    BreakArrayKernel32[7].breakProc = OnGetStdHandle;
    BreakArrayKernel32[7].dwFlags = BREAK_OUT;

    BreakArrayKernel32[8].funcName = "OpenConsoleW";
    BreakArrayKernel32[8].nargs = 4;
    BreakArrayKernel32[8].breakProc = OnOpenConsoleW;
    BreakArrayKernel32[8].dwFlags = BREAK_OUT;

    BreakArrayKernel32[9].funcName = "ScrollConsoleScreenBufferA";
    BreakArrayKernel32[9].nargs = 5;
    BreakArrayKernel32[9].breakProc = OnScrollConsoleScreenBuffer;
    BreakArrayKernel32[9].dwFlags = BREAK_OUT;

    BreakArrayKernel32[10].funcName = "ScrollConsoleScreenBufferW";
    BreakArrayKernel32[10].nargs = 5;
    BreakArrayKernel32[10].breakProc = OnScrollConsoleScreenBuffer;
    BreakArrayKernel32[10].dwFlags = BREAK_OUT;

    BreakArrayKernel32[11].funcName = "SetConsoleActiveScreenBuffer";
    BreakArrayKernel32[11].nargs = 1;
    BreakArrayKernel32[11].breakProc = OnSetConsoleActiveScreenBuffer;
    BreakArrayKernel32[11].dwFlags = BREAK_OUT;

    BreakArrayKernel32[12].funcName = "SetConsoleCP";
    BreakArrayKernel32[12].nargs = 1;
    BreakArrayKernel32[12].breakProc = OnSetConsoleCP;
    BreakArrayKernel32[12].dwFlags = BREAK_OUT;

    BreakArrayKernel32[13].funcName = "SetConsoleCursorInfo";
    BreakArrayKernel32[13].nargs = 2;
    BreakArrayKernel32[13].breakProc = OnSetConsoleCursorInfo;
    BreakArrayKernel32[13].dwFlags = BREAK_OUT;

    BreakArrayKernel32[14].funcName = "SetConsoleCursorPosition";
    BreakArrayKernel32[14].nargs = 2;
    BreakArrayKernel32[14].breakProc = OnSetConsoleCursorPosition;
    BreakArrayKernel32[14].dwFlags = BREAK_OUT;

    BreakArrayKernel32[15].funcName = "SetConsoleMode";
    BreakArrayKernel32[15].nargs = 2;
    BreakArrayKernel32[15].breakProc = OnSetConsoleMode;
    BreakArrayKernel32[15].dwFlags = BREAK_OUT;

    BreakArrayKernel32[16].funcName = "SetConsoleOutputCP";
    BreakArrayKernel32[16].nargs = 1;
    BreakArrayKernel32[16].breakProc = OnSetConsoleOutputCP;
    BreakArrayKernel32[16].dwFlags = BREAK_OUT;

    BreakArrayKernel32[17].funcName = "SetConsoleTextAttribute";
    BreakArrayKernel32[17].nargs = 2;
    BreakArrayKernel32[17].breakProc = OnSetConsoleTextAttribute;
    BreakArrayKernel32[17].dwFlags = BREAK_OUT;

    BreakArrayKernel32[18].funcName = "SetConsoleWindowInfo";
    BreakArrayKernel32[18].nargs = 3;
    BreakArrayKernel32[18].breakProc = OnSetConsoleWindowInfo;
    BreakArrayKernel32[18].dwFlags = BREAK_OUT;

    BreakArrayKernel32[19].funcName = "WriteConsoleA";
    BreakArrayKernel32[19].nargs = 5;
    BreakArrayKernel32[19].breakProc = OnWriteConsoleA;
    BreakArrayKernel32[19].dwFlags = BREAK_OUT;

    BreakArrayKernel32[20].funcName = "WriteConsoleW";
    BreakArrayKernel32[20].nargs = 5;
    BreakArrayKernel32[20].breakProc = OnWriteConsoleW;
    BreakArrayKernel32[20].dwFlags = BREAK_OUT;

    BreakArrayKernel32[21].funcName = "WriteConsoleOutputA";
    BreakArrayKernel32[21].nargs = 5;
    BreakArrayKernel32[21].breakProc = OnWriteConsoleOutputA;
    BreakArrayKernel32[21].dwFlags = BREAK_OUT;

    BreakArrayKernel32[22].funcName = "WriteConsoleOutputW";
    BreakArrayKernel32[22].nargs = 5;
    BreakArrayKernel32[22].breakProc = OnWriteConsoleOutputW;
    BreakArrayKernel32[22].dwFlags = BREAK_OUT;

    BreakArrayKernel32[23].funcName = "WriteConsoleOutputCharacterA";
    BreakArrayKernel32[23].nargs = 5;
    BreakArrayKernel32[23].breakProc = OnWriteConsoleOutputCharacterA;
    BreakArrayKernel32[23].dwFlags = BREAK_OUT;

    BreakArrayKernel32[24].funcName = "WriteConsoleOutputCharacterW";
    BreakArrayKernel32[24].nargs = 5;
    BreakArrayKernel32[24].breakProc = OnWriteConsoleOutputCharacterW;
    BreakArrayKernel32[24].dwFlags = BREAK_OUT;

    BreakArrayKernel32[25].funcName = "WriteFile";
    BreakArrayKernel32[25].nargs = 5;
    BreakArrayKernel32[25].breakProc = OnWriteFile;
    BreakArrayKernel32[25].dwFlags = BREAK_OUT;

    BreakArrayKernel32[26].funcName = 0L;
    BreakArrayKernel32[26].nargs = 0;
    BreakArrayKernel32[26].breakProc = 0L;
    BreakArrayKernel32[26].dwFlags = 0;

    BreakArrayUser32[0].funcName = "IsWindowVisible";
    BreakArrayUser32[0].nargs = 1;
    BreakArrayUser32[0].breakProc = OnIsWindowVisible;
    BreakArrayUser32[0].dwFlags = BREAK_OUT;

    BreakArrayUser32[1].funcName = 0L;
174
175
176
177
178
179
180
181


182
183
184
185
186
187
188
189
190
191
192
193
194
195


196


197
198
199
200
201
202
203
204
205
206
207
208


209


210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400


401
402
403
404
405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420


421
422
423
424
425
426
427
428
429
430

431
432
433
434


435


436
437
438
439
440

441
442
443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488


489


490
491
492


493
494

495
496
497

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

580
581

582

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

610





611



















































612
613


614
615
616

617

618

619




620











621




622
623




624
625
626



627
628




629



630
631



632
633
634
635
636
637
638
639


















































































640
641
642
643
644
645
646

    hMasterConsole = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
}

ConsoleDebugger::~ConsoleDebugger()
{
    if (SymbolPath) delete [] SymbolPath;


}

unsigned
ConsoleDebugger::ThreadHandlerProc(void)
{
    Process *proc;
    DWORD ok;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    char *cmdline;

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);


    si.wShowWindow = SW_SHOWDEFAULT;



    cmdline = ArgMaker::BuildCommandLine(argc, argv);

    // Make sure the master does not ignore Ctrl-C
    SetConsoleCtrlHandler(0L, FALSE);

    ok = CreateProcess (
	    0L,		// Module name (not needed).
	    cmdline,	// Command line.
	    0L,		// Process handle will not be inheritable.
	    0L,		// Thread handle will not be inheritable.
	    FALSE,	// No handle inheritance.


	    DEBUG_PROCESS|CREATE_NEW_CONSOLE|CREATE_DEFAULT_ERROR_MODE,


			// Creation flags.
	    0L,		// Use parent's environment block.
	    0L,		// Use parent's starting directory.
	    &si,	// Pointer to STARTUPINFO structure.
	    &pi);	// Pointer to PROCESS_INFORMATION structure.

    delete [] cmdline;

    if (!ok) {
	//arg->lastError = GetLastError();
    }


    WaitForInputIdle(pi.hProcess, 5000);
    CloseHandle(pi.hThread);

    // Make sure we now ignore Ctrl-C
    SetConsoleCtrlHandler(0L, TRUE);

    proc = ProcessNew();
    //CloseHandle(pi.hProcess);
    proc->hProcess = pi.hProcess;
    proc->pid = pi.dwProcessId;

    CommonDebugger();
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ProcessNew --
 *
 *	Allocates a new structure for debugging a process and
 *	initializes it.
 *
 * Results:
 *	A new structure
 *
 * Side Effects:
 *	Memory is allocated, an event is created.
 *
 *----------------------------------------------------------------------
 */

ConsoleDebugger::Process *
ConsoleDebugger::ProcessNew(void)
{
    Process *proc;
    proc = new Process;
    proc->threadList = 0L;
    proc->threadCount = 0;
    proc->brkptList = 0L;
    proc->lastBrkpt = 0L;
    proc->offset = 0;
    proc->nBreakCount = 0;
    proc->consoleHandlesMax = 0;
    proc->isConsoleApp = FALSE;
    proc->isShell = FALSE;
    proc->hProcess = 0L;
    proc->pSubprocessMemory = 0;
    proc->pSubprocessBuffer = 0;
    proc->pMemoryCacheBase = 0;
    proc->exeModule = 0L;
    proc->nextPtr = ProcessList;
    ProcessList = proc;
    return proc;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ProcessFree --
 *
 *	Frees all allocated memory for a process and closes any
 *	open handles
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::ProcessFree(Process *proc)
{
    ThreadInfo *tcurr, *tnext;
    Breakpoint *bcurr, *bnext;
    Process *pcurr, *pprev;

    for (tcurr = proc->threadList; tcurr != 0L; tcurr = tnext) {
	tnext = tcurr->nextPtr;
	proc->threadCount--;
	CloseHandle(tcurr->hThread);
	delete tcurr;
    }
    for (bcurr = proc->brkptList; bcurr != 0L; bcurr = bnext) {
	bnext = bcurr->nextPtr;
	delete bcurr;
    }
    for (pprev = 0L, pcurr = ProcessList; pcurr != 0L;
	 pcurr = pcurr->nextPtr)
    {
	if (pcurr == proc) {
	    if (pprev == 0L) {
		ProcessList = pcurr->nextPtr;
	    } else {
		pprev->nextPtr = pcurr->nextPtr;
	    }
	    break;
	}
    }
    CloseHandle(proc->hProcess);

    delete proc;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::CommonDebugger --
 *
 *	This is the function that is the debugger for all slave processes
 *
 * Results:
 *	None.  This thread exits with ExitThread() when the subprocess dies.
 *
 * Side Effects:
 *	Adds the process to the things being waited for by
 *	WaitForMultipleObjects
 *
 *----------------------------------------------------------------------
 */
void

ConsoleDebugger::CommonDebugger()
{
    DEBUG_EVENT debEvent;	// debugging event info.
    DWORD dwContinueStatus;	// exception continuation.
    DWORD err;
    Process *proc;
    DWORD n, i;

    n = GetEnvironmentVariable("Path", 0L, 0);
    n += GetEnvironmentVariable("_NT_SYMBOL_PATH", 0L, 0) + 1;
    n += GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", 0L, 0) + 1;
    n += GetEnvironmentVariable("SystemRoot", 0L, 0) + 1;

    SymbolPath = new char [n];

    i = GetEnvironmentVariable("Path", SymbolPath, n);
    SymbolPath[i++] = ';';
    i += GetEnvironmentVariable("_NT_SYMBOL_PATH", &SymbolPath[i], n-i);
    SymbolPath[i++] = ';';
    i += GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", &SymbolPath[i], n-i);
    SymbolPath[i++] = ';';
    i += GetEnvironmentVariable("SystemRoot", &SymbolPath[i], n-i);

    for(;;) {
	dwContinueStatus = DBG_CONTINUE;

	// Wait for a debugging event to occur. The second parameter
	// indicates that the function does not return until
	// a debugging event occurs.
	//
	if (WaitForDebugEvent(&debEvent, INFINITE) == FALSE) {
	    err = GetLastError();
	    *((char *) 0L) = 0;   // cause an exception.
	}

	// Find the process that is responsible for this event.
	//
	for (proc = ProcessList; proc; proc = proc->nextPtr) {
	    if (proc->pid == debEvent.dwProcessId) {
		break;
	    }
	}

	if (!proc && debEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
	    char buf[50];
	    wsprintf(buf, "%d/%d (%d)", 
		    debEvent.dwProcessId, debEvent.dwThreadId,
		    debEvent.dwDebugEventCode);
	    EXP_LOG1(MSG_DT_UNEXPECTEDDBGEVENT, buf);
	    if (debEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
		char buf[50];
		wsprintf(buf, "0x%08x", debEvent.u.Exception.ExceptionRecord.ExceptionCode);
		EXP_LOG1(MSG_DT_EXCEPTIONDBGEVENT, buf);
		dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
	    }
	    goto skip;
	}



	// Process the debugging event code.
	//
	switch (debEvent.dwDebugEventCode) {
	case EXCEPTION_DEBUG_EVENT:
	    // Process the exception code. When handling
	    // exceptions, remember to set the continuation
	    // status parameter (dwContinueStatus). This value
	    // is used by the ContinueDebugEvent function.
	    //
	    switch (debEvent.u.Exception.ExceptionRecord.ExceptionCode) {
	    case EXCEPTION_BREAKPOINT:
	    {

		if (proc->nBreakCount < 1000) {
		    proc->nBreakCount++;
		}
		if (proc->nBreakCount == 1) {
		    OnXFirstBreakpoint(proc, &debEvent);
		} else if (proc->nBreakCount == 2) {
		    OnXSecondBreakpoint(proc, &debEvent);
		} else {


		    OnXBreakpoint(proc, &debEvent);
		}
		break;
	    }

	    case EXCEPTION_SINGLE_STEP:
		OnXSingleStep(proc, &debEvent);
		break;

	    case DBG_CONTROL_C:

		dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
		break;

	    case DBG_CONTROL_BREAK:


		dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;


		break;

	    case EXCEPTION_DATATYPE_MISALIGNMENT:
	    case EXCEPTION_ACCESS_VIOLATION:
	    default:

		// An exception was hit and it was not handled by the program.
		// Now it is time to get a backtrace.
		if (! debEvent.u.Exception.dwFirstChance) {

		    OnXSecondChanceException(proc, &debEvent);
		}
		dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
	    }
	    break;

	case CREATE_THREAD_DEBUG_EVENT:
	    OnXCreateThread(proc, &debEvent);
	    break;

	case CREATE_PROCESS_DEBUG_EVENT:
	    OnXCreateProcess(proc, &debEvent);
	    break;

	case EXIT_THREAD_DEBUG_EVENT:
	    OnXDeleteThread(proc, &debEvent);
	    break;

	case EXIT_PROCESS_DEBUG_EVENT:
	    // XXX: This is really screwed up, but we get breakpoints
	    // for processes that are already dead.  So we cannot remove
	    // and cleanup a process until some later (How much later?)
	    // point.  This really, really sucks....
	    //
#if 0 /* This gets closed in WaitQueueThread */
	    CloseHandle(proc->hProcess);
#endif
	    err = debEvent.u.ExitProcess.dwExitCode;
	    ProcessFree(proc);
	    if (ProcessList == 0L) {
		// When the last process exits, we exit.
		NotifyDone();
		return;
	    }
	    break;

	case LOAD_DLL_DEBUG_EVENT:
	    OnXLoadDll(proc, &debEvent);
	    break;

	case UNLOAD_DLL_DEBUG_EVENT:
	    OnXUnloadDll(proc, &debEvent);
	    break;

	case OUTPUT_DEBUG_STRING_EVENT:


	    // Display the output debugging string.


	    break;
	}



    skip:
	// Resume executing the thread that reported the debugging event.

	ContinueDebugEvent(debEvent.dwProcessId, debEvent.dwThreadId,
		dwContinueStatus);
    }

}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXFirstBreakpoint --
 *
 *	This routine is called when a EXCEPTION_DEBUG_EVENT with
 *	an exception code of EXCEPTION_BREAKPOINT, and it is the
 *	first one to occur in the program.  This happens when the
 *	process finally gets loaded into memory and is about to
 *	start.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

static CONTEXT FirstContext;
static UCHAR   FirstPage[PAGESIZE];
static HANDLE  FirstThread;
#include <pshpack1.h>
typedef struct _InjectCode {
    UCHAR instPush1;
    DWORD argMemProtect;
    UCHAR instPush2;
    DWORD argMemType;
    UCHAR instPush3;
    DWORD argMemSize;
    UCHAR instPush4;
    DWORD argMemAddr;
    UCHAR instCall;
    DWORD argCallAddr;
    DWORD instIntr;
} InjectCode;
#include <poppack.h>

void
ConsoleDebugger::OnXFirstBreakpoint(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    DWORD base;
    ThreadInfo *tinfo;

    for (tinfo = proc->threadList; tinfo != 0L; tinfo = tinfo->nextPtr) {
	if (pDebEvent->dwThreadId == tinfo->dwThreadId) {
	    break;
	}
    }

    // Set up the memory that will serve as the place for our
    // intercepted function return points.

    {
	InjectCode code;
	DWORD addr;

	FirstThread = tinfo->hThread;
	FirstContext.ContextFlags = CONTEXT_FULL;
	GetThreadContext(FirstThread, &FirstContext);

	if (proc->funcTable.Find("VirtualAlloc",
		reinterpret_cast<PVOID *>(&addr)) != TCL_OK)
	{
	    proc->nBreakCount++;	// Don't stop at second breakpoint
	    EXP_LOG0(MSG_DT_NOVIRT);
	    return;
	}

	code.instPush1     = 0x68;
	code.argMemProtect = PAGE_EXECUTE_READWRITE;
	code.instPush2     = 0x68;
	code.argMemType    = MEM_COMMIT;
	code.instPush3     = 0x68;
	code.argMemSize    = 2048;
	code.instPush4     = 0x68;
	code.argMemAddr    = 0;
	code.instCall      = 0xe8;
	code.argCallAddr   = addr - FirstContext.Eip - offsetof(InjectCode, instCall) - 5;
	code.instIntr      = 0xCC;

	base = FirstContext.Eip;

	if (!ReadSubprocessMemory(proc, (PVOID) base, FirstPage, sizeof(InjectCode))) {
	    EXP_LOG0(MSG_DT_CANTREADSPMEM);

	}

	if (!WriteSubprocessMemory(proc, (PVOID) base, &code, sizeof(InjectCode))) {
	    EXP_LOG0(MSG_DT_CANTWRITESPMEM);
	}
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXSecondBreakpoint --
 *
 *	This routine is called when the second breakpoint is hit.
 *	The second breakpoint is at the end of our call to GlobalAlloc().
 *	Save the returned pointer from GlobalAlloc, then restore the
 *	first page of memory and put everything back the way it was.
 *	Finally, we can start.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXSecondBreakpoint(Process *proc, LPDEBUG_EVENT pDebEvent)
{

    CONTEXT context;





    BYTE retbuf[2048];



















































    DWORD base;
    LPEXCEPTION_DEBUG_INFO exceptInfo;


    BreakInfo *info;
    int i;


    exceptInfo = &pDebEvent->u.Exception;



    context.ContextFlags = CONTEXT_FULL;




    GetThreadContext(FirstThread, &context);











    proc->pSubprocessMemory = context.Eax;





    memset(retbuf, 0xcc, sizeof(retbuf));	// All breakpoints




    WriteSubprocessMemory(proc, (PVOID) proc->pSubprocessMemory,
			  retbuf, sizeof(retbuf));




    base = FirstContext.Eip;
    if (!WriteSubprocessMemory(proc, (PVOID) base, FirstPage, sizeof(InjectCode))) {




	EXP_LOG0(MSG_DT_CANTWRITESPMEM);



    }
    SetThreadContext(FirstThread, &FirstContext);




    // Set all breakpoints
    //
    for (i = 0; BreakPoints[i].dllName; i++) {
	for (info = BreakPoints[i].breakInfo; info->funcName; info++) {
	    SetBreakpoint(proc, info);
	}
    }


















































































}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXSingleStep --
 *







|
>
>





<
|







>
>
|
>
>



<
<
<
|





>
>
|
>
>






<
<

|

>



<
<
<
<
<
|
<
<

|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















<
>




<

<
|
<
<
<
<

<
|
<
<
<
<
<
<
<
<
<
|

|
<
<
|
|
|
<
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

>
>
|
|
|
|
<
<
<
<
<
|
|
|
>
|
<
<
|
|
|
|
|
>
>
|
|
|
|

|
|
|

|
>
|
|

|
>
>
|
>
>
|

<
<
|
>

|
<
>
|
|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|
|
<

<
<
<
|
<
<
<
<
<
|
|

|
|
|

|
|
|

|
>
>
|
>
>
|
|

>
>
|
|
>
|
|
<
>



















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




<








<
<
|
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
>
|
<
>
|
>
|
<
|
<









|
<
|
|










>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
|


>
|
>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>

|
>
>
>
>
|
|

>
>
>
|
|
>
>
>
>
|
>
>
>
|
<
>
>
>

|


|
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311


312
313
314
315
316
317
318





319


320
321


322






































323
















































324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346

347

348




349

350









351
352
353


354
355
356

357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387





388
389
390
391
392


393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421


422
423
424
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

449



450





451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497


















498
499
500
501

502
503
504
505
506
507
508
509


510



511



512



513



514











515

516
517

518
519
520
521

522

523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759

    hMasterConsole = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
}

ConsoleDebugger::~ConsoleDebugger()
{
    delete [] SymbolPath;
    if (injectorIPC) delete injectorIPC;
    CloseHandle(hMasterConsole);
}

unsigned
ConsoleDebugger::ThreadHandlerProc(void)
{

    DWORD ok, exitcode;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    char *cmdline;

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwXCountChars = 80;
    si.dwYCountChars = 25;
    si.wShowWindow = SW_SHOWNOACTIVATE;
    si.dwFlags = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW |
	STARTF_USECOUNTCHARS;

    cmdline = ArgMaker::BuildCommandLine(argc, argv);




    ok = CreateProcess(
	    0L,		// Module name (not needed).
	    cmdline,	// Command line.
	    0L,		// Process handle will not be inheritable.
	    0L,		// Thread handle will not be inheritable.
	    FALSE,	// No handle inheritance.
	    DEBUG_PROCESS |
	    CREATE_NEW_CONSOLE |
	    CREATE_DEFAULT_ERROR_MODE |
	    CREATE_SEPARATE_WOW_VDM |
	    0,
			// Creation flags.
	    0L,		// Use parent's environment block.
	    0L,		// Use parent's starting directory.
	    &si,	// Pointer to STARTUPINFO structure.
	    &pi);	// Pointer to PROCESS_INFORMATION structure.



    if (!ok) {
	EXP_LOG2(MSG_DT_BADDEBUGGEE, cmdline, GetSysMsg(GetLastError()));
    }
    delete [] cmdline;

    WaitForInputIdle(pi.hProcess, 5000);
    CloseHandle(pi.hThread);





    CloseHandle(pi.hProcess);



    exitcode = CommonDebugger();


    NotifyDone();






































    return exitcode;
















































}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::CommonDebugger --
 *
 *	This is the function that is the debugger for all slave processes
 *
 * Results:
 *	None.  This thread exits with ExitThread() when the subprocess dies.
 *
 * Side Effects:
 *	Adds the process to the things being waited for by
 *	WaitForMultipleObjects
 *
 *----------------------------------------------------------------------
 */

DWORD
ConsoleDebugger::CommonDebugger()
{
    DEBUG_EVENT debEvent;	// debugging event info.
    DWORD dwContinueStatus;	// exception continuation.

    Process *proc;

    int breakCount = 0;






again:









    dwContinueStatus = DBG_CONTINUE;

    // Wait (forever) for a debugging event to occur.


    //
    if (WaitForDebugEvent(&debEvent, INFINITE) == FALSE) {
	return GetLastError();

    }

    // Find the process that is responsible for this event.
    //
    for (proc = ProcessList; proc; proc = proc->nextPtr) {
	if (proc->pid == debEvent.dwProcessId) {
	    break;
	}
    }

    if (!proc && debEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) {
/*	char buf[50];
	wsprintf(buf, "%d/%d (%d)", 
		debEvent.dwProcessId, debEvent.dwThreadId,
		debEvent.dwDebugEventCode);
	EXP_LOG1(MSG_DT_UNEXPECTEDDBGEVENT, buf);*/
	if (debEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
	    /*char buf[50];
	    wsprintf(buf, "0x%08x", debEvent.u.Exception.ExceptionRecord.ExceptionCode);
	    EXP_LOG1(MSG_DT_EXCEPTIONDBGEVENT, buf);*/
	    dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
	}
	goto skip;
    }

    bpCritSec.Enter();

    // Process the debugging event code.
    //
    switch (debEvent.dwDebugEventCode) {
    case EXCEPTION_DEBUG_EVENT:





	switch (debEvent.u.Exception.ExceptionRecord.ExceptionCode) {
	case EXCEPTION_BREAKPOINT:
	{
	    // only the first three get special attention.
	    switch (breakCount < 4 ? ++breakCount : 4) {


	    case 1:
		OnXFirstBreakpoint(proc, &debEvent); break;
	    case 2:
		OnXSecondBreakpoint(proc, &debEvent); break;
	    case 3:
		OnXThirdBreakpoint(proc, &debEvent); break;
	    case 4:
		OnXBreakpoint(proc, &debEvent);
	    }
	    break;
	}

	case EXCEPTION_SINGLE_STEP:
	    OnXSingleStep(proc, &debEvent);
	    break;

	case DBG_CONTROL_C:
	case DBG_CONTROL_BREAK:
	    dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
	    break;

	case EXCEPTION_NONCONTINUABLE_EXCEPTION:
	    // we die here.
	    return EXCEPTION_NONCONTINUABLE_EXCEPTION;

	case STATUS_VDM_EVENT:
	    OnXVDMException(proc, &debEvent);
	    break;



	default:
	    if (!debEvent.u.Exception.dwFirstChance) {
		// An exception was hit and it was not handled by the program.
		// Now it is time to get a backtrace before it's death.

		//
		OnXSecondChanceException(proc, &debEvent);
	    }
	    dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
	}
	break;

    case CREATE_THREAD_DEBUG_EVENT:
	OnXCreateThread(proc, &debEvent);
	break;

    case CREATE_PROCESS_DEBUG_EVENT:
	OnXCreateProcess(proc, &debEvent);
	break;

    case EXIT_THREAD_DEBUG_EVENT:
	OnXDeleteThread(proc, &debEvent);
	break;

    case EXIT_PROCESS_DEBUG_EVENT:
	ProcessFree(proc);
	if (ProcessList == 0L) {
	    // When the last process exits, we exit.

	    //



	    return debEvent.u.ExitProcess.dwExitCode;





	}
	break;

    case LOAD_DLL_DEBUG_EVENT:
	OnXLoadDll(proc, &debEvent);
	break;

    case UNLOAD_DLL_DEBUG_EVENT:
	OnXUnloadDll(proc, &debEvent);
	break;

    case OUTPUT_DEBUG_STRING_EVENT:
	OnXDebugString(proc, &debEvent);
	break;

    case RIP_EVENT:
	OnXRip(proc, &debEvent);
	break;
    }

    bpCritSec.Leave();

skip:
    // Resume executing the thread that reported the debugging event.
    //
    ContinueDebugEvent(debEvent.dwProcessId, debEvent.dwThreadId,
	    dwContinueStatus);

    goto again;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXFirstBreakpoint --
 *
 *	This routine is called when a EXCEPTION_DEBUG_EVENT with
 *	an exception code of EXCEPTION_BREAKPOINT, and it is the
 *	first one to occur in the program.  This happens when the
 *	process finally gets loaded into memory and is about to
 *	start.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */




















void
ConsoleDebugger::OnXFirstBreakpoint(Process *proc, LPDEBUG_EVENT pDebEvent)
{

    ThreadInfo *tinfo;

    for (tinfo = proc->threadList; tinfo != 0L; tinfo = tinfo->nextPtr) {
	if (pDebEvent->dwThreadId == tinfo->dwThreadId) {
	    break;
	}
    }



    // Install our entry breakpoint.  We can't run the injector Stub now



    // as the process heap hasn't been created.  (it was some memory related



    // error and I don't know exactly why, but moving the stub run later



    // solved it).  It seems that the first breakpoint naturally fired is



    // much too early in the creation of the initial process for much of











    // anything to be ready.

    //
    ReadSubprocessMemory(proc, pStartAddress,

	    &originalExeEntryPointOpcode, sizeof(BYTE));

    BYTE bpOpcode = BRK_OPCODE;
    WriteSubprocessMemory(proc, pStartAddress, &bpOpcode, sizeof(BYTE));



    return;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXSecondBreakpoint --
 *
 *	This routine is called when the second breakpoint is hit.
 *	The processes' entry-point is getting called.  We intercept this

 *	and make our injector.dll load first before the entry-point is
 *	called.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXSecondBreakpoint(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    ThreadInfo *tinfo;

    for (tinfo = proc->threadList; tinfo != 0L; tinfo = tinfo->nextPtr) {
	if (pDebEvent->dwThreadId == tinfo->dwThreadId) {
	    break;
	}
    }

    // Put the first opcode at the entry point back in place.
    WriteSubprocessMemory(proc, pStartAddress,
	    &originalExeEntryPointOpcode, sizeof(BYTE));

    //  Make some memory for our stub that we place into the processes' address
    //  space.  This stub (or set of opcodes) calls LoadLibrary() to bring in our
    //  injector dll that acts as the receiver for "injecting" console events.
    //
    MakeSubprocessMemory(proc, sizeof(LOADLIBRARY_STUB), &pInjectorStub,
	    PAGE_EXECUTE_READWRITE);
    injectorStub.operand_PUSH_value = (DWORD) pInjectorStub +
	    offsetof(LOADLIBRARY_STUB, data_DllName);
    injectorStub.operand_MOV_EAX = (DWORD) GetProcAddress(GetModuleHandle(
	    "KERNEL32.DLL"), "LoadLibraryA");
    WriteSubprocessMemory(proc, pInjectorStub, &injectorStub,
	    sizeof(LOADLIBRARY_STUB));
    FlushInstructionCache(proc->hProcess, pInjectorStub, sizeof(LOADLIBRARY_STUB));


    //  Save the instruction pointer so we can restore it later.
    //
    preStubContext.ContextFlags = CONTEXT_FULL;
    GetThreadContext(tinfo->hThread, &preStubContext);

    //  Set instruction pointer to run the Stub instead of continuing
    //  from where we are (which is the app's entry point).
    //
    CONTEXT stubContext = preStubContext;
    stubContext.Eip = (DWORD) pInjectorStub;
    SetThreadContext(tinfo->hThread, &stubContext);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXThirdBreakpoint --
 *
 *	This routine is called when the third breakpoint is hit and
 *	our stub has run and our injector is loaded.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXThirdBreakpoint(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    ThreadInfo *tinfo;
    CHAR boxName[50];
    DWORD err;

#   define RETBUF_SIZE 2048
    BYTE retbuf[RETBUF_SIZE];
    BreakInfo *binfo;
    int i;

    for (tinfo = proc->threadList; tinfo != 0L; tinfo = tinfo->nextPtr) {
	if (pDebEvent->dwThreadId == tinfo->dwThreadId) {
	    break;
	}
    }

    // Create the IPC connection to our loaded injector.dll
    //
    wsprintf(boxName, "ExpectInjector_pid%d", proc->pid);
    injectorIPC = new CMclMailbox(IPC_NUMSLOTS, IPC_SLOTSIZE, boxName);

    // Check status.
    err = injectorIPC->Status();
    if (err != NO_ERROR && err != ERROR_ALREADY_EXISTS) {
	char *error = new char [512];
	strcpy(error, "IPC connection to injector.dll could not be made: ");
	strcat(error, GetSysMsg(err));
	strcat(error, "\n");
	WriteMasterError(error, strlen(error));
	delete injectorIPC;
	injectorIPC = 0L;
    }

    // Set our thread to run the entry point, now, starting the
    // application once we return from this breakpoint.
    preStubContext.Eip -= sizeof(BYTE);
    SetThreadContext(tinfo->hThread, &preStubContext);


    // We should now remove the memory allocated in the sub process for
    // our injector stub.  The dll is already loaded and there's no sense
    // hogging a virtual memory page.
    //
    RemoveSubprocessMemory(proc, pInjectorStub);


    /////////////////////////////////////////////////////////////////////
    // Now create our breakpoints on all calls to the OS console API.
    /////////////////////////////////////////////////////////////////////


    // Set up the memory that will serve as the place for our
    // intercepted function return points.
    //
    MakeSubprocessMemory(proc, RETBUF_SIZE, &(proc->pSubprocessMemory));

    // Fill the buffer with all breakpoint opcodes.
    //
    memset(retbuf, BRK_OPCODE, RETBUF_SIZE);


    // Write it out to our buffer space in the other process.
    //
    WriteSubprocessMemory(proc, proc->pSubprocessMemory, retbuf, RETBUF_SIZE);

    // Set all Console API breakpoints.
    //
    for (i = 0; BreakPoints[i].dllName; i++) {
	for (binfo = BreakPoints[i].breakInfo; binfo->funcName; binfo++) {
	    SetBreakpoint(proc, binfo);
	}
    }

#   undef RETBUF_SIZE
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::SetBreakpoint --
 *
 *	Inserts a single breakpoint
 *
 * Results:
 *	TRUE if successful, FALSE if unsuccessful.
 *
 *----------------------------------------------------------------------
 */

BOOL
ConsoleDebugger::SetBreakpoint(Process *process, BreakInfo *info)
{
    PVOID funcPtr;

    if (process->funcTable.Find(info->funcName, &funcPtr) == TCL_ERROR)
    {
//	PCHAR buffer;
//	DWORD len;
//
//	buffer = new CHAR [128];
//	len = wsprintf(buffer, "Unable to set breakpoint at %s", info->funcName);
//	WriteMasterError(buffer, len);
	return FALSE;
    }

    // Set a breakpoint at the function start in the subprocess and
    // save the original code at the function start.
    //
    return SetBreakpointAtAddr(process, info, funcPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::SetBreakpointAtAddr --
 *
 *	Inserts a single breakpoint at the given address
 *
 * Results:
 *	The new BreakPoint instance.
 *
 *----------------------------------------------------------------------
 */

BOOL
ConsoleDebugger::SetBreakpointAtAddr(Process *proc, BreakInfo *info, PVOID funcPtr)
{
    Breakpoint *bpt, *lastBpt;
    BYTE code;
    BOOL ok;

    bpt = new Breakpoint;
    bpt->codePtr = funcPtr;
    bpt->codeReturnPtr = (PVOID) (proc->offset + (DWORD) proc->pSubprocessMemory);
    bpt->breakInfo = info;
    proc->offset += 2;
    bpt->nextPtr = lastBpt = proc->brkptList;
    proc->brkptList = bpt;

    if ((ok = ReadSubprocessMemory(proc, funcPtr, &bpt->code, sizeof(BYTE)))
	    == TRUE) {
	code = BRK_OPCODE;
	ok = WriteSubprocessMemory(proc, funcPtr, &code, sizeof(BYTE));
    }

    if (!ok) {
	// unsplice it.
	proc->brkptList = lastBpt;
	delete bpt;
	bpt = 0L;
    }

    return ok;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXSingleStep --
 *
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
void
ConsoleDebugger::OnXSingleStep(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    BYTE code;

    // Now, we need to restore the breakpoint that we had removed.
    //
    code = 0xcc;
    WriteSubprocessMemory(proc, proc->lastBrkpt->codePtr, &code, sizeof(BYTE));
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXSecondChanceException --







|







769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
void
ConsoleDebugger::OnXSingleStep(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    BYTE code;

    // Now, we need to restore the breakpoint that we had removed.
    //
    code = BRK_OPCODE;
    WriteSubprocessMemory(proc, proc->lastBrkpt->codePtr, &code, sizeof(BYTE));
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXSecondChanceException --
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704

705
706
707
708
709
710
711
712
713

714
715



716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

751
752


753


754
755
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772








773



774
775
776
777
778
779






780
781
782
783
784
785
786


787
788
789
790
791
792
793
794
795
796
797



798
799
800
801
802
803
804
805
806


807
808
809
810


811
812
813
814

































815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
    CONTEXT context;
    ThreadInfo *tinfo;
    Module *modPtr;
    DWORD displacement;
    BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512];
    PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
    char *s;

    if (!ShowExceptionBacktraces) {
	return;
    }

    for (tinfo = proc->threadList; tinfo != 0L; tinfo = tinfo->nextPtr) {
	if (pDebEvent->dwThreadId == tinfo->dwThreadId) {
	    break;
	}
    }
    assert(tinfo != 0L);

    context.ContextFlags = CONTEXT_FULL;
    GetThreadContext(tinfo->hThread, &context);


    // XXX: From what I can tell, SymInitialize is broken on Windows NT 4.0
    // if you try to have it iterate the modules in a process.  It always
    // returns an object mismatch error.  Instead, initialize without iterating
    // the modules.  Contrary to what MSDN documentation says,
    // Microsoft debuggers do not exclusively use the imagehlp API.  In
    // fact, the only thing VC 5.0 uses is the StackWalk function.
    // Windbg uses a few more functions, but it doesn't use SymInitialize.
    // We will then do the hard work of finding all the
    // modules and doing the right thing.

    //
    if (! SymInitialize(proc->hProcess, SymbolPath, FALSE)){



	fprintf(stderr, "Unable to get backtrace (Debug 1): 0x%08x\n",
	    GetLastError());

	return;
    }

#ifdef _M_IX86
    memset(&frame, 0, sizeof(frame));
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrPC.Segment = 0;
    frame.AddrPC.Offset = context.Eip;

    frame.AddrReturn.Mode = AddrModeFlat;
    frame.AddrReturn.Segment = 0;
    frame.AddrReturn.Offset = context.Ebp; // I think this is correct

    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrFrame.Segment = 0;
    frame.AddrFrame.Offset = context.Ebp;

    frame.AddrStack.Mode = AddrModeFlat;
    frame.AddrStack.Segment = 0;
    frame.AddrStack.Offset = context.Esp;

    frame.FuncTableEntry = 0L;
    frame.Params[0] = context.Eax;
    frame.Params[1] = context.Ecx;
    frame.Params[2] = context.Edx;
    frame.Params[3] = context.Ebx;
    frame.Far = FALSE;
    frame.Virtual = FALSE;
    frame.Reserved[0] = 0;
    frame.Reserved[1] = 0;
    frame.Reserved[2] = 0;
    /* frame.KdHelp.* is not set */


    //  Iterate through the loaded modules and load symbols for each one.
    //


    proc->moduleTable.Top(&modPtr);


    do {
	if (! modPtr->loaded) {
	    modPtr->dbgInfo = MapDebugInformation(modPtr->hFile, 0L,
		SymbolPath, (DWORD)modPtr->baseAddr);

	    SymLoadModule(proc->hProcess, modPtr->hFile,
		0L, 0L, (DWORD) modPtr->baseAddr, 0);
	    modPtr->loaded = TRUE;
	}
    } while (proc->moduleTable.Next(&modPtr) != TCL_ERROR);



    if (proc->exeModule && proc->exeModule->dbgInfo && 
	proc->exeModule->dbgInfo->ImageFileName) {
	s = proc->exeModule->dbgInfo->ImageFileName;
    } else {
	s = "";
    }
//    fprintf(stderr, "Backtrace for %s\n", s);








//    fprintf(stderr, "-------------------------------------\n");



//    EXP_LOG("Backtrace for %s", s);
    while (1) {
        pSymbol->SizeOfStruct = sizeof(symbolBuffer);
        pSymbol->MaxNameLength = 512;

	b = StackWalk(IMAGE_FILE_MACHINE_I386, proc->hProcess,






	    tinfo->hThread, &frame, &context, 0L,
	    SymFunctionTableAccess, SymGetModuleBase,
	    0L);

	if (b == FALSE || frame.AddrPC.Offset == 0) {
	    break;
	}


	    
        if (SymGetSymFromAddr(proc->hProcess, frame.AddrPC.Offset,
	    &displacement, pSymbol) )
        {
	    DWORD base;
	    char buf[1024];

	    base = SymGetModuleBase(proc->hProcess, frame.AddrPC.Offset);
	    proc->moduleTable.Find(reinterpret_cast<PVOID>(base), &modPtr);
	    if (modPtr->dbgInfo && modPtr->dbgInfo->ImageFileName) {
		s = modPtr->dbgInfo->ImageFileName;



	    } else {
		s = "";
	    }
//            fprintf(stderr, "%.20s %08x\t%s+%X\n", s, frame.AddrPC.Offset,
//		pSymbol->Name, displacement);
	    sprintf(buf, "%.20s %08x\t%s+%X", s, frame.AddrPC.Offset,
		pSymbol->Name, displacement);
//	    EXP_LOG("%s", buf);
	} else {


//	    fprintf(stderr, "%08x\n", frame.AddrPC.Offset);
//	    EXP_LOG("%08x\t", frame.AddrPC.Offset);
	}
    }


#else
#  error "Unsupported architecture"	    
#endif
}


































/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXCreateThread --
 *
 *	This routine is called when a CREATE_THREAD_DEBUG_EVENT
 *	occurs.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXCreateThread(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    // As needed, examine or change the thread's registers
    // with the GetThreadContext and SetThreadContext functions;
    // and suspend and resume thread execution with the
    // SuspendThread and ResumeThread functions.
    //
    ThreadInfo *threadInfo;

    threadInfo = new ThreadInfo;
    threadInfo->dwThreadId = pDebEvent->dwThreadId;
    threadInfo->hThread = pDebEvent->u.CreateThread.hThread;
    proc->threadCount++;
    threadInfo->nextPtr = proc->threadList;







|
|
<
|
<
|




<




>
|
|
|
|
|
|
|
|
|
>
|
|
>
>
>
|
|
>



|







|









|











>
|
<
>
>
|
>
>
|
|







<
>








|
>
>
>
>
>
>
>
>
|
>
>
>
|




|
>
>
>
>
>
>







>
>




|
|


|
|
|
>
>
>



<
<
|
|
|

>
>
|
|


>
>

|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















<
<
<
<
<







796
797
798
799
800
801
802
803
804

805

806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
876
877
878
879
880
881
882

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942


943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009





1010
1011
1012
1013
1014
1015
1016
    CONTEXT context;
    ThreadInfo *tinfo;
    Module *modPtr;
    DWORD displacement;
    BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512];
    PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
    char *s;
    int result;
    unsigned int level = 0;



    for (tinfo = proc->threadList; tinfo != NULL; tinfo = tinfo->nextPtr) {
	if (pDebEvent->dwThreadId == tinfo->dwThreadId) {
	    break;
	}
    }


    context.ContextFlags = CONTEXT_FULL;
    GetThreadContext(tinfo->hThread, &context);

    /*
     * XXX: From what I can tell, SymInitialize is broken on Windows NT 4.0
     * if you try to have it iterate the modules in a process.  It always
     * returns an object mismatch error.  Instead, initialize without iterating
     * the modules.  Contrary to what MSDN documentation says,
     * Microsoft debuggers do not exclusively use the imagehlp API.  In
     * fact, the only thing VC 5.0 uses is the StackWalk function.
     * Windbg uses a few more functions, but it doesn't use SymInitialize.
     * We will then do the hard work of finding all the
     * modules and doing the right thing.
     */

    if (!SymInitialize(proc->hProcess, SymbolPath, FALSE))
    {
	CHAR *buffer = new CHAR [512];
	DWORD len;
	len = wsprintf(buffer, "Unable to get backtrace: %s\n",
		GetSysMsg(GetLastError()));
	WriteMasterError(buffer, len);
	return;
    }

#ifdef _X86_
    memset(&frame, 0, sizeof(frame));
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrPC.Segment = 0;
    frame.AddrPC.Offset = context.Eip;

    frame.AddrReturn.Mode = AddrModeFlat;
    frame.AddrReturn.Segment = 0;
    frame.AddrReturn.Offset = context.Ebp; /* I think this is correct */

    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrFrame.Segment = 0;
    frame.AddrFrame.Offset = context.Ebp;

    frame.AddrStack.Mode = AddrModeFlat;
    frame.AddrStack.Segment = 0;
    frame.AddrStack.Offset = context.Esp;

    frame.FuncTableEntry = NULL;
    frame.Params[0] = context.Eax;
    frame.Params[1] = context.Ecx;
    frame.Params[2] = context.Edx;
    frame.Params[3] = context.Ebx;
    frame.Far = FALSE;
    frame.Virtual = FALSE;
    frame.Reserved[0] = 0;
    frame.Reserved[1] = 0;
    frame.Reserved[2] = 0;
    /* frame.KdHelp.* is not set */

    /*
     * Iterate through the loaded modules and load symbols for each one.

     */
    for (
	result = proc->moduleTable.Top(&modPtr);
	result == TCL_OK;
	result = proc->moduleTable.Next(&modPtr)
    ) {
	if (!modPtr->loaded) {
	    modPtr->dbgInfo = MapDebugInformation(modPtr->hFile, 0L,
		SymbolPath, (DWORD)modPtr->baseAddr);

	    SymLoadModule(proc->hProcess, modPtr->hFile,
		0L, 0L, (DWORD) modPtr->baseAddr, 0);
	    modPtr->loaded = TRUE;
	}

    }


    if (proc->exeModule && proc->exeModule->dbgInfo && 
	proc->exeModule->dbgInfo->ImageFileName) {
	s = proc->exeModule->dbgInfo->ImageFileName;
    } else {
	s = "";
    }

    {
	DWORD len;
	CHAR *buffer = new CHAR [MAX_PATH+600];
	DWORD exCode = pDebEvent->u.Exception.ExceptionRecord.ExceptionCode;
	len = wsprintf(buffer,
		"\nA fatal, second-chance exception has occured in \"%s\".\n"
		"(0x%X) -- %s\n"
		"This is the backtrace:\n"
		"-------------------------------------\n", s, exCode,
		GetExceptionCodeString(exCode));
	WriteMasterError(buffer, len);
    }

    while (1) {
        pSymbol->SizeOfStruct = sizeof(symbolBuffer);
        pSymbol->MaxNameLength = 512;

	b = StackWalk(
#ifdef _WIN64
	    IMAGE_FILE_MACHINE_IA64,
#else
	    IMAGE_FILE_MACHINE_I386,
#endif
	    proc->hProcess,
	    tinfo->hThread, &frame, &context, 0L,
	    SymFunctionTableAccess, SymGetModuleBase,
	    0L);

	if (b == FALSE || frame.AddrPC.Offset == 0) {
	    break;
	}

	level++;
	    
        if (SymGetSymFromAddr(proc->hProcess, frame.AddrPC.Offset,
	    &displacement, pSymbol) )
        {
	    DWORD base, len;
	    CHAR *buffer = new CHAR [128];

	    base = SymGetModuleBase(proc->hProcess, frame.AddrPC.Offset);
	    if (proc->moduleTable.Find((void *)base, &modPtr) != TCL_ERROR) {
		if (modPtr->dbgInfo && modPtr->dbgInfo->ImageFileName) {
		    s = modPtr->dbgInfo->ImageFileName;
		} else {
		    s = "";
		}
	    } else {
		s = "";
	    }


	    len = wsprintf(buffer, "%u) %.20s 0x%08.8x\t%s+%X\n", level, s, frame.AddrPC.Offset,
		    pSymbol->Name, displacement);
	    WriteMasterError(buffer, len);
	} else {
	    DWORD len;
	    CHAR *buffer = new CHAR [33];
	    len = wsprintf(buffer, "%08.8x\n", frame.AddrPC.Offset);
	    WriteMasterError(buffer, len);
	}
    }

    SymCleanup(proc->hProcess);
#else
#  error Unsupported architecture	    
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::GetExceptionCodeString --
 *
 *	Returns a string about the exception code.  Much more can
 *	be added.
 *
 *----------------------------------------------------------------------
 */

PCSTR
ConsoleDebugger::GetExceptionCodeString (DWORD exCode)
{
    switch (exCode)
    {
	case EXCEPTION_ACCESS_VIOLATION:
	    return "Access Violation.";
	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
	    return "Array access was out-of-bounds.";
	case EXCEPTION_INT_DIVIDE_BY_ZERO:
	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
	    return "Divide by zero.";
	case EXCEPTION_ILLEGAL_INSTRUCTION:
	case EXCEPTION_PRIV_INSTRUCTION:
	    return "Illegal opcode.";
	case EXCEPTION_STACK_OVERFLOW:
	    return "Stack overflow.";
	default:
	    return "exception unknown.";
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXCreateThread --
 *
 *	This routine is called when a CREATE_THREAD_DEBUG_EVENT
 *	occurs.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXCreateThread(Process *proc, LPDEBUG_EVENT pDebEvent)
{





    ThreadInfo *threadInfo;

    threadInfo = new ThreadInfo;
    threadInfo->dwThreadId = pDebEvent->dwThreadId;
    threadInfo->hThread = pDebEvent->u.CreateThread.hThread;
    proc->threadCount++;
    threadInfo->nextPtr = proc->threadList;
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXDeleteThread(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    // As needed, examine or change the thread's registers
    // with the GetThreadContext and SetThreadContext functions;
    // and suspend and resume thread execution with the
    // SuspendThread and ResumeThread functions.
    //
    ThreadInfo *threadInfo;
    ThreadInfo *prev;

    prev = 0L;
    for (threadInfo = proc->threadList; threadInfo;
	 prev = threadInfo, threadInfo = threadInfo->nextPtr)
    {







<
<
<
<
<







1030
1031
1032
1033
1034
1035
1036





1037
1038
1039
1040
1041
1042
1043
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXDeleteThread(Process *proc, LPDEBUG_EVENT pDebEvent)
{





    ThreadInfo *threadInfo;
    ThreadInfo *prev;

    prev = 0L;
    for (threadInfo = proc->threadList; threadInfo;
	 prev = threadInfo, threadInfo = threadInfo->nextPtr)
    {
905
906
907
908
909
910
911




912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
void
ConsoleDebugger::OnXCreateProcess(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    ThreadInfo *threadInfo;
    CREATE_PROCESS_DEBUG_INFO *info = &pDebEvent->u.CreateProcessInfo;
    int known;





    if (proc == 0L) {
	proc = ProcessNew();
//	proc->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	
	if (!DuplicateHandle(GetCurrentProcess(),
			     info->hProcess,
			     GetCurrentProcess(),
			     &proc->hProcess, PROCESS_ALL_ACCESS,
			     FALSE, 0)) {
	    fprintf(stderr, "Unable to duplicate handle\n");
	}
	proc->pid = pDebEvent->dwProcessId;

//	ExpAddToWaitQueue(proc->hProcess);
    }

    known = LoadedModule(proc, info->hFile, info->lpImageName,
		info->fUnicode, info->lpBaseOfImage,
		info->dwDebugInfoFileOffset);

    // As needed, examine or change the registers of the
    // process's initial thread with the GetThreadContext and
    // SetThreadContext functions; read from and write to the
    // process's virtual memory with the ReadProcessMemory and
    // WriteProcessMemory functions; and suspend and resume
    // thread execution with the SuspendThread and ResumeThread
    // functions.
    //
    threadInfo = new ThreadInfo;
    threadInfo->dwThreadId = pDebEvent->dwThreadId;
    threadInfo->hThread = info->hThread;
    threadInfo->nextPtr = proc->threadList;
    proc->threadCount++;
    proc->threadList = threadInfo;
}

/*
 *----------------------------------------------------------------------
 *
 * OnXLoadDll --
 *
 *	This routine is called when a LOAD_DLL_DEBUG_EVENT is seen
 *
 * Results:
 *	None
 *
 * Side Effects:







>
>
>
>


<
<
<
|
<
<
<
<
<

|
<
|
<
|
<
|

<
<
<
<
<
<
<
<











|







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084



1085





1086
1087

1088

1089

1090
1091








1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
void
ConsoleDebugger::OnXCreateProcess(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    ThreadInfo *threadInfo;
    CREATE_PROCESS_DEBUG_INFO *info = &pDebEvent->u.CreateProcessInfo;
    int known;

    // Save the first processes' start address.
    if (!pStartAddress)
	    pStartAddress = info->lpStartAddress;

    if (proc == 0L) {
	proc = ProcessNew();



	proc->hProcess = info->hProcess;





	proc->pid = pDebEvent->dwProcessId;
    }



    known = LoadedModule(proc, info->hFile, info->lpImageName, info->fUnicode,

	    info->lpBaseOfImage, info->dwDebugInfoFileOffset);









    threadInfo = new ThreadInfo;
    threadInfo->dwThreadId = pDebEvent->dwThreadId;
    threadInfo->hThread = info->hThread;
    threadInfo->nextPtr = proc->threadList;
    proc->threadCount++;
    proc->threadList = threadInfo;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXLoadDll --
 *
 *	This routine is called when a LOAD_DLL_DEBUG_EVENT is seen
 *
 * Results:
 *	None
 *
 * Side Effects:
1039
1040
1041
1042
1043
1044
1045
















1046
1047
1048
1049
1050
1051
1052

    // See if this is a DLL we are interested in
    //
    ptr = &ped->Name;
    ReadSubprocessMemory(proc, ptr, &dw, sizeof(DWORD));
    ptr = (PVOID) (base + dw);
    ReadSubprocessStringA(proc, ptr, dllname, sizeof(dllname));

















    bFound = FALSE;
    for (n = 0; BreakPoints[n].dllName; n++) {
	if (stricmp(dllname, BreakPoints[n].dllName) == 0) {
	    bFound = TRUE;
	    break;
	}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220

    // See if this is a DLL we are interested in
    //
    ptr = &ped->Name;
    ReadSubprocessMemory(proc, ptr, &dw, sizeof(DWORD));
    ptr = (PVOID) (base + dw);
    ReadSubprocessStringA(proc, ptr, dllname, sizeof(dllname));

    {
	int len;
	CHAR msg[256];

	if (dllname[0] == '\0') {
	    // image has no export section, so get the name another way.
	    // TODO: How??

	} else {
	    strcpy(msg, dllname);
	    strcat(msg, " has loaded.\n");
	    len = strlen(msg);
	}
	WriteMasterWarning(strdup(msg), len);
    }

    bFound = FALSE;
    for (n = 0; BreakPoints[n].dllName; n++) {
	if (stricmp(dllname, BreakPoints[n].dllName) == 0) {
	    bFound = TRUE;
	    break;
	}
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121


1122






































































































































































































1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379

    psh = (PIMAGE_SECTION_HEADER) p;
}

/*
 *----------------------------------------------------------------------
 *
 * OnXUnloadDll --
 *
 *	This routine is called when a UNLOAD_DLL_DEBUG_EVENT is seen
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Some information is printed
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXUnloadDll(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    Module *modPtr;

    if (proc->moduleTable.Find(pDebEvent->u.UnloadDll.lpBaseOfDll, &modPtr)
	    != TCL_ERROR)
    {
	if (modPtr->hFile) {
	    CloseHandle(modPtr->hFile);
	}
	if (modPtr->modName) {
	    free(modPtr->modName);
	}
	if (modPtr->dbgInfo) {
	    UnmapDebugInformation(modPtr->dbgInfo);
	}
	delete modPtr;


	proc->moduleTable.Delete(pDebEvent->u.UnloadDll.lpBaseOfDll);






































































































































































































    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::SetBreakpoint --
 *
 *	Inserts a single breakpoint
 *
 * Results:
 *	TRUE if successful, FALSE if unsuccessful.
 *
 *----------------------------------------------------------------------
 */

BOOL
ConsoleDebugger::SetBreakpoint(Process *proc, BreakInfo *info)
{
    PVOID funcPtr;

    if (proc->funcTable.Find((void *)info->funcName, &funcPtr) == TCL_ERROR)
    {
//	EXP_LOG("Unable to set breakpoint at %s", info->funcName);
	return FALSE;
    }

    // Set a breakpoint at the function start in the subprocess and
    // save the original code at the function start.
    //
    SetBreakpointAtAddr(proc, info, funcPtr);
    return TRUE;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::SetBreakpointAtAddr --
 *
 *	Inserts a single breakpoint at the given address
 *
 * Results:
 *	TRUE if successful, FALSE if unsuccessful.
 *
 *----------------------------------------------------------------------
 */

ConsoleDebugger::Breakpoint *
ConsoleDebugger::SetBreakpointAtAddr(Process *proc, BreakInfo *info, PVOID funcPtr)
{
    Breakpoint *bpt;
    BYTE code;

    bpt = new Breakpoint;
    bpt->returning = FALSE;
    bpt->codePtr = funcPtr;
    bpt->codeReturnPtr = (PVOID) (proc->offset + (DWORD) proc->pSubprocessMemory);
    bpt->origRetAddr = 0;
    bpt->breakInfo = info;
    bpt->threadInfo = 0L;
    proc->offset += 2;
    bpt->nextPtr = proc->brkptList;
    proc->brkptList = bpt;

    ReadSubprocessMemory(proc, funcPtr, &bpt->code, sizeof(BYTE));
#ifdef _M_IX86
    // Breakpoint opcode on i386
    code = 0xcc;
#else
#   error "need breakpoint opcode for this hardware"
#endif
    WriteSubprocessMemory(proc, funcPtr, &code, sizeof(BYTE));
    return bpt;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ReadSubprocessMemory --
 *
 *	Reads memory from the subprocess.  Takes care of all the
 *	issues with page protection.
 *
 * Results:
 *	FALSE if unsuccessful, TRUE if successful.
 *
 * Notes:
 *	The efficient memory reading routine is disabled here
 *	because it doesn't quite work right.  I don't see the
 *	problem in the code, but there must be something there
 *	since the test suite fails when run with this code
 *	enabled.  When it works, it should be much faster than
 *	the current safe but slow implementation.
 *
 *----------------------------------------------------------------------
 */

#if 0
BOOL
ConsoleDebugger::ReadSubprocessMemory(ExpProcess *proc, LPVOID addr, LPVOID buf, DWORD len)
{
    DWORD oldProtection = 0;
    MEMORY_BASIC_INFORMATION mbi;
    BOOL ret = TRUE;
    DWORD offset;
    DWORD base, curr, end, n;
    HANDLE hProcess;
    PBYTE bufpos = buf;

    hProcess = proc->hProcess;

    end = len + (DWORD) addr;
    for (curr = (DWORD) addr; curr < end; ) {
	base = curr & (~PAGEMASK);
	offset = curr & PAGEMASK;
	if (offset + len > PAGESIZE) {
	    n = PAGESIZE - offset;
	} else {
	    n = len;
	}
	if (proc->pMemoryCacheBase != (curr & PAGEMASK)) {
	    /* if not committed memory abort */
	    if (!VirtualQueryEx(hProcess, (LPVOID) base, &mbi, sizeof(mbi)) ||
		(mbi.State != MEM_COMMIT))
	    {
		return FALSE;
	    }

	    /* if guarded memory, change protection temporarily */
	    if (!(mbi.Protect & PAGE_READONLY) &&
		!(mbi.Protect & PAGE_READWRITE))
	    {
		VirtualProtectEx(hProcess, (LPVOID) base, PAGESIZE,
		    PAGE_READONLY, &oldProtection);
	    }

	    if (!ReadProcessMemory(hProcess, (LPVOID) base, proc->pMemoryCache,
		PAGESIZE, 0L)) {
		ret = FALSE;
	    }
    
	    /* reset protection if changed */
	    if (oldProtection) {
		VirtualProtectEx(hProcess, (LPVOID) base, PAGESIZE,
		    oldProtection, &oldProtection);
	    }
	    if (ret == FALSE) {
		return FALSE;
	    }
	    proc->pMemoryCacheBase = base;
	}

	memcpy(bufpos, &proc->pMemoryCache[offset], n);
	bufpos += n;
	curr += n;
    }

    return ret;
}

#else
BOOL
ConsoleDebugger::ReadSubprocessMemory(Process *proc, LPVOID addr, LPVOID buf, DWORD len)
{
    DWORD oldProtection = 0;
    MEMORY_BASIC_INFORMATION mbi;
    BOOL ret;
    LONG error;

    // if not committed memory abort
    if (!VirtualQueryEx(proc->hProcess, addr, &mbi, sizeof(mbi)) ||
	mbi.State != MEM_COMMIT)
    {
	return FALSE;
    }
    
    // if guarded memory, change protection temporarily
    if (!(mbi.Protect & PAGE_READONLY) && !(mbi.Protect & PAGE_READWRITE)) {
	VirtualProtectEx(proc->hProcess, addr, len, PAGE_READONLY, &oldProtection);
    }
    
    ret = ReadProcessMemory(proc->hProcess, addr, buf, len, 0L);
    if (ret == FALSE) {
	error = GetLastError();
    }
    
    // reset protection if changed
    if (oldProtection) {
	VirtualProtectEx(proc->hProcess, addr, len, oldProtection, &oldProtection);
	SetLastError(error);
    }
    return ret;
}
#endif /* XXX */

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::WriteSubprocessMemory --
 *
 *	Writes memory from the subprocess.  Takes care of all the
 *	issues with page protection.
 *
 * Results:
 *	0 if unsuccessful, 1 if successful.
 *
 *----------------------------------------------------------------------
 */

BOOL
ConsoleDebugger::WriteSubprocessMemory(Process *proc, LPVOID addr, LPVOID buf, DWORD len)
{
    DWORD oldProtection = 0;
    MEMORY_BASIC_INFORMATION mbi;
    BOOL ret = TRUE;
    DWORD err;
    HANDLE hProcess;

    hProcess = proc->hProcess;

    // Flush the read cache.
    proc->pMemoryCacheBase = 0;

    // if not committed memory abort
    if (!VirtualQueryEx(hProcess, addr, &mbi, sizeof(mbi)) ||
	mbi.State != MEM_COMMIT)
    {
	ret = FALSE;
	// assert(ret != FALSE);
	return ret;
    }
    
    // if guarded memory, change protection temporarily.
    if (!(mbi.Protect & PAGE_READWRITE)) {
	if (!VirtualProtectEx(hProcess, addr, len, PAGE_READWRITE,
			      &oldProtection)) {
	    err = GetLastError();
	}
    }
    
    if (!WriteProcessMemory(hProcess, addr, buf, len, 0L)) {
	ret = FALSE;
	err = GetLastError();
    }
    
    // reset protection if changed
    if (oldProtection) {
	VirtualProtectEx(hProcess, addr, len, oldProtection, &oldProtection);
    }
    return ret;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXBreakpoint --
 *







|

















|






|





>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|

<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
<
<
|

<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498







1499




1500





1501














1502

1503


1504




















1505






1506


1507
















1508
1509
1510


1511
1512


1513
1514


























1515



1516




1517










1518




1519



1520







1521






1522




1523



1524

































































1525
1526
1527
1528
1529
1530
1531

    psh = (PIMAGE_SECTION_HEADER) p;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXUnloadDll --
 *
 *	This routine is called when a UNLOAD_DLL_DEBUG_EVENT is seen
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Some information is printed
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXUnloadDll(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    Module *modPtr;

    if (proc->moduleTable.Extract(pDebEvent->u.UnloadDll.lpBaseOfDll, &modPtr)
	    != TCL_ERROR)
    {
	if (modPtr->hFile) {
	    CloseHandle(modPtr->hFile);
	}
	if (modPtr->modName) {
	    delete [] modPtr->modName;
	}
	if (modPtr->dbgInfo) {
	    UnmapDebugInformation(modPtr->dbgInfo);
	}
	delete modPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXDebugString --
 *
 *	This routine is called when a OUTPUT_DEBUG_STRING_EVENT
 *	happens.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Allocates a buffer for the string that is not cleared *here*.
 *
 *----------------------------------------------------------------------
 */
void
ConsoleDebugger::OnXDebugString(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    CHAR *buffer;
    DWORD len;

    if (pDebEvent->u.DebugString.fUnicode) {
	int wlen = pDebEvent->u.DebugString.nDebugStringLength;
	WCHAR *wbuffer = new WCHAR [wlen];
	ReadSubprocessStringW(proc,
		pDebEvent->u.DebugString.lpDebugStringData,
		wbuffer, wlen);
	len = WideCharToMultiByte(CP_ACP, 0, wbuffer, wlen, 0L, 0, 0L, 0L);
	buffer = new CHAR [len+1];
	WideCharToMultiByte(CP_ACP, 0, wbuffer, wlen, buffer, len, 0L, 0L);
    } else {
	len = pDebEvent->u.DebugString.nDebugStringLength;
	buffer = new CHAR [len+1];
	ReadSubprocessStringA(proc,
		pDebEvent->u.DebugString.lpDebugStringData,
		buffer, len);
    }

//    buffer[len] = '\0';  // Oops, Win9x forgets this.
    WriteMasterWarning(buffer, len-1);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXVDMException --
 *
 *	Exceptions raised by the NTVDM (Virtual Dos Machine).  We only
 *	get here when a DOS or Win16 (not likely for us, though)
 *	application is the slave or a child of the slave.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnXVDMException(Process *proc, LPDEBUG_EVENT pDebEvent)
{
    EXCEPTION_RECORD &exrec = pDebEvent->u.Exception.ExceptionRecord;
    USHORT exCode = W1(exrec);
    VDMProcessException(pDebEvent);

    switch (exCode) {
        case DBG_SEGLOAD:
	    __asm nop;
	    break;

        case DBG_SEGMOVE:
	    __asm nop;
	    break;

        case DBG_SEGFREE:
	    __asm nop;
	    break;

        case DBG_MODFREE:
        case DBG_MODLOAD:
	    {
		SEGMENT_NOTE segNote;
		char *buffer;
		DWORD len;
		const char *verb;

                switch (exCode)
                {
                    case DBG_MODLOAD:
                        verb = "loaded into"; break;
                    case DBG_MODFREE:
                        verb = "unloaded from"; break;
		}


		ReadSubprocessMemory(proc, (PVOID)DW3(exrec), &segNote, sizeof(segNote));
		len = strlen(segNote.FileName) + 25;
		buffer = new char [len];
		len = wsprintf(buffer, "%s %s the VDM.\n", segNote.FileName, verb);
		WriteMasterWarning(buffer, len);
	    }
	    break;

        case DBG_SINGLESTEP:
	    __asm nop;
	    break;

        case DBG_BREAK:
	    __asm nop;
	    break;

        case DBG_GPFAULT:
	    __asm nop;
	    break;

        case DBG_DIVOVERFLOW:
	    __asm nop;
	    break;

        case DBG_INSTRFAULT:
	    __asm nop;
	    break;

        case DBG_TASKSTART:
        case DBG_TASKSTOP:
        case DBG_DLLSTART:
        case DBG_DLLSTOP:
	    {
		IMAGE_NOTE imgNote;
		char *buffer;
		DWORD len;
		const char *verb;

                switch (exCode)
                {
                    case DBG_TASKSTART:
                        verb = "started in"; break;
                    case DBG_DLLSTART:
                        verb = "started in"; break;
                    case DBG_DLLSTOP:
                        verb = "stopped in"; break;
                    case DBG_TASKSTOP:
                        verb = "stopped in"; break;
                }

		ReadSubprocessMemory(proc, (PVOID)DW3(exrec), &imgNote, sizeof(IMAGE_NOTE));
		len = strlen(imgNote.FileName) + 25;
		buffer = new char [len];
		len = wsprintf(buffer, "%s %s the VDM.\n", imgNote.FileName, verb);
		WriteMasterWarning(buffer, len);
	    }
	    break;

        case DBG_ATTACH:
	    __asm nop;
	    break;

	case DBG_TOOLHELP:
	    __asm nop;
	    break;

	case DBG_STACKFAULT:
	    __asm nop;
	    break;

	case DBG_WOWINIT:
	    __asm nop;
	    break;

	case DBG_TEMPBP:
	    __asm nop;
	    break;

	case DBG_MODMOVE:
	    __asm nop;
	    break;

	case DBG_INIT:
	    VDMSetDbgFlags(proc->hProcess,
//		    VDMDBG_BREAK_DOSTASK |  // <- seems to cause a non-continueable exception on it's own.
//		    VDMDBG_BREAK_WOWTASK |
		    VDMDBG_BREAK_LOADDLL |
		    VDMDBG_BREAK_EXCEPTIONS |
		    VDMDBG_BREAK_DEBUGGER |
//		    VDMDBG_TRACE_HISTORY |
		    0);
	    break;

	case DBG_GPFAULT2:
	    __asm nop;
	    break;

	default:
	    __asm nop;
	    break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXRip --
 *







 *	Catches and reports RIP events (system error messages).




 *	Is RIP short for Rest-In-Peace??





 *














 * Results:

 *	None


 *




















 * Side Effects:






 *	allocates memory that is freed by the Message destructor.


 *
















 *----------------------------------------------------------------------
 */
void


ConsoleDebugger::OnXRip(Process *proc, LPDEBUG_EVENT pDebEvent)
{


    char *errorMsg = new CHAR [512];
    DWORD len;






























    if (pDebEvent->u.RipInfo.dwType == SLE_ERROR) {




	len = wsprintf(errorMsg, "A fatal RIP error was caught: %s",










		GetSysMsg(pDebEvent->u.RipInfo.dwError));




	WriteMasterError(errorMsg, len);



    } else {







	len = wsprintf(errorMsg, "A non-fatal RIP error was caught: %s",






		GetSysMsg(pDebEvent->u.RipInfo.dwError));




	WriteMasterWarning(errorMsg, len);



    }

































































}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnXBreakpoint --
 *
1414
1415
1416
1417
1418
1419
1420






1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
		break;
	    }
	    if (brkpt->threadInfo == tinfo) {
		break;
	    }
	}
    }







    context.ContextFlags = CONTEXT_FULL;
    GetThreadContext(tinfo->hThread, &context);

    if (! brkpt->returning) {
	Breakpoint *bpt;
	// Get the arguments to the function and store them in the thread
	// specific data structure.
	for (pdw = tinfo->args, i=0; i < brkpt->breakInfo->nargs; i++, pdw++) {
	    ReadSubprocessMemory(proc, (PVOID) (context.Esp+(4*(i+1))),
				 pdw, sizeof(DWORD));
	}







>
>
>
>
>
>




|







1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
		break;
	    }
	    if (brkpt->threadInfo == tinfo) {
		break;
	    }
	}
    }

    if (brkpt == 0L) {
	// shouldn't happen, but does..
	// ask td32 for a new OS shell in a seperate console and this happens.
	return;
    }

    context.ContextFlags = CONTEXT_FULL;
    GetThreadContext(tinfo->hThread, &context);

    if (!brkpt->returning) {
	Breakpoint *bpt;
	// Get the arguments to the function and store them in the thread
	// specific data structure.
	for (pdw = tinfo->args, i=0; i < brkpt->breakInfo->nargs; i++, pdw++) {
	    ReadSubprocessMemory(proc, (PVOID) (context.Esp+(4*(i+1))),
				 pdw, sizeof(DWORD));
	}
1482
1483
1484
1485
1486
1487
1488


























































































































1489
1490
1491
1492
1493
1494
1495
1496
    }
    SetThreadContext(tinfo->hThread, &context);
}

/*
 *----------------------------------------------------------------------
 *


























































































































 * ReadSubprocessStringA --
 *
 *	Read a character string from the subprocess
 *
 * Results:
 *	The length of the string
 *
 *----------------------------------------------------------------------







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
    }
    SetThreadContext(tinfo->hThread, &context);
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ReadSubprocessMemory --
 *
 *	Reads memory from the subprocess.  Takes care of all the
 *	issues with page protection.
 *
 * Results:
 *	FALSE if unsuccessful, TRUE if successful.
 *
 * Notes:
 *	Currently safe, but slow.
 *
 *----------------------------------------------------------------------
 */

BOOL
ConsoleDebugger::ReadSubprocessMemory(Process *proc, LPVOID addr, LPVOID buf, DWORD len)
{
    DWORD oldProtection = 0;
    MEMORY_BASIC_INFORMATION mbi;
    BOOL ret = TRUE;
    DWORD err = ERROR_SUCCESS;

    // if inaccessible or not committed memory, abort
    //
    if (!VirtualQueryEx(proc->hProcess, addr, &mbi,
	    sizeof(MEMORY_BASIC_INFORMATION)) || mbi.State != MEM_COMMIT)
    {
	return FALSE;
    }

    // On Win9x, special ranges can't have their protection changed.
    //
    if (dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
	    && addr >= (LPVOID) 0x80000000 && addr <= (LPVOID) 0xBFFFFFFF) {
	ret = ReadProcessMemory(proc->hProcess, addr, buf, len, 0L);
    } else {
	// if guarded memory, change protection temporarily.
	//
	if (!(mbi.Protect & PAGE_READONLY) && !(mbi.Protect & PAGE_READWRITE)) {
	    VirtualProtectEx(proc->hProcess, addr, len, PAGE_READONLY,
		    &oldProtection);
	}
    
	if (!ReadProcessMemory(proc->hProcess, addr, buf, len, 0L)) {
	    err = GetLastError();
	    ret = FALSE;
	}
    
	// reset protection if changed.
	//
	if (oldProtection) {
	    VirtualProtectEx(proc->hProcess, addr, len, oldProtection,
		    &oldProtection);
	    SetLastError(err);
	}
    }
    return ret;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::WriteSubprocessMemory --
 *
 *	Writes memory from the subprocess.  Takes care of all the
 *	issues with page protection.
 *
 * Results:
 *	zero if unsuccessful, non-zero if successful.
 *
 *----------------------------------------------------------------------
 */

BOOL
ConsoleDebugger::WriteSubprocessMemory(Process *proc, LPVOID addr, LPVOID buf, DWORD len)
{
    DWORD oldProtection = 0;
    MEMORY_BASIC_INFORMATION mbi;
    BOOL ret = TRUE;
    DWORD err = ERROR_SUCCESS;

    // if inaccessible or not committed memory, abort
    if (!VirtualQueryEx(proc->hProcess, addr, &mbi,
	    sizeof(MEMORY_BASIC_INFORMATION)) || mbi.State != MEM_COMMIT)
    {
	return FALSE;
    }
    
    // On Win9x, special ranges can't have their protection changed.
    //
    if (dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
	    && addr >= (LPVOID) 0x80000000 && addr <= (LPVOID) 0xBFFFFFFF) {
	ret = WriteProcessMemory(proc->hProcess, addr, buf, len, 0L);
    } else {
	// if guarded memory, change protection temporarily.
	//
	if (!(mbi.Protect & PAGE_READWRITE || mbi.Protect & PAGE_EXECUTE_READWRITE)) {
	    if (!VirtualProtectEx(proc->hProcess, addr, len, PAGE_READWRITE,
		    &oldProtection)) {
		return FALSE;
	    }
	}
    
	if (!WriteProcessMemory(proc->hProcess, addr, buf, len, 0L)) {
	    ret = FALSE;
	    err = GetLastError();
	}
    
	// reset protection if changed.
	//
	if (oldProtection) {
	    VirtualProtectEx(proc->hProcess, addr, len, oldProtection,
		    &oldProtection);
	    SetLastError(err);
	}
    }
    return ret;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ReadSubprocessStringA --
 *
 *	Read a character string from the subprocess
 *
 * Results:
 *	The length of the string
 *
 *----------------------------------------------------------------------
1578
1579
1580
1581
1582
1583
1584
1585

1586


1587
1588
1589
1590

1591
1592
1593
1594
1595
1596
1597
1598
1599

    if (modname) {
	// This modname is a pointer to the name of the
	// DLL in the process space of the subprocess
	//
	if (ReadSubprocessMemory(proc, modname, &ptr, sizeof(PVOID)) && ptr) {
	    if (isUnicode) {
		WCHAR name[512];

		ReadSubprocessStringW(proc, ptr, name, 512);


		wcstombs(mbstr, name, sizeof(mbstr));
	    } else {
		ReadSubprocessStringA(proc, ptr, mbstr, sizeof(mbstr));
	    }

	    s = strdup(mbstr);

	} else {
	    known = 0;
	}
    }

    modPtr = new Module;
    modPtr->loaded = FALSE;







|
>

>
>
|


<
>
|
|







1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872

1873
1874
1875
1876
1877
1878
1879
1880
1881
1882

    if (modname) {
	// This modname is a pointer to the name of the
	// DLL in the process space of the subprocess
	//
	if (ReadSubprocessMemory(proc, modname, &ptr, sizeof(PVOID)) && ptr) {
	    if (isUnicode) {
		WCHAR name[MAX_PATH];
		int len;
		ReadSubprocessStringW(proc, ptr, name, 512);
		len = WideCharToMultiByte(CP_ACP, 0, name, -1, 0L, 0, 0L, 0L);
		s = new char [len];
		WideCharToMultiByte(CP_ACP, 0, name, -1, s, len, 0L, 0L);
	    } else {
		ReadSubprocessStringA(proc, ptr, mbstr, sizeof(mbstr));

		s = new char [strlen(mbstr)];
		strcpy(s, mbstr);
	    }
	} else {
	    known = 0;
	}
    }

    modPtr = new Module;
    modPtr->loaded = FALSE;
1607
1608
1609
1610
1611
1612
1613














































































































































































































1614
1615
1616


1617














1618












1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
































    proc->moduleTable.Add(baseAddr, modPtr);

    return known;
}

void














































































































































































































ConsoleDebugger::WriteMaster(CHAR *buf, DWORD len)
{
    Message *msg;


    msg = new Message;














    msg->bytes = (BYTE *) _strdup(buf);












    msg->length = len;
    msg->type = Message::TYPE_NORMAL;
    mQ.Put(msg);
}

void
ConsoleDebugger::NotifyDone()
{
    Message *msg;
    msg = new Message;
    msg->type = Message::TYPE_SLAVEDONE;
    mQ.Put(msg);
}






































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179

    proc->moduleTable.Add(baseAddr, modPtr);

    return known;
}

void
ConsoleDebugger::MakeSubprocessMemory(Process *proc, SIZE_T amount,
    LPVOID *pBuff, DWORD access)
{
    if (dwPlatformId == VER_PLATFORM_WIN32_NT) {
        if (!(*pBuff = pfnVirtualAllocEx(proc->hProcess, 0, amount, MEM_COMMIT,
		access))) {
	    EXP_LOG1(MSG_DT_CANTMAKENTSPMEM, GetSysMsg(GetLastError()));
	}
    } else {
        // In Windows 9X, create a small memory mapped file.  On this
        // platform, memory mapped files are above 2GB, and thus are
        // accessible to all processes.
	//
        HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, 0,
		access | SEC_COMMIT, 0, amount, 0);

	if (!hFileMapping) {
	    EXP_LOG1(MSG_DT_CANTMAKE95SPMEM, GetSysMsg(GetLastError()));
	}

	LPVOID buffer = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0,
		amount);

	if (!buffer) {
	    EXP_LOG1(MSG_DT_CANTMAKE95SPMEM, GetSysMsg(GetLastError()));
	}

	// Save the association
	//
	spMemMapping.Add(buffer, hFileMapping);
	*pBuff = buffer;
    }
}

BOOL
ConsoleDebugger::RemoveSubprocessMemory(Process *proc, LPVOID buff)
{
    BOOL ret;

    if (dwPlatformId == VER_PLATFORM_WIN32_NT) {
	ret = pfnVirtualFreeEx(proc->hProcess, buff, 0, MEM_RELEASE);
    } else {
	HANDLE hFileMapping;
	if (spMemMapping.Extract(buff, &hFileMapping) != TCL_OK) {
	    SetLastError(ERROR_FILE_NOT_FOUND);
	    return FALSE;
	}
	ret = UnmapViewOfFile(buff);
	CloseHandle(hFileMapping);
    }
    return ret;
}

/*
 *----------------------------------------------------------------------
 *
 * RefreshScreen --
 *
 *	Redraw the entire screen
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */
/*
void
ConsoleDebugger::RefreshScreen(void)
{
    CONSOLE_SCREEN_BUFFER_INFO info;
    CHAR buf[4096];
    DWORD bufpos = 0;
    CHAR_INFO consoleBuf[4096];
    COORD size = {ConsoleSize.X, ConsoleSize.Y};
    COORD begin = {0, 0};
    SMALL_RECT rect = {0, 0, ConsoleSize.X-1, ConsoleSize.Y-1};
    int x, y, prespaces, postspaces, offset;

    // Clear the screen
    bufpos += wsprintf(&buf[bufpos], "\033[2J");
    bufpos += wsprintf(&buf[bufpos], "\033[%d;%dH", CursorPosition.Y+1,
	    CursorPosition.X+1);
    CursorKnown = TRUE;

    WriteMasterCopy(buf, bufpos);
    bufpos = 0;

//    if (GetConsoleScreenBufferInfo(HConsole, &info) != FALSE) {
//	return;
//    }

    CursorPosition = info.dwCursorPosition;

//    if (! ReadConsoleOutput(HConsole, consoleBuf, size, begin, &rect)) {
//	return;
//    }

    offset = 0;
    for (y = 0; y < ConsoleSize.Y; y++) {
	offset += ConsoleSize.X;
	for (x = 0; x < ConsoleSize.X; x++) {
	    if (consoleBuf[offset+x].Char.AsciiChar != ' ') {
		break;
	    }
	}
	prespaces = x;
	if (prespaces == ConsoleSize.X) {
	    continue;
	}

	for (x = ConsoleSize.X-1; x >= 0; x--) {
	    if (consoleBuf[offset+x].Char.AsciiChar != ' ') {
		break;
	    }
	}
	postspaces = x;
	bufpos += wsprintf(&buf[bufpos], "\033[%d;%dH", y+1, prespaces+1);

	for (x = prespaces; x < postspaces; x++) {
	    buf[bufpos++] = consoleBuf[offset+x].Char.AsciiChar;
	}
    }

    bufpos += wsprintf(&buf[bufpos], "\033[%d;%dH", CursorPosition.Y+1,
	    CursorPosition.X+1);
    CursorKnown = TRUE;
    WriteMasterCopy(buf, bufpos);
}
*/

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ProcessNew --
 *
 *	Allocates a new structure for debugging a process and
 *	initializes it.
 *
 * Results:
 *	A new structure
 *
 * Side Effects:
 *	Memory is allocated, an event is created.
 *
 *----------------------------------------------------------------------
 */

ConsoleDebugger::Process *
ConsoleDebugger::ProcessNew(void)
{
    Process *proc;
    proc = new Process;
    proc->nextPtr = ProcessList;
    ProcessList = proc;
    return proc;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::ProcessFree --
 *
 *	Frees all allocated memory for a process and closes any
 *	open handles
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::ProcessFree(Process *proc)
{
    ThreadInfo *tcurr, *tnext;
    Breakpoint *bcurr, *bnext;
    Process *pcurr, *pprev;

    for (tcurr = proc->threadList; tcurr != 0L; tcurr = tnext) {
	tnext = tcurr->nextPtr;
	proc->threadCount--;
	CloseHandle(tcurr->hThread);
	delete tcurr;
    }
    for (bcurr = proc->brkptList; bcurr != 0L; bcurr = bnext) {
	bnext = bcurr->nextPtr;
	delete bcurr;
    }
    for (pprev = 0L, pcurr = ProcessList; pcurr != 0L;
	 pcurr = pcurr->nextPtr)
    {
	if (pcurr == proc) {
	    if (pprev == 0L) {
		ProcessList = pcurr->nextPtr;
	    } else {
		pprev->nextPtr = pcurr->nextPtr;
	    }
	    break;
	}
    }
    CloseHandle(proc->hProcess);

    delete proc;
}

void
ConsoleDebugger::WriteMasterCopy(CHAR *buf, DWORD len)
{
    Message *msg;
    DWORD i;

    msg = new Message;
    msg->bytes = new CHAR [len];
    for (i = 0; i < len; i++)
	    ((PCHAR)msg->bytes)[i] = buf[i];
    msg->length = len;
    msg->type = Message::TYPE_NORMAL;
    mQ.Put(msg);
}

/* doesn't copy! */
void
ConsoleDebugger::WriteMasterWarning(CHAR *buf, DWORD len)
{
    Message *msg;
    msg = new Message;
    msg->bytes = buf;
    msg->length = len;
    msg->type = Message::TYPE_WARNING;
    mQ.Put(msg);
}

/* doesn't copy! */
void
ConsoleDebugger::WriteMasterError(CHAR *buf, DWORD len)
{
    Message *msg;
    msg = new Message;
    msg->bytes = buf;
    msg->length = len;
    msg->type = Message::TYPE_ERROR;
    mQ.Put(msg);
}

void
ConsoleDebugger::NotifyDone()
{
    Message *msg;
    msg = new Message;
    msg->type = Message::TYPE_SLAVEDONE;
    mQ.Put(msg);
}

void
ConsoleDebugger::WriteRecord (INPUT_RECORD *ir)
{
    if (injectorIPC != 0L) {
	injectorIPC->Post(ir);
    }
}

void
ConsoleDebugger::EnterInteract (HANDLE OutConsole)
{
    bpCritSec.Enter();

    interactingConsole = OutConsole;

    // More stuff to do here... What?
    // Copy entire screen contents, how?
    // Set interactingConsole to the proper size?
    // more ???  help!

    interacting = true;
    bpCritSec.Leave();
}

void
ConsoleDebugger::ExitInteract ()
{
    interactingConsole = 0L;
    interacting = false;
}

Changes to win/expWinConsoleDebugger.hpp.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31


32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55




56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97




98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166





























167
168
169
170
171

172
173
174
175
176
177



178
179
180
181
182

183




184
185
186
187

188
189
190
191


192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210


211
212
213



214


215
216



217
218
219
220
221
222
223
224
225
226
227
228
229
230

231
232
233



234
235
236


237
238
239
240

241































242
243
244
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleDebugger.hpp,v 1.1.2.16 2002/03/15 07:51:56 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinConsoleDebugger_hpp__
#define INC_expWinConsoleDebugger_hpp__



#include "expWinSlave.hpp"

#include "TclHash.hpp"	    // for the hash table template.
#include <imagehlp.h>


#ifdef _M_IX86
    // 4096 is for ix86 only
#   define PAGESIZE 0x1000
    // This only works on ix86
#   define SINGLE_STEP_BIT 0x100;
#else
#   error "need platform page size"
#endif
#define PAGEMASK (PAGESIZE-1)



//  This is our debugger.  We run it in a thread. 
//
class ConsoleDebugger : public CMclThreadHandler, ArgMaker
{
public:
    ConsoleDebugger(int argc, char * const *argv, CMclQueue<Message *> &_mQ);
    ~ConsoleDebugger();





private:
    virtual unsigned ThreadHandlerProc(void);

    // forward reference.
    class Process;
    class Breakpoint;

    class CreateProcessInfo {
	friend class ConsoleDebugger;
	TCHAR	    appName[8192];
	TCHAR	    cmdLine[8192];
	SECURITY_ATTRIBUTES procAttrs;
	SECURITY_ATTRIBUTES threadAttrs;
	BOOL	    bInheritHandles;
	DWORD	    dwCreationFlags;
	LPVOID	    lpEnvironment;
	TCHAR	    currDir[8192];
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	PVOID	    piPtr;  // Pointer to PROCESS_INFORMATION in slave.
	DWORD	    flags;
    };

    class CreateProcessThreadArgs {
	friend class ConsoleDebugger;
	CreateProcessInfo *cp;
	Process	    *proc;
    };

    class ThreadInfo {
	friend class ConsoleDebugger;
	HANDLE	    hThread;
	DWORD	    dwThreadId;
	DWORD	    nargs;
	DWORD	    args[16];	// Space for saving 16 args.  We need this
				// space while we are waiting for the return
				// value for the function.
	LPCONTEXT   context;	// Current context.
	CreateProcessInfo *createProcess; // Create process pointer.
	ThreadInfo  *nextPtr;	// Linked list.
    };





    class BreakInfo {
	friend class ConsoleDebugger;
	const char  *funcName;	// Name of function to intercept.
	DWORD	    nargs;	// Number of arguments.
	void (ConsoleDebugger::*breakProc)(Process *, ThreadInfo *,
		Breakpoint *, PDWORD, DWORD);
				// Function to call when the breakpoint is hit.
#	define BREAK_IN  1	// Call handler on the way in.
#	define BREAK_OUT 2	// Call handler on the way out.
	DWORD	    dwFlags;	// Bits for direction to call handler in.
    };

    class DllBreakpoints {
	friend class ConsoleDebugger;
	const char  *dllName;
	BreakInfo   *breakInfo;
    };

    class Breakpoint {
	friend class ConsoleDebugger;

	BOOL	    returning;	    // Is this a returning breakpoint?
	BYTE	    code;	    // Original code.
	PVOID	    codePtr;	    // Address of original code.
	PVOID	    codeReturnPtr;  // Address of return breakpoint.
	DWORD	    origRetAddr;    // Original return address.
	BreakInfo   *breakInfo;	    // Information about the breakpoint.
	ThreadInfo  *threadInfo;    // If this breakpoint is for a specific thread.

	Breakpoint  *nextPtr;	    // Linked list.
    };

    class Module {
	friend class ConsoleDebugger;
	BOOL	    loaded;
	HANDLE	    hFile;
	LPVOID	    baseAddr;
	PCHAR	    modName;
	PIMAGE_DEBUG_INFORMATION dbgInfo;
    };

    typedef Tcl::Hash<PVOID,TCL_STRING_KEYS> STRING2PTR;
    typedef Tcl::Hash<Module *,TCL_ONE_WORD_KEYS> PTR2MODULE;

    //  There is one of these instances for each subprocess that we are
    //  controlling.
    //
    class Process {
	friend class ConsoleDebugger;



	ThreadInfo  *threadList;	// List of threads in the subprocess.
	Breakpoint  *brkptList;		// List of breakpoints in the subprocess.
	Breakpoint  *lastBrkpt;		// Last breakpoint hit.
	DWORD	    offset;		// Breakpoint offset in allocated mem.
	DWORD	    nBreakCount;	// Number of breakpoints hit.
	DWORD	    consoleHandles[100];// A list of input console handles.
	DWORD	    consoleHandlesMax;
	BOOL	    isConsoleApp;	// Is this a console app?
	BOOL	    isShell;		// Is this some sort of console shell?
	HANDLE	    hProcess;		// handle to subprocess.
	DWORD	    pid;		// Global process id.
	DWORD	    threadCount;	// Number of threads in process.
	DWORD	    pSubprocessMemory;	// Pointer to allocated memory in subprocess.
	DWORD	    pSubprocessBuffer;	// Pointer to buffer memory in subprocess.
	DWORD	    pMemoryCacheBase;	// Base address of memory cache.
	BYTE	    pMemoryCache[PAGESIZE];// Subprocess memory cache.
	STRING2PTR  funcTable;		// Function table name to address mapping.
	PTR2MODULE  moduleTable;	// Win32 modules that have been loaded.
	Module	    *exeModule;		// Executable module info.
	Process	    *nextPtr;		// Linked list.
    };






























    //  Direct debug event handlers.
    //
    void OnXFirstBreakpoint	(Process *, LPDEBUG_EVENT);
    void OnXSecondBreakpoint	(Process *, LPDEBUG_EVENT);

    void OnXBreakpoint		(Process *, LPDEBUG_EVENT);
    void OnXCreateProcess	(Process *, LPDEBUG_EVENT);
    void OnXCreateThread	(Process *, LPDEBUG_EVENT);
    void OnXDeleteThread	(Process *, LPDEBUG_EVENT);
    void OnXLoadDll		(Process *, LPDEBUG_EVENT);
    void OnXUnloadDll		(Process *, LPDEBUG_EVENT);



    void OnXSecondChanceException (Process *, LPDEBUG_EVENT);
    void OnXSingleStep		(Process *, LPDEBUG_EVENT);

    //  Our breakpoint handlers (indirect).  Called from OnXBreakpoint().
    //

    void OnBeep			(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);




    void OnFillConsoleOutputCharacter (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnGetStdHandle		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnIsWindowVisible	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnOpenConsoleW		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);

    void OnReadConsoleInput	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleActiveScreenBuffer	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleCursorPosition (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleMode	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);


    void OnSetConsoleWindowInfo	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnScrollConsoleScreenBuffer (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleA	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleW	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputA	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputW	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputCharacterA	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputCharacterW	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);


    // Internal utilities
    //
    Process *ProcessNew		();
    void ProcessFree		(Process *);
    void CommonDebugger		();
    BOOL SetBreakpoint		(Process *, BreakInfo *);
    Breakpoint *SetBreakpointAtAddr (Process *, BreakInfo *, PVOID);
    int LoadedModule		(Process *, HANDLE, LPVOID, int, LPVOID, DWORD);
    BOOL ReadSubprocessMemory	(Process *, LPVOID, LPVOID, DWORD);
    BOOL WriteSubprocessMemory	(Process *, LPVOID, LPVOID, DWORD);


    int ReadSubprocessStringA	(Process *, PVOID, PCHAR, int);
    int ReadSubprocessStringW	(Process *, PVOID, PWCHAR, int);
    void CreateVtSequence	(Process *, COORD, DWORD);






    // send info back to the parent
    void WriteMaster		(CHAR *, DWORD);




    // announce we are done.
    void NotifyDone		();

    // The arrays of functions where we set breakpoints
    //
    BreakInfo	BreakArrayKernel32[20];
    BreakInfo	BreakArrayUser32[2];
    DllBreakpoints BreakPoints[3];

    // private vars
    //
    Process	*ProcessList;   // Top of linked list of Process instances.
    HANDLE	hMasterConsole;	// Master console handle (us).

    DWORD	MasterConsoleInputMode;// Current flags for the master console.
    COORD	ConsoleSize;    // Size of the console in the slave.
    COORD	CursorPosition; // Coordinates of the cursor in the slave.



    BOOL	CursorKnown;    // Do we know where the slave's cursor is?
    char	*SymbolPath;    // Storage for setting OS kernel symbols path.
    BOOL	ShowExceptionBacktraces;// print exception info from debuggee?


    int		argc;		// Debugee process commandline count
    char * const * argv;	// Debugee process commandline args

    // Thread-safe message queue used for communication back to the parent.

    CMclQueue<Message *> &mQ;































};

#endif // INC_expWinConsoleDebugger_hpp__







>







|






>
>
|
>



<
<
<
<
<
<
<
<
<
<
<







|

>
>
>
>




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









<


>
>
>
>










|










>






|
>












|
|

|




>
>
>







<
<
|


|
<
<
<





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>






>
>
>





>

>
>
>
>
|



>
|
|


>
>








>





|

|



>
>



>
>
>

>
>

|
>
>
>






|







>
|


>
>
>

<
<
>
>




>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39











40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56


























57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131


132
133
134
135



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264


265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleDebugger.hpp,v 1.1.2.30 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinConsoleDebugger_hpp__
#define INC_expWinConsoleDebugger_hpp__

#include "CMcl.h"
#include "slavedrvmc.h"
#include "expWinUtils.hpp"
#include "expWinMessage.hpp"
#include "TclHash.hpp"	    // for the hash table template.
#include <imagehlp.h>














//  This is our debugger.  We run it in a thread. 
//
class ConsoleDebugger : public CMclThreadHandler, ArgMaker
{
public:
    ConsoleDebugger(int _argc, char * const *_argv, CMclQueue<Message *> &_mQ);
    ~ConsoleDebugger();

    void WriteRecord (INPUT_RECORD *ir);
    void EnterInteract (HANDLE OutConsole);
    void ExitInteract (void);

private:
    virtual unsigned ThreadHandlerProc(void);



























    class ThreadInfo {
	friend class ConsoleDebugger;
	HANDLE	    hThread;
	DWORD	    dwThreadId;
	DWORD	    nargs;
	DWORD	    args[16];	// Space for saving 16 args.  We need this
				// space while we are waiting for the return
				// value for the function.
	LPCONTEXT   context;	// Current context.

	ThreadInfo  *nextPtr;	// Linked list.
    };

    // forward reference.
    class Process;
    class Breakpoint;

    class BreakInfo {
	friend class ConsoleDebugger;
	const char  *funcName;	// Name of function to intercept.
	DWORD	    nargs;	// Number of arguments.
	void (ConsoleDebugger::*breakProc)(Process *, ThreadInfo *,
		Breakpoint *, PDWORD, DWORD);
				// Function to call when the breakpoint is hit.
#	define BREAK_IN  1	// Call handler on the way in.
#	define BREAK_OUT 2	// Call handler on the way out.
	DWORD   dwFlags;	// Bits for direction to call handler in.
    };

    class DllBreakpoints {
	friend class ConsoleDebugger;
	const char  *dllName;
	BreakInfo   *breakInfo;
    };

    class Breakpoint {
	friend class ConsoleDebugger;
	Breakpoint() : returning(FALSE), origRetAddr(0), threadInfo(0L) {}
	BOOL	    returning;	    // Is this a returning breakpoint?
	BYTE	    code;	    // Original code.
	PVOID	    codePtr;	    // Address of original code.
	PVOID	    codeReturnPtr;  // Address of return breakpoint.
	DWORD	    origRetAddr;    // Original return address.
	BreakInfo   *breakInfo;	    // Information about the breakpoint.
	ThreadInfo  *threadInfo;    // If this breakpoint is for a specific
				    //  thread.
	Breakpoint  *nextPtr;	    // Linked list.
    };

    class Module {
	friend class ConsoleDebugger;
	BOOL	    loaded;
	HANDLE	    hFile;
	LPVOID	    baseAddr;
	PCHAR	    modName;
	PIMAGE_DEBUG_INFORMATION dbgInfo;
    };

    typedef Tcl::Hash<PVOID, TCL_STRING_KEYS> STRING2PTR;
    typedef Tcl::Hash<Module*, TCL_ONE_WORD_KEYS> PTR2MODULE;

    //  There is one of these instances for each process that we are
    //  controlling.
    //
    class Process {
	friend class ConsoleDebugger;
	Process() : threadList(0L), threadCount(0), brkptList(0L),
	    lastBrkpt(0L), offset(0), nBreakCount(0), consoleHandlesMax(0),
	    hProcess(0L), pSubprocessMemory(0), exeModule(0L) {}
	ThreadInfo  *threadList;	// List of threads in the subprocess.
	Breakpoint  *brkptList;		// List of breakpoints in the subprocess.
	Breakpoint  *lastBrkpt;		// Last breakpoint hit.
	DWORD	    offset;		// Breakpoint offset in allocated mem.
	DWORD	    nBreakCount;	// Number of breakpoints hit.
	DWORD	    consoleHandles[100];// A list of input console handles.
	DWORD	    consoleHandlesMax;


	HANDLE	    hProcess;		// Handle of process.
	DWORD	    pid;		// Global process id.
	DWORD	    threadCount;	// Number of threads in process.
	PVOID	    pSubprocessMemory;	// Pointer to allocated memory in subprocess.



	STRING2PTR  funcTable;		// Function table name to address mapping.
	PTR2MODULE  moduleTable;	// Win32 modules that have been loaded.
	Module	    *exeModule;		// Executable module info.
	Process	    *nextPtr;		// Linked list.
    };

#   include <pshpack1.h>
#   ifdef _M_IX86
    struct LOADLIBRARY_STUB
    {
        BYTE    instr_PUSH;
        DWORD   operand_PUSH_value;
        BYTE    instr_MOV_EAX;
        DWORD   operand_MOV_EAX;
        WORD    instr_CALL_EAX;
        BYTE    instr_INT_3;
        char    data_DllName[MAX_PATH];

        LOADLIBRARY_STUB() :
            instr_PUSH(0x68), instr_MOV_EAX(0xB8),
            instr_CALL_EAX(0xD0FF), instr_INT_3(0xCC)
	{
		// Just a temporary hack.. just ignore for now.
#	ifdef _DEBUG
	    strcpy(data_DllName, "D:\\expect_wslive\\expect_win32_take2\\win\\Debug\\injector.dll");
#	else
	    strcpy(data_DllName, "injector.dll");
#	endif
	}
    };
#   else
#	error "need correct stub loader opcodes for this hardware."
#   endif
#   include <poppack.h>

    //  Direct debug event handlers.
    //
    void OnXFirstBreakpoint	(Process *, LPDEBUG_EVENT);
    void OnXSecondBreakpoint	(Process *, LPDEBUG_EVENT);
    void OnXThirdBreakpoint	(Process *, LPDEBUG_EVENT);
    void OnXBreakpoint		(Process *, LPDEBUG_EVENT);
    void OnXCreateProcess	(Process *, LPDEBUG_EVENT);
    void OnXCreateThread	(Process *, LPDEBUG_EVENT);
    void OnXDeleteThread	(Process *, LPDEBUG_EVENT);
    void OnXLoadDll		(Process *, LPDEBUG_EVENT);
    void OnXUnloadDll		(Process *, LPDEBUG_EVENT);
    void OnXDebugString		(Process *, LPDEBUG_EVENT);
    void OnXRip			(Process *, LPDEBUG_EVENT);
    void OnXVDMException	(Process *, LPDEBUG_EVENT);
    void OnXSecondChanceException (Process *, LPDEBUG_EVENT);
    void OnXSingleStep		(Process *, LPDEBUG_EVENT);

    //  Our breakpoint handlers (indirect).  Called from OnXBreakpoint().
    //
    void OnAllocConsole		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnBeep			(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnCreateConsoleScreenBuffer (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnFillConsoleOutputAttribute (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnFillConsoleOutputCharacterA (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnFillConsoleOutputCharacterW (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnFreeConsole		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnGetStdHandle		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnIsWindowVisible	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnOpenConsoleW		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleActiveScreenBuffer	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleCP		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleCursorInfo (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleCursorPosition (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleMode	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleOutputCP	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleTextAttribute (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnSetConsoleWindowInfo	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnScrollConsoleScreenBuffer (Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleA	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleW	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputA	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputW	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputCharacterA	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteConsoleOutputCharacterW	(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);
    void OnWriteFile		(Process *, ThreadInfo *, Breakpoint *, PDWORD, DWORD);

    // Internal utilities
    //
    Process *ProcessNew		();
    void ProcessFree		(Process *);
    DWORD CommonDebugger	();
    BOOL SetBreakpoint		(Process *, BreakInfo *);
    BOOL SetBreakpointAtAddr	(Process *, BreakInfo *, PVOID);
    int LoadedModule		(Process *, HANDLE, LPVOID, int, LPVOID, DWORD);
    BOOL ReadSubprocessMemory	(Process *, LPVOID, LPVOID, DWORD);
    BOOL WriteSubprocessMemory	(Process *, LPVOID, LPVOID, DWORD);
    void MakeSubprocessMemory   (Process *, SIZE_T, LPVOID *, DWORD = PAGE_READWRITE);
    BOOL RemoveSubprocessMemory (Process *, LPVOID);
    int ReadSubprocessStringA	(Process *, PVOID, PCHAR, int);
    int ReadSubprocessStringW	(Process *, PVOID, PWCHAR, int);
    void CreateVtSequence	(Process *, COORD, DWORD);
    void OnFillCOC_Finish	(CHAR, DWORD, COORD);
    DWORD lastBeepDuration;
    PCSTR GetExceptionCodeString (DWORD);

//    void RefreshScreen		(void);

    // send info back to the parent
    void WriteMasterCopy	(CHAR *, DWORD);
    void WriteMasterWarning	(CHAR *, DWORD);
    void WriteMasterError	(CHAR *, DWORD);


    // announce we are done.
    void NotifyDone		();

    // The arrays of functions where we set breakpoints
    //
    BreakInfo	BreakArrayKernel32[27];
    BreakInfo	BreakArrayUser32[2];
    DllBreakpoints BreakPoints[3];

    // private vars
    //
    Process	*ProcessList;   // Top of linked list of Process instances.
    HANDLE	hMasterConsole;	// Master console handle (us).
    DWORD	dwPlatformId;	// what OS are we under?
    DWORD	ConsoleInputMode;// Current flags for the master console.
    COORD	ConsoleSize;    // Size of the console in the slave.
    COORD	CursorPosition; // Coordinates of the cursor in the slave.
    char	*SymbolPath;
    UINT	ConsoleCP;	// console input code page of the slave.
    UINT	ConsoleOutputCP;// console output code page of the slave.
    BOOL	CursorKnown;    // Do we know where the slave's cursor is?


    CONSOLE_CURSOR_INFO CursorInfo;// Cursor info structure that is a copy of
				   //  the slave's.
    int		argc;		// Debugee process commandline count
    char * const * argv;	// Debugee process commandline args

    // Thread-safe message queue used for communication back to the parent.
    //
    CMclQueue<Message *> &mQ;

    // This critical section is set when breakpoints are running.
    //
    CMclCritSec bpCritSec;

    LPVOID	pStartAddress;	// Start address of the top process.
    BYTE	originalExeEntryPointOpcode;

    LOADLIBRARY_STUB injectorStub;// opcodes we use to force load our injector
				//  dll.
    PVOID	pInjectorStub;	// Pointer to memory in sub process used
				//  for the injector's loader.
    CONTEXT	preStubContext; // Thread context info before switching to run
				//  the stub.

    typedef Tcl::Hash<HANDLE, TCL_ONE_WORD_KEYS> PTR2HANDLE;
    PTR2HANDLE	spMemMapping;	// Used on Win9x to associate the file mapping
				//  handle to the memory address it provides.

    // A couple NT routines we'll might need when running
    // on NT/2K/XP
    typedef LPVOID (__stdcall *PFNVIRTUALALLOCEX)(HANDLE,LPVOID,SIZE_T,DWORD,DWORD);
    typedef BOOL (__stdcall *PFNVIRTUALFREEEX)(HANDLE,LPVOID,SIZE_T,DWORD);

    PFNVIRTUALALLOCEX pfnVirtualAllocEx;
    PFNVIRTUALFREEEX pfnVirtualFreeEx;

    CMclMailbox *injectorIPC;	// IPC transfer mechanism to the injector dll.

    bool interacting;
    HANDLE interactingConsole;
};

#endif // INC_expWinConsoleDebugger_hpp__

Changes to win/expWinConsoleDebuggerBreakPoints.cpp.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32

33

34
35
36
37
38
39
40
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleDebuggerBreakPoints.cpp,v 1.1.2.9 2002/03/13 03:52:57 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinConsoleDebugger.hpp"


// NOTE:  black magic abounds...  be warry young padwon...


/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::CreateVtSequence --
 *
 *	When moving the cursor to a new location, this will create







>







|





>
|
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleDebuggerBreakPoints.cpp,v 1.1.2.16 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinConsoleDebugger.hpp"

/////////////////////////////////////////////////////////////
// NOTE:  black magic abounds...  be warry young padwon... //
/////////////////////////////////////////////////////////////

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::CreateVtSequence --
 *
 *	When moving the cursor to a new location, this will create
71
72
73
74
75
76
77
78























79
80
81
82
83
84
85
	wsprintfA(buf, "\033[%d;%dH", newPos.Y+1, newPos.X+1);
	count = strlen(buf);
    }
    newPos.X += (SHORT) (n % ConsoleSize.X);
    newPos.Y += (SHORT) (n / ConsoleSize.X);
    CursorPosition = newPos;

    WriteMaster(buf, count);























}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnBeep --
 *







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
	wsprintfA(buf, "\033[%d;%dH", newPos.Y+1, newPos.X+1);
	count = strlen(buf);
    }
    newPos.X += (SHORT) (n % ConsoleSize.X);
    newPos.Y += (SHORT) (n / ConsoleSize.X);
    CursorPosition = newPos;

    WriteMasterCopy(buf, count);
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnAllocConsole --
 *
 * Results:
 *	None
 *
 * Notes:
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnAllocConsole(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }
    __asm nop;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnBeep --
 *
101
102
103
104
105
106
107

108
109
110
111
112
113


114
115
116
117

118
119
120





























121























122
123







































124



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139





























140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267























268
269
270
271
272
273
274
void
ConsoleDebugger::OnBeep(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    CHAR buf[2] = {0,0};

    if (direction == BREAK_IN) {

	// Modify the arguments so a beep doesn't sound in the slave.
	threadInfo->args[1] = 0;
    } else if (direction == BREAK_OUT) {
	if (*returnValue == 0) {
	    buf[0] = 7; // ASCII beep
	    WriteMaster(buf, 1);


	}
    }
}


/*
 *-----------------------------------------------------------------------------
 *





























 * ConsoleDebugger::OnFillConsoleOutputCharacter --























 *
 *	This function gets called when an FillConsoleOutputCharacterA







































 *	or FillConsoleOutputCharacterW breakpoint is hit.



 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnFillConsoleOutputCharacter(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{





























    CHAR buf[4096];
    int bufpos;
    UCHAR c;
    PVOID ptr;
    DWORD i;
    DWORD len;
    COORD coord;
    DWORD lines, preCols, postCols;
    BOOL eol, bol;		// Needs clearing to end, beginning of line
    CONSOLE_SCREEN_BUFFER_INFO info;

    if (*returnValue == 0) {
	return;
    }

    c = (UCHAR) threadInfo->args[1];
    len = threadInfo->args[2];
    coord = *((PCOORD) &(threadInfo->args[3]));
    ptr = (PVOID) threadInfo->args[4];
    if (ptr) {
	ReadSubprocessMemory(proc, ptr, &len, sizeof(DWORD));
    }

    preCols = 0;
    bufpos = 0;
    eol = bol = FALSE;
    if (coord.X) {
	preCols = ConsoleSize.X - coord.X;
	if (len <= preCols) {
	    preCols = len;
	    len = 0;
	    if (len == preCols) {
		eol = TRUE;
	    }
	} else {
	    eol = TRUE;
	    len -= preCols;
	}
    } else if (len < (DWORD) ConsoleSize.X) {
	bol = TRUE;
	preCols = len;
	len = 0;
    }

    lines = len / ConsoleSize.X;
    postCols = len % ConsoleSize.X;

    if (preCols) {
	if (bol) {
	    // Beginning of line to before end of line
	    if (c == ' ') {
		wsprintfA(&buf[bufpos], "\033[%d;%dH\033[1K",
			  coord.Y+1, preCols+coord.X);
		bufpos += strlen(&buf[bufpos]);
	    } else {
		wsprintfA(&buf[bufpos], "\033[%d;%dH",
			  coord.Y+1, coord.X+1);
		bufpos += strlen(&buf[bufpos]);
		memset(&buf[bufpos], c, preCols);
		bufpos += preCols;
	    }
	} else {
	    // After beginning of line to end of line
	    wsprintfA(&buf[bufpos], "\033[%d;%dH", coord.Y+1, coord.X+1);
	    bufpos += strlen(&buf[bufpos]);
	    if (eol && c == ' ') {
		wsprintfA(&buf[bufpos], "\033[K");
		bufpos += strlen(&buf[bufpos]);
	    } else {
		memset(&buf[bufpos], c, preCols);
		bufpos += preCols;
	    }
	}
	coord.X = 0;
	coord.Y++;
    }
    if (lines) {
	if ((c == ' ') && ((lines + coord.Y) >= (DWORD) ConsoleSize.Y)) {
	    // Clear to end of screen
	    wsprintfA(&buf[bufpos], "\033[%d;%dH\033[J",
		      coord.Y+1, coord.X+1);
	    bufpos += strlen(&buf[bufpos]);
	} else if ((c == ' ') && (coord.Y == 0) && (lines > 0)) {
	    // Clear to top of screen
	    wsprintfA(&buf[bufpos], "\033[%d;%dH\033[1J", lines, 1);
	    bufpos += strlen(&buf[bufpos]);
	} else {
	    for (i = 0; i < lines; i++) {
		wsprintfA(&buf[bufpos], "\033[%d;%dH",
			  coord.Y+i+1, coord.X+1);
		bufpos += strlen(&buf[bufpos]);
		if (c == ' ') {
		    wsprintfA(&buf[bufpos], "\033[2K");
		    bufpos += strlen(&buf[bufpos]);
		} else {
		    memset(&buf[bufpos], c, ConsoleSize.X);
		    bufpos += ConsoleSize.X;
		}
	    }
	}
	coord.Y += (SHORT) lines;
    }
	
    if (postCols) {
	if (c == ' ') {
	    // Clear to beginning of line
	    wsprintfA(&buf[bufpos], "\033[%d;%dH\033[1K",
		      coord.Y+1, postCols+coord.X);
	    bufpos += strlen(&buf[bufpos]);
	} else {
	    wsprintfA(&buf[bufpos], "\033[%d;%dH", coord.X+1, coord.Y+1);
	    bufpos += strlen(&buf[bufpos]);
	    memset(&buf[bufpos], c, postCols);
	    bufpos += postCols;
	}
    }
    if (GetConsoleScreenBufferInfo(hMasterConsole, &info) == FALSE) {
	char errbuf[200];
	wsprintfA(errbuf, "handle=0x%08x", hMasterConsole);
	EXP_LOG2(MSG_DT_SCREENBUF, errbuf, ExpSyslogGetSysMsg(GetLastError()));
    } else {
	CursorPosition = info.dwCursorPosition;
	wsprintfA(&buf[bufpos], "\033[%d;%dH",
		  CursorPosition.Y+1, CursorPosition.X+1);
	bufpos += strlen(&buf[bufpos]);
	CursorKnown = TRUE;
    }
    WriteMaster(buf, bufpos);























}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnGetStdHandle --
 *







>





|
>
>
|
|
|
|
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>











|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


<
<

<
<




|
|
<
|
<
<
<
<
<
<





|
|
|
|
|
|




|

|

|
|


|
|




|

|



|

|




|

|



|



|
|


|


|

|






|

|



|




|



|


|


|

|






|







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294


295


296
297
298
299
300
301

302






303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
void
ConsoleDebugger::OnBeep(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    CHAR buf[2] = {0,0};

    if (direction == BREAK_IN) {
	lastBeepDuration = threadInfo->args[1];
	// Modify the arguments so a beep doesn't sound in the slave.
	threadInfo->args[1] = 0;
    } else if (direction == BREAK_OUT) {
	if (*returnValue == 0) {
	    buf[0] = 7; // ASCII beep
	    WriteMasterCopy(buf, 1);
	    if (interacting) {
		Beep(threadInfo->args[0], lastBeepDuration);
	    }
	}
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnCreateConsoleScreenBuffer --
 *
 *	This function gets called when a CreateConsoleScreenBuffer
 *	breakpoint is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	unknown.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnCreateConsoleScreenBuffer(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }
    // TODO: what to do here?
    __asm nop;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnFillConsoleOutputAttribute --
 *
 * Results:
 *	None
 *
 * Notes:
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnFillConsoleOutputAttribute(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }
    __asm nop;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnFillConsoleOutputCharacterA --
 *
 *	This function gets called when an FillConsoleOutputCharacterA
 *	breakpoint is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnFillConsoleOutputCharacterA(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    CHAR cCharacter;
    DWORD nLength;
    COORD dwWriteCoord;
    PVOID ptr;

    if (*returnValue == 0) {
	return;
    }

    cCharacter = (CHAR) threadInfo->args[1];
    nLength = threadInfo->args[2];
    dwWriteCoord = *((PCOORD) &(threadInfo->args[3]));
    ptr = (PVOID) threadInfo->args[4];
    if (ptr) {
	ReadSubprocessMemory(proc, ptr, &nLength, sizeof(DWORD));
    }

    OnFillCOC_Finish(cCharacter, nLength, dwWriteCoord);
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnFillConsoleOutputCharacterW --
 *
 *	This function gets called when an FillConsoleOutputCharacterW
 *	breakpoint is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnFillConsoleOutputCharacterW(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    CHAR cCharacter;
    WCHAR cWCharacter;
    DWORD nLength;
    COORD dwWriteCoord;
    PVOID ptr;

    if (*returnValue == 0) {
	return;
    }

    cWCharacter = (WCHAR) threadInfo->args[1];
    nLength = threadInfo->args[2];
    dwWriteCoord = *((PCOORD) &(threadInfo->args[3]));
    ptr = (PVOID) threadInfo->args[4];
    if (ptr) {
	ReadSubprocessMemory(proc, ptr, &nLength, sizeof(DWORD));
    }

    // For now, just truncated it.
    // TODO: fix me!
    //
    cCharacter = (cWCharacter & 0xff);

    OnFillCOC_Finish(cCharacter, nLength, dwWriteCoord);
}

void
ConsoleDebugger::OnFillCOC_Finish(CHAR cCharacter, DWORD nLength, COORD dwWriteCoord)
{
    CHAR buf[4096];
    int bufpos;


    DWORD i;


    DWORD lines, preCols, postCols;
    BOOL eol, bol;		// Needs clearing to end, beginning of line
    CONSOLE_SCREEN_BUFFER_INFO info;

    if (interacting) {
	DWORD dwWritten;

	FillConsoleOutputCharacter(interactingConsole, cCharacter, nLength, dwWriteCoord, &dwWritten);






    }

    preCols = 0;
    bufpos = 0;
    eol = bol = FALSE;
    if (dwWriteCoord.X) {
	preCols = ConsoleSize.X - dwWriteCoord.X;
	if (nLength <= preCols) {
	    preCols = nLength;
	    nLength = 0;
	    if (nLength == preCols) {
		eol = TRUE;
	    }
	} else {
	    eol = TRUE;
	    nLength -= preCols;
	}
    } else if (nLength < (DWORD) ConsoleSize.X) {
	bol = TRUE;
	preCols = nLength;
	nLength = 0;
    }

    lines = nLength / ConsoleSize.X;
    postCols = nLength % ConsoleSize.X;

    if (preCols) {
	if (bol) {
	    // Beginning of line to before end of line
	    if (cCharacter == ' ') {
		wsprintfA(&buf[bufpos], "\033[%d;%dH\033[1K",
			  dwWriteCoord.Y+1, preCols+dwWriteCoord.X);
		bufpos += strlen(&buf[bufpos]);
	    } else {
		wsprintfA(&buf[bufpos], "\033[%d;%dH",
			  dwWriteCoord.Y+1, dwWriteCoord.X+1);
		bufpos += strlen(&buf[bufpos]);
		memset(&buf[bufpos], cCharacter, preCols);
		bufpos += preCols;
	    }
	} else {
	    // After beginning of line to end of line
	    wsprintfA(&buf[bufpos], "\033[%d;%dH", dwWriteCoord.Y+1, dwWriteCoord.X+1);
	    bufpos += strlen(&buf[bufpos]);
	    if (eol && cCharacter == ' ') {
		wsprintfA(&buf[bufpos], "\033[K");
		bufpos += strlen(&buf[bufpos]);
	    } else {
		memset(&buf[bufpos], cCharacter, preCols);
		bufpos += preCols;
	    }
	}
	dwWriteCoord.X = 0;
	dwWriteCoord.Y++;
    }
    if (lines) {
	if ((cCharacter == ' ') && ((lines + dwWriteCoord.Y) >= (DWORD) ConsoleSize.Y)) {
	    // Clear to end of screen
	    wsprintfA(&buf[bufpos], "\033[%d;%dH\033[J",
		      dwWriteCoord.Y+1, dwWriteCoord.X+1);
	    bufpos += strlen(&buf[bufpos]);
	} else if ((cCharacter == ' ') && (dwWriteCoord.Y == 0) && (lines > 0)) {
	    // Clear to top of screen
	    wsprintfA(&buf[bufpos], "\033[%d;%dH\033[1J", lines, 1);
	    bufpos += strlen(&buf[bufpos]);
	} else {
	    for (i = 0; i < lines; i++) {
		wsprintfA(&buf[bufpos], "\033[%d;%dH",
			  dwWriteCoord.Y+i+1, dwWriteCoord.X+1);
		bufpos += strlen(&buf[bufpos]);
		if (cCharacter == ' ') {
		    wsprintfA(&buf[bufpos], "\033[2K");
		    bufpos += strlen(&buf[bufpos]);
		} else {
		    memset(&buf[bufpos], cCharacter, ConsoleSize.X);
		    bufpos += ConsoleSize.X;
		}
	    }
	}
	dwWriteCoord.Y += (SHORT) lines;
    }
	
    if (postCols) {
	if (cCharacter == ' ') {
	    // Clear to beginning of line
	    wsprintfA(&buf[bufpos], "\033[%d;%dH\033[1K",
		      dwWriteCoord.Y+1, postCols+dwWriteCoord.X);
	    bufpos += strlen(&buf[bufpos]);
	} else {
	    wsprintfA(&buf[bufpos], "\033[%d;%dH", dwWriteCoord.X+1, dwWriteCoord.Y+1);
	    bufpos += strlen(&buf[bufpos]);
	    memset(&buf[bufpos], cCharacter, postCols);
	    bufpos += postCols;
	}
    }
    if (GetConsoleScreenBufferInfo(hMasterConsole, &info) == FALSE) {
	char errbuf[200];
	wsprintfA(errbuf, "handle=0x%08x", hMasterConsole);
	EXP_LOG2(MSG_DT_SCREENBUF, errbuf, GetSysMsg(GetLastError()));
    } else {
	CursorPosition = info.dwCursorPosition;
	wsprintfA(&buf[bufpos], "\033[%d;%dH",
		  CursorPosition.Y+1, CursorPosition.X+1);
	bufpos += strlen(&buf[bufpos]);
	CursorKnown = TRUE;
    }
    WriteMasterCopy(buf, bufpos);
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnFreeConsole --
 *
 * Results:
 *	None
 *
 * Notes:
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnFreeConsole(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }
    __asm nop;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnGetStdHandle --
 *
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnReadConsoleInput --
 *
 *	This function gets called when a ReadConsoleInput breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Notes:
 *	If this is ever used for real, there need to be ASCII
 *	and UNICODE versions.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnReadConsoleInput(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnScrollConsoleScreenBuffer --
 *
 *	This funtions gets called when a ScrollConsoleScreenBuffer
 *	breakpoint is hit.
 *
 * Results:
 *	None







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







535
536
537
538
539
540
541
























542
543
544
545
546
547
548
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
























 * ConsoleDebugger::OnScrollConsoleScreenBuffer --
 *
 *	This funtions gets called when a ScrollConsoleScreenBuffer
 *	breakpoint is hit.
 *
 * Results:
 *	None
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
		      scroll.Top+1,dest.Y+1+(scroll.Bottom - scroll.Top),
		      scroll.Top+1,1,
		      dest.Y - scroll.Top);
	}
	count = strlen(&buf[count]);
	wsprintf(&buf[count], "\033[%d;%dr", 1, ConsoleSize.Y);
	count += strlen(&buf[count]);
	WriteMaster(buf, count);
    } else {
//	RefreshScreen(&proc->overlapped);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleMode --
 *
 *	This function gets called when a SetConsoleMode breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Sets some flags that are used in determining echoing
 *	characteristics of the slave driver.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleMode(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    DWORD i;
    BOOL found;

    // The console mode seems to get set even if the return value is FALSE
    if (*returnValue == FALSE) {
	return;
    }
    for (found = FALSE, i = 0; i < proc->consoleHandlesMax; i++) {
	if (threadInfo->args[0] == proc->consoleHandles[i]) {
	    found = TRUE;
	    break;
	}
    }
    if (found) {
	MasterConsoleInputMode = threadInfo->args[1];
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleActiveScreenBuffer --
 *
 *	This function gets called when a SetConsoleActiveScreenBuffer
 *	breakpoint is hit.







|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







600
601
602
603
604
605
606
607
608
609
610
611
612








































613
614
615
616
617
618
619
		      scroll.Top+1,dest.Y+1+(scroll.Bottom - scroll.Top),
		      scroll.Top+1,1,
		      dest.Y - scroll.Top);
	}
	count = strlen(&buf[count]);
	wsprintf(&buf[count], "\033[%d;%dr", 1, ConsoleSize.Y);
	count += strlen(&buf[count]);
	WriteMasterCopy(buf, count);
    } else {
//	RefreshScreen(&proc->overlapped);
    }
}









































/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleActiveScreenBuffer --
 *
 *	This function gets called when a SetConsoleActiveScreenBuffer
 *	breakpoint is hit.
532
533
534
535
536
537
538

539
540
541
542
543


























































544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572

573




574

















575



576






















577
578


























































579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598



















599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }


//    RefreshScreen(&proc->overlapped);
}

/*
 *----------------------------------------------------------------------


























































 *
 * ConsoleDebugger::OnSetConsoleCursorPosition --
 *
 *	This function gets called when a SetConsoleCursorPosition breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Updates the current console cursor position
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleCursorPosition(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    CHAR buf[50];
    DWORD count;

    if (*returnValue == FALSE) {
	return;
    }
    CursorPosition = *((PCOORD) &threadInfo->args[1]);

    wsprintfA(buf, "\033[%d;%dH", CursorPosition.Y+1, CursorPosition.X+1);

    count = strlen(buf);




    WriteMaster(buf, count);

















}


























/*
 *----------------------------------------------------------------------


























































 *
 * ConsoleDebugger::OnSetConsoleWindowInfo --
 *
 *	This function gets called when a SetConsoleWindowInfo breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Updates the current console cursor position
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleWindowInfo(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{



















}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleA --
 *
 *	This function gets called when an WriteConsoleA breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleA(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    CHAR buf[1024];







>




|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|

|







|







|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|













|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }

    __asm nop;
//    RefreshScreen(&proc->overlapped);
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleCP --
 *
 * Results:
 *	None
 *
 * Notes:
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleCP(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }
    ConsoleCP = (UINT) threadInfo->args[0];

    if (interacting) {
	SetConsoleCP(ConsoleCP);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleCursorInfo --
 *
 * Results:
 *	None
 *
 * Notes:
 *	Updates the current console's cursor info.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleCursorInfo(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    PVOID ptr;

    if (*returnValue == FALSE) {
	return;
    }
    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, &CursorInfo, sizeof(CONSOLE_CURSOR_INFO));

    if (interacting) {
	SetConsoleCursorInfo(interactingConsole, &CursorInfo);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleCursorPosition --
 *
 *	This function gets called when a SetConsoleCursorPosition breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Updates the current console's cursor position
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleCursorPosition(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    static CHAR buf[50];
    DWORD count;

    if (*returnValue == FALSE) {
	return;
    }
    CursorPosition = *((PCOORD) &threadInfo->args[1]);

    count = wsprintf(buf, "\033[%d;%dH", CursorPosition.Y+1, CursorPosition.X+1);
    WriteMasterCopy(buf, count);

    if (interacting) {
	SetConsoleCursorPosition(interactingConsole, CursorPosition);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleMode --
 *
 *	This function gets called when a SetConsoleMode breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Sets some flags that are used in determining echoing
 *	characteristics of the slave driver.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleMode(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    DWORD i;
    BOOL found;

    // The console mode seems to get set even if the return value is FALSE
    if (*returnValue == FALSE) {
	return;
    }
    for (found = FALSE, i = 0; i < proc->consoleHandlesMax; i++) {
	if (threadInfo->args[0] == proc->consoleHandles[i]) {
	    found = TRUE;
	    break;
	}
    }
    if (found) {
	ConsoleInputMode = threadInfo->args[1];
    }

    if (interacting) {
	SetConsoleMode(interactingConsole, ConsoleInputMode);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleOutputCP --
 *
 * Results:
 *	None
 *
 * Notes:
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleOutputCP(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    if (*returnValue == FALSE) {
	return;
    }
    ConsoleOutputCP = (UINT) threadInfo->args[0];

    if (interacting) {
	SetConsoleOutputCP(ConsoleOutputCP);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleTextAttribute --
 *
 * Results:
 *	None
 *
 * Notes:
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleTextAttribute(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    WORD wAttributes;

    wAttributes = (WORD) threadInfo->args[1];

    // TODO: fix me!
    //
    __asm nop;

    if (interacting) {
	SetConsoleTextAttribute(interactingConsole, wAttributes);
    }

}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnSetConsoleWindowInfo --
 *
 *	This function gets called when a SetConsoleWindowInfo breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Updates the current console cursor position
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnSetConsoleWindowInfo(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    HANDLE hConsoleOutput;
    BOOL bAbsolute;
    SMALL_RECT ConsoleWindowRect;
    PVOID ptr;

    if (*returnValue == FALSE) {
	return;
    }

    hConsoleOutput = (HANDLE) threadInfo->args[0];
    bAbsolute = threadInfo->args[1];
    ptr = (PVOID) threadInfo->args[2];
    if (ptr) {
	ReadSubprocessMemory(proc, ptr, &ConsoleWindowRect, sizeof(SMALL_RECT));
    }

    // TODO: fix me!  What do we do here?
    //
    __asm nop;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleA --
 *
 *	This function gets called when an WriteConsoleA breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleA(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    CHAR buf[1024];
639
640
641
642
643
644
645
646
647





648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
	p = new CHAR [n];
    } else {
	p = buf;
    }

    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, p, n * sizeof(CHAR));
//    ResetEvent(proc->overlapped.hEvent);
    WriteMaster(p, n);






    if (p != buf) {
	delete [] p;
    }
    CursorKnown = FALSE;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleW --
 *
 *	This function gets called when an WriteConsoleW breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleW(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    static WCHAR buf[1024];







<
|
>
>
>
>
>








|












|







923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
	p = new CHAR [n];
    } else {
	p = buf;
    }

    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, p, n * sizeof(CHAR));

    WriteMasterCopy(p, n);

    if (interacting) {
	DWORD x;
	WriteConsole(interactingConsole, p, n, &x, 0L);
    }

    if (p != buf) {
	delete [] p;
    }
    CursorKnown = FALSE;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleW --
 *
 *	This function gets called when an WriteConsoleW breakpoint
 *	is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleW(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    static WCHAR buf[1024];
695
696
697
698
699
700
701
702
703
704
705
706
707





708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
	a = new CHAR [n * 2];
    } else {
	p = buf;
	a = ansi;
	asize = sizeof(ansi);
    }
    ReadSubprocessMemory(proc, ptr, p, n * sizeof(WCHAR));
//    ResetEvent(proc->overlapped.hEvent);

    // Convert to ASCII and write the intercepted data to the pipe.
    //
    w = WideCharToMultiByte(CP_ACP, 0, p, n, a, asize, 0L, 0L);
    WriteMaster(a, w);






    if (p != buf) {
	delete [] p, a;
    }
    CursorKnown = FALSE;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputA --
 *
 *	This function gets called when an WriteConsoleOutputA breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputA(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{







<

|


|
>
>
>
>
>








|













|







983
984
985
986
987
988
989

990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
	a = new CHAR [n * 2];
    } else {
	p = buf;
	a = ansi;
	asize = sizeof(ansi);
    }
    ReadSubprocessMemory(proc, ptr, p, n * sizeof(WCHAR));


    // Convert to ASCII and write-out the intercepted data.
    //
    w = WideCharToMultiByte(CP_ACP, 0, p, n, a, asize, 0L, 0L);
    WriteMasterCopy(a, w);

    if (interacting) {
	DWORD x;
	WriteConsole(interactingConsole, a, w, &x, 0L);
    }

    if (p != buf) {
	delete [] p, a;
    }
    CursorKnown = FALSE;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputA --
 *
 *	This function gets called when an WriteConsoleOutputA breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputA(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
	return;
    }

    bufferSize = *((PCOORD) &threadInfo->args[2]);
    bufferCoord = *((PCOORD) &threadInfo->args[3]);
    ptr = (PVOID) threadInfo->args[4]; // Get the rectangle written
    if (ptr == 0L) return;
    ReadSubprocessMemory(proc, ptr, &writeRegion,sizeof(SMALL_RECT));

    ptr = (PVOID) threadInfo->args[1]; // Get character array
    if (ptr == 0L) return;

    n = bufferSize.X * bufferSize.Y * sizeof(CHAR_INFO);
    charBuf = new CHAR_INFO [n];








|







1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
	return;
    }

    bufferSize = *((PCOORD) &threadInfo->args[2]);
    bufferCoord = *((PCOORD) &threadInfo->args[3]);
    ptr = (PVOID) threadInfo->args[4]; // Get the rectangle written
    if (ptr == 0L) return;
    ReadSubprocessMemory(proc, ptr, &writeRegion, sizeof(SMALL_RECT));

    ptr = (PVOID) threadInfo->args[1]; // Get character array
    if (ptr == 0L) return;

    n = bufferSize.X * bufferSize.Y * sizeof(CHAR_INFO);
    charBuf = new CHAR_INFO [n];

777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798




799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
	pcb += bufferCoord.X;
	p = buf;
	maxbuf = sizeof(buf);
	end = buf + maxbuf;
	for (x = 0; x <= writeRegion.Right - writeRegion.Left; x++, pcb++) {
	    *p++ = pcb->Char.AsciiChar;
	    if (p == end) {
//		ResetEvent(proc->overlapped.hEvent);
		WriteMaster(buf, maxbuf);
		p = buf;
	    }
	}
	curr.X = writeRegion.Left;
	curr.Y = writeRegion.Top + y;
	n = writeRegion.Right - writeRegion.Left;
	CreateVtSequence(proc, curr, n);
//	ResetEvent(proc->overlapped.hEvent);

	maxbuf = p - buf;
	WriteMaster(buf, maxbuf);
	buf[maxbuf] = 0;
    }





    delete [] charBuf;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputW --
 *
 *	This function gets called when an WriteConsoleOutputW breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputW(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{







<
|







<


|


>
>
>
>





|













|







1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
	pcb += bufferCoord.X;
	p = buf;
	maxbuf = sizeof(buf);
	end = buf + maxbuf;
	for (x = 0; x <= writeRegion.Right - writeRegion.Left; x++, pcb++) {
	    *p++ = pcb->Char.AsciiChar;
	    if (p == end) {

		WriteMasterCopy(buf, maxbuf);
		p = buf;
	    }
	}
	curr.X = writeRegion.Left;
	curr.Y = writeRegion.Top + y;
	n = writeRegion.Right - writeRegion.Left;
	CreateVtSequence(proc, curr, n);


	maxbuf = p - buf;
	WriteMasterCopy(buf, maxbuf);
	buf[maxbuf] = 0;
    }

    if (interacting) {
	WriteConsoleOutput(interactingConsole, charBuf, bufferSize, bufferCoord, &writeRegion);
    }

    delete [] charBuf;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputW --
 *
 *	This function gets called when an WriteConsoleOutputW breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputW(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886




887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916

917
918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938

939



940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

977
978
979
980
981
982
983
984
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010





1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
















































	pcb += bufferCoord.X;
	p = buf;
	maxbuf = sizeof(buf);
	end = buf + maxbuf;
	for (x = 0; x <= writeRegion.Right - writeRegion.Left; x++, pcb++) {
	    *p++ = (CHAR) (pcb->Char.UnicodeChar & 0xff);
	    if (p == end) {
//		ResetEvent(proc->overlapped.hEvent);
		WriteMaster((char *)buf, maxbuf);
		p = buf;
	    }
	}
	curr.X = writeRegion.Left;
	curr.Y = writeRegion.Top + y;
	n = writeRegion.Right - writeRegion.Left;
	CreateVtSequence(proc, curr, n);
//	ResetEvent(proc->overlapped.hEvent);

	maxbuf = p - buf;
	WriteMaster((char *)buf, maxbuf);
	buf[maxbuf] = 0;
    }





    delete [] charBuf;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputCharacterA --
 *
 *	This function gets called when an WriteConsoleOutputCharacterA breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputCharacterA(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    static CHAR buf[1024];
    PVOID ptr;
    DWORD n;
    PCHAR p;


    if (*returnValue == 0) {
	return;
    }
    // Get number of bytes written
    ptr = (PVOID) threadInfo->args[4];
    if (ptr == 0L) {
	n = threadInfo->args[2];
    } else {
	ReadSubprocessMemory(proc, ptr, &n, sizeof(DWORD));
    }

    CreateVtSequence(proc, *((PCOORD) &threadInfo->args[3]), n);


    if (n > 1024) {
	p = new CHAR [n];
    } else {
	p = buf;
    }

    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, p, n * sizeof(CHAR));

//    ResetEvent(proc->overlapped.hEvent);




    WriteMaster(p, n);

    if (p != buf) {
	delete [] p;
    }
    CursorKnown = FALSE;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputCharacterW --
 *
 *	This function gets called when an WriteConsoleOutputCharacterW
 *	breakpoint is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputCharacterW(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    static WCHAR buf[1024];
    static CHAR ansi[2048];
    PVOID ptr;
    DWORD n;
    PWCHAR p;
    PCHAR a;

    int asize;
    int w;

    if (*returnValue == 0) {
	return;
    }
    // Get number of bytes written
    ptr = (PVOID) threadInfo->args[4];
    if (ptr == 0L) {
	n = threadInfo->args[2];
    } else {
	ReadSubprocessMemory(proc, ptr, &n, sizeof(DWORD));
    }

    CreateVtSequence(proc, *((PCOORD) &threadInfo->args[3]), n);


    if (n > 1024) {
	p = new WCHAR [n];
	asize = n * 2 * sizeof(CHAR);
	a = new CHAR [n * 2];
    } else {
	p = buf;
	a = ansi;
	asize = sizeof(ansi);
    }

    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, p, n * sizeof(WCHAR));
//    ResetEvent(proc->overlapped.hEvent);

    // Convert to ASCI and Write the intercepted data to the pipe.
    w = WideCharToMultiByte(CP_ACP, 0, p, n, a, asize, 0L, 0L);
    WriteMaster(a, w);






    if (p != buf) {
	delete [] p, a;
    }
    CursorKnown = FALSE;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleDebugger::OnIsWindowVisible --
 *
 *	This routine gets called when IsWindowVisible is called.
 *	The MKS Korn shell uses this as an indication of a window
 *	that can be seen by the user.  If the window can't be seen,
 *	it pops up a graphical error notification.  We really, really
 *	don't want those damn things popping up, so this helps avoid
 *	it.  And there really doesn't seem to be any good reason to
 *	return FALSE given that nobody is ever going to see anything.
 *
 * Results:
 *	None
 *
 *----------------------------------------------------------------------
 */

void
ConsoleDebugger::OnIsWindowVisible(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    *returnValue = TRUE;
}























































<
|







<


|


>
>
>
>





|













|








|
|
>







|

|


|
>

|
|

|



|
>
|
>
>
>
|
<

|
|





|












|










|

|
>

<







|

|


|
>

|
|
|
|


|




|
<


|
|

>
>
>
>
>

|





|














|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242

1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306

1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
	pcb += bufferCoord.X;
	p = buf;
	maxbuf = sizeof(buf);
	end = buf + maxbuf;
	for (x = 0; x <= writeRegion.Right - writeRegion.Left; x++, pcb++) {
	    *p++ = (CHAR) (pcb->Char.UnicodeChar & 0xff);
	    if (p == end) {

		WriteMasterCopy((char *)buf, maxbuf);
		p = buf;
	    }
	}
	curr.X = writeRegion.Left;
	curr.Y = writeRegion.Top + y;
	n = writeRegion.Right - writeRegion.Left;
	CreateVtSequence(proc, curr, n);


	maxbuf = p - buf;
	WriteMasterCopy((char *)buf, maxbuf);
	buf[maxbuf] = 0;
    }

    if (interacting) {
	WriteConsoleOutput(interactingConsole, charBuf, bufferSize, bufferCoord, &writeRegion);
    }

    delete [] charBuf;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputCharacterA --
 *
 *	This function gets called when an WriteConsoleOutputCharacterA breakpoint
 *	is hit.  The data is also redirected to expect since expect
 *	normally couldn't see any output going through this interface.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputCharacterA(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    static CHAR buf[1024];
    PVOID ptr;
    DWORD nLength;
    PCHAR lpCharacter;
    COORD dwWriteCoord;

    if (*returnValue == 0) {
	return;
    }
    // Get number of bytes written
    ptr = (PVOID) threadInfo->args[4];
    if (ptr == 0L) {
	nLength = threadInfo->args[2];
    } else {
	ReadSubprocessMemory(proc, ptr, &nLength, sizeof(DWORD));
    }

    dwWriteCoord = *((PCOORD) &threadInfo->args[3]);
    CreateVtSequence(proc, dwWriteCoord, nLength);

    if (nLength > 1024) {
	lpCharacter = new CHAR [nLength];
    } else {
	lpCharacter = buf;
    }

    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, lpCharacter, nLength * sizeof(CHAR));
    WriteMasterCopy(lpCharacter, nLength);

    if (interacting) {
	DWORD dwWritten;
	WriteConsoleOutputCharacter(interactingConsole, lpCharacter, nLength, dwWriteCoord, &dwWritten);
    }


    if (lpCharacter != buf) {
	delete [] lpCharacter;
    }
    CursorKnown = FALSE;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteConsoleOutputCharacterW --
 *
 *	This function gets called when an WriteConsoleOutputCharacterW
 *	breakpoint is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	Prints some output.
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteConsoleOutputCharacterW(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    static WCHAR buf[1024];
    static CHAR ansi[2048];
    PVOID ptr;
    DWORD nLength;
    PWCHAR p;
    PCHAR lpCharacter;
    COORD dwWriteCoord;
    int asize;


    if (*returnValue == 0) {
	return;
    }
    // Get number of bytes written
    ptr = (PVOID) threadInfo->args[4];
    if (ptr == 0L) {
	nLength = threadInfo->args[2];
    } else {
	ReadSubprocessMemory(proc, ptr, &nLength, sizeof(DWORD));
    }

    dwWriteCoord = *((PCOORD) &threadInfo->args[3]);
    CreateVtSequence(proc, dwWriteCoord, nLength);

    if (nLength > 1024) {
	p = new WCHAR [nLength];
	asize = nLength * 2 * sizeof(CHAR);
	lpCharacter = new CHAR [nLength * 2];
    } else {
	p = buf;
	lpCharacter = ansi;
	asize = sizeof(ansi);
    }

    ptr = (PVOID) threadInfo->args[1];
    ReadSubprocessMemory(proc, ptr, p, nLength * sizeof(WCHAR));


    // Convert to ASCI and Write the intercepted data to the pipe.
    nLength = WideCharToMultiByte(CP_ACP, 0, p, nLength, lpCharacter, asize, 0L, 0L);
    WriteMasterCopy(lpCharacter, nLength);

    if (interacting) {
	DWORD dwWritten;
	WriteConsoleOutputCharacter(interactingConsole, lpCharacter, nLength, dwWriteCoord, &dwWritten);
    }

    if (p != buf) {
	delete [] p, lpCharacter;
    }
    CursorKnown = FALSE;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnIsWindowVisible --
 *
 *	This routine gets called when IsWindowVisible is called.
 *	The MKS Korn shell uses this as an indication of a window
 *	that can be seen by the user.  If the window can't be seen,
 *	it pops up a graphical error notification.  We really, really
 *	don't want those damn things popping up, so this helps avoid
 *	it.  And there really doesn't seem to be any good reason to
 *	return FALSE given that nobody is ever going to see anything.
 *
 * Results:
 *	None
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnIsWindowVisible(Process *proc, ThreadInfo *threadInfo,
    Breakpoint *brkpt, PDWORD returnValue, DWORD direction)
{
    *returnValue = TRUE;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ConsoleDebugger::OnWriteFile --
 *
 *	This function gets called when a WriteFile
 *	breakpoint is hit.
 *
 * Results:
 *	None
 *
 * Side Effects:
 *	none yet..
 *
 *-----------------------------------------------------------------------------
 */

void
ConsoleDebugger::OnWriteFile(Process *proc,
    ThreadInfo *threadInfo, Breakpoint *brkpt, PDWORD returnValue,
    DWORD direction)
{
    HANDLE hFile;		    // handle to file
    PCHAR lpBuffer;		    // data buffer
    DWORD nNumberOfBytesToWrite;    // number of bytes to write
//    LPOVERLAPPED lpOverlapped;	    // overlapped buffer
    PVOID ptr;

    hFile = (HANDLE) threadInfo->args[0];

    // TODO: is this a console handle in the slave?
    return;

    // Get number of bytes written, if available.
    ptr = (PVOID) threadInfo->args[4];
    if (ptr == 0L) {
	nNumberOfBytesToWrite = threadInfo->args[2];
    } else {
	ReadSubprocessMemory(proc, ptr, &nNumberOfBytesToWrite, sizeof(DWORD));
    }

    ptr = (PVOID) threadInfo->args[1];
    lpBuffer = new CHAR [nNumberOfBytesToWrite];
    ReadSubprocessMemory(proc, ptr, lpBuffer, nNumberOfBytesToWrite);

    delete lpBuffer;
}

Added win/expWinConsoleKeyMap.cpp.





























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/* ----------------------------------------------------------------------------
 * expWinConsoleKeyMap.cpp --
 *
 *	Routines for recomposing a string into a series of keypress events.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinConsoleKeyMap.cpp,v 1.1.2.2 2002/06/23 09:26:28 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinSlave.hpp"

struct KEY_MATRIX {
    WORD wVirtualKeyCode;
    WORD wVirtualScanCode;
    DWORD dwControlKeyState;
};

static const KEY_MATRIX ModifierKeyArray[] = {
/* Control */ { 17,  29, 0},
/* LShift */  { 16,  42, 0},
/* RShift */  { 16,  54, 0},
/* Alt */     { 18,  56, 0},
};

static const KEY_MATRIX AsciiToKeyArray[] = {
/*   0 */ { 50,   3, RIGHT_CTRL_PRESSED|SHIFT_PRESSED},
/*   1 */ { 65,  30, RIGHT_CTRL_PRESSED},
/*   2 */ { 66,  48, RIGHT_CTRL_PRESSED},
/*   3 */ { 67,  46, RIGHT_CTRL_PRESSED},
/*   4 */ { 68,  32, RIGHT_CTRL_PRESSED},
/*   5 */ { 69,  18, RIGHT_CTRL_PRESSED},
/*   6 */ { 70,  33, RIGHT_CTRL_PRESSED},
/*   7 */ { 71,  34, RIGHT_CTRL_PRESSED},
/*   8 */ { 72,  35, RIGHT_CTRL_PRESSED},
/*   9 */ {  9,  15, RIGHT_CTRL_PRESSED},
/*  10 */ { 74,  36, RIGHT_CTRL_PRESSED},
/*  11 */ { 75,  37, RIGHT_CTRL_PRESSED},
/*  12 */ { 76,  38, RIGHT_CTRL_PRESSED},
/*  13 */ { 13,  28, 0},
/*  14 */ { 78,  49, RIGHT_CTRL_PRESSED},
/*  15 */ { 79,  24, RIGHT_CTRL_PRESSED},
/*  16 */ { 80,  25, RIGHT_CTRL_PRESSED},
/*  17 */ { 81,  16, RIGHT_CTRL_PRESSED},
/*  18 */ { 82,  19, RIGHT_CTRL_PRESSED},
/*  19 */ { 83,  31, RIGHT_CTRL_PRESSED},
/*  20 */ { 84,  20, RIGHT_CTRL_PRESSED},
/*  21 */ { 85,  22, RIGHT_CTRL_PRESSED},
/*  22 */ { 86,  47, RIGHT_CTRL_PRESSED},
/*  23 */ { 87,  17, RIGHT_CTRL_PRESSED},
/*  24 */ { 88,  45, RIGHT_CTRL_PRESSED},
/*  25 */ { 89,  21, RIGHT_CTRL_PRESSED},
/*  26 */ { 90,  44, RIGHT_CTRL_PRESSED},
/*  27 */ {219, 219, RIGHT_CTRL_PRESSED|SHIFT_PRESSED},
/*  28 */ {220, 220, RIGHT_CTRL_PRESSED|SHIFT_PRESSED},
/*  29 */ {221, 221, RIGHT_CTRL_PRESSED|SHIFT_PRESSED},
/*  30 */ { 54,  54, RIGHT_CTRL_PRESSED|SHIFT_PRESSED},
/*  31 */ {189, 189, RIGHT_CTRL_PRESSED|SHIFT_PRESSED},
/*  32 */ { 32,  32, 0},
/*  33 */ { 49,  49, SHIFT_PRESSED},
/*  34 */ {222, 222, SHIFT_PRESSED},
/*  35 */ { 51,  51, SHIFT_PRESSED},
/*  36 */ { 52,  52, SHIFT_PRESSED},
/*  37 */ { 53,  53, SHIFT_PRESSED},
/*  38 */ { 55,  55, SHIFT_PRESSED},
/*  39 */ {222, 222, 0},
/*  40 */ { 57,  57, SHIFT_PRESSED},
/*  41 */ { 48,  48, SHIFT_PRESSED},
/*  42 */ { 56,  56, SHIFT_PRESSED},
/*  43 */ {187, 187, SHIFT_PRESSED},
/*  44 */ {188, 188, 0},
/*  45 */ {189, 189, SHIFT_PRESSED},
/*  46 */ {190, 190, 0},
/*  47 */ {191, 191, 0},
/*  48 */ { 48,  48, 0},
/*  49 */ { 49,  49, 0},
/*  50 */ { 50,   3, 0},
/*  51 */ { 51,  51, 0},
/*  52 */ { 52,  52, 0},
/*  53 */ { 53,  53, 0},
/*  54 */ { 54,  54, 0},
/*  55 */ { 55,  55, 0},
/*  56 */ { 56,  56, 0},
/*  57 */ { 57,  57, 0},
/*  58 */ {186, 186, SHIFT_PRESSED},
/*  59 */ {186, 186, 0},
/*  60 */ {188, 188, SHIFT_PRESSED},
/*  61 */ {187, 187, SHIFT_PRESSED},
/*  62 */ {190, 190, SHIFT_PRESSED},
/*  63 */ {191, 191, SHIFT_PRESSED},
/*  64 */ { 50,   3, 0},
/*  65 */ { 65,  30, SHIFT_PRESSED},
/*  66 */ { 66,  48, SHIFT_PRESSED},
/*  67 */ { 67,  46, SHIFT_PRESSED},
/*  68 */ { 68,  32, SHIFT_PRESSED},
/*  69 */ { 69,  18, SHIFT_PRESSED},
/*  70 */ { 70,  33, SHIFT_PRESSED},
/*  71 */ { 71,  34, SHIFT_PRESSED},
/*  72 */ { 72,  35, SHIFT_PRESSED},
/*  73 */ { 73,  23, SHIFT_PRESSED},
/*  74 */ { 74,  36, SHIFT_PRESSED},
/*  75 */ { 75,  37, SHIFT_PRESSED},
/*  76 */ { 76,  38, SHIFT_PRESSED},
/*  77 */ { 77,  50, SHIFT_PRESSED},
/*  78 */ { 78,  49, SHIFT_PRESSED},
/*  79 */ { 79,  24, SHIFT_PRESSED},
/*  80 */ { 80,  25, SHIFT_PRESSED},
/*  81 */ { 81,  16, SHIFT_PRESSED},
/*  82 */ { 82,  19, SHIFT_PRESSED},
/*  83 */ { 83,  31, SHIFT_PRESSED},
/*  84 */ { 84,  20, SHIFT_PRESSED},
/*  85 */ { 85,  22, SHIFT_PRESSED},
/*  86 */ { 86,  47, SHIFT_PRESSED},
/*  87 */ { 87,  17, SHIFT_PRESSED},
/*  88 */ { 88,  45, SHIFT_PRESSED},
/*  89 */ { 89,  21, SHIFT_PRESSED},
/*  90 */ { 90,  44, SHIFT_PRESSED},
/*  91 */ {219, 219, 0},
/*  92 */ {220, 220, 0},
/*  93 */ {221, 221, 0},
/*  94 */ { 54,  54, SHIFT_PRESSED},
/*  95 */ {189, 189, SHIFT_PRESSED},
/*  96 */ {192, 192, 0},
/*  97 */ { 65,  30, 0},
/*  98 */ { 66,  48, 0},
/*  99 */ { 67,  46, 0},
/* 100 */ { 68,  32, 0},
/* 101 */ { 69,  18, 0},
/* 102 */ { 70,  33, 0},
/* 103 */ { 71,  34, 0},
/* 104 */ { 72,  35, 0},
/* 105 */ { 73,  23, 0},
/* 106 */ { 74,  36, 0},
/* 107 */ { 75,  37, 0},
/* 108 */ { 76,  38, 0},
/* 109 */ { 77,  50, 0},
/* 110 */ { 78,  49, 0},
/* 111 */ { 79,  24, 0},
/* 112 */ { 80,  25, 0},
/* 113 */ { 81,  16, 0},
/* 114 */ { 82,  19, 0},
/* 115 */ { 83,  31, 0},
/* 116 */ { 84,  20, 0},
/* 117 */ { 85,  22, 0},
/* 118 */ { 86,  47, 0},
/* 119 */ { 87,  17, 0},
/* 120 */ { 88,  45, 0},
/* 121 */ { 89,  21, 0},
/* 122 */ { 90,  44, 0},
/* 123 */ {219, 219, SHIFT_PRESSED},
/* 124 */ {220, 220, SHIFT_PRESSED},
/* 125 */ {221, 221, SHIFT_PRESSED},
/* 126 */ {192, 192, SHIFT_PRESSED},
#if 0
/* 127 */ {  8,  14, RIGHT_CTRL_PRESSED},
#else
/* Delete */ { VK_DELETE, 83, 0},
#endif
};

static const KEY_MATRIX FunctionToKeyArray[] = {
/* Cursor Up */	    {VK_UP,      72,	0},
/* Cursor Down */   {VK_DOWN,    80,	0},
/* Cursor Right */  {VK_RIGHT,   77,	0},
/* Cursor Left */   {VK_LEFT,    75,	0},
/* End */	    {VK_END,     79,	0},
/* Home */	    {VK_HOME,    71,	0},
/* PageUp */	    {VK_PRIOR,   73,	0},
/* PageDown */	    {VK_NEXT,    81,	0},
/* Insert */	    {VK_INSERT,  82,	0},
/* Delete */	    {VK_DELETE,  83,	0},
/* Select */	    {VK_SELECT,   0,	0},
/* F1 */	    {VK_F1,      59,	0},
/* F2 */	    {VK_F2,      60,	0},
/* F3 */	    {VK_F3,      61,	0},
/* F4 */	    {VK_F4,      62,	0},
/* F5 */	    {VK_F5,      63,	0},
/* F6 */	    {VK_F6,      64,	0},
/* F7 */	    {VK_F7,      65,	0},
/* F8 */	    {VK_F8,      66,	0},
/* F9 */	    {VK_F9,      67,	0},
/* F10 */	    {VK_F10,     68,	0},
/* F11 */	    {VK_F11,     87,	0},
/* F12 */	    {VK_F12,     88,	0},
/* F13 */	    {VK_F13,      0,	0},
/* F14 */	    {VK_F14,      0,	0},
/* F15 */	    {VK_F15,      0,	0},
/* F16 */	    {VK_F16,      0,	0},
/* F17 */	    {VK_F17,      0,	0},
/* F18 */	    {VK_F18,      0,	0},
/* F19 */	    {VK_F19,      0,	0},
/* F20 */	    {VK_F20,      0,	0},
};

const DWORD KEY_CONTROL	    = 0;
const DWORD KEY_SHIFT	    = 1;
const DWORD KEY_LSHIFT	    = 1;
const DWORD KEY_RSHIFT	    = 2;
const DWORD KEY_ALT	    = 3;

static void
SendIR(INPUT_RECORD *ir, CMclQueue<Message *> &mQ)
{
    Message *msg = new Message;
    msg->type = Message::TYPE_INRECORD;
    msg->length = sizeof(INPUT_RECORD);  // not needed
    msg->bytes = ir;
    mQ.Put(msg);
}

static void
MapCharToIRs (UCHAR c, CMclQueue<Message *> &mQ)
{
    UCHAR lc;
    DWORD mods;
    INPUT_RECORD *ir;

    lc = c < 128 ? c : c - 128;
    mods = AsciiToKeyArray[lc].dwControlKeyState;

#if 0
    if (mods & RIGHT_CTRL_PRESSED) {
	/* First, generate a control key press */
	ir = new INPUT_RECORD;
	ir->EventType = KEY_EVENT;
	ir->Event.KeyEvent.bKeyDown = TRUE;
	ir->Event.KeyEvent.wRepeatCount = 1;
	ir->Event.KeyEvent.wVirtualKeyCode =
		ModifierKeyArray[KEY_CONTROL].wVirtualKeyCode;
	ir->Event.KeyEvent.wVirtualScanCode =
		ModifierKeyArray[KEY_CONTROL].wVirtualScanCode;
	ir->Event.KeyEvent.uChar.AsciiChar = 0;
	ir->Event.KeyEvent.dwControlKeyState = RIGHT_CTRL_PRESSED;
	SendIR(ir, mQ);
    }
    if (mods & SHIFT_PRESSED) {
	/* First, generate a control key press */
	ir = new INPUT_RECORD;
	ir->EventType = KEY_EVENT;
	ir->Event.KeyEvent.bKeyDown = TRUE;
	ir->Event.KeyEvent.wVirtualKeyCode =
		ModifierKeyArray[KEY_SHIFT].wVirtualKeyCode;
	ir->Event.KeyEvent.wVirtualScanCode =
		ModifierKeyArray[KEY_SHIFT].wVirtualScanCode;
	ir->Event.KeyEvent.uChar.AsciiChar = 0;
	ir->Event.KeyEvent.dwControlKeyState = mods;
	injectorIPC->Post(&ir);
    }
#endif

    ir = new INPUT_RECORD;
    ir->EventType = KEY_EVENT;
    ir->Event.KeyEvent.bKeyDown = TRUE;
    ir->Event.KeyEvent.wRepeatCount = 1;
    ir->Event.KeyEvent.wVirtualKeyCode =
	    AsciiToKeyArray[lc].wVirtualKeyCode;
    ir->Event.KeyEvent.wVirtualScanCode =
	    AsciiToKeyArray[lc].wVirtualScanCode;
    ir->Event.KeyEvent.dwControlKeyState =
	    AsciiToKeyArray[lc].dwControlKeyState;
    ir->Event.KeyEvent.uChar.AsciiChar = c;
    SendIR(ir, mQ);

    ir = new INPUT_RECORD;
    ir->EventType = KEY_EVENT;
    ir->Event.KeyEvent.bKeyDown = FALSE;
    ir->Event.KeyEvent.wRepeatCount = 1;
    ir->Event.KeyEvent.wVirtualKeyCode =
	    AsciiToKeyArray[lc].wVirtualKeyCode;
    ir->Event.KeyEvent.wVirtualScanCode =
	    AsciiToKeyArray[lc].wVirtualScanCode;
    ir->Event.KeyEvent.dwControlKeyState =
	    AsciiToKeyArray[lc].dwControlKeyState;
    ir->Event.KeyEvent.uChar.AsciiChar = c;
    SendIR(ir, mQ);

#if 0
    if (mods & SHIFT_PRESSED) {
	/* First, generate a control key press */
	ir = new INPUT_RECORD;
	ir->EventType = KEY_EVENT;
	ir->Event.KeyEvent.bKeyDown = FALSE;
	ir->Event.KeyEvent.wVirtualKeyCode =
		ModifierKeyArray[KEY_SHIFT].wVirtualKeyCode;
	ir->Event.KeyEvent.wVirtualScanCode =
		ModifierKeyArray[KEY_SHIFT].wVirtualScanCode;
	ir->Event.KeyEvent.uChar.AsciiChar = 0;
	ir->Event.KeyEvent.dwControlKeyState = mods & ~SHIFT_PRESSED;
	SendIR(ir, mQ);
    }
    if (mods & RIGHT_CTRL_PRESSED) {
	/* First, generate a control key press */
	ir = new INPUT_RECORD;
	ir->EventType = KEY_EVENT;
	ir->Event.KeyEvent.bKeyDown = FALSE;
	ir->Event.KeyEvent.wVirtualKeyCode =
		ModifierKeyArray[KEY_CONTROL].wVirtualKeyCode;
	ir->Event.KeyEvent.wVirtualScanCode =
		ModifierKeyArray[KEY_CONTROL].wVirtualScanCode;
	ir->Event.KeyEvent.uChar.AsciiChar = 0;
	ir->Event.KeyEvent.dwControlKeyState = 0;
	SendIR(ir, mQ);
    }
#endif
}

void
MapToKeys (Message *msg, CMclQueue<Message *> &mQ)
{
    size_t i;
    for (i = 0; i < msg->length; i++) {
	MapCharToIRs(((PUCHAR)msg->bytes)[i], mQ);
    }
    delete msg;
}

void
MapFKeyToIRs(DWORD fk, CMclQueue<Message *> &mQ)
{
    INPUT_RECORD *ir;

    ir = new INPUT_RECORD;
    ir->EventType = KEY_EVENT;
    ir->Event.KeyEvent.bKeyDown = TRUE;
    ir->Event.KeyEvent.wRepeatCount = 1;
    ir->Event.KeyEvent.wVirtualKeyCode =
	    FunctionToKeyArray[fk].wVirtualKeyCode;
    ir->Event.KeyEvent.wVirtualScanCode =
	    FunctionToKeyArray[fk].wVirtualScanCode;
    ir->Event.KeyEvent.dwControlKeyState =
	    FunctionToKeyArray[fk].dwControlKeyState;
    ir->Event.KeyEvent.uChar.AsciiChar = 0;
    SendIR(ir, mQ);

    ir = new INPUT_RECORD;
    ir->EventType = KEY_EVENT;
    ir->Event.KeyEvent.bKeyDown = FALSE;
    ir->Event.KeyEvent.wRepeatCount = 1;
    ir->Event.KeyEvent.wVirtualKeyCode =
	    FunctionToKeyArray[fk].wVirtualKeyCode;
    ir->Event.KeyEvent.wVirtualScanCode =
	    FunctionToKeyArray[fk].wVirtualScanCode;
    ir->Event.KeyEvent.dwControlKeyState =
	    FunctionToKeyArray[fk].dwControlKeyState;
    ir->Event.KeyEvent.uChar.AsciiChar = 0;
    SendIR(ir, mQ);
}

Changes to win/expWinDynloadTclStubs.cpp.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.sf.net/
 *	    http://expect.nist.gov/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinDynloadTclStubs.cpp,v 1.1.2.1 2002/03/12 18:41:38 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "tcl.h"

// We need at least the Tcl_Obj interface that was started in 8.0
#if TCL_MAJOR_VERSION < 8







>







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.sf.net/
 *	    http://expect.nist.gov/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinDynloadTclStubs.cpp,v 1.1.2.2 2002/03/12 21:06:51 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "tcl.h"

// We need at least the Tcl_Obj interface that was started in 8.0
#if TCL_MAJOR_VERSION < 8

Changes to win/expWinInit.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinInit.c,v 1.1.4.3 2002/02/11 09:56:00 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

static ExpWinProcs asciiProcs = {
    0,







>







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinInit.c,v 1.1.4.4 2002/02/16 03:16:59 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

static ExpWinProcs asciiProcs = {
    0,

Added win/expWinInjectorIPC.hpp.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
/* ----------------------------------------------------------------------------
 * expWinInjectorIPC.hpp --
 *
 *	CMclMailbox values saved to a common include file to avoid
 *	differences in the constructor calls on either end of the IPC
 *	connection phase.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinInjectorIPC.hpp,v 1.1.2.2 2002/06/28 02:00:56 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinInjectorIPC_hpp__
#define INC_expWinInjectorIPC_hpp__

#define IPC_NUMSLOTS 80
#define IPC_SLOTSIZE sizeof(INPUT_RECORD)

#endif

Added win/expWinInjectorMain.cpp.





























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* ----------------------------------------------------------------------------
 * expWinInjectorMain.cpp --
 *
 *	Console event injector DLL that's loaded into the slave's address space
 *	used by the ConsoleDebugger class for "writing" to the slave.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinInjectorMain.cpp,v 1.1.2.15 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "CMcl.h"
#include "expWinInjectorIPC.hpp"

class Injector : public CMclThreadHandler
{
    CMclMailbox *ConsoleDebuggerIPC;
    HANDLE console;
    CMclEvent *interrupt;
    char sysMsgSpace[512];

public:

    Injector(HANDLE _console, CMclEvent *_interrupt) 
	: console(_console), interrupt(_interrupt), ConsoleDebuggerIPC(0L)
    {}
    
    ~Injector() {}

private:

    virtual unsigned ThreadHandlerProc(void)
    {
	CHAR boxName[50];
	DWORD err, dwWritten;
	INPUT_RECORD ir;

	wsprintf(boxName, "ExpectInjector_pid%d", GetCurrentProcessId());

	// Create the shared memory IPC transfer mechanism by name
	// (a mailbox).
	ConsoleDebuggerIPC = 
		new CMclMailbox(IPC_NUMSLOTS, IPC_SLOTSIZE, boxName);

	// Check status.
	err = ConsoleDebuggerIPC->Status();
	if (err != NO_ERROR && err != ERROR_ALREADY_EXISTS) {
	    OutputDebugString(GetSysMsg(err));
	    delete ConsoleDebuggerIPC;
	    return 0x666;
	}

	OutputDebugString("Expect's injector DLL loaded and ready.\n");

	// forever loop receiving INPUT_RECORDs over IPC.
	while (ConsoleDebuggerIPC->GetAlertable(&ir, interrupt)) {
	    // Stuff it into our slave console as if it had been entered
	    // by the user.
	    WriteConsoleInput(console, &ir, 1, &dwWritten);
	}

	delete ConsoleDebuggerIPC;
	return 0;
    }

    const char *GetSysMsg(DWORD id)
    {
	int chars;

	chars = wsprintf(sysMsgSpace,
		"Expect's injector DLL could not start IPC: [%u] ", id);
	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
		FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, id, 0,
		sysMsgSpace+chars, (512-chars),	0);
	return sysMsgSpace;
    }
};

CMclEvent *interrupt;
CMclThread *injectorThread;
Injector *inject;
HANDLE console;

BOOL WINAPI
DllMain (HINSTANCE hInst, ULONG ulReason, LPVOID lpReserved)
{
    switch (ulReason) {
    case DLL_PROCESS_ATTACH:
	DisableThreadLibraryCalls(hInst);
	console = CreateFile("CONIN$", GENERIC_WRITE,
		FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
	interrupt = new CMclEvent();
	inject = new Injector(console, interrupt);
	injectorThread = new CMclThread(inject);
	break;
    case DLL_PROCESS_DETACH:
	interrupt->Set();
	injectorThread->Wait(INFINITE);
	CloseHandle(console);
	delete interrupt;
	delete injectorThread;
	delete inject;
	break;
    }
    return TRUE;
}

Changes to win/expWinInt.h.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinInt.h,v 1.1.4.5 2002/03/09 01:17:29 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */
#ifndef _EXPWININT
#define _EXPWININT

#ifndef _EXPINT
#   ifndef _EXP







>







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinInt.h,v 1.1.4.7 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */
#ifndef _EXPWININT
#define _EXPWININT

#ifndef _EXPINT
#   ifndef _EXP
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65

#ifndef _EXPPORT
#   include "expPort.h"
#endif

#undef TCL_STORAGE_CLASS
#if defined(BUILD_slavedriver)
#   define TCL_STORAGE_CLASS
#   include "expWinSlave.hpp"
#   ifdef _DEBUG
#	include "MsvcDbgControl.h"
#   endif
#   include "slavedrvmc.h"
#elif defined(BUILD_exp)
#   define TCL_STORAGE_CLASS DLLEXPORT

#else
#   ifdef USE_EXP_STUBS
#	define TCL_STORAGE_CLASS
#   else
#	define TCL_STORAGE_CLASS DLLIMPORT
#   endif
#endif







|
|
<
<
<
<


>







45
46
47
48
49
50
51
52
53




54
55
56
57
58
59
60
61
62
63

#ifndef _EXPPORT
#   include "expPort.h"
#endif

#undef TCL_STORAGE_CLASS
#if defined(BUILD_slavedriver)
//#   define TCL_STORAGE_CLASS
//#   include "expWinSlave.hpp"




#elif defined(BUILD_exp)
#   define TCL_STORAGE_CLASS DLLEXPORT
#   include "slavedrvmc.h"  /* error code constants */
#else
#   ifdef USE_EXP_STUBS
#	define TCL_STORAGE_CLASS
#   else
#	define TCL_STORAGE_CLASS DLLIMPORT
#   endif
#endif
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    DWORD (WINAPI *getModuleFileNameProc)(HMODULE, LPTSTR, DWORD);
    BOOL (WINAPI *setEnvironmentVariableProc)(LPCTSTR, LPCTSTR);
    BOOL (WINAPI *getEnvironmentVariableProc)(LPCTSTR, LPTSTR, DWORD);
    LONG (WINAPI *regSetValueExProc)(HKEY, LPCTSTR, DWORD, DWORD, CONST BYTE *,
	    DWORD);
} ExpWinProcs;

extern TCL_CPP ExpWinProcs *expWinProcs;


#include "expIntPlatDecls.h"

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _EXPWININT */







|








125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    DWORD (WINAPI *getModuleFileNameProc)(HMODULE, LPTSTR, DWORD);
    BOOL (WINAPI *setEnvironmentVariableProc)(LPCTSTR, LPCTSTR);
    BOOL (WINAPI *getEnvironmentVariableProc)(LPCTSTR, LPTSTR, DWORD);
    LONG (WINAPI *regSetValueExProc)(HKEY, LPCTSTR, DWORD, DWORD, CONST BYTE *,
	    DWORD);
} ExpWinProcs;

TCL_EXTRNC ExpWinProcs *expWinProcs;


#include "expIntPlatDecls.h"

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _EXPWININT */

Changes to win/expWinLog.c.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinLog.c,v 1.1.2.1.2.2 2002/02/10 12:03:30 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

static char sysMsgSpace[1024];








>







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinLog.c,v 1.1.2.1.2.3 2002/03/09 05:48:51 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

static char sysMsgSpace[1024];

Changes to win/expWinMessage.cpp.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35











36
37
38
39
40
41
42
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 *
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinMessage.cpp,v 1.1.2.4 2002/03/15 07:41:45 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinMessage.hpp"

Message::Message()
    : bytes(0L), length(0), type(TYPE_BLANK)
{
}












Message::Message(Message &other)
{
    type = other.type;
    bytes = other.bytes;
    length = other.length;
}







>







|









>
>
>
>
>
>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 *
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinMessage.cpp,v 1.1.2.8 2002/06/23 09:24:03 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinMessage.hpp"

Message::Message()
    : bytes(0L), length(0), type(TYPE_BLANK)
{
}

Message::~Message()
{
    switch (type) {
    case TYPE_NORMAL:
    case TYPE_ERROR:
    case TYPE_WARNING:
    case TYPE_INRECORD:
	delete [] bytes;
    }
}

Message::Message(Message &other)
{
    type = other.type;
    bytes = other.bytes;
    length = other.length;
}

Changes to win/expWinMessage.hpp.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40











41
42
43
44
45
46
47
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinMessage.hpp,v 1.1.2.4 2002/03/15 07:41:45 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinMessage_hpp__
#define INC_expWinMessage_hpp__

#include <stddef.h>	// for size_t

class Message
{
public:
    Message();

    Message(Message &);












    enum Mode {TYPE_BLANK, TYPE_NORMAL, TYPE_ERROR, TYPE_INSTREAM, TYPE_FUNCTION, TYPE_SLAVEDONE};
    Mode type;
    size_t length;
    unsigned char *bytes;
};

#endif







>







|












>


>
>
>
>
>
>
>
>
>
>
>
|


|



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinMessage.hpp,v 1.1.2.9 2002/06/28 01:26:57 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinMessage_hpp__
#define INC_expWinMessage_hpp__

#include <stddef.h>	// for size_t

class Message
{
public:
    Message();
    ~Message();
    Message(Message &);

    enum Mode {
	TYPE_BLANK,
	TYPE_NORMAL,
	TYPE_ERROR,
	TYPE_WARNING,
	TYPE_INSTREAM,
	TYPE_INRECORD,
	TYPE_ENTERINTERACT,
	TYPE_EXITINTERACT,
	TYPE_SLAVEDONE
    };

    Mode type;
    size_t length;
    void *bytes;
};

#endif

Changes to win/expWinPort.h.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinPort.h,v 1.1.2.1.2.4 2002/02/11 09:56:00 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPWINPORT
#define _EXPWINPORT

#ifndef _EXPINT







>







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinPort.h,v 1.1.2.1.2.5 2002/03/08 23:33:13 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef _EXPWINPORT
#define _EXPWINPORT

#ifndef _EXPINT

Changes to win/expWinProcess.c.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinProcess.c,v 1.1.2.1.2.7 2002/03/08 23:31:18 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

/*
 * This list is used to map from pids to process handles.







>







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinProcess.c,v 1.1.2.1.2.8 2002/03/09 05:48:51 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

/*
 * This list is used to map from pids to process handles.

Changes to win/expWinSlave.hpp.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42


43



44
45
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlave.hpp,v 1.1.4.9 2002/03/12 21:07:00 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */
#ifndef INC_expWinSlave_hpp__
#define INC_expWinSlave_hpp__

#include <windows.h>

void DynloadTclStubs (void);
void ShutdownTcl (void);


#include "Mcl/include/CMcl.h"
#include "slavedrvmc.h"
#include "expWinUtils.hpp"
#include "expWinMessage.hpp"
#include "expWinSpawnClient.hpp"


#include "expWinSlaveTrap.hpp"




#endif // INC_expWinSlave_hpp__







>







|











|



|
>
>

>
>
>


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlave.hpp,v 1.1.4.15 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */
#ifndef INC_expWinSlave_hpp__
#define INC_expWinSlave_hpp__

#include <windows.h>

void DynloadTclStubs (void);
void ShutdownTcl (void);


#include "CMcl.h"
#include "slavedrvmc.h"
#include "expWinUtils.hpp"
#include "expWinMessage.hpp"
#include "expWinTestClient.hpp"
#include "expWinConsoleDebugger.hpp"
//#include "expWinConsoleDetour.hpp"
#include "expWinSlaveTrap.hpp"

void MapToKeys (Message *msg, CMclQueue<Message *> &mQ);


#endif // INC_expWinSlave_hpp__

Changes to win/expWinSlaveMain.cpp.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* ----------------------------------------------------------------------------
 * expWinSlaveMain.cpp --
 *
 *	Program entry for the Win32 slave driver helper application.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlaveMain.cpp,v 1.1.4.16 2002/03/15 07:41:45 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinSlave.hpp"


// local protos
static SpawnClientTransport *SpawnOpenClientTransport(const char *, CMclQueue<Message *> &);
static SlaveTrap *SlaveOpenTrap(const char *, int, char * const *, CMclQueue<Message *> &);
static int DoEvents(SpawnClientTransport *, SlaveTrap *, CMclQueue<Message *> &, CMclEvent &);
static char *OurGetCmdLine();

// Turns on/off special debugger hooks used in development.
//
#ifndef IDE_LATCHED
#   define IDE_LATCHED 0
#endif


int
main (void)
{
    int argc;			    // Number of command-line arguments.
    char **argv;		    // Values of command-line arguments.
    SpawnClientTransport *transport;// class pointer of transport client.
    SlaveTrap *slaveCtrl;	    // trap method class pointer.
    CMclQueue<Message *> messageQ;  // Our message Queue we hand off to everyone.
    CMclEvent Shutdown;		    // global shutdown for the event queue.
    int code;			    // exitcode.
    CHAR *cmdLine;		    // commandline to use.

    //  We need a few Tcl APIs in here.  Load it now.
    //
    DynloadTclStubs();




|













>







|







|

|














|
|

<







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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
/* ----------------------------------------------------------------------------
 * expWinSlaveMain.cpp --
 *
 *	Program entry for the Win32 slave tester application.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlaveMain.cpp,v 1.1.4.28 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinSlave.hpp"


// local protos
static TestClient *OpenTestClient(const char *, CMclQueue<Message *> &);
static SlaveTrap *SlaveOpenTrap(const char *, int, char * const *, CMclQueue<Message *> &);
static int DoEvents(TestClient *, SlaveTrap *, CMclQueue<Message *> &);
static char *OurGetCmdLine();

// Turns on/off special debugger hooks used in development.
//
#ifndef IDE_LATCHED
#   define IDE_LATCHED 0
#endif


int
main (void)
{
    int argc;			    // Number of command-line arguments.
    char **argv;		    // Values of command-line arguments.
    TestClient *client;		    // class pointer of transport client.
    SlaveTrap *slave;		    // trap method class pointer.
    CMclQueue<Message *> messageQ;  // Our message Queue we hand off to everyone.

    int code;			    // exitcode.
    CHAR *cmdLine;		    // commandline to use.

    //  We need a few Tcl APIs in here.  Load it now.
    //
    DynloadTclStubs();

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112






113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169
170








171
172
173
174
175
176
177
178
179
180
181

182
183
184
185
186


187
188
189
190
191
192
193
194
195
196
197
    if (argc < 4) {
	EXP_LOG0(MSG_IO_ARGSWRONG);
    }

    //  Open the client side of our IPC transport that connects us back
    //  to the parent (ie. the Expect extension).
    //
    transport = SpawnOpenClientTransport(argv[1], messageQ);

    //  Start the process to be intercepted within the trap method requested
    //  on the commandline (ie. run telnet in a debugger and trap OS calls).
    //
    slaveCtrl = SlaveOpenTrap(argv[2], argc-3, &argv[3], messageQ);

    //  Process messages.
    //
    code = DoEvents(transport, slaveCtrl, messageQ, Shutdown);

    //  Close up.
    //
    ShutdownTcl();
    return code;
}

/*
 *----------------------------------------------------------------------
 *  SpawnOpenTransport --
 *
 *	The factory method for creating the client IPC transport from
 *	the name asked of it.
 *
 *  Returns:
 *	a polymorphed SpawnClientTransport pointer or die.
 *
 *----------------------------------------------------------------------
 */

SpawnClientTransport *
SpawnOpenClientTransport(const char *method, CMclQueue<Message *> &mQ)
{
    if (!strcmp(method, "stdio")) {
	return new SpawnStdioClient(method, mQ);






    }
    else EXP_LOG1(MSG_IO_TRANSPRTARGSBAD, method);

    // not reached.
    return 0L;
}

/*
 *----------------------------------------------------------------------
 *  SlaveOpenTrap --
 *
 *	The factory method for creating the trap class instance.
 *
 *  Returns:
 *	a polymorphed SpawnTrap pointer or die.
 *
 *----------------------------------------------------------------------
 */

SlaveTrap *
SlaveOpenTrap(const char *method, int argc, char * const argv[],
    CMclQueue<Message *> &mQ)
{
    if (!strcmp(method, "dbg")) {
	return new SlaveTrapDbg(argc, argv, mQ);
    }



    else EXP_LOG1(MSG_IO_TRAPARGSBAD, method);

    // not reached.
    return 0L;
}

/*
 *----------------------------------------------------------------------
 *  DoEvents --
 *
 *	Process all events for the slavedrv application.  We are the
 *	master.  The slave is the process we are trapping.
 *
 *  Returns:
 *	an exit code.
 *
 *----------------------------------------------------------------------
 */

int
DoEvents(SpawnClientTransport *transport, SlaveTrap *slaveCtrl,
    CMclQueue<Message *> &mQ, CMclEvent &sd)
{
    Message *msg;

    while (mQ.Get(msg, INFINITE)) {
	switch (msg->type) {
	case Message::TYPE_NORMAL:

	case Message::TYPE_ERROR:
	    //  Send stuff back to the parent.
	    //
	    transport->Write(msg);








	    break;

	case Message::TYPE_INSTREAM:
	    //  Send stuff to the slave.
	    //
	    slaveCtrl->Write(msg);
	    break;

	case Message::TYPE_FUNCTION:
	    //  Internal mode switching and info gathering.
	    //

	    break;

	case Message::TYPE_SLAVEDONE:
	    //delete slaveCtrl;
	    Sleep(500);  // bad hack, please ignore for now.


	    return 0;
	}
    }
    //delete transport, slaveCtrl;
    return 0;
}

/*
 *----------------------------------------------------------------------
 *  OurGetCmdLine --
 *







|




|



|









|










|
|


|
>
>
>
>
>
>














|











>
>
>




















<
|



|


>



|
>
>
>
>
>
>
>
>



|
<
<
<
|
<
<

>



|
|
>
>



<







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191



192


193
194
195
196
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
    if (argc < 4) {
	EXP_LOG0(MSG_IO_ARGSWRONG);
    }

    //  Open the client side of our IPC transport that connects us back
    //  to the parent (ie. the Expect extension).
    //
    client = OpenTestClient(argv[1], messageQ);

    //  Start the process to be intercepted within the trap method requested
    //  on the commandline (ie. run telnet in a debugger and trap OS calls).
    //
    slave = SlaveOpenTrap(argv[2], argc-3, &argv[3], messageQ);

    //  Process messages.
    //
    code = DoEvents(client, slave, messageQ);

    //  Close up.
    //
    ShutdownTcl();
    return code;
}

/*
 *----------------------------------------------------------------------
 *  OpenTestClient --
 *
 *	The factory method for creating the client IPC transport from
 *	the name asked of it.
 *
 *  Returns:
 *	a polymorphed SpawnClientTransport pointer or die.
 *
 *----------------------------------------------------------------------
 */

TestClient *
OpenTestClient(const char *method, CMclQueue<Message *> &mQ)
{
    if (!strcmp(method, "stdio")) {
	return new ClientStdio(mQ);
    }
    else if (!strcmp(method, "conio")) {
	return new ClientConio(mQ);
    }
    else if (!strcmp(method, "interact")) {
	return new ClientInteract(mQ);
    }
    else EXP_LOG1(MSG_IO_TRANSPRTARGSBAD, method);

    // not reached.
    return 0L;
}

/*
 *----------------------------------------------------------------------
 *  SlaveOpenTrap --
 *
 *	The factory method for creating the trap class instance.
 *
 *  Returns:
 *	a polymorphed SlaveTrap pointer or die.
 *
 *----------------------------------------------------------------------
 */

SlaveTrap *
SlaveOpenTrap(const char *method, int argc, char * const argv[],
    CMclQueue<Message *> &mQ)
{
    if (!strcmp(method, "dbg")) {
	return new SlaveTrapDbg(argc, argv, mQ);
    }
//    else if (!strcmp(method, "detour")) {
//	return new SlaveTrapDetour(argc, argv, mQ);
//    }
    else EXP_LOG1(MSG_IO_TRAPARGSBAD, method);

    // not reached.
    return 0L;
}

/*
 *----------------------------------------------------------------------
 *  DoEvents --
 *
 *	Process all events for the slavedrv application.  We are the
 *	master.  The slave is the process we are trapping.
 *
 *  Returns:
 *	an exit code.
 *
 *----------------------------------------------------------------------
 */

int

DoEvents(TestClient *client, SlaveTrap *slave, CMclQueue<Message *> &msgQ)
{
    Message *msg;

    while (msgQ.Get(msg, INFINITE)) {
	switch (msg->type) {
	case Message::TYPE_NORMAL:
	case Message::TYPE_WARNING:
	case Message::TYPE_ERROR:
	    //  Send stuff back to the parent.
	    //
	    client->Write(msg);
	    break;

	case Message::TYPE_INRECORD:
	case Message::TYPE_ENTERINTERACT:
	case Message::TYPE_EXITINTERACT:
	    //  Send stuff to the slave.
	    //
	    slave->Write(msg);
	    break;

	case Message::TYPE_INSTREAM:
	    //  Do char to keypress conversion here.



	    //  These get reposted back as TYPE_INRECORD messages.


	    //
	    MapToKeys(msg, msgQ);
	    break;

	case Message::TYPE_SLAVEDONE:
	    delete slave;
	    delete client;
	    //  Returning the exitcode of the slave is not yet supported.
	    //
	    return 0;
	}
    }

    return 0;
}

/*
 *----------------------------------------------------------------------
 *  OurGetCmdLine --
 *
248
249
250
251
252
253
254
255
256
257
258
259
260
261

    // >>>> END IMPORTANT! <<<<

    itoa(pid, pidChar, 10);
    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Tomasoft\\MsDevDbgCtrl",
	    0, KEY_ALL_ACCESS, &root);
    RegQueryValueEx(root, pidChar, 0, &type, 0L, &size);
    buf = (CHAR *) HeapAlloc(GetProcessHeap(), 0, size);
    RegQueryValueEx(root, pidChar, 0, &type, (LPBYTE) buf, &size);
    RegDeleteValue(root, pidChar);
    RegCloseKey(root);
    return buf;
}
#endif  // _DEBUG && _MSC_VER && IDE_LATCHED







|






262
263
264
265
266
267
268
269
270
271
272
273
274
275

    // >>>> END IMPORTANT! <<<<

    itoa(pid, pidChar, 10);
    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Tomasoft\\MsDevDbgCtrl",
	    0, KEY_ALL_ACCESS, &root);
    RegQueryValueEx(root, pidChar, 0, &type, 0L, &size);
    buf = new CHAR [size];
    RegQueryValueEx(root, pidChar, 0, &type, (LPBYTE) buf, &size);
    RegDeleteValue(root, pidChar);
    RegCloseKey(root);
    return buf;
}
#endif  // _DEBUG && _MSC_VER && IDE_LATCHED

Changes to win/expWinSlaveTrap.hpp.

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
32
33
34
35
36

37
38
39
40




41

42
43

44

45

46
47
















48
49
50
/* ----------------------------------------------------------------------------
 * expWinSlaveTrap.hpp --
 *
 *	Declares the SlaveTrap classes.

 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlaveTrap.hpp,v 1.1.2.1 2002/03/12 07:09:36 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinSlaveTrap_hpp__
#define INC_expWinSlaveTrap_hpp__

#include "expWinMessage.hpp"
#include "Mcl/include/CMcl.h"

class SlaveTrap {
public:

    virtual void Write(Message *) = 0;
};






class SlaveTrapDbg : public SlaveTrap {

public:
    SlaveTrapDbg(int argc, char * const argv[], CMclQueue<Message *> &_mQ);

    virtual void Write(Message *);

private:

    CMclQueue<Message *> &mQ;
    CMclThreadAutoPtr debuggerThread;
















};

#endif



|
>













>







|






<
<
<


>



|
>
>
>
>
|
>


>

>

>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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
32
33



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* ----------------------------------------------------------------------------
 * expWinSlaveTrap.hpp --
 *
 *	Declares the SlaveTrap classes which are our "invokation
 *	managers" of the trap method we run in a thread.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlaveTrap.hpp,v 1.1.2.5 2002/07/03 02:47:44 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#ifndef INC_expWinSlaveTrap_hpp__
#define INC_expWinSlaveTrap_hpp__




class SlaveTrap {
public:
    virtual ~SlaveTrap() {};
    virtual void Write(Message *) = 0;
};

// This uses the debugger method by setting breakpoints on all calls the
// process makes to the console API and running the process within the
// native OS debugger.  See expWinConsoleDebugger.hpp for the details of
// what we run in the thread.
//
class SlaveTrapDbg : public SlaveTrap
{
public:
    SlaveTrapDbg(int argc, char * const argv[], CMclQueue<Message *> &_mQ);
    virtual ~SlaveTrapDbg();
    virtual void Write(Message *);

private:
    ConsoleDebugger *debugger;
    CMclQueue<Message *> &mQ;
    CMclThread *debuggerThread;
};

// This uses the detour method by rewriting the import directory of the
// processes' image (in memory) so as to pass though us.  This method
// doesn't require the debugger APIs.  See expWinConsoleDetour.hpp for
// more detials.
//
class SlaveTrapDetour : public SlaveTrap
{
public:
    SlaveTrapDetour(int argc, char * const argv[], CMclQueue<Message *> &_mQ);
    virtual ~SlaveTrapDetour();
    virtual void Write(Message *);

private:
    CMclQueue<Message *> &mQ;
};

#endif

Changes to win/expWinSlaveTrapDbg.cpp.

18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43











44
45
46
47




48








49
50
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlaveTrapDbg.cpp,v 1.1.4.9 2002/03/13 03:52:57 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinSlave.hpp"
#include "expWinConsoleDebugger.hpp"


SlaveTrapDbg::SlaveTrapDbg(int argc, char * const argv[], CMclQueue<Message *> &_mQ)
    : mQ(_mQ)
{

    debuggerThread = new CMclThread(new ConsoleDebugger(argc, argv, _mQ));











}

void SlaveTrapDbg::Write(Message *msg)
{




    // inject it from here.. how?








    delete [] msg->bytes;
}







>







|




<





>
|
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
|
>
>
>
>
>
>
>
>
|

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSlaveTrapDbg.cpp,v 1.1.4.13 2002/06/28 01:26:57 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinSlave.hpp"



SlaveTrapDbg::SlaveTrapDbg(int argc, char * const argv[], CMclQueue<Message *> &_mQ)
    : mQ(_mQ)
{
    debugger = new ConsoleDebugger(argc, argv, _mQ);
    debuggerThread = new CMclThread(debugger);
}

SlaveTrapDbg::~SlaveTrapDbg()
{
    DWORD exitCode;

    debuggerThread->GetExitCode(&exitCode);
    if (exitCode == STILL_ACTIVE) {
	debuggerThread->Terminate(128);
    }
    delete debuggerThread, debugger;
}

void SlaveTrapDbg::Write(Message *msg)
{
    switch (msg->type) {
    case Message::TYPE_ENTERINTERACT:
	debugger->EnterInteract(static_cast<HANDLE>(msg->bytes));
	break;

    case Message::TYPE_EXITINTERACT:
	debugger->ExitInteract();
	break;

    case Message::TYPE_INRECORD:
	debugger->WriteRecord(static_cast<INPUT_RECORD *>(msg->bytes));
	break;
    }
    delete msg;
}

Changes to win/expWinSpawnChan.c.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: exp.h,v 1.1.4.4 2002/02/10 10:17:04 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

/*
 *----------------------------------------------------------------------







>







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSpawnChan.c,v 1.1.2.1.2.3 2002/02/10 12:03:30 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

/*
 *----------------------------------------------------------------------

Deleted win/expWinSpawnClient.hpp.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/* ----------------------------------------------------------------------------
 * expWinSpawnClient.hpp --
 *
 *	Declares the SpawnClient classes.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSpawnClient.hpp,v 1.1.2.2 2002/03/12 21:34:16 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinMessage.hpp"
#include "Mcl/include/CMcl.h"

class SpawnClientTransport
{
public:
    virtual void Write(Message *) = 0;
};

class SpawnMailboxClient : public SpawnClientTransport
{
public:
    SpawnMailboxClient(const char *name, CMclQueue<Message *> &_mQ);
    virtual void Write(Message *);
private:
    CMclMailbox *MasterToExpect;
    CMclMailbox *MasterFromExpect;
    CMclQueue<Message *> &mQ;
};

class ReadPipe : public CMclThreadHandler
{
public:
    ReadPipe(CMclQueue<Message *> &_mQ);
private:
    virtual unsigned ThreadHandlerProc(void);
    CMclQueue<Message *> &mQ;
    HANDLE hStdIn;
};

class SpawnStdioClient : public SpawnClientTransport
{
public:
    SpawnStdioClient(const char *name, CMclQueue<Message *> &_mQ);
    ~SpawnStdioClient();
    virtual void Write(Message *);
private:
    CMclQueue<Message *> &mQ;
    HANDLE hStdOut;
    HANDLE hStdErr;
    ReadPipe *reader;
    CMclThreadAutoPtr readThread;
};
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































































Deleted win/expWinSpawnStdioClient.cpp.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* ----------------------------------------------------------------------------
 * expWinSpawnStdioClient.cpp --
 *
 *	Simple standard IO as our IPC mechanism.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 *
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 *
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinSpawnStdioClient.cpp,v 1.1.2.1 2002/03/12 21:33:26 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinSpawnClient.hpp"



SpawnStdioClient::SpawnStdioClient(const char *name, CMclQueue<Message *> &_mQ)
    : mQ(_mQ)
{
    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    hStdErr = GetStdHandle(STD_ERROR_HANDLE);
    reader = new ReadPipe(_mQ);
    readThread = new CMclThread(reader);
}

SpawnStdioClient::~SpawnStdioClient()
{
    DWORD dwExit;

    readThread->GetExitCode(&dwExit);
    if (dwExit == STILL_ACTIVE) {
	// by cute convention, terminate threads with a 666.
	//
	readThread->Terminate(666);
    }
    delete reader;
}

void
SpawnStdioClient::Write(Message *what)
{
    DWORD dwWritten;
    HANDLE where;

    switch (what->type) {
    case Message::TYPE_NORMAL:
	where = hStdOut;
    case Message::TYPE_ERROR:
	where = hStdErr;
    }
    WriteFile(where, what->bytes, what->length, &dwWritten, 0L);
}

ReadPipe::ReadPipe(CMclQueue<Message *> &_mQ)
    : mQ(_mQ)
{
    hStdIn = GetStdHandle(STD_INPUT_HANDLE);
}

#define READ_BUFFER_SIZE    128

unsigned ReadPipe::ThreadHandlerProc(void)
{
    BOOL ok;
    DWORD dwRead;
    Message *msg;
    BYTE *readBuf;

again:
    readBuf = new BYTE [READ_BUFFER_SIZE];
    ok = ReadFile(hStdIn, readBuf, READ_BUFFER_SIZE, &dwRead, 0L);
    if (!ok || dwRead == 0) {
	CloseHandle(hStdIn);  // <- should this be here?
	delete [] readBuf;
	goto done;
    }
    msg = new Message;
    msg->bytes = readBuf;
    msg->length = dwRead;
    msg->type = Message::TYPE_INSTREAM;
    mQ.Put(msg);
    goto again;

done:
    return 0;
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































































































Changes to win/expWinTest.cpp.

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
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52





53
54
55
56
57
58
59
#include "TclAdapter.hpp"
#include "expWinUtils.hpp"

class Test1 : protected Tcl::Adapter<Test1>, ArgMaker
{


public:
    Test1(Tcl_Interp *_interp) : Tcl::Adapter<Test1>(_interp) {


	NewTclCmd(interp, "test_buildcmdline", TestCmdLineCmd);
	NewTclCmd(interp, "test_passthru", TestPassThruCmd);
    };
    virtual void DoCleanup () {
	// The adapter base class is telling us we are about to go away and it is
	// safe to use the interp pointer to do any needed cleanup.
    };

    ~Test1() {
	// can't use interp pointer in here.

    };
private:
    // Test the ArgMaker::BuildCommandLine() function.
    //
    int TestCmdLineCmd (int objc, struct Tcl_Obj * CONST objv[])
    {
	char **argv = new char * [objc-1];
	int i;
	char *line;

	for (i = objc-1; i > 0; i--) argv[i-1] = Tcl_GetString(objv[i]);
	line = BuildCommandLine(objc-1, argv);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(line, -1));
	delete [] line;
	return TCL_OK;
    }

    // Test the full pass-thru
    //
    int TestPassThruCmd (int objc, struct Tcl_Obj * CONST objv[])
    {
	char **argvIn = new char * [objc-1];
	int i, argc;
	char *line, **argv;
	Tcl_Obj **oobjv;

	// Take the array and turn it into a string.
	for (i = objc-1; i > 0; i--) argvIn[i-1] = Tcl_GetString(objv[i]);
	line = BuildCommandLine(objc-1, argvIn);
	// Now take the string and turn it back into an array.
	SetArgv(line, &argc, &argv);
	delete [] line;
	oobjv = new Tcl_Obj * [argc];
	for (i = 0; i < argc; i++) oobjv[i] = Tcl_NewStringObj(argv[i], -1);
	Tcl_SetObjResult(interp, Tcl_NewListObj(argc, oobjv));
	return TCL_OK;
    }





};

// tell the EXTERN macro we want to declare functions for export.
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT

EXTERN int
|


|

>
>

|
>
>
|
|
<
<
<
<
<
>


>
|















>




















>
>
>
>
>







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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "TclAdaptor.hpp"
#include "expWinUtils.hpp"

class Test1 : protected Tcl::Adaptor<Test1>, ArgMaker
{
    friend Tcl::Adaptor<Test1>;

public:
    Test1(Tcl_Interp *_interp)
	: Tcl::Adaptor<Test1>(_interp)
    {
	NewTclCmd("test_buildcmdline", TestCmdLineCmd);
	NewTclCmd("test_passthru", TestPassThruCmd);





    }
    ~Test1() {
	// can't use interp pointer in here.
    }

private:
    // Test the ArgMaker::BuildCommandLine() function.
    //
    int TestCmdLineCmd (int objc, struct Tcl_Obj * CONST objv[])
    {
	char **argv = new char * [objc-1];
	int i;
	char *line;

	for (i = objc-1; i > 0; i--) argv[i-1] = Tcl_GetString(objv[i]);
	line = BuildCommandLine(objc-1, argv);
	Tcl_SetObjResult(interp, Tcl_NewStringObj(line, -1));
	delete [] line;
	return TCL_OK;
    }

    // Test the full pass-thru
    //
    int TestPassThruCmd (int objc, struct Tcl_Obj * CONST objv[])
    {
	char **argvIn = new char * [objc-1];
	int i, argc;
	char *line, **argv;
	Tcl_Obj **oobjv;

	// Take the array and turn it into a string.
	for (i = objc-1; i > 0; i--) argvIn[i-1] = Tcl_GetString(objv[i]);
	line = BuildCommandLine(objc-1, argvIn);
	// Now take the string and turn it back into an array.
	SetArgv(line, &argc, &argv);
	delete [] line;
	oobjv = new Tcl_Obj * [argc];
	for (i = 0; i < argc; i++) oobjv[i] = Tcl_NewStringObj(argv[i], -1);
	Tcl_SetObjResult(interp, Tcl_NewListObj(argc, oobjv));
	return TCL_OK;
    }

    virtual void DoCleanup () {
	// The adapter base class is telling us we are about to go away and it is
	// safe to use the interp pointer to do any needed cleanup.
    };
};

// tell the EXTERN macro we want to declare functions for export.
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT

EXTERN int

Added win/expWinTestClient.hpp.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* ----------------------------------------------------------------------------
 * expWinTestClient.hpp --
 *
 *	Declares all the TestClient classes.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinTestClient.hpp,v 1.1.2.4 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinMessage.hpp"
#include "CMcl.h"

class TestClient
{
public:
    virtual ~TestClient() {};
    virtual void Write(Message *) = 0;
};


// Forward reference.
class ReadPipe;
class ReadCon;
class ReadConWithSwitching;

class ClientStdio : public TestClient
{
public:
    ClientStdio(CMclQueue<Message *> &_mQ);
    virtual ~ClientStdio();
    virtual void Write(Message *);
private:
    CMclQueue<Message *> &mQ;
    HANDLE hStdOut;
    HANDLE hStdErr;
    ReadPipe *reader;
    CMclThreadAutoPtr readThread;
};

class ClientConio : public TestClient
{
public:
    ClientConio(CMclQueue<Message *> &_mQ);
    virtual ~ClientConio();
    virtual void Write(Message *);
private:
    CMclQueue<Message *> &mQ;
    HANDLE ConOut, ConIn, oldBuffer;
    ReadCon *reader;
    CMclEvent Stop;
    CMclThread *readThread;
};

class ClientInteract : public TestClient
{
public:
    ClientInteract(CMclQueue<Message *> &_mQ);
    virtual ~ClientInteract();
    virtual void Write(Message *);
private:
    CMclQueue<Message *> &mQ;
    HANDLE ConOut, ConIn, ConInteract, oldBuffer;
    ReadConWithSwitching *reader;
    CMclEvent Stop;
    CMclThread *readThread;
};

Added win/expWinTestClientConio.cpp.





























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* ----------------------------------------------------------------------------
 * expWinTestClientConio.cpp --
 *
 *	Simple console I/O as our client.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 *
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 *
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinTestClientConio.cpp,v 1.1.2.3 2002/06/29 00:44:36 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinTestClient.hpp"

class ReadCon : public CMclThreadHandler
{
    CMclQueue<Message *> &mQ;
    CMclEvent &Stop;
    HANDLE ConIn;
    CMclWaitableCollection groupedHandles;
#   define RECORD_SIZE 15

public:
    ReadCon(CMclQueue<Message *> &_mQ, CMclEvent &_Stop, HANDLE _ConIn)
	: mQ(_mQ), Stop(_Stop), ConIn(_ConIn)
    {
	// Turn on mouse and window events, too.
        SetConsoleMode(ConIn, ENABLE_MOUSE_INPUT);
    }

    ~ReadCon()
    {
    }

private:
    virtual unsigned ThreadHandlerProc(void)
    {
	DWORD dwRet, dwRead, i;
	INPUT_RECORD Records[RECORD_SIZE], *record;
	MOUSE_EVENT_RECORD lastMouse;
	Message *msg;

	// Index 0, highest priority goes first.
	groupedHandles.AddObject(Stop);

	// Console handles are waitable objects.
	// Index 1
	groupedHandles.AddObject(ConIn);

    again:
	// Wait for any (either) to signal.
	dwRet = groupedHandles.Wait(FALSE, INFINITE);

	if (!CMclWaitSucceeded(dwRet, 2) ||
		CMclWaitSucceeded(dwRet, 2) && CMclWaitSucceededIndex(dwRet) == 0) {
	    // stop event or some other error, so die.
	    return 0;
	}

	ReadConsoleInput(ConIn, Records, RECORD_SIZE, &dwRead);
	for (i = 0; i < dwRead; i++) {
	    switch (Records[i].EventType) {
	    case FOCUS_EVENT:
	    case MENU_EVENT:
		// ignore these.
		continue;

	    case MOUSE_EVENT:
		// only send a mouse event if it's different then the last one.
		if (!isDiff(&lastMouse, &Records[i].Event.MouseEvent)) {
		    continue;
		}
		lastMouse = Records[i].Event.MouseEvent;
		break;
	    }
	    msg = new Message;
	    msg->type = Message::TYPE_INRECORD;
	    msg->length = sizeof(INPUT_RECORD);
	    record = new INPUT_RECORD;
	    memcpy(record, &Records[i], sizeof(INPUT_RECORD));
	    msg->bytes = (BYTE *)record;
	    mQ.Put(msg);
	}
	goto again;
    }

    BOOL
    isDiff(MOUSE_EVENT_RECORD *mer1, MOUSE_EVENT_RECORD *mer2)
    {
	if (
	    mer1->dwMousePosition.X ^ mer2->dwMousePosition.X ||
	    mer1->dwMousePosition.Y ^ mer2->dwMousePosition.Y ||
	    mer1->dwButtonState     ^ mer2->dwButtonState ||
	    mer1->dwControlKeyState ^ mer2->dwControlKeyState ||
	    mer1->dwEventFlags      ^ mer2->dwEventFlags
	) {
	    return TRUE;
	} else {
	    return FALSE;
	}

    }
};


ClientConio::ClientConio(CMclQueue<Message *> &_mQ)
    : mQ(_mQ), Stop()
{
    COORD Size = {80, 500};

    ConIn = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);

    reader = new ReadCon(_mQ, Stop, ConIn);
    readThread = new CMclThread(reader);

    oldBuffer = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
    ConOut = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, CONSOLE_TEXTMODE_BUFFER, 0L);
//    SetConsoleCtrlHandler(ConsoleHandler, TRUE);
    SetConsoleActiveScreenBuffer(ConOut);
    SetConsoleScreenBufferSize(ConOut, Size);
}

ClientConio::~ClientConio()
{
    DWORD dwRead;
    INPUT_RECORD record;

    Stop.Set();
    readThread->Wait(INFINITE);
    delete reader, readThread;

    SetConsoleTextAttribute(ConOut, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
    WriteConsole(ConOut, "\nPress any key to exit...\n", 26, &dwRead, 0L);
    FlushConsoleInputBuffer(ConIn);

again:
    ReadConsoleInput(ConIn, &record, 1, &dwRead);
    if (record.EventType != KEY_EVENT) {
	goto again;
    }

    SetConsoleActiveScreenBuffer(oldBuffer);
    CloseHandle(ConOut);
    CloseHandle(ConIn);
}

void
ClientConio::Write(Message *what)
{
    WORD color;
    DWORD dwWritten;

    switch (what->type) {
    case Message::TYPE_NORMAL:
	// grey
	color = FOREGROUND_BLUE |FOREGROUND_GREEN | FOREGROUND_RED;
	break;
    case Message::TYPE_WARNING:
	// bright yellow
	color = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
	break;
    case Message::TYPE_ERROR:
	// bright red
	color = FOREGROUND_RED | FOREGROUND_INTENSITY;
	break;
    }
    SetConsoleTextAttribute(ConOut, color);
    WriteConsole(ConOut, what->bytes, what->length, &dwWritten, 0L);
    delete what;
}

Added win/expWinTestClientInteract.cpp.



















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* ----------------------------------------------------------------------------
 * expWinTestClientInteract.cpp --
 *
 *	This tests the interact capabilities.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 *
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 *
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinTestClientInteract.cpp,v 1.1.2.3 2002/07/03 02:48:22 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinTestClient.hpp"

class ReadConWithSwitching : public CMclThreadHandler
{
    CMclQueue<Message *> &mQ;
    CMclEvent &Stop;
    HANDLE ConIn;
    CMclWaitableCollection groupedHandles;
#   define RECORD_SIZE 15

public:
    ReadConWithSwitching(CMclQueue<Message *> &_mQ, CMclEvent &_Stop, HANDLE _ConIn)
	: mQ(_mQ), Stop(_Stop), ConIn(_ConIn)
    {
	// Turn on mouse and window events, too.
        SetConsoleMode(ConIn, ENABLE_MOUSE_INPUT);
    }

    ~ReadConWithSwitching()
    {
    }

private:
    virtual unsigned ThreadHandlerProc(void)
    {
	DWORD dwRet, dwRead, i;
	INPUT_RECORD Records[RECORD_SIZE], *record;
	MOUSE_EVENT_RECORD lastMouse;
	Message *msg;

	// Index 0, highest priority goes first.
	groupedHandles.AddObject(Stop);

	// Console handles are waitable objects.
	// Index 1
	groupedHandles.AddObject(ConIn);

    again:
	// Wait for any (either) to signal.
	dwRet = groupedHandles.Wait(FALSE, INFINITE);

	if (!CMclWaitSucceeded(dwRet, 2) ||
		CMclWaitSucceeded(dwRet, 2) && CMclWaitSucceededIndex(dwRet) == 0) {
	    // stop event or some other error, so die.
	    return 0;
	}

	ReadConsoleInput(ConIn, Records, RECORD_SIZE, &dwRead);
	for (i = 0; i < dwRead; i++) {
	    switch (Records[i].EventType) {
	    case FOCUS_EVENT:
	    case MENU_EVENT:
	    case WINDOW_BUFFER_SIZE_EVENT:
		// ignore these.
		continue;

	    case MOUSE_EVENT:
		// only send a mouse event if it's different then the last one.
		if (!isDiff(&lastMouse, &Records[i].Event.MouseEvent)) {
		    continue;
		}
		lastMouse = Records[i].Event.MouseEvent;
		break;

	    case KEY_EVENT:
		break;
	    }
	    msg = new Message;
	    msg->type = Message::TYPE_INRECORD;
	    msg->length = sizeof(INPUT_RECORD);
	    record = new INPUT_RECORD;
	    memcpy(record, &Records[i], sizeof(INPUT_RECORD));
	    msg->bytes = record;
	    mQ.Put(msg);
	}
	goto again;
    }

    BOOL
    isDiff(MOUSE_EVENT_RECORD *mer1, MOUSE_EVENT_RECORD *mer2)
    {
	if (
	    mer1->dwMousePosition.X ^ mer2->dwMousePosition.X ||
	    mer1->dwMousePosition.Y ^ mer2->dwMousePosition.Y ||
	    mer1->dwButtonState     ^ mer2->dwButtonState ||
	    mer1->dwControlKeyState ^ mer2->dwControlKeyState ||
	    mer1->dwEventFlags      ^ mer2->dwEventFlags
	) {
	    return TRUE;
	} else {
	    return FALSE;
	}

    }
};


ClientInteract::ClientInteract(CMclQueue<Message *> &_mQ)
    : mQ(_mQ), ConOut(0L), ConIn(0L), ConInteract(0L), oldBuffer(0L)
{
    COORD Size = {80, 500};

    ConIn = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);

    reader = new ReadConWithSwitching(mQ, Stop, ConIn);
    readThread = new CMclThread(reader);

    oldBuffer = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
    ConOut = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, CONSOLE_TEXTMODE_BUFFER, 0L);
//    SetConsoleCtrlHandler(ConsoleHandler, TRUE);
    SetConsoleActiveScreenBuffer(ConOut);
    SetConsoleScreenBufferSize(ConOut, Size);
}

ClientInteract::~ClientInteract()
{
}

void ClientInteract::Write(Message *)
{
}

Added win/expWinTestClientStdio.cpp.

























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* ----------------------------------------------------------------------------
 * expWinTestClientStdio.cpp --
 *
 *	Simple standard I/O as our client.
 *
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 *
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 *
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinTestClientStdio.cpp,v 1.1.2.2 2002/06/28 01:26:57 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinTestClient.hpp"


class ReadPipe : public CMclThreadHandler
{
public:
    ReadPipe(CMclQueue<Message *> &_mQ)	: mQ(_mQ)
    {
	hStdIn = GetStdHandle(STD_INPUT_HANDLE);
    }

private:

#   define READ_BUFFER_SIZE    128
    virtual unsigned ThreadHandlerProc(void)
    {
	BOOL ok;
	DWORD dwRead;
	Message *msg;
	BYTE *readBuf;

    again:
	readBuf = new BYTE [READ_BUFFER_SIZE];
	ok = ReadFile(hStdIn, readBuf, READ_BUFFER_SIZE, &dwRead, 0L);
	if (!ok || dwRead == 0) {
	    CloseHandle(hStdIn);  // <- should this be here?
	    delete [] readBuf;
	    goto done;
	}
	msg = new Message;
	msg->bytes = (CHAR *) readBuf;
	msg->length = dwRead;
	msg->type = Message::TYPE_INSTREAM;
	mQ.Put(msg);
	goto again;

    done:
	return 0;
    }

    CMclQueue<Message *> &mQ;
    HANDLE hStdIn;
};

ClientStdio::ClientStdio(CMclQueue<Message *> &_mQ)
    : mQ(_mQ)
{
    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    hStdErr = GetStdHandle(STD_ERROR_HANDLE);
    reader = new ReadPipe(_mQ);
    readThread = new CMclThread(reader);
}

ClientStdio::~ClientStdio()
{
    DWORD dwExit;

    readThread->GetExitCode(&dwExit);
    if (dwExit == STILL_ACTIVE) {
	readThread->Terminate(128);
    }
}

void
ClientStdio::Write(Message *what)
{
    DWORD dwWritten;
    HANDLE where;

    switch (what->type) {
    case Message::TYPE_NORMAL:
	where = hStdOut; break;
    case Message::TYPE_WARNING:
    case Message::TYPE_ERROR:
	where = hStdErr;
    }
    WriteFile(where, what->bytes, what->length, &dwWritten, 0L);
    delete what;
}

Changes to win/expWinTty.c.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: exp.h,v 1.1.4.4 2002/02/10 10:17:04 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

struct exp_f *exp_dev_tty = NULL;
char *exp_dev_tty_id = "exp_tty";







>







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinTty.c,v 1.1.2.1.2.4 2003/08/25 23:17:49 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinInt.h"

struct exp_f *exp_dev_tty = NULL;
char *exp_dev_tty_id = "exp_tty";
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

/*ARGSUSED*/
static int
Exp_SttyCmd(clientData, interp, argc, argv)
    ClientData clientData;
    Tcl_Interp *interp;
    int argc;
    char **argv;
{
#if 1
    /* redirection symbol is not counted as a stty arg in terms */
    /* of recognition. */
    int saw_unknown_stty_arg = FALSE;
    int saw_known_stty_arg = FALSE;
    int no_args = TRUE;

    int rc = TCL_OK;
    int cooked = FALSE;
    int was_raw, was_echo;

    char **argv0 = argv;

    for (argv=argv0+1;*argv;argv++) {
	if (argv[0][0] == '<') {
	    Tcl_AppendResult(interp, argv0,
		": redirection not supported on Windows NT", NULL);
	    return TCL_ERROR;
	}







|












|







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

/*ARGSUSED*/
static int
Exp_SttyCmd(clientData, interp, argc, argv)
    ClientData clientData;
    Tcl_Interp *interp;
    int argc;
    CONST char **argv;
{
#if 1
    /* redirection symbol is not counted as a stty arg in terms */
    /* of recognition. */
    int saw_unknown_stty_arg = FALSE;
    int saw_known_stty_arg = FALSE;
    int no_args = TRUE;

    int rc = TCL_OK;
    int cooked = FALSE;
    int was_raw, was_echo;

    CONST char **argv0 = argv;

    for (argv=argv0+1;*argv;argv++) {
	if (argv[0][0] == '<') {
	    Tcl_AppendResult(interp, argv0,
		": redirection not supported on Windows NT", NULL);
	    return TCL_ERROR;
	}
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

/*ARGSUSED*/
static int
Exp_SystemCmd(clientData, interp, argc, argv)
    ClientData clientData;
    Tcl_Interp *interp;
    int argc;
    char **argv;
{
    Tcl_AppendResult(interp, argv[0], ": not implemented", NULL);
    return TCL_ERROR;
}

static struct exp_cmd_data
cmd_data[]  = {







|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

/*ARGSUSED*/
static int
Exp_SystemCmd(clientData, interp, argc, argv)
    ClientData clientData;
    Tcl_Interp *interp;
    int argc;
    CONST char **argv;
{
    Tcl_AppendResult(interp, argv[0], ": not implemented", NULL);
    return TCL_ERROR;
}

static struct exp_cmd_data
cmd_data[]  = {

Changes to win/expWinUtils.cpp.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinUtils.cpp,v 1.1.2.5 2002/03/12 07:59:14 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinUtils.hpp"
#include "slavedrvmc.h"
#include <ctype.h>
#include <string.h>







>







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expWinUtils.cpp,v 1.1.2.8 2002/07/03 02:50:05 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "expWinUtils.hpp"
#include "slavedrvmc.h"
#include <ctype.h>
#include <string.h>
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
	Sleep(5000);
	ExitProcess(255);
    }

    LocalFree(errMsg);
}

char *ExpSyslogGetSysMsg (DWORD id)
{
    int chars;

    chars = wsprintf(sysMsgSpace, "[%d] ", id);

    FormatMessage(
	    FORMAT_MESSAGE_FROM_SYSTEM |
	    FORMAT_MESSAGE_MAX_WIDTH_MASK,
	    0L,
	    id,
	    0,







|



|







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
	Sleep(5000);
	ExitProcess(255);
    }

    LocalFree(errMsg);
}

char *GetSysMsg (DWORD id)
{
    int chars;

    chars = wsprintf(sysMsgSpace, "[%u] ", id);

    FormatMessage(
	    FORMAT_MESSAGE_FROM_SYSTEM |
	    FORMAT_MESSAGE_MAX_WIDTH_MASK,
	    0L,
	    id,
	    0,

Changes to win/expWinUtils.hpp.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

// Errors and logging
#define EXP_LOG0(errCode)		ExpWinSyslog(errCode, __FILE__, (int)__LINE__, 0)
#define EXP_LOG1(errCode, arg1)		ExpWinSyslog(errCode, __FILE__, (int)__LINE__, arg1, 0)
#define EXP_LOG2(errCode, arg1, arg2)	ExpWinSyslog(errCode, __FILE__, (int)__LINE__, arg1, arg2, 0)

void ExpWinSyslog (DWORD errCode, ...);
char *ExpSyslogGetSysMsg (DWORD id);

class ArgMaker
{
public:
    char *BuildCommandLine (int, char * const *);
};








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

// Errors and logging
#define EXP_LOG0(errCode)		ExpWinSyslog(errCode, __FILE__, (int)__LINE__, 0)
#define EXP_LOG1(errCode, arg1)		ExpWinSyslog(errCode, __FILE__, (int)__LINE__, arg1, 0)
#define EXP_LOG2(errCode, arg1, arg2)	ExpWinSyslog(errCode, __FILE__, (int)__LINE__, arg1, arg2, 0)

void ExpWinSyslog (DWORD errCode, ...);
char *GetSysMsg (DWORD id);

class ArgMaker
{
public:
    char *BuildCommandLine (int, char * const *);
};

Changes to win/expect.dsp.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\expect"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPECT_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\generic" /I "d:\tcl_workspace\tcl_head\generic" /D "NDEBUG" /D "WIN32" /D "BUILD_exp" /D TCL_THREADS=1 /D "USE_TCL_STUBS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head\generic" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 advapi32.lib user32.lib /nologo /dll /machine:I386 /out:"Release/expect60.dll" /libpath:"d:\tcl_workspace\tcl_head\win\Release"








|



|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\expect"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPECT_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\generic" /I "d:\tcl_workspace\tcl_head_stock\generic" /I "$(IntDir)" /D "NDEBUG" /D "WIN32" /D "BUILD_exp" /D TCL_THREADS=1 /D "USE_TCL_STUBS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head_stock\generic" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 advapi32.lib user32.lib /nologo /dll /machine:I386 /out:"Release/expect60.dll" /libpath:"d:\tcl_workspace\tcl_head\win\Release"

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\expect"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPECT_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /GB /MDd /W3 /Gm /GX /ZI /Od /I "." /I "..\generic" /I "d:\tcl_workspace\tcl_head\generic" /D "_DEBUG" /D "WIN32" /D "BUILD_exp" /D TCL_THREADS=1 /D "USE_TCL_STUBS" /FR /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head\generic" /d "DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 advapi32.lib user32.lib /nologo /dll /debug /machine:I386 /out:"Debug/expect60d.dll" /pdbtype:sept /libpath:"d:\tcl_workspace\tcl_head\win\Debug"

!ENDIF 

# Begin Target

# Name "expect - Win32 Release"
# Name "expect - Win32 Debug"







|



|





|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\expect"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPECT_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "..\generic" /I "d:\tcl_workspace\tcl_head_stock\generic" /I "$(IntDir)" /D "_DEBUG" /D "WIN32" /D "BUILD_exp" /D TCL_THREADS=1 /D "USE_TCL_STUBS" /FR /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head_stock\generic" /d "DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 advapi32.lib user32.lib /nologo /dll /debug /machine:I386 /out:"Debug/expect60d.dll" /pdbtype:sept /libpath:"d:\tcl_workspace\tcl_head_stock\win\Debug"

!ENDIF 

# Begin Target

# Name "expect - Win32 Release"
# Name "expect - Win32 Debug"
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
!ELSEIF  "$(CFG)" == "expect - Win32 Debug"

# Begin Custom Build - Rebuilding the Stubs table...
InputDir=\expect_wslive\expect_win32_take2\generic
InputPath=..\generic\exp.decls

BuildCmds= \
	c:\progra~1\tcl\bin\tclsh84 d:/tcl_workspace/tcl_head/tools/genStubs.tcl $(InputDir) $(InputPath)

"$(InputDir)\expDecls.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

"$(InputDir)\expPlatDecls.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)








|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
!ELSEIF  "$(CFG)" == "expect - Win32 Debug"

# Begin Custom Build - Rebuilding the Stubs table...
InputDir=\expect_wslive\expect_win32_take2\generic
InputPath=..\generic\exp.decls

BuildCmds= \
	c:\progra~1\tcl\bin\tclsh84 d:/tcl_workspace/tcl_head_stock/tools/genStubs.tcl $(InputDir) $(InputPath)

"$(InputDir)\expDecls.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

"$(InputDir)\expPlatDecls.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

239
240
241
242
243
244
245








246
247
248
249




250
251
252
253
254
255
256
257
258
259
260
261
262
# Begin Group "win"

# PROP Default_Filter ""
# Begin Group "winheaders"

# PROP Default_Filter ""
# Begin Source File









SOURCE=.\expWinInt.h
# End Source File
# Begin Source File





SOURCE=.\expWinPort.h
# End Source File
# Begin Source File

SOURCE=.\MsvcDbgControl.h
# End Source File
# End Group
# Begin Source File

SOURCE=.\expect.rc

!IF  "$(CFG)" == "expect - Win32 Release"







>
>
>
>
>
>
>
>




>
>
>
>





|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# Begin Group "win"

# PROP Default_Filter ""
# Begin Group "winheaders"

# PROP Default_Filter ""
# Begin Source File

SOURCE=.\expWinConsoleDebugger.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinInjectorIPC.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinInt.h
# End Source File
# Begin Source File

SOURCE=.\expWinMessage.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinPort.h
# End Source File
# Begin Source File

SOURCE=.\expWinUtils.hpp
# End Source File
# End Group
# Begin Source File

SOURCE=.\expect.rc

!IF  "$(CFG)" == "expect - Win32 Release"
270
271
272
273
274
275
276








277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297




298
299
300
301



302


303










304

















305
306
307
308
309
310
311
312
313
314
315

# End Source File
# Begin Source File

SOURCE=.\expWinCommand.c
# End Source File
# Begin Source File









SOURCE=.\expWinInit.c
# End Source File
# Begin Source File

SOURCE=.\expWinLog.c
# End Source File
# Begin Source File

SOURCE=.\expWinProcess.c
# End Source File
# Begin Source File

SOURCE=.\expWinSpawnChan.c
# End Source File
# Begin Source File

SOURCE=.\expWinTty.c
# End Source File
# Begin Source File





SOURCE=.\MsvcDbgControl.cpp

!IF  "$(CFG)" == "expect - Win32 Release"




# PROP Exclude_From_Build 1













!ELSEIF  "$(CFG)" == "expect - Win32 Debug"


















!ENDIF 

# End Source File
# Begin Source File

SOURCE=.\winDllMain.c
# End Source File
# End Group
# End Target
# End Project







>
>
>
>
>
>
>
>









|











>
>
>
>
|



>
>
>
|
>
>

>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371

# End Source File
# Begin Source File

SOURCE=.\expWinCommand.c
# End Source File
# Begin Source File

SOURCE=.\expWinConsoleDebugger.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinConsoleDebuggerBreakPoints.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinInit.c
# End Source File
# Begin Source File

SOURCE=.\expWinLog.c
# End Source File
# Begin Source File

SOURCE=.\expWinMessage.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinSpawnChan.c
# End Source File
# Begin Source File

SOURCE=.\expWinTty.c
# End Source File
# Begin Source File

SOURCE=.\expWinUtils.cpp
# End Source File
# Begin Source File

SOURCE=.\slavedrvmc.mc

!IF  "$(CFG)" == "expect - Win32 Release"

# Begin Custom Build - Compiling message catalog...
IntDir=.\Release\expect
InputPath=.\slavedrvmc.mc

BuildCmds= \
	mc -w -h "$(IntDir)" -r "$(IntDir)" $(InputPath)

"$(IntDir)\slavedrvmc.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

"$(IntDir)\slavedrvmc.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

"$(IntDir)\MSG00409.bin" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)
# End Custom Build

!ELSEIF  "$(CFG)" == "expect - Win32 Debug"

# Begin Custom Build - Compiling message catalog...
IntDir=.\Debug\expect
InputPath=.\slavedrvmc.mc

BuildCmds= \
	mc -w -h "$(IntDir)" -r "$(IntDir)" $(InputPath)

"$(IntDir)\slavedrvmc.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

"$(IntDir)\slavedrvmc.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)

"$(IntDir)\MSG00409.bin" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
   $(BuildCmds)
# End Custom Build

!ENDIF 

# End Source File
# Begin Source File

SOURCE=.\winDllMain.c
# End Source File
# End Group
# End Target
# End Project

Changes to win/expect.dsw.

1
2
3
4
5












6
7
8
9
10
11
12
13



14
15
16
17
18
19
20
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

###############################################################################













Project: "expect"=.\expect.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{



}}}

###############################################################################

Global:

Package=<5>





>
>
>
>
>
>
>
>
>
>
>
>








>
>
>







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
32
33
34
35
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

###############################################################################

Project: "Mcl"=.\Mcl\Mcl.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Project: "expect"=.\expect.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
    Begin Project Dependency
    Project_Dep_Name Mcl
    End Project Dependency
}}}

###############################################################################

Global:

Package=<5>

Changes to win/expect.rc.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: exp.h,v 1.1.4.4 2002/02/10 10:17:04 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <winver.h>
#include <winnt.h>

#define RESOURCE_INCLUDED  /* needed for tcl.h, only */
#include "exp.h"

#ifdef DEBUG
#define SUFFIX_DEBUG	    "d"
#else
#define SUFFIX_DEBUG	    ""
#endif







>







|





<
<







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31


32
33
34
35
36
37
38
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: expect.rc,v 1.1.2.1.2.5 2002/06/18 22:51:31 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <winver.h>
#include <winnt.h>


#include "exp.h"

#ifdef DEBUG
#define SUFFIX_DEBUG	    "d"
#else
#define SUFFIX_DEBUG	    ""
#endif
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    FILETYPE 	    VFT_DLL
    FILESUBTYPE	    0x0L
    BEGIN
	BLOCK "StringFileInfo"
	BEGIN
	    BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
	    BEGIN
		VALUE "FileDescription", "Expect DLL\0"
		VALUE "OriginalFilename", "expect" STRINGIFY(EXP_MAJOR_VERSION) STRINGIFY(EXP_MINOR_VERSION) SUFFIX ".dll\0"
		VALUE "CompanyName", "Teleindustrie, LLC\0"
		VALUE "FileVersion", EXP_PATCH_LEVEL
		VALUE "LegalCopyright", "Copyright \251 Teleindustrie, LLC 2002\0"
		VALUE "ProductName", "Expect " EXP_VERSION " for Win32\0"
		VALUE "ProductVersion", EXP_PATCH_LEVEL
		VALUE "Comments", "Expect was written for Unix by Don Libes at NIST.  This is the Win32 port.\0"
	    END
	END
	BLOCK "VarFileInfo"
	BEGIN
	    VALUE "Translation", 0x409, 1200
	END
    END







|
|
|
|
|
|
|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    FILETYPE 	    VFT_DLL
    FILESUBTYPE	    0x0L
    BEGIN
	BLOCK "StringFileInfo"
	BEGIN
	    BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
	    BEGIN
		VALUE "FileDescription",    "Expect Tcl extension DLL\0"
		VALUE "OriginalFilename",   "expect" EXP_VERSION SUFFIX ".dll\0"
		VALUE "CompanyName",	    "Teleindustrie, LLC\0"
		VALUE "FileVersion",	    EXP_PATCH_LEVEL
		VALUE "LegalCopyright",	    "Copyright \251 Teleindustrie, LLC 2002\r\nCopyright \251 2003 by ActiveState Corporation\0"
		VALUE "ProductName",	    "Expect " EXP_VERSION " for Win32\0"
		VALUE "ProductVersion",	    EXP_PATCH_LEVEL
		VALUE "Comments",	    "Expect was written for Unix by Don Libes at NIST.\r\n" "Gordon Chaffee ported it to WinNT for Mitel Corporation in 1997.\r\n" "David Gravereaux merged Gordon's port back into the official sources for Telindustrie LLC in Oct. 2001.\0"
	    END
	END
	BLOCK "VarFileInfo"
	BEGIN
	    VALUE "Translation", 0x409, 1200
	END
    END

Added win/inject.rc.



































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* ----------------------------------------------------------------------------
 * inject.rc --
 *
 *	Resource script for use with the resource compiler.
 * 
 * ----------------------------------------------------------------------------
 *
 * Written by: Don Libes, [email protected], NIST, 12/3/90
 * 
 * Design and implementation of this program was paid for by U.S. tax
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: inject.rc,v 1.1.2.1 2002/06/19 06:42:45 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <winver.h>
#include "exp.h"

VS_VERSION_INFO VERSIONINFO
    FILEVERSION	    1,0,0,0
    PRODUCTVERSION  EXP_MAJOR_VERSION,EXP_MINOR_VERSION,EXP_RELEASE_LEVEL,EXP_RELEASE_SERIAL
    FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK

#if defined(_DEBUG)
    FILEFLAGS	    VS_FF_DEBUG
#else
    FILEFLAGS	    0x0L
#endif
    FILEOS	    VOS__WINDOWS32    /* open to all */
    FILETYPE	    VFT_DLL
    FILESUBTYPE     VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
        BEGIN
            VALUE "FileDescription",	"Expect's console event injector tool that sits inside the slave process\0"
            VALUE "OriginalFilename",	"inject.dll\0"
            VALUE "CompanyName",	"Telindustrie, LLC\0"
            VALUE "FileVersion",	"1.0a0" "\0"
            VALUE "LegalCopyright",	"Copyright \251 Telindustrie, LLC 2002\r\nCopyright \251 2003 by ActiveState Corporation\0"
            VALUE "ProductName",	"Expect " EXP_VERSION " for Win32\0"
            VALUE "ProductVersion",	EXP_PATCH_LEVEL "\0"
	    VALUE "Comments",		"Expect was written for Unix by Don Libes at NIST.\r\n" "Gordon Chaffee ported it to WinNT for Mitel Corporation in 1997.\r\n" "David Gravereaux merged Gordon's port back into the official sources for Telindustrie LLC in Oct. 2001.\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

Added win/injector.dsp.

















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# Microsoft Developer Studio Project File - Name="injector" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102

CFG=injector - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "injector.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "injector.mak" CFG="injector - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "injector - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "injector - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe

!IF  "$(CFG)" == "injector - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "injector___Win32_Release"
# PROP BASE Intermediate_Dir "injector___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\injector"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INJECTOR_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\Mcl\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head_stock\generic" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib /nologo /subsystem:console /dll /machine:I386 /opt:nowin98
# SUBTRACT LINK32 /pdb:none

!ELSEIF  "$(CFG)" == "injector - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "injector___Win32_Debug"
# PROP BASE Intermediate_Dir "injector___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\injector"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INJECTOR_EXPORTS" /YX /FD /GZ  /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\Mcl\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ  /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head_stock\generic" /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept

!ENDIF 

# Begin Target

# Name "injector - Win32 Release"
# Name "injector - Win32 Debug"
# Begin Source File

SOURCE=.\expWinInjectorIPC.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinInjectorMain.cpp
# End Source File
# Begin Source File

SOURCE=.\inject.rc
# End Source File
# End Target
# End Project

Added win/injector.dsw.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

###############################################################################

Project: "Mcl"=.\Mcl\Mcl.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Project: "injector"=.\injector.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
    Begin Project Dependency
    Project_Dep_Name Mcl
    End Project Dependency
}}}

###############################################################################

Global:

Package=<5>
{{{
}}}

Package=<3>
{{{
}}}

###############################################################################

Changes to win/slavedrv.dsp.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\slavedrv"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\generic" /I "d:\tcl_workspace\tcl_head\generic" /I "d:\tcl_workspace\tcl_head\win" /I "$(IntDir)" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "USE_TCL_STUBS" /D IDE_LATCHED=0 /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head\generic" /i "$(IntDir)" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"d:\tcl_workspace\tcl_head\win\Release" /opt:nowin98
# SUBTRACT LINK32 /pdb:none

!ELSEIF  "$(CFG)" == "slavedrv - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "slavedrv___Win32_Debug"
# PROP BASE Intermediate_Dir "slavedrv___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\slavedrv"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /GB /MDd /W3 /Gm /GX /ZI /Od /I "." /I "..\generic" /I "d:\tcl_workspace\tcl_head\generic" /I "d:\tcl_workspace\tcl_head\win" /I "$(IntDir)" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "USE_TCL_STUBS" /D "BUILD_slavedriver" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head\generic" /i "$(IntDir)" /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"d:\tcl_workspace\tcl_head\win\Release"


!ENDIF 

# Begin Target

# Name "slavedrv - Win32 Release"
# Name "slavedrv - Win32 Debug"







|

|





|
















|

|





|
>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\slavedrv"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /G5 /MD /W3 /GX /O1 /I "." /I "..\generic" /I ".\Mcl\include" /I "c:\progra~1\tcl\include" /I "$(IntDir)" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "USE_TCL_STUBS" /D IDE_LATCHED=0 /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head_stock\generic" /i "$(IntDir)" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /libpath:"d:\tcl_workspace\tcl_head_stock\win\Release" /opt:nowin98
# SUBTRACT LINK32 /pdb:none

!ELSEIF  "$(CFG)" == "slavedrv - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "slavedrv___Win32_Debug"
# PROP BASE Intermediate_Dir "slavedrv___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\slavedrv"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "." /I "..\generic" /I ".\Mcl\include" /I "d:\tcl_workspace\tcl_head_stock\generic" /I "$(IntDir)" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "USE_TCL_STUBS" /D "BUILD_slavedriver" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /i "..\generic" /i "d:\tcl_workspace\tcl_head_stock\generic" /i "$(IntDir)" /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"d:\tcl_workspace\tcl_head_stock\win\Release"
# SUBTRACT LINK32 /profile /map

!ENDIF 

# Begin Target

# Name "slavedrv - Win32 Release"
# Name "slavedrv - Win32 Debug"
100
101
102
103
104
105
106




107
108
109
110




111
112
113
114
115
116
117
SOURCE=.\expWinConsoleDebugger.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinConsoleDebuggerBreakPoints.cpp
# End Source File
# Begin Source File





SOURCE=.\expWinDynloadTclStubs.cpp
# End Source File
# Begin Source File





SOURCE=.\expWinMessage.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinMessage.hpp
# End Source File







>
>
>
>




>
>
>
>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
SOURCE=.\expWinConsoleDebugger.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinConsoleDebuggerBreakPoints.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinConsoleKeyMap.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinDynloadTclStubs.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinInjectorIPC.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinMessage.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinMessage.hpp
# End Source File
125
126
127
128
129
130
131
132








133
134
135
136
137
138
139
140
141
142
143
# End Source File
# Begin Source File

SOURCE=.\expWinSlaveTrapDbg.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinSpawnClient.hpp








# End Source File
# Begin Source File

SOURCE=.\expWinSpawnStdioClient.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinUtils.cpp
# End Source File
# Begin Source File








|
>
>
>
>
>
>
>
>



|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# End Source File
# Begin Source File

SOURCE=.\expWinSlaveTrapDbg.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinTestClient.hpp
# End Source File
# Begin Source File

SOURCE=.\expWinTestClientConio.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinTestClientInteract.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinTestClientStdio.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinUtils.cpp
# End Source File
# Begin Source File

Changes to win/slavedrv.dsw.

35
36
37
38
39
40
41















42
43
44
45
46
47
48
Package=<5>
{{{
}}}

Package=<4>
{{{
}}}
















###############################################################################

Global:

Package=<5>
{{{







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Project: "test1"=.\test1.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
    Begin Project Dependency
    Project_Dep_Name Mcl
    End Project Dependency
}}}

###############################################################################

Global:

Package=<5>
{{{

Changes to win/slavedrv.rc.

18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

68
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: slavedrv.rc,v 1.1.2.1 2002/03/09 01:42:25 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <winver.h>


VS_VERSION_INFO VERSIONINFO
    FILEVERSION	    6,0,0,0
    PRODUCTVERSION  6,0,0,0
    FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK

#if defined(_DEBUG)
    FILEFLAGS	    VS_FF_DEBUG
#else
    FILEFLAGS	    0x0L
#endif
    FILEOS	    VOS__WINDOWS32    /* open to all */
    FILETYPE	    VFT_DLL
    FILESUBTYPE     VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
        BEGIN
            VALUE "FileDescription", "Spawn Driver helper application for overseeing Win32 consoles.\0"
            VALUE "OriginalFilename", "spawndrv.exe\0"
            VALUE "CompanyName", "Telindustrie, LLC\0"
            VALUE "FileVersion", "6.0a0" "\0"
            VALUE "LegalCopyright", "Copyright \251 Telindustrie, LLC 2002\0"
            VALUE "ProductName", "Expect " "6.0" " for Win32\0"
            VALUE "ProductVersion", "6.0a0" "\0"
	    VALUE "Comments", "Expect was written for Unix by Don Libes at NIST.\r\n" "Gordon Chaffee ported it to WinNT for Mitel Corporation in 1997.\r\n" "David Gravereaux merged Gordon's port back into the official sources for Telindustrie LLC in Oct. 2001.\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END


// Include the Message Table that lists the error codes and textual replies.
// This is output from the message compiler and found in the temp build directory.

#include "slavedrvmc.rc"







|




>


|
|








|






|
|
|
|
|
|
|
|











>

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: slavedrv.rc,v 1.1.2.3 2002/06/18 22:51:31 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include <winver.h>
#include "exp.h"

VS_VERSION_INFO VERSIONINFO
    FILEVERSION	    1,0,0,0
    PRODUCTVERSION  EXP_MAJOR_VERSION,EXP_MINOR_VERSION,EXP_RELEASE_LEVEL,EXP_RELEASE_SERIAL
    FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK

#if defined(_DEBUG)
    FILEFLAGS	    VS_FF_DEBUG
#else
    FILEFLAGS	    0x0L
#endif
    FILEOS	    VOS__WINDOWS32    /* open to all */
    FILETYPE	    VFT_APP
    FILESUBTYPE     VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
        BEGIN
            VALUE "FileDescription",	"Spawn Driver test application for overseeing Win32 consoles.\0"
            VALUE "OriginalFilename",	"spawndrv.exe\0"
            VALUE "CompanyName",	"Telindustrie, LLC\0"
            VALUE "FileVersion",	"1.0a0" "\0"
            VALUE "LegalCopyright",	"Copyright \251 Telindustrie, LLC 2002\0"
            VALUE "ProductName",	"Expect " EXP_VERSION " for Win32\0"
            VALUE "ProductVersion",	EXP_PATCH_LEVEL "\0"
	    VALUE "Comments",		"Expect was written for Unix by Don Libes at NIST.\r\n" "Gordon Chaffee ported it to WinNT for Mitel Corporation in 1997.\r\n" "David Gravereaux merged Gordon's port back into the official sources for Telindustrie LLC in Oct. 2001.\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END


// Include the Message Table that lists the error codes and textual replies.
// This is output from the message compiler and found in the temp build directory.

#include "slavedrvmc.rc"

Changes to win/slavedrv_test.dsp.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\slavedrv_test"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SLAVEDRV_TEST_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "d:\tcl_workspace\tcl_head\generic" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "USE_TCL_STUBS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\slavedrv_test"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SLAVEDRV_TEST_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "d:\tcl_workspace\tcl_head_stock\generic" /I "$(OUTDIR)..\slavedrv" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "USE_TCL_STUBS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
90
91
92
93
94
95
96







97
98
99
100
101
102
103
104
105
106
107
# Begin Source File

SOURCE=.\expWinTest.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinUtils.cpp







# End Source File
# Begin Source File

SOURCE=.\expWinUtils.hpp
# End Source File
# Begin Source File

SOURCE=.\TclAdapter.hpp
# End Source File
# End Target
# End Project







>
>
>
>
>
>
>











90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# Begin Source File

SOURCE=.\expWinTest.cpp
# End Source File
# Begin Source File

SOURCE=.\expWinUtils.cpp

!IF  "$(CFG)" == "slavedrv_test - Win32 Release"

!ELSEIF  "$(CFG)" == "slavedrv_test - Win32 Debug"

!ENDIF 

# End Source File
# Begin Source File

SOURCE=.\expWinUtils.hpp
# End Source File
# Begin Source File

SOURCE=.\TclAdapter.hpp
# End Source File
# End Target
# End Project

Added win/slavedrv_test.dsw.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

###############################################################################

Project: "slavedrv_test"=.\slavedrv_test.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Global:

Package=<5>
{{{
}}}

Package=<3>
{{{
}}}

###############################################################################

Changes to win/slavedrvmc.mc.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
; *	work by David Gravereaux <[email protected]> for any Win32 OS.
; *
; * ----------------------------------------------------------------------------
; * URLs:    http://expect.nist.gov/
; *	    http://expect.sf.net/
; *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
; * ----------------------------------------------------------------------------
; * RCS: @(#) $Id: slavedrvmc.mc,v 1.1.2.1 2002/03/09 01:42:00 davygrvy Exp $
; * ----------------------------------------------------------------------------
; */

MessageIdTypedef = DWORD
OutputBase = 16

SeverityNames = (







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
; *	work by David Gravereaux <[email protected]> for any Win32 OS.
; *
; * ----------------------------------------------------------------------------
; * URLs:    http://expect.nist.gov/
; *	    http://expect.sf.net/
; *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
; * ----------------------------------------------------------------------------
; * RCS: @(#) $Id: slavedrvmc.mc,v 1.1.2.3 2002/06/18 22:51:31 davygrvy Exp $
; * ----------------------------------------------------------------------------
; */

MessageIdTypedef = DWORD
OutputBase = 16

SeverityNames = (
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
Language=English
%1
.



MessageId=0x1
Severity=Error
Facility=Io
SymbolicName=MSG_IO_ARGSWRONG
Language=English
%1 : %2 (%3,%4): No commandline arguements to slavedrv.exe.  No work to do.
.

MessageId=0x2
Severity=Warning
Facility=Io
SymbolicName=MSG_IO_BADSHUTDOWN
Language=English
%1 : %2 (%3,%4): Unclean shutdown: %5
.

MessageId=0x2
Severity=Error
Facility=Io
SymbolicName=MSG_IO_UNEXPECTED
Language=English
%1 : %2 (%3,%4): Unexpected error: %5
.

MessageId=0x3
Severity=Fatal
Facility=Io
SymbolicName=MSG_IO_TRANSPRTARGSBAD
Language=English
%1 : %2 (%3,%4): Transport protocol bad: %5
.

MessageId=0x4
Severity=Fatal
Facility=Io
SymbolicName=MSG_IO_TRAPARGSBAD
Language=English
%1 : %2 (%3,%4): Trap method bad: %5
.



MessageId=0x0
Severity=Error
Facility=Mailbox
SymbolicName=MSG_MB_CANTOPENCLIENT1
Language=English
%1 : %2 (%3,%4): Can't open client-side IPC mailbox for named mailbox "%5".
.

MessageId=0x1
Severity=Error
Facility=Mailbox
SymbolicName=MSG_MB_CANTOPENCLIENT2
Language=English
%1 : %2 (%3,%4): Can't open client-side IPC mailbox for named mailbox "%5".  Got system error %6
.









|















|











|







|





|







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
Language=English
%1
.



MessageId=0x1
Severity=Fatal
Facility=Io
SymbolicName=MSG_IO_ARGSWRONG
Language=English
%1 : %2 (%3,%4): No commandline arguements to slavedrv.exe.  No work to do.
.

MessageId=0x2
Severity=Warning
Facility=Io
SymbolicName=MSG_IO_BADSHUTDOWN
Language=English
%1 : %2 (%3,%4): Unclean shutdown: %5
.

MessageId=0x2
Severity=Fatal
Facility=Io
SymbolicName=MSG_IO_UNEXPECTED
Language=English
%1 : %2 (%3,%4): Unexpected error: %5
.

MessageId=0x3
Severity=Fatal
Facility=Io
SymbolicName=MSG_IO_TRANSPRTARGSBAD
Language=English
%1 : %2 (%3,%4): Transport protocol bad (must be 'conio' or 'stdio'): %5
.

MessageId=0x4
Severity=Fatal
Facility=Io
SymbolicName=MSG_IO_TRAPARGSBAD
Language=English
%1 : %2 (%3,%4): Trap method bad (only 'dbg' is available): %5
.



MessageId=0x0
Severity=Fatal
Facility=Mailbox
SymbolicName=MSG_MB_CANTOPENCLIENT1
Language=English
%1 : %2 (%3,%4): Can't open client-side IPC mailbox for named mailbox "%5".
.

MessageId=0x1
Severity=Fatal
Facility=Mailbox
SymbolicName=MSG_MB_CANTOPENCLIENT2
Language=English
%1 : %2 (%3,%4): Can't open client-side IPC mailbox for named mailbox "%5".  Got system error %6
.


209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
Facility=MasterSlave_Protocol
SymbolicName=MSG_MS_SLAVENOWRITABLE
Language=English
%1 : %2 (%3,%4): Unable to write to slave: %5
.

MessageId=0x2
Severity=Error
Facility=MasterSlave_Protocol
SymbolicName=MSG_MS_BADSTATE
Language=English
%1 : %2 (%3,%4): Unexpected state
.




MessageId=0x1
Severity=Error
Facility=NamedPipe
SymbolicName=MSG_NP_CANTOPEN
Language=English
%1 : %2 (%3,%4): Can't open argv[1], "%5", for read/write.  CreateFile() returned: %6
.

MessageId=0x2
Severity=Error
Facility=NamedPipe
SymbolicName=MSG_NP_BADTYPE
Language=English
%1 : %2 (%3,%4): NamedPipe specified as, "%5", was found not to be a pipe filetype.
.


MessageId=0x1
Severity=Error
Facility=WinSock
SymbolicName=MSG_WS_CANTSTART
Language=English
%1 : %2 (%3,%4): WinSock system was unable to start.  slavedrv.exe requested version %5.  WSAStartup() returned: %6
.

MessageId=0x2
Severity=Error
Facility=WinSock
SymbolicName=MSG_WS_CANTCREATEMASTERSOCK
Language=English
%1 : %2 (%3,%4): Master socket was unable to be created.  WSASocket() returned: %6
.

MessageId=0x3
Severity=Error
Facility=WinSock
SymbolicName=MSG_WS_CANTCONNECTMASTERSOCK
Language=English
%1 : %2 (%3,%4): Can't connect to local loopback on port %5.  connect() returned: %6
.

MessageId=0x4
Severity=Error
Facility=WinSock
SymbolicName=MSG_WS_PORTOUTOFRANGE
Language=English
%1 : %2 (%3,%4): Local loopback port out-of-range at "%5".  Must be greater than zero and less than 65536.
.




MessageId=0x1
Severity=Error
Facility=DbgTrap
SymbolicName=MSG_DT_CANTGETCONSOLEHANDLE
Language=English
%1 : %2 (%3,%4): Can't open the console handle. CreateFile("%5") returned: %6
.

MessageId=0x2







|










|







|








|







|







|







|










|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
Facility=MasterSlave_Protocol
SymbolicName=MSG_MS_SLAVENOWRITABLE
Language=English
%1 : %2 (%3,%4): Unable to write to slave: %5
.

MessageId=0x2
Severity=Fatal
Facility=MasterSlave_Protocol
SymbolicName=MSG_MS_BADSTATE
Language=English
%1 : %2 (%3,%4): Unexpected state
.




MessageId=0x1
Severity=Fatal
Facility=NamedPipe
SymbolicName=MSG_NP_CANTOPEN
Language=English
%1 : %2 (%3,%4): Can't open argv[1], "%5", for read/write.  CreateFile() returned: %6
.

MessageId=0x2
Severity=Fatal
Facility=NamedPipe
SymbolicName=MSG_NP_BADTYPE
Language=English
%1 : %2 (%3,%4): NamedPipe specified as, "%5", was found not to be a pipe filetype.
.


MessageId=0x1
Severity=Fatal
Facility=WinSock
SymbolicName=MSG_WS_CANTSTART
Language=English
%1 : %2 (%3,%4): WinSock system was unable to start.  slavedrv.exe requested version %5.  WSAStartup() returned: %6
.

MessageId=0x2
Severity=Fatal
Facility=WinSock
SymbolicName=MSG_WS_CANTCREATEMASTERSOCK
Language=English
%1 : %2 (%3,%4): Master socket was unable to be created.  WSASocket() returned: %6
.

MessageId=0x3
Severity=Fatal
Facility=WinSock
SymbolicName=MSG_WS_CANTCONNECTMASTERSOCK
Language=English
%1 : %2 (%3,%4): Can't connect to local loopback on port %5.  connect() returned: %6
.

MessageId=0x4
Severity=Fatal
Facility=WinSock
SymbolicName=MSG_WS_PORTOUTOFRANGE
Language=English
%1 : %2 (%3,%4): Local loopback port out-of-range at "%5".  Must be greater than zero and less than 65536.
.




MessageId=0x1
Severity=Fatal
Facility=DbgTrap
SymbolicName=MSG_DT_CANTGETCONSOLEHANDLE
Language=English
%1 : %2 (%3,%4): Can't open the console handle. CreateFile("%5") returned: %6
.

MessageId=0x2
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
















327
328
329
330
331
332








Facility=DbgTrap
SymbolicName=MSG_DT_NOVIRT
Language=English
%1 : %2 (%3,%4): Unable to find entry for VirtualAlloc
.

MessageId=0x5
Severity=Warning
Facility=DbgTrap
SymbolicName=MSG_DT_CANTREADSPMEM
Language=English
%1 : %2 (%3,%4): Error reading from subprocess memory
.

MessageId=0x6
Severity=Warning
Facility=DbgTrap
SymbolicName=MSG_DT_CANTWRITESPMEM
Language=English
%1 : %2 (%3,%4): Error writing to subprocess memory
.

MessageId=0x7
















Severity=Warning
Facility=DbgTrap
SymbolicName=MSG_DT_SCREENBUF
Language=English
%1 : %2 (%3,%4): Call to GetConsoleScreenBufferInfo() failed with %5, %6
.















|



|



|



|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
Facility=DbgTrap
SymbolicName=MSG_DT_NOVIRT
Language=English
%1 : %2 (%3,%4): Unable to find entry for VirtualAlloc
.

MessageId=0x5
Severity=Fatal
Facility=DbgTrap
SymbolicName=MSG_DT_CANTREADSPMEM
Language=English
%1 : %2 (%3,%4): Error reading from subprocess memory, %5
.

MessageId=0x6
Severity=Fatal
Facility=DbgTrap
SymbolicName=MSG_DT_CANTWRITESPMEM
Language=English
%1 : %2 (%3,%4): Error writing to subprocess memory, %5
.

MessageId=0x7
Severity=Fatal
Facility=DbgTrap
SymbolicName=MSG_DT_CANTMAKENTSPMEM
Language=English
%1 : %2 (%3,%4): Error creating subprocess memory.  VirtualAllocEx() failed, %5
.

MessageId=0x8
Severity=Fatal
Facility=DbgTrap
SymbolicName=MSG_DT_CANTMAKE95SPMEM
Language=English
%1 : %2 (%3,%4): Error creating subprocess memory, %5
.

MessageId=0x9
Severity=Warning
Facility=DbgTrap
SymbolicName=MSG_DT_SCREENBUF
Language=English
%1 : %2 (%3,%4): Call to GetConsoleScreenBufferInfo() failed with %5, %6
.

MessageId=0xa
Severity=Fatal
Facility=DbgTrap
SymbolicName=MSG_DT_BADDEBUGGEE
Language=English
%1 : %2 (%3,%4): Unable to start debuggee from commandline: "%5", %6
.

Added win/test1.cpp.









































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
    Follow the mouse.
*/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincon.h>
#include "./Mcl/include/cmcl.h"

#define RECORD_SIZE 15
INPUT_RECORD Records[RECORD_SIZE];
HANDLE ConIn, ConOut;
CMclEvent stop;

void HandleKey(KEY_EVENT_RECORD *ker);
void HandleMouse(MOUSE_EVENT_RECORD *mer);
void HandleWindow(WINDOW_BUFFER_SIZE_RECORD *wbsr);
BOOL isDiff(MOUSE_EVENT_RECORD *mer1, MOUSE_EVENT_RECORD *mer2);
BOOL WINAPI ConsoleHandler(DWORD code);

int main (void)
{
    DWORD dwRead, i;
    CONSOLE_CURSOR_INFO cci = {100, 1};
    MOUSE_EVENT_RECORD lastMouse;
    CMclWaitableCollection groupedHandles;
    DWORD dwRet;
    HANDLE oldBuffer;

    ConIn = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
    oldBuffer = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
    ConOut = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
	    FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, CONSOLE_TEXTMODE_BUFFER, 0L);

    if (!ConIn || !oldBuffer || !ConOut) {
	WriteFile(GetStdHandle(STD_ERROR_HANDLE), "need console! die, die!\n", 24, &dwRet, 0L);
	return -1;
    }

    SetConsoleCtrlHandler(ConsoleHandler, TRUE);
    SetConsoleActiveScreenBuffer(ConOut);
    SetConsoleMode(ConIn, ENABLE_WINDOW_INPUT|ENABLE_MOUSE_INPUT);
    SetConsoleCursorInfo(ConOut, &cci);
    SetConsoleOutputCP(437); // us-ascii code page.

    // Index 0, highest priority goes first.
    groupedHandles.AddObject(stop);

    // Console handles are waitable objects.
    // Index 1
    groupedHandles.AddObject(ConIn);

again:
    // Wait for any (either) to signal.
    dwRet = groupedHandles.Wait(FALSE, INFINITE);

    if (!CMclWaitSucceeded(dwRet, groupedHandles.GetCount()) ||
	    CMclWaitSucceededIndex(dwRet) == 0) {
	// stop event or some other error, so die.
	CloseHandle(ConIn);
	CloseHandle(ConOut);
	SetConsoleActiveScreenBuffer(oldBuffer);
	return 0;
    }

    ReadConsoleInput(ConIn, Records, RECORD_SIZE, &dwRead);
    for (i = 0; i < dwRead; i++) {
	switch (Records[i].EventType) {
	case KEY_EVENT:
	    HandleKey(&Records[i].Event.KeyEvent);
	    break;
	case MOUSE_EVENT:
	    if (isDiff(&lastMouse, &Records[i].Event.MouseEvent)) {
		lastMouse = Records[i].Event.MouseEvent;
		HandleMouse(&Records[i].Event.MouseEvent);
	    }
	    break;
	case WINDOW_BUFFER_SIZE_EVENT:
	    HandleWindow(&Records[i].Event.WindowBufferSizeEvent);
	    break;
	}
    }
    goto again;
}

void
HandleKey(KEY_EVENT_RECORD *ker)
{
    // exit on esc.
    if (ker->wVirtualKeyCode == VK_ESCAPE && ker->bKeyDown) stop.Set();
}

void
HandleMouse(MOUSE_EVENT_RECORD *mer)
{
    // put the cursor where the mouse is.
    SetConsoleCursorPosition(ConOut, mer->dwMousePosition);
}

void
HandleWindow(WINDOW_BUFFER_SIZE_RECORD *wbsr)
{
}

BOOL
isDiff(MOUSE_EVENT_RECORD *mer1, MOUSE_EVENT_RECORD *mer2)
{
    if (
	mer1->dwMousePosition.X ^ mer2->dwMousePosition.X ||
	mer1->dwMousePosition.Y ^ mer2->dwMousePosition.Y ||
	mer1->dwButtonState     ^ mer2->dwButtonState ||
	mer1->dwControlKeyState ^ mer2->dwControlKeyState ||
	mer1->dwEventFlags      ^ mer2->dwEventFlags
    ) {
	return TRUE;
    } else {
	return FALSE;
    }

}

BOOL WINAPI
ConsoleHandler (DWORD code)
{
    // this routine is called by a kernel supplied thread.

    // no matter what condition comes in, shutdown.
    stop.Set();
    return TRUE;
}

Added win/test1.dsp.



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# Microsoft Developer Studio Project File - Name="test1" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Console Application" 0x0103

CFG=test1 - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "test1.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "test1.mak" CFG="test1 - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "test1 - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "test1 - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe

!IF  "$(CFG)" == "test1 - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "test1___Win32_Release"
# PROP BASE Intermediate_Dir "test1___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release\test1"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib /nologo /subsystem:console /machine:I386

!ELSEIF  "$(CFG)" == "test1 - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "test1___Win32_Debug"
# PROP BASE Intermediate_Dir "test1___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug\test1"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

!ENDIF 

# Begin Target

# Name "test1 - Win32 Release"
# Name "test1 - Win32 Debug"
# Begin Source File

SOURCE=.\test1.cpp
# End Source File
# End Target
# End Project

Changes to win/winDllMain.c.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC

 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: winDllMain.c,v 1.1.2.4 2002/02/10 12:03:30 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "tcl.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>








>







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * dollars.  Therefore it is public domain.  However, the author and NIST
 * would appreciate credit if this program or parts of it are used.
 * 
 * Copyright (c) 1997 Mitel Corporation
 *	work by Gordon Chaffee <[email protected]> for the WinNT port.
 *
 * Copyright (c) 2001-2002 Telindustrie, LLC
 * Copyright (c) 2003 ActiveState Corporation
 *	work by David Gravereaux <[email protected]> for any Win32 OS.
 *
 * ----------------------------------------------------------------------------
 * URLs:    http://expect.nist.gov/
 *	    http://expect.sf.net/
 *	    http://bmrc.berkeley.edu/people/chaffee/expectnt.html
 * ----------------------------------------------------------------------------
 * RCS: @(#) $Id: winDllMain.c,v 1.1.2.5 2002/02/16 03:17:00 davygrvy Exp $
 * ----------------------------------------------------------------------------
 */

#include "tcl.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	     * The requirement for msvcrt.lib from tclstubXX.lib must
	     * be removed.  This bug has been fixed since 8.4a3, I beleive. */
#	    pragma comment(linker, "-nodefaultlib:msvcrt.lib")
#	endif
#   else
#	ifdef _DEBUG
#	    pragma comment (lib, "tcl" \
		    STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) "d.lib")
#	else
#	    pragma comment (lib, "tcl" \
		    STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
#	endif
#   endif
#endif








|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
	     * The requirement for msvcrt.lib from tclstubXX.lib must
	     * be removed.  This bug has been fixed since 8.4a3, I beleive. */
#	    pragma comment(linker, "-nodefaultlib:msvcrt.lib")
#	endif
#   else
#	ifdef _DEBUG
#	    pragma comment (lib, "tcl" \
		    STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) "g.lib")
#	else
#	    pragma comment (lib, "tcl" \
		    STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
#	endif
#   endif
#endif