| 89 |
FILE *sendfp; // file pointer |
FILE *sendfp; // file pointer |
| 90 |
struct _stat filestat; // file status information |
struct _stat filestat; // file status information |
| 91 |
HWND progress; |
HWND progress; |
| 92 |
|
HANDLE thread; |
| 93 |
|
PTInstVar pvar; |
| 94 |
} scp_t; |
} scp_t; |
| 95 |
|
|
| 96 |
typedef struct channel { |
typedef struct channel { |
| 259 |
|
|
| 260 |
if (c->type == TYPE_SCP) { |
if (c->type == TYPE_SCP) { |
| 261 |
c->scp.state = SCP_CLOSING; |
c->scp.state = SCP_CLOSING; |
| 262 |
|
if (c->scp.thread != (HANDLE)-1L) { |
| 263 |
|
WaitForSingleObject(c->scp.thread, INFINITE); |
| 264 |
|
CloseHandle(c->scp.thread); |
| 265 |
|
c->scp.thread = (HANDLE)-1L; |
| 266 |
|
} |
| 267 |
if (c->scp.progress != NULL) { |
if (c->scp.progress != NULL) { |
|
//SendMessage(c->scp.progress, WM_CLOSE, 0, 0); |
|
| 268 |
DestroyWindow(c->scp.progress); |
DestroyWindow(c->scp.progress); |
| 269 |
c->scp.progress = NULL; |
c->scp.progress = NULL; |
| 270 |
} |
} |
| 7029 |
} |
} |
| 7030 |
|
|
| 7031 |
|
|
| 7032 |
void ssh2_channel_remote_close(PTInstVar pvar, Channel_t *c) |
void ssh2_channel_send_close(PTInstVar pvar, Channel_t *c) |
| 7033 |
{ |
{ |
| 7034 |
if (SSHv2(pvar)) { |
if (SSHv2(pvar)) { |
| 7035 |
buffer_t *msg; |
buffer_t *msg; |
| 7052 |
} |
} |
| 7053 |
} |
} |
| 7054 |
|
|
| 7055 |
#define WM_START_SENDING_FILE (WM_USER + 1) |
#define WM_SENDING_FILE (WM_USER + 1) |
| 7056 |
|
|
| 7057 |
typedef struct scp_thread_parm { |
typedef struct scp_dlg_parm { |
|
PTInstVar pvar; |
|
| 7058 |
Channel_t *c; |
Channel_t *c; |
| 7059 |
} scp_thread_parm_t; |
PTInstVar pvar; |
| 7060 |
|
char *buf; |
| 7061 |
|
size_t buflen; |
| 7062 |
|
} scp_dlg_parm_t; |
| 7063 |
|
|
| 7064 |
static LRESULT CALLBACK ssh_scp_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) |
static LRESULT CALLBACK ssh_scp_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) |
| 7065 |
{ |
{ |
|
const int RWIN_TIMEOUT = 100; // 100 msec |
|
|
const int SEND_TIMEOUT = 1; // 1 msec |
|
|
const int IDC_TIMER = 1; |
|
|
static int instance = 0; |
|
|
static PTInstVar pvar = NULL; |
|
|
static Channel_t *c = NULL; |
|
|
static long long total_size = 0; |
|
|
char buf[8192]; |
|
|
size_t ret; |
|
|
scp_thread_parm_t *parm; |
|
| 7066 |
|
|
| 7067 |
switch (msg) { |
switch (msg) { |
| 7068 |
case WM_INITDIALOG: |
case WM_INITDIALOG: |
|
if (instance > 0) { |
|
|
EndDialog(hWnd, 0); |
|
|
} else { |
|
|
instance++; |
|
|
} |
|
| 7069 |
return FALSE; |
return FALSE; |
| 7070 |
|
|
| 7071 |
case WM_TIMER: |
case WM_SENDING_FILE: |
| 7072 |
{ |
{ |
| 7073 |
char s[80]; |
scp_dlg_parm_t *parm = (scp_dlg_parm_t *)wp; |
|
|
|
|
// socket or channelがクローズされたらスレッドを終わる |
|
|
if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0) |
|
|
goto end; |
|
|
|
|
|
if (sizeof(buf) > c->remote_window) { |
|
|
SetTimer(hWnd, 1, RWIN_TIMEOUT, 0); |
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
// ファイルから読み込んだデータはかならずサーバへ送信する。 |
|
|
ret = fread(buf, 1, sizeof(buf), c->scp.sendfp); |
|
|
if (ret == 0) |
|
|
goto eof; |
|
|
SSH2_send_channel_data(pvar, c, buf, ret); |
|
|
total_size += ret; |
|
|
|
|
|
_snprintf_s(s, sizeof(s), _TRUNCATE, "%lld / %lld (%d%%)", total_size, (long long)c->scp.filestat.st_size, |
|
|
(100 * total_size / c->scp.filestat.st_size)%100 ); |
|
|
SendMessage(GetDlgItem(hWnd, IDC_PROGRESS), WM_SETTEXT, 0, (LPARAM)s); |
|
|
goto retry; |
|
|
|
|
|
eof: |
|
|
SSH2_send_channel_data(pvar, c, "\0", 1); |
|
|
c->scp.state = SCP_DATA; |
|
|
assert(total_size == c->scp.filestat.st_size); |
|
|
end: |
|
|
c->scp.state = SCP_DATA; |
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0); |
|
|
return TRUE; |
|
| 7074 |
|
|
| 7075 |
retry: |
SSH2_send_channel_data(parm->pvar, parm->c, parm->buf, parm->buflen); |
|
SetTimer(hWnd, IDC_TIMER, SEND_TIMEOUT, 0); |
|
|
} |
|
|
return TRUE; |
|
|
break; |
|
|
|
|
|
case WM_START_SENDING_FILE: |
|
|
{ |
|
|
parm = (scp_thread_parm_t *)wp; |
|
|
pvar = parm->pvar; |
|
|
c = parm->c; |
|
|
free(parm); // free! |
|
|
total_size = 0; |
|
|
|
|
|
SendMessage(GetDlgItem(hWnd, IDC_FILENAME), WM_SETTEXT, 0, (LPARAM)c->scp.sendfile); |
|
|
|
|
|
SetTimer(hWnd, 1, 100, 0); |
|
| 7076 |
} |
} |
| 7077 |
return TRUE; |
return TRUE; |
| 7078 |
break; |
break; |
| 7088 |
} |
} |
| 7089 |
|
|
| 7090 |
case IDCANCEL: |
case IDCANCEL: |
| 7091 |
ssh2_channel_remote_close(pvar, c); |
EndDialog(hWnd, 0); |
|
PostMessage(hWnd, WM_CLOSE, 0, 0); |
|
|
//EndDialog(hWnd, 0); |
|
| 7092 |
return TRUE; |
return TRUE; |
| 7093 |
default: |
default: |
| 7094 |
return FALSE; |
return FALSE; |
| 7096 |
break; |
break; |
| 7097 |
|
|
| 7098 |
case WM_CLOSE: |
case WM_CLOSE: |
| 7099 |
KillTimer(hWnd, IDC_TIMER); |
// closeボタンが押下されても window が閉じないようにする。 |
|
EndDialog(hWnd, 0); |
|
| 7100 |
return TRUE; |
return TRUE; |
| 7101 |
|
|
| 7102 |
case WM_DESTROY: |
case WM_DESTROY: |
|
instance--; |
|
| 7103 |
return TRUE; |
return TRUE; |
| 7104 |
|
|
| 7105 |
default: |
default: |
| 7108 |
return TRUE; |
return TRUE; |
| 7109 |
} |
} |
| 7110 |
|
|
| 7111 |
|
static unsigned __stdcall ssh_scp_thread(void FAR * p) |
| 7112 |
|
{ |
| 7113 |
|
Channel_t *c = (Channel_t *)p; |
| 7114 |
|
PTInstVar pvar = c->scp.pvar; |
| 7115 |
|
long long total_size = 0; |
| 7116 |
|
char buf[8192]; |
| 7117 |
|
char s[80]; |
| 7118 |
|
size_t ret; |
| 7119 |
|
HWND hWnd = c->scp.progress; |
| 7120 |
|
scp_dlg_parm_t parm; |
| 7121 |
|
|
| 7122 |
|
SendMessage(GetDlgItem(hWnd, IDC_FILENAME), WM_SETTEXT, 0, (LPARAM)c->scp.sendfile); |
| 7123 |
|
|
| 7124 |
|
do { |
| 7125 |
|
// Cancelボタンが押下されたらウィンドウが消える。 |
| 7126 |
|
if (IsWindowVisible(hWnd) == 0) |
| 7127 |
|
goto abort; |
| 7128 |
|
|
| 7129 |
|
// ファイルから読み込んだデータはかならずサーバへ送信する。 |
| 7130 |
|
ret = fread(buf, 1, sizeof(buf), c->scp.sendfp); |
| 7131 |
|
if (ret == 0) |
| 7132 |
|
break; |
| 7133 |
|
|
| 7134 |
|
do { |
| 7135 |
|
// socket or channelがクローズされたらスレッドを終わる |
| 7136 |
|
if (pvar->socket == INVALID_SOCKET || c->scp.state == SCP_CLOSING || c->used == 0) |
| 7137 |
|
goto abort; |
| 7138 |
|
|
| 7139 |
|
if (ret > c->remote_window) { |
| 7140 |
|
Sleep(100); |
| 7141 |
|
} |
| 7142 |
|
|
| 7143 |
|
} while (ret > c->remote_window); |
| 7144 |
|
|
| 7145 |
|
// sending data |
| 7146 |
|
parm.buf = buf; |
| 7147 |
|
parm.buflen = ret; |
| 7148 |
|
parm.c = c; |
| 7149 |
|
parm.pvar = pvar; |
| 7150 |
|
SendMessage(hWnd, WM_SENDING_FILE, (WPARAM)&parm, 0); |
| 7151 |
|
|
| 7152 |
|
total_size += ret; |
| 7153 |
|
|
| 7154 |
|
_snprintf_s(s, sizeof(s), _TRUNCATE, "%lld / %lld (%d%%)", total_size, (long long)c->scp.filestat.st_size, |
| 7155 |
|
(100 * total_size / c->scp.filestat.st_size)%100 ); |
| 7156 |
|
SendMessage(GetDlgItem(hWnd, IDC_PROGRESS), WM_SETTEXT, 0, (LPARAM)s); |
| 7157 |
|
|
| 7158 |
|
} while (ret <= sizeof(buf)); |
| 7159 |
|
|
| 7160 |
|
// eof |
| 7161 |
|
buf[0] = '\0'; |
| 7162 |
|
parm.buf = buf; |
| 7163 |
|
parm.buflen = 1; |
| 7164 |
|
parm.c = c; |
| 7165 |
|
parm.pvar = pvar; |
| 7166 |
|
SendMessage(hWnd, WM_SENDING_FILE, (WPARAM)&parm, 0); |
| 7167 |
|
|
| 7168 |
|
c->scp.state = SCP_DATA; |
| 7169 |
|
return 0; |
| 7170 |
|
|
| 7171 |
|
abort: |
| 7172 |
|
ssh2_channel_send_close(pvar, c); |
| 7173 |
|
|
| 7174 |
|
#if 0 |
| 7175 |
|
// デッドロック回避のため、自分でハンドルをクローズする。 |
| 7176 |
|
CloseHandle(c->scp.thread); |
| 7177 |
|
c->scp.thread = (HANDLE)-1L; |
| 7178 |
|
//ssh2_channel_delete(c); // free channel |
| 7179 |
|
#endif |
| 7180 |
|
return 0; |
| 7181 |
|
} |
| 7182 |
|
|
| 7183 |
static BOOL handle_SSH2_channel_data(PTInstVar pvar) |
static BOOL handle_SSH2_channel_data(PTInstVar pvar) |
| 7184 |
{ |
{ |
| 7250 |
SSH2_send_channel_data(pvar, c, buf, strlen(buf)); |
SSH2_send_channel_data(pvar, c, buf, strlen(buf)); |
| 7251 |
|
|
| 7252 |
} else if (c->scp.state == SCP_FILEINFO) { |
} else if (c->scp.state == SCP_FILEINFO) { |
|
scp_thread_parm_t *parm = malloc(sizeof(scp_thread_parm_t)); |
|
| 7253 |
HWND hDlgWnd; |
HWND hDlgWnd; |
| 7254 |
|
HANDLE thread; |
| 7255 |
|
unsigned int tid; |
| 7256 |
|
|
| 7257 |
if (parm == NULL) { |
c->scp.pvar = pvar; |
|
// TODO: |
|
|
} |
|
|
parm->pvar = pvar; |
|
|
parm->c = c; |
|
| 7258 |
|
|
| 7259 |
hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS), |
hDlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SSHSCP_PROGRESS), |
| 7260 |
pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc); |
pvar->cv->HWin, (DLGPROC)ssh_scp_dlg_proc); |
| 7261 |
if (hDlgWnd != NULL) { |
if (hDlgWnd != NULL) { |
| 7262 |
c->scp.progress = hDlgWnd; |
c->scp.progress = hDlgWnd; |
| 7263 |
ShowWindow(hDlgWnd, SW_SHOW); |
ShowWindow(hDlgWnd, SW_SHOW); |
|
SendMessage(hDlgWnd, WM_START_SENDING_FILE, (WPARAM)parm, 0); |
|
| 7264 |
} |
} |
| 7265 |
|
|
| 7266 |
|
thread = (HANDLE)_beginthreadex(NULL, 0, ssh_scp_thread, c, 0, &tid); |
| 7267 |
|
if (thread == (HANDLE)-1) { |
| 7268 |
|
// TODO: |
| 7269 |
|
} |
| 7270 |
|
c->scp.thread = thread; |
| 7271 |
|
|
| 7272 |
|
|
| 7273 |
} else if (c->scp.state == SCP_DATA) { |
} else if (c->scp.state == SCP_DATA) { |
| 7274 |
// 送信完了 |
// 送信完了 |
| 7275 |
ssh2_channel_delete(c); // free channel |
ssh2_channel_delete(c); // free channel |
| 7290 |
} |
} |
| 7291 |
msg[i] = '\0'; |
msg[i] = '\0'; |
| 7292 |
|
|
| 7293 |
ssh2_channel_remote_close(pvar, c); |
ssh2_channel_send_close(pvar, c); |
| 7294 |
ssh2_channel_delete(c); // free channel |
ssh2_channel_delete(c); // free channel |
| 7295 |
|
|
| 7296 |
MessageBox(NULL, msg, "TTSSH: SCP error", MB_OK | MB_ICONEXCLAMATION); |
MessageBox(NULL, msg, "TTSSH: SCP error", MB_OK | MB_ICONEXCLAMATION); |
| 7563 |
// チャネルの解放漏れを修正 (2007.4.26 yutaka) |
// チャネルの解放漏れを修正 (2007.4.26 yutaka) |
| 7564 |
ssh2_channel_delete(c); |
ssh2_channel_delete(c); |
| 7565 |
|
|
| 7566 |
|
} else if (c->type == TYPE_SCP) { |
| 7567 |
|
ssh2_channel_delete(c); |
| 7568 |
|
|
| 7569 |
} else { |
} else { |
| 7570 |
|
ssh2_channel_delete(c); |
| 7571 |
|
|
| 7572 |
} |
} |
| 7573 |
|
|
| 7668 |
data += 4; |
data += 4; |
| 7669 |
|
|
| 7670 |
c = ssh2_channel_lookup(id); |
c = ssh2_channel_lookup(id); |
| 7671 |
if (c == NULL) |
if (c == NULL) { |
| 7672 |
return FALSE; |
// channel close後にadjust messageが遅れてやってくるケースもあるため、 |
| 7673 |
|
// FALSEでは返さないようにする。(2007.12.26 yutaka) |
| 7674 |
|
return TRUE; |
| 7675 |
|
} |
| 7676 |
|
|
| 7677 |
adjust = get_uint32_MSBfirst(data); |
adjust = get_uint32_MSBfirst(data); |
| 7678 |
data += 4; |
data += 4; |