Send Shift/Alt/Ctrl in SendInput - c#

I'm writing a controller program, which simulates keystrokes to any active application. I found the SendInput method like this(I only care for keyboard, so irrelevant definitions omitted):
[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)]
public Int32 type;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public Int16 wVk;
public Int16 wScan;
public Int32 dwFlags;
public Int32 time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll")]
public static extern UInt32 SendInput(UInt32 nInputs, ref INPUT pInputs, int cbSize);
I know the wVk and wScan can be assigned by a System.Windows.Forms.Keys enumation value. I also looked at the values, and found Shift=65536, Control=131072, Alt=262144(the value of all keys is 1-254). I also know those three values should be in wScan(corresponding 1,2,4) and they are modifier state flags. But three questions:
For example, I want to send a left Ctrl key to the active application, must I pass both wVk==LControlKey and wScan==Control right? What will happen if I only pass the first and not the second? And should I pass wVk==LControlKey; wScan==Control; dwFlags==0(key down dwFlags), and wVk==LControlKey; wScan==0; dwFlags==2(key up dwFlags)?
in Keys enumation there exist LControlKey, RControlKey, ControlKey, what's the third one mean?
in Keys enumation there exist Control keys and Shift keys, but why not Alt keys? So isn't it possible to send an Alt keystroke by SendInput method?

Related

AccessViolationException when calling C dll from C#

I'm trying to create a wrapper for a C dll to use it in C#. I don't have the source code of the dll.
I'm having problem using a method that gives me "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt'" when executing. I tried to search online for the same problem but I didn't find what the problem with my code is.
The method that gives the problem is the following:
C:
L3B6_API L3B6_ERR_t STDCALL L3B6_ActivateBoot(int nodeid, unsigned cpunum, unsigned ms_timeout, const char * devicenames, A * dev_param);
the wrapper I created in C# is this:
[DllImport("L3B6.dll", EntryPoint = "L3B6_ActivateBoot")]
return: MarshalAs(UnmanagedType.I4)]
static extern L3B6ErrorCode ActivateBoot(
int nodeid,
uint cpunum,
uint msTimeout,
[MarshalAs(UnmanagedType.LPStr)]
string deviceNames,
ref A devParams
);
Where L3B6ErrorCode is an enum I created but it doesn't give any problem (I used it for other methods that work).
I think the problem is in the structure A. The original structure is like this:
struct A
{
unsigned char blv;
unsigned char cpunum;
unsigned char nodeid;
unsigned char hwverA;
unsigned char hwverB;
unsigned char hwverC;
unsigned char hwverD;
unsigned char cputype;
unsigned char hwcode;
B memini_devrec;
};
struct B
{
unsigned hwCode;
unsigned cpuCode;
unsigned dualCPU;
unsigned cpuNumber;
unsigned internalFlashStart;
unsigned internalFlashEnd;
unsigned externalFlashAccess;
unsigned externalFlashStart;
unsigned externalFlashEnd;
unsigned isResetVectorSpecified;
unsigned resetVectors;
char bootName[32];
unsigned isS19toPhyConversionAllowed;
unsigned noFlashPaging;
char deviceName[32];
char cpuName[32];
};
The corresponding structures I created are the following:
[StructLayout(LayoutKind.Sequential)]
public struct A
{
public byte bootloaderversion;
public byte cpuNum;
public byte nodeId;
public byte hwVerA;
public byte hwVerB;
public byte hwVerC;
public byte hwVerD;
public byte cpuType;
public byte hwCode;
public B meminiDeviceRecord;
};
[StructLayout(LayoutKind.Sequential)]
public struct B
{
public uint hwCode;
public uint cpuCode;
[MarshalAs(UnmanagedType.Bool)]
public bool dualCPU;
public uint cpuNumber;
public uint internalFlashStart;
public uint internalFlashEnd;
public uint externalFlashAccess;
public uint externalFlashStart;
public uint externalFlashEnd;
[MarshalAs(UnmanagedType.Bool)]
public bool isResetVectorSpecified;
public uint resetVectors;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string bootName;
[MarshalAs(UnmanagedType.Bool)]
public bool isS19toPhyConversionAllowed;
[MarshalAs(UnmanagedType.Bool)]
public bool noFlashPaging;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string deviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string cpuName;
};
I've used the structure B in another method that needed to fill it and didn't have any problem, so I suppose the problem is in the A structure, but I can't understand what I'm doing wrong. I think the problem is that structure because also another method that takes that structure as parameter is giving me the same exception. I checked the size of the structs in C and C# and it is the same.

how to convert c struct with void* to c#

