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 9048 - (show annotations) (download) (as text)
Wed Dec 16 12:24:13 2020 UTC (3 years, 2 months ago) by nmaya
Original Path: trunk/teraterm/teraterm/commlib.c
File MIME type: text/x-csrc
File size: 36030 byte(s)
ソースファイルの著作権表記の "最後の発行の年" を削除

ticket #40996
1 /*
2 * Copyright (C) 1994-1998 T. Teranishi
3 * (C) 2005- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /* IPv6 modification is Copyright (C) 2000, 2001 Jun-ya KATO <kato@win6.jp> */
30
31 /* TERATERM.EXE, Communication routines */
32 #include "teraterm.h"
33 #include "tttypes.h"
34 #include "tt_res.h"
35 #include <process.h>
36
37 #include "ttcommon.h"
38 #include "ttwsk.h"
39 #include "ttlib.h"
40 #include "ttfileio.h"
41 #include "ttplug.h" /* TTPLUG */
42 #include "ttdde.h"
43
44 #include "commlib.h"
45 #include <winsock2.h>
46 #include <ws2tcpip.h>
47 #include <stdio.h> /* for _snprintf() */
48 #include <time.h>
49 #include <locale.h>
50
51 #include "filesys_log.h"
52 #include "ttlib.h"
53 #include "codeconv.h"
54
55 static SOCKET OpenSocket(PComVar);
56 static void AsyncConnect(PComVar);
57 static int CloseSocket(SOCKET);
58
59 /* create socket */
60 static SOCKET OpenSocket(PComVar cv)
61 {
62 cv->s = cv->res->ai_family;
63 cv->s = Psocket(cv->res->ai_family, cv->res->ai_socktype, cv->res->ai_protocol);
64 return cv->s;
65 }
66
67 /* connect with asynchronous mode */
68 static void AsyncConnect(PComVar cv)
69 {
70 int Err;
71 BOOL BBuf;
72 BBuf = TRUE;
73 /* set synchronous mode */
74 PWSAAsyncSelect(cv->s,cv->HWin,0,0);
75 Psetsockopt(cv->s,(int)SOL_SOCKET,SO_OOBINLINE,(char *)&BBuf,sizeof(BBuf));
76 /* set asynchronous mode */
77 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMOPEN, FD_CONNECT);
78
79 // �z�X�g���������������������������A�����I���\�P�b�g���N���[�Y�����A
80 // �����������L�����Z���������B�l��0�������������������B
81 // (2007.1.11 yutaka)
82 if (*cv->ConnetingTimeout > 0) {
83 SetTimer(cv->HWin, IdCancelConnectTimer, *cv->ConnetingTimeout * 1000, NULL);
84 }
85
86 /* WM_USER_COMMOPEN occurs, CommOpen is called, then CommStart is called */
87 Err = Pconnect(cv->s, cv->res->ai_addr, cv->res->ai_addrlen);
88 if (Err != 0) {
89 Err = PWSAGetLastError();
90 if (Err == WSAEWOULDBLOCK) {
91 /* Do nothing */
92 } else if (Err!=0 ) {
93 PostMessage(cv->HWin, WM_USER_COMMOPEN,0,
94 MAKELONG(FD_CONNECT,Err));
95 }
96 }
97 }
98
99 /* close socket */
100 static int CloseSocket(SOCKET s)
101 {
102 return Pclosesocket(s);
103 }
104
105 #define CommInQueSize 8192
106 #define CommOutQueSize 2048
107 #define CommXonLim 2048
108 #define CommXoffLim 2048
109
110 #define READENDNAME "ReadEnd"
111 #define WRITENAME "Write"
112 #define READNAME "Read"
113 #define PRNWRITENAME "PrnWrite"
114
115 static HANDLE ReadEnd;
116 static OVERLAPPED wol, rol;
117
118 // Winsock async operation handle
119 static HANDLE HAsync=0;
120
121 BOOL TCPIPClosed = TRUE;
122
123 /* Printer port handle for
124 direct pass-thru printing */
125 static HANDLE PrnID = INVALID_HANDLE_VALUE;
126 static BOOL LPTFlag;
127
128 // Initialize ComVar.
129 // This routine is called only once
130 // by the initialization procedure of Tera Term.
131 void CommInit(PComVar cv)
132 {
133 cv->Open = FALSE;
134 cv->Ready = FALSE;
135
136 // log-buffer variables
137 cv->FilePause = 0;
138 cv->ProtoFlag = FALSE;
139 /* message flag */
140 cv->NoMsg = 0;
141
142 cv->isSSH = 0;
143 cv->TitleRemote[0] = '\0';
144
145 cv->NotifyIcon = NULL;
146
147 cv->ConnectedTime = 0;
148 }
149
150 /* reset a serial port which is already open */
151 void CommResetSerial(PTTSet ts, PComVar cv, BOOL ClearBuff)
152 {
153 DCB dcb;
154 DWORD DErr;
155 COMMTIMEOUTS ctmo;
156
157 if (! cv->Open ||
158 (cv->PortType != IdSerial)) {
159 return;
160 }
161
162 ClearCommError(cv->ComID,&DErr,NULL);
163 SetupComm(cv->ComID,CommInQueSize,CommOutQueSize);
164 /* flush input and output buffers */
165 if (ClearBuff) {
166 PurgeComm(cv->ComID, PURGE_TXABORT | PURGE_RXABORT |
167 PURGE_TXCLEAR | PURGE_RXCLEAR);
168 }
169
170 memset(&ctmo,0,sizeof(ctmo));
171 ctmo.ReadIntervalTimeout = MAXDWORD;
172 ctmo.WriteTotalTimeoutConstant = 500;
173 SetCommTimeouts(cv->ComID,&ctmo);
174 cv->InBuffCount = 0;
175 cv->InPtr = 0;
176 cv->OutBuffCount = 0;
177 cv->OutPtr = 0;
178
179 cv->DelayPerChar = ts->DelayPerChar;
180 cv->DelayPerLine = ts->DelayPerLine;
181
182 memset(&dcb,0,sizeof(DCB));
183 dcb.DCBlength = sizeof(DCB);
184 dcb.BaudRate = ts->Baud;
185 dcb.fBinary = TRUE;
186 switch (ts->Parity) {
187 case IdParityNone:
188 dcb.Parity = NOPARITY;
189 break;
190 case IdParityOdd:
191 dcb.fParity = TRUE;
192 dcb.Parity = ODDPARITY;
193 break;
194 case IdParityEven:
195 dcb.fParity = TRUE;
196 dcb.Parity = EVENPARITY;
197 break;
198 case IdParityMark:
199 dcb.fParity = TRUE;
200 dcb.Parity = MARKPARITY;
201 break;
202 case IdParitySpace:
203 dcb.fParity = TRUE;
204 dcb.Parity = SPACEPARITY;
205 break;
206 }
207
208 dcb.fDtrControl = DTR_CONTROL_ENABLE;
209 dcb.fRtsControl = RTS_CONTROL_ENABLE;
210 switch (ts->Flow) {
211 case IdFlowX:
212 dcb.fOutX = TRUE;
213 dcb.fInX = TRUE;
214 dcb.XonLim = CommXonLim;
215 dcb.XoffLim = CommXoffLim;
216 dcb.XonChar = XON;
217 dcb.XoffChar = XOFF;
218 break;
219 case IdFlowHard: // RTS/CTS
220 dcb.fOutxCtsFlow = TRUE;
221 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
222 break;
223 case IdFlowHardDsrDtr: // DSR/DTR
224 dcb.fOutxDsrFlow = TRUE;
225 dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
226 break;
227 }
228
229 switch (ts->DataBit) {
230 case IdDataBit7:
231 dcb.ByteSize = 7;
232 break;
233 case IdDataBit8:
234 dcb.ByteSize = 8;
235 break;
236 }
237 switch (ts->StopBit) {
238 case IdStopBit1:
239 dcb.StopBits = ONESTOPBIT;
240 break;
241 case IdStopBit15:
242 dcb.StopBits = ONE5STOPBITS;
243 break;
244 case IdStopBit2:
245 dcb.StopBits = TWOSTOPBITS;
246 break;
247 }
248
249 SetCommState(cv->ComID, &dcb);
250
251 /* enable receive request */
252 SetCommMask(cv->ComID,0);
253 SetCommMask(cv->ComID,EV_RXCHAR);
254 }
255
256 // ���O�t���p�C�v�����������������`�F�b�N�����B
257 // \\ServerName\pipe\PipeName
258 //
259 // return 0: ������
260 // -1: �s��
261 // (2012.3.10 yutaka)
262 int CheckNamedPipeFormat(char *p, int size)
263 {
264 int ret = -1;
265 char *s;
266
267 if (size <= 8)
268 goto error;
269
270 if (p[0] == '\\' && p[1] == '\\') {
271 s = strchr(&p[2], '\\');
272 if (s && _strnicmp(s+1, "pipe\\", 5) == 0) {
273 ret = 0;
274 }
275 }
276
277 error:
278 return (ret);
279 }
280
281 void CommOpen(HWND HW, PTTSet ts, PComVar cv)
282 {
283 char ErrMsg[21 + 256];
284 wchar_t ErrMsgW[21 + 256];
285 char P[50+256];
286
287 MSG Msg;
288 ADDRINFO hints;
289 char pname[NI_MAXSERV];
290
291 BOOL InvalidHost;
292
293 // �z�X�g�������O�t���p�C�v�����������������B
294 if (ts->PortType == IdTCPIP) {
295 if (CheckNamedPipeFormat(ts->HostName, strlen(ts->HostName)) == 0) {
296 ts->PortType = IdNamedPipe;
297 }
298 }
299
300 /* initialize ComVar */
301 cv->InBuffCount = 0;
302 cv->InPtr = 0;
303 cv->OutBuffCount = 0;
304 cv->OutPtr = 0;
305 cv->HWin = HW;
306 cv->Ready = FALSE;
307 cv->Open = FALSE;
308 cv->PortType = ts->PortType;
309 cv->ComPort = 0;
310 cv->RetryCount = 0;
311 cv->RetryWithOtherProtocol = TRUE;
312 cv->s = INVALID_SOCKET;
313 cv->ComID = INVALID_HANDLE_VALUE;
314 cv->CanSend = TRUE;
315 cv->RRQ = FALSE;
316 cv->SendKanjiFlag = FALSE;
317 cv->SendCode = IdASCII;
318 cv->EchoKanjiFlag = FALSE;
319 cv->EchoCode = IdASCII;
320 cv->Language = ts->Language;
321 cv->CRSend = ts->CRSend;
322 cv->KanjiCodeEcho = ts->KanjiCode;
323 cv->JIS7KatakanaEcho = ts->JIS7Katakana;
324 cv->KanjiCodeSend = ts->KanjiCodeSend;
325 cv->JIS7KatakanaSend = ts->JIS7KatakanaSend;
326 cv->KanjiIn = ts->KanjiIn;
327 cv->KanjiOut = ts->KanjiOut;
328 cv->RussHost = ts->RussHost;
329 cv->RussClient = ts->RussClient;
330 cv->DelayFlag = TRUE;
331 cv->DelayPerChar = ts->DelayPerChar;
332 cv->DelayPerLine = ts->DelayPerLine;
333 cv->TelBinRecv = FALSE;
334 cv->TelBinSend = FALSE;
335 cv->TelFlag = FALSE;
336 cv->TelMode = FALSE;
337 cv->IACFlag = FALSE;
338 cv->TelCRFlag = FALSE;
339 cv->TelCRSend = FALSE;
340 cv->TelCRSendEcho = FALSE;
341 cv->TelAutoDetect = ts->TelAutoDetect; /* TTPLUG */
342 cv->Locale = ts->Locale;
343 cv->locale = _create_locale(LC_ALL, cv->Locale);
344 cv->CodePage = &ts->CodePage;
345 cv->ConnetingTimeout = &ts->ConnectingTimeout;
346 cv->LastSendTime = time(NULL);
347 cv->LineModeBuffCount = 0;
348 cv->Flush = FALSE;
349 cv->FlushLen = 0;
350 cv->TelLineMode = FALSE;
351 cv->ConnectedTime = 0;
352
353 if ((ts->PortType!=IdSerial) && (strlen(ts->HostName)==0))
354 {
355 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
356 return;
357 }
358
359 switch (ts->PortType) {
360 case IdTCPIP:
361 cv->TelFlag = (ts->Telnet > 0);
362 if (ts->EnableLineMode) {
363 cv->TelLineMode = TRUE;
364 }
365 if (! LoadWinsock()) {
366 if (cv->NoMsg==0) {
367 static const TTMessageBoxInfoW info = {
368 "Tera Term",
369 "MSG_TT_ERROR", L"Tera Term: Error",
370 "MSG_WINSOCK_ERROR", L"Cannot use winsock",
371 };
372 TTMessageBoxW(
373 cv->HWin,
374 &info, (MB_TASKMODAL | MB_ICONEXCLAMATION),
375 ts->UILanguageFile);
376 }
377 InvalidHost = TRUE;
378 }
379 else {
380 TTXOpenTCP(); /* TTPLUG */
381 cv->Open = TRUE;
382 /* resolving address */
383 memset(&hints, 0, sizeof(hints));
384 hints.ai_family = ts->ProtocolFamily;
385 hints.ai_socktype = SOCK_STREAM;
386 hints.ai_protocol = IPPROTO_TCP;
387 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", ts->TCPPort);
388
389 HAsync = PWSAAsyncGetAddrInfo(HW, WM_USER_GETHOST,
390 ts->HostName, pname, &hints, &cv->res0);
391 if (HAsync == 0)
392 InvalidHost = TRUE;
393 else {
394 cv->ComPort = 1; // set "getting host" flag
395 // (see CVTWindow::OnSysCommand())
396 do {
397 if (GetMessage(&Msg,0,0,0)) {
398 if ((Msg.hwnd==HW) &&
399 ((Msg.message == WM_SYSCOMMAND) &&
400 ((Msg.wParam & 0xfff0) == SC_CLOSE) ||
401 (Msg.message == WM_COMMAND) &&
402 (LOWORD(Msg.wParam) == ID_FILE_EXIT) ||
403 (Msg.message == WM_CLOSE))) { /* Exit when the user closes Tera Term */
404 PWSACancelAsyncRequest(HAsync);
405 CloseHandle(HAsync);
406 HAsync = 0;
407 cv->ComPort = 0; // clear "getting host" flag
408 PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam);
409 return;
410 }
411 if (Msg.message != WM_USER_GETHOST) { /* Prosess messages */
412 TranslateMessage(&Msg);
413 DispatchMessage(&Msg);
414 }
415 }
416 else {
417 return;
418 }
419 } while (Msg.message!=WM_USER_GETHOST);
420 cv->ComPort = 0; // clear "getting host" flag
421 CloseHandle(HAsync);
422 HAsync = 0;
423 InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0;
424 }
425 } /* if (!LoadWinsock()) */
426
427 if (InvalidHost) {
428 if (cv->NoMsg==0) {
429 static const TTMessageBoxInfoW info = {
430 "Tera Term",
431 "MSG_TT_ERROR", L"Tera Term: Error",
432 "MSG_INVALID_HOST_ERROR", L"Invalid host"
433 };
434 TTMessageBoxW(
435 cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile);
436 }
437 goto BreakSC;
438 }
439 for (cv->res = cv->res0; cv->res; cv->res = cv->res->ai_next) {
440 cv->s = OpenSocket(cv);
441 if (cv->s == INVALID_SOCKET) {
442 CloseSocket(cv->s);
443 continue;
444 }
445 /* start asynchronous connect */
446 AsyncConnect(cv);
447 break; /* break for-loop immediately */
448 }
449 break;
450
451 case IdSerial:
452 InitFileIO(IdSerial); /* TTPLUG */
453 TTXOpenFile(); /* TTPLUG */
454 _snprintf_s(P, sizeof(P), _TRUNCATE, "COM%d", ts->ComPort);
455 strncpy_s(ErrMsg, sizeof(ErrMsg),P, _TRUNCATE);
456 strncpy_s(P, sizeof(P),"\\\\.\\", _TRUNCATE);
457 strncat_s(P, sizeof(P),ErrMsg, _TRUNCATE);
458 cv->ComID = PCreateFile(P, GENERIC_READ | GENERIC_WRITE, 0, NULL,
459 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
460 if (cv->ComID == INVALID_HANDLE_VALUE ) {
461 if (cv->NoMsg==0) {
462 DWORD err = GetLastError();
463 wchar_t *format;
464 wchar_t *PW = ToWcharA(&P[4]);
465 static const TTMessageBoxInfoW info = {
466 "Tera Term",
467 "MSG_TT_ERROR", L"Tera Term: Error",
468 NULL, NULL
469 };
470
471 switch (err) {
472 case ERROR_FILE_NOT_FOUND:
473 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_NOTFOUND", L"Cannot open %s. Not found.", ts->UILanguageFile);
474 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
475 break;
476 case ERROR_ACCESS_DENIED:
477 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_DENIED", L"Cannot open %s. Access denied.", ts->UILanguageFile);
478 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
479 break;
480 default:
481 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR", L"Cannot open %s. (0x%08x)", ts->UILanguageFile);
482 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW, err);
483 break;
484 }
485 free(format);
486 free(PW);
487
488 TTMessageBoxW(
489 cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile, ErrMsgW);
490 }
491 InvalidHost = TRUE;
492 }
493 else {
494 cv->Open = TRUE;
495 cv->ComPort = ts->ComPort;
496 CommResetSerial(ts, cv, ts->ClearComBuffOnOpen);
497 if (!ts->ClearComBuffOnOpen) {
498 cv->RRQ = TRUE;
499 }
500
501 /* notify to VT window that Comm Port is open */
502 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
503 InvalidHost = FALSE;
504
505 SetCOMFlag(ts->ComPort);
506 }
507 break; /* end of "case IdSerial:" */
508
509 case IdFile:
510 InitFileIO(IdFile); /* TTPLUG */
511 TTXOpenFile(); /* TTPLUG */
512 cv->ComID = PCreateFile(ts->HostName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
513 InvalidHost = (cv->ComID == INVALID_HANDLE_VALUE);
514 if (InvalidHost) {
515 if (cv->NoMsg==0) {
516 static const TTMessageBoxInfoW info = {
517 "Tera Term",
518 "MSG_TT_ERROR", L"Tera Term: Error",
519 "MSG_CANTOPEN_FILE_ERROR", L"Cannot open file"
520 };
521 TTMessageBoxW(
522 cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile);
523 }
524 }
525 else {
526 cv->Open = TRUE;
527 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
528 }
529 break;
530
531 case IdNamedPipe:
532 InitFileIO(IdNamedPipe); /* TTPLUG */
533 TTXOpenFile(); /* TTPLUG */
534
535 memset(P, 0, sizeof(P));
536 strncpy_s(P, sizeof(P), ts->HostName, _TRUNCATE);
537
538 // ���O�t���p�C�v�����������������`�F�b�N�����B
539 if (CheckNamedPipeFormat(P, strlen(P)) < 0) {
540 static const TTMessageBoxInfoW info = {
541 "Tera Term",
542 "MSG_TT_ERROR", L"Tera Term: Error",
543 NULL, NULL
544 };
545 InvalidHost = TRUE;
546
547 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE,
548 L"Invalid pipe name (%d)\n\n"
549 L"A valid pipe name has the form\n"
550 L"\"\\\\<ServerName>\\pipe\\<PipeName>\"",
551 GetLastError());
552 TTMessageBoxW(cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile, ErrMsgW);
553 break;
554 }
555
556 cv->ComID = PCreateFile(P, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
557 0, // �u���b�L���O���[�h������(FILE_FLAG_OVERLAPPED ���w��������)
558 NULL);
559 if (cv->ComID == INVALID_HANDLE_VALUE ) {
560 if (cv->NoMsg==0) {
561 DWORD err = GetLastError();
562 wchar_t *format;
563 wchar_t* PW = ToWcharA(&P[4]);
564 static const TTMessageBoxInfoW info = {
565 "Tera Term",
566 "MSG_TT_ERROR", L"Tera Term: Error",
567 NULL, NULL
568 };
569
570 switch (err) {
571 case ERROR_FILE_NOT_FOUND:
572 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_NOTFOUND", L"Cannot open %s. Not found.", ts->UILanguageFile);
573 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
574 break;
575 case ERROR_ACCESS_DENIED:
576 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_DENIED", L"Cannot open %s. Access denied.", ts->UILanguageFile);
577 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
578 break;
579 case ERROR_PIPE_BUSY:
580 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_PIPEBUSY", L"Cannot open %s. Pipe is busy.", ts->UILanguageFile);
581 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
582 break;
583 default:
584 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR", L"Cannot open %s. (0x%08x)", ts->UILanguageFile);
585 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW, err);
586 break;
587 }
588 free(format);
589 free(PW);
590
591 TTMessageBoxW(
592 cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile, ErrMsgW);
593 }
594 InvalidHost = TRUE;
595 }
596 else {
597 cv->Open = TRUE;
598 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
599 InvalidHost = FALSE;
600 }
601 break; /* end of "case IdNamedPipe:" */
602
603 } /* end of "switch" */
604
605 BreakSC:
606 if (InvalidHost) {
607 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
608 if ( (ts->PortType==IdTCPIP) && cv->Open ) {
609 if ( cv->s!=INVALID_SOCKET ) {
610 Pclosesocket(cv->s);
611 cv->s = INVALID_SOCKET; /* �\�P�b�g�����������t�����B(2010.8.6 yutaka) */
612 }
613 FreeWinsock();
614 }
615 return;
616 }
617 }
618
619 // ���O�t���p�C�v�p�X���b�h
620 void NamedPipeThread(void *arg)
621 {
622 PComVar cv = (PComVar)arg;
623 DWORD DErr;
624 HANDLE REnd;
625 char Temp[20];
626 char Buffer[1]; // 1byte
627 DWORD BytesRead, TotalBytesAvail, BytesLeftThisMessage;
628
629 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
630 REnd = OpenEvent(EVENT_ALL_ACCESS,FALSE, Temp);
631 while (TRUE) {
632 BytesRead = 0;
633 // ���O�t���p�C�v���C�x���g���������������������d�l�������A�L���[�����g��
634 // �`���������������AReadFile() ���������������f�����B
635 if (PeekNamedPipe(cv->ComID, Buffer, sizeof(Buffer), &BytesRead, &TotalBytesAvail, &BytesLeftThisMessage)) {
636 if (! cv->Ready) {
637 _endthread();
638 }
639 if (BytesRead == 0) { // �����������A�����������B
640 Sleep(1);
641 continue;
642 }
643 if (! cv->RRQ) {
644 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_READ);
645 }
646 // ReadFile() ���I�������������B
647 WaitForSingleObject(REnd,INFINITE);
648 }
649 else {
650 DErr = GetLastError();
651 // [VMware] this returns 109 (broken pipe) if a named pipe is removed.
652 // [Virtual Box] this returns 233 (pipe not connected) if a named pipe is removed.
653 if (! cv->Ready || ERROR_BROKEN_PIPE == DErr || ERROR_PIPE_NOT_CONNECTED == DErr) {
654 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
655 _endthread();
656 }
657 }
658 }
659 }
660
661 void CommThread(void *arg)
662 {
663 DWORD Evt;
664 PComVar cv = (PComVar)arg;
665 DWORD DErr;
666 HANDLE REnd;
667 char Temp[20];
668
669 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
670 REnd = OpenEvent(EVENT_ALL_ACCESS,FALSE, Temp);
671 while (TRUE) {
672 if (WaitCommEvent(cv->ComID,&Evt,NULL)) {
673 if (! cv->Ready) {
674 _endthread();
675 }
676 if (! cv->RRQ) {
677 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_READ);
678 }
679 WaitForSingleObject(REnd,INFINITE);
680 }
681 else {
682 DErr = GetLastError(); // this returns 995 (operation aborted) if a USB com port is removed
683 if (! cv->Ready || ERROR_OPERATION_ABORTED == DErr) {
684 _endthread();
685 }
686 ClearCommError(cv->ComID,&DErr,NULL);
687 }
688 }
689 }
690
691 void CommStart(PComVar cv, LONG lParam, PTTSet ts)
692 {
693 char ErrMsg[31];
694 wchar_t ErrMsgW[31];
695 char Temp[20];
696 wchar_t UIMsgW[MAX_UIMSG];
697
698 if (! cv->Open ) {
699 return;
700 }
701 if ( cv->Ready ) {
702 return;
703 }
704
705 // �L�����Z���^�C�}�����������������B�������A�������_�� WM_TIMER �����������������\���������B
706 if (*cv->ConnetingTimeout > 0) {
707 KillTimer(cv->HWin, IdCancelConnectTimer);
708 }
709
710 switch (cv->PortType) {
711 case IdTCPIP:
712 ErrMsg[0] = 0;
713 switch (HIWORD(lParam)) {
714 case WSAECONNREFUSED:
715 get_lang_msgW("MSG_COMM_REFUSE_ERROR", UIMsgW, _countof(UIMsgW), L"Connection refused", ts->UILanguageFile);
716 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, L"%s", UIMsgW);
717 break;
718 case WSAENETUNREACH:
719 get_lang_msgW("MSG_COMM_REACH_ERROR", UIMsgW, _countof(UIMsgW), L"Network cannot be reached", ts->UILanguageFile);
720 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, L"%s", UIMsgW);
721 break;
722 case WSAETIMEDOUT:
723 get_lang_msgW("MSG_COMM_CONNECT_ERROR", UIMsgW, _countof(UIMsgW), L"Connection timed out", ts->UILanguageFile);
724 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, L"%s", UIMsgW);
725 break;
726 default:
727 get_lang_msgW("MSG_COMM_TIMEOUT_ERROR", UIMsgW, _countof(UIMsgW), L"Cannot connect the host", ts->UILanguageFile);
728 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, L"%s", UIMsgW);
729 }
730 if (HIWORD(lParam)>0) {
731 /* connect() failed */
732 if (cv->res->ai_next != NULL) {
733 /* try to connect with other protocol */
734 CloseSocket(cv->s);
735 for (cv->res = cv->res->ai_next; cv->res; cv->res = cv->res->ai_next) {
736 cv->s = OpenSocket(cv);
737 if (cv->s == INVALID_SOCKET) {
738 CloseSocket(cv->s);
739 continue;
740 }
741 AsyncConnect(cv);
742 cv->Ready = FALSE;
743 cv->RetryWithOtherProtocol = TRUE; /* retry with other procotol */
744 return;
745 }
746 } else {
747 /* trying with all protocol family are failed */
748 if (cv->NoMsg==0)
749 {
750 static const TTMessageBoxInfoW info = {
751 "Tera Term",
752 "MSG_TT_ERROR", L"Tera Term: Error",
753 NULL, NULL
754 };
755 TTMessageBoxW(
756 cv->HWin,
757 &info, (MB_TASKMODAL | MB_ICONEXCLAMATION),
758 ts->UILanguageFile, ErrMsgW);
759 }
760 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
761 cv->RetryWithOtherProtocol = FALSE;
762 return;
763 }
764 }
765
766 /* here is connection established */
767 cv->RetryWithOtherProtocol = FALSE;
768 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_READ | FD_OOB | FD_CLOSE);
769 TCPIPClosed = FALSE;
770 break;
771
772 case IdSerial:
773 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
774 ReadEnd = CreateEvent(NULL,FALSE,FALSE,Temp);
775 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", WRITENAME, cv->ComPort);
776 memset(&wol,0,sizeof(OVERLAPPED));
777 wol.hEvent = CreateEvent(NULL,TRUE,TRUE,Temp);
778 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READNAME, cv->ComPort);
779 memset(&rol,0,sizeof(OVERLAPPED));
780 rol.hEvent = CreateEvent(NULL,TRUE,FALSE,Temp);
781
782 /* create the receiver thread */
783 if (_beginthread(CommThread,0,cv) == -1) {
784 static const TTMessageBoxInfoW info = {
785 "Tera Term",
786 "MSG_TT_ERROR", L"Tera Term: Error",
787 "MSG_TT_ERROR", L"Can't create thread"
788 };
789 TTMessageBoxW(cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile);
790 }
791 break;
792
793 case IdFile:
794 cv->RRQ = TRUE;
795 break;
796
797 case IdNamedPipe:
798 cv->ComPort = 0;
799 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
800 ReadEnd = CreateEvent(NULL,FALSE,FALSE,Temp);
801 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", WRITENAME, cv->ComPort);
802 memset(&wol,0,sizeof(OVERLAPPED));
803 wol.hEvent = CreateEvent(NULL,TRUE,TRUE,Temp);
804 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READNAME, cv->ComPort);
805 memset(&rol,0,sizeof(OVERLAPPED));
806 rol.hEvent = CreateEvent(NULL,TRUE,FALSE,Temp);
807
808 /* create the receiver thread */
809 if (_beginthread(NamedPipeThread,0,cv) == -1) {
810 static const TTMessageBoxInfoW info = {
811 "Tera Term",
812 "MSG_TT_ERROR", L"Tera Term: Error",
813 "MSG_TT_ERROR", L"Can't create thread"
814 };
815 TTMessageBoxW(cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile);
816 }
817 break;
818 }
819 cv->Ready = TRUE;
820 cv->ConnectedTime = GetTickCount();
821 }
822
823 BOOL CommCanClose(PComVar cv)
824 { // check if data remains in buffer
825 if (! cv->Open) {
826 return TRUE;
827 }
828 if (cv->InBuffCount>0) {
829 return FALSE;
830 }
831 if (FLogIsOpend() && FLogGetCount() > 0) {
832 return FALSE;
833 }
834 if (DDELog && DDEGetCount() > 0) {
835 return FALSE;
836 }
837 return TRUE;
838 }
839
840 void CommClose(PComVar cv)
841 {
842 if ( ! cv->Open ) {
843 return;
844 }
845 cv->Open = FALSE;
846
847 /* disable event message posting & flush buffer */
848 cv->RRQ = FALSE;
849 cv->Ready = FALSE;
850 cv->InPtr = 0;
851 cv->InBuffCount = 0;
852 cv->OutPtr = 0;
853 cv->OutBuffCount = 0;
854 cv->LineModeBuffCount = 0;
855 cv->FlushLen = 0;
856 cv->Flush = FALSE;
857
858 /* close port & release resources */
859 switch (cv->PortType) {
860 case IdTCPIP:
861 if (HAsync!=0) {
862 PWSACancelAsyncRequest(HAsync);
863 }
864 HAsync = 0;
865 Pfreeaddrinfo(cv->res0);
866 if ( cv->s!=INVALID_SOCKET ) {
867 Pclosesocket(cv->s);
868 }
869 cv->s = INVALID_SOCKET;
870 TTXCloseTCP(); /* TTPLUG */
871 FreeWinsock();
872 break;
873 case IdSerial:
874 if ( cv->ComID != INVALID_HANDLE_VALUE ) {
875 CloseHandle(ReadEnd);
876 CloseHandle(wol.hEvent);
877 CloseHandle(rol.hEvent);
878 PurgeComm(cv->ComID, PURGE_TXABORT | PURGE_RXABORT |
879 PURGE_TXCLEAR | PURGE_RXCLEAR);
880 EscapeCommFunction(cv->ComID,CLRDTR);
881 SetCommMask(cv->ComID,0);
882 PCloseFile(cv->ComID);
883 ClearCOMFlag(cv->ComPort);
884 }
885 TTXCloseFile(); /* TTPLUG */
886 break;
887 case IdFile:
888 if (cv->ComID != INVALID_HANDLE_VALUE) {
889 PCloseFile(cv->ComID);
890 }
891 TTXCloseFile(); /* TTPLUG */
892 break;
893
894 case IdNamedPipe:
895 if ( cv->ComID != INVALID_HANDLE_VALUE ) {
896 CloseHandle(ReadEnd);
897 CloseHandle(wol.hEvent);
898 CloseHandle(rol.hEvent);
899 PCloseFile(cv->ComID);
900 }
901 TTXCloseFile(); /* TTPLUG */
902 break;
903 }
904 cv->ComID = INVALID_HANDLE_VALUE;
905 cv->PortType = 0;
906
907 _free_locale(cv->locale);
908 }
909
910 void CommProcRRQ(PComVar cv)
911 {
912 if ( ! cv->Ready ) {
913 return;
914 }
915 /* disable receive request */
916 switch (cv->PortType) {
917 case IdTCPIP:
918 if (! TCPIPClosed) {
919 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_OOB | FD_CLOSE);
920 }
921 break;
922 case IdSerial:
923 break;
924 }
925 cv->RRQ = TRUE;
926 CommReceive(cv);
927 }
928
929 void CommReceive(PComVar cv)
930 {
931 DWORD C;
932 DWORD DErr;
933
934 if (! cv->Ready || ! cv->RRQ ||
935 (cv->InBuffCount>=InBuffSize)) {
936 return;
937 }
938
939 /* Compact buffer */
940 if ((cv->InBuffCount>0) && (cv->InPtr>0)) {
941 memmove(cv->InBuff,&(cv->InBuff[cv->InPtr]),cv->InBuffCount);
942 cv->InPtr = 0;
943 }
944
945 if (cv->InBuffCount<InBuffSize) {
946 switch (cv->PortType) {
947 case IdTCPIP:
948 C = Precv(cv->s, &(cv->InBuff[cv->InBuffCount]),
949 InBuffSize-cv->InBuffCount, 0);
950 if (C == SOCKET_ERROR) {
951 C = 0;
952 PWSAGetLastError();
953 }
954 cv->InBuffCount = cv->InBuffCount + C;
955 break;
956 case IdSerial:
957 do {
958 ClearCommError(cv->ComID,&DErr,NULL);
959 if (! PReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
960 InBuffSize-cv->InBuffCount,&C,&rol)) {
961 if (GetLastError() == ERROR_IO_PENDING) {
962 if (WaitForSingleObject(rol.hEvent, 1000) != WAIT_OBJECT_0) {
963 C = 0;
964 }
965 else {
966 GetOverlappedResult(cv->ComID,&rol,&C,FALSE);
967 }
968 }
969 else {
970 C = 0;
971 }
972 }
973 cv->InBuffCount = cv->InBuffCount + C;
974 } while ((C!=0) && (cv->InBuffCount<InBuffSize));
975 ClearCommError(cv->ComID,&DErr,NULL);
976 break;
977 case IdFile:
978 if (PReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
979 InBuffSize-cv->InBuffCount,&C,NULL)) {
980 if (C == 0) {
981 DErr = ERROR_HANDLE_EOF;
982 }
983 else {
984 cv->InBuffCount = cv->InBuffCount + C;
985 }
986 }
987 else {
988 DErr = GetLastError();
989 }
990 break;
991
992 case IdNamedPipe:
993 // �L���[����������1�o�C�g�������f�[�^�������������������m�F���������������A
994 // ReadFile() ���u���b�N�������������������A�������������B
995 if (PReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
996 InBuffSize-cv->InBuffCount,&C,NULL)) {
997 if (C == 0) {
998 DErr = ERROR_HANDLE_EOF;
999 }
1000 else {
1001 cv->InBuffCount = cv->InBuffCount + C;
1002 }
1003 }
1004 else {
1005 DErr = GetLastError();
1006 }
1007
1008 // 1�o�C�g�������������A�C�x���g���N�����A�X���b�h�����J�������B
1009 if (cv->InBuffCount > 0) {
1010 cv->RRQ = FALSE;
1011 SetEvent(ReadEnd);
1012 }
1013 break;
1014 }
1015 }
1016
1017 if (cv->InBuffCount==0) {
1018 switch (cv->PortType) {
1019 case IdTCPIP:
1020 if (! TCPIPClosed) {
1021 PWSAAsyncSelect(cv->s,cv->HWin, WM_USER_COMMNOTIFY,
1022 FD_READ | FD_OOB | FD_CLOSE);
1023 }
1024 break;
1025 case IdSerial:
1026 cv->RRQ = FALSE;
1027 SetEvent(ReadEnd);
1028 return;
1029 case IdFile:
1030 if (DErr != ERROR_IO_PENDING) {
1031 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
1032 cv->RRQ = FALSE;
1033 }
1034 else {
1035 cv->RRQ = TRUE;
1036 }
1037 return;
1038 case IdNamedPipe:
1039 // TODO: �������A���������������������B
1040 if (DErr != ERROR_IO_PENDING) {
1041 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
1042 cv->RRQ = FALSE;
1043 }
1044 else {
1045 cv->RRQ = TRUE;
1046 }
1047 SetEvent(ReadEnd);
1048 return;
1049 }
1050 cv->RRQ = FALSE;
1051 }
1052 }
1053
1054 void CommSend(PComVar cv)
1055 {
1056 int delay;
1057 COMSTAT Stat;
1058 BYTE LineEnd;
1059 int C, D, Max;
1060 DWORD DErr;
1061
1062 if ((! cv->Open) || (! cv->Ready)) {
1063 cv->OutBuffCount = 0;
1064 return;
1065 }
1066
1067 if ((cv->OutBuffCount == 0) || (! cv->CanSend)) {
1068 return;
1069 }
1070
1071 /* Max num of bytes to be written */
1072 switch (cv->PortType) {
1073 case IdTCPIP:
1074 if (TCPIPClosed) {
1075 cv->OutBuffCount = 0;
1076 }
1077 Max = cv->OutBuffCount;
1078 break;
1079 case IdSerial:
1080 ClearCommError(cv->ComID,&DErr,&Stat);
1081 Max = OutBuffSize - Stat.cbOutQue;
1082 break;
1083 case IdFile:
1084 Max = cv->OutBuffCount;
1085 break;
1086 case IdNamedPipe:
1087 Max = cv->OutBuffCount;
1088 break;
1089 }
1090
1091 if ( Max<=0 ) {
1092 return;
1093 }
1094 if ( Max > cv->OutBuffCount ) {
1095 Max = cv->OutBuffCount;
1096 }
1097
1098 if (cv->PortType == IdTCPIP && cv->TelFlag) {
1099 cv->LastSendTime = time(NULL);
1100 }
1101
1102 C = Max;
1103 delay = 0;
1104
1105 if ( cv->DelayFlag && (cv->PortType==IdSerial) ) {
1106 if ( cv->DelayPerLine > 0 ) {
1107 if ( cv->CRSend==IdCR ) {
1108 LineEnd = 0x0d;
1109 }
1110 else { // CRLF or LF
1111 LineEnd = 0x0a;
1112 }
1113 C = 1;
1114 if ( cv->DelayPerChar==0 ) {
1115 while ((C<Max) && (cv->OutBuff[cv->OutPtr+C-1]!=LineEnd)) {
1116 C++;
1117 }
1118 }
1119 if ( cv->OutBuff[cv->OutPtr+C-1]==LineEnd ) {
1120 delay = cv->DelayPerLine;
1121 }
1122 else {
1123 delay = cv->DelayPerChar;
1124 }
1125 }
1126 else if ( cv->DelayPerChar > 0 ) {
1127 C = 1;
1128 delay = cv->DelayPerChar;
1129 }
1130 }
1131
1132 /* Write to comm driver/Winsock */
1133 switch (cv->PortType) {
1134 case IdTCPIP:
1135 D = Psend(cv->s, &(cv->OutBuff[cv->OutPtr]), C, 0);
1136 if ( D==SOCKET_ERROR ) { /* if error occurs */
1137 PWSAGetLastError(); /* Clear error */
1138 D = 0;
1139 }
1140 break;
1141
1142 case IdSerial:
1143 if (! PWriteFile(cv->ComID,&(cv->OutBuff[cv->OutPtr]),C,(LPDWORD)&D,&wol)) {
1144 if (GetLastError() == ERROR_IO_PENDING) {
1145 if (WaitForSingleObject(wol.hEvent,1000) != WAIT_OBJECT_0) {
1146 D = C; /* Time out, ignore data */
1147 }
1148 else {
1149 GetOverlappedResult(cv->ComID,&wol,(LPDWORD)&D,FALSE);
1150 }
1151 }
1152 else { /* I/O error */
1153 D = C; /* ignore error */
1154 }
1155 }
1156 ClearCommError(cv->ComID,&DErr,&Stat);
1157 break;
1158
1159 case IdFile:
1160 if (! PWriteFile(cv->ComID, &(cv->OutBuff[cv->OutPtr]), C, (LPDWORD)&D, NULL)) {
1161 if (! (GetLastError() == ERROR_IO_PENDING)) {
1162 D = C; /* ignore data */
1163 }
1164 }
1165 break;
1166
1167 case IdNamedPipe:
1168 if (! PWriteFile(cv->ComID, &(cv->OutBuff[cv->OutPtr]), C, (LPDWORD)&D, NULL)) {
1169 // ERROR_IO_PENDING ���O���G���[���������A�p�C�v���N���[�Y�������������������������A
1170 // ���M�����������������B
1171 if (! (GetLastError() == ERROR_IO_PENDING)) {
1172 D = C; /* ignore data */
1173 }
1174 }
1175 break;
1176 }
1177
1178 cv->OutBuffCount = cv->OutBuffCount - D;
1179 if ( cv->OutBuffCount==0 ) {
1180 cv->OutPtr = 0;
1181 }
1182 else {
1183 cv->OutPtr = cv->OutPtr + D;
1184 }
1185
1186 if ( (C==D) && (delay>0) ) {
1187 cv->CanSend = FALSE;
1188 SetTimer(cv->HWin, IdDelayTimer, delay, NULL);
1189 }
1190 }
1191
1192 void CommSendBreak(PComVar cv, int msec)
1193 /* for only serial ports */
1194 {
1195 MSG DummyMsg;
1196
1197 if ( ! cv->Ready ) {
1198 return;
1199 }
1200
1201 switch (cv->PortType) {
1202 case IdSerial:
1203 /* Set com port into a break state */
1204 SetCommBreak(cv->ComID);
1205
1206 /* pause for 1 sec */
1207 if (SetTimer(cv->HWin, IdBreakTimer, msec, NULL) != 0) {
1208 GetMessage(&DummyMsg,cv->HWin,WM_TIMER,WM_TIMER);
1209 }
1210
1211 /* Set com port into the nonbreak state */
1212 ClearCommBreak(cv->ComID);
1213 break;
1214 }
1215 }
1216
1217 void CommLock(PTTSet ts, PComVar cv, BOOL Lock)
1218 {
1219 BYTE b;
1220 DWORD Func;
1221
1222 if (! cv->Ready) {
1223 return;
1224 }
1225 if ((cv->PortType==IdTCPIP) ||
1226 (cv->PortType==IdSerial) &&
1227 (!(ts->Flow == IdFlowHard || ts->Flow == IdFlowHardDsrDtr))
1228 ) {
1229 if (Lock) {
1230 b = XOFF;
1231 }
1232 else {
1233 b = XON;
1234 }
1235 CommBinaryOut(cv,&b,1);
1236 }
1237 else if ((cv->PortType==IdSerial) &&
1238 (ts->Flow == IdFlowHard || ts->Flow == IdFlowHardDsrDtr)) {
1239 // �n�[�h�E�F�A�t���[���������������g���@�\�R�[�h�������������B
1240 if (Lock) {
1241 Func = CLRRTS;
1242 if (ts->Flow == IdFlowHardDsrDtr)
1243 Func = CLRDTR;
1244 }
1245 else {
1246 Func = SETRTS;
1247 if (ts->Flow == IdFlowHardDsrDtr)
1248 Func = SETDTR;
1249 }
1250 EscapeCommFunction(cv->ComID,Func);
1251 }
1252 }
1253
1254 BOOL PrnOpen(PCHAR DevName)
1255 {
1256 char Temp[MAXPATHLEN], *c;
1257 DCB dcb;
1258 DWORD DErr;
1259 COMMTIMEOUTS ctmo;
1260
1261 strncpy_s(Temp, sizeof(Temp),DevName, _TRUNCATE);
1262 c = Temp;
1263 while (*c != '\0' && *c != ':') {
1264 c++;
1265 }
1266 *c = '\0';
1267 LPTFlag = (Temp[0]=='L') ||
1268 (Temp[0]=='l');
1269
1270 if (IsWindowsNTKernel()) {
1271 // �l�b�g���[�N���L���}�b�v�������f�o�C�X�������������A�������������������������� (2011.01.25 maya)
1272 // http://logmett.com/forum/viewtopic.php?f=2&t=1383
1273 // http://msdn.microsoft.com/en-us/library/aa363858(v=vs.85).aspx#5
1274 PrnID = CreateFile(Temp,GENERIC_WRITE | FILE_READ_ATTRIBUTES,
1275 FILE_SHARE_READ,NULL,CREATE_ALWAYS,
1276 0,NULL);
1277 }
1278 else {
1279 // 9x �������L���R�[�h���������������������]������������
1280 PrnID = CreateFile(Temp,GENERIC_WRITE,
1281 0,NULL,OPEN_EXISTING,
1282 0,NULL);
1283 }
1284
1285 if (PrnID == INVALID_HANDLE_VALUE) {
1286 return FALSE;
1287 }
1288
1289 if (GetCommState(PrnID,&dcb)) {
1290 BuildCommDCB(DevName,&dcb);
1291 SetCommState(PrnID,&dcb);
1292 }
1293 ClearCommError(PrnID,&DErr,NULL);
1294 if (! LPTFlag) {
1295 SetupComm(PrnID,0,CommOutQueSize);
1296 }
1297 /* flush output buffer */
1298 PurgeComm(PrnID, PURGE_TXABORT | PURGE_TXCLEAR);
1299 memset(&ctmo,0,sizeof(ctmo));
1300 ctmo.WriteTotalTimeoutConstant = 1000;
1301 SetCommTimeouts(PrnID,&ctmo);
1302 if (! LPTFlag) {
1303 EscapeCommFunction(PrnID,SETDTR);
1304 }
1305 return TRUE;
1306 }
1307
1308 int PrnWrite(PCHAR b, int c)
1309 {
1310 int d;
1311 DWORD DErr;
1312 COMSTAT Stat;
1313
1314 if (PrnID == INVALID_HANDLE_VALUE ) {
1315 return c;
1316 }
1317
1318 ClearCommError(PrnID,&DErr,&Stat);
1319 if (! LPTFlag &&
1320 (OutBuffSize - (int)Stat.cbOutQue < c)) {
1321 c = OutBuffSize - Stat.cbOutQue;
1322 }
1323 if (c<=0) {
1324 return 0;
1325 }
1326 if (! WriteFile(PrnID,b,c,(LPDWORD)&d,NULL)) {
1327 d = 0;
1328 }
1329 ClearCommError(PrnID,&DErr,NULL);
1330 return d;
1331 }
1332
1333 void PrnCancel()
1334 {
1335 PurgeComm(PrnID, PURGE_TXABORT | PURGE_TXCLEAR);
1336 PrnClose();
1337 }
1338
1339 void PrnClose()
1340 {
1341 if (PrnID != INVALID_HANDLE_VALUE) {
1342 if (!LPTFlag) {
1343 EscapeCommFunction(PrnID,CLRDTR);
1344 }
1345 CloseHandle(PrnID);
1346 }
1347 PrnID = INVALID_HANDLE_VALUE;
1348 }

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