Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ttcomtester/teraterm/teraterm/commlib.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3926 - (show annotations) (download) (as text)
Mon Jun 7 14:01:51 2010 UTC (13 years, 10 months ago) by yutakapon
Original Path: trunk/teraterm/teraterm/commlib.c
File MIME type: text/x-csrc
File size: 28731 byte(s)
以下に示す UTF-8 送信処理を、純粋なUnicodeとして処理するようにした。

 ・IME入力
 ・クリップボードの貼り付け

teraterm.iniに PureUTF8 エントリを追加。当該処理の on/off を切り替えられる。
デフォルトはまだ off とする。

これにより、SNOWMAN(U+2603)などの文字を送信しても、正しいUTF-8エンコーディングとして、
サーバへ送信される。
ただし、サロゲートペアには未対応。

1 /* Tera Term
2 Copyright(C) 1994-1998 T. Teranishi
3 All rights reserved. */
4 /* IPv6 modification is Copyright (C) 2000, 2001 Jun-ya KATO <kato@win6.jp> */
5
6 /* TERATERM.EXE, Communication routines */
7 #include "teraterm.h"
8 #include "tttypes.h"
9 #include "tt_res.h"
10 #include <process.h>
11
12 #include "ttcommon.h"
13 #include "ttwsk.h"
14 #include "ttlib.h"
15 #include "ttfileio.h"
16 #include "ttplug.h" /* TTPLUG */
17
18 #include "commlib.h"
19 #ifndef NO_INET6
20 #include <winsock2.h>
21 #include <ws2tcpip.h>
22 #include <stdio.h> /* for _snprintf() */
23 #include "WSAAsyncGetAddrInfo.h"
24 #endif /* NO_INET6 */
25 #include <time.h>
26
27 static SOCKET OpenSocket(PComVar);
28 static void AsyncConnect(PComVar);
29 static int CloseSocket(SOCKET);
30
31 /* create socket */
32 static SOCKET OpenSocket(PComVar cv)
33 {
34 cv->s = cv->res->ai_family;
35 cv->s = Psocket(cv->res->ai_family, cv->res->ai_socktype, cv->res->ai_protocol);
36 return cv->s;
37 }
38
39 /* connect with asynchronous mode */
40 static void AsyncConnect(PComVar cv)
41 {
42 int Err;
43 BOOL BBuf;
44 BBuf = TRUE;
45 /* set synchronous mode */
46 PWSAAsyncSelect(cv->s,cv->HWin,0,0);
47 Psetsockopt(cv->s,(int)SOL_SOCKET,SO_OOBINLINE,(char FAR *)&BBuf,sizeof(BBuf));
48 /* set asynchronous mode */
49 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMOPEN, FD_CONNECT);
50
51 // �z�X�g���������������������������A�����I���\�P�b�g���N���[�Y�����A
52 // �����������L�����Z���������B�l��0�������������������B
53 // (2007.1.11 yutaka)
54 if (*cv->ConnetingTimeout > 0) {
55 SetTimer(cv->HWin, IdCancelConnectTimer, *cv->ConnetingTimeout * 1000, NULL);
56 }
57
58 /* WM_USER_COMMOPEN occurs, CommOpen is called, then CommStart is called */
59 Err = Pconnect(cv->s, cv->res->ai_addr, cv->res->ai_addrlen);
60 if (Err != 0) {
61 Err = PWSAGetLastError();
62 if (Err == WSAEWOULDBLOCK) {
63 /* Do nothing */
64 } else if (Err!=0 ) {
65 PostMessage(cv->HWin, WM_USER_COMMOPEN,0,
66 MAKELONG(FD_CONNECT,Err));
67 }
68 }
69 }
70
71 /* close socket */
72 static int CloseSocket(SOCKET s)
73 {
74 return Pclosesocket(s);
75 }
76
77 #define CommInQueSize 8192
78 #define CommOutQueSize 2048
79 #define CommXonLim 2048
80 #define CommXoffLim 2048
81
82 #define READENDNAME "ReadEnd"
83 #define WRITENAME "Write"
84 #define READNAME "Read"
85 #define PRNWRITENAME "PrnWrite"
86
87 static HANDLE ReadEnd;
88 static OVERLAPPED wol, rol;
89
90 // Winsock async operation handle
91 static HANDLE HAsync=0;
92
93 BOOL TCPIPClosed = TRUE;
94
95 /* Printer port handle for
96 direct pass-thru printing */
97 static HANDLE PrnID = INVALID_HANDLE_VALUE;
98 static BOOL LPTFlag;
99
100 // Initialize ComVar.
101 // This routine is called only once
102 // by the initialization procedure of Tera Term.
103 void CommInit(PComVar cv)
104 {
105 cv->Open = FALSE;
106 cv->Ready = FALSE;
107
108 // log-buffer variables
109 cv->HLogBuf = 0;
110 cv->HBinBuf = 0;
111 cv->LogBuf = NULL;
112 cv->BinBuf = NULL;
113 cv->LogPtr = 0;
114 cv->LStart = 0;
115 cv->LCount = 0;
116 cv->BinPtr = 0;
117 cv->BStart = 0;
118 cv->BCount = 0;
119 cv->DStart = 0;
120 cv->DCount = 0;
121 cv->BinSkip = 0;
122 cv->FilePause = 0;
123 cv->ProtoFlag = FALSE;
124 /* message flag */
125 cv->NoMsg = 0;
126 }
127
128 /* reset a serial port which is already open */
129 void CommResetSerial(PTTSet ts, PComVar cv, BOOL ClearBuff)
130 {
131 DCB dcb;
132 DWORD DErr;
133 COMMTIMEOUTS ctmo;
134
135 if (! cv->Open ||
136 (cv->PortType != IdSerial)) {
137 return;
138 }
139
140 ClearCommError(cv->ComID,&DErr,NULL);
141 SetupComm(cv->ComID,CommInQueSize,CommOutQueSize);
142 /* flush input and output buffers */
143 if (ClearBuff) {
144 PurgeComm(cv->ComID, PURGE_TXABORT | PURGE_RXABORT |
145 PURGE_TXCLEAR | PURGE_RXCLEAR);
146 }
147
148 memset(&ctmo,0,sizeof(ctmo));
149 ctmo.ReadIntervalTimeout = MAXDWORD;
150 ctmo.WriteTotalTimeoutConstant = 500;
151 SetCommTimeouts(cv->ComID,&ctmo);
152 cv->InBuffCount = 0;
153 cv->InPtr = 0;
154 cv->OutBuffCount = 0;
155 cv->OutPtr = 0;
156
157 cv->DelayPerChar = ts->DelayPerChar;
158 cv->DelayPerLine = ts->DelayPerLine;
159
160 memset(&dcb,0,sizeof(DCB));
161 dcb.DCBlength = sizeof(DCB);
162 dcb.BaudRate = ts->Baud;
163 dcb.fBinary = TRUE;
164 switch (ts->Parity) {
165 case IdParityEven:
166 dcb.fParity = TRUE;
167 dcb.Parity = EVENPARITY;
168 break;
169 case IdParityOdd:
170 dcb.fParity = TRUE;
171 dcb.Parity = ODDPARITY;
172 break;
173 case IdParityNone:
174 dcb.Parity = NOPARITY;
175 break;
176 }
177
178 dcb.fDtrControl = DTR_CONTROL_ENABLE;
179 dcb.fRtsControl = RTS_CONTROL_ENABLE;
180 switch (ts->Flow) {
181 case IdFlowX:
182 dcb.fOutX = TRUE;
183 dcb.fInX = TRUE;
184 dcb.XonLim = CommXonLim;
185 dcb.XoffLim = CommXoffLim;
186 dcb.XonChar = XON;
187 dcb.XoffChar = XOFF;
188 break;
189 case IdFlowHard:
190 dcb.fOutxCtsFlow = TRUE;
191 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
192 break;
193 }
194
195 switch (ts->DataBit) {
196 case IdDataBit7:
197 dcb.ByteSize = 7;
198 break;
199 case IdDataBit8:
200 dcb.ByteSize = 8;
201 break;
202 }
203 switch (ts->StopBit) {
204 case IdStopBit1:
205 dcb.StopBits = ONESTOPBIT;
206 break;
207 case IdStopBit2:
208 dcb.StopBits = TWOSTOPBITS;
209 break;
210 }
211
212 SetCommState(cv->ComID, &dcb);
213
214 /* enable receive request */
215 SetCommMask(cv->ComID,0);
216 SetCommMask(cv->ComID,EV_RXCHAR);
217 }
218
219 void CommOpen(HWND HW, PTTSet ts, PComVar cv)
220 {
221 #ifdef NO_INET6
222 int Err;
223 #endif /* NO_INET6 */
224 char ErrMsg[21];
225 char P[50];
226
227 MSG Msg;
228 #ifndef NO_INET6
229 ADDRINFO hints;
230 char pname[NI_MAXSERV];
231 #else
232 char HEntBuff[MAXGETHOSTSTRUCT];
233 u_long addr;
234 SOCKADDR_IN saddr;
235 #endif /* NO_INET6 */
236
237 BOOL InvalidHost;
238 #ifdef NO_INET6
239 BOOL BBuf;
240 #endif /* NO_INET6 */
241
242 char uimsg[MAX_UIMSG];
243
244 /* initialize ComVar */
245 cv->InBuffCount = 0;
246 cv->InPtr = 0;
247 cv->OutBuffCount = 0;
248 cv->OutPtr = 0;
249 cv->HWin = HW;
250 cv->Ready = FALSE;
251 cv->Open = FALSE;
252 cv->PortType = ts->PortType;
253 cv->ComPort = 0;
254 cv->RetryCount = 0;
255 #ifndef NO_INET6
256 cv->RetryWithOtherProtocol = TRUE;
257 #endif /* NO_INET6 */
258 cv->s = INVALID_SOCKET;
259 cv->ComID = INVALID_HANDLE_VALUE;
260 cv->CanSend = TRUE;
261 cv->RRQ = FALSE;
262 cv->SendKanjiFlag = FALSE;
263 cv->SendCode = IdASCII;
264 cv->EchoKanjiFlag = FALSE;
265 cv->EchoCode = IdASCII;
266 cv->Language = ts->Language;
267 cv->CRSend = ts->CRSend;
268 cv->KanjiCodeEcho = ts->KanjiCode;
269 cv->JIS7KatakanaEcho = ts->JIS7Katakana;
270 cv->KanjiCodeSend = ts->KanjiCodeSend;
271 cv->JIS7KatakanaSend = ts->JIS7KatakanaSend;
272 cv->KanjiIn = ts->KanjiIn;
273 cv->KanjiOut = ts->KanjiOut;
274 cv->RussHost = ts->RussHost;
275 cv->RussClient = ts->RussClient;
276 cv->DelayFlag = TRUE;
277 cv->DelayPerChar = ts->DelayPerChar;
278 cv->DelayPerLine = ts->DelayPerLine;
279 cv->TelBinRecv = FALSE;
280 cv->TelBinSend = FALSE;
281 cv->TelFlag = FALSE;
282 cv->TelMode = FALSE;
283 cv->IACFlag = FALSE;
284 cv->TelCRFlag = FALSE;
285 cv->TelCRSend = FALSE;
286 cv->TelCRSendEcho = FALSE;
287 cv->TelAutoDetect = ts->TelAutoDetect; /* TTPLUG */
288 cv->Locale = ts->Locale;
289 cv->CodePage = &ts->CodePage;
290 cv->ConnetingTimeout = &ts->ConnectingTimeout;
291 cv->LastSendTime = time(NULL);
292 cv->LineModeBuffCount = 0;
293 cv->Flush = FALSE;
294 cv->FlushLen = 0;
295 cv->TelLineMode = FALSE;
296 cv->pureutf8 = &ts->pureutf8;
297
298 if ((ts->PortType!=IdSerial) && (strlen(ts->HostName)==0))
299 {
300 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
301 return;
302 }
303
304 switch (ts->PortType) {
305 case IdTCPIP:
306 cv->TelFlag = (ts->Telnet > 0);
307 if (ts->EnableLineMode) {
308 cv->TelLineMode = TRUE;
309 }
310 if (! LoadWinsock()) {
311 if (cv->NoMsg==0) {
312 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
313 get_lang_msg("MSG_WINSOCK_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot use winsock", ts->UILanguageFile);
314 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
315 }
316 InvalidHost = TRUE;
317 }
318 else {
319 TTXOpenTCP(); /* TTPLUG */
320 cv->Open = TRUE;
321 #ifndef NO_INET6
322 /* resolving address */
323 memset(&hints, 0, sizeof(hints));
324 hints.ai_family = ts->ProtocolFamily;
325 hints.ai_socktype = SOCK_STREAM;
326 hints.ai_protocol = IPPROTO_TCP;
327 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", ts->TCPPort);
328
329 HAsync = WSAAsyncGetAddrInfo(HW, WM_USER_GETHOST,
330 ts->HostName, pname, &hints, &cv->res0);
331 if (HAsync == 0)
332 InvalidHost = TRUE;
333 else {
334 cv->ComPort = 1; // set "getting host" flag
335 // (see CVTWindow::OnSysCommand())
336 do {
337 if (GetMessage(&Msg,0,0,0)) {
338 if ((Msg.hwnd==HW) &&
339 ((Msg.message == WM_SYSCOMMAND) &&
340 ((Msg.wParam & 0xfff0) == SC_CLOSE) ||
341 (Msg.message == WM_COMMAND) &&
342 (LOWORD(Msg.wParam) == ID_FILE_EXIT) ||
343 (Msg.message == WM_CLOSE))) { /* Exit when the user closes Tera Term */
344 PWSACancelAsyncRequest(HAsync);
345 CloseHandle(HAsync);
346 HAsync = 0;
347 cv->ComPort = 0; // clear "getting host" flag
348 PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam);
349 return;
350 }
351 if (Msg.message != WM_USER_GETHOST) { /* Prosess messages */
352 TranslateMessage(&Msg);
353 DispatchMessage(&Msg);
354 }
355 }
356 else {
357 return;
358 }
359 } while (Msg.message!=WM_USER_GETHOST);
360 cv->ComPort = 0; // clear "getting host" flag
361 CloseHandle(HAsync);
362 HAsync = 0;
363 InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0;
364 }
365 } /* if (!LoadWinsock()) */
366
367 if (InvalidHost) {
368 if (cv->NoMsg==0) {
369 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
370 get_lang_msg("MSG_INVALID_HOST_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Invalid host", ts->UILanguageFile);
371 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
372 }
373 goto BreakSC;
374 }
375 for (cv->res = cv->res0; cv->res; cv->res = cv->res->ai_next) {
376 cv->s = OpenSocket(cv);
377 if (cv->s == INVALID_SOCKET) {
378 CloseSocket(cv->s);
379 continue;
380 }
381 /* start asynchronous connect */
382 AsyncConnect(cv);
383 break; /* break for-loop immediately */
384 }
385 break;
386 #else
387 if ((ts->HostName[0] >= 0x30) && (ts->HostName[0] <= 0x39))
388 {
389 addr = Pinet_addr(ts->HostName);
390 InvalidHost = (addr == 0xffffffff);
391 }
392 else {
393 HAsync = PWSAAsyncGetHostByName(HW,WM_USER_GETHOST,
394 ts->HostName,HEntBuff,sizeof(HEntBuff));
395 if (HAsync == 0)
396 InvalidHost = TRUE;
397 else {
398 cv->ComPort = 1; // set "getting host" flag
399 // (see CVTWindow::OnSysCommand())
400 do {
401 if (GetMessage(&Msg,0,0,0))
402 {
403 if ((Msg.hwnd==HW) &&
404 ((Msg.message == WM_SYSCOMMAND) &&
405 ((Msg.wParam & 0xfff0) == SC_CLOSE) ||
406 (Msg.message == WM_COMMAND) &&
407 (LOWORD(Msg.wParam) == ID_FILE_EXIT) ||
408 (Msg.message == WM_CLOSE)))
409 { /* Exit when the user closes Tera Term */
410 PWSACancelAsyncRequest(HAsync);
411 HAsync = 0;
412 cv->ComPort = 0; // clear "getting host" flag
413 PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam);
414 return;
415 }
416 if (Msg.message != WM_USER_GETHOST)
417 { /* Prosess messages */
418 TranslateMessage(&Msg);
419 DispatchMessage(&Msg);
420 }
421 }
422 else {
423 return;
424 }
425 } while (Msg.message!=WM_USER_GETHOST);
426 cv->ComPort = 0; // clear "getting host" flag
427 HAsync = 0;
428 InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0;
429 if (! InvalidHost)
430 {
431 if (((PHOSTENT)HEntBuff)->h_addr_list != NULL)
432 memcpy(&addr,
433 ((PHOSTENT)HEntBuff)->h_addr_list[0],sizeof(addr));
434 else
435 InvalidHost = TRUE;
436 }
437 }
438
439 }
440
441 if (InvalidHost)
442 {
443 if (cv->NoMsg==0)
444 MessageBox(cv->HWin,"Invalid host",ErrorCaption,
445 MB_TASKMODAL | MB_ICONEXCLAMATION);
446 }
447 else {
448 cv->s= Psocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
449 if (cv->s==INVALID_SOCKET)
450 {
451 InvalidHost = TRUE;
452 if (cv->NoMsg==0)
453 MessageBox(cv->HWin,ErrorCantConn,ErrorCaption,
454 MB_TASKMODAL | MB_ICONEXCLAMATION);
455 }
456 else {
457 BBuf = TRUE;
458 Psetsockopt(cv->s,(int)SOL_SOCKET,SO_OOBINLINE,(char FAR *)&BBuf,sizeof(BBuf));
459
460 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMOPEN, FD_CONNECT);
461 saddr.sin_family = AF_INET;
462 saddr.sin_port = Phtons(ts->TCPPort);
463 saddr.sin_addr.s_addr = addr;
464 memset(saddr.sin_zero,0,8);
465
466 Err = Pconnect(cv->s,(LPSOCKADDR)&saddr,sizeof(saddr));
467 if (Err!=0 ) Err = PWSAGetLastError();
468 if (Err==WSAEWOULDBLOCK )
469 {
470 /* Do nothing */
471 }
472 else if (Err!=0 )
473 PostMessage(cv->HWin, WM_USER_COMMOPEN,0,
474 MAKELONG(FD_CONNECT,Err));
475 }
476 }
477 }
478 break;
479 #endif /* NO_INET6 */
480
481 case IdSerial:
482 InitFileIO(IdSerial); /* TTPLUG */
483 TTXOpenFile(); /* TTPLUG */
484 _snprintf_s(P, sizeof(P), _TRUNCATE, "COM%d", ts->ComPort);
485 strncpy_s(ErrMsg, sizeof(ErrMsg),P, _TRUNCATE);
486 strncpy_s(P, sizeof(P),"\\\\.\\", _TRUNCATE);
487 strncat_s(P, sizeof(P),ErrMsg, _TRUNCATE);
488 cv->ComID =
489 PCreateFile(P,GENERIC_READ | GENERIC_WRITE,
490 0,NULL,OPEN_EXISTING,
491 FILE_FLAG_OVERLAPPED,NULL);
492 if (cv->ComID == INVALID_HANDLE_VALUE ) {
493 get_lang_msg("MSG_CANTOEPN_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open %s", ts->UILanguageFile);
494 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, ts->UIMsg, &P[4]);
495
496 if (cv->NoMsg==0) {
497 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
498 MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
499 }
500 InvalidHost = TRUE;
501 }
502 else {
503 cv->Open = TRUE;
504 cv->ComPort = ts->ComPort;
505 CommResetSerial(ts, cv, ts->ClearComBuffOnOpen);
506 if (!ts->ClearComBuffOnOpen) {
507 cv->RRQ = TRUE;
508 }
509
510 /* notify to VT window that Comm Port is open */
511 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
512 InvalidHost = FALSE;
513
514 SetCOMFlag(ts->ComPort);
515 }
516 break; /* end of "case IdSerial:" */
517
518 case IdFile:
519 InitFileIO(IdFile); /* TTPLUG */
520 TTXOpenFile(); /* TTPLUG */
521 cv->ComID = PCreateFile(ts->HostName,GENERIC_READ,0,NULL,
522 OPEN_EXISTING,0,NULL);
523 InvalidHost = (cv->ComID == INVALID_HANDLE_VALUE);
524 if (InvalidHost) {
525 if (cv->NoMsg==0) {
526 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
527 get_lang_msg("MSG_CANTOEPN_FILE_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open file", ts->UILanguageFile);
528 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
529 }
530 }
531 else {
532 cv->Open = TRUE;
533 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
534 }
535 break;
536 } /* end of "switch" */
537
538 #ifndef NO_INET6
539 BreakSC:
540 #endif /* NO_INET6 */
541 if (InvalidHost) {
542 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
543 if ( (ts->PortType==IdTCPIP) && cv->Open ) {
544 if ( cv->s!=INVALID_SOCKET ) {
545 Pclosesocket(cv->s);
546 }
547 FreeWinsock();
548 }
549 return;
550 }
551 }
552
553 void CommThread(void *arg)
554 {
555 DWORD Evt;
556 PComVar cv = (PComVar)arg;
557 DWORD DErr;
558 HANDLE REnd;
559 char Temp[20];
560
561 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
562 REnd = OpenEvent(EVENT_ALL_ACCESS,FALSE, Temp);
563 while (TRUE) {
564 if (WaitCommEvent(cv->ComID,&Evt,NULL)) {
565 if (! cv->Ready) {
566 _endthread();
567 }
568 if (! cv->RRQ) {
569 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_READ);
570 }
571 WaitForSingleObject(REnd,INFINITE);
572 }
573 else {
574 DErr = GetLastError(); // this returns 995 (operation aborted) if a USB com port is removed
575 if (! cv->Ready || ERROR_OPERATION_ABORTED == DErr) {
576 _endthread();
577 }
578 ClearCommError(cv->ComID,&DErr,NULL);
579 }
580 }
581 }
582
583 void CommStart(PComVar cv, LONG lParam, PTTSet ts)
584 {
585 char ErrMsg[31];
586 char Temp[20];
587 char uimsg[MAX_UIMSG];
588
589 if (! cv->Open ) {
590 return;
591 }
592 if ( cv->Ready ) {
593 return;
594 }
595
596 // �L�����Z���^�C�}�����������������B�������A�������_�� WM_TIMER �����������������\���������B
597 if (*cv->ConnetingTimeout > 0) {
598 KillTimer(cv->HWin, IdCancelConnectTimer);
599 }
600
601 switch (cv->PortType) {
602 case IdTCPIP:
603 ErrMsg[0] = 0;
604 switch (HIWORD(lParam)) {
605 case WSAECONNREFUSED:
606 get_lang_msg("MSG_COMM_REFUSE_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Connection refused", ts->UILanguageFile);
607 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
608 break;
609 case WSAENETUNREACH:
610 get_lang_msg("MSG_COMM_REACH_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Network cannot be reached", ts->UILanguageFile);
611 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
612 break;
613 case WSAETIMEDOUT:
614 get_lang_msg("MSG_COMM_CONNECT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Connection timed out", ts->UILanguageFile);
615 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
616 break;
617 default:
618 get_lang_msg("MSG_COMM_TIMEOUT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot connect the host", ts->UILanguageFile);
619 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
620 }
621 if (HIWORD(lParam)>0) {
622 #ifndef NO_INET6
623 /* connect() failed */
624 if (cv->res->ai_next != NULL) {
625 /* try to connect with other protocol */
626 CloseSocket(cv->s);
627 for (cv->res = cv->res->ai_next; cv->res; cv->res = cv->res->ai_next) {
628 cv->s = OpenSocket(cv);
629 if (cv->s == INVALID_SOCKET) {
630 CloseSocket(cv->s);
631 continue;
632 }
633 AsyncConnect(cv);
634 cv->Ready = FALSE;
635 cv->RetryWithOtherProtocol = TRUE; /* retry with other procotol */
636 return;
637 }
638 } else {
639 /* trying with all protocol family are failed */
640 if (cv->NoMsg==0)
641 {
642 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
643 MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
644 }
645 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
646 cv->RetryWithOtherProtocol = FALSE;
647 return;
648 }
649 #else
650 if (cv->NoMsg==0)
651 MessageBox(cv->HWin,ErrMsg,ErrorCaption,
652 MB_TASKMODAL | MB_ICONEXCLAMATION);
653 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
654 return;
655 #endif /* NO_INET6 */
656 }
657
658 #ifndef NO_INET6
659 /* here is connection established */
660 cv->RetryWithOtherProtocol = FALSE;
661 #endif /* NO_INET6 */
662 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_READ | FD_OOB | FD_CLOSE);
663 TCPIPClosed = FALSE;
664 break;
665
666 case IdSerial:
667 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
668 ReadEnd = CreateEvent(NULL,FALSE,FALSE,Temp);
669 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", WRITENAME, cv->ComPort);
670 memset(&wol,0,sizeof(OVERLAPPED));
671 wol.hEvent = CreateEvent(NULL,TRUE,TRUE,Temp);
672 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READNAME, cv->ComPort);
673 memset(&rol,0,sizeof(OVERLAPPED));
674 rol.hEvent = CreateEvent(NULL,TRUE,FALSE,Temp);
675
676 /* create the receiver thread */
677 if (_beginthread(CommThread,0,cv) == -1) {
678 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
679 get_lang_msg("MSG_TT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Can't create thread", ts->UILanguageFile);
680 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
681 }
682 break;
683
684 case IdFile:
685 cv->RRQ = TRUE;
686 break;
687 }
688 cv->Ready = TRUE;
689 }
690
691 BOOL CommCanClose(PComVar cv)
692 { // check if data remains in buffer
693 if (! cv->Open) {
694 return TRUE;
695 }
696 if (cv->InBuffCount>0) {
697 return FALSE;
698 }
699 if ((cv->HLogBuf!=NULL) &&
700 ((cv->LCount>0) ||
701 (cv->DCount>0))) {
702 return FALSE;
703 }
704 if ((cv->HBinBuf!=NULL) &&
705 (cv->BCount>0)) {
706 return FALSE;
707 }
708 return TRUE;
709 }
710
711 void CommClose(PComVar cv)
712 {
713 if ( ! cv->Open ) {
714 return;
715 }
716 cv->Open = FALSE;
717
718 /* disable event message posting & flush buffer */
719 cv->RRQ = FALSE;
720 cv->Ready = FALSE;
721 cv->InPtr = 0;
722 cv->InBuffCount = 0;
723 cv->OutPtr = 0;
724 cv->OutBuffCount = 0;
725 cv->LineModeBuffCount = 0;
726 cv->FlushLen = 0;
727 cv->Flush = FALSE;
728
729 /* close port & release resources */
730 switch (cv->PortType) {
731 case IdTCPIP:
732 if (HAsync!=0) {
733 PWSACancelAsyncRequest(HAsync);
734 }
735 HAsync = 0;
736 #ifndef NO_INET6
737 freeaddrinfo(cv->res0);
738 #endif /* NO_INET6 */
739 if ( cv->s!=INVALID_SOCKET ) {
740 Pclosesocket(cv->s);
741 }
742 cv->s = INVALID_SOCKET;
743 TTXCloseTCP(); /* TTPLUG */
744 FreeWinsock();
745 break;
746 case IdSerial:
747 if ( cv->ComID != INVALID_HANDLE_VALUE ) {
748 CloseHandle(ReadEnd);
749 CloseHandle(wol.hEvent);
750 CloseHandle(rol.hEvent);
751 PurgeComm(cv->ComID, PURGE_TXABORT | PURGE_RXABORT |
752 PURGE_TXCLEAR | PURGE_RXCLEAR);
753 EscapeCommFunction(cv->ComID,CLRDTR);
754 SetCommMask(cv->ComID,0);
755 PCloseFile(cv->ComID);
756 ClearCOMFlag(cv->ComPort);
757 }
758 TTXCloseFile(); /* TTPLUG */
759 break;
760 case IdFile:
761 if (cv->ComID != INVALID_HANDLE_VALUE) {
762 PCloseFile(cv->ComID);
763 }
764 TTXCloseFile(); /* TTPLUG */
765 break;
766 }
767 cv->ComID = INVALID_HANDLE_VALUE;
768 cv->PortType = 0;
769 }
770
771 void CommProcRRQ(PComVar cv)
772 {
773 if ( ! cv->Ready ) {
774 return;
775 }
776 /* disable receive request */
777 switch (cv->PortType) {
778 case IdTCPIP:
779 if (! TCPIPClosed) {
780 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_OOB | FD_CLOSE);
781 }
782 break;
783 case IdSerial:
784 break;
785 }
786 cv->RRQ = TRUE;
787 CommReceive(cv);
788 }
789
790 void CommReceive(PComVar cv)
791 {
792 DWORD C;
793 DWORD DErr;
794
795 if (! cv->Ready || ! cv->RRQ ||
796 (cv->InBuffCount>=InBuffSize)) {
797 return;
798 }
799
800 /* Compact buffer */
801 if ((cv->InBuffCount>0) && (cv->InPtr>0)) {
802 memmove(cv->InBuff,&(cv->InBuff[cv->InPtr]),cv->InBuffCount);
803 cv->InPtr = 0;
804 }
805
806 if (cv->InBuffCount<InBuffSize) {
807 switch (cv->PortType) {
808 case IdTCPIP:
809 C = Precv(cv->s, &(cv->InBuff[cv->InBuffCount]),
810 InBuffSize-cv->InBuffCount, 0);
811 if (C == SOCKET_ERROR) {
812 C = 0;
813 PWSAGetLastError();
814 }
815 cv->InBuffCount = cv->InBuffCount + C;
816 break;
817 case IdSerial:
818 do {
819 ClearCommError(cv->ComID,&DErr,NULL);
820 if (! PReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
821 InBuffSize-cv->InBuffCount,&C,&rol)) {
822 if (GetLastError() == ERROR_IO_PENDING) {
823 if (WaitForSingleObject(rol.hEvent, 1000) != WAIT_OBJECT_0) {
824 C = 0;
825 }
826 else {
827 GetOverlappedResult(cv->ComID,&rol,&C,FALSE);
828 }
829 }
830 else {
831 C = 0;
832 }
833 }
834 cv->InBuffCount = cv->InBuffCount + C;
835 } while ((C!=0) && (cv->InBuffCount<InBuffSize));
836 ClearCommError(cv->ComID,&DErr,NULL);
837 break;
838 case IdFile:
839 if (PReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
840 InBuffSize-cv->InBuffCount,&C,NULL)) {
841 if (C == 0) {
842 DErr = ERROR_HANDLE_EOF;
843 }
844 else {
845 cv->InBuffCount = cv->InBuffCount + C;
846 }
847 }
848 else {
849 DErr = GetLastError();
850 }
851 break;
852 }
853 }
854
855 if (cv->InBuffCount==0) {
856 switch (cv->PortType) {
857 case IdTCPIP:
858 if (! TCPIPClosed) {
859 PWSAAsyncSelect(cv->s,cv->HWin, WM_USER_COMMNOTIFY,
860 FD_READ | FD_OOB | FD_CLOSE);
861 }
862 break;
863 case IdSerial:
864 cv->RRQ = FALSE;
865 SetEvent(ReadEnd);
866 return;
867 case IdFile:
868 if (DErr != ERROR_IO_PENDING) {
869 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
870 cv->RRQ = FALSE;
871 }
872 else {
873 cv->RRQ = TRUE;
874 }
875 return;
876 }
877 cv->RRQ = FALSE;
878 }
879 }
880
881 void CommSend(PComVar cv)
882 {
883 int delay;
884 COMSTAT Stat;
885 BYTE LineEnd;
886 int C, D, Max;
887 DWORD DErr;
888
889 if ((! cv->Open) || (! cv->Ready)) {
890 cv->OutBuffCount = 0;
891 return;
892 }
893
894 if ((cv->OutBuffCount == 0) || (! cv->CanSend)) {
895 return;
896 }
897
898 /* Max num of bytes to be written */
899 switch (cv->PortType) {
900 case IdTCPIP:
901 if (TCPIPClosed) {
902 cv->OutBuffCount = 0;
903 }
904 Max = cv->OutBuffCount;
905 break;
906 case IdSerial:
907 ClearCommError(cv->ComID,&DErr,&Stat);
908 Max = OutBuffSize - Stat.cbOutQue;
909 break;
910 case IdFile:
911 Max = cv->OutBuffCount;
912 break;
913 }
914
915 if ( Max<=0 ) {
916 return;
917 }
918 if ( Max > cv->OutBuffCount ) {
919 Max = cv->OutBuffCount;
920 }
921
922 if (cv->PortType == IdTCPIP && cv->TelFlag) {
923 cv->LastSendTime = time(NULL);
924 }
925
926 C = Max;
927 delay = 0;
928
929 if ( cv->DelayFlag && (cv->PortType==IdSerial) ) {
930 if ( cv->DelayPerLine > 0 ) {
931 if ( cv->CRSend==IdCR ) {
932 LineEnd = 0x0d;
933 }
934 else {
935 LineEnd = 0x0a;
936 }
937 C = 1;
938 if ( cv->DelayPerChar==0 ) {
939 while ((C<Max) && (cv->OutBuff[cv->OutPtr+C-1]!=LineEnd)) {
940 C++;
941 }
942 }
943 if ( cv->OutBuff[cv->OutPtr+C-1]==LineEnd ) {
944 delay = cv->DelayPerLine;
945 }
946 else {
947 delay = cv->DelayPerChar;
948 }
949 }
950 else if ( cv->DelayPerChar > 0 ) {
951 C = 1;
952 delay = cv->DelayPerChar;
953 }
954 }
955
956 /* Write to comm driver/Winsock */
957 switch (cv->PortType) {
958 case IdTCPIP:
959 D = Psend(cv->s, &(cv->OutBuff[cv->OutPtr]), C, 0);
960 if ( D==SOCKET_ERROR ) { /* if error occurs */
961 PWSAGetLastError(); /* Clear error */
962 D = 0;
963 }
964 break;
965
966 case IdSerial:
967 if (! PWriteFile(cv->ComID,&(cv->OutBuff[cv->OutPtr]),C,(LPDWORD)&D,&wol)) {
968 if (GetLastError() == ERROR_IO_PENDING) {
969 if (WaitForSingleObject(wol.hEvent,1000) != WAIT_OBJECT_0) {
970 D = C; /* Time out, ignore data */
971 }
972 else {
973 GetOverlappedResult(cv->ComID,&wol,(LPDWORD)&D,FALSE);
974 }
975 }
976 else { /* I/O error */
977 D = C; /* ignore error */
978 }
979 }
980 ClearCommError(cv->ComID,&DErr,&Stat);
981 break;
982
983 case IdFile:
984 if (! PWriteFile(cv->ComID, &(cv->OutBuff[cv->OutPtr]), C, (LPDWORD)&D, NULL)) {
985 if (! GetLastError() == ERROR_IO_PENDING) {
986 D = C; /* ignore data */
987 }
988 }
989 break;
990 }
991
992 cv->OutBuffCount = cv->OutBuffCount - D;
993 if ( cv->OutBuffCount==0 ) {
994 cv->OutPtr = 0;
995 }
996 else {
997 cv->OutPtr = cv->OutPtr + D;
998 }
999
1000 if ( (C==D) && (delay>0) ) {
1001 cv->CanSend = FALSE;
1002 SetTimer(cv->HWin, IdDelayTimer, delay, NULL);
1003 }
1004 }
1005
1006 void CommSendBreak(PComVar cv)
1007 /* for only serial ports */
1008 {
1009 MSG DummyMsg;
1010
1011 if ( ! cv->Ready ) {
1012 return;
1013 }
1014
1015 switch (cv->PortType) {
1016 case IdSerial:
1017 /* Set com port into a break state */
1018 SetCommBreak(cv->ComID);
1019
1020 /* pause for 1 sec */
1021 if (SetTimer(cv->HWin, IdBreakTimer, 1000, NULL) != 0) {
1022 GetMessage(&DummyMsg,cv->HWin,WM_TIMER,WM_TIMER);
1023 }
1024
1025 /* Set com port into the nonbreak state */
1026 ClearCommBreak(cv->ComID);
1027 break;
1028 }
1029 }
1030
1031 void CommLock(PTTSet ts, PComVar cv, BOOL Lock)
1032 {
1033 BYTE b;
1034 DWORD Func;
1035
1036 if (! cv->Ready) {
1037 return;
1038 }
1039 if ((cv->PortType==IdTCPIP) ||
1040 (cv->PortType==IdSerial) &&
1041 (ts->Flow!=IdFlowHard)) {
1042 if (Lock) {
1043 b = XOFF;
1044 }
1045 else {
1046 b = XON;
1047 }
1048 CommBinaryOut(cv,&b,1);
1049 }
1050 else if ((cv->PortType==IdSerial) &&
1051 (ts->Flow==IdFlowHard)) {
1052 if (Lock) {
1053 Func = CLRRTS;
1054 }
1055 else {
1056 Func = SETRTS;
1057 }
1058 EscapeCommFunction(cv->ComID,Func);
1059 }
1060 }
1061
1062 BOOL PrnOpen(PCHAR DevName)
1063 {
1064 char Temp[MAXPATHLEN];
1065 DCB dcb;
1066 DWORD DErr;
1067 COMMTIMEOUTS ctmo;
1068
1069 strncpy_s(Temp, sizeof(Temp),DevName, _TRUNCATE);
1070 Temp[4] = 0; // COMn or LPTn
1071 LPTFlag = (Temp[0]=='L') ||
1072 (Temp[0]=='l');
1073 PrnID = CreateFile(Temp,GENERIC_WRITE,
1074 0,NULL,OPEN_EXISTING,
1075 0,NULL);
1076 if (PrnID == INVALID_HANDLE_VALUE) {
1077 return FALSE;
1078 }
1079
1080 if (GetCommState(PrnID,&dcb)) {
1081 BuildCommDCB(DevName,&dcb);
1082 SetCommState(PrnID,&dcb);
1083 }
1084 ClearCommError(PrnID,&DErr,NULL);
1085 if (! LPTFlag) {
1086 SetupComm(PrnID,0,CommOutQueSize);
1087 }
1088 /* flush output buffer */
1089 PurgeComm(PrnID, PURGE_TXABORT | PURGE_TXCLEAR);
1090 memset(&ctmo,0,sizeof(ctmo));
1091 ctmo.WriteTotalTimeoutConstant = 1000;
1092 SetCommTimeouts(PrnID,&ctmo);
1093 if (! LPTFlag) {
1094 EscapeCommFunction(PrnID,SETDTR);
1095 }
1096 return TRUE;
1097 }
1098
1099 int PrnWrite(PCHAR b, int c)
1100 {
1101 int d;
1102 DWORD DErr;
1103 COMSTAT Stat;
1104
1105 if (PrnID == INVALID_HANDLE_VALUE ) {
1106 return c;
1107 }
1108
1109 ClearCommError(PrnID,&DErr,&Stat);
1110 if (! LPTFlag &&
1111 (OutBuffSize - (int)Stat.cbOutQue < c)) {
1112 c = OutBuffSize - Stat.cbOutQue;
1113 }
1114 if (c<=0) {
1115 return 0;
1116 }
1117 if (! WriteFile(PrnID,b,c,(LPDWORD)&d,NULL)) {
1118 d = 0;
1119 }
1120 ClearCommError(PrnID,&DErr,NULL);
1121 return d;
1122 }
1123
1124 void PrnCancel()
1125 {
1126 PurgeComm(PrnID, PURGE_TXABORT | PURGE_TXCLEAR);
1127 PrnClose();
1128 }
1129
1130 void PrnClose()
1131 {
1132 if (PrnID != INVALID_HANDLE_VALUE) {
1133 if (!LPTFlag) {
1134 EscapeCommFunction(PrnID,CLRDTR);
1135 }
1136 CloseHandle(PrnID);
1137 }
1138 PrnID = INVALID_HANDLE_VALUE;
1139 }

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