modified dll/win32/kernel32/k32.h
authorKJK::Hyperion <hackbunny@reactos.org>
Fri, 26 Dec 2008 22:09:38 +0000 (22:09 +0000)
committerKJK::Hyperion <hackbunny@reactos.org>
Fri, 26 Dec 2008 22:09:38 +0000 (22:09 +0000)
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

svn path=/trunk/; revision=38362

reactos/dll/win32/kernel32/k32.h
reactos/dll/win32/kernel32/kernel32.rbuild
reactos/dll/win32/kernel32/misc/comm.c
reactos/dll/win32/kernel32/misc/commdcb.c [new file with mode: 0644]

index 503cca5..bc55db7 100755 (executable)
@@ -13,7 +13,6 @@
 
 /* PSDK/NDK Headers */
 #define WIN32_NO_STATUS
-#define _KERNEL32_
 #include <windows.h>
 #include <tlhelp32.h>
 
index 7b5041a..c3ef057 100644 (file)
@@ -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>
index 10d7867..8bed46d 100644 (file)
@@ -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
  *
  */
 
 #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 @@ CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
        result = drvCommDlgW(lpszName, hWnd, lpCC);
        SetLastError(result);
        FreeLibrary(hSerialuiDll);
-       
+
        return (result == ERROR_SUCCESS ? TRUE : FALSE);
 }
 
@@ -976,7 +250,7 @@ GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
                return FALSE;
        }
 
-       if( (NULL == lpdwSize) 
+       if( (NULL == lpdwSize)
                || (NULL == lpCC) ) {
                        DPRINT("GetCommConfig() - invalid parameter\n");
                        SetLastError(ERROR_INVALID_PARAMETER);
diff --git a/reactos/dll/win32/kernel32/misc/commdcb.c b/reactos/dll/win32/kernel32/misc/commdcb.c
new file mode 100644 (file)
index 0000000..8de2bf2
--- /dev/null
@@ -0,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 */