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)
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
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
47 /* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */
50 static const WCHAR lpszSerialUI
[] = {
51 's','e','r','i','a','l','u','i','.','d','l','l',0 };
55 /* Pointer to a callback that handles a particular parameter */
56 typedef BOOL (*COMMDCB_PARAM_CALLBACK
)(DCB
*, COMMTIMEOUTS
*, BOOL
*, LPWSTR
*);
58 /* Symbolic flag of any length */
59 typedef struct _COMMDCB_PARAM_STRFLAG
61 UNICODE_STRING String
;
63 } COMMDCB_PARAM_STRFLAG
, *PCOMMDCB_PARAM_STRFLAG
;
65 /* One char long symbolic flag */
66 typedef struct _COMMDCB_PARAM_CHARFLAG
70 } COMMDCB_PARAM_CHARFLAG
, *PCOMMDCB_PARAM_CHARFLAG
;
74 /* Declare a parameter handler */
75 #define COMMDCB_PARAM_HANDLER(__P__) \
76 BOOL COMMDCB_ ## __P__ ## Param \
79 COMMTIMEOUTS * Timeouts, \
86 Lookup a string flag and return its numerical value. The flags array must be
87 sorted - a dichotomycal search is performed
90 COMMDCB_LookupStrFlag(PUNICODE_STRING Flag
,
91 PCOMMDCB_PARAM_STRFLAG Flags
,
95 /* Lower and upper bound for dichotomycal search */
97 int nUpperBound
= FlagCount
- 1;
102 /* pick the element in the middle of the area of interest as the pivot */
103 int nCurFlag
= nLowerBound
+ (nUpperBound
- nLowerBound
) / 2;
105 /* compare the string with the pivot */
106 nComparison
= RtlCompareUnicodeString(Flag
,
107 &Flags
[nCurFlag
].String
,
110 /* string is equal */
113 /* return the flag's value */
114 *Value
= Flags
[nCurFlag
].Value
;
119 else if(nComparison
< 0)
122 * restrict the search to the first half of the current slice, minus the pivot
124 nUpperBound
= nCurFlag
- 1;
129 * restrict the search to the second half of the current slice, minus the pivot
131 nLowerBound
= nCurFlag
+ 1;
133 } while(nLowerBound
<= nUpperBound
);
135 /* string not found: failure */
141 Find the next character flag and return its numerical value. The flags array
142 must be sorted - a dichotomycal search is performed
145 COMMDCB_ParseCharFlag(LPWSTR
*StrTail
,
146 PCOMMDCB_PARAM_CHARFLAG Flags
,
150 /* Lower and upper bound for dichotomycal search */
152 int nUpperBound
= FlagCount
- 1;
153 /* get the first character as the flag */
154 WCHAR wcFlag
= (*StrTail
)[0];
156 /* premature end of string, or the character is whitespace */
157 if(!wcFlag
|| iswspace(wcFlag
))
160 /* uppercase the character for case-insensitive search */
161 wcFlag
= towupper(wcFlag
);
163 /* skip the character flag */
166 /* see COMMDCB_LookupStrFlag for a description of the algorithm */
170 int nCurFlag
= nLowerBound
+ (nUpperBound
- nLowerBound
) / 2;
172 nComparison
= wcFlag
- towupper(Flags
[nCurFlag
].Char
);
176 *Value
= Flags
[nCurFlag
].Value
;
180 else if(nComparison
< 0)
182 nUpperBound
= nCurFlag
- 1;
186 nLowerBound
= nCurFlag
+ 1;
188 } while(nUpperBound
>= nLowerBound
);
190 /* flag not found: failure */
195 Find the next string flag and return its numerical value. The flags array must
196 be sorted - a dichotomycal search is performed
199 COMMDCB_ParseStrFlag(LPWSTR
*StrTail
,
200 PCOMMDCB_PARAM_STRFLAG Flags
,
205 UNICODE_STRING wstrFlag
;
207 /* scan the string until the first space character or the terminating null */
208 for(pwcNewTail
= *StrTail
;
209 pwcNewTail
[0] && !iswspace(pwcNewTail
[0]);
212 /* string flag empty */
213 if(pwcNewTail
== *StrTail
)
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
;
221 /* skip the string flag */
222 *StrTail
= pwcNewTail
;
224 /* lookup the string flag's value and return it */
225 return COMMDCB_LookupStrFlag(&wstrFlag
, Flags
, FlagCount
, Value
);
229 Parse a boolean value in the symbolic form on/off
232 COMMDCB_ParseBool(LPWSTR
*StrTail
,
237 static COMMDCB_PARAM_STRFLAG a_BoolFlags
[] = {
238 { RTL_CONSTANT_STRING(L
"off"), FALSE
},
239 { RTL_CONSTANT_STRING(L
"on"), TRUE
}
242 /* try to recognize the next flag as a boolean */
243 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
245 sizeof(a_BoolFlags
) / sizeof(a_BoolFlags
[0]),
253 *Value
= (nValue
? TRUE
: FALSE
);
258 Parse a decimal integer
261 COMMDCB_ParseInt(LPWSTR
*StrTail
,
264 LPWSTR pwcPrevTail
= *StrTail
;
265 DWORD nValue
= wcstoul(*StrTail
, StrTail
, 10);
267 /* no character was consumed: failure */
268 if(pwcPrevTail
== *StrTail
)
276 /* PARAMETER HANDLERS */
278 COMMDCB_PARAM_HANDLER(baud
)
284 /* parse the baudrate */
285 if(!COMMDCB_ParseInt(StrTail
, &nValue
))
290 /* documented abbreviations */
304 Dcb
->BaudRate
= 1200;
307 Dcb
->BaudRate
= 2400;
310 Dcb
->BaudRate
= 4800;
313 Dcb
->BaudRate
= 9600;
316 Dcb
->BaudRate
= 19200;
321 Dcb
->BaudRate
= nValue
;
325 /* if the stop bits haven't been specified explicitely */
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 */
333 Dcb
->StopBits
= ONESTOPBIT
;
341 COMMDCB_PARAM_HANDLER(data
)
348 /* parse the data bits */
349 if(!COMMDCB_ParseInt(StrTail
, &nValue
))
352 /* value out of range: failure */
353 if(nValue
< 5 || nValue
> 8)
357 Dcb
->ByteSize
= (BYTE
)nValue
;
362 COMMDCB_PARAM_HANDLER(dtr
)
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
}
376 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
378 sizeof(a_DTRFlags
) / sizeof(a_DTRFlags
[0]),
386 Dcb
->fDtrControl
= nValue
;
391 COMMDCB_PARAM_HANDLER(idsr
)
399 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
403 Dcb
->fDsrSensitivity
= bValue
;
408 COMMDCB_PARAM_HANDLER(octs
)
416 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
420 Dcb
->fOutxCtsFlow
= bValue
;
425 COMMDCB_PARAM_HANDLER(odsr
)
433 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
437 Dcb
->fOutxDsrFlow
= bValue
;
442 COMMDCB_PARAM_HANDLER(parity
)
446 static COMMDCB_PARAM_CHARFLAG a_ParityFlags
[] = {
447 { L
'e', EVENPARITY
},
448 { L
'm', MARKPARITY
},
451 { L
's', SPACEPARITY
}
458 bRetVal
= COMMDCB_ParseCharFlag(StrTail
,
460 sizeof(a_ParityFlags
) / sizeof(a_ParityFlags
[0]),
468 Dcb
->Parity
= (BYTE
)nValue
;
473 COMMDCB_PARAM_HANDLER(rts
)
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
}
488 nRetVal
= COMMDCB_ParseStrFlag(StrTail
,
490 sizeof(a_RTSFlags
) / sizeof(a_RTSFlags
[0]),
498 Dcb
->fRtsControl
= nValue
;
503 COMMDCB_PARAM_HANDLER(stop
)
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
}
516 bRetVal
= COMMDCB_ParseStrFlag(StrTail
,
518 sizeof(a_StopFlags
) / sizeof(a_StopFlags
[0]),
525 /* tell the baud= handler that the stop bits have been specified explicitely */
529 Dcb
->StopBits
= (BYTE
)nValue
;
534 COMMDCB_PARAM_HANDLER(to
)
542 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
545 /* for BuildCommDCB(), Timeouts is NULL */
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;
557 Timeouts
->WriteTotalTimeoutConstant
= 60000;
562 Timeouts
->WriteTotalTimeoutConstant
= 0;
571 COMMDCB_PARAM_HANDLER(xon
)
579 if(!COMMDCB_ParseBool(StrTail
, &bValue
))
585 Dcb
->fInX
= Dcb
->fOutX
= TRUE
;
590 Dcb
->fInX
= Dcb
->fOutX
= FALSE
;
598 #define COMMDCB_PARAM(__P__) \
600 RTL_CONSTANT_STRING(L""UNICODIZE(#__P__ )), \
601 (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \
609 BuildCommDCBAndTimeoutsW(LPCWSTR lpDef
,
611 LPCOMMTIMEOUTS lpCommTimeouts
)
613 /* tell the baud= handler that the stop bits should be defaulted */
614 BOOL bStopBitsSet
= FALSE
;
616 /* parameter validation */
617 if(lpDCB
->DCBlength
!= sizeof(DCB
))
621 lpDCB
->StopBits
= ONESTOPBIT
;
624 * The documentation for MODE says that data= defaults to 7, but BuildCommDCB
625 * doesn't seem to set it
627 /* lpDCB->ByteSize = 7; */
631 towupper(lpDef
[0]) == L
'C' &&
633 towupper(lpDef
[1]) == L
'O' &&
635 towupper(lpDef
[2]) == L
'M')
642 /* premature end of string */
647 if(!COMMDCB_ParseInt((LPWSTR
*)&lpDef
, &nDummy
))
655 /* skip leading whitespace */
656 while(lpDef
[0] && iswspace(lpDef
[0]))
659 /* repeat until the end of the string */
662 static COMMDCB_PARAM_STRFLAG a_Params
[] = {
669 COMMDCB_PARAM(parity
),
676 COMMDCB_PARAM_CALLBACK pCallback
;
677 UNICODE_STRING wstrParam
;
678 LPWSTR pwcPrevTail
= (LPWSTR
)lpDef
;
680 /* get the parameter */
681 while(lpDef
[0] && lpDef
[0] != L
'=')
684 /* premature end of string */
688 /* build the parameter's UNICODE_STRING */
689 wstrParam
.Buffer
= pwcPrevTail
;
690 wstrParam
.Length
= (lpDef
- pwcPrevTail
) * sizeof(WCHAR
);
691 wstrParam
.MaximumLength
= wstrParam
.Length
;
696 /* lookup the callback for the parameter */
697 bRetVal
= COMMDCB_LookupStrFlag(&wstrParam
,
699 sizeof(a_Params
) / sizeof(a_Params
[0]),
700 (ULONG_PTR
*)&pCallback
);
702 /* invalid parameter */
706 /* call the callback to parse the parameter's argument */
707 if(!pCallback(lpDCB
, lpCommTimeouts
, &bStopBitsSet
, (LPWSTR
*)&lpDef
))
710 /* skip trailing whitespace */
711 while(lpDef
[0] && iswspace(lpDef
[0]))
719 SetLastError(ERROR_INVALID_PARAMETER
);
729 BuildCommDCBAndTimeoutsA(LPCSTR lpDef
,
731 LPCOMMTIMEOUTS lpCommTimeouts
)
736 UNICODE_STRING wstrDef
;
738 RtlInitAnsiString(&strDef
, (LPSTR
)lpDef
);
740 Status
= RtlAnsiStringToUnicodeString(&wstrDef
, &strDef
, TRUE
);
742 if(!NT_SUCCESS(Status
))
744 SetLastErrorByStatus(Status
);
748 bRetVal
= BuildCommDCBAndTimeoutsW(wstrDef
.Buffer
, lpDCB
, lpCommTimeouts
);
750 RtlFreeUnicodeString(&wstrDef
);
760 BuildCommDCBA(LPCSTR lpDef
, LPDCB lpDCB
)
762 return BuildCommDCBAndTimeoutsA(lpDef
, lpDCB
, NULL
);
771 BuildCommDCBW(LPCWSTR lpDef
, LPDCB lpDCB
)
773 return BuildCommDCBAndTimeoutsW(lpDef
, lpDCB
, NULL
);
782 ClearCommBreak(HANDLE hFile
)
784 DWORD dwBytesReturned
;
785 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_OFF
,
786 NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
795 ClearCommError(HANDLE hFile
, LPDWORD lpErrors
, LPCOMSTAT lpComStat
)
798 DWORD dwBytesReturned
;
799 SERIAL_STATUS SerialStatus
;
801 status
= DeviceIoControl(hFile
, IOCTL_SERIAL_GET_COMMSTATUS
, NULL
, 0,
802 &SerialStatus
, sizeof(SERIAL_STATUS
), &dwBytesReturned
, NULL
);
804 if(!NT_SUCCESS(status
))
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
;
826 ZeroMemory(lpComStat
, sizeof(COMSTAT
));
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
;
839 if(SerialStatus
.EofReceived
)
840 lpComStat
->fEof
= TRUE
;
842 if(SerialStatus
.WaitForImmediate
)
843 lpComStat
->fTxim
= TRUE
;
845 lpComStat
->cbInQue
= SerialStatus
.AmountInInQueue
;
846 lpComStat
->cbOutQue
= SerialStatus
.AmountInOutQueue
;
857 CommConfigDialogA(LPCSTR lpszName
, HWND hWnd
, LPCOMMCONFIG lpCC
)
862 /* don't use the static thread buffer so operations in serialui
863 don't overwrite the string */
864 if(!(NameW
= FilenameA2W(lpszName
, TRUE
)))
869 result
= CommConfigDialogW(NameW
, hWnd
, lpCC
);
871 RtlFreeHeap(RtlGetProcessHeap(), 0, NameW
);
882 CommConfigDialogW(LPCWSTR lpszName
, HWND hWnd
, LPCOMMCONFIG lpCC
)
884 DWORD (WINAPI
*drvCommDlgW
)(LPCWSTR
, HWND
, LPCOMMCONFIG
);
885 HMODULE hSerialuiDll
;
888 //FIXME: Get dll name from registry. (setupapi needed)
889 if(!(hSerialuiDll
= LoadLibraryW(L
"serialui.dll")))
891 DPRINT("CommConfigDialogW: serialui.dll not found.\n");
895 drvCommDlgW
= (DWORD (WINAPI
*)(LPCWSTR
, HWND
, LPCOMMCONFIG
))
896 GetProcAddress(hSerialuiDll
, "drvCommConfigDialogW");
900 DPRINT("CommConfigDialogW: serialui does not export drvCommConfigDialogW\n");
901 FreeLibrary(hSerialuiDll
);
905 result
= drvCommDlgW(lpszName
, hWnd
, lpCC
);
906 SetLastError(result
);
907 FreeLibrary(hSerialuiDll
);
909 return (result
== ERROR_SUCCESS
? TRUE
: FALSE
);
918 EscapeCommFunction(HANDLE hFile
, DWORD dwFunc
)
921 DWORD dwBytesReturned
;
924 case CLRDTR
: // Clears the DTR (data-terminal-ready) signal.
925 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_CLR_DTR
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
927 case CLRRTS
: // Clears the RTS (request-to-send) signal.
928 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_CLR_RTS
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
930 case SETDTR
: // Sends the DTR (data-terminal-ready) signal.
931 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_DTR
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
933 case SETRTS
: // Sends the RTS (request-to-send) signal.
934 result
= DeviceIoControl(hFile
, IOCTL_SERIAL_SET_RTS
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
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
);
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
);
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
);
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
);
949 DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
950 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
962 GetCommConfig(HANDLE hCommDev
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
964 BOOL ReturnValue
= FALSE
;
965 LPCOMMPROP lpComPort
;
967 DPRINT("GetCommConfig(%d, %p, %p)\n", hCommDev
, lpCC
, lpdwSize
);
969 lpComPort
= RtlAllocateHeap( hProcessHeap
,
971 sizeof(COMMPROP
) + 0x100 );
973 if(NULL
== lpComPort
) {
974 DPRINT("GetCommConfig() - ERROR_NOT_ENOUGH_MEMORY\n");
975 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
979 if( (NULL
== lpdwSize
)
980 || (NULL
== lpCC
) ) {
981 DPRINT("GetCommConfig() - invalid parameter\n");
982 SetLastError(ERROR_INVALID_PARAMETER
);
987 lpComPort
->wPacketLength
= sizeof(COMMPROP
) + 0x100;
988 lpComPort
->dwProvSpec1
= COMMPROP_INITIALIZED
;
989 ReturnValue
= GetCommProperties(hCommDev
, lpComPort
);
992 lpCC
->dwSize
= sizeof(COMMCONFIG
);
995 lpCC
->dwProviderSubType
= lpComPort
->dwProvSubType
;
996 lpCC
->dwProviderSize
= lpComPort
->dwProvSpec2
;
997 if( 0 == lpComPort
->dwProvSpec2
) {
998 lpCC
->dwProviderOffset
= 0;
1000 lpCC
->dwProviderOffset
= (ULONG_PTR
)&lpCC
->wcProviderData
[0] - (ULONG_PTR
)lpCC
;
1002 if( (lpCC
->dwProviderSize
+lpCC
->dwSize
) > *lpdwSize
) {
1003 DPRINT("GetCommConfig() - ERROR_INSUFFICIENT_BUFFER\n");
1004 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1005 ReturnValue
= FALSE
;
1007 RtlCopyMemory(lpCC
->wcProviderData
, lpComPort
->wcProvChar
, lpCC
->dwProviderSize
);
1008 ReturnValue
= GetCommState(hCommDev
, &lpCC
->dcb
);
1010 *lpdwSize
= lpCC
->dwSize
+lpCC
->dwProviderSize
;
1014 RtlFreeHeap(hProcessHeap
, 0, lpComPort
);
1015 return (ReturnValue
);
1024 GetCommMask(HANDLE hFile
, LPDWORD lpEvtMask
)
1026 DWORD dwBytesReturned
;
1027 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_WAIT_MASK
,
1028 NULL
, 0, lpEvtMask
, sizeof(DWORD
), &dwBytesReturned
, NULL
);
1037 GetCommModemStatus(HANDLE hFile
, LPDWORD lpModemStat
)
1039 DWORD dwBytesReturned
;
1041 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_MODEMSTATUS
,
1042 NULL
, 0, lpModemStat
, sizeof(DWORD
), &dwBytesReturned
, NULL
);
1051 GetCommProperties(HANDLE hFile
, LPCOMMPROP lpCommProp
)
1053 DWORD dwBytesReturned
;
1054 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_PROPERTIES
, 0, 0,
1055 lpCommProp
, sizeof(COMMPROP
), &dwBytesReturned
, 0);
1064 GetCommState(HANDLE hFile
, LPDCB lpDCB
)
1066 BOOL result
= FALSE
;
1067 DWORD dwBytesReturned
;
1069 SERIAL_BAUD_RATE BaudRate
;
1070 SERIAL_HANDFLOW HandFlow
;
1071 SERIAL_CHARS SpecialChars
;
1072 SERIAL_LINE_CONTROL LineControl
;
1074 DPRINT("GetCommState(%d, %p)\n", hFile
, lpDCB
);
1076 if (lpDCB
== NULL
) {
1077 SetLastError(ERROR_INVALID_PARAMETER
);
1078 DPRINT("ERROR: GetCommState() - NULL DCB pointer\n");
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
))
1092 memset(lpDCB
, 0, sizeof(*lpDCB
));
1093 lpDCB
->DCBlength
= sizeof(*lpDCB
);
1097 lpDCB
->BaudRate
= BaudRate
.BaudRate
;
1099 lpDCB
->StopBits
= LineControl
.StopBits
;
1100 lpDCB
->Parity
= LineControl
.Parity
;
1101 lpDCB
->ByteSize
= LineControl
.WordLength
;
1103 if (HandFlow
.ControlHandShake
& SERIAL_CTS_HANDSHAKE
) {
1104 lpDCB
->fOutxCtsFlow
= 1;
1106 if (HandFlow
.ControlHandShake
& SERIAL_DSR_HANDSHAKE
) {
1107 lpDCB
->fOutxDsrFlow
= 1;
1109 if (HandFlow
.ControlHandShake
& SERIAL_DTR_CONTROL
) {
1110 lpDCB
->fDtrControl
= 1;
1112 if (HandFlow
.ControlHandShake
& SERIAL_DTR_HANDSHAKE
) {
1113 lpDCB
->fDtrControl
= 2;
1115 if (HandFlow
.ControlHandShake
& SERIAL_RTS_CONTROL
) {
1116 lpDCB
->fRtsControl
= 1;
1118 if (HandFlow
.ControlHandShake
& SERIAL_RTS_HANDSHAKE
) {
1119 lpDCB
->fRtsControl
= 2;
1121 if (HandFlow
.ControlHandShake
& SERIAL_DSR_SENSITIVITY
) {
1122 lpDCB
->fDsrSensitivity
= 1;
1124 if (HandFlow
.ControlHandShake
& SERIAL_ERROR_ABORT
) {
1125 lpDCB
->fAbortOnError
= 1;
1128 if (HandFlow
.FlowReplace
& SERIAL_ERROR_CHAR
) {
1129 lpDCB
->fErrorChar
= 1;
1131 if (HandFlow
.FlowReplace
& SERIAL_NULL_STRIPPING
) {
1134 if (HandFlow
.FlowReplace
& SERIAL_XOFF_CONTINUE
) {
1135 lpDCB
->fTXContinueOnXoff
= 1;
1137 lpDCB
->XonLim
= (WORD
)HandFlow
.XonLimit
;
1138 lpDCB
->XoffLim
= (WORD
)HandFlow
.XoffLimit
;
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");
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
;
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");
1160 lpDCB
->StopBits
= LineControl
.StopBits
;
1161 lpDCB
->Parity
= LineControl
.Parity
;
1162 lpDCB
->ByteSize
= LineControl
.WordLength
;
1163 DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n");
1173 GetCommTimeouts(HANDLE hFile
, LPCOMMTIMEOUTS lpCommTimeouts
)
1175 DWORD dwBytesReturned
;
1177 if (lpCommTimeouts
== NULL
) {
1181 return DeviceIoControl(hFile
, IOCTL_SERIAL_GET_TIMEOUTS
,
1183 lpCommTimeouts
, sizeof(COMMTIMEOUTS
),
1184 &dwBytesReturned
, NULL
);
1193 GetDefaultCommConfigW(LPCWSTR lpszName
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
1195 FARPROC pGetDefaultCommConfig
;
1196 HMODULE hConfigModule
;
1197 DWORD res
= ERROR_INVALID_PARAMETER
;
1199 DPRINT("(%s, %p, %p) *lpdwSize: %u\n", lpszName
, lpCC
, lpdwSize
, lpdwSize
? *lpdwSize
: 0 );
1200 hConfigModule
= LoadLibraryW(lpszSerialUI
);
1202 if (hConfigModule
) {
1203 pGetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvGetDefaultCommConfigW");
1204 if (pGetDefaultCommConfig
) {
1205 res
= pGetDefaultCommConfig(lpszName
, lpCC
, lpdwSize
);
1207 FreeLibrary(hConfigModule
);
1210 if (res
) SetLastError(res
);
1211 return (res
== ERROR_SUCCESS
);
1220 GetDefaultCommConfigA(LPCSTR lpszName
, LPCOMMCONFIG lpCC
, LPDWORD lpdwSize
)
1223 UNICODE_STRING lpszNameW
;
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
;
1229 ret
= GetDefaultCommConfigW(lpszNameW
.Buffer
,lpCC
,lpdwSize
);
1231 RtlFreeUnicodeString(&lpszNameW
);
1241 PurgeComm(HANDLE hFile
, DWORD dwFlags
)
1243 DWORD dwBytesReturned
;
1245 return DeviceIoControl(hFile
, IOCTL_SERIAL_PURGE
,
1246 &dwFlags
, sizeof(DWORD
), NULL
, 0, &dwBytesReturned
, NULL
);
1255 SetCommBreak(HANDLE hFile
)
1257 DWORD dwBytesReturned
;
1259 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_BREAK_ON
, NULL
, 0, NULL
, 0, &dwBytesReturned
, NULL
);
1268 SetCommConfig(HANDLE hCommDev
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1270 BOOL ReturnValue
= FALSE
;
1272 DPRINT("SetCommConfig(%d, %p, %d)\n", hCommDev
, lpCC
, dwSize
);
1276 DPRINT("SetCommConfig() - invalid parameter\n");
1277 SetLastError(ERROR_INVALID_PARAMETER
);
1278 ReturnValue
= FALSE
;
1282 ReturnValue
= SetCommState(hCommDev
, &lpCC
->dcb
);
1294 SetCommMask(HANDLE hFile
, DWORD dwEvtMask
)
1296 DWORD dwBytesReturned
;
1298 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_WAIT_MASK
,
1299 &dwEvtMask
, sizeof(DWORD
), NULL
, 0, &dwBytesReturned
, NULL
);
1308 SetCommState(HANDLE hFile
, LPDCB lpDCB
)
1310 BOOL result
= FALSE
;
1311 DWORD dwBytesReturned
;
1313 SERIAL_BAUD_RATE BaudRate
;
1314 SERIAL_HANDFLOW HandFlow
;
1315 SERIAL_CHARS SpecialChars
;
1316 SERIAL_LINE_CONTROL LineControl
;
1318 DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile
, lpDCB
);
1320 if (lpDCB
== NULL
) {
1321 DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n");
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");
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)
1344 HandFlow
.ControlHandShake
= 0;
1346 if (lpDCB
->fOutxCtsFlow
) {
1347 HandFlow
.ControlHandShake
|= SERIAL_CTS_HANDSHAKE
;
1349 if (lpDCB
->fOutxDsrFlow
) {
1350 HandFlow
.ControlHandShake
|= SERIAL_DSR_HANDSHAKE
;
1352 if (lpDCB
->fDtrControl
) {
1353 HandFlow
.ControlHandShake
|= SERIAL_DTR_CONTROL
;
1355 if (lpDCB
->fDtrControl
) {
1356 HandFlow
.ControlHandShake
|= SERIAL_DTR_HANDSHAKE
;
1358 if (lpDCB
->fRtsControl
) {
1359 HandFlow
.ControlHandShake
|= SERIAL_RTS_CONTROL
;
1361 if (lpDCB
->fRtsControl
) {
1362 HandFlow
.ControlHandShake
|= SERIAL_RTS_HANDSHAKE
;
1364 if (lpDCB
->fDsrSensitivity
) {
1365 HandFlow
.ControlHandShake
|= SERIAL_DSR_SENSITIVITY
;
1367 if (lpDCB
->fAbortOnError
) {
1368 HandFlow
.ControlHandShake
|= SERIAL_ERROR_ABORT
;
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)
1383 HandFlow
.FlowReplace
= 0;
1384 if (lpDCB
->fErrorChar
) {
1385 HandFlow
.FlowReplace
|= SERIAL_ERROR_CHAR
;
1388 HandFlow
.FlowReplace
|= SERIAL_NULL_STRIPPING
;
1390 if (lpDCB
->fTXContinueOnXoff
) {
1391 HandFlow
.FlowReplace
|= SERIAL_XOFF_CONTINUE
;
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");
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");
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");
1425 DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n");
1435 SetCommTimeouts(HANDLE hFile
, LPCOMMTIMEOUTS lpCommTimeouts
)
1437 DWORD dwBytesReturned
;
1438 SERIAL_TIMEOUTS Timeouts
;
1440 if (lpCommTimeouts
== NULL
) {
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
;
1449 return DeviceIoControl(hFile
, IOCTL_SERIAL_SET_TIMEOUTS
,
1450 &Timeouts
, sizeof(Timeouts
), NULL
, 0, &dwBytesReturned
, NULL
);
1459 SetDefaultCommConfigA(LPCSTR lpszName
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1462 LPWSTR lpDeviceW
= NULL
;
1465 DPRINT("(%s, %p, %u)\n", lpszName
, lpCC
, dwSize
);
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
);
1473 r
= SetDefaultCommConfigW(lpDeviceW
,lpCC
,dwSize
);
1474 HeapFree( GetProcessHeap(), 0, lpDeviceW
);
1484 SetDefaultCommConfigW(LPCWSTR lpszName
, LPCOMMCONFIG lpCC
, DWORD dwSize
)
1486 FARPROC pGetDefaultCommConfig
;
1487 HMODULE hConfigModule
;
1488 DWORD res
= ERROR_INVALID_PARAMETER
;
1490 DPRINT("(%s, %p, %p) *dwSize: %u\n", lpszName
, lpCC
, dwSize
, dwSize
? dwSize
: 0 );
1491 hConfigModule
= LoadLibraryW(lpszSerialUI
);
1493 if (hConfigModule
) {
1494 pGetDefaultCommConfig
= GetProcAddress(hConfigModule
, "drvGetDefaultCommConfigW");
1495 if (pGetDefaultCommConfig
) {
1496 res
= pGetDefaultCommConfig(lpszName
, lpCC
, &dwSize
);
1498 FreeLibrary(hConfigModule
);
1501 if (res
) SetLastError(res
);
1502 return (res
== ERROR_SUCCESS
);
1511 SetupComm(HANDLE hFile
, DWORD dwInQueue
, DWORD dwOutQueue
)
1513 DWORD dwBytesReturned
;
1514 SERIAL_QUEUE_SIZE QueueSize
;
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
);
1528 TransmitCommChar(HANDLE hFile
, char cChar
)
1530 DWORD dwBytesReturned
;
1531 return DeviceIoControl(hFile
, IOCTL_SERIAL_IMMEDIATE_CHAR
,
1532 &cChar
, sizeof(cChar
), NULL
, 0, &dwBytesReturned
, NULL
);
1541 WaitCommEvent(HANDLE hFile
, LPDWORD lpEvtMask
, LPOVERLAPPED lpOverlapped
)
1543 DWORD dwBytesReturned
;
1545 if (lpEvtMask
== NULL
) {
1549 return DeviceIoControl(hFile
, IOCTL_SERIAL_WAIT_ON_MASK
,
1550 NULL
, 0, lpEvtMask
, sizeof(DWORD
), &dwBytesReturned
, lpOverlapped
);