Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1360 lines
32 KiB

  1. /* xfr_srcv.c -- transfer service routines
  2. *
  3. * Copyright 1990 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 13 $
  7. * $Date: 5/21/02 9:58a $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #define BYTE char
  12. #include <tdll\stdtyp.h>
  13. #include <tdll\comdev.h>
  14. #include <tdll\com.h>
  15. #include <tdll\com.hh>
  16. #include <tdll\session.h>
  17. #include <tdll\assert.h>
  18. #include <tdll\file_msc.h>
  19. #include <tdll\xfer_msc.hh>
  20. #include <tdll\file_io.h>
  21. #include <tdll\tdll.h>
  22. #include <tdll\htchar.h>
  23. #include <tdll\misc.h>
  24. #include <tdll\globals.h>
  25. #include <tdll\errorbox.h>
  26. #include <term\res.h>
  27. #include "itime.h"
  28. #include "xfer.h"
  29. #include "xfer.hh"
  30. #include "xfer_tsc.h"
  31. #include "xfr_srvc.h"
  32. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*
  33. * *
  34. * R E A D M E *
  35. * *
  36. * Everybody keeps changing the TIME standard to whatever they feel might be *
  37. * a little bit better for them. So far I have found 3 different standards *
  38. * in Microsoft functions. This does not even count the fact that HyperP *
  39. * uses its own format for time. *
  40. * *
  41. * Henceforth, all time values that are passed around in the program will be *
  42. * based on the old UCT format of the number of seconds since Jan 1, 1970. *
  43. * *
  44. * Please use an unsigned long for these values. *
  45. * *
  46. *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  47. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  48. * FUNCTION:
  49. * xfer_set_pointer
  50. *
  51. * DESCRIPTION:
  52. * When a transfer is started, it is passed a parameter block. This is
  53. * where the address of that block gets stored.
  54. *
  55. * PARAMETERS:
  56. * hSession -- the session handle
  57. * pV -- pointer to the parameter block
  58. *
  59. * RETURNS:
  60. * Nothing.
  61. *
  62. */
  63. void xfer_set_pointer(HSESSION hSession, void *pV)
  64. {
  65. XD_TYPE *pX;
  66. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  67. if (pX)
  68. {
  69. pX->pXferStuff = pV;
  70. }
  71. }
  72. void *xfer_get_pointer(HSESSION hSession)
  73. {
  74. XD_TYPE *pX;
  75. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  76. if (pX)
  77. {
  78. return (void *)pX->pXferStuff;
  79. }
  80. return (void *)0;
  81. }
  82. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  83. * FUNCTION:
  84. * xfer_idle
  85. *
  86. * DESCRIPTION:
  87. * This function got called in Windows to make sure that the transfer
  88. * display (and other tasks) got some time every now and then during a
  89. * transfer. I don't know if this needs to be done under CHICAGO, with
  90. * a pre-emptive multi-tasking design. The call is still here until it
  91. * can be determined one way or another.
  92. *
  93. * PARAMETERS:
  94. * hSession -- the session handle
  95. *
  96. * RETURNS:
  97. * Nothing.
  98. *
  99. */
  100. #define IDLE_WAIT 150
  101. void xfer_idle(HSESSION h, int nMode)
  102. {
  103. /*
  104. * This is set up for the mode flags to be OR'ed together if necessary
  105. */
  106. if (nMode & XFER_IDLE_IO)
  107. {
  108. HCOM hComHandle = sessQueryComHdl(h);
  109. if (hComHandle && ComValidHandle(hComHandle) &&
  110. (hComHandle->pfPortConnected)(hComHandle->pvDriverData) == COM_PORT_OPEN);
  111. {
  112. HANDLE hComEvent = ComGetRcvEvent(hComHandle);
  113. if (hComEvent)
  114. {
  115. WaitForSingleObject(hComEvent, IDLE_WAIT);
  116. }
  117. }
  118. }
  119. if (nMode & XFER_IDLE_DISPLAY)
  120. {
  121. /*
  122. * The documentation says that this caused the thread to yield,
  123. * presumably back to the scheduler cycle. It tries to let the
  124. * display update if possible.
  125. */
  126. Sleep(0);
  127. }
  128. }
  129. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  130. * FUNCTION:
  131. * xfer_user_interrupt
  132. *
  133. * DESCRIPTION:
  134. * This function is called by the transfer routines to determine if the user
  135. * has hit any of the cancel or skip buttons in the display window.
  136. *
  137. * PARAMETERS:
  138. * hSession -- the session handle.
  139. *
  140. * RETURNS:
  141. * ZERO if nothing to report, otherwise a CANCEL or SKIP indicator.
  142. *
  143. */
  144. int xfer_user_interrupt(HSESSION hSession)
  145. {
  146. INT nRetVal;
  147. XD_TYPE *pX;
  148. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  149. if (pX == NULL)
  150. {
  151. // DbgOutStr("xfer_user_interrupt returns an error\r\n", 0,0,0,0,0);
  152. return FALSE;
  153. }
  154. switch (pX->nUserCancel)
  155. {
  156. case XFER_ABORT:
  157. nRetVal = XFER_ABORT;
  158. pX->nUserCancel = 0; // Reset to default value
  159. // DbgOutStr("xfer_user_interrupt returns 1\r\n", 0,0,0,0,0);
  160. break;
  161. case XFER_SKIP:
  162. nRetVal = XFER_SKIP;
  163. pX->nUserCancel = 0; // Reset to default value
  164. // DbgOutStr("xfer_user_interrupt returns 2\r\n", 0,0,0,0,0);
  165. break;
  166. default:
  167. // DbgOutStr("xfer_user_interrupt returns 0\r\n", 0,0,0,0,0);
  168. nRetVal = 0;
  169. break;
  170. }
  171. return nRetVal;
  172. }
  173. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  174. * FUNCTION:
  175. * xfer_user_abort
  176. *
  177. * DESCRIPTION:
  178. *
  179. * PARAMETERS:
  180. *
  181. * RETURNS:
  182. *
  183. */
  184. int xfer_user_abort(HSESSION hSession, int p)
  185. {
  186. XD_TYPE *pX;
  187. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  188. if (pX == NULL)
  189. {
  190. // TODO: decide if we need CLoopClearOutput
  191. // CLoopClearOutput(sessQueryCLoopHdl(hSession));
  192. return TRUE;
  193. }
  194. switch (p)
  195. {
  196. case 0:
  197. case XFER_ABORT:
  198. case XFER_SKIP:
  199. pX->nUserCancel = p;
  200. break;
  201. default:
  202. pX->nUserCancel = 0;
  203. break;
  204. }
  205. return TRUE;
  206. }
  207. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  208. * FUNCTION:
  209. * xfer_carrier_lost
  210. *
  211. * DESCRIPTION:
  212. * This function is called by the transfer routines to determine if the
  213. * session is still connected to something.
  214. *
  215. * PARAMETERS:
  216. * hSession -- the session handle
  217. *
  218. * RETURNS:
  219. * TRUE if carrier has been lost, otherwise FALSE;
  220. *
  221. */
  222. int xfer_carrier_lost(HSESSION hSession)
  223. {
  224. XD_TYPE *pX;
  225. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  226. if (pX == NULL)
  227. {
  228. // DbgOutStr("xfer_user_interrupt returns an error\r\n", 0,0,0,0,0);
  229. return FALSE;
  230. }
  231. return pX->nCarrierLost; // Set by the COM the driver (ComActivatePort()
  232. // and ComDeactivatePort()) and the transfer
  233. // display (WM_INITDIALOG and XFER_LOST_CARRIER
  234. // messages to XfrDisplayDlg()). REV: 9/7/2001
  235. }
  236. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  237. * FUNCTION:
  238. * xfer_purgefile
  239. *
  240. * DESCRIPTION:
  241. * This function is called after a VIRUS has been detected. It is supposed
  242. * to make sure that whatever was written out to disk from the infected file
  243. * gets seriously blasted.
  244. *
  245. * PARAMETERS:
  246. * hSession -- the session handle
  247. * fname -- the name of the file
  248. *
  249. * RETURNS:
  250. * Nothing.
  251. *
  252. */
  253. void xfer_purgefile(HSESSION hSession, TCHAR *fname)
  254. {
  255. /*
  256. * Given the way buffering and deletion recovery can be done in modern
  257. * systems, I am not real sure what should be done here.
  258. */
  259. DeleteFile(fname);
  260. }
  261. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  262. * FUNCTION:
  263. * xfrUniqueName
  264. *
  265. * DESCRIPTION:
  266. * This function is called to build a NEW (currently unused) file name from
  267. * an existing file name by using a sequential numbering operation.
  268. *
  269. * PARAMETERS:
  270. * hSession -- the session handle
  271. * pszSrc -- the origional file name
  272. * pszDst -- where to put the new file name
  273. *
  274. * RETURNS:
  275. * 0 if everything is OK, otherwise a negative number.
  276. *
  277. */
  278. static int xfrUniqueName(HSESSION hSession, LPTSTR pszSrc, LPTSTR pszDst)
  279. {
  280. int nRetVal = -1;
  281. TCHAR szSrc[MAX_PATH];
  282. TCHAR szName[MAX_PATH];
  283. TCHAR szTag[10]; // big enough to hold "0" to "9999"
  284. TCHAR *pszFName = NULL;
  285. TCHAR *pszExtension = NULL;
  286. TCHAR *pszScan = NULL;
  287. long nComponentSize = 0L;
  288. int nNameSpace;
  289. int nTag = 0;
  290. int nSize = 0;
  291. // Let Operating system figure out full name. This will also set pszFName
  292. // to point to the file name component of the path.
  293. nSize = GetFullPathName(pszSrc, MAX_PATH, szSrc, &pszFName);
  294. if (nSize)
  295. {
  296. if (pszFName)
  297. {
  298. // Copy name portion off for later manipulation and remove ext.
  299. StrCharCopy(szName, pszFName);
  300. mscStripExt(szName);
  301. // Isolate the dir portion of the path
  302. pszScan = StrCharPrev(szSrc, pszFName);
  303. if (pszScan)
  304. *pszScan = TEXT('\0');
  305. // Keep pointer to extension, if any, in original string
  306. pszExtension = StrCharFindLast(pszFName, TEXT('.'));
  307. }
  308. // Find maximum length of path component (this is platform dependent)
  309. // TODO:jkh, 12/19/94 Different drives may use different sizes
  310. if (!GetVolumeInformation(NULL, NULL, 0, NULL, &nComponentSize,
  311. NULL, NULL, 0))
  312. nComponentSize = 12; // Safest size if call fails
  313. // Try attaching numeric tags to the name until name is unique
  314. nNameSpace = nComponentSize - StrCharGetByteCount(pszExtension);
  315. for (nTag = 0; nTag < 10000; ++nTag)
  316. {
  317. _itoa(nTag, szTag, 10);
  318. // make sure tag will fit on filename
  319. while (StrCharGetByteCount(szName) >
  320. nNameSpace - StrCharGetByteCount(szTag))
  321. {
  322. pszScan = StrCharLast(szName);
  323. *pszScan = TEXT('\0');
  324. }
  325. StrCharCopy(pszDst, szSrc); // start with dir portion
  326. StrCharCat(pszDst, TEXT("\\")); // separator
  327. StrCharCat(pszDst, szName); // original file name (truncated)
  328. StrCharCat(pszDst, szTag); // numeric tag to make unique
  329. StrCharCat(pszDst, pszExtension); // Extension (if any)
  330. if (!mscIsDirectory(pszDst) && !GetFileSizeFromName(pszDst, 0))
  331. {
  332. nRetVal = 0;
  333. break; /* Exit with good name */
  334. }
  335. }
  336. }
  337. return nRetVal;
  338. }
  339. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  340. * FUNCTION:
  341. * xfrUniqueDateName
  342. *
  343. * DESCRIPTION:
  344. * This function is called to build a NEW (currently unused) file name from
  345. * an existing file name by using the current data/time.
  346. *
  347. * PARAMETERS:
  348. * hSession -- the session handle
  349. * pszSrc -- the origional file name
  350. * pszDst -- where to put the new file name
  351. *
  352. * RETURNS:
  353. * 0 if everything is OK, otherwise a negative number.
  354. *
  355. */
  356. static int xfrUniqueDateName(HSESSION hSession, LPTSTR pszSrc, LPTSTR pszDst)
  357. {
  358. int nRet = 0;
  359. int nTag;
  360. LPTSTR pszDir;
  361. LPTSTR pszExt;
  362. SYSTEMTIME stT;
  363. TCHAR acDatestr[8];
  364. TCHAR acFrm[16];
  365. TCHAR acSrc[FNAME_LEN];
  366. TCHAR acDst[FNAME_LEN];
  367. /* Get a pointer to the path portion only */
  368. StrCharCopy(acSrc, pszSrc);
  369. pszDir = acSrc;
  370. pszExt = StrCharFindLast(acSrc, TEXT('\\'));
  371. /* Get a pointer to the file name section */
  372. nTag = 0;
  373. while ((*pszExt != TEXT('.')) && (nTag < 8))
  374. acFrm[nTag++] = *pszExt++;
  375. acFrm[nTag] = TEXT('\0');
  376. if (StrCharGetByteCount(acFrm) == 0)
  377. StrCharCopy(acFrm, TEXT("D"));
  378. /* Get a pointer to the extension */
  379. pszExt = StrCharFindLast(pszDst, TEXT('.'));
  380. if (pszExt == NULL)
  381. pszExt = ".FIL";
  382. GetLocalTime(&stT);
  383. wsprintf(acDatestr, "%x%02d%02d%1d",
  384. stT.wMonth,
  385. stT.wDay,
  386. stT.wHour,
  387. stT.wMinute % 10);
  388. acFrm[8 - StrCharGetByteCount(acDatestr)] = TEXT('\0');
  389. wsprintf(acDst, "%s%s%s%s",
  390. pszDir,
  391. acFrm,
  392. acDatestr,
  393. pszExt);
  394. return xfrUniqueName(hSession, acDst, pszDst);
  395. }
  396. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  397. * FUNCTION:
  398. * xfer_modify_rcv_name
  399. *
  400. * DESCRIPTION:
  401. * This function is called to modify the name as necessary based on the users
  402. * parameters.
  403. *
  404. * PARAMETERS:
  405. * hSession -- the session handle
  406. * pszName -- the file name
  407. * lTime -- our internal time format, see READ ME above
  408. * lFlags -- flags
  409. * pfFlags -- pointer to returned flags
  410. *
  411. * RETURNS:
  412. * 0 -- everything was OK
  413. * -1 -- file error
  414. * -2 -- reject due to date
  415. * -4 -- no date, time provided
  416. * -6 -- unconditinally refuse file
  417. * -7 -- general failure
  418. *
  419. */
  420. int xfer_modify_rcv_name(HSESSION hSession,
  421. LPTSTR pszName,
  422. unsigned long ulTime,
  423. long lFlags,
  424. int *pfFlags)
  425. {
  426. int nRetVal = 0;
  427. int nOpenFlags = 0;
  428. int isFile = 0;
  429. unsigned long locTime;
  430. TCHAR szNewName[FNAME_LEN];
  431. DWORD dwRetVal;
  432. isFile = GetFileSizeFromName(pszName, NULL);
  433. if (isFile == FALSE)
  434. {
  435. nOpenFlags = 0;
  436. }
  437. else
  438. {
  439. switch (lFlags)
  440. {
  441. case XFR_RO_APPEND:
  442. nOpenFlags = TRUE;
  443. break;
  444. case XFR_RO_ALWAYS:
  445. nOpenFlags = 0;
  446. break;
  447. case XFR_RO_NEWER:
  448. if (ulTime != 0) // Let's check the time.
  449. {
  450. locTime = itimeGetFileTime(pszName);
  451. if (locTime != 0)
  452. if (locTime <= ulTime) // File is newer, accept it.
  453. nOpenFlags = 0;
  454. else
  455. nRetVal = -2; // Reject it due to date.
  456. else
  457. nRetVal = -1; // File error...
  458. }
  459. else
  460. nRetVal = -4; // No date, time supplied.
  461. break;
  462. case XFR_RO_REN_DATE:
  463. //
  464. // Build a new name, based upon the date of the new file.
  465. //
  466. nRetVal = xfrUniqueDateName(hSession, pszName, pszName);
  467. if (nRetVal < 0)
  468. nRetVal = -7; // Ambiguous file name.
  469. nOpenFlags = 0;
  470. break;
  471. default:
  472. case XFR_RO_REN_SEQ:
  473. //
  474. // Build a new name, based upon a sequence number algorithm.
  475. //
  476. nRetVal = xfrUniqueName(hSession, pszName, szNewName);
  477. if (nRetVal < 0)
  478. nRetVal = -7; // Ambiguous file name.
  479. else
  480. {
  481. dwRetVal = GetFileAttributes(pszName);
  482. if (dwRetVal != 0xFFFFFFFF &&
  483. (dwRetVal & FILE_ATTRIBUTE_DIRECTORY) != 0)
  484. {
  485. nRetVal = -8; // File is a directory
  486. }
  487. else if (MoveFile(pszName, szNewName) == FALSE)
  488. {
  489. nRetVal = -8; // File is opened
  490. }
  491. }
  492. nOpenFlags = 0;
  493. break;
  494. case XFR_RO_NEVER:
  495. nRetVal = -6;
  496. break;
  497. }
  498. }
  499. if (nRetVal >= 0)
  500. *pfFlags = nOpenFlags;
  501. return nRetVal;
  502. }
  503. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  504. * FUNCTION:
  505. * xfer_makepaths
  506. *
  507. * DESCRIPTION:
  508. * This function is called to make sure that a pathname exists. It creates
  509. * whatever portion of the pathname needs to be created.
  510. *
  511. * PARAMETERS:
  512. * hSession -- the session handle
  513. * pszPath -- the path
  514. *
  515. * RETURNS:
  516. * 0 -- everything was OK
  517. * -1 -- bad path format
  518. * -2 -- disk error of some sort
  519. *
  520. */
  521. int xfer_makepaths(HSESSION hSession, LPTSTR pszPath)
  522. {
  523. TCHAR ach[256];
  524. TCHAR achFormat[256];
  525. TCHAR ach2[50];
  526. if (pszPath == 0)
  527. return -1;
  528. if (!mscIsDirectory(pszPath))
  529. {
  530. if (LoadString(glblQueryDllHinst(), IDS_GNRL_CREATE_PATH, achFormat,
  531. sizeof(achFormat) / sizeof(TCHAR)) == 0)
  532. {
  533. DbgShowLastError();
  534. return -3;
  535. }
  536. if (LoadString(glblQueryDllHinst(), IDS_MB_TITLE_WARN, ach2,
  537. sizeof(ach2) / sizeof(TCHAR)) == 0)
  538. {
  539. DbgShowLastError();
  540. return -4;
  541. }
  542. wsprintf(ach, achFormat, pszPath);
  543. if (TimedMessageBox(sessQueryHwnd(hSession), ach, ach2,
  544. MB_YESNO | MB_TASKMODAL | MB_ICONEXCLAMATION,
  545. sessQueryTimeout(hSession)) == IDYES)
  546. {
  547. if (mscCreatePath(pszPath) != 0)
  548. {
  549. assert(0);
  550. return -2;
  551. }
  552. }
  553. else
  554. {
  555. return -5;
  556. }
  557. }
  558. return 0;
  559. }
  560. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  561. * FUNCTION:
  562. * xfer_create_rcv_file
  563. *
  564. * DESCRIPTION:
  565. * This function is called to open the file for receiving. It has the code
  566. * to create the path to the file for those protocols that can transfer a
  567. * path as well as a file name.
  568. *
  569. * PARAMETERS:
  570. * hSession -- the session handle
  571. * pszName -- the complete path name of the file
  572. * lOpenFlags -- the flags to pass to fio_open
  573. * nowdays TRUE means APPEND, FALSE means overwrite
  574. * phRet -- where to return the file handle
  575. *
  576. * RETURNS:
  577. * 0 -- everything was OK
  578. * -1 -- couldn't create the file
  579. *
  580. */
  581. int xfer_create_rcv_file(HSESSION hSession,
  582. LPTSTR pszName,
  583. long lOpenFlags,
  584. HANDLE *phRet)
  585. {
  586. ST_IOBUF *hFile;
  587. LPTSTR pszStr;
  588. TCHAR acDir[FNAME_LEN];
  589. StrCharCopy(acDir, pszName);
  590. pszStr = StrCharLast(acDir);
  591. while ((*pszStr != TEXT('\\')) && (pszStr > acDir))
  592. pszStr = StrCharPrev(acDir, pszStr);
  593. if (pszStr == acDir)
  594. return -1;
  595. *pszStr = TEXT('\0');
  596. if (xfer_makepaths(hSession, acDir) < 0)
  597. return -1;
  598. if (lOpenFlags)
  599. {
  600. /* Open for appending */
  601. hFile = fio_open(pszName, FIO_APPEND | FIO_WRITE);
  602. }
  603. else
  604. {
  605. hFile = fio_open(pszName, FIO_CREATE | FIO_WRITE);
  606. }
  607. if (hFile == NULL)
  608. return -1;
  609. *phRet = hFile;
  610. return 0;
  611. }
  612. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  613. * FUNCTION:
  614. * xfer_open_rcv_file
  615. *
  616. * DESCRIPTION:
  617. * This function is called to actually do the open of the receive file. It
  618. * calls a bunch of other stuff, fiddles with names, and eventually returns.
  619. *
  620. * PARAMETERS:
  621. * hSesssion -- the session handle
  622. * pstRcv -- pointer to the receive open structure
  623. * ulOverRide -- if set, flags to use instead of contents of pstRcv
  624. *
  625. * RETURNS:
  626. * 0 if A-OK
  627. * -1 if error occurred
  628. * -2 if rejected due to date
  629. * -3 if rejected because it can't save file
  630. * -4 if no date/time supplied when required
  631. * -5 if unable to create needed directories
  632. * -6 if file rejected unconditionally
  633. * -7 if general failure
  634. *
  635. */
  636. int xfer_open_rcv_file(HSESSION hSession,
  637. struct st_rcv_open *pstRcv,
  638. unsigned long ulOverRide)
  639. {
  640. unsigned long ulFlags = 0;
  641. int nOpenFlags;
  642. int nRetVal = 0;
  643. #if FALSE
  644. // Lower Wacker does not support message logging
  645. int msgIndex = -1;
  646. #endif
  647. XD_TYPE *pX;
  648. XFR_PARAMS *pP;
  649. pstRcv->bfHdl = NULL;
  650. pstRcv->lInitialSize = 0;
  651. xfer_build_rcv_name(hSession, pstRcv);
  652. /* Get the overwrite parameters */
  653. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  654. if (pX)
  655. {
  656. pP = (XFR_PARAMS *)pX->xfer_params;
  657. if (pP)
  658. {
  659. ulFlags = pP->nRecOverwrite;
  660. }
  661. }
  662. if (ulOverRide != 0)
  663. ulFlags = ulOverRide;
  664. nRetVal = xfer_modify_rcv_name(hSession,
  665. pstRcv->pszActualName,
  666. pstRcv->lFileTime,
  667. ulFlags,
  668. &nOpenFlags);
  669. if (nRetVal >= 0)
  670. {
  671. HANDLE lRet;
  672. unsigned long size;
  673. size = 0;
  674. // if (nOpenFlags & O_APPEND)
  675. if (nOpenFlags)
  676. {
  677. if (!GetFileSizeFromName(pstRcv->pszActualName, &size))
  678. {
  679. size = 0;
  680. }
  681. }
  682. nRetVal = xfer_create_rcv_file(hSession,
  683. pstRcv->pszActualName,
  684. nOpenFlags,
  685. &lRet);
  686. if (nRetVal >= 0)
  687. {
  688. pstRcv->bfHdl = lRet;
  689. // if (nOpenFlags & O_APPEND)
  690. if (nOpenFlags)
  691. {
  692. pstRcv->lInitialSize = size;
  693. }
  694. }
  695. }
  696. #if FALSE
  697. // Lower Wacker does not support logging
  698. if (nRetVal < 0)
  699. {
  700. switch (nRetVal)
  701. {
  702. case -6: // File was rejected unconditionally
  703. msgIndex = 23; // "User refused"
  704. break;
  705. case -5: // Were unable to create needed directories
  706. msgIndex = 11; // "Fatal disk error"
  707. break;
  708. case -4: // No date, time supplied when required
  709. msgIndex = 17; // "No file time available"
  710. break;
  711. case -3: // File could not be saved
  712. msgIndex = 9; // "Cannot writ file to disk"
  713. break;
  714. case -2: // File was rejected due to date
  715. msgIndex = 16; // "File is too old"
  716. break;
  717. case -1: // Some error occured
  718. msgIndex = 10; // "Cannot open file"
  719. break;
  720. default: // Failed
  721. msgIndex = 19; // "General failure"
  722. break;
  723. }
  724. xfer_log_xfer( hSession,
  725. FALSE,
  726. pstRcv->pszSuggestedName,
  727. pstRcv->pszActualName,
  728. msgIndex );
  729. }
  730. #endif
  731. return nRetVal;
  732. }
  733. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  734. * FUNCTION:
  735. * xfer_build_rcv_name
  736. *
  737. * DESCRIPTION:
  738. * This function is called to help build the name of the file that the
  739. * transfer receive code is going to dump the data into.
  740. *
  741. * PARAMETERS:
  742. * hSession -- the session handle
  743. * pstRcv -- pointer to the receive open structure (contains the name)
  744. *
  745. * RETURNS:
  746. * Nothing.
  747. *
  748. */
  749. void xfer_build_rcv_name(HSESSION hSession,
  750. struct st_rcv_open *pstRcv)
  751. {
  752. int nSingle;
  753. XD_TYPE *pX;
  754. XFR_PARAMS *pP;
  755. XFR_RECEIVE *pR;
  756. #if defined(INC_VSCAN)
  757. SSHDLMCH ssVscanMch;
  758. #endif
  759. LPTSTR pszStr;
  760. TCHAR acBuffer[FNAME_LEN];
  761. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  762. if (pX)
  763. {
  764. pP = (XFR_PARAMS *)pX->xfer_params;
  765. if (pP)
  766. {
  767. /* Just continue on to the rest of the function */
  768. }
  769. else
  770. {
  771. assert(FALSE);
  772. return;
  773. }
  774. pR = pX->pXferStuff;
  775. if (pR)
  776. {
  777. /* Just continue on to the rest of the function */
  778. }
  779. else
  780. {
  781. assert(FALSE);
  782. return;
  783. }
  784. }
  785. else
  786. {
  787. assert(FALSE);
  788. return;
  789. }
  790. nSingle = !pP->fUseFilenames;
  791. nSingle |= (pP->nRecProtocol == XF_XMODEM);
  792. nSingle |= (pP->nRecProtocol == XF_XMODEM_1K);
  793. if (nSingle)
  794. {
  795. /* User specified a single file */
  796. StrCharCopy(acBuffer, pR->pszDir);
  797. pszStr = (LPTSTR)StrCharLast(acBuffer);
  798. if (*pszStr != TEXT('\\'))
  799. {
  800. pszStr += 1;
  801. *pszStr = TEXT('\\');
  802. pszStr += 1;
  803. *pszStr = TEXT('\0');
  804. }
  805. StrCharCat(acBuffer, pR->pszName);
  806. fileFinalizeName(
  807. acBuffer, /* values to use */
  808. pstRcv->pszSuggestedName, /* filler */
  809. pstRcv->pszActualName,
  810. MAX_PATH);
  811. }
  812. else if (!pP->fUseDirectory)
  813. {
  814. /* Use directory flag is not set */
  815. //
  816. // Ignore all paths sent to us in this case.
  817. //
  818. pszStr = StrCharLast(pstRcv->pszSuggestedName);
  819. /* TODO: fix this up for wide characters */
  820. while (pszStr >= pstRcv->pszSuggestedName)
  821. {
  822. if ((*pszStr == TEXT('\\')) || (*pszStr == TEXT(':')))
  823. {
  824. StrCharCopy(pstRcv->pszSuggestedName, ++pszStr);
  825. break;
  826. }
  827. else
  828. {
  829. if (pszStr == pstRcv->pszSuggestedName)
  830. break;
  831. pszStr = (LPTSTR)StrCharPrev(pstRcv->pszSuggestedName, pszStr);
  832. }
  833. }
  834. fileFinalizeName(
  835. pstRcv->pszSuggestedName, /* values to use */
  836. pR->pszDir, /* filler */
  837. pstRcv->pszActualName,
  838. MAX_PATH);
  839. }
  840. else
  841. {
  842. /* I am not a all sure about this stuff */
  843. if ((pstRcv->pszSuggestedName[0] == TEXT('\\')) ||
  844. (pstRcv->pszSuggestedName[1] == TEXT(':')))
  845. {
  846. /* if full path given */
  847. StrCharCopy(pstRcv->pszActualName, pstRcv->pszSuggestedName);
  848. }
  849. else
  850. {
  851. /* else use our path 1st */
  852. StrCharCopy(pstRcv->pszActualName, pR->pszDir);
  853. if ((pR->pszName != NULL) &&
  854. (StrCharGetByteCount(pR->pszName) > 0))
  855. StrCharCat(pstRcv->pszActualName, pR->pszName);
  856. else
  857. StrCharCat(pstRcv->pszActualName, pstRcv->pszSuggestedName);
  858. fileFinalizeName(
  859. pstRcv->pszActualName, /* values to use */
  860. pstRcv->pszSuggestedName, /* filler */
  861. pstRcv->pszActualName,
  862. MAX_PATH);
  863. }
  864. }
  865. }
  866. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  867. * FUNCTION:
  868. * xfer_close_rcv_file
  869. *
  870. * DESCRIPTION:
  871. * This function is called at the end of a transfer. It does various things
  872. * such as setting the file time/date, the size, saving partial files, and
  873. * logging the transfer. A cleanup routine.
  874. *
  875. * PARAMETERS:
  876. * hSession -- the session handle
  877. * fhdl -- the actual file handle
  878. * nReason -- transfer status code
  879. * pszRemoteName -- the file name as it was sent to us
  880. * pszOurName -- the file name we actually used to save the data
  881. * nSave -- partial save flag
  882. * lFilesize -- size to set the file to
  883. * lTime -- date/time value to use to set the file
  884. *
  885. * RETURNS:
  886. * TRUE if the transfer was successful, otherwise FALSE.
  887. *
  888. */
  889. int xfer_close_rcv_file(HSESSION Hsession,
  890. void *vhdl,
  891. int nReason,
  892. TCHAR *pszRemoteName,
  893. TCHAR *pszOurName,
  894. int nSave,
  895. unsigned long lFilesize,
  896. unsigned long lTime) /* Fix this later */
  897. {
  898. ST_IOBUF *fhdl = (ST_IOBUF *)vhdl;
  899. if (nReason == TSC_COMPLETE)
  900. nReason = TSC_OK;
  901. if (fio_close(fhdl) == 0)
  902. {
  903. /* Set the size */
  904. if (lFilesize > 0 && nReason == TSC_OK) /*lFilesize != 0 jmh 03-08-96 */
  905. SetFileSize(pszOurName, lFilesize);
  906. /* Set the date/time */
  907. if (lTime != 0)
  908. itimeSetFileTime(pszOurName, lTime);
  909. }
  910. else
  911. {
  912. nReason = TSC_DISK_ERROR;
  913. }
  914. #if FALSE
  915. // Lower Wacker does not log transfers */
  916. xfer_log_xfer(hSession, FALSE, pszRemoteName, pszOurName, nReason);
  917. #endif
  918. if (nReason == TSC_OLDER_FILE)
  919. nReason = TSC_OK;
  920. if (nReason != TSC_OK && pszOurName && *pszOurName)
  921. {
  922. if (nSave == FALSE)
  923. DeleteFile(pszOurName);
  924. }
  925. if (nReason == TSC_LOST_CARRIER)
  926. {
  927. nReason = TSC_OK;
  928. }
  929. return (nReason == TSC_OK);
  930. }
  931. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  932. * FUNCTION:
  933. * xfer_get_params
  934. *
  935. * DESCRIPTION:
  936. * This function gets the protocol specific parameters for the transfer
  937. * routines.
  938. *
  939. * PARAMETERS:
  940. * hSession -- the session handle
  941. * nProtocol -- the protocol ID
  942. *
  943. * RETURNS:
  944. * A pointer to the protocol block, or a NULL.
  945. *
  946. */
  947. VOID FAR * xfer_get_params(HSESSION hSession, int nProtocol)
  948. {
  949. void *pVret = (void *)0;
  950. XD_TYPE *pX;
  951. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  952. if (pX)
  953. {
  954. int nLimit = SFID_PROTO_PARAMS_END - SFID_PROTO_PARAMS;
  955. if (nProtocol < nLimit)
  956. {
  957. if (pX->xfer_proto_params[nProtocol] == NULL)
  958. {
  959. int nRet = xfrInitializeParams(hSession,
  960. nProtocol,
  961. &pX->xfer_proto_params[nProtocol]);
  962. assert(nRet == 0);
  963. }
  964. pVret = (VOID FAR *)pX->xfer_proto_params[nProtocol];
  965. }
  966. }
  967. return pVret;
  968. }
  969. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  970. * FUNCTION:
  971. * xfer_set_comport
  972. *
  973. * DESCRIPTION:
  974. * This function is called to save the current com port settings so that the
  975. * transfer code can go ahead and change them to whatever it likes.
  976. *
  977. * PARAMETERS:
  978. * hSession -- the session handle
  979. * fSending -- TRUE if sending, FALSE if receiving
  980. * puiOldOptions -- where to store the old settings
  981. *
  982. * RETURNS:
  983. * TRUE if everything was OK, otherwise FALSE
  984. *
  985. */
  986. int xfer_set_comport(HSESSION hSession, int fSending, unsigned *puiOldOptions)
  987. {
  988. unsigned uiOptions = COM_OVERRIDE_8BIT;
  989. unsigned uiOldOptions;
  990. if (fSending)
  991. bitset(uiOptions, COM_OVERRIDE_SNDALL);
  992. else
  993. bitset(uiOptions, COM_OVERRIDE_RCVALL);
  994. /* TODO: find out how to decide which things need to be changed, BFMI */
  995. if (ComOverride(sessQueryComHdl(hSession),
  996. uiOptions,
  997. &uiOldOptions) != COM_OK)
  998. {
  999. return FALSE;
  1000. }
  1001. if (puiOldOptions != NULL)
  1002. *puiOldOptions = uiOldOptions;
  1003. return TRUE;
  1004. }
  1005. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1006. * FUNCTION:
  1007. * xfer_restore_comport
  1008. *
  1009. * DESCRIPTION:
  1010. * This function is called to restore the parameters that the previous call
  1011. * saved.
  1012. *
  1013. * PARAMETERS:
  1014. * hSession -- the session handle
  1015. * uiOldOptions -- the old comm parameters
  1016. *
  1017. * RETURNS:
  1018. * TRUE if everything was OK, otherwise FALSE
  1019. *
  1020. */
  1021. int xfer_restore_comport(HSESSION hSession, unsigned uiOldOptions)
  1022. {
  1023. ComSndBufrWait(sessQueryComHdl(hSession), 10);
  1024. // Let any trailing data get sent
  1025. ComSndBufrWait(sessQueryComHdl(hSession), 10);
  1026. if (ComOverride(sessQueryComHdl(hSession), uiOldOptions, NULL) != COM_OK)
  1027. return FALSE;
  1028. return TRUE;
  1029. }
  1030. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1031. * FUNCTION:
  1032. * xfer_save_partial
  1033. *
  1034. * DESCRIPTION:
  1035. * This function is called by the transfer routines to decide if it is
  1036. * OK to leave a partial file around if a transfer is aborted.
  1037. *
  1038. * PARAMETERS:
  1039. * hSession -- the session handle
  1040. *
  1041. * RETURNS:
  1042. * TRUE if it is OK, otherwise FALSE
  1043. *
  1044. */
  1045. int xfer_save_partial(HSESSION hSession)
  1046. {
  1047. XD_TYPE *pX;
  1048. XFR_PARAMS *pP;
  1049. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  1050. if (pX)
  1051. {
  1052. pP = (XFR_PARAMS *)pX->xfer_params;
  1053. if (pP)
  1054. {
  1055. return pP->fSavePartial;
  1056. }
  1057. }
  1058. return FALSE;
  1059. }
  1060. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1061. * FUNCTION:
  1062. * xfer_nextfile
  1063. *
  1064. * DESCRIPTION:
  1065. * This function is called by the transfer routines to get the name of the
  1066. * next file that is to be sent on over to the other side.
  1067. *
  1068. * PARAMETERS:
  1069. * hSession -- the session handle
  1070. * filename -- where to copy the file name
  1071. *
  1072. * RETURNS:
  1073. * TRUE if there was a filename available, otherwise FALSE
  1074. *
  1075. */
  1076. int xfer_nextfile(HSESSION hSession, TCHAR *filename)
  1077. {
  1078. XD_TYPE *pX;
  1079. XFR_SEND *pS;
  1080. LPTSTR pszStr;
  1081. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  1082. if (pX)
  1083. {
  1084. pS = (XFR_SEND *)pX->pXferStuff;
  1085. if (pS)
  1086. {
  1087. if (pS->nIndex < pS->nCount)
  1088. {
  1089. pszStr = pS->pList[pS->nIndex].pszName;
  1090. StrCharCopy(filename, pszStr);
  1091. pS->nIndex += 1;
  1092. /*
  1093. * TODO: decide where the memory gets freed
  1094. */
  1095. return TRUE;
  1096. }
  1097. }
  1098. }
  1099. return FALSE;
  1100. }
  1101. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1102. * FUNCTION:
  1103. * xfer_log_xfer
  1104. *
  1105. * DESCRIPTION:
  1106. * This function is called after a file is sent or received to place that
  1107. * information in the log file.
  1108. *
  1109. * PARAMETERS:
  1110. * hSession -- the session handle
  1111. * sending -- TRUE if the file was sent, otherwise FALSE
  1112. * theirname -- the name that was given to the other system
  1113. * ourname -- the name of the file on this system
  1114. * result -- the final transfer status code
  1115. *
  1116. * RETURNS:
  1117. * Nothing.
  1118. *
  1119. */
  1120. void xfer_log_xfer(HSESSION hSession,
  1121. int sending,
  1122. TCHAR *theirname,
  1123. TCHAR *ourname,
  1124. int result)
  1125. {
  1126. /*
  1127. * Lower Wacker does not do transfer logging. This is here mostly as a
  1128. * place holder and for the eventual conversion to Upper Wacker.
  1129. */
  1130. }
  1131. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1132. * FUNCTION:
  1133. * xfer_opensendfile
  1134. *
  1135. * DESCRIPTION:
  1136. * This function is called to open a file that is to be sent to another
  1137. * system.
  1138. *
  1139. * PARAMETERS:
  1140. * hSession -- the session handle
  1141. * fp -- where to store the open file handle
  1142. * file_to_open -- the name of the file to open (duh!)
  1143. * size -- where to save the size of the file
  1144. * name_to_send -- what name to send to the other system
  1145. * ft -- currently unused
  1146. *
  1147. * RETURNS:
  1148. * 0 if everything is OK
  1149. * -1 if an error occurred
  1150. * -2 if the file was not found
  1151. *
  1152. */
  1153. int xfer_opensendfile(HSESSION hSession,
  1154. HANDLE *fp,
  1155. TCHAR *file_to_open,
  1156. long *size,
  1157. TCHAR *name_to_send,
  1158. void *ft)
  1159. {
  1160. DWORD dwFoo;
  1161. *fp = (HANDLE)0;
  1162. /*
  1163. * Just try an open the file
  1164. */
  1165. *fp = fio_open(file_to_open, FIO_READ);
  1166. if (*fp == NULL)
  1167. {
  1168. *fp = (HANDLE)0;
  1169. return -1;
  1170. }
  1171. /*
  1172. * Got the file open, get the size
  1173. */
  1174. *size = GetFileSize(fio_gethandle((ST_IOBUF *)*fp), &dwFoo);
  1175. /*
  1176. * TODO: do the date and time stuff
  1177. */
  1178. /*
  1179. * Give them a file name
  1180. */
  1181. if (name_to_send != NULL)
  1182. xfer_name_to_send(hSession, file_to_open, name_to_send);
  1183. return 0;
  1184. }
  1185. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1186. * FUNCTION:
  1187. * xfer_name_to_send
  1188. *
  1189. * DESCRIPTION:
  1190. * This function is called to modify the file name into some sort of form
  1191. * that should be sent over to the other side. Kind of sounds like an
  1192. * exchange of captured spys at Checkpoint Charlie.
  1193. *
  1194. * PARAMETERS:
  1195. * hSession -- the session handle
  1196. * local_name -- what the name is on this system
  1197. * name_to_send -- where to put the processed name
  1198. *
  1199. * RETURNS:
  1200. * Nothing.
  1201. *
  1202. */
  1203. void xfer_name_to_send(HSESSION hSession,
  1204. TCHAR *local_name,
  1205. TCHAR *name_to_send)
  1206. {
  1207. TCHAR *pszStr;
  1208. XD_TYPE *pX;
  1209. XFR_PARAMS *pP;
  1210. if (local_name == NULL)
  1211. return;
  1212. if (name_to_send == NULL)
  1213. return;
  1214. pX = (XD_TYPE *)sessQueryXferHdl(hSession);
  1215. if (pX)
  1216. {
  1217. pP = (XFR_PARAMS *)pX->xfer_params;
  1218. if (pP)
  1219. {
  1220. if (pP->fIncPaths)
  1221. {
  1222. StrCharCopy(name_to_send, local_name);
  1223. }
  1224. }
  1225. }
  1226. /*
  1227. * Otherwise, just do this
  1228. */
  1229. pszStr = StrCharFindLast(local_name, TEXT('\\'));
  1230. if (*pszStr == TEXT('\\'))
  1231. pszStr += 1;
  1232. StrCharCopy(name_to_send, pszStr);
  1233. }