close serial port in C - c

windows 7
I have built a project in C to make a dll, whcih could be used in a big program written by python.
static HANDLE hCom = INVALID_HANDLE_VALUE;
unsigned int g_dldtool_exit_code = 0;//can not be written by other threads.
hCom = CreateFile( commPort,
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // default security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (hCom == INVALID_HANDLE_VALUE) {
// Handle the error.
TRACE ("CreateFile failed with error %d", GetLastError());
g_dldtool_exit_code = 1;
goto _exit;
}
if (hCom != INVALID_HANDLE_VALUE) {
unconfig_serial_port();
fSuccess = CloseHandle(hCom);
I have used
if (hCom != INVALID_HANDLE_VALUE) {
unconfig_serial_port();
fSuccess = CloseHandle(hCom);
to close the serial port, but the if condition can not be meet every time program goes here, so the serial port can not be closed.
When I annotate the if condition, error occurs: ERROR showed when building dll
How could I close the
serial port?
The full code could be download here:
https://www.dropbox.com/s/kk2sc3r6pmmh7tt/download_main.c?dl=0

The error you are reporting seems to be due to a problem in the syntax.
Maybe when you comment out the "if" statement you remove a open bracket "{" but do not remove the close bracket "}".
Concerning why the code does not meet the if statement condition, it is difficult to say from those pieces of code.

Related

How to modify file attributes without race conditions?

I want to modify a single attribute on a file (e.g the read-only attribute). In order to do that, it looks like I have to query the current file attributes with either GetFileAttributes or GetFileInformationByHandle, then set the new attributes with either SetFileAttributes or SetFileInformationByHandle: https://learn.microsoft.com/en-us/windows/win32/fileio/retrieving-and-changing-file-attributes
However that is inherently racy, as the file attributes may change between the query and the update. Is there a method to update file attributes atomically? I would expect there to be an API like ModifyFileAttributes(DWORD addAttributes, DWORD rmAttributes) which would do its best to work atomically. Transactional NTFS is not an option for me because a) it's deprecated b) only works on NTFS.
Thanks!
As mentioned in the comment, FILE_SHARE_READ is a trade-off. The following code is adapted from SetFileInformationByHandle function. SetFileInformationByHandle for hFile2 is ERROR_ACCESS_DENIED.
#include <Windows.h>
#include <Tchar.h>
int main()
{
//...
HANDLE hFile1 = CreateFile(TEXT("tempfile"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
0,
NULL);
HANDLE hFile2 = CreateFile(TEXT("tempfile"),
GENERIC_READ,
FILE_SHARE_READ| FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
0,
NULL);
if (hFile1 != INVALID_HANDLE_VALUE && hFile2 != INVALID_HANDLE_VALUE)
{
HANDLE hFile = hFile1;
//HANDLE hFile = hFile2;
FILE_BASIC_INFO fdi{};
fdi.FileAttributes = FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_NORMAL;
BOOL fResult = SetFileInformationByHandle(hFile,
FileBasicInfo,
&fdi,
sizeof(FILE_BASIC_INFO));
if (fResult)
{
// File will be deleted upon CloseHandle.
_tprintf(TEXT("SetFileInformationByHandle marked tempfile for deletion\n"));
// ...
// Now use the file for whatever temp data storage you need,
// it will automatically be deleted upon CloseHandle or
// application termination.
// ...
}
else
{
_tprintf(TEXT("error %lu: SetFileInformationByHandle could not mark tempfile for deletion\n"),
GetLastError());
}
CloseHandle(hFile);
// At this point, the file is closed and deleted by the system.
}
else
{
_tprintf(TEXT("error %lu: could not create tempfile\n"),
GetLastError());
}
//...
}

Virtual comport communication with windows 10 in C

im trying to communicate with a device via a virtual comport (comport to usb adapter,PL2303) on Win10. The device is an Eltek RC250 datalogger.
I have already installed an older PL2303 driver. The devicemanager recognized the device without any errors. Sending and receiving data between the device and the official software is working properly.
My problem is that after ReadFile is executed the program is doing nothing. I think ReadFile is waiting for more input from the device and therefore stucked in this function.
Trying it on a win7 System gets to the same issue.
The message which i write to the device is a valid message.
The following code shows the communication.
hComm = CreateFile("COM3", //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices /* establish connection to serial port */
if (hComm == INVALID_HANDLE_VALUE)
printf("Error in opening serial port");
else
printf("opening serial port successfully");
nNumberOfBytesToWrite = sizeof(message);
resW = WriteFile(
hComm,
message,
nNumberOfBytesToWrite,
&lpNumberOfBytesWritten,
NULL);
do
{
printf("\nread");
resR = ReadFile(
hComm,
&answer,
sizeof(lpNumberOfBytesRead),
&lpNumberOfBytesRead,
NULL);
SerialBuffer[i] = answer;
i++;
}
while (lpNumberOfBytesRead > 0);
return 0;
Please help me, i have no clue what the problem might be.
Thomas
In the ReadFile() call, third parameter should be sizeof(answer) (or possibly just 1 since it appears to be a single byte), but certainly not sizeof(lpNumberOfBytesRead). It is blocking waiting for 4 bytes (size of a DWORD) when presumably answer is a single byte?
Also if you have not explicitly set a Comm timeout, you have no idea how long ReadFile() will wait before returning 0 to exit the loop. If the timeout is indefinite then it will never exist the loop.
There are other potential issues in this call, but without seeing how the parameters are declared, it is not possible to say.

C - Windows Exception Handler Invalid Handle

I have a problem about managing an exception. In my code I put hIn = INVALID_HANDLE_VALUE to test the exception, and "null" is a non existing file. My piece of code is
__try
{
hIn = CreateFile (_T("null"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hIn = INVALID_HANDLE_VALUE;
ReadFile (hIn, buffer, BUF_SIZE*sizeof(DWORD), &nIn, NULL);
}
__except(GetExceptionCode() == EXCEPTION_INVALID_HANDLE ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
_tprintf (_T("-> Error OPENING FILE <-\n"));
return -1;
}
I don't understand why it doesn't catch the exception. What is the problem?
Thank you in advance
The __except block is never entered because ReadFile does not throw exceptions.
Remember that the Windows API is agnostic of programming language and needs to present an interface that can be consumed by any programming language. And not all languages have support for exceptions, and even those that do use different mechanisms. So for an API like the Windows API, throwing exceptions is simply not an option.
Both of the API calls in your question indicate errors by their return values. You need to check these return values and act accordingly. Not all functions report errors in the same way so you need to pay close attention to the documentation for each API function that you call.
The C-function (Win32 API) ReadFile() doesn't normally throw an exception. Instead check return value of ReadFile and if FALSE, call GetLastError() to get the error code.
Have you btw enabled SEH ? See compiler switch /EHsc
see
As others have stated, your __except does not catch an exception because there is no exception being raised in the first place. You need to check return values and error codes instead:
hIn = CreateFile (_T("null"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hIn == INVALID_HANDLE_VALUE)
{
_tprintf (_T("-> Error %u OPENING FILE <-\n"), GetLastError());
return -1;
}
...
ReadFile (hIn, buffer, BUF_SIZE*sizeof(DWORD), &nIn, NULL);
...
CloseHandle(hIn);

SetFileShortName does not reset short (8.3) name of a file

I am trying to remove short name of a file in NTFS. I am testing it on Windows 7. I am running my process as an administrator.
Here is my code:
HANDLE hFile;
DWORD error = NO_ERROR;
hFile = fh = CreateFileA(name,
GENERIC_ALL,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if(hFile == NULL || hFile == INVALID_HANDLE_VALUE)
{
error = GetLastError();
if(GetLastError() == ERROR_ACCESS_DENIED)
printf("File Access Denied.\n");
if(GetLastError() == ERROR_FILE_NOT_FOUND)
printf("File not found.\n");
return error;
}
SetLastError(NO_ERROR);
ModifyPrivilege(SE_RESTORE_NAME, TRUE);
SetLastError(NO_ERROR);
SetFileShortNameW(hFile, L""); // As per MSDN, It will work only in windows 7 and above
error = GetlastError(); // returns 1314 error
ModifyPrivilege(SE_RESTORE_NAME, FALSE);
CloseHandle(hFile);
Code for ModifyPrivilege() is same as on MSDN:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa387705(v=vs.85).aspx
I am making sure that I have SE_RESTORE_NAME privilege (using process explorer for this). Above code does not generate any error but when I look at mft record of the file in hex editor, Short file name is still there i.e. MFT record has two $30 File name attributes, one for full name and other for short name.
I want to know if my code is wrong or some thing else that I have to do? Why does not SetFileShortNameEx function does not any effect in this case?
You need to add the privilege before you call CreateFile.
Your error handling is a bit messed up too. There's no need for any calls to SetLastError. You simply need to check the return values of the API call before you call GetLastError. Only call GetLastError if the docs say that it has meaning. In the case of SetFileShortName, as is the case for many API calls, you only call GetLastError when the API call returns FALSE. So you should write:
if (!SetFileShortNameW(hFile, L""))
{
error = GetLastError();
// ...
}

program hangs when using windows 32bit serial communications

written below is a crude code i wrote for accessing a serial port. attached to that port is a microcontroller that sends me data and having a baud rate of 57600. i ran the code once and got results but after closing the window, my computer hanged. i pressed ctrl+alt+del and saw that under processes my program was still running. i cant close it too.
int n = 20;
char szBuff[20 + 1] = {0};
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts={0};
DWORD dwBytesRead = 20;
dcbSerialParams.DCBlength=sizeof(DCB);
hSerial = CreateFile("COM5",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE)
{
if(GetLastError()==ERROR_FILE_NOT_FOUND)
{
puts ("cannot open port!");
}
puts ("invalid handle value!");
}
if (!GetCommState(hSerial, &dcbSerialParams))
{
puts ("error getting state");
}
dcbSerialParams.BaudRate=CBR_57600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams))
{
puts ("error setting port state");
}
while (1)
{
if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)){
puts ("serial read error fail!");
}
else
{
printf ("%s\n" , szBuff);
}
}
That sounds like a buggy serial port driver. See Why do some process stay in Task Manager after they've been killed?. When you kill your program, it doesn't go away until all of its pending I/O operations have been canceled.
You MUST to define some type of stop to the app if it will loop in a while(1).
Option 1: The microcontroller must send a terminate command or character that you use to break the while.
Option 2: Some type of timeout instead while(1).
Option 3: Catch some signal and then break the while().
And there are a lot of other options.

Resources