Wednesday, June 29, 2016

Unity's Invalid DWORD (32-bit) value problem

Apparently, the Unity developers decided that it is good idea to store floating point values in the registry.
The registry does not support floating point, but you know what it does support? Integers. so let's use that!
So they did something like:
double f;
RegSetValueExA ( KeyHandle, ValName, 0, REG_DWORD, &f, sizeof(f) )

It is just that... double is 64-bit type. DWORD is 32-bit type.

Well, Windows doesn't care. For it, the type is just a label on the value, for readability. Internally, all the registry values are binary blobs. 

And that's why I had to implement 64-bit DWORDs. 

Tuesday, June 14, 2016

XInput's hidden functions

Inside X_Input, there are a couple of undocumented functions. You can load them not by name, but by ordinal.
I tried to find as much as I can about them:

DWORD __stdcall __ordinal(100) XInputGetStateEx(DWORD dwUserIndex, XINPUT_STATE* pState)
The same as XInputGetState, adding the "Guide" button.
#define XINPUT_GAMEPAD_GUIDE 0x0400

DWORD __stdcall __ordinal(101) XInputWaitForGuideButton(DWORD dwUserIndex, DWORD dwFlags, PVOID pUnKnown)
If dwFlags == 0 - blocking until Guide button is pressed. Otherwise, it is async.
I am not clear on how to get the async option to report.

DWORD __stdcall __ordinal(102) XInputCancelGuideButtonWait(DWORD dwUserIndex)
If XInputWaitForGuideButton was activated in async mode, this will stop it.

DWORD __stdcall __ordinal(103) XInputPowerOffController(DWORD dwUserIndex)
I think that his one is clear.

struct _XINPUT_BASE_BUS_INFORMATION
{
WORD a1;
WORD a2;
DWORD a3;
DWORD Flags; // probably
BYTE a4;
BYTE a5;
BYTE a6;
BYTE reserved;
 }
DWORD __stdcall __ordinal(104) XInputGetBaseBusInformation(DWORD dwUserIndex, XINPUT_BASE_BUS_INFORMATION *pInfo)
Not working on all gamepads. It can refuse and return ERROR_DEVICE_NOT_CONNECTED, even if connected.

struct XINPUT_CAPABILITIES_EX
{
XINPUT_CAPABILITIES Capabilities;
WORD a1;
WORD a2;
WORD a3;
DWORD a4;
};
DWORD __stdcall __ordinal(108) XInputGetCapabilitiesEx(DWORD a1, DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES_EX *pCapabilities)
a1 should probably be 1.

Sunday, June 5, 2016

Monkey business in IMMDeviceEnumerator

winmmbase.dll's function winmmGetMidiInterfaces create a IMMDeviceEnumerator object, and the uses QueryInterface using this UUID:
"3e52272f-3c89-45f8-be26-cb3b91ab42a0"
I couldn't find why and what is this uuid is about.

Wednesday, June 1, 2016

COM objects can be elusive

When proxying a COM object, queryinterface it can be frustrating.
A program can ask for other interface, and then return to the original interface.
If you are not covering all the interfaces that the object support, a program can bypass the proxy this way.

Also, A lot of unexpected interfaces can be created using CoCreateInstance, bypassing their official "create" function.