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 10593 - (show annotations) (download) (as text)
Mon Feb 13 14:41:35 2023 UTC (12 months, 3 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 37182 byte(s)
r10587の送信フロー制御が誤っていたので修正

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

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