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 8906 - (show annotations) (download) (as text)
Tue Aug 18 15:31:34 2020 UTC (3 years, 6 months ago) by zmatsuo
Original Path: trunk/teraterm/teraterm/commlib.c
File MIME type: text/x-csrc
File size: 35981 byte(s)
ログに関する変数を移動、バッファをヒープから取るよう修正

- ログに関する変数を filesys_log.cpp に移動した
- バッファをヒープから取るようにした
  - GlobalAlloc() で取得するのをやめた
  - GlobalLock(), GlobalUnlock() を行う必要がなくなった
1 /*
2 * Copyright (C) 1994-1998 T. Teranishi
3 * (C) 2005-2020 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 };
469
470 switch (err) {
471 case ERROR_FILE_NOT_FOUND:
472 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_NOTFOUND", L"Cannot open %s. Not found.", ts->UILanguageFile);
473 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
474 break;
475 case ERROR_ACCESS_DENIED:
476 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR_DENIED", L"Cannot open %s. Access denied.", ts->UILanguageFile);
477 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW);
478 break;
479 default:
480 format = TTGetLangStrW("Tera Term", "MSG_CANTOPEN_ERROR", L"Cannot open %s. (0x%08x)", ts->UILanguageFile);
481 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE, format, PW, err);
482 break;
483 }
484 free(format);
485 free(PW);
486
487 TTMessageBoxW(
488 cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile, ErrMsgW);
489 }
490 InvalidHost = TRUE;
491 }
492 else {
493 cv->Open = TRUE;
494 cv->ComPort = ts->ComPort;
495 CommResetSerial(ts, cv, ts->ClearComBuffOnOpen);
496 if (!ts->ClearComBuffOnOpen) {
497 cv->RRQ = TRUE;
498 }
499
500 /* notify to VT window that Comm Port is open */
501 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
502 InvalidHost = FALSE;
503
504 SetCOMFlag(ts->ComPort);
505 }
506 break; /* end of "case IdSerial:" */
507
508 case IdFile:
509 InitFileIO(IdFile); /* TTPLUG */
510 TTXOpenFile(); /* TTPLUG */
511 cv->ComID = PCreateFile(ts->HostName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
512 InvalidHost = (cv->ComID == INVALID_HANDLE_VALUE);
513 if (InvalidHost) {
514 if (cv->NoMsg==0) {
515 static const TTMessageBoxInfoW info = {
516 "Tera Term",
517 "MSG_TT_ERROR", L"Tera Term: Error",
518 "MSG_CANTOPEN_FILE_ERROR", L"Cannot open file"
519 };
520 TTMessageBoxW(
521 cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile);
522 }
523 }
524 else {
525 cv->Open = TRUE;
526 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
527 }
528 break;
529
530 case IdNamedPipe:
531 InitFileIO(IdNamedPipe); /* TTPLUG */
532 TTXOpenFile(); /* TTPLUG */
533
534 memset(P, 0, sizeof(P));
535 strncpy_s(P, sizeof(P), ts->HostName, _TRUNCATE);
536
537 // ���O�t���p�C�v�����������������`�F�b�N�����B
538 if (CheckNamedPipeFormat(P, strlen(P)) < 0) {
539 static const TTMessageBoxInfoW info = {
540 "Tera Term",
541 "MSG_TT_ERROR", L"Tera Term: Error",
542 };
543 InvalidHost = TRUE;
544
545 _snwprintf_s(ErrMsgW, _countof(ErrMsgW), _TRUNCATE,
546 L"Invalid pipe name (%d)\n\n"
547 L"A valid pipe name has the form\n"
548 L"\"\\\\<ServerName>\\pipe\\<PipeName>\"",
549 GetLastError());
550 TTMessageBoxW(cv->HWin, &info, MB_TASKMODAL | MB_ICONEXCLAMATION, ts->UILanguageFile, ErrMsgW);
551 break;
552 }
553
554 cv->ComID = PCreateFile(P, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
555 0, // �u���b�L���O���[�h������(FILE_FLAG_OVERLAPPED ���w��������)
556 NULL);
557 if (cv->ComID == INVALID_HANDLE_VALUE ) {
558 if (cv->NoMsg==0) {
559 DWORD err = GetLastError();
560 wchar_t *format;
561 wchar_t* PW = ToWcharA(&P[4]);
562 static const TTMessageBoxInfoW info = {
563 "Tera Term",
564 "MSG_TT_ERROR", L"Tera Term: Error",
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