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 9206 - (show annotations) (download) (as text)
Mon Apr 12 14:16:18 2021 UTC (2 years, 10 months ago) by nmaya
Original Path: trunk/teraterm/teraterm/commlib.c
File MIME type: text/x-csrc
File size: 35786 byte(s)
シリアルポート接続の1.5ストップビットのサポートを削除

ticket #40299
1.5ストップビットは常に不正な設定となるため

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

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