Source code of Windows XP (NT5)
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.

1134 lines
33 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* COMDEV.C - */
  4. /* */
  5. /* Windows Communication Routines */
  6. /* */
  7. /****************************************************************************/
  8. /*************************************************************************
  9. **
  10. ** Windows Communication Layer
  11. **
  12. ** This is the library interface layer for the Communications Device Driver.
  13. ** The driver presents an interface between windows based applications and the
  14. ** communications hardware.
  15. **
  16. ** /-----------------------------\
  17. ** / Windows \
  18. ** \ Application Program /
  19. ** \-----------------------------/
  20. ** | Windows Interface |
  21. ** +-----------------------------+
  22. ** | OEM Dependant LowLevel Code |
  23. ** /-----------------------------\
  24. ** / Machine Layer \
  25. ** \ Communications Hardware /
  26. ** \-----------------------------/
  27. **
  28. *************************************************************************/
  29. #define USECOMM
  30. #include "user.h"
  31. #include "comdev.h" /* Device driver structure defs */
  32. #include "comdevi.h" /* Device driver internal defs */
  33. HANDLE FAR GlobalDOSAlloc(LONG h);
  34. void FAR GlobalDOSFree(HANDLE h);
  35. #define length(string) lstrlen((char FAR *)string)
  36. #define UPPERCASE(x) MyToUpper(x)
  37. LPSTR NEAR PASCAL field(LPSTR, LPSTR);
  38. short getid(LPSTR);
  39. char FAR *GetMem(WORD);
  40. cinfo *cinfoPtr(int);
  41. void FreeMem(LPSTR);
  42. char _fastcall NEAR MyToUpper(char);
  43. /* Array of information for each communications device that we support. */
  44. cinfo rgcinfo[DEVMAX] = {0}; /* Device additional info table */
  45. /* Strings used for determining device characteristics. */
  46. static char CODESEG COMbuf[] = "COM1:9600,E,7,1";
  47. static char CODESEG LPTbuf[] = "LPT1";
  48. static char CODESEG AUXbuf[] = "AUX1"; /* AUX will map to COM1 */
  49. static char CODESEG PRNbuf[] = "PRN1"; /* PRN will map to LPT1 */
  50. #define CONFIGINDEX 5 /* Index to 9600,... in COMbuf */
  51. /*************************************************************************
  52. ** OpenComm - open a communication device
  53. **
  54. ** Synopsis:
  55. ** short OpenComm(pszComName, cbInQue, cbOutQue)
  56. ** FAR char *pszComName;
  57. ** ushort cbInQue;
  58. ** ushort cbOutQue;
  59. **
  60. ** Description:
  61. ** OpenComm opens a comunication device an associates a com handle with it. The
  62. ** communication device is initialized to a default configuration. The csetcom
  63. ** function call, below, should be used to initialized the device to alternate
  64. ** values.
  65. **
  66. ** OpenComm returns an id which is used in subsequent calls to reference the
  67. ** communication device, or a negative error initialization error code.
  68. **
  69. ** pszComName points to a string which contains "COMn" where "n" is allowed to
  70. ** range from 1 to the number of COMM devices supported by the OEM. cbInQue
  71. ** and cbOutQue reflect the receive and transmit queue sizes, respectively.
  72. ** These queues are allocated at open time, deallocated at close time, and are
  73. ** used by the interrupt driven transmit/receive software.
  74. **
  75. ** pszComName may also point to a string which contains "LPTn" where "n" is
  76. ** allowed to range from 1 to the number of LPT devices supported by the OEM.
  77. ** cbInQue and cbOutQue are ignored for LPT devices. LPT devices are not
  78. ** interrupt driven.
  79. **
  80. *************************************************************************/
  81. int API IOpenComm(LPSTR pszComName, WORD cbInQue, WORD cbOutQue)
  82. {
  83. short cidCur; /* ID of device */
  84. DCB dcbNew; /* Temp DCB */
  85. short ierr; /* Return code from inicom */
  86. register cinfo *pcinfo; /* pointer to information block */
  87. register qdb *pqdbNew; /* pointer to queue information */
  88. if ((cidCur = getid(pszComName)) == -1) /* if not recognized, return */
  89. return(IE_BADID); /* error to caller */
  90. pcinfo = cinfoPtr(cidCur); /* form pointer to info block */
  91. if (pcinfo->fOpen) /* if device already open */
  92. return(IE_OPEN); /* return error to caller */
  93. if (pcinfo->fReservedHardware)
  94. /* if device locked for some reason return error to caller ex locked for
  95. * use by mouse.
  96. */
  97. return(IE_HARDWARE);
  98. /* do nothing if device is LPTn. */
  99. if (!(cidCur & LPTx))
  100. {
  101. if( (cbInQue == 0) && (cbOutQue == 0) ) /* if Queue length's zero, */
  102. return(IE_MEMORY); /* return memory error right away, */
  103. /* so a buildDCB isn't done...
  104. this is a common method of
  105. finding if the comm port is
  106. already opened or not...
  107. wanted to make it fast */
  108. if (lstrlen(pszComName) < 4 || BuildCommDCB(pszComName, &dcbNew) == -1)
  109. {
  110. if (BuildCommDCB(COMbuf, &dcbNew) == -1)
  111. return(IE_DEFAULT);
  112. }
  113. pqdbNew = &pcinfo->qdbCur; /* form pointer to qdb */
  114. if ((pqdbNew->pqRx = GetMem(cbInQue)) == (char FAR *)NULL)
  115. return(IE_MEMORY); /* no room for Rx queue */
  116. if ((pqdbNew->pqTx = GetMem(cbOutQue)) == (char FAR *)NULL)
  117. {
  118. FreeMem(pqdbNew->pqRx); /* no room for Tx queue */
  119. return(IE_MEMORY);
  120. }
  121. pqdbNew->cbqRx = cbInQue;
  122. pqdbNew->cbqTx = cbOutQue;
  123. setque(cidCur,(qdb FAR *)pqdbNew); /* init the queue's as well */
  124. }
  125. dcbNew.Id = (char)cidCur; /* set device ID in dcb */
  126. ierr = inicom((DCB FAR *)&dcbNew); /* attempt to init */
  127. if (ierr)
  128. {
  129. if (!(cidCur & LPTx)) /* if a comm device */
  130. {
  131. FreeMem(pqdbNew->pqRx); /* free Tx queue */
  132. FreeMem(pqdbNew->pqTx); /* free Rx queue */
  133. }
  134. return(ierr); /* return error code */
  135. }
  136. pcinfo->fOpen = TRUE; /* indicate device open */
  137. pcinfo->hTask = GetCurrentTask();
  138. return(cidCur); /* all's well, return dev id */
  139. }
  140. #ifdef DISABLE
  141. int FAR PASCAL OpenCommFromDCB(LPDCB pdcb, WORD cbInQue, WORD cbOutQue)
  142. {
  143. short cidCur; /* ID of device */
  144. short ierr; /* Return code from inicom */
  145. register cinfo *pcinfo; /* pointer to information block */
  146. register qdb *pqdbNew; /* pointer to queue information */
  147. cidCur = (WORD)pdcb->Id & 0x00FF;
  148. if ((cidCur & LPTxMask) > ((cidCur & LPTx) ? (PIOMAX - 1) : (CDEVMAX - 1)))
  149. return(IE_BADID); /* check cid for validity */
  150. pcinfo = cinfoPtr(cidCur); /* form pointer to info block */
  151. if (pcinfo->fOpen) /* if device already open */
  152. return(IE_OPEN); /* return error to caller */
  153. if (!(cidCur & LPTx)) /* device is LPTn */
  154. {
  155. if( (cbInQue == 0) && (cbOutQue == 0) ) /* if Queue length's zero, */
  156. return(IE_MEMORY); /* return memory error right away, */
  157. /* so a buildDCB isn't done... this
  158. * is a common method of finding if
  159. * the comm port is already opened
  160. * or not... wanted to make it fast
  161. */
  162. pqdbNew = &pcinfo->qdbCur; /* form pointer to qdb */
  163. if ((pqdbNew->pqRx = GetMem(cbInQue)) == (char FAR *)NULL)
  164. return(IE_MEMORY); /* no room for Rx queue */
  165. if ((pqdbNew->pqTx = GetMem(cbOutQue)) == (char FAR *)NULL)
  166. {
  167. FreeMem(pqdbNew->pqRx); /* no room for Tx queue */
  168. return(IE_MEMORY);
  169. }
  170. pqdbNew->cbqRx = cbInQue;
  171. pqdbNew->cbqTx = cbOutQue;
  172. setque(cidCur,(qdb FAR *)pqdbNew); /* init the queue's as well */
  173. }
  174. ierr = inicom(pdcb); /* attempt to init */
  175. if (ierr)
  176. {
  177. if (!(cidCur & LPTx)) /* if a comm device */
  178. {
  179. FreeMem(pqdbNew->pqRx); /* free Tx queue */
  180. FreeMem(pqdbNew->pqTx); /* free Rx queue */
  181. }
  182. return(ierr); /* return error code */
  183. }
  184. pcinfo->fOpen = TRUE; /* indicate device open */
  185. pcinfo->hTask = GetCurrentTask();
  186. return(cidCur); /* all's well, return dev id */
  187. }
  188. #endif
  189. /*************************************************************************
  190. ** SetCommState - set communciation device configuration
  191. **
  192. ** Synopsis:
  193. ** int SetCommState(pdcb)
  194. ** LPDCB pdcb;
  195. **
  196. ** Description:
  197. ** pdcb points to an initialized Device Control Block for a device which
  198. ** has been openned. The referenced device, as defined by the dcb's id field,
  199. ** is set to the state as defined by the dcb. SetCommState returns 0 on
  200. ** success, or a negative initialization error code if an error occurred. Note
  201. ** that this will reinitialize all hardware and control as defined in the dcb,
  202. ** but will not empty transmit or receive queues.
  203. **
  204. *************************************************************************/
  205. int API ISetCommState(LPDCB pdcb)
  206. {
  207. if (cinfoPtr(pdcb->Id)->fOpen == 0)
  208. return(IE_NOPEN); /* File must be open first */
  209. return(setcom(pdcb));
  210. }
  211. /*************************************************************************
  212. ** GetCommState - return current dcb values
  213. **
  214. ** Synopsis:
  215. ** int GetCommState(cid,pdcb)
  216. ** WORD cid;
  217. ** LPDCB *pdcb;
  218. **
  219. ** Description:
  220. ** The dcb pointed to by pdcb is updated to reflect the current dcb in use
  221. ** for the device referenced by cid. Returns 0 on success, -1 on illegal
  222. ** handle or IE_OPEN if port has not been opened yet.
  223. **
  224. *************************************************************************/
  225. int API IGetCommState(register int cid, LPDCB pdcb)
  226. {
  227. LPDCB pdcbSrc;
  228. register int i;
  229. if (cinfoPtr(cid)->fOpen == 0) /* File must be open first */
  230. return(IE_NOPEN);
  231. if ( (pdcbSrc = getdcb(cid)) ) /* pointer to dcb for device */
  232. {
  233. i = sizeof(DCB);
  234. while (i--)
  235. *((char FAR *)pdcb)++ = *((char FAR *)pdcbSrc)++;
  236. return(0);
  237. }
  238. else
  239. return(-1);
  240. }
  241. /*************************************************************************
  242. ** ReadComm - read characters from communication device
  243. **
  244. ** Synopsis:
  245. ** int ReadComm(cid, pbuf, size)
  246. ** WORD cid;
  247. ** LPSTR *pbuf;
  248. ** int size;
  249. **
  250. ** Description:
  251. ** ReadComm reads size characters into pbuf and returns the number of characters
  252. ** actually read. If the return value equals size bytes there may exist
  253. ** additional characters to read. The return count will be less if the number
  254. ** of characters present in the receive queue is less. If the return value is
  255. ** 0 then no characters were present.
  256. **
  257. ** If the return value is negative, then an error was also detected, and an
  258. ** error code can be retrieved from GetCommError. The absolute value of the return
  259. ** value is the number of characters read. Note that this implies that if
  260. ** there are no characters to be read, then no error status can be returned,
  261. ** and GetCommError should be used to read the status.
  262. **
  263. *************************************************************************/
  264. int API IReadComm(int cid, LPSTR pbuf, int size)
  265. {
  266. register int cbT;
  267. int ch;
  268. cid &= 0xff; /* get "pure" device ID */
  269. if (size == 0) /* Empty read */
  270. return(0);
  271. if ((cid & LPTxMask) > ((cid & LPTx) ? (PIOMAX - 1) : (CDEVMAX - 1)))
  272. return(0); /* check cid for validity */
  273. if (cinfoPtr(cid)->fOpen == 0)
  274. return(0); /* can't assume valid dcb... */
  275. cbT = 0;
  276. if (cinfoPtr(cid)->fchUnget) /* if there's a backed-up char */
  277. {
  278. cinfoPtr(cid)->fchUnget = FALSE; /* return backed up char */
  279. *pbuf++ = cinfoPtr(cid)->chUnget; /* and update transfer count */
  280. cbT++;
  281. }
  282. /*note. reccom returns -2 if no */
  283. /*data available, - 1 if error */
  284. ch = 0;
  285. if (SELECTOROF(lpCommReadString) == NULL)
  286. {
  287. while (cbT < size) /* up to size characters */
  288. {
  289. if ((ch = reccom(cid)) < 0) /* stop when no char available */
  290. break; /* or error */
  291. *pbuf++ = (char)ch; /* place character in users buf */
  292. cbT++; /* and update transfer count */
  293. }
  294. }
  295. else
  296. {
  297. ch = 0;
  298. cbT = lpCommReadString(cid, pbuf, size);
  299. }
  300. return(ch == -1 ? -cbT : cbT);
  301. }
  302. /*************************************************************************
  303. ** UngetCommChar - push a character back onto receive queue.
  304. **
  305. ** Synopsis:
  306. ** int UngetCommChar(cid,ch)
  307. ** WORD cid;
  308. ** char ch;
  309. **
  310. ** Description:
  311. ** Allows an application to "back-up" one character in the receive character
  312. ** stream by placing a character back into the receive stream. This character
  313. ** is then the first character returned by the next call to ReadComm. UngetCommChar may
  314. ** only be called once between calls to ReadComm. Returns 0 on success, -1 if
  315. ** illegal id, or unable to back-up.
  316. **
  317. *************************************************************************/
  318. int API IUngetCommChar(int cid, char ch)
  319. {
  320. cid &= 0xFF; /* get "pure" device ID */
  321. if ((cid & LPTxMask) > ((cid & LPTx) ? (PIOMAX - 1) : (CDEVMAX - 1)))
  322. return(0); /* check cid for validity */
  323. if (cinfoPtr(cid)->fchUnget) /* have we already backed up 1 */
  324. return(-1);
  325. if (cinfoPtr(cid)->fOpen == 0) /* can't assume valid dcb... */
  326. return(-1);
  327. cinfoPtr(cid)->fchUnget = TRUE; /* set flag indicating backed-up*/
  328. cinfoPtr(cid)->chUnget = ch; /* and save the character */
  329. return(0);
  330. }
  331. /*************************************************************************
  332. ** WriteComm - write characters to communication device
  333. **
  334. ** Synopsis:
  335. ** int WriteComm(cid, pbuf, size)
  336. ** int cid;
  337. ** LPSTR *pbuf;
  338. ** int size;
  339. **
  340. ** Description:
  341. ** WriteComm will write size character to the communication device. The byte
  342. ** count written is returned on success, negative byte count on error. GetCommError
  343. ** can be used to retrieve any error code.
  344. **
  345. *************************************************************************/
  346. int API IWriteComm(int cid, LPSTR pbuf, int size)
  347. {
  348. int cbT;
  349. cid &= 0xFF; /* get "pure" device ID */
  350. if ((cid & LPTxMask) > ((cid & LPTx) ? (PIOMAX - 1) : (CDEVMAX - 1)))
  351. return(0); /* check cid for validity */
  352. /*return zero if not valid */
  353. if (cinfoPtr(cid)->fOpen == 0) /* verify port has been opened */
  354. return(-1);
  355. cbT = 0;
  356. if (SELECTOROF(lpCommWriteString) == NULL)
  357. {
  358. while (size--)
  359. {
  360. if (sndcom(cid,*pbuf++)) /* transmit character */
  361. return(-cbT); /* return if error */
  362. cbT++;
  363. }
  364. }
  365. else
  366. {
  367. cbT = lpCommWriteString(cid, pbuf, size);
  368. if (cbT < size)
  369. {
  370. /* For consistency, if we couldn't transmit all the characters we
  371. * were asked to, return the negative of the number actually
  372. * transmitted.
  373. */
  374. cbT = -cbT;
  375. }
  376. }
  377. return(cbT);
  378. }
  379. /*************************************************************************
  380. ** CloseComm - close communication device
  381. **
  382. ** Synopsis:
  383. ** int CloseComm(cid)
  384. ** ushort cid;
  385. **
  386. ** Description:
  387. ** closes the communication device and dealloctes any buffers. Returns 0 on
  388. ** success, -1 on error.
  389. **
  390. *************************************************************************/
  391. int API ICloseComm(int cid)
  392. {
  393. register cinfo *pcinfo;
  394. WORD retval;
  395. cid &= 0xFF; /* get "pure" device ID */
  396. if ((cid & LPTxMask) > ((cid & LPTx) ? (PIOMAX - 1) : (CDEVMAX - 1)))
  397. return(-1); /* return error, cid not valid */
  398. if ((pcinfo = cinfoPtr(cid))->fOpen==0) /* verify port opened ... */
  399. return(-1); /* return error, port not open */
  400. retval = trmcom(cid); /* terminate the device */
  401. if (retval == 0x8000) /* if invalid ID */
  402. return(-1); /* return error code */
  403. pcinfo->fOpen = FALSE; /* indicate not open */
  404. if (!(cid & LPTx))
  405. {
  406. FreeMem(pcinfo->qdbCur.pqRx); /* Free Rx buffer */
  407. FreeMem(pcinfo->qdbCur.pqTx); /* Free Rx buffer */
  408. }
  409. return(retval); /* 0 if OK, -2 if queue trashed */
  410. }
  411. /*************************************************************************
  412. ** GetCommError - return device status
  413. **
  414. ** Synopsis:
  415. ** short GetCommError(cid,pstat)
  416. ** ushort cid;
  417. ** stat FAR *pstat;
  418. **
  419. ** Description:
  420. ** GetCommError returns the most recent error code for the referenced device, or -1
  421. ** for an illegal handle. In addition, if pstat is non-zero, GetCommError also
  422. ** updates the status record it points to.
  423. **
  424. *************************************************************************/
  425. int API IGetCommError(int cid, COMSTAT FAR *pstat)
  426. {
  427. register WORD st;
  428. cid &= 0xFF;
  429. st = stacom(cid,pstat);
  430. if ((st != 0x8000) && pstat && (cinfoPtr(cid)->fchUnget))
  431. pstat->cbInQue++;
  432. return(st);
  433. }
  434. void FAR PASCAL SP_GPFaultCommCleanup(HANDLE hTask)
  435. /* effects: When the given task gp faults, we check if it had any comm ports
  436. * opened and we close them.
  437. */
  438. {
  439. register int i;
  440. for (i=0; i<DEVMAX; i++) /* check all devices */
  441. if (rgcinfo[i].fOpen && rgcinfo[i].hTask == hTask)
  442. /* if device is open */
  443. CloseComm(i); /* close it */
  444. }
  445. /*************************************************************************
  446. ** BuildCommDCB - Parse a string into a dcb.
  447. **
  448. ** Synopsis:
  449. ** short BuildCommDCB(pszDef,pdcb)
  450. ** char FAR *pszDef;
  451. ** DCB FAR *pdcb;
  452. **
  453. ** Description:
  454. ** Parses a passed string and fills appropriate fields in a dcb, the address
  455. ** off which is also passed. The string conforms to that of a DOS MODE
  456. ** command for COMn. For example: "COM1:9600,N,7,1". Returns 0 on success,
  457. ** -1 on error.
  458. **
  459. *************************************************************************/
  460. int API IBuildCommDCB(LPSTR pszDef, LPDCB pdcb)
  461. {
  462. register int i;
  463. register int tempid;
  464. char c;
  465. char szT[80]; /* buffer in which to put things*/
  466. LFillStruct((LPSTR)pdcb, sizeof(DCB), 0);/* zero the dcb since probably on
  467. * app's stack
  468. */
  469. pszDef = field(pszDef,(char FAR *)szT); /* Get first token */
  470. if ((tempid=getid((char FAR *)szT))==-1)/* Get ID of device */
  471. return(-1); /* Unknown device */
  472. pdcb->Id = (char)tempid; /* we have a device id */
  473. if (tempid & LPTx) /* if a LPTx port, then let the */
  474. return(0); /* rest default to whatever */
  475. pszDef = field(pszDef,(char FAR *)szT); /* next field */
  476. if (length(szT) < 2)
  477. return(-1); /* must be at least two chars */
  478. i = (szT[0] << 8) | szT[1]; /* cheap and sleazy mapping */
  479. switch (i) /* based on first 2 chars */
  480. {
  481. case 0x3131:
  482. i = 110;
  483. break;
  484. case 0x3135:
  485. i = 150;
  486. break;
  487. case 0x3330:
  488. i = 300;
  489. break;
  490. case 0x3630:
  491. i = 600;
  492. break;
  493. case 0x3132:
  494. i = 1200;
  495. break;
  496. case 0x3234:
  497. i = 2400;
  498. break;
  499. case 0x3438:
  500. i = 4800;
  501. break;
  502. case 0x3936:
  503. i = 9600;
  504. break;
  505. case 0x3139:
  506. i = 19200;
  507. break;
  508. case 0x3338: /* handle 38400 baud in BuildCommDCB() */
  509. i = 38400;
  510. break;
  511. default:
  512. return(-1);
  513. }
  514. pdcb->BaudRate = i;
  515. pdcb->XonLim = 10; /* Set these up always. */
  516. pdcb->XoffLim = 10; /* Set these up always. */
  517. pdcb->fBinary = 1; /* Set these up always. */
  518. pdcb->XonChar = 0x11; /* Ctrl-Q */
  519. pdcb->XoffChar = 0x13; /* Ctrl-S */
  520. if ((pszDef = field(pszDef,(char FAR *)szT)) == 0)
  521. return(0);
  522. switch (szT[0])
  523. {
  524. case 0:
  525. case 'E':
  526. c = EVENPARITY;
  527. break;
  528. case 'O':
  529. c = ODDPARITY;
  530. break;
  531. case 'N':
  532. c = NOPARITY;
  533. break;
  534. case 'M':
  535. c = MARKPARITY;
  536. break;
  537. case 'S':
  538. c = SPACEPARITY;
  539. break;
  540. default:
  541. return(-1);
  542. }
  543. pdcb->Parity = c;
  544. if ((pszDef = field(pszDef,(char FAR *)szT)) == 0)
  545. return(0);
  546. switch (szT[0])
  547. {
  548. case 0:
  549. case '7':
  550. c = 7;
  551. break;
  552. case '8':
  553. c = 8;
  554. break;
  555. default:
  556. return(-1);
  557. }
  558. pdcb->ByteSize = c;
  559. if ((pszDef = field(pszDef,(char FAR *)szT)) == 0)
  560. return(0);
  561. switch (szT[0])
  562. {
  563. case 0:
  564. if (pdcb->BaudRate == 110)
  565. {
  566. c = TWOSTOPBITS;
  567. break;
  568. }
  569. /*** FALL THRU ***/
  570. case '1':
  571. c = ONESTOPBIT;
  572. break;
  573. case '2':
  574. c = TWOSTOPBITS;
  575. break;
  576. default:
  577. return(-1);
  578. }
  579. pdcb->StopBits = c;
  580. if ((pszDef = field(pszDef,(char FAR *)szT)) == 0)
  581. return(0);
  582. if (szT[0] != 'P')
  583. return(-1);
  584. pdcb->RlsTimeout = INFINITE;
  585. pdcb->CtsTimeout = INFINITE;
  586. pdcb->DsrTimeout = INFINITE;
  587. return(0);
  588. }
  589. /*--------------------------------------------------------------------------*/
  590. /* */
  591. /* field() - */
  592. /* */
  593. /*--------------------------------------------------------------------------*/
  594. LPSTR NEAR PASCAL field(LPSTR pszSrc, LPSTR lpszDst)
  595. {
  596. register char c;
  597. if (!(pszSrc))
  598. return(char FAR *)0;
  599. if (!(*pszSrc))
  600. return(char FAR *)0;
  601. /* While not the end of the string. */
  602. while (c = *pszSrc)
  603. {
  604. pszSrc++;
  605. /* Look for end of string. */
  606. if ((c == ' ') || (c == ':') || (c == ','))
  607. {
  608. *lpszDst = 0;
  609. while (*pszSrc == ' ')
  610. pszSrc++;
  611. if (*pszSrc)
  612. return(pszSrc);
  613. return(char FAR *)0;
  614. }
  615. *lpszDst++ = UPPERCASE(c);
  616. }
  617. *lpszDst = 0;
  618. return(pszSrc);
  619. }
  620. /*************************************************************************
  621. **
  622. ** U T I L I T Y R O U T I N E S
  623. **
  624. **************************************************************************
  625. **
  626. ** getid
  627. ** Given a (far) pointer to a string, returns the comm ID of that device,
  628. ** or -1 indicating error. This routine accepts all device references of
  629. ** the form "COMn", where n is any number from 0 to 9, or "LPTn" where
  630. ** n is any number from 1 to 9
  631. **
  632. *************************************************************************/
  633. short getid(LPSTR pszComName)
  634. {
  635. int id;
  636. register int base;
  637. ushort isLPTorCOM;
  638. LPSTR pszName;
  639. #ifdef JAPAN
  640. /* Brought from WIN2 */
  641. /* ------------- support 'oemgetid' (Jul,29,1987 SatoN) ----------- */
  642. typedef int (far *FARPROC)();
  643. extern void far int3();
  644. static FARPROC lpOEMgetid = (FARPROC)(-1L);
  645. /* If lpOEMgetid has not been initialized yet, initialize it.
  646. This assumes 'GetProcAddress' does not cause FatalExit. */
  647. if (lpOEMgetid==(FARPROC)(-1L))
  648. {
  649. unsigned hComm;
  650. if ((hComm = GetModuleHandle( (char far *)"COMM" ))==NULL)
  651. lpOEMgetid = NULL;
  652. else
  653. lpOEMgetid = GetProcAddress( hComm,(char far *)"oemgetid" );
  654. }
  655. /* If COMM driver has the routine 'oemgetid', then call it. */
  656. if (lpOEMgetid && (id=(*lpOEMgetid)(pszComName))!=-1)
  657. return id;
  658. /* ------------- end of support 'oemgetid' ---------------------- */
  659. #endif /* JAPAN */
  660. isLPTorCOM = TRUE; /* assume LPTx or COMx */
  661. base = 0; /* assume serial */
  662. id = 0; /* assume LPT1 or COM1 9/25/86 */
  663. switch (UPPERCASE(*pszComName))
  664. {
  665. case 'A': /* AUX possibility */
  666. pszName = AUXbuf; /* Search string to match */
  667. isLPTorCOM = FALSE; /* Show AUX or PRN */
  668. break;
  669. case 'C': /* COMx possibility */
  670. pszName = COMbuf; /* Search string to match */
  671. break; /* cid base */
  672. case 'L': /* LPTx possibility */
  673. pszName = LPTbuf; /* Search string to match */
  674. base = LPTx; /* cid base */
  675. break;
  676. case 'P': /* PRN possibility */
  677. pszName = PRNbuf; /* Search string to match */
  678. base = LPTx; /* cid base */
  679. isLPTorCOM = FALSE; /* Show AUX or PRN */
  680. break;
  681. default:
  682. return(-1);
  683. }
  684. while(*pszName != '1') /* make sure strings match */
  685. {
  686. if (*pszName++ != UPPERCASE(*pszComName++))
  687. return(-1);
  688. }
  689. if (isLPTorCOM || /* then get device number */
  690. (*pszComName && *pszComName != ':'))/* accept PRN or AUX */
  691. id = (*pszComName++) - '1';
  692. if (*pszComName == ':') /* skip ':' if present */
  693. pszComName++;
  694. if ((id < 0) || (*pszComName != '\0'))
  695. return(-1);
  696. if (id > (base ? (PIOMAX - 1) : (CDEVMAX - 1)))
  697. return(-1);
  698. return(base + id);
  699. }
  700. /*--------------------------------------------------------------------------*/
  701. /* */
  702. /* cinfoPtr() - */
  703. /* */
  704. /*--------------------------------------------------------------------------*/
  705. cinfo *cinfoPtr(int cid)
  706. {
  707. if (cid & LPTx)
  708. return(&rgcinfo[((cid & LPTxMask)+CDEVMAX)]);
  709. return(&rgcinfo[(cid & 0xFF)]);
  710. }
  711. /*************************************************************************
  712. **
  713. ** GetMem
  714. ** Uses windows memory allocator to get far, global memory. We fudge here,
  715. ** in that GlobalAlloc returns a handle, which happens to be the segment
  716. ** of the fixed memory we've asked for. Hence we need to fudge it to get
  717. ** an address.
  718. **
  719. *************************************************************************/
  720. LPSTR GetMem(WORD size)
  721. {
  722. /* See if the 286 DOS extender is installed, and if so, we must allocate
  723. memory from conventional memory, so the queue can be used in both
  724. protect and real modes (segment/selector ablility)
  725. */
  726. if( (WinFlags & (WF_PMODE|WF_WIN286)) == (WF_PMODE|WF_WIN286) )
  727. {
  728. return(MAKELP(GlobalDOSAlloc((LONG)size), NULL));
  729. }
  730. else
  731. {
  732. return(MAKELP(GlobalAlloc(
  733. GMEM_LOWER | GMEM_SHARE | GMEM_ZEROINIT | GMEM_FIXED,
  734. (LONG)size), NULL));
  735. }
  736. }
  737. /*--------------------------------------------------------------------------*/
  738. /* */
  739. /* FreeMem() - */
  740. /* */
  741. /*--------------------------------------------------------------------------*/
  742. void FreeMem(LPSTR pMem)
  743. {
  744. /* See if the 286 DOS extender is installed, and if so, we must deallocate
  745. memory from conventional memory, so the queue can be used in both
  746. protect and real modes (segment/selector ablility)
  747. */
  748. if( (WinFlags & (WF_PMODE|WF_WIN286)) == (WF_PMODE|WF_WIN286) )
  749. {
  750. GlobalDOSFree((HANDLE)(((LONG)pMem) >> 16));
  751. }
  752. else
  753. {
  754. GlobalFree((HANDLE)(((LONG)pMem) >> 16));
  755. }
  756. }
  757. /*--------------------------------------------------------------------------*/
  758. /* */
  759. /* TransmitCommChar() - */
  760. /* */
  761. /*--------------------------------------------------------------------------*/
  762. int API ITransmitCommChar(int cid, char character)
  763. {
  764. cid &= 0xFF;
  765. return(ctx(cid, character));
  766. }
  767. /*--------------------------------------------------------------------------*/
  768. /* */
  769. /* SetCommEventMask() - */
  770. /* */
  771. /*--------------------------------------------------------------------------*/
  772. WORD FAR * API ISetCommEventMask(int cid, WORD evtmask)
  773. {
  774. cid &= 0xFF;
  775. return(cevt(cid, evtmask));
  776. }
  777. /*--------------------------------------------------------------------------*/
  778. /* */
  779. /* GetCommEventMask() - */
  780. /* */
  781. /*--------------------------------------------------------------------------*/
  782. WORD API IGetCommEventMask(int cid, int evtmask)
  783. {
  784. cid &= 0xFF;
  785. return(cevtGet(cid, evtmask));
  786. }
  787. /*--------------------------------------------------------------------------*/
  788. /* */
  789. /* SetCommBreak() - */
  790. /* */
  791. /*--------------------------------------------------------------------------*/
  792. int API ISetCommBreak(int cid)
  793. {
  794. cid &= 0xFF;
  795. return(csetbrk(cid));
  796. }
  797. /*--------------------------------------------------------------------------*/
  798. /* */
  799. /* ClearCommBreak() - */
  800. /* */
  801. /*--------------------------------------------------------------------------*/
  802. int API IClearCommBreak(int cid)
  803. {
  804. cid &= 0xFF;
  805. return(cclrbrk(cid));
  806. }
  807. /*--------------------------------------------------------------------------*/
  808. /* */
  809. /* FlushComm() - */
  810. /* */
  811. /*--------------------------------------------------------------------------*/
  812. /* Parameters:
  813. * ushort cid -- 0=com1 1=com2
  814. * ushort queue -- 0 = clear transmit 1 = receive
  815. */
  816. int API IFlushComm(int cid, int queue)
  817. {
  818. cid &= 0xFF;
  819. return(cflush(cid, queue));
  820. }
  821. /*--------------------------------------------------------------------------*/
  822. /* */
  823. /* EscapeCommFunction() - */
  824. /* */
  825. /*--------------------------------------------------------------------------*/
  826. LONG API IEscapeCommFunction(int cid, int fcn)
  827. {
  828. LONG ret;
  829. cid &= 0xFF;
  830. ret = cextfcn(cid, fcn);
  831. if (SELECTOROF(lpCommWriteString) == NULL)
  832. {
  833. #if 0
  834. if (fcn == GETMAXBAUD)
  835. /* For 3.0 drivers, fake the maxbaud rate escape.
  836. */
  837. ret = (LONG)CBR_19200;
  838. else
  839. #endif
  840. if (fcn == GETMAXLPT)
  841. ret = (LONG)LPTx+2; /* 3 lpt ports */
  842. else
  843. if (fcn == GETMAXCOM)
  844. ret = (LONG)9;
  845. else
  846. if ((WORD)fcn <= RESETDEV)
  847. /* New for 3.1, we need to return a long from this function. So fix
  848. * things up for old 3.0 drivers who used the defined escape range
  849. * (we had 7 escapes for 3.0 drivers).
  850. */
  851. ret = (LONG)(int)(LOWORD(ret));
  852. }
  853. return(ret);
  854. }
  855. /*--------------------------------------------------------------------------*/
  856. /* */
  857. /* EnableCommNotification() - */
  858. /* */
  859. /*--------------------------------------------------------------------------*/
  860. BOOL API IEnableCommNotification(int cid, HWND hwnd,
  861. int recvth, int sendth)
  862. {
  863. cid &= 0xFF;
  864. if (SELECTOROF(lpCommEnableNotification) == NULL)
  865. return(FALSE);
  866. return(lpCommEnableNotification(cid, hwnd, recvth, sendth));
  867. }
  868. /*--------------------------------------------------------------------------*/
  869. /* */
  870. /* MyToUpper() - */
  871. /* */
  872. /*--------------------------------------------------------------------------*/
  873. char _fastcall NEAR MyToUpper(char c)
  874. {
  875. return((c < (char)'a') ? c : c - (char)32);
  876. }
  877. /*--------------------------------------------------------------------------*/
  878. /* */
  879. /* LW_DriversInit() - */
  880. /* */
  881. /*--------------------------------------------------------------------------*/
  882. void LW_DriversInit(void)
  883. {
  884. HMODULE hModule;
  885. char szString[128];
  886. /*------------------------------------------------------------------------*/
  887. /* Comm Initialization */
  888. /*------------------------------------------------------------------------*/
  889. /* Find out if the poor user is running with a 3.0 comm driver. Do this by
  890. * checking for the 3.1 function WriteCommString. Also, save off the
  891. * addresses of these functions so we don't rip had we imported them
  892. * directly.
  893. */
  894. LoadString(hInstanceWin, STR_COMMMODULENAME, szString, sizeof(szString));
  895. hModule = GetModuleHandle(szString);
  896. LoadString(hInstanceWin, STR_COMMWRITESTRING, szString, sizeof(szString));
  897. (FARPROC)lpCommWriteString = GetProcAddress((HINSTANCE)hModule, szString);
  898. LoadString(hInstanceWin, STR_COMMREADSTRING, szString, sizeof(szString));
  899. (FARPROC)lpCommReadString = GetProcAddress((HINSTANCE)hModule, szString);
  900. LoadString(hInstanceWin, STR_COMMENABLENOTIFICATION, szString, sizeof(szString));
  901. (FARPROC)lpCommEnableNotification = GetProcAddress((HINSTANCE)hModule, szString);
  902. }