I have faced with a strange behavior.
The manual claimed: "When two sockets are bound to the same port number but on different explicit interfaces, there is no conflict". Why the system fails in the following case on the step 3? Is it a bug in the OS? (my post on Microsoft forums has no answer)
Is there some workaround on this?
Step 1. process A binds the 127.0.1.1:88 (default) — OK
Step 2. process B binds the 127.0.0.1:88 (with SO_REUSEADDR) — OK
Step 3. process C binds the 127.0.0.1:88 (with SO_REUSEADDR) — fail (10013 WSAEACCES)
Note: the tcp-ports are the same, the interfaces are different and explicit (between step 1 and 2-3). User is the same.
The problem occurs in the Windows Vista (32-bit), Windows Server 2008 (32-bit), Window Server 2008 R2 (64-bit), etc.
In Windows XP it is all right: step 3 succeeds.
Update: just for reference, the same problem: Windows 7 socket bind behavior difference from XP, with reuse address socket option (WSAEACCES 10013 error)
Binding two sockets to the same explicit interface and port when both sockets use SO_REUSEADDR is guaranteed to succeed, even the Microsoft documentation says so. It has to be a bug in your code, either you are not enabling SO_REUSEADDR on both sockets prior to calling bind(), or you are not actually binding both sockets to the same explicit interface and port.
bind() does not return WSAEACCES if the interface/port are already in use. It returns WSAEADDRINUSE instead. WSAEACCES means you tried to bind to something that you do not have permission to bind to. That is a different kind of error condition.
Related
I am trying to determine the current session state using the Win32 API ::WTSQuerySessionInformation function by querying for SessionFlags of the WTSINFOEX_LEVEL1 structure according to the answers to C++: check if computer is locked.
On my machine (Windows 10 1703) SesssionFlags can reach only two (of three documented) values: WTS_SESSIONSTATE_UNLOCK and WTS_SESSIONSTATE_UNKNOWN. The latter seems to mean the same as the expected WTS_SESSIONSTATE_LOCK which I cannot reach, neither through <WinKey>+<L> nor by programmatically locking the session through ::LockWorkStation.
So my questions are:
Does WTS_SESSIONSTATE_LOCK exist?
If yes, then how can I reach that state?
If yes, what is the difference between both states (LOCK and UNKNOWN)?
According to SessionChangeReason Enumeration the .NET Framework distinguishes (correctly?) between just two corresponding states SessionUnlock and SessionUnlock. So the state of a session is triple or binary?
One would think that WTS_SESSIONSTATE_UNKNOWN means that the state is unknown and you should not interpret it as locked nor unlocked. It seems this member has a sorry history, MSDN says
Windows Server 2008 R2 and Windows 7: Due to a code defect, the usage of the WTS_SESSIONSTATE_LOCK and WTS_SESSIONSTATE_UNLOCK flags is reversed. That is, WTS_SESSIONSTATE_LOCK indicates that the session is unlocked, and WTS_SESSIONSTATE_UNLOCK indicates the session is locked.
Because the member is named SessionFlags and MSDN says "This can be one or more of the following values" one could imagine that more flags could be added over time and you should actually be doing:
isUnlocked = SessionFlags & WTS_SESSIONSTATE_UNLOCK;
(and the logic reversed on Windows 7). I don't think anyone does this so I doubt Microsoft will ever add more flags but you never know.
On my Windows 8 and 10.0.17134 machines it returns WTS_SESSIONSTATE_UNLOCK normally and WTS_SESSIONSTATE_LOCK when I press Win+L so it is possible you are doing something wrong?
I don't know what happens if a Windows 7+ machine tries to ask a Vista machine, maybe you get WTS_SESSIONSTATE_UNKNOWN or maybe the entire call fails because Vista does not support WTSSessionInfoEx.
The accepted answer in the question you linked to tells you to use WTSRegisterSessionNotification and it will provide you with the same values as SessionChangeReason and you don't have to pull to detect changes.
I am new to kernel mode windows driver development and having issues getting debug information out of the WFP callout samples. I am looking for either more options or tips of what I am doing wrong with the options I have been trying.
To start with I downloaded the WFP sampler and followed the instructions in it's description. I am using a Windows 8.1 x64 host and a Windows 7 x64 target connected via a simulated serial cable. They are both VirtualBox VMs.
The primary command I am debugging with is
WFPSampler.Exe -s PROXY -l FWPM_LAYER_ALE_BIND_REDIRECT_V4 -aaid "C:\Program Files (x86)\Internet Explorer\iexplore.exe" -pla 10.0.2.15 -v
Where 10.0.2.15 is the IP address of a diffrent network interface than the routing table is endign traffic to. I also used the following inspect command as recommended by the instructions:
WFPSampler.exe -s BASIC_PACKET_EXAMINATION -l FWPM_LAYER_INBOUND_IPPACKET_V4 -v
"netsh wfp show state" shows the callout and filter associated with the expected layer
However I never got any messages from traceview as per the last steps of those instructions. Tracelog had similar lack of output. This was true with or without WPP tracing enabled on the driver project. I also tried higher verbosity, all to no effect.
Additionally the remote debugger in visual studio either stopped at "Driver Post Install Actions (x64) (possible reboot): Pass" or "Waiting to reconnect..." rebooting the target did not cause more output in the Debugger Immediate Window (the Output window never got any output). Rebooting the target VM did not get any unusual prompts (some things I read implied it should). The reconnect checkbox when setting up the debugger sometimes caused it to get past the "Waiting to reconnect..." prompt, other times it was not needed. I set a number of breakpoints that should have been hit including one at the top of every classify function and none were ever hit.
I tried to debug with WinDbg, but well, frankly I can't find the documentation about how to use this tool. I start it on the target machine and chose kernel debug, local. then I get a prompt that tells me the symbol search path is invalid and no clue what I am supposed to set it to. Any documentation on how to use this tool as opposed to just installing it may be helpful if it lets me debug these callout drivers.
Finally of course I tried just debugging it based on symptoms and I find that the examination callout does nothing as far as I can tell, while the proxy callout just eats all traffic from the targeted application, with one caveat. That caveat is that when I target firefox or chrome with the proxy callout and try to launch that app it fails to launch a UI and the partially started process cannot be killed from task manager.
I assumed that behavior may be the result of the sample failing to check FwpsQueryPacketInjectionState but modifying as best I can figure out that should be used does not seem to change the behavior.
So in short I am stuck and need direction please?
I started experimenting with the WFPSampler and also discovered that tracing didn't work. Oddly enough, there was a lot of additional code to make WPP tracing work on multiple OS's, but the sample doesn’t capture any trace events. So I debugged it and found the call to the nt!WmiTraceMessage always passed 2 as the TRACE_HANDLE. This seemed bad. Safe it to say, this wasn't exactly straight forward to unscramble WPP macros and then finally find the origin in the .vcxprog file. The definition of WPP_COMPID_LEVEL_LOGGER(COMPID,LEVEL)=2 is incorrect. While I was there, I also converted the DbgPrintEx Levels to match Tace_Level by adding 2 so Error/Warning match the model.
Complete the following steps for SysLib/WFPSampler and Sys/WFPSamplerCalloutDriver
Open the Project
Right Click on WFPSamplerCalloutDriver
Unload Project
Right Cick on WFPSamplerCalloutDriver
Edit WFPSamplerCalloutDriver.vcxproj
Type: WppPreprpocessorDefinitions
Change this definition in both places in the file:
To:
<WppTraceFunction>DbgPrintEx(COMPID,LEVEL,MSG,...)</WppTraceFunction
<WppPreprocessorDefinitions>WPP_COMPID_LEVEL_LOGGER(COMPID,lvl)=(WPP_CONTROL(0).Logger),;WPP_COMPID_LEVEL_ENABLED(COMPID,lvl)=(WPP_CONTROL(0).Level >= lvl+2)</WppPreprocessorDefinitions>
Save the File
Right Cick on WFPSamplerCalloutDriver
Click Reload Project
Rebuild
I believe if you adopt this model of using DbgPrintEx as your trace function, you can switch to WPP without editing the entire project. However, I still think it's better to just convert in your program.
Cheers,
John
Not exactly an answer to this question, I never got a debugger working, but an explanation of why the wfpsampler sample didn't work for proxying by ALE layers. The end goal of this project.
In the Proxy callout there were these lines (i think before my refactor they were in the PerformProxySocketRedirection method):
if (ipProtocol == IPPROTO_TCP)
pBindRequest1->portReservationToken = (pRedirectData)->pProxyData->tcpPortReservationToken;
else if (ipProtocol == IPPROTO_UDP)
pBindRequest1->portReservationToken = (pRedirectData)->pProxyData->udpPortReservationToken;
udpPortReservationToken or tcpPortReservationToken should have been initialized by a call to CreatePersistentUdpPortReservation or CreatePersistentTcpPortReservation and this is handled in a helper function named HlprWinSockCreatePortReservation, but said helper function is never called, from anywhere in the entire solution. Those fields are never set, anywhere, ever.
Additionaly, that value only needed set if the local port was being changed, but that block of code executed regardless.
remove these lines, and so long as you don't change the local port, the ale redirect sample works as you would expect including changing the outgoing interface if you change the local IP. If you do need to change the local port, you will have to use HlprWinSockCreatePortReservation to initialize the appropriate port reservation token variable in the PROXY_DATA. This must be done in user mode, so you need to do it in the service when setting up the filter.
Disclaimer: I think that is the only important change, but if you are here for a solution to this problem know that while tracking this down without a working debugger i changed a ridiculously large amount of code so there may have been more to it I forgot over the course of the last few weeks. But I did go back and verify that that block was always called and those fields were never set in the original.
I'm interfacing to a hardware serial device using QT, I've based my application roughly around the Terminal example, but as the communication needs to be very synchronous the serial handler is living in another thread. The connection is via a 2xRS232 to USB adaptor with an FTDI chipset.
The serial comms are fine, I can connect, send commands, etc. However, when I quit and reload the application the serial port seems to be blocked.
Let COM1 be the connected device, COM2 is unconnected.
If I run the program, do a bit of talking to the hardware and quit, I can no longer connect to COM1 the next time I run the program (the data leds don't flash on the adaptor) unless I attempt to connect to COM2 first. Once I've tried this I can then connect back to COM1 as usual. This behaviour is not seen in the reference utility for the hardware and so must be down to some way I'm handling the port.
My close code is:
void mydevice::closeSerialPort()
{
this->stop();
serial->close();
emit serialClosed();
emit log("Serial port closed.");
}
serial is a QTSerialPort. First a stop command is sent to turn off the hardware (not relevant to the problem, it's just a convenience) and then I send a close command to the serial.
I have a subclassed QWidget for my main window, which calls this command on exit:
/* In the constructor */
connect(this, SIGNAL(WindowClosed()), mydevice, SLOT(closeSerialPort()));
void mainwindow::closeEvent(QCloseEvent *event)
{
emit WindowClosed();
event->accept();
}
Is there any reason for this behaviour? I assume I'm blocking the port open somehow, but surely it would complain that it's already open.
Another odd issue is that say the device is on COM1 and I open it in my application, COM1 is unresponsive in the other utility and the device appears on COM2. However, when I switch back to my program and fiddle a bit, the device appears on COM1 again (though always in COM2 in the other application).
So there seems to be a fairly simple solution, though I don't understand exactly what was causing the problem.
I have two threads, each controlling a different serial device. The serial configuration is accessed through a dialog which I stole from a QT example (the terminal). Each thread has an instance of this settings dialog. It seems that something goes wrong when selecting the port - for instance all the selections in the dialog actually point to the same COM port if checked in a debugger.
Anyway, I chalked this up to non-thread-safe code and changed the program to just ask for the serial port name as the data rates, stop bits, parity, etc are fixed by the hardware and aren't going to change. This has fixed the problem.
There are two possible answers, I think:
Your process doesn't terminate in spite of you closing the main window. How have you verified that the process is, in fact, terminated?
Your use of qt's serialport module exposes a bug in FTDI's driver. That's not unthinkable, but I'd call it a remote possibility at the moment.
Personally I don't see any use for the serial port emulation of the FTDI driver, it's adding an extra layer for no good reason. The D2XX interface is the way to do it, if you don't want to use something like libftdi. On Windows, I've found D2XX and libftdi to be the only viable alternatives, with libftdi working much better than D2XX on virtual machines.
Don't know if this could be useful.
I have a similar issue (but not the same) with a prolific pl2303.
In my case when i close the port (or even at startup, before opening it!), data is received anyway somehow and presented immediately when i open the port.
This happens only with an usb-rs232 adapter, if I use the ttyS0 (physical serial port) the problem does not appear.
The solution for me was forcing QSerialPort::clear() to clear buffers just after QSerialPort::open(). This avoids signal readyRead to be emitted and thus unwanted data to be received.
I have an application in windows, that opens a com port. It attempts to call a comport, then fails and prompts me with an error.
The issue is this is very legacy software that we no longer have the source code for. I'm wondering if anyone knows of a way that can trace, or follow a program calling a com port to find out what com port its attempting to allocate.
Appearantly you can use Process Explorer (as called out in this post) to search for processes using serial ports. It sounds like you should be able to use the same searching concept called out the other post to find what you need.
I actually gave up on this solution and re-wrote the entire program in a week, it had to be done due to binary compatibility issues with the PCI cards.
There's getaddrinfo() for blocking host resolution, but is there a non blocking method?
I don't think there is such a thing but you can always wrap it in a thread and use a semaphore to signal completion.
Linux has getaddrinfo_a(). See the StackOverflow tag getaddrinfo-a, such as this question "How to use getaddrinfo_a to do async resolve with glibc". But I guess this isn't applicable for Windows.
There is a cross-platform library c-ares for asynchronous DNS requests, which says it runs on Windows. (I haven't tried it myself.)
From the MSDN page on GetAddrInfoEx the OVERLAPPED parameter says:
On Windows 7 and Windows Server 2008 R2 or earlier, this parameter is currently reserved and must be set to NULL since asynchronous operations are not supported.
This means you can only use the OVERLAPPED function in Windows 8 and newer. Unless steve can show otherwise that it works in older version of windows...
From Windows Vista and Windows Server 2008 you can use GetAddrInfoEx with an OVERLAPPED structure.
Once the hEvent event is set in the OVERLAPPED structure use GetAddrInfoExOverlappedResult.