Named Pipes Issue - c++

I am trying to learn how named pipes work, and created 2 consoles to test the connectivity between server and client. Client will send a message to the server and the server will display the message, but instead of the message, it returns a value of "nullptr" as shown in the error exception break from VS.
below are my codes, do enlighten me if you found any problem with my code, and I am still learning..
Server.cpp
#include "cust_ostream.hpp"
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID buffer = NULL;
DWORD readbyte;
cout << "---Named Pipe Server Test---" << endl << endl;
cout << "Creating named pipe: \\\\.\\pipe\\mypipe" << endl;
HANDLE hPipe = CreateNamedPipeA("\\\\.\\pipe\\mypipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
if (!hPipe || hPipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe creation failed." << endl;
return 0;
}
cout << "Connecting pipe to client..." << endl;
BOOL connect = ConnectNamedPipe(hPipe, NULL);
if (!connect)
{
cout << "Connect named pipe failed" << endl;
}
cout << "Success! Reading pipe message from client..." << endl;
ReadFile(hPipe, buffer, sizeof(buffer), &readbyte, NULL);
c_cout << "Pipe message = " << *(int *)buffer << endl;
_getch();
return 0;
}
cust_ostream.hpp
#include <Windows.h>
#include <iostream>
#include <sstream>
using namespace std;
#define endl "\n"
class cust_ostream
{
public:
~cust_ostream()
{
cout << m_buffer.str();
}
template <typename T>
cust_ostream &operator<<(T const &value)
{
m_buffer << value;
return *this;
}
private:
ostringstream m_buffer;
};
#define c_cout cust_ostream()
and my client
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID data;
DWORD writebyte;
int i = 2;
cout << "---Named Pipe Client---" << endl << endl;
cout << "Creating pipe file: \\\\.\\pipe\\mypipe" << endl;
HANDLE pipe = CreateFileA("\\\\.\\pipe\\mypipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (!pipe || pipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe client failed." << endl;
return 0;
}
cout << "Pipe connected to server, sending data..." << endl;
WriteFile(pipe, &i, sizeof(i), &writebyte, NULL);
_getch();
return 0;
}

You need to wait for the NamedPipe to have a ConnectPipeReady event on it. As it stands, you are trying to create the pipe without actually seeing if it was succesfull. See the MSDN documentation for Named Pipes here: https://msdn.microsoft.com/en-ca/library/windows/desktop/aa365592(v=vs.85).aspx
Specifically, this block:
while (1)
{
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
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)
{
_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() );
return -1;
}
// All pipe instances are busy, so wait for 20 seconds.
if ( ! WaitNamedPipe(lpszPipename, 20000))
{
printf("Could not open pipe: 20 second wait timed out.");
return -1;
}
}
Also you shouldn't use #define endl "\n", use std::endl

You have initialized your buffer as NULL which means that by default its length is zero. Now when you use the sizeof operator in your read function in server (to retrieve the message received by server from client), what happens is that you are asking the sizeof operator in Read function to read 0 bytes! which means that nothing will be read.
To solve this, you can declare a char array of size 100 or a size of a message which you are sure that won't be exceeded by client. Like if you are assuming that message by client is not going to be longer than lets say 60 characters, then you can create your char buffer to be of size 100 just to make sure that you do accommodate all the message by client.
And one more thing, if problem still persists, instead of using sizeof in read, use 100 or whatever the size of of your char buffer array. This should solve your problem.

Related

How can I read and write to pipes created for a child process in c++

