Fast Loopback Socket Windows 8 machine - windows

I currently searching for some performance problems in our distributed multiprocess application!
Thats the reason I would like to try fast loopback sockets
SIO_LOOPBACK_FAST_PATH descreption and msdn desc.
here is my code fragment for opening server socket:
TcpipSocket::TcpipSocket(FullIPAddress const& address)
: m_Port(address.m_Port)
, m_IPAddress(address.m_Address)
, m_Socket(INVALID_SOCKET)
{
if (0 == ms_NumberOfInstances)
{
initNetwork(NULL); // here i call the WSAStartup function
}
m_Socket = ::socket(TCPSocketFamily, TCPSocketType, TCPProtocol);
if (INVALID_SOCKET == m_Socket)
{
throwException(ConstrName);
}
else
{
// this is the code to enable the FAST Loopback Sockets see [1]
int OptionValue =1;
DWORD NumberOfBytesReturned =0;
int status=::WSAIoctl(m_Socket,
SIO_LOOPBACK_FAST_PATH,
&OptionValue,
sizeof(OptionValue),
NULL,
0,
&NumberOfBytesReturned,
0,
0);
if (SOCKET_ERROR == status)
{
DWORD LastError = ::WSAGetLastError();
if (WSAEOPNOTSUPP == LastError)
{
std::ostringstream out;
out << "This system is not Windows Windows Server 2012/Windows 8, \n";
out << "and the call is not supported.\n";
out << "ErrorNumber: "<< LastError;
throwException(out.str().c_str());
}
else
{
std::ostringstream out;
out << "TcpipSocket::Loopback Fastpath WSAIoctl failed: ";
out << "\nErrorNumber: "<< LastError;
throwException(out.str().c_str());
}
}
}
}
The problem: I always receive the error WSAEOPNOTSUPP
running the example on Windows 8 64 bit with all updates..
What did I miss? regarding the example, it should work straight forward?
The code is written on a win 7 x64 with VS2012
I using the Platform toolset "Visual Studio 2012 (v110)"

Related

What's the order of use of Win32 APIs for Server-client Pipe comm. in C++ (CreateNamedPipe, WriteFile, CreateFile, ReadFile)

