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