|
|
/* xfr_srcv.c -- transfer service routines
* * Copyright 1990 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 13 $ * $Date: 5/21/02 9:58a $ */
#include <windows.h>
#pragma hdrstop
#define BYTE char
#include <tdll\stdtyp.h>
#include <tdll\comdev.h>
#include <tdll\com.h>
#include <tdll\com.hh>
#include <tdll\session.h>
#include <tdll\assert.h>
#include <tdll\file_msc.h>
#include <tdll\xfer_msc.hh>
#include <tdll\file_io.h>
#include <tdll\tdll.h>
#include <tdll\htchar.h>
#include <tdll\misc.h>
#include <tdll\globals.h>
#include <tdll\errorbox.h>
#include <term\res.h>
#include "itime.h"
#include "xfer.h"
#include "xfer.hh"
#include "xfer_tsc.h"
#include "xfr_srvc.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
* * * R E A D M E * * * * Everybody keeps changing the TIME standard to whatever they feel might be * * a little bit better for them. So far I have found 3 different standards * * in Microsoft functions. This does not even count the fact that HyperP * * uses its own format for time. * * * * Henceforth, all time values that are passed around in the program will be * * based on the old UCT format of the number of seconds since Jan 1, 1970. * * * * Please use an unsigned long for these values. * * * *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_set_pointer * * DESCRIPTION: * When a transfer is started, it is passed a parameter block. This is * where the address of that block gets stored. * * PARAMETERS: * hSession -- the session handle * pV -- pointer to the parameter block * * RETURNS: * Nothing. * */ void xfer_set_pointer(HSESSION hSession, void *pV) { XD_TYPE *pX;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { pX->pXferStuff = pV; } }
void *xfer_get_pointer(HSESSION hSession) { XD_TYPE *pX;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { return (void *)pX->pXferStuff; } return (void *)0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_idle * * DESCRIPTION: * This function got called in Windows to make sure that the transfer * display (and other tasks) got some time every now and then during a * transfer. I don't know if this needs to be done under CHICAGO, with * a pre-emptive multi-tasking design. The call is still here until it * can be determined one way or another. * * PARAMETERS: * hSession -- the session handle * * RETURNS: * Nothing. * */
#define IDLE_WAIT 150
void xfer_idle(HSESSION h, int nMode) { /*
* This is set up for the mode flags to be OR'ed together if necessary */ if (nMode & XFER_IDLE_IO) { HCOM hComHandle = sessQueryComHdl(h);
if (hComHandle && ComValidHandle(hComHandle) && (hComHandle->pfPortConnected)(hComHandle->pvDriverData) == COM_PORT_OPEN); { HANDLE hComEvent = ComGetRcvEvent(hComHandle);
if (hComEvent) { WaitForSingleObject(hComEvent, IDLE_WAIT); } } }
if (nMode & XFER_IDLE_DISPLAY) { /*
* The documentation says that this caused the thread to yield, * presumably back to the scheduler cycle. It tries to let the * display update if possible. */ Sleep(0); }
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_user_interrupt * * DESCRIPTION: * This function is called by the transfer routines to determine if the user * has hit any of the cancel or skip buttons in the display window. * * PARAMETERS: * hSession -- the session handle. * * RETURNS: * ZERO if nothing to report, otherwise a CANCEL or SKIP indicator. * */ int xfer_user_interrupt(HSESSION hSession) { INT nRetVal; XD_TYPE *pX;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX == NULL) { // DbgOutStr("xfer_user_interrupt returns an error\r\n", 0,0,0,0,0);
return FALSE; }
switch (pX->nUserCancel) { case XFER_ABORT: nRetVal = XFER_ABORT; pX->nUserCancel = 0; // Reset to default value
// DbgOutStr("xfer_user_interrupt returns 1\r\n", 0,0,0,0,0);
break;
case XFER_SKIP: nRetVal = XFER_SKIP; pX->nUserCancel = 0; // Reset to default value
// DbgOutStr("xfer_user_interrupt returns 2\r\n", 0,0,0,0,0);
break;
default: // DbgOutStr("xfer_user_interrupt returns 0\r\n", 0,0,0,0,0);
nRetVal = 0; break; } return nRetVal; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_user_abort * * DESCRIPTION: * * PARAMETERS: * * RETURNS: * */ int xfer_user_abort(HSESSION hSession, int p) { XD_TYPE *pX;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX == NULL) { // TODO: decide if we need CLoopClearOutput
// CLoopClearOutput(sessQueryCLoopHdl(hSession));
return TRUE; }
switch (p) { case 0: case XFER_ABORT: case XFER_SKIP: pX->nUserCancel = p; break; default: pX->nUserCancel = 0; break; }
return TRUE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_carrier_lost * * DESCRIPTION: * This function is called by the transfer routines to determine if the * session is still connected to something. * * PARAMETERS: * hSession -- the session handle * * RETURNS: * TRUE if carrier has been lost, otherwise FALSE; * */ int xfer_carrier_lost(HSESSION hSession) { XD_TYPE *pX;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX == NULL) { // DbgOutStr("xfer_user_interrupt returns an error\r\n", 0,0,0,0,0);
return FALSE; }
return pX->nCarrierLost; // Set by the COM the driver (ComActivatePort()
// and ComDeactivatePort()) and the transfer
// display (WM_INITDIALOG and XFER_LOST_CARRIER
// messages to XfrDisplayDlg()). REV: 9/7/2001
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_purgefile * * DESCRIPTION: * This function is called after a VIRUS has been detected. It is supposed * to make sure that whatever was written out to disk from the infected file * gets seriously blasted. * * PARAMETERS: * hSession -- the session handle * fname -- the name of the file * * RETURNS: * Nothing. * */ void xfer_purgefile(HSESSION hSession, TCHAR *fname) {
/*
* Given the way buffering and deletion recovery can be done in modern * systems, I am not real sure what should be done here. */ DeleteFile(fname); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfrUniqueName * * DESCRIPTION: * This function is called to build a NEW (currently unused) file name from * an existing file name by using a sequential numbering operation. * * PARAMETERS: * hSession -- the session handle * pszSrc -- the origional file name * pszDst -- where to put the new file name * * RETURNS: * 0 if everything is OK, otherwise a negative number. * */ static int xfrUniqueName(HSESSION hSession, LPTSTR pszSrc, LPTSTR pszDst) { int nRetVal = -1; TCHAR szSrc[MAX_PATH]; TCHAR szName[MAX_PATH]; TCHAR szTag[10]; // big enough to hold "0" to "9999"
TCHAR *pszFName = NULL; TCHAR *pszExtension = NULL; TCHAR *pszScan = NULL; long nComponentSize = 0L; int nNameSpace; int nTag = 0; int nSize = 0;
// Let Operating system figure out full name. This will also set pszFName
// to point to the file name component of the path.
nSize = GetFullPathName(pszSrc, MAX_PATH, szSrc, &pszFName); if (nSize) { if (pszFName) { // Copy name portion off for later manipulation and remove ext.
StrCharCopy(szName, pszFName); mscStripExt(szName);
// Isolate the dir portion of the path
pszScan = StrCharPrev(szSrc, pszFName); if (pszScan) *pszScan = TEXT('\0');
// Keep pointer to extension, if any, in original string
pszExtension = StrCharFindLast(pszFName, TEXT('.')); }
// Find maximum length of path component (this is platform dependent)
// TODO:jkh, 12/19/94 Different drives may use different sizes
if (!GetVolumeInformation(NULL, NULL, 0, NULL, &nComponentSize, NULL, NULL, 0)) nComponentSize = 12; // Safest size if call fails
// Try attaching numeric tags to the name until name is unique
nNameSpace = nComponentSize - StrCharGetByteCount(pszExtension); for (nTag = 0; nTag < 10000; ++nTag) { _itoa(nTag, szTag, 10); // make sure tag will fit on filename
while (StrCharGetByteCount(szName) > nNameSpace - StrCharGetByteCount(szTag)) { pszScan = StrCharLast(szName); *pszScan = TEXT('\0'); } StrCharCopy(pszDst, szSrc); // start with dir portion
StrCharCat(pszDst, TEXT("\\")); // separator
StrCharCat(pszDst, szName); // original file name (truncated)
StrCharCat(pszDst, szTag); // numeric tag to make unique
StrCharCat(pszDst, pszExtension); // Extension (if any)
if (!mscIsDirectory(pszDst) && !GetFileSizeFromName(pszDst, 0)) { nRetVal = 0; break; /* Exit with good name */ } } }
return nRetVal; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfrUniqueDateName * * DESCRIPTION: * This function is called to build a NEW (currently unused) file name from * an existing file name by using the current data/time. * * PARAMETERS: * hSession -- the session handle * pszSrc -- the origional file name * pszDst -- where to put the new file name * * RETURNS: * 0 if everything is OK, otherwise a negative number. * */ static int xfrUniqueDateName(HSESSION hSession, LPTSTR pszSrc, LPTSTR pszDst) { int nRet = 0; int nTag; LPTSTR pszDir; LPTSTR pszExt; SYSTEMTIME stT; TCHAR acDatestr[8]; TCHAR acFrm[16]; TCHAR acSrc[FNAME_LEN]; TCHAR acDst[FNAME_LEN];
/* Get a pointer to the path portion only */ StrCharCopy(acSrc, pszSrc); pszDir = acSrc; pszExt = StrCharFindLast(acSrc, TEXT('\\'));
/* Get a pointer to the file name section */ nTag = 0; while ((*pszExt != TEXT('.')) && (nTag < 8)) acFrm[nTag++] = *pszExt++; acFrm[nTag] = TEXT('\0'); if (StrCharGetByteCount(acFrm) == 0) StrCharCopy(acFrm, TEXT("D"));
/* Get a pointer to the extension */ pszExt = StrCharFindLast(pszDst, TEXT('.')); if (pszExt == NULL) pszExt = ".FIL";
GetLocalTime(&stT); wsprintf(acDatestr, "%x%02d%02d%1d", stT.wMonth, stT.wDay, stT.wHour, stT.wMinute % 10); acFrm[8 - StrCharGetByteCount(acDatestr)] = TEXT('\0');
wsprintf(acDst, "%s%s%s%s", pszDir, acFrm, acDatestr, pszExt);
return xfrUniqueName(hSession, acDst, pszDst); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_modify_rcv_name * * DESCRIPTION: * This function is called to modify the name as necessary based on the users * parameters. * * PARAMETERS: * hSession -- the session handle * pszName -- the file name * lTime -- our internal time format, see READ ME above * lFlags -- flags * pfFlags -- pointer to returned flags * * RETURNS: * 0 -- everything was OK * -1 -- file error * -2 -- reject due to date * -4 -- no date, time provided * -6 -- unconditinally refuse file * -7 -- general failure * */ int xfer_modify_rcv_name(HSESSION hSession, LPTSTR pszName, unsigned long ulTime, long lFlags, int *pfFlags) { int nRetVal = 0; int nOpenFlags = 0; int isFile = 0; unsigned long locTime; TCHAR szNewName[FNAME_LEN]; DWORD dwRetVal;
isFile = GetFileSizeFromName(pszName, NULL);
if (isFile == FALSE) { nOpenFlags = 0; } else { switch (lFlags) { case XFR_RO_APPEND: nOpenFlags = TRUE; break;
case XFR_RO_ALWAYS: nOpenFlags = 0; break;
case XFR_RO_NEWER: if (ulTime != 0) // Let's check the time.
{ locTime = itimeGetFileTime(pszName); if (locTime != 0) if (locTime <= ulTime) // File is newer, accept it.
nOpenFlags = 0; else nRetVal = -2; // Reject it due to date.
else nRetVal = -1; // File error...
} else nRetVal = -4; // No date, time supplied.
break;
case XFR_RO_REN_DATE: //
// Build a new name, based upon the date of the new file.
//
nRetVal = xfrUniqueDateName(hSession, pszName, pszName); if (nRetVal < 0) nRetVal = -7; // Ambiguous file name.
nOpenFlags = 0; break;
default: case XFR_RO_REN_SEQ: //
// Build a new name, based upon a sequence number algorithm.
//
nRetVal = xfrUniqueName(hSession, pszName, szNewName); if (nRetVal < 0) nRetVal = -7; // Ambiguous file name.
else { dwRetVal = GetFileAttributes(pszName); if (dwRetVal != 0xFFFFFFFF && (dwRetVal & FILE_ATTRIBUTE_DIRECTORY) != 0) { nRetVal = -8; // File is a directory
} else if (MoveFile(pszName, szNewName) == FALSE) { nRetVal = -8; // File is opened
} } nOpenFlags = 0; break;
case XFR_RO_NEVER: nRetVal = -6; break; } }
if (nRetVal >= 0) *pfFlags = nOpenFlags;
return nRetVal; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_makepaths * * DESCRIPTION: * This function is called to make sure that a pathname exists. It creates * whatever portion of the pathname needs to be created. * * PARAMETERS: * hSession -- the session handle * pszPath -- the path * * RETURNS: * 0 -- everything was OK * -1 -- bad path format * -2 -- disk error of some sort * */ int xfer_makepaths(HSESSION hSession, LPTSTR pszPath) { TCHAR ach[256]; TCHAR achFormat[256]; TCHAR ach2[50];
if (pszPath == 0) return -1;
if (!mscIsDirectory(pszPath)) { if (LoadString(glblQueryDllHinst(), IDS_GNRL_CREATE_PATH, achFormat, sizeof(achFormat) / sizeof(TCHAR)) == 0) { DbgShowLastError(); return -3; }
if (LoadString(glblQueryDllHinst(), IDS_MB_TITLE_WARN, ach2, sizeof(ach2) / sizeof(TCHAR)) == 0) { DbgShowLastError(); return -4; }
wsprintf(ach, achFormat, pszPath);
if (TimedMessageBox(sessQueryHwnd(hSession), ach, ach2, MB_YESNO | MB_TASKMODAL | MB_ICONEXCLAMATION, sessQueryTimeout(hSession)) == IDYES) { if (mscCreatePath(pszPath) != 0) { assert(0); return -2; } }
else { return -5; } }
return 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_create_rcv_file * * DESCRIPTION: * This function is called to open the file for receiving. It has the code * to create the path to the file for those protocols that can transfer a * path as well as a file name. * * PARAMETERS: * hSession -- the session handle * pszName -- the complete path name of the file * lOpenFlags -- the flags to pass to fio_open * nowdays TRUE means APPEND, FALSE means overwrite * phRet -- where to return the file handle * * RETURNS: * 0 -- everything was OK * -1 -- couldn't create the file * */ int xfer_create_rcv_file(HSESSION hSession, LPTSTR pszName, long lOpenFlags, HANDLE *phRet) { ST_IOBUF *hFile; LPTSTR pszStr; TCHAR acDir[FNAME_LEN];
StrCharCopy(acDir, pszName); pszStr = StrCharLast(acDir); while ((*pszStr != TEXT('\\')) && (pszStr > acDir)) pszStr = StrCharPrev(acDir, pszStr);
if (pszStr == acDir) return -1;
*pszStr = TEXT('\0'); if (xfer_makepaths(hSession, acDir) < 0) return -1;
if (lOpenFlags) { /* Open for appending */ hFile = fio_open(pszName, FIO_APPEND | FIO_WRITE); } else { hFile = fio_open(pszName, FIO_CREATE | FIO_WRITE); } if (hFile == NULL) return -1;
*phRet = hFile; return 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_open_rcv_file * * DESCRIPTION: * This function is called to actually do the open of the receive file. It * calls a bunch of other stuff, fiddles with names, and eventually returns. * * PARAMETERS: * hSesssion -- the session handle * pstRcv -- pointer to the receive open structure * ulOverRide -- if set, flags to use instead of contents of pstRcv * * RETURNS: * 0 if A-OK * -1 if error occurred * -2 if rejected due to date * -3 if rejected because it can't save file * -4 if no date/time supplied when required * -5 if unable to create needed directories * -6 if file rejected unconditionally * -7 if general failure * */ int xfer_open_rcv_file(HSESSION hSession, struct st_rcv_open *pstRcv, unsigned long ulOverRide) { unsigned long ulFlags = 0; int nOpenFlags; int nRetVal = 0; #if FALSE
// Lower Wacker does not support message logging
int msgIndex = -1; #endif
XD_TYPE *pX; XFR_PARAMS *pP;
pstRcv->bfHdl = NULL; pstRcv->lInitialSize = 0;
xfer_build_rcv_name(hSession, pstRcv);
/* Get the overwrite parameters */ pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { pP = (XFR_PARAMS *)pX->xfer_params; if (pP) { ulFlags = pP->nRecOverwrite; } } if (ulOverRide != 0) ulFlags = ulOverRide;
nRetVal = xfer_modify_rcv_name(hSession, pstRcv->pszActualName, pstRcv->lFileTime, ulFlags, &nOpenFlags);
if (nRetVal >= 0) { HANDLE lRet; unsigned long size;
size = 0; // if (nOpenFlags & O_APPEND)
if (nOpenFlags) { if (!GetFileSizeFromName(pstRcv->pszActualName, &size)) { size = 0; } }
nRetVal = xfer_create_rcv_file(hSession, pstRcv->pszActualName, nOpenFlags, &lRet); if (nRetVal >= 0) { pstRcv->bfHdl = lRet;
// if (nOpenFlags & O_APPEND)
if (nOpenFlags) { pstRcv->lInitialSize = size; } } }
#if FALSE
// Lower Wacker does not support logging
if (nRetVal < 0) { switch (nRetVal) { case -6: // File was rejected unconditionally
msgIndex = 23; // "User refused"
break; case -5: // Were unable to create needed directories
msgIndex = 11; // "Fatal disk error"
break; case -4: // No date, time supplied when required
msgIndex = 17; // "No file time available"
break; case -3: // File could not be saved
msgIndex = 9; // "Cannot writ file to disk"
break; case -2: // File was rejected due to date
msgIndex = 16; // "File is too old"
break; case -1: // Some error occured
msgIndex = 10; // "Cannot open file"
break; default: // Failed
msgIndex = 19; // "General failure"
break; } xfer_log_xfer( hSession, FALSE, pstRcv->pszSuggestedName, pstRcv->pszActualName, msgIndex ); } #endif
return nRetVal; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_build_rcv_name * * DESCRIPTION: * This function is called to help build the name of the file that the * transfer receive code is going to dump the data into. * * PARAMETERS: * hSession -- the session handle * pstRcv -- pointer to the receive open structure (contains the name) * * RETURNS: * Nothing. * */ void xfer_build_rcv_name(HSESSION hSession, struct st_rcv_open *pstRcv) { int nSingle; XD_TYPE *pX; XFR_PARAMS *pP; XFR_RECEIVE *pR; #if defined(INC_VSCAN)
SSHDLMCH ssVscanMch; #endif
LPTSTR pszStr; TCHAR acBuffer[FNAME_LEN];
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { pP = (XFR_PARAMS *)pX->xfer_params; if (pP) { /* Just continue on to the rest of the function */ } else { assert(FALSE); return; } pR = pX->pXferStuff; if (pR) { /* Just continue on to the rest of the function */ } else { assert(FALSE); return; } } else { assert(FALSE); return; }
nSingle = !pP->fUseFilenames; nSingle |= (pP->nRecProtocol == XF_XMODEM); nSingle |= (pP->nRecProtocol == XF_XMODEM_1K);
if (nSingle) { /* User specified a single file */ StrCharCopy(acBuffer, pR->pszDir); pszStr = (LPTSTR)StrCharLast(acBuffer); if (*pszStr != TEXT('\\')) { pszStr += 1; *pszStr = TEXT('\\'); pszStr += 1; *pszStr = TEXT('\0'); } StrCharCat(acBuffer, pR->pszName);
fileFinalizeName( acBuffer, /* values to use */ pstRcv->pszSuggestedName, /* filler */ pstRcv->pszActualName, MAX_PATH); } else if (!pP->fUseDirectory) { /* Use directory flag is not set */ //
// Ignore all paths sent to us in this case.
//
pszStr = StrCharLast(pstRcv->pszSuggestedName);
/* TODO: fix this up for wide characters */ while (pszStr >= pstRcv->pszSuggestedName) { if ((*pszStr == TEXT('\\')) || (*pszStr == TEXT(':'))) { StrCharCopy(pstRcv->pszSuggestedName, ++pszStr); break; } else { if (pszStr == pstRcv->pszSuggestedName) break; pszStr = (LPTSTR)StrCharPrev(pstRcv->pszSuggestedName, pszStr); } }
fileFinalizeName( pstRcv->pszSuggestedName, /* values to use */ pR->pszDir, /* filler */ pstRcv->pszActualName, MAX_PATH); } else { /* I am not a all sure about this stuff */ if ((pstRcv->pszSuggestedName[0] == TEXT('\\')) || (pstRcv->pszSuggestedName[1] == TEXT(':'))) { /* if full path given */ StrCharCopy(pstRcv->pszActualName, pstRcv->pszSuggestedName); } else { /* else use our path 1st */ StrCharCopy(pstRcv->pszActualName, pR->pszDir); if ((pR->pszName != NULL) && (StrCharGetByteCount(pR->pszName) > 0)) StrCharCat(pstRcv->pszActualName, pR->pszName); else StrCharCat(pstRcv->pszActualName, pstRcv->pszSuggestedName);
fileFinalizeName( pstRcv->pszActualName, /* values to use */ pstRcv->pszSuggestedName, /* filler */ pstRcv->pszActualName, MAX_PATH); } } }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_close_rcv_file * * DESCRIPTION: * This function is called at the end of a transfer. It does various things * such as setting the file time/date, the size, saving partial files, and * logging the transfer. A cleanup routine. * * PARAMETERS: * hSession -- the session handle * fhdl -- the actual file handle * nReason -- transfer status code * pszRemoteName -- the file name as it was sent to us * pszOurName -- the file name we actually used to save the data * nSave -- partial save flag * lFilesize -- size to set the file to * lTime -- date/time value to use to set the file * * RETURNS: * TRUE if the transfer was successful, otherwise FALSE. * */ int xfer_close_rcv_file(HSESSION Hsession, void *vhdl, int nReason, TCHAR *pszRemoteName, TCHAR *pszOurName, int nSave, unsigned long lFilesize, unsigned long lTime) /* Fix this later */ { ST_IOBUF *fhdl = (ST_IOBUF *)vhdl;
if (nReason == TSC_COMPLETE) nReason = TSC_OK;
if (fio_close(fhdl) == 0) { /* Set the size */ if (lFilesize > 0 && nReason == TSC_OK) /*lFilesize != 0 jmh 03-08-96 */ SetFileSize(pszOurName, lFilesize);
/* Set the date/time */ if (lTime != 0) itimeSetFileTime(pszOurName, lTime); } else { nReason = TSC_DISK_ERROR; }
#if FALSE
// Lower Wacker does not log transfers */
xfer_log_xfer(hSession, FALSE, pszRemoteName, pszOurName, nReason); #endif
if (nReason == TSC_OLDER_FILE) nReason = TSC_OK;
if (nReason != TSC_OK && pszOurName && *pszOurName) { if (nSave == FALSE) DeleteFile(pszOurName); }
if (nReason == TSC_LOST_CARRIER) { nReason = TSC_OK; }
return (nReason == TSC_OK); }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_get_params * * DESCRIPTION: * This function gets the protocol specific parameters for the transfer * routines. * * PARAMETERS: * hSession -- the session handle * nProtocol -- the protocol ID * * RETURNS: * A pointer to the protocol block, or a NULL. * */ VOID FAR * xfer_get_params(HSESSION hSession, int nProtocol) { void *pVret = (void *)0; XD_TYPE *pX;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { int nLimit = SFID_PROTO_PARAMS_END - SFID_PROTO_PARAMS; if (nProtocol < nLimit) { if (pX->xfer_proto_params[nProtocol] == NULL) { int nRet = xfrInitializeParams(hSession, nProtocol, &pX->xfer_proto_params[nProtocol]); assert(nRet == 0); } pVret = (VOID FAR *)pX->xfer_proto_params[nProtocol]; } } return pVret; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_set_comport * * DESCRIPTION: * This function is called to save the current com port settings so that the * transfer code can go ahead and change them to whatever it likes. * * PARAMETERS: * hSession -- the session handle * fSending -- TRUE if sending, FALSE if receiving * puiOldOptions -- where to store the old settings * * RETURNS: * TRUE if everything was OK, otherwise FALSE * */ int xfer_set_comport(HSESSION hSession, int fSending, unsigned *puiOldOptions) { unsigned uiOptions = COM_OVERRIDE_8BIT; unsigned uiOldOptions;
if (fSending) bitset(uiOptions, COM_OVERRIDE_SNDALL); else bitset(uiOptions, COM_OVERRIDE_RCVALL);
/* TODO: find out how to decide which things need to be changed, BFMI */ if (ComOverride(sessQueryComHdl(hSession), uiOptions, &uiOldOptions) != COM_OK) { return FALSE; } if (puiOldOptions != NULL) *puiOldOptions = uiOldOptions; return TRUE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_restore_comport * * DESCRIPTION: * This function is called to restore the parameters that the previous call * saved. * * PARAMETERS: * hSession -- the session handle * uiOldOptions -- the old comm parameters * * RETURNS: * TRUE if everything was OK, otherwise FALSE * */ int xfer_restore_comport(HSESSION hSession, unsigned uiOldOptions) {
ComSndBufrWait(sessQueryComHdl(hSession), 10);
// Let any trailing data get sent
ComSndBufrWait(sessQueryComHdl(hSession), 10); if (ComOverride(sessQueryComHdl(hSession), uiOldOptions, NULL) != COM_OK) return FALSE; return TRUE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_save_partial * * DESCRIPTION: * This function is called by the transfer routines to decide if it is * OK to leave a partial file around if a transfer is aborted. * * PARAMETERS: * hSession -- the session handle * * RETURNS: * TRUE if it is OK, otherwise FALSE * */ int xfer_save_partial(HSESSION hSession) { XD_TYPE *pX; XFR_PARAMS *pP;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { pP = (XFR_PARAMS *)pX->xfer_params; if (pP) { return pP->fSavePartial; } } return FALSE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_nextfile * * DESCRIPTION: * This function is called by the transfer routines to get the name of the * next file that is to be sent on over to the other side. * * PARAMETERS: * hSession -- the session handle * filename -- where to copy the file name * * RETURNS: * TRUE if there was a filename available, otherwise FALSE * */ int xfer_nextfile(HSESSION hSession, TCHAR *filename) { XD_TYPE *pX; XFR_SEND *pS; LPTSTR pszStr;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { pS = (XFR_SEND *)pX->pXferStuff; if (pS) { if (pS->nIndex < pS->nCount) { pszStr = pS->pList[pS->nIndex].pszName; StrCharCopy(filename, pszStr); pS->nIndex += 1; /*
* TODO: decide where the memory gets freed */ return TRUE; } } } return FALSE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_log_xfer * * DESCRIPTION: * This function is called after a file is sent or received to place that * information in the log file. * * PARAMETERS: * hSession -- the session handle * sending -- TRUE if the file was sent, otherwise FALSE * theirname -- the name that was given to the other system * ourname -- the name of the file on this system * result -- the final transfer status code * * RETURNS: * Nothing. * */ void xfer_log_xfer(HSESSION hSession, int sending, TCHAR *theirname, TCHAR *ourname, int result) { /*
* Lower Wacker does not do transfer logging. This is here mostly as a * place holder and for the eventual conversion to Upper Wacker. */ }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_opensendfile * * DESCRIPTION: * This function is called to open a file that is to be sent to another * system. * * PARAMETERS: * hSession -- the session handle * fp -- where to store the open file handle * file_to_open -- the name of the file to open (duh!) * size -- where to save the size of the file * name_to_send -- what name to send to the other system * ft -- currently unused * * RETURNS: * 0 if everything is OK * -1 if an error occurred * -2 if the file was not found * */ int xfer_opensendfile(HSESSION hSession, HANDLE *fp, TCHAR *file_to_open, long *size, TCHAR *name_to_send, void *ft) { DWORD dwFoo;
*fp = (HANDLE)0;
/*
* Just try an open the file */ *fp = fio_open(file_to_open, FIO_READ);
if (*fp == NULL) { *fp = (HANDLE)0; return -1; }
/*
* Got the file open, get the size */ *size = GetFileSize(fio_gethandle((ST_IOBUF *)*fp), &dwFoo);
/*
* TODO: do the date and time stuff */
/*
* Give them a file name */ if (name_to_send != NULL) xfer_name_to_send(hSession, file_to_open, name_to_send);
return 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
* FUNCTION: * xfer_name_to_send * * DESCRIPTION: * This function is called to modify the file name into some sort of form * that should be sent over to the other side. Kind of sounds like an * exchange of captured spys at Checkpoint Charlie. * * PARAMETERS: * hSession -- the session handle * local_name -- what the name is on this system * name_to_send -- where to put the processed name * * RETURNS: * Nothing. * */ void xfer_name_to_send(HSESSION hSession, TCHAR *local_name, TCHAR *name_to_send) { TCHAR *pszStr; XD_TYPE *pX; XFR_PARAMS *pP;
if (local_name == NULL) return; if (name_to_send == NULL) return;
pX = (XD_TYPE *)sessQueryXferHdl(hSession); if (pX) { pP = (XFR_PARAMS *)pX->xfer_params; if (pP) { if (pP->fIncPaths) { StrCharCopy(name_to_send, local_name); } } } /*
* Otherwise, just do this */ pszStr = StrCharFindLast(local_name, TEXT('\\')); if (*pszStr == TEXT('\\')) pszStr += 1; StrCharCopy(name_to_send, pszStr); }
|