GetCommState fails with error code 87.
Can this system call be used with any type of serial port? I have an RS422 USART card. Port can be configured as Sync or Async. I have it configured as Async and was using boost:asio. I noticed the failure while stepping through the code and ended up in the code below in a boost file. I took it out and put it in my main along with a call to CreateFile right before it. I get a good handle(handle is not INVALID_HANDLE_VALUE). I can't get it to return successful. Any ideas? I called the serial card tech support and I was told this call should work.
Here is my code:
using namespace std; // For memset.
DCB dcb;
//memset(&dcb, 0, sizeof(DCB));
SecureZeroMemory(&dcb, sizeof(DCB)); // tried this from a suggestion I saw online somewhere
dcb.DCBlength = sizeof(DCB);
if (!GetCommState(hDevice, &dcb))
{
DWORD last_error = ::GetLastError();
CloseHandle(hDevice);
exit(1);
// ec = boost::system::error_code(last_error,
// boost::asio::error::get_system_category());
//return ec;
}
If you were on a *NIX platform, check out /usr/include/errno.h (which probably has a #include for /usr/include/sys/errno.h) and see what matches up with your return code. Since you're on Windows, you'll have to hit up MSDN. Error code 87:
ERROR_INVALID_PARAMETER 87 One of the parameters was invalid.
I'd guess GetCommState() isn't liking your hDevice parameter. The call to SecureZeroMemory() shouldn't be necessary if you use memset(). Have you checked to see if all of the necessary parameters of dcb are set with respect to hDevice?
Related
Overview...
I have read How to get device interface GUID for a device? and How to open a handle to a device using its Device Instance ID?, but I'm still confused about how I am to (or whether I should even) use SetupDiEnumDeviceInterfaces paired with SetupDiGetDeviceInterfaceDetail to get a DevicePath that can be opened with CreateFile to access the device when no device interface class GUID is known. My question is based on the MSDN article here and here which rely on these functions.
More details...
The high level of my problem is I've got an audio USB device I need to send control transfer commands. To do so, I want to use WinUSB's API, and to do that I need to get a handle to the device via CreateFile. Unfortunately, there is no .inf file associated with the device and so there is no known device interface class GUID. If one plugs the device in, Windows associates with it usbaudio.sys as the driver. To start talking over WinUSB, I use libwdi to install WinUSB as the device driver so that I can communicate with it via the WinUSB API. To accomplish the install of WinUSB, libwdi dynamically creates a self-signed .cat and .inf file pair, which unfortunately has no device interface class defined. In fact, the INF file has the following in it:
[NoDeviceInterfaceGUID]
; Avoids adding a DeviceInterfaceGUID for generic driver
So, despite the fact I now have swapped out usbaudio.sys for winusb.sys, I'm unable to communicate with the device.
At first I thought maybe I should try using GUID_DEVINTERFACE_USB_DEVICE, reasoning that this is WinUSB and therefore seen as a generic USB device. But, if I invoke
SetupDiEnumDeviceInterfaces(_deviceList,
&devInfo,
&GUID_DEVINTERFACE_USB_DEVICE,
0,
&usbInterface)
it fails and GetLastError returns 259, or ERROR_NO_MORE_ITEMS immediately. I'm assuming this means it doesn't implement the interface?
So, in general, when no interface class guid is known, am I able to use the aforementioned functions in any form to get the full device path?
Thanks in advance for your time.
Yes, first you need to get a device information set for devices that implement the interface via SetupDiGetClassDevs, then pick one of the devices and read its device interface data, and use that to get the device interface detail that contains the device path.
Example:
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include <usbioctl.h>
#include <stdio.h>
BOOL DevicePath(_In_ LPCGUID interfaceGuid, DWORD instance)
{
BOOL result = FALSE;
PSP_DEVICE_INTERFACE_DETAIL_DATA_W devInterfaceDetailData = NULL;
HDEVINFO hDevInfo = SetupDiGetClassDevsW(interfaceGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(hDevInfo == INVALID_HANDLE_VALUE)
goto cleanup;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if(!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, interfaceGuid, instance, &devInterfaceData))
goto cleanup;
// Call this with an empty buffer to the required size of the structure.
ULONG requiredSize;
SetupDiGetDeviceInterfaceDetailW(hDevInfo, &devInterfaceData, NULL, 0, &requiredSize, NULL);
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto cleanup;
devInterfaceDetailData = malloc(requiredSize);
if(!devInterfaceDetailData)
goto cleanup;
devInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if(!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &devInterfaceData, devInterfaceDetailData, requiredSize, &requiredSize, NULL))
goto cleanup;
wprintf(L"%s\n", devInterfaceDetailData->DevicePath);
result = TRUE;
cleanup:
if(hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
free(devInterfaceDetailData);
return result;
}
int main()
{
for(DWORD i = 0; DevicePath(&GUID_DEVINTERFACE_USB_DEVICE, i); ++i)
;
}
Ordinarily XInput controllers are identified simply using an index corresponding to the player number of the controller. Is there a way to obtain more information about a controller with a specific index, such as its vendor ID, product ID, or device name?
Even better would be a identifier that corresponds uniquely and consistently to just that controller so that it can be distinguished from all other XInput devices regardless of its index, including another controller that's an identical model (i.e. same product and vendor ID), similar to the instance GUID available using DirectInput.
Can this be accomplished using XInput or another Microsoft API? I'm also open to using undocumented functions if need be.
There are a few undocumented functions inside the XInput1_4.dll. You can get the Vendor ID and Product ID like this:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Xinput.h>
#include <stdio.h>
struct XINPUT_CAPABILITIES_EX
{
XINPUT_CAPABILITIES Capabilities;
WORD vendorId;
WORD productId;
WORD revisionId;
DWORD a4; //unknown
};
typedef DWORD(_stdcall* _XInputGetCapabilitiesEx)(DWORD a1, DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES_EX* pCapabilities);
_XInputGetCapabilitiesEx XInputGetCapabilitiesEx;
void main()
{
HMODULE moduleHandle = LoadLibrary(TEXT("XInput1_4.dll"));
XInputGetCapabilitiesEx = (_XInputGetCapabilitiesEx)GetProcAddress(moduleHandle, (char*)108);
for (int i = 0; i < 4; ++i)
{
printf("Gamepad %d ", i);
XINPUT_CAPABILITIES_EX capsEx;
if (XInputGetCapabilitiesEx(1, i, 0, &capsEx) == ERROR_SUCCESS)
{
printf("connected, vid = 0x%04X pid = 0x%04X\n", (int)capsEx.vendorId, (int)capsEx.productId);
}
else
{
printf("not connected\n");
}
}
}
What XInput internally does is open a device, then call DeviceIoControl on it every time it reads the joypad. (control code 0x8000e00c)
You need to hook these functions imported by "XInput1_4.dll":
CreateFileW from "api-ms-win-core-file-l1-1-0.dll"
DuplicateHandle from "api-ms-win-core-handle-l1-1-0.dll"
CloseHandle from "api-ms-win-core-handle-l1-1-0.dll"
DeviceIoControl from "api-ms-win-core-io-l1-1-0.dll"
Using the hooks for CreateFileW, DuplicateHandle and CloseHandle, you can keep track of what filename is associated with a handle.
Then when you see a call to DeviceIoControl with control code 0x8000e00c, you will know what filename is being read.
The first time you call XInputGetState, it will open multiple devices, and call DeviceIoControl multiple times, regardless of what player number you have asked for. You are only interested in the last filename seen by DeviceIoControl before XInputGetState returns. And if XInputGetState indicates the controller is not plugged in, disregard the filename you have collected for that controller number.
Examples of filenames I have seen on my own computer:
\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}&vid_045e&pid_02e0&ig_00#8&7074921&2&0000#{ec87f1e3-c13b-4100-b5f7-8b84d54260cb}
\\?\usb#vid_045e&pid_028e#1&1a590e2c&1&01#{ec87f1e3-c13b-4100-b5f7-8b84d54260cb}
edit:
One more hook is required as well.
CoCreateInstance from "api-ms-win-core-com-l1-1-0.dll", to hook creating the undocumented IDeviceBroker COM object. If it can successfully create an IDeviceBroker COM object, it will use that instead of the call to CreateFileW. Parameters will be: CLSID_DeviceBroker = {acc56a05-e277-4b1e-a43e-7a73e3cd6e6c}, IID_IDeviceBroker = {8604b268-34a6-4b1a-a59f-cdbd8379fd98}. The method OpenDeviceFromInterfacePath will be called instead of CreateFileW. Alternatively, you can make creating the IDeviceBroker object simply fail, and it will proceed to use CreateFileW as usual.
I am looking for a way to programmatically clear/flush the local win32 dns cache (Equivalent of calling "ipconfig /flushdns").
There were ways to do this with a hidden API in winsock.dll but winsock.dll is no longer part of Windows and as such this method will no longer work.
Does anyone know how this should be done now?
Checked ipconfig.exe's dependencies using Dependency Walker
Found dnsapi.dll among them
Checked its exported functions, and found DnsFlushResolverCache
Shallowly browsed the web, and found its signature (only found references like this on official site: [MS.Docs]: Windows 8 API Sets), meaning it's not public, so software relying on it, is not robust)
Created a small test program
main00.c:
#include <stdio.h>
#include <Windows.h>
typedef BOOL (WINAPI *DnsFlushResolverCacheFuncPtr)();
int main() {
HMODULE dnsapi = LoadLibrary("dnsapi.dll");
if (dnsapi == NULL) {
printf("Failed loading module: %d\n", GetLastError());
return -1;
}
DnsFlushResolverCacheFuncPtr DnsFlushResolverCache = (DnsFlushResolverCacheFuncPtr)GetProcAddress(dnsapi, "DnsFlushResolverCache");
if (DnsFlushResolverCache == NULL) {
printf("Failed loading function: %d\n", GetLastError());
FreeLibrary(dnsapi);
return -2;
}
BOOL result = DnsFlushResolverCache();
if (result) {
printf("DnsFlushResolverCache succeeded\n");
} else {
printf("DnsFlushResolverCache succeeded: %d\n", GetLastError());
}
FreeLibrary(dnsapi);
return 0;
}
Output:
e:\Work\Dev\StackOverflow\q052007372>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64
e:\Work\Dev\StackOverflow\q052007372>dir /b
dnsapi_func_list.txt
main00.c
e:\Work\Dev\StackOverflow\q052007372>cl /nologo main00.c /link /OUT:main00.exe
main00.c
e:\Work\Dev\StackOverflow\q052007372>dir /b
dnsapi_func_list.txt
main00.c
main00.exe
main00.obj
e:\Work\Dev\StackOverflow\q052007372>main00.exe
DnsFlushResolverCache succeeded
Note: Even if the function call completed successfully, I am not sure how to check whether it did what it's supposed to do (or better: what its name suggests it should do, which seems to be what you need).
Let me know how it works.
Update #0
Thank you for the info #TimJohnson!! I was too in a rush to look at ipconfig /? ([MS.Docs]: ipconfig) output (which I had in another cmd window :d ) and notice the option :) . It does work (the cache is heavily updated, and I can see differences before and after running the program) !!!
I'm using WPE PRO, and I can capture packets and send it back. I tried do it using WinSock 2(The same lib which WPE PRO use), but I don't know how to send packet to a existent TCP connection like WPE PRO does.
http://wpepro.net/index.php?categoryid=2
How can I do it ?
Are you asking how to make someone else's program send data over its existing Winsock connection?
I've done exactly this but unfortunately do not have the code on-hand at the moment. If you give me an hour or two I can put up a working example using C; if you need one let me know and I will.
Edit: sample DLL to test at the bottom of the page if you or anyone else wants to; I can't. All I know is that it compiles. You just need to download (or write!) a freeware DLL injector program to test it; there are tons out there.
In the meantime, what you need to research is:
The very basics of how EXEs are executed.
DLL injection
API hooking
Windows Sockets API
1. The very basics of how EXEs are executed:
The whole entire process of what I'm about to explain to you boils down to this very principal. When you double-click an executable, Windows parses it and loads its code, etc. into memory. This is the key. The compiled code is all being put into RAM. What does this imply? Well, if the application's code is all in RAM, can we change the application's code while it's running by just changing some of its memory? After all, it's just a bunch of instructions.
The answer is yes and will provide us the means of messing with another application - in this case, telling it to send some data over its open socket.
(This principal is also the reason you have to be careful writing programs in low-level languages like C since if you put bad stuff in bad parts of RAM, it can crash the program or open you up to shell code exploits).
2. DLL injection:
The problem is, how do we know which memory to overwrite? Do we have access to that program's memory, especially the parts containing the instructions we want to change? You can write to another process' memory but it's more complicated. The easiest way to change their memory (again, when I say memory, we're talking about the machine code instructions being executed) is by having a DLL loaded and running within that process. Think of your DLL as a .c file you can add to another program and write your own code: you can access the program's variables, call its functions, anything; because it's running within the process.
DLL injection can be done through numerous methods. The usual is by calling the CreateRemoteThread() API function. Do a Google search on that.
3. API Hooking
What is API hooking? To put it more generally, it's "function hooking", we just happen to be interested in hooking API calls; in this case, the ones used for Sockets (socket(), send(), etc.).
Let's use an example. A target application written in C using Winsock. Let's see what they are doing and then show an example of what we WANT to make it do:
Their original source code creating a socket:
SOCKET ConnectSocket = INVALID_SOCKET;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Now, that's the original program's source code. Our DLL won't have access to that because it's loaded within an EXE and an EXE is compiled (duh!). So let's say their call to socket() looked something like this after being compiled to machine code (assembly). I don't know assembly at all but this is just for illustration:
The assembly/machine code:
PUSH 06 ; IPPROTO_TCP
PUSH 01 ; SOCK_STREAM
PUSH 02 ; AF_INET
CALL WS2_32.socket ; This is one of the parts our DLL will need to intercept ("hook").
In order for us to make that program send data (using our DLL), we need to know the socket's handle. So we need to intercept their call to the socket function. Here are some considerations:
The last instruction there would need to be changed to: CALL OurOwnDLL.socket. That CALL instruction is just a value in memory somewhere (remember?) so we can do that with WriteProcessMemory. We'll get to that.
We want to take control of the target program, not crash it or make it behave strangely. So our code needs to be transparent. Our DLL which we will inject needs to have a socket function identical to the original, return the same value, etc. The only difference is, we will be logging the return value (SocketHandle) so that we can use it later when we want to send data.
We also need to know if/when the socket connects since we can't send data unless it is (assuming we're using TCP like most applications do). This means we need to also hook the Winsock connect API function and also duplicate that in our DLL.
DLL to inject and monitor the socket and connect functions (untested):
This C DLL will have everything in place to hook and unhook functions. I can't test it at the moment and I'm not even much of a C programmer so let me know if you come across any problems.
Compile this as a Windows DLL not using Unicode and inject it into a process that you know uses WS2_32's socket() and connect() functions and let me know if it works. I have no means to test, sorry. If you need further help or fixes, let me know.
/*
SocketHookDLL.c
Author: Daniel Elkins
License: Public Domain
Version: 1.0.0
Created: May 14th, 2014 at 12:23 AM
Updated: [Never]
Summary:
1. Link to the Winsock library so we can use its functions.
2. Export our own `socket` and `connect` functions so that
they can be called by the target application instead of
the original ones from WS2_32.
3. "Hook" the socket APIs by writing over the target's memory,
causing `CALL WS2_32.socket` to `CALL SocketHookDLL.socket`, using
WriteProcessMemory.
4. Make sure to keep a copy of the original memory for when we no
no longer want to hook those socket functions (i.e. DLL detaching).
*/
#pragma comment(lib, "WS2_32.lib")
#include <WinSock2.h>
/* These functions hook and un-hook an API function. */
unsigned long hookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup);
unsigned int unHookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup);
/*
These functions (the ones we want to hook) are copies of the original Winsock's functions from Winsock2.h.
1. Calls OurDLL.hooked_socket() (unknowingly).
2. OurDLL.hooked_socket() calls the original Winsock.socket() function.
3. We take note of the returned SOCKET handle so we can use it later to send data.
4. OurDLL.hooked_socket() returns the SOCKET back to the target app so everthing works as it should (hopefully!).
Note: You can change return values, parameters (like data being sent/received like WPE does), just be aware it will
also (hopefully, intendingly) change the behavior of the target application.
*/
SOCKET WSAAPI hooked_socket (int af, int type, int protocol);
int WSAAPI hooked_connect (SOCKET s, const struct sockaddr FAR * name, int namelen);
/* Backups of the original memory; need one for each API function you hook (if you want to unhook it later). */
unsigned char backupSocket[6];
unsigned char backupConnect[6];
/* Our SOCKET handle used by the target application. */
SOCKET targetsSocket = INVALID_SOCKET;
/* This is the very first code that gets executed once our DLL is injected: */
BOOL APIENTRY DllMain (HMODULE moduleHandle, DWORD reason, LPVOID reserved)
{
/*
We will hook the desired Socket APIs when attaching
to target EXE and UN-hook them when being detached.
*/
switch (reason)
{
case DLL_PROCESS_ATTACH:
/* Here goes nothing! */
hookFunction ("WS2_32.DLL", "socket", backupSocket);
hookFunction ("WS2_32.DLL", "connect", backupConnect);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_PROCESS_DETACH:
unHookFunction ("WS2_32.DLL", "socket", backupSocket);
unHookFunction ("WS2_32.DLL", "connect", backupConnect);
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
unsigned long hookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup)
{
/*
Hook an API function:
=====================
1. Build the necessary assembly (machine code) opcodes to get our DLL called!
2. Get a handle to the API we're hooking.
3. Use ReadProcessMemory() to backup the original memory to un-hook the function later.
4. Use WriteProcessMemory to make changes to the instructions in memory.
*/
HANDLE thisTargetProcess;
HMODULE dllModuleHandle;
unsigned long apiAddress;
unsigned long memoryWritePosition;
unsigned char newOpcodes[6] = {
0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3 // Step #1.
};
thisTargetProcess = GetCurrentProcess ();
// Step #2.
dllModuleHandle = GetModuleHandle (dllModule);
if (!dllModuleHandle)
return 0;
apiAddress = (unsigned long) GetProcAddress (dllModuleHandle, apiFunction);
if (!apiAddress)
return 0;
// Step #3.
ReadProcessMemory (thisTargetProcess, (void *) apiAddress, memoryBackup, 6, 0);
memoryWritePosition = ((unsigned long) apiFunction - apiAddress - 5);
memcpy (&newOpcodes[1], &apiAddress, 4);
// Step #4.
WriteProcessMemory (thisTargetProcess, (void *) apiAddress, newOpcodes, 6, 0);
return apiAddress;
}
unsigned int unHookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup)
{
HANDLE thisTargetProcess;
HMODULE dllModuleHandle;
unsigned long apiAddress;
unsigned long memoryWritePosition;
thisTargetProcess = GetCurrentProcess ();
dllModuleHandle = GetModuleHandleA (dllModule);
if (!dllModuleHandle)
return 0;
apiAddress = (unsigned long) GetProcAddress (dllModuleHandle, apiFunction);
if (!apiAddress)
return 0;
if (WriteProcessMemory (thisTargetProcess, (void *) apiAddress, memoryBackup, 6, 0))
return 1;
return 0;
}
/* You may want to use a log file instead of a MessageBox due to time-outs, etc. */
SOCKET WSAAPI hooked_socket (int af, int type, int protocol)
{
targetsSocket = socket (af, type, protocol);
MessageBox (NULL, "(Close this quickly)\r\n\r\nThe target's socket was hooked successfully!", "Hooked SOCKET", MB_OK);
return targetsSocket;
}
int WSAAPI hooked_connect (SOCKET s, const struct sockaddr FAR * name, int namelen)
{
MessageBox (NULL, "(Close this quickly)\r\n\r\nThe target just connected to a remote address.", "Target Connected", MB_OK);
return connect (s, name, namelen);
}
i have problem with this code:
int
WINAPI
Getdesc(IN WORD wcode,
OUT LPWSTR lpBuf)
{
WCHAR szDescription[256];
int res = LoadStringW(NULL,wcode,szDescription,256);
if(res == 0)
{
wcscpy(lpBuf, L"Undefined");
return 0;
}
else
{
wcscpy(lpBuf,szDescription);
return 0;
}
}
The function is placed in a DLL, and when i access it, it always returns "Undefined",
I think there is problem in my LoadString call, but i can't figure it out.
I'm new to windows programming, any help would be appreciated
The problem is that you are passing NULL as the HINSTANCE parameter. That means that you look for the resource in the executable host and not the DLL. You'll have to pass the module handle of the DLL. You are provided with that instance handle as the first parameter passed to your DllMain function.
If you are compiling with MSVC then you could use __ImageBase to obtain the module handle. Personally I would suggest that making a note of the value passed to DllMain is a cleaner approach. It avoids taking a dependency on one specific compiler.
Note also that you can call GetLastError in case LoadString fails to obtain more information about the reason for the error. It's quite possible that would have helped you identify the fault.