update for HEAD-2003021201
[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 WINBOOL
583 STDCALL
584 BuildCommDCBAndTimeoutsW
585 (
586  LPCWSTR lpDef,
587  LPDCB lpDCB,
588  LPCOMMTIMEOUTS lpCommTimeouts
589 )
590 {
591  /* tell the baud= handler that the stop bits should be defaulted */
592  BOOL bStopBitsSet = FALSE;
593
594  /* parameter validation */
595  if(lpDCB->DCBlength != sizeof(DCB)) goto InvalidParam;
596
597  /* set defaults */
598  lpDCB->StopBits = ONESTOPBIT;
599
600  /*
601   The documentation for MODE says that data= defaults to 7, but BuildCommDCB
602   doesn't seem to set it
603  */
604  /* lpDCB->ByteSize = 7; */
605
606  /* skip COMx[n] */
607  if
608  (
609   lpDef[0] &&
610   towupper(lpDef[0]) == L'C' &&
611   lpDef[1] &&
612   towupper(lpDef[1]) == L'O' &&
613   lpDef[2] &&
614   towupper(lpDef[2]) == L'M'
615  )
616  {
617   DWORD nDummy;
618
619   /* skip "COM" */
620   lpDef += 3;
621
622   /* premature end of string */
623   if(!lpDef[0]) goto InvalidParam;
624
625   /* skip "x" */
626   if(!COMMDCB_ParseInt((LPWSTR *)&lpDef, &nDummy)) goto InvalidParam;
627
628   /* skip ":" */
629   if(lpDef[0] == L':') ++ lpDef;
630  }
631
632  /* skip leading whitespace */
633  while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
634
635  /* repeat until the end of the string */
636  while(lpDef[0])
637  {
638   static COMMDCB_PARAM_STRFLAG a_Params[] =
639   {
640    COMMDCB_PARAM(baud),
641    COMMDCB_PARAM(data),
642    COMMDCB_PARAM(dtr),
643    COMMDCB_PARAM(idsr),
644    COMMDCB_PARAM(octs),
645    COMMDCB_PARAM(odsr),
646    COMMDCB_PARAM(parity),
647    COMMDCB_PARAM(rts),
648    COMMDCB_PARAM(stop),
649    COMMDCB_PARAM(to),
650    COMMDCB_PARAM(xon)
651   };
652   BOOL bRetVal;
653   COMMDCB_PARAM_CALLBACK pCallback;
654   UNICODE_STRING wstrParam;
655   LPWSTR pwcPrevTail = (LPWSTR)lpDef;
656
657   /* get the parameter */
658   while(lpDef[0] && lpDef[0] != L'=') ++ lpDef;
659
660   /* premature end of string */
661   if(!lpDef[0]) goto InvalidParam;
662
663   /* build the parameter's UNICODE_STRING */
664   wstrParam.Buffer = pwcPrevTail;
665   wstrParam.Length = (lpDef - pwcPrevTail) * sizeof(WCHAR);
666   wstrParam.MaximumLength = wstrParam.Length;
667
668   /* skip the "=" */
669   ++ lpDef;
670
671   /* lookup the callback for the parameter */
672   bRetVal = COMMDCB_LookupStrFlag
673   (
674    &wstrParam,
675    a_Params,
676    sizeof(a_Params) / sizeof(a_Params[0]),
677    (ULONG_PTR *)&pCallback
678   );
679
680   /* invalid parameter */
681   if(!bRetVal) goto InvalidParam;
682
683   /* call the callback to parse the parameter's argument */
684   if(!pCallback(lpDCB, lpCommTimeouts, &bStopBitsSet, (LPWSTR *)&lpDef))
685    /* failure */
686    goto InvalidParam;
687
688   /* skip trailing whitespace */
689   while(lpDef[0] && iswspace(lpDef[0])) ++ lpDef;
690  }
691
692  /* success */
693  return TRUE;
694
695 InvalidParam:
696  /* failure */
697  SetLastError(ERROR_INVALID_PARAMETER);
698  return FALSE;
699 }
700
701
702 WINBOOL
703 STDCALL
704 BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB,     LPCOMMTIMEOUTS lpCommTimeouts)
705 {
706  NTSTATUS nErrCode;
707  WINBOOL bRetVal;
708  ANSI_STRING strDef;
709  UNICODE_STRING wstrDef;
710
711  RtlInitAnsiString(&strDef, (LPSTR)lpDef);
712  
713  nErrCode = RtlAnsiStringToUnicodeString(&wstrDef, &strDef, TRUE);
714
715  if(!NT_SUCCESS(nErrCode))
716  {
717   SetLastErrorByStatus(nErrCode);
718   return FALSE;
719  }
720  
721  bRetVal = BuildCommDCBAndTimeoutsW(wstrDef.Buffer, lpDCB, lpCommTimeouts);
722
723  RtlFreeUnicodeString(&wstrDef);
724  
725  return bRetVal;
726 }
727
728 WINBOOL
729 STDCALL
730 BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
731 {
732  return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL);
733 }
734
735 WINBOOL
736 STDCALL
737 BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
738 {
739  return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL);
740 }
741
742 WINBOOL
743 STDCALL
744 ClearCommBreak(HANDLE hFile)
745 {
746         WINBOOL result = FALSE;
747         DWORD dwBytesReturned;
748
749         if (hFile == INVALID_HANDLE_VALUE) {
750                 return FALSE;
751         }
752     result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
753         return TRUE;
754 }
755
756 WINBOOL
757 STDCALL
758 ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
759 {
760         WINBOOL result = FALSE;
761         DWORD dwBytesReturned;
762
763         if (hFile == INVALID_HANDLE_VALUE) {
764                 //SetLastError(CE_MODE);
765                 return FALSE;
766         }
767         if (lpErrors == NULL) {
768         DPRINT("ERROR: GetCommState() - NULL Errors pointer\n");
769                 return FALSE;
770         }
771 //      *lpErrors = CE_BREAK;
772 //      *lpErrors = CE_FRAME;
773 //      *lpErrors = CE_IOE;
774 //      *lpErrors = CE_MODE;
775 //      *lpErrors = CE_OVERRUN;
776 //      *lpErrors = CE_RXOVER;
777 //      *lpErrors = CE_RXPARITY;
778 //      *lpErrors = CE_TXFULL;
779 /*
780 CE_BREAK The hardware detected a break condition. 
781 CE_FRAME The hardware detected a framing error. 
782 CE_IOE An I/O error occurred during communications with the device. 
783 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. 
784 CE_OVERRUN A character-buffer overrun has occurred. The next character is lost. 
785 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. 
786 CE_RXPARITY The hardware detected a parity error. 
787 CE_TXFULL The application tried to transmit a character, but the output buffer was full. 
788  */
789     result = DeviceIoControl(hFile, IOCTL_SERIAL_RESET_DEVICE, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
790
791         if (lpStat != NULL) {
792                 lpStat->fCtsHold = 0;
793                 lpStat->fDsrHold = 0;
794                 lpStat->fRlsdHold = 0;
795                 lpStat->fXoffHold = 0;
796                 lpStat->fXoffSent = 0;
797                 lpStat->fEof = 0;
798                 lpStat->fTxim = 0;
799                 lpStat->cbInQue = 0;
800                 lpStat->cbOutQue = 0;
801         }
802         return TRUE;
803 }
804
805 WINBOOL
806 STDCALL
807 CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
808 {
809         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
810         return FALSE;
811 }
812
813 WINBOOL
814 STDCALL
815 CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
816 {
817         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
818         return FALSE;
819 }
820
821 WINBOOL
822 STDCALL
823 EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
824 {
825         WINBOOL result = FALSE;
826         DWORD dwBytesReturned;
827
828         if (hFile == INVALID_HANDLE_VALUE) {
829                 return FALSE;
830         }
831         switch (dwFunc) {
832     case CLRDTR: // Clears the DTR (data-terminal-ready) signal. 
833         result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
834                 break;
835     case CLRRTS: // Clears the RTS (request-to-send) signal. 
836         result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
837                 break;
838     case SETDTR: // Sends the DTR (data-terminal-ready) signal. 
839         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
840                 break;
841     case SETRTS: // Sends the RTS (request-to-send) signal. 
842         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
843                 break;
844     case SETXOFF: // Causes transmission to act as if an XOFF character has been received. 
845         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XOFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
846                 break;
847     case SETXON: // Causes transmission to act as if an XON character has been received. 
848         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
849                 break;
850     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. 
851         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
852                 break;
853     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. 
854         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
855                 break;
856         default:
857         DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
858         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
859                 break;
860         }
861         return TRUE;
862 }
863
864 WINBOOL
865 STDCALL
866 GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
867 {
868         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
869         return FALSE;
870 }
871
872 WINBOOL
873 STDCALL
874 GetCommMask(HANDLE hFile, LPDWORD lpEvtMask)
875 {
876         WINBOOL result = FALSE;
877         DWORD dwBytesReturned;
878
879         if (hFile == INVALID_HANDLE_VALUE) {
880                 return FALSE;
881         }
882     result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_WAIT_MASK, 
883                 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, NULL);
884         return TRUE;
885 }
886
887 WINBOOL
888 STDCALL
889 GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
890 {
891         WINBOOL result = FALSE;
892         DWORD dwBytesReturned;
893
894         if (hFile == INVALID_HANDLE_VALUE) {
895                 return FALSE;
896         }
897         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
898                 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
899         return TRUE;
900 }
901
902 WINBOOL
903 STDCALL
904 GetCommProperties(HANDLE hFile, LPCOMMPROP lpCommProp)
905 {
906         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
907         return FALSE;
908 }
909
910 WINBOOL
911 STDCALL
912 GetCommState(HANDLE hFile, LPDCB lpDCB)
913 {
914         WINBOOL result = FALSE;
915         DWORD dwBytesReturned;
916
917         SERIAL_BAUD_RATE BaudRate;
918         SERIAL_HANDFLOW HandFlow;
919         SERIAL_CHARS SpecialChars;
920         SERIAL_LINE_CONTROL LineControl;
921
922     DPRINT("GetCommState(%d, %p)\n", hFile, lpDCB);
923
924         if (hFile == INVALID_HANDLE_VALUE) {
925         DPRINT("ERROR: GetCommState() - INVALID_HANDLE_VALUE\n");
926                 return FALSE;
927         }
928         if (lpDCB == NULL) {
929         DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
930                 return FALSE;
931         }
932         if (lpDCB->DCBlength != sizeof(DCB)) {
933         DPRINT("ERROR: GetCommState() - Invalid DCB size\n");
934                 return FALSE;
935         }
936
937 //    DPRINT("    GetCommState() CALLING DeviceIoControl\n");
938 //    result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
939 //    DPRINT("    GetCommState() DeviceIoControl returned %d\n", result);
940
941         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_BAUD_RATE,
942                          NULL, 0, &BaudRate, sizeof(BaudRate),&dwBytesReturned, NULL);
943         if (!NT_SUCCESS(result)) {
944         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n");
945                 return FALSE;
946         }
947     lpDCB->BaudRate = BaudRate.BaudRate;
948
949         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_HANDFLOW,
950                         NULL, 0, &HandFlow, sizeof(HandFlow), &dwBytesReturned, NULL);
951         if (!NT_SUCCESS(result)) {
952         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n");
953                 return FALSE;
954         }
955         if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
956         lpDCB->fOutxCtsFlow = 1;
957         }
958     if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
959         lpDCB->fOutxDsrFlow = 1;
960         }
961     if (HandFlow.ControlHandShake & SERIAL_DTR_CONTROL) {
962         lpDCB->fDtrControl = 1;
963         }
964     if (HandFlow.ControlHandShake & SERIAL_DTR_HANDSHAKE) {
965         lpDCB->fDtrControl = 2;
966         }
967     if (HandFlow.ControlHandShake & SERIAL_RTS_CONTROL) {
968         lpDCB->fRtsControl = 1;
969         }
970     if (HandFlow.ControlHandShake & SERIAL_RTS_HANDSHAKE) {
971         lpDCB->fRtsControl = 2;
972         }
973     if (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {
974         lpDCB->fDsrSensitivity = 1;
975         }
976     if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
977         lpDCB->fAbortOnError = 1;
978         }
979
980     if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
981         lpDCB->fErrorChar = 1;
982         }
983     if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) {
984         lpDCB->fNull = 1;
985         }
986     if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) {
987         lpDCB->fTXContinueOnXoff = 1;
988         }
989     lpDCB->XonLim = HandFlow.XonLimit;
990     lpDCB->XoffLim = HandFlow.XoffLimit;
991
992         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_CHARS,
993                         NULL, 0, &SpecialChars, sizeof(SpecialChars), &dwBytesReturned, NULL);
994         if (!NT_SUCCESS(result)) {
995         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n");
996                 return FALSE;
997         }
998
999     lpDCB->EofChar = SpecialChars.EofChar;
1000     lpDCB->ErrorChar = SpecialChars.ErrorChar;
1001     // = SpecialChars.BreakChar;
1002     lpDCB->EvtChar = SpecialChars.EventChar;
1003     lpDCB->XonChar = SpecialChars.XonChar;
1004     lpDCB->XoffChar = SpecialChars.XoffChar;
1005
1006         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_LINE_CONTROL,
1007                         NULL, 0, &LineControl, sizeof(LineControl), &dwBytesReturned, NULL);
1008         if (!NT_SUCCESS(result)) {
1009         DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n");
1010                 return FALSE;
1011         }
1012         lpDCB->StopBits = LineControl.StopBits;
1013         lpDCB->Parity = LineControl.Parity;
1014         lpDCB->ByteSize = LineControl.WordLength;
1015     DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1016         return TRUE;
1017 }
1018
1019 WINBOOL
1020 STDCALL
1021 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1022 {
1023         WINBOOL result = FALSE;
1024         DWORD dwBytesReturned;
1025
1026         if (hFile == INVALID_HANDLE_VALUE) {
1027                 return FALSE;
1028         }
1029         if (lpCommTimeouts == NULL) {
1030                 return FALSE;
1031         }
1032         result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_TIMEOUTS,
1033                                                          NULL, 0, 
1034                                                          lpCommTimeouts, sizeof(COMMTIMEOUTS), 
1035                                                          &dwBytesReturned, NULL);
1036         return TRUE;
1037 }
1038
1039 WINBOOL
1040 STDCALL
1041 GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1042 {
1043         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1044         return FALSE;
1045 }
1046
1047 WINBOOL
1048 STDCALL
1049 GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
1050 {
1051         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1052         return FALSE;
1053 }
1054
1055 WINBOOL
1056 STDCALL
1057 PurgeComm(HANDLE hFile, DWORD dwFlags)
1058 {
1059         WINBOOL result = FALSE;
1060         DWORD dwBytesReturned;
1061
1062         if (hFile == INVALID_HANDLE_VALUE) {
1063                 return FALSE;
1064         }
1065     result = DeviceIoControl(hFile, IOCTL_SERIAL_PURGE, 
1066                 &dwFlags, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1067         return TRUE;
1068 }
1069
1070 WINBOOL
1071 STDCALL
1072 SetCommBreak(HANDLE hFile)
1073 {
1074         WINBOOL result = FALSE;
1075         DWORD dwBytesReturned;
1076
1077         if (hFile == INVALID_HANDLE_VALUE) {
1078                 return FALSE;
1079         }
1080     result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
1081         return TRUE;
1082 }
1083
1084 WINBOOL
1085 STDCALL
1086 SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize)
1087 {
1088         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1089         return FALSE;
1090 }
1091
1092 WINBOOL
1093 STDCALL
1094 SetCommMask(HANDLE hFile, DWORD dwEvtMask)
1095 {
1096         WINBOOL result = FALSE;
1097         DWORD dwBytesReturned;
1098
1099         if (hFile == INVALID_HANDLE_VALUE) {
1100                 return FALSE;
1101         }
1102     result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_WAIT_MASK, 
1103                 &dwEvtMask, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL);
1104         return TRUE;
1105 }
1106
1107 WINBOOL
1108 STDCALL
1109 SetCommState(HANDLE     hFile, LPDCB lpDCB)
1110 {
1111         WINBOOL result = FALSE;
1112         DWORD dwBytesReturned;
1113
1114         SERIAL_BAUD_RATE BaudRate;
1115         SERIAL_HANDFLOW HandFlow;
1116         SERIAL_CHARS SpecialChars;
1117         SERIAL_LINE_CONTROL LineControl;
1118
1119     DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile, lpDCB);
1120
1121         if (hFile == INVALID_HANDLE_VALUE) {
1122         DPRINT("SetCommState() - ERROR: INVALID_HANDLE_VALUE\n");
1123                 return FALSE;
1124         }
1125         if (lpDCB == NULL) {
1126         DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
1127                 return FALSE;
1128         }
1129
1130         BaudRate.BaudRate = lpDCB->BaudRate;
1131         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BAUD_RATE,
1132                 &BaudRate, sizeof(BaudRate), NULL, 0, &dwBytesReturned, NULL);
1133         if (!NT_SUCCESS(result)) {
1134         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n");
1135                 return FALSE;
1136         }
1137 /*
1138 #define SERIAL_DTR_MASK           ((ULONG)0x03)
1139 #define SERIAL_DTR_CONTROL        ((ULONG)0x01)
1140 #define SERIAL_DTR_HANDSHAKE      ((ULONG)0x02)
1141 #define SERIAL_CTS_HANDSHAKE      ((ULONG)0x08)
1142 #define SERIAL_DSR_HANDSHAKE      ((ULONG)0x10)
1143 #define SERIAL_DCD_HANDSHAKE      ((ULONG)0x20)
1144 #define SERIAL_OUT_HANDSHAKEMASK  ((ULONG)0x38)
1145 #define SERIAL_DSR_SENSITIVITY    ((ULONG)0x40)
1146 #define SERIAL_ERROR_ABORT        ((ULONG)0x80000000)
1147 #define SERIAL_CONTROL_INVALID    ((ULONG)0x7fffff84)
1148  */
1149     HandFlow.ControlHandShake = 0;
1150
1151         if (lpDCB->fOutxCtsFlow) {
1152         HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
1153         }
1154         if (lpDCB->fOutxDsrFlow) {
1155         HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
1156         }
1157         if (lpDCB->fDtrControl) {
1158         HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL;
1159         }
1160         if (lpDCB->fDtrControl) {
1161         HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
1162         }
1163         if (lpDCB->fRtsControl) {
1164         HandFlow.ControlHandShake |= SERIAL_RTS_CONTROL;
1165         }
1166         if (lpDCB->fRtsControl) {
1167         HandFlow.ControlHandShake |= SERIAL_RTS_HANDSHAKE;
1168         }
1169         if (lpDCB->fDsrSensitivity) {
1170         HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
1171         }
1172         if (lpDCB->fAbortOnError) {
1173         HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT;
1174         }
1175 /*
1176 #define SERIAL_AUTO_TRANSMIT      ((ULONG)0x01)
1177 #define SERIAL_AUTO_RECEIVE       ((ULONG)0x02)
1178 #define SERIAL_ERROR_CHAR         ((ULONG)0x04)
1179 #define SERIAL_NULL_STRIPPING     ((ULONG)0x08)
1180 #define SERIAL_BREAK_CHAR         ((ULONG)0x10)
1181 #define SERIAL_RTS_MASK           ((ULONG)0xc0)
1182 #define SERIAL_RTS_CONTROL        ((ULONG)0x40)
1183 #define SERIAL_RTS_HANDSHAKE      ((ULONG)0x80)
1184 #define SERIAL_TRANSMIT_TOGGLE    ((ULONG)0xc0)
1185 #define SERIAL_XOFF_CONTINUE      ((ULONG)0x80000000)
1186 #define SERIAL_FLOW_INVALID       ((ULONG)0x7fffff20)
1187  */
1188     HandFlow.FlowReplace = 0;
1189         if (lpDCB->fErrorChar) {
1190         HandFlow.FlowReplace |= SERIAL_ERROR_CHAR;
1191         }
1192         if (lpDCB->fNull) {
1193         HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING;
1194         }
1195         if (lpDCB->fTXContinueOnXoff) {
1196         HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE;
1197         }
1198     HandFlow.XonLimit = lpDCB->XonLim;
1199     HandFlow.XoffLimit = lpDCB->XoffLim;
1200         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_HANDFLOW,
1201                 &HandFlow, sizeof(HandFlow), NULL, 0, &dwBytesReturned, NULL);
1202         if (!NT_SUCCESS(result)) {
1203         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n");
1204                 return FALSE;
1205         }
1206
1207     SpecialChars.EofChar = lpDCB->EofChar;
1208     SpecialChars.ErrorChar = lpDCB->ErrorChar;
1209     SpecialChars.BreakChar = 0;
1210     SpecialChars.EventChar = lpDCB->EvtChar;
1211     SpecialChars.XonChar = lpDCB->XonChar;
1212     SpecialChars.XoffChar = lpDCB->XoffChar;
1213         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_CHARS,
1214                 &SpecialChars, sizeof(SpecialChars), NULL, 0, &dwBytesReturned, NULL);
1215         if (!NT_SUCCESS(result)) {
1216         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n");
1217                 return FALSE;
1218         }
1219
1220         LineControl.StopBits = lpDCB->StopBits;
1221         LineControl.Parity = lpDCB->Parity;
1222         LineControl.WordLength = lpDCB->ByteSize;
1223         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_LINE_CONTROL,
1224                 &LineControl, sizeof(LineControl), NULL, 0, &dwBytesReturned, NULL);
1225         if (!NT_SUCCESS(result)) {
1226         DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n");
1227                 return FALSE;
1228         }
1229
1230     DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1231         return TRUE;
1232 }
1233
1234 WINBOOL
1235 STDCALL
1236 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1237 {
1238         WINBOOL result = FALSE;
1239         DWORD dwBytesReturned;
1240         SERIAL_TIMEOUTS Timeouts;
1241
1242         if (hFile == INVALID_HANDLE_VALUE) {
1243                 return FALSE;
1244         }
1245         if (lpCommTimeouts == NULL) {
1246                 return FALSE;
1247         }
1248         Timeouts.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout;
1249         Timeouts.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier;
1250         Timeouts.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant;
1251         Timeouts.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier;
1252         Timeouts.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant;
1253         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_TIMEOUTS,
1254                 &Timeouts, sizeof(Timeouts), NULL, 0, &dwBytesReturned, NULL);
1255         return TRUE;
1256 }
1257
1258 WINBOOL
1259 STDCALL
1260 SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1261 {
1262         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1263         return FALSE;
1264 }
1265
1266 WINBOOL
1267 STDCALL
1268 SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize)
1269 {
1270         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1271         return FALSE;
1272 }
1273
1274 WINBOOL
1275 STDCALL
1276 SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
1277 {
1278         WINBOOL result = FALSE;
1279         DWORD dwBytesReturned;
1280         SERIAL_QUEUE_SIZE QueueSize;
1281
1282         if (hFile == INVALID_HANDLE_VALUE) {
1283                 return FALSE;
1284         }
1285     QueueSize.InSize = dwInQueue;
1286     QueueSize.OutSize = dwOutQueue;
1287         result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_QUEUE_SIZE,
1288                 &QueueSize, sizeof(QueueSize), NULL, 0, &dwBytesReturned, NULL);
1289         return TRUE;
1290 }
1291
1292 WINBOOL
1293 STDCALL
1294 TransmitCommChar(HANDLE hFile, char cChar)
1295 {
1296         WINBOOL result = FALSE;
1297         DWORD dwBytesReturned;
1298
1299         if (hFile == INVALID_HANDLE_VALUE) {
1300                 return FALSE;
1301         }
1302         result = DeviceIoControl(hFile, IOCTL_SERIAL_IMMEDIATE_CHAR,
1303                 &cChar, sizeof(cChar), NULL, 0, &dwBytesReturned, NULL);
1304         return TRUE;
1305 }
1306
1307 WINBOOL
1308 STDCALL
1309 WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
1310 {
1311         WINBOOL result = FALSE;
1312         DWORD dwBytesReturned;
1313
1314         if (hFile == INVALID_HANDLE_VALUE) {
1315                 return FALSE;
1316         }
1317         if (lpEvtMask == NULL) {
1318                 return FALSE;
1319         }
1320         result = DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK,
1321                 NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, lpOverlapped);
1322         return TRUE;
1323 }
1324
1325 /* EOF */