I'm write a plugin with c# . the program with c# will use a dll which writes by c ,so I have to call c function in my c# program ,but unfortunately the c function's parameter is a struct and it is so complex that I never find any
help information about how to convert it to c# parameter.
the struct has an embedded function and void* parameter ,I didn't find anyway to convert them to c#.
the struct is mostly like this
struct first_struct{
char* parameter1;
int parameter2;
unsigned long parameter3;
unsigned short parameter4;
void* parameter5;
int (*parameter6)(int,void *);
second_struct parameter7;
};
struct second_struct{
char parameter8[64] ;
char parameter9[256];
};
I want change this c struct to c# struct but I have no idea how to do it
thanks #Biesi Grr and #Ian Abbott ‘s help it sames that I can change the c struct to c# like that.
public delegate int parameter6(int volcnt, System.IntPtr vod);
[StructLayout(LayoutKind.Sequential)]
public struct csharp_firstSturct
{
[MarshalAs(UnmanagedType.LPStr)]
public string parameter1;
public int parameter2;
public ulong parameter3;
public ushort parameter4;
public System.IntPtr parameter5;
public parameter6 m_parameter6;
}
but I still has no idea about how to convert parameter7 from C to C#,what should I do to convert parameter7 form c to c#.
Assuming your char arrays are null terminated strings you can do it the following way
public delegate int parameter6(int volcnt, System.IntPtr vod);
[StructLayout(LayoutKind.Sequential)]
public struct csharp_firstSturct
{
[MarshalAs(UnmanagedType.LPStr)]
public string parameter1;
public int parameter2;
public ulong parameter3;
public ushort parameter4;
public System.IntPtr parameter5;
public parameter6 m_parameter6;
[MarshalAs(UnmanagedType.Struct)]
public second_struct parameter7;
}
[StructLayout(LayoutKind.Sequential)]
public struct second_struct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string parameter8;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string parameter9;
}

How to differenciate mousemove inputs of multiple mouse devices?

I have a mouse and a touchpad on my laptop. I want a global hook for mousemove that tells me not only the new position, but also the physical device where it came from. Subscribing the hook only to the touchpad would be an even better solution, since I'm only interested in the touchpad. The hook has to work system wide (even if my application is not in focus).
How can I do this?
I'm not afraid to use Pinvoke in my C#/WPF application
You could use
P-Invoke user32.getrawinputdeviceinfo .
For mouse input you can get thing such:
[StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_MOUSE
{
[MarshalAs(UnmanagedType.U4)]
public int dwId;
[MarshalAs(UnmanagedType.U4)]
public int dwNumberOfButtons;
[MarshalAs(UnmanagedType.U4)]
public int dwSampleRate;
[MarshalAs(UnmanagedType.U4)]
public int fHasHorizontalWheel;
}
and, about Device:
StructLayout(LayoutKind.Sequential)]
internal struct RID_DEVICE_INFO_HID
{
[MarshalAs(UnmanagedType.U4)]
public int dwVendorId;
[MarshalAs(UnmanagedType.U4)]
public int dwProductId;
[MarshalAs(UnmanagedType.U4)]
public int dwVersionNumber;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public ushort usUsage;
}

Cannot declare pointer to non-unmanaged type

I'm trying to learn how to write a wrapper around a DLL and I've hit a bit of a road-block. I've got a struct declared as such:
[StructLayout(LayoutKind.Sequential)]
unsafe struct SDL_Surface
{
public readonly UInt32 flags;
public readonly SDL_PixelFormat* format;
public readonly int w, h;
public readonly int pitch;
public void* pixels;
/// <summary>Application data associated with the surface</summary>
public void* userdata;
/// <summary>information needed for surfaces requiring locks</summary>
public readonly int locked;
public readonly void* lock_data;
/// <summary>clipping information</summary>
public readonly SDL_Rect clip_rect;
/// <summary>info for fast blit mapping to other surfaces</summary>
private SDL_BlitMap *map; // <--- Cannot take the address of, get the size of, or declare a pointer to a managed type
/// <summary>Reference count -- used when freeing surface</summary>
public int refcount;
}
When I try to compile my project, it gives the above error.
But you will notice above it, I do have a pointer to another struct. I'm trying to figure out what the difference between these two structs is that makes one work but the other doesn't, but I'm not sure; they're both unsafe structs. They are as follows:
[StructLayout(LayoutKind.Sequential)]
unsafe struct SDL_PixelFormat
{
UInt32 format;
SDL_Palette *palette;
byte BitsPerPixel;
byte BytesPerPixel;
fixed byte padding [2];
UInt32 Rmask;
UInt32 Gmask;
UInt32 Bmask;
UInt32 Amask;
byte Rloss;
byte Gloss;
byte Bloss;
byte Aloss;
byte Rshift;
byte Gshift;
byte Bshift;
byte Ashift;
int refcount;
SDL_PixelFormat *next;
}
unsafe internal delegate int SDL_blit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect);
[StructLayout(LayoutKind.Sequential)]
unsafe struct SDL_BlitMap
{
SDL_Surface* dst;
int identity;
SDL_blit blit;
void* data;
SDL_BlitInfo info;
/* the version count matches the destination; mismatch indicates
an invalid mapping */
UInt32 dst_palette_version;
UInt32 src_palette_version;
}
[StructLayout(LayoutKind.Sequential)]
struct SDL_Rect
{
int x, y;
int w, h;
}
So what do I have to change to make this compile?
I believe it's the reference to SDL_blit in SDL_BlitMap that's causing the problem. I've declared it as a delegate; is there something else I should be declaring it as? It's defined as this, in C:
typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
struct SDL_Surface * dst, SDL_Rect * dstrect);
Any struct that contains a managed type cannot have its address taken.
Delegates are a reference type, therefore they are also a managed type.
This means that an SDL_Blitmap is a managed type because it contains a managed reference to an SDL_blit, thus you cannot get a pointer to it without fixing it first.
If the function you are trying to invoke is already available in the dll, I suggest you have a look at the DllImportAttribute.(http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.100).aspx)
By combining a public static extern declaration with a DllImportAttribute, you can invoke any global function declared in the dll you are interop-ing.
Alternatively you'll need to create a C/C++ side function that takes a function pointer and invokes it, which could get messy.
What if you don't rely on unsafe code? It may affect affect performance though if your code is performance/speed critical. Something along the lines of this:
[StructLayout(LayoutKind.Sequential)]
struct SDL_PixelFormat
{
UInt32 format;
IntPtr palettePtr;
byte BitsPerPixel;
byte BytesPerPixel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
byte padding[];
UInt32 Rmask;
UInt32 Gmask;
UInt32 Bmask;
UInt32 Amask;
byte Rloss;
byte Gloss;
byte Bloss;
byte Aloss;
byte Rshift;
byte Gshift;
byte Bshift;
byte Ashift;
int refcount;
IntPtr nextPtr;
}
[StructLayout(LayoutKind.Sequential)]
struct SDL_Surface
{
public readonly UInt32 flags;
public readonly IntPtr format;
public readonly int w, h;
public readonly int pitch;
public IntPtr pixels;
/// <summary>Application data associated with the surface</summary>
public IntPtr userdata;
/// <summary>information needed for surfaces requiring locks</summary>
public readonly int locked;
public readonly IntPtr lock_data;
/// <summary>clipping information</summary>
public readonly SDL_Rect clip_rect;
/// <summary>info for fast blit mapping to other surfaces</summary>
private IntPtr mapPtr;
/// <summary>Reference count -- used when freeing surface</summary>
public int refcount;
}
[StructLayout(LayoutKind.Sequential)]
struct SDL_BlitMap
{
IntPtr dstPtr;
int identity;
SDL_blit blit;
IntPtr data;
SDL_BlitInfo info;
/* the version count matches the destination; mismatch indicates
an invalid mapping */
UInt32 dst_palette_version;
UInt32 src_palette_version;
}
[StructLayout(LayoutKind.Sequential)]
struct SDL_Rect
{
int x, y;
int w, h;
}
[UnmanagedFunctionPointer(CallingConvention.ToBeAdded)]
internal delegate int SDL_blit(ref SDL_Surface src, ref SDL_Rect srcrect, ref SDL_Surface dst, ref SDL_Rect dstrect);
When you need to read any structure pointers:
var palette = (SDL_Palette) Marshal.PtrToStructure(surface.palettePtr, typeof (SDL_Pallete));
Otherwise, if you wish to stick to your current code, try declaring the function pointer as an IntPtr instead of a delegate and create the delegate during runtime using Marshal.GetDelegateForFunctionPointer.

Can I set the size attribute of StructLayout at runtime?

Im trying to use SendInput to simulate keyboard presses in my app and want to support both 32-bit and 64-bit.
I've determined that for this to work, I need to have 2 different INPUT structs as such
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public ushort wVk; // Virtual Key Code
public ushort wScan; // Scan Code
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Explicit, Size = 28)]
public struct INPUT32
{
[FieldOffset(0)]
public uint type; // eg. INPUT_KEYBOARD
[FieldOffset(4)]
public KEYBDINPUT ki;
}
[StructLayout(LayoutKind.Explicit, Size = 40)]
public struct INPUT64
{
[FieldOffset(0)]
public uint type; // eg. INPUT_KEYBOARD
[FieldOffset(8)]
public KEYBDINPUT ki;
}
I wanted to know if there was a way to set the StructLayout size and FieldOffsets at runtime so I could use just one INPUT struct and determine the size and fieldoffset depending on the machine.
I have tried the code below but I would like to know if the same is possible at runtime instead of compile time.
#if _M_IX86
[StructLayout(LayoutKind.Explicit, Size = 28)]
#else
[StructLayout(LayoutKind.Explicit, Size = 40)]
#endif
public struct INPUT
{
[FieldOffset(0)]
public uint type; // eg. INPUT_KEYBOARD
#if _M_IX86
[FieldOffset(4)]
#else
[FieldOffset(8)]
#endif
public KEYBDINPUT ki;
}
Unfortunately, no.
Attributes are "fused" to the type at compile-time, which is why all values passed to an attribute constructor must be constants.
And at runtime you can't modify the attributes attached to the type. You can grab a copy and modify its values, but the actual attribute attached to the type will remain unchanged, so you can't "trick" mscorlib code into seeing your changes instead of the original, either.
You could always have 2 structs and determine which one to use at runtime.
With a proper design you could limit code duplication to a few lines. (Plus having the structures twice.)

Categories

Resources