📄 comm.c
字号:
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
STDCALL
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
STDCALL
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
STDCALL
BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB)
{
return BuildCommDCBAndTimeoutsA(lpDef, lpDCB, NULL);
}
/*
* @implemented
*/
BOOL
STDCALL
BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB)
{
return BuildCommDCBAndTimeoutsW(lpDef, lpDCB, NULL);
}
/*
* @implemented
*/
BOOL
STDCALL
ClearCommBreak(HANDLE hFile)
{
DWORD dwBytesReturned;
return DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF,
NULL, 0, NULL, 0, &dwBytesReturned, NULL);
}
/*
* @implemented
*/
BOOL
STDCALL
ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpComStat)
{
BOOL status = FALSE;
DWORD dwBytesReturned;
SERIAL_STATUS SerialStatus;
status = DeviceIoControl(hFile, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
&SerialStatus, sizeof(SERIAL_STATUS), &dwBytesReturned, NULL);
if(!NT_SUCCESS(status))
{
return status;
}
if(lpErrors)
{
*lpErrors = 0;
if(SerialStatus.Errors & SERIAL_ERROR_BREAK)
*lpErrors |= CE_BREAK;
if(SerialStatus.Errors & SERIAL_ERROR_FRAMING)
*lpErrors |= CE_FRAME;
if(SerialStatus.Errors & SERIAL_ERROR_OVERRUN)
*lpErrors |= CE_OVERRUN;
if(SerialStatus.Errors & SERIAL_ERROR_QUEUEOVERRUN )
*lpErrors |= CE_RXOVER;
if(SerialStatus.Errors & SERIAL_ERROR_PARITY)
*lpErrors |= CE_RXPARITY;
}
if (lpComStat)
{
ZeroMemory(lpComStat, sizeof(COMSTAT));
if(SerialStatus.HoldReasons & SERIAL_TX_WAITING_FOR_CTS)
lpComStat->fCtsHold = TRUE;
if(SerialStatus.HoldReasons & SERIAL_TX_WAITING_FOR_DSR)
lpComStat->fDsrHold = TRUE;
if(SerialStatus.HoldReasons & SERIAL_TX_WAITING_FOR_DCD)
lpComStat->fRlsdHold = TRUE;
if(SerialStatus.HoldReasons & SERIAL_TX_WAITING_FOR_XON)
lpComStat->fXoffHold = TRUE;
if(SerialStatus.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT)
lpComStat->fXoffSent = TRUE;
if(SerialStatus.EofReceived)
lpComStat->fEof = TRUE;
if(SerialStatus.WaitForImmediate)
lpComStat->fTxim = TRUE;
lpComStat->cbInQue = SerialStatus.AmountInInQueue;
lpComStat->cbOutQue = SerialStatus.AmountInOutQueue;
}
return TRUE;
}
/*
* @implemented
*/
BOOL
STDCALL
CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
{
PWCHAR NameW;
DWORD result;
/* don't use the static thread buffer so operations in serialui
don't overwrite the string */
if(!(NameW = FilenameA2W(lpszName, TRUE)))
{
return FALSE;
}
result = CommConfigDialogW(NameW, hWnd, lpCC);
RtlFreeHeap(RtlGetProcessHeap(), 0, NameW);
return result;
}
/*
* @implemented
*/
BOOL
STDCALL
CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC)
{
DWORD (STDCALL *drvCommDlgW)(LPCWSTR, HWND, LPCOMMCONFIG);
HMODULE hSerialuiDll;
DWORD result;
//FIXME: Get dll name from registry. (setupapi needed)
if(!(hSerialuiDll = LoadLibraryW(L"serialui.dll")))
{
DPRINT("CommConfigDialogW: serialui.dll not found.\n");
return FALSE;
}
drvCommDlgW = (DWORD (STDCALL *)(LPCWSTR, HWND, LPCOMMCONFIG))
GetProcAddress(hSerialuiDll, "drvCommConfigDialogW");
if(!drvCommDlgW)
{
DPRINT("CommConfigDialogW: serialui does not export drvCommConfigDialogW\n");
FreeLibrary(hSerialuiDll);
return FALSE;
}
result = drvCommDlgW(lpszName, hWnd, lpCC);
SetLastError(result);
FreeLibrary(hSerialuiDll);
return (result == ERROR_SUCCESS ? TRUE : FALSE);
}
/*
* @implemented
*/
BOOL
STDCALL
EscapeCommFunction(HANDLE hFile, DWORD dwFunc)
{
BOOL result = FALSE;
DWORD dwBytesReturned;
switch (dwFunc) {
case CLRDTR: // Clears the DTR (data-terminal-ready) signal.
result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
case CLRRTS: // Clears the RTS (request-to-send) signal.
result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
case SETDTR: // Sends the DTR (data-terminal-ready) signal.
result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
case SETRTS: // Sends the RTS (request-to-send) signal.
result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
case SETXOFF: // Causes transmission to act as if an XOFF character has been received.
result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XOFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
case SETXON: // Causes transmission to act as if an XON character has been received.
result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
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.
result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
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.
result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
break;
default:
DPRINT("EscapeCommFunction() WARNING: unknown function code\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
break;
}
return result;
}
/*
* @implemented
*/
BOOL
STDCALL
GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
{
BOOL ReturnValue = FALSE;
LPCOMMPROP lpComPort;
DPRINT("GetCommConfig(%d, %p, %p)\n", hCommDev, lpCC, lpdwSize);
lpComPort = RtlAllocateHeap( hProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(COMMPROP) + 0x100 );
if(NULL == lpComPort) {
DPRINT("GetCommConfig() - ERROR_NOT_ENOUGH_MEMORY\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if( (NULL == lpdwSize)
|| (NULL == lpCC) ) {
DPRINT("GetCommConfig() - invalid parameter\n");
SetLastError(ERROR_INVALID_PARAMETER);
ReturnValue = FALSE;
}
else
{
lpComPort->wPacketLength = sizeof(COMMPROP) + 0x100;
lpComPort->dwProvSpec1 = COMMPROP_INITIALIZED;
ReturnValue = GetCommProperties(hCommDev, lpComPort);
if( ReturnValue )
{
lpCC->dwSize = sizeof(COMMCONFIG);
lpCC->wVersion = 1;
lpCC->wReserved = 0;
lpCC->dwProviderSubType = lpComPort->dwProvSubType;
lpCC->dwProviderSize = lpComPort->dwProvSpec2;
if( 0 == lpComPort->dwProvSpec2 ) {
lpCC->dwProviderOffset = 0;
} else {
lpCC->dwProviderOffset = (ULONG_PTR)&lpCC->wcProviderData[0] - (ULONG_PTR)lpCC;
}
if( (lpCC->dwProviderSize+lpCC->dwSize) > *lpdwSize ) {
DPRINT("GetCommConfig() - ERROR_INSUFFICIENT_BUFFER\n");
SetLastError(ERROR_INSUFFICIENT_BUFFER);
ReturnValue = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -