Emanuele Aliberti <ea@reactos.com>
[reactos.git] / reactos / lib / kernel32 / misc / comm.c
1 /* $Id: comm.c,v 1.11 2004/01/23 21:16:03 ekohl Exp $
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 "../include/debug.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 { ROS_STRING_INITIALIZER(L"off"), FALSE },
235 { ROS_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 { ROS_STRING_INITIALIZER(L"hs"), DTR_CONTROL_HANDSHAKE },
342 { ROS_STRING_INITIALIZER(L"off"), DTR_CONTROL_DISABLE },
343 { ROS_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 { ROS_STRING_INITIALIZER(L"hs"), RTS_CONTROL_HANDSHAKE },
462 { ROS_STRING_INITIALIZER(L"off"), RTS_CONTROL_DISABLE },
463 { ROS_STRING_INITIALIZER(L"on"), RTS_CONTROL_ENABLE },
464 { ROS_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 { ROS_STRING_INITIALIZER(L"1"), ONESTOPBIT },
495 { ROS_STRING_INITIALIZER(L"1.5"), ONE5STOPBITS },
496 { ROS_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 ROS_STRING_INITIALIZER(_L(#__P__)), \
579 (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
580 }
581
582 /*
583 * @unimplemented
584 */
585 BOOL
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 BOOL
709 STDCALL
710 BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts)
711 {
712 NTSTATUS nErrCode;
713 BOOL 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 BOOL
738 STDCALL
739 BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
740 {
741 return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL);
742 }
743
744
745 /*
746 * @unimplemented
747 */
748 BOOL
749 STDCALL
750 BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
751 {
752 return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL);
753 }
754
755
756 /*
757 * @implemented
758 */
759 BOOL
760 STDCALL
761 ClearCommBreak(HANDLE hFile)
762 {
763 BOOL 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 BOOL
778 STDCALL
779 ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat)
780 {
781 BOOL 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 BOOL
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 BOOL
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 BOOL
855 STDCALL
856 EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
857 {
858 BOOL 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 BOOL
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 BOOL
914 STDCALL
915 GetCommMask(HANDLE hFile, LPDWORD lpEvtMask)
916 {
917 BOOL 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 BOOL
933 STDCALL
934 GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
935 {
936 BOOL 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 BOOL
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 BOOL
964 STDCALL
965 GetCommState(HANDLE hFile, LPDCB lpDCB)
966 {
967 BOOL 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 BOOL
1077 STDCALL
1078 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1079 {
1080 BOOL 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 BOOL
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 BOOL
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 BOOL
1125 STDCALL
1126 PurgeComm(HANDLE hFile, DWORD dwFlags)
1127 {
1128 BOOL 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 BOOL
1144 STDCALL
1145 SetCommBreak(HANDLE hFile)
1146 {
1147 BOOL 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 BOOL
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 BOOL
1174 STDCALL
1175 SetCommMask(HANDLE hFile, DWORD dwEvtMask)
1176 {
1177 BOOL 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 BOOL
1193 STDCALL
1194 SetCommState(HANDLE hFile, LPDCB lpDCB)
1195 {
1196 BOOL 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 BOOL
1324 STDCALL
1325 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
1326 {
1327 BOOL 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 BOOL
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 BOOL
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 BOOL
1376 STDCALL
1377 SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
1378 {
1379 BOOL 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 BOOL
1398 STDCALL
1399 TransmitCommChar(HANDLE hFile, char cChar)
1400 {
1401 BOOL 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 BOOL
1417 STDCALL
1418 WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
1419 {
1420 BOOL 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 */