JNIEXPORT jlong JNICALL Java_com_fazecast_jSerialComm_SerialPort_openPortNative()

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;
}