I am trying to write a server/client program in C++, in Visual Studio 2019, using Win32 APIs.
This is the referred documentation: Named Pipe Open Modes
I have used 4 APIs:
On the server side (the one creating the pipe and writing to it): CreateNamedPipe(), WriteFile()
On the client side (the one connecting and reading from the pipe): CreateFile(), ReadFile()
However, I observe the server is NOT able to write to the pipe.
Following is the code I have used.
Servermain.cpp
#include <iostream>
#include <windows.h>
using namespace std;
void namedPipeServer()
{
HANDLE hPipeServer;
char Wbuffer[1024] = "Hello, from the pipe server!";
DWORD dwWrite;
BOOL writeSuccessFlag;
//Create a named pipe
hPipeServer = CreateNamedPipe(
TEXT("\\\\.\\pipe\\Agentpipe"), //lpName
PIPE_ACCESS_OUTBOUND, //dwOpenMode
PIPE_TYPE_BYTE, //dwPipeMode
1, //nMaxInstances
1024 * 16, //nOutBufferSize
1024 * 16, //nInBufferSize
NMPWAIT_USE_DEFAULT_WAIT, //nDefaultTimeOut
NULL); //lpSecurityAttributes
cout << "Inside namedPipeServer()" << endl;
if (hPipeServer != INVALID_HANDLE_VALUE)
{
cout << "Just writing to pipe" << endl;
writeSuccessFlag = WriteFile(
hPipeServer, //HANDLE hFile
Wbuffer, //LPCVOID lpBuffer
30, //DWORD nNumberOfBytesToWrite
&dwWrite,
NULL //LPOVERLAPPED lpOverlapped
);
if (writeSuccessFlag)
{
cout << "Server has written to pipe!" << endl;
}
else
{
cout << "Unsuccessful write to pipe, From Agent" << endl;
}
}
else
{
cout << "Unsuccesful pipe connection. hPipeServer: " << hPipeServer << endl;
}
}
int main()
{
cout << "Inside Agent server. Creating a named pipe.\n" << endl;
namedPipeServer();
while (1);
return 0;
}
Clientmain.cpp:
#include <iostream>
#include <windows.h>
using namespace std;
void readFromPipe()
{
HANDLE hPipeClient;
char rBuffer[1024];
DWORD dwRead;
BOOL readSuccessFlag = 0;
//Connect to the server pipe: \\.\\pipe\\Agentpipe
cout << "Inside readFromPipe()." << endl;
hPipeClient = CreateFile(
TEXT("\\\\.\\pipe\\Agentpipe"), //lpFileName
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
NULL,
NULL
);
while (hPipeClient != INVALID_HANDLE_VALUE)
{
cout << "Just connecting to pipe" << endl;
readSuccessFlag = ReadFile(
hPipeClient, //HANDLE hFile,
rBuffer, //LPVOID lpBuffer,
30, //DWORD nNumberOfBytesToRead,
&dwRead, //LPDWORD lpNumberOfBytesRead,
NULL //LPOVERLAPPED lpOverlapped
);
if (readSuccessFlag)
{
cout << "Client has read from pipe of Agent!" << endl;
cout << "From Agent Pipe: " << rBuffer << endl;
}
else
{
cout << "Unsuccessful Pipe read!" << endl;
}
}
if(hPipeClient == INVALID_HANDLE_VALUE)
{
cout << "Unsuccesful pipe connection at client end. hPipeClient: " << hPipeClient << endl;
}
}
int main()
{
cout << "Inside the client. Calling readFromPipe()" << endl;
readFromPipe();
while (1);
return 0;
}
When the above program is executed, it shows that the server is NOT able to write to the pipe, and the output on the server-side is:
Inside Agent server. Creating a named pipe.
Inside namedPipeServer()
Just writing to pipe
Unsuccessful write to pipe, From Agent
Output on the client console is:
Inside the client. Calling readFromPipe()
Inside readFromPipe().
Just connecting to pipe
Upon looking into the sample program in the Win32 documentation, I have observed that the order of use of these Win32 APIs is different, that looks like below:
Pipe Server program:
main(){
...
namedPipeServer()
...
}
void namedPipeServer()
{
...
CreateFile()
WriteFile()
...
}
Pipe Client program:
main(){
...
readFromPipe()
...
}
void readFromPipe()
{
...
CreateNamedPipe()
ReadFile()
...
}
I would be happy if anyone can provide me with clarity on the use of CreateNamedPipe() & CreateFile() especially.
Does the server have to use CreateFile() first (to create the pipe, before writing to it), or can I use CreateNamedPipe()?
Is the order of use of the APIs in MY program posted incorrect? If it is, please specify why.

Programmatically Change Windows Laptop's Refresh Rate

I'm thinking of coding something up that will change a laptop's refresh rate based on whether or not the device is plugged in.
From my research, these are two links I came across. One is 20 years old and the other is from Microsoft, but I don't see any mentions of refresh rate specifically.
https://www.codeproject.com/Articles/558/Changing-your-monitor-s-refresh-rate
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-changedisplaysettingsa?redirectedfrom=MSDN
Does anyone have any insight into how to do this? I'm not too particular about what language would have to be used for it, so let me know whatever would be most viable. Of course I'd also have to be able to check a change in state for plugged in/unplugged, but I haven't gotten to that point yet.
I'm mostly targeting Windows 10 since that's what my device is on.
You can use EnumDisplaySettings to enumerate the information of the current display device, and then set the display by ChangeDisplaySettingsA.
If you want to modify the refresh rate, you only need to modify the dmDisplayFrequency parameter of DEVMODEA.
Here is the sample:
#include <Windows.h>
#include <iostream>
using namespace std;
int main(int argc, const char* argv[])
{
DEVMODE dm;
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
cout << "DisplayFrequency before setting = " << dm.dmDisplayFrequency << endl;
dm.dmDisplayFrequency = 60; //set the DisplayFrequency
LONG ret = ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, NULL);
std::cout << "ChangeDisplaySettingsEx returned " << ret << '\n';
if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
cout << "DisplayFrequency after setting = " << dm.dmDisplayFrequency << endl;
}
switch (ret)
{
case DISP_CHANGE_SUCCESSFUL:
std::cout << "display successfully changed\n";
break;
case DISP_CHANGE_BADDUALVIEW:
std::cout << "The settings change was unsuccessful because the system is DualView capable\n";
break;
case DISP_CHANGE_BADFLAGS:
std::cout << "An invalid set of flags was passed in.\n";
break;
case DISP_CHANGE_BADMODE:
std::cout << "The graphics mode is not supported.\n";
break;
case DISP_CHANGE_BADPARAM:
std::cout << "An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n";
break;
case DISP_CHANGE_FAILED:
std::cout << "The display driver failed the specified graphics mode.\n";
break;
case DISP_CHANGE_NOTUPDATED:
std::cout << "Unable to write settings to the registry.\n";
break;
case DISP_CHANGE_RESTART:
std::cout << "The computer must be restarted for the graphics mode to work.\n";
break;
}
}
system("pause");
}
This example is not always successful. Whether you can modify the refresh rate depends on whether your monitor supports it. This is the output of successful setup:

