Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2734 - (hide annotations) (download) (as text)
Tue Nov 23 14:32:26 2004 UTC (19 years, 4 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 52361 byte(s)
接続ダイアログの起動時に、TCP/IPの「ホスト名」にフォーカスが当たるようにした。

1 yutakakn 2728 /*
2     Copyright (c) 1998-2001, Robert O'Callahan
3     All rights reserved.
4    
5     Redistribution and use in source and binary forms, with or without modification,
6     are permitted provided that the following conditions are met:
7    
8     Redistributions of source code must retain the above copyright notice, this list of
9     conditions and the following disclaimer.
10    
11     Redistributions in binary form must reproduce the above copyright notice, this list
12     of conditions and the following disclaimer in the documentation and/or other materials
13     provided with the distribution.
14    
15     The name of Robert O'Callahan may not be used to endorse or promote products derived from
16     this software without specific prior written permission.
17    
18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21     THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27     */
28    
29     /* Teraterm extension mechanism
30     Robert O'Callahan (roc+tt@cs.cmu.edu)
31    
32     Teraterm by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
33     */
34    
35     #include "ttxssh.h"
36     #include "fwdui.h"
37     #include "util.h"
38    
39     #include <stdlib.h>
40     #include <stdio.h>
41     #include <string.h>
42     #include <io.h>
43     #include <fcntl.h>
44     #include <sys/stat.h>
45     #include <time.h>
46    
47     #include "resource.h"
48     #include <commctrl.h>
49     #include <commdlg.h>
50     #ifdef INET6
51     #include <winsock2.h>
52     static char FAR *ProtocolFamilyList[] = { "UNSPEC", "IPv6", "IPv4", NULL };
53     #else
54     #include <winsock.h>
55     #endif /* INET6 */
56    
57     #define MATCH_STR(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
58    
59     /* This extension implements SSH, so we choose a load order in the
60     "protocols" range. */
61     #define ORDER 2500
62    
63     #ifdef TERATERM32
64     static HICON SecureIcon = NULL;
65     #endif
66    
67     static TInstVar FAR *pvar;
68    
69     #ifdef TERATERM32
70     /* WIN32 allows multiple instances of a DLL */
71     static TInstVar InstVar;
72     #define GET_VAR()
73     #else
74     /* WIN16 does not allow multiple instances of a DLL */
75    
76     /* maximum number of Tera Term instances */
77     #define MAXNUMINST 32
78     /* list of task handles for Tera Term instances */
79     static HANDLE FAR TaskList[MAXNUMINST];
80     /* variable sets for instances */
81     static TInstVar FAR *FAR InstVar[MAXNUMINST];
82    
83     /* Here's how the TS settings work.
84     Whenever the TS settings are read or written to the INI file, then
85     the shared memory containing those settings is updated.
86     When Teraterm starts, the shared memory is read to initialize the TS
87     settings. */
88    
89     /* TS settings shared across instances */
90     static TS_SSH ts_SSH_settings;
91    
92    
93     extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
94    
95    
96     static BOOL NewVar()
97     {
98     int i = 0;
99     HANDLE Task = GetCurrentTask();
100    
101     if (TaskList[0] == NULL)
102    
103     if (Task == NULL)
104     return FALSE;
105     while ((i < MAXNUMINST) && (TaskList[i] != NULL))
106     i++;
107     if (i >= MAXNUMINST)
108     return FALSE;
109     pvar = (TInstVar FAR *) malloc(sizeof(TInstVar));
110     InstVar[i] = pvar;
111     TaskList[i] = Task;
112     return TRUE;
113     }
114    
115     void DelVar()
116     {
117     int i = 0;
118     HANDLE Task = GetCurrentTask();
119    
120     if (Task == NULL)
121     return;
122     while ((i < MAXNUMINST) && (TaskList[i] != Task))
123     i++;
124     if (i >= MAXNUMINST)
125     return;
126     free(TaskList[i]);
127     TaskList[i] = NULL;
128     }
129    
130     BOOL GetVar()
131     {
132     int i = 0;
133     HANDLE Task = GetCurrentTask();
134    
135     if (Task == NULL)
136     return FALSE;
137     while ((i < MAXNUMINST) && (TaskList[i] != Task))
138     i++;
139     if (i >= MAXNUMINST)
140     return FALSE;
141     pvar = InstVar[i];
142     return TRUE;
143     }
144    
145     #define GET_VAR() if (!GetVar()) return
146     #endif
147    
148     /*
149     This code makes lots of assumptions about the order in which Teraterm
150     does things, and how. A key assumption is that the Notification window
151     passed into WSAAsyncSelect is the main terminal window. We also assume
152     that the socket used in the first WSAconnect is the main session socket.
153     */
154    
155     static void init_TTSSH(PTInstVar pvar)
156     {
157     pvar->socket = INVALID_SOCKET;
158     pvar->OldLargeIcon = NULL;
159     pvar->OldSmallIcon = NULL;
160     pvar->NotificationWindow = NULL;
161     pvar->hostdlg_activated = FALSE;
162     pvar->socket = INVALID_SOCKET;
163     pvar->NotificationWindow = NULL;
164     pvar->protocol_major = 0;
165     pvar->protocol_minor = 0;
166    
167     PKT_init(pvar);
168     SSH_init(pvar);
169     CRYPT_init(pvar);
170     AUTH_init(pvar);
171     HOSTS_init(pvar);
172     FWD_init(pvar);
173     FWDUI_init(pvar);
174     }
175    
176     static void uninit_TTSSH(PTInstVar pvar)
177     {
178     SSH_end(pvar);
179     PKT_end(pvar);
180     AUTH_end(pvar);
181     CRYPT_end(pvar);
182     HOSTS_end(pvar);
183     FWD_end(pvar);
184     FWDUI_end(pvar);
185    
186     if (pvar->OldLargeIcon != NULL) {
187     PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
188     (LPARAM) pvar->OldLargeIcon);
189     pvar->OldLargeIcon = NULL;
190     }
191     if (pvar->OldSmallIcon != NULL) {
192     PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
193     (LPARAM) pvar->OldSmallIcon);
194     pvar->OldSmallIcon = NULL;
195     }
196     }
197    
198     static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv)
199     {
200     #ifndef TERATERM32
201     if (!NewVar())
202     return; /* should be called first */
203     pvar->ts_SSH = &ts_SSH_settings;
204     #endif
205     pvar->settings = *pvar->ts_SSH;
206     pvar->ts = ts;
207     pvar->cv = cv;
208     pvar->fatal_error = FALSE;
209     pvar->showing_err = FALSE;
210     pvar->err_msg = NULL;
211    
212     init_TTSSH(pvar);
213     }
214    
215     static void normalize_cipher_order(char FAR * buf)
216     {
217     char ciphers_listed[SSH_CIPHER_MAX + 1];
218     char ciphers_allowed[SSH_CIPHER_MAX + 1];
219     int i, j;
220    
221     /* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
222     We *never* allow no encryption. */
223     #if 0
224     static char default_ciphers[] = {
225     SSH_CIPHER_3DES,
226     SSH_CIPHER_NONE,
227     SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
228     };
229     #else
230     // for SSH2(yutaka)
231     static char default_ciphers[] = {
232     SSH_CIPHER_AES128,
233     SSH_CIPHER_3DES_CBC,
234     SSH_CIPHER_3DES,
235     SSH_CIPHER_NONE,
236     SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
237     };
238     #endif
239    
240     memset(ciphers_listed, 0, sizeof(ciphers_listed));
241    
242     memset(ciphers_allowed, 0, sizeof(ciphers_allowed));
243     for (i = 0; i < NUM_ELEM(default_ciphers); i++) {
244     ciphers_allowed[default_ciphers[i]] = 1;
245     }
246    
247     for (i = 0; buf[i] != 0; i++) {
248     int cipher_num = buf[i] - '0';
249    
250     if (cipher_num < 0 || cipher_num > SSH_CIPHER_MAX
251     || !ciphers_allowed[cipher_num]
252     || ciphers_listed[cipher_num]) {
253     memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
254     i--;
255     } else {
256     ciphers_listed[cipher_num] = 1;
257     }
258     }
259    
260     for (j = 0; j < NUM_ELEM(default_ciphers); j++) {
261     int cipher_num = default_ciphers[j];
262    
263     if (!ciphers_listed[cipher_num]) {
264     buf[i] = cipher_num + '0';
265     i++;
266     }
267     }
268    
269     buf[i] = 0;
270     }
271    
272     /* Remove local settings from the shared memory block. */
273     static void clear_local_settings(PTInstVar pvar)
274     {
275     pvar->ts_SSH->TryDefaultAuth = FALSE;
276     }
277    
278     static BOOL read_BOOL_option(PCHAR fileName, char FAR * keyName, BOOL def)
279     {
280     char buf[1024];
281    
282     buf[0] = 0;
283     GetPrivateProfileString("TTSSH", keyName, "", buf, sizeof(buf),
284     fileName);
285     if (buf[0] == 0) {
286     return def;
287     } else {
288     return atoi(buf) != 0 ||
289     stricmp(buf, "yes") == 0 || stricmp(buf, "y") == 0;
290     }
291     }
292    
293     static void read_string_option(PCHAR fileName, char FAR * keyName,
294     char FAR * def, char FAR * buf, int bufSize)
295     {
296    
297     buf[0] = 0;
298     GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
299     }
300    
301     static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
302     {
303     extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
304     char buf[1024];
305     TS_SSH FAR *settings = pvar->ts_SSH;
306    
307     #define READ_STD_STRING_OPTION(name) \
308     read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
309    
310     settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
311    
312     buf[0] = 0;
313     GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
314     fileName);
315     settings->CompressionLevel = atoi(buf);
316     if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
317     settings->CompressionLevel = 0;
318     }
319    
320     READ_STD_STRING_OPTION(DefaultUserName);
321     READ_STD_STRING_OPTION(DefaultForwarding);
322     READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
323     READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
324     READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
325    
326     READ_STD_STRING_OPTION(CipherOrder);
327     normalize_cipher_order(settings->CipherOrder);
328     SSH2_update_cipher_myproposal(pvar); // yutaka
329    
330     read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
331     settings->KnownHostsFiles,
332     sizeof(settings->KnownHostsFiles));
333    
334     buf[0] = 0;
335     GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
336     sizeof(buf), fileName);
337     settings->DefaultAuthMethod = atoi(buf);
338     if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
339     && settings->DefaultAuthMethod != SSH_AUTH_RSA
340     && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS) {
341     /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
342     selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
343     when the dialog box has rhosts selected and an host private key file
344     is supplied. */
345     settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
346     }
347    
348     buf[0] = 0;
349     GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
350     fileName);
351     settings->LogLevel = atoi(buf);
352    
353     buf[0] = 0;
354     GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
355     sizeof(buf), fileName);
356     settings->WriteBufferSize = atoi(buf);
357     if (settings->WriteBufferSize <= 0) {
358     settings->WriteBufferSize = 2 * 1024 * 1024;
359     }
360    
361     settings->LocalForwardingIdentityCheck =
362     read_BOOL_option(fileName, "LocalForwardingIdentityCheck", TRUE);
363    
364     // SSH protocol version (2004.10.11 yutaka)
365     settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 1, fileName);
366    
367     clear_local_settings(pvar);
368     }
369    
370     static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
371     TS_SSH FAR * settings)
372     {
373     char buf[1024];
374    
375     WritePrivateProfileString("TTSSH", "Enabled",
376     settings->Enabled ? "1" : "0", fileName);
377    
378     _itoa(settings->CompressionLevel, buf, 10);
379     WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
380    
381     WritePrivateProfileString("TTSSH", "DefaultUserName",
382     settings->DefaultUserName, fileName);
383    
384     WritePrivateProfileString("TTSSH", "DefaultForwarding",
385     settings->DefaultForwarding, fileName);
386    
387     WritePrivateProfileString("TTSSH", "CipherOrder",
388     settings->CipherOrder, fileName);
389    
390     WritePrivateProfileString("TTSSH", "KnownHostsFiles",
391     settings->KnownHostsFiles, fileName);
392    
393     WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
394     settings->DefaultRhostsLocalUserName,
395     fileName);
396    
397     WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
398     settings->DefaultRhostsHostPrivateKeyFile,
399     fileName);
400    
401     WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
402     settings->DefaultRSAPrivateKeyFile,
403     fileName);
404    
405     _itoa(settings->DefaultAuthMethod, buf, 10);
406     WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
407    
408     _itoa(settings->LogLevel, buf, 10);
409     WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
410    
411     _itoa(settings->WriteBufferSize, buf, 10);
412     WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
413    
414     WritePrivateProfileString("TTSSH", "LocalForwardingIdentityCheck",
415     settings->
416     LocalForwardingIdentityCheck ? "1" : "0",
417     fileName);
418    
419     // SSH protocol version (2004.10.11 yutaka)
420     WritePrivateProfileString("TTSSH", "ProtocolVersion",
421     settings->ssh_protocol_version==2 ? "2" : "1",
422     fileName);
423    
424     }
425    
426     /* find free port in all protocol family */
427     static unsigned short find_local_port(PTInstVar pvar)
428     {
429     int tries;
430     #ifdef INET6
431     SOCKET connecter;
432     struct addrinfo hints;
433     struct addrinfo FAR *res;
434     struct addrinfo FAR *res0;
435     unsigned short port;
436     char pname[NI_MAXHOST];
437     #endif /* INET6 */
438    
439     if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
440     return 0;
441     }
442    
443     /* The random numbers here are only used to try to get fresh
444     ports across runs (dangling ports can cause bind errors
445     if we're unlucky). They do not need to be (and are not)
446     cryptographically strong.
447     */
448     srand((unsigned) GetTickCount());
449    
450     #ifdef INET6
451     for (tries = 20; tries > 0; tries--) {
452     memset(&hints, 0, sizeof(hints));
453     hints.ai_family = pvar->ts->ProtocolFamily;
454     hints.ai_flags = AI_PASSIVE;
455     hints.ai_socktype = SOCK_STREAM;
456     port = (unsigned) rand() % 512 + 512;
457     _snprintf(pname, sizeof(pname), "%d", (int) port);
458     if (getaddrinfo(NULL, pname, &hints, &res0)) {
459     return 0;
460     /* NOT REACHED */
461     }
462    
463     for (res = res0; res; res = res->ai_next) {
464     if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
465     continue;
466    
467     connecter =
468     socket(res->ai_family, res->ai_socktype, res->ai_protocol);
469     if (connecter == INVALID_SOCKET) {
470     freeaddrinfo(res0);
471     return 0;
472     }
473    
474     if (bind(connecter, res->ai_addr, res->ai_addrlen) !=
475     SOCKET_ERROR) {
476     return port;
477     freeaddrinfo(res0);
478     closesocket(connecter);
479     } else if (WSAGetLastError() != WSAEADDRINUSE) {
480     closesocket(connecter);
481     freeaddrinfo(res0);
482     return 0;
483     }
484    
485     closesocket(connecter);
486     }
487     freeaddrinfo(res0);
488     }
489    
490     return 0;
491     #else
492     for (tries = 20; tries > 0; tries--) {
493     SOCKET connecter = socket(AF_INET, SOCK_STREAM, 0);
494     struct sockaddr_in connecter_addr;
495    
496     connecter_addr.sin_family = AF_INET;
497     connecter_addr.sin_port = (unsigned) rand() % 512 + 512;
498     connecter_addr.sin_addr.s_addr = htonl(INADDR_ANY);
499    
500     if (connecter == INVALID_SOCKET) {
501     return 0;
502     }
503    
504     if (bind
505     (connecter, (struct sockaddr FAR *) &connecter_addr,
506     sizeof(connecter_addr)) != SOCKET_ERROR) {
507     closesocket(connecter);
508     return connecter_addr.sin_port;
509     } else if (WSAGetLastError() != WSAEADDRINUSE) {
510     closesocket(connecter);
511     return 0;
512     }
513    
514     closesocket(connecter);
515     }
516    
517     return 0;
518     #endif /* INET6 */
519     }
520    
521     static int PASCAL FAR TTXconnect(SOCKET s,
522     const struct sockaddr FAR * name,
523     int namelen)
524     {
525     GET_VAR();
526    
527     #ifdef INET6
528     if (pvar->socket == INVALID_SOCKET) {
529     struct sockaddr_storage ss;
530     int len;
531    
532     pvar->socket = s;
533    
534     memset(&ss, 0, sizeof(ss));
535     switch (pvar->ts->ProtocolFamily) {
536     case AF_INET:
537     len = sizeof(struct sockaddr_in);
538     ((struct sockaddr_in FAR *) &ss)->sin_family = AF_INET;
539     ((struct sockaddr_in FAR *) &ss)->sin_addr.s_addr = INADDR_ANY;
540     ((struct sockaddr_in FAR *) &ss)->sin_port =
541     htons(find_local_port(pvar));
542     break;
543     case AF_INET6:
544     len = sizeof(struct sockaddr_in6);
545     ((struct sockaddr_in6 FAR *) &ss)->sin6_family = AF_INET6;
546     #if 0 /* symbol "in6addr_any" is not included in wsock32.lib */
547     /* if wsock32.lib will be linked, we can't refer "in6addr_any" */
548     ((struct sockaddr_in6 FAR *) &ss)->sin6_addr = in6addr_any;
549     #eles
550     memset(&((struct sockaddr_in6 FAR *) &ss)->sin6_addr, 0,
551     sizeof(struct in_addr6));
552     #endif /* 0 */
553     ((struct sockaddr_in6 FAR *) &ss)->sin6_port =
554     htons(find_local_port(pvar));
555     break;
556     default:
557     /* NOT REACHED */
558     break;
559     }
560    
561     bind(s, (struct sockaddr FAR *) &ss, len);
562     }
563     #else
564     if (pvar->socket == INVALID_SOCKET) {
565     struct sockaddr_in addr;
566    
567     pvar->socket = s;
568    
569     addr.sin_family = AF_INET;
570     addr.sin_port = htons(find_local_port(pvar));
571     addr.sin_addr.s_addr = INADDR_ANY;
572     memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
573    
574     bind(s, (struct sockaddr FAR *) &addr, sizeof(addr));
575     }
576     #endif /* INET6 */
577    
578     return (pvar->Pconnect) (s, name, namelen);
579     }
580    
581     static int PASCAL FAR TTXWSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
582     long lEvent)
583     {
584     GET_VAR();
585    
586     if (s == pvar->socket) {
587     pvar->notification_events = lEvent;
588     pvar->notification_msg = wMsg;
589    
590     if (pvar->NotificationWindow == NULL) {
591     pvar->NotificationWindow = hWnd;
592     AUTH_advance_to_next_cred(pvar);
593     }
594     }
595    
596     return (pvar->PWSAAsyncSelect) (s, hWnd, wMsg, lEvent);
597     }
598    
599     static int PASCAL FAR TTXrecv(SOCKET s, char FAR * buf, int len, int flags)
600     {
601     GET_VAR();
602    
603     if (s == pvar->socket) {
604     return PKT_recv(pvar, buf, len);
605     } else {
606     return (pvar->Precv) (s, buf, len, flags);
607     }
608     }
609    
610     static int PASCAL FAR TTXsend(SOCKET s, char const FAR * buf, int len,
611     int flags)
612     {
613     GET_VAR();
614    
615     if (s == pvar->socket) {
616     SSH_send(pvar, buf, len);
617     return len;
618     } else {
619     return (pvar->Psend) (s, buf, len, flags);
620     }
621     }
622    
623     void notify_established_secure_connection(PTInstVar pvar)
624     {
625     #ifdef TERATERM32
626     if (SecureIcon == NULL) {
627     SecureIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SECURETT));
628     }
629    
630     if (SecureIcon != NULL) {
631     pvar->OldSmallIcon =
632     (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
633     ICON_SMALL, 0);
634     pvar->OldLargeIcon =
635     (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
636     ICON_BIG, 0);
637     PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
638     (LPARAM) SecureIcon);
639     PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
640     (LPARAM) SecureIcon);
641     }
642     #endif
643    
644     notify_verbose_message(pvar, "Entering secure mode",
645     LOG_LEVEL_VERBOSE);
646     }
647    
648     void notify_closed_connection(PTInstVar pvar)
649     {
650     PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
651     pvar->socket, MAKELPARAM(FD_CLOSE, 0));
652    
653     SSH_notify_disconnecting(pvar, NULL);
654     AUTH_notify_disconnecting(pvar);
655     HOSTS_notify_disconnecting(pvar);
656     }
657    
658     static void add_err_msg(PTInstVar pvar, char FAR * msg)
659     {
660     if (pvar->err_msg != NULL) {
661     char FAR *buf =
662     (char FAR *) malloc(strlen(pvar->err_msg) + 3 + strlen(msg));
663    
664     strcpy(buf, pvar->err_msg);
665     strcat(buf, "\n\n");
666     strcat(buf, msg);
667     free(pvar->err_msg);
668     pvar->err_msg = buf;
669     } else {
670     pvar->err_msg = _strdup(msg);
671     }
672     }
673    
674     void notify_nonfatal_error(PTInstVar pvar, char FAR * msg)
675     {
676     if (!pvar->showing_err) {
677     PostMessage(pvar->NotificationWindow, WM_COMMAND,
678     ID_SSHASYNCMESSAGEBOX, 0);
679     }
680     if (msg[0] != 0) {
681     notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
682     add_err_msg(pvar, msg);
683     }
684     }
685    
686     void notify_fatal_error(PTInstVar pvar, char FAR * msg)
687     {
688     if (msg[0] != 0) {
689     notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
690     add_err_msg(pvar, msg);
691     }
692    
693     if (!pvar->fatal_error) {
694     pvar->fatal_error = TRUE;
695    
696     SSH_notify_disconnecting(pvar, msg);
697     AUTH_notify_disconnecting(pvar);
698     HOSTS_notify_disconnecting(pvar);
699    
700     PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
701     pvar->socket, MAKELPARAM(FD_CLOSE,
702     (pvar->PWSAGetLastError) ()));
703     }
704     }
705    
706     void notify_verbose_message(PTInstVar pvar, char FAR * msg, int level)
707     {
708     if (level <= pvar->session_settings.LogLevel) {
709     char buf[1024];
710     int file;
711    
712     get_teraterm_dir_relative_name(buf, NUM_ELEM(buf), "TTSSH.LOG");
713     file = _open(buf, _O_RDWR | _O_APPEND | _O_CREAT | _O_TEXT,
714     _S_IREAD | _S_IWRITE);
715    
716     if (file >= 0) {
717     _write(file, msg, strlen(msg));
718     _write(file, "\n", 1);
719     _close(file);
720     }
721     }
722     }
723    
724     static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks)
725     {
726     GET_VAR();
727    
728     if (pvar->settings.Enabled) {
729     char buf[1024] = "\nInitiating SSH session at ";
730     struct tm FAR *newtime;
731     time_t long_time;
732    
733     pvar->session_settings = pvar->settings;
734    
735     time(&long_time);
736     newtime = localtime(&long_time);
737     strcat(buf, asctime(newtime));
738     buf[strlen(buf) - 1] = 0;
739     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
740    
741     FWDUI_load_settings(pvar);
742    
743     pvar->cv->TelAutoDetect = FALSE;
744     /* This next line should not be needed because Teraterm's
745     CommLib should find ts->Telnet == 0 ... but we'll do this
746     just to be on the safe side. */
747     pvar->cv->TelFlag = FALSE;
748    
749     pvar->Precv = *hooks->Precv;
750     pvar->Psend = *hooks->Psend;
751     pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
752     pvar->Pconnect = *hooks->Pconnect;
753     pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
754    
755     *hooks->Precv = TTXrecv;
756     *hooks->Psend = TTXsend;
757     *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
758     *hooks->Pconnect = TTXconnect;
759    
760     SSH_open(pvar);
761     HOSTS_open(pvar);
762     FWDUI_open(pvar);
763     }
764     }
765    
766     static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks)
767     {
768     GET_VAR();
769    
770     if (pvar->session_settings.Enabled) {
771     pvar->socket = INVALID_SOCKET;
772    
773     notify_verbose_message(pvar, "Terminating SSH session...",
774     LOG_LEVEL_VERBOSE);
775    
776     *hooks->Precv = pvar->Precv;
777     *hooks->Psend = pvar->Psend;
778     *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
779     *hooks->Pconnect = pvar->Pconnect;
780     }
781    
782     uninit_TTSSH(pvar);
783     init_TTSSH(pvar);
784     }
785    
786     static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
787     {
788     for (; from <= to; from++) {
789     EnableWindow(GetDlgItem(dlg, from), enabled);
790     }
791     }
792    
793     static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
794     LPARAM lParam)
795     {
796     static char *ssh_version[] = {"SSH1", "SSH2", NULL};
797     PGetHNRec GetHNRec;
798     char EntName[7];
799     char TempHost[HostNameMaxLength + 1];
800     WORD i, j, w;
801     BOOL Ok;
802    
803     GET_VAR();
804    
805     switch (msg) {
806     case WM_INITDIALOG:
807     GetHNRec = (PGetHNRec) lParam;
808     SetWindowLong(dlg, DWL_USER, lParam);
809    
810     if (GetHNRec->PortType == IdFile)
811     GetHNRec->PortType = IdTCPIP;
812     CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
813     IDC_HOSTTCPIP + GetHNRec->PortType - 1);
814    
815     strcpy(EntName, "Host");
816    
817     i = 1;
818     do {
819     sprintf(&EntName[4], "%d", i);
820     GetPrivateProfileString("Hosts", EntName, "",
821     TempHost, sizeof(TempHost),
822     GetHNRec->SetupFN);
823     if (strlen(TempHost) > 0)
824     SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
825     0, (LPARAM) TempHost);
826     i++;
827     } while ((i <= 99) && (strlen(TempHost) > 0));
828    
829     SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
830     HostNameMaxLength - 1, 0);
831    
832     SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
833    
834     CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
835     pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
836     Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
837     SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
838     SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
839     #ifdef INET6
840     for (i = 0; ProtocolFamilyList[i]; ++i) {
841     SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
842     0, (LPARAM) ProtocolFamilyList[i]);
843     }
844     SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
845     ProtocolFamilyMaxLength - 1, 0);
846     SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
847     #endif /* INET6 */
848    
849     /////// SSH version
850     for (i = 0; ssh_version[i]; ++i) {
851     SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
852     0, (LPARAM) ssh_version[i]);
853     }
854     SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
855     NUM_ELEM(ssh_version) - 1, 0);
856    
857 yutakakn 2734 if (pvar->settings.ssh_protocol_version == 1) {
858     SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
859     } else {
860 yutakakn 2728 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
861     }
862    
863     if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
864     enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
865     } else {
866     enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
867     }
868     /////// SSH version
869    
870    
871     j = 0;
872     w = 1;
873     strcpy(EntName, "COM");
874     for (i = 1; i <= GetHNRec->MaxComPort; i++) {
875     sprintf(&EntName[3], "%d", i);
876     SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
877     0, (LPARAM) EntName);
878     j++;
879     if (GetHNRec->ComPort == i)
880     w = j;
881     }
882     if (j > 0)
883     SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
884     else /* All com ports are already used */
885     GetHNRec->PortType = IdTCPIP;
886    
887     if (GetHNRec->PortType == IdTCPIP)
888     enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
889     #ifdef INET6
890     else {
891     enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
892     FALSE);
893     enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
894     IDC_HOSTTCPPROTOCOL, FALSE);
895     }
896     #else
897     else
898     enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
899     FALSE);
900     #endif /* INET6 */
901    
902     // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
903     {
904     HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
905 yutakakn 2734
906 yutakakn 2728 SetFocus(hwnd);
907 yutakakn 2734 //SendMessage(hwnd, BM_SETCHECK, BST_CHECKED, 0);
908     //style = GetClassLongPtr(hwnd, GCL_STYLE);
909     //SetClassLongPtr(hwnd, GCL_STYLE, style | WS_TABSTOP);
910 yutakakn 2728 }
911    
912 yutakakn 2734 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
913     // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
914     // (2004.11.23 yutaka)
915     return FALSE;
916     //return TRUE;
917 yutakakn 2728
918     case WM_COMMAND:
919     switch (LOWORD(wParam)) {
920     case IDOK:
921     GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
922     if (GetHNRec != NULL) {
923     if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
924     #ifdef INET6
925     char afstr[BUFSIZ];
926     #endif /* INET6 */
927     i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
928     if (Ok) {
929     GetHNRec->TCPPort = i;
930     } else {
931     MessageBox(dlg, "Teraterm",
932     "The TCP port must be a number.",
933     MB_OK | MB_ICONEXCLAMATION);
934     return TRUE;
935     }
936     #ifdef INET6
937     #define getaf(str) \
938     ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
939     ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
940     memset(afstr, 0, sizeof(afstr));
941     GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
942     sizeof(afstr));
943     GetHNRec->ProtocolFamily = getaf(afstr);
944     #endif /* INET6 */
945     GetHNRec->PortType = IdTCPIP;
946     GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
947     HostNameMaxLength);
948     GetHNRec->Telnet = FALSE;
949     pvar->hostdlg_activated = TRUE;
950     pvar->hostdlg_Enabled = FALSE;
951     if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
952     GetHNRec->Telnet = TRUE;
953     } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
954     pvar->hostdlg_Enabled = TRUE;
955    
956     // check SSH protocol version
957     memset(afstr, 0, sizeof(afstr));
958     GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
959     if (stricmp(afstr, "SSH1") == 0) {
960     pvar->settings.ssh_protocol_version = 1;
961     } else {
962     pvar->settings.ssh_protocol_version = 2;
963     }
964     }
965     } else {
966     GetHNRec->PortType = IdSerial;
967     GetHNRec->HostName[0] = 0;
968     memset(EntName, 0, sizeof(EntName));
969     GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
970     sizeof(EntName) - 1);
971     GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
972     if (strlen(EntName) > 4)
973     GetHNRec->ComPort =
974     GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
975     0x30;
976     }
977     }
978     EndDialog(dlg, 1);
979     return TRUE;
980    
981     case IDCANCEL:
982     EndDialog(dlg, 0);
983     return TRUE;
984    
985     case IDC_HOSTTCPIP:
986     enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
987     TRUE);
988     #ifdef INET6
989     enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
990     IDC_HOSTTCPPROTOCOL, TRUE);
991     #endif /* INET6 */
992     enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
993    
994 yutakakn 2734 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
995 yutakakn 2728 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
996     enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
997     } else {
998     enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
999     }
1000    
1001     return TRUE;
1002    
1003     case IDC_HOSTSERIAL:
1004     enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1005     enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1006     FALSE);
1007     #ifdef INET6
1008     enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1009     IDC_HOSTTCPPROTOCOL, FALSE);
1010     #endif /* INET6 */
1011     enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1012 yutakakn 2734 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1013 yutakakn 2728
1014     return TRUE;
1015    
1016     case IDC_HOSTSSH:
1017     enable_dlg_items(dlg, IDC_SSH_VERSION,
1018     IDC_SSH_VERSION, TRUE);
1019     goto hostssh_enabled;
1020    
1021     case IDC_HOSTTELNET:
1022     case IDC_HOSTOTHER:
1023     enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1024     hostssh_enabled:
1025    
1026     GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1027    
1028     if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1029     if (GetHNRec != NULL)
1030     SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1031     FALSE);
1032     } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1033     SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1034     }
1035     return TRUE;
1036    
1037     case IDC_HOSTHELP:
1038     PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1039     }
1040     }
1041     return FALSE;
1042     }
1043    
1044     static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1045     {
1046     return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1047     parent, TTXHostDlg, (LONG) rec);
1048     }
1049    
1050     static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1051     {
1052     GET_VAR();
1053    
1054     *hooks->GetHostName = TTXGetHostName;
1055     }
1056    
1057     static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1058     {
1059     GET_VAR();
1060    
1061     (pvar->ReadIniFile) (fileName, ts);
1062     read_ssh_options(pvar, fileName);
1063     pvar->settings = *pvar->ts_SSH;
1064     notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1065     FWDUI_load_settings(pvar);
1066     }
1067    
1068     static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1069     {
1070     GET_VAR();
1071    
1072     (pvar->WriteIniFile) (fileName, ts);
1073     *pvar->ts_SSH = pvar->settings;
1074     clear_local_settings(pvar);
1075     notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1076     write_ssh_options(pvar, fileName, pvar->ts_SSH);
1077     }
1078    
1079     static void read_ssh_options_from_user_file(PTInstVar pvar,
1080     char FAR * user_file_name)
1081     {
1082     if (user_file_name[0] == '.') {
1083     read_ssh_options(pvar, user_file_name);
1084     } else {
1085     char buf[1024];
1086    
1087     get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1088     read_ssh_options(pvar, buf);
1089     }
1090    
1091     pvar->settings = *pvar->ts_SSH;
1092     FWDUI_load_settings(pvar);
1093     }
1094    
1095     /* returns 1 if the option text must be deleted */
1096     static int parse_option(PTInstVar pvar, char FAR * option)
1097     {
1098     if ((option[0] == '-' || option[0] == '/')) {
1099     if (MATCH_STR(option + 1, "ssh") == 0) {
1100     if (option[4] == 0) {
1101     pvar->settings.Enabled = 1;
1102     } else if (MATCH_STR(option + 4, "-L") == 0
1103     || MATCH_STR(option + 4, "-R") == 0
1104     || stricmp(option + 4, "-X") == 0) {
1105     if (pvar->settings.DefaultForwarding[0] == 0) {
1106     strcpy(pvar->settings.DefaultForwarding, option + 5);
1107     } else {
1108     strcat(pvar->settings.DefaultForwarding, ";");
1109     strcat(pvar->settings.DefaultForwarding, option + 5);
1110     }
1111     } else if (MATCH_STR(option + 4, "-f=") == 0) {
1112     read_ssh_options_from_user_file(pvar, option + 7);
1113     } else if (MATCH_STR(option + 4, "-v") == 0) {
1114     pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1115     } else if (stricmp(option + 4, "-autologin") == 0
1116     || stricmp(option + 4, "-autologon") == 0) {
1117     pvar->settings.TryDefaultAuth = TRUE;
1118     } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1119     read_ssh_options_from_user_file(pvar, option + 13);
1120     DeleteFile(option + 13);
1121     } else {
1122     char buf[1024];
1123    
1124     _snprintf(buf, sizeof(buf),
1125     "Unrecognized command-line option: %s", option);
1126     buf[sizeof(buf) - 1] = 0;
1127    
1128     MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1129     }
1130    
1131     return 1;
1132     } else if (MATCH_STR(option + 1, "t=") == 0) {
1133     if (strcmp(option + 3, "2") == 0) {
1134     pvar->settings.Enabled = 1;
1135     return 1;
1136     } else {
1137     pvar->settings.Enabled = 0;
1138     }
1139     } else if (MATCH_STR(option + 1, "f=") == 0) {
1140     read_ssh_options_from_user_file(pvar, option + 3);
1141    
1142     // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1143     } else if (MATCH_STR(option + 1, "1") == 0) {
1144     // command line: /ssh /1 is SSH1 only
1145     pvar->settings.ssh_protocol_version = 1;
1146    
1147     } else if (MATCH_STR(option + 1, "2") == 0) {
1148     // command line: /ssh /2 is SSH2 & SSH1
1149     pvar->settings.ssh_protocol_version = 2;
1150    
1151     } else if (MATCH_STR(option + 1, "nossh") == 0) {
1152     // '/nossh' �I�v�V�����������B
1153     // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1154     // �����������������B(2004.10.11 yutaka)
1155     pvar->settings.Enabled = 0;
1156    
1157     }
1158    
1159     }
1160    
1161     return 0;
1162     }
1163    
1164     static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1165     PCHAR DDETopic)
1166     {
1167     int i;
1168     BOOL inParam = FALSE;
1169     BOOL inQuotes = FALSE;
1170     PCHAR option = NULL;
1171     GET_VAR();
1172    
1173     if (pvar->hostdlg_activated) {
1174     pvar->settings.Enabled = pvar->hostdlg_Enabled;
1175     }
1176    
1177     for (i = 0; param[i] != 0; i++) {
1178     if (inQuotes ? param[i] ==
1179     '"' : (param[i] == ' ' || param[i] == '\t')) {
1180     if (option != NULL) {
1181     char ch = param[i];
1182    
1183     param[i] = 0;
1184     if (parse_option
1185     (pvar, *option == '"' ? option + 1 : option)) {
1186     memset(option, ' ', i + 1 - (option - param));
1187     } else {
1188     param[i] = ch;
1189     }
1190     option = NULL;
1191     }
1192     inParam = FALSE;
1193     inQuotes = FALSE;
1194     } else if (!inParam) {
1195     if (param[i] == '"') {
1196     inQuotes = TRUE;
1197     inParam = TRUE;
1198     option = param + i;
1199     } else if (param[i] != ' ' && param[i] != '\t') {
1200     inParam = TRUE;
1201     option = param + i;
1202     }
1203     }
1204     }
1205    
1206     if (option != NULL) {
1207     if (parse_option(pvar, option)) {
1208     memset(option, ' ', i - (option - param));
1209     }
1210     }
1211    
1212     FWDUI_load_settings(pvar);
1213    
1214     (pvar->ParseParam) (param, ts, DDETopic);
1215    
1216     }
1217    
1218     static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1219     {
1220     GET_VAR();
1221    
1222     pvar->ReadIniFile = *hooks->ReadIniFile;
1223     pvar->WriteIniFile = *hooks->WriteIniFile;
1224     pvar->ParseParam = *hooks->ParseParam;
1225    
1226     *hooks->ReadIniFile = TTXReadINIFile;
1227     *hooks->WriteIniFile = TTXWriteINIFile;
1228     *hooks->ParseParam = TTXParseParam;
1229     }
1230    
1231     static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1232     {
1233     GET_VAR();
1234    
1235     SSH_notify_win_size(pvar, cols, rows);
1236     }
1237    
1238     static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1239     WORD newItemID, char FAR * text)
1240     {
1241     int i, j;
1242    
1243     for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1244     HMENU submenu = GetSubMenu(menu, i);
1245    
1246     for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1247     if (GetMenuItemID(submenu, j) == beforeItemID) {
1248     InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1249     text);
1250     return;
1251     }
1252     }
1253     }
1254     }
1255    
1256     static void PASCAL FAR TTXModifyMenu(HMENU menu)
1257     {
1258     GET_VAR();
1259    
1260     /* inserts before ID_HELP_ABOUT */
1261     insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1262     "About &TTSSH...");
1263    
1264     /* inserts before ID_SETUP_TCPIP */
1265     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1266     "SS&H...");
1267     /* inserts before ID_SETUP_TCPIP */
1268     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1269     "SSH &Authentication...");
1270     /* inserts before ID_SETUP_TCPIP */
1271     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1272     "SSH F&orwarding...");
1273     }
1274    
1275     static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1276     {
1277     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1278     (LPARAM) prefix);
1279     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1280     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1281     (LPARAM) (char FAR *) "\r\n");
1282     }
1283    
1284     static void init_about_dlg(PTInstVar pvar, HWND dlg)
1285     {
1286     char buf[1024];
1287    
1288     // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1289    
1290     if (pvar->socket != INVALID_SOCKET) {
1291     if (SSHv1(pvar)) {
1292     SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1293     append_about_text(dlg, "Server ID: ", buf);
1294     SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1295     append_about_text(dlg, "Using protocol: ", buf);
1296     CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1297     append_about_text(dlg, "Encryption: ", buf);
1298     CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1299     append_about_text(dlg, "Server keys: ", buf);
1300     AUTH_get_auth_info(pvar, buf, sizeof(buf));
1301     append_about_text(dlg, "Authentication: ", buf);
1302     SSH_get_compression_info(pvar, buf, sizeof(buf));
1303     append_about_text(dlg, "Compression: ", buf);
1304    
1305     } else { // SSH2
1306     SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1307     append_about_text(dlg, "Server ID: ", buf);
1308    
1309     append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1310    
1311     SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1312     append_about_text(dlg, "Using protocol: ", buf);
1313    
1314     if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1315     strcpy(buf, KEX_DH1);
1316     } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1317     strcpy(buf, KEX_DH14);
1318     } else {
1319     strcpy(buf, KEX_DHGEX);
1320     }
1321     append_about_text(dlg, "KEX: ", buf);
1322    
1323     if (pvar->hostkey_type == KEY_DSA) {
1324     strcpy(buf, "ssh-dss");
1325     } else {
1326     strcpy(buf, "ssh-rsa");
1327     }
1328     append_about_text(dlg, "Host Key: ", buf);
1329    
1330     CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1331     append_about_text(dlg, "Encryption: ", buf);
1332     CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1333     append_about_text(dlg, "Server keys: ", buf);
1334     AUTH_get_auth_info(pvar, buf, sizeof(buf));
1335     append_about_text(dlg, "Authentication: ", buf);
1336     SSH_get_compression_info(pvar, buf, sizeof(buf));
1337     append_about_text(dlg, "Compression: ", buf);
1338    
1339     }
1340     }
1341     }
1342    
1343     static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1344     LPARAM lParam)
1345     {
1346     switch (msg) {
1347     case WM_INITDIALOG:
1348     init_about_dlg((PTInstVar) lParam, dlg);
1349     return TRUE;
1350     case WM_COMMAND:
1351     switch (LOWORD(wParam)) {
1352     case IDOK:
1353     EndDialog(dlg, 1);
1354     return TRUE;
1355     case IDCANCEL: /* there isn't a cancel button, but other Windows
1356     UI things can send this message */
1357     EndDialog(dlg, 0);
1358     return TRUE;
1359     }
1360     break;
1361     }
1362    
1363     return FALSE;
1364     }
1365    
1366     static char FAR *get_cipher_name(int cipher)
1367     {
1368     switch (cipher) {
1369     case SSH_CIPHER_NONE:
1370     return "<ciphers below this line are disabled>";
1371     case SSH_CIPHER_RC4:
1372     return "RC4";
1373     case SSH_CIPHER_3DES:
1374     return "3DES";
1375     case SSH_CIPHER_DES:
1376     return "DES";
1377     case SSH_CIPHER_IDEA:
1378     return "IDEA";
1379     case SSH_CIPHER_TSS:
1380     return "TSS";
1381     case SSH_CIPHER_BLOWFISH:
1382     return "Blowfish";
1383    
1384     // for SSH2(yutaka)
1385     case SSH_CIPHER_AES128:
1386     return "AES128(SSH2)";
1387     case SSH_CIPHER_3DES_CBC:
1388     return "3DES-CBC(SSH2)";
1389    
1390     default:
1391     return NULL;
1392     }
1393     }
1394    
1395     static void set_move_button_status(HWND dlg)
1396     {
1397     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1398     int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1399     int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1400    
1401     EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1402     && curPos <= maxPos);
1403     EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1404     && curPos < maxPos);
1405     }
1406    
1407     static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1408     {
1409     HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1410     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1411     int i;
1412     int ch;
1413    
1414     SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1415     SendMessage(compressionControl, TBM_SETPOS, TRUE,
1416     pvar->settings.CompressionLevel);
1417    
1418     normalize_cipher_order(pvar->settings.CipherOrder);
1419     SSH2_update_cipher_myproposal(pvar); // yutaka
1420    
1421     for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1422     int cipher = pvar->settings.CipherOrder[i] - '0';
1423     char FAR *name = get_cipher_name(cipher);
1424    
1425     if (name != NULL) {
1426     SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1427     }
1428     }
1429    
1430     SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1431     set_move_button_status(dlg);
1432    
1433     for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1434     i++) {
1435     }
1436     if (ch != 0) {
1437     pvar->settings.KnownHostsFiles[i] = 0;
1438     SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1439     pvar->settings.KnownHostsFiles);
1440     pvar->settings.KnownHostsFiles[i] = ch;
1441     SetDlgItemText(dlg, IDC_READONLYFILENAME,
1442     pvar->settings.KnownHostsFiles + i + 1);
1443     } else {
1444     SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1445     pvar->settings.KnownHostsFiles);
1446     }
1447     }
1448    
1449     void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1450     char FAR * basename)
1451     {
1452     int filename_start = 0;
1453     int i;
1454     int ch;
1455    
1456     if (basename[0] == '\\' || basename[0] == '/'
1457     || (basename[0] != 0 && basename[1] == ':')) {
1458     strncpy(buf, basename, bufsize);
1459     buf[bufsize - 1] = 0;
1460     return;
1461     }
1462    
1463     GetModuleFileName(NULL, buf, bufsize);
1464     for (i = 0; (ch = buf[i]) != 0; i++) {
1465     if (ch == '\\' || ch == '/' || ch == ':') {
1466     filename_start = i + 1;
1467     }
1468     }
1469    
1470     if (bufsize > filename_start) {
1471     strncpy(buf + filename_start, basename, bufsize - filename_start);
1472     }
1473     buf[bufsize - 1] = 0;
1474     }
1475    
1476     int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1477     char FAR * basename)
1478     {
1479     char buf[1024];
1480     int filename_start = 0;
1481     int i;
1482     int ch, ch2;
1483    
1484     if (basename[0] != '\\' && basename[0] != '/'
1485     && (basename[0] == 0 || basename[1] != ':')) {
1486     strncpy(dest, basename, destsize);
1487     dest[destsize - 1] = 0;
1488     return strlen(dest);
1489     }
1490    
1491     GetModuleFileName(NULL, buf, sizeof(buf));
1492     for (i = 0; (ch = buf[i]) != 0; i++) {
1493     if (ch == '\\' || ch == '/' || ch == ':') {
1494     filename_start = i + 1;
1495     }
1496     }
1497    
1498     for (i = 0; i < filename_start; i++) {
1499     ch = toupper(buf[i]);
1500     ch2 = toupper(basename[i]);
1501    
1502     if (ch == ch2
1503     || ((ch == '\\' || ch == '/')
1504     && (ch2 == '\\' || ch2 == '/'))) {
1505     } else {
1506     break;
1507     }
1508     }
1509    
1510     if (i == filename_start) {
1511     strncpy(dest, basename + i, destsize);
1512     } else {
1513     strncpy(dest, basename, destsize);
1514     }
1515     dest[destsize - 1] = 0;
1516     return strlen(dest);
1517     }
1518    
1519     static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1520     {
1521     char buf[4096];
1522     char buf2[1024];
1523     HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1524     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1525     int i, j, buf2index, bufindex;
1526     int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1527    
1528     pvar->settings.CompressionLevel =
1529     (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1530    
1531     buf2index = 0;
1532     for (i = 0; i < count; i++) {
1533     int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1534    
1535     if (len > 0 && len < sizeof(buf)) { /* should always be true */
1536     buf[0] = 0;
1537     SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1538     for (j = 0;
1539     j <= SSH_CIPHER_MAX
1540     && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1541     }
1542     if (j <= SSH_CIPHER_MAX) {
1543     buf2[buf2index] = '0' + j;
1544     buf2index++;
1545     }
1546     }
1547     }
1548     buf2[buf2index] = 0;
1549     normalize_cipher_order(buf2);
1550     strcpy(pvar->settings.CipherOrder, buf2);
1551     SSH2_update_cipher_myproposal(pvar); // yutaka
1552    
1553     buf[0] = 0;
1554     GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1555     j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1556     sizeof(pvar->settings.
1557     KnownHostsFiles), buf);
1558     buf[0] = 0;
1559     bufindex = 0;
1560     GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1561     for (i = 0; buf[i] != 0; i++) {
1562     if (buf[i] == ';') {
1563     buf[i] = 0;
1564     if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1565     pvar->settings.KnownHostsFiles[j] = ';';
1566     j++;
1567     j += copy_teraterm_dir_relative_path(pvar->settings.
1568     KnownHostsFiles + j,
1569     sizeof(pvar->settings.
1570     KnownHostsFiles)
1571     - j, buf + bufindex);
1572     }
1573     bufindex = i + 1;
1574     }
1575     }
1576     if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1577     pvar->settings.KnownHostsFiles[j] = ';';
1578     j++;
1579     copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1580     sizeof(pvar->settings.
1581     KnownHostsFiles) - j,
1582     buf + bufindex);
1583     }
1584     }
1585    
1586     static void move_cur_sel_delta(HWND listbox, int delta)
1587     {
1588     int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1589     int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1590     int newPos = curPos + delta;
1591     char buf[1024];
1592    
1593     if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1594     int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1595    
1596     if (len > 0 && len < sizeof(buf)) { /* should always be true */
1597     buf[0] = 0;
1598     SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1599     SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1600     SendMessage(listbox, LB_INSERTSTRING, newPos,
1601     (LPARAM) (char FAR *) buf);
1602     SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1603     }
1604     }
1605     }
1606    
1607     static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1608     int readonly)
1609     {
1610     #ifdef TERATERM32
1611     OPENFILENAME params;
1612     char fullname_buf[2048] = "ssh_known_hosts";
1613    
1614     params.lStructSize = sizeof(OPENFILENAME);
1615     params.hwndOwner = parent;
1616     params.lpstrFilter = NULL;
1617     params.lpstrCustomFilter = NULL;
1618     params.nFilterIndex = 0;
1619     buf[0] = 0;
1620     params.lpstrFile = fullname_buf;
1621     params.nMaxFile = sizeof(fullname_buf);
1622     params.lpstrFileTitle = NULL;
1623     params.lpstrInitialDir = NULL;
1624     params.lpstrTitle =
1625     readonly ? "Choose a read-only known-hosts file to add" :
1626     "Choose a read/write known-hosts file";
1627     params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1628     | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1629     params.lpstrDefExt = NULL;
1630    
1631     if (GetOpenFileName(&params) != 0) {
1632     copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1633     return 1;
1634     } else {
1635     int err = CommDlgExtendedError();
1636    
1637     if (err != 0) {
1638     char buf[1024];
1639    
1640     _snprintf(buf, sizeof(buf),
1641     "Cannot show file dialog box: error %d", err);
1642     buf[sizeof(buf) - 1] = 0;
1643     MessageBox(parent, buf, "TTSSH Error",
1644     MB_OK | MB_ICONEXCLAMATION);
1645     }
1646    
1647     return 0;
1648     }
1649     #else
1650     return 0;
1651     #endif
1652     }
1653    
1654     static void choose_read_write_file(HWND dlg)
1655     {
1656     char buf[1024];
1657    
1658     if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
1659     SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
1660     }
1661     }
1662    
1663     static void choose_read_only_file(HWND dlg)
1664     {
1665     char buf[1024];
1666     char buf2[4096];
1667    
1668     if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
1669     buf2[0] = 0;
1670     GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
1671     if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
1672     strncat(buf2, ";", sizeof(buf2));
1673     }
1674     strncat(buf2, buf, sizeof(buf2));
1675     SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
1676     }
1677     }
1678    
1679     static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
1680     LPARAM lParam)
1681     {
1682     switch (msg) {
1683     case WM_INITDIALOG:
1684     SetWindowLong(dlg, DWL_USER, lParam);
1685     init_setup_dlg((PTInstVar) lParam, dlg);
1686     return TRUE;
1687     case WM_COMMAND:
1688     switch (LOWORD(wParam)) {
1689     case IDOK:
1690     complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
1691     dlg);
1692     EndDialog(dlg, 1);
1693     return TRUE;
1694     case IDCANCEL: /* there isn't a cancel button, but other Windows
1695     UI things can send this message */
1696     EndDialog(dlg, 0);
1697     return TRUE;
1698     case IDC_SSHMOVECIPHERUP:
1699     move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
1700     set_move_button_status(dlg);
1701     SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1702     return TRUE;
1703     case IDC_SSHMOVECIPHERDOWN:
1704     move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
1705     set_move_button_status(dlg);
1706     SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1707     return TRUE;
1708     case IDC_SSHCIPHERPREFS:
1709     set_move_button_status(dlg);
1710     return TRUE;
1711     case IDC_CHOOSEREADWRITEFILE:
1712     choose_read_write_file(dlg);
1713     return TRUE;
1714     case IDC_CHOOSEREADONLYFILE:
1715     choose_read_only_file(dlg);
1716     return TRUE;
1717     }
1718     break;
1719     }
1720    
1721     return FALSE;
1722     }
1723    
1724     static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
1725     {
1726     GET_VAR();
1727    
1728     if (pvar->fatal_error) {
1729     return 0;
1730     }
1731    
1732     switch (cmd) {
1733     case ID_ABOUTMENU:
1734     if (DialogBoxParam
1735     (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
1736     (LPARAM) pvar)
1737     == -1) {
1738     MessageBox(hWin, "Cannot create About box window.",
1739     "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1740     }
1741     return 1;
1742     case ID_SSHAUTH:
1743     AUTH_do_cred_dialog(pvar);
1744     return 1;
1745     case ID_SSHSETUPMENU:
1746     if (DialogBoxParam
1747     (hInst, MAKEINTRESOURCE(IDD_SSHSETUP), hWin, TTXSetupDlg,
1748     (LPARAM) pvar)
1749     == -1) {
1750     MessageBox(hWin, "Cannot create TTSSH Setup window.",
1751     "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1752     }
1753     return 1;
1754     case ID_SSHAUTHSETUPMENU:
1755     AUTH_do_default_cred_dialog(pvar);
1756     return 1;
1757     case ID_SSHFWDSETUPMENU:
1758     FWDUI_do_forwarding_dialog(pvar);
1759     return 1;
1760     case ID_SSHUNKNOWNHOST:
1761     HOSTS_do_unknown_host_dialog(hWin, pvar);
1762     return 1;
1763     case ID_SSHDIFFERENTHOST:
1764     HOSTS_do_different_host_dialog(hWin, pvar);
1765     return 1;
1766     case ID_SSHASYNCMESSAGEBOX:
1767     if (pvar->err_msg != NULL) {
1768     char FAR *msg = pvar->err_msg;
1769    
1770     /* Could there be a buffer overrun bug anywhere in Win32
1771     MessageBox? Who knows? I'm paranoid. */
1772     if (strlen(msg) > 2048) {
1773     msg[2048] = 0;
1774     }
1775    
1776     pvar->showing_err = TRUE;
1777     pvar->err_msg = NULL;
1778     MessageBox(NULL, msg, "TTSSH",
1779     MB_TASKMODAL | MB_ICONEXCLAMATION);
1780     free(msg);
1781     pvar->showing_err = FALSE;
1782     if (pvar->err_msg != NULL) {
1783     PostMessage(hWin, WM_COMMAND, ID_SSHASYNCMESSAGEBOX, 0);
1784     } else {
1785     AUTH_notify_end_error(pvar);
1786     }
1787     }
1788     return 1;
1789     default:
1790     return 0;
1791     }
1792     }
1793    
1794     static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen,
1795     PGetHNRec rec)
1796     {
1797     char tmpFile[MAX_PATH];
1798     char tmpPath[1024];
1799     char buf[1024];
1800     int i;
1801     GET_VAR();
1802    
1803     GetTempPath(sizeof(tmpPath), tmpPath);
1804     GetTempFileName(tmpPath, "TTX", 0, tmpFile);
1805    
1806     for (i = 0; cmd[i] != ' ' && cmd[i] != 0; i++) {
1807     }
1808    
1809     if (i < cmdlen) {
1810     strncpy(buf, cmd + i, sizeof(buf));
1811     cmd[i] = 0;
1812    
1813     write_ssh_options(pvar, tmpFile, &pvar->settings);
1814    
1815     strncat(cmd, " /ssh-consume=", cmdlen);
1816     strncat(cmd, tmpFile, cmdlen);
1817    
1818     strncat(cmd, buf, cmdlen);
1819    
1820     if (pvar->hostdlg_Enabled) {
1821     strncat(cmd, " /ssh", cmdlen);
1822    
1823     // add option of SSH protcol version (2004.10.11 yutaka)
1824     if (pvar->settings.ssh_protocol_version == 2) {
1825     strncat(cmd, " /2", cmdlen);
1826     } else {
1827     strncat(cmd, " /1", cmdlen);
1828     }
1829    
1830     }
1831     }
1832     }
1833    
1834     /* This function is called when Teraterm is quitting. You can use it to clean
1835     up.
1836    
1837     This function is called for each extension, in reverse load order (see
1838     below).
1839     */
1840     static void PASCAL FAR TTXEnd(void)
1841     {
1842     GET_VAR();
1843    
1844     uninit_TTSSH(pvar);
1845    
1846     if (pvar->err_msg != NULL) {
1847     /* Could there be a buffer overrun bug anywhere in Win32
1848     MessageBox? Who knows? I'm paranoid. */
1849     if (strlen(pvar->err_msg) > 2048) {
1850     pvar->err_msg[2048] = 0;
1851     }
1852    
1853     MessageBox(NULL, pvar->err_msg, "TTSSH",
1854     MB_TASKMODAL | MB_ICONEXCLAMATION);
1855    
1856     free(pvar->err_msg);
1857     pvar->err_msg = NULL;
1858     }
1859     #ifndef TERATERM32
1860     DelVar();
1861     #endif
1862     }
1863    
1864     /* This record contains all the information that the extension forwards to the
1865     main Teraterm code. It mostly consists of pointers to the above functions.
1866     Any of the function pointers can be replaced with NULL, in which case
1867     Teraterm will just ignore that function and assume default behaviour, which
1868     means "do nothing".
1869     */
1870     static TTXExports Exports = {
1871     /* This must contain the size of the structure. See below for its usage. */
1872     sizeof(TTXExports),
1873     ORDER,
1874    
1875     /* Now we just list the functions that we've implemented. */
1876     TTXInit,
1877     TTXGetUIHooks,
1878     TTXGetSetupHooks,
1879     TTXOpenTCP,
1880     TTXCloseTCP,
1881     TTXSetWinSize,
1882     TTXModifyMenu,
1883     NULL,
1884     TTXProcessCommand,
1885     TTXEnd,
1886     TTXSetCommandLine
1887     };
1888    
1889     #ifdef TERATERM32
1890     BOOL __declspec(dllexport)
1891     PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
1892     {
1893     #else
1894     BOOL __export PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
1895     {
1896     #endif
1897     int size = sizeof(Exports) - sizeof(exports->size);
1898     /* do version checking if necessary */
1899     /* if (Version!=TTVERSION) return FALSE; */
1900    
1901     if (size > exports->size) {
1902     size = exports->size;
1903     }
1904     memcpy((char FAR *) exports + sizeof(exports->size),
1905     (char FAR *) &Exports + sizeof(exports->size), size);
1906     return TRUE;
1907     }
1908    
1909     #ifdef TERATERM32
1910     static HANDLE __mem_mapping = NULL;
1911    
1912     BOOL WINAPI DllMain(HANDLE hInstance,
1913     ULONG ul_reason_for_call, LPVOID lpReserved)
1914     {
1915     switch (ul_reason_for_call) {
1916     case DLL_THREAD_ATTACH:
1917     /* do thread initialization */
1918     break;
1919     case DLL_THREAD_DETACH:
1920     /* do thread cleanup */
1921     break;
1922     case DLL_PROCESS_ATTACH:
1923     /* do process initialization */
1924     DisableThreadLibraryCalls(hInstance);
1925     hInst = hInstance;
1926     pvar = &InstVar;
1927     __mem_mapping =
1928     CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0,
1929     sizeof(TS_SSH), "TTSSH_1-4_TS_data");
1930     if (__mem_mapping == NULL) {
1931     /* fake it. The settings won't be shared, but what the heck. */
1932     pvar->ts_SSH = NULL;
1933     } else {
1934     pvar->ts_SSH =
1935     (TS_SSH *) MapViewOfFile(__mem_mapping, FILE_MAP_WRITE, 0,
1936     0, 0);
1937     }
1938     if (pvar->ts_SSH == NULL) {
1939     /* fake it. The settings won't be shared, but what the heck. */
1940     pvar->ts_SSH = (TS_SSH *) malloc(sizeof(TS_SSH));
1941     if (__mem_mapping != NULL) {
1942     CloseHandle(__mem_mapping);
1943     }
1944     }
1945     break;
1946     case DLL_PROCESS_DETACH:
1947     /* do process cleanup */
1948     if (__mem_mapping == NULL) {
1949     free(pvar->ts_SSH);
1950     } else {
1951     CloseHandle(__mem_mapping);
1952     UnmapViewOfFile(pvar->ts_SSH);
1953     }
1954     break;
1955     }
1956     return TRUE;
1957     }
1958     #else
1959     #ifdef WATCOM
1960     #pragma off (unreferenced);
1961     #endif
1962     int CALLBACK LibMain(HANDLE hInstance, WORD wDataSegment,
1963     WORD wHeapSize, LPSTR lpszCmdLine)
1964     #ifdef WATCOM
1965     #pragma on (unreferenced);
1966     #endif
1967     {
1968     int i;
1969     for (i = 0; i < MAXNUMINST; i++)
1970     TaskList[i] = NULL;
1971     hInst = hInstance;
1972     return (1);
1973     }
1974     #endif
1975 yutakakn 2734
1976    
1977     /*
1978     * $Log: not supported by cvs2svn $
1979     *
1980     */

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