421 lines
11 KiB
C
421 lines
11 KiB
C
#ifdef MOD_ZMODEM
|
|
|
|
#include "putty.h"
|
|
#include "terminal.h"
|
|
#include <windows.h>
|
|
#include <time.h>
|
|
|
|
void c_write(Ldisc *ldisc, const void *buf, int len);
|
|
|
|
void xyz_updateMenuItems(Terminal *term);
|
|
|
|
void xyz_ReceiveInit(Terminal *term);
|
|
int xyz_ReceiveData(Terminal *term, const u_char *buffer, int len);
|
|
static int xyz_SpawnProcess(Terminal *term, const char *incommand, const char *inparams);
|
|
void xyz_Cancel(Terminal *term) ;
|
|
|
|
int existfile( const char * filename ) ;
|
|
|
|
#define MAX_UPLOAD_FILES 512
|
|
|
|
#define PIPE_SIZE (64*1024)
|
|
|
|
struct zModemInternals {
|
|
PROCESS_INFORMATION pi;
|
|
HANDLE read_stdout;
|
|
HANDLE read_stderr;
|
|
HANDLE write_stdin;
|
|
};
|
|
|
|
static int IsWinNT()
|
|
{
|
|
OSVERSIONINFO osv;
|
|
osv.dwOSVersionInfoSize = sizeof(osv);
|
|
GetVersionEx(&osv);
|
|
return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
|
}
|
|
|
|
void xyz_Done(Terminal *term)
|
|
{
|
|
if (term->xyz_transfering != 0) {
|
|
term->xyz_transfering = 0;
|
|
xyz_updateMenuItems(term);
|
|
|
|
if (term->xyz_Internals) {
|
|
DWORD exitcode = 0;
|
|
CloseHandle(term->xyz_Internals->write_stdin);
|
|
Sleep(500);
|
|
CloseHandle(term->xyz_Internals->read_stdout);
|
|
CloseHandle(term->xyz_Internals->read_stderr);
|
|
GetExitCodeProcess(term->xyz_Internals->pi.hProcess,&exitcode); //while the process is running
|
|
if (exitcode == STILL_ACTIVE) {
|
|
TerminateProcess(term->xyz_Internals->pi.hProcess, 0);
|
|
}
|
|
sfree(term->xyz_Internals);
|
|
term->xyz_Internals = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int xyz_Check(Backend *back, void *backhandle, Terminal *term, int outerr) ;
|
|
|
|
int xyz_Process(Backend *back, void *backhandle, Terminal *term) {
|
|
return xyz_Check(back, backhandle, term, 0) + xyz_Check(back, backhandle, term, 1);
|
|
}
|
|
|
|
static int xyz_Check(Backend *back, void *backhandle, Terminal *term, int outerr) {
|
|
DWORD exitcode = 0;
|
|
DWORD bread, avail;
|
|
char buf[1024];
|
|
HANDLE h;
|
|
|
|
if (!term->xyz_transfering) {
|
|
return 0;
|
|
}
|
|
|
|
if (outerr) {
|
|
h = term->xyz_Internals->read_stdout;
|
|
} else {
|
|
h = term->xyz_Internals->read_stderr;
|
|
}
|
|
|
|
bread = 0;
|
|
PeekNamedPipe(h,buf,1,&bread,&avail,NULL);
|
|
//check to see if there is any data to read from stdout
|
|
if (bread != 0)
|
|
{
|
|
while (1)
|
|
{
|
|
bread = 0;
|
|
|
|
PeekNamedPipe(h,buf,1,&bread,&avail,NULL);
|
|
if (bread == 0)
|
|
return 0;
|
|
|
|
if (ReadFile(h,buf,sizeof(buf),&bread,NULL)) { //read the stdout pipe
|
|
if (bread) {
|
|
#if 0
|
|
char *buffer;
|
|
int len;
|
|
|
|
buffer = buf;
|
|
len = bread;
|
|
if (0)
|
|
{
|
|
char *debugbuff;
|
|
char *bb, *p;
|
|
int i;
|
|
|
|
debugbuff = _alloca(len*3+128);
|
|
debugbuff[0] = 0;
|
|
bb = debugbuff;
|
|
p = buffer;
|
|
bb += sprintf(bb, "R: %8d ", time(NULL));
|
|
for(i=0; i < len; i++) {
|
|
bb += sprintf(bb, "%2x ", *p++);
|
|
}
|
|
bb += sprintf(bb, "\n");
|
|
|
|
OutputDebugString(debugbuff);
|
|
} else {
|
|
char *debugbuff;
|
|
debugbuff = _alloca(len+128);
|
|
memcpy(debugbuff, buffer, len);
|
|
debugbuff[len] = 0;
|
|
if (outerr) {
|
|
strcat(debugbuff, "<<<<<<<\n");
|
|
} else {
|
|
strcat(debugbuff, "*******\n");
|
|
}
|
|
OutputDebugString(debugbuff);
|
|
}
|
|
#endif
|
|
if (outerr) {
|
|
// back->send(backhandle, buf, bread);
|
|
backend_send( backhandle, buf, bread );
|
|
} else {
|
|
//from_backend(term, 1, buf, bread);
|
|
c_write(term->ldisc, buf, bread);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
// EOF/ERROR
|
|
xyz_Done(term);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
GetExitCodeProcess(term->xyz_Internals->pi.hProcess,&exitcode);
|
|
if (exitcode != STILL_ACTIVE) {
|
|
xyz_Done(term);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void xyz_ReceiveInit(Terminal *term) {
|
|
if( !existfile( conf_get_filename(term->conf,CONF_rzcommand)->path ) ) {
|
|
char b[512] ;
|
|
sprintf( b, "Unable to find Zmodem receive program: \n%s", conf_get_filename(term->conf,CONF_rzcommand)->path ) ;
|
|
xyz_Cancel( term ) ;
|
|
MessageBox( NULL, b, "Error", MB_OK|MB_ICONERROR ) ;
|
|
return ;
|
|
}
|
|
if (xyz_SpawnProcess(term, conf_get_filename(term->conf,CONF_rzcommand)->path, conf_get_str(term->conf,CONF_rzoptions)) == 0) {
|
|
term->xyz_transfering = 1;
|
|
} else {
|
|
MessageBox(NULL,"Unable to start receiving !", "Error", MB_OK|MB_ICONERROR);
|
|
}
|
|
}
|
|
|
|
void xyz_StartSending(Terminal *term) {
|
|
OPENFILENAME fn;
|
|
char filenames[32000];
|
|
BOOL res;
|
|
|
|
memset(&fn, 0, sizeof(fn));
|
|
memset(filenames, 0, sizeof(filenames));
|
|
fn.lStructSize = sizeof(fn);
|
|
fn.lpstrFile = filenames;
|
|
fn.nMaxFile = sizeof(filenames)-1; // the missing -1 was causing a crash on very long selections
|
|
fn.lpstrTitle = "Select files to upload...";
|
|
fn.Flags = OFN_ALLOWMULTISELECT | OFN_CREATEPROMPT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
|
|
|
|
res = GetOpenFileName(&fn);
|
|
|
|
if (res)
|
|
{
|
|
char sz_full_params[32767];
|
|
char *p, *curparams;
|
|
p = filenames;
|
|
|
|
curparams = sz_full_params;
|
|
sz_full_params[0] = 0;
|
|
|
|
curparams += sprintf(curparams, "%s", conf_get_str(term->conf,CONF_szoptions));
|
|
|
|
if (*(p+strlen(filenames)+1)==0) {
|
|
sprintf(curparams, " \"%s\"", filenames);
|
|
} else {
|
|
for (;;) {
|
|
p=p+strlen(p)+1;
|
|
if (*p==0)
|
|
break;
|
|
curparams += sprintf(curparams, " \"%s\\%s\"", filenames, p);
|
|
}
|
|
}
|
|
|
|
if( !existfile( conf_get_filename(term->conf,CONF_szcommand)->path ) ) {
|
|
char b[512] ;
|
|
sprintf( b, "Unable to find Zmodem send program: \n%s", conf_get_filename(term->conf,CONF_szcommand)->path ) ;
|
|
xyz_Cancel( term ) ;
|
|
MessageBox( NULL, b, "Error", MB_OK|MB_ICONERROR ) ;
|
|
return ;
|
|
}
|
|
|
|
if (xyz_SpawnProcess(term, conf_get_filename(term->conf,CONF_szcommand)->path, sz_full_params) == 0) {
|
|
term->xyz_transfering = 1;
|
|
|
|
} else {
|
|
MessageBox(NULL,"Unable to start sending !", "Error", MB_OK|MB_ICONERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
void xyz_Cancel(Terminal *term)
|
|
{
|
|
xyz_Done(term);
|
|
}
|
|
|
|
static int xyz_SpawnProcess(Terminal *term, const char *incommand, const char *inparams)
|
|
{
|
|
STARTUPINFO si;
|
|
SECURITY_ATTRIBUTES sa;
|
|
SECURITY_DESCRIPTOR sd; //security information for pipes
|
|
|
|
|
|
|
|
// Essai en bypassant le process spawn
|
|
|
|
GetStartupInfo(&si);
|
|
term->xyz_Internals = (struct zModemInternals *)smalloc(sizeof(struct zModemInternals));
|
|
memset(term->xyz_Internals, 0, sizeof(struct zModemInternals));
|
|
|
|
term->xyz_Internals->write_stdin = si.hStdInput ;
|
|
term->xyz_Internals->read_stdout = si.hStdOutput ;
|
|
term->xyz_Internals->read_stderr = si.hStdError ;
|
|
|
|
return 0;
|
|
/**/
|
|
|
|
HANDLE read_stdout, read_stderr, write_stdin, newstdin, newstdout, newstderr; //pipe handles
|
|
|
|
term->xyz_Internals = (struct zModemInternals *)smalloc(sizeof(struct zModemInternals));
|
|
memset(term->xyz_Internals, 0, sizeof(struct zModemInternals));
|
|
|
|
if (IsWinNT()) //initialize security descriptor (Windows NT)
|
|
{
|
|
InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
|
|
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
|
|
sa.lpSecurityDescriptor = &sd;
|
|
}
|
|
else sa.lpSecurityDescriptor = NULL;
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
sa.bInheritHandle = TRUE; //allow inheritable handles
|
|
|
|
if (!CreatePipe(&newstdin,&write_stdin,&sa,PIPE_SIZE)) //create stdin pipe
|
|
{
|
|
return 1;
|
|
}
|
|
if (!CreatePipe(&read_stdout,&newstdout,&sa,PIPE_SIZE)) //create stdout pipe
|
|
{
|
|
CloseHandle(newstdin);
|
|
CloseHandle(write_stdin);
|
|
return 1;
|
|
}
|
|
if (!CreatePipe(&read_stderr,&newstderr,&sa,PIPE_SIZE)) //create stdout pipe
|
|
{
|
|
CloseHandle(newstdin);
|
|
CloseHandle(write_stdin);
|
|
CloseHandle(newstdout);
|
|
CloseHandle(read_stdout);
|
|
return 1;
|
|
}
|
|
|
|
GetStartupInfo(&si); //set startupinfo for the spawned process
|
|
/*
|
|
The dwFlags member tells CreateProcess how to make the process.
|
|
STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
|
|
validates the wShowWindow member.
|
|
*/
|
|
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_HIDE;
|
|
si.hStdOutput = newstdout;
|
|
si.hStdError = newstderr; //set the new handles for the child process
|
|
si.hStdInput = newstdin;
|
|
|
|
//system
|
|
if (!DuplicateHandle(GetCurrentProcess(), read_stdout, GetCurrentProcess(), &term->xyz_Internals->read_stdout, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
|
{
|
|
CloseHandle(newstdin);
|
|
CloseHandle(write_stdin);
|
|
CloseHandle(newstdout);
|
|
CloseHandle(read_stdout);
|
|
CloseHandle(newstderr);
|
|
CloseHandle(read_stderr);
|
|
return 1;
|
|
}
|
|
|
|
CloseHandle(read_stdout);
|
|
|
|
if (!DuplicateHandle(GetCurrentProcess(), read_stderr, GetCurrentProcess(), &term->xyz_Internals->read_stderr, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
|
{
|
|
CloseHandle(newstdin);
|
|
CloseHandle(newstdout);
|
|
CloseHandle(read_stdout);
|
|
CloseHandle(write_stdin);
|
|
CloseHandle(newstderr);
|
|
CloseHandle(read_stderr);
|
|
return 1;
|
|
}
|
|
|
|
CloseHandle(read_stderr);
|
|
|
|
if (!DuplicateHandle(GetCurrentProcess(), write_stdin, GetCurrentProcess(), &term->xyz_Internals->write_stdin, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
|
{
|
|
CloseHandle(newstdin);
|
|
CloseHandle(write_stdin);
|
|
CloseHandle(newstdout);
|
|
CloseHandle(term->xyz_Internals->read_stdout);
|
|
CloseHandle(newstderr);
|
|
CloseHandle(term->xyz_Internals->read_stderr);
|
|
return 1;
|
|
}
|
|
|
|
CloseHandle(write_stdin);
|
|
|
|
//spawn the child process
|
|
{
|
|
char params[1204];
|
|
const char *p;
|
|
|
|
p = incommand + strlen(incommand);
|
|
while (p != incommand) {
|
|
if (*p == '\\' || *p == ' ') { // no space in name either
|
|
p++;
|
|
break;
|
|
}
|
|
p--;
|
|
}
|
|
|
|
sprintf(params, "%s %s", p, inparams);
|
|
if (!CreateProcess(incommand,params,NULL, NULL,TRUE,CREATE_NEW_CONSOLE, NULL,conf_get_str(term->conf,CONF_zdownloaddir),&si,&term->xyz_Internals->pi)) {
|
|
//DWORD err = GetLastError();
|
|
//ErrorMessage("CreateProcess");
|
|
CloseHandle(newstdin);
|
|
CloseHandle(term->xyz_Internals->write_stdin);
|
|
CloseHandle(newstdout);
|
|
CloseHandle(term->xyz_Internals->read_stdout);
|
|
CloseHandle(newstderr);
|
|
CloseHandle(term->xyz_Internals->read_stderr);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
CloseHandle(newstdin);
|
|
CloseHandle(newstdout);
|
|
CloseHandle(newstderr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xyz_ReceiveData(Terminal *term, const u_char *buffer, int len)
|
|
{
|
|
DWORD written;
|
|
#if 0
|
|
if (0)
|
|
{
|
|
char *debugbuff;
|
|
char *bb, *p;
|
|
int i;
|
|
|
|
debugbuff = _alloca(len*3+128);
|
|
debugbuff[0] = 0;
|
|
bb = debugbuff;
|
|
p = buffer;
|
|
bb += sprintf(bb, "R: %8d ", time(NULL));
|
|
for(i=0; i < len; i++) {
|
|
bb += sprintf(bb, "%2x ", *p++);
|
|
}
|
|
bb += sprintf(bb, "\n");
|
|
|
|
OutputDebugString(debugbuff);
|
|
} else {
|
|
char *debugbuff;
|
|
debugbuff = _alloca(len+128);
|
|
memcpy(debugbuff, buffer, len);
|
|
debugbuff[len] = 0;
|
|
strcat(debugbuff, ">>>>>>>\n");
|
|
OutputDebugString(debugbuff);
|
|
}
|
|
#endif
|
|
// if( !
|
|
WriteFile(term->xyz_Internals->write_stdin,buffer,len,&written,NULL)
|
|
// ) { char buf[1024]; sprintf(buf, "Unable to write %d characters", len); MessageBox(NULL,buf,"Error",MB_OK|MB_ICONERROR); }
|
|
;
|
|
return 0 ;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
E:\DEV\MinGW\msys\1.0\home\cyril\putty-0.71\zmodem\rz.exe rz.exe -e -v
|
|
|
|
E:\DEV\MinGW\msys\1.0\home\cyril\putty-0.71\zmodem\sz.exe sz.exe -e -v "E:\DEV\windiff.exe"
|
|
*/
|