This seems like it should be a simple question, but I'm not sure how best to solve it. I've seen a few posts on how to detect if a connected device is USB 2 or 3, but I need to know if USB 3 ports are available, even if no devices are connected.
One solution would be to traverse the 'SYSTEM\CurrentControlSet\Services' key in the registry and compare against a pre-set list of known USB3 services. I was hoping there was something more accurate like an IOCTL call.
I can implement C++ (preferred) or C#.
Thanks in advance for any help.
Here's how I implemented this. Not really the solution I'm looking for. This basically will tell me if USB 3.0 drivers are present on the system. It does not detect if the hardware on the system includes USB 3.0 ports. Would prefer something lower level in C++.
I would greatly appreciate it if someone could show me how to detect the hardware for this (rather than just slag and not contribute). Thanks!
private bool IsUsb3()
{
string val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\USBXHCI", "ImagePath", 0);
if (val != null) return true; // Microsoft
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\USBHUB3", "ImagePath", 0);
if (val != null) return true; // Microsoft
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usb3Hub", "ImagePath", 0);
if (val != null) return true; // Microsoft
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\UCX01000", "ImagePath", 0);
if (val != null) return true; // Microsoft
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\nusb3hub", "ImagePath", 0);
if (val != null) return true; // Renesas
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\nusb3xhc", "ImagePath", 0);
if (val != null) return true; // Renesas
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\iusb3xhc", "ImagePath", 0);
if (val != null) return true; // Intel
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\iusb3hub", "ImagePath", 0);
if (val != null) return true; // Intel
val = (string)Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\iusb3hcs", "ImagePath", 0);
if (val != null) return true;
return false;
}
Here's exactly what I was looking for:
http://read.pudn.com/downloads105/sourcecode/windows/vxd/432626/USBLib/USB.cs__.htm
I then added the following code:
// Get USB information
bool supportsUsb3 = false;
System.Collections.ObjectModel.ReadOnlyCollection<USB.USBController> hostlist = null;
hostlist = USB.GetHostControllers();
mControllerCount = hostlist.Count;
foreach (USB.USBController host in hostlist)
{
USB.USBController controller = new USB.USBController();
controller.ControllerDevicePath = host.ControllerDevicePath;
USB.USBHub roothub = controller.GetRootHub();
System.Collections.ObjectModel.ReadOnlyCollection<USB.USBPort> portlist = null;
portlist = roothub.GetPorts();
foreach (USB.USBPort port in portlist)
{
USB.USBHub hub = port.GetHub();
if (port.PortSpeed == USBLib.USB.USB_DEVICE_SPEED.UsbSuperSpeed.ToString())
{
supportsUsb3 = true;
break;
}
}
if (supportsUsb3)
break;
}
I can now determine if the user's PC has USB 3.0 ports. If they only have 2.0 ports, then I can use the previous code to determine if USB 3 drivers are installed.
Related
So I have tried looking at a couple of different answers for this. One that I thought may have promise was this one:
How to check network interface type is Ethernet or Wireless on Windows using Qt?
However, I don't really know too much about Networking or even about Windows. Personally, I cannot understand most of the Microsoft documentation on their websites. I have tried things like INetworkConnection, NativeWiFi, etc. But either they do not do what I want, or I just cannot figure out how to do it from the available documentation.
With that being said, I would like to use C++ to check if the device this program is being run on is connected to the internet via Ethernet cable. Basically, I want to do the following:
If the computer is connected to Wireless only, run the program
If the computer is connected to Wired only, don't run the program
If the computer is connected to both Wired AND Wireless, don't run the program
However, the problem is that I don't know how to check if the device has Ethernet connected. Is there a way to do this? I am NOT using QT. Thank you!
EDIT: I should also include what I have tried so far.
I tried using GetAdaptersInfo and getting the Type trait from the PIP_ADAPTER_INFO variable type, but that always gives me Unknown type 71 whether I am on Ethernet or not.
The documentation for that GetAdaptersInfo is here:
https://msdn.microsoft.com/en-us/library/aa365917%28VS.85%29.aspx
Thanks
EDIT 2: Here is the code I was using for GetAdaptersInfo
bool is_on_ethernet{
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
UINT i;
struct tm newtime;
char buffer[32];
errno_t error;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
if(pAdapterInfo == NULL)
printf("Error allocating memory need to call GetAdaptersInfo");
if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
}
if((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){
pAdapter = pAdapterInfo;
switch(pAdapter->Type){
case MIB_IF_TYPE_OTHER:
printf("Other\n");
return false;
break;
case MIB_IF_TYPE_ETHERNET:
printf("Ethernet\h");
return true;
break;
case MIB_IF_TYPE_TOKENRING:
printf("Token Ring\n");
return false;
break;
case MIB_IF_TYPE_FDDI
printf("FDDI\n");
return false;
break;
case MIB_IF_TYPE_PPP
printf("PPP\n");
return false;
break;
case MIB_IF_TYPE_LOOPBACK
printf("Lookback\n");
return false;
break;
case MIB_IF_TYPE_SLIP
printf("Slip\n");
return false;
break;
default
printf("Unknown type %ld\n\n", pAdapter->Type);
return false;
break;
}
}
if(pAdapterInfo)
free(pAdapterInfo);
return false;
}
Your problem is somewhat difficult as it can be really complicated to get the "current" network adapter --- windows routes packets depending on network adapter configuration and destination reachability so your "current" adapter may change at any time ... but since you already know how to retrieve IPs and MACs ("hardware address") of available adapters you could simply use your hack to retrieve a MAC for your current IP and filter/search inside of my second function for it! The field "PhysicalAddress" is what you're looking for, thats the MAC adress
I have made the experience that the only, somewhat reliable way of doing that is via GetIfTable and GetIfTable2, the former returns somewhat superficial adpater info and the latter provides great detail.
Heres a sample implementation, as it uses the detailed function you can also query for WLAN adapters :
vector<MIB_IF_ROW2>* getDevices(NDIS_PHYSICAL_MEDIUM type)
{
vector<MIB_IF_ROW2> *v = new vector<MIB_IF_ROW2>();
PMIB_IF_TABLE2 table = NULL;
if(GetIfTable2Ex(MibIfTableRaw, &table) == NOERROR && table)
{
UINT32 i = 0;
for(; i < table->NumEntries; i++)
{
MIB_IF_ROW2 row;
ZeroMemory(&row, sizeof(MIB_IF_ROW2));
row.InterfaceIndex = i;
if(GetIfEntry2(&row) == NOERROR)
{
if(row.PhysicalMediumType == type)
{
v->push_back(row);
}
}
}
FreeMibTable(table);
}
return v;
}
Now all you need to do is iterate over the list and filter out disabled adapters and whatnot :
vector<MIB_IF_ROW2>* wlan = getDevices(NdisPhysicalMediumNative802_11); //WLAN adapters
//see https://msdn.microsoft.com/en-us/library/windows/desktop/aa814491(v=vs.85).aspx, "PhysicalMediumType" for a full list
for(auto &row : *v)
{
//do some additional filtering, this needs to be changed for non-WLAN
if( row.TunnelType == TUNNEL_TYPE_NONE &&
row.AccessType != NET_IF_ACCESS_LOOPBACK &&
row.Type == IF_TYPE_IEEE80211 &&
row.InterfaceAndOperStatusFlags.HardwareInterface == TRUE)
{
//HERE BE DRAGONS!
}
}
Now its quite easy to generate lists of WLAN adapters and non-WLAN adapters (see comment in second function), search for your current MAC and conclude that it is wired or wireless - but be aware that these lists may overlap since 802.11 basically is an extended version of 802.3 but 802.3 does not include 802.11 (since its an extension) - so you will need a tiny bit of if/else logic going on in order to seperate WLAN from non-WLAN adapters.
You could also use WlanEnumInterfaces to get all of the WLAN adapters but thats basically the same as using the above function with NdisPhysicalMediumNative802_11 as parameter ...
So first, thank you very much to user #Nighthawk441 for pointing me in the right direction for this. Without this user, I would most certainly have not come up with a solution.
That being said, the solution I have right now is, at best, a hack. It seems to work, but I don't think it is even close to the best option. Thus, I will leave this as an answer but I will not accept it for a little while in the event that a better answer is found. I am also very open to any comments anyone may have as it pertains to this answer.
In short, what I did was I looped through all of the Adapters from GetAdaptersInfo. In order to see if the adapter was connected, I compared the IP address of the adapter to the string "0.0.0.0", as if it were something other than this I felt it was safe to say that the adapter was connected. So, without further ado, here is the code that I implemented.
bool is_on_ethernet(){
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
UINT i;
struct tm newtime;
char buffer[32];
errno_t error;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
if(pAdapterInfo == NULL)
printf("Error allocating memory needed to call GetAdaptersInfo");
if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
}
if((dwRetValue = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){
do{
pAdapter = pAdapterInfo;
string ip_string = pAdapter->IpAddressList.IpAddress.String;
switch(pAdapter->Type){
case MIB_IF_TYPE_OTHER:
printf("Other\n");
break;
...
case MIB_IF_TYPE_ETHERNET:
printf("Ethernet\n");
//new code
if(ip_string.compare("0.0.0.0") != 0){
free(pAdapterInfo);
return true;
}
break;
default:
printf("Unknown type %ld\n", pAdapter->Type);
break;
}
}while(pAdapterInfo = pAdapterInfo->Next);
}
if(pAdapterInfo)
free(pAdapterInfo);
return false;
}
Looking at this reference really helped me:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365819%28v=vs.85%29.aspx
So thank you to Nighthawk for supplying that information to me. Hopefully this will help someone else! If anyone has any comments or any other answers, feel free to post them! Thanks!
Based on #specializt's answer, and with some minor modification, I got it work for me as following:
BOOL getDevices(NDIS_PHYSICAL_MEDIUM type, vector<MIB_IF_ROW2>& vetIFRow)
{
PMIB_IF_TABLE2 table = NULL;
if (GetIfTable2Ex(MibIfTableRaw, &table) != NOERROR || !table)
{
return FALSE;
}
for (ULONG i = 0; i < table->NumEntries; i++)
{
MIB_IF_ROW2 row;
ZeroMemory(&row, sizeof(MIB_IF_ROW2));
row.InterfaceIndex = i;
if (GetIfEntry2(&row) == NOERROR && row.PhysicalMediumType == type)
{
vetIFRow.push_back(row);
}
}
FreeMibTable(table);
return TRUE;
}
BOOL isNetIFConnected(const MIB_IF_ROW2& row, IFTYPE Type)
{
return (row.TunnelType == TUNNEL_TYPE_NONE &&
row.AccessType != NET_IF_ACCESS_LOOPBACK &&
row.Type == Type &&
row.InterfaceAndOperStatusFlags.HardwareInterface == TRUE &&
row.MediaConnectState == MediaConnectStateConnected);
}
tstring getNetWorkType()
{
vector<MIB_IF_ROW2> vectRow;
BOOL bRet = getDevices(NdisPhysicalMedium802_3, vectRow); // ETHERNET adapters
if (bRet)
{
for (auto it = vectRow.begin(); it != vectRow.end(); it++)
{
if (isNetIFConnected(*it, IF_TYPE_ETHERNET_CSMACD))
{
return L"ETHERNET";
}
}
}
vectRow.clear();
bRet = getDevices(NdisPhysicalMediumNative802_11, vectRow); //WLAN adapters
if (bRet)
{
for (auto it = vectRow.begin(); it != vectRow.end(); it++)
{
if (isNetIFConnected(*it, IF_TYPE_IEEE80211))
{
return L"WIFI";
}
}
}
return L"Unknown";
}
Thanks to #specializt
I have an application that tries to verify the mmc.exe (services) signature. (the context of the application I think is irrelevant) I am trying with winapi function which both fails with
WinVerifyTrust. I get TRUST_E_BAD_DIGEST when I am trying with verification from catalog, and
TRUST_E_NOSIGNATURE when trying from file info. it is very important to mention that my function succeeds on win7, XP but fails on win8.
this is the code snippet for the function
CATALOG_INFO InfoStruct = {0};
InfoStruct.cbStruct = sizeof(CATALOG_INFO);
WINTRUST_CATALOG_INFO WintrustCatalogStructure = {0};
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WINTRUST_FILE_INFO WintrustFileStructure = {0};
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
//Get a context for signature verification.
HCATADMIN Context = NULL;
if(!::CryptCATAdminAcquireContext(&Context, NULL, 0) ){
return false;
}
//Open file.
cx_handle hFile(::CreateFileW(filename_.c_str(), GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL));
if( INVALID_HANDLE_VALUE == (HANDLE)hFile )
{
CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Get the size we need for our hash.
DWORD HashSize = 0;
::CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, NULL, 0);
if( HashSize == 0 )
{
//0-sized has means error!
::CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Allocate memory.
buffer hashbuf(HashSize);
//Actually calculate the hash
if( !CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, hashbuf.data, 0) )
{
CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Convert the hash to a string.
buffer MemberTag(((HashSize * 2) + 1) * sizeof(wchar_t));
for( unsigned int i = 0; i < HashSize; i++ ){
swprintf(&((PWCHAR)MemberTag.data)[i * 2], L"%02X", hashbuf.data[i ]);
}
//Get catalog for our context.
HCATINFO CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, hashbuf, HashSize, 0, NULL);
if ( CatalogContext )
{
//If we couldn't get information
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
{
//Release the context and set the context to null so it gets picked up below.
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
CatalogContext = NULL;
}
}
//If we have a valid context, we got our info.
//Otherwise, we attempt to verify the internal signature.
WINTRUST_DATA WintrustStructure = {0};
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
if( !CatalogContext )
{
load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure);
}
else
{
load_signature_verification_from_catalog(WintrustStructure, WintrustCatalogStructure, InfoStruct, MemberTag);
}
//Call our verification function.
long verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
//Check return.
bool is_success = SUCCEEDED(verification_res) ? true : false;
// if failed with CatalogContext, try with FILE_INFO
if(!is_success && CatalogContext && verification_res != TRUST_E_NOSIGNATURE)
{
//warning2(L"Failed verification with Catalog Context: 0x%x %s ; Retrying with FILE_INFO.", verification_res, (const wchar_t*)format_last_error(verification_res));
load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure);
verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
is_success = SUCCEEDED(verification_res) ? true : false;
}
if(perr && !is_success && verification_res != TRUST_E_NOSIGNATURE)
{
perr->code = verification_res;
perr->description = format_last_error(verification_res);
}
//Free context.
if( CatalogContext ){
::CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
}
//If we successfully verified, we need to free.
if( is_success )
{
WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE;
::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
}
::CryptCATAdminReleaseContext(Context, 0);
return is_success;
I don't think any thing had changed in this function from win7 to win 8 so what could possibly go wrong?
UPDATE
I did notice that my function does work for task manager at win 8.
but again for the mmc it does not work.
It appears that your general approach is correct and the functions themselves haven't changed. However there are subtle changes; namely the data on which they operate has changed. The hashes stored for files on Windows 8, according to comments on CryptCATAdminCalcHashFromFileHandle, are calculated using SHA-256 hashes.
The SHA-256 hashing algorithm is not supported by CryptCATAdminCalcHashFromFileHandle, so you must update the code to use CryptCATAdminAcquireContext2 and CryptCATAdminCalcHashFromFileHandle2 on Windows 8; the former allows you to acquire a HCATADMIN with a specified hash algorithm, and the latter allows using that HCATADMIN.
(Interestingly, WINTRUST_CATALOG_INFO also points this direction with its HCATADMIN hCatAdmin member, documented as "Windows 8 and Windows Server 2012: Support for this member begins.")
I am using the following function and query to retrieve the network adapter's MAC address :
QueryValue( pService, L"SELECT MACAddress FROM Win32_NetworkAdapter", L"MACAddress", NetMacAddress, bufferLength );
But i don't know how to specify which card i want to get the address of. Is there a way to get the MAC address of every card on the computer (assuming they are activated and all that) using WMI ? Or using something else ?
Thank you :)
Without WMI you can simply use something like this...
unsigned long ulLen = 0;
IP_ADAPTER_ADDRESSES* p_adapAddress = NULL;
DWORD dwRetValue = GetAdaptersAddresses(AF_INET, 0, NULL, p_adapAddress,&ulLen);
if(dwRetValue == ERROR_BUFFER_OVERFLOW)
{
p_adapAddress = (PIP_ADAPTER_ADDRESSES)malloc(ulLen);
if(p_adapAddress)
{
dwRetValue = GetAdaptersAddresses(AF_INET, 0, NULL, p_adapAddress,&ulLen);
if(dwRetValue == NO_ERROR)
{
IP_ADAPTER_ADDRESSES* p_adapAddressAux = p_adapAddress;
do
{
// Get the value of the p_adapAddressAux.PhysicalAddress
}
while(p_adapAddressAux != NULL);
}
free(p_adapAddress);
}
}
I try to use DirectX Input to manage input mouse. But when I try to get X and Y coordinates of my mouse, values are incorrect (negative or seem to be random).
I show you the code that I used :
bool System::frame()
{
bool result;
if (input->isButtonDown(BUTTON_L)) //if left button is down
{
result = ReadMouse();
if(!result)
return false;
ProcessInput();
}
}
bool System::ReadMouse()
{
HRESULT result;
//this->mouseState is a DIMOUSESTATE ; this->mouse is a LDIRECTINPUTDEVICE8
result = this->mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&this->mouseState);
if(FAILED(result))
{
if((result == DIERR_INPUTLOST) || (result == DIERR_NOTACQUIRED))
this->mouse->Acquire();
else
return false;
}
return true;
}
void System::ProcessInput()
{
this->mouseX = this->mouseState.lX;
this->mouseY = this->mouseState.lY;
if(this->mouseX < 0)
this->mouseX = 0;
if(this->mouseY < 0)
this->mouseY = 0;
if(this->mouseX > this->ScreenWidth)
this->mouseX = this->ScreenWidth;
if(this->mouseY > this->ScreenHeight)
this->mouseY = this->ScreenHeight;
return;
}
My last test give this->mouseX = -657 and this->mouseY = -36 instead of 200 and 200 (approximately). I check the function when I initialize the mouse, they seem to works (I followed a tutorial).
I think the reason is that DirectInput gives you relative data for the position of the mouse.
Please see: http://msdn.microsoft.com/en-us/library/windows/desktop/ee418272(v=vs.85).aspx for an explanation of how to interpret data from mouse and how to switch to absolute mode.
It is recommended to use the Raw Input API instead of DirectInput.
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx)
I have tried all the normal methods of faking keyboard actions (SendInput/SendKeys/etc) but none of them seemed to work for games that used DirectInput. After a lot of reading and searching I stumbled across Interception, which is a C++ Library that allows you to hook into your devices.
It has been a very long time since I worked with C++ (Nothing existed for C#) so I am having some trouble with this. I have pasted in the sample code below.
Does it look like there would be anyway to initiate key actions from the code using this? The samples all just hook into the devices and rewrite actions (x key prints y, inverts mouse axis, etc).
enum ScanCode
{
SCANCODE_X = 0x2D,
SCANCODE_Y = 0x15,
SCANCODE_ESC = 0x01
};
int main()
{
InterceptionContext context;
InterceptionDevice device;
InterceptionKeyStroke stroke;
raise_process_priority();
context = interception_create_context();
interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP);
/*
for (int i = 0; i < 10; i++)
{
Sleep(1000);
stroke.code = SCANCODE_Y;
interception_send(context, device, (const InterceptionStroke *)&stroke, 1);
}
*/
while(interception_receive(context, device = interception_wait(context), (InterceptionStroke *)&stroke, 1) > 0)
{
if(stroke.code == SCANCODE_X) stroke.code = SCANCODE_Y;
interception_send(context, device, (const InterceptionStroke *)&stroke, 1);
if(stroke.code == SCANCODE_ESC) break;
}
The code I commented out was something I tried that didn't work.
You need to tweak key states for UP and DOWN states to get key presses. Pay attention at the while loop that the variable device is returned by interception_wait, your commented out code would send events to what?? device is not initialized! Forget your code and try some more basic. Look at the line inside the loop with the interception_send call, make more two calls after it, but don't forget to change stroke.state before each call using INTERCEPTION_KEY_DOWN and INTERCEPTION_KEY_UP so that you fake down and up events. You'll get extra keys at each keyboard event.
Also, you may try use INTERCEPTION_FILTER_KEY_ALL instead of INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP. The arrow keys may be special ones as mentioned at the website.
void ThreadMethod()
{
while (true)
{
if (turn)
{
for (int i = 0; i < 10; i++)
{
Sleep(1000);
InterceptionKeyStroke stroke;
stroke.code = SCANCODE_Y;
stroke.state = 0;
interception_send(context, device, (const InterceptionStroke *)&stroke, 1);
Sleep(1);
stroke.state = 1;
interception_send(context, device, (const InterceptionStroke *)&stroke, 1);
turn = false;
}
}
else Sleep(1);
}
}
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadMethod, NULL, NULL, NULL);
while (interception_receive(context, device = interception_wait(context), (InterceptionStroke*)&stroke, 1) > 0)
{
if (stroke.code == SCANCODE_F5) turn = true;
interception_send(context, device, (InterceptionStroke*)&stroke, 1);
if (stroke.code == SCANCODE_ESC) break;
}