Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/commlib.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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