PeekNamedPipe always returns 0 for totalBytesAvailable - c

PeekNamedPipe(
tmp_pipe, // __in HANDLE hNamedPipe,
NULL, // __out_opt LPVOID lpBuffer,
0, // __in DWORD nBufferSize,
NULL, // __out_opt LPDWORD lpBytesRead,
&totalBytesAvailable, // __out_opt LPDWORD lpTotalBytesAvail,
NULL // __out_opt LPDWORD lpBytesLeftThisMessage
);
I have written bytes to the pipe somewhere else,but totalBytesAvailable is always 0,why?

I have found that in Windows, if you call PeekNamedPipe before calling ReadFile, it will always return zero bytes, even if there are in fact bytes to be read. You have to call ReadFile, followed by PeekNamedPipe, and keep looping until PeekNamedPipe returns zero bytes.
I have noticed that even under these circumstances, sometimes PeekNamedPipe returns zero bytes even though there are bytes left to be gotten. Must be a timing thing. The sender is going to have to preface each message with a byte count. Sigh...

It's an old question but I haven't found the answer online so I figured I'd answer it anyway. You have to loop until the pipe reads, here's my working code:
DWORD bytesAvail = 0;
while(bytesAvail==0){
if( !PeekNamedPipe(pipeHandle, NULL, 0, NULL, &bytesAvail, NULL) ){
printf("PeekNamedPipe error %d.\n", GetLastError()); //error check
}
}
printf("Bytes available: %d\n", bytesAvail);
Of course, this only works if you are sure there is data waiting to be read, otherwise you will be stuck in an endless loop because there isn't actually data to be read, so it will always be 0.

Related

Segmentation fault when writing to comport

I am writing a small program to communicate with a USB to UART bridge (CP210x).
The program is fairly simple, but when ever I decrease the size of the outbound message array below (wm_size < 25) I get a segmentation fault.
The code yielding the segmentation fault looks as follows:
HANDLE prog_com_port;
prog_com_port = CreateFileA("\\\\.\\COM4",
GENERIC_READ | GENERIC_WRITE, //Request Read and Write Acess
0, //Block others from sharing Acess
NULL, //Disable Security features
OPEN_EXISTING, //Only open existing device
FILE_ATTRIBUTE_NORMAL, //Used to set atributes and flags
NULL);
//Handle to
if(prog_com_port == INVALID_HANDLE_VALUE)
{
printf("Opening COM port failed - INVALID_HANDLE_VALUE\n");
CloseHandle(prog_com_port);
return 1;
}
else
printf("COM port was opened successfully \n");
SetupCommState(prog_com_port);
Sleep(2);
#define wm_size 25
int messageLength = 2;
char W_message[wm_size] = {0x01,0x01};
long unsigned int * bytes_sent;
BOOL Status;
Status = WriteFile(prog_com_port, // Handle to the Serial port
&W_message, // Pointer to message buffer
messageLength, // No of bytes to write
bytes_sent, // Pointer to number of bytes written
NULL);
if(!Status)
{
printf("Failed to write to COM port - 0x00 \n");
CloseHandle(prog_com_port);
return 2;
}
CloseHandle(prog_com_port);
My logic tells me that setting wm_size = 2 is enough but apparently that is wrong. Can someone tell me why?
I played around with the size of wm_size and found experiemtally that 25 fixed the problem.
wm_size = 2 is enough, the problem is elsewhere: bytes_sent is a pointer that points nowhere.
Your "fix" didn't fix anything. You are experiencing undefined behaviour (which includes apparently working fine).
You want this (all comments are mine):
DWORD messageLength = 2; // use DWORD
DWORD bytes_sent; // use DWORD
char W_message[] = {0x01,0x01}; // you don't need wm_size
Status = WriteFile(prog_com_port,
W_message, // remove &, W_message decays into a pointer
messageLength,
&bytes_sent, // put &, you need a pointer here
NULL);
or even better: you don't need messageLength:
Status = WriteFile(prog_com_port,
W_message, // remove &
sizeof(W_message), // assuming W_message contains chars
&bytes_sent, // put &
NULL);
// now bytes_sent contains the number of bytes sent (hopefully 2),
// providing WriteFile succeeded (Status is TRUE)
The usage of DWORD is highly recommended, so the types of the arguments passed to to WriteFile actually match the declaration (and the documentation). Also be aware that LPDWORD in all Microsoft documentation and header files is is the
same thing as DWORD*.

