Author: hyperion Date: Fri Dec 26 16:09:38 2008 New Revision: 38362
URL: http://svn.reactos.org/svn/reactos?rev=38362&view=rev Log: modified dll/win32/kernel32/k32.h modified dll/win32/kernel32/kernel32.rbuild modified dll/win32/kernel32/misc/comm.c added dll/win32/kernel32/misc/commdcb.c Define _KERNEL32_ globally for kernel32, outside the common header file Reimplemented the whole BuildCommDCB family of APIs, deleting embarrassing code by my younger self, written almost 6 years ago. Passes the full Wine test suite, too
Added: trunk/reactos/dll/win32/kernel32/misc/commdcb.c (with props) Modified: trunk/reactos/dll/win32/kernel32/k32.h trunk/reactos/dll/win32/kernel32/kernel32.rbuild trunk/reactos/dll/win32/kernel32/misc/comm.c
Modified: trunk/reactos/dll/win32/kernel32/k32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/k32.h?re... ============================================================================== --- trunk/reactos/dll/win32/kernel32/k32.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/k32.h [iso-8859-1] Fri Dec 26 16:09:38 2008 @@ -13,7 +13,6 @@
/* PSDK/NDK Headers */ #define WIN32_NO_STATUS -#define _KERNEL32_ #include <windows.h> #include <tlhelp32.h>
Modified: trunk/reactos/dll/win32/kernel32/kernel32.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/kernel32... ============================================================================== --- trunk/reactos/dll/win32/kernel32/kernel32.rbuild [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/kernel32.rbuild [iso-8859-1] Fri Dec 26 16:09:38 2008 @@ -5,6 +5,7 @@ <include base="kernel32_base">.</include> <include base="kernel32_base">include</include> <include base="ReactOS">include/reactos/subsys</include> + <define name="_KERNEL32_" /> <define name="_DISABLE_TIDENTS" /> <define name="_WIN32_WINNT">0x0600</define> <define name="__NO_CTYPE_INLINES" /> @@ -64,6 +65,7 @@ <file>collation.c</file> <file>casemap.c</file> <file>comm.c</file> + <file>commdcb.c</file> <file>computername.c</file> <file>console.c</file> <file>dllmain.c</file>
Modified: trunk/reactos/dll/win32/kernel32/misc/comm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/com... ============================================================================== --- trunk/reactos/dll/win32/kernel32/misc/comm.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/misc/comm.c [iso-8859-1] Fri Dec 26 16:09:38 2008 @@ -17,6 +17,7 @@ * ST (05/04/2005) implemented CommConfigDialog * DP (11/06/2005) implemented GetCommConfig * DP (12/06/2005) implemented SetCommConfig + * KJK (26/12/2008) reimplemented BuildCommDCB & BuildCommDCBAndTimeouts elsewhere * */
@@ -44,735 +45,8 @@ #define NDEBUG #include <debug.h>
-/* BUILDCOMMDCB & BUILDCOMMDCBANDTIMEOUTS */ - -/* STRINGS */ -static const WCHAR lpszSerialUI[] = { +static const WCHAR lpszSerialUI[] = { 's','e','r','i','a','l','u','i','.','d','l','l',0 }; - -/* TYPES */ - -/* Pointer to a callback that handles a particular parameter */ -typedef BOOL (*COMMDCB_PARAM_CALLBACK)(DCB *, COMMTIMEOUTS *, BOOL *, LPWSTR *); - -/* Symbolic flag of any length */ -typedef struct _COMMDCB_PARAM_STRFLAG -{ - UNICODE_STRING String; - ULONG_PTR Value; -} COMMDCB_PARAM_STRFLAG, *PCOMMDCB_PARAM_STRFLAG; - -/* One char long symbolic flag */ -typedef struct _COMMDCB_PARAM_CHARFLAG -{ - WCHAR Char; - ULONG_PTR Value; -} COMMDCB_PARAM_CHARFLAG, *PCOMMDCB_PARAM_CHARFLAG; - -/* MACROS */ - -/* Declare a parameter handler */ -#define COMMDCB_PARAM_HANDLER(__P__) \ - BOOL COMMDCB_ ## __P__ ## Param \ - ( \ - DCB * Dcb, \ - COMMTIMEOUTS * Timeouts, \ - BOOL *StopBitsSet, \ - LPWSTR *StrTail \ - ) - -/* UTILITIES */ -/* - Lookup a string flag and return its numerical value. The flags array must be - sorted - a dichotomycal search is performed -*/ -static BOOL -COMMDCB_LookupStrFlag(PUNICODE_STRING Flag, - PCOMMDCB_PARAM_STRFLAG Flags, - int FlagCount, - PULONG_PTR Value) -{ - /* Lower and upper bound for dichotomycal search */ - int nLowerBound = 0; - int nUpperBound = FlagCount - 1; - - do - { - LONG nComparison; - /* pick the element in the middle of the area of interest as the pivot */ - int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2; - - /* compare the string with the pivot */ - nComparison = RtlCompareUnicodeString(Flag, - &Flags[nCurFlag].String, - TRUE); - - /* string is equal */ - if(nComparison == 0) - { - /* return the flag's value */ - *Value = Flags[nCurFlag].Value; - - /* success */ - return TRUE; - } - else if(nComparison < 0) - { - /* - * restrict the search to the first half of the current slice, minus the pivot - */ - nUpperBound = nCurFlag - 1; - } - else - { - /* - * restrict the search to the second half of the current slice, minus the pivot - */ - nLowerBound = nCurFlag + 1; - } - } while(nLowerBound <= nUpperBound); - - /* string not found: failure */ - return FALSE; -} - -/* PARSERS */ -/* - Find the next character flag and return its numerical value. The flags array - must be sorted - a dichotomycal search is performed -*/ -static BOOL -COMMDCB_ParseCharFlag(LPWSTR *StrTail, - PCOMMDCB_PARAM_CHARFLAG Flags, - int FlagCount, - PULONG_PTR Value) -{ - /* Lower and upper bound for dichotomycal search */ - int nLowerBound = 0; - int nUpperBound = FlagCount - 1; - /* get the first character as the flag */ - WCHAR wcFlag = (*StrTail)[0]; - - /* premature end of string, or the character is whitespace */ - if(!wcFlag || iswspace(wcFlag)) - return FALSE; - - /* uppercase the character for case-insensitive search */ - wcFlag = towupper(wcFlag); - - /* skip the character flag */ - (*StrTail)++; - - /* see COMMDCB_LookupStrFlag for a description of the algorithm */ - do - { - LONG nComparison; - int nCurFlag = nLowerBound + (nUpperBound - nLowerBound) / 2; - - nComparison = wcFlag - towupper(Flags[nCurFlag].Char); - - if(nComparison == 0) - { - *Value = Flags[nCurFlag].Value; - - return TRUE; - } - else if(nComparison < 0) - { - nUpperBound = nCurFlag - 1; - } - else - { - nLowerBound = nCurFlag + 1; - } - } while(nUpperBound >= nLowerBound); - - /* flag not found: failure */ - return FALSE; -} - -/* - Find the next string flag and return its numerical value. The flags array must - be sorted - a dichotomycal search is performed -*/ -static BOOL -COMMDCB_ParseStrFlag(LPWSTR *StrTail, - PCOMMDCB_PARAM_STRFLAG Flags, - int FlagCount, - PULONG_PTR Value) -{ - LPWSTR pwcNewTail; - UNICODE_STRING wstrFlag; - - /* scan the string until the first space character or the terminating null */ - for(pwcNewTail = *StrTail; - pwcNewTail[0] && !iswspace(pwcNewTail[0]); - pwcNewTail++); - - /* string flag empty */ - if(pwcNewTail == *StrTail) - return FALSE; - - /* build the UNICODE_STRING description of the string flag */ - wstrFlag.Buffer = *StrTail; - wstrFlag.Length = (pwcNewTail - *StrTail) * sizeof(WCHAR); - wstrFlag.MaximumLength = wstrFlag.Length; - - /* skip the string flag */ - *StrTail = pwcNewTail; - - /* lookup the string flag's value and return it */ - return COMMDCB_LookupStrFlag(&wstrFlag, Flags, FlagCount, Value); -} - -/* - Parse a boolean value in the symbolic form on/off -*/ -static BOOL -COMMDCB_ParseBool(LPWSTR *StrTail, - PBOOL Value) -{ - BOOL bRetVal; - ULONG_PTR nValue; - static COMMDCB_PARAM_STRFLAG a_BoolFlags[] = { - { RTL_CONSTANT_STRING(L"off"), FALSE }, - { RTL_CONSTANT_STRING(L"on"), TRUE } - }; - - /* try to recognize the next flag as a boolean */ - bRetVal = COMMDCB_ParseStrFlag(StrTail, - a_BoolFlags, - sizeof(a_BoolFlags) / sizeof(a_BoolFlags[0]), - &nValue); - - - if(!bRetVal) - return FALSE; - - /* success */ - *Value = (nValue ? TRUE : FALSE); - return TRUE; -} - -/* - Parse a decimal integer -*/ -static BOOL -COMMDCB_ParseInt(LPWSTR *StrTail, - DWORD *Value) -{ - LPWSTR pwcPrevTail = *StrTail; - DWORD nValue = wcstoul(*StrTail, StrTail, 10); - - /* no character was consumed: failure */ - if(pwcPrevTail == *StrTail) - return FALSE; - - /* success */ - *Value = nValue; - return TRUE; -} - -/* PARAMETER HANDLERS */ -/* baud= */ -COMMDCB_PARAM_HANDLER(baud) -{ - DWORD nValue; - - (void)Timeouts; - - /* parse the baudrate */ - if(!COMMDCB_ParseInt(StrTail, &nValue)) - return FALSE; - - switch(nValue) - { - /* documented abbreviations */ - case 11: - Dcb->BaudRate = 110; - break; - case 15: - Dcb->BaudRate = 150; - break; - case 30: - Dcb->BaudRate = 300; - break; - case 60: - Dcb->BaudRate = 600; - break; - case 12: - Dcb->BaudRate = 1200; - break; - case 24: - Dcb->BaudRate = 2400; - break; - case 48: - Dcb->BaudRate = 4800; - break; - case 96: - Dcb->BaudRate = 9600; - break; - case 19: - Dcb->BaudRate = 19200; - break; - - /* literal value */ - default: - Dcb->BaudRate = nValue; - break; - } - - /* if the stop bits haven't been specified explicitely */ - if(!(*StopBitsSet)) - { - /* default the stop bits to 2 for 110 baud */ - if(Dcb->BaudRate == 110) - Dcb->StopBits = TWOSTOPBITS; - /* else, default the stop bits to 1 */ - else - Dcb->StopBits = ONESTOPBIT; - } - - /* success */ - return TRUE; -} - -/* data= */ -COMMDCB_PARAM_HANDLER(data) -{ - DWORD nValue; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the data bits */ - if(!COMMDCB_ParseInt(StrTail, &nValue)) - return FALSE; - - /* value out of range: failure */ - if(nValue < 5 || nValue > 8) - return FALSE; - - /* success */ - Dcb->ByteSize = (BYTE)nValue; - return TRUE; -} - -/* dtr= */ -COMMDCB_PARAM_HANDLER(dtr) -{ - BOOL bRetVal; - ULONG_PTR nValue; - static COMMDCB_PARAM_STRFLAG a_DTRFlags[] = { - { RTL_CONSTANT_STRING(L"hs"), DTR_CONTROL_HANDSHAKE }, - { RTL_CONSTANT_STRING(L"off"), DTR_CONTROL_DISABLE }, - { RTL_CONSTANT_STRING(L"on"), DTR_CONTROL_ENABLE } - }; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - bRetVal = COMMDCB_ParseStrFlag(StrTail, - a_DTRFlags, - sizeof(a_DTRFlags) / sizeof(a_DTRFlags[0]), - &nValue); - - /* failure */ - if(!bRetVal) - return FALSE; - - /* success */ - Dcb->fDtrControl = nValue; - return TRUE; -} - -/* idsr= */ -COMMDCB_PARAM_HANDLER(idsr) -{ - BOOL bValue; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - if(!COMMDCB_ParseBool(StrTail, &bValue)) - return FALSE; - - /* success */ - Dcb->fDsrSensitivity = bValue; - return TRUE; -} - -/* octs= */ -COMMDCB_PARAM_HANDLER(octs) -{ - BOOL bValue; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - if(!COMMDCB_ParseBool(StrTail, &bValue)) - return FALSE; - - /* success */ - Dcb->fOutxCtsFlow = bValue; - return TRUE; -} - -/* odsr= */ -COMMDCB_PARAM_HANDLER(odsr) -{ - BOOL bValue; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - if(!COMMDCB_ParseBool(StrTail, &bValue)) - return FALSE; - - /* success */ - Dcb->fOutxDsrFlow = bValue; - return TRUE; -} - -/* parity= */ -COMMDCB_PARAM_HANDLER(parity) -{ - BOOL bRetVal; - ULONG_PTR nValue; - static COMMDCB_PARAM_CHARFLAG a_ParityFlags[] = { - { L'e', EVENPARITY }, - { L'm', MARKPARITY }, - { L'n', NOPARITY }, - { L'o', ODDPARITY }, - { L's', SPACEPARITY } - }; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - bRetVal = COMMDCB_ParseCharFlag(StrTail, - a_ParityFlags, - sizeof(a_ParityFlags) / sizeof(a_ParityFlags[0]), - &nValue); - - /* failure */ - if(!bRetVal) - return FALSE; - - /* success */ - Dcb->Parity = (BYTE)nValue; - return TRUE; -} - -/* rts= */ -COMMDCB_PARAM_HANDLER(rts) -{ - DWORD nRetVal; - ULONG_PTR nValue; - static COMMDCB_PARAM_STRFLAG a_RTSFlags[] = { - { RTL_CONSTANT_STRING(L"hs"), RTS_CONTROL_HANDSHAKE }, - { RTL_CONSTANT_STRING(L"off"), RTS_CONTROL_DISABLE }, - { RTL_CONSTANT_STRING(L"on"), RTS_CONTROL_ENABLE }, - { RTL_CONSTANT_STRING(L"tg"), RTS_CONTROL_TOGGLE } - }; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - nRetVal = COMMDCB_ParseStrFlag(StrTail, - a_RTSFlags, - sizeof(a_RTSFlags) / sizeof(a_RTSFlags[0]), - &nValue); - - /* failure */ - if(!nRetVal) - return FALSE; - - /* success */ - Dcb->fRtsControl = nValue; - return TRUE; -} - -/* stop= */ -COMMDCB_PARAM_HANDLER(stop) -{ - BOOL bRetVal; - ULONG_PTR nValue; - static COMMDCB_PARAM_STRFLAG a_StopFlags[] = { - { RTL_CONSTANT_STRING(L"1"), ONESTOPBIT }, - { RTL_CONSTANT_STRING(L"1.5"), ONE5STOPBITS }, - { RTL_CONSTANT_STRING(L"2"), TWOSTOPBITS } - }; - - (void)Timeouts; - - /* parse the flag */ - bRetVal = COMMDCB_ParseStrFlag(StrTail, - a_StopFlags, - sizeof(a_StopFlags) / sizeof(a_StopFlags[0]), - &nValue); - - /* failure */ - if(!bRetVal) - return FALSE; - - /* tell the baud= handler that the stop bits have been specified explicitely */ - *StopBitsSet = TRUE; - - /* success */ - Dcb->StopBits = (BYTE)nValue; - return TRUE; -} - -/* to= */ -COMMDCB_PARAM_HANDLER(to) -{ - BOOL bValue; - - (void)Dcb; - (void)StopBitsSet; - - /* parse the flag */ - if(!COMMDCB_ParseBool(StrTail, &bValue)) - return FALSE; - - /* for BuildCommDCB(), Timeouts is NULL */ - if(Timeouts) - { - /* why? no idea. All values taken from Windows 2000 with experimentation */ - Timeouts->ReadIntervalTimeout = 0; - Timeouts->ReadTotalTimeoutMultiplier = 0; - Timeouts->ReadTotalTimeoutConstant = 0; - Timeouts->WriteTotalTimeoutMultiplier = 0; - - if(bValue) - { - /* timeout */ - Timeouts->WriteTotalTimeoutConstant = 60000; - } - else - { - /* no timeout */ - Timeouts->WriteTotalTimeoutConstant = 0; - } - } - - /* success */ - return TRUE; -} - -/* xon= */ -COMMDCB_PARAM_HANDLER(xon) -{ - BOOL bValue; - - (void)Timeouts; - (void)StopBitsSet; - - /* parse the flag */ - if(!COMMDCB_ParseBool(StrTail, &bValue)) - return FALSE; - - if(bValue) - { - /* XON/XOFF */ - Dcb->fInX = Dcb->fOutX = TRUE; - } - else - { - /* no XON/XOFF */ - Dcb->fInX = Dcb->fOutX = FALSE; - } - - /* success */ - return TRUE; -} - -/* FUNCTIONS */ -#define COMMDCB_PARAM(__P__) \ - { \ - RTL_CONSTANT_STRING(L""UNICODIZE(#__P__ )), \ - (ULONG_PTR)&COMMDCB_ ## __P__ ## Param \ - } - -/* - * @implemented - */ -BOOL -WINAPI -BuildCommDCBAndTimeoutsW(LPCWSTR lpDef, - LPDCB lpDCB, - LPCOMMTIMEOUTS lpCommTimeouts) -{ - /* tell the baud= handler that the stop bits should be defaulted */ - BOOL bStopBitsSet = FALSE; - - /* parameter validation */ - if(lpDCB->DCBlength != sizeof(DCB)) - goto InvalidParam; - - /* set defaults */ - lpDCB->StopBits = ONESTOPBIT; - - /* - * The documentation for MODE says that data= defaults to 7, but BuildCommDCB - * doesn't seem to set it - */ - /* lpDCB->ByteSize = 7; */ - - /* skip COMx[n] */ - if(lpDef[0] && - towupper(lpDef[0]) == L'C' && - lpDef[1] && - towupper(lpDef[1]) == L'O' && - lpDef[2] && - towupper(lpDef[2]) == L'M') - { - DWORD nDummy; - - /* skip "COM" */ - lpDef += 3; - - /* premature end of string */ - if(!lpDef[0]) - goto InvalidParam; - - /* skip "x" */ - if(!COMMDCB_ParseInt((LPWSTR *)&lpDef, &nDummy)) - goto InvalidParam; - - /* skip ":" */ - if(lpDef[0] == L':') - lpDef++; - } - - /* skip leading whitespace */ - while(lpDef[0] && iswspace(lpDef[0])) - lpDef++; - - /* repeat until the end of the string */ - while(lpDef[0]) - { - static COMMDCB_PARAM_STRFLAG a_Params[] = { - COMMDCB_PARAM(baud), - COMMDCB_PARAM(data), - COMMDCB_PARAM(dtr), - COMMDCB_PARAM(idsr), - COMMDCB_PARAM(octs), - COMMDCB_PARAM(odsr), - COMMDCB_PARAM(parity), - COMMDCB_PARAM(rts), - COMMDCB_PARAM(stop), - COMMDCB_PARAM(to), - COMMDCB_PARAM(xon) - }; - BOOL bRetVal; - COMMDCB_PARAM_CALLBACK pCallback; - UNICODE_STRING wstrParam; - LPWSTR pwcPrevTail = (LPWSTR)lpDef; - - /* get the parameter */ - while(lpDef[0] && lpDef[0] != L'=') - lpDef++; - - /* premature end of string */ - if(!lpDef[0]) - goto InvalidParam; - - /* build the parameter's UNICODE_STRING */ - wstrParam.Buffer = pwcPrevTail; - wstrParam.Length = (lpDef - pwcPrevTail) * sizeof(WCHAR); - wstrParam.MaximumLength = wstrParam.Length; - - /* skip the "=" */ - lpDef++; - - /* lookup the callback for the parameter */ - bRetVal = COMMDCB_LookupStrFlag(&wstrParam, - a_Params, - sizeof(a_Params) / sizeof(a_Params[0]), - (ULONG_PTR *)&pCallback); - - /* invalid parameter */ - if(!bRetVal) - goto InvalidParam; - - /* call the callback to parse the parameter's argument */ - if(!pCallback(lpDCB, lpCommTimeouts, &bStopBitsSet, (LPWSTR *)&lpDef)) - goto InvalidParam; - - /* skip trailing whitespace */ - while(lpDef[0] && iswspace(lpDef[0])) - lpDef++; - } - - /* success */ - return TRUE; - -InvalidParam: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; -} - - -/* - * @implemented - */ -BOOL -WINAPI -BuildCommDCBAndTimeoutsA(LPCSTR lpDef, - LPDCB lpDCB, - LPCOMMTIMEOUTS lpCommTimeouts) -{ - NTSTATUS Status; - BOOL bRetVal; - ANSI_STRING strDef; - UNICODE_STRING wstrDef; - - RtlInitAnsiString(&strDef, (LPSTR)lpDef); - - Status = RtlAnsiStringToUnicodeString(&wstrDef, &strDef, TRUE); - - if(!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - bRetVal = BuildCommDCBAndTimeoutsW(wstrDef.Buffer, lpDCB, lpCommTimeouts); - - RtlFreeUnicodeString(&wstrDef); - - return bRetVal; -} - -/* - * @implemented - */ -BOOL -WINAPI -BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB) -{ - return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL); -} - - -/* - * @implemented - */ -BOOL -WINAPI -BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB) -{ - return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL); -} -
/* * @implemented @@ -905,7 +179,7 @@ result = drvCommDlgW(lpszName, hWnd, lpCC); SetLastError(result); FreeLibrary(hSerialuiDll); - + return (result == ERROR_SUCCESS ? TRUE : FALSE); }
@@ -976,7 +250,7 @@ return FALSE; }
- if( (NULL == lpdwSize) + if( (NULL == lpdwSize) || (NULL == lpCC) ) { DPRINT("GetCommConfig() - invalid parameter\n"); SetLastError(ERROR_INVALID_PARAMETER);
Added: trunk/reactos/dll/win32/kernel32/misc/commdcb.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/misc/com... ============================================================================== --- trunk/reactos/dll/win32/kernel32/misc/commdcb.c (added) +++ trunk/reactos/dll/win32/kernel32/misc/commdcb.c [iso-8859-1] Fri Dec 26 16:09:38 2008 @@ -1,0 +1,673 @@ +/* + Copyright (c) 2008 KJK::Hyperion + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Parses a mode string for a serial port, in the same syntax as the mode.com command */ + +#if defined(__REACTOS__) && defined(_KERNEL32_) +#include <k32.h> + +#define DCB_BuildCommDCBA BuildCommDCBA +#define DCB_BuildCommDCBAndTimeoutsA BuildCommDCBAndTimeoutsA +#define DCB_BuildCommDCBW BuildCommDCBW +#define DCB_BuildCommDCBAndTimeoutsW BuildCommDCBAndTimeoutsW +#else +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +static +void DCB_SkipSpace(const char ** ppTail) +{ + while(**ppTail && isspace(**ppTail)) + ++ *ppTail; +} + +static +size_t DCB_SkipNonSpace(const char ** ppTail) +{ + const char * pOriginal = *ppTail; + + while(**ppTail && !isspace(**ppTail)) + ++ *ppTail; + + return *ppTail - pOriginal; +} + +static +BOOL DCB_SetBaudRate(unsigned long baudRate, LPDCB lpDCB) +{ + switch(baudRate) + { + case 11: lpDCB->BaudRate = 110; break; + case 15: lpDCB->BaudRate = 150; break; + case 30: lpDCB->BaudRate = 300; break; + case 60: lpDCB->BaudRate = 600; break; + case 12: lpDCB->BaudRate = 1200; break; + case 24: lpDCB->BaudRate = 2400; break; + case 48: lpDCB->BaudRate = 4800; break; + case 96: lpDCB->BaudRate = 9600; break; + case 19: lpDCB->BaudRate = 19200; break; + default: lpDCB->BaudRate = baudRate; break; + } + + return TRUE; +} + +static +BYTE DCB_SetParity(char parity, LPDCB lpDCB) +{ + switch(parity) + { + case 'N': + case 'n': + lpDCB->Parity = 0; + break; + + case 'O': + case 'o': + lpDCB->Parity = 1; + break; + + case 'E': + case 'e': + lpDCB->Parity = 2; + break; + + case 'M': + case 'm': + lpDCB->Parity = 3; + break; + + case 'S': + case 's': + lpDCB->Parity = 4; + break; + + default: + return FALSE; + } + + return TRUE; +} + +static +BYTE DCB_SetDataBits(unsigned long dataBits, LPDCB lpDCB) +{ + BOOL bRet; + + bRet = dataBits >= 5 && dataBits <= 8; + + if(!bRet) + return bRet; + + lpDCB->ByteSize = (BYTE)dataBits; + return bRet; +} + +static +BOOL DCB_ParseOldSeparator(const char ** ppTail) +{ + BOOL bRet; + + bRet = **ppTail == 0; + + if(bRet) + return bRet; + + bRet = **ppTail == ','; + + if(bRet) + { + ++ *ppTail; + return bRet; + } + + return bRet; +} + +static +unsigned long DCB_ParseOldNumber(const char ** ppTail, unsigned long nDefault) +{ + char * pNumTail; + unsigned long number; + + DCB_SkipSpace(ppTail); + + if(!isdigit(**ppTail)) + return nDefault; + + number = strtoul(*ppTail, &pNumTail, 10); + *ppTail = pNumTail; + + DCB_SkipSpace(ppTail); + return number; +} + +static +char DCB_ParseOldCharacter(const char ** ppTail, char cDefault) +{ + char character; + + DCB_SkipSpace(ppTail); + + if(**ppTail == 0 || **ppTail == ',') + return cDefault; + + character = **ppTail; + ++ *ppTail; + + DCB_SkipSpace(ppTail); + return character; +} + +static +const char * DCB_ParseOldString(const char ** ppTail, const char * pDefault, size_t * pLength) +{ + const char * string; + + DCB_SkipSpace(ppTail); + + if(**ppTail == 0 || **ppTail == ',') + return pDefault; + + string = *ppTail; + + *pLength = 0; + + while(**ppTail != 0 && **ppTail != ',' && !isspace(**ppTail)) + { + ++ *ppTail; + ++ *pLength; + } + + DCB_SkipSpace(ppTail); + return string; +} + +static +BOOL +DCB_ParseOldMode(const char * pTail, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +{ + BOOL bRet; + + unsigned long baudRate; + char parity; + unsigned long dataBits; + size_t stopBitsLength; + const char * stopBits; + char retry; + + /* Baud rate */ + baudRate = DCB_ParseOldNumber(&pTail, 0); + bRet = DCB_ParseOldSeparator(&pTail); + bRet = bRet && DCB_SetBaudRate(baudRate, lpDCB); + + if(!bRet) + return bRet; + + /* Parity */ + parity = DCB_ParseOldCharacter(&pTail, 'E'); + bRet = DCB_ParseOldSeparator(&pTail); + bRet = bRet && DCB_SetParity(parity, lpDCB); + + if(!bRet) + return bRet; + + /* Data bits */ + dataBits = DCB_ParseOldNumber(&pTail, 7); + bRet = DCB_ParseOldSeparator(&pTail); + bRet = bRet && DCB_SetDataBits(dataBits, lpDCB); + + if(!bRet) + return bRet; + + /* Stop bits */ + stopBitsLength = 1; + stopBits = DCB_ParseOldString(&pTail, baudRate == 110 ? "2" : "1", &stopBitsLength); + bRet = DCB_ParseOldSeparator(&pTail); + + if(!bRet) + return bRet; + + if(strncmp(stopBits, "1", stopBitsLength) == 0) + lpDCB->StopBits = 0; + else if(strncmp(stopBits, "1.5", stopBitsLength) == 0) + lpDCB->StopBits = 1; + else if(strncmp(stopBits, "2", stopBitsLength) == 0) + lpDCB->StopBits = 2; + else + return FALSE; + + /* Retry */ + retry = DCB_ParseOldCharacter(&pTail, 0); + bRet = *pTail == 0; + + if(!bRet) + return bRet; + + switch(retry) + { + case 0: + lpDCB->fInX = FALSE; + lpDCB->fOutX = FALSE; + lpDCB->fOutxCtsFlow = FALSE; + lpDCB->fOutxDsrFlow = FALSE; + lpDCB->fDtrControl = DTR_CONTROL_ENABLE; + lpDCB->fRtsControl = RTS_CONTROL_ENABLE; + break; + + case 'p': + case 'P': + lpDCB->fInX = FALSE; + lpDCB->fOutX = FALSE; + lpDCB->fOutxCtsFlow = TRUE; + lpDCB->fOutxDsrFlow = TRUE; + lpDCB->fDtrControl = DTR_CONTROL_HANDSHAKE; + lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE; + break; + + case 'x': + case 'X': + lpDCB->fInX = TRUE; + lpDCB->fOutX = TRUE; + lpDCB->fOutxCtsFlow = FALSE; + lpDCB->fOutxDsrFlow = FALSE; + lpDCB->fDtrControl = DTR_CONTROL_ENABLE; + lpDCB->fRtsControl = RTS_CONTROL_ENABLE; + break; + + default: + return FALSE; + } + + return bRet; +} + +static +BOOL DCB_ParseNewNumber(const char * pString, size_t cchString, unsigned long * pNumber) +{ + BOOL bRet; + char * pStringEnd; + unsigned long number; + + bRet = cchString > 0; + + if(!bRet) + return bRet; + + number = strtoul(pString, &pStringEnd, 10); + + bRet = pStringEnd - pString == cchString; + + if(!bRet) + return bRet; + + *pNumber = number; + return bRet; +} + +static +BOOL DCB_ParseNewBoolean(const char * pString, size_t cchString, BOOL * pBoolean) +{ + BOOL bRet; + + bRet = _strnicmp(pString, "on", cchString) == 0; + + if(bRet) + { + *pBoolean = bRet; + return bRet; + } + + bRet = _strnicmp(pString, "off", cchString) == 0; + + if(bRet) + { + *pBoolean = !bRet; + return bRet; + } + + return bRet; +} + +static +BOOL +DCB_ParseNewMode(const char * pTail, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +{ + BOOL bRet; + BOOL stopBitsSet = FALSE; + + lpDCB->StopBits = 0; + + while(*pTail) + { + const char * pArg; + size_t cchArg; + size_t cchArgName; + size_t cchArgValue; + const char * pArgName; + const char * pArgValue; + unsigned long nArgValue; + BOOL fArgValue; + + pArg = pTail; + cchArg = DCB_SkipNonSpace(&pTail); + DCB_SkipSpace(&pTail); + + for(cchArgName = 0; cchArgName < cchArg; ++ cchArgName) + { + if(pArg[cchArgName] == '=') + break; + } + + bRet = cchArgName < cchArg; + + if(!bRet) + return bRet; + + cchArgValue = cchArg - cchArgName - 1; + pArgName = pArg; + pArgValue = pArg + cchArgName + 1; + + if(_strnicmp(pArgName, "baud", cchArgName) == 0) + { + bRet = DCB_ParseNewNumber(pArgValue, cchArgValue, &nArgValue); + bRet = bRet && DCB_SetBaudRate(nArgValue, lpDCB); + + if(bRet) + { + if(lpDCB->BaudRate == 110 && !stopBitsSet) + lpDCB->StopBits = 2; + else + lpDCB->StopBits = 0; + } + } + else if(_strnicmp(pArgName, "parity", cchArgName) == 0) + { + bRet = cchArgValue == 1; + bRet = bRet && DCB_SetParity(pArgValue[0], lpDCB); + } + else if(_strnicmp(pArgName, "data", cchArgName) == 0) + { + bRet = DCB_ParseNewNumber(pArgValue, cchArgValue, &nArgValue); + bRet = bRet && DCB_SetDataBits(nArgValue, lpDCB); + } + else if(_strnicmp(pArgName, "stop", cchArgName) == 0) + { + stopBitsSet = TRUE; + + if(strncmp(pArgValue, "1", cchArgValue) == 0) + lpDCB->StopBits = 0; + else if(strncmp(pArgValue, "1.5", cchArgValue) == 0) + lpDCB->StopBits = 1; + else if(strncmp(pArgValue, "2", cchArgValue) == 0) + lpDCB->StopBits = 2; + else + bRet = FALSE; + } + else if(_strnicmp(pArgName, "to", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + { + if(lpCommTimeouts) + { + memset(lpCommTimeouts, 0, sizeof(*lpCommTimeouts)); + + if(fArgValue) + lpCommTimeouts->WriteTotalTimeoutConstant = 60000; + } + } + } + else if(_strnicmp(pArgName, "xon", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + { + lpDCB->fInX = !!fArgValue; + lpDCB->fOutX = !!fArgValue; + } + } + else if(_strnicmp(pArgName, "odsr", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + lpDCB->fOutxDsrFlow = !!fArgValue; + } + else if(_strnicmp(pArgName, "octs", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + lpDCB->fOutxCtsFlow = !!fArgValue; + } + else if(_strnicmp(pArgName, "dtr", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + { + if(fArgValue) + lpDCB->fDtrControl = DTR_CONTROL_ENABLE; + else + lpDCB->fDtrControl = DTR_CONTROL_DISABLE; + } + else + { + bRet = _strnicmp(pArgValue, "hs", cchArgValue) == 0; + + if(bRet) + lpDCB->fDtrControl = DTR_CONTROL_HANDSHAKE; + } + } + else if(_strnicmp(pArgName, "rts", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + { + if(fArgValue) + lpDCB->fRtsControl = RTS_CONTROL_ENABLE; + else + lpDCB->fRtsControl = RTS_CONTROL_DISABLE; + } + else + { + bRet = _strnicmp(pArgValue, "hs", cchArgValue) == 0; + + if(bRet) + lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE; + else + { + bRet = _strnicmp(pArgValue, "tg", cchArgValue) == 0; + + if(bRet) + lpDCB->fRtsControl = RTS_CONTROL_TOGGLE; + } + } + } + else if(_strnicmp(pArgName, "idsr", cchArgName) == 0) + { + bRet = DCB_ParseNewBoolean(pArgValue, cchArgValue, &fArgValue); + + if(bRet) + lpDCB->fDsrSensitivity = !!fArgValue; + } + else + bRet = FALSE; + + if(!bRet) + return bRet; + } + + return TRUE; +} + +static +BOOL +DCB_ValidPort(unsigned long nPort) +{ + BOOL bRet; + DWORD dwErr; + WCHAR szPort[3 + 10 + 1]; + + dwErr = GetLastError(); + + _snwprintf(szPort, sizeof(szPort) / sizeof(szPort[0]), L"COM%lu", nPort); + + bRet = QueryDosDeviceW(szPort, NULL, 0) == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER; + + if(!bRet) + dwErr = ERROR_INVALID_PARAMETER; + + SetLastError(dwErr); + return bRet; +} + +/* + * @implemented + */ +BOOL +WINAPI +DCB_BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +{ + BOOL bRet; + LPCSTR pTail = lpDef; + DCB DCBCopy; + + if(_strnicmp(pTail, "COM", 3) == 0) + { + char * pNumTail; + unsigned long nPort; + + pTail += 3; + + if(!isdigit(*pTail)) + return FALSE; + + nPort = strtoul(pTail, &pNumTail, 10); + pTail = pNumTail; + + bRet = DCB_ValidPort(nPort); + + if(!bRet) + return bRet; + + DCB_SkipSpace(&pTail); + + if(*pTail == ':') + ++ pTail; + + DCB_SkipSpace(&pTail); + } + + DCBCopy = *lpDCB; + + if(isdigit(*pTail)) + bRet = DCB_ParseOldMode(pTail, &DCBCopy, lpCommTimeouts); + else + bRet = DCB_ParseNewMode(pTail, &DCBCopy, lpCommTimeouts); + + if(!bRet) + SetLastError(ERROR_INVALID_PARAMETER); + else + *lpDCB = DCBCopy; + + return bRet; +} + +/* + * @implemented + */ +BOOL +WINAPI +DCB_BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB) +{ + return DCB_BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL); +} + +/* + * @implemented + */ +BOOL +WINAPI +DCB_BuildCommDCBAndTimeoutsW(LPCWSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +{ + BOOL bRet; + HANDLE hHeap; + BOOL bInvalidChars; + LPSTR pszAscii; + int cchAscii; + DWORD dwErr; + + dwErr = ERROR_INVALID_PARAMETER; + cchAscii = WideCharToMultiByte(20127, 0, lpDef, -1, NULL, 0, NULL, NULL); + + bRet = cchAscii > 0; + + if(bRet) + { + hHeap = GetProcessHeap(); + pszAscii = HeapAlloc(hHeap, 0, cchAscii); + + bRet = pszAscii != NULL; + + if(bRet) + { + bInvalidChars = FALSE; + cchAscii = WideCharToMultiByte(20127, 0, lpDef, -1, pszAscii, cchAscii, NULL, &bInvalidChars); + + bRet = cchAscii > 0 && !bInvalidChars; + + if(bRet) + bRet = DCB_BuildCommDCBAndTimeoutsA(pszAscii, lpDCB, lpCommTimeouts); + + HeapFree(hHeap, 0, pszAscii); + } + else + dwErr = ERROR_OUTOFMEMORY; + } + + if(!bRet) + SetLastError(dwErr); + + return bRet; +} + +/* + * @implemented + */ +BOOL +WINAPI +DCB_BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB) +{ + return DCB_BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL); +} + +/* EOF */
Propchange: trunk/reactos/dll/win32/kernel32/misc/commdcb.c ------------------------------------------------------------------------------ svn:eol-style = native