update for HEAD-2003091401
[reactos.git] / lib / kernel32 / misc / comm.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/misc/comm.c
6  * PURPOSE:         Comm functions
7  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
8  *                  modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
9  *                                      Robert Dickenson (robd@mok.lvcom.com)
10  * UPDATE HISTORY:
11  *                  Created 01/11/98
12  *                                      RDD (30/09/2002) implemented many function bodies to call serial driver.
13  *                                      KJK (11/02/2003) implemented BuildCommDCB & BuildCommDCBAndTimeouts
14  */
15
16 #include <k32.h>
17
18 #define NDEBUG
19 #include <kernel32/kernel32.h>
20
21 /* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */
22
23 /* TYPES */
24
25 /* Pointer to a callback that handles a particular parameter */
26 typedef BOOL (*COMMDCB_PARAM_CALLBACK)
27 (
28  DCB *,
29  COMMTIMEOUTS *,
30  BOOL *,
31  LPWSTR *
32 );
33
34 /* Symbolic flag of any length */
35 typedef struct _COMMDCB_PARAM_STRFLAG
36 {
37  UNICODE_STRING String;
38  ULONG_PTR Value;
39 } COMMDCB_PARAM_STRFLAG;
40
41 /* One char long symbolic flag */
42 typedef struct _COMMDCB_PARAM_CHARFLAG
43 {
44  WCHAR Char;
45  ULONG_PTR Value;
46 } COMMDCB_PARAM_CHARFLAG;
47
48 /* MACROS */
49 /* stupid Borland C++ requires this */
50 #define _L(__S__) L ## __S__
51
52 /* Declare a parameter handler */
53 #define COMMDCB_PARAM_HANDLER(__P__) \
54  BOOL COMMDCB_ ## __P__ ## Param \
55  ( \
56   DCB * Dcb, \
57   COMMTIMEOUTS * Timeouts, \
58   BOOL * StopBitsSet, \
59   LPWSTR * StrTail \
60  )
61
62 /* UTILITIES */
63 /*
64  Lookup a string flag and return its numerical value. The flags array must be
65  sorted - a dichotomycal search is performed
66 */
67 BOOL COMMDCB_LookupStrFlag
68 (
69  UNICODE_STRING * Flag,
70  COMMDCB_PARAM_STRFLAG * Flags,
71  int FlagCount,
72  ULONG_PTR * Value
73 )
74 {
75  /* Lower and upper bound for dichotomycal search */
76  int nLowerBound = 0;
77  int nUpperBound = FlagCount - 1;
78
79  do
80  {
81   LONG nComparison;
82   /* pick the element in the middle of the area of interest as the pivot */
83   int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;
84
85   /* compare the string with the pivot */
86   nComparison = RtlCompareUnicodeString
87   (
88    Flag,
89    &Flags[nCurFlag].String,
90    TRUE
91   );
92
93   /* string is equal */
94   if(nComparison == 0)
95   {
96    /* return the flag's value */
97    *Value = Flags[nCurFlag].Value;
98
99    /* success */
100    return TRUE;
101   }
102   /* string is less than */
103   else if(nComparison < 0)
104   {
105    /*
106     restrict the search to the first half of the current slice, minus the pivot
107    */
108    nUpperBound = nCurFlag - 1;
109
110    /* fallthrough */
111   }
112   /* string is greater than */
113   else
114   {
115    /*
116     restrict the search to the second half of the current slice, minus the pivot
117    */
118    nLowerBound = nCurFlag + 1;
119
120    /* fallthrough */
121   }
122  }
123  /* continue until the slice is empty */
124  while(nLowerBound <= nUpperBound);
125
126  /* string not found: failure */
127  return FALSE;
128 }
129
130 /* PARSERS */
131 /*
132  Find the next character flag and return its numerical value. The flags array
133  must be sorted - a dichotomycal search is performed
134 */
135 BOOL COMMDCB_ParseCharFlag
136 (
137  LPWSTR * StrTail,
138  COMMDCB_PARAM_CHARFLAG * Flags,
139  int FlagCount,
140  ULONG_PTR * Value
141 )
142 {
143  /* Lower and upper bound for dichotomycal search */
144  int nLowerBound = 0;
145  int nUpperBound = FlagCount - 1;
146  /* get the first character as the flag */
147  WCHAR wcFlag = (*StrTail)[0];
148
149  /* premature end of string, or the character is whitespace */
150  if(!wcFlag || iswspace(wcFlag))
151   /* failure */
152   return FALSE;
153  
154  /* uppercase the character for case-insensitive search */
155  wcFlag = towupper(wcFlag);
156
157  /* skip the character flag */
158  ++ (*StrTail);
159
160  /* see COMMDCB_LookupStrFlag for a description of the algorithm */
161  do
162  {
163   LONG nComparison;
164   int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2;
165
166   nComparison = wcFlag - towupper(Flags[nCurFlag].Char);
167
168   if(nComparison == 0)
169   {
170    *Value = Flags[nCurFlag].Value;
171     
172    return TRUE;
173   }
174   else if(nComparison < 0)
175   {
176    nUpperBound = nCurFlag - 1;
177   }
178   else
179   {
180    nLowerBound = nCurFlag + 1;
181   }
182  }
183  while(nUpperBound >= nLowerBound);
184
185  /* flag not found: failure */
186  return FALSE;
187 }
188
189 /*
190  Find the next string flag and return its numerical value. The flags array must
191  be sorted - a dichotomycal search is performed
192 */
193 BOOL COMMDCB_ParseStrFlag
194 (
195  LPWSTR * StrTail,
196  COMMDCB_PARAM_STRFLAG * Flags,
197  int FlagCount,
198  ULONG_PTR * Value
199 )
200 {
201  LPWSTR pwcNewTail = *StrTail;
202  UNICODE_STRING wstrFlag;
203
204  /* scan the string until the first space character or the terminating null */
205  while(pwcNewTail[0] && !iswspace(pwcNewTail[0]))
206   ++ pwcNewTail;
207
208  /* string flag empty */
209  if(pwcNewTail == *StrTail)
210   /* failure */
211   return FALSE;
212
213  /* build the UNICODE_STRING description of the string flag */
214  wstrFlag.Buffer = *StrTail;
215  wstrFlag.Length = (pwcNewTail - *StrTail) * sizeof(WCHAR);
216  wstrFlag.MaximumLength = wstrFlag.Length;
217
218  /* skip the string flag */
219  *StrTail = pwcNewTail;
220
221  /* lookup the string flag's value and return it */
222  return COMMDCB_LookupStrFlag(&wstrFlag, Flags, FlagCount, Value);
223 }
224
225 /*
226  Parse a boolean value in the symbolic form on/off
227 */
228 BOOL COMMDCB_ParseBool(LPWSTR * StrTail, BOOL * Value)
229 {
230  BOOL bRetVal;
231  ULONG_PTR nValue;
232  static COMMDCB_PARAM_STRFLAG a_BoolFlags[] =
233  {
234   { UNICODE_STRING_INITIALIZER(L"off"), FALSE },
235   { UNICODE_STRING_INITIALIZER(L"on"),  TRUE }
236  };
237
238  /* try to recognize the next flag as a boolean */
239  bRetVal = COMMDCB_ParseStrFlag
240  (
241   StrTail,
242   a_BoolFlags,
243   sizeof(a_BoolFlags) / sizeof(a_BoolFlags[0]),
244   &nValue
245  );
246
247  /* failure */
248  if(!bRetVal) return FALSE;
249
250  /* success */
251  *Value = nValue ? TRUE : FALSE;
252  return TRUE;
253 }
254
255 /*
256  Parse a decimal integer
257 */
258 BOOL COMMDCB_ParseInt(LPWSTR * StrTail, DWORD * Value)
259 {
260  LPWSTR pwcPrevTail = *StrTail;
261  DWORD nValue = wcstoul(*StrTail, StrTail, 10);
262  
263  /* no character was consumed: failure */
264  if(pwcPrevTail == *StrTail) return FALSE;
265
266  /* success */
267  *Value = nValue;
268  return TRUE;
269 }
270
271 /* PARAMETER HANDLERS */
272 /* baud= */
273 COMMDCB_PARAM_HANDLER(baud)
274 {
275  DWORD nValue;
276  
277  (void)Timeouts;
278
279  /* parse the baudrate */
280  if(!COMMDCB_ParseInt(StrTail, &nValue))
281   /* failure */
282   return FALSE;
283
284  switch(nValue)
285  {
286   /* documented abbreviations */
287   case 11: Dcb->BaudRate = 110; break;
288   case 15: Dcb->BaudRate = 150; break;
289   case 30: Dcb->BaudRate = 300; break;
290   case 60: Dcb->BaudRate = 600; break;
291   case 12: Dcb->BaudRate = 1200; break;
292   case 24: Dcb->BaudRate = 2400; break;
293   case 48: Dcb->BaudRate = 4800; break;
294   case 96: Dcb->BaudRate = 9600; break;
295   case 19: Dcb->BaudRate = 19200; break;
296   /* literal value */
297   default: Dcb->BaudRate = nValue; break;
298  }
299
300  /* if the stop bits haven't been specified explicitely */
301  if(!(*StopBitsSet))
302  {
303   /* default the stop bits to 2 for 110 baud */
304   if(Dcb->BaudRate == 110) Dcb->StopBits = TWOSTOPBITS;
305   /* else, default the stop bits to 1 */  
306   else Dcb->StopBits = ONESTOPBIT;
307  }
308
309  /* success */
310  return TRUE;
311 }
312
313 /* data= */
314 COMMDCB_PARAM_HANDLER(data)
315 {
316  DWORD nValue;
317
318  (void)Timeouts;
319  (void)StopBitsSet;
320
321  /* parse the data bits */
322  if(!COMMDCB_ParseInt(StrTail, &nValue))
323   /* failure */
324   return FALSE;
325
326  /* value out of range: failure */
327  if(nValue < 5 || nValue > 8) return FALSE;
328   
329  /* success */
330  Dcb->ByteSize = nValue;
331  return TRUE;
332 }
333
334 /* dtr= */
335 COMMDCB_PARAM_HANDLER(dtr)
336 {
337  BOOL bRetVal;
338  ULONG_PTR nValue;
339  static COMMDCB_PARAM_STRFLAG a_DTRFlags[] =
340  {
341   { UNICODE_STRING_INITIALIZER(L"hs"),  DTR_CONTROL_HANDSHAKE },
342   { UNICODE_STRING_INITIALIZER(L"off"), DTR_CONTROL_DISABLE },
343   { UNICODE_STRING_INITIALIZER(L"on"),  DTR_CONTROL_ENABLE }
344  };
345
346  (void)Timeouts;
347  (void)StopBitsSet;
348
349  /* parse the flag */
350  bRetVal = COMMDCB_ParseStrFlag
351  (
352   StrTail,
353   a_DTRFlags,
354   sizeof(a_DTRFlags) / sizeof(a_DTRFlags[0]),
355   &nValue
356  );
357
358  /* failure */
359  if(!bRetVal) return FALSE;
360
361  /* success */
362  Dcb->fDtrControl = nValue;
363  return TRUE;
364 }
365
366 /* idsr= */
367 COMMDCB_PARAM_HANDLER(idsr)
368 {
369  BOOL bValue;
370  
371  (void)Timeouts;
372  (void)StopBitsSet;
373
374  /* parse the flag */
375  if(!COMMDCB_ParseBool(StrTail, &bValue))
376   /* failure */
377   return FALSE;
378
379  /* success */
380  Dcb->fDsrSensitivity = bValue;
381  return TRUE;
382 }
383
384 /* octs= */
385 COMMDCB_PARAM_HANDLER(octs)
386 {
387  BOOL bValue;
388
389  (void)Timeouts;
390  (void)StopBitsSet;
391
392  /* parse the flag */
393  if(!COMMDCB_ParseBool(StrTail, &bValue))
394   /* failure */
395   return FALSE;
396
397  /* success */
398  Dcb->fOutxCtsFlow = bValue;
399  return TRUE;
400 }
401
402 /* odsr= */
403 COMMDCB_PARAM_HANDLER(odsr)
404 {
405  BOOL bValue;
406
407  (void)Timeouts;
408  (void)StopBitsSet;
409
410  /* parse the flag */
411  if(!COMMDCB_ParseBool(StrTail, &bValue))
412   /* failure */
413   return FALSE;
414
415  /* success */
416  Dcb->fOutxDsrFlow = bValue;
417  return TRUE;
418 }
419
420 /* parity= */
421 COMMDCB_PARAM_HANDLER(parity)
422 {
423  BOOL bRetVal;
424  ULONG_PTR nValue;
425  static COMMDCB_PARAM_CHARFLAG a_ParityFlags[] =
426  {
427   { L'e', EVENPARITY },
428   { L'm', MARKPARITY },
429   { L'n', NOPARITY },
430   { L'o', ODDPARITY },
431   { L's', SPACEPARITY }
432  };
433
434  (void)Timeouts;
435  (void)StopBitsSet;
436
437  /* parse the flag */
438  bRetVal = COMMDCB_ParseCharFlag
439  (
440   StrTail,
441   a_ParityFlags,
442   sizeof(a_ParityFlags) / sizeof(a_ParityFlags[0]),
443   &nValue
444  );
445
446  /* failure */
447  if(!bRetVal) return FALSE;
448
449  /* success */
450  Dcb->Parity = nValue;
451  return TRUE;
452 }
453
454 /* rts= */
455 COMMDCB_PARAM_HANDLER(rts)
456 {
457  DWORD nRetVal;
458  ULONG_PTR nValue;
459  static COMMDCB_PARAM_STRFLAG a_RTSFlags[] =
460  {
461   { UNICODE_STRING_INITIALIZER(L"hs"),  RTS_CONTROL_HANDSHAKE },
462   { UNICODE_STRING_INITIALIZER(L"off"), RTS_CONTROL_DISABLE },
463   { UNICODE_STRING_INITIALIZER(L"on"),  RTS_CONTROL_ENABLE },
464   { UNICODE_STRING_INITIALIZER(L"tg"),  RTS_CONTROL_TOGGLE }
465  };
466
467  (void)Timeouts;
468  (void)StopBitsSet;
469
470  /* parse the flag */
471  nRetVal = COMMDCB_ParseStrFlag
472  (
473   StrTail,
474   a_RTSFlags,
475   sizeof(a_RTSFlags) / sizeof(a_RTSFlags[0]),
476   &nValue
477  );
478
479  /* failure */
480  if(!nRetVal) return FALSE;
481
482  /* success */
483  Dcb->fRtsControl = nValue;
484  return TRUE;
485 }
486
487 /* stop= */
488 COMMDCB_PARAM_HANDLER(stop)
489 {
490  BOOL bRetVal;
491  ULONG_PTR nValue;
492  static COMMDCB_PARAM_STRFLAG a_StopFlags[] =
493  {
494   { UNICODE_STRING_INITIALIZER(L"1"),   ONESTOPBIT },
495   { UNICODE_STRING_INITIALIZER(L"1.5"), ONE5STOPBITS },
496   { UNICODE_STRING_INITIALIZER(L"2"),   TWOSTOPBITS }
497  };
498
499  (void)Timeouts;
500
501  /* parse the flag */
502  bRetVal = COMMDCB_ParseStrFlag
503  (
504   StrTail,
505   a_StopFlags,
506   sizeof(a_StopFlags) / sizeof(a_StopFlags[0]),
507   &nValue
508  );
509
510  /* failure */
511  if(!bRetVal) return FALSE;
512
513  /* tell the baud= handler that the stop bits have been specified explicitely */
514  *StopBitsSet = TRUE;
515
516  /* success */
517  Dcb->StopBits = nValue;
518  return TRUE;
519 }
520
521 /* to= */
522 COMMDCB_PARAM_HANDLER(to)
523 {
524  BOOL bValue;
525
526  (void)Dcb;
527  (void)StopBitsSet;
528
529  /* parse the flag */
530  if(!COMMDCB_ParseBool(StrTail, &bValue))
531   /* failure */
532   return FALSE;
533
534  /* for BuildCommDCB(), Timeouts is NULL */
535  if(Timeouts)
536  {
537   /* why? no idea. All values taken from Windows 2000 with experimentation */
538   Timeouts->ReadIntervalTimeout = 0;
539   Timeouts->ReadTotalTimeoutMultiplier = 0;
540   Timeouts->ReadTotalTimeoutConstant = 0;
541   Timeouts->WriteTotalTimeoutMultiplier = 0;
542
543   /* timeout */
544   if(bValue) Timeouts->WriteTotalTimeoutConstant = 60000;
545   /* no timeout */
546   else Timeouts->WriteTotalTimeoutConstant = 0;
547  }
548
549  /* success */
550  return TRUE;
551 }
552
553 /* xon= */
554 COMMDCB_PARAM_HANDLER(xon)
555 {
556  BOOL bValue;
557
558  (void)Timeouts;
559  (void)StopBitsSet;
560
561  /* parse the flag */
562  if(!COMMDCB_ParseBool(StrTail, &bValue))
563   /* failure */
564   return FALSE;
565
566  /* XON/XOFF */
567  if(bValue) Dcb->fInX = Dcb->fOutX = TRUE;
568  /* no XON/XOFF */
569  else Dcb->fInX = Dcb->fOutX = FALSE;
570
571  /* success */
572  return TRUE;
573 }
574
575 /* FUNCTIONS */
576 #define COMMDCB_PARAM(__P__) \
577  { \
578   UNICODE_STRING_INITIALIZER(_L(#__P__)), \
579   (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
580  }
581
582 /*
583  * @unimplemented
584  */
585 WINBOOL
586 STDCALL
587 BuildCommDCBAndTimeoutsW
588 (
589  LPCWSTR lpDef,
590  LPDCB lpDCB,
591  LPCOMMTIMEOUTS lpCommTimeouts
592 )
593 {
594  /* tell the baud= handler that the stop bits should be defaulted */
595  BOOL bStopBitsSet = FALSE;
596
597  /* parameter validation */
598  if(lpDCB->DCBlength != sizeof(DCB)) goto InvalidParam;
599
600  /* set defaults */
601  lpDCB->StopBits = ONESTOPBIT;
602
603  /*
604   The documentation for MODE says that data= defaults to 7, but BuildCommDCB
605   doesn't seem to set it
606  */
607  /* lpDCB->ByteSize = 7; */
608
609  /* skip COMx[n] */
610  if
611  (
612   lpDef[0] &&
613   towupper(lpDef[0]) == L'C' &&
614   lpDef[1] &&
615   towupper(lpDef[1]) == L'O' &&
616   lpDef[2] &&
617   towupper(lpDef[2]) == L'M'
618  )
619  {
620   DWORD nDummy;
621
622   /* skip "COM" */
623   lpDef += 3;
624
625   /* premature end of string */
626   if(!lpDef[0]) goto InvalidParam;
627
628   /* skip "x" */
629   if(!COMMDCB_ParseInt((LPWSTR *)&lpDef, &nDummy)) goto InvalidParam;
630
631   /* skip ":" */
632   if(lpDef[0] == L':') ++ lpDef;
633  }
634
635  /* skip leading whitespace */
636  while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
637
638  /* repeat until the end of the string */
639  while(lpDef[0])
640  {
641   static COMMDCB_PARAM_STRFLAG a_Params[] =
642   {
643    COMMDCB_PARAM(baud),
644    COMMDCB_PARAM(data),
645    COMMDCB_PARAM(dtr),
646    COMMDCB_PARAM(idsr),
647    COMMDCB_PARAM(octs),
648    COMMDCB_PARAM(odsr),
649    COMMDCB_PARAM(parity),
650    COMMDCB_PARAM(rts),
651    COMMDCB_PARAM(stop),
652    COMMDCB_PARAM(to),
653    COMMDCB_PARAM(xon)
654   };
655   BOOL bRetVal;
656   COMMDCB_PARAM_CALLBACK pCallback;
657   UNICODE_STRING wstrParam;
658   LPWSTR pwcPrevTail = (LPWSTR)lpDef;
659
660   /* get the parameter */
661   while(lpDef[0] && lpDef[0] != L'=') ++ lpDef;
662
663   /* premature end of string */
664   if(!lpDef[0]) goto InvalidParam;
665
666   /* build the parameter's UNICODE_STRING */
667   wstrParam.Buffer = pwcPrevTail;
668   wstrParam.Length = (lpDef - pwcPrevTail) * sizeof(WCHAR);
669   wstrParam.MaximumLength = wstrParam.Length;
670
671   /* skip the "=" */
672   ++ lpDef;
673
674   /* lookup the callback for the parameter */
675   bRetVal = COMMDCB_LookupStrFlag
676   (
677    &wstrParam,
678    a_Params,
679    sizeof(a_Params) / sizeof(a_Params[0]),
680    (ULONG_PTR *)&pCallback
681   );
682
683   /* invalid parameter */
684   if(!bRetVal) goto InvalidParam;
685
686   /* call the callback to parse the parameter's argument */
687   if(!pCallback(lpDCB, lpCommTimeouts, &bStopBitsSet, (LPWSTR *)&lpDef))
688    /* failure */
689    goto InvalidParam;
690
691   /* skip trailing whitespace */
692   while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
693  }
694
695  /* success */
696  return TRUE;
697
698 InvalidParam:
699  /* failure */
700  SetLastError(ERROR_INVALID_PARAMETER);
701  return FALSE;
702 }
703
704
705 /*
706  * @unimplemented
707  */
708 WINBOOL
709 STDCALL
710 BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB,     LPCOMMTIMEOUTS lpCommTimeouts)
711 {
712  NTSTATUS nErrCode;
713  WINBOOL bRetVal;
714  ANSI_STRING strDef;
715  UNICODE_STRING wstrDef;
716
717  RtlInitAnsiString(&strDef, (LPSTR)lpDef);
718  
719  nErrCode = RtlAnsiStringToUnicodeString(&wstrDef, &strDef, TRUE);
720
721  if(!NT_SUCCESS(nErrCode))
722  {
723   SetLastErrorByStatus(nErrCode);
724   return FALSE;
725  }
726  
727  bRetVal = BuildCommDCBAndTimeoutsW(wstrDef.Buffer, lpDCB, lpCommTimeouts);
728
729  RtlFreeUnicodeString(&wstrDef);
730  
731  return bRetVal;
732 }
733
734 /*
735  * @unimplemented
736  */
737 WINBOOL
738 STDCALL
739 BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
740 {
741  return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL);
742 }
743
744
745 /*
746  * @unimplemented
747  */
748 WINBOOL
749 STDCALL
750 BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
751 {
752  return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL);
753 }
754
755
756 /*
757  * @implemented
758  */
759 WINBOOL
760 STDCALL
761 ClearCommBreak(HANDLE hFile)
762 {
763         WINBOOL result = FALSE;
764         DWORD dwBytesReturned;
765
766         if (hFile == INVALID_HANDLE_VALUE) {
767                 return FALSE;
768         }
769     result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
770         return TRUE;
771 }
772
773
774 /*
775  * @unimplemented
776  */
777 WINBOOL
778 STDCALL
779 ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
780 {
781         WINBOOL result = FALSE;
782         DWORD dwBytesReturned;
783
784         if (hFile == INVALID_HANDLE_VALUE) {
785                 //SetLastError(CE_MODE);
786                 return FALSE;
787         }
788         if (lpErrors == NULL) {
789         DPRINT("ERROR: GetCommState() - NULL Errors pointer\n");
790                 return FALSE;
791         }
792 //      *lpErrors = CE_BREAK;
793 //      *lpErrors = CE_FRAME;
794 //      *lpErrors = CE_IOE;
795 //      *lpErrors = CE_MODE;
796 //      *lpErrors = CE_OVERRUN;
797 //      *lpErrors = CE_RXOVER;
798 //      *lpErrors = CE_RXPARITY;
799 //      *lpErrors = CE_TXFULL;
800 /*
801 CE_BREAK The hardware detected a break condition. 
802 CE_FRAME The hardware detected a framing error. 
803 CE_IOE An I/O error occurred during communications with the device. 
804 CE_MODE The requested mode is not supported, or the hFile parameter is invalid. If this value is specified, it is the only valid error. 
805 CE_OVERRUN A character-buffer overrun has occurred. The next character is lost. 
806 CE_RXOVER An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character. 
807 CE_RXPARITY The hardware detected a parity error. 
808 CE_TXFULL The application tried to transmit a character, but the output buffer was full. 
809  */
810     result = DeviceIoControl(hFile, IOCTL_SERIAL_RESET_DEVICE, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
811
812         if (lpStat != NULL) {
813                 lpStat->fCtsHold = 0;
814                 lpStat->fDsrHold = 0;
815                 lpStat->fRlsdHold = 0;
816                 lpStat->fXoffHold = 0;
817                 lpStat->fXoffSent = 0;
818                 lpStat->fEof = 0;
819                 lpStat->fTxim = 0;
820                 lpStat->cbInQue = 0;
821                 lpStat->cbOutQue = 0;
822         }
823         return TRUE;
824 }
825
826
827 /*
828  * @unimplemented
829  */
830 WINBOOL
831 STDCALL
832 CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
833 {
834         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
835         return FALSE;
836 }
837
838
839 /*
840  * @unimplemented
841  */
842 WINBOOL
843 STDCALL
844 CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
845 {
846         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
847         return FALSE;
848 }
849
850
851 /*
852  * @implemented
853  */
854 WINBOOL
855 STDCALL
856 EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
857 {
858         WINBOOL result = FALSE;
859         DWORD dwBytesReturned;
860
861         if (hFile == INVALID_HANDLE_VALUE) {
862                 return FALSE;
863         }
864         switch (dwFunc) {
865     case CLRDTR: // Clears the DTR (data-terminal-ready) signal. 
866         result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
867                 break;
868     case CLRRTS: // Clears the RTS (request-to-send) signal. 
869         result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
870                 break;
871     case SETDTR: // Sends the DTR (data-terminal-ready) signal. 
872         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
873                 break;
874     case SETRTS: // Sends the RTS (request-to-send) signal. 
875         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
876                 break;
877     case SETXOFF: // Causes transmission to act as if an XOFF character has been received. 
878         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XOFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
879                 break;
880     case SETXON: // Causes transmission to act as if an XON character has been received. 
881         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
882                 break;
883     case SETBREAK: // Suspends character transmission and places the transmission line in a break state until the ClearCommBreak function is called (or EscapeCommFunction is called with the CLRBREAK extended function code). The SETBREAK extended function code is identical to the SetCommBreak function. Note that this extended function does not flush data that has not been transmitted. 
884         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
885                 break;
886     case CLRBREAK: // Restores character transmission and places the transmission line in a nonbreak state. The CLRBREAK extended function code is identical to the ClearCommBreak function. 
887         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
888                 break;
889         default:
890         DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
891         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
892                 break;
893         }
894         return TRUE;
895 }
896
897
898 /*
899  * @unimplemented
900  */
901 WINBOOL
902 STDCALL
903 GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
904 {
905         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
906         return FALSE;
907 }
908
909
910 /*
911  * @implemented
912  */
913 WINBOOL
914 STDCALL
915 GetCommMask(HANDLE hFile, LPDWORD lpEvtMask)
916 {
917         WINBOOL result = FALSE;
918         DWORD dwBytesReturned;
919
920         if (hFile == INVALID_HANDLE_VALUE) {
921                 return FALSE;
922         }
923     result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_WAIT_MASK, 
924                 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, NULL);
925         return TRUE;
926 }
927
928
929 /*
930  * @implemented
931  */
932 WINBOOL
933 STDCALL
934 GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
935 {
936         WINBOOL result = FALSE;
937         DWORD dwBytesReturned;
938
939         if (hFile == INVALID_HANDLE_VALUE) {
940                 return FALSE;
941         }
942         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
943                 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
944         return TRUE;
945 }
946
947
948 /*
949  * @unimplemented
950  */
951 WINBOOL
952 STDCALL
953 GetCommProperties(HANDLE hFile, LPCOMMPROP lpCommProp)
954 {
955         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
956         return FALSE;
957 }
958
959
960 /*
961  * @implemented
962  */
963 WINBOOL
964 STDCALL
965 GetCommState(HANDLE hFile, LPDCB lpDCB)
966 {
967         WINBOOL result = FALSE;
968         DWORD dwBytesReturned;
969
970         SERIAL_BAUD_RATE BaudRate;
971         SERIAL_HANDFLOW HandFlow;
972         SERIAL_CHARS SpecialChars;
973         SERIAL_LINE_CONTROL LineControl;
974
975     DPRINT("GetCommState(%d, %p)\n", hFile, lpDCB);
976
977         if (hFile == INVALID_HANDLE_VALUE) {
978         DPRINT("ERROR: GetCommState() - INVALID_HANDLE_VALUE\n");
979                 return FALSE;
980         }
981         if (lpDCB == NULL) {
982         DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
983                 return FALSE;
984         }
985         if (lpDCB->DCBlength != sizeof(DCB)) {
986         DPRINT("ERROR: GetCommState() - Invalid DCB size\n");
987                 return FALSE;
988         }
989
990 //    DPRINT("    GetCommState() CALLING DeviceIoControl\n");
991 //    result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
992 //    DPRINT("    GetCommState() DeviceIoControl returned %d\n", result);
993
994         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_BAUD_RATE,
995                          NULL, 0, &BaudRate, sizeof(BaudRate),&dwBytesReturned, NULL);
996         if (!NT_SUCCESS(result)) {
997         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n");
998                 return FALSE;
999         }
1000     lpDCB->BaudRate = BaudRate.BaudRate;
1001
1002         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_HANDFLOW,
1003                         NULL, 0, &HandFlow, sizeof(HandFlow), &dwBytesReturned, NULL);
1004         if (!NT_SUCCESS(result)) {
1005         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n");
1006                 return FALSE;
1007         }
1008         if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
1009         lpDCB->fOutxCtsFlow = 1;
1010         }
1011     if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
1012         lpDCB->fOutxDsrFlow = 1;
1013         }
1014     if (HandFlow.ControlHandShake & SERIAL_DTR_CONTROL) {
1015         lpDCB->fDtrControl = 1;
1016         }
1017     if (HandFlow.ControlHandShake & SERIAL_DTR_HANDSHAKE) {
1018         lpDCB->fDtrControl = 2;
1019         }
1020     if (HandFlow.ControlHandShake & SERIAL_RTS_CONTROL) {
1021         lpDCB->fRtsControl = 1;
1022         }
1023     if (HandFlow.ControlHandShake & SERIAL_RTS_HANDSHAKE) {
1024         lpDCB->fRtsControl = 2;
1025         }
1026     if (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
1027         lpDCB->fDsrSensitivity = 1;
1028         }
1029     if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
1030         lpDCB->fAbortOnError = 1;
1031         }
1032
1033     if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
1034         lpDCB->fErrorChar = 1;
1035         }
1036     if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) {
1037         lpDCB->fNull = 1;
1038         }
1039     if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) {
1040         lpDCB->fTXContinueOnXoff = 1;
1041         }
1042     lpDCB->XonLim = HandFlow.XonLimit;
1043     lpDCB->XoffLim = HandFlow.XoffLimit;
1044
1045         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_CHARS,
1046                         NULL, 0, &SpecialChars, sizeof(SpecialChars), &dwBytesReturned, NULL);
1047         if (!NT_SUCCESS(result)) {
1048         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n");
1049                 return FALSE;
1050         }
1051
1052     lpDCB->EofChar = SpecialChars.EofChar;
1053     lpDCB->ErrorChar = SpecialChars.ErrorChar;
1054     // = SpecialChars.BreakChar;
1055     lpDCB->EvtChar = SpecialChars.EventChar;
1056     lpDCB->XonChar = SpecialChars.XonChar;
1057     lpDCB->XoffChar = SpecialChars.XoffChar;
1058
1059         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_LINE_CONTROL,
1060                         NULL, 0, &LineControl, sizeof(LineControl), &dwBytesReturned, NULL);
1061         if (!NT_SUCCESS(result)) {
1062         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n");
1063                 return FALSE;
1064         }
1065         lpDCB->StopBits = LineControl.StopBits;
1066         lpDCB->Parity = LineControl.Parity;
1067         lpDCB->ByteSize = LineControl.WordLength;
1068     DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1069         return TRUE;
1070 }
1071
1072
1073 /*
1074  * @implemented
1075  */
1076 WINBOOL
1077 STDCALL
1078 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1079 {
1080         WINBOOL result = FALSE;
1081         DWORD dwBytesReturned;
1082
1083         if (hFile == INVALID_HANDLE_VALUE) {
1084                 return FALSE;
1085         }
1086         if (lpCommTimeouts == NULL) {
1087                 return FALSE;
1088         }
1089         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_TIMEOUTS,
1090                                                          NULL, 0, 
1091                                                          lpCommTimeouts, sizeof(COMMTIMEOUTS), 
1092                                                          &dwBytesReturned, NULL);
1093         return TRUE;
1094 }
1095
1096
1097 /*
1098  * @unimplemented
1099  */
1100 WINBOOL
1101 STDCALL
1102 GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1103 {
1104         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1105         return FALSE;
1106 }
1107
1108
1109 /*
1110  * @unimplemented
1111  */
1112 WINBOOL
1113 STDCALL
1114 GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1115 {
1116         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1117         return FALSE;
1118 }
1119
1120
1121 /*
1122  * @implemented
1123  */
1124 WINBOOL
1125 STDCALL
1126 PurgeComm(HANDLE hFile, DWORD dwFlags)
1127 {
1128         WINBOOL result = FALSE;
1129         DWORD dwBytesReturned;
1130
1131         if (hFile == INVALID_HANDLE_VALUE) {
1132                 return FALSE;
1133         }
1134     result = DeviceIoControl(hFile, IOCTL_SERIAL_PURGE, 
1135                 &dwFlags, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1136         return TRUE;
1137 }
1138
1139
1140 /*
1141  * @implemented
1142  */
1143 WINBOOL
1144 STDCALL
1145 SetCommBreak(HANDLE hFile)
1146 {
1147         WINBOOL result = FALSE;
1148         DWORD dwBytesReturned;
1149
1150         if (hFile == INVALID_HANDLE_VALUE) {
1151                 return FALSE;
1152         }
1153     result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
1154         return TRUE;
1155 }
1156
1157
1158 /*
1159  * @unimplemented
1160  */
1161 WINBOOL
1162 STDCALL
1163 SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize)
1164 {
1165         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1166         return FALSE;
1167 }
1168
1169
1170 /*
1171  * @implemented
1172  */
1173 WINBOOL
1174 STDCALL
1175 SetCommMask(HANDLE hFile, DWORD dwEvtMask)
1176 {
1177         WINBOOL result = FALSE;
1178         DWORD dwBytesReturned;
1179
1180         if (hFile == INVALID_HANDLE_VALUE) {
1181                 return FALSE;
1182         }
1183     result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_WAIT_MASK, 
1184                 &dwEvtMask, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1185         return TRUE;
1186 }
1187
1188
1189 /*
1190  * @implemented
1191  */
1192 WINBOOL
1193 STDCALL
1194 SetCommState(HANDLE     hFile, LPDCB lpDCB)
1195 {
1196         WINBOOL result = FALSE;
1197         DWORD dwBytesReturned;
1198
1199         SERIAL_BAUD_RATE BaudRate;
1200         SERIAL_HANDFLOW HandFlow;
1201         SERIAL_CHARS SpecialChars;
1202         SERIAL_LINE_CONTROL LineControl;
1203
1204     DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile, lpDCB);
1205
1206         if (hFile == INVALID_HANDLE_VALUE) {
1207         DPRINT("SetCommState() - ERROR: INVALID_HANDLE_VALUE\n");
1208                 return FALSE;
1209         }
1210         if (lpDCB == NULL) {
1211         DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
1212                 return FALSE;
1213         }
1214
1215         BaudRate.BaudRate = lpDCB->BaudRate;
1216         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BAUD_RATE,
1217                 &BaudRate, sizeof(BaudRate), NULL, 0, &dwBytesReturned, NULL);
1218         if (!NT_SUCCESS(result)) {
1219         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n");
1220                 return FALSE;
1221         }
1222 /*
1223 #define SERIAL_DTR_MASK           ((ULONG)0x03)
1224 #define SERIAL_DTR_CONTROL        ((ULONG)0x01)
1225 #define SERIAL_DTR_HANDSHAKE      ((ULONG)0x02)
1226 #define SERIAL_CTS_HANDSHAKE      ((ULONG)0x08)
1227 #define SERIAL_DSR_HANDSHAKE      ((ULONG)0x10)
1228 #define SERIAL_DCD_HANDSHAKE      ((ULONG)0x20)
1229 #define SERIAL_OUT_HANDSHAKEMASK  ((ULONG)0x38)
1230 #define SERIAL_DSR_SENSITIVITY    ((ULONG)0x40)
1231 #define SERIAL_ERROR_ABORT        ((ULONG)0x80000000)
1232 #define SERIAL_CONTROL_INVALID    ((ULONG)0x7fffff84)
1233  */
1234     HandFlow.ControlHandShake = 0;
1235
1236         if (lpDCB->fOutxCtsFlow) {
1237         HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
1238         }
1239         if (lpDCB->fOutxDsrFlow) {
1240         HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
1241         }
1242         if (lpDCB->fDtrControl) {
1243         HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL;
1244         }
1245         if (lpDCB->fDtrControl) {
1246         HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
1247         }
1248         if (lpDCB->fRtsControl) {
1249         HandFlow.ControlHandShake |= SERIAL_RTS_CONTROL;
1250         }
1251         if (lpDCB->fRtsControl) {
1252         HandFlow.ControlHandShake |= SERIAL_RTS_HANDSHAKE;
1253         }
1254         if (lpDCB->fDsrSensitivity) {
1255         HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
1256         }
1257         if (lpDCB->fAbortOnError) {
1258         HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT;
1259         }
1260 /*
1261 #define SERIAL_AUTO_TRANSMIT      ((ULONG)0x01)
1262 #define SERIAL_AUTO_RECEIVE       ((ULONG)0x02)
1263 #define SERIAL_ERROR_CHAR         ((ULONG)0x04)
1264 #define SERIAL_NULL_STRIPPING     ((ULONG)0x08)
1265 #define SERIAL_BREAK_CHAR         ((ULONG)0x10)
1266 #define SERIAL_RTS_MASK           ((ULONG)0xc0)
1267 #define SERIAL_RTS_CONTROL        ((ULONG)0x40)
1268 #define SERIAL_RTS_HANDSHAKE      ((ULONG)0x80)
1269 #define SERIAL_TRANSMIT_TOGGLE    ((ULONG)0xc0)
1270 #define SERIAL_XOFF_CONTINUE      ((ULONG)0x80000000)
1271 #define SERIAL_FLOW_INVALID       ((ULONG)0x7fffff20)
1272  */
1273     HandFlow.FlowReplace = 0;
1274         if (lpDCB->fErrorChar) {
1275         HandFlow.FlowReplace |= SERIAL_ERROR_CHAR;
1276         }
1277         if (lpDCB->fNull) {
1278         HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING;
1279         }
1280         if (lpDCB->fTXContinueOnXoff) {
1281         HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE;
1282         }
1283     HandFlow.XonLimit = lpDCB->XonLim;
1284     HandFlow.XoffLimit = lpDCB->XoffLim;
1285         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_HANDFLOW,
1286                 &HandFlow, sizeof(HandFlow), NULL, 0, &dwBytesReturned, NULL);
1287         if (!NT_SUCCESS(result)) {
1288         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n");
1289                 return FALSE;
1290         }
1291
1292     SpecialChars.EofChar = lpDCB->EofChar;
1293     SpecialChars.ErrorChar = lpDCB->ErrorChar;
1294     SpecialChars.BreakChar = 0;
1295     SpecialChars.EventChar = lpDCB->EvtChar;
1296     SpecialChars.XonChar = lpDCB->XonChar;
1297     SpecialChars.XoffChar = lpDCB->XoffChar;
1298         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_CHARS,
1299                 &SpecialChars, sizeof(SpecialChars), NULL, 0, &dwBytesReturned, NULL);
1300         if (!NT_SUCCESS(result)) {
1301         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n");
1302                 return FALSE;
1303         }
1304
1305         LineControl.StopBits = lpDCB->StopBits;
1306         LineControl.Parity = lpDCB->Parity;
1307         LineControl.WordLength = lpDCB->ByteSize;
1308         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_LINE_CONTROL,
1309                 &LineControl, sizeof(LineControl), NULL, 0, &dwBytesReturned, NULL);
1310         if (!NT_SUCCESS(result)) {
1311         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n");
1312                 return FALSE;
1313         }
1314
1315     DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1316         return TRUE;
1317 }
1318
1319
1320 /*
1321  * @implemented
1322  */
1323 WINBOOL
1324 STDCALL
1325 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1326 {
1327         WINBOOL result = FALSE;
1328         DWORD dwBytesReturned;
1329         SERIAL_TIMEOUTS Timeouts;
1330
1331         if (hFile == INVALID_HANDLE_VALUE) {
1332                 return FALSE;
1333         }
1334         if (lpCommTimeouts == NULL) {
1335                 return FALSE;
1336         }
1337         Timeouts.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout;
1338         Timeouts.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier;
1339         Timeouts.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant;
1340         Timeouts.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier;
1341         Timeouts.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant;
1342         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_TIMEOUTS,
1343                 &Timeouts, sizeof(Timeouts), NULL, 0, &dwBytesReturned, NULL);
1344         return TRUE;
1345 }
1346
1347
1348 /*
1349  * @unimplemented
1350  */
1351 WINBOOL
1352 STDCALL
1353 SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1354 {
1355         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1356         return FALSE;
1357 }
1358
1359
1360 /*
1361  * @unimplemented
1362  */
1363 WINBOOL
1364 STDCALL
1365 SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1366 {
1367         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1368         return FALSE;
1369 }
1370
1371
1372 /*
1373  * @implemented
1374  */
1375 WINBOOL
1376 STDCALL
1377 SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
1378 {
1379         WINBOOL result = FALSE;
1380         DWORD dwBytesReturned;
1381         SERIAL_QUEUE_SIZE QueueSize;
1382
1383         if (hFile == INVALID_HANDLE_VALUE) {
1384                 return FALSE;
1385         }
1386     QueueSize.InSize = dwInQueue;
1387     QueueSize.OutSize = dwOutQueue;
1388         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_QUEUE_SIZE,
1389                 &QueueSize, sizeof(QueueSize), NULL, 0, &dwBytesReturned, NULL);
1390         return TRUE;
1391 }
1392
1393
1394 /*
1395  * @implemented
1396  */
1397 WINBOOL
1398 STDCALL
1399 TransmitCommChar(HANDLE hFile, char cChar)
1400 {
1401         WINBOOL result = FALSE;
1402         DWORD dwBytesReturned;
1403
1404         if (hFile == INVALID_HANDLE_VALUE) {
1405                 return FALSE;
1406         }
1407         result = DeviceIoControl(hFile, IOCTL_SERIAL_IMMEDIATE_CHAR,
1408                 &cChar, sizeof(cChar), NULL, 0, &dwBytesReturned, NULL);
1409         return TRUE;
1410 }
1411
1412
1413 /*
1414  * @implemented
1415  */
1416 WINBOOL
1417 STDCALL
1418 WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
1419 {
1420         WINBOOL result = FALSE;
1421         DWORD dwBytesReturned;
1422
1423         if (hFile == INVALID_HANDLE_VALUE) {
1424                 return FALSE;
1425         }
1426         if (lpEvtMask == NULL) {
1427                 return FALSE;
1428         }
1429         result = DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK,
1430                 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, lpOverlapped);
1431         return TRUE;
1432 }
1433
1434 /* EOF */