ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

comm.c
Go to the documentation of this file.
00001 /*
00002  * DEC 93 Erik Bos <erik@xs4all.nl>
00003  *
00004  * Copyright 1996 Marcus Meissner
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 //#include "config.h"
00022 //#include "wine/port.h"
00023 
00024 #include <stdlib.h>
00025 #include <stdarg.h>
00026 #include <stdio.h>
00027 
00028 #define NONAMELESSUNION
00029 #define NONAMELESSSTRUCT
00030 #include "windef.h"
00031 #include "winbase.h"
00032 #include "winerror.h"
00033 #include "winioctl.h"
00034 #include "winternl.h"
00035 //#include "ddk/ntddser.h"
00036 
00037 typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
00038 #undef SERIAL_LSRMST_ESCAPE
00039 #undef SERIAL_LSRMST_LSR_DATA
00040 #undef SERIAL_LSRMST_LSR_NODATA
00041 #undef SERIAL_LSRMST_MST
00042 #undef SERIAL_IOC_FCR_FIFO_ENABLE
00043 #undef SERIAL_IOC_FCR_RCVR_RESET
00044 #undef SERIAL_IOC_FCR_XMIT_RESET
00045 #undef SERIAL_IOC_FCR_DMA_MODE
00046 #undef SERIAL_IOC_FCR_RES1
00047 #undef SERIAL_IOC_FCR_RES2
00048 #undef SERIAL_IOC_FCR_RCVR_TRIGGER_LSB
00049 #undef SERIAL_IOC_FCR_RCVR_TRIGGER_MSB
00050 #undef SERIAL_IOC_MCR_DTR
00051 #undef SERIAL_IOC_MCR_RTS
00052 #undef SERIAL_IOC_MCR_OUT1
00053 #undef SERIAL_IOC_MCR_OUT2
00054 #undef SERIAL_IOC_MCR_LOOP
00055 #undef IOCTL_SERIAL_LSRMST_INSERT
00056 #include <ntddser.h>
00057 
00058 #include "wine/unicode.h"
00059 
00060 #include "wine/debug.h"
00061 
00062 #define HeapAlloc RtlAllocateHeap
00063 #define HeapReAlloc RtlReAllocateHeap
00064 #define HeapFree RtlFreeHeap
00065 WINE_DEFAULT_DEBUG_CHANNEL(comm);
00066 
00067 /***********************************************************************
00068  *           COMM_Parse*   (Internal)
00069  *
00070  *  The following COMM_Parse* functions are used by the BuildCommDCB
00071  *  functions to help parse the various parts of the device control string.
00072  */
00073 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
00074 {
00075     static const WCHAR comW[] = {'C','O','M',0};
00076 
00077     /* The device control string may optionally start with "COMx" followed
00078        by an optional ':' and spaces. */
00079     if(!strncmpiW(ptr, comW, 3))
00080     {
00081         ptr += 3;
00082 
00083         /* Allow any com port above 0 as Win 9x does (NT only allows
00084            values for com ports which are actually present) */
00085         if(*ptr < '1' || *ptr > '9')
00086             return NULL;
00087         
00088         /* Advance pointer past port number */
00089         while(*ptr >= '0' && *ptr <= '9') ptr++;
00090         
00091         /* The com port number must be followed by a ':' or ' ' */
00092         if(*ptr != ':' && *ptr != ' ')
00093             return NULL;
00094 
00095         /* Advance pointer to beginning of next parameter */
00096         while(*ptr == ' ') ptr++;
00097         if(*ptr == ':')
00098         {
00099             ptr++;
00100             while(*ptr == ' ') ptr++;
00101         }
00102     }
00103     /* The device control string must not start with a space. */
00104     else if(*ptr == ' ')
00105         return NULL;
00106     
00107     return ptr;
00108 }
00109  
00110 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
00111 {
00112     if(*ptr < '0' || *ptr > '9') return NULL;
00113     *lpnumber = strtoulW(ptr, NULL, 10);
00114     while(*ptr >= '0' && *ptr <= '9') ptr++;
00115     return ptr;
00116 }
00117 
00118 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
00119 {
00120     /* Contrary to what you might expect, Windows only sets the Parity
00121        member of DCB and not fParity even when parity is specified in the
00122        device control string */
00123 
00124     switch(toupperW(*ptr++))
00125     {
00126     case 'E':
00127         *lpparity = EVENPARITY;
00128         break;
00129     case 'M':
00130         *lpparity = MARKPARITY;
00131         break;
00132     case 'N':
00133         *lpparity = NOPARITY;
00134         break;
00135     case 'O':
00136         *lpparity = ODDPARITY;
00137         break;
00138     case 'S':
00139         *lpparity = SPACEPARITY;
00140         break;
00141     default:
00142         return NULL;
00143     }
00144 
00145     return ptr;
00146 }
00147 
00148 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
00149 {
00150     DWORD temp;
00151 
00152     if(!(ptr = COMM_ParseNumber(ptr, &temp)))
00153         return NULL;
00154 
00155     if(temp >= 5 && temp <= 8)
00156     {
00157         *lpbytesize = temp;
00158         return ptr;
00159     }
00160     else
00161         return NULL;
00162 }
00163 
00164 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
00165 {
00166     DWORD temp;
00167     static const WCHAR stopbits15W[] = {'1','.','5',0};
00168 
00169     if(!strncmpW(stopbits15W, ptr, 3))
00170     {
00171         ptr += 3;
00172         *lpstopbits = ONE5STOPBITS;
00173     }
00174     else
00175     {
00176         if(!(ptr = COMM_ParseNumber(ptr, &temp)))
00177             return NULL;
00178 
00179         if(temp == 1)
00180             *lpstopbits = ONESTOPBIT;
00181         else if(temp == 2)
00182             *lpstopbits = TWOSTOPBITS;
00183         else
00184             return NULL;
00185     }
00186     
00187     return ptr;
00188 }
00189 
00190 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
00191 {
00192     static const WCHAR onW[] = {'o','n',0};
00193     static const WCHAR offW[] = {'o','f','f',0};
00194 
00195     if(!strncmpiW(onW, ptr, 2))
00196     {
00197         ptr += 2;
00198         *lponoff = 1;
00199     }
00200     else if(!strncmpiW(offW, ptr, 3))
00201     {
00202         ptr += 3;
00203         *lponoff = 0;
00204     }
00205     else
00206         return NULL;
00207 
00208     return ptr;
00209 }
00210 
00211 /***********************************************************************
00212  *           COMM_BuildOldCommDCB   (Internal)
00213  *
00214  *  Build a DCB using the old style settings string eg: "96,n,8,1"
00215  */
00216 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
00217 {
00218     WCHAR last = 0;
00219 
00220     if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
00221         return FALSE;
00222     
00223     switch(lpdcb->BaudRate)
00224     {
00225     case 11:
00226     case 30:
00227     case 60:
00228         lpdcb->BaudRate *= 10;
00229         break;
00230     case 12:
00231     case 24:
00232     case 48:
00233     case 96:
00234         lpdcb->BaudRate *= 100;
00235         break;
00236     case 19:
00237         lpdcb->BaudRate = 19200;
00238         break;
00239     }
00240 
00241     while(*device == ' ') device++;
00242     if(*device++ != ',') return FALSE;
00243     while(*device == ' ') device++;
00244 
00245     if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
00246         return FALSE;
00247 
00248     while(*device == ' ') device++;
00249     if(*device++ != ',') return FALSE;
00250     while(*device == ' ') device++;
00251         
00252     if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
00253         return FALSE;
00254 
00255     while(*device == ' ') device++;
00256     if(*device++ != ',') return FALSE;
00257     while(*device == ' ') device++;
00258 
00259     if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
00260         return FALSE;
00261 
00262     /* The last parameter for flow control is optional. */
00263     while(*device == ' ') device++;
00264     if(*device == ',')
00265     {
00266         device++;
00267         while(*device == ' ') device++;
00268         if(*device) last = toupperW(*device++);
00269         while(*device == ' ') device++;
00270     }
00271 
00272     /* Win NT sets the flow control members based on (or lack of) the last
00273        parameter.  Win 9x does not set these members. */
00274     switch(last)
00275     {
00276     case 0:
00277         lpdcb->fInX = FALSE;
00278         lpdcb->fOutX = FALSE;
00279         lpdcb->fOutxCtsFlow = FALSE;
00280         lpdcb->fOutxDsrFlow = FALSE;
00281         lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
00282         lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
00283         break;
00284     case 'X':
00285         lpdcb->fInX = TRUE;
00286         lpdcb->fOutX = TRUE;
00287         lpdcb->fOutxCtsFlow = FALSE;
00288         lpdcb->fOutxDsrFlow = FALSE;
00289         lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
00290         lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
00291         break;
00292     case 'P':
00293         lpdcb->fInX = FALSE;
00294         lpdcb->fOutX = FALSE;
00295         lpdcb->fOutxCtsFlow = TRUE;
00296         lpdcb->fOutxDsrFlow = TRUE;
00297         lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
00298         lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
00299         break;
00300     default:
00301         return FALSE;
00302     }
00303 
00304     /* This should be the end of the string. */
00305     if(*device) return FALSE;
00306     
00307     return TRUE;
00308 }
00309 
00310 /***********************************************************************
00311  *           COMM_BuildNewCommDCB   (Internal)
00312  *
00313  *  Build a DCB using the new style settings string.
00314  *   eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
00315  */
00316 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
00317 {
00318     DWORD temp;
00319     BOOL baud = FALSE, stop = FALSE;
00320     static const WCHAR baudW[] = {'b','a','u','d','=',0};
00321     static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
00322     static const WCHAR dataW[] = {'d','a','t','a','=',0};
00323     static const WCHAR stopW[] = {'s','t','o','p','=',0};
00324     static const WCHAR toW[] = {'t','o','=',0};
00325     static const WCHAR xonW[] = {'x','o','n','=',0};
00326     static const WCHAR odsrW[] = {'o','d','s','r','=',0};
00327     static const WCHAR octsW[] = {'o','c','t','s','=',0};
00328     static const WCHAR dtrW[] = {'d','t','r','=',0};
00329     static const WCHAR rtsW[] = {'r','t','s','=',0};
00330     static const WCHAR idsrW[] = {'i','d','s','r','=',0};
00331 
00332     while(*device)
00333     {
00334         while(*device == ' ') device++;
00335 
00336         if(!strncmpiW(baudW, device, 5))
00337         {
00338             baud = TRUE;
00339             
00340             if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
00341                 return FALSE;
00342         }
00343         else if(!strncmpiW(parityW, device, 7))
00344         {
00345             if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
00346                 return FALSE;
00347         }
00348         else if(!strncmpiW(dataW, device, 5))
00349         {
00350             if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
00351                 return FALSE;
00352         }
00353         else if(!strncmpiW(stopW, device, 5))
00354         {
00355             stop = TRUE;
00356             
00357             if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
00358                 return FALSE;
00359         }
00360         else if(!strncmpiW(toW, device, 3))
00361         {
00362             if(!(device = COMM_ParseOnOff(device + 3, &temp)))
00363                 return FALSE;
00364 
00365             lptimeouts->ReadIntervalTimeout = 0;
00366             lptimeouts->ReadTotalTimeoutMultiplier = 0;
00367             lptimeouts->ReadTotalTimeoutConstant = 0;
00368             lptimeouts->WriteTotalTimeoutMultiplier = 0;
00369             lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
00370         }
00371         else if(!strncmpiW(xonW, device, 4))
00372         {
00373             if(!(device = COMM_ParseOnOff(device + 4, &temp)))
00374                 return FALSE;
00375 
00376             lpdcb->fOutX = temp;
00377             lpdcb->fInX = temp;
00378         }
00379         else if(!strncmpiW(odsrW, device, 5))
00380         {
00381             if(!(device = COMM_ParseOnOff(device + 5, &temp)))
00382                 return FALSE;
00383 
00384             lpdcb->fOutxDsrFlow = temp;
00385         }
00386         else if(!strncmpiW(octsW, device, 5))
00387         {
00388             if(!(device = COMM_ParseOnOff(device + 5, &temp)))
00389                 return FALSE;
00390 
00391             lpdcb->fOutxCtsFlow = temp;
00392         }
00393         else if(!strncmpiW(dtrW, device, 4))
00394         {
00395             if(!(device = COMM_ParseOnOff(device + 4, &temp)))
00396                 return FALSE;
00397 
00398             lpdcb->fDtrControl = temp;
00399         }
00400         else if(!strncmpiW(rtsW, device, 4))
00401         {
00402             if(!(device = COMM_ParseOnOff(device + 4, &temp)))
00403                 return FALSE;
00404 
00405             lpdcb->fRtsControl = temp;
00406         }
00407         else if(!strncmpiW(idsrW, device, 5))
00408         {
00409             if(!(device = COMM_ParseOnOff(device + 5, &temp)))
00410                 return FALSE;
00411 
00412             /* Win NT sets the fDsrSensitivity member based on the
00413                idsr parameter.  Win 9x sets fOutxDsrFlow instead. */
00414             lpdcb->fDsrSensitivity = temp;
00415         }
00416         else
00417             return FALSE;
00418 
00419         /* After the above parsing, the next character (if not the end of
00420            the string) should be a space */
00421         if(*device && *device != ' ')
00422             return FALSE;
00423     }
00424 
00425     /* If stop bits were not specified, a default is always supplied. */
00426     if(!stop)
00427     {
00428         if(baud && lpdcb->BaudRate == 110)
00429             lpdcb->StopBits = TWOSTOPBITS;
00430         else
00431             lpdcb->StopBits = ONESTOPBIT;
00432     }
00433 
00434     return TRUE;
00435 }
00436 
00437 /**************************************************************************
00438  *         BuildCommDCBA        (KERNEL32.@)
00439  *
00440  *  Updates a device control block data structure with values from an
00441  *  ascii device control string.  The device control string has two forms
00442  *  normal and extended, it must be exclusively in one or the other form.
00443  *
00444  * RETURNS
00445  *
00446  *  True on success, false on a malformed control string.
00447  */
00448 BOOL WINAPI BuildCommDCBA(
00449     LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
00450     LPDCB  lpdcb)  /* [out] The device control block to be updated. */
00451 {
00452     return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
00453 }
00454 
00455 /**************************************************************************
00456  *         BuildCommDCBAndTimeoutsA     (KERNEL32.@)
00457  *
00458  *  Updates a device control block data structure with values from an
00459  *  ascii device control string.  Taking timeout values from a timeouts
00460  *  struct if desired by the control string.
00461  *
00462  * RETURNS
00463  *
00464  *  True on success, false bad handles etc.
00465  */
00466 BOOL WINAPI BuildCommDCBAndTimeoutsA(
00467     LPCSTR         device,     /* [in] The ascii device control string. */
00468     LPDCB          lpdcb,      /* [out] The device control block to be updated. */
00469     LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
00470 {
00471     BOOL ret = FALSE;
00472     UNICODE_STRING deviceW;
00473 
00474     TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
00475     if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
00476     else deviceW.Buffer = NULL;
00477 
00478     if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
00479 
00480     RtlFreeUnicodeString(&deviceW);
00481     return ret;
00482 }
00483 
00484 /**************************************************************************
00485  *         BuildCommDCBAndTimeoutsW (KERNEL32.@)
00486  *
00487  *  Updates a device control block data structure with values from a
00488  *  unicode device control string.  Taking timeout values from a timeouts
00489  *  struct if desired by the control string.
00490  *
00491  * RETURNS
00492  *
00493  *  True on success, false bad handles etc
00494  */
00495 BOOL WINAPI BuildCommDCBAndTimeoutsW(
00496     LPCWSTR        devid,      /* [in] The unicode device control string. */
00497     LPDCB          lpdcb,      /* [out] The device control block to be updated. */
00498     LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
00499 {
00500     DCB dcb;
00501     COMMTIMEOUTS timeouts;
00502     BOOL result;
00503     LPCWSTR ptr = devid;
00504 
00505     TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
00506 
00507     memset(&timeouts, 0, sizeof timeouts);
00508 
00509     /* Set DCBlength. (Windows NT does not do this, but 9x does) */
00510     lpdcb->DCBlength = sizeof(DCB);
00511 
00512     /* Make a copy of the original data structures to work with since if
00513        if there is an error in the device control string the originals
00514        should not be modified (except possibly DCBlength) */
00515     dcb = *lpdcb;
00516     if(lptimeouts) timeouts = *lptimeouts;
00517 
00518     ptr = COMM_ParseStart(ptr);
00519 
00520     if(ptr == NULL)
00521         result = FALSE;
00522     else if(strchrW(ptr, ','))
00523         result = COMM_BuildOldCommDCB(ptr, &dcb);
00524     else
00525         result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
00526 
00527     if(result)
00528     {
00529         *lpdcb = dcb;
00530         if(lptimeouts) *lptimeouts = timeouts;
00531         return TRUE;
00532     }
00533     else
00534     {
00535         WARN("Invalid device control string: %s\n", debugstr_w(devid));
00536         SetLastError(ERROR_INVALID_PARAMETER);
00537         return FALSE;
00538     }   
00539 }
00540 
00541 /**************************************************************************
00542  *         BuildCommDCBW        (KERNEL32.@)
00543  *
00544  *  Updates a device control block structure with values from an
00545  *  unicode device control string.  The device control string has two forms
00546  *  normal and extended, it must be exclusively in one or the other form.
00547  *
00548  * RETURNS
00549  *
00550  *  True on success, false on a malformed control string.
00551  */
00552 BOOL WINAPI BuildCommDCBW(
00553     LPCWSTR devid, /* [in] The unicode device control string. */
00554     LPDCB   lpdcb) /* [out] The device control block to be updated. */
00555 {
00556     return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
00557 }
00558 
00559 /*****************************************************************************
00560  *  SetCommBreak        (KERNEL32.@)
00561  *
00562  *  Halts the transmission of characters to a communications device.
00563  *
00564  * PARAMS
00565  *      handle  [in] The communications device to suspend
00566  *
00567  * RETURNS
00568  *
00569  *  True on success, and false if the communications device could not be found,
00570  *  the control is not supported.
00571  *
00572  * BUGS
00573  *
00574  *  Only TIOCSBRK and TIOCCBRK are supported.
00575  */
00576 BOOL WINAPI SetCommBreak(HANDLE handle)
00577 {
00578     DWORD dwBytesReturned;
00579     return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
00580 }
00581 
00582 /*****************************************************************************
00583  *  ClearCommBreak      (KERNEL32.@)
00584  *
00585  *  Resumes character transmission from a communication device.
00586  *
00587  * PARAMS
00588  *
00589  *      handle [in] The halted communication device whose character transmission is to be resumed
00590  *
00591  * RETURNS
00592  *
00593  *  True on success and false if the communications device could not be found.
00594  *
00595  * BUGS
00596  *
00597  *  Only TIOCSBRK and TIOCCBRK are supported.
00598  */
00599 BOOL WINAPI ClearCommBreak(HANDLE handle)
00600 {
00601     DWORD dwBytesReturned;
00602     return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
00603 }
00604 
00605 /*****************************************************************************
00606  *  EscapeCommFunction  (KERNEL32.@)
00607  *
00608  *  Directs a communication device to perform an extended function.
00609  *
00610  * PARAMS
00611  *
00612  *      handle          [in] The communication device to perform the extended function
00613  *      nFunction       [in] The extended function to be performed
00614  *
00615  * RETURNS
00616  *
00617  *  True or requested data on successful completion of the command,
00618  *  false if the device is not present cannot execute the command
00619  *  or the command failed.
00620  */
00621 BOOL WINAPI EscapeCommFunction(HANDLE handle, DWORD func)
00622 {
00623     DWORD       ioc;
00624     DWORD dwBytesReturned;
00625 
00626     switch (func)
00627     {
00628     case CLRDTR:        ioc = IOCTL_SERIAL_CLR_DTR;             break;
00629     case CLRRTS:        ioc = IOCTL_SERIAL_CLR_RTS;             break;
00630     case SETDTR:        ioc = IOCTL_SERIAL_SET_DTR;             break;
00631     case SETRTS:        ioc = IOCTL_SERIAL_SET_RTS;             break;
00632     case SETXOFF:       ioc = IOCTL_SERIAL_SET_XOFF;            break;
00633     case SETXON:        ioc = IOCTL_SERIAL_SET_XON;             break;
00634     case SETBREAK:      ioc = IOCTL_SERIAL_SET_BREAK_ON;        break;
00635     case CLRBREAK:      ioc = IOCTL_SERIAL_SET_BREAK_OFF;       break;
00636     case RESETDEV:      ioc = IOCTL_SERIAL_RESET_DEVICE;        break;
00637     default:
00638         ERR("Unknown function code (%u)\n", func);
00639         SetLastError(ERROR_INVALID_PARAMETER);
00640         return FALSE;
00641     }
00642     return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
00643 }
00644 
00645 /********************************************************************
00646  *      PurgeComm        (KERNEL32.@)
00647  *
00648  *  Terminates pending operations and/or discards buffers on a
00649  *  communication resource.
00650  *
00651  * PARAMS
00652  *
00653  *      handle  [in] The communication resource to be purged
00654  *      flags   [in] Flags for clear pending/buffer on input/output
00655  *
00656  * RETURNS
00657  *
00658  *  True on success and false if the communications handle is bad.
00659  */
00660 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
00661 {
00662     DWORD dwBytesReturned;
00663     return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
00664                            NULL, 0, &dwBytesReturned, NULL);
00665 }
00666 
00667 /*****************************************************************************
00668  *  ClearCommError  (KERNEL32.@)
00669  *
00670  *  Enables further I/O operations on a communications resource after
00671  *  supplying error and current status information.
00672  *
00673  * PARAMS
00674  *
00675  *      handle  [in]    The communication resource with the error
00676  *      errors  [out]   Flags indicating error the resource experienced
00677  *      lpStat  [out] The status of the communication resource
00678  * RETURNS
00679  *
00680  *  True on success, false if the communication resource handle is bad.
00681  */
00682 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
00683 {
00684     SERIAL_STATUS       ss;
00685     DWORD dwBytesReturned;
00686 
00687     if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
00688                          &ss, sizeof(ss), &dwBytesReturned, NULL))
00689         return FALSE;
00690 
00691     if (errors)
00692     {
00693         *errors = 0;
00694         if (ss.Errors & SERIAL_ERROR_BREAK)             *errors |= CE_BREAK;
00695         if (ss.Errors & SERIAL_ERROR_FRAMING)           *errors |= CE_FRAME;
00696         if (ss.Errors & SERIAL_ERROR_OVERRUN)           *errors |= CE_OVERRUN;
00697         if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN)      *errors |= CE_RXOVER;
00698         if (ss.Errors & SERIAL_ERROR_PARITY)            *errors |= CE_RXPARITY;
00699     }
00700  
00701     if (lpStat)
00702     {
00703         memset(lpStat, 0, sizeof(*lpStat));
00704 
00705         if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS)         lpStat->fCtsHold = TRUE;
00706         if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR)         lpStat->fDsrHold = TRUE;
00707         if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD)         lpStat->fRlsdHold = TRUE;
00708         if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON)         lpStat->fXoffHold = TRUE;
00709         if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT)       lpStat->fXoffSent = TRUE;
00710         if (ss.EofReceived)                                     lpStat->fEof = TRUE;
00711         if (ss.WaitForImmediate)                                lpStat->fTxim = TRUE;
00712         lpStat->cbInQue = ss.AmountInInQueue;
00713         lpStat->cbOutQue = ss.AmountInOutQueue;
00714     }
00715     return TRUE;
00716 }
00717 
00718 /*****************************************************************************
00719  *      SetupComm       (KERNEL32.@)
00720  *
00721  *  Called after CreateFile to hint to the communication resource to use
00722  *  specified sizes for input and output buffers rather than the default values.
00723  *
00724  * PARAMS
00725  *      handle  [in]    The just created communication resource handle
00726  *      insize  [in]    The suggested size of the communication resources input buffer in bytes
00727  *      outsize [in]    The suggested size of the communication resources output buffer in bytes
00728  *
00729  * RETURNS
00730  *
00731  *  True if successful, false if the communications resource handle is bad.
00732  *
00733  * BUGS
00734  *
00735  *  Stub.
00736  */
00737 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
00738 {
00739     SERIAL_QUEUE_SIZE   sqs;
00740     DWORD dwBytesReturned;
00741 
00742     sqs.InSize = insize;
00743     sqs.OutSize = outsize;
00744     return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE,
00745                            &sqs, sizeof(sqs), NULL, 0, &dwBytesReturned, NULL);
00746 }
00747 
00748 /*****************************************************************************
00749  *  GetCommMask (KERNEL32.@)
00750  *
00751  *  Obtain the events associated with a communication device that will cause
00752  *  a call WaitCommEvent to return.
00753  *
00754  *  PARAMS
00755  *
00756  *      handle  [in]    The communications device
00757  *      evtmask [out]   The events which cause WaitCommEvent to return
00758  *
00759  *  RETURNS
00760  *
00761  *   True on success, fail on bad device handle etc.
00762  */
00763 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
00764 {
00765     DWORD dwBytesReturned;
00766     TRACE("handle %p, mask %p\n", handle, evtmask);
00767     return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
00768                            NULL, 0, evtmask, sizeof(*evtmask), &dwBytesReturned, NULL);
00769 }
00770 
00771 /*****************************************************************************
00772  *  SetCommMask (KERNEL32.@)
00773  *
00774  *  There be some things we need to hear about yon there communications device.
00775  *  (Set which events associated with a communication device should cause
00776  *  a call WaitCommEvent to return.)
00777  *
00778  * PARAMS
00779  *
00780  *      handle  [in]    The communications device
00781  *      evtmask [in]    The events that are to be monitored
00782  *
00783  * RETURNS
00784  *
00785  *  True on success, false on bad handle etc.
00786  */
00787 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
00788 {
00789     DWORD dwBytesReturned;
00790     TRACE("handle %p, mask %x\n", handle, evtmask);
00791     return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
00792                            &evtmask, sizeof(evtmask), NULL, 0, &dwBytesReturned, NULL);
00793 }
00794 
00795 static void dump_dcb(const DCB* lpdcb)
00796 {
00797     TRACE("bytesize=%d baudrate=%d fParity=%d Parity=%d stopbits=%d\n",
00798           lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity,
00799           (lpdcb->StopBits == ONESTOPBIT) ? 1 :
00800           (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0);
00801     TRACE("%sIXON %sIXOFF\n", (lpdcb->fOutX) ? "" : "~", (lpdcb->fInX) ? "" : "~");
00802     TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl);
00803     TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl);
00804     if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE)
00805         TRACE("CRTSCTS\n");
00806     else
00807         TRACE("~CRTSCTS\n");
00808 }
00809 
00810 /*****************************************************************************
00811  *  SetCommState    (KERNEL32.@)
00812  *
00813  *  Re-initializes all hardware and control settings of a communications device,
00814  *  with values from a device control block without affecting the input and output
00815  *  queues.
00816  *
00817  * PARAMS
00818  *
00819  *      handle  [in]    The communications device
00820  *      lpdcb   [out]   The device control block
00821  *
00822  * RETURNS
00823  *
00824  *  True on success, false on failure, e.g., if the XonChar is equal to the XoffChar.
00825  */
00826 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
00827 {
00828     SERIAL_BAUD_RATE           sbr;
00829     SERIAL_LINE_CONTROL        slc;
00830     SERIAL_HANDFLOW            shf;
00831     SERIAL_CHARS               sc;
00832     DWORD dwBytesReturned;
00833 
00834     if (lpdcb == NULL)
00835     {
00836         SetLastError(ERROR_INVALID_PARAMETER);
00837         return FALSE;
00838     }
00839     dump_dcb(lpdcb);
00840 
00841     sbr.BaudRate = lpdcb->BaudRate;
00842              
00843     slc.StopBits = lpdcb->StopBits;
00844     slc.Parity = lpdcb->Parity;
00845     slc.WordLength = lpdcb->ByteSize;
00846 
00847     shf.ControlHandShake = 0;
00848     shf.FlowReplace = 0;
00849     if (lpdcb->fOutxCtsFlow)      shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
00850     if (lpdcb->fOutxDsrFlow)      shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
00851     switch (lpdcb->fDtrControl)
00852     {
00853     case DTR_CONTROL_DISABLE:                                                  break;
00854     case DTR_CONTROL_ENABLE:      shf.ControlHandShake |= SERIAL_DTR_CONTROL;  break;
00855     case DTR_CONTROL_HANDSHAKE:   shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break;
00856     default:
00857         SetLastError(ERROR_INVALID_PARAMETER);
00858         return FALSE;
00859     }
00860     switch (lpdcb->fRtsControl)
00861     {
00862     case RTS_CONTROL_DISABLE:                                                  break;
00863     case RTS_CONTROL_ENABLE:      shf.FlowReplace |= SERIAL_RTS_CONTROL;       break;
00864     case RTS_CONTROL_HANDSHAKE:   shf.FlowReplace |= SERIAL_RTS_HANDSHAKE;     break;
00865     case RTS_CONTROL_TOGGLE:      shf.FlowReplace |= SERIAL_RTS_CONTROL | 
00866                                                      SERIAL_RTS_HANDSHAKE;     break;
00867     default:
00868         SetLastError(ERROR_INVALID_PARAMETER);
00869         return FALSE;
00870     }
00871     if (lpdcb->fDsrSensitivity)   shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
00872     if (lpdcb->fAbortOnError)     shf.ControlHandShake |= SERIAL_ERROR_ABORT;
00873 
00874     if (lpdcb->fErrorChar)        shf.FlowReplace |= SERIAL_ERROR_CHAR;
00875     if (lpdcb->fNull)             shf.FlowReplace |= SERIAL_NULL_STRIPPING;
00876     if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE;
00877     if (lpdcb->fOutX)             shf.FlowReplace |= SERIAL_AUTO_TRANSMIT;
00878     if (lpdcb->fInX)              shf.FlowReplace |= SERIAL_AUTO_RECEIVE;
00879 
00880     shf.XonLimit = lpdcb->XonLim;
00881     shf.XoffLimit = lpdcb->XoffLim;
00882 
00883     sc.EofChar = lpdcb->EofChar;
00884     sc.ErrorChar = lpdcb->ErrorChar;
00885     sc.BreakChar = 0;
00886     sc.EventChar = lpdcb->EvtChar;
00887     sc.XonChar = lpdcb->XonChar;
00888     sc.XoffChar = lpdcb->XoffChar;
00889 
00890     /* note: change DTR/RTS lines after setting the comm attributes,
00891      * so flow control does not interfere.
00892      */
00893     return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
00894                             &sbr, sizeof(sbr), NULL, 0, &dwBytesReturned, NULL) &&
00895             DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
00896                             &slc, sizeof(slc), NULL, 0, &dwBytesReturned, NULL) &&
00897             DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
00898                             &shf, sizeof(shf), NULL, 0, &dwBytesReturned, NULL) &&
00899             DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS,
00900                             &sc, sizeof(sc), NULL, 0, &dwBytesReturned, NULL));
00901 }
00902 
00903 
00904 /*****************************************************************************
00905  *  GetCommState    (KERNEL32.@)
00906  *
00907  *  Fills in a device control block with information from a communications device.
00908  *
00909  * PARAMS
00910  *      handle          [in]    The communications device
00911  *      lpdcb           [out]   The device control block
00912  *
00913  * RETURNS
00914  *
00915  *  True on success, false if the communication device handle is bad etc
00916  *
00917  * BUGS
00918  *
00919  *  XonChar and XoffChar are not set.
00920  */
00921 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
00922 {
00923     SERIAL_BAUD_RATE    sbr;
00924     SERIAL_LINE_CONTROL slc;
00925     SERIAL_HANDFLOW     shf;
00926     SERIAL_CHARS        sc;
00927     DWORD dwBytesReturned;
00928 
00929     TRACE("handle %p, ptr %p\n", handle, lpdcb);
00930 
00931     if (!lpdcb)
00932     {
00933         SetLastError(ERROR_INVALID_PARAMETER);
00934         return FALSE;
00935     }
00936     
00937     if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
00938                          NULL, 0, &sbr, sizeof(sbr), &dwBytesReturned, NULL) ||
00939         !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
00940                          NULL, 0, &slc, sizeof(slc), &dwBytesReturned, NULL) ||
00941         !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW,
00942                          NULL, 0, &shf, sizeof(shf), &dwBytesReturned, NULL) ||
00943         !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS,
00944                          NULL, 0, &sc, sizeof(sc), &dwBytesReturned, NULL))
00945         return FALSE;
00946 
00947     memset(lpdcb, 0, sizeof(*lpdcb));
00948     lpdcb->DCBlength = sizeof(*lpdcb);
00949 
00950     /* yes, they seem no never be (re)set on NT */
00951     lpdcb->fBinary = 1;
00952     lpdcb->fParity = 0;
00953 
00954     lpdcb->BaudRate = sbr.BaudRate;
00955 
00956     lpdcb->StopBits = slc.StopBits;
00957     lpdcb->Parity = slc.Parity;
00958     lpdcb->ByteSize = slc.WordLength;
00959 
00960     if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE)    lpdcb->fOutxCtsFlow = 1;
00961     if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE)    lpdcb->fOutxDsrFlow = 1;
00962     switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
00963     {
00964     case 0:                     lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
00965     case SERIAL_DTR_CONTROL:    lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
00966     case SERIAL_DTR_HANDSHAKE:  lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
00967     }
00968     switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
00969     {
00970     case 0:                     lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
00971     case SERIAL_RTS_CONTROL:    lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
00972     case SERIAL_RTS_HANDSHAKE:  lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
00973     case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
00974                                 lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
00975     }
00976     if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY)  lpdcb->fDsrSensitivity = 1;
00977     if (shf.ControlHandShake & SERIAL_ERROR_ABORT)      lpdcb->fAbortOnError = 1;
00978     if (shf.FlowReplace & SERIAL_ERROR_CHAR)            lpdcb->fErrorChar = 1;
00979     if (shf.FlowReplace & SERIAL_NULL_STRIPPING)        lpdcb->fNull = 1;
00980     if (shf.FlowReplace & SERIAL_XOFF_CONTINUE)         lpdcb->fTXContinueOnXoff = 1;
00981     lpdcb->XonLim = shf.XonLimit;
00982     lpdcb->XoffLim = shf.XoffLimit;
00983 
00984     if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
00985     if (shf.FlowReplace & SERIAL_AUTO_RECEIVE)  lpdcb->fInX = 1;
00986 
00987     lpdcb->EofChar = sc.EofChar;
00988     lpdcb->ErrorChar = sc.ErrorChar;
00989     lpdcb->EvtChar = sc.EventChar;
00990     lpdcb->XonChar = sc.XonChar;
00991     lpdcb->XoffChar = sc.XoffChar;
00992 
00993     TRACE("OK\n");
00994     dump_dcb(lpdcb);
00995 
00996     return TRUE;
00997 }
00998 
00999 /*****************************************************************************
01000  *  TransmitCommChar    (KERNEL32.@)
01001  *
01002  *  Transmits a single character in front of any pending characters in the
01003  *  output buffer.  Usually used to send an interrupt character to a host.
01004  *
01005  * PARAMS
01006  *      hComm           [in]    The communication device in need of a command character
01007  *      chTransmit      [in]    The character to transmit
01008  *
01009  * RETURNS
01010  *
01011  *  True if the call succeeded, false if the previous command character to the
01012  *  same device has not been sent yet the handle is bad etc.
01013  *
01014  */
01015 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
01016 {
01017     DWORD dwBytesReturned;
01018     return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
01019                            &chTransmit, sizeof(chTransmit), NULL, 0, &dwBytesReturned, NULL);
01020 }
01021 
01022 
01023 /*****************************************************************************
01024  *  GetCommTimeouts     (KERNEL32.@)
01025  *
01026  *  Obtains the request timeout values for the communications device.
01027  *
01028  * PARAMS
01029  *      hComm           [in]    The communications device
01030  *      lptimeouts      [out]   The struct of request timeouts
01031  *
01032  * RETURNS
01033  *
01034  *  True on success, false if communications device handle is bad
01035  *  or the target structure is null.
01036  */
01037 BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
01038 {
01039     SERIAL_TIMEOUTS     st;
01040     DWORD dwBytesReturned;
01041 
01042     TRACE("(%p, %p)\n", hComm, lptimeouts);
01043     if (!lptimeouts)
01044     {
01045         SetLastError(ERROR_INVALID_PARAMETER);
01046         return FALSE;
01047     }
01048     if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
01049                          NULL, 0, &st, sizeof(st), &dwBytesReturned, NULL))
01050         return FALSE;
01051     lptimeouts->ReadIntervalTimeout         = st.ReadIntervalTimeout;
01052     lptimeouts->ReadTotalTimeoutMultiplier  = st.ReadTotalTimeoutMultiplier;
01053     lptimeouts->ReadTotalTimeoutConstant    = st.ReadTotalTimeoutConstant;
01054     lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
01055     lptimeouts->WriteTotalTimeoutConstant   = st.WriteTotalTimeoutConstant;
01056     return TRUE;
01057 }
01058 
01059 /*****************************************************************************
01060  *  SetCommTimeouts     (KERNEL32.@)
01061  *
01062  * Sets the timeouts used when reading and writing data to/from COMM ports.
01063  *
01064  * PARAMS
01065  *      hComm           [in]    handle of COMM device
01066  *      lptimeouts      [in]    pointer to COMMTIMEOUTS structure
01067  *
01068  * ReadIntervalTimeout
01069  *     - converted and passes to linux kernel as c_cc[VTIME]
01070  * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
01071  *     - used in ReadFile to calculate GetOverlappedResult's timeout
01072  * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
01073  *     - used in WriteFile to calculate GetOverlappedResult's timeout
01074  *
01075  * RETURNS
01076  *
01077  *  True if the timeouts were set, false otherwise.
01078  */
01079 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
01080 {
01081     SERIAL_TIMEOUTS     st;
01082     DWORD dwBytesReturned;
01083 
01084     TRACE("(%p, %p)\n", hComm, lptimeouts);
01085 
01086     if (lptimeouts == NULL)
01087     {
01088         SetLastError(ERROR_INVALID_PARAMETER);
01089         return FALSE;
01090     }
01091     st.ReadIntervalTimeout         = lptimeouts->ReadIntervalTimeout;
01092     st.ReadTotalTimeoutMultiplier  = lptimeouts->ReadTotalTimeoutMultiplier;
01093     st.ReadTotalTimeoutConstant    = lptimeouts->ReadTotalTimeoutConstant;
01094     st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
01095     st.WriteTotalTimeoutConstant   = lptimeouts->WriteTotalTimeoutConstant;
01096  
01097     return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
01098                            &st, sizeof(st), NULL, 0, &dwBytesReturned, NULL);
01099 }
01100 
01101 /***********************************************************************
01102  *           GetCommModemStatus   (KERNEL32.@)
01103  *
01104  *  Obtains the four control register bits if supported by the hardware.
01105  *
01106  * PARAMS
01107  *
01108  *      hFile           [in]    The communications device
01109  *      lpModemStat     [out]   The control register bits
01110  *
01111  * RETURNS
01112  *
01113  *  True if the communications handle was good and for hardware that
01114  *  control register access, false otherwise.
01115  */
01116 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
01117 {
01118     DWORD dwBytesReturned;
01119     return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
01120                            NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
01121 }
01122 
01123 /***********************************************************************
01124  *           WaitCommEvent   (KERNEL32.@)
01125  *
01126  * Wait until something interesting happens on a COMM port.
01127  * Interesting things (events) are set by calling SetCommMask before
01128  * this function is called.
01129  *
01130  * RETURNS
01131  *   TRUE if successful
01132  *   FALSE if failure
01133  *
01134  *   The set of detected events will be written to *lpdwEventMask
01135  *   ERROR_IO_PENDING will be returned the overlapped structure was passed
01136  *
01137  * BUGS:
01138  *  Only supports EV_RXCHAR and EV_TXEMPTY
01139  */
01140 BOOL WINAPI WaitCommEvent(
01141     HANDLE hFile,              /* [in] handle of comm port to wait for */
01142     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
01143     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
01144 {
01145     return DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, NULL, 0,
01146                            lpdwEvents, sizeof(DWORD), NULL, lpOverlapped);
01147 }
01148 
01149 /***********************************************************************
01150  *           GetCommProperties   (KERNEL32.@)
01151  *
01152  * This function fills in a structure with the capabilities of the
01153  * communications port driver.
01154  *
01155  * RETURNS
01156  *
01157  *  TRUE on success, FALSE on failure
01158  *  If successful, the lpCommProp structure be filled in with
01159  *  properties of the comm port.
01160  */
01161 BOOL WINAPI GetCommProperties(
01162     HANDLE hFile,          /* [in] handle of the comm port */
01163     LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
01164 {
01165     TRACE("(%p %p)\n",hFile,lpCommProp);
01166     if(!lpCommProp)
01167         return FALSE;
01168 
01169     /*
01170      * These values should be valid for LINUX's serial driver
01171      * FIXME: Perhaps they deserve an #ifdef LINUX
01172      */
01173     memset(lpCommProp,0,sizeof(COMMPROP));
01174     lpCommProp->wPacketLength       = 1;
01175     lpCommProp->wPacketVersion      = 1;
01176     lpCommProp->dwServiceMask       = SP_SERIALCOMM;
01177     lpCommProp->dwMaxTxQueue        = 4096;
01178     lpCommProp->dwMaxRxQueue        = 4096;
01179     lpCommProp->dwMaxBaud           = BAUD_115200;
01180     lpCommProp->dwProvSubType       = PST_RS232;
01181     lpCommProp->dwProvCapabilities  = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
01182     lpCommProp->dwSettableParams    = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
01183                                       SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
01184     lpCommProp->dwSettableBaud      = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
01185                 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
01186                 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
01187     lpCommProp->wSettableData       = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
01188     lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
01189                 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
01190     lpCommProp->dwCurrentTxQueue    = lpCommProp->dwMaxTxQueue;
01191     lpCommProp->dwCurrentRxQueue    = lpCommProp->dwMaxRxQueue;
01192 
01193     return TRUE;
01194 }
01195 
01196 /***********************************************************************
01197  * FIXME:
01198  * The functionality of CommConfigDialogA, GetDefaultCommConfig and
01199  * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
01200  * This is dependent on the type of COMM port, but since it is doubtful
01201  * anybody will get around to implementing support for fancy serial
01202  * ports in WINE, this is hardcoded for the time being.  The name of
01203  * this DLL should be stored in and read from the system registry in
01204  * the hive HKEY_LOCAL_MACHINE, key
01205  * System\\CurrentControlSet\\Services\\Class\\Ports\\????
01206  * where ???? is the port number... that is determined by PNP
01207  * The DLL should be loaded when the COMM port is opened, and closed
01208  * when the COMM port is closed. - MJM 20 June 2000
01209  ***********************************************************************/
01210 static const WCHAR lpszSerialUI[] = { 
01211    's','e','r','i','a','l','u','i','.','d','l','l',0 };
01212 
01213 
01214 /***********************************************************************
01215  *           CommConfigDialogA   (KERNEL32.@)
01216  *
01217  * Raises a dialog that allows the user to configure a comm port.
01218  * Fills the COMMCONFIG struct with information specified by the user.
01219  * This function should call a similar routine in the COMM driver...
01220  *
01221  * RETURNS
01222  *
01223  *  TRUE on success, FALSE on failure
01224  *  If successful, the lpCommConfig structure will contain a new
01225  *  configuration for the comm port, as specified by the user.
01226  *
01227  * BUGS
01228  *  The library with the CommConfigDialog code is never unloaded.
01229  * Perhaps this should be done when the comm port is closed?
01230  */
01231 BOOL WINAPI CommConfigDialogA(
01232     LPCSTR lpszDevice,         /* [in] name of communications device */
01233     HWND hWnd,                 /* [in] parent window for the dialog */
01234     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
01235 {
01236     LPWSTR  lpDeviceW = NULL;
01237     DWORD   len;
01238     BOOL    r;
01239 
01240     TRACE("(%s, %p, %p)\n", debugstr_a(lpszDevice), hWnd, lpCommConfig);
01241 
01242     if (lpszDevice)
01243     {
01244         len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
01245         lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
01246         MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
01247     }
01248     r = CommConfigDialogW(lpDeviceW, hWnd, lpCommConfig);
01249     HeapFree( GetProcessHeap(), 0, lpDeviceW );
01250     return r;
01251 }
01252 
01253 /***********************************************************************
01254  *           CommConfigDialogW   (KERNEL32.@)
01255  *
01256  * See CommConfigDialogA.
01257  */
01258 BOOL WINAPI CommConfigDialogW(
01259     LPCWSTR lpszDevice,        /* [in] name of communications device */
01260     HWND hWnd,                 /* [in] parent window for the dialog */
01261     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
01262 {
01263     DWORD (WINAPI *pCommConfigDialog)(LPCWSTR, HWND, LPCOMMCONFIG);
01264     HMODULE hConfigModule;
01265     DWORD   res = ERROR_INVALID_PARAMETER;
01266 
01267     TRACE("(%s, %p, %p)\n", debugstr_w(lpszDevice), hWnd, lpCommConfig);
01268     hConfigModule = LoadLibraryW(lpszSerialUI);
01269 
01270     if (hConfigModule) {
01271         pCommConfigDialog = (void *)GetProcAddress(hConfigModule, "drvCommConfigDialogW");
01272         if (pCommConfigDialog) {
01273             res = pCommConfigDialog(lpszDevice, hWnd, lpCommConfig);
01274         }
01275         FreeLibrary(hConfigModule);
01276     }
01277 
01278     if (res) SetLastError(res);
01279     return (res == ERROR_SUCCESS);
01280 }
01281 
01282 /***********************************************************************
01283  *           GetCommConfig     (KERNEL32.@)
01284  *
01285  * Fill in the COMMCONFIG structure for the comm port hFile
01286  *
01287  * RETURNS
01288  *
01289  *  TRUE on success, FALSE on failure
01290  *  If successful, lpCommConfig contains the comm port configuration.
01291  *
01292  * BUGS
01293  *
01294  */
01295 BOOL WINAPI GetCommConfig(
01296     HANDLE       hFile,        /* [in] The communications device. */
01297     LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
01298     LPDWORD      lpdwSize)     /* [in/out] Initially the size of the configuration buffer/structure,
01299                                   afterwards the number of bytes copied to the buffer or
01300                                   the needed size of the buffer. */
01301 {
01302     BOOL r;
01303 
01304     TRACE("(%p, %p, %p) *lpdwSize: %u\n", hFile, lpCommConfig, lpdwSize, lpdwSize ? *lpdwSize : 0 );
01305 
01306     if(lpCommConfig == NULL)
01307         return FALSE;
01308     r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
01309     *lpdwSize = sizeof(COMMCONFIG);
01310     if(r)
01311         return FALSE;
01312 
01313     lpCommConfig->dwSize = sizeof(COMMCONFIG);
01314     lpCommConfig->wVersion = 1;
01315     lpCommConfig->wReserved = 0;
01316     r = GetCommState(hFile,&lpCommConfig->dcb);
01317     lpCommConfig->dwProviderSubType = PST_RS232;
01318     lpCommConfig->dwProviderOffset = 0;
01319     lpCommConfig->dwProviderSize = 0;
01320 
01321     return r;
01322 }
01323 
01324 /***********************************************************************
01325  *           SetCommConfig     (KERNEL32.@)
01326  *
01327  *  Sets the configuration of the communications device.
01328  *
01329  * RETURNS
01330  *
01331  *  True on success, false if the handle was bad is not a communications device.
01332  */
01333 BOOL WINAPI SetCommConfig(
01334     HANDLE       hFile,     /* [in] The communications device. */
01335     LPCOMMCONFIG lpCommConfig,  /* [in] The desired configuration. */
01336     DWORD dwSize)       /* [in] size of the lpCommConfig struct */
01337 {
01338     TRACE("(%p, %p, %u)\n", hFile, lpCommConfig, dwSize);
01339     return SetCommState(hFile,&lpCommConfig->dcb);
01340 }
01341 
01342 /***********************************************************************
01343  *           SetDefaultCommConfigW  (KERNEL32.@)
01344  *
01345  * Initializes the default configuration for a communication device.
01346  *
01347  * PARAMS
01348  *  lpszDevice   [I] Name of the device targeted for configuration
01349  *  lpCommConfig [I] PTR to a buffer with the configuration for the device
01350  *  dwSize       [I] Number of bytes in the buffer
01351  *
01352  * RETURNS
01353  *  Failure: FALSE
01354  *  Success: TRUE, and default configuration saved
01355  *
01356  */
01357 BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
01358 {
01359     BOOL (WINAPI *lpfnSetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, DWORD);
01360     HMODULE hConfigModule;
01361     BOOL r = FALSE;
01362 
01363     TRACE("(%s, %p, %u)\n", debugstr_w(lpszDevice), lpCommConfig, dwSize);
01364 
01365     hConfigModule = LoadLibraryW(lpszSerialUI);
01366     if(!hConfigModule)
01367         return r;
01368 
01369     lpfnSetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
01370     if (lpfnSetDefaultCommConfig)
01371         r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
01372 
01373     FreeLibrary(hConfigModule);
01374 
01375     return r;
01376 }
01377 
01378 
01379 /***********************************************************************
01380  *           SetDefaultCommConfigA     (KERNEL32.@)
01381  *
01382  * Initializes the default configuration for a communication device.
01383  *
01384  * See SetDefaultCommConfigW.
01385  *
01386  */
01387 BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
01388 {
01389     BOOL r;
01390     LPWSTR lpDeviceW = NULL;
01391     DWORD len;
01392 
01393     TRACE("(%s, %p, %u)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize);
01394 
01395     if (lpszDevice)
01396     {
01397         len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
01398         lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
01399         MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
01400     }
01401     r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
01402     HeapFree( GetProcessHeap(), 0, lpDeviceW );
01403     return r;
01404 }
01405 
01406 
01407 /***********************************************************************
01408  *           GetDefaultCommConfigW   (KERNEL32.@)
01409  *
01410  *   Acquires the default configuration of the specified communication device. (unicode)
01411  *
01412  *  RETURNS
01413  *
01414  *   True on successful reading of the default configuration,
01415  *   if the device is not found or the buffer is too small.
01416  */
01417 BOOL WINAPI GetDefaultCommConfigW(
01418     LPCWSTR      lpszName, /* [in] The unicode name of the device targeted for configuration. */
01419     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
01420     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
01421                               afterwards the number of bytes copied to the buffer or
01422                               the needed size of the buffer. */
01423 {
01424     DWORD (WINAPI *pGetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, LPDWORD);
01425     HMODULE hConfigModule;
01426     DWORD   res = ERROR_INVALID_PARAMETER;
01427 
01428     TRACE("(%s, %p, %p)  *lpdwSize: %u\n", debugstr_w(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
01429     hConfigModule = LoadLibraryW(lpszSerialUI);
01430 
01431     if (hConfigModule) {
01432         pGetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvGetDefaultCommConfigW");
01433         if (pGetDefaultCommConfig) {
01434             res = pGetDefaultCommConfig(lpszName, lpCC, lpdwSize);
01435         }
01436         FreeLibrary(hConfigModule);
01437     }
01438 
01439     if (res) SetLastError(res);
01440     return (res == ERROR_SUCCESS);
01441 }
01442 
01443 /**************************************************************************
01444  *         GetDefaultCommConfigA        (KERNEL32.@)
01445  *
01446  *   Acquires the default configuration of the specified communication device. (ascii)
01447  *
01448  *  RETURNS
01449  *
01450  *   True on successful reading of the default configuration,
01451  *   if the device is not found or the buffer is too small.
01452  */
01453 BOOL WINAPI GetDefaultCommConfigA(
01454     LPCSTR       lpszName, /* [in] The ascii name of the device targeted for configuration. */
01455     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
01456     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
01457                   afterwards the number of bytes copied to the buffer or
01458                               the needed size of the buffer. */
01459 {
01460     BOOL ret = FALSE;
01461     UNICODE_STRING lpszNameW;
01462 
01463     TRACE("(%s, %p, %p)  *lpdwSize: %u\n", debugstr_a(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
01464     if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
01465     else lpszNameW.Buffer = NULL;
01466 
01467     ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
01468 
01469     RtlFreeUnicodeString(&lpszNameW);
01470     return ret;
01471 }

Generated on Sun May 27 2012 04:24:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.