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.

719 lines
19 KiB

  1. /* File: C:\WACKER\xfer\hpr_rcv0.c (created: 24-Jun-1994)
  2. * created from HAWIN source file:
  3. * hpr_rcv0.c -- Routines to implement HyperProtocol receiver.
  4. *
  5. * Copyright 1989,1994 by Hilgraeve Inc. -- Monroe, MI
  6. * All rights reserved
  7. *
  8. * $Revision: 1 $
  9. * $Date: 10/05/98 1:16p $
  10. */
  11. #include <windows.h>
  12. #include <setjmp.h>
  13. #include <time.h>
  14. #include <term\res.h>
  15. #include <sys\types.h>
  16. #include <sys\utime.h>
  17. #include <tdll\stdtyp.h>
  18. #include <tdll\mc.h>
  19. // #include <tdll\com.h>
  20. #include <tdll\session.h>
  21. #include <tdll\load_res.h>
  22. #include <tdll\xfer_msc.h>
  23. #include <tdll\globals.h>
  24. #include <tdll\file_io.h>
  25. #if !defined(BYTE)
  26. #define BYTE unsigned char
  27. #endif
  28. #include "cmprs.h"
  29. #include "xfr_dsp.h"
  30. #include "xfr_todo.h"
  31. #include "xfr_srvc.h"
  32. #include "xfer.h"
  33. #include "xfer.hh"
  34. #include "xfer_tsc.h"
  35. #include "hpr.h"
  36. #include "hpr.hh"
  37. #include "hpr_sd.hh"
  38. /*
  39. * not all event codes in this table are needed here, but having a complete
  40. * table simplifies the lookup code substantially.
  41. */
  42. int hr_result_codes[] = /* maps HyperProtocol event codes to result codes */
  43. {
  44. TSC_OK, /* HRE_NONE */
  45. TSC_ERROR_LIMIT, /* HRE_DATAERR */
  46. TSC_OUT_OF_SEQ, /* HRE_LOSTDATA */
  47. TSC_NO_RESPONSE, /* HRE_NORESP */
  48. TSC_ERROR_LIMIT, /* HRE_RETRYERR */
  49. TSC_BAD_FORMAT, /* HRE_ILLEGAL */
  50. TSC_OK, /* HRE_ERRFIXED */
  51. TSC_RMT_CANNED, /* HRE_RMTABORT */
  52. TSC_USER_CANNED, /* HRE_USRCANCEL */
  53. TSC_NO_RESPONSE, /* HRE_TIMEOUT */
  54. TSC_ERROR_LIMIT, /* HRE_DCMPERR */
  55. TSC_LOST_CARRIER, /* HRE_LOST_CARR */
  56. TSC_TOO_MANY, /* HRE_TOO_MANY */
  57. TSC_DISK_FULL, /* HRE_DISK_FULL */
  58. TSC_CANT_OPEN, /* HRE_CANT_OPEN */
  59. TSC_DISK_ERROR, /* HRE_DISK_ERR */
  60. TSC_OLDER_FILE, /* HRE_OLDER_FILE */
  61. TSC_NO_FILETIME, /* HRE_NO_FILETIME */
  62. TSC_VIRUS_DETECT, /* HRE_VIRUS_DET */
  63. TSC_USER_SKIP, /* HRE_USER_SKIP */
  64. TSC_REFUSE /* HRE_REFUSE */
  65. };
  66. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  67. * hpr_rcv
  68. *
  69. * DESCRIPTION:
  70. * Receives files using the Hyperprotocol transfer method.
  71. *
  72. * ARGUMENTS:
  73. * attended -- True if the program determines that a user is likely to be
  74. * present at the computer keyboard. FALSE if a user is NOT
  75. * likely to be present (such as host and script modes)
  76. * single_file -- TRUE if user specified only a file name to receive the
  77. * result of the transfer as opposed to naming a dirctory.
  78. *
  79. * RETURNS:
  80. * TRUE if the transfer successfully completes. FALSE otherwise.
  81. */
  82. int hpr_rcv(HSESSION hSession, int attended, int single_file)
  83. {
  84. struct s_hc *hc;
  85. HCOM hCom;
  86. int usRetVal;
  87. int iret;
  88. int status;
  89. int result;
  90. int timeout_cnt = 0;
  91. int mtype;
  92. BYTE *mdata;
  93. char str[20];
  94. long timer;
  95. struct st_rcv_open stRcv;
  96. BYTE tmp_name[FNAME_LEN];
  97. hCom = sessQueryComHdl(hSession);
  98. hc = malloc(sizeof(struct s_hc));
  99. if (hc == NULL)
  100. return TSC_NO_MEM;
  101. memset(hc, 0, sizeof(struct s_hc));
  102. hc->hSession = hSession;
  103. /* initialize stuff */
  104. if (!hr_setup(hc))
  105. {
  106. free(hc);
  107. return TSC_NO_MEM;
  108. }
  109. /* initialize control variables */
  110. /* blocksize depends on the speed of the connection. Larger block sizes
  111. * can be used for faster connections. If the blocksize is too large,
  112. * error detection will be slow. If too small, there is unnecessary overhead
  113. */
  114. hc->blocksize = 2048;
  115. // hc->blocksize = xfer_blocksize(hSession);
  116. hc->current_filen = 0;
  117. hc->datacnt = hc->blocksize;
  118. hc->deadmantime = 600;
  119. hc->total_tries = 0;
  120. hc->total_thru = 0L;
  121. hc->total_dsp = 0L;
  122. hc->ucancel = FALSE;
  123. hc->usecrc = TRUE; /* first messages in will use CRC */
  124. hc->fhdl = NULL;
  125. hc->rc.checkpoint = 0L;
  126. hc->rc.files_expected = 0;
  127. hc->rc.bytes_expected = -1L;
  128. hc->rc.filesize = -1L;
  129. hc->rc.expected_msg = 0;
  130. hc->rc.cancel_reason = HRE_NONE;
  131. hc->rc.using_compression = FALSE;
  132. hc->rc.virus_detected = FALSE;
  133. hc->rc.hr_ptr_putc = hr_toss;
  134. hc->h_crc = hc->h_checksum = 0;
  135. omsg_init(hc, TRUE, FALSE);
  136. hc->rc.single_file = single_file; /* to the sender */
  137. /* Receiver begins the transfer by transmitting a starting message
  138. repeatedly until the sender begins */
  139. /* prepare the initial message */
  140. omsg_new(hc, 'c');
  141. /* tell sender who we are */
  142. hpr_id_get(hc, str);
  143. omsg_add(hc, str);
  144. /* we can express our opinion about what checktype and blocksize to use
  145. * but it will be up to the sender to make the final choice
  146. */
  147. wsprintf(str, "T%d", hc->h_chkt == H_CRC ? H_CRC : H_CHECKSUM);
  148. omsg_add(hc, str);
  149. wsprintf(str, "B%d", hc->blocksize);
  150. omsg_add(hc, str);
  151. /* let sender know whether we can handle compression */
  152. if (hc->h_trycompress & compress_enable());
  153. {
  154. omsg_add(hc, "C");
  155. }
  156. /* A restart 0,0 request causes sender to start */
  157. omsg_add(hc, "R0,0");
  158. /* send first response packet at intervals until first H_MSGCHAR
  159. * is received
  160. */
  161. status = H_OK;
  162. hrdsp_status(hc, HRS_REQSTART);
  163. timer = startinterval();
  164. stRcv.pszSuggestedName = "junk.jnk";
  165. stRcv.pszActualName = tmp_name;
  166. // stRcv.pstFtCompare = NULL;
  167. stRcv.lFileTime = 0;
  168. // stRcv.pfnVscanOutput = NULL;
  169. // stRcv.ssmchVscanHdl = (SSHDLMCH)0;
  170. // hc->rc.pfVirusCheck = MakeProcInstance((FARPROC)hr_virus_detect,
  171. // hSession->hInstance);
  172. // stRcv.pfnVscanOutput = (VOID (FAR *)(void *, int))hc->rc.pfVirusCheck;
  173. // transfer_build_rcv_name(&stRcv);
  174. xfer_build_rcv_name(hSession, &stRcv);
  175. // hc->rc.ssmchVscan = stRcv.ssmchVscanHdl;
  176. hc->xfertimer = -1;
  177. #if FALSE
  178. /* if we are the host, don't send an immediate start request because
  179. * the user probably had to start us first and then set himself up. If
  180. * we are the attended machine, though, the other end has probably already
  181. * been started.
  182. */
  183. // sendnext = (attended ? 0 : 40);
  184. // Changed to always try to start immediately since we may be responding
  185. // to auto-start in which case sender is already waiting
  186. sendnext = 0;
  187. repeat
  188. {
  189. hc->xfertimer = startinterval();
  190. if (mComRcvBufrPeek(hCom, &rcode) != 0)
  191. {
  192. if (rcode == H_MSGCHAR)
  193. {
  194. if (!hr_resynch(hSession, HRE_NONE))
  195. status = H_NOSTART;
  196. break;
  197. }
  198. // RemoteGet(); /* wrong character, remove it from buffer */
  199. mComRcvChar(hCom, &rcode);
  200. /* Other end can send us an ESC to cancel the transfer before
  201. * it ever gets started.
  202. */
  203. if ((rcode == ESC) || (rcode == CAN))
  204. {
  205. status = H_RMTABORT;
  206. hrdsp_event(hSession, hc->rc.cancel_reason = HRE_RMTABORT);
  207. break;
  208. }
  209. }
  210. /* We can't wait forever to get started. If we haven't seen a start
  211. * character in H_START_WAIT seconds, give up.
  212. */
  213. if ((time = interval(timer)) > H_START_WAIT * 10)
  214. {
  215. status = H_NOSTART;
  216. hc->rc.cancel_reason = HRE_NORESP;
  217. break;
  218. }
  219. /* see if it's time to send another startup request */
  220. else if (time > sendnext || (rcode & 0x7F) == '\r')
  221. {
  222. sendnext = time + 40; /* send again in 4 seconds */
  223. omsg_send(hc, 1, FALSE, TRUE);
  224. }
  225. /* finally, see if someone at keyboard want's us to stop trying */
  226. iret = xfer_user_interrupt(hSession);
  227. if (iret == XFER_ABORT)
  228. {
  229. status = H_USERABORT;
  230. hrdsp_event(hSession, hc->rc.cancel_reason = HRE_USRCANCEL);
  231. break;
  232. }
  233. else if (iret == XFER_SKIP)
  234. {
  235. hr_reject_file(hSession, HRE_USER_SKIP);
  236. }
  237. hpr_idle(hSession);
  238. }
  239. #endif
  240. omsg_send(hc, 1, FALSE, TRUE);
  241. if (!hr_resynch(hc, HRE_NONE))
  242. status = H_NOSTART;
  243. /* If status is still H_OK, it means we've synched with sender.
  244. * We'll stay in this loop now until the transfer is finished.
  245. */
  246. while (status == H_OK)
  247. {
  248. hr_still_alive(hc, FALSE, FALSE); /* check whether deadman msg
  249. is in order */
  250. hrdsp_progress(hc, 0); /* keep user notified */
  251. /* Collect blocks of data, which may be interrupted by messages
  252. * from the sender.
  253. */
  254. result = hr_collect_data(hc, &hc->datacnt, TRUE, H_CHARTIME);
  255. if (result != HR_TIMEOUT)
  256. timeout_cnt = 0;
  257. switch(result)
  258. {
  259. case HR_VIRUS_FOUND:
  260. goto virus_found;
  261. case HR_COMPLETE:
  262. /* got all chars. we asked for, setup to receive another
  263. * full block
  264. */
  265. hc->rc.checkpoint = hc->h_filebytes;
  266. hc->h_checksum = hc->h_crc = 0;
  267. hc->datacnt = hc->blocksize;
  268. break;
  269. case HR_DCMPERR :
  270. /* data error caused decompression algorithm to fail */
  271. if (!hr_restart(hc, HRE_DCMPERR))
  272. status = H_NORESYNCH;
  273. break;
  274. case HR_BADCHECK :
  275. /* got complete block but checksum or CRC didn't match */
  276. if (!hr_restart(hc, HRE_DATAERR))
  277. status = H_NORESYNCH;
  278. break;
  279. case HR_LOSTDATA :
  280. /* received block n+1 before block n */
  281. if (!hr_restart(hc, HRE_LOSTDATA))
  282. status = H_NORESYNCH;
  283. break;
  284. case HR_MESSAGE:
  285. /* Block of data was interrupted by a message. All that's
  286. * actually been detected is a message character in the data,
  287. * we must now extract and analyze the message
  288. */
  289. switch(result = hr_collect_msg(hc, &mtype, &mdata, H_CHARTIME))
  290. {
  291. case HR_KBDINT:
  292. /* local user interrupted us while receiving the message
  293. * if user had interrupted us once and is doing it again
  294. * while we are attempting to tell the other end what we're
  295. * doing, drop out immediately and leave the sender to fend
  296. * for himself.
  297. */
  298. if (hc->ucancel)
  299. status = H_USERABORT;
  300. else
  301. {
  302. hr_kbdint(hc);
  303. /* try to let sender know what we're doing */
  304. if (!hr_cancel(hc, HRE_USRCANCEL))
  305. status = H_USERABORT;
  306. }
  307. break;
  308. case HR_TIMEOUT:
  309. case HR_BADMSG:
  310. case HR_BADCHECK:
  311. /* message was scrambled, try to resynch */
  312. if (!hr_restart(hc, HRE_DATAERR))
  313. status = H_NORESYNCH;
  314. break;
  315. case HR_LOSTDATA:
  316. /* message was recevied, but it was the wrong one */
  317. if (!hr_restart(hc, HRE_LOSTDATA))
  318. status = H_NORESYNCH;
  319. break;
  320. case HR_COMPLETE:
  321. /* message received ok, figure out what sender wants */
  322. status = hr_decode_msg(hc, mdata);
  323. break;
  324. }
  325. break;
  326. case HR_TIMEOUT:
  327. /* sender stopped sending to us, try to prod him into restartting */
  328. if (timeout_cnt++ < TIMEOUT_LIMIT)
  329. {
  330. /* TODO: generalize this
  331. if (cnfg.save_xprot)
  332. RemoteSendChar(cnfg.save_xon);
  333. */
  334. hr_still_alive(hc, TRUE, TRUE); /* send file ack and timeout msg */
  335. }
  336. else
  337. {
  338. status = H_TIMEOUT;
  339. hc->rc.cancel_reason = HRE_TIMEOUT;
  340. }
  341. break;
  342. case HR_KBDINT:
  343. /* user is trying to interrupt the transfer */
  344. if (hc->ucancel)
  345. status = H_USERABORT;
  346. else
  347. {
  348. hr_kbdint(hc);
  349. /* try to inform sender about what we are doing */
  350. if (!hr_cancel(hc, HRE_USRCANCEL))
  351. status = H_USERABORT;
  352. }
  353. break;
  354. case HR_LOST_CARR:
  355. /* we lost carrier while trying to transfer */
  356. if (!hr_cancel(hc, HRE_LOST_CARR))
  357. status = H_TIMEOUT;
  358. break;
  359. case HR_FILEERR:
  360. /* A file error occurred while trying to save incoming data */
  361. if (!hr_cancel(hc, HRE_DISK_ERR))
  362. status = H_FILEERR;
  363. break;
  364. }
  365. /* during full-bore transfers, the data collection routines won't
  366. * waste time checking the keyboard for an interrupt request from
  367. * the user or carrier loss so we'll check here at least once per
  368. * data block
  369. */
  370. iret = xfer_user_interrupt(hSession);
  371. if (iret == XFER_ABORT)
  372. {
  373. if (hc->ucancel)
  374. status = H_USERABORT;
  375. else
  376. {
  377. hr_kbdint(hc);
  378. if (!hr_cancel(hc, HRE_USRCANCEL))
  379. status = H_USERABORT;
  380. }
  381. }
  382. else if (iret == XFER_SKIP)
  383. {
  384. hr_reject_file(hc, HRE_USER_SKIP);
  385. }
  386. if (xfer_carrier_lost(hSession))
  387. if (!hr_cancel(hc, HRE_LOST_CARR))
  388. status = H_TIMEOUT;
  389. /* Actual virus detection occurs deep in the bowels of a transfer.
  390. * Therefore, the detecting routine merely sets a flag and begins
  391. * tossing data. We actually shut down here
  392. */
  393. virus_found:
  394. if (hc->rc.virus_detected)
  395. {
  396. hc->rc.virus_detected = FALSE; /* don't come in here again */
  397. if (!hr_cancel(hc, HRE_VIRUS_DET))
  398. status = H_USERABORT;
  399. }
  400. }
  401. /* Transfer is all done, 'status' indicates the final result. */
  402. hrdsp_progress(hc, TRANSFER_DONE);
  403. compress_disable();
  404. // if (stRcv.ssmchVscanHdl != (SSHDLMCH)0)
  405. // StrSrchStopSrch(stRcv.ssmchVscanHdl);
  406. // if (hc->rc.pfVirusCheck != NULL)
  407. // {
  408. // FreeProcInstance(hc->rc.pfVirusCheck);
  409. // hc->rc.pfVirusCheck = NULL;
  410. // }
  411. usRetVal = (int)hr_result_codes[hc->rc.cancel_reason];
  412. /* clear display, free memory, etc. */
  413. status = hr_wrapup(hc, attended, status);
  414. free(hc);
  415. return usRetVal;
  416. }
  417. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  418. * hr_collect_msg
  419. *
  420. * DESCRIPTION:
  421. * Called when a message has been detected within a block of data. Messages
  422. * start with H_MSGCHAR (0x01). If an H_MSGCHAR occurs as part of the data
  423. * being sent, it will be doubled. When it is encountered alone, this routine
  424. * is called to extract the following message from the stream of data.
  425. *
  426. * ARGUMENTS:
  427. * mtype -- pointer to a variable to be updated with the message type
  428. * mdata -- pointer to a variable to be updated with the address of the
  429. * message data
  430. * timeout -- amount of time (in tenths of seconds) to wait for the data
  431. * to complete the message.
  432. *
  433. * RETURNS:
  434. * Returns a status code:
  435. * HR_COMPLETE -- message successfully received
  436. * HR_BADCHECK -- crc or checksum error on message data
  437. * HR_TIMEOUT -- time out exceeded while waiting for data
  438. * HR_KBDINT -- user interrupted from keyboard
  439. * HR_BADMSG -- message data was not in recognized format
  440. * HR_LOSTDATA -- message was complete but message number was not the
  441. * expected one.
  442. * HR_LOST_CARR --Lost carrier while collecting message
  443. */
  444. // char FAR *storageptr; /* place to put data as we receive it */
  445. int hr_collect_msg(struct s_hc *hc,
  446. int *mtype,
  447. BYTE **mdata,
  448. long timeout)
  449. {
  450. unsigned hold_checksum;
  451. unsigned hold_crc;
  452. int gotlen = FALSE;
  453. int count;
  454. int result = HR_UNDECIDED;
  455. int (*holdptr)(void *, int);
  456. int msgn;
  457. /* since a message is embedded within a data block, we need to preserve
  458. * a few values for the interrupted data collection routine.
  459. */
  460. holdptr = hc->rc.hr_ptr_putc;
  461. /* set collection routine to store data for us */
  462. hc->rc.hr_ptr_putc = hr_storedata;
  463. hold_checksum = hc->h_checksum;
  464. hold_crc = hc->h_crc;
  465. hc->h_checksum = 0; /* messages have their own check bytes */
  466. hc->h_crc = 0;
  467. /* We will retrieve the message in two parts, first we'll get the type and
  468. * length fields, then, based on those, we can collect the rest of the
  469. * message.
  470. */
  471. hc->storageptr = hc->rc.rmsg_bufr;
  472. count = 2;
  473. while (result == HR_UNDECIDED)
  474. {
  475. switch (result = hr_collect_data(hc, &count, FALSE, timeout))
  476. {
  477. case HR_COMPLETE:
  478. if (!gotlen)
  479. {
  480. /* got first part, set up to get rest of message */
  481. result = HR_UNDECIDED;
  482. *mtype = hc->rc.rmsg_bufr[0];
  483. count = hc->rc.rmsg_bufr[1];
  484. if (count < 3)
  485. result = HR_BADMSG;
  486. gotlen = TRUE;
  487. }
  488. else
  489. {
  490. /* got everything, check for valid message */
  491. msgn = hc->rc.rmsg_bufr[2];
  492. count = hc->rc.rmsg_bufr[1];
  493. if (hc->usecrc)
  494. {
  495. if (hc->h_crc != 0)
  496. result = HR_BADCHECK;
  497. }
  498. else
  499. {
  500. hc->h_checksum -= hc->rc.rmsg_bufr[count];
  501. hc->h_checksum -= hc->rc.rmsg_bufr[count + 1];
  502. if (hc->rc.rmsg_bufr[count] != (BYTE)(hc->h_checksum % 256) ||
  503. hc->rc.rmsg_bufr[count + 1] !=
  504. (BYTE)(hc->h_checksum / 256))
  505. result = HR_BADCHECK;
  506. }
  507. hc->rc.rmsg_bufr[count] = '\0';
  508. }
  509. break;
  510. case HR_LOST_CARR:
  511. case HR_TIMEOUT:
  512. case HR_KBDINT:
  513. /* return same result */
  514. break;
  515. case HR_MESSAGE:
  516. /* we encountered what looked like a message within a message
  517. * but that is illegal
  518. */
  519. result = HR_BADMSG;
  520. break;
  521. }
  522. }
  523. /* we're done, restore details for overlying data collection routine */
  524. hc->rc.hr_ptr_putc = holdptr;
  525. hc->h_checksum = hold_checksum;
  526. hc->h_crc = hold_crc;
  527. *mdata = &hc->rc.rmsg_bufr[3];
  528. if (result == HR_COMPLETE)
  529. {
  530. if (msgn != hc->rc.expected_msg)
  531. result = HR_LOSTDATA;
  532. else
  533. hc->rc.expected_msg = ++hc->rc.expected_msg % 256;
  534. }
  535. return(result);
  536. }
  537. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  538. * hr_still_alive
  539. *
  540. * DESCRIPTION:
  541. * This routine is called periodically during receiving. It determines
  542. * whether it is time to send the sender a 'deadman' message. Since there
  543. * is no regular response from the receiver to the sender unless errors
  544. * occur, the deadman message prevents the sender from sending into a void
  545. * for long periods of time. If the sender doesn't receive ANYTHING from
  546. * the receiver for the negotiated deadman time, it can assume the receiver
  547. * is no longer active.
  548. *
  549. * ARGUMENTS:
  550. * force -- TRUE if a deadman notification should be sent whether it is
  551. * officially time for one or not.
  552. * timed_out -- TRUE if receiver has timeout and we want sender to know that.
  553. *
  554. * RETURNS:
  555. * nothing
  556. */
  557. void hr_still_alive(struct s_hc *hc, int force, int timed_out)
  558. {
  559. char msg[20];
  560. if (force || (long)interval(omsg_last(hc)) >= hc->deadmantime)
  561. {
  562. omsg_new(hc, 'c');
  563. if (timed_out)
  564. omsg_add(hc, "t");
  565. /* While we're talking to the sender, we'll let him know how much
  566. * we've actually received. This lets him clear the table of
  567. * unacknowledged files that he keeps.
  568. */
  569. // StrFmt(msg, "f%d,%lu", hc->current_filen, hc->rc.checkpoint);
  570. wsprintf(msg, "f%d,%lu", hc->current_filen, hc->rc.checkpoint);
  571. omsg_add(hc, msg);
  572. omsg_send(hc, BURSTSIZE, FALSE, FALSE);
  573. }
  574. }
  575. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  576. * hr_kbdint
  577. *
  578. * DESCRIPTION:
  579. *
  580. *
  581. * ARGUMENTS:
  582. *
  583. *
  584. * RETURNS:
  585. *
  586. */
  587. void hr_kbdint(struct s_hc *hc)
  588. {
  589. /* TODO: fix this somehow
  590. if (!hc->ucancel)
  591. errorline(FALSE, strld(TM_WAIT_CONF));
  592. */
  593. hc->ucancel = TRUE;
  594. }
  595. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  596. * hr_suspend_input
  597. *
  598. * DESCRIPTION:
  599. *
  600. *
  601. * ARGUMENTS:
  602. *
  603. *
  604. * RETURNS:
  605. *
  606. */
  607. void hr_suspend_input(void *hS, int suspend)
  608. {
  609. #if FALSE
  610. if (suspend)
  611. suspendinput(FLG_DISK_ACTIVE, 5);
  612. else
  613. allowinput(FLG_DISK_ACTIVE);
  614. #endif
  615. }
  616. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  617. * hr_check_input
  618. *
  619. * DESCRIPTION:
  620. *
  621. * ARGUEMENTS:
  622. *
  623. * RETURNS:
  624. *
  625. */
  626. void hr_check_input(void *hS, int suspend)
  627. {
  628. }
  629. /********************** end of hpr_rcv0.c ***************************/