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.

3165 lines
85 KiB

  1. /* File: D:\WACKER\comwsock\comwsock.c (Created: 12/26/95)
  2. *
  3. * Copyright 1996 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 22 $
  7. * $Date: 7/08/02 6:31p $
  8. *
  9. * $Log: /Products/wacker/Comwsock/Comwsock.c $
  10. *
  11. * 22 7/08/02 6:31p Dans
  12. * Replaced StrCharCopy to StrCharCopyN to protect against buffer
  13. * overruns.
  14. *
  15. * 21 5/31/02 3:48p Ronv
  16. * fAnswer is a flag i n the ST_STDCOM structure. This revision makes
  17. * sure the value is set to FALSE (this did not cause any problems in the
  18. * past since FALSE is defined as 0 on Windows).
  19. *
  20. * 19 4/30/02 4:02p Ronv
  21. * Handles to events should not use INVALID_HANDLE_VALUE since that is
  22. * just a value to be used for file handles.
  23. *
  24. * 18 4/16/02 2:36p Ronv
  25. * No need to register the window class again if it is already registered.
  26. *
  27. * 17 4/10/02 3:12p Ronv
  28. * Now using INVALID_HANDLE_VALUE to make sure the Com handles (event
  29. * handles) are released and freed correctly.
  30. *
  31. * 16 4/05/02 4:26p Ronv
  32. * Cleaned up some logic in WsckSndBufrSend() to release the critical
  33. * section as soon as possible so that we don't get into a thread lock.
  34. *
  35. * 15 3/22/02 1:53p Ronv
  36. *
  37. * 14 3/20/02 11:45a Ronv
  38. * Revisions per MS to cleaning up the use of handles outside of crital
  39. * locks (MS security review).
  40. *
  41. * 13 2/25/02 1:17p Ronv
  42. * 02-19-2002 MS Source Code Drop
  43. *
  44. * 12 1/18/02 4:59p Ronv
  45. * Made sure the serial port defaults are used when the serial port is
  46. * selected for the first time, or the serial port selected is not the
  47. * same as what is currently set in the session.
  48. *
  49. * Also, changed to using the StrCharxxx() functions in HTCHAR.H for
  50. * maintainability.
  51. *
  52. * 11 11/08/01 11:05a Ronv
  53. * Revisions to use the COM_PORT defines for the states of the connection
  54. * to be consistent with serial and other TAPI devices.
  55. *
  56. * 10 5/09/01 4:43p Ronv
  57. * Changed tcahr.h to htchar.h per MS request to resolve some build
  58. * issues. Also other misc. #include revisions.
  59. *
  60. * 9 3/22/01 11:26a Ronv
  61. * Removed previous revisions needed (include shfusion.h) for Windows XP
  62. * Themeing.
  63. *
  64. * 8 2/27/01 5:45p Ronv
  65. * Revisions needed (include shfusion.h) for Windows XP Themeing.
  66. *
  67. * 7 2/16/01 4:01p Ronv
  68. * Fix for not dereferencing a null pointer.
  69. *
  70. * 6 12/21/00 11:15a Ronv
  71. * Corrected usage of sizeof().
  72. *
  73. * 5 11/07/00 12:06p Ronv
  74. * Fix for setting character in a TCHAR array to correct NULL character.
  75. *
  76. * Fix for setting character in a TCHAR array to correct NULL character.
  77. *
  78. * Using StrCharCopyN() instead of StrCharCopy() to make sure there is not
  79. * a buffer overrun.
  80. *
  81. *
  82. * 4 9/20/00 4:54p Ronv
  83. * Fix for buffer overrun in with WINSOCK sessions when the URL was > 116
  84. * characters. We will now truncate the URL to 127 characters to make
  85. * sure we don't overwrite the buffer allocated for the URL.
  86. *
  87. * 3 11/16/99 9:56a Johnh
  88. * Fixed bug reported by IBM that isolated, unsupported NVT control
  89. * sequences (when sent alone) caused cursor movement.
  90. *
  91. * 2 2/05/99 3:20p Supervisor
  92. * 64-bit changes and bug fixes for Microsoft
  93. *
  94. * 1 10/05/98 1:02p Supervisor
  95. * Revision 1.16 1998/09/11 11:41:41 JKH
  96. * none
  97. *
  98. * Revision 1.15 1998/09/10 14:54:58 bld
  99. * none
  100. *
  101. * Revision 1.14 1998/09/10 11:04:39 bld
  102. * none
  103. *
  104. * Revision 1.13 1998/09/09 16:15:37 rev
  105. * none
  106. *
  107. * Revision 1.12 1998/08/28 15:24:13 rev
  108. * none
  109. *
  110. * Revision 1.11 1998/08/28 10:31:23 bld
  111. * none
  112. *
  113. * Revision 1.10 1998/06/17 16:04:17 JKH
  114. * none
  115. *
  116. * Revision 1.9 1998/03/10 15:49:00 bld
  117. * none
  118. *
  119. * Revision 1.8 1997/03/24 09:53:07 JKH
  120. * Added Telnet break and command line telnet port selection
  121. *
  122. * Revision 1.7 1997/02/26 09:34:37 dmn
  123. * none
  124. *
  125. * Revision 1.6 1996/11/21 14:15:43 cab
  126. * Added call answering
  127. *
  128. * Revision 1.5 1996/02/22 14:24:07 jmh
  129. * Winsock com driver now uses same private data structure as standard com.
  130. *
  131. * Revision 1.4 1996/02/22 11:22:39 mcc
  132. * none
  133. *
  134. * Revision 1.3 1996/02/22 10:20:19 mcc
  135. * none
  136. *
  137. * Revision 1.2 1996/02/05 14:17:12 mcc
  138. * none
  139. *
  140. * Revision 1.1 1996/01/31 15:52:15 mcc
  141. * Winsock Comm driver
  142. *
  143. *Design Overview =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  144. This module would do Dr. Frankenstein proud ... it's basic structure is
  145. taken from WACKER's COMSTD module, but the internal logic is taken from
  146. HAWIN. (I tried to port NPORT's OS/2 code but there is apparently some
  147. flaw in Win95's support for threaded Winsock apps, anyway I could not
  148. get it to work). This code is preserved here (controlled by #ifdef
  149. MULTITHREAD), it would be interesting to see if it works under Windows NT.
  150. A few random bits from NPORT are stitched in too ...
  151. This driver gets its remote address and port number settings from the
  152. connection driver via DeviceSpecial calls. It stores nothing in
  153. the session file, so those load/save calls are stubs.
  154. Tidbits of possibly useful information:
  155. Sometimes a send() appears to succeed but no data appears at the other
  156. end. It appears that sometimes Winsock is internally waiting forever
  157. for something to happen, and never actually sends the data. This
  158. might be caused by a recv() call outstanding that asks for
  159. a large amount of data, and maybe the send() call can't get enough
  160. memory until it completes (but it never WILL complete because the
  161. other system is waiting for data). Also, I've seen this happening
  162. with the MULTITHREAD code, possibly due to a Winsock bug
  163. under Win95.
  164. The EscFF business is because Telnet (a protocol on top of TCP/IP
  165. that we will often encounter) uses FF as a command character,
  166. and sends FF FF as a literal FF. Thus, file transfers to
  167. a system running Telnet must escape FF characters in a file
  168. by doubling them.
  169. The STDCOM drivers work by activating the port then sending
  170. data out to dial the modem, thus there is no ComConnect
  171. call in the high-level Com API. For better or worse, TCP/IP
  172. requires that the IP address and Port number be supplied
  173. by the CNCT driver (via ComDeviceSpecial calls) before
  174. ComActivatePort is called so that activating the port actually
  175. establishes the link to the other system. In this kinda kludgy
  176. non-threaded implementation, ComActivatePort cannot block, so
  177. it will return success if it can successfully send out a
  178. connection request. If the request ultimately fails, this
  179. driver will call ComNotify to let the CNCT driver know that there
  180. is a connection status change, and it must pick up the pieces.
  181. *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  182. //#define DEBUGSTR
  183. #include <windows.h>
  184. #pragma hdrstop
  185. #include <tdll\stdtyp.h>
  186. #if defined(INCL_WINSOCK)
  187. #include <tdll\session.h>
  188. #include <tdll\mc.h>
  189. #include <tdll\sf.h>
  190. #include <tdll\timers.h>
  191. #include <tdll\com.h>
  192. #include <tdll\comdev.h>
  193. #include <comstd\comstd.hh>
  194. #include "comwsock.hh"
  195. #include <tdll\assert.h>
  196. #include <tdll\statusbr.h>
  197. #include <tdll\htchar.h>
  198. #include <tdll\com.hh>
  199. BOOL WINAPI _CRT_INIT(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved);
  200. int wsckResolveAddress(TCHAR *pszRemote, unsigned long *pulAddr);
  201. LRESULT FAR PASCAL WndSockWndProc(HWND hWnd, UINT uiMsg, WPARAM uiPar1, LPARAM lPar2);
  202. BOOL WinSockCreateEventWindow (ST_STDCOM *pstPrivate);
  203. int FAR PASCAL sndQueueAppend(ST_STDCOM *pstPrivate,
  204. VOID FAR *pvBufr, int nBytesToAppend);
  205. int WinSockConnectSpecial(ST_STDCOM *pstPrivate);
  206. int WinSockAnswerSpecial(ST_STDCOM *pstPrivate);
  207. LONG WinSockConnectEvent(ST_STDCOM* pstPrivate, LPARAM lPar);
  208. LONG WinSockReadEvent(ST_STDCOM* pstPrivate, LPARAM lPar);
  209. LONG WinSockWriteEvent(ST_STDCOM*pstPrivate, LPARAM lPar);
  210. LONG WinSockResolveEvent(ST_STDCOM* pstPrivate, LPARAM lPar);
  211. LONG WinSockCloseEvent(ST_STDCOM* pstPrivate, LPARAM lPar);
  212. LONG WinSockAcceptEvent(ST_STDCOM*pstPrivate, LPARAM lPar);
  213. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  214. * FUNCTION:
  215. * ComLoadWinsockDriver
  216. *
  217. * DESCRIPTION:
  218. * Loads the COM handle with pointers to the Winsock driver functions
  219. *
  220. * ARGUMENTS:
  221. *
  222. * RETURNS:
  223. * COM_OK if successful
  224. * COM_FAILED otherwise
  225. *
  226. * AUTHOR:
  227. * mcc 12/26/95
  228. */
  229. int ComLoadWinsockDriver(HCOM pstCom)
  230. {
  231. int iRetVal = COM_OK;
  232. if ( !pstCom )
  233. return COM_FAILED;
  234. pstCom->pfPortActivate = WsckPortActivate;
  235. pstCom->pfPortDeactivate = WsckPortDeactivate;
  236. pstCom->pfPortConnected = WsckPortConnected;
  237. pstCom->pfRcvRefill = WsckRcvRefill;
  238. pstCom->pfRcvClear = WsckRcvClear;
  239. pstCom->pfSndBufrSend = WsckSndBufrSend;
  240. pstCom->pfSndBufrIsBusy = WsckSndBufrIsBusy;
  241. pstCom->pfSndBufrClear = WsckSndBufrClear;
  242. pstCom->pfSndBufrQuery = WsckSndBufrQuery;
  243. pstCom->pfDeviceSpecial = WsckDeviceSpecial;
  244. pstCom->pfPortConfigure = WsckPortConfigure;
  245. return iRetVal;
  246. }
  247. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  248. * FUNCTION:
  249. * WsckComWinsockEntry
  250. *
  251. * DESCRIPTION:
  252. * Currently, just initializes the C-Runtime library but may be used
  253. * for other things later.
  254. *
  255. * ARGUMENTS:
  256. * hInstDll - Instance of this DLL
  257. * fdwReason - Why this entry point is called
  258. * lpReserved - reserved
  259. *
  260. * RETURNS:
  261. * BOOL
  262. *
  263. * AUTHOR:
  264. * mcc 12/26/95
  265. */
  266. BOOL WINAPI WsckComWinsockEntry(HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved)
  267. {
  268. hinstDLL = hInst;
  269. return _CRT_INIT(hInst, fdwReason, lpReserved);
  270. }
  271. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  272. * FUNCTION: WsckDeviceInitialize
  273. *
  274. * DESCRIPTION:
  275. * Called whenever the driver is being loaded
  276. *
  277. * ARGUMENTS:
  278. * hCom -- A copy of the com handle. Can be used in the
  279. * driver code to call com services
  280. * usInterfaceVersion -- A version number identifying the version of the
  281. * driver interface
  282. * ppvDriverData -- A place to put the pointer to our private data.
  283. * This value will be passed back to us in all
  284. * subsequent calls.
  285. *
  286. * RETURNS:
  287. * COM_OK if all is hunky dory
  288. * COM_DEVICE_VERSION_ERROR if Wacker expects a different interface version.
  289. * COM_NOT_ENOUGH_MEMORY
  290. * COM_DEVICE_ERROR if anything else goes wrong
  291. *
  292. * AUTHOR:
  293. * mcc 12/26/95
  294. */
  295. int WINAPI WsckDeviceInitialize(HCOM hCom,
  296. unsigned nInterfaceVersion,
  297. void **ppvDriverData)
  298. {
  299. int iRetVal = COM_OK;
  300. int ix;
  301. ST_STDCOM *pstPrivate = NULL;
  302. // Check version number and compatibility
  303. if (nInterfaceVersion != COM_VERSION)
  304. {
  305. // This error is reported by Com Routines. We cannot report errors
  306. // until after DeviceInitialize has completed.
  307. return COM_DEVICE_VERSION_ERROR;
  308. }
  309. if (*ppvDriverData)
  310. {
  311. pstPrivate = (ST_STDCOM*) *ppvDriverData;
  312. }
  313. else
  314. {
  315. // Allocate our private storage structure
  316. if ((pstPrivate = malloc(sizeof(*pstPrivate))) == NULL)
  317. {
  318. return COM_NOT_ENOUGH_MEMORY;
  319. }
  320. *ppvDriverData = pstPrivate;
  321. // These members are common to both com drivers
  322. //
  323. pstPrivate->hCom = hCom;
  324. pstPrivate->fNotifyRcv = TRUE;
  325. pstPrivate->dwEventMask = 0;
  326. pstPrivate->fSending = FALSE;
  327. pstPrivate->lSndTimer = 0L;
  328. pstPrivate->lSndLimit = 0L;
  329. pstPrivate->lSndStuck = 0L;
  330. pstPrivate->hwndEvents = (HWND)0;
  331. pstPrivate->nRBufrSize = WSOCK_SIZE_INQ;
  332. pstPrivate->pbBufrStart = NULL;
  333. pstPrivate->fHaltThread = TRUE;
  334. InitializeCriticalSection(&pstPrivate->csect);
  335. for (ix = 0; ix < EVENT_COUNT; ++ix)
  336. {
  337. pstPrivate->ahEvent[ix] = CreateEvent(NULL,
  338. TRUE, // must be manually reset
  339. FALSE, // create unsignalled
  340. NULL); // unnamed
  341. if (pstPrivate->ahEvent[ix] == NULL)
  342. {
  343. iRetVal = COM_FAILED;
  344. //
  345. // Make sure to initialize the rest of the event handles to NULL;
  346. //
  347. for (++ix; ix < EVENT_COUNT; ++ix)
  348. {
  349. pstPrivate->ahEvent[ix] = NULL;
  350. }
  351. }
  352. }
  353. }
  354. // Setup up reasonable default device values in case this type of
  355. // device has not been used in a session before
  356. pstPrivate->hSocket = INVALID_SOCKET;
  357. pstPrivate->nPort = 23;
  358. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  359. pstPrivate->hComReadThread = NULL;
  360. pstPrivate->hComWriteThread = NULL;
  361. pstPrivate->fEscapeFF = TRUE;
  362. #ifdef INCL_CALL_ANSWERING
  363. pstPrivate->fAnswer = FALSE;
  364. #endif
  365. if (iRetVal != COM_OK)
  366. {
  367. if (pstPrivate)
  368. {
  369. free(pstPrivate);
  370. pstPrivate = NULL;
  371. }
  372. }
  373. return iRetVal;
  374. }
  375. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  376. * FUNCTION: WsckDeviceClose
  377. *
  378. * DESCRIPTION:
  379. * Called when Wacker is done with this driver and is about to release .DLL
  380. *
  381. * ARGUMENTS:
  382. * pstPrivate -- Pointer to our private data structure
  383. *
  384. * RETURNS:
  385. * COM_OK
  386. *
  387. * AUTHOR:
  388. * mcc 01/19/96
  389. */
  390. int WINAPI WsckDeviceClose(void *pvPrivate)
  391. {
  392. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  393. int ix;
  394. // Driver is about to be let go, do any cleanup
  395. // Port should have been deactivated before we are called, but
  396. // check anyway.
  397. WsckPortDeactivate(pstPrivate);
  398. for (ix = 0; ix < EVENT_COUNT; ++ix)
  399. {
  400. if (pstPrivate->ahEvent[ix])
  401. {
  402. CloseHandle(pstPrivate->ahEvent[ix]);
  403. pstPrivate->ahEvent[ix] = NULL;
  404. }
  405. }
  406. DeleteCriticalSection(&pstPrivate->csect);
  407. // Free our private data area
  408. free(pstPrivate);
  409. pstPrivate = NULL;
  410. DbgOutStr("WsckDeviceClose complete", 0,0,0,0,0);
  411. return COM_OK;
  412. }
  413. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  414. * FUNCTION: WsckDeviceSpecial
  415. *
  416. * DESCRIPTION:
  417. * The means for others to control any special features in this driver
  418. * that are not supported by all drivers.
  419. *
  420. * ARGUMENTS:
  421. *
  422. *
  423. * RETURNS:
  424. * COM_NOT_SUPPORTED if the instruction string was not recognized
  425. * otherwise depends on instruction string
  426. *
  427. * AUTHOR:
  428. * mcc 12/26/95 (ported from NPORT)
  429. */
  430. int WINAPI WsckDeviceSpecial(void *pvPrivate, const TCHAR *pszInstructions,
  431. TCHAR *pszResult, int nBufrSize)
  432. {
  433. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  434. int iRetVal = COM_NOT_SUPPORTED;
  435. unsigned long ulSetVal;
  436. TCHAR *pszEnd;
  437. //
  438. // MAX_IP_ADDR_LEN+11+1 = buffer size of pstPrivate->szRemoteAddr +
  439. // settings string "SET IPADDR=" + 1 for the terminating NULL
  440. // character. REV 09/20/2000
  441. //
  442. TCHAR achInstructions[MAX_IP_ADDR_LEN+11+1];
  443. TCHAR *pszToken = achInstructions;
  444. int iIndex;
  445. TCHAR szResult[MAX_IP_ADDR_LEN+11+1];
  446. //ULONG dwThreadID;
  447. static TCHAR *apszItems[] =
  448. {
  449. "IPADDR",
  450. "PORTNUM",
  451. "ISCONNECTED",
  452. "ESC_FF", /* 3 */
  453. "ANSWER",
  454. NULL
  455. };
  456. // supported instruction strings:
  457. // "Set xxx=vv"
  458. // "Query xxx"
  459. if (!pszInstructions || !*pszInstructions)
  460. return COM_FAILED;
  461. //DbgOutStr("DevSpec: %s", pszInstructions, 0,0,0,0);
  462. if (sizeof(achInstructions)/sizeof(TCHAR) < (size_t)(StrCharGetStrLength(pszInstructions) + 1))
  463. return COM_NOT_SUPPORTED;
  464. StrCharCopyN(achInstructions, (LPTSTR)pszInstructions, MAX_IP_ADDR_LEN+11+1);
  465. if (pszResult)
  466. *pszResult = TEXT('\0');
  467. pszToken = strtok(achInstructions, " ");
  468. if (!pszToken)
  469. return COM_NOT_SUPPORTED;
  470. EnterCriticalSection(&pstPrivate->csect);
  471. if (StrCharCmpi(pszToken, "SET") == 0)
  472. {
  473. iRetVal = COM_OK;
  474. pszToken = strtok(NULL, " =");
  475. if (!pszToken)
  476. pszToken = "";
  477. // Look up the item to set.
  478. for (iIndex = 0; apszItems[iIndex]; ++iIndex)
  479. if (StrCharCmpi(pszToken, apszItems[iIndex]) == 0)
  480. break;
  481. // Isolate the new value to be set
  482. pszToken = strtok(NULL, "\n");
  483. if (pszToken && *pszToken)
  484. {
  485. // Several items take numeric values
  486. ulSetVal = strtoul(pszToken, &pszEnd, 0);
  487. switch(iIndex)
  488. {
  489. case 0: // IPADDR
  490. ulSetVal = (unsigned) StrCharGetByteCount(pszToken);
  491. if ( ulSetVal < sizeof(pstPrivate->szRemoteAddr))
  492. {
  493. StrCharCopyN(pstPrivate->szRemoteAddr, pszToken, IP_ADDR_LEN);
  494. iRetVal = 0;
  495. }
  496. else
  497. iRetVal = -1;
  498. break;
  499. case 1: // PORTNUM
  500. pstPrivate->nPort = (short) ulSetVal;
  501. iRetVal = 0;
  502. break;
  503. case 3: // ESC_FF
  504. pstPrivate->fEscapeFF = (int) atoi(pszToken);
  505. //DbgOutStr("set fEscapeFF = %d (%d) %s %d",
  506. //pstPrivate->fEscapeFF,ulSetVal,pszToken,
  507. //(int) atoi(pszToken),0);
  508. break;
  509. case 4: // ANSWER
  510. #ifdef INCL_CALL_ANSWERING
  511. pstPrivate->fAnswer = ulSetVal;
  512. iRetVal = 0;
  513. #else
  514. iRetVal = COM_FAILED;
  515. #endif
  516. break;
  517. default:
  518. iRetVal = COM_FAILED;
  519. //DbgOutStr("DevSpec: Unrecognized instructions!", 0,0,0,0,0);
  520. break;
  521. }
  522. }
  523. else // if (pszToken && *pszToken)
  524. {
  525. assert(0);
  526. iRetVal = COM_NOT_SUPPORTED;
  527. }
  528. }
  529. else if (StrCharCmpi(pszToken, "QUERY") == 0)
  530. {
  531. iRetVal = COM_OK;
  532. pszToken = strtok(NULL, "\n");
  533. szResult[0] = TEXT('\0');
  534. // Look up the item to query
  535. for (iIndex = 0; apszItems[iIndex]; ++iIndex)
  536. if (StrCharCmpi(pszToken, apszItems[iIndex]) == 0)
  537. break;
  538. if (*pszToken)
  539. {
  540. switch(iIndex)
  541. {
  542. case 0: // IPADDR
  543. StrCharCopyN(szResult, pstPrivate->szRemoteAddr, (sizeof(szResult)/sizeof(TCHAR)));
  544. szResult[sizeof(szResult)/sizeof(TCHAR) - 1] = TEXT('\0');
  545. iRetVal = 0;
  546. break;
  547. case 1: // PORTNUM
  548. wsprintf(szResult, "%d", pstPrivate->nPort);
  549. iRetVal = 0;
  550. break;
  551. case 2: // ISCONNECTED
  552. wsprintf(szResult, "%d", pstPrivate->fConnected);
  553. iRetVal = 0;
  554. break;
  555. case 4: // ANSWER
  556. #ifdef INCL_CALL_ANSWERING
  557. wsprintf(szResult, "%d", pstPrivate->fAnswer);
  558. iRetVal = 0;
  559. #else
  560. iRetVal = COM_FAILED;
  561. #endif
  562. break;
  563. default:
  564. iRetVal = COM_FAILED;
  565. break;
  566. }
  567. if ( iRetVal == 0 && StrCharGetByteCount(szResult) < nBufrSize )
  568. {
  569. StrCharCopyN(pszResult, szResult, nBufrSize);
  570. }
  571. else
  572. {
  573. iRetVal = COM_FAILED;
  574. }
  575. }
  576. }
  577. else if (StrCharCmpi(pszInstructions, "Send Break") == 0)
  578. {
  579. // This is the telent "Break" key processing. When
  580. // the user presses Ctrl-Break on the terminal sreen
  581. // with a WinSOck connection, we arrive here.
  582. //
  583. // Please refer to RFC 854 for specifics on this
  584. // implementation. Basically, we need to..
  585. // send the IAC BREAK signal (0xFF 0xF3)
  586. unsigned char ach[2];
  587. ach[0] = IAC;
  588. ach[1] = BREAK;
  589. if (send(pstPrivate->hSocket, ach, 2, 0) != 2)
  590. {
  591. assert(0);
  592. }
  593. iRetVal = COM_OK;
  594. }
  595. else if (StrCharCmpi(pszInstructions, "Send IP") == 0)
  596. {
  597. // This is the telent Interrupt Process. When
  598. // the user presses Alt-Break on the terminal sreen
  599. // with a WinSock connection, we arrive here.
  600. //
  601. // Please refer to RFC 854 for specifics on this
  602. // implementation. Basically, we need to..
  603. //
  604. // Send the Telnet IP (Interrupt Processs)
  605. // sequence (0xFF 0xF4).
  606. //
  607. // Send the Telnet SYNC sequence. That is,
  608. // send the Data Mark (DM) as the only character
  609. // is a TCP urgent mode send operation (the mode
  610. // flag MSG_OOB does this for us).
  611. //
  612. unsigned char ach[2];
  613. SndBufrClear(pstPrivate);
  614. ach[0] = IAC;
  615. ach[1] = IP;
  616. if (send(pstPrivate->hSocket, ach, 2, 0) != 2)
  617. {
  618. assert(0);
  619. }
  620. ach[0] = IAC;
  621. ach[1] = DM;
  622. if (send(pstPrivate->hSocket, ach, 2, MSG_OOB) != 2)
  623. {
  624. assert(0);
  625. }
  626. iRetVal = COM_OK;
  627. }
  628. else if (StrCharCmpi(pszInstructions, "Update Terminal Size") == 0)
  629. {
  630. // The dimensions of the terminal have changed. If we have negotiated
  631. // to use the Telnet NAWS option, (Negotiate About Terminal Size), then
  632. // we must send the new terminal size to the server. This method will
  633. // only send data out if the option has been enabled.
  634. WinSockSendNAWS( pstPrivate );
  635. }
  636. //
  637. // This is necessary to get the default settings on COM ports. REV: 08/22/2001
  638. //
  639. else if (StrCharCmpi(pszInstructions, "GET Defaults") == 0)
  640. {
  641. iRetVal = PortDefaultSettings(pstPrivate);
  642. }
  643. LeaveCriticalSection(&pstPrivate->csect);
  644. return iRetVal;
  645. }
  646. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  647. * FUNCTION:
  648. * WsckDeviceLoadHdl
  649. *
  650. * DESCRIPTION:
  651. * We need a function that appears to load/save to the session file,
  652. * returning SF_OK, but actually doing nothing since this driver saves
  653. * no settings.
  654. *
  655. * ARGUMENTS:
  656. * pstPrivate -- dummy (not used)
  657. * sfHdl -- dummy (not used)
  658. *
  659. * RETURNS:
  660. *
  661. * AUTHOR:
  662. * mcc 01/19/95
  663. */
  664. int WINAPI WsckDeviceLoadHdl(void *pvPrivate, SF_HANDLE sfHdl)
  665. {
  666. return SF_OK;
  667. }/*lint !e715 */
  668. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  669. * FUNCTION:
  670. * WsckDeviceSaveStub
  671. *
  672. * DESCRIPTION:
  673. * We need a function that appears to Save/save to the session file,
  674. * returning SF_OK, but actually doing nothing since this driver saves
  675. * no settings.
  676. *
  677. * ARGUMENTS:
  678. * pstPrivate -- dummy (not used)
  679. * sfHdl -- dummy (not used)
  680. *
  681. * RETURNS:
  682. *
  683. * AUTHOR:
  684. * mcc 01/19/95
  685. */
  686. int WINAPI WsckDeviceSaveHdl(void *pvPrivate, SF_HANDLE sfHdl)
  687. {
  688. return SF_OK;
  689. }/*lint !e715 */
  690. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  691. * FUNCTION: WsckDeviceStub
  692. *
  693. * DESCRIPTION:
  694. * Stub that returns COM_OK (unlike default stubs)
  695. *
  696. * ARGUMENTS:
  697. * pstPrivate -- not used
  698. *
  699. * RETURNS:
  700. * COM_OK if port is configured successfully
  701. *
  702. * AUTHOR:
  703. * mcc 12/26/95
  704. */
  705. int WINAPI WsckDeviceStub(void *pvPrivate)
  706. {
  707. int iRetVal = COM_OK;
  708. return iRetVal;
  709. } /*lint !e715 */
  710. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  711. * FUNCTION: WsckPortConfigure
  712. *
  713. * DESCRIPTION:
  714. * Configures an open port with the current set of user settings
  715. *
  716. * ARGUMENTS:
  717. * pstPrivate -- The driver data structure
  718. *
  719. * RETURNS:
  720. * COM_OK if port is configured successfully
  721. * COM_DEVICE_ERROR if API errors are encountered
  722. * COM_DEVICE_INVALID_SETTING if some user settings are not valid
  723. */
  724. int WINAPI WsckPortConfigure(void *pvPrivate)
  725. {
  726. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  727. int iRetVal = COM_OK;
  728. unsigned uOverrides = 0;
  729. // Check for overrides
  730. ComQueryOverride(pstPrivate->hCom, &uOverrides);
  731. if (bittest(uOverrides, COM_OVERRIDE_8BIT))
  732. {
  733. DbgOutStr("Requesting binary Telnet mode\n", 0,0,0,0,0);
  734. // Ask the other side to send binary data (default
  735. // is 7-bit ASCII), and inform them that we will
  736. // be sending binary data.
  737. WinSockSendMessage(pstPrivate, DO, TELOPT_BINARY);
  738. WinSockSendMessage(pstPrivate, WILL, TELOPT_BINARY);
  739. }
  740. return iRetVal;
  741. }
  742. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  743. * FUNCTION: WsckPortConnected
  744. *
  745. * DESCRIPTION:
  746. * Determines whether the driver is currently connected to a host system.
  747. * (Sort of like having a "carrier" in the STDCOM drivers)
  748. *
  749. * ARGUMENTS:
  750. * pstPrivate -- Our private data structure
  751. *
  752. * RETURNS:
  753. * TRUE if we have an active connection
  754. * FALSE otherwise
  755. *
  756. * AUTHOR:
  757. * mcc 01/19/96
  758. */
  759. int WINAPI WsckPortConnected(void *pvPrivate)
  760. {
  761. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  762. return pstPrivate->fConnected;
  763. }
  764. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  765. * FUNCTION: WsckSndBufrIsBusy
  766. *
  767. * DESCRIPTION:
  768. * Determines whether the driver is available to transmit a buffer of
  769. * data or not.
  770. *
  771. * ARGUMENTS:
  772. * pstPrivate -- address of com driver's data structure
  773. *
  774. * RETURNS:
  775. * COM_OK if data can be transmitted
  776. * COM_BUSY if driver is still working on a previous buffer
  777. *
  778. * AUTHOR:
  779. * mcc 12/26/95
  780. */
  781. int WINAPI WsckSndBufrIsBusy(void *pvPrivate)
  782. {
  783. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  784. int iRetVal = COM_OK;
  785. EnterCriticalSection(&pstPrivate->csect);
  786. if (pstPrivate->fSending)
  787. {
  788. iRetVal = COM_BUSY;
  789. }
  790. LeaveCriticalSection(&pstPrivate->csect);
  791. // DBG_WRITE((iRetVal==COM_BUSY)?"Snd Bufr Busy\r\n":"Snd Bufr Ready\r\n",
  792. // 0,0,0,0,0);
  793. return iRetVal;
  794. }
  795. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  796. * FUNCTION:
  797. * WsckSndBufrQuery
  798. *
  799. * DESCRIPTION:
  800. * A stub; I'm not really sure what else it COULD do in TCP/IP
  801. *
  802. * ARGUMENTS:
  803. * ignored
  804. *
  805. * RETURNS:
  806. * COM_OK
  807. *
  808. * AUTHOR:
  809. * mcc 12/26/95
  810. */
  811. int WINAPI WsckSndBufrQuery(void *pvPrivate,
  812. unsigned *pafStatus,
  813. long *plHandshakeDelay)
  814. {
  815. int iRetVal = COM_OK;
  816. return iRetVal;
  817. }
  818. #if !defined(MULTITHREAD)
  819. // WINSOCK the way we know and love it from Win3.1 days
  820. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  821. * FUNCTION: WsckPortActivate
  822. *
  823. * DESCRIPTION:
  824. * Called to activate the port and connect to destination
  825. *
  826. * ARGUMENTS:
  827. * pstPrivate -- driver data structure
  828. * pszPortName -- not used
  829. * dwMediaHdl -- not used (stub used only by TAPI-aware drivers)
  830. *
  831. * RETURNS:
  832. * COM_OK if port is successfully activated
  833. * COM_NOT_ENOUGH_MEMORY if there in insufficient memory for data storage
  834. * COM_NOT_FOUND if named port cannot be opened
  835. * COM_DEVICE_ERROR if API errors are encountered
  836. *
  837. * AUTHOR:
  838. * mcc 12/26/95
  839. */
  840. int WINAPI WsckPortActivate(void *pvPrivate,
  841. TCHAR *pszPortName,
  842. DWORD_PTR dwMediaHdl)
  843. {
  844. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  845. int iRetVal = COM_OK;
  846. WNDCLASSEX wc;
  847. ST_COM_CONTROL *pstComCntrl;
  848. // Make sure we can get enough memory for buffers before opening device
  849. pstPrivate->pbBufrStart = malloc((size_t)pstPrivate->nRBufrSize);
  850. if (pstPrivate->pbBufrStart == NULL)
  851. {
  852. iRetVal = COM_NOT_ENOUGH_MEMORY;
  853. //* DeviceReportError(pstPrivate, SID_ERR_NOMEM, 0, TRUE);
  854. goto checkout;
  855. }
  856. pstPrivate->pbBufrEnd = pstPrivate->pbBufrStart + pstPrivate->nRBufrSize;
  857. pstPrivate->pbReadEnd = pstPrivate->pbBufrStart;
  858. pstPrivate->pbComStart = pstPrivate->pbComEnd = pstPrivate->pbBufrStart;
  859. pstPrivate->fBufrEmpty = TRUE;
  860. pstPrivate->nSendBufrLen = 0;
  861. if (iRetVal == COM_OK)
  862. {
  863. pstComCntrl = (ST_COM_CONTROL *)pstPrivate->hCom;
  864. pstComCntrl->puchRBData =
  865. pstComCntrl->puchRBDataLimit =
  866. pstPrivate->pbBufrStart;
  867. pstPrivate->dwEventMask = EV_ERR | EV_RLSD;
  868. pstPrivate->fNotifyRcv = TRUE;
  869. pstPrivate->fBufrEmpty = TRUE;
  870. }
  871. memset(&wc, 0, sizeof(WNDCLASSEX));
  872. wc.cbSize = sizeof(WNDCLASSEX);
  873. if (GetClassInfoEx(hinstDLL, WINSOCK_EVENT_WINDOW_CLASS, &wc) == FALSE)
  874. {
  875. // Register event window class to handle Winsock asynchronous
  876. // notifications
  877. wc.style = CS_GLOBALCLASS;
  878. wc.lpfnWndProc = WndSockWndProc;
  879. wc.cbClsExtra = 0;
  880. wc.cbWndExtra = sizeof(ST_STDCOM*);
  881. wc.hInstance = hinstDLL;
  882. wc.hIcon = NULL;
  883. wc.hCursor = NULL;
  884. wc.hbrBackground = NULL;
  885. wc.lpszMenuName = NULL;
  886. wc.lpszClassName = WINSOCK_EVENT_WINDOW_CLASS;
  887. wc.hIconSm = NULL;
  888. // Register the class, we don't check for failure because the driver
  889. // can operate without it if it has to
  890. RegisterClassEx(&wc);
  891. }
  892. WinSockCreateNVT(pstPrivate);
  893. if (!WinSockCreateEventWindow(pstPrivate))
  894. {
  895. iRetVal = COM_DEVICE_ERROR;
  896. goto checkout;
  897. }
  898. // Kick off Winsock processing
  899. PostMessage(pstPrivate->hwndEvents, WM_WINSOCK_STARTUP,
  900. 0, 0L);
  901. checkout:
  902. if (iRetVal != COM_OK)
  903. WsckPortDeactivate(pstPrivate);
  904. return iRetVal;
  905. } /*lint !e715 */
  906. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  907. * FUNCTION: WsckPortDeactivate
  908. *
  909. * DESCRIPTION:
  910. * Deactivates and closes an open port
  911. *
  912. * ARGUMENTS:
  913. * pstPrivate -- Driver data structure
  914. *
  915. * RETURNS:
  916. * COM_OK
  917. *
  918. * AUTHOR:
  919. * mcc 12/26/95
  920. */
  921. int WINAPI WsckPortDeactivate(void *pvPrivate)
  922. {
  923. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  924. int iRetVal = COM_OK;
  925. // Shut down socket and WINSOCK
  926. shutdown(pstPrivate->hSocket, 2);
  927. closesocket(pstPrivate->hSocket);
  928. WSACleanup();
  929. pstPrivate->hSocket = INVALID_SOCKET;
  930. // Destroy the WINSOCK event window
  931. if (pstPrivate->hwndEvents)
  932. {
  933. DestroyWindow(pstPrivate->hwndEvents);
  934. pstPrivate->hwndEvents = 0;
  935. }
  936. // Destroy the read buffer
  937. if (pstPrivate->pbBufrStart)
  938. {
  939. free(pstPrivate->pbBufrStart);
  940. pstPrivate->pbBufrStart = NULL;
  941. }
  942. return iRetVal;
  943. }
  944. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  945. * FUNCTION: WsckRcvRefill
  946. *
  947. * DESCRIPTION:
  948. * Called when the receive buffer is empty to refill it. This routine
  949. * should attempt to refill the buffer and return the first character.
  950. * It is important that this function be implemented efficiently.
  951. *
  952. * ARGUMENTS:
  953. * pstPrivate -- the driver data structure
  954. *
  955. * RETURNS:
  956. * TRUE if data is put in the receive buffer
  957. * FALSE if there is no new incoming data
  958. *
  959. * AUTHOR:
  960. * mcc 01/18/95 (from HAWIN)
  961. */
  962. int WINAPI WsckRcvRefill(void *pvPrivate)
  963. {
  964. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  965. int nIndx;
  966. int iBytesRead = 0;
  967. int nNVTRes;
  968. int nBytesCopied;
  969. ST_COM_CONTROL FAR *pstComCntrl;
  970. int iReturn = TRUE;
  971. if (pstPrivate->fConnected == COM_PORT_NOT_OPEN)
  972. return FALSE;
  973. //for (nIndx = 0; nIndx < (int)pstPrivate->usRBufrSize; nIndx += 1)
  974. //pstPrivate->puchRBufr[nIndx] = 0;
  975. // Read up to pstPrivate->usRBufrSize bytes into pstPrivate->puchRBufr
  976. // and set iBytesRead to the number read.
  977. iBytesRead = 0;
  978. iBytesRead = recv(pstPrivate->hSocket,
  979. (LPSTR)pstPrivate->pbBufrStart,
  980. (int)pstPrivate->nRBufrSize,
  981. 0);
  982. if (iBytesRead == SOCKET_ERROR)
  983. {
  984. int iErr;
  985. iBytesRead = 0;
  986. iErr = WSAGetLastError();
  987. if (iErr != WSAEWOULDBLOCK)
  988. DbgOutStr("Refill: error %d reading %d bytes on socket %d\n", iErr,
  989. pstPrivate->nRBufrSize,
  990. pstPrivate->hSocket,0,0);
  991. }
  992. if (iBytesRead == 0)
  993. {
  994. ComNotify(pstPrivate->hCom, NODATA);
  995. return FALSE;
  996. }
  997. // update the com handle with info on new data. This is implemented
  998. // this way to allow HA to access these characters quickly
  999. nBytesCopied = 0;
  1000. for (nIndx = 0; nIndx < iBytesRead; nIndx++)
  1001. {
  1002. if (pstPrivate->pbBufrStart == NULL)
  1003. {
  1004. return FALSE;
  1005. }
  1006. // If we have an FF or we are in the middle of a Telnet
  1007. // command, run this character thru the NVT. Unless the
  1008. // says to discard the character, we then copy it to the
  1009. // output position.
  1010. if (pstPrivate->pbBufrStart[nIndx] == 0xFF ||
  1011. pstPrivate->NVTstate != NVT_THRU)
  1012. {
  1013. nNVTRes = WinSockNetworkVirtualTerminal(
  1014. (ECHAR) pstPrivate->pbBufrStart[nIndx],
  1015. (void far *) pstPrivate);
  1016. //DbgOutStr("NVT returns %d\n", nNVTRes, 0,0,0,0);
  1017. }
  1018. else
  1019. nNVTRes = NVT_KEEP;
  1020. if (nNVTRes != NVT_DISCARD)
  1021. {
  1022. pstPrivate->pbBufrStart[nBytesCopied] = pstPrivate->pbBufrStart[nIndx];
  1023. nBytesCopied++;
  1024. }
  1025. }
  1026. // if we got no data (perhaps because data were "eaten" by NVT),
  1027. // make sure we return -1
  1028. if (nBytesCopied == 0)
  1029. {
  1030. *(pstPrivate->pbBufrStart) = (char) -1;
  1031. iReturn = FALSE;
  1032. }
  1033. pstComCntrl = (ST_COM_CONTROL *)pstPrivate->hCom;
  1034. pstComCntrl->puchRBData = pstPrivate->pbBufrStart;
  1035. pstComCntrl->puchRBDataLimit = pstPrivate->pbBufrStart + nBytesCopied;
  1036. return iReturn;
  1037. }
  1038. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1039. * FUNCTION: WsckRcvClear
  1040. *
  1041. * DESCRIPTION:
  1042. * Clears the receiver of all received data.
  1043. *
  1044. * ARGUMENTS:
  1045. * hCom -- a comm handle returned by an earlier call to ComCreateHandle
  1046. *
  1047. * RETURNS:
  1048. * COM_OK if data is cleared
  1049. * COM_DEVICE_ERROR if Windows com device driver returns an error
  1050. *
  1051. * AUTHOR:
  1052. * mcc 01/18/96 (taken almost entirely from HAWIN)
  1053. */
  1054. int WINAPI WsckRcvClear(void *pvPrivate)
  1055. {
  1056. CHAR ch[128];
  1057. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  1058. ST_COM_CONTROL *pstComCntrl = (ST_COM_CONTROL *)pstPrivate->hCom;
  1059. if (pstPrivate->fConnected == COM_PORT_NOT_OPEN)
  1060. return COM_DEVICE_ERROR;
  1061. pstComCntrl->puchRBData = pstComCntrl->puchRBDataLimit =
  1062. pstPrivate->pbBufrStart;
  1063. // Do whatever is necessary to remove any buffered data from the com port
  1064. while (recv(pstPrivate->hSocket, ch, 128, 0) != SOCKET_ERROR)
  1065. {
  1066. }
  1067. return COM_OK;
  1068. }
  1069. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1070. * FUNCTION: WsckSndBufrSend
  1071. *
  1072. * DESCRIPTION:
  1073. * Transmits a buffer of characters. This routine need only queue up a
  1074. * buffer to be transmitted. If the com device supports interrupt-driven
  1075. * or hardware-controlled transmission, this function should start the
  1076. * process but should not wait until all the data has actually been sent.
  1077. *
  1078. * ARGUMENTS:
  1079. * pstPrivate -- Pointer to driver data structure
  1080. * pvBufr -- Pointer to data to send
  1081. * nSize -- Number of bytes to send
  1082. *
  1083. * RETURNS:
  1084. * COM_OK
  1085. * or appropriate error code
  1086. *
  1087. * AUTHOR:
  1088. * mcc 01/19/96
  1089. */
  1090. int WINAPI WsckSndBufrSend(void *pvPrivate, void *pvBufr, int nBytesToSend)
  1091. {
  1092. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  1093. int nCount;
  1094. int nError;
  1095. int nSize; // num bytes to send during this pass
  1096. int usReturnValue = COM_OK;
  1097. unsigned char *pszPtr = (unsigned char *)pvBufr;
  1098. unsigned char *pcThisPassData;
  1099. int fGotFF = FALSE; // TRUE if last char detected was an FF
  1100. int nOffset;
  1101. LPSTR puchRemains;
  1102. int fQueueing = FALSE;
  1103. assert(pvBufr != (VOID FAR *)0);
  1104. assert(nBytesToSend <= WSOCK_SIZE_OUTQ);
  1105. if (pstPrivate->fSending)
  1106. {
  1107. DbgOutStr("SBS: Busy = %d\n", pstPrivate->fSending, 0,0,0,0);
  1108. return COM_BUSY;
  1109. }
  1110. assert(pstPrivate->nSendBufrLen == 0);
  1111. if (pstPrivate->fConnected == COM_PORT_NOT_OPEN)
  1112. return COM_DEVICE_ERROR;
  1113. // If we are escaping FF characters by sending them as FFFF,
  1114. // things are a bit tricky because we have no extra room in the buffer
  1115. // for the doubled characters. The idea here is to send the buffer
  1116. // in several passes; if an FF character is found, it is sent once
  1117. // at the end of one pass and again at the beginning of the next
  1118. // At the end of each pass, we decrement nBytesToSend by the
  1119. // number of bytes sent during the pass (nSize), and keep looping
  1120. // until all the data are sent
  1121. nOffset = 0;
  1122. ComNotify(pstPrivate->hCom, SEND_STARTED);
  1123. while (nBytesToSend > 0 && usReturnValue == COM_OK)
  1124. {
  1125. if (pstPrivate->fEscapeFF)
  1126. {
  1127. pcThisPassData = &pszPtr[nOffset];
  1128. // If we are processing an FF that was found on the
  1129. // last pass, send it out again by itself. Otherwise,
  1130. // search for the next FF and send everything up to and
  1131. // including it.
  1132. if (fGotFF)
  1133. {
  1134. //DbgOutStr("SndBufrSend: 2nd FF\n", 0,0,0,0,0);
  1135. nSize = 1;
  1136. nOffset++;
  1137. fGotFF = FALSE;
  1138. }
  1139. else
  1140. {
  1141. nSize = 0;
  1142. while (pszPtr[nOffset] != 0xFF && nOffset < nBytesToSend)
  1143. {
  1144. nSize++, nOffset++;
  1145. }
  1146. // If no FF's were found, send everything
  1147. if (nOffset >= nBytesToSend)
  1148. {
  1149. nBytesToSend = 0;
  1150. fGotFF = 0;
  1151. }
  1152. // otherwise, send data up to and including FF
  1153. else
  1154. {
  1155. nSize++; // include the FF!
  1156. fGotFF = TRUE; // Send the 2nd FF on next pass
  1157. //DbgOutStr("SndBufrSend: 1st FF ...", 0,0,0,0,0);
  1158. }
  1159. }
  1160. }
  1161. else // send everything in one pass
  1162. {
  1163. nSize = nBytesToSend;
  1164. nBytesToSend = 0;
  1165. pcThisPassData = pvBufr;
  1166. }
  1167. // If we already have data queued, don't try to send directly, since
  1168. // it might get out before the queued data do.
  1169. if (fQueueing)
  1170. {
  1171. DbgOutStr("SBS queueing output. Queueing %d bytes\n",
  1172. nSize,0,0,0,0);
  1173. if (sndQueueAppend(pstPrivate,pcThisPassData,nSize) != COM_OK)
  1174. usReturnValue = COM_DEVICE_ERROR;
  1175. }
  1176. else
  1177. {
  1178. // Pass data to TCP/IP
  1179. nCount = 0;
  1180. nCount = send(pstPrivate->hSocket,
  1181. pcThisPassData, (int)nSize, 0);
  1182. // If we got a "would block" error, copy the data to send
  1183. // to pstPrivate->auchSndBufr. (Since the FF processing may
  1184. // cause this block of code to be executed multiple times in
  1185. // one SndBufrSend call, we will append new data to existing
  1186. // data in the buffer).
  1187. if (nCount == SOCKET_ERROR)
  1188. {
  1189. nError = WSAGetLastError();
  1190. if (nError == WSAEWOULDBLOCK)
  1191. {
  1192. // Winsock won't accept data, so queue it up for
  1193. // WinSockWriteEvent to handle. Also, lock the handle
  1194. // until we are done so that WinSockWriteEvent can't get in
  1195. // there.
  1196. fQueueing = TRUE;
  1197. DbgOutStr("SBS would block. Queueing %d bytes\n",
  1198. nSize,0,0,0,0);
  1199. EnterCriticalSection(&pstPrivate->csect);
  1200. if (sndQueueAppend(pstPrivate,pcThisPassData,nSize) != COM_OK)
  1201. {
  1202. usReturnValue = COM_DEVICE_ERROR;
  1203. }
  1204. LeaveCriticalSection(&pstPrivate->csect);
  1205. }
  1206. else
  1207. {
  1208. DbgOutStr("WinSock send error %d\r\n", nError, 0,0,0,0);
  1209. //DeviceReportError(pstPrivate, (UINT)nError, 0, FALSE);
  1210. usReturnValue = COM_DEVICE_ERROR;
  1211. DbgOutStr("SBS: Bad error\n", 0,0,0,0,0);
  1212. }
  1213. }
  1214. else
  1215. {
  1216. ComNotify(pstPrivate->hCom, SEND_DONE);
  1217. if (nCount < (int)nSize)
  1218. {
  1219. /*
  1220. * Set stuff up for next time through
  1221. */
  1222. DbgOutStr("SBS send incomplete.. Queueing %d bytes\n",
  1223. (int)nSize-nCount,0,0,0,0);
  1224. // Get pointer to remaining data and queue it up
  1225. puchRemains = pcThisPassData + nCount;
  1226. if (sndQueueAppend(pstPrivate, puchRemains,
  1227. (nSize - nCount)) != COM_OK)
  1228. {
  1229. usReturnValue = COM_DEVICE_ERROR;
  1230. DbgOutStr("SBS: Bad error\n", 0,0,0,0,0);
  1231. }
  1232. }
  1233. }
  1234. }
  1235. }
  1236. return usReturnValue;
  1237. }
  1238. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1239. * FUNCTION: sndQueueAppend
  1240. *
  1241. * DESCRIPTION:
  1242. * Appends new data to any data that have been queued up for
  1243. * re-transmission by WinSockWriteEvent
  1244. *
  1245. * ARGUMENTS:
  1246. * pstPrivate -- address of com driver's data structure
  1247. * pvBufr -- address of new data block to queue up
  1248. * nBytesToAppend -- size of new data block to append
  1249. *
  1250. * RETURNS:
  1251. * COM_OK if data can be transmitted
  1252. * COM_BUSY if no more room for data to queue up
  1253. *
  1254. * AUTHOR:
  1255. * mcc 01/19/96 (from HAWIN)
  1256. */
  1257. int FAR PASCAL sndQueueAppend(ST_STDCOM* pstPrivate,
  1258. VOID FAR *pvBufr, int nBytesToAppend)
  1259. {
  1260. LPSTR puchEnd;
  1261. USHORT usReturns = COM_OK;
  1262. assert( pstPrivate != NULL );
  1263. assert( pvBufr != NULL );
  1264. //jkh 9/11/98 to avoid memcpy with invalid params
  1265. if ( pstPrivate && pvBufr && nBytesToAppend > 0 )
  1266. {
  1267. if (pstPrivate->nSendBufrLen + nBytesToAppend >
  1268. (int) sizeof(pstPrivate->abSndBufr))
  1269. {
  1270. DbgOutStr("SQAPP: buffer full", 0,0,0,0,0);
  1271. return COM_BUSY;
  1272. }
  1273. // Set the flag that SndBufrIsBusy looks at; we are
  1274. // in the middle of a send until the buffer is cleared
  1275. // by WinSockWriteEvent
  1276. pstPrivate->fSending = TRUE;
  1277. pstPrivate->pbSendBufr = pstPrivate->abSndBufr;
  1278. puchEnd = pstPrivate->pbSendBufr + pstPrivate->nSendBufrLen;
  1279. DbgOutStr("sQA: appending %d bytes to addr = %lx. Existing buffer is %d bytes at %lx\n",
  1280. nBytesToAppend, puchEnd, pstPrivate->nSendBufrLen, pstPrivate->pbSendBufr,0);
  1281. pstPrivate->nSendBufrLen += nBytesToAppend;
  1282. MemCopy(puchEnd, (LPSTR) pvBufr, (unsigned) nBytesToAppend);
  1283. }
  1284. DbgOutStr("sQA: copy done\n", 0,0,0,0,0);
  1285. return usReturns;
  1286. }
  1287. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1288. * FUNCTION: WsckSndBufrClear
  1289. *
  1290. * DESCRIPTION:
  1291. * Clear any data waiting to be transmitted
  1292. *
  1293. * ARGUMENTS:
  1294. * pstPrivate -- pointer to driver data structure
  1295. *
  1296. * RETURNS:
  1297. * COM_OK
  1298. * or appropriate error code
  1299. *
  1300. * AUTHOR
  1301. * mcc 01/19/96 (from HAWIN)
  1302. */
  1303. int WINAPI WsckSndBufrClear(ST_STDCOM *pstPrivate)
  1304. {
  1305. USHORT usReturnValue = COM_OK;
  1306. DbgOutStr("SndBufrClear called", 0,0,0,0,0);
  1307. if (WsckSndBufrIsBusy(pstPrivate))
  1308. {
  1309. pstPrivate->nSendBufrLen = 0;
  1310. pstPrivate->pbSendBufr = 0;
  1311. }
  1312. // Call SndBufrIsBusy again to clear flags, timers, etc.
  1313. WsckSndBufrIsBusy(pstPrivate);
  1314. return usReturnValue;
  1315. }
  1316. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1317. * FUNCTION: WndSockWndProc
  1318. *
  1319. * DESCRIPTION:
  1320. * This is the window procedure for the window that is used to receive event
  1321. * messages from the WinSock interface. It uses this to get around the pesky
  1322. * problem of blocking vs. non-blocking requirements and expectations.
  1323. *
  1324. * ARGUEMENTS:
  1325. * The usual stuff for a window procedure.
  1326. *
  1327. * RETURNS:
  1328. * The usual stuff for a window procedure.
  1329. *
  1330. * AUTHOR
  1331. * mcc 01/19/96 (from HAWIN)
  1332. */
  1333. LRESULT FAR PASCAL WndSockWndProc(HWND hWnd, UINT uiMsg, WPARAM uiPar1, LPARAM lPar2)
  1334. {
  1335. ST_STDCOM*pstPrivate;
  1336. WORD wVersion;
  1337. WSADATA stWsaData;
  1338. switch (uiMsg)
  1339. {
  1340. case WM_WINSOCK_STARTUP:
  1341. pstPrivate = (ST_STDCOM*)GetWindowLongPtr(hWnd, 0);
  1342. if (pstPrivate == (ST_STDCOM*)0)
  1343. break;
  1344. DbgOutStr("Calling WSAStartup\n", 0,0,0,0,0);
  1345. /*
  1346. * Initialize the Windows Socket DLL
  1347. */
  1348. wVersion = 0x0101; // The version of WinSock that we want
  1349. if (WSAStartup(wVersion, &stWsaData) != 0)
  1350. {
  1351. /* No DLL was available */
  1352. return COM_DEVICE_ERROR;
  1353. }
  1354. DbgOutStr("Done calling WSAStartup\n", 0,0,0,0,0);
  1355. // pstPrivate->fActive = TRUE;
  1356. /* Confirm that the Windows Socket DLL supports 1.1. */
  1357. /* Note that if the DLL supports versions greater */
  1358. /* than 1.1 in addition to 1.1, it will still return */
  1359. /* 1.1 in wVersion since that is the version we */
  1360. /* requested */
  1361. if ((LOBYTE(stWsaData.wVersion) != 1) &&
  1362. (HIBYTE(stWsaData.wVersion) != 1))
  1363. {
  1364. /* No acceptable DLL was available */
  1365. return COM_DEVICE_ERROR;
  1366. }
  1367. /*
  1368. * Create a socket for later use.
  1369. */
  1370. DbgOutStr("Calling socket\n", 0,0,0,0,0);
  1371. pstPrivate->hSocket = socket(PF_INET, SOCK_STREAM, 0);
  1372. if (pstPrivate->hSocket == INVALID_SOCKET)
  1373. {
  1374. return COM_DEVICE_ERROR;
  1375. }
  1376. DbgOutStr("Done calling socket\n", 0,0,0,0,0);
  1377. #ifdef INCL_CALL_ANSWERING
  1378. if (pstPrivate->fAnswer)
  1379. {
  1380. WinSockAnswerSpecial(pstPrivate);
  1381. }
  1382. else
  1383. {
  1384. WinSockConnectSpecial(pstPrivate);
  1385. }
  1386. #else
  1387. WinSockConnectSpecial(pstPrivate);
  1388. #endif
  1389. break;
  1390. case WM_WINSOCK_NOTIFY:
  1391. {
  1392. pstPrivate = (ST_STDCOM*)GetWindowLongPtr(hWnd, 0);
  1393. if (pstPrivate == (ST_STDCOM*)0)
  1394. break;
  1395. switch(LOWORD(lPar2))
  1396. {
  1397. case FD_READ:
  1398. return WinSockReadEvent(pstPrivate, lPar2);
  1399. case FD_WRITE:
  1400. return WinSockWriteEvent(pstPrivate, lPar2);
  1401. case FD_CLOSE:
  1402. //DbgOutStr("FD_CLOSE\r\n", 0,0,0,0,0);
  1403. return WinSockCloseEvent(pstPrivate, lPar2);
  1404. case FD_CONNECT:
  1405. //DbgOutStr("FD_CONNECT\r\n", 0,0,0,0,0);
  1406. return WinSockConnectEvent(pstPrivate, lPar2);
  1407. case FD_ACCEPT:
  1408. //DbgOutStr("FD_ACCEPT\r\n", 0,0,0,0,0);
  1409. return WinSockAcceptEvent(pstPrivate, lPar2);
  1410. default:
  1411. break;
  1412. }
  1413. }
  1414. break;
  1415. case WM_WINSOCK_RESOLVE:
  1416. {
  1417. /* We get here after a call to WSAAsyncGetHostByName */
  1418. pstPrivate = (ST_STDCOM*)GetWindowLongPtr(hWnd, 0);
  1419. if (pstPrivate == (ST_STDCOM*)0)
  1420. break;
  1421. return WinSockResolveEvent(pstPrivate, lPar2);
  1422. }
  1423. default:
  1424. break;
  1425. }
  1426. return DefWindowProc(hWnd, uiMsg, uiPar1, lPar2);
  1427. }
  1428. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1429. * FUNCTION: WndSockCreateEventWindow
  1430. *
  1431. * DESCRIPTION:
  1432. * Creates the event window used to process messages sent by the WinSock DLL.
  1433. *
  1434. * ARGUMENTS:
  1435. * pstPrivate pointer to private data structure; attach to window
  1436. *
  1437. * RETURNS:
  1438. * TRUE if everything is OK, otherwise FALSE.
  1439. *
  1440. * AUTHOR
  1441. * mcc 01/19/96 (from HAWIN)
  1442. */
  1443. BOOL WinSockCreateEventWindow (ST_STDCOM *pstPrivate)
  1444. {
  1445. BOOL fRetVal = TRUE;
  1446. if (fRetVal)
  1447. {
  1448. pstPrivate->hwndEvents = CreateWindow(
  1449. WINSOCK_EVENT_WINDOW_CLASS,
  1450. TEXT(""),
  1451. WS_OVERLAPPEDWINDOW,
  1452. 0, 0, 0, 0,
  1453. HWND_DESKTOP,
  1454. NULL,
  1455. hinstDLL,
  1456. NULL);
  1457. fRetVal = (pstPrivate->hwndEvents != (HWND)0);
  1458. }
  1459. if (fRetVal)
  1460. {
  1461. SetWindowLongPtr(pstPrivate->hwndEvents, 0, (LONG_PTR)pstPrivate);
  1462. }
  1463. return fRetVal;
  1464. }
  1465. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1466. * FUNCTION:
  1467. * WinSockSendBreak
  1468. *
  1469. * DESCRIPTION:
  1470. * This function attempts to send a break condition to the NVT on the other
  1471. * end of the connection. See RFC854 for details and good luck.
  1472. *
  1473. * PARAMETERS:
  1474. * pstPrivate Driver's private data structure
  1475. *
  1476. * RETURNS:
  1477. *
  1478. * AUTHOR
  1479. * mcc 01/19/96 (from HAWIN)
  1480. */
  1481. VOID WinSockSendBreak(ST_STDCOM*pstPrivate)
  1482. {
  1483. UCHAR acSendBreak[2];
  1484. //DbgOutStr("WinSockSendBreak\r\n", 0,0,0,0,0);
  1485. acSendBreak[0] = 255;
  1486. acSendBreak[1] = 243;
  1487. send(pstPrivate->hSocket, acSendBreak, 2, 0);
  1488. }
  1489. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1490. * FUNCTION:
  1491. *
  1492. * DESCRIPTION:
  1493. *
  1494. * PARAMETERS:
  1495. *
  1496. * RETURNS:
  1497. */
  1498. USHORT WinSockSendBreakSpecial(ST_STDCOM *pstPrivate,
  1499. LPSTR pszData,
  1500. UINT uiSize)
  1501. {
  1502. if (pstPrivate->nSendBufrLen > 0)
  1503. {
  1504. /* Can't do it now, wait until next time */
  1505. pstPrivate->fSndBreak = TRUE;
  1506. }
  1507. else
  1508. {
  1509. WinSockSendBreak(pstPrivate);
  1510. }
  1511. return 0;
  1512. } /*lint !e715 */
  1513. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1514. * FUNCTION:
  1515. *
  1516. * DESCRIPTION:
  1517. *
  1518. * PARAMETERS:
  1519. *
  1520. * RETURNS:
  1521. *
  1522. * AUTHOR
  1523. * mcc 01/19/96 (from HAWIN)
  1524. */
  1525. int WinSockConnectSpecial(ST_STDCOM*pstPrivate)
  1526. {
  1527. USHORT usRetVal;
  1528. int nIndx;
  1529. int nError;
  1530. unsigned long ulAddr;
  1531. struct sockaddr_in srv_addr;
  1532. struct sockaddr_in cli_addr;
  1533. HANDLE hReturn;
  1534. usRetVal = COM_OK;
  1535. cli_addr.sin_family = AF_INET;
  1536. cli_addr.sin_addr.s_addr = INADDR_ANY;
  1537. cli_addr.sin_port = 0;
  1538. // Bind the socket to any internet address. Ignore errors;
  1539. // real ones will be detected later, and this WILL fail
  1540. // if the socket is already bound.
  1541. usRetVal = (USHORT)bind(pstPrivate->hSocket, (LPSOCKADDR)&cli_addr,
  1542. sizeof(cli_addr));
  1543. DbgOutStr("Socket %d bind returns %d\n", pstPrivate->hSocket, usRetVal, 0,0,0);
  1544. // See if the remote address has been entered in numeric form. If not,
  1545. // we will have to call WSAAsynchGetHostByName to translate it; in that
  1546. // case, the EventWindow handler will call connect.
  1547. ulAddr = inet_addr(pstPrivate->szRemoteAddr);
  1548. if ((ulAddr == INADDR_NONE) || (ulAddr == 0))
  1549. {
  1550. DbgOutStr("WSCnctSp: calling WSA...HostByName\n", 0,0,0,0,0);
  1551. /* We take the long way around */
  1552. hReturn = WSAAsyncGetHostByName(
  1553. pstPrivate->hwndEvents,
  1554. WM_WINSOCK_RESOLVE,
  1555. pstPrivate->szRemoteAddr,
  1556. (char *) &pstPrivate->stHostBuf,
  1557. MAXGETHOSTSTRUCT);
  1558. if (hReturn == 0)
  1559. nError = WSAGetLastError();
  1560. else
  1561. nError = 0 ;
  1562. DbgOutStr("WSAAsynchGetHostByName returns %lx (err = %d)\n", hReturn,
  1563. nError,0,0,0);
  1564. goto WSCSexit;
  1565. }
  1566. /*
  1567. * This is the alternate pathway for the connect. We go thru here if
  1568. * the address was in the form of a 123.456.789.123 address.
  1569. */
  1570. srv_addr.sin_family = AF_INET;
  1571. srv_addr.sin_addr.s_addr = ulAddr;
  1572. srv_addr.sin_port = htons((USHORT)pstPrivate->nPort);
  1573. nIndx = WSAAsyncSelect(pstPrivate->hSocket,
  1574. pstPrivate->hwndEvents,
  1575. WM_WINSOCK_NOTIFY,
  1576. FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE
  1577. );
  1578. if (nIndx != 0)
  1579. {
  1580. /* Oops, something goofed */
  1581. usRetVal = COM_DEVICE_ERROR;
  1582. DbgOutStr("WSAAsyncSelect failed\n", 0,0,0,0,0);
  1583. goto WSCSexit;
  1584. }
  1585. if (connect(pstPrivate->hSocket,
  1586. (LPSOCKADDR)&srv_addr,
  1587. sizeof(srv_addr)) == SOCKET_ERROR)
  1588. {
  1589. nIndx = WSAGetLastError();
  1590. if (nIndx != WSAEWOULDBLOCK)
  1591. {
  1592. usRetVal = COM_DEVICE_ERROR;
  1593. //DeviceReportError(pstPrivate, (UINT)nIndx, 0, FALSE);
  1594. DbgOutStr("Connect failed (err = %d)\n", nIndx, 0,0,0,0);
  1595. goto WSCSexit;
  1596. }
  1597. }
  1598. WSCSexit:
  1599. //DbgOutStr(" returns %d\r\n", usRetVal, 0,0,0,0);
  1600. if (usRetVal != COM_OK)
  1601. {
  1602. closesocket(pstPrivate->hSocket);
  1603. }
  1604. return usRetVal;
  1605. }
  1606. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1607. * FUNCTION:
  1608. * WinSockAnswerSpecial
  1609. *
  1610. * DESCRIPTION:
  1611. * Sets up WinSock to answer a call.
  1612. *
  1613. * PARAMETERS:
  1614. *
  1615. * RETURNS:
  1616. *
  1617. * AUTHOR: C. Baumgartner, 11/19/96 (ported from HAWin16)
  1618. */
  1619. int WinSockAnswerSpecial(ST_STDCOM*pstPrivate)
  1620. {
  1621. int nError = 0;
  1622. USHORT usRetVal = COM_OK;
  1623. struct sockaddr_in host_addr;
  1624. // Create our local internet address.
  1625. //
  1626. host_addr.sin_family = AF_INET;
  1627. host_addr.sin_addr.s_addr = INADDR_ANY;
  1628. host_addr.sin_port = htons((USHORT)pstPrivate->nPort);
  1629. // Bind the socket to our local address.
  1630. //
  1631. nError = bind(pstPrivate->hSocket, (LPSOCKADDR)&host_addr,
  1632. sizeof(host_addr));
  1633. DbgOutStr("Socket %d bind returns %d\n", pstPrivate->hSocket, nError, 0,0,0);
  1634. if (nError != 0)
  1635. {
  1636. usRetVal = COM_DEVICE_ERROR;
  1637. goto WSASexit;
  1638. }
  1639. // Tell the socket to notify us of events that we are interested
  1640. // in (like when somebody connects to us).
  1641. //
  1642. nError = WSAAsyncSelect(pstPrivate->hSocket, pstPrivate->hwndEvents,
  1643. WM_WINSOCK_NOTIFY, FD_ACCEPT | FD_READ | FD_WRITE | FD_CLOSE);
  1644. if (nError != 0)
  1645. {
  1646. usRetVal = COM_DEVICE_ERROR;
  1647. goto WSASexit;
  1648. }
  1649. // Tell the socket to wait for incoming calls.
  1650. //
  1651. if (listen(pstPrivate->hSocket, 1) != 0)
  1652. {
  1653. usRetVal = COM_DEVICE_ERROR;
  1654. goto WSASexit;
  1655. }
  1656. WSASexit:
  1657. if (usRetVal != COM_OK)
  1658. {
  1659. closesocket(pstPrivate->hSocket);
  1660. }
  1661. return usRetVal;
  1662. }
  1663. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1664. * FUNCTION:
  1665. *
  1666. * DESCRIPTION:
  1667. *
  1668. * PARAMETERS:
  1669. *
  1670. * RETURNS:
  1671. *
  1672. * AUTHOR
  1673. * mcc 01/19/96 (from HAWIN)
  1674. USHORT WinSockDisconnectSpecial(ST_STDCOM*pstPrivate,
  1675. LPSTR pszData,
  1676. UINT uiSize)
  1677. {
  1678. if (pstPrivate->hSocket != INVALID_SOCKET)
  1679. {
  1680. closesocket(pstPrivate->hSocket);
  1681. pstPrivate->hSocket = INVALID_SOCKET;
  1682. }
  1683. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  1684. return COM_OK;
  1685. } /*lint !e715 */
  1686. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1687. * FUNCTION:
  1688. *
  1689. * DESCRIPTION:
  1690. *
  1691. * PARAMETERS:
  1692. *
  1693. * RETURNS:
  1694. *
  1695. * AUTHOR
  1696. * mcc 01/19/96 (from HAWIN)
  1697. */
  1698. LONG WinSockCloseEvent(ST_STDCOM*pstPrivate, LPARAM lPar)
  1699. {
  1700. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  1701. ComNotify(pstPrivate->hCom, CONNECT);
  1702. return 0;
  1703. } /*lint !e715 */
  1704. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1705. * FUNCTION:
  1706. *
  1707. * DESCRIPTION:
  1708. *
  1709. * PARAMETERS:
  1710. * pstPrivate Driver's private data structure
  1711. * lPar status code from Winsock
  1712. *
  1713. * RETURNS:
  1714. */
  1715. LONG WinSockConnectEvent(ST_STDCOM*pstPrivate, LPARAM lPar)
  1716. {
  1717. int status;
  1718. status = (int)HIWORD(lPar);
  1719. if (status)
  1720. {
  1721. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  1722. ComNotify(pstPrivate->hCom, CONNECT);
  1723. }
  1724. else
  1725. {
  1726. pstPrivate->fConnected = COM_PORT_OPEN;
  1727. ComNotify(pstPrivate->hCom, CONNECT);
  1728. }
  1729. return 0;
  1730. } /*lint !e715 */
  1731. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1732. * FUNCTION:
  1733. * WinSockAcceptEvent
  1734. *
  1735. * DESCRIPTION:
  1736. * Accepts an incoming call.
  1737. *
  1738. * PARAMETERS:
  1739. * pstPrivate Driver's private data structure
  1740. * lPar status code from Winsock
  1741. *
  1742. * RETURNS:
  1743. *
  1744. * AUTHOR: C. Baumgartner, 11/19/96 (ported from HAWin16)
  1745. */
  1746. LONG WinSockAcceptEvent(ST_STDCOM*pstPrivate, LPARAM lPar)
  1747. {
  1748. int status = HIWORD(lPar);
  1749. SOCKET hAnswer = INVALID_SOCKET;
  1750. SOCKET hOldSocket = INVALID_SOCKET;
  1751. // We aren't connected yet.
  1752. //
  1753. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  1754. // Attempt to accept the call.
  1755. //
  1756. hAnswer = accept(pstPrivate->hSocket, NULL, 0);
  1757. if (hAnswer != INVALID_SOCKET)
  1758. {
  1759. // Now we are connected.
  1760. //
  1761. pstPrivate->fConnected = COM_PORT_OPEN;
  1762. // Get the newly accepted socket.
  1763. //
  1764. hOldSocket = pstPrivate->hSocket;
  1765. pstPrivate->hSocket = hAnswer;
  1766. // Now close the old socket because we don't want to
  1767. // be listening when we are connected.
  1768. //
  1769. closesocket(hOldSocket);
  1770. }
  1771. // Let the rest of the world know that we are connected.
  1772. //
  1773. ComNotify(pstPrivate->hCom, CONNECT);
  1774. return 0;
  1775. }
  1776. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1777. * FUNCTION:
  1778. *
  1779. * DESCRIPTION:
  1780. *
  1781. * PARAMETERS:
  1782. * pstPrivate Driver's private data structure
  1783. * lPar status code from Winsock
  1784. *
  1785. * RETURNS:
  1786. *
  1787. * AUTHOR
  1788. * mcc 01/19/96 (from HAWIN)
  1789. */
  1790. LONG WinSockReadEvent(ST_STDCOM*pstPrivate, LPARAM lPar)
  1791. {
  1792. ComNotify(pstPrivate->hCom, DATA_RECEIVED);
  1793. return 0;
  1794. } /*lint !e715 */
  1795. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1796. * FUNCTION:
  1797. * WinSockWriteEvent
  1798. *
  1799. * DESCRIPTION:
  1800. * Called back by Winsock when write completes; updates data structures
  1801. * to allow another write to take place
  1802. *
  1803. * PARAMETERS:
  1804. * pstPrivate Driver's private data structure
  1805. * lPar status code from Winsock
  1806. *
  1807. * RETURNS:
  1808. *
  1809. * AUTHOR
  1810. * mcc 01/19/96 (from HAWIN)
  1811. */
  1812. LONG WinSockWriteEvent(ST_STDCOM *pstPrivate, LPARAM lPar)
  1813. {
  1814. int nCount;
  1815. int nError;
  1816. DbgOutStr("WinSockWriteEvent called to handle %d bytes ...",
  1817. pstPrivate->nSendBufrLen,0,0,0,0);
  1818. if (pstPrivate->fConnected == COM_PORT_NOT_OPEN)
  1819. return 0;
  1820. if (pstPrivate->fSndBreak)
  1821. {
  1822. WinSockSendBreak(pstPrivate);
  1823. pstPrivate->fSndBreak = FALSE;
  1824. }
  1825. if (pstPrivate->nSendBufrLen)
  1826. {
  1827. // This is done to keep the "main thread" from updating the buffer
  1828. // while we send it. OK, I think, since send won't block.
  1829. EnterCriticalSection(&pstPrivate->csect);
  1830. nCount = send(pstPrivate->hSocket,
  1831. pstPrivate->pbSendBufr,
  1832. (int)pstPrivate->nSendBufrLen,
  1833. 0);
  1834. LeaveCriticalSection(&pstPrivate->csect);
  1835. // DbgOutStr("WinSock send returned %d\r\n", nCount, 0,0,0,0);
  1836. // assert((int)pstPrivate->SendBufrLen == nCount);
  1837. if (nCount == SOCKET_ERROR)
  1838. {
  1839. nError = WSAGetLastError();
  1840. if (nError == WSAEWOULDBLOCK)
  1841. {
  1842. DbgOutStr(" still blocked\n", 0,0,0,0,0);
  1843. /*
  1844. * Nothing to do in this case
  1845. */
  1846. }
  1847. else
  1848. {
  1849. // Got some weird error. Notify interested parties
  1850. // that our connection is suspect
  1851. DbgOutStr(" got error %d\r\n", nError, 0,0,0,0);
  1852. pstPrivate->nSendBufrLen = 0;
  1853. pstPrivate->pbSendBufr = 0;
  1854. ComNotify(pstPrivate->hCom, CONNECT);
  1855. }
  1856. }
  1857. else
  1858. {
  1859. DbgOutStr("%d bytes sent.\n", nCount, 0,0,0,0);
  1860. if (nCount < (int)pstPrivate->nSendBufrLen)
  1861. {
  1862. pstPrivate->nSendBufrLen -= (USHORT)nCount;
  1863. pstPrivate->pbSendBufr += nCount;
  1864. }
  1865. else
  1866. {
  1867. pstPrivate->nSendBufrLen = 0;
  1868. pstPrivate->pbSendBufr = 0;
  1869. }
  1870. }
  1871. }
  1872. if (pstPrivate->nSendBufrLen == 0)
  1873. {
  1874. pstPrivate->fSending = FALSE;
  1875. //DbgOutStr("Sending WM_COM_SEND_DONE in WinSockWriteEvent\n",0,0,0,0,0);
  1876. ComNotify(pstPrivate->hCom, SEND_DONE);
  1877. }
  1878. return 0;
  1879. } /*lint !e715 */
  1880. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1881. * FUNCTION:
  1882. * WinSockResolveEvent
  1883. *
  1884. * DESCRIPTION:
  1885. * Called once WSAAsynchGetHostByName has done its dirty work to actually
  1886. * generate a connect call
  1887. *
  1888. * PARAMETERS:
  1889. * pstPrivate Driver's private data structure
  1890. * lPar returned from previous Winsock call
  1891. *
  1892. * RETURNS:
  1893. * 0
  1894. *
  1895. * AUTHOR
  1896. * mcc 01/18/96 (borrowed from HAWIN)
  1897. */
  1898. LONG WinSockResolveEvent(ST_STDCOM *pstPrivate, LPARAM lPar)
  1899. {
  1900. int nError;
  1901. struct sockaddr_in srv_addr;
  1902. LPHOSTENT pstHost;
  1903. ULONG *pulAddress;
  1904. DbgOutStr("WinSockResolveEvent called\n", 0,0,0,0,0);
  1905. nError = HIWORD(lPar);
  1906. if (nError)
  1907. {
  1908. // Notify the connection driver that a change in status may
  1909. // have taken place. It will follow up and display
  1910. // an appropriate message
  1911. DbgOutStr("Resolve: hiword of lpar = %d\n", nError,0,0,0,0);
  1912. ComNotify(pstPrivate->hCom, CONNECT);
  1913. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  1914. return 0;
  1915. }
  1916. pstHost = (LPHOSTENT) &pstPrivate->stHostBuf;
  1917. pulAddress = (ULONG FAR *)*(pstHost->h_addr_list);
  1918. nError = WSAAsyncSelect(pstPrivate->hSocket,
  1919. pstPrivate->hwndEvents,
  1920. WM_WINSOCK_NOTIFY,
  1921. FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE
  1922. );
  1923. if (nError != 0)
  1924. {
  1925. DbgOutStr("Resolve: WSAAsyncSelect failed\n", 0,0,0,0,0);
  1926. ComNotify(pstPrivate->hCom, CONNECT);
  1927. return 0;
  1928. }
  1929. srv_addr.sin_family = AF_INET;
  1930. srv_addr.sin_addr.s_addr = *pulAddress;
  1931. srv_addr.sin_port = (short) htons(pstPrivate->nPort);
  1932. if (connect(pstPrivate->hSocket,
  1933. (LPSOCKADDR)&srv_addr,
  1934. sizeof(srv_addr)) == SOCKET_ERROR)
  1935. {
  1936. nError = WSAGetLastError();
  1937. if (nError != WSAEWOULDBLOCK)
  1938. {
  1939. DbgOutStr("Resolve: connect failed, code = %d\n", nError,
  1940. 0,0,0,0);
  1941. //DeviceReportError(pstPrivate, (UINT)nError, 0, FALSE);
  1942. ComNotify(pstPrivate->hCom, CONNECT);
  1943. }
  1944. }
  1945. return 0;
  1946. }
  1947. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1948. * FUNCTION:
  1949. * WinSockSendMessage
  1950. *
  1951. * DESCRIPTION:
  1952. * Used to send a Telnet option message. This calls send() directly so
  1953. * that data can go out while SndBufrSend is reporting COM_BUSY.
  1954. *
  1955. * PARAMETERS:
  1956. * pstPrivate Com driver private data
  1957. * nMsg The message number , e.g. DO, WILL, WONT, (see comwsock.hh)
  1958. * nChar The message data, e.g. TELOPT_BINARY (see comwsock.hh)
  1959. *
  1960. * RETURNS:
  1961. * void
  1962. *
  1963. * AUTHOR
  1964. * mcc 02/06/96
  1965. */
  1966. VOID WinSockSendMessage(ST_STDCOM * pstPrivate, INT nMsg, INT nChar)
  1967. {
  1968. unsigned char acMsg[3];
  1969. #if defined(_DEBUG)
  1970. char *nNames[] = {"WILL", "WONT", "DO", "DONT"};
  1971. assert( nMsg >= WILL && nMsg <= DONT );
  1972. DbgOutStr("Send %s: %lx\r\n", nNames[nMsg - WILL], nChar,0,0,0);
  1973. #endif
  1974. acMsg[0] = IAC;
  1975. acMsg[1] = (UCHAR) nMsg;
  1976. acMsg[2] = (UCHAR) nChar;
  1977. WinSockSendBuffer(pstPrivate, 3, acMsg);
  1978. }
  1979. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1980. * FUNCTION:
  1981. * WinSockSendBuffer
  1982. *
  1983. * DESCRIPTION:
  1984. * Used to send an arbitrary string of data (e.g., a terminal type)
  1985. * during Telnet option negotiation
  1986. *
  1987. * PARAMETERS:
  1988. * pstPrivate Winsock Com driver private data
  1989. * nSize Number of bytes to send
  1990. * pszBuffer Pointer to data to send
  1991. *
  1992. * RETURNS:
  1993. * void
  1994. *
  1995. * AUTHOR
  1996. * mcc 02/06/96
  1997. */
  1998. VOID WinSockSendBuffer(ST_STDCOM * pstPrivate, INT nSize, LPSTR pszBuffer)
  1999. {
  2000. int nCount, nError;
  2001. nCount = send(pstPrivate->hSocket, pszBuffer, nSize,0);
  2002. if (nCount == SOCKET_ERROR)
  2003. {
  2004. nError = WSAGetLastError();
  2005. if (nError == WSAEWOULDBLOCK)
  2006. {
  2007. DbgOutStr("WSSB would block. Queueing 3 bytes\n",
  2008. 0,0,0,0,0);
  2009. if (sndQueueAppend(pstPrivate,pszBuffer, 3) != COM_OK)
  2010. ComNotify(pstPrivate->hCom, CONNECT);
  2011. }
  2012. else
  2013. ComNotify(pstPrivate->hCom, CONNECT);
  2014. }
  2015. else
  2016. {
  2017. int i;
  2018. DbgOutStr("%4d >> ", nCount,0,0,0,0);
  2019. for (i = 0; i < nCount; i++)
  2020. DbgOutStr("%x ", pszBuffer[i],0,0,0,0);
  2021. DbgOutStr("\n", 0,0,0,0,0);
  2022. }
  2023. }
  2024. #endif // !defined(MULTITHREAD)
  2025. #ifdef MULTITHREAD
  2026. // This is essentially the NPORT TCPCOM driver ported to
  2027. // Win32. It uses different threads for reading and
  2028. // writing to the TCP socket.
  2029. // This code is deadwood at the moment, but might prove
  2030. // useful in Upper Wacker if someone can figure out
  2031. // why it does not work reliably under Win95. (send() calls
  2032. // would often appear to work but no data would come out
  2033. // over the socket.)
  2034. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2035. * FUNCTION: WsckPortActivate
  2036. *
  2037. * DESCRIPTION:
  2038. * Called to activate the port and connect to destination
  2039. *
  2040. * ARGUMENTS:
  2041. * pstPrivate -- driver data structure
  2042. * pszPortName -- not used
  2043. *
  2044. * RETURNS:
  2045. * COM_OK if port is successfully activated
  2046. * COM_NOT_ENOUGH_MEMORY if there in insufficient memory for data storage
  2047. * COM_NOT_FOUND if named port cannot be opened
  2048. * COM_DEVICE_ERROR if API errors are encountered
  2049. *
  2050. * AUTHOR:
  2051. * mcc 12/26/95
  2052. */
  2053. int WINAPI WsckPortActivate(void *pvPrivate,
  2054. TCHAR *pszPortName,
  2055. DWORD_PTR dwMediaHdl)
  2056. {
  2057. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  2058. int iRetVal = COM_OK;
  2059. ST_COM_CONTROL *pstComCntrl;
  2060. DWORD dwThreadID;
  2061. WORD wVersion;
  2062. WSADATA stWsaData;
  2063. struct sockaddr_in cli_addr;
  2064. /*
  2065. * Initialize the Windows Socket DLL
  2066. */
  2067. wVersion = 0x0101; // The version of WinSock that we want
  2068. if (WSAStartup(wVersion, &stWsaData) != 0)
  2069. {
  2070. /* No DLL was available */
  2071. iRetVal = COM_DEVICE_ERROR;
  2072. goto checkout;
  2073. }
  2074. DbgOutStr("Done calling WSAStartup\n", 0,0,0,0,0);
  2075. /* Confirm that the Windows Socket DLL supports 1.1. */
  2076. /* Note that if the DLL supports versions greater */
  2077. /* than 1.1 in addition to 1.1, it will still return */
  2078. /* 1.1 in wVersion since that is the version we */
  2079. /* requested */
  2080. if ((LOBYTE(stWsaData.wVersion) != 1) &&
  2081. (HIBYTE(stWsaData.wVersion) != 1))
  2082. {
  2083. /* No acceptable DLL was available */
  2084. iRetVal = COM_DEVICE_ERROR;
  2085. goto checkout;
  2086. }
  2087. /*
  2088. * Create a socket for later use.
  2089. */
  2090. pstPrivate->hSocket = socket(PF_INET, SOCK_STREAM, 0);
  2091. if (pstPrivate->hSocket == INVALID_SOCKET)
  2092. {
  2093. iRetVal = WSAGetLastError();
  2094. DbgOutStr("Error %d creating socket\n", iRetVal, 0,0,0,0);
  2095. iRetVal = COM_DEVICE_ERROR;
  2096. goto checkout;
  2097. }
  2098. DbgOutStr("Done creating socket %d \n", pstPrivate->hSocket,0,0,0,0);
  2099. cli_addr.sin_family = AF_INET;
  2100. cli_addr.sin_addr.s_addr = INADDR_ANY;
  2101. cli_addr.sin_port = 0;
  2102. // Bind the socket to any internet address. Ignore errors;
  2103. // real ones will be detected later, and this WILL fail
  2104. // if the socket is already bound.
  2105. iRetVal = bind(pstPrivate->hSocket, (LPSOCKADDR)&cli_addr,
  2106. sizeof(cli_addr));
  2107. DbgOutStr("Socket %d bind returns %d\n", pstPrivate->hSocket, iRetVal, 0,0,0);
  2108. // Make sure we can get enough memory for buffers before opening device
  2109. pstPrivate->pbBufrStart = malloc((size_t)pstPrivate->nRBufrSize);
  2110. if (pstPrivate->pbBufrStart == NULL)
  2111. {
  2112. iRetVal = COM_NOT_ENOUGH_MEMORY;
  2113. //* DeviceReportError(pstPrivate, SID_ERR_NOMEM, 0, TRUE);
  2114. goto checkout;
  2115. }
  2116. pstPrivate->pbBufrEnd = pstPrivate->pbBufrStart + pstPrivate->nRBufrSize;
  2117. pstPrivate->pbReadEnd = pstPrivate->pbBufrStart;
  2118. pstPrivate->pbComStart = pstPrivate->pbComEnd = pstPrivate->pbBufrStart;
  2119. pstPrivate->fBufrEmpty = TRUE;
  2120. if (iRetVal == COM_OK)
  2121. {
  2122. pstComCntrl = (ST_COM_CONTROL *)pstPrivate->hCom;
  2123. pstComCntrl->puchRBData =
  2124. pstComCntrl->puchRBDataLimit =
  2125. pstPrivate->pbBufrStart;
  2126. pstPrivate->dwEventMask = EV_ERR | EV_RLSD;
  2127. pstPrivate->fNotifyRcv = TRUE;
  2128. pstPrivate->fBufrEmpty = TRUE;
  2129. // Start thread to handle Reading, Writing (& 'rithmetic) & events
  2130. pstPrivate->fHaltThread = FALSE;
  2131. pstPrivate->hComReadThread = CreateThread((LPSECURITY_ATTRIBUTES)0,
  2132. 16384, WsckComReadThread, pstPrivate, 0, &dwThreadID);
  2133. DBG_THREAD("CreateThread (Read Thread) returned %08X %08X\r\n",
  2134. pstPrivate->hComReadThread,0,0,0,0);
  2135. pstPrivate->hComWriteThread = CreateThread((LPSECURITY_ATTRIBUTES)0,
  2136. 16384, WsckComWriteThread, pstPrivate, 0, &dwThreadID);
  2137. DBG_THREAD("CreateThread (Write Thread) returned %08X %08X\r\n",
  2138. pstPrivate->hComWriteThread,0,0,0,0);
  2139. // TODO discuss with JKH what thread priorities should be
  2140. // Make sure that we have a valid address to connect to
  2141. if ( wsckResolveAddress(pstPrivate->szRemoteAddr, &pstPrivate->ulAddr) != COM_OK )
  2142. {
  2143. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  2144. ComNotify(pstPrivate->hCom, CONNECT);
  2145. iRetVal = COM_NOT_FOUND;
  2146. goto checkout;
  2147. }
  2148. // Connect to the specified host
  2149. pstPrivate->stHost.sin_family = AF_INET;
  2150. pstPrivate->stHost.sin_addr.s_addr = pstPrivate->ulAddr;
  2151. pstPrivate->stHost.sin_port = htons(pstPrivate->nPort);
  2152. //DbgOutStr("About to call connect", 0,0,0,0,0);
  2153. iRetVal = connect(pstPrivate->hSocket,
  2154. (struct sockaddr *) &pstPrivate->stHost,
  2155. sizeof(pstPrivate->stHost));
  2156. if ( iRetVal == COM_OK )
  2157. {
  2158. pstPrivate->fConnected = COM_PORT_OPEN;
  2159. // Turn loose the read thread
  2160. DbgOutStr("connect OK", 0,0,0,0,0);
  2161. SetEvent(pstPrivate->ahEvent[EVENT_READ]);
  2162. SetEvent(pstPrivate->ahEvent[EVENT_WRITE]);
  2163. }
  2164. else
  2165. {
  2166. iRetVal = WSAGetLastError();
  2167. DbgOutStr(" connect() failed, rc = %d",iRetVal, 0,0,0,0);
  2168. iRetVal = COM_NOT_FOUND;
  2169. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  2170. ComNotify(pstPrivate->hCom, CONNECT);
  2171. }
  2172. }
  2173. checkout:
  2174. if (iRetVal != COM_OK)
  2175. WsckPortDeactivate(pstPrivate);
  2176. return iRetVal;
  2177. } /*lint !e715 */
  2178. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2179. * FUNCTION: WsckPortDeactivate
  2180. *
  2181. * DESCRIPTION:
  2182. * Deactivates and closes an open port
  2183. *
  2184. * ARGUMENTS:
  2185. * pstPrivate -- Driver data structure
  2186. *
  2187. * RETURNS:
  2188. * COM_OK
  2189. *
  2190. * AUTHOR:
  2191. * mcc 12/26/95
  2192. */
  2193. int WINAPI WsckPortDeactivate(void *pvPrivate)
  2194. {
  2195. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  2196. int iRetVal = COM_OK;
  2197. if (pstPrivate->hComReadThread || pstPrivate->hComWriteThread)
  2198. {
  2199. // Halt the thread by setting a flag for the thread to detect and then
  2200. // forcing WaitCommEvent to return by changing the event mask
  2201. DBG_THREAD("DBG_THREAD: Shutting down ComWinsock thread\r\n", 0,0,0,0,0);
  2202. pstPrivate->fHaltThread = TRUE;
  2203. // Read thread should exit now, it's handle will signal when it has exited
  2204. CloseHandle(pstPrivate->hComReadThread);
  2205. WaitForSingleObject(pstPrivate->hComReadThread, 5000);
  2206. pstPrivate->hComReadThread = NULL;
  2207. DBG_THREAD("DBG_THREAD: ComWinsock thread has shut down\r\n", 0,0,0,0,0);
  2208. // Write thread should exit now, it's handle will signal when it has exited
  2209. CloseHandle(pstPrivate->hComWriteThread);
  2210. WaitForSingleObject(pstPrivate->hComWriteThread, 5000);
  2211. pstPrivate->hComWriteThread = NULL;
  2212. DBG_THREAD("DBG_THWrite: ComWriteThread has shut down\r\n", 0,0,0,0,0);
  2213. }
  2214. if (pstPrivate->pbBufrStart)
  2215. {
  2216. free(pstPrivate->pbBufrStart);
  2217. pstPrivate->pbBufrStart = NULL;
  2218. }
  2219. // Shut down socket and WINSOCK
  2220. closesocket(pstPrivate->hSocket);
  2221. WSACleanup();
  2222. pstPrivate->hSocket = INVALID_SOCKET;
  2223. return iRetVal;
  2224. }
  2225. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2226. * FUNCTION: WsckRcvRefill
  2227. *
  2228. * DESCRIPTION:
  2229. * Called when the receive buffer is empty to refill it. This routine
  2230. * should attempt to refill the buffer and return the first character.
  2231. * It is important that this function be implemented efficiently.
  2232. *
  2233. * ARGUMENTS:
  2234. * pstPrivate -- the driver data structure
  2235. *
  2236. * RETURNS:
  2237. * TRUE if data is put in the receive buffer
  2238. * FALSE if there is no new incoming data
  2239. *
  2240. * AUTHOR:
  2241. * mcc 12/26/95 (taken almost entirely from comstd.c)
  2242. */
  2243. int WINAPI WsckRcvRefill(void *pvPrivate)
  2244. {
  2245. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  2246. int fRetVal = FALSE;
  2247. ST_COM_CONTROL *pstComCntrl;
  2248. EnterCriticalSection(&pstPrivate->csect);
  2249. pstPrivate->pbComStart = (pstPrivate->pbComEnd == pstPrivate->pbBufrEnd) ?
  2250. pstPrivate->pbBufrStart :
  2251. pstPrivate->pbComEnd;
  2252. pstPrivate->pbComEnd = (pstPrivate->pbReadEnd >= pstPrivate->pbComStart) ?
  2253. pstPrivate->pbReadEnd :
  2254. pstPrivate->pbBufrEnd;
  2255. DBG_READ("DBG_READ: Refill ComStart==%x, ComEnd==%x (ReadEnd==%x)\r\n",
  2256. pstPrivate->pbComStart, pstPrivate->pbComEnd,
  2257. pstPrivate->pbReadEnd, 0,0);
  2258. if (pstPrivate->fBufrFull)
  2259. {
  2260. DBG_READ("DBG_READ: Refill Signalling EVENT_READ\r\n", 0,0,0,0,0);
  2261. SetEvent(pstPrivate->ahEvent[EVENT_READ]);
  2262. }
  2263. if (pstPrivate->pbComStart == pstPrivate->pbComEnd)
  2264. {
  2265. DBG_READ("DBG_READ: Refill setting fBufrEmpty = TRUE\r\n", 0,0,0,0,0);
  2266. pstPrivate->fBufrEmpty = TRUE;
  2267. ComNotify(pstPrivate->hCom, NODATA);
  2268. }
  2269. else
  2270. {
  2271. pstComCntrl = (ST_COM_CONTROL *)pstPrivate->hCom;
  2272. pstComCntrl->puchRBData = pstPrivate->pbComStart;
  2273. pstComCntrl->puchRBDataLimit = pstPrivate->pbComEnd;
  2274. fRetVal = TRUE;
  2275. }
  2276. LeaveCriticalSection(&pstPrivate->csect);
  2277. return fRetVal;
  2278. }
  2279. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2280. * FUNCTION: WsckRcvClear
  2281. *
  2282. * DESCRIPTION:
  2283. * Clears the receiver of all received data.
  2284. *
  2285. * ARGUMENTS:
  2286. * hCom -- a comm handle returned by an earlier call to ComCreateHandle
  2287. *
  2288. * RETURNS:
  2289. * COM_OK if data is cleared
  2290. * COM_DEVICE_ERROR if Windows com device driver returns an error
  2291. *
  2292. * AUTHOR:
  2293. * mcc 12/26/95 (taken almost entirely from comstd.c)
  2294. */
  2295. int WINAPI WsckRcvClear(void *pvPrivate)
  2296. {
  2297. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  2298. int iRetVal = COM_OK;
  2299. ST_COM_CONTROL *pstComCntrl;
  2300. EnterCriticalSection(&pstPrivate->csect);
  2301. pstComCntrl = (ST_COM_CONTROL *)pstPrivate->hCom;
  2302. // Set buffer pointers to clear out any data we might have queued
  2303. pstComCntrl->puchRBData = pstPrivate->pbBufrStart;
  2304. pstComCntrl->puchRBDataLimit = pstPrivate->pbBufrStart;
  2305. pstPrivate->pbReadEnd = pstPrivate->pbBufrStart;
  2306. pstPrivate->pbComStart = pstPrivate->pbBufrStart;
  2307. pstPrivate->pbComEnd = pstPrivate->pbBufrStart;
  2308. LeaveCriticalSection(&pstPrivate->csect);
  2309. return iRetVal;
  2310. }
  2311. // Buffered send routines
  2312. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2313. * FUNCTION: WsckSndBufrSend
  2314. *
  2315. * DESCRIPTION:
  2316. * Sends a buffer over the socket
  2317. *
  2318. * ARGUMENTS:
  2319. * pstPrivate Driver's private data structure
  2320. * pvBufr Pointer to data to send
  2321. * nSize Number of bytes to send
  2322. *
  2323. * RETURNS:
  2324. * COM_OK if successful
  2325. * COM_FAILED otherwise
  2326. *
  2327. *
  2328. * AUTHOR:
  2329. * mcc 12/26/95
  2330. */
  2331. int WINAPI WsckSndBufrSend(void *pvPrivate, void *pvBufr, int nSize)
  2332. {
  2333. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  2334. int iRetVal = COM_OK;
  2335. int iCode;
  2336. assert(pvBufr != (void *)0);
  2337. assert(nSize <= WSOCK_SIZE_OUTQ);
  2338. if (pstPrivate->fSending)
  2339. {
  2340. DbgOutStr("SBS: Busy", 0,0,0,0,0);
  2341. return COM_BUSY;
  2342. }
  2343. else if (nSize > 0)
  2344. {
  2345. ComNotify(pstPrivate->hCom, SEND_STARTED);
  2346. EnterCriticalSection(&pstPrivate->csect);
  2347. pstPrivate->pbSendBufr = pvBufr;
  2348. pstPrivate->nSendBufrLen = nSize;
  2349. pstPrivate->fSending = TRUE;
  2350. LeaveCriticalSection(&pstPrivate->csect);
  2351. // Tell the write thread to run
  2352. iCode = SetEvent(pstPrivate->ahEvent[EVENT_WRITE]);
  2353. DbgOutStr("SBS: %d bytes in buffer. SetEvent returns %d", nSize,
  2354. iCode,0,0,0);
  2355. }
  2356. return iRetVal;
  2357. }
  2358. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2359. * FUNCTION: WsckSndBufrClear
  2360. *
  2361. * DESCRIPTION:
  2362. *
  2363. *
  2364. * ARGUMENTS:
  2365. *
  2366. *
  2367. * RETURNS:
  2368. *
  2369. * AUTHOR:
  2370. * mcc 12/26/95
  2371. */
  2372. int WINAPI WsckSndBufrClear(void *pvPrivate)
  2373. {
  2374. ST_STDCOM *pstPrivate = (ST_STDCOM *) pvPrivate;
  2375. int iRetVal = COM_OK;
  2376. EnterCriticalSection(&pstPrivate->csect);
  2377. if (WsckSndBufrIsBusy(pstPrivate))
  2378. {
  2379. pstPrivate->fClearSendBufr = TRUE;
  2380. }
  2381. LeaveCriticalSection(&pstPrivate->csect);
  2382. return iRetVal;
  2383. }
  2384. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2385. * FUNCTION: WsckComWriteThread
  2386. *
  2387. * DESCRIPTION:
  2388. * One of the "main" threads of the comm driver ...
  2389. * Waits on an "anything to write?" semaphore
  2390. * When awakened, writes the write buffer in the driver data structure
  2391. * to the comm port and resets the semaphore
  2392. *
  2393. * ARGUMENTS
  2394. * pvData Address of driver data structure
  2395. *
  2396. *
  2397. * RETURNS:
  2398. * Nothing
  2399. *
  2400. * AUTHOR
  2401. * mcc 12/27/95 (stolen from Northport)
  2402. */
  2403. DWORD WINAPI WsckComWriteThread(void *pvData)
  2404. {
  2405. ST_STDCOM *pstPrivate = (ST_STDCOM *)pvData;
  2406. int nBytesWritten;
  2407. unsigned uSize, nBytesToSend, nBytesSent;
  2408. int fRunning = TRUE;
  2409. DWORD iResult = COM_OK;
  2410. char *pchData;
  2411. int iCode;
  2412. DBG_THREAD("DBG_THREAD: ComWriteThread starting",0,0,0,0,0);
  2413. // Initialize the "Something to write" semaphore to Reset, so that
  2414. // we will wait for SndBufrSend to hand something to us
  2415. if (! ResetEvent(pstPrivate->ahEvent[EVENT_WRITE]))
  2416. {
  2417. assert(0);
  2418. }
  2419. while (fRunning)
  2420. {
  2421. // Wait on a semaphore for something to write
  2422. iCode = WaitForSingleObject(pstPrivate->ahEvent[EVENT_WRITE],
  2423. (unsigned long) 60000);
  2424. DBG_WRITE("WrThread: Got EVENT_WRITE %d\n", iCode,0,0,0,0);
  2425. // Has anybody told us to shut down?
  2426. //
  2427. if (pstPrivate->fHaltThread)
  2428. {
  2429. DBG_WRITE(" WrThread: fHaltThread==TRUE, shutting down", 0,0,0,0,0);
  2430. ExitThread(0);
  2431. }
  2432. else
  2433. {
  2434. iResult = COM_OK;
  2435. EnterCriticalSection(&pstPrivate->csect);
  2436. pchData = pstPrivate->pbSendBufr;
  2437. nBytesToSend = (unsigned) pstPrivate->nSendBufrLen;
  2438. nBytesSent = 0;
  2439. if (nBytesToSend > 0)
  2440. {
  2441. DbgOutStr("WriteThrd: %d to send\n", nBytesToSend, 0,0,0,0);
  2442. // Loop until we send all the requested data
  2443. while ( fRunning && nBytesSent < nBytesToSend )
  2444. {
  2445. uSize = nBytesToSend - nBytesSent;
  2446. LeaveCriticalSection(&pstPrivate->csect);
  2447. assert(uSize > 0 && uSize < 32767);
  2448. nBytesWritten = send(pstPrivate->hSocket,
  2449. pchData,(int) uSize, 0);
  2450. DbgOutStr("WriteThrd: %d bytes of %d sent. 1st 3 = %x %x %x\n",
  2451. nBytesWritten, uSize, pchData[0], pchData[1], pchData[2]);
  2452. // We have an error -- probably the connection got dropped
  2453. // report it to the various interested parties
  2454. if ( nBytesWritten == -1 )
  2455. {
  2456. iResult = (unsigned) WSAGetLastError();
  2457. DbgOutStr("WriteThrd: error %d sending %d bytes (%d - %d). Byebye.\n",
  2458. iResult, (int) uSize, nBytesToSend,nBytesSent,0);
  2459. ComNotify(pstPrivate->hCom, CONNECT);
  2460. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  2461. fRunning = 0;
  2462. }
  2463. nBytesSent += (unsigned) nBytesWritten;
  2464. if (nBytesSent < nBytesToSend )
  2465. {
  2466. DbgOutStr("WrtThrd: can't send all data to socket\n",
  2467. 0,0,0,0,0);
  2468. pchData += nBytesWritten;
  2469. }
  2470. }
  2471. EnterCriticalSection(&pstPrivate->csect);
  2472. //DbgOutStr(" WrThread: Wrote %u bytes, %lu written, ret=%lu\n",
  2473. //uSize, nBytesWritten, 0, 0, 0);
  2474. // We've sent the buffer, so clear the Sending flag
  2475. pstPrivate->fSending = FALSE;
  2476. pstPrivate->nSendBufrLen = 0;
  2477. pstPrivate->pbSendBufr = NULL;
  2478. pstPrivate->fClearSendBufr = FALSE;
  2479. //DBG_WRITE(" WrThread: posting EVENT_SENT", 0,0,0,0,0);
  2480. // TOCO:mcc 12/29/95 SetEvent(pstPrivate->ahEvent[EVENT_SENT]);
  2481. }
  2482. if (pstPrivate->fHaltThread)
  2483. {
  2484. DBG_WRITE(" WrThread: fHaltThread==TRUE, shutting down", 0,0,0,0,0);
  2485. ExitThread(0);
  2486. }
  2487. DbgOutStr(" WrThread: setting fSending=FALSE, resetting EVENT_WRITE\n",
  2488. 0,0,0,0,0);
  2489. if (!ResetEvent(pstPrivate->ahEvent[EVENT_WRITE]))
  2490. {
  2491. assert(0);
  2492. }
  2493. LeaveCriticalSection(&pstPrivate->csect);
  2494. ComNotify(pstPrivate->hCom, SEND_DONE);
  2495. }
  2496. }
  2497. DbgOutStr("WriteThread exiting ...", 0,0,0,0,0);
  2498. ExitThread(0);
  2499. return (iResult);
  2500. }
  2501. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2502. * FUNCTION: WsckComReadThread
  2503. *
  2504. * DESCRIPTION:
  2505. * One of the main threads of the comm driver ...
  2506. * Reads data from the comm port as long as we have a place to put it
  2507. * If the buffer fills up, go to sleep until RcvRefill takes some data
  2508. * out of the buffer
  2509. *
  2510. *
  2511. * ARGUMENTS:
  2512. * pvData address of our private data structure
  2513. *
  2514. * RETURNS:
  2515. * nothing
  2516. *
  2517. * AUTHOR
  2518. * mcc 12/27/95 (stolen from Northport)
  2519. */
  2520. DWORD WINAPI WsckComReadThread(void *pvData)
  2521. {
  2522. ST_STDCOM *pstPrivate = (ST_STDCOM *)pvData;
  2523. int fRunning = TRUE;
  2524. int fReading = TRUE;
  2525. char *pbReadFrom, *pOut;
  2526. unsigned nReadSize;
  2527. long lBytesRead, nFFs;
  2528. int iResult;
  2529. int nIndx;
  2530. DWORD rc;
  2531. DBG_THREAD("DBG_THREAD: ComtcpReadThread starting",0,0,0,0,0);
  2532. EnterCriticalSection(&pstPrivate->csect);
  2533. // Set Read event to reset so we don't read until the connection is up
  2534. // By setting fBufrFull TRUE, the thread will think it is being
  2535. // reawakened from a full buffer condition when PortActivate posts the
  2536. // semaphore
  2537. pstPrivate->fBufrFull = TRUE;
  2538. ResetEvent(pstPrivate->ahEvent[EVENT_READ]);
  2539. LeaveCriticalSection(&pstPrivate->csect);
  2540. pstPrivate->fSeenFF = 0;
  2541. while ( fRunning )
  2542. {
  2543. // Wait for a wakeup call if we put ourself to sleep
  2544. //DbgOutStr("ReadThread: Waiting for EVENT_READ", 0,0,0,0,0);
  2545. rc = WaitForSingleObject(pstPrivate->ahEvent[EVENT_READ], 60000);
  2546. if ( rc != 0 )
  2547. {
  2548. DbgOutStr("ReadThread: EVENT_READ timed out. fBufFull=%d",
  2549. pstPrivate->fBufrFull,0,0,0,0);
  2550. }
  2551. else
  2552. {
  2553. //DbgOutStr("ReadThread: Got EVENT_READ.", 0,0,0,0,0);
  2554. }
  2555. // To get this thread to exit, the deactivate routine forces a
  2556. // fake com event by posting EVENT_READ
  2557. if (pstPrivate->fHaltThread)
  2558. {
  2559. DBG_THREAD("DBG_THREAD: Comtcp exiting thread",0,0,0,0,0);
  2560. fRunning = FALSE;
  2561. }
  2562. else
  2563. {
  2564. EnterCriticalSection(&pstPrivate->csect);
  2565. if (pstPrivate->fBufrFull)
  2566. {
  2567. //DbgOutStr("ReadThread: fBufrFull = FALSE", 0,0,0,0,0);
  2568. pstPrivate->fBufrFull = FALSE;
  2569. fReading = TRUE;
  2570. }
  2571. LeaveCriticalSection(&pstPrivate->csect);
  2572. // Do reads until we fill the buffer
  2573. while (fReading && fRunning)
  2574. {
  2575. // Check for wrap around in circular buffer
  2576. pbReadFrom = (pstPrivate->pbReadEnd >= pstPrivate->pbBufrEnd) ?
  2577. pstPrivate->pbBufrStart : pstPrivate->pbReadEnd;
  2578. nReadSize = (unsigned) (pbReadFrom < pstPrivate->pbComStart) ?
  2579. (unsigned) (pstPrivate->pbComStart - pbReadFrom - 1) :
  2580. (unsigned) (pstPrivate->pbBufrEnd - pbReadFrom);
  2581. if (nReadSize > WSOCK_MAX_READSIZE)
  2582. nReadSize = WSOCK_MAX_READSIZE;
  2583. if (!nReadSize)
  2584. {
  2585. DBG_READ("Read Thread -- fBufrFull = TRUE, unsignalling EVENT_READ\r\n",
  2586. 0,0,0,0,0);
  2587. pstPrivate->fBufrFull = TRUE;
  2588. ResetEvent(pstPrivate->ahEvent[EVENT_READ]);
  2589. break;
  2590. }
  2591. else
  2592. {
  2593. DBG_READ("ReadThread posting a recv\n", 0,0,0,0,0);
  2594. lBytesRead = recv(pstPrivate->hSocket, pbReadFrom,
  2595. (int)nReadSize, 0);
  2596. if (lBytesRead > 0)
  2597. {
  2598. pstPrivate->pbReadEnd += lBytesRead;
  2599. if (pstPrivate->pbReadEnd >= pstPrivate->pbBufrEnd)
  2600. pstPrivate->pbReadEnd = pstPrivate->pbBufrStart;
  2601. DBG_READ("DBG_READ: Thread -- recv completed synchronously,"
  2602. " lBytesRead==%ld, ReadEnd==%x\r\n",
  2603. lBytesRead, pstPrivate->pbReadEnd,0,0,0);
  2604. if (pstPrivate->fBufrEmpty)
  2605. {
  2606. DBG_READ("DBG_READ: Thread -- fBufrEmpty = FALSE\r\n", 0,0,0,0,0);
  2607. pstPrivate->fBufrEmpty = FALSE;
  2608. ComNotify(pstPrivate->hCom, DATA_RECEIVED);
  2609. }
  2610. if (pstPrivate->fEscapeFF)
  2611. {
  2612. // The sender escaped FF characters by doubling
  2613. // them. Copy the received data buffer onto itself,
  2614. // skipping every other FF
  2615. pOut = pbReadFrom;
  2616. nFFs = 0;
  2617. for (nIndx = 0; nIndx < lBytesRead; nIndx += 1)
  2618. {
  2619. if (pstPrivate->fSeenFF)
  2620. {
  2621. if (pbReadFrom[nIndx] == 0xFF)
  2622. {
  2623. // Skip this one
  2624. nFFs++;
  2625. }
  2626. else
  2627. {
  2628. // This should not happen, but copy
  2629. // anyway
  2630. *pOut = pbReadFrom[nIndx];
  2631. pOut++;
  2632. }
  2633. pstPrivate->fSeenFF = FALSE;
  2634. }
  2635. else
  2636. {
  2637. // Test to see if this is an FF; copy
  2638. // input to output.
  2639. if (pbReadFrom[nIndx] == 0xFF)
  2640. {
  2641. pstPrivate->fSeenFF = TRUE;
  2642. }
  2643. *pOut = pbReadFrom[nIndx];
  2644. pOut++;
  2645. }
  2646. }
  2647. // Decrement the number of bytes read by the
  2648. // number of duplicate FF's we tossed.
  2649. lBytesRead -= nFFs;
  2650. }
  2651. // Notify application that we got some data
  2652. // if buffer had been empty
  2653. EnterCriticalSection(&pstPrivate->csect);
  2654. if (pstPrivate->fBufrEmpty)
  2655. {
  2656. DBG_READ("DBG_READ: Thread -- fBufrEmpty = FALSE", 0,0,0,0,0);
  2657. pstPrivate->fBufrEmpty = FALSE;
  2658. }
  2659. LeaveCriticalSection(&pstPrivate->csect);
  2660. ComNotify(pstPrivate->hCom, DATA_RECEIVED);
  2661. }
  2662. else
  2663. {
  2664. // 0 value from recv indicates that the connection is closed;
  2665. // -1 indicates another error. Notify CNCT driver.
  2666. // (re-set the connection status
  2667. // if the error code indicates that the connection is down)
  2668. iResult = WSAGetLastError();
  2669. DbgOutStr("ReadThread: Got no data, err=%d", iResult, 0,0,0,0);
  2670. EnterCriticalSection(&pstPrivate->csect);
  2671. if ( lBytesRead == 0 ||
  2672. iResult == WSAENETDOWN ||
  2673. iResult == WSAENOTCONN ||
  2674. iResult == WSAEHOSTDOWN ||
  2675. iResult == WSAETIMEDOUT)
  2676. {
  2677. // Wait until we are told to shut down; don't try to read
  2678. // anymore!
  2679. ResetEvent(pstPrivate->ahEvent[EVENT_READ]);
  2680. pstPrivate->fConnected = COM_PORT_NOT_OPEN;
  2681. }
  2682. LeaveCriticalSection(&pstPrivate->csect);
  2683. ComNotify(pstPrivate->hCom, DATA_RECEIVED);
  2684. }
  2685. }
  2686. if (pstPrivate->fHaltThread)
  2687. {
  2688. DBG_THREAD("DBG_THREAD: Comtcp exiting thread",0,0,0,0,0);
  2689. fRunning = FALSE;
  2690. }
  2691. } // end of fReading && fRunning
  2692. }
  2693. } // end of fRunning loop
  2694. EnterCriticalSection(&pstPrivate->csect);
  2695. pstPrivate->hComReadThread = 0;
  2696. LeaveCriticalSection(&pstPrivate->csect);
  2697. DbgOutStr("ReadThread exiting ...", 0,0,0,0,0);
  2698. ExitThread(0);
  2699. return(0);
  2700. }
  2701. /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2702. * FUNCTION:
  2703. * wsckResolveAddress
  2704. *
  2705. * DESCRIPTION:
  2706. * Takes a numeric or symbolic net address string and returns
  2707. * a valid binary internet address.
  2708. *
  2709. * ARGUMENTS:
  2710. * pszRemote The remote system's address as a string
  2711. * pulAddr Pointer to binary internet address
  2712. *
  2713. * RETURNS:
  2714. * COM_OK If successful
  2715. * COM_NOT_FOUND If the address is invalid
  2716. *
  2717. * AUTHOR
  2718. * mcc 01/09/96 (stolen from Northport)
  2719. */
  2720. int wsckResolveAddress(TCHAR *pszRemote, unsigned long *pulAddr)
  2721. {
  2722. int iRetVal = COM_NOT_FOUND;
  2723. struct hostent *pstHost;
  2724. assert(pszRemote);
  2725. assert(pulAddr);
  2726. if (pszRemote && pulAddr)
  2727. {
  2728. // Convert pszRemote to an internet address. If not successful,
  2729. // assume that the string is a host NAME and try to turn
  2730. // that into an address
  2731. *pulAddr = inet_addr(pszRemote);
  2732. if ((*pulAddr == INADDR_NONE) || (*pulAddr == 0))
  2733. {
  2734. // If not a valid network address, it should be a name, so
  2735. // look that up (in the hosts file or via a name server)
  2736. pstHost = gethostbyname(pszRemote);
  2737. if ( pstHost)
  2738. *pulAddr = *((unsigned long *)pstHost->h_addr);
  2739. }
  2740. if ((*pulAddr != INADDR_NONE) && (*pulAddr != 0))
  2741. iRetVal = COM_OK;
  2742. else
  2743. iRetVal = COM_NOT_FOUND;
  2744. }
  2745. return iRetVal;
  2746. }
  2747. #endif // MULTITHREAD
  2748. #endif // INCL_WINSOCK