FTDI. Would need to know more details about the FT_Write() function

A question about the FT_Write() function.
FT_STATUS FT_Write (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpdwBytesWritten)
I wonder about the lpdwBytesWritten.
When will it ever return *lpdwBytesWritten < dwBytesToWrite? Would FT_Write return other than FT_OK in that case?
And how much data can I send in one call to FT_Write? What limit has the dwBytesToWrite parameter?
I have not been able to find the answers to these questions. Have read in the FTDI Knowledgebase and also in the D2XX Programmer's Guide.
FT_Write returns status other than FT_OK on "critical" errors.
This function (as well as FT_Read) might return FT_OK and put in *lpdwBytesWritten any number from 0 (timeout) to dwBytesToWrite (transmission finished).
Intermediate values means that not all data transferred yet but transmission process can be continued.
Transmission loop might be like this:
BYTE *buf = pointer_to_data;
DWORD len = length_of_data;
FT_STATUS status;
DWORD written;
for (;;) {
status = FT_Write(handle, buf, len, &written);
if (status != FT_OK)
return status;
if (written == 0)
return -1; // or FT_OTHER_ERROR if no special timeout handling required
if (written == len)
return FT_OK;
len -= written;
buf += written;
}
See also Example 3, FT2232C Test Application (file t_titan.cpp, function DoRxTest at line 289)
dwBytesToWrite is a double word, that is 32 bits. A rather large number of bytes to write. My guess is that the function can return FT_OK even if the number of bytes written is < the number of bytes to write. It is useful to know how many bytes have been written, so that the next time you call the function, you know exactly where to set your transmit pointer in the buffer.

C - RegQueryValueEx sometimes in Release build

This is driving me crazy. I'm compiling my project on Visual Studio 2012. I want to read a REG_BINARY registry entry using RegOpenKeyEx and RegQueryValueEx calls. In Debug (Multi-Threaded Debug) mode, everything works perfectly. However, in Release (Multi-Threaded) mode, RegQueryValueEx will VERY often fail with error code ERROR_MORE_DATA. Here is the code I am using:
HKEY keyHandle;
TCHAR lpData[1024];
DWORD lpcbData;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle) != ERROR_SUCCESS){
MessageBox(NULL, L"fail", L"title", MB_OK);
return NULL;
} else if (RegQueryValueEx(keyHandle, L"DigitalProductId", NULL, NULL, (LPBYTE)lpData, &lpcbData) != ERROR_SUCCESS){
MessageBox(NULL, L"fail!", L"title", MB_OK);
return NULL;
}
MessageBox(NULL, L"success", L"title", MB_OK);
By the definition of RegQueryValueEx, lpcbData is both an In and Out parameter. That is, RegQueryValueEx both reads it and writes to it. It complains because you are passing it without initializing it first with the size of the buffer, which in your case is 1024 (also I recommend that you change TCHAR to BYTE as required by the API; You can convert it to a Unicode string later on).
Try setting it to 1024 before calling the function. If then it fails with ERROR_MORE_DATA, then your buffer is not big enough - in other words, the registry key string is too long - you can either define it to contain more characters, or, better yet, call the function first with a NULL parameter instead of the buffer, and you will get back in lpcbData the required size of the buffer. You can then allocate the required buffer on the heap. Hope this helps!
You are not initializing lpcbData before calling RegQueryValueEx(). You have to tell it how large lpData is, in bytes, so it knows how many bytes it can retreive.
DWORD lpcbData = sizeof(lpData);
Read the documentation:
lpcbData [in, out, optional]
A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter, in bytes. When the function returns, this variable contains the size of the data copied to lpData.
A better option is to ask the Registry how large the data is, then (re)allocate the buffer as needed. The example in the documentation shows you how to do that.
You should set the lpcbData to size of your buffer before passing it to RegQueryValueEx().
Sample code:
HKEY keyHandle;
TCHAR lpData[1024];
DWORD lpcbData= sizeof(lpData); //set size.
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle) != ERROR_SUCCESS){
MessageBox(NULL, L"fail", L"title", MB_OK);
return NULL;
} else if (RegQueryValueEx(keyHandle, L"DigitalProductId", NULL, NULL, (LPBYTE)lpData, &lpcbData) != ERROR_SUCCESS){
MessageBox(NULL, L"fail!", L"title", MB_OK);
return NULL;
}
Its working by chance so that lpcData contains some random value which is higher than the actual size of data. And probably your data is not more than 1024.
Moreover, if you get ERROR_MORE_DATA error, the lpcData will indicate how much size is required to read the data. So you should update your buffer accordingly and retry.

