Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Contents of /trunk/TTXSamples/ttxtest/ttxtest.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3227 - (show annotations) (download) (as text)
Tue Mar 24 15:10:33 2009 UTC (15 years, 1 month ago) by maya
File MIME type: text/x-csrc
File size: 18081 byte(s)
CVS から SVN へ移行: 改行コードを LF から CR+LF へ変換
1 /* Tera Term extension mechanism
2 Robert O'Callahan (roc+tt@cs.cmu.edu)
3
4 Tera Term by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
5 */
6
7 /* HOW TO WRITE A TERATERM EXTENSION
8
9 First of all, you will need the source code to Tera Term. For that, you
10 should visit the Tera Term Web page:
11 http://www.vector.co.jp/authors/VA002416/teraterm.html
12 You will frequently need to refer to the source code to find out how things
13 work and when your functions are called. However, please try to write your
14 extension without assuming too much about the behaviour of Tera Term, in
15 case it changes in the future!
16
17 You will also need a compiler that can build Tera Term. So far, the
18 extension system has only been tested with Visual C++ 4.2. Please report
19 any problems to me (roc).
20
21 Then you can compile this sample extension.
22
23 Make sure you set the structure alignment option in the project to
24 8 bytes (for Win32) or 2 bytes (for Win16), to be compatible with the
25 standard Tera Term binary.
26
27 You must add the Tera Term "common" directory to your include path
28 to find the following 3 include files:
29 */
30
31 #include "teraterm.h"
32 #include "tttypes.h"
33 #include "ttplugin.h"
34
35 /* These are the standard libraries used below. The main Tera Term program and
36 all its DLLs are each statically linked to the C runtime library --- i.e.
37 they do not require any runtime library DLL, and they each have private
38 copies of the runtime library functions that they use. Therefore, it's
39 probably best if TTXs use the same strategy.
40 */
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45
46 #include "compat_w95.h"
47
48 /* When you build this extension, it should be called TTXTEST.DLL. To try it
49 out, copy it into the directory containing Tera Term. Currently, in order
50 to use extensions with Tera Term, you have to set the environment variable
51 TERATERM_EXTENSIONS to something. So in a command shell, use
52 "set TERATERM_EXTENSIONS=1". Then use "ttermpro > dump" to run Tera Term
53 and save the debugging output below to the file "dump".
54
55 When TERATERM_EXTENSIONS is set, Tera Term automatically scans the
56 directory containing it, looking for files of the form TTX*.DLL.
57 It loads any that it finds. For each one that it finds, it calls TTXBind;
58 see below for details.
59 */
60
61
62 /* This variable is used for the load order of the extension (see below for
63 details). We also print it out in all the diagnostics, to make sure the
64 functions are being called according to the correct order. */
65 #define ORDER 4000
66
67 /* This code demonstrates how to maintain separate instance variables for
68 each instance of Tera Term that's using the DLL. It's easy in Win32,
69 because it happens automatically, but in Win16 there is only one set of
70 global data for all Tera Terms using the DLL, so we have to jump through
71 some hoops.
72 */
73 static HANDLE hInst; /* Instance handle of TTX*.DLL */
74
75 typedef struct {
76 PTTSet ts;
77 PComVar cv;
78 HMENU SetupMenu;
79 } TInstVar;
80
81 static TInstVar FAR * pvar;
82
83 /* WIN32 allows multiple instances of a DLL */
84 static TInstVar InstVar;
85
86 /* When this function is called, you should save copies of the ts and cv
87 pointers if you need to access them later. All sorts of global session data
88 is stored in these variables, and you can do all sorts of tricks by reading
89 and modifying their fields in some of the functions below. You'll have to
90 look at the Tera Term source code to see what the fields do and how and
91 when they're used.
92
93 This is called when Tera Term starts up, so don't do too much work in here
94 or you will slow down the startup process even if your extension is not
95 going to be used.
96 */
97 static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv) {
98 pvar->ts = ts;
99 pvar->cv = cv;
100 }
101
102 /* This function is called when Tera Term is opening a TCP connection, before
103 any Winsock functions have actually been called.
104
105 You receive a 'hooks' structure containing pointers to pointers to all the
106 Winsock functions that Tera Term will use. You can replace any of these
107 function pointers to point to your own routines. However, if you replace a
108 function pointer, you should save the old pointer somewhere and use that
109 instead of calling Winsock directly. Some other extension might have put
110 something there for you to use!
111
112 For example:
113
114 [in TTXOpenTCP]
115 ... saved_connect = hooks->Pconnect; hooks->Pconnect = my_connect; ...
116
117 [in my_connect]
118 ... saved_connect(...); ...
119 [don't call the real connect!]
120
121 Extensions that don't apply to all sessions (e.g. any extension that can be
122 disabled by the user) will check to see if they apply to the current
123 session, and if they don't, then no functions are be changed.
124
125 This function is called for each extension, in load order (see below).
126 Thus, the extension with highest load order puts its hooks in last.
127 */
128 static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks) {
129 printf("TTXOpenTCP %d\n", ORDER);
130 }
131
132 /* This function is called when Tera Term is closing a TCP connection, after
133 all Winsock functions have been called.
134
135 Here you should restore any hooked pointers that you saved away. For
136 example:
137 ... hooks->Pconnect = saved_connect; ...
138
139 This function is called for each extension, in reverse load order (see
140 below).
141 */
142 static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks) {
143 printf("TTXCloseTCP %d\n", ORDER);
144 }
145
146 /* This function is called when Tera Term has loaded the TTDLG library. It
147 gives the extension an opportunity to modify the function pointers that are
148 used to create dialog boxes.
149
150 Unlike the TCP functions, there's no reason to call the previous version of
151 a hooked function. When you replace a dialog box, the new dialog box should
152 do everything that the original dialog box did, plus any extra controls
153 that you want. You'll probably have to copy the code from TTDLG to do this.
154
155 If multiple extensions want to replace the same dialog box, the one with
156 the highest load order number (see below) wins. For this reason, when
157 writing an extension, you should look at the extensions that already exist
158 and try to figure out how to make your extension work nicely with the
159 others that modify the same dialog box as you do. I suggest that anyone who
160 modifies a dialog box should export functions from their extension DLL so
161 that other code can change the extra settings without going through that
162 dialog box. Then, if there is an extension with a lower load order number
163 that changes a dialog box that you also want to change, you can create a
164 new dialog box that has all their changes plus your own, and call the
165 exported functions in the other DLL when the user sets options for that
166 other DLL. If that didn't make sense, send me email :-).
167
168 A typical use for this function is to hook the GetHostName function so that
169 extra options can be added to the connection dialog box. Whenever possible
170 (without making the user interface clumsy), an extension should introduce
171 new dialog boxes reachable by adding menu items (see below), rather than
172 overriding an existing dialog box. Any UI for setup options should probably
173 be handled this way.
174
175 This function is called for each extension, in load order (see below).
176 Thus, the extension with highest load order puts its hooks in last.
177 */
178 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks) {
179 printf("TTXSetUIHooks %d\n", ORDER);
180 }
181
182 /* This function is called when Tera Term has loaded the TTSETUP library. It
183 gives the extension an opportunity to modify the function pointers that are
184 used to read and write the settings file (TERATERM.INI) and to read and
185 write the command line.
186
187 An extension will almost always hook these functions. When Tera Term reads
188 or writes its setup file, the extension will read or write its own internal
189 settings to an appropriate section of the INI file. When Tera Term parses
190 its command line, or builds a new command line to spawn a new Tera Term
191 session, the extension will check for its own options or write out its own
192 options.
193
194 Any hooked functions should pass through to the old functions, just as in
195 TTXOpenTCP.
196
197 This function is called for each extension, in load order (see below).
198 Thus, the extension with highest load order puts its hooks in last.
199 */
200 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks) {
201 printf("TTXSetSetupHooks %d\n", ORDER);
202 }
203
204 /* This function is called whenever Tera Term changes the window size.
205
206 This function is called for each extension, in load order (see below).
207 */
208 static void PASCAL FAR TTXSetWinSize(int rows, int cols) {
209 printf("TTXSetWinSize %d\n", ORDER);
210 }
211
212 /* This function is called when Tera Term creates a new menu. This can happen
213 quite often, especially when the menubar is hidden and Tera Term wants to
214 create a popup menu because the user ctrl-clicked in the window.
215
216 The 'menu' parameter is the HMENU for the menu bar. The extension can add
217 items to the existing submenus or even add an entirely new submenu. This is
218 great for adding menu items that control the extension's options.
219
220 This function is called for each extension, in load order (see below).
221 Thus, the extension with highest load order number puts its items in last.
222 */
223 #define ID_MENUITEM 6000
224 static void PASCAL FAR TTXModifyMenu(HMENU menu) {
225 UINT flag = MF_ENABLED;
226
227 printf("TTXModifyMenu %d\n", ORDER);
228
229 pvar->SetupMenu = GetSubMenu(menu,2);
230 AppendMenu(pvar->SetupMenu,MF_SEPARATOR,0,NULL);
231 if (pvar->ts->Debug>0) flag |= MF_CHECKED;
232 AppendMenu(pvar->SetupMenu,flag, ID_MENUITEM,"&Debug mode");
233 }
234
235 /* This function is called when Tera Term pops up a submenu menu.
236
237 The 'menu' parameter is the HMENU for the submenu. The extension can change
238 the status of any of the menu items, for example graying out some items.
239 Extensions should make sure that this is actually the submenu that they
240 care about!
241
242 This function is called for each extension, in load order (see below).
243 */
244 static void PASCAL FAR TTXModifyPopupMenu(HMENU menu) {
245 printf("TTXModifyPopupMenu %d\n", ORDER);
246
247 if (menu==pvar->SetupMenu)
248 {
249 if (pvar->cv->Ready)
250 EnableMenuItem(pvar->SetupMenu,ID_MENUITEM,MF_BYCOMMAND | MF_ENABLED);
251 else
252 EnableMenuItem(pvar->SetupMenu,ID_MENUITEM,MF_BYCOMMAND | MF_GRAYED);
253 }
254 }
255
256 /* This function is called when Tera Term receives a command message.
257
258 The extension returns 1 if it processed the message, 0 otherwise. If it
259 says it processed the message, then the message will not be processed
260 anywhere else. The extensions look at the messages before the main
261 Tera Term code, so be careful of overriding existing commands.
262
263 This function is called for each extension, in reverse load order (see
264 below). Thus, the extension that has highest load order number gets to
265 process the command first.
266 */
267 static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd) {
268 printf("TTXProcessCommand %d\n", ORDER);
269
270 if (cmd==ID_MENUITEM)
271 {
272 if (pvar->ts->Debug==0)
273 {
274 pvar->ts->Debug=1;
275 CheckMenuItem(pvar->SetupMenu,ID_MENUITEM,MF_BYCOMMAND | MF_CHECKED);
276 }
277 else {
278 pvar->ts->Debug=0;
279 CheckMenuItem(pvar->SetupMenu,ID_MENUITEM,MF_BYCOMMAND | MF_UNCHECKED);
280 }
281 return 1;
282 }
283 return 0;
284 }
285
286 /* This function is called when Tera Term is quitting. You can use it to clean
287 up.
288
289 This function is called for each extension, in reverse load order (see
290 below).
291 */
292 static void PASCAL FAR TTXEnd(void) {
293 printf("TTXEnd %d\n", ORDER);
294 }
295
296 /*
297 */
298 static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen, PGetHNRec rec) {
299 printf("TTXSetCommandLine %d\n", ORDER);
300 }
301
302 /* This function is called when Tera Term is opening a Serial port and Replay
303 log file.
304
305 You receive a 'hooks' structure containing pointers to pointers to all the
306 file IO functions that Tera Term will use. You can replace any of these
307 function pointers to point to your own routines. However, if you replace a
308 function pointer, you should save the old pointer somewhere and use that
309 instead of calling file IO functions directly. Some other extension might
310 have put something there for you to use!
311
312 For example:
313
314 [in TTXOpenFile]
315 ... saved_createfile = hooks->PCreateFile; hooks->PCreateFile = my_createfile; ...
316
317 [in my_createfile]
318 ... saved_createfile(...); ...
319 [don't call the real CreateFile!]
320
321 Extensions that don't apply to all sessions (e.g. any extension that can be
322 disabled by the user) will check to see if they apply to the current
323 session, and if they don't, then no functions are be changed.
324
325 This function is called for each extension, in load order (see below).
326 Thus, the extension with highest load order puts its hooks in last.
327 */
328 static void PASCAL FAR TTXOpenFile(TTXFileHooks FAR * hooks) {
329 printf("TTXOpenFile %d\n", ORDER);
330 }
331
332 /* This function is called when Tera Term is closing a serial connection,
333 after all file IO functions have been called.
334
335 Here you should restore any hooked pointers that you saved away. For
336 example:
337 ... hooks->PCreateFile = saved_createfile; ...
338
339 This function is called for each extension, in reverse load order (see
340 below).
341 */
342 static void PASCAL FAR TTXCloseFile(TTXFileHooks FAR * hooks) {
343 printf("TTXCloseFile %d\n", ORDER);
344 }
345
346 /* This record contains all the information that the extension forwards to the
347 main Tera Term code. It mostly consists of pointers to the above functions.
348 Any of the function pointers can be replaced with NULL, in which case
349 Tera Term will just ignore that function and assume default behaviour,
350 which means "do nothing".
351 */
352 static TTXExports Exports = {
353 /* This must contain the size of the structure. See below for its usage. */
354 sizeof(TTXExports),
355
356 /* This is the load order number of this DLL. It affects which order the above
357 functions are called in, as noted for each function. Choose this number
358 carefully! Typically the DLLs with higher numbers are layered on top of the
359 DLLs with lower numbers. Thus, a DLL that does SOCKS redirection will have
360 a lower load order than a DLL that does the SSH protocol, because SOCKS
361 redirection must happen "before" SSH processing. Likewise, a DLL that does
362 Kerberos authentication must have a higher order number than a DLL that
363 does SSL, because the Kerberos protocol uses telnet options that would go
364 "on top of" SSL.
365
366 Currently, no order numbers are used because no real extensions have been
367 written.
368 I suggest the following numbers:
369 0-999: Basic network naming and communication (e.g. SOCKS)
370 1000-1999: Transport emulation (e.g. SSL)
371 2000-2999: Protocols (e.g. SSH, telnet)
372 3000-3999: Protocol extensions (e.g. Kerberos telnet options)
373 4000-4999: Application features (e.g. file transfers, UI for hidden setup
374 options)
375
376 Try to use numbers in the middle of any available range so that other
377 extensions can load before or after you as they wish.
378 */
379 ORDER,
380
381 /* Now we just list the functions that we've implemented. */
382 TTXInit,
383 TTXGetUIHooks,
384 TTXGetSetupHooks,
385 TTXOpenTCP,
386 TTXCloseTCP,
387 TTXSetWinSize,
388 TTXModifyMenu,
389 TTXModifyPopupMenu,
390 TTXProcessCommand,
391 TTXEnd,
392 TTXSetCommandLine,
393 TTXOpenFile,
394 TTXCloseFile
395 };
396
397 /* This is the function that Tera Term calls to retrieve the export
398 information. This code is for Visual C++. The name that gets exported is
399 "_TTXBind@8" and that is what the Tera Term program looks for. So,
400 whichever compiler you use, you must make sure that that name is exported.
401
402 The job of this function is to copy the export data from the structure
403 above into the record that Tera Term passed us a pointer to. That record
404 contains its size; we make sure we don't copy more than that amount of
405 data. In the future, if we add TTX functions to the TTXExports record,
406 then we could have new extensions that have a bigger TTXExports record than
407 old Tera Term binaries. In this case, the extra functions will simply not
408 be called. This means we can write extensions that will work with both old
409 and new versions of Tera Term.
410
411 (In a similar way, we can run old extensions with new versions of Tera Term.
412 The main program initialises its exports record to zeroes before it calls
413 TTXBind. This means that any data we don't copy in there is NULL, so any
414 extra functions that have been added since this extension was compiled
415 will automatically be NULL and thus get default behaviour.)
416 */
417 BOOL __declspec(dllexport) PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports) {
418 int size = sizeof(Exports) - sizeof(exports->size);
419 /* do version checking if necessary */
420 /* if (Version!=TTVERSION) return FALSE; */
421
422 if (size > exports->size) {
423 size = exports->size;
424 }
425 memcpy((char FAR *)exports + sizeof(exports->size),
426 (char FAR *)&Exports + sizeof(exports->size),
427 size);
428 return TRUE;
429 }
430
431 BOOL WINAPI DllMain(HANDLE hInstance,
432 ULONG ul_reason_for_call,
433 LPVOID lpReserved)
434 {
435 switch( ul_reason_for_call ) {
436 case DLL_THREAD_ATTACH:
437 /* do thread initialization */
438 break;
439 case DLL_THREAD_DETACH:
440 /* do thread cleanup */
441 break;
442 case DLL_PROCESS_ATTACH:
443 /* do process initialization */
444 DoCover_IsDebuggerPresent();
445 hInst = hInstance;
446 pvar = &InstVar;
447 break;
448 case DLL_PROCESS_DETACH:
449 /* do process cleanup */
450 break;
451 }
452 return TRUE;
453 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26