Fetching Data with winapi - winapi

I've found on google this code and adapted somewhat. As far as that goes without problems. However, I have much in the output file at the very beginning of a blank line to. I do not know how I can get off this.
I try to get data from a php.
$echo "hello file";
And the C++
int main()
{
HINTERNET connect = InternetOpen("MyBrowser",0 ,0, 0, 0);
if(!connect){
cout<<"Connection Failed or Syntax error";
return 0;
}
HINTERNET OpenAddress = InternetOpenUrl(connect, http://www.myurl.com/winapi.php", 0, 0, 0, 0);
if ( !OpenAddress )
{
DWORD ErrorNum = GetLastError();
cout<<"Failed to open URL \nError No: "<<ErrorNum;
InternetCloseHandle(connect);
return 0;
}
char DataReceived[4096];
DWORD NumberOfBytesRead = 0;
ofstream data;
data.open("output.txt");
while(InternetReadFile(OpenAddress, DataReceived, 4096,
&NumberOfBytesRead) && NumberOfBytesRead) {
DataReceived[NumberOfBytesRead]='\x00';
data<< DataReceived;
}
system( "pause" );
}
In the file at the beginning of a blank line is too much. How do I remove them?

You have a buffer overflow if InternetReadFile() actually reads 4096 bytes. You do not need to null-terminate the buffer, just write the buffer as-is up to the number of bytes actually read by using the write() method instead of the << operator:
int main()
{
HINTERNET connect = InternetOpen("MyBrowser",0 ,0, 0, 0);
if (!connect)
{
cout << "Connection Failed or Syntax error";
return 0;
}
HINTERNET OpenAddress = InternetOpenUrl(connect, "http://www.myurl.com/winapi.php", 0, 0, 0, 0);
if (!OpenAddress)
{
DWORD ErrorNum = GetLastError();
cout << "Failed to open URL" << endl << " Error No: " << ErrorNum;
InternetCloseHandle(connect);
return 0;
}
ofstream data("output.txt");
if (!data)
{
cout << "Failed to open txt file";
InternetCloseHandle(OpenAddress);
InternetCloseHandle(connect);
return 0;
}
char DataReceived[4096];
DWORD NumberOfBytesRead = 0;
do
{
if (!InternetReadFile(OpenAddress, DataReceived, 4096, &NumberOfBytesRead))
{
DWORD ErrorNum = GetLastError();
cout << "Failed to read from URL" << endl << " Error No: " << ErrorNum;
InternetCloseHandle(OpenAddress);
InternetCloseHandle(connect);
return 0;
}
if (NumberOfBytesRead == 0)
break;
data.write(DataReceived, NumberOfBytesRead);
}
while (true);
cout << "Finished reading from URL";
system( "pause" );
return 0;
}
With that said, if you are still seeing the extra line appear in the file, then use a packet sniffer to check the data actually being transmitted by PHP and make sure it is not sending an extra blank line to begin with. If it is, then you need to address the issue on the PHP side, not the client side.

Related

How do I capture the stdin/stderr from a process that I'm spawning a windows process?

So, I'm trying to capture the stdout and stderr from a process that I'm spawning.
I create some fifos:
HANDLE hstdout;
while ((hstdout = CreateNamedPipe(
stdout_filename.c_str()
, PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE
, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS
, 10
, 4096
, 4096
, 0
, &sa)) == INVALID_HANDLE_VALUE)
{
// In case the fifo is already in use, add a _ to the name and try again.
stdout_filename += L"_";
}
I do the same for stderr.
Then I create the process, with all that it entails:
PROCESS_INFORMATION pi = {};
ZeroMemory(&pi, sizeof(pi));
STARTUPINFO sui = {
sizeof(STARTUPINFO) // size
, 0 // reserved
, nullptr // desktop
, nullptr // title
, 0, 0, 0, 0 // x, y, cx, cy
, 0, 0 // x buffer, y buffer
, 0 // fill attribute
, STARTF_FORCEOFFFEEDBACK // flags
| STARTF_USESTDHANDLES
, false // show window
, 0 // reserved
, 0 // reserved
, GetStdHandle(STD_INPUT_HANDLE) // stdin
, hstdout // stdout
, hstderr // stderr
};
BOOL success
= CreateProcess(
nullptr // application name
, &cmdline[0] // command line
, nullptr // process attributes
, nullptr // security attributes
, true // inherit handles
, CREATE_NO_WINDOW // creation flags
| INHERIT_PARENT_AFFINITY
, nullptr // environment
, nullptr // current directory
, &sui // startup info
, &pi // process info
);
Then I wait on the handles:
if (success) {
WCHAR buffer[4096];
DWORD bytesRead;
enum { eStdOut, eStdErr, eProcess };
HANDLE handles[] = { hstdout, hstderr, pi.hProcess };
DWORD waitResult;
bool process_terminated = false;
do {
waitResult = WaitForMultipleObjects(_countof(handles), handles, TRUE, INFINITE);
switch (waitResult) {
case WAIT_TIMEOUT:
log_fs << L"Error: Wait timed out\n";
break;
case WAIT_FAILED:
log_fs << L"Error: Wait failed\n";
break;
case eStdOut + WAIT_OBJECT_0:
// stdin signaled
if (ReadFile(hstdout, buffer, _countof(buffer), &bytesRead, nullptr)) {
log_fs.write(buffer, bytesRead);
wcout.write(buffer, bytesRead);
}
else {
log_fs << "Error reading from stdout" << endl << get_error() << endl;
}
break;
case eStdErr + WAIT_OBJECT_0:
// stderr signaled
if (ReadFile(hstderr, buffer, _countof(buffer), &bytesRead, nullptr)) {
log_fs.write(buffer, bytesRead);
wcerr.write(buffer, bytesRead);
}
else {
log_fs << "Error reading from stderr" << endl << get_error() << endl;
}
break;
case eProcess + WAIT_OBJECT_0:
// process signaled it terminated
log_fs << L"Process terminated" << endl;
break;
case eStdOut + WAIT_ABANDONED_0:
case eStdErr + WAIT_ABANDONED_0:
case eProcess + WAIT_ABANDONED_0:
// One of the handles have been abandoned.
log_fs << L"Error: wait abandoned " << (waitResult - WAIT_ABANDONED_0)
<< endl << get_error() << endl;
break;
default:
log_fs << L"Error: Unknown " << waitResult
<< " (" << (waitResult - WAIT_OBJECT_0)
<< ", " << (waitResult - WAIT_ABANDONED_0) << ")"
<< endl << get_error() << endl;
break;
}
} while (waitResult != WAIT_OBJECT_0 + eProcess);
if (!GetExitCodeProcess(pi.hProcess, &exitCode)) {
log_fs << L"Error getting return code\n";
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
I then test it with my test program:
int main()
{
std::cout << "Hello World!\n";
std::cerr << "Hello Underworld!\n";
// std::wstring str;
// std::wcin >> str;
}
What happens is that without the comments, it executes to the error else in the eStdOut + WAIT_OBJECT_0 case. With the windows error string being "Waiting for a process to open the other end of the pipe." It then blocks on WaitForMultipleObjects indefinitely.
If I were to uncomment the last two lines in my test file, my application just blocks on WaitForMultipleObjects indefinitely.
What am I doing wrong?
If you take a look at the Creating a Child Process with Redirected Input and Output example on MSDN you will see
Use CreatePipe to create an anonymous pipe.
Configure inheritance of the read and write end of the pipes.
After the child process has been created they CloseHandle the ends of the pipes they don't need before they read/write to the pipes!
The trick of closing the write end of stdout means you can read from it until the pipe breaks. When that happens you can WaitForSingleObject on the process...

PRINTER_INFO_6 not available using WIn32 api

I have been trying to get printer status from a DNP rx1 printer, but the status of the printer does not change when I open the tray of the printer. Here is an example using py32win library to access the status and it always return status = 0 event when the tray is open.
device_name = win32print.GetDefaultPrinter()
handle = win32print.OpenPrinter(device_name)
# Get the default properties for the printer
properties = win32print.GetPrinter(handle, 2)
When I try win32print.GetPrinter(handle, 6) # 6 = print_info_6 I get the some NotImplementedException. So my guess is that the firmware of the printer have not implemented print_info_6. So I can't get the status from the printer
I have also tried using powershell with:
Get-Printer | Select Name, PrinterStatus
Also no change in status when I open the tray or if there is a paper jam.
Is there anything that I'm overlooking? Is there anything else I can try to get the status of the printer?
PRINTER_INFO_6 works for me in C++ on Windows 10 1903 with OneNote printer.
And when I pause the printer I get status 0x00000001 (PRINTER_STATUS_PAUSED).
The C++ code I used for testing.
#pragma comment(lib, "Winspool")
int main()
{
DWORD bufSize;
WCHAR* buf = NULL;
HANDLE hPrinter = NULL;
PRINTER_INFO_6 info = {};
DWORD needed;
BOOL result = FALSE;
DWORD err;
// Get required buffer size
result = GetDefaultPrinter(NULL, &bufSize);
if(!result)
{
err = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER != err)
{
std::cout << "GetDefaultPrinter failed with error: \n" << GetLastError();
return 0;
}
}
buf = (WCHAR*)calloc(bufSize, sizeof(WCHAR));
result = GetDefaultPrinter(buf, &bufSize);
if (!result)
{
std::cout << "GetDefaultPrinter failed with error: \n" << GetLastError();
return 0;
}
std::wcout << "Printer name: " << buf << "\n";
result = OpenPrinter(buf, &hPrinter, NULL);
if (!result)
{
std::cout << "OpenPrinter failed with error: \n" << GetLastError();
return 0;
}
result = GetPrinter(hPrinter, 6, (LPBYTE)&info, sizeof(PRINTER_INFO_6), &needed);
if (!result)
{
err = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER != err)
{
std::cout << "GetPrinter failed with error: \n" << GetLastError();
return 0;
}
}
BYTE* statBuf = (BYTE*)calloc(needed, sizeof(BYTE));
result = GetPrinter(hPrinter, 6, statBuf, needed, &needed);
if (!result)
{
std::cout << "GetPrinter failed with error: \n" << GetLastError();
return 0;
}
std::cout << "Printer status (low 32bit): " << *((DWORD*)statBuf) << "\n";
statBuf += sizeof(DWORD);
std::cout << "Printer status (high 32bit): " << *((DWORD*)statBuf) << "\n";
getchar();
}
Some issues I found in testing:
Pinter status defined as a DWORD (4 bytes) in PRINTER_INFO_6 structure but GetPrinter requries 8 bytes for it (needed == 8). So you will get ERROR_INSUFFICIENT_BUFFER error when you pass a PRINTER_INFO_6 structure as pPrinter parameter.
There is only PRINTER_INFO_6 defined but no _PRINTER_INFO_6W (Unicode) and _PRINTER_INFO_6A (ANSI) mentioned in the document.

Full duplex named pipe lockup when written to

I'm trying to use one NamedPipe for bi-direction IPC. In my mind (and I can't find more information on MSDN), one full-duplex pipe would be sufficient. Here's my code.
//Compiled with these commands during my test:
//g++ -DCLIENT -o client.exe xxx.cpp
//g++ -DSERVER -o server.exe xxx.cpp
#include <iostream>
#include <windows.h>
using namespace std;
DWORD WINAPI ReadingThread(LPVOID a)
{
HANDLE pipe = (HANDLE)a;
BOOL result;
char buffer[256];
DWORD numBytesRead;
while (true)
{
result = ReadFile(pipe, buffer, sizeof(buffer) - 1, &numBytesRead, NULL);
if (result)
{
buffer[numBytesRead] = 0;
cout << "[Thread] Number of bytes read: " << numBytesRead << endl;
cout << "[Thread] Message: " << endl
<< buffer << endl
<< endl;
}
else
{
cout << "[Thread] Failed to read data from the pipe. err=" << GetLastError() << endl;
break;
}
}
return 0;
}
int main(int argc, const char **argv)
{
#ifdef CLIENT
cout << "[Main] Connecting to pipe..." << endl;
HANDLE pipe = CreateFileA("\\\\.\\pipe\\PipeTest", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#else
cout << "[Main] Creating an instance of a named pipe..." << endl;
HANDLE pipe = CreateNamedPipeA("\\\\.\\pipe\\PipeTest", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 1, 0, 0, 0, NULL);
#endif
if (pipe == NULL || pipe == INVALID_HANDLE_VALUE)
{
cout << "[Main] Failed to acquire pipe handle." << endl;
return 1;
}
#ifdef CLIENT
#else
cout << "[Server] Waiting for a client to connect to the pipe..." << endl;
BOOL result = ConnectNamedPipe(pipe, NULL);
if (!result)
{
cout << "[Server] Failed to make connection on named pipe." << endl;
CloseHandle(pipe);
return 1;
}
cout << "[Server] Client is here!" << endl;
{
const char *buf = "Hello pipe!\n";
WriteFile(pipe, buf, strnlen(buf, 30), 0, 0);
}
#endif
CreateThread(0, 0, ReadingThread, pipe, 0, 0);
cout << "[Main] Ready to send data." << endl;
while (true)
{
char buffer[128];
DWORD numBytesWritten = 0;
BOOL result;
cin >> buffer;
if (!strcmp(buffer, "q"))
{
break;
}
cout << "[Main] Writing data to pipe..." << endl;
result = WriteFile(pipe, buffer, strnlen(buffer, _countof(buffer)), &numBytesWritten, 0);
if (result)
{
cout << "[Main] Written " << numBytesWritten << " bytes to the pipe." << endl;
}
else
{
cout << "[Main] Failed to write data to the pipe. err=" << GetLastError() << endl;
}
}
CloseHandle(pipe);
cout << "[Main] Done." << endl;
return 0;
}
I can get the "Hello pipe!" message from server-side to client-side. And I'm expecting to type some string on either program's terminal and press enter, and see it on the other side.
However after the hello message, both program will stuck on the WriteFile call. Meanwhile the thread is stuck at the ReadFile call. How can I make it work, or did I left something out?
when file created for synchronous I/O (flag FO_SYNCHRONOUS_IO present in FILE_OBJECT ) all I/O operations on file is serialized - new operation will be wait in I/O manager before passed to driver, until current(if exist) not complete. in concurrent can execute only single I/O request. if we do blocked read in dedicated thread - all another I/O request on this file will be blocked until read not complete. this related not only to write. even query file name/attributes will block here. as result render reading in separate not help here - we block on first write attemp. solution here use asynchronous files - this let any count of I/O operation execute in concurrent.
Named Pipes in Windows are HALF DUPLEX. As demonstrated on Windows 10. The MSDN Documentation is Wrong. A request has been submitted to Microsoft to correct their documentation.
While a pipe can be opened on the client to be "Generic Read | Generic Write" you can NOT do both at the same time.
And Overlapped IO submitted after the First Overlapped IO will break the pipe.
You can submit overlapped io. Then Wait for it to finish. Then submit the next overlapped io. You can not simultaneously Submit overlapped Reads AND overlapped Writes.
This is by definition, "Half Duplex".

Using QIODevice with anonymous pipes

I want to use a QIODevice in order to read from a unnamed pipe if data is available.
I tried this with QFile:
m_pFile_Pipe = new QFile();
HANDLE hRead, hWrite;
connect(m_pFile_Pipe, SIGNAL(readyRead()), this, SLOT(OutputAvailable_QFile()));
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CreatePipe(&hRead, &hWrite, &sa, 0);
auto fhRead = _open_osfhandle((intptr_t)hRead, _O_RDONLY);
auto OpenResult = m_pFile_Pipe->open(fhRead, QIODevice::ReadOnly);
The "raw" pipe itself works, I can read data from it.
However, readyRead() is never signaled and during testing:
void TestPipe() {
char acBuffer[128];
DWORD NumBytesRead;
auto NumBytes = m_pFile_Pipe->bytesAvailable();
qDebug() << "NumBytes" << NumBytes;
ReadFile(hRead, acBuffer, sizeof(acBuffer), &NumBytesRead, NULL);
qDebug() << QString::fromUtf8(acBuffer);
while (m_pFile_Pipe->canReadLine()) {
auto out = m_pFile_Pipe->readLine(512);
qDebug() << "Line: " << out;
}
auto out_all = m_pFile_Pipe->readAll();
qDebug() << "Raw: " << out_all;
}
NumBytes was always 0, canReadLine() always returned false, and readAll() did not return.
ReadFile() could read the expected data.
Is there a QOIDevice to use for anonymous pipes?
The Qt docs say that QLocalSocket shall be used for named pipes, but I did not find anything about anonymous pipes.

Problem reconnecting to the named pipe

I have a named pipe server and client. (Doing this in VC++).
Server does
CreateNamedPipe
ConnectNamedPipe
WriteFile
Disconnect
Repeat from 2 to 4
Client does
CreateFile
ReadFile
The order of execution is as follows,
Server -- CreateNamedPipe
Client -- CreateFile
Server -- ConnectNamedPipe (should return immediately as the client is already connected)
Server -- WriteFile
Client -- ReadFile
Server -- DisconnectNamedPipe
Client -- CloseHandle
goto 2
This works fine for the first time. However problem occurs when client tries to connects for the second time. When the client tries to connect (CreateFile) for the second time before the server did ConnectNamedPipe (but after disconnectnamedpipe), it gets ERROR_PIPE_BUSY. It works if client calls createfile after the server calls ConnectNamedPipe.
Is there anyway that i can get client connected (CreateFile) before server called ConnectNamedPipe (after DisconnectNamedPipe)?
Server code:
pipe_handle.pipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\testpipe1"),
PIPE_ACCESS_OUTBOUND |
FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFFER_SIZE, // output buffer size
BUFFER_SIZE, // input buffer size
2000, // client time-out
NULL);
if (pipe_handle.pipe == INVALID_HANDLE_VALUE) {
std::cout << "Error while creating pipe" << std::endl;
return -1;
}
std::cout <<"Connecting to named pipe" << std::endl;
std::cout<< "Somebody connected to named pipe" << std::endl;
int ac;
for (ac=0; ac<2; ac++) {
char a[25];
// Wait for some input. This helps me to start the client in other terminal.
cin >> a;
cout << "Connecting..." << endl;
ConnectNamedPipe(pipe_handle.pipe, 0);
cout << "Connect pipe returned." << endl;
// Wait for some input.
cin >> a;
string message = "Test message";
DWORD bytes_written;
if (!WriteFile(pipe_handle.pipe, message.c_str(), message.size(),
&bytes_written, NULL)) {
DWORD er = GetLastError();
char errs[200];
sprintf(errs, "Error : %ld", er);
std::cout << "Error communicating to client.";
std::cout << errs;
}
std::cout << "Written to pipe";
FlushFileBuffers(pipe_handle.pipe);
if (!DisconnectNamedPipe(pipe_handle.pipe)) {
std::cout << "Disconnect failed"<< GetLastError() << endl;
} else {
std::cout << "Disconnect successful"<<endl;
}
}
Client Code:
while (1) {
std::cout << "Returned" << std::endl;
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
FILE_FLAG_OVERLAPPED, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY) {
std::cout<< "Could not open pipe " << GetLastError() << std::endl;
return -1;
}
// All pipe instances are busy, so wait for sometime.
if ( ! WaitNamedPipe(lpszPipename, NMPWAIT_USE_DEFAULT_WAIT)) {
std::cout<< "Could not open pipe: wait timed out." << std::endl;
}
}
OVERLAPPED ol1;
memset(&ol1, 0, sizeof(ol1));
ol1.Offset = 0;
ol1.OffsetHigh = 0;
ol1.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE events[1];
events[0] = ol1.hEvent;
cbToWrite = (lstrlen(message)+1)*sizeof(TCHAR);
DWORD bytes_to_read = 2000;
char * buf = reinterpret_cast<char *>(malloc(bytes_to_read));
DWORD bytes_read;
std::cout << "Waiting for read" << std::endl;
bool a = ReadFile(hPipe, buf, bytes_to_read, &bytes_read, &ol1);
if ( ! fSuccess) {
std::cout << "WriteFile to pipe failed. GLE " << GetLastError() << std::endl;
}
std::cout << "Waiting for multiple objects" << std::endl;
WaitForMultipleObjects(1, events, FALSE, INFINITE);
std::cout << "multiple objects returned" << std::endl;
printf("\nMessage sent to server");
CancelIo(hPipe);
CloseHandle(hPipe);
If you get ERROR_PIPE_BUSY on the CreateFile() call in the client, you need to call WaitNamedPipe() and then retry when it returns. If you get a return of zero from WaitNamedPipe() that means it timed out without the pipe becoming available. You'll never see that happen if you pass NMPWAIT_WAIT_FOREVER as the timeout.
You also need to keep in mind that the pipe may become busy again between the time WaitNamedPipe() returns and you call CreateFile(); therefore, you need to do it in a loop. Like this:
while (true)
{
hPipe = CreateFile(pipeName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hPipe == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_PIPE_BUSY)
{
if (!WaitNamedPipe(pipeName, NMPWAIT_USE_DEFAULT_WAIT))
continue; // timeout, try again
}
else
return false; // error
}
else
break; // success
}
EDIT:
I simplified your code and now it works fine. Working server and client follow.
Server:
#include <windows.h>
#include <stdio.h>
int main(void)
{
HANDLE pipe;
const DWORD BUFFER_SIZE = 1024;
pipe = CreateNamedPipe("\\\\.\\pipe\\testpipe1",
PIPE_ACCESS_OUTBOUND |
FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFFER_SIZE, // output buffer size
BUFFER_SIZE, // input buffer size
2000, // client time-out
NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
printf("Error while creating pipe\n");
return -1;
}
printf("Connecting to named pipe\n");
int ac;
for (ac=0; ac<2; ac++)
{
// Wait for some input. This helps me to start the client in other terminal.
printf("Connecting...\n");
ConnectNamedPipe(pipe, 0);
printf("Connect pipe returned.\n");
// Wait for some input.
char * message = "Test message";
DWORD bytes_written;
if (!WriteFile(pipe, message, strlen(message)+1, &bytes_written, NULL))
{
DWORD er = GetLastError();
char errs[200];
sprintf_s(errs, "Error : %ld", er);
printf("Error communicating to client.\n");
printf(errs);
}
printf("Written to pipe\n");
FlushFileBuffers(pipe);
if (!DisconnectNamedPipe(pipe))
{
printf("Disconnect failed %d\n", GetLastError());
}
else
{
printf("Disconnect successful\n");
}
}
}
Client:
#include <windows.h>
#include <stdio.h>
int main(void)
{
HANDLE hPipe;
while (1)
{
printf("Returned\n");
hPipe = CreateFile("\\\\.\\pipe\\testpipe1",
GENERIC_READ,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
printf("Could not open pipe %d\n", GetLastError());
return -1;
}
// All pipe instances are busy, so wait for sometime.
if ( ! WaitNamedPipe("\\\\.\\pipe\\testpipe1", NMPWAIT_USE_DEFAULT_WAIT))
{
printf("Could not open pipe: wait timed out.\n");
}
}
char *message = "hello";
DWORD cbToWrite = (strlen(message)+1)*sizeof(message[0]);
DWORD bytes_to_read = 2000;
char * buf = reinterpret_cast<char *>(malloc(bytes_to_read));
DWORD bytes_read;
printf("Waiting for read\n");
bytes_read = 0;
ReadFile(hPipe, buf, bytes_to_read, &bytes_read, 0);
if (bytes_read <= 0)
{
printf("ReadFile from pipe failed. GLE \n");
}
else
printf("Read %d bytes: %s\n", bytes_read, buf);
CloseHandle(hPipe);
return 0;
}
On the Server side when you decide to break the connection you must use chain:
1) CloseHandle (Pipe);
2) DisconnectNamedPipe (Pipe);

Resources