I am making a tester program that opens a console application and reads it's standard input writes to it's standard output, but am having issues with the pipes. I am using named pipes since I might have to run this threaded or even open multiple executables to communicate with at once. These will need to remain running and continuously take input and give out put, as in a console calculator that asks if you if you want another calculation or to exit after each calculation.
Using error checking I have found that The pipes are created successfully, I apply them to the startupInfo struct and successfully open the executable. A note here, if I set a break point in visual studio just after the call to createProcess, the child process does show up in my task manager, the check STILL_ACTIVE is true and peaking at the pipe reveals an empty pipe. If no break point is set then I don't see it, and the check STILL_ACTIVE is false.
To simplify the problem I went back to basics, a simple hello world executable in c++. The calculator will be the next test. This prints hello world to the console and via a cin:get() waits for the enter key to be pressed. I ran this with the tester and tried to read the "Hello World" from the child process. I get nothing.
The end project will be open source, I don't want the user to have to download any other libraries to compile the project, and Boost::Process actually requires 2 install since process is not standard yet.
I know that I am close, here is my simple tester as one file with the process class extracted to be inline in the main. Note: I have enabled c++20 in my compiler.
// Tester.cpp
#include <string>
#include <string_view>
#include <vector>
#include <iostream>
#include <fstream>
#include <filesystem>
#include <io.h>
#include <fcntl.h>
#include <windows.h>
int main()
{
std::string data = "";
int id = 1;
std::string executable = "HelloWorld.exe";
if (_access((executable).c_str(), 0) != -1)
{
std::cerr << "Error: Executable file not found: " << executable << std::endl;
exit(0);
}
SECURITY_ATTRIBUTES saAttr{};
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
//Pipe names
std::wstring pipeErr = L"\\\\.\\pipe\\err_" + std::to_wstring(id);
std::wstring pipeOut = L"\\\\.\\pipe\\out_" + std::to_wstring(id);
std::wstring pipeIn = L"\\\\.\\pipe\\in_" + std::to_wstring(id);
// The Child error pipe for reading
CreateNamedPipeW(pipeErr.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 1024, 1024, 0, NULL);
HANDLE err_pipe = CreateFileW(pipeErr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &saAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
// The Child out pipe for reading
CreateNamedPipeW(pipeOut.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 1024, 1024, 0, NULL);
HANDLE out_pipe = CreateFileW(pipeOut.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &saAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
// The Child in pipe for writing
CreateNamedPipeW(pipeIn.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 0, NULL);
HANDLE in_pipe = CreateFileW(pipeIn.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &saAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (in_pipe == INVALID_HANDLE_VALUE || out_pipe == INVALID_HANDLE_VALUE || err_pipe == INVALID_HANDLE_VALUE)
{
std::cout << "Error Creating Handles, Code: " << GetLastError() << std::endl;
return 0;
}
// Make sure the handles' inheritance is set correctly
if (!SetHandleInformation(in_pipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ||
!SetHandleInformation(out_pipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ||
!SetHandleInformation(err_pipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
{
std::cerr << "Error: Failed to set handle information for the child process" << std::endl;
return 0;
}
// Set up the startup info struct
STARTUPINFOA startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(STARTUPINFOA);
startupInfo.hStdInput = in_pipe;
startupInfo.hStdOutput = out_pipe;
startupInfo.hStdError = err_pipe;
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
// Set up the process info struct
PROCESS_INFORMATION processInfo;
memset(&processInfo, 0, sizeof(processInfo));
// Create the child process
if (CreateProcessA(NULL, executable.data(), NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo) == 0)
{
std::cerr << "Error: Failed to create the child process" << std::endl;
return 0;
}
// Set the pipes to non-blocking mode
DWORD mode = PIPE_NOWAIT;
SetNamedPipeHandleState(out_pipe, &mode, NULL, NULL);
SetNamedPipeHandleState(err_pipe, &mode, NULL, NULL);
SetNamedPipeHandleState(in_pipe, &mode, NULL, NULL);
Sleep(500); //wait for child to start, may not be neccesary
// Get the exit code of the child process
DWORD exitCode;
GetExitCodeProcess(processInfo.hProcess, &exitCode);
if (exitCode == STILL_ACTIVE) {
// Set up the read buffer
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
DWORD bytesRead = 0;
DWORD bytesAvail = 0;
// Check if there is data available to read from the pipe
if (!PeekNamedPipe(out_pipe, buffer, sizeof(buffer), &bytesRead, &bytesAvail, NULL)) {
std::cerr << "PeekNamedPipe failed (" << GetLastError() << ").\n";
return 0;
}
if (bytesAvail == 0)
{
std::cerr << "Pipe is empty" << std::endl;
}
if (!ReadFile(out_pipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL))
{
std::cerr << "Failed to read from pipe. Error code: " << GetLastError() << std::endl;
return 0;
}
data = buffer;
}
if (data == "") {
std::cout << "Something went wrong. Code: " << GetLastError() << std::endl;
}
else {
std::cout << data << std::endl;
}
std::cout << "Press any key." << std::endl;
std::cin.get();
return 0;
}
and, for reference, here is helloworld.exe:
// HelloWorld.cpp
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
std::cin.get();
}
Thanks to #Igor Tandetnik!
Here is the working Tester.cpp:
// Tester.cpp
#include <string>
#include <string_view>
#include <vector>
#include <iostream>
#include <fstream>
#include <filesystem>
#include <io.h>
#include <fcntl.h>
#include <windows.h>
#include <aclapi.h>
constexpr auto BUFSIZE = 4096;
int main()
{
std::string data = "";
int id = 1;
std::wstring executable = L"HelloWorld.exe";
std::wstring argv = L"";
std::string name_c = "";
std::string path_c = "";
HANDLE hChildStd_IN_Rd = NULL;
HANDLE hChildStd_IN_Wr = NULL;
HANDLE hChildStd_OUT_Rd = NULL;
HANDLE hChildStd_OUT_Wr = NULL;
HANDLE hChildStd_ERR_Rd = NULL;
HANDLE hChildStd_ERR_Wr = NULL;
size_t size;
wcstombs_s(&size, nullptr, 0, executable.c_str(), executable.length());
name_c.resize(size);
wcstombs_s(&size, name_c.data(), name_c.size(), executable.c_str(), executable.length());
wchar_t current_dir[FILENAME_MAX];
if (_wgetcwd(current_dir, FILENAME_MAX) == nullptr) {
std::cerr << "Error getting current working directory. Code:" << GetLastError() << std::endl;
exit(0);
}
wchar_t path_exe[MAX_PATH];
GetModuleFileName(NULL, path_exe, MAX_PATH);
std::wstring path = path_exe;
path = std::filesystem::path(path).parent_path();
path += L"\\";
path += executable;
wcstombs_s(&size, nullptr, 0, path.c_str(), path.length());
path_c.resize(size);
wcstombs_s(&size, path_c.data(), path_c.size(), path.c_str(), path.length());
int found = _waccess_s(path.c_str(), 0);
if (found != 0)
{
std::cerr << "Error: Executable file not found: " << name_c << std::endl;
exit(0);
}
SECURITY_ATTRIBUTES sa_attr{};
sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
sa_attr.bInheritHandle = TRUE;
sa_attr.lpSecurityDescriptor = NULL;
// Create the pipes
if (!CreatePipe(&hChildStd_OUT_Rd, &hChildStd_OUT_Wr, &sa_attr, 0)
|| !CreatePipe(&hChildStd_IN_Rd, &hChildStd_IN_Wr, &sa_attr, 0)
|| !CreatePipe(&hChildStd_ERR_Rd, &hChildStd_ERR_Wr, &sa_attr, 0)) {
std::cout << "Error Creating Pipes, Code: " << GetLastError() << std::endl;
return 1;
}
if (hChildStd_OUT_Rd == INVALID_HANDLE_VALUE || hChildStd_OUT_Wr == INVALID_HANDLE_VALUE
|| hChildStd_IN_Rd == INVALID_HANDLE_VALUE || hChildStd_IN_Wr == INVALID_HANDLE_VALUE
|| hChildStd_ERR_Rd == INVALID_HANDLE_VALUE || hChildStd_ERR_Wr == INVALID_HANDLE_VALUE)
{
std::cout << "Error Creating Handles, Code: " << GetLastError() << std::endl;
return 1;
}
// Set up the startup info struct
STARTUPINFOW startup_info;
ZeroMemory(&startup_info, sizeof(STARTUPINFOW));
startup_info.cb = sizeof(STARTUPINFOW);
startup_info.hStdOutput = hChildStd_OUT_Wr;
startup_info.hStdError = hChildStd_ERR_Wr;
startup_info.hStdInput = hChildStd_IN_Rd;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
// Set up the process info struct
PROCESS_INFORMATION process_info;
memset(&process_info, 0, sizeof(process_info));
// Create the child process
if (!CreateProcess(path.data(), NULL, &sa_attr, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info))
{
std::cerr << "Error: Failed to create the child process. Code: " << GetLastError() << std::endl;
return 1;
}
// Get the exit code of the child process
DWORD exitCode;
GetExitCodeProcess(process_info.hProcess, &exitCode);
if (exitCode != STILL_ACTIVE) {
std::wcout << "Unable to Start Process: " << executable.c_str() << std::endl;
return 1;
}
std::wcout << "Started Process: " << executable.c_str() << std::endl;
Sleep(500); //wait for child to start, may not be neccesary
// Get the exit code of the child process
GetExitCodeProcess(process_info.hProcess, &exitCode);
if (exitCode == STILL_ACTIVE) {
// Set up the read buffer
DWORD bytesRead{}, dwWritten{};
CHAR buffer[BUFSIZE]{};
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
bSuccess = ReadFile(hChildStd_OUT_Rd, buffer, BUFSIZE, &bytesRead, NULL);
if (!bSuccess || bytesRead == 0)
{
std::cerr << "Failed to read from pipe. Error code: " << GetLastError() << std::endl;
return 1;
}
std::vector<char> v_data(buffer, buffer + bytesRead);
data = std::string(v_data.data(), v_data.size());
}
std::cout << "Recieved from Child: " << data << std::endl;
if (data == "") {
std::cout << "Something went wrong. Code: " << GetLastError() << std::endl;
return 1;
}
else {
std::cout << data << std::endl;
}
CloseHandle(process_info.hThread);
std::cout << "Press any key." << std::endl;
std::cin.get();
return 0;
}

privilege escalation with named pipe in c++

I have this code:
#include <Windows.h>
#include <namedpipeapi.h>
#include <processthreadsapi.h>
#include <iostream>
int main() {
LPCWSTR pipeName = L"\\\\.\\pipe\\TestSV";
HANDLE serverPipe;
int err = 0;
BOOL isPipeConnected;
BOOL isPipeOpen;
DWORD bytesWritten = 0;
std::wcout << "Creating named pipe " << pipeName << std::endl;
serverPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 2048, 2048, 0, NULL);
isPipeConnected = ConnectNamedPipe(serverPipe, NULL);
if (isPipeConnected) {
std::wcout << "Incoming connection to " << pipeName << std::endl;
}
std::wcout << "Impersonating the client..." << std::endl;
ImpersonateNamedPipeClient(serverPipe);
err = GetLastError();
std::wcout << "Impersonating status..." << err << std::endl;
STARTUPINFO si = {};
wchar_t command[] = L"C:\\Windows\\System32\\notepad.exe";
std::wcout << command << std::endl;
PROCESS_INFORMATION pi = {};
HANDLE threadToken = GetCurrentThreadToken();
std::wcout << "Thread token " << threadToken << std::endl;
CreateProcessWithTokenW(threadToken, LOGON_WITH_PROFILE, command, NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
err = GetLastError();
std::wcout << "Elv status..." << err << std::endl;
return 0;
}
I create a server pipe and listen for an incoming connection. In my case, I run:
cmd.exe /c echo hello > //./pipe/TestSV
I am supposed to be able to impersonate the thread token of cmd.exe and launch notepad.exe as the SYSTEM user instead of the local user, however something is not working correctly.
I checked Microsoft documentation, and it states that a successful call to CreateProcessWithTokenW() and ImpersonateNamedPipeClient() should return a non-zero value. I got large numbers as my return in both cases, so I am kind of confused why it's not working. Am I missing something?
UPDATE: I updated the code as suggested, but it is still not working correctly, and I get a different error now:
#include <Windows.h>
#include <namedpipeapi.h>
#include <processthreadsapi.h>
#include <iostream>
int main() {
LPCWSTR pipeName = L"\\\\.\\pipe\\TestSV";
LPVOID pipeBuffer = NULL;
HANDLE serverPipe;
HANDLE threadToken = NULL;
DWORD readBytes = 0;
DWORD readBuffer = 0;
int err = 0;
BOOL isPipeConnected;
BOOL isPipeOpen;
BYTE bMessage[128] = { 0 };
DWORD bytesWritten = 0;
std::wcout << "Creating named pipe " << pipeName << std::endl;
serverPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 2048, 2048, 0, NULL);
isPipeConnected = ConnectNamedPipe(serverPipe, NULL);
if (isPipeConnected) {
std::wcout << "Incoming connection to " << pipeName << std::endl;
}
if (!ReadFile(serverPipe, &bMessage, 1, &bytesWritten, NULL)) {
std::wcout << "Failed to READ" << std::endl;
}
std::wcout << "Impersonating the client..." << std::endl;
if (!ImpersonateNamedPipeClient(serverPipe)) {
err = GetLastError();
std::wcout << "Impersonating error..." << err << std::endl;
}
// get a handle to this threads token
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &threadToken)) {
err = GetLastError();
std::wcout << "Token error..." << err << std::endl;
}
STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
wchar_t command[] = L"C:\\Windows\\System32\\notepad.exe";
int process_status = CreateProcessWithTokenW(&threadToken, LOGON_WITH_PROFILE, command, NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
err = GetLastError();
std::wcout << "Elv error..." << process_status << std::endl;
std::wcout << "Elv error..." << err << std::endl;
return 0;
}
First off, you are NOT checking the return values of ImpersonateNamedPipeClient() and CreateProcessWithTokenW() at all (like you do with ConnectNamedPipe()). You are checking the return value of GetLastError() instead. Not the same thing. GetLastError() is meaningless for these functions if they do not return FALSE on failure. So, use this instead:
if (!ImpersonateNamedPipeClient(serverPipe))
{
err = GetLastError();
std::wcout << "Impersonating failed..." << err << std::endl;
}
if (!CreateProcessWithTokenW(threadToken, LOGON_WITH_PROFILE, command, NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
err = GetLastError();
std::wcout << "Elv failed..." << err << std::endl;
}
That being said, once you have fixed that, you'll notice that ImpersonateNamedPipeClient() fails with error 1368 (ERROR_CANNOT_IMPERSONATE):
Unable to impersonate using a named pipe until data has been read from that pipe.
The ImpersonateNamedPipeClient() documentation states:
The ImpersonateNamedPipeClient function allows the server end of a named pipe to impersonate the client end. When this function is called, the named-pipe file system changes the thread of the calling process to start impersonating the security context of the last message read from the pipe. Only the server end of the pipe can call this function.
Typically, you would not impersonate a client until after the client has first sent you a request to access something that needs the client's security context. Read a request, then impersonate if needed, then access whatever is needed, then revert impersonation, and repeat, until the client is disconnected.
So, in your case, read the hello input first, then impersonate, then launch cmd.exe.

C++ windows.h WriteFile function

I am trying to display in console a list of running processes and the current time and save them to a text file using the WriteFile and windows.h functions. How to effectively redirect the output stream and "My data..." to a text file without using "freopen" in C ++?
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <chrono>
using namespace std;
int main()
{
char temp;
HANDLE h = CreateFile("process.txt", // name of the file
GENERIC_WRITE, // open for writing
0, // sharing mode, none in this case
0, // use default security descriptor
CREATE_ALWAYS, // overwrite if exists
FILE_ATTRIBUTE_NORMAL,
0);
if (h)
{
std::cout << "CreateFile() succeeded\n";
CloseHandle(h);
}
else
{
std::cerr << "CreateFile() failed:" << GetLastError() << "\n";
}
time_t actualTime = chrono::system_clock::to_time_t(chrono::system_clock::now());
cout << ctime(&actualTime);
cout << "My data..." << endl;
PROCESSENTRY32 proc32;
HANDLE hSnapshot;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
proc32.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hSnapshot, &proc32))
{
cout << proc32.szExeFile << endl;
while(Process32Next(hSnapshot, &proc32))
cout << proc32.szExeFile << endl;
}
WriteFile(HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
CloseHandle(hSnapshot);
system ("pause >nul");
return 0;
}
Use OPEN_ALWAYS instead of CREATE_ALWAYS and then use SetFilePointer to move the file pointer to the end of file.

How to read serial data from a bluetooth port? C++

I created a program to read serial data from a COM port using C++, however due to changes in my project I have to read data from a BT port. Since Im using a bluetooth adapter to connect my computer to the device I expected the reading process to be the same but apparently it is not. Since Im using the Window OS to perform this task GetLastError() returns 2 which means the specified file is not found. However when I use Arduino's serial monitor the data is read just fine. Does anyone know how to read from a BT port in C++? Im using Windows 8 by the way, here is my code:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
///-----------------------------Open port-----------------------------------------------------------------
// Name of port where device is found
LPCWSTR port = L"COM40";
// Open port for reading
HANDLE hComm = ::CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
// Check if port has been opened succesfully
if (hComm == INVALID_HANDLE_VALUE) std::cout << "Failed to open " << port << " error: " << GetLastError() << std::endl;
else std::cout << port << " has been opened succesfully\n";
///-----------------------------Configure port------------------------------------------------------------
// Create DCB structure
DCB dcb = { 0 };
// Get Comm state
if (!::GetCommState(hComm, &dcb)) std::cout << "Failed to get Comm state, error: " << GetLastError() << std::endl;
// Configure strcutre
dcb.DCBlength = sizeof(DCB);
// Set Baud rate
dcb.BaudRate = CBR_9600;
// Set number of bytes in bits that are recieved through the port
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
// Check if port has been configured correctly
if (!::SetCommState(hComm, &dcb)) std::cout << "\nFailed to set Comm State, error: " << GetLastError();
else std::cout << "Comm state has been set succesfully\n";
///-----------------------------Read data-------------------------------------------------------------------
char buffer;
DWORD maxBytes = 1;
if (!::ReadFile(hComm, &buffer, maxBytes, NULL, NULL)) std::cout << "\nFailed to read from " << port << " error: " << GetLastError() << std::endl;
else std::cout << "File has been read succesfully\n";
///-----------------------------Write to text file----------------------------------------------------------
std::fstream file;
int counter = 0;
// Writing to text file will be done later
while (ReadFile(hComm, &buffer, maxBytes, NULL, NULL))
{
std::cout << buffer;
}
///-----------------------------Close port------------------------------------------------------------------
CloseHandle(hComm);
file.close();
std::cout << "\nCOM40 has been closed!\n";
return 0;
}

c++ cant transfer data through com port when hyperterminal is connected

I am trying to make RS-232 communication between the PC and the PC MCU PIC. So I started making the PC program first in C++, and it was errorless, and according to the cout I made to output the status it should be working, but I wanted to be sure. So I downloaded Hyperterminal and connected Tx to Rx pin in serial com port, but whenever I try to connect the hyperterminal it gives an error, saying access denied (error 5) when I try to run my C++ program. I don't understand where the problem really is. Here's the full code, if the problem was the code's, just to make sure:
main.c:
#include <windows.h>
#include <winbase.h>
#include <iostream>
PDWORD sent;
char buf;
int main(){
DCB serial;
HANDLE hserial = CreateFile("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
serial.DCBlength = sizeof(DCB);
serial.BaudRate = CBR_9600;
serial.fBinary = true;
serial.fParity = false;
serial.ByteSize = 8;
serial.Parity = NOPARITY;
serial.StopBits = ONESTOPBIT;
char result = BuildCommDCB("baud=9600 parity=N data=8 stop=1", &serial);
if(result != 0){
std::cout << "DCB Structure Successfully Created!" << std::endl;
}else{
std::cout << "DCB Structure Creation Failed!" << std::endl;
}
if(hserial != INVALID_HANDLE_VALUE){
std::cout << "COM Port Handle Successfully Created!" << std::endl;
}else{
std::cout << "COM Port Handle Creation Failed!" << std::endl;
std::cout << GetLastError() << std::endl;
}
char res = WriteFile(hserial, "0xFF", 1, sent, NULL);
if(res != 0){
std::cout << "Writing to COM Port Successfull!" << std::endl;
}else{
std::cout << "Writing to COM Port Failed!" << std::endl;
std::cout << GetLastError() << std::endl;
}
CloseHandle(&hserial);
return 0;
}
Only one program at a time can open a particular COM port. You can do your test if you have two COM ports available.