Quite funny. I just asked few minutes ago here SendInput() for keyboard - only lowercase, how to send letters upper case. The solution was to send shift before letter. But after turning shift on I can't turn it off...
I'm trying hard with KEYEVENTF_KEYUP flag like this:
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = VK_LSHIFT;
SendInput( 1, &Input, sizeof( INPUT ) );
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = 'A';
SendInput( 1, &Input, sizeof( INPUT ) );
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = VK_LSHIFT;
SendInput( 1, &Input, sizeof( INPUT ) );
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = 'A';
SendInput( 1, &Input, sizeof( INPUT ) );
but it seems to not work at all. It always sends AA.
Thanks.
The problem was with
Input.mi.dwFlags
it should be
Input.ki.dwFlags
thanks to rodrigo.
Another way is to use KEYEVENTF_SCANCODE flag. Then we have to scan our char using VkKeyScan() - http://msdn.microsoft.com/en-us/library/windows/desktop/ms646329(v=vs.85).aspx, which gives us virtual key code in low byte and state (shift, ctrl etc.) in high byte.
Due to using scan codes we have to map our virtual code to scan code by using MapVirtualKey() with MAPVK_VK_TO_VSC value, MSDN says:
uCode is a virtual-key code and is translated into a scan code. If it
is a virtual-key code that does not distinguish between left- and
right-hand keys, the left-hand scan code is returned. If there is no
translation, the function returns 0.
and then pass it to the wScan field of the Input.ki structure, because according to MSDN if we use scan codes it ignores wVk and uses wScan, MSDN says:
If specified, wScan identifies the key and wVk is ignored.
Therefore the code can look something like this:
INPUT Event = { 0 };
const SHORT key = VkKeyScan('a');
const UINT mappedKey = MapVirtualKey( LOBYTE( key ), 0 );
// Press shift key
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = MapVirtualKey( VK_LSHIFT, 0 );
SendInput( 1, &Event, sizeof( Event ) );
// upper case 'A' (press down)
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey;
SendInput( 1, &Event, sizeof( Event ) );
// release 'A'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = mappedKey;
SendInput( 1, &Event, sizeof( Event ) );
// Release shift key
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = MapVirtualKey( VK_LSHIFT, 0 );
SendInput( 1, &Event, sizeof( Event ) );
const SHORT key1 = VkKeyScan('a');
const UINT mappedKey1 = MapVirtualKey( LOBYTE( key1 ), 0 );
// lower case 'a' (press down)
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey1;
SendInput( 1, &Event, sizeof( Event ) );
// release 'a'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey1;
SendInput( 1, &Event, sizeof( Event ) );
If I have said something wrong, please correct me.
Thanks for this! It was very helpful in debugging my code. Here is my final version for those who need it.
void Type(const char* text) {
INPUT ip[4] = {};
for (; *text; text++) {
int startInput = 1; // Assume 1 keyup and keydown pair.
int nInputs = 2;
if (HIBYTE(VkKeyScan(*text)) == 1) { // Set up SHIFT key and release
startInput = 0;
nInputs = 4;
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.dwFlags = KEYEVENTF_SCANCODE;
ip[0].ki.wScan = MapVirtualKey(VK_LSHIFT, 0);
ip[3] = ip[0];
ip[3].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
}
ip[1].type = INPUT_KEYBOARD; // Set up key and release
ip[1].ki.wScan = MapVirtualKey(LOBYTE(VkKeyScan(*text)), 0);
ip[1].ki.dwFlags = KEYEVENTF_SCANCODE;
ip[2] = ip[1];
ip[2].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(nInputs, &ip[startInput], sizeof(INPUT));
Sleep(100);
}
}
Related
First question is PROT_WRITE and PROT_READ i wasn't able to find anywhere and it's giving me a hard time compiling. I replaced with 0 and 1 but it doesn't seem to work.
Second, "rejected (unexisting region cookie)"
int rank;
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Win win;
int knem_fd = open("/dev/knem", O_RDWR);
int err;
uint64_t size = 64;
if( rank == 0 ){
char *inbuf = malloc(size);
for( int i = 0; i < size; i++ )
inbuf[i] = rand() % 26 + 97;
print_array( inbuf, size, '0' );
struct knem_cmd_create_region create;
struct knem_cmd_param_iovec knem_iov[1];
knem_iov[0].base = (uint64_t)&inbuf;
knem_iov[0].len = size;
create.iovec_array = (uintptr_t) &knem_iov[0];
create.iovec_nr = 1;
create.flags = KNEM_FLAG_SINGLEUSE;
//create.protection = 1;
err = ioctl( knem_fd, KNEM_CMD_CREATE_REGION, &create );
MPI_Send( &(create.cookie), 1, MPI_UINT64_T, 1, 0, MPI_COMM_WORLD );
MPI_Barrier( MPI_COMM_WORLD );
} else if( rank == 1 ){
char *obuf = malloc(size);
int err;
struct knem_cmd_copy copy;
struct knem_cmd_create_region create;
struct knem_cmd_param_iovec knem_iov[1];
knem_iov[0].base = (uint64_t)&obuf;
knem_iov[0].len = size;
create.iovec_array = (uintptr_t) &knem_iov[0];
create.iovec_nr = 1;
//create.protection = 0;
create.flags = KNEM_FLAG_SINGLEUSE;
err = ioctl( knem_fd, KNEM_CMD_CREATE_REGION, &create );
MPI_Recv( &(copy.src_cookie), 1, MPI_UINT64_T, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
copy.src_offset = 0;
copy.dst_cookie = create.cookie;
copy.dst_offset = 0;
copy.flags = 0;
err = ioctl(knem_fd, KNEM_CMD_COPY, ©);
print_array( obuf, size, '1' );
MPI_Barrier( MPI_COMM_WORLD );
}
0 and 1 both create a region, 0 sends its cookie to 1 and 1 goes in grab data from 0. I checked the received cookie is the same as the send cookie, but it just failed to find the declared region.
PROT_READ and PROT_WRITE are mmap flags, you need to include sys/mman.h to get them. In the second part of the code, you need to set copy.src_cookie to create.cookie (or just use an inline copy to avoid creating that region at all since it'll be destroyed immediately because of the SINGLEUSE flag). Also, make sure ou check the return values of all ioctl before continuing. Copy cannot work if create.cookie wasn't initialized because the create ioctl failed.
In the cmd.exe window there is a status called "Scroll mode". At this site there is a description of how to activate it; via keyboard: Alt-Space, then Edit, then scroLl; or via mouse: right-click on the title bar, then select Edit and Scroll.
My question is simple: what Win-32 API function is used to activate this status?
I reviewed the SetConsoleMode function, but it does not manage this mode (nor anyone of the rest of console functions). I searched the web looking for "cmd.exe scroll mode", but no one of the multiple results refers to this mode...
After some digging and tests, it "seems" that this behaviour is not exposed by any public API function. While someone find a non obvious way (or still better an obvious one), this workaround can be used
#define _WIN32_WINNT 0x0500
#include <windows.h>
#define SC_SCROLL 0xFFF3
int main(void) {
HWND hWnd;
// Search current console
if (!(
hWnd = GetConsoleWindow()
)) return 1;
// Set scroll mode
if (
SendMessage(
hWnd
, WM_SYSCOMMAND
, (WPARAM) SC_SCROLL
, (LPARAM) NULL
) != 0
) return 2;
// Done
return 0;
}
edited to adapt to comments
To disable the scroll, we only need a Enter, Esc or Ctrl-C key press
#define _WIN32_WINNT 0x0500
#include <windows.h>
#define KEYEVENTF_KEYDOWN 0
int main(void) {
INPUT ip;
// Keyboard input structure initialize
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
// Control key down
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYDOWN;
SendInput( 1, &ip, sizeof(INPUT) );
// C key down
ip.ki.wVk = 'C';
ip.ki.dwFlags = KEYEVENTF_KEYDOWN;
SendInput( 1, &ip, sizeof(INPUT) );
// C key up
ip.ki.wVk = 'C';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput( 1, &ip, sizeof(INPUT) );
// Control key up
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput( 1, &ip, sizeof(INPUT) );
// Done
return 0;
}
This code sends a Ctrl+C, but you can not indicate the target of the keypress. To avoid problems from focus loss it is probably better to send the Esc directly to the window
#define _WIN32_WINNT 0x0500
#include <windows.h>
int main(void) {
int KEY = VK_ESCAPE;
unsigned int lParamKeyDown = 0;
unsigned int lParamKeyUp = 0;
HWND hWnd;
// Search current console
if (!(
hWnd = GetConsoleWindow()
)) return 1;
// Configure lParam for key down event
lParamKeyDown |= 1;
lParamKeyDown |= 1 << 24;
lParamKeyDown |= MapVirtualKey(KEY, 0) << 16;
// Configure lParam for key up event
lParamKeyUp |= 1 << 30;
lParamKeyUp |= 1 << 31;
lParamKeyUp |= MapVirtualKey(KEY, 0) << 16;
// Send the key
SendMessage( hWnd, WM_KEYDOWN, KEY, lParamKeyDown );
SendMessage( hWnd, WM_KEYUP, KEY, lParamKeyUp );
// Done
return 0;
}
I'm trying to get a HANDLE from a Bluetooth Low Energy device by using CreateFile().
Therefore I need to extract the device path of the device.
I get an ERROR_INVALID_PARAMETER error when calling SetupDiEnumDeviceInterfaces. It seems that the second parameter (DeviceInfoData) has a problem.
Any ideas what the problem could be?
EDITED: Simplified code
HDEVINFO hDevInfo;
DWORD i;
// Create a HDEVINFO with all present devices.
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_BLUETOOTH, 0, 0, DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
// Insert error handling here.
return;//1;
}
PSP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA;
DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
{
DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
char detailDataBuf[0x100];
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)detailDataBuf;
ULONG length;
ULONG requiredLength = 0;
bool bResult = FALSE;
for(DWORD j = 0; j < 10; j++ )
{
SP_DEVICE_INTERFACE_DATA interfaceData;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
bResult = SetupDiEnumDeviceInterfaces(hDevInfo, DeviceInfoData, &GUID_DEVCLASS_BLUETOOTH, j, &interfaceData );
if (!bResult) {
int lastError = GetLastError(); // always returns ERROR 259
continue;
}
// Get the size of the buffer required to receive the device info
SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, NULL, 0, &requiredLength, NULL );
if( requiredLength >= sizeof( detailDataBuf ) )
break;
// Get the name of the device
detailData->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA );
length = requiredLength;
bResult = SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, detailData, length, &requiredLength, NULL ) != 0;
if( !bResult )
break;
}
}
EDITED2:
Passing in NULL for DeviceInfoData: This simple case always returns false
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_BLUETOOTH, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
bool bResult = FALSE;
for(DWORD j = 0; j < 10; j++ )
{
SP_DEVICE_INTERFACE_DATA interfaceData;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
bResult = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVCLASS_BLUETOOTH, j, &interfaceData );
if (!bResult) {
int lastError = GetLastError(); // ERROR 259
continue;
}
}
The documentation says:
DeviceInfoData [in, optional]
A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet.
In other words, it must point to an element of deviceInfo, which the pointer you are passing doesn't. If you don't want to filter the results to the interfaces of a specific device in the device information set, pass NULL.
(Note that this is an input parameter, as indicated by the "in" tag. The output is passed via the fifth parameter, DeviceInterfaceData.)
I have a task where I need to put some mouse clicks on web form displayed in browser, and also do some keyboard input, as fill the text box with numbers or make sequence of pressing down arrows in order to get choice in combo box.
Window handlers I have, coordinates where click too, it works fine for me (very simple function):
extern "C" __declspec(dllexport) void __stdcall PutSingleClick(unsigned hwnd, int x, int y)
{
SendMessage(((HWND) hwnd), WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
SendMessage(((HWND) hwnd), WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
}
My problem appears while I try to send keyboard input, as for example by calling:
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.time = 0;
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wScan = VK_DOWN;
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
ip.ki.wScan = VK_RETURN;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
After calling this function nothing done, only in input buffer remains strange character (" ยด " [akcent, dead character] in my case).
While I try to catch what happens by Spy++, mouse events (clicks) are spied correctly (when generated both manually and by program), but keyboard ones not - either program or manual.
While I try utility On screen keyboard (common part of Windows), it works as good as hardware keyboard (numbers was inputed, chosen value are changed....), but no messages is generated.
Any idea how emulate hardware keystrokes and put sequence where I need?
Thanks a lot.
VK_DOWN and VK_RETURN are virtual keys, not scan codes. As such, when calling SendInput(), use the ip.ki.wVk field instead of the ip.ki.wScan field, and get rid of the KEYEVENTF_SCANCODE flag:
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip = {0};
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = VK_DOWN;
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
ip.ki.dwFlags = 0;
ip.ki.wVk = VK_RETURN;
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
However, you shouldn't call SendInput() to send multiple input events individually like this. It defeats the purpose of using SendInput() vs keybd_event(), with none of the benefits. Instead, you should send all of the events at one time in a single call to SendInput() by using an array, eg:
#include <vector>
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
INPUT ip = {0};
ip.type = INPUT_KEYBOARD;
ip.ki.wVk = VK_DOWN;
std::vector<INPUT> ips;
ips.reserve((times*2)+2);
for(int i = 0; i < times; i++)
{
ip.ki.dwFlags = 0;
ips.push_back(ip);
ip.ki.dwFlags = KEYEVENTF_KEYUP;
ips.push_back(ip);
}
ip.ki.dwFlags = 0;
ip.ki.wVk = VK_RETURN;
ips.push_back(ip);
ip.ki.dwFlags = KEYEVENTF_KEYUP;
ips.push_back(ip);
SendInput(ips.size(), &ips[0], sizeof(INPUT));
}
The content of the '.text' section is accessed using code like this:
1) For the application which is loaded into memory (i.e. executing):
//accessing code in memory
PIMAGE_DOS_HEADER pDOSHeader = NULL;
pDOSHeader = static_cast<PIMAGE_DOS_HEADER>( (void*)hModule);
...
PIMAGE_NT_HEADERS pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>((byte*)hModule + pDOSHeader->e_lfanew );
...
PIMAGE_FILE_HEADER pFileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>((byte*)&pNTHeader->FileHeader );
...
PIMAGE_OPTIONAL_HEADER pOptionalHeader =
reinterpret_cast<PIMAGE_OPTIONAL_HEADER>((byte*)&pNTHeader->OptionalHeader );
...
PIMAGE_SECTION_HEADER pSectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
(byte*)&pNTHeader->OptionalHeader +
pNTHeader->FileHeader.SizeOfOptionalHeader );
//so iterate headers and select one with right name
const char TEXT[] = ".text";
const char BSSTEXT[] = ".textbss";
unsigned int nSectionCount = pNTHeader->FileHeader.NumberOfSections;
char szSectionName[ IMAGE_SIZEOF_SHORT_NAME + 1 ];
szSectionName[ IMAGE_SIZEOF_SHORT_NAME ] = '\0';
for( unsigned int i = 0; i < nSectionCount; i++ )
{
memcpy( szSectionName, pSectionHeader->Name,
IMAGE_SIZEOF_SHORT_NAME );
if( 0 == strncmp( TEXT, szSectionName,
IMAGE_SIZEOF_SHORT_NAME ) )
{
break;
}
pSectionHeader++;
}
pVirtualAddress = (void*)(pSectionHeader->VirtualAddress);
dwCodeSize = pSectionHeader->Misc.VirtualSize;
//seems resonable: To calculate the real starting address of a given section in memory,
//add the base address of the image to the section's VirtualAddress stored in this field.
pCodeStart = (void*)(((byte*)hModule) +(size_t)((byte*)pVirtualAddress) );
pCodeEnd = (void*)((byte*)pCodeStart + dwCodeSize);
2) For the application file read from hdd and mapped into memory:
//loading code from file and mapping
hFile = CreateFile( filename, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
...
hFileMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY ),0, 0, NULL );
...
pBaseAddress = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 );
...
PIMAGE_DOS_HEADER pDOSHeader = static_cast<PIMAGE_DOS_HEADER>( pBaseAddress);
...
PIMAGE_NT_HEADERS pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(
(PBYTE)_pBaseAddress() + pDOSHeader->e_lfanew );
...
PIMAGE_FILE_HEADER pFileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>(
(PBYTE)&pNTHeader->FileHeader );
...
PIMAGE_OPTIONAL_HEADER pOptionalHeader =
reinterpret_cast<PIMAGE_OPTIONAL_HEADER>(
(PBYTE)&pNTHeader->OptionalHeader );
PIMAGE_SECTION_HEADER pSectionHeader =
reinterpret_cast<PIMAGE_SECTION_HEADER>(
(PBYTE)&pNTHeader->OptionalHeader +
pNTHeader->FileHeader.SizeOfOptionalHeader );
DWORD dwEntryPoint = pNTHeader->OptionalHeader.AddressOfEntryPoint;
UINT nSectionCount = pNTHeader->FileHeader.NumberOfSections;
const char TEXT[] = ".text";
const char BSSTEXT[] = ".textbss";
char szSectionName[ IMAGE_SIZEOF_SHORT_NAME + 1 ];
szSectionName[ IMAGE_SIZEOF_SHORT_NAME ] = '\0';
for( unsigned int i = 0; i < nSectionCount; i++ )
{
memcpy( szSectionName, pSectionHeader->Name,
IMAGE_SIZEOF_SHORT_NAME );
if( 0 == strncmp( TEXT, szSectionName,
IMAGE_SIZEOF_SHORT_NAME ) )
{
break;
}
pSectionHeader++;
}
// Use this when probing On Disk. It is where things
// are on disk - not where they will be in memory
dwRawData = pSectionHeader->PointerToRawData;
// Use this when probing On Disk. It is where things
// are on disk - not where they will be in memory
pCodeStart = (void*)((byte*)pBaseAddress +
pSectionHeader->PointerToRawData );
pEntryPoint = (void*)(((byte*)pBaseAddress) + dwEntryPoint);
dwCodeSize = pSectionHeader->Misc.VirtualSize;
pCodeEnd = (void*)((byte*)pCodeStart + pSectionHeader->Misc.VirtualSize );
If the application is built with Visual Studio, all the bytes between pCodeStart and pCodeEnd are matching in both cases.
But if the application is built with GCC (MinGW) some bytes which are following pCodeStart and prior pCodeEnd are the same but somewhere in the middle some different bytes are appearing.
Why does it happen?