Revision: 10960 https://osdn.net/projects/ttssh2/scm/svn/commits/10960 Author: zmatsuo Date: 2023-10-08 02:40:35 +0900 (Sun, 08 Oct 2023) Log Message: ----------- SCP受信時、受信したデータが随時書き込まれない場合があるので修正 - SCP 受信したデータが随時書き込まれない (GitHub #15) Ticket #34056 Ticket Links: ------------ https://osdn.net/projects/ttssh2/tracker/detail/15 https://osdn.net/projects/ttssh2/tracker/detail/34056 Modified Paths: -------------- trunk/ttssh2/ttxssh/pkt.c trunk/ttssh2/ttxssh/ssh.c trunk/ttssh2/ttxssh/ssh.h trunk/ttssh2/ttxssh/ttxssh.h -------------- next part -------------- Modified: trunk/ttssh2/ttxssh/pkt.c =================================================================== --- trunk/ttssh2/ttxssh/pkt.c 2023-10-07 17:40:26 UTC (rev 10959) +++ trunk/ttssh2/ttxssh/pkt.c 2023-10-07 17:40:35 UTC (rev 10960) @@ -319,7 +319,7 @@ int amount_read; // SCP\x83t\x83@\x83C\x83\x8B\x8E\xF3\x90M\x8F\x88\x97\x9D\x82\xF0\x88ꎞ\x92\xE2\x8E~\x92\x86\x82Ȃ\xE7\x82Arecv()\x82\xF0\x82\xB5\x82Ȃ\xA2\x81B - if (pvar->recv_suspended) { + if (pvar->recv.suspended) { // \x82\xBB\x82\xEA\x82܂łɎ\xF3\x90M\x82\xB5\x82\xBD\x83f\x81[\x83^\x83T\x83C\x83Y\x82\xF0Tera Term\x91\xA4\x82ɕԂ\xB7\x81B return amount_in_buf; Modified: trunk/ttssh2/ttxssh/ssh.c =================================================================== --- trunk/ttssh2/ttxssh/ssh.c 2023-10-07 17:40:26 UTC (rev 10959) +++ trunk/ttssh2/ttxssh/ssh.c 2023-10-07 17:40:35 UTC (rev 10960) @@ -327,7 +327,6 @@ { bufchain_t *ch, *ptr; enum scp_state prev_state; - PTInstVar pvar; ch = c->bufchain; while (ch) { @@ -371,12 +370,12 @@ // SCP\x8E\xF3\x90M\x82̏ꍇ\x82̂݁ASCP\x97p\x83\x8A\x83X\x83g\x82̊J\x95\xFA\x82\xF0\x8Ds\x82\xA4\x81B // Windows9x\x82ŗ\x8E\x82\xBF\x82\xE9\x96\xE2\x91\xE8\x82\xF0\x8FC\x90\xB3\x82\xB5\x82\xBD\x81B - if (c->scp.dir == FROMREMOTE) - ssh2_scp_free_packetlist(c); + if (c->scp.dir == FROMREMOTE) { + PTInstVar pvar = c->scp.pvar; + ssh2_scp_free_packetlist(pvar, c); + } g_scp_sending = FALSE; - pvar = c->scp.pvar; - ssh2_scp_free_packetlist(pvar, c); } if (c->type == TYPE_AGENT) { buffer_free(c->agent_msg); @@ -8104,10 +8103,6 @@ { scp_dlg_parm_t *parm = (scp_dlg_parm_t *)wp; - // SCP\x82̎\xF3\x90M\x8F\x88\x97\x9D\x82𒆒f\x82\xB5\x82\xBD\x8Fꍇ\x82ɂ\xE0\x81Arecv()\x82̃u\x83\x8D\x83b\x83N\x82\xF0\x89\xF0\x8F\x9C\x82\xB7\x82\xE9\x81B - // \x82\xB1\x82\xEA\x82\xF0\x82\xE2\x82\xE7\x82Ȃ\xA2\x82ƁATera Term\x82\xAA\x8Cł܂\xC1\x82\xBD\x82܂܂ɂȂ\xC1\x82Ă\xB5\x82܂\xA4\x81B - ssh2_scp_recv_unblocked(parm->pvar); - ssh2_channel_send_close(parm->pvar, parm->c); } return TRUE; @@ -8484,7 +8479,6 @@ c->scp.state = SCP_CLOSING; ShowWindow(c->scp.progress_window, SW_HIDE); -cancel_abort: // \x83`\x83\x83\x83l\x83\x8B\x82̃N\x83\x8D\x81[\x83Y\x82\xF0\x8Ds\x82\xA2\x82\xBD\x82\xA2\x82\xAA\x81A\x92\xBC\x90\xDA ssh2_channel_send_close() \x82\xF0\x8CĂяo\x82\xB7\x82ƁA // \x93\x96\x8AY\x8A\x94\x82\xAA\x83X\x83\x8C\x83b\x83h\x83Z\x81[\x83t\x82ł͂Ȃ\xA2\x82\xBD\x82߁ASCP\x8F\x88\x97\x9D\x82\xAA\x90\xB3\x8F\xED\x82ɏI\x97\xB9\x82\xB5\x82Ȃ\xA2\x8Fꍇ\x82\xAA\x82\xA0\x82\xE9\x81B // (2011.6.1 yutaka) @@ -8491,20 +8485,37 @@ parm.c = c; parm.pvar = pvar; SendMessage(hWnd, WM_CHANNEL_CLOSE, (WPARAM)&parm, 0); + return 0; +cancel_abort: + pvar->recv.close_request = TRUE; return 0; } -// SCP\x83t\x83@\x83C\x83\x8B\x8E\xF3\x90M\x8F\x88\x97\x9D\x92\x86\x82\xC9 recv \x82\xF0\x83u\x83\x8D\x83b\x83N\x82\xB5\x82Ă\xA2\x82\xE9\x8Fꍇ\x82́A\x83u\x83\x8D\x83b\x83N\x82\xF0\x89\xF0\x8F\x9C\x82\xB7\x82\xE9\x81B -static void ssh2_scp_recv_unblocked(PTInstVar pvar) +// do_SSH2_adjust_window_size() \x82\xF0\x82\xA0\x82\xE9\x92\xF6\x93x\x8E\x9E\x8AԂ\xAA\x8Co\x89߂\xB5\x82Ă\xA9\x82\xE7\x83R\x81[\x83\x8B\x82\xB7\x82\xE9 +// \x83t\x83\x8D\x81[\x90\xA7\x8C\xE4\x81A\x8E\xF3\x90M\x8F\x88\x97\x9D\x82\xF0\x8DĊJ +static void CALLBACK do_SSH2_adjust_window_size_timer( + HWND hWnd, UINT uMsg, UINT_PTR nIDEvent, DWORD dwTime) { - // \x83u\x83\x8D\x83b\x83N\x82\xB5\x82Ă\xA2\x82\xE9\x8Fꍇ - if (pvar->recv_suspended) { - // recv()\x82̃u\x83\x8D\x83b\x83N\x82\xF0\x89\xF0\x8F\x9C\x82\xB7\x82\xE9\x81B - pvar->recv_suspended = FALSE; - // FD_READ\x83\x81\x83b\x83Z\x81[\x83W\x82𓊂\xB0\x82\xC4 recv() \x82̍ĊJ\x82𑣂\xB7\x81B - PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY, pvar->socket, MAKELPARAM(FD_READ, 0)); + (void)hWnd; + (void)uMsg; + (void)dwTime; + Channel_t *c = (Channel_t *)nIDEvent; + PTInstVar pvar = c->scp.pvar; + + if (pvar->recv.data_finished) { + // \x91\x97\x90M\x8FI\x97\xB9\x82\xB5\x82\xBD\x82̂Ƀ\x81\x83b\x83Z\x81[\x83W\x82\xAA\x8Ec\x82\xC1\x82Ă\xA2\x82\xBD\x8E\x9E\x91\xF4 + return; } + if (pvar->recv.timer_id != 0) { + // SetTimer() \x82̓C\x83\x93\x83^\x81[\x83o\x83\x8B\x82ɔ\xAD\x90\xB6\x82\xB7\x82\xE9\x82̂ō폜\x82\xB7\x82\xE9 + KillTimer(pvar->cv->HWin, pvar->recv.timer_id); + pvar->recv.timer_id = 0; + } + + logprintf(LOG_LEVEL_NOTICE, "%s: SCP receive, send SSH_MSG_CHANNEL_WINDOW_ADJUST", __FUNCTION__); + pvar->recv.suspended = FALSE; + do_SSH2_adjust_window_size(pvar, c); } // SSH\x83T\x81[\x83o\x82\xA9\x82瑗\x82\xE7\x82\xEA\x82Ă\xAB\x82\xBD\x83t\x83@\x83C\x83\x8B\x82̃f\x81[\x83^\x82\xF0\x83\x8A\x83X\x83g\x82ɂȂ\xAE\x81B @@ -8544,13 +8555,15 @@ // \x82\xB1\x82̃t\x83\x89\x83O\x82𗧂Ă\xBD\x8Fꍇ\x81ASSH\x92ʐM\x91S\x91̂\xCCrecv()\x82\xF0\x83u\x83\x8D\x83b\x83N\x82\xB7\x82邽\x82߁A // SCP\x8F\x88\x97\x9D\x82\xAA\x8A\xAE\x97\xB9 or \x92\x86\x92f\x82\xB3\x82ꂽ\x8Fꍇ\x82́A\x82\xA9\x82Ȃ炸\x83t\x83\x89\x83O\x82𗎂Ƃ\xB5\x82Ă\xA8\x82\xAD // \x95K\x97v\x82\xAA\x82\xA0\x82\xE9\x81B - pvar->recv_suspended = TRUE; + logprintf(LOG_LEVEL_NOTICE, + "%s: enter suspend", __FUNCTION__); + pvar->recv.suspended = TRUE; } logprintf(LOG_LEVEL_NOTICE, - "%s: channel=#%d SCP recv %lu(bytes) and enqueued.(%s)", + "%s: channel=#%d SCP recv %lu(bytes) and enqueued.%s", __FUNCTION__, c->local_num, c->scp.pktlist_cursize, - pvar->recv_suspended ? "recv suspended" : "recv resumed" + pvar->recv.suspended ? "(suspended)" : "" ); error:; @@ -8586,14 +8599,23 @@ // \x83L\x83\x85\x81[\x82ɋl\x82f\x81[\x83^\x82̑\x8D\x83T\x83C\x83Y\x82\xAA\x89\xBA\x8C\xC0臒l\x82\xF0\x89\xBA\x89\xF1\x82\xC1\x82\xBD\x8Fꍇ\x81A // SSH\x83T\x81[\x83o\x82\xA9\x82\xE7\x82̎\xF3\x90M\x82\xF0\x8DĊJ\x82\xB7\x82\xE9\x82悤\x82Ɏw\x8E\xA6\x82\xF0\x8Fo\x82\xB7\x81B if (c->scp.pktlist_cursize <= SCPRCV_LOW_WATER_MARK) { - // recv()\x82̃u\x83\x8D\x83b\x83N\x82\xF0\x89\xF0\x8F\x9C\x82\xB7\x82\xE9\x81B - ssh2_scp_recv_unblocked(pvar); + logprintf(LOG_LEVEL_NOTICE, "%s: SCP receive resumed", __FUNCTION__); + // \x83u\x83\x8D\x83b\x83N\x82\xB5\x82Ă\xA2\x82\xE9\x8Fꍇ + if (pvar->recv.suspended) { + // SCP\x8E\xF3\x90M\x82̃u\x83\x8D\x83b\x83N\x82\xF0\x89\xF0\x8F\x9C\x82\xB7\x82\xE9\x81B + pvar->recv.suspended = FALSE; + if (c->scp.filercvsize < c->scp.filetotalsize) { + // \x91\xB1\x82\xAB\x82\xF0\x8E\xF3\x90M + pvar->recv.timer_id = + SetTimer(pvar->cv->HWin, (UINT_PTR)c, USER_TIMER_MINIMUM, do_SSH2_adjust_window_size_timer); + } + } } logprintf(LOG_LEVEL_NOTICE, - "%s: channel=#%d SCP recv %lu(bytes) and dequeued.(%s)", + "%s: channel=#%d SCP recv %lu(bytes) and dequeued.%s", __FUNCTION__, c->local_num, c->scp.pktlist_cursize, - pvar->recv_suspended ? "recv suspended" : "recv resumed" + pvar->recv.suspended ? "(suspended)" : "" ); end:; @@ -8606,7 +8628,9 @@ c->scp.pktlist_tail = NULL; InitializeCriticalSection(&g_ssh_scp_lock); c->scp.pktlist_cursize = 0; - pvar->recv_suspended = FALSE; + pvar->recv.suspended = FALSE; + pvar->recv.timer_id = 0; + pvar->recv.close_request = FALSE; } static void ssh2_scp_free_packetlist(PTInstVar pvar, Channel_t *c) @@ -8626,19 +8650,12 @@ c->scp.pktlist_tail = NULL; DeleteCriticalSection(&g_ssh_scp_lock); c->scp.pktlist_cursize = 0; - pvar->recv_suspended = FALSE; + pvar->recv.suspended = FALSE; + pvar->recv.data_finished = FALSE; } static BOOL SSH2_scp_fromremote(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen) { - int permission; - long long size; - char filename[MAX_PATH]; - char ch; - HWND hDlgWnd; - char msg[256]; - int copylen; - if (buflen == 0) return FALSE; @@ -8660,14 +8677,22 @@ goto reply; } else if (data[0] == 'C') { // C0666 size file + HWND hDlgWnd; HANDLE thread; unsigned int tid; + int permission; + long long size; + char filename[MAX_PATH]; sscanf_s(data, "C%o %lld %s", &permission, &size, filename, (unsigned int)sizeof(filename)); + logprintf(LOG_LEVEL_NOTICE, "%s: SCP '%s', size=%lld, perm=0x%08x", + __FUNCTION__, + filename, size, permission); // Windows\x82Ȃ̂Ńp\x81[\x83~\x83b\x83V\x83\x87\x83\x93\x82͖\xB3\x8E\x8B\x81B\x83T\x83C\x83Y\x82̂L\x98^\x81B c->scp.filetotalsize = size; c->scp.filercvsize = 0; + c->scp.recv.received_size = 0; c->scp.state = SCP_DATA; @@ -8703,6 +8728,9 @@ } else { // \x83T\x81[\x83o\x82\xA9\x82\xE7\x82̃f\x81[\x83^\x82\xAA\x95s\x92\xE8\x82̏ꍇ\x82́A\x83G\x83\x89\x81[\x95\\x8E\xA6\x82\xF0\x8Ds\x82\xA4\x81B // (2014.7.13 yutaka) + char msg[256]; + int copylen; + copylen = min(buflen, sizeof(msg)); memcpy(msg, data, copylen); msg[copylen - 1] = 0; @@ -8713,16 +8741,60 @@ } } else if (c->scp.state == SCP_DATA) { // payload\x82̎\xF3\x90M - unsigned char *newdata = malloc(buflen); - if (newdata != NULL) { - memcpy(newdata, data, buflen); + logprintf(LOG_LEVEL_VERBOSE, "%s: SCP_DATA size=%lld", + __FUNCTION__, + buflen); + if (pvar->recv.close_request) { + // \x83L\x83\x83\x83\x93\x83Z\x83\x8B\x83{\x83^\x83\x93\x82\xF0\x89\x9F\x82\xB3\x82ꂽ + ssh2_channel_send_close(pvar, c); + } + else { + unsigned char *newdata = malloc(buflen); + if (newdata != NULL) { + memcpy(newdata, data, buflen); - // SCP\x8E\xF3\x90M\x8F\x88\x97\x9D\x82̃X\x83s\x81[\x83h\x82\xAA\x91\xAC\x82\xA2\x8Fꍇ\x81A\x83X\x83\x8C\x83b\x83h\x82̃\x81\x83b\x83Z\x81[\x83W\x83L\x83\x85\x81[\x82\xAA\x83t\x83\x8B(10000\x8C\xC2)\x82\xC9 - // \x82Ȃ\xE8\x81A\x82\xA9\x82X\x83\x8C\x83b\x83h\x8F\xE3\x82ł\xCC SendMessage \x82\xAA\x83u\x83\x8D\x83b\x83N\x82\xB7\x82邱\x82Ƃɂ\xE6\x82\xE8\x81ATera Term(TTSSH) - // \x8E\xA9\x91̂\xAA\x83X\x83g\x81[\x83\x8B\x82\xB5\x82Ă\xB5\x82܂\xA4\x81B\x82\xB1\x82̖\xE2\x91\xE8\x82\xF0\x89\xF1\x94\xF0\x82\xB7\x82邽\x82߁A\x83X\x83\x8C\x83b\x83h\x82̃\x81\x83b\x83Z\x81[\x83W\x83L\x83\x85\x81[\x82\xF0 - // \x8Eg\x82\xA4\x82̂\xF0\x82\xE2\x82߂āA\x83\x8A\x83\x93\x83N\x83h\x83\x8A\x83X\x83g\x95\xFB\x8E\xAE\x82ɐ\xE8\x91ւ\xA6\x82\xE9\x81B - // (2016.11.3 yutaka) - ssh2_scp_add_packetlist(pvar, c, newdata, buflen); + // \x82\xB1\x82̒\x86\x82\xC5 suspended \x82\xAA TRUE \x82ɂȂ邱\x82Ƃ\xAA\x82\xA0\x82\xE9 + ssh2_scp_add_packetlist(pvar, c, newdata, buflen); + } + + c->scp.recv.received_size += buflen; + + if (c->scp.recv.received_size >= c->scp.filetotalsize) { + // \x8E\xF3\x90M\x8FI\x97\xB9 + assert (pvar->recv.timer_id == 0); + PTInstVar pvar = c->scp.pvar; + pvar->recv.data_finished = TRUE; + if (pvar->recv.timer_id != 0) { + pvar->recv.timer_id = 0; + KillTimer(pvar->cv->HWin, pvar->recv.timer_id); + } + } + else if (pvar->recv.suspended) { + // \x83t\x83\x8D\x81[\x90\xA7\x8C䒆 + logprintf(LOG_LEVEL_NOTICE, "%s: scp receive suspended", __FUNCTION__); + } + else { + // \x83\x8D\x81[\x83J\x83\x8B\x82\xCCwindow size\x82\xF0\x83`\x83F\x83b\x83N + // \x82\xB1\x82܂߂ɂ\xE2\x82炸\x82ɁA\x82\xA0\x82\xE9\x92\xF6\x93x\x82܂Ƃ߂Ē\xB2\x90\xAE\x82\xF0\x8Ds\x82\xA4 + if (c->local_window < c->local_window_max/2) { + // window\x83T\x83C\x83Y\x82\xAE\x82\xB7\x82\xE9 +#if 0 + // \x82\xB7\x82\xAE\x82ɒ\xB2\x90\xAE\x82\xB7\x82\xE9 + // \x82\xB7\x82\xAE\x82ɃT\x81[\x83o\x81[\x82\xA9\x82\xE7\x83f\x81[\x83^\x82\xAA\x8E\xF3\x90M\x82ł\xAB\x82\xE9\x8A\xAB\x82̏ꍇ\x81A + // FD_READ\x82\xAA\x97D\x90悳\x82\xEA\x82ă\x81\x83b\x83Z\x81[\x83W\x83L\x83\x85\x81[\x82ɐς܂\xEA\x82\xC4 + // \x91\xBC\x82\xCCwindows\x82̃\x81\x83b\x83Z\x81[\x83W\x8F\x88\x97\x9D(\x83L\x83\x83\x83\x93\x83Z\x83\x8B\x83{\x83^\x83\x93\x89\x9F\x89\xBA\x82Ȃ\xC7)\x82\xAA + // \x82ł\xAB\x82Ȃ\xAD\x82Ȃ邽\x82ߎg\x97p\x82\xB5\x82Ȃ\xA2 + do_ssh2_adjust_window_size(pvar, c); +#else + // \x8F\xAD\x82\xB5\x8E\x9E\x8AԂ\xF0\x92u\x82\xA2\x82Ă\xA9\x82璲\x90\xAE + // \x83^\x83C\x83}\x81[\x82\xF0\x8Eg\x82\xC1\x82\xC4GUI\x83X\x83\x8C\x83b\x83h\x82Ŋ\x94\x82\xF0\x83R\x81[\x83\x8B\x82\xB7\x82\xE9 + if (pvar->recv.timer_id == 0) { + pvar->recv.timer_id = + SetTimer(pvar->cv->HWin, (UINT_PTR)c, USER_TIMER_MINIMUM, do_SSH2_adjust_window_size_timer); + } +#endif + } + } } } else if (c->scp.state == SCP_CLOSING) { // EOF\x82̎\xF3\x90M @@ -8733,8 +8805,11 @@ return TRUE; reply: - ch = '\0'; - SSH2_send_channel_data(pvar, c, &ch, 1, 0); + { + char ch; + ch = '\0'; + SSH2_send_channel_data(pvar, c, &ch, 1, 0); + } return TRUE; } @@ -8857,6 +8932,9 @@ } else if (c->type == TYPE_SCP) { // SCP SSH2_scp_response(pvar, c, data, str_len); + // \x83E\x83B\x83\x93\x83h\x83E\x83T\x83C\x83Y\x82̒\xB2\x90\xAE + c->local_window -= str_len; + return TRUE; } else if (c->type == TYPE_SFTP) { // SFTP sftp_response(pvar, c, data, str_len); @@ -8956,7 +9034,12 @@ // \x83E\x83B\x83\x93\x83h\x83E\x83T\x83C\x83Y\x82̒\xB2\x90\xAE c->local_window -= strlen; - do_SSH2_adjust_window_size(pvar, c); + if (c->type == TYPE_SCP && pvar->recv.suspended) { + logprintf(LOG_LEVEL_NOTICE, "%s: SCP suspended", __FUNCTION__); + } + else { + do_SSH2_adjust_window_size(pvar, c); + } return TRUE; } @@ -9209,6 +9292,10 @@ ssh2_channel_delete(c); } else if (c->type == TYPE_SCP) { + // \x8E\xF3\x90M\x8FI\x97\xB9 + PTInstVar pvar = c->scp.pvar; + pvar->recv.data_finished = TRUE; + ssh2_channel_delete(c); } else if (c->type == TYPE_AGENT) { Modified: trunk/ttssh2/ttxssh/ssh.h =================================================================== --- trunk/ttssh2/ttxssh/ssh.h 2023-10-07 17:40:26 UTC (rev 10959) +++ trunk/ttssh2/ttxssh/ssh.h 2023-10-07 17:40:35 UTC (rev 10960) @@ -529,7 +529,7 @@ // SCP\x8E\xF3\x90M\x8F\x88\x97\x9D\x82ɂ\xA8\x82\xAF\x82\xE9\x83t\x83\x8D\x81[\x90\xA7\x8C\xE4\x82\xCC臒l // \x93K\x97p\x90\xE6 scp_t.filercvsize -#define SCPRCV_HIGH_WATER_MARK (1 * 1024 * 1024) // 16MB +#define SCPRCV_HIGH_WATER_MARK (1 * 1024 * 1024) // 1MB #define SCPRCV_LOW_WATER_MARK (0) // 0MB typedef struct scp { @@ -552,6 +552,9 @@ PacketList_t *pktlist_head; PacketList_t *pktlist_tail; unsigned long pktlist_cursize; + struct { + uint64_t received_size; + } recv; } scp_t; enum sftp_state { Modified: trunk/ttssh2/ttxssh/ttxssh.h =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.h 2023-10-07 17:40:26 UTC (rev 10959) +++ trunk/ttssh2/ttxssh/ttxssh.h 2023-10-07 17:40:35 UTC (rev 10960) @@ -355,11 +355,17 @@ // dialog resource HFONT hFontFixed; // hosts.c\x93\xE0\x82̃_\x83C\x83A\x83\x8D\x83O\x97p + struct { + BOOL suspended; // SCP\x8E\xF3\x90M\x82̃t\x83\x8D\x81[\x90\xA7\x8C\xE4\x97p,TRUE\x82̂Ƃ\xAB\x89\x9E\x93\x9A\x82\xF0\x95Ԃ\xB3\x82Ȃ\xA2\x8F\xF3\x91\xD4 + //BOOL timer_triggerd; + UINT_PTR timer_id; + BOOL data_finished; // TRUE\x82̂Ƃ\xAB,\x83f\x81[\x83^\x82̎\xF3\x90M\x82͊\xAE\x97\xB9\x82\xB5\x82\xBD + BOOL close_request; + } recv; + char *server_sig_algs; char UIMsg[MAX_UIMSG]; - BOOL recv_suspended; // SCP\x8E\xF3\x90M\x82̃t\x83\x8D\x81[\x90\xA7\x8C\xE4\x97p - } TInstVar; // \x83o\x81[\x83W\x83\x87\x83\x93\x82ɍ\x87\x82킹\x82Ď\xA9\x93\xAE\x95ύX\x82\xB3\x82\xEA\x82\xE9\x81B \x97\xE1: TTSSH_2-81_TS_data