Programmatically installing unsigned driver with CreateService

I am trying to install an unsigned driver that I got from an older embedded solution (winxp embedded), that I am currently reversing. I am installing and setting up the driver like the software does, however, with the driver being unsigned, I am unable to install it, at least programmatically.
Installation code:
std::cout << "Installing driver from " << this->driverPath << std::endl;
SC_HANDLE scManager = OpenSCManagerA(0, 0, 0xF003F);
if (!scManager) {
std::cout << "Failed to open SCManager" << std::endl;
return;
}
SC_HANDLE hService = CreateServiceA(scManager, this->serviceName, this->serviceName, 0xF01FF, 1, 3, 1, this->driverPath, 0, 0, 0, 0, 0);
if (!hService) {
hService = OpenServiceA(scManager, this->serviceName, 0xF01FF);
if (!hService) {
std::cout << "error: " << std::to_string(GetLastError()) << std::endl;
CloseServiceHandle(scManager);
return;
}
else {
std::cout << "OK!" << std::endl;
}
}
if (!StartServiceA(hService, 0, 0)) {
std::cout << "StartService failed: " << std::to_string(GetLastError()) << std::endl;
return;
}
The command line output based on this is as follows:
Installing driver from C:\driver.sys
OK!
StartService failed: 1275
The error code is that of ERROR_DRIVER_BLOCKED. I tried to force Windows to allow me to install this after all by going into advanced startup and disabling signature enforcement, but the only effect was that Windows no longer gave me a separate OS window telling me it blocked driver installation.
I have tried the three methods described here, without any luck: https://www.maketecheasier.com/install-unsigned-drivers-windows10/
(However, I assume these are made for users hand-installing the drivers).
How can I tell Windows to allow me to programmatically install this unsigned driver?
The driver was 32-bit, the system was 64-bit. Using a 32-bit system solves this.

Cause of serial port transmitting bad data and WriteFile return wrong number of bytes written?