Why does MapViewOfFile fail with ERROR_ACCESS_DENIED?

I came across this situation with WinAPI's MapViewOfFile function. An Internet search didn't turn up any apparent fixes, so I will share my problem and solution here.
Consider the following snippet:
const char *name = "Global\\Object_Name";
unsigned long size = get_object_size();
HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
size,
name);
if (!handle || handle == INVALID_HANDLE_VALUE)
exit(GetLastError());
bool created = GetLastError() == 0;
void *block = MapViewOfFile( handle,
FILE_MAP_ALL_ACCESS,
0,
0,
size);
if (block == NULL)
exit(GetLastError());
In one particular case, CreateFileMapping was successfully returning a handle. GetLastError was returning ERROR_ALREADY_EXISTS, so created == false. Now, the call to MapViewOfFile, using the same size that I passed to CreateFileMapping, returns NULL and GetLastError returns 0x05: ERROR_ACCESS_DENIED. The process was running with administrator privileges.
The MSDN documentation doesn't really mention any reason why this situation would occur. So why does CreateFileMapping succeed, but MapViewOfFile fail?
After a lot of suffer, I finally found what was causing this error in my application, in case someone else is struggling with the same, the problem is not with the MapViewOfFile method, but with the CreateFileMapping, the size of the createFileMapping should be the size of the file, not the size of the element to read, if you don't know the size then it should be 0, this does not apply to the MapViewOfFile as the value to pass as size is the length of the block you want to read/write.
Your code working will look like this:
const char *name = "Global\\Object_Name";
unsigned long size = get_object_size();
HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
0,
name);
if (!handle || handle == INVALID_HANDLE_VALUE)
exit(GetLastError());
bool created = GetLastError() == 0;
void *block = MapViewOfFile( handle,
FILE_MAP_ALL_ACCESS,
0,
0,
size);
if (block == NULL)
exit(GetLastError());
A just putting this here to document what I found, unfortunately is hard to search for this error when you don't know what is causing it. I hope this saves a couple of hours to someone else.
I'm sure there are many reasons why ERROR_ACCESS_DENIED could occur from a call to MapViewOfFile. In my particular situation, it was due to the size argument.
The hint is in the fact that created == false. It shows that the object "Global\\Object_Name" has already been created. For whatever reason, the creating call initialised the section with a smaller size. For what seems like an oversight, the second call to CreateFileMapping will happily give you a handle to the already-existing object, even if you asked for a bigger mapping.
The call to MapViewOfFile now fails, because it's requesting a view that is bigger than the actual section.
So, if you're in a similar situation where the second call to MapViewOfFile fails, check the size that you're trying to map to.
It could be that the second project is compiling with a different structure alignment, resulting in the sizeof() operator determining different values, or some other size-determining function is not behaving as expected.

lpNumberOfBytesRead and lpNumberOfBytesWritten using Sockets

I am learning C and I am wondering what I need to add for those values in my WriteFile and ReadFile methods
lpNumberOfBytesRead and lpNumberOfBytesWritten
WriteFile((HANDLE)sock, "\x05\x01\x00", 3, NULL, NULL);
ReadFile((HANDLE)sock, buf, 1024, NULL, NULL);
it says in the documentation one of the two NULL values can't be NULL as my friend pointed out...
Any ideas *cheers
Assuming that you are not going to use overlapped I/O, (and from your question, I get a strong feeling that you are not), you need to pass a pointer to a DWORD variable that will receive the values:
DWORD NumberOfBytesWritten;
WriteFile((HANDLE)sock, "\x05\x01\x00", 3, &NumberOfBytesWritten, NULL);
If the function returns successfully (and you should check its return value to determine that), NumberOfBytesWritten will be set to the number of bytes that were actually written to the file.

Resources