SetCommState failing on Windows 7 - 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.

Related

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.

EnumProcessModulesEx and CreateToolhelp32Snapshot fails - whatever 32bit or 64bit

Edit:
The answer of this question is here:
https://stackoverflow.com/a/27317947/996540
When you create a project in msvc, the option /DYNAMICBASE is default enabled
now. Because of ASLR(Address space layout randomization, since Windows Vista),
everytime you run an exe, it's load address is random.
I am doing the DLL injection job recently, so I did some research into it on
google, and have read some projects. Get the load address (base address) of an
exe is important.
It seems there're two simple APIs to do this: EnumProcessModulesEx and
CreateToolhelp32Snapshot. But I never succeeded.
So this is the code sample:
void TestEnumProcessModulesEx(const char* app)
{
std::cout << "Begin TestEnumProcessModulesEx(" << mybit() << ")" << std::endl;
STARTUPINFOA startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION processInformation = {0};
if (CreateProcessA(app, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
{
std::vector<HMODULE> buf(128);
DWORD needed = 0;
for (;;) {
if (EnumProcessModulesEx(processInformation.hProcess, &buf[0], DWORD(buf.size()*sizeof(HMODULE)), &needed, LIST_MODULES_ALL) == FALSE) {
DWORD ec = GetLastError();
std::cout << "GetLastError() = " << ec << std::endl;
break;
}
else if (needed <= buf.size() * sizeof(HMODULE)) {
break;
}
else {
const size_t oldSize = buf.size();
buf.resize(oldSize * 2);
}
}
ResumeThread(processInformation.hThread);
WaitForSingleObject(processInformation.hProcess, INFINITE);
}
std::cout << "End TestEnumProcessModulesEx(" << mybit() << ")" << std::endl;
}
To reduce the length of this Question, the complete code - including the
CreateToolhelp32Snapshot's test code - is not listed here, but you can get it
from:
https://dl.dropboxusercontent.com/u/235920/enum_proc_mods_sample.7z
or
https://www.mediafire.com/?cry3pnra8392099
"If this function is called from a 32-bit application running on WOW64, it can
only enumerate the modules of a 32-bit process. If the process is a 64-bit
process, this function fails and the last error code is ERROR_PARTIAL_COPY
(299)." - from MSDN.
And this is a blog post about this question:
http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/
Unfortunately, this does not make sence, because whatever the specified
process is 32bit or 64bit, it fails with 299; whatever the caller process is
32-bit or 64bit, it fails with 299.
This is the output of my sample:
Begin TestEnumProcessModulesEx(32bit)
GetLastError() = 299
hello world 32bit
End TestEnumProcessModulesEx(32bit)
Begin TestEnumProcessModulesEx(32bit)
GetLastError() = 299
hello world 64bit
End TestEnumProcessModulesEx(32bit)
Begin TestEnumProcessModulesEx(64bit)
GetLastError() = 299
hello world 32bit
End TestEnumProcessModulesEx(64bit)
Begin TestEnumProcessModulesEx(64bit)
GetLastError() = 299
hello world 64bit
End TestEnumProcessModulesEx(64bit)
As you see, any combination is failed.
My OS is Windows 7 64bit pro and my compiler is VS2013.
So, what can I do ?
I have no idea about the unsuccess of EnumProcessModulesEx and
CreateToolhelp32Snapshot, let's leave this question to the expert.
My goal is to get the load address (base address) of the child process, find
the entry point and patch it - the reason to patch the entry point is here:
https://opcode0x90.wordpress.com/2011/01/15/injecting-dll-into-process-on-load/
Since DLL injection is the main purpose of mine, I have to reconsider this
question. I would use the "CreateRemoteThread & LoadLibrary Technique"
http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_2
to do the DLL injection (In fact ASLR is not the barrier of this technique by the way),
Although there are so many limits in DLLMain
http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971%28v=vs.85%29.aspx
, but do a little works is OK: Find the base address of an exe using
GetModuleHandleA(NULL), save the HMODULE returned into shared memory,
next, the caller process read shared memory and get the HMODULE.
Synchronization mechanism is necessary of course.
So, the answer is IPC. (not every IPC mechanism is safe in DLLMain by the way)

Fast Loopback Socket Windows 8 machine

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)"

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.

Resources