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