Bugfix update:
As of Jun, 2013 FTDI did acknowledge to me that the bug was real. They have since released a new version of their driver (2.8.30.0, dated 2013-July-12) that fixes the problem. The driver made it through WHQL around the first of August, 2013 and is available via Windows Update at this time.
I've re-tested running the same test code and am not able to reproduce the problem with the new driver, so at the moment the fix seems to be 'upgrade the driver'.
The original question:
I've got an 8 port USB-serial device (from VsCOM) that is based on the FTDI FT2232D chip. When I transmit at certain settings from one of the ports, AND I use the hardware handshaking to stop and start the data flow from the other end, I get two symptoms:
1) The output data sometimes becomes garbage. There will be NUL characters, and pretty much any random thing you can think of.
2) The WriteFile call will sometimes return a number of bytes GREATER than the number I asked it to write. That's not a typo. I ask for 30 bytes to be transmitted and the number of bytes sent comes back 8192 (and yes, I do clear the number sent to 0 before I make the call).
Relevant facts:
Using FTDI drivers 2.8.24.0, which is the latest as of today.
Serial port settings are 19200, 7 data bits, odd parity, 1 stop bit.
I get this same behavior with another FTDI based serial device, this time a single port one.
I get the same behavior with another 8 port device of the same type.
I do NOT get this behavior when transmitting on the built-in serial ports (COM1).
I have a very simple 'Writer' program that just transmits continuously and a very simple 'Toggler' program that toggles RTS once per second. Together these seem to trigger the issue within 60 seconds.
I have put an issue into the manufacturer of the device, but they've not yet had much time to respond.
Compiler is mingw32, the one included with the Qt installer for Qt 4.8.1 (gcc 4.4.0)
I'd like to know first off, if there's anything that anyone can think of that I could possibly do to trigger this behavior. I can't conceive of anything, but there's always things I don't know.
Secondly, I've attached the Writer and Toggler test programs. If anyone can spot some issue that might trigger the program, I'd love to hear about it. I have a lot of trouble thinking that there is a driver bug (especially from something as mature as the FTDI chip), but the circumstances force me to think that there's at least SOME driver involvement. At the least, no matter what I do to it, it shouldn't be returning a number of bytes written greater than what I asked it to write.
Writer program:
#include <iostream>
#include <string>
using std::cerr;
using std::endl;
#include <stdio.h>
#include <windows.h>
int main(int argc, char **argv)
{
cerr << "COM Writer, ctrl-c to end" << endl;
if (argc != 2) {
cerr << "Please specify a COM port for parameter 2";
return 1;
}
char fixedbuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
std::string portName = "\\\\.\\";
portName += argv[1];
cerr << "Transmitting on port " << portName << endl;
HANDLE ph = CreateFileA( portName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // default security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // overlapped I/O
NULL ); // hTemplate must be NULL for comm devices
if (ph == INVALID_HANDLE_VALUE) {
cerr << "CreateFile " << portName << " failed, error " << GetLastError() << endl;
return 1;
}
COMMCONFIG ccfg;
DWORD ccfgSize = sizeof(COMMCONFIG);
ccfg.dwSize = ccfgSize;
GetCommConfig(ph, &ccfg, &ccfgSize);
GetCommState(ph, &(ccfg.dcb));
ccfg.dcb.fBinary=TRUE;
ccfg.dcb.fInX=FALSE;
ccfg.dcb.fOutX=FALSE;
ccfg.dcb.fAbortOnError=FALSE;
ccfg.dcb.fNull=FALSE;
// Camino is 19200 7-O-1
ccfg.dcb.BaudRate = 19200;
ccfg.dcb.Parity = ODDPARITY;
ccfg.dcb.fParity = TRUE;
ccfg.dcb.ByteSize = 7;
ccfg.dcb.StopBits = ONESTOPBIT;
// HW flow control
ccfg.dcb.fOutxCtsFlow=TRUE;
ccfg.dcb.fRtsControl=RTS_CONTROL_HANDSHAKE;
ccfg.dcb.fInX=FALSE;
ccfg.dcb.fOutX=FALSE;
COMMTIMEOUTS ctimeout;
DWORD tout = 10;// 10 ms
ctimeout.ReadIntervalTimeout = tout;
ctimeout.ReadTotalTimeoutConstant = tout;
ctimeout.ReadTotalTimeoutMultiplier = 0;
ctimeout.WriteTotalTimeoutMultiplier = tout;
ctimeout.WriteTotalTimeoutConstant = 0;
SetCommConfig(ph, &ccfg, sizeof(COMMCONFIG));
SetCommTimeouts(ph, &ctimeout);
DWORD nwrite = 1;
for(;;) {
nwrite++;
if (nwrite > 30) nwrite = 1;
DWORD nwritten = 0;
if (!WriteFile(ph, fixedbuf, nwrite, &nwritten, NULL)) {
cerr << "f" << endl;
}
if ((nwritten != 0) && (nwritten != nwrite)) {
cerr << "nwrite: " << nwrite << " written: " << nwritten << endl;
}
}
return 0;
}
Toggler program:
#include <iostream>
#include <string>
using std::cerr;
using std::endl;
#include <stdio.h>
#include <windows.h>
int main(int argc, char **argv)
{
cerr << "COM Toggler, ctrl-c to end" << endl;
cerr << "Flips the RTS line every second." << endl;
if (argc != 2) {
cerr << "Please specify a COM port for parameter 2";
return 1;
}
std::string portName = "\\\\.\\";
portName += argv[1];
cerr << "Toggling RTS on port " << portName << endl;
HANDLE ph = CreateFileA( portName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // default security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // overlapped I/O
NULL ); // hTemplate must be NULL for comm devices
if (ph == INVALID_HANDLE_VALUE) {
cerr << "CreateFile " << portName << " failed, error " << GetLastError() << endl;
return 1;
}
COMMCONFIG ccfg;
DWORD ccfgSize = sizeof(COMMCONFIG);
ccfg.dwSize = ccfgSize;
GetCommConfig(ph, &ccfg, &ccfgSize);
GetCommState(ph, &(ccfg.dcb));
ccfg.dcb.fBinary=TRUE;
ccfg.dcb.fInX=FALSE;
ccfg.dcb.fOutX=FALSE;
ccfg.dcb.fAbortOnError=FALSE;
ccfg.dcb.fNull=FALSE;
// Camino is 19200 7-O-1
ccfg.dcb.BaudRate = 19200;
ccfg.dcb.Parity = ODDPARITY;
ccfg.dcb.fParity = TRUE;
ccfg.dcb.ByteSize = 7;
ccfg.dcb.StopBits = ONESTOPBIT;
// no flow control (so we can do manually)
ccfg.dcb.fOutxCtsFlow=FALSE;
ccfg.dcb.fRtsControl=RTS_CONTROL_DISABLE;
ccfg.dcb.fInX=FALSE;
ccfg.dcb.fOutX=FALSE;
COMMTIMEOUTS ctimeout;
DWORD tout = 10;// 10 ms
ctimeout.ReadIntervalTimeout = tout;
ctimeout.ReadTotalTimeoutConstant = tout;
ctimeout.ReadTotalTimeoutMultiplier = 0;
ctimeout.WriteTotalTimeoutMultiplier = tout;
ctimeout.WriteTotalTimeoutConstant = 0;
SetCommConfig(ph, &ccfg, sizeof(COMMCONFIG));
SetCommTimeouts(ph, &ctimeout);
bool rts = true;// true for set
for(;;) {
if (rts)
EscapeCommFunction(ph, SETRTS);
else
EscapeCommFunction(ph, CLRRTS);
rts = !rts;
Sleep(1000);// 1 sec wait.
}
return 0;
}
I don't have a good answer yet from FTDI, but I've got the following suggestions for anyone dealing with this issue:
1) Consider switching to a non-FTDI usb-serial converter. This is what my company did, but certainly this isn't an option for everyone (we're putting the chip in our own product). We're using Silicon Labs chips now, but I think there are one or two other vendors as well.
2) Per Hans Passant in the comments - reconsider the use of RTS/CTS signalling. If the writes don't fail due to blocking, then you shouldn't trigger this bug.
3) Set all writes to infinite timeout. Again, no fail due to blocking, no triggering of the bug. This may not be appropriate for all applications, of course.
Note that if pursuing strategy #3, if Overlapped IO is used for writes, then CancelIo and it's newer cousin CancelIoEx could be used to kill off the writes if necessary. I have NOT tried doing so, but I suspect that such cancels might also result in triggering this bug. If they were only used when closing the port anyway, then it might be you could get away with it, even if they do trigger the bug.
If anyone else is still seeing this -- update your FTDI driver to 2.8.30.0 or later, as this is caused by a driver bug in earlier versions of the FTDI driver.

