7
votes

I'm repeating a question from another forum, as I'd like the same answer.

From MSDN's SwapMouseButton Function.

How do I pass boolean data from command prompt through rundll32.exe to a boolean type argument in a command running from user32.dll?

I'm trying to run this from CMD (the command prompt)

RUNDLL32.EXE user32.dll,SwapMouseButton *

Where the asterisk is here is where the argument should go. I already ran it without an argument and it swapped my left and right mouse buttons (seems TRUE is the default entry for the boolean argument). Now I want to undo it. However I've tried each of these for passing FALSE in the argument, and none have worked (none set my mouse buttons back to normal).

  • F
  • f
  • false
  • False
  • FALSE
  • "false"
  • "False"
  • "FALSE"
  • 0
  • -1

Please help me pass the argument as needed. Thanks in advance.

5
I'm not on a Windows machine right now, but did you try 1 at all, or nothing at all?user114600
rundll32 always passes the argument as a string, hence in your case a string pointer != FALSE = TRUE to SwapMouseButtons. rundll32 can't just magically know to parse your argument as an integer.wj32

5 Answers

13
votes

You do not use rundll32 for that.

Q164787: INFO: Windows Rundll and Rundll32 Interface

[...] Rundll and Rundll32 programs do not allow you to call any exported function from any DLL. For example, you can not use these utility programs to call the Win32 API (Application Programming Interface) calls exported from the system DLLs. The programs only allow you to call functions from a DLL that are explicitly written to be called by them.


If you have the .NET Framework Runtime installed, it comes with compilers for several languages (for example, %SystemRoot%\Microsoft.NET\Framework64\v3.5\csc.exe for the v3.5 C# compiler on 64-bit systems). You can write a program in C#:

using System.Runtime.InteropServices;
using System;

class SwapMouse {
    [DllImport("user32.dll")]
    public static extern Int32 SwapMouseButton(Int32 bSwap);
    static void Main(string[] args) {
        if (args.Length > 0 && String.Compare(args[0], "/u", true) == 0)
            SwapMouseButton(0);
        else
            SwapMouseButton(1);
    }
}

Compile with:

"%SystemRoot%\Microsoft.NET\Framework64\v3.5\csc" swap.cs

Swap/unswap buttons:

swap
swap /u
16
votes

Thanks so much for the C# solution. It worked like a charm.

I made a slight alteration so that I could simply click on a desktop short-cut to toggle the primary mouse button, without passing in arguments. In case my approach helps someone else, here is that version:

using System.Runtime.InteropServices;
using System;

class SwapMouse
{
    [DllImport("user32.dll")]
    public static extern Int32 SwapMouseButton(Int32 bSwap);

    static void Main(string[] args)
    {
        int rightButtonIsAlreadyPrimary = SwapMouseButton(1);
        if (rightButtonIsAlreadyPrimary != 0)
        {
            SwapMouseButton(0);  // Make the left mousebutton primary
        }
    }
}
4
votes

There is hack, which can be used to configure the layout of the mouse for a left-handed user. Just run the following command:

rundll32.exe user32.dll,SwapMouseButton

Run this command to reconfigure the layout of the mouse for a left-handed user.

I am going to give you an explanation for this kind of behaviour:

Functions, which are called by rundll32.exe, have the following function prototype:

void CALLBACK  EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

SwapMouseButton has the following function prototype:

BOOL WINAPI SwapMouseButton(
  _In_ BOOL fSwap
)

SwapMouseButton uses the same calling convention (__stdcall) as every function called by rundll32.exe does.

If you call SwapMouseButton using rundll32.exe with an additional command-line, this command-line will be passed to this function as lpszCmdLine and will be ignored.

If you call that functions using rundll32, rundll32 automatically passes a valid window handle (HWND) as the first argument of the called function.

hwnd - window handle that should be used as the owner window for any windows your DLL creates

The function SwapMouseButton function called by rundll32 requires TRUE as the first argument in order to configure the layout of the mouse for a left-handed user. The valid window handle passed by rundll32.exe to SwapMouseButton within user32.dll is unequal to 0 and is defined as TRUE, when using a BOOL value.

You can find details on rundll32.exe and the prototype used by functions called by this executable here: INFO: Windows Rundll and Rundll32 Interface

You can find details about the function SwapMouseButton here: SwapMouseButton function (Windows)

3
votes

A shorter swapper in C:

#include <windows.h>

int main()  
{
    if (SwapMouseButton(TRUE))
        SwapMouseButton(FALSE);

    return 0;  
}

Install Windows SDK and Compile in x86_x64 Cross Tools Command Prompt via eg. cl swapmbtn.c "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\x64\user32.lib"

Rename main to WinMain to prevent the console window flash.

-1
votes

I solved the same problem by searching "mouse" in the start menu. You will find an option with the same name. click it. A dialog box will appear. There untick the option "switch primary and secondary buttons" in the buttons tab with the "button configurations" box.