I have created a NamedPipe inside a Windows Service and starting the Service Manually or as the System Starts up.
EDIT:
lpszPipename = TEXT("\\\\.\\pipe\\1stPipe");
OVERLAPPED m_OverLaped;
HANDLE hEvent;
hPipe=CreateNamedPipe (lpszPipename,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
PIPE_UNLIMITED_INSTANCES,BUFSIZE,
BUFSIZE,0,NULL);
m_OverLaped.hEvent=CreateEvent(NULL,TRUE,TRUE,NULL);
m_OverLaped.Internal=0;
m_OverLaped.InternalHigh=0;
m_OverLaped.Offset=0;
m_OverLaped.OffsetHigh=0;
ConnectNamedPipe(hPipe,&m_OverLaped);
Now I want to Access the Named Pipe, Write some Message and Response back.
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\1stPipe");
OVERLAPPED m_OverLaped;
m_OverLaped.hEvent=CreateEvent(NULL,TRUE,TRUE,NULL);
m_OverLaped.Internal=0;
m_OverLaped.InternalHigh=0;
m_OverLaped.Offset=0;
m_OverLaped.OffsetHigh=0;
hPipe=CreateFile (lpszPipename, // Gets the Pipename
GENERIC_READ | GENERIC_WRITE,// Client only writes to this pipe.
0, // Do not share this pipe with others.
NULL, // Do not inherit security.
OPEN_EXISTING, // Pipe must exist.
FILE_ATTRIBUTE_NORMAL, // I have no special requirements on
//file attributes
NULL);
dwMode = PIPE_READMODE_MESSAGE;
fSuccess = SetNamedPipeHandleState (hPipe, // pipe handle
&dwMode, // new pipe mode
NULL, // don't set maximum bytes
NULL); // don't set maximum time
fSuccess = TransactNamedPipe (hPipe, // pipe handle
lpszWrite, // message to server
(lstrlen(lpszWrite)+1)*sizeof(TCHAR),//message length
chReadBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of read buffer
&cbRead, // bytes read
&m_OverLaped);
fSuccess = ReadFile (hPipe, // pipe handle
chReadBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbRead, // number of bytes read
&m_OverLaped); // overlapped
I have ommited the Error Checking Codes to be make it readable here. I get stuck for long(infinite may be ) time while executing TransactNamedPipe. I must be setting some parameters wrong , but I have tried the options as specified at MSDN.
m_OverLaped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
...
ConnectNamedPipe(hPipe, &m_OverLaped);
Since the pipe is created with FILE_FLAG_OVERLAPPED flag, you must pass LPOVERLAPPED parameter to every pipe I/O call (including TransactNamedPipe). If function returns FALSE and GetLastError returns ERROR_IO_PENDING, wait for m_OverLaped.hEvent - when it is set, operation is completed.
For starters
m_OverLaped.hEvent=hPipe;
Is wrong, hEvent needs to be set to the event you've created, not the pipe. Before you do the read you need to call:
WaitForSingleObject( oOverlap.hEvent,
and then:
GetOverlappedResult()
Have you got the pipe working in non-overlapped mode?
Related
I am trying to create named pipe server for remote using 127.0.0.1 but after I run CreateNamedPipe it failed with error 6 which means:
The handle is invalid
I also tried to add PIPE_ACCEPT_REMOTE_CLIENTS but it doesn't work.
This is my server code:
LPCWSTR pwsPipePrefix = L"\\\\127.0.0.1\\pipe\\";
LPCWSTR pwsPipeName = NULL;
HANDLE hServerPipe;
BOOL bSuccess;
DWORD bytesWritten = 0;
DWORD messageLenght;
BOOL bAttemptImpersonation = TRUE;
// Read name pipe name to from STDIN
wchar_t wcInputPipeName[200];
wprintf(L"[*] Pipe name to connect to (max 200 chars): ");
std::wcin.getline(wcInputPipeName, 200);
int iInputLen = wcslen(wcInputPipeName);
if (iInputLen > 200) {
wprintf(L"[-] More than 200 chars (%d).. exiting.\n", iInputLen);
return 1;
}
std::wstring wsConcat = pwsPipePrefix + (std::wstring)wcInputPipeName;
pwsPipeName = wsConcat.c_str();
wprintf(L"[*] Creating named pipe: %ls\n", pwsPipeName);
hServerPipe = CreateNamedPipe(
pwsPipeName, // name of our pipe, must be in the form of \\.\pipe\<NAME>
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, // open mode, specifying a duplex pipe so server and client can send and receive data
PIPE_TYPE_MESSAGE | PIPE_ACCEPT_REMOTE_CLIENTS, // MESSAGE mode to send/receive messages in discrete units (instead of a byte stream)
PIPE_UNLIMITED_INSTANCES, // number of instanced for this pipe, 1 is enough for our use case
2048, // output buffer size
2048, // input buffer size
0, // default timeout value, equal to 50 milliseconds
NULL // use default security attributes
);
wprintf(L"[*] Waiting for incoming connections...");
bSuccess = ConnectNamedPipe(hServerPipe, NULL);
if (bSuccess) {
wprintf(L"Got one.\n");
}
else wprintf(L"Error: %d", GetLastError());
*This piece of code was taken from this project.
I'm trying to make my named pipe server skip the block-wait of the ConnectNamedPipe function until my client tries to connect. So I want is for my code to continue past the ConnetNamedPipe line until the end but keep the connection for my pipe open in the backgroun. If I use the PIPE_NOWAIT mode when creating the pipe it just returns imediatelly and the pipe closes before my client can connect.
I know that I tried doing this using a thread but even when I create a thread and execute the ConnectNamedPipe part of the code within the thread it still waits on this line instead of continuing with my code. Once it reaches the end of my server cpp file code I want to connect to the pipe with my client.
My Pipe:
hPipe = CreateNamedPipe(
lpszPipename,
PIPE_ACCESS_OUTBOUND, // one way access, only send data
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
512,
512,
0,
NULL);
if (hPipe == INVALID_HANDLE_VALUE)
{
Out->msg(ERR,"Creating the pipe failed.");
}
// Create a thread for this client.
hThread = CreateThread(
NULL, // no security attribute
0, // default stack size
InstanceThread, // thread proc
(LPVOID) hPipe, // thread parameter
0, // not suspended
&dwThreadId); // returns thread ID
if (hThread == NULL)
{
Out->msg(ERR,"Creating the thread failed.");
}
else CloseHandle(hThread);
// Close the pipe.
CloseHandle(hPipe);
My Thread:
DWORD WINAPI InstanceThread(LPVOID lpvParam)
{
Out->msg(output::SEV_INFO,"Waiting for client to connect.");
fConnected = ConnectNamedPipe(hPipe, NULL) ? //This is where the execution hangs
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
HANDLE hHeap = GetProcessHeap();
TCHAR* pchReply = (TCHAR*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(TCHAR));
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
BOOL fSuccess = FALSE;
HANDLE hPipe = NULL;
// The thread's parameter is a handle to a pipe object instance.
hPipe = (HANDLE) lpvParam;
uint32_t startTime = time(NULL);
uint32_t elapsedTime;
// Loop until done reading
while ((elapsedTime < 60))
{
elapsedTime = difftime(time(NULL), startTime);
// Write to the pipe.
fSuccess = WriteFile(
hPipe, // handle to pipe
pchReply, // buffer to write from
cbReplyBytes, // number of bytes to write
&cbWritten, // number of bytes written
NULL); // not overlapped I/O
if (!fSuccess || cbReplyBytes != cbWritten)
{
Out->msg(ERR,"InstanceThread WriteFile failed.");
break;
}
}
// Flush the pipe to allow the client to read the pipe's contents
// before disconnecting. Then disconnect the pipe, and close the
// handle to this pipe instance.
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
HeapFree(hHeap, 0, pchReply);
Out->msg(output::SEV_INFO,"InstanceThread exitting.\n");
return 1;
}
I'm trying to make my named pipe server skip the block-wait of the ConnectNamedPipe function until my client tries to connect.
So you're talking about the server.
So I want my code to continue past the ConnectNamedPipe line while still being able to connect to my server.
So you're talking about the client.
It doesn't make sense. ConnectNamedPipe() is a server-side function, and you don't have anything useful to do in a thread dedicated to it except block until a client connects. So do that.
I am starting out with named pipes and need to use them for IPC between two local processes. I have both the server and client process using the pipe in nonblocking overlapped mode.
Everything works fine (the server successfully receives a string sent by the client) except that the event passed to ConnectNamedPipe() via the OVERLAPPED structure is not getting signaled as expected (signaled when a client connects).
While the server is blocked on the WaitForSingleObject() call the client process connected to the pipe, sent its data and terminated yet the event does not get signaled. What am I missing?
Server code:
HANDLE hPipe = ::CreateNamedPipeW(
L"\\\\.\\pipe\\ThePipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
1,
4096,
4096,
100,
nullptr);
OVERLAPPED ov = {0};
ov.hEvent = ::CreateEventW(nullptr, TRUE, FALSE, nullptr);
BOOL retVal = ::ConnectNamedPipe(hPipe, &ov);
if (retVal == 0)
{
DWORD err = ::GetLastError();
if (err == ERROR_IO_PENDING)
{
::WaitForSingleObject(ov.hEvent, 30000);
}
if (err == ERROR_PIPE_LISTENING)
{
::WaitForSingleObject(ov.hEvent, 30000); // this blocks until time-out???
}
}
You shouldn't use (deprecated) PIPE_NOWAIT together with overlapped mode. PIPE_NOWAIT makes ConnectNamedPipe immediately return ERROR_PIPE_LISTENING if no client is connected; overlapped I/O just doesn't happen, and waiting for event is useless.
Either you set PIPE_NOWAIT and poll the pipe periodically until success, or you set FILE_FLAG_OVERLAPPED and use an event to check/wait for completion.
I have a long-running console-based application Sender that sends simple text to STDOUT using non-buffered output such as cout << "Message" << flush(). I want to create an MFC dialog-based application (named Receiver) that starts Sender and can read it's output. Receiver should also be able to detect when Sender has died, or be able to kill Sender if it wants to. Sender knows nothing of Reciever, and I can't change Sender's code.
I have asked a separate question about the best way to do this. My first attempt was to create pipes with redirected STDIN and STDOUT for the child process and use asynchronous ReadFileEx calls to read in Sender's data. This isn't working correctly, because the ReadFileEx function only fires once, and only with zero bytes transferred even though I know for a fact that Sender is sending data.
I am creating 2 pipes with redirected STDIN and STDOUT, ala this MS example:
// allow the child process to inherit handles
SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(sa);
sa.bInheritHandle = 1;
// create pipes with rerouted stdin & stdout
CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&handles[h_Child_StdIn_Read], &handles[h_Child_StdIn_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdIn_Read], HANDLE_FLAG_INHERIT, 0);
...Receiver then goes on to start Sender via CreateProcess():
// create child process
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);
si.hStdOutput = handles[h_Child_StdOut_Write];
si.hStdInput = handles[h_Child_StdIn_Read];
si.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess( 0, "Sender.EXE", 0, 0, 1, 0, 0, 0, &si, &pi);
handles[h_Child_Process] = pi.hProcess;
handles[h_Child_Thread] = pi.hThread;
My main loop is based on WaitForObjectsEx, placed in to an alertable wait state to support the asynch file read. I am waiting on two handles: one that signals when Sender dies prematurely, and one that signals when Receiver's main thread wants Sender to die. Before starting the loop, I kick off an overlapped (asynchronous) file read operation on Sender's STDOUT. Ignore the obvious memory leaks and other hacks -- this is illustrative:
vector<HANDLE> wait_handles;
wait_handles.push_back(handles[h_Die_Sig]);
wait_handles.push_back(handles[h_Child_Process]);
for( bool cont = true; cont; )
{
IO* io = new IO;
memset(io, 0, sizeof(IO));
io->buf_size_ = 16 * 1024;
io->buf_ = new char[io->buf_size_];
memset(io->buf_, 0, io->buf_size_);
io->thread_ = ¶m;
io->file_ = handles[h_Child_StdOut_Read];
if( !ReadFileEx(io->file_, io->buf_, io->buf_size_, io, OnFileRead) )
{
DWORD err = GetLastError();
string err_msg = util::strprintwinerr(err);
}
DWORD rc = WaitForMultipleObjectsEx(wait_handles.size(), &wait_handles[0], FALSE, INFINITE, TRUE);
// ...
}
The IO object above is derived publicly from OVERLAPPED:
struct IO : public OVERLAPPED
{
char* buf_;
DWORD buf_size_;
DWORD read_;
ThreadParam* thread_;
HANDLE file_;
};
When the overlapped Read function completes, I read the incoming data and generate a string:
void CALLBACK OnFileRead(DWORD err, DWORD bytes, OVERLAPPED* ovr)
{
IO* io = static_cast<IO*>(ovr);
string msg(io->buf_, bytes);
}
Sender knows nothing of Receiver, and it sends text to the console using very simple, but non-buffered means.
The problem: I know that Sender is sending data to its STDOUT, but my OnFileRead function is called only once, and only with zero bytes transferred.
Why can't I receive Sender's output this way? Do I have a bug, or am I doing something wrong?
Besides the error pointed out by #DyP, you are assuming that CreatePipe opened the handle in overlapped mode. Your assumption is incorrect. Microsoft documents it:
Asynchronous (overlapped) read and write operations are not supported
by anonymous pipes. This means that you cannot use the ReadFileEx and
WriteFileEx functions with anonymous pipes. In addition, the
lpOverlapped parameter of ReadFile and WriteFile is ignored when these
functions are used with anonymous pipes.
(Indeed, if you look inside kernel32.dll, on Windows XP for example, CreatePipe does not set the lower bit on the seventh parameter to NtCreateNamedPipeFile; that bit is set when CreateNamedPipe is called with FILE_FLAG_OVERLAPPED.)
Look for Dave Hart's MyCreatePipeEx implementation; it can be used as a drop-in replacement for CreatePipe when overlapped I/O is needed. Simply change PipeSerialNumber++ to InterlockedIncrement(&PipeSerialNumber) to avoid race conditions in MT code.
I think you have a typo:
CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&handles[h_Child_StdIn_Read], &handles[h_Child_StdIn_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdIn_Read], HANDLE_FLAG_INHERIT, 0);
change the last one to
SetHandleInformation(handles[h_Child_StdIn_Write], HANDLE_FLAG_INHERIT, 0);
that's also what they do at the MSDN example.
Asynchronous operations with I/O Completion Ports return 0 bytes transferred, although the I/O operations work as expected (my read buffers become full).
BYTE buffer[1024] = {0};
OVERLAPPED o = {0};
HANDLE file = CreateFile(
_T("hello.txt"),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
HANDLE completion_port = CreateIoCompletionPort(
file,
NULL,
0,
0
);
ReadFile(
file,
buffer,
1024,
NULL,
&o
);
In the work thread:
DWORD numBytes = 0;
LPOVERLAPPED po;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
0,
&po,
INFINITE
);
GetOverlappedResult(file, &o, &numBytes, FALSE);
Both functions return 0 bytes in numBytes, but buffer is filling. Is this expected behaviour?
Thanks.
For GetIoCompletionPort to work correctly, you need to specify a non-null pointer to a ULONG_PTR for it to write the 'key' value to:
ULONG_PTR key;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
&key,
&po,
INFINITE
);
To use GetOverlappedResult successfully, I believe you need to specify an event handle in the OVERLAPPED structure (strongly recommended in any case):
o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
Calling the two in succession as you were doesn't really accomplish much -- they both tell you about the same things. Though if you do call both in succession, you'll need to change the Event to be a manual-reset by changing the third parameter to CreateEvent to TRUE. My guess is that you were just trying both to see if you could get one to work. All things considered, I'd probably just use GetQueuedCompletionStatus, and leave it at that. Of course, you'll usually do more than call it once and quit. You normally call it in a loop, processing the current buffer you've read, then calling ReadFile again to read another buffer of info, something like this:
DWORD numBytes;
LPOVERLAPPED po;
while (GetQueuedCompletionStatus(completion_port, &numBytes, &key, &po, INFINITE)) {
std::cout << "\rRead: " << numBytes; // just to show it's set correctly.
process(buffer);
po->offset += sizeof(buffer);
ReadFile(file, buffer, sizeof(buffer), NULL, po);
}
At least in a quick test on my machine, this showed the number of bytes read correctly (sizeof(buffer) up to the last packet, then the remaining size of the file).