SetCommState failing on Windows 7

We have code that talks to our USB COMM class device, which works fine under Windows XP but is failing under Windows 7. Specifically the call to SetCommState is failing. Here's a simplified snippet. Note that in this case we don't even change any fields from GetCommState, but the result is that SetCommState fails with an error code of 87 (illegal parameter).
DCB dcb;
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if (!GetCommState(m_hIDComDev, &dcb)) {
DWORD dwError = GetLastError();
CloseHandle(m_hIDComDev);
dlDebug(5, "SerialPort::openPort") << "GetCommState failed for" << m_portName << dwError;
return 0;
}
dlDebug(5, "SerialPort::openPort") << m_portName << "rate" << dcb.BaudRate << "size" << dcb.ByteSize;
// dcb.BaudRate = baud;
// dcb.ByteSize = 8;
if (!SetCommState(m_hIDComDev, &dcb)) {
DWORD dwError = GetLastError();
CloseHandle(m_hIDComDev);
dlDebug(5, "SerialPort::openPort") << "SetCommState failed for" << m_portName << dwError;
return 0;
}
Any ideas what might be going wrong? One thought is that the USB device descriptor is incorrect and Win7 is more rigorous about double-checking (but I'm a little skeptical about that as the device works fine under MacOS X and Linux with no issues). I'm stumped!
If you are working on 64 bit, maybe you have to set dcb.DCBLength not to sizeof(DCB) but to the next highest multiple of 8.

Resources