| 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 |
} |