No bytes in named pipe - c++

Service:
Creates std out,err,in named pipes. Attaches them to a process that it creates.
HANDLE hStdOut = CreateNamedPipe(szStdOutPipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE,
1,
100,
100,
15000,
pSa);
yStartupInfo.hStdOutput = hStdOut;
CreateProcessAsUserW( ..., yStartupInfo, ... );
This part works. The created process's output is being redirected into the pipes.
Client:
Connection to named pipe, Successful. Check if there are bytes to read with a peek (at this point bytes are pushed into the pipe!). Then read the bytes from the pipe.
hStdOutPide = CreateFileW(szPipeNameStdOut,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
PeekNamedPipe(hStdOutPide,
szBuffer,
kunBufferSize,
&ulBytesRead,
&ulBytesAvailable,
&ulRemainingBytes);
if( ulBytesAvailable > 0)
ReadFile(hStdOutPide, szBuffer, 1000, &ulBytesRead, NULL)
I have removed the surrounding code that makes sure the handles are valid and the process is running and so on.
The Peek reveals that ulRemainingBytes is ALWAYS 0. Does anyone see where my error could be? I have been trying to get this to work for some time and don't know what the proper flags for anything is anymore. Please ask if you need more information!
Security Attributes in the CreateNamesPipe are generated from a method. It is used in many other places in the code so I do not believe the problem to be there.
Thanks.

PeekNamedPipe() returns a BOOL that should be checked.
If it fails (FALSE or 0), use GetLastError() to figure out the reason.
And before that you should also check the return value of CreateFile() (hStdOutPide) against INVALID_HANDLE_VALUE. If the returned handle is invalid that could well be a reason for PeekNamedPipe() to fail.
All in all you seem to be taking too many (good) results for taken. Don't! Check your return codes and never rely on luck.
Just one more thing: it's possible that the sharing flags are set improperly. Make sure that they don't conflict with what you want to do. Either way, GetLastError() will again tell you about such issue in case CreateFile() failed.

I suspect you are trying to read from the stdout rather than stdin in your child process. But from the limited code I cannot confirm this. Refer to this question for IPC using pipes
How do I take the output of one program and use it as the input of another on C++?

Related

How to set Socket File Descriptor with FD_SET Unix in C / C++

I’m currently working on a socket programming project.
Let’s assume:
fd_set fd_in;
Now I would like to set the file Descriptor for the select function:
FD_SET(socket_fd, &fd_in);
Is that the right way ?
Then I use the select function:
int rc = select(socket_fd + 1, &fd_in, NULL, NULL, NULL);
Having done some research I haven’t managed to proceed.
I appreciate your support,
Regards, from Brooks
The appropriate manual pages are available on line, for example here.
Nevertheless, it might not be clear to you that before adding any file descriptors to your fd_set, you should first clear it:
FD_ZERO(&fd_in);
Then, yes, you use FD_SET() just as you present in the question:
FD_SET(socket_fd, &fd_in);
That assumes that the value of socket_fd is an open file descriptor.
Having done so, it is reasonable to use a pointer to the resulting fd_set as one of the arguments to select(), again as you present:
int rc = select(socket_fd + 1, &fd_in, NULL, NULL, NULL);
Do note that
that particular call registers interest only in the specified file descriptor becoming available for reading (or for accepting a connection if it is a listening socket), not for writing or exceptional conditions.
you must check select()'s return value and take appropriate action based on the result. Since you're using only a single fd_set with a single element, without a timeout, you should expect select to return either 1 (when the file descriptor is ready) or -1 (on error).
generally speaking, you need to set up the fd_set(s) each time you call select. Except in certain special cases, the contents of the sets after select() returns are often not the same as they were before the call, and in the event that select reports an error then you cannot afterward rely on anything about them at all. Thus, when select() is called in a loop, which is common, there generally needs to be fd_set setup code in the same loop.

INVALID_HANDLE_VALUE when calling CreateFileA several times

I'm using CreateFileA and the first time I call it, it works as expected. But when i call it the second time, it returns handle INVALID_HANDLE_VALUE. What could be the problem? Just for information, I'm calling it every time I need to check if my USB device is connected..
int port = 500;
char port_name [MAX_CAR] = {0};
sprintf_s (port_name, MAX_CAR, "\\\\.\\COM%d", port);
com->id = CreateFileA (port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
EDIT: I did try to use CloseHandle like CloseHandle(com->id); but it doesn't help.
From the documentation:
When an application is finished using the object handle returned by
CreateFile, use the CloseHandle function to close the handle. This not
only frees up system resources, but can have wider influence on things
like sharing the file or device and committing data to disk. Specifics
are noted within this topic as appropriate.
Use GetLastError to get the error code, and use the FormatMessage to get a human readable error description, or just simply Google the error code.
There are many reasons can cause the same error (CreateFile returns INVALID_HANDLE_VALUE), without the GetLastError, you will very hard to find out what is the real reason.

Is there any way GetExitCodeProcess could set the exit code to the wrong value?

I'm maintaining code written by someone just before they retired, which means I can't find them to ask questions. :-) This is basically a C++ wrapper to launch a program. The chunk of code in question is this:
BOOL bSuccess = CreateProcess(NULL, (char *)strBatFile.c_str(),
NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, strLocalWorkingDir.c_str(), &si, &pi );
if( bSuccess )
{
DWORD dwMillisec = INFINITE;
DWORD dwWaitStatus = WaitForSingleObject( pi.hProcess, dwMillisec );
if( dwWaitStatus == WAIT_OBJECT_0 )
{
DWORD dwExitCode = NULL;
GetExitCodeProcess( pi.hProcess, &dwExitCode );
nRet = (int)dwExitCode;
}
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
else
nRet = START_PROCESS_FAILED;
If just one instance is run at a time, it always works fine. If multiple are run within a very short time frame, though, about half of them are having dwExitCode set to 1 instead of 0, even though the process isn't crashing, and the log file that internal program writes is completing.
So to clarify, the process is always starting fine, and it's always getting into the if statements, but it's the value of dwExitCode set by GetExitCodeProcess that isn't containing what's expected. Since we error check on this, we're flagging a bunch of these runs as incomplete when they in fact are fine.
Is there any way this value could be set to something different than the process exit code? And/or is there a utility I could run at the same time to confirm the exit codes are what I think they are?
Thanks!
ETA: Just realised this is putting the internal program call in a .bat file - "C:\\ --flags etc..." and then calling that as a command line in the second argument, rather than just calling it directly using lpApplicationName. No idea if this makes a difference! But when I print the PID of the process, I can see it's the PID for a cmd.exe process, and then our program has a child PID. However, when I trace in Process Monitor, I can see that both parent and child are exiting with exit code 0.
Found it! The application itself was in fact returning a 0 error code...it was the shell around it that was returning 1. And that was due to that .bat file in the second argument. The name was being generated from time, so it ended up being exactly the same name if multiple instances were run too closely together. This is why the inner app would run fine...there was always a bat file there with that name. But there were access collisions when the different instances were trying to generate or clean up the bat, from what I can tell.
As a proof-of-concept hack I just added the current PID to the end of the file name, and everything worked perfectly. Now I just need to decide the real fix, which I think will likely be getting rid of the whole bat file mechanism entirely and calling the app directly.
Whew! Thanks for all the help, everyone! Sadly, the bit of code I included didn't have the offending line, but everyone's tips above helped me narrow in on the problem. :-)

DuplicateHandle error: error_invalid_handle

I'm trying to pass a handle from process1 to process2 using the DuplicateHandle function. I obtain the handle using the CreateFile function:
HANDLE COMportHandle;
COMportHandle = CreateFile(TEXT("COM5"),
GENERIC_ALL | PROCESS_DUP_HANDLE,
0,
0,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
0);
In the second process, I first obtain the process ID from process1 through shared memory, and then try to duplicate the handle:
HANDLE pr1handle, CPH, COMportHandle;
pr1handle = OpenProcess(PROCESS_DUP_HANDLE,FALSE,process_id);
if(!DuplicateHandle(pr1handle,COMportHandle,GetCurrentProcess(),&CPH,PROCESS_DUP_HANDLE,FALSE,0))
printf("Error: %d\n",GetLastError());
Then I get the ERROR_INVALID_HANDLE.
The processes are not related, I run the first to open the COM port, and then want to be able to read from it with the second process.
Can somebody tell me where the catch is?
In this code here:
HANDLE pr1handle, CPH, COMportHandle;
pr1handle = OpenProcess(PROCESS_DUP_HANDLE,FALSE,process_id);
if(!DuplicateHandle(pr1handle,COMportHandle,GetCurrentProcess(),&CPH,PROCESS_DUP_HANDLE,FALSE,0))
printf("Error: %d\n",GetLastError());
you introduce a new, uninitialized COMportHandle. So, assuming this is the actual code, I'm not at all surprised COMportHandle is invalid". You will somehow need to get the actual value of COMportHandle from your first process.

How to check if a HANDLE is valid or not?

In C++, I have opened a serial port that has a HANDLE. Since the port may close by an external application, how can I verify that the HANDLE is still valid before reading data?
I think it can be done by checking the HANDLE against a suitable API function, but which?
Thank you.
Checking to see whether a handle is "valid" is a mistake. You need to have a better way of dealing with this.
The problem is that once a handle has been closed, the same handle value can be generated by a new open of something different, and your test might say the handle is valid, but you are not operating on the file you think you are.
For example, consider this sequence:
Handle is opened, actual value is 0x1234
Handle is used and the value is passed around
Handle is closed.
Some other part of the program opens a file, gets handle value 0x1234
The original handle value is "checked for validity", and passes.
The handle is used, operating on the wrong file.
So, if it is your process, you need to keep track of which handles are valid and which ones are not. If you got the handle from some other process, it will have been put into your process using DuplicateHandle(). In that case, you should manage the lifetime of the handle and the source process shouldn't do that for you. If your handles are being closed from another process, I assume that you are the one doing that, and you need to deal with the book keeping.
Some WinAPI functions return meaningless ERROR_INVALID_PARAMETER even if valid handles are passed to them, so there is a real use case to check handles for validity.
GetHandleInformation function does the job:
http://msdn.microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx
as the port may close by a external application
This is not possible, an external application cannot obtain the proper handle value to pass to CloseHandle(). Once you have the port opened, any other process trying to get a handle to the port will get AccessDenied.
That said, there's crapware out there that hacks around this restriction by having secret knowledge of the undocumented kernel structures that stores handles for a process. You are powerless against them, don't make the mistake of taking on this battle by doing the same. You will lose. If a customer complains about this then give them my doctor's advice: "if it hurts then don't do it".
If you are given a HANDLE and simply want to find out whether it is indeed an open file handle, there is the Windows API function GetFileInformationByHandle for that.
Depending on the permissions your handle grants you for the file, you can also try to move the file pointer using SetFilePointer, read some data from it using ReadFile, or perform a null write operation using WriteFile with nNumberOfBytesToWrite set to 0.
Probably you are under windows and using ReadFile to read the data. The only way to check it is trying to read. If the HANDLE is invalid it'll return an error code (use GetLastEror() to see which one it is) which will probably be ERROR_HANDLE_INVALID.
I know that it's a little bit late but I had a similar question to you, how to check if a pipe (a pipe I created using CreateFile) is still open (maybe the other end shut down the connection) and can read, and if it is not, to open it again. I did what #Felix Dombek suggested, and I used the WriteFile to check the connection. If it returned 1 it means the pipe is open, else I opened it using the CreateFile again. This implies that your pipe is duplex. Here's the CreateFile:
hPipe2 = CreateFile(lpszPipename2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
and here is how I checked for the connection:
while(1)
{
bool MessageSent = WriteFile(hPipe2, "Test", 0, &cbWritten, NULL);
if (!(MessageSent))
{
LogsOut("Read pipe has been disconnected");
//Call method to start the pipe again
break;
}
Sleep(200); // I need this because it is a thread
}
This is working just fine for me :)
You can use DuplicateHandle to test handle validity.
First method: You can try to duplicate the handle you want to check on validity. Basically, invalid handles can not be duplicated.
Second method: The DuplicateHandle function does search the Win32 handle descriptor table from beginning for an empty record to reuse it and so assign into it a duplicated handle. You can just test the duplicated handle address value on value greater than yours handle address and if it is greater, then the handle is not treated as invalid and so is not reused. But this method is very specific and limited, and it does only work, when there is no more empty or invalid handle records above the handle value address you want to test.
But all this just said above is valid only if you track all handles creation and duplication on your side.
Examples for Windows 7:
Method #1
// check stdin on validity
HANDLE stdin_handle_dup = INVALID_HANDLE_VALUE;
const bool is_stdin_handle_dup = !!DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), GetCurrentProcess(), &stdin_handle_dup, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (is_stdin_handle_dup && stdin_handle_dup != INVALID_HANDLE_VALUE) {
CloseHandle(stdin_handle_dup);
stdin_handle_dup = INVALID_HANDLE_VALUE;
}
Method #2
// Assume `0x03` address has a valid stdin handle, then the `0x07` address can be tested on validity (in Windows 7 basically stdin=0x03, stdout=0x07, stderr=0x0b).
// So you can duplicate `0x03` to test `0x07`.
bool is_stdout_handle_default_address_valid = false;
HANDLE stdin_handle_dup = INVALID_HANDLE_VALUE;
const bool is_stdin_handle_dup = !!DuplicateHandle(GetCurrentProcess(), (HANDLE)0x03, GetCurrentProcess(), &stdin_handle_dup, 0, FALSE, DUPLICATE_SAME_ACCESS);
if (is_stdin_handle_dup && stdin_handle_dup != INVALID_HANDLE_VALUE) {
if (stdin_handle_dup > (HANDLE)0x07) {
is_stdout_handle_default_address_valid = true; // duplicated into address higher than 0x07, so 0x07 contains a valid handle
}
CloseHandle(stdin_handle_dup);
stdin_handle_dup = INVALID_HANDLE_VALUE;
}
In order to check the handle , first we need to know what is our HANDLE for, (for a File/Port/Window, ...), Then find an appropriate function to check it (thanks #janm for help). Note that the function's duty may be specially for this destination or not. In my case that iv'e opened a Serial port by CreateFile() , i can check the COM status by GetCommState() API function that fills our COM info struct. If the port is not open anymore or inaccessible the function returns 0 and if you call GetLastError() immediately, you`ll get the ERROR_INVALID_HANDLE value. Thanks everyone for helps.