Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/filesys_log.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10958 - (show annotations) (download) (as text)
Sat Oct 7 17:40:16 2023 UTC (7 months, 3 weeks ago) by zmatsuo
File MIME type: text/x-c++src
File size: 27979 byte(s)
文字列を返す関数の文字領域を動的確保するよう変更

- 複数スレッドを使用している箇所でログが壊れたり不正な処理で終了することがあった
- ログ出力時に使用していた関数が文字領域を静的に持っていた
- マルチスレッドで使用していると文字領域を破壊することがある
- 返す文字領域を動的にして不要になったらfree()するよう仕様を変更
1 /*
2 * (C) 2020- TeraTerm Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* TERATERM.EXE, log routines */
30 #include <stdio.h>
31 #if !defined(_CRTDBG_MAP_ALLOC)
32 #define _CRTDBG_MAP_ALLOC
33 #endif
34 #include <stdlib.h>
35 #include <crtdbg.h>
36 #include <process.h>
37 #include <windows.h>
38 #include <htmlhelp.h>
39 #include <assert.h>
40
41 #include "teraterm.h"
42 #include "tttypes.h"
43 #include "ftdlg.h"
44 #include "ttwinman.h"
45 #include "commlib.h"
46 #include "ttcommon.h"
47 #include "ttlib.h"
48 #include "dlglib.h"
49 #include "vtterm.h"
50 #include "ftlib.h"
51 #include "buffer.h"
52 #include "helpid.h"
53 #include "codeconv.h"
54 #include "asprintf.h"
55 #include "win32helper.h"
56
57 #include "filesys_log_res.h"
58 #include "filesys_log.h"
59 #include "filesys.h" // for ProtoGetProtoFlag()
60
61 #define TitLog L"Log"
62
63 /*
64 Line Head flag for timestamping
65 2007.05.24 Gentaro
66 */
67 enum enumLineEnd {
68 Line_Other = 0,
69 Line_LineHead = 1,
70 Line_FileHead = 2,
71 };
72
73 typedef struct {
74 wchar_t *FullName;
75
76 HANDLE FileHandle;
77 LONG FileSize, ByteCount;
78
79 DWORD StartTime;
80
81 enum enumLineEnd eLineEnd;
82
83 // log rotate
84 int RotateMode; // enum rotate_mode RotateMode;
85 LONG RotateSize;
86 int RotateStep;
87
88 HANDLE LogThread;
89 DWORD LogThreadId;
90 HANDLE LogThreadEvent;
91
92 BOOL IsPause;
93
94 PFileTransDlg FLogDlg;
95
96 LogCode_t log_code;
97 BOOL bom;
98
99 BOOL FileLog;
100 BOOL BinLog;
101 } TFileVar;
102 typedef TFileVar *PFileVar;
103
104 static PFileVar LogVar = NULL;
105
106 static PCHAR cv_LogBuf;
107 static int cv_LogPtr, cv_LStart, cv_LCount;
108 static PCHAR cv_BinBuf;
109 static int cv_BinPtr, cv_BStart, cv_BCount;
110 static int cv_BinSkip;
111
112 // �x�����������p�X���b�h�����b�Z�[�W
113 #define WM_DPC_LOGTHREAD_SEND (WM_APP + 1)
114
115 static void Log1Bin(BYTE b);
116 static void LogBinSkip(int add);
117 static BOOL CreateLogBuf(void);
118 static BOOL CreateBinBuf(void);
119 void LogPut1(BYTE b);
120 static void OutputStr(const wchar_t *str);
121 static void LogToFile(PFileVar fv);
122 static void FLogOutputBOM(PFileVar fv);
123
124 static BOOL OpenFTDlg_(PFileVar fv)
125 {
126 PFileTransDlg FTDlg = new CFileTransDlg();
127 if (FTDlg == NULL) {
128 return FALSE;
129 }
130
131 wchar_t *DlgCaption;
132 wchar_t *uimsg;
133 GetI18nStrWW("Tera Term", "FILEDLG_TRANS_TITLE_LOG", TitLog, ts.UILanguageFileW, &uimsg);
134 aswprintf(&DlgCaption, L"Tera Term: %s", uimsg);
135 free(uimsg);
136
137 CFileTransDlg::Info info;
138 info.UILanguageFileW = ts.UILanguageFileW;
139 info.OpId = CFileTransDlg::OpLog;
140 info.DlgCaption = DlgCaption;
141 info.FileName = NULL;
142 info.FullName = fv->FullName;
143 info.HideDialog = ts.LogHideDialog ? TRUE : FALSE;
144 info.HMainWin = HVTWin;
145 FTDlg->Create(hInst, &info);
146 FTDlg->RefreshNum(0, fv->FileSize, fv->ByteCount);
147
148 fv->FLogDlg = FTDlg;
149
150 free(DlgCaption);
151 return TRUE;
152 }
153
154 /**
155 * �t�@�C�������������u������,���O�p
156 * �����������u��������
157 * &h �z�X�g�����u��
158 * &p TCP�|�[�g�������u��
159 * &u ���O�I���������[�U��
160 *
161 * @param pcv
162 * @param src �u���������O��������(�t�@�C����)
163 * @return �u������������������
164 * �s�v����������free()��������
165 */
166 static wchar_t *ConvertLognameW(const TComVar *pcv, const wchar_t *src)
167 {
168 const TTTSet *pts = pcv->ts;
169 size_t dest_len = wcslen(src) + 1;
170 wchar_t *dest = (wchar_t *)malloc(sizeof(wchar_t) * dest_len);
171
172 const wchar_t *s = src;
173 size_t i = 0;
174
175 while(*s != '\0') {
176 if (*s == '&' && *(s+1) != '\0') {
177 wchar_t c = *(s+1);
178 wchar_t *add_text = NULL;
179 switch (c) {
180 case 'h':
181 s += 2;
182 if (pcv->Open) {
183 switch(pcv->PortType) {
184 case IdTCPIP: {
185 // �z�X�g����IPv6�A�h���X�����A�t�@�C�������g�p������������(:)�����������u��
186 wchar_t *host = ToWcharA(pts->HostName);
187 wchar_t *host_fix = replaceInvalidFileNameCharW(host, '_');
188 free(host);
189 add_text = host_fix;
190 break;
191 }
192 case IdSerial: {
193 wchar_t *port;
194 aswprintf(&port, L"COM%d", ts.ComPort);
195 add_text = port;
196 break;
197 }
198 default:
199 ;
200 }
201 }
202 break;
203 case 'p':
204 s += 2;
205 if (pcv->Open) {
206 if (pcv->PortType == IdTCPIP) {
207 wchar_t *port;
208 aswprintf(&port, L"%d", ts.TCPPort);
209 add_text = port;
210 }
211 }
212 break;
213 case 'u': {
214 s += 2;
215 wchar_t user[256 + 1]; // 256=UNLEN
216 DWORD l = _countof(user);
217 if (GetUserNameW(user, &l) != 0) {
218 add_text = _wcsdup(user);
219 }
220 break;
221 }
222 default:
223 // pass '&'
224 s++;
225 add_text = NULL;
226 break;
227 }
228
229 if (add_text != NULL) {
230 size_t l = wcslen(add_text);
231 dest_len += l;
232 dest = (wchar_t *)realloc(dest, sizeof(wchar_t) * dest_len);
233 wcscpy(&dest[i], add_text);
234 free(add_text);
235 i += l;
236 }
237 }
238 else {
239 dest[i] = *s++;
240 i++;
241 }
242 }
243 dest[i] = 0;
244 return dest;
245 }
246
247 static void FixLogOption(void)
248 {
249 if (ts.LogBinary) {
250 ts.LogTypePlainText = false;
251 ts.LogTimestamp = false;
252 }
253 }
254
255
256 // �X���b�h���I�����t�@�C�����N���[�Y
257 static void CloseFileSync(PFileVar fv)
258 {
259 BOOL ret;
260
261 if (fv->FileHandle == INVALID_HANDLE_VALUE) {
262 return;
263 }
264
265 if (fv->LogThread != INVALID_HANDLE_VALUE) {
266 // �X���b�h���I������
267 ret = PostThreadMessage(fv->LogThreadId, WM_QUIT, 0, 0);
268 if (ret != 0) {
269 // �X���b�h�L���[���G���L���[���������������������������s���B
270 WaitForSingleObject(fv->LogThread, INFINITE);
271 }
272 else {
273 //DWORD code = GetLastError();
274 }
275 CloseHandle(fv->LogThread);
276 fv->LogThread = INVALID_HANDLE_VALUE;
277 }
278 CloseHandle(fv->FileHandle);
279 fv->FileHandle = INVALID_HANDLE_VALUE;
280 }
281
282 // �x�����������p�X���b�h
283 static unsigned _stdcall DeferredLogWriteThread(void *arg)
284 {
285 MSG msg;
286 PFileVar fv = (PFileVar)arg;
287 PCHAR buf;
288 DWORD buflen;
289 DWORD wrote;
290
291 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
292
293 // �X���b�h�L���[���������I�������������X���b�h�����������m�����B
294 if (fv->LogThreadEvent != NULL) {
295 SetEvent(fv->LogThreadEvent);
296 }
297
298 while (GetMessage(&msg, NULL, 0, 0) > 0) {
299 switch (msg.message) {
300 case WM_DPC_LOGTHREAD_SEND:
301 buf = (PCHAR)msg.wParam;
302 buflen = (DWORD)msg.lParam;
303 WriteFile(fv->FileHandle, buf, buflen, &wrote, NULL);
304 free(buf); // ����������������
305 break;
306
307 case WM_QUIT:
308 goto end;
309 break;
310 }
311 }
312
313 end:
314 _endthreadex(0);
315 return (0);
316 }
317
318 // �x�����������p�X���b�h���N�����B
319 // (2013.4.19 yutaka)
320 // DeferredLogWriteThread �X���b�h���N�������A�X���b�h�L���[�����������������O���A
321 // ���O�t�@�C�����N���[�Y(CloseFileSync)���s���������A�G���L���[�����s���A�f�b�h���b�N
322 // �����������������C�������B
323 // �X���b�h�����������s�������A���O�����C�x���g�I�u�W�F�N�g���g�����A�X���b�h�L���[��
324 // ���������������������������������B���O�t���C�x���g�I�u�W�F�N�g���g���������A
325 // �V�X�e��(Windows OS)�������j�[�N�����O�������K�v�������B
326 // (2016.9.23 yutaka)
327 static void StartThread(PFileVar fv)
328 {
329 unsigned tid;
330 fv->LogThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
331 fv->LogThread = (HANDLE)_beginthreadex(NULL, 0, DeferredLogWriteThread, fv, 0, &tid);
332 fv->LogThreadId = tid;
333 if (fv->LogThreadEvent != NULL) {
334 WaitForSingleObject(fv->LogThreadEvent, INFINITE);
335 CloseHandle(fv->LogThreadEvent);
336 }
337 }
338
339 static void OpenLogFile(PFileVar fv)
340 {
341 // LogLockExclusive ���L���������������������L���������A
342 // ���������������O�t�@�C���������G�f�B�^���J����������
343 int dwShareMode = FILE_SHARE_READ;
344 if (!ts.LogLockExclusive) {
345 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
346 }
347 fv->FileHandle = CreateFileW(fv->FullName, GENERIC_WRITE, dwShareMode, NULL,
348 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
349 }
350
351 static BOOL LogStart(PFileVar fv, const wchar_t *fname)
352 {
353 fv->FullName = _wcsdup(fname);
354 FixLogOption();
355
356 if (ts.LogBinary > 0)
357 {
358 fv->BinLog = TRUE;
359 fv->FileLog = FALSE;
360 if (! CreateBinBuf())
361 {
362 return FALSE;
363 }
364 }
365 else {
366 fv->BinLog = FALSE;
367 fv->FileLog = TRUE;
368 if (! CreateLogBuf())
369 {
370 return FALSE;
371 }
372 }
373 cv_LStart = cv_LogPtr;
374 cv_LCount = 0;
375
376 OpenLogFile(fv);
377 if (fv->FileHandle == INVALID_HANDLE_VALUE) {
378 return FALSE;
379 }
380
381 /* 2007.05.24 Gentaro */
382 fv->eLineEnd = Line_LineHead;
383 if (ts.Append > 0)
384 {
385 SetFilePointer(fv->FileHandle, 0, NULL, FILE_END);
386 /* 2007.05.24 Gentaro
387 If log file already exists,
388 a newline is inserted before the first timestamp.
389 */
390 fv->eLineEnd = Line_FileHead;
391 }
392
393 // BOM�o��
394 if (ts.Append == 0 && ts.LogBinary == 0 && fv->bom) {
395 // ���L��������(�V�K) && �o�C�i���������� && BOM ���o����
396 FLogOutputBOM(fv);
397 }
398
399 // Log rotate configuration
400 fv->RotateMode = ts.LogRotate;
401 fv->RotateSize = ts.LogRotateSize;
402 fv->RotateStep = ts.LogRotateStep;
403
404 // Log rotate���L���������A�����t�@�C���T�C�Y�����������B
405 // �������t�@�C�������������T�C�Y�����[�e�[�g�������������C���B
406 // (2016.4.9 yutaka)
407 if (fv->RotateMode != ROTATE_NONE) {
408 DWORD size = GetFileSize(fv->FileHandle, NULL);
409 if (size == -1) {
410 return FALSE;
411 }
412 fv->ByteCount = size;
413 }
414 else {
415 fv->ByteCount = 0;
416 }
417
418 if (! OpenFTDlg_(fv)) {
419 return FALSE;
420 }
421
422 fv->IsPause = FALSE;
423 fv->StartTime = GetTickCount();
424
425 if (ts.DeferredLogWriteMode) {
426 StartThread(fv);
427 }
428
429 if (fv->FileLog) {
430 cv.Log1Byte = LogPut1;
431 }
432 if (fv->BinLog) {
433 cv.Log1Bin = Log1Bin;
434 cv.LogBinSkip = LogBinSkip;
435 }
436
437 return TRUE;
438 }
439
440 /**
441 * �����o�b�t�@�������f�[�^�����������O�������o��
442 * (2013.9.29 yutaka)
443 *
444 * TODO
445 * 1�s������
446 */
447 void FLogOutputAllBuffer(void)
448 {
449 PFileVar fv = LogVar;
450 DWORD ofs;
451 int size;
452 wchar_t buf[512];
453 for (ofs = 0 ; ; ofs++ ) {
454 // 1�����s�����������B���������������A�G�X�P�[�v�V�[�P���X�������������B
455 size = BuffGetAnyLineDataW(ofs, buf, _countof(buf));
456 if (size == -1)
457 break;
458
459 OutputStr(buf);
460 OutputStr(L"\r\n");
461 LogToFile(fv);
462 }
463 }
464
465 /**
466 * ���O��1byte��������
467 * �o�b�t�@��������������
468 * ���������������� LogToFile() ���s������
469 */
470 void LogPut1(BYTE b)
471 {
472 PFileVar fv = LogVar;
473
474 cv_LogBuf[cv_LogPtr] = b;
475 cv_LogPtr++;
476 if (cv_LogPtr>=InBuffSize)
477 cv_LogPtr = cv_LogPtr-InBuffSize;
478
479 if (fv->FileLog)
480 {
481 if (cv_LCount>=InBuffSize)
482 {
483 cv_LCount = InBuffSize;
484 cv_LStart = cv_LogPtr;
485 }
486 else
487 cv_LCount++;
488 }
489 else
490 cv_LCount = 0;
491 }
492
493 static BOOL Get1(PCHAR Buf, int *Start, int *Count, PBYTE b)
494 {
495 if (*Count<=0) return FALSE;
496 *b = Buf[*Start];
497 (*Start)++;
498 if (*Start>=InBuffSize)
499 *Start = *Start-InBuffSize;
500 (*Count)--;
501 return TRUE;
502 }
503
504
505
506 static CRITICAL_SECTION g_filelog_lock; /* ���b�N�p���� */
507
508 void logfile_lock_initialize(void)
509 {
510 InitializeCriticalSection(&g_filelog_lock);
511 }
512
513 static inline void logfile_lock(void)
514 {
515 EnterCriticalSection(&g_filelog_lock);
516 }
517
518 static inline void logfile_unlock(void)
519 {
520 LeaveCriticalSection(&g_filelog_lock);
521 }
522
523 // ���O�����[�e�[�g�����B
524 // (2013.3.21 yutaka)
525 static void LogRotate(PFileVar fv)
526 {
527 int loopmax = 10000; // XXX
528 int i, k;
529
530 if (fv->RotateMode == ROTATE_NONE)
531 return;
532
533 if (fv->RotateMode == ROTATE_SIZE) {
534 if (fv->ByteCount <= fv->RotateSize)
535 return;
536 //OutputDebugPrintf("%s: mode %d size %ld\n", __FUNCTION__, fv->RotateMode, fv->ByteCount);
537 } else {
538 return;
539 }
540
541 logfile_lock();
542 // ���O�T�C�Y���������������B
543 fv->ByteCount = 0;
544
545 // �������������t�@�C�����N���[�Y�����A�������t�@�C�����I�[�v�������B
546 CloseFileSync(fv);
547
548 // �������[�e�[�V�������X�e�b�v�����w����������
549 if (fv->RotateStep > 0)
550 loopmax = fv->RotateStep;
551
552 for (i = 1 ; i <= loopmax ; i++) {
553 wchar_t *filename;
554 aswprintf(&filename, L"%s.%d", fv->FullName, i);
555 DWORD attr = GetFileAttributesW(filename);
556 free(filename);
557 if (attr == INVALID_FILE_ATTRIBUTES)
558 break;
559 }
560 if (i > loopmax) {
561 // �������������������������A�������t�@�C�������p�������B
562 i = loopmax;
563 }
564
565 // ���t�@�C�������l�[���B
566 for (k = i-1 ; k >= 0 ; k--) {
567 wchar_t *oldfile;
568 if (k == 0)
569 oldfile = _wcsdup(fv->FullName);
570 else
571 aswprintf(&oldfile, L"%s.%d", fv->FullName, k);
572 wchar_t *newfile;
573 aswprintf(&newfile, L"%s.%d", fv->FullName, k+1);
574 DeleteFileW(newfile);
575 if (MoveFileW(oldfile, newfile) == 0) {
576 OutputDebugPrintf("%s: rename %d\n", __FUNCTION__, errno);
577 }
578 free(oldfile);
579 free(newfile);
580 }
581
582 // ���I�[�v��
583 OpenLogFile(fv);
584 if (fv->bom) {
585 FLogOutputBOM(fv);
586 }
587 if (ts.DeferredLogWriteMode) {
588 StartThread(fv);
589 }
590
591 logfile_unlock();
592 }
593
594 static wchar_t *TimeStampStr(PFileVar fv)
595 {
596 char *strtime = NULL;
597 switch (ts.LogTimestampType) {
598 case TIMESTAMP_LOCAL:
599 default:
600 strtime = mctimelocal(ts.LogTimestampFormat, FALSE);
601 break;
602 case TIMESTAMP_UTC:
603 strtime = mctimelocal(ts.LogTimestampFormat, TRUE);
604 break;
605 case TIMESTAMP_ELAPSED_LOGSTART:
606 strtime = strelapsed(fv->StartTime);
607 break;
608 case TIMESTAMP_ELAPSED_CONNECTED:
609 strtime = strelapsed(cv.ConnectedTime);
610 break;
611 }
612
613 char tmp[128];
614 tmp[0] = 0;
615 strncat_s(tmp, sizeof(tmp), "[", _TRUNCATE);
616 strncat_s(tmp, sizeof(tmp), strtime, _TRUNCATE);
617 strncat_s(tmp, sizeof(tmp), "] ", _TRUNCATE);
618 free(strtime);
619
620 return ToWcharA(tmp);
621 }
622
623 /**
624 * �o�b�t�@�������O���t�@�C������������
625 */
626 static void LogToFile(PFileVar fv)
627 {
628 PCHAR Buf;
629 int Start, Count;
630 BYTE b;
631
632 if (fv->FileLog)
633 {
634 Buf = cv_LogBuf;
635 Start = cv_LStart;
636 Count = cv_LCount;
637 }
638 else if (fv->BinLog)
639 {
640 Buf = cv_BinBuf;
641 Start = cv_BStart;
642 Count = cv_BCount;
643 }
644 else
645 return;
646
647 if (Buf==NULL) return;
648 if (Count==0) return;
649
650 // ���b�N������(2004.8.6 yutaka)
651 logfile_lock();
652
653 // ���������f�[�^����������
654 DWORD WriteBufMax = 8192;
655 DWORD WriteBufLen = 0;
656 PCHAR WriteBuf = (PCHAR)malloc(WriteBufMax);
657 while (Get1(Buf,&Start,&Count,&b)) {
658 if (FLogIsPause() || ProtoGetProtoFlag()) {
659 continue;
660 }
661
662 if (WriteBufLen >= (WriteBufMax*4/5)) {
663 WriteBufMax *= 2;
664 WriteBuf = (PCHAR)realloc(WriteBuf, WriteBufMax);
665 }
666
667 WriteBuf[WriteBufLen++] = b;
668
669 (fv->ByteCount)++;
670 }
671
672 // ��������
673 if (WriteBufLen > 0) {
674 if (ts.DeferredLogWriteMode) {
675 PostThreadMessage(fv->LogThreadId, WM_DPC_LOGTHREAD_SEND, (WPARAM)WriteBuf, WriteBufLen);
676 }
677 else {
678 DWORD wrote;
679 WriteFile(fv->FileHandle, WriteBuf, WriteBufLen, &wrote, NULL);
680 free(WriteBuf);
681 }
682 }
683
684 logfile_unlock();
685
686 if (fv->FileLog)
687 {
688 cv_LStart = Start;
689 cv_LCount = Count;
690 }
691 else {
692 cv_BStart = Start;
693 cv_BCount = Count;
694 }
695 if (FLogIsPause() || ProtoGetProtoFlag()) return;
696 fv->FLogDlg->RefreshNum(fv->StartTime, fv->FileSize, fv->ByteCount);
697
698
699 // ���O�E���[�e�[�g
700 LogRotate(fv);
701 }
702
703 static BOOL CreateLogBuf(void)
704 {
705 if (cv_LogBuf==NULL)
706 {
707 cv_LogBuf = (char *)malloc(InBuffSize);
708 cv_LogPtr = 0;
709 cv_LStart = 0;
710 cv_LCount = 0;
711 }
712 return (cv_LogBuf!=NULL);
713 }
714
715 static void FreeLogBuf(void)
716 {
717 free(cv_LogBuf);
718 cv_LogBuf = NULL;
719 cv_LogPtr = 0;
720 cv_LStart = 0;
721 cv_LCount = 0;
722 }
723
724 static BOOL CreateBinBuf(void)
725 {
726 if (cv_BinBuf==NULL)
727 {
728 cv_BinBuf = (PCHAR)malloc(InBuffSize);
729 cv_BinPtr = 0;
730 cv_BStart = 0;
731 cv_BCount = 0;
732 }
733 return (cv_BinBuf!=NULL);
734 }
735
736 static void FreeBinBuf(void)
737 {
738 free(cv_BinBuf);
739 cv_BinBuf = NULL;
740 cv_BinPtr = 0;
741 cv_BStart = 0;
742 cv_BCount = 0;
743 }
744
745 static void FileTransEnd_(PFileVar fv)
746 {
747 fv->FileLog = FALSE;
748 fv->BinLog = FALSE;
749 cv.Log1Byte = NULL;
750 cv.Log1Bin = NULL;
751 cv.LogBinSkip = NULL;
752 PFileTransDlg FLogDlg = fv->FLogDlg;
753 if (FLogDlg != NULL) {
754 FLogDlg->DestroyWindow();
755 FLogDlg = NULL;
756 fv->FLogDlg = NULL;
757 }
758 CloseFileSync(fv);
759 FreeLogBuf();
760 FreeBinBuf();
761 free(fv->FullName);
762 fv->FullName = NULL;
763 free(fv);
764
765 LogVar = NULL;
766 }
767
768 /**
769 * ���O���|�[�Y����
770 */
771 void FLogPause(BOOL Pause)
772 {
773 PFileVar fv = LogVar;
774 if (fv == NULL) {
775 return;
776 }
777 fv->IsPause = Pause;
778 fv->FLogDlg->ChangeButton(Pause);
779 }
780
781 /**
782 * ���O���[�e�[�g������
783 * ���O���T�C�Y��<size>�o�C�g���������������A���[�e�[�V��������������������
784 */
785 void FLogRotateSize(size_t size)
786 {
787 PFileVar fv = LogVar;
788 if (fv == NULL) {
789 return;
790 }
791 fv->RotateMode = ROTATE_SIZE;
792 fv->RotateSize = (LONG)size;
793 }
794
795 /**
796 * ���O���[�e�[�g������
797 * ���O�t�@�C������������������
798 */
799 void FLogRotateRotate(int step)
800 {
801 PFileVar fv = LogVar;
802 if (fv == NULL) {
803 return;
804 }
805 fv->RotateStep = step;
806 }
807
808 /**
809 * ���O���[�e�[�g������
810 * ���[�e�[�V���������~
811 */
812 void FLogRotateHalt(void)
813 {
814 PFileVar fv = LogVar;
815 if (fv == NULL) {
816 return;
817 }
818 fv->RotateMode = ROTATE_NONE;
819 fv->RotateSize = 0;
820 fv->RotateStep = 0;
821 }
822
823 static INT_PTR CALLBACK OnCommentDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM)
824 {
825 static const DlgTextInfo TextInfos[] = {
826 { 0, "DLG_COMMENT_TITLE" },
827 { IDOK, "BTN_OK" }
828 };
829
830 switch (msg) {
831 case WM_INITDIALOG:
832 // �G�f�B�b�g�R���g���[�����t�H�[�J�X��������
833 SetFocus(GetDlgItem(hDlgWnd, IDC_EDIT_COMMENT));
834 SetDlgTextsW(hDlgWnd, TextInfos, _countof(TextInfos), ts.UILanguageFileW);
835 return FALSE;
836
837 case WM_COMMAND:
838 switch (LOWORD(wp)) {
839 case IDOK: {
840 size_t len = SendDlgItemMessageW(hDlgWnd, IDC_EDIT_COMMENT, WM_GETTEXTLENGTH, 0, 0);
841 len += 1;
842 wchar_t *buf = (wchar_t *)malloc(len * sizeof(wchar_t));
843 GetDlgItemTextW(hDlgWnd, IDC_EDIT_COMMENT, buf, (int)len);
844 FLogWriteStr(buf);
845 FLogWriteStr(L"\n"); // TODO ���s�R�[�h
846 free(buf);
847 TTEndDialog(hDlgWnd, IDOK);
848 break;
849 }
850 default:
851 return FALSE;
852 }
853 break;
854
855 case WM_CLOSE:
856 TTEndDialog(hDlgWnd, 0);
857 return TRUE;
858
859 default:
860 return FALSE;
861 }
862 return TRUE;
863 }
864
865 /**
866 * ���O�t�@�C�����R�����g���������� (2004.8.6 yutaka)
867 */
868 void FLogAddCommentDlg(HINSTANCE hInst, HWND hWnd)
869 {
870 PFileVar fv = LogVar;
871 if (fv == NULL) {
872 return;
873 }
874 TTDialogBox(hInst, MAKEINTRESOURCE(IDD_COMMENT_DIALOG),
875 hWnd, OnCommentDlgProc);
876 }
877
878 void FLogClose(void)
879 {
880 PFileVar fv = LogVar;
881 if (fv == NULL) {
882 return;
883 }
884
885 FileTransEnd_(fv);
886 }
887
888 /**
889 * ���O���I�[�v������
890 * @param[in] fname ���O�t�@�C����, CreateFile()���n������
891 *
892 * ���O�t�@�C������strftime���W�J�������s���������B
893 * FLogGetLogFilename() �� FLogOpenDialog() ��
894 * �t�@�C�����������������B
895 */
896 BOOL FLogOpen(const wchar_t *fname, LogCode_t code, BOOL bom)
897 {
898 if (LogVar != NULL) {
899 return FALSE;
900 }
901
902 //
903 PFileVar fv = (PFileVar)malloc(sizeof(*fv));
904 if (fv == NULL) {
905 return FALSE;
906 }
907 LogVar = fv;
908 memset(fv, 0, sizeof(TFileVar));
909 fv->FileHandle = INVALID_HANDLE_VALUE;
910 fv->LogThread = INVALID_HANDLE_VALUE;
911 fv->eLineEnd = Line_LineHead;
912
913 fv->log_code = code;
914 fv->bom = bom;
915 BOOL ret = LogStart(fv, fname);
916 if (ret == FALSE) {
917 FileTransEnd_(fv);
918 }
919
920 return ret;
921 }
922
923 BOOL FLogIsOpend(void)
924 {
925 return LogVar != NULL;
926 }
927
928 BOOL FLogIsOpendText(void)
929 {
930 return LogVar != NULL && LogVar->FileLog;
931 }
932
933 BOOL FLogIsOpendBin(void)
934 {
935 return LogVar != NULL && LogVar->BinLog;
936 }
937
938 void FLogWriteStr(const wchar_t *str)
939 {
940 if (LogVar != NULL) {
941 OutputStr(str);
942 }
943 }
944
945 void FLogInfo(char *param_ptr, size_t param_len)
946 {
947 PFileVar fv = LogVar;
948 if (fv) {
949 param_ptr[0] = '0'
950 + (ts.LogBinary != 0)
951 + ((ts.Append != 0) << 1)
952 + ((ts.LogTypePlainText != 0) << 2)
953 + ((ts.LogTimestamp != 0) << 3)
954 + ((ts.LogHideDialog != 0) << 4);
955 char *filenameU8 = ToU8W(fv->FullName);
956 strncpy_s(param_ptr + 1, param_len - 1, filenameU8, _TRUNCATE);
957 free(filenameU8);
958 }
959 else {
960 param_ptr[0] = '0' - 1;
961 param_ptr[1] = 0;
962 }
963 }
964
965 /**
966 * ���������O�t�@�C����������
967 */
968 const wchar_t *FLogGetFilename(void)
969 {
970 if (LogVar == NULL) {
971 return NULL;
972 }
973 return LogVar->FullName;
974 }
975
976 /**
977 * ���O�t�@�C�����p���C�����s��,�t�@�C������������
978 * - strftime() ���������t�W�J
979 * - �������������O�t�@�C���t�H���_������
980 * - �z�X�g��,�|�[�g�����W�J
981 *
982 * @param filename �t�@�C����(�p�X����������)
983 * @return �C�������t�@�C����
984 */
985 wchar_t *FLogGetLogFilenameBase(const wchar_t *filename)
986 {
987 // �t�@�C�������������o
988 const wchar_t *last_path_sep = wcsrchr(filename, L'\\');
989 wchar_t *format;
990 if (last_path_sep == NULL) {
991 format = _wcsdup(filename);
992 }
993 else {
994 format = _wcsdup(last_path_sep + 1);
995 }
996
997 // strftime ���g�p������������������
998 deleteInvalidStrftimeCharW(format);
999
1000 // ����������0��������?
1001 if (format[0] == 0) {
1002 free(format);
1003 return _wcsdup(L"");
1004 }
1005
1006 // ��������������
1007 time_t time_local;
1008 time(&time_local);
1009 struct tm tm_local;
1010 localtime_s(&tm_local, &time_local);
1011
1012 // strftime()������
1013 // ���������������g��
1014 size_t len = 32;
1015 wchar_t *formated = NULL;
1016 while (1) {
1017 wchar_t *formated_realloc = (wchar_t *)realloc(formated, sizeof(wchar_t) * len);
1018 if (formated_realloc == NULL) {
1019 free(format);
1020 free(formated);
1021 return _wcsdup(L"");
1022 }
1023 formated = formated_realloc;
1024 size_t r = wcsftime(formated, len, format, &tm_local);
1025 if (r != 0) {
1026 // �t�H�[�}�b�g������
1027 break;
1028 }
1029 len *= 2;
1030 }
1031 free(format);
1032
1033 // �z�X�g������
1034 wchar_t *host = ConvertLognameW(&cv, formated);
1035 free(formated);
1036
1037 // �t�@�C�������g�p���������������u��
1038 //wchar_t *replaced = replaceInvalidFileNameCharW(host, 0); // ����
1039 wchar_t *replaced = replaceInvalidFileNameCharW(host, L'_');
1040 free(host);
1041
1042 return replaced;
1043 }
1044
1045 /**
1046 * ���O�t�@�C����������
1047 * ���O�t�@�C�����p���C�����s��
1048 * - strftime() ���������t�W�J
1049 * - �������������O�t�@�C���t�H���_������
1050 * - �z�X�g��,�|�[�g�����W�J
1051 *
1052 * @param[in] log_filename �t�@�C����(����/��������������ok)
1053 * NULL�������f�t�H���g�t�@�C����������
1054 * strftime�`��ok
1055 * @return �t���p�X�t�@�C����
1056 * �s�v���������� free() ��������
1057 */
1058 wchar_t *FLogGetLogFilename(const wchar_t *log_filename)
1059 {
1060 wchar_t *dir;
1061 wchar_t *fname;
1062 if (log_filename == NULL) {
1063 dir = _wcsdup(ts.LogDefaultPathW);
1064 fname = _wcsdup(ts.LogDefaultNameW);
1065 } else if (!IsRelativePathW(log_filename)) {
1066 // �����p�X������������
1067 dir = ExtractDirNameW(log_filename);
1068 fname = ExtractFileNameW(log_filename);
1069 }
1070 else {
1071 dir = _wcsdup(ts.LogDefaultPathW);
1072 fname = _wcsdup(log_filename);
1073 }
1074
1075 wchar_t *formated = FLogGetLogFilenameBase(fname);
1076 free(fname);
1077
1078 // �A������
1079 wchar_t *logfull = NULL;
1080 awcscats(&logfull, dir, L"\\", formated, NULL);
1081 free(formated);
1082 free(dir);
1083
1084 // ���K��
1085 wchar_t *normal;
1086 hGetFullPathNameW(logfull, &normal, NULL);
1087 free(logfull);
1088
1089 return normal;
1090 }
1091
1092 BOOL FLogIsPause()
1093 {
1094 if (LogVar == NULL) {
1095 return FALSE;
1096 }
1097 return LogVar->IsPause;
1098 }
1099
1100 void FLogWindow(int nCmdShow)
1101 {
1102 if (LogVar == NULL) {
1103 return;
1104 }
1105
1106 HWND HWndLog = LogVar->FLogDlg->m_hWnd;
1107 ShowWindow(HWndLog, nCmdShow);
1108 if (nCmdShow == SW_RESTORE) {
1109 // �g���X�^�C�� WS_EX_NOACTIVATE ��������������
1110 SetForegroundWindow(HWndLog);
1111 }
1112 }
1113
1114 void FLogShowDlg(void)
1115 {
1116 if (LogVar == NULL) {
1117 return;
1118 }
1119 HWND HWndLog = LogVar->FLogDlg->m_hWnd;
1120 ShowWindow(HWndLog, SW_SHOWNORMAL);
1121 SetForegroundWindow(HWndLog);
1122 }
1123
1124 /**
1125 * ���O��1byte��������
1126 * LogPut1() ������?
1127 */
1128 //void Log1Bin(PComVar cv, BYTE b)
1129 static void Log1Bin(BYTE b)
1130 {
1131 if (LogVar->IsPause || ProtoGetProtoFlag()) {
1132 return;
1133 }
1134 if (cv_BinSkip > 0) {
1135 cv_BinSkip--;
1136 return;
1137 }
1138 cv_BinBuf[cv_BinPtr] = b;
1139 cv_BinPtr++;
1140 if (cv_BinPtr>=InBuffSize) {
1141 cv_BinPtr = cv_BinPtr-InBuffSize;
1142 }
1143 if (cv_BCount>=InBuffSize) {
1144 cv_BCount = InBuffSize;
1145 cv_BStart = cv_BinPtr;
1146 }
1147 else {
1148 cv_BCount++;
1149 }
1150 }
1151
1152 static void LogBinSkip(int add)
1153 {
1154 if (cv_BinBuf != NULL) {
1155 cv_BinSkip += add;
1156 }
1157 }
1158
1159 /**
1160 * ���O�o�b�t�@���������������f�[�^���o�C�g��������
1161 */
1162 int FLogGetCount(void)
1163 {
1164 PFileVar fv = LogVar;
1165 if (fv == NULL) {
1166 return 0;
1167 }
1168 if (fv->FileLog) {
1169 return cv_LCount;
1170 }
1171 if (fv->BinLog) {
1172 return cv_BCount;
1173 }
1174 return 0;
1175 }
1176
1177 /**
1178 * ���O�o�b�t�@�������o�C�g��������
1179 */
1180 int FLogGetFreeCount(void)
1181 {
1182 PFileVar fv = LogVar;
1183 if (fv == NULL) {
1184 return 0;
1185 }
1186 if (fv->FileLog) {
1187 return InBuffSize - cv_LCount;
1188 }
1189 if (fv->BinLog) {
1190 return InBuffSize - cv_BCount;
1191 }
1192 return 0;
1193 }
1194
1195 /**
1196 * �o�b�t�@�������O���t�@�C������������
1197 */
1198 void FLogWriteFile(void)
1199 {
1200 PFileVar fv = LogVar;
1201 if (fv == NULL) {
1202 return;
1203 }
1204 if (cv_LogBuf!=NULL)
1205 {
1206 if (fv->FileLog) {
1207 LogToFile(fv);
1208 }
1209 }
1210
1211 if (cv_BinBuf!=NULL)
1212 {
1213 if (fv->BinLog) {
1214 LogToFile(fv);
1215 }
1216 }
1217 }
1218
1219 void FLogPutUTF32(unsigned int u32)
1220 {
1221 PFileVar fv = LogVar;
1222 BOOL log_available = (cv_LogBuf != 0);
1223
1224 if (!log_available) {
1225 // ���O�����o��������
1226 return;
1227 }
1228
1229 // �s����?(���s���o����������)
1230 if (ts.LogTimestamp && fv->eLineEnd) {
1231 // �^�C���X�^���v���o��
1232 fv->eLineEnd = Line_Other; /* clear endmark*/
1233 wchar_t* strtime = TimeStampStr(fv);
1234 FLogWriteStr(strtime);
1235 free(strtime);
1236 }
1237
1238 switch(fv->log_code) {
1239 case LOG_UTF8: {
1240 // UTF-8
1241 char u8_buf[4];
1242 size_t u8_len = UTF32ToUTF8(u32, u8_buf, _countof(u8_buf));
1243 for (size_t i = 0; i < u8_len; i++) {
1244 BYTE b = u8_buf[i];
1245 LogPut1(b);
1246 }
1247 break;
1248 }
1249 case LOG_UTF16LE:
1250 case LOG_UTF16BE: {
1251 // UTF-16
1252 wchar_t u16[2];
1253 size_t u16_len = UTF32ToUTF16(u32, u16, _countof(u16));
1254 for (size_t i = 0; i < u16_len; i++) {
1255 if (fv->log_code == LOG_UTF16LE) {
1256 // UTF-16LE
1257 LogPut1(u16[i] & 0xff);
1258 LogPut1((u16[i] >> 8) & 0xff);
1259 }
1260 else {
1261 // UTF-16BE
1262 LogPut1((u16[i] >> 8) & 0xff);
1263 LogPut1(u16[i] & 0xff);
1264 }
1265 }
1266 }
1267 }
1268
1269 if (u32 == 0x0a) {
1270 fv->eLineEnd = Line_LineHead; /* set endmark*/
1271 }
1272 }
1273
1274 static void FLogOutputBOM(PFileVar fv)
1275 {
1276 DWORD wrote;
1277
1278 switch(fv->log_code) {
1279 case 0: {
1280 // UTF-8
1281 const char *bom = "\xef\xbb\xbf";
1282 WriteFile(fv->FileHandle, bom, 3, &wrote, NULL);
1283 fv->ByteCount += 3;
1284 break;
1285 }
1286 case 1: {
1287 // UTF-16LE
1288 const char *bom = "\xff\xfe";
1289 WriteFile(fv->FileHandle, bom, 2, &wrote, NULL);
1290 fv->ByteCount += 2;
1291 break;
1292 }
1293 case 2: {
1294 // UTF-16BE
1295 const char *bom = "\xfe\xff";
1296 WriteFile(fv->FileHandle, bom, 2, &wrote, NULL);
1297 fv->ByteCount += 2;
1298 break;
1299 }
1300 default:
1301 break;
1302 }
1303 }
1304
1305 static void OutputStr(const wchar_t *str)
1306 {
1307 size_t len;
1308
1309 assert(str != NULL);
1310
1311 len = wcslen(str);
1312 while(*str != 0) {
1313 unsigned int u32;
1314 size_t u16_len = UTF16ToUTF32(str, len, &u32);
1315 switch (u16_len) {
1316 case 0:
1317 default:
1318 // ������������
1319 str++;
1320 len--;
1321 break;
1322 case 1:
1323 case 2: {
1324 FLogPutUTF32(u32);
1325 str += u16_len;
1326 len -= u16_len;
1327 break;
1328 }
1329 }
1330 }
1331 }

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