winapiexec is a small tool that allows to run WinAPI functions through command line parameters.


The syntax is:
winapiexec.exe library.dll@FunctionName 123 unicode_text "a space"

If you don’t specify a library or use “k”, kernel32.dll is used.
If you specify “u” as a library, user32.dll is used.

Numbers are detected automatically. You can use hex numbers (like 0xFE) and use the minus sign (e.g. -5).
Strings are Unicode by default.

You can use special prefixes to specify parameter types:
$s:ansi – an ANSI string.
$u:unicode – a Unicode string (it’s Unicode by default, but you can use it to force numbers as strings).
$b:1024 – a zero-bytes buffer with the size you specify, in bytes.
$$:1 – a reference to another parameter, you can also use $$:0 for the program’s name (argv[0]).
$a:0,1,two,3 – an array of parameters, divided by commas. you can use all the prefixes here.
$a[a,b,$a[c,d],e] – an alternative syntax for an array of parameters. Allows to have nested arrays.
$$:3@2 – a reference to an item in an array of parameters, can have more than one indirection.

While referencing to another parameter, note that they are processed by the order of execution, which means there’s no point to reference to a parameter right to the referencing one.
Also note that after a function is run, its first parameter (like library.dll@FunctionName) is replaced with the return value.

You can execute multiple WinAPI functions, one after the other, using a comma:
winapiexec.exe library.dll@FunctionName1 123 , library.dll@FunctionName2 456
You can also have nested functions, using parentheses:
winapiexec.exe library.dll@FunctionName1 ( library.dll@FunctionName2 456 )
While the return value of the internal function is passed as a parameter to the external function.


zip (6.02 kB)


Here are some examples of what you can do:

Display temp path:
winapiexec.exe GetTempPathW 260 $b:520 , u@MessageBoxW 0 $$:3 $$:0 0x40

winapiexec.exe advapi32.dll@GetUserNameW $b:65534 $a:32767 , u@wsprintfW $b:2050 "Hello %s from %s" $$:2 $$:0 , u@MessageBoxW 0 $$:6 ... 0

Hide the taskbar for half a second, then show it:
winapiexec.exe u@ShowWindow ( u@FindWindowW Shell_TrayWnd 0 ) 0 , Sleep 500 , u@ShowWindow $$:3 5

Run calculator for a second, then terminate it:
winapiexec.exe CreateProcessW 0 calc 0 0 0 0x20 0 0 $a:0x44,,,,,,,,,,,,,,,, $b:16 , Sleep 1000 , TerminateProcess $$:11@0 0

Show a messagebox and then create a new instance of the process:
winapiexec.exe u@MessageBoxW 0 Hello! :) 0 , CreateProcessW $$:0 ( GetCommandLineW ) 0 0 0 0x20 0 0 $a:0x44,,,,,,,,,,,,,,,, $b:16

Eject your disc drive :)
winapiexec.exe winmm.dll@mciSendStringW "open cdaudio" 0 0 0 , winmm.dll@mciSendStringW "set cdaudio door open" 0 0 0 , winmm.dll@mciSendStringW "close cdaudio" 0 0 0

And some more practical examples…

Copy some text into the clipboard:
winapiexec.exe lstrcpyW ( GlobalLock ( GlobalAlloc 0x0042 8192 ) ) "Sample text" , GlobalUnlock $$:5 , u@OpenClipboard 0 , u@SetClipboardData 13 $$:5 , u@CloseClipboard

Turn off and on monitor:
winapiexec.exe u@SendMessageW 0xFFFF 0x112 0xF170 2
winapiexec.exe u@SendMessageW 0xFFFF 0x112 0xF170 -1

Display the Start menu:
winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 305 0
Run task manager:
winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 420 0
More tricks like that can be found here.

Posted in Releases, Software by RaMMicHaeL at January 8th, 2011.

105 Responses to “winapiexec”

  1. xpclient says:

    What would be the command to show the Quick launch? :)

  2. mike says:

    I have the clock hidden in the system tray (windows 7) so I just want to know if there is a way to open the clock window (ex: via command line?

    Thanks in advance and keep up the good work

  3. Anonymous says:

    Does winapiexec allow sending an e-mail with custom message text and attachments via the default e-mail client?
    A while ago I tried to find a way to modify the default text Windows forces upon the user (“Your message is ready to be sent with the following file or link attachments:”) but I think I gave up.
    I think I was trying to take advantage of Windows’ simple image resizing interface. There may be other ways to achieve this (AutoHotkey), though.

  4. Mark Hopkins says:

    I took the UNIX/POSIX language BC, a while back, and upgraded it practically into a C interpreter, called C-BC. I can take some of that code and language design, remake it into a command shell and adapt it into your program’s source code, if you wish.

    C-BC has the “include” directive, so it has the ability to load modules containing pre-defined routines as well.

    The proposed extension would be invoked by just calling “winapiexec.exe” with no command-line arguments. Alternatively, it might be invoked with an argument like $@ to start the shell in mid-command. Or, the modified program might be given a different name, such as wsh.exe, mssh.exe or winsh.exe.

    The main question on my mind is how much of C-BC’s facilities to keep intact. I’d probably take out or replace its data types (extended precision numbers, strings, arrays and pointers) with a simpler system of types (bytes, words, strings, arrays). On the other hand, the temptation is strong to go into the opposite direction and throw in the whole type system of a modern language: polymorphism, abstract types, classes and all.

    The other question, of course, is what unforeseen consequences there will be in combining a command-line windows API processor with a programming language interpreter.

    If you’re interested, send an e-mail note.

    • RaMMicHaeL says:

      Hi Mark,

      1995, huh? I was 4 back then 😛

      I can take some of that code and language design, remake it into a command shell and adapt it into your program’s source code, if you wish.

      If I wish? I won’t mind.

      the temptation is strong to go into the opposite direction and throw in the whole type system of a modern language: polymorphism, abstract types, classes and all.

      Polymorphism and classes in a command shell? o_O

      Do I get it right, that by command shell you mean something like cmd.exe? I’m not very familiar with UNIX/POSIX OSes, but from what I understand, you want to extend the syntax to include C-BC functions, to allow e.g. to create a while loop from command line?

      A couple of examples of what would it look like or what would it be able to do will help me get the idea better.


      • Mark says:

        You were 4? That’s a pretty good memory. Though I have to admit, my earliest memory was some time around the age of 3-6 months.

        But C-BC was put out in October 1993, not 1995. The source is 4000 lines and I was always intending on putting threaded multitasking directly in C-BC. This would yield a vastly simplified wrapper for WinAPI, if it is properly integrated with it. It goes the other way too. It’s easier to put multithreading in the language if it can deferred to native OS API’s. The 2010 extensions to C/C++ may also help, though they’re 20 years overdue.

        I’ll back away a little from all this to think more about everything — especially with Windows and even PC’s quickly falling out of date.

        But yes, in answer to your question: shells do loops, branches and other control flow as a matter of course. Take a look at the page on C-shell at and there are similar features are in Window shell, too … and even in DOS… which is what Windows shell was up until Windows XP.

        But nobody pulls out the Windows API up front. I also found this comparison for command line shells:

        Scripting languages, do control flow too, like these:

        both of which has more contemporary systems of data types built into them.

        But after thinking about all this, it might actually be better to focus on mobile systems (or even Linux), rather than Windows.

        • RaMMicHaeL says:

          You were 4? That’s a pretty good memory. Though I have to admit, my earliest memory was some time around the age of 3-6 months.

          I found the article in Google, and just wanted to say it was written a long time ago. I surely wasn’t interested in programming when I was 4.

          Anyway, winapiexec is a tiny <4 KB tool that I wrote for no specific purpose. The nice thing about it is that you can create a shortcut that would do some unique stuff, e.g. showing the system clock.

          I’ve never used it in a shell script, and I assume that if a single command line for winapiexec is not enough, it might be worth to just write the code in e.g. C, or even in a scripting language such as Lua (which appears to support calling WinAPI functions).

  5. Jegimeco says:

    Please a command to enable/disable windows shadows in Windows 7 x64 on the fly. Thanks.

  6. Bizarre™ says:

    Does anyone know how to decommit private bytes for a specific process using this program?

  7. Aquilai says:

    Avast Anti-Virus blocked my download before it started stating winapiexec is a suspicious Win32:MDE-B [Susp] item. Could you contact Avast to have it allowed?

  8. Iron Slippers says:

    А можно этой чудо-программкой запустить команду “Minimize all”, ну и соответственно обратно?

    • RaMMicHaeL says:

      “Minimize all”:
      winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 419 0

      Обратно оно не работает. Для этого можно использовать “Show desktop”:
      winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 407 0

      • IronSlippers says:

        Спасибо. До этого у меня вот такая веселая конструкция была:
        chp.exe —> cmdow.exe —> ярлык с командой

  9. Sleeping_Dragon says:

    Is there a command for this tool to do manual garbage collection? If so, can it also be done on a specific process?

  10. YouCrazyKids says:

    Hi there, I’m attempting to use winapiexec through a batch file to read the system idle time (using the User32.dll function GetLastInputInfo), but don’t understand how it would be expressed in the batch file. Is it even possible using winapiexec? My attempt was:

    winapiexec User32.dll@GetLastInputInfo(LastInputInfo)

    The GetLastInputInfo function description from Microsoft is really cryptic. Any help you can give would be appreciated. Thanks!

    • RaMMicHaeL says:


      GetLastInputInfo is a bit complicated, as it expects a reference of a structure.

      Here’s an example of how it can be done:

      winapiexec.exe u@GetLastInputInfo $a:8,0 , InterlockedExchange $b:4 $$:2@1 , InterlockedExchange $$:5 0

      According to the documentation, this will return “The tick count when the last input event was received.”.

      The current tick count can be retrieved with the GetTickCount function:

      winapiexec.exe GetTickCount
      • Dragos says:

        Hi, I was just about to ask about this when I saw this post, I’ve tried the code but it did not work.

        I’m running Windows 8.1 (x86), does this work on your end?

        Thank you

          • Dragos says:

            Thank you Michael!

            I wasn’t calling it right, it works with your example but it seems to get something else rather that what I’ve expected.

            GetTickCount gets the time passed sinced the last restart/power on but what I need is GetLastInputInfo wich “retrieves the time of the last input event.”

            I’ve found something made with AutoIt, here:
            and I guess I’ll stick with this for the moment.

            Thank you once again for your fast reply (it was late last night for me to respond) and best regards!

            PS: btw nice hack for ResHacker :)

            • RaMMicHaeL says:

              what I need is GetLastInputInfo wich “retrieves the time of the last input event.”

              By subtracting the GetTickCount result from the GetLastInputInfo result, you can get the number of milliseconds the PC was idle. I don’t know what you’re into, so I can’t give a more specific advice.

              Seems like the code in the link you posted calls GetLastInputInfo repeatedly, until the value changes, which means that the user is not idle anymore.

  11. highend says:


    would it be possible to use SHGetKnownFolderPath from shell32.dll to return the real folder if we supply the GUID?

    E.g.: “{4BD8D571-6D19-48D3-BE97-422220080E43}”
    which is the GUID for “My Music”. Many of the new GUIDs (SkyDrive / OneDrive on Win 8.1) aren’t present in the User Shell Folder (registry path) so SHGetKnownFolderPath is the the only viable option 😉

    • RaMMicHaeL says:


      Yeah, that’s possible:

      winapiexec.exe shell32.dll@SHGetKnownFolderPath $a:0x4BD8D571,0x48D36D19,0x224297BE,0x430E0820 0 0 $b:4 , u@MessageBoxW 0 $$:5@0 $$:0 0x40

      The GUID format is not straightforward, so I wrote a small conversion script:

      Click on fork, replace the GUID, and run it right in the browser :)

      $guid = '{4BD8D571-6D19-48D3-BE97-422220080E43}';
      $p = '#{?([0-9A-F]{8})-'.
      preg_match($p, strtoupper($guid), $m);
      echo sprintf('0x%s,0x%s%s,0x%s%s%s%s,0x%s%s%s%s', 
      	$m[3], $m[2], 
      	$m[7], $m[6], $m[5], $m[4], 
      	$m[11], $m[10], $m[9], $m[8]);
  12. highend says:

    Hi RaMMicHaeL,

    thanks for your reply and posting the necessary command line, much appreciated!

    Works perfectly fine (the .php code for putting the 0x… things together as well.

    Is there a way to return the output to stdout (e.g. when called from inside a dos box) instead of a real window?


    • RaMMicHaeL says:

      Here you go:

      winapiexec.exe shell32.dll@SHGetKnownFolderPath $a:0x4BD8D571,0x48D36D19,0x224297BE,0x430E0820 0 0 $b:4 , AttachConsole -1 , WriteConsoleW ( GetStdHandle -11 ) $$:5@0 ( lstrlenW $$:5@0 ) $b:4 0

      Note that by default the process starts in the background, so the output order could get mixed up. You can use START /WAIT to fix this:

      START /WAIT winapiexec.exe shell32.dll@SHGetKnownFolderPath $a:0x4BD8D571,0x48D36D19,0x224297BE,0x430E0820 0 0 $b:4 , AttachConsole -1 , WriteConsoleW ( GetStdHandle -11 ) $$:5@0 ( lstrlenW $$:5@0 ) $b:4 0

  13. highend says:

    Just incredible…

    Thanks again!


  14. David.M says:


    I having trouble understanding how WinApiExec replicates C structures. I know it can create arrays but how do you control how many bytes each array member takes up? Some API structures have a mix of different width members. Also can you explain the array referencing syntax a little more. What does $$:5@0 reference? Is the 0 array one which is passed to the executable?



    • RaMMicHaeL says:

      Hi David,

      See the example with CreateProcess (“Run calculator for a second, then terminate it”).
      $a is an array of doublewords, and because most structures are padded, this should fit nicely. If it’s not padded, you’ll have to hack around, similarly to what I did above with GUIDs:

      What does $$:5@0 reference?

      $$:5 is the fifth argument. $$:5@0 is equivalent to this in C:
      ((DWORD *)argv[5])[0];

      In the example above (with the GUIDs), the fifth argument holds a pointer to a string, so argv[5] is a pointer to a pointer.

  15. David.M says:


    Thanks for the info, I understand the syntax now. Is there a why to return the output to the global atom table? I use a scripting language that could get the data from athe atom table rather than the console.



  16. David Paul says:

    I need to refresh after changing registry keys
    “HKCU \ Software \ Microsoft \ Windows \ CurrentVersion \ Internet Settings \ ProxyEnable” to 0/1 DWORD.

    It is about turning off the proxy in the registry. But after that change the system knows that proxy was changed and only works when the ticks manually in the GUI.

    Thanks for your time

    David Paul

  17. sheldon says:

    I try to change taskbar icons size on the fly without terminating explorer process
    So long I came up with this script (Windows 7):

    @echo off
    (reg add “hkcu\software\microsoft\windows\currentversion\explorer\advanced” /v TaskbarSmallIcons /t REG_DWORD /d 0 /f)>NUL
    winapiexec.exe u@SendMessageW ( u@FindWindowW Shell_TrayWnd 0 ) 0x111 413 0
    ping -n 1 -w 1 > nul
    nircmd.exe dlg “” “” click OK

    Could you please take a look at this? How to make this shorter or at least replace nircmd with winapiexec


  18. peter says:

    I would like to send a message to the taskbar window that will restore all firefox windows, then another message that will minimize them. Minimizing is less important than restoring, since there are other ways to do that. I can’t figure out how to use winapiexec to send the correct message.

    Here is why I want to do this. I use the auto-hide feature of taskbar, and in addition place it at the left of my screen to maximize readability of a large number of open windows.

    Windows has the “helpful” feature that taskbar will not autohide as long as some window is demanding focus. Unfortunately, it is often impossible to determine what window that is. In the case of firefox, this happens every time, because some windows put up a modal dialog for passwords, or other warning. Usually, the FF taskbar icons are not grouped, so getting taskbar to autohide requires multiple operations. Thus, I want to create a desktop shortcut to do it. Nircmd almost is enough, but for example I do not know FF window class.

  19. peter says:


    Knowing the window class might be enough to use Nircmd to do what I want.

    BTW, as a former c++ programmer, you’d think I could just write a few lines of code, but re-learning all the details of how to use the Windows API is not a torture I want to endure a second time. (And, these days I would have to compile in visual studio, not g++ under linux, yet another form of torture.)

    • peter says:

      Oh, actually I guess it is “gcc”.


      Knowing the window class might be enough to use Nircmd to do what I want.

      BTW, as a former c++ programmer, you’d think I could just write a few lines of code, but re-learning all the details of how to use the Windows API is not a torture I want to endure a second time.(And, these days I would have to compile in visual studio, not g++ under linux, yet another form of torture.)

  20. peter says:

    For the benefit of those who might stumble upon my question in the future, it turned out that I did not need to know the window class after all; it was sufficient to know the process name for Nircmd.

    The following nircmd invocation accomplishes what I wanted:

    nircmd.exe win activate process “firefox.exe”

    That restores all firefox windows. BTW, using the class instead will also restore windows built on firefox, such as icedragon, which is essentially a branded firefox. However, the command line above does not allow selecting which profile’s process’s windows get restored. (I.e., does not differentiate among groups.)

  21. DV says:

    Fantastic small tool! Exactly what I was looking for (or was thinking about writing something similar myself).
    The only thing I’d be happy to see in addition would be a 64-bit version of the very same tool to be able to deal with 64-bit dlls.

  22. DV says:

    Just curious: what is the programming language of winapiexec?

    And let me show an example of using winapiexec to put some unicode text into the clipboard. ( Inspired by )

    Example 1: places the text “Sample text” into the clipboard:
    winapiexec kernel32@GlobalAlloc 0x0042 8192 , kernel32@GlobalLock $$:1 , kernel32@lstrcpyW $$:5 “Sample text” , kernel32@GlobalUnlock $$:1 , user32@OpenClipboard 0 , user32@SetClipboardData 13 $$:1 , user32@CloseClipboard

    Example 2: something more useful – placing path to current directory into the clipboard:
    winapiexec kernel32@GetCurrentDirectoryW 512 $b:1024 , kernel32@GlobalAlloc 0x0042 8192 , kernel32@GlobalLock $$:5 , kernel32@lstrcpyW $$:9 $$:3 , kernel32@GlobalUnlock $$:5 , user32@OpenClipboard 0 , user32@SetClipboardData 13 $$:5 , user32@CloseClipboard

    • RaMMicHaeL says:

      Just curious: what is the programming language of winapiexec?

      C, with one function in inline assembly.

      And let me show an example of using winapiexec

      Cool. I really like that such a small tool of 4 KB can do so much.

      A couple of notes:

      • kernel32 can be replaced with k, or omitted at all. user32 can be replaced with u.
        e.g. kernel32@GlobalAlloc -> GlobalAlloc. user32@OpenClipboard -> u@OpenClipboard.
      • Calls can be nested. e.g.:
        kernel32@GlobalAlloc 0x0042 8192 , kernel32@GlobalLock $$:1 -> kernel32@GlobalLock ( kernel32@GlobalAlloc 0x0042 8192 )

      All in all, the first example can look like this:
      winapiexec.exe lstrcpyW ( GlobalLock ( GlobalAlloc 0x0042 8192 ) ) "Sample text" , GlobalUnlock $$:5 , u@OpenClipboard 0 , u@SetClipboardData 13 $$:5 , u@CloseClipboard

      • DV says:

        OK, C is good! Optimistically it means: to produce a 64-bit binary, just a different target machine needs to be specified during the compilation of the very same source file! (Though, pessimistically it means that additionally amd64-related paths to headers, libraries and so on must exist and must be specified for the compilation; plus some compiler-specific flags and/or environment variables.)
        Anyway, looking at disassembled code, I’ve noticed usage of LoadLibraryW, but not of FreeLibrary. I mean, to be 100% safe, it would be better to call FreeLibrary after the library is no more needed. (Surely, FreeLibrary needs to be called only for libraries loaded via LoadLibraryW – and not for libraries acquired via GetModuleHandle.)

        • RaMMicHaeL says:

          To produce a 64-bit binary, I’ll have to rewrite that one assembly function to 64-bit. And because Visual Studio doesn’t support 64-bit inline assembly, I’ll have to find another way to integrate it with the C code.

          As of FreeLibrary: because winapiexec is usually a short-lived process, I don’t free memory and don’t unload the libraries. For libraries, MSDN states the following:

          The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).

          Therefore, it looks to me that everything is 100% safe as is.

          • DV says:

            You are right.
            As for the assembly, looks like the 64-bit asm code needs to be located inside a separate .asm file. (I was looking at the sources of as an example. There are source files ISystemFunction.c, ISystemFunction.h and ISystemFunction64.asm inside the archive. And the Build-x64.cmd includes such line: “ML64 /c ISystemFunction64.asm”)

  23. RaMMicHaeL says:

    winapiexec v1.1 was just released.

    Release notes:
    * A 64-bit version.
    * An additional syntax for arrays. Allows to have nested arrays.
    Example: $a[a,b,$a[c,d],e].
    * A little bit safer: if arguments are missing (16 at most), zero values are being used instead of random values on the stack. For example:
    winapiexec.exe u@wsprintfW $b:2050 %p,%p,%p,%p , u@MessageBoxW 0 $$:2 $u: 0

    As for the 64-bit version, note that not every command which works for the 32-bit version works for the 64-bit version without changes.
    For example, this command:
    winapiexec.exe shell32.dll@SHGetKnownFolderPath $a:0x4BD8D571,0x48D36D19,0x224297BE,0x430E0820 0 0 $b:4 , u@MessageBoxW 0 $$:5@0 $$:0 0x40
    Has to be adjusted like this:
    winapiexec64.exe shell32.dll@SHGetKnownFolderPath $a:0x48D36D194BD8D571,0x430E0820224297BE 0 0 $b:8 , u@MessageBoxW 0 $$:5@0 $$:0 0x40

  24. EliadTech says:

    Hi RaMMicHaeL.

    First, this seems like a really great tool.

    I can’t figure out how to pass a boolean value to the API function (specifically User32@BlockInput).

    I’ve tried 1/0 and True/False, and both seem to fail. (Though there’s no output, so I’m flying blind here…)

    Any suggestions?

    • RaMMicHaeL says:

      BOOL is defined as int, so 1/0 should do.
      But note that according to MSDN:

      The thread that blocked input unexpectedly exits without calling BlockInput with fBlock set to FALSE. In this case, the system cleans up properly and re-enables input.

  25. EliadTech says:

    Here’s my script:
    winapiexec64.exe user32.dll@BlockInput 1
    Timeout /T 5
    winapiexec64.exe user32.dll@BlockInput 0

    During the timeout it sohould be blocked, right? But it ain’t working…

    • RaMMicHaeL says:

      Two things:
      * After your first use of winapiexec64.exe, the process terminates. Therefore, the blocking resets (read my reply above).
      * Seems like you can successfully call BlockInput only as administrator.

      This command seems to work if launched as administrator:
      winapiexec64.exe u@BlockInput 1 , Sleep 5000 , u@BlockInput 0

  26. EliadTech says:

    Right, I had the CMD process in mind…
    I’ve a Posh script that use the same function, and I could’ve sworn that it worked without admin rights…

    Thanks for the tool and the support.

  27. DTM says:

    Just so that you are aware :: Your other stuff is great!

    WinAPI Exec fails on my machine.

    ERROR : winapiexec.exe is not a valid Win32 application.

    Is it just my machine? WinXP SP3

    Compile time switches? /IncludeDeadOSFuncs =)


  28. DTM says:

    The file from dropbox:
    winapiexec.exe 2015.08.15 11:51PM

    SHA : 46e4d50b8812457ae27ca1aad178d59e6f7efcd4

    VS.JIT Debugger Popup
    An unhandled win32 exception occurred in winapiexec.exe [3704]


    For what it’s worth…
    My WinXP SP3 has almost ALL of WBEM ripped out, if that matters.
    It HAS .NET minimum install to run all major software.
    .NET Optimizer and many other nonessential services are disabled.

    This tiny WinAPI executor that you’ve built seems like it would
    be very useful for tiny tasks that Windows can perform much
    easier than .BAT

    Although the current build fails your timely response is VERY
    appreciated. Don’t misunderstand nor underestimate!

  29. DTM says:

    Nothing about WinAPIexec in the event logs.

    I’m beginning to suspect it has to do calls into MUI and/or NLS since I’ve ripped those out of this WinXP also.

    Likely the issue is beyond your control. I use English only.

    On another thought:
    It’s my understanding that RESHACKER does not recompile
    unicode strings within edited EXE & DLL properly. I could be wrong.

    My SHELL32.DLL is heavily edited, thus, any calls into SHELL32.DLL
    unicode strings may cause WinAPIexec.exe to fail?


    Your efforts on behalf of my OS are greatly appreciated.
    I fully expect WinAPIexec runs flawlessly on a stock installation
    (or mildly customized WinXP SP3++).

    • RaMMicHaeL says:

      I can’t see a reason for winapiexec not to work if e.g. reshacker, which is much more complex, works.

      If you’d like to investigate further, download and run OllyDbg, open winapiexec with it, run it, and make a screenshot of what you see. If you’re not willing to be bothered, then never mind :)

  30. DTM says:

    I neglected to mention:
    SHA : 46e4d50b8812457ae27ca1aad178d59e6f7efcd4

    DOES execute the simple statements as your example above:
    :: winapiexec.exe u@ShowWindow ( u@FindWindowW Shell_TrayWnd 0 ) 0 , Sleep 500 , u@ShowWindow $$:3 5

    It hides the SysTray. It breaks somewhere thereafter.

    Compound statements in your examples always break.

    Nothing in event logs.

    In any event, the ZIP that you posted is only missing the README.
    I might suggest adding your site & contact info into the README.

  31. DTM says:

    Using OllyDBG 1.10
    SHA : b08e0b5f1a3633bd6d0a6a71b54c13477cd3c991

    SHA : 46e4d50b8812457ae27ca1aad178d59e6f7efcd4

    CMD Line args:

    GetTempPathW 260 $b:520 , u@MessageBoxW 0 $$:3 $$:0 0x40

    Breaks with:

    UNICODE “Stack error on argument number %d”

    Any unicode breakage would be no surprise to me
    (As I’ve noted aboove). I could be wrong again.
    I haven’t DBG for at least 20 years
    (LONG before Win32 existed).

  32. DTM says:

    That fixed the WinXP issue.

    SHA : c1cd5777883451b702bd71fe93d2de28c6918f27

    Runs all the examples above flawlessly.

    NOW, it’s time to kick ass and chew bubblegum.

    And I’m all outta gum… =)

    Thanks for behaving like a human in this world overrun by aliens (and their iPhones). It’s very refreshing. My wife says Thanks & Hi!

  33. Matt says:

    Im new to programming and using api’s, I have found a function in shell32.dll using dll export viewer called SHChangeNotify however when i try to reference it using winapiexec64.exe shell32.dll@SHChangeNotify, H8000000, H0, 0, 0 it states that it could not find procedure SHChangeNotify in module shell32.dll



    • RaMMicHaeL says:

      winapiexec tries to find an export with the name “SHChangeNotify,” (note the comma). You need to use spaces – see the examples above.
      Also, H8000000 is parsed as a string. See documentation. For hexadecimal numbers, you can use 0x8000000.

  34. Mexxxi says:

    I’m trying to detach a VHD with winapiexec, but no luck so far:

    winapiexec64.exe virtdisk.dll@DetachVirtualDisk (k@CreateFileW “\.\PhysicalDrive3” GENERIC_READ NULL OPEN_EXISTING FILE_ATTRIBUTE_NORMAL NULL) DETACH_VIRTUAL_DISK_FLAG_NONE 0

    What am I doing wrong?



    • RaMMicHaeL says:

      I’m not familiar with the API, but syntax-wise, you need to put a space between the parentheses and the other arguments. Also, winapiexec doesn’t recognize constants such as FILE_ATTRIBUTE_NORMAL or even NULL (what did you expect from a 4 KB tool?). They are being interpreted as strings. Use numbers instead, such as 0 instead of NULL.

      • Mexxxi says:

        Thank you for your quick reply and your heads up. That got me off the ground :)

        I almost have it working, just a small problem: I’m trying to chain two API-calls. The first one is needed to get a handle which I need for the second API. I created a buffer with $b:4 in API1 and referenced it with $$: in API, yet it seems that not the value of the handle is being passed, but the pointer address instead. Is there any way to pass the handle? The syntax looks like this:

        function1 (param1, param2, param3, _out_handle)
        function2 (_in_handle)

        winapiexec.exe library.dll@function1 param1 param2 param3 $b:4 , library.dll@function2 §§:5

        Btw, I love the ultra-tiny size of this tool. In this day and age where even mere file headers can exceed winapiexec’s size, I’m stunned to see such a small, yet functional tool in action :)

  35. NikolaS says:

    Hi, can winapiexec be used to disable registry redirection and reflection for a registry key on 64 bit Windows so that 32 bit command line tool (like subinacl or any other) can access redirected keys? Could you show me some example for that?

  36. h-h says:


    thanks for this great tool!

    What do you think about something like this: !$a:1,2,3

    “!” means dereferencing. The idea is to pass data structures by value.

    • RaMMicHaeL says:


      I don’t see much use for it, especially since data structures are not directly supported by winapiexec, only word-sized arrays.
      For the rare cases where WinAPI functions receive data structures by value (e.g. PtInRect), the structure is usually small, and the call is equivalent to passing every field of the structure as a parameter.
      With the case of PtInRect, one can use the following signature:
      BOOL PtInRect(const RECT *lprc, LONG pt_x, LONG pt_y);

      • h-h says:

        the call is equivalent to passing every field of the structure as a parameter.

        Yeah, you’re right. So then that’s the way it should be used.

  37. h-h says:

    Am I right that stdcall is the only calling convention winapiexec supports? If yes, do you plan on supporting cdecl and possibly other calling conventions too?

    • RaMMicHaeL says:

      Both stdcall and cdecl are supported. You can notice that one of the call examples use wsprintfW, which is cdecl. Both work as the stack is being restored manually.
      Other calling conventions, such as fastcall, are not supported. I don’t plan to add support for other calling conventions, as winapiexec is mostly targeted at WinAPIs, and I don’t think that anything other than stdcall and cdecl is used.

  38. h-h says:

    Are you able to access the standard input stream? Otherwise: Would you please enable this? This way, you could pipe the output of a command to winapiexec which then displays it in a message box. I think you should be able to access the data as ANSI and Unicode.

    • RaMMicHaeL says:

      It’s certainly possible to access the output stream, as demonstrated here.
      I believe that something similar can be done with the input stream, but I’m not familiar enough with the console API to implement what you’re asking for.

      Here’s my 5-minutes attempt, and it kind of captures the input, but doesn’t work with piping:
      winapiexec.exe AttachConsole -1 , ReadConsoleW ( GetStdHandle -10 ) $b:2048 1024 $b:4 0 , u@MessageBoxW 0 $$:9 test 0

      Run the command, then input some strings. That’s what you’ll see:

      I’m not sure why test1 isn’t being captured, and test2 is. Go play with it, and let me know if you find a solution :)

Leave a Reply