Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2581 - (hide annotations) (download) (as text)
Mon Sep 8 04:03:08 2008 UTC (15 years, 6 months ago) by doda
Original Path: teraterm/trunk/teraterm/commlib.c
File MIME type: text/x-csrc
File size: 28605 byte(s)
・ログ再生時、ReadFileの結果がERROR_IO_PENDINGの時はログが終了したと見なさないように変更
  (通常はERROR_IO_PENDINGになる事はないはずだが、TTXでReadFileをフックした時に便利なため)
・ログ再生時、CommSend()でダミーのWriteFileを呼ぶように変更
  (TTXでフック出来るようにするため)

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

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