2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
36 #include "wine/port.h"
49 #ifdef HAVE_SYS_FILIO_H
50 # include <sys/filio.h>
52 #include <sys/ioctl.h>
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
65 #include "wine/server.h"
69 #include "debugtools.h"
71 DEFAULT_DEBUG_CHANNEL(comm);
73 #if !defined(TIOCINQ) && defined(FIONREAD)
74 #define TIOCINQ FIONREAD
77 static int WinError(void)
79 TRACE("errno = %d\n", errno);
86 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
88 unsigned int mstat, okay;
89 okay = ioctl(fd, TIOCMGET, &mstat);
90 if (okay) return okay;
91 if (andy) mstat &= andy;
93 return ioctl(fd, TIOCMSET, &mstat);
96 /***********************************************************************
97 * COMM_BuildOldCommDCB (Internal)
99 * Build a DCB using the old style settings string eg: "COMx:96,n,8,1"
100 * We ignore the COM port index, since we can support more than 4 ports.
102 BOOL WINAPI COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
104 /* "COM1:96,n,8,1" */
106 char *ptr, temp[256], last;
109 TRACE("(%s), ptr %p\n", device, lpdcb);
111 if (strncasecmp(device,"COM",3))
117 if (*(device+4) != ':')
120 strcpy(temp,device+5);
121 last=temp[strlen(temp)-1];
122 ptr = strtok(temp, ", ");
124 /* DOS/Windows only compares the first two numbers
125 * and assigns an appropriate baud rate.
126 * You can supply 961324245, it still returns 9600 ! */
129 WARN("Unknown baudrate string '%s' !\n", ptr);
130 return FALSE; /* error: less than 2 chars */
151 WARN("Unknown baudrate indicator %d !\n", rate);
155 lpdcb->BaudRate = rate;
156 TRACE("baudrate (%ld)\n", lpdcb->BaudRate);
158 ptr = strtok(NULL, ", ");
160 *ptr = toupper(*ptr);
162 TRACE("parity (%c)\n", *ptr);
163 lpdcb->fParity = TRUE;
166 lpdcb->Parity = NOPARITY;
167 lpdcb->fParity = FALSE;
170 lpdcb->Parity = EVENPARITY;
173 lpdcb->Parity = MARKPARITY;
176 lpdcb->Parity = ODDPARITY;
179 WARN("Unknown parity `%c'!\n", *ptr);
183 ptr = strtok(NULL, ", ");
184 TRACE("charsize (%c)\n", *ptr);
185 lpdcb->ByteSize = *ptr - '0';
187 ptr = strtok(NULL, ", ");
188 TRACE("stopbits (%c)\n", *ptr);
191 lpdcb->StopBits = ONESTOPBIT;
194 lpdcb->StopBits = TWOSTOPBITS;
197 WARN("Unknown # of stopbits `%c'!\n", *ptr);
204 lpdcb->fOutxCtsFlow = FALSE;
205 lpdcb->fOutxDsrFlow = FALSE;
206 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
207 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
208 } else if (last=='p') {
210 lpdcb->fOutX = FALSE;
211 lpdcb->fOutxCtsFlow = TRUE;
212 lpdcb->fOutxDsrFlow = TRUE;
213 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
214 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
217 lpdcb->fOutX = FALSE;
218 lpdcb->fOutxCtsFlow = FALSE;
219 lpdcb->fOutxDsrFlow = FALSE;
220 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
221 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
227 /**************************************************************************
228 * BuildCommDCBA (KERNEL32.@)
230 * Updates a device control block data structure with values from an
231 * ascii device control string. The device control string has two forms
232 * normal and extended, it must be exclusively in one or the other form.
236 * True on success, false on an malformed control string.
238 BOOL WINAPI BuildCommDCBA(
239 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
240 LPDCB lpdcb) /* [out] The device control block to be updated. */
242 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
245 /**************************************************************************
246 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
248 * Updates a device control block data structure with values from an
249 * ascii device control string. Taking time out values from a time outs
250 * struct if desired by the control string.
254 * True on success, false bad handles etc
256 BOOL WINAPI BuildCommDCBAndTimeoutsA(
257 LPCSTR device, /* [in] The ascii device control string. */
258 LPDCB lpdcb, /* [out] The device control block to be updated. */
259 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
264 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
266 if (!strncasecmp(device,"COM",3)) {
269 ERR("BUG! COM0 can't exist!\n");
272 if (*(device+4)!=':')
274 temp=(LPSTR)(device+5);
278 memset(lpdcb,0,sizeof (DCB));
279 lpdcb->DCBlength = sizeof(DCB);
280 if (strchr(temp,',')) { /* old style */
282 return COMM_BuildOldCommDCB(device,lpdcb);
284 ptr=strtok(temp," ");
289 if (!strncmp("baud=",ptr,5)) {
290 if (!sscanf(ptr+5,"%ld",&x))
291 WARN("Couldn't parse %s\n",ptr);
295 if (!strncmp("stop=",ptr,5)) {
296 if (!sscanf(ptr+5,"%ld",&x))
297 WARN("Couldn't parse %s\n",ptr);
301 if (!strncmp("data=",ptr,5)) {
302 if (!sscanf(ptr+5,"%ld",&x))
303 WARN("Couldn't parse %s\n",ptr);
307 if (!strncmp("parity=",ptr,7)) {
308 lpdcb->fParity = TRUE;
311 lpdcb->fParity = FALSE;
312 lpdcb->Parity = NOPARITY;
315 lpdcb->Parity = EVENPARITY;
318 lpdcb->Parity = ODDPARITY;
321 lpdcb->Parity = MARKPARITY;
327 ERR("Unhandled specifier '%s', please report.\n",ptr);
328 ptr=strtok(NULL," ");
330 if (lpdcb->BaudRate==110)
335 /**************************************************************************
336 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
338 * Updates a device control block data structure with values from an
339 * unicode device control string. Taking time out values from a time outs
340 * struct if desired by the control string.
344 * True on success, false bad handles etc.
346 BOOL WINAPI BuildCommDCBAndTimeoutsW(
347 LPCWSTR devid, /* [in] The unicode device control string. */
348 LPDCB lpdcb, /* [out] The device control block to be updated. */
349 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
354 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
355 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
358 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
359 HeapFree( GetProcessHeap(), 0, devidA );
364 /**************************************************************************
365 * BuildCommDCBW (KERNEL32.@)
367 * Updates a device control block structure with values from an
368 * unicode device control string. The device control string has two forms
369 * normal and extended, it must be exclusively in one or the other form.
373 * True on success, false on an malformed control string.
375 BOOL WINAPI BuildCommDCBW(
376 LPCWSTR devid, /* [in] The unicode device control string. */
377 LPDCB lpdcb) /* [out] The device control block to be updated. */
379 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
382 /* FIXME: having these global for win32 for now */
385 /*****************************************************************************
386 * SetCommBreak (KERNEL32.@)
388 * Halts the transmission of characters to a communications device.
392 * True on success, and false if the communications device could not be found,
393 * the control is not supported.
397 * Only TIOCSBRK and TIOCCBRK are supported.
399 BOOL WINAPI SetCommBreak(
400 HANDLE handle) /* [in] The communictions device to suspend. */
402 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
405 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
407 TRACE("FILE_GetUnixHandle failed\n");
410 result = ioctl(fd,TIOCSBRK,0);
414 TRACE("ioctl failed\n");
415 SetLastError(ERROR_NOT_SUPPORTED);
420 FIXME("ioctl not available\n");
421 SetLastError(ERROR_NOT_SUPPORTED);
426 /*****************************************************************************
427 * ClearCommBreak (KERNEL32.@)
429 * Resumes character transmission from a communication device.
433 * True on success and false if the communications device could not be found.
437 * Only TIOCSBRK and TIOCCBRK are supported.
439 BOOL WINAPI ClearCommBreak(
440 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
442 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
445 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
447 TRACE("FILE_GetUnixHandle failed\n");
450 result = ioctl(fd,TIOCCBRK,0);
454 TRACE("ioctl failed\n");
455 SetLastError(ERROR_NOT_SUPPORTED);
460 FIXME("ioctl not available\n");
461 SetLastError(ERROR_NOT_SUPPORTED);
466 /*****************************************************************************
467 * EscapeCommFunction (KERNEL32.@)
469 * Directs a communication device to perform an extended function.
473 * True or requested data on successful completion of the command,
474 * false if the device is not present cannot execute the command
475 * or the command failed.
477 BOOL WINAPI EscapeCommFunction(
478 HANDLE handle, /* [in] The communication device to perform the extended function. */
479 UINT nFunction) /* [in] The extended function to be performed. */
481 int fd,direct=FALSE,result=FALSE;
484 TRACE("handle %d, function=%d\n", handle, nFunction);
485 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
487 FIXME("handle %d not found.\n",handle);
491 if (tcgetattr(fd,&port) == -1) {
492 commerror=WinError();
506 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
514 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
522 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
530 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
536 port.c_iflag |= IXOFF;
541 port.c_iflag |= IXON;
547 result = ioctl(fd,TIOCSBRK,0);
554 result = ioctl(fd,TIOCCBRK,0);
558 WARN("(handle=%d,nFunction=%d): Unknown function\n",
564 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
565 commerror = WinError();
575 commerror=WinError();
584 /********************************************************************
585 * PurgeComm (KERNEL32.@)
587 * Terminates pending operations and/or discards buffers on a
588 * communication resource.
592 * True on success and false if the communications handle is bad.
594 BOOL WINAPI PurgeComm(
595 HANDLE handle, /* [in] The communication resource to be purged. */
596 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
600 TRACE("handle %d, flags %lx\n", handle, flags);
602 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
604 FIXME("no handle %d found\n",handle);
609 ** not exactly sure how these are different
610 ** Perhaps if we had our own internal queues, one flushes them
611 ** and the other flushes the kernel's buffers.
613 if(flags&PURGE_TXABORT)
614 tcflush(fd,TCOFLUSH);
615 if(flags&PURGE_RXABORT)
616 tcflush(fd,TCIFLUSH);
617 if(flags&PURGE_TXCLEAR)
618 tcflush(fd,TCOFLUSH);
619 if(flags&PURGE_RXCLEAR)
620 tcflush(fd,TCIFLUSH);
626 /*****************************************************************************
627 * ClearCommError (KERNEL32.@)
629 * Enables further I/O operations on a communications resource after
630 * supplying error and current status information.
634 * True on success, false if the communication resource handle is bad.
636 BOOL WINAPI ClearCommError(
637 HANDLE handle, /* [in] The communication resource with the error. */
638 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
639 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
643 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
646 FIXME("no handle %d found\n",handle);
655 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
656 WARN("ioctl returned error\n");
658 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
662 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
663 WARN("ioctl returned error\n");
666 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
667 handle, lpStat->cbInQue, lpStat->cbOutQue);
676 ** After an asynchronous write opperation, the
677 ** app will call ClearCommError to see if the
678 ** results are ready yet. It waits for ERROR_IO_PENDING
680 commerror = ERROR_IO_PENDING;
685 /*****************************************************************************
686 * SetupComm (KERNEL32.@)
688 * Called after CreateFile to hint to the communication resource to use
689 * specified sizes for input and output buffers rather than the default values.
693 * True if successful, false if the communications resource handle is bad.
699 BOOL WINAPI SetupComm(
700 HANDLE handle, /* [in] The just created communication resource handle. */
701 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
702 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
706 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
707 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
709 FIXME("handle %d not found?\n",handle);
716 /*****************************************************************************
717 * GetCommMask (KERNEL32.@)
719 * Obtain the events associated with a communication device that will cause a call
720 * WaitCommEvent to return.
724 * True on success, fail on bad device handle etc.
726 BOOL WINAPI GetCommMask(
727 HANDLE handle, /* [in] The communications device. */
728 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
732 TRACE("handle %d, mask %p\n", handle, evtmask);
734 SERVER_START_REQ( get_serial_info )
736 req->handle = handle;
737 if ((ret = !SERVER_CALL_ERR()))
739 if (evtmask) *evtmask = req->eventmask;
746 /*****************************************************************************
747 * SetCommMask (KERNEL32.@)
749 * There be some things we need to hear about yon there communications device.
750 * (Set which events associated with a communication device should cause
751 * a call WaitCommEvent to return.)
755 * True on success, false on bad handle etc.
757 BOOL WINAPI SetCommMask(
758 HANDLE handle, /* [in] The communications device. */
759 DWORD evtmask) /* [in] The events that to be monitored. */
763 TRACE("handle %d, mask %lx\n", handle, evtmask);
765 SERVER_START_REQ( set_serial_info )
767 req->handle = handle;
768 req->flags = SERIALINFO_SET_MASK;
769 req->eventmask = evtmask;
770 ret = !SERVER_CALL_ERR();
776 /*****************************************************************************
777 * SetCommState (KERNEL32.@)
779 * Re-initializes all hardware and control settings of a communications device,
780 * with values from a device control block without effecting the input and output
785 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
787 BOOL WINAPI SetCommState(
788 HANDLE handle, /* [in] The communications device. */
789 LPDCB lpdcb) /* [out] The device control block. */
792 int fd, bytesize, stopbits;
794 TRACE("handle %d, ptr %p\n", handle, lpdcb);
795 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
796 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
797 (lpdcb->StopBits == ONESTOPBIT)?1:
798 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
799 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
800 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
802 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
804 FIXME("no handle %d found\n",handle);
808 if ((tcgetattr(fd,&port)) == -1) {
809 int save_error = errno;
810 commerror = WinError();
812 ERR("tcgetattr error '%s'\n", strerror(save_error));
817 port.c_cc[VTIME] = 1;
820 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
822 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
824 port.c_iflag |= (IGNBRK);
826 port.c_oflag &= ~(OPOST);
828 port.c_cflag &= ~(HUPCL);
829 port.c_cflag |= CLOCAL | CREAD;
831 port.c_lflag &= ~(ICANON|ECHO|ISIG);
832 port.c_lflag |= NOFLSH;
835 ** MJM - removed default baudrate settings
836 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
839 port.c_cflag &= ~CBAUD;
840 switch (lpdcb->BaudRate) {
843 port.c_cflag |= B110;
847 port.c_cflag |= B300;
851 port.c_cflag |= B600;
855 port.c_cflag |= B1200;
859 port.c_cflag |= B2400;
863 port.c_cflag |= B4800;
867 port.c_cflag |= B9600;
871 port.c_cflag |= B19200;
875 port.c_cflag |= B38400;
879 port.c_cflag |= B57600;
884 port.c_cflag |= B115200;
889 port.c_cflag |= B230400;
894 port.c_cflag |= B460800;
898 commerror = IE_BAUDRATE;
900 ERR("baudrate %ld\n",lpdcb->BaudRate);
903 #elif !defined(__EMX__)
904 switch (lpdcb->BaudRate) {
907 port.c_ospeed = B110;
911 port.c_ospeed = B300;
915 port.c_ospeed = B600;
919 port.c_ospeed = B1200;
923 port.c_ospeed = B2400;
927 port.c_ospeed = B4800;
931 port.c_ospeed = B9600;
935 port.c_ospeed = B19200;
939 port.c_ospeed = B38400;
942 commerror = IE_BAUDRATE;
944 ERR("baudrate %ld\n",lpdcb->BaudRate);
947 port.c_ispeed = port.c_ospeed;
949 bytesize=lpdcb->ByteSize;
950 stopbits=lpdcb->StopBits;
953 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
955 port.c_cflag &= ~(PARENB | PARODD);
958 port.c_iflag |= INPCK;
960 port.c_iflag &= ~INPCK;
961 switch (lpdcb->Parity) {
965 port.c_cflag |= (PARENB | PARODD);
968 port.c_cflag |= PARENB;
971 /* Linux defines mark/space (stick) parity */
973 port.c_cflag |= (PARENB | CMSPAR);
976 port.c_cflag |= (PARENB | PARODD | CMSPAR);
979 /* try the POSIX way */
981 if( stopbits == ONESTOPBIT) {
982 stopbits = TWOSTOPBITS;
983 port.c_iflag &= ~INPCK;
985 commerror = IE_BYTESIZE;
987 ERR("Cannot set MARK Parity\n");
994 port.c_iflag &= ~INPCK;
996 commerror = IE_BYTESIZE;
998 ERR("Cannot set SPACE Parity\n");
1004 commerror = IE_BYTESIZE;
1011 port.c_cflag &= ~CSIZE;
1014 port.c_cflag |= CS5;
1017 port.c_cflag |= CS6;
1020 port.c_cflag |= CS7;
1023 port.c_cflag |= CS8;
1026 commerror = IE_BYTESIZE;
1034 port.c_cflag &= ~CSTOPB;
1036 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1038 port.c_cflag |= CSTOPB;
1041 commerror = IE_BYTESIZE;
1047 if ( lpdcb->fOutxCtsFlow ||
1048 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1051 port.c_cflag |= CRTSCTS;
1055 if (lpdcb->fDtrControl == DTR_CONTROL_ENABLE)
1057 port.c_cflag &= ~CRTSCTS;
1058 TRACE("~CRTSCTS\n");
1063 port.c_iflag |= IXON;
1065 port.c_iflag &= ~IXON;
1067 port.c_iflag |= IXOFF;
1069 port.c_iflag &= ~IXOFF;
1071 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1072 int save_error=errno;
1073 commerror = WinError();
1075 ERR("tcsetattr error '%s'\n", strerror(save_error));
1085 /*****************************************************************************
1086 * GetCommState (KERNEL32.@)
1088 * Fills in a device control block with information from a communications device.
1092 * True on success, false if the communication device handle is bad etc
1096 * XonChar and XoffChar are not set.
1098 BOOL WINAPI GetCommState(
1099 HANDLE handle, /* [in] The communications device. */
1100 LPDCB lpdcb) /* [out] The device control block. */
1102 struct termios port;
1105 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1107 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1110 ERR("FILE_GetUnixHandle failed\n");
1113 if (tcgetattr(fd, &port) == -1) {
1114 int save_error=errno;
1115 ERR("tcgetattr error '%s'\n", strerror(save_error));
1116 commerror = WinError();
1123 speed= (port.c_cflag & CBAUD);
1125 speed= (cfgetospeed(&port));
1129 lpdcb->BaudRate = 110;
1132 lpdcb->BaudRate = 300;
1135 lpdcb->BaudRate = 600;
1138 lpdcb->BaudRate = 1200;
1141 lpdcb->BaudRate = 2400;
1144 lpdcb->BaudRate = 4800;
1147 lpdcb->BaudRate = 9600;
1150 lpdcb->BaudRate = 19200;
1153 lpdcb->BaudRate = 38400;
1157 lpdcb->BaudRate = 57600;
1162 lpdcb->BaudRate = 115200;
1167 lpdcb->BaudRate = 230400;
1172 lpdcb->BaudRate = 460800;
1176 ERR("unknown speed %x \n",speed);
1179 switch (port.c_cflag & CSIZE) {
1181 lpdcb->ByteSize = 5;
1184 lpdcb->ByteSize = 6;
1187 lpdcb->ByteSize = 7;
1190 lpdcb->ByteSize = 8;
1193 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1196 if(port.c_iflag & INPCK)
1197 lpdcb->fParity = TRUE;
1199 lpdcb->fParity = FALSE;
1201 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1203 switch (port.c_cflag & (PARENB | PARODD))
1207 lpdcb->Parity = NOPARITY;
1210 lpdcb->Parity = EVENPARITY;
1212 case (PARENB | PARODD):
1213 lpdcb->Parity = ODDPARITY;
1216 case (PARENB | CMSPAR):
1217 lpdcb->Parity = MARKPARITY;
1219 case (PARENB | PARODD | CMSPAR):
1220 lpdcb->Parity = SPACEPARITY;
1225 if (port.c_cflag & CSTOPB)
1226 if(lpdcb->ByteSize == 5)
1227 lpdcb->StopBits = ONE5STOPBITS;
1229 lpdcb->StopBits = TWOSTOPBITS;
1231 lpdcb->StopBits = ONESTOPBIT;
1238 if (port.c_cflag & CRTSCTS) {
1239 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1240 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1241 lpdcb->fOutxCtsFlow = 1;
1242 lpdcb->fOutxDsrFlow = 1;
1246 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1247 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1249 if (port.c_iflag & IXON)
1254 if (port.c_iflag & IXOFF)
1263 lpdcb->XoffLim = 10;
1269 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1270 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1271 (lpdcb->StopBits == ONESTOPBIT)?1:
1272 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1273 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1274 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1276 if ( lpdcb->fOutxCtsFlow ||
1277 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1278 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1282 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1283 TRACE("~CRTSCTS\n");
1289 /*****************************************************************************
1290 * TransmitCommChar (KERNEL32.@)
1292 * Transmits a single character in front of any pending characters in the
1293 * output buffer. Usually used to send an interrupt character to a host.
1297 * True if the call succeeded, false if the previous command character to the
1298 * same device has not been sent yet the handle is bad etc.
1304 BOOL WINAPI TransmitCommChar(
1305 HANDLE hComm, /* [in] The communication device in need of a command character. */
1306 CHAR chTransmit) /* [in] The character to transmit. */
1308 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
1312 /*****************************************************************************
1313 * GetCommTimeouts (KERNEL32.@)
1315 * Obtains the request time out values for the communications device.
1319 * True on success, false if communications device handle is bad
1320 * or the target structure is null.
1322 BOOL WINAPI GetCommTimeouts(
1323 HANDLE hComm, /* [in] The communications device. */
1324 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request time outs. */
1328 TRACE("(%x,%p)\n",hComm,lptimeouts);
1332 SetLastError(ERROR_INVALID_PARAMETER);
1336 SERVER_START_REQ( get_serial_info )
1338 req->handle = hComm;
1339 if ((ret = !SERVER_CALL_ERR()))
1341 lptimeouts->ReadIntervalTimeout = req->readinterval;
1342 lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
1343 lptimeouts->ReadTotalTimeoutConstant = req->readconst;
1344 lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
1345 lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
1352 /*****************************************************************************
1353 * SetCommTimeouts (KERNEL32.@)
1355 * Sets the timeouts used when reading and writing data to/from COMM ports.
1357 * ReadIntervalTimeout
1358 * - converted and passes to linux kernel as c_cc[VTIME]
1359 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1360 * - used in ReadFile to calculate GetOverlappedResult's timeout
1361 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1362 * - used in WriteFile to calculate GetOverlappedResult's timeout
1366 * True if the time outs were set, false otherwise.
1368 BOOL WINAPI SetCommTimeouts(
1369 HANDLE hComm, /* [in] handle of COMM device */
1370 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1374 struct termios tios;
1376 TRACE("(%x,%p)\n",hComm,lptimeouts);
1380 SetLastError(ERROR_INVALID_PARAMETER);
1384 SERVER_START_REQ( set_serial_info )
1386 req->handle = hComm;
1387 req->flags = SERIALINFO_SET_TIMEOUTS;
1388 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1389 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1390 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1391 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1392 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1393 ret = !SERVER_CALL_ERR();
1396 if (!ret) return FALSE;
1398 /* FIXME: move this stuff to the server */
1399 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
1401 FIXME("no fd for handle = %0x!.\n",hComm);
1405 if (-1==tcgetattr(fd,&tios)) {
1406 FIXME("tcgetattr on fd %d failed!\n",fd);
1410 /* VTIME is in 1/10 seconds */
1412 unsigned int ux_timeout;
1414 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1420 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1423 ux_timeout = 1; /* must be at least some timeout */
1426 tios.c_cc[VTIME] = ux_timeout;
1429 if (-1==tcsetattr(fd,0,&tios)) {
1430 FIXME("tcsetattr on fd %d failed!\n",fd);
1437 /***********************************************************************
1438 * GetCommModemStatus (KERNEL32.@)
1440 * Obtains the four control register bits if supported by the hardware.
1444 * True if the communications handle was good and for hardware that
1445 * control register access, false otherwise.
1447 BOOL WINAPI GetCommModemStatus(
1448 HANDLE hFile, /* [in] The communications device. */
1449 LPDWORD lpModemStat) /* [out] The control register bits. */
1451 int fd,mstat, result=FALSE;
1455 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
1458 result = ioctl(fd, TIOCMGET, &mstat);
1462 WARN("ioctl failed\n");
1466 if (mstat & TIOCM_CTS)
1467 *lpModemStat |= MS_CTS_ON;
1470 if (mstat & TIOCM_DSR)
1471 *lpModemStat |= MS_DSR_ON;
1474 if (mstat & TIOCM_RNG)
1475 *lpModemStat |= MS_RING_ON;
1478 /*FIXME: Not really sure about RLSD UB 990810*/
1479 if (mstat & TIOCM_CAR)
1480 *lpModemStat |= MS_RLSD_ON;
1482 TRACE("%04x -> %s%s%s%s\n", mstat,
1483 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1484 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1485 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1486 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1493 /***********************************************************************
1494 * COMM_WaitCommEventService (INTERNAL)
1496 * This function is called while the client is waiting on the
1497 * server, so we can't make any server calls here.
1499 static void COMM_WaitCommEventService(async_private *ovp, int events)
1501 LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
1503 TRACE("overlapped %p wait complete %p <- %x\n",lpOverlapped,ovp->buffer,events);
1506 lpOverlapped->Internal = STATUS_HANDLES_CLOSED;
1512 *ovp->buffer = EV_RXCHAR;
1515 lpOverlapped->Internal = STATUS_SUCCESS;
1520 /***********************************************************************
1521 * COMM_WaitCommEvent (INTERNAL)
1523 * This function must have an lpOverlapped.
1525 static BOOL COMM_WaitCommEvent(
1526 HANDLE hFile, /* [in] handle of comm port to wait for */
1527 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1528 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1535 SetLastError(ERROR_INVALID_PARAMETER);
1539 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1542 lpOverlapped->Internal = STATUS_PENDING;
1543 lpOverlapped->InternalHigh = 0;
1544 lpOverlapped->Offset = 0;
1545 lpOverlapped->OffsetHigh = 0;
1547 /* start an ASYNCHRONOUS WaitCommEvent */
1548 SERVER_START_REQ( create_async )
1550 req->file_handle = hFile;
1552 req->type = ASYNC_TYPE_WAIT;
1554 ret=SERVER_CALL_ERR();
1561 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
1565 ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
1571 ovp->lpOverlapped = lpOverlapped;
1574 ovp->tv.tv_usec = 0;
1575 ovp->event = POLLIN;
1576 ovp->func = COMM_WaitCommEventService;
1577 ovp->buffer = (char *)lpdwEvents;
1580 ovp->completion_func = 0;
1582 ovp->next = NtCurrentTeb()->pending_list;
1585 ovp->next->prev=ovp;
1586 NtCurrentTeb()->pending_list = ovp;
1588 SetLastError(ERROR_IO_PENDING);
1593 /***********************************************************************
1594 * WaitCommEvent (KERNEL32.@)
1596 * Wait until something interesting happens on a COMM port.
1597 * Interesting things (events) are set by calling SetCommMask before
1598 * this function is called.
1601 * TRUE if successful
1604 * The set of detected events will be written to *lpdwEventMask
1605 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1608 * Only supports EV_RXCHAR and EV_TXEMPTY
1610 BOOL WINAPI WaitCommEvent(
1611 HANDLE hFile, /* [in] handle of comm port to wait for */
1612 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1613 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1618 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1621 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1623 /* if there is no overlapped structure, create our own */
1624 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1626 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1628 if(GetLastError()!=STATUS_PENDING)
1630 CloseHandle(ov.hEvent);
1634 /* wait for the overlapped to complete */
1635 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1636 CloseHandle(ov.hEvent);
1641 /***********************************************************************
1642 * GetCommProperties (KERNEL32.@)
1644 * This function fills in a structure with the capabilities of the
1645 * communications port driver.
1649 * TRUE on success, FALSE on failure
1650 * If successful, the lpCommProp structure be filled in with
1651 * properties of the comm port.
1653 BOOL WINAPI GetCommProperties(
1654 HANDLE hFile, /* [in] handle of the comm port */
1655 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1657 FIXME("(%d %p )\n",hFile,lpCommProp);
1662 * These values should be valid for LINUX's serial driver
1663 * FIXME: Perhaps they deserve an #ifdef LINUX
1665 memset(lpCommProp,0,sizeof(COMMPROP));
1666 lpCommProp->wPacketLength = 1;
1667 lpCommProp->wPacketVersion = 1;
1668 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1669 lpCommProp->dwReserved1 = 0;
1670 lpCommProp->dwMaxTxQueue = 4096;
1671 lpCommProp->dwMaxRxQueue = 4096;
1672 lpCommProp->dwMaxBaud = BAUD_115200;
1673 lpCommProp->dwProvSubType = PST_RS232;
1674 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
1675 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1676 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1677 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1678 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1679 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1680 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1681 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1682 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1683 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1684 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1689 /***********************************************************************
1691 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1692 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1693 * This is dependent on the type of COMM port, but since it is doubtful
1694 * anybody will get around to implementing support for fancy serial
1695 * ports in WINE, this is hardcoded for the time being. The name of
1696 * this DLL should be stored in and read from the system registry in
1697 * the hive HKEY_LOCAL_MACHINE, key
1698 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1699 * where ???? is the port number... that is determined by PNP
1700 * The DLL should be loaded when the COMM port is opened, and closed
1701 * when the COMM port is closed. - MJM 20 June 2000
1702 ***********************************************************************/
1703 static CHAR lpszSerialUI[] = "serialui.dll";
1706 /***********************************************************************
1707 * CommConfigDialogA (KERNEL32.@)
1709 * Raises a dialog that allows the user to configure a comm port.
1710 * Fills the COMMCONFIG struct with information specified by the user.
1711 * This function should call a similar routine in the COMM driver...
1715 * TRUE on success, FALSE on failure
1716 * If successful, the lpCommConfig structure will contain a new
1717 * configuration for the comm port, as specified by the user.
1720 * The library with the CommConfigDialog code is never unloaded.
1721 * Perhaps this should be done when the comm port is closed?
1723 BOOL WINAPI CommConfigDialogA(
1724 LPCSTR lpszDevice, /* [in] name of communications device */
1725 HANDLE hWnd, /* [in] parent window for the dialog */
1726 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1728 FARPROC lpfnCommDialog;
1729 HMODULE hConfigModule;
1732 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
1734 hConfigModule = LoadLibraryA(lpszSerialUI);
1738 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
1743 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
1745 /* UnloadLibrary(hConfigModule); */
1750 /***********************************************************************
1751 * CommConfigDialogW (KERNEL32.@)
1753 * see CommConfigDialogA for more info
1755 BOOL WINAPI CommConfigDialogW(
1756 LPCWSTR lpszDevice, /* [in] name of communications device */
1757 HANDLE hWnd, /* [in] parent window for the dialog */
1758 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1763 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1766 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
1767 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1771 /***********************************************************************
1772 * GetCommConfig (KERNEL32.@)
1774 * Fill in the COMMCONFIG structure for the comm port hFile
1778 * TRUE on success, FALSE on failure
1779 * If successful, lpCommConfig contains the comm port configuration.
1783 * The signature is missing a the parameter for the size of the COMMCONFIG
1784 * structure/buffer it should be
1785 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
1787 BOOL WINAPI GetCommConfig(
1788 HANDLE hFile, /* [in] The communications device. */
1789 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1790 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1791 afterwards the number of bytes copied to the buffer or
1792 the needed size of the buffer. */
1796 TRACE("(%x %p)\n",hFile,lpCommConfig);
1798 if(lpCommConfig == NULL)
1801 r = *lpdwSize < sizeof(COMMCONFIG);
1802 *lpdwSize = sizeof(COMMCONFIG);
1806 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1807 lpCommConfig->wVersion = 1;
1808 lpCommConfig->wReserved = 0;
1809 r = GetCommState(hFile,&lpCommConfig->dcb);
1810 lpCommConfig->dwProviderSubType = PST_RS232;
1811 lpCommConfig->dwProviderOffset = 0;
1812 lpCommConfig->dwProviderSize = 0;
1817 /***********************************************************************
1818 * SetCommConfig (KERNEL32.@)
1820 * Sets the configuration of the commications device.
1824 * True on success, false if the handle was bad is not a communications device.
1826 BOOL WINAPI SetCommConfig(
1827 HANDLE hFile, /* [in] The communications device. */
1828 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1829 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1831 TRACE("(%x %p)\n",hFile,lpCommConfig);
1832 return SetCommState(hFile,&lpCommConfig->dcb);
1835 /***********************************************************************
1836 * SetDefaultCommConfigA (KERNEL32.@)
1838 * Initializes the default configuration for the specified communication
1843 * True if the device was found and the defaults set, false otherwise
1845 BOOL WINAPI SetDefaultCommConfigA(
1846 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
1847 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1848 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1850 FARPROC lpfnSetDefaultCommConfig;
1851 HMODULE hConfigModule;
1854 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
1856 hConfigModule = LoadLibraryA(lpszSerialUI);
1860 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
1862 if(! lpfnSetDefaultCommConfig)
1865 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1867 /* UnloadLibrary(hConfigModule); */
1873 /***********************************************************************
1874 * SetDefaultCommConfigW (KERNEL32.@)
1876 * Initializes the default configuration for the specified
1877 * communication device. (unicode)
1882 BOOL WINAPI SetDefaultCommConfigW(
1883 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
1884 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
1885 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
1890 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
1892 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
1895 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
1896 HeapFree( GetProcessHeap(), 0, lpDeviceA );
1901 /***********************************************************************
1902 * GetDefaultCommConfigA (KERNEL32.@)
1904 * Acquires the default configuration of the specified communication device. (unicode)
1908 * True on successful reading of the default configuration,
1909 * if the device is not found or the buffer is too small.
1911 BOOL WINAPI GetDefaultCommConfigA(
1912 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
1913 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1914 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1915 afterwards the number of bytes copied to the buffer or
1916 the needed size of the buffer. */
1918 LPDCB lpdcb = &(lpCC->dcb);
1921 if (strncasecmp(lpszName,"COM",3)) {
1922 ERR("not implemented for <%s>\n", lpszName);
1926 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
1927 if (*lpdwSize < sizeof(COMMCONFIG)) {
1928 *lpdwSize = sizeof(COMMCONFIG);
1932 *lpdwSize = sizeof(COMMCONFIG);
1934 lpCC->dwSize = sizeof(COMMCONFIG);
1936 lpCC->dwProviderSubType = PST_RS232;
1937 lpCC->dwProviderOffset = 0L;
1938 lpCC->dwProviderSize = 0L;
1940 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
1941 FIXME("setting %s as default\n", temp);
1943 return BuildCommDCBA( temp, lpdcb);
1946 /**************************************************************************
1947 * GetDefaultCommConfigW (KERNEL32.@)
1949 * Acquires the default configuration of the specified communication device. (unicode)
1953 * True on successful reading of the default configuration,
1954 * if the device is not found or the buffer is too small.
1956 BOOL WINAPI GetDefaultCommConfigW(
1957 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
1958 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1959 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1960 afterwards the number of bytes copied to the buffer or
1961 the needed size of the buffer. */
1966 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
1967 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
1970 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
1971 HeapFree( GetProcessHeap(), 0, lpszNameA );