in src/main/c/Windows/SerialPort_Windows.c [863:936]
JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields
jstring portNameJString = (jstring)(*env)->GetObjectField(env, obj, comPortField);
if (checkJniError(env, __LINE__ - 1)) return 0;
unsigned char requestElevatedPermissions = (*env)->GetBooleanField(env, obj, requestElevatedPermissionsField);
if (checkJniError(env, __LINE__ - 1)) return 0;
unsigned char autoFlushIOBuffers = (*env)->GetBooleanField(env, obj, autoFlushIOBuffersField);
if (checkJniError(env, __LINE__ - 1)) return 0;
unsigned char isDtrEnabled = (*env)->GetBooleanField(env, obj, isDtrEnabledField);
if (checkJniError(env, __LINE__ - 1)) return 0;
unsigned char isRtsEnabled = (*env)->GetBooleanField(env, obj, isRtsEnabledField);
if (checkJniError(env, __LINE__ - 1)) return 0;
const wchar_t *portName = (wchar_t*)(*env)->GetStringChars(env, portNameJString, NULL);
if (checkJniError(env, __LINE__ - 1)) return 0;
// Ensure that the serial port still exists and is not already open
EnterCriticalSection(&criticalSection);
serialPort *port = fetchPort(&serialPorts, portName);
if (!port)
{
// Create port representation and add to serial port listing
port = pushBack(&serialPorts, portName, L"User-Specified Port", L"User-Specified Port", L"0-0", L"Unknown", L"Unknown", L"Unknown", -1, -1);
}
LeaveCriticalSection(&criticalSection);
if (!port || (port->handle != INVALID_HANDLE_VALUE))
{
(*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName);
checkJniError(env, __LINE__ - 1);
lastErrorLineNumber = __LINE__ - 4;
lastErrorNumber = (!port ? 1 : 2);
return 0;
}
// Reduce the port's latency to its minimum value
reduceLatencyToMinimum(portName + 4, requestElevatedPermissions);
// Try to open the serial port with read/write access
port->errorLineNumber = lastErrorLineNumber = __LINE__ + 1;
void *portHandle = CreateFileW(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED, NULL);
if (portHandle != INVALID_HANDLE_VALUE)
{
// Set the newly opened port handle in the serial port structure
EnterCriticalSection(&criticalSection);
port->handle = portHandle;
LeaveCriticalSection(&criticalSection);
// Quickly set the desired RTS/DTR line status immediately upon opening
Java_com_fazecast_jSerialComm_SerialPort_setDTRandRTS(env, obj, (jlong)(intptr_t)port, isDtrEnabled, isRtsEnabled);
// Configure the port parameters and timeouts
if (!Java_com_fazecast_jSerialComm_SerialPort_configPort(env, obj, (jlong)(intptr_t)port))
{
// Close the port if there was a problem setting the parameters
PurgeComm(port->handle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
if (CancelIoEx)
CancelIoEx(port->handle, NULL);
SetCommMask(port->handle, 0);
CloseHandle(port->handle);
EnterCriticalSection(&criticalSection);
port->handle = INVALID_HANDLE_VALUE;
LeaveCriticalSection(&criticalSection);
}
else if (autoFlushIOBuffers)
Java_com_fazecast_jSerialComm_SerialPort_flushRxTxBuffers(env, obj, (jlong)(intptr_t)port);
}
else
port->errorNumber = lastErrorNumber = GetLastError();
// Return a pointer to the serial port data structure
(*env)->ReleaseStringChars(env, portNameJString, (const jchar*)portName);
checkJniError(env, __LINE__ - 1);
return (port->handle != INVALID_HANDLE_VALUE) ? (jlong)(intptr_t)port : 0;
}