How to create a DLL callable from batch using rundll32.exe - winapi

With rundll32 it is possible to call simple APIs into DLLs.
Two questions:
for this usage, should be the entry point use the __cdecl calling convention, or some other calling convention?
is it possible to pass only numeric args or also strings?

Don't use rundll32.exe. I can't word it any better than Raymond Chen did: What’s the guidance on when to use rundll32? Easy: Don’t use it.
If you read through the blog entry, and are still convinced, that this is the solution you need, here is the deal: The entry point must follow the __stdcall calling convention:
void CALLBACK
EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow);
The trailing W is important, so that the lpszCmdLine argument is passed as Unicode (UTF-16LE). EntryPoint is a placeholder, it can be any legal symbol.
As an example, you can export a symbol called MyFunctionW, and pass an arbitrary command line using:
rundll32.exe MyDll.dll,MyFunction 132 C:\WINDOWS\INF\SHELL.INF
But really, you should evaluate other options (e.g. PowerShell). Convenience doesn't come for free.

The entry point must use the __stdcall calling convention:
void CALLBACK
EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
This is covered in the following documentation:
NFO: Windows Rundll and Rundll32 Interface

Related

Getting VS Code's C++ intellisense to deal with WinAPI types

So, I'm using WinAPI in a C++ project with VS Code. Something I've noticed is that the standard C++ intellisense doesn't play so nicely with WinAPI's many macros.
For example,
#include <windows.h>
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(0, "This is a test", "Test", MB_OK|MB_ICONINFORMATION);
return 0;
}
In the above code, error squiggles appear under "This is a test" and "Test" because VS Code's intellisense is expecting those parameters to be of type LPCWSTR and is instead interpreting them as being const char *.
This shouldn't be the case, as "This is a test" and "Test" are valid as LPCWSTRs and the program compiles and runs perfectly fine.
Is there anyway I can get the intellisense engine to recognize that this is not an error? Or will I have to disable error squiggles entirely?
Sorry, VS is working correctly in this case.
"This is a test" is a char const * (LPCSTR), not a LPCWSTR. For a wide character string literal add the 'L' prefix: L"This is a test".
Try wrapping your string with macro _T(string) from <tchar.h>. Compiles fine and intellisense doesn't panic.

comparing the edit control value with string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i have 2 edit control in dialog box. And onclick of Ok Button i want to compare this value with string.
case IDC_BUTTON1:
UINT WINAPI GetDlgItemText(
_In_ HWND hDlg,
_In_ int nIDDlgItem,
_Out_ LPTSTR lpString,
_In_ int nMaxCount
);
TCHAR szBuf[BUFF_LEN];
TCHAR szBuf1[BUFF_LEN];
GetDlgItemText(hDlg, IDC_EDIT1, szBuf, BUFF_LEN - 1);
GetDlgItemText(hDlg,IDC_EDIT2,szBuf1,BUFF_LEN-1);
now after that if condition check the value szBuf and szBuf1 but it say can not convert cont char to tchar how to convert this value.
The important details are leaking out in comments. That's too bad – the details should appear in the question. In particular you should at least have shown the line of code that performed the comparison and that led to the compiler error. And the compiler error should always be transcribed verbatim.
That said, it looks as though you are using either wcscmp or _tcscmp to perform the comparison. But you are passing szBuf which is a wide string for one argument, and a literal like "hello" for the other. The problem with that is that szBuf is a wide string and the literal is 8 bit, a const char*.
I hypothesise that you have written code this this:
int cmp = _tcscmp(szBuf, "Hello");
And the compiler objects because you have defined the UNICODE conditional and so _tcscmp expects both parameters to be of type const wchar_t*. The literal is not, it is const char*.
So the simple solution is to use a wide literal:
int cmp = _tcscmp(szBuf, _T("Hello"));
That said, I would not recommend using TCHAR in this day and age. I think it unlikely that you are still targeting Windows 98. Stick to the Windows native Unicode API and use wide strings. Declare your buffers like this:
wchar_t szBuf[BUFF_LEN];
And compare like this:
int cmp = wcscmp(szBuf, L"Hello");
Done that way it's much easier to understand what you are working with. Using TCHAR if you always compile with UNICODE defined is a pointless exercise that just results in obfuscated code.
Even better still though would be to avoid C strings as much as possible and use native C++ strings. For example std::wstring would be the obvious choice here. Clearly you need to use the C strings for the low-level Windows API calls, but as soon as they return you a value, transfer that to a C++ string and life will be so much simpler.

G++ error: ‘<anonymous>’ has incomplete type

I am forced to use a third party dongle access library that provides an include file 'sense4.h' with code as follows:
#if !defined _WINDOWS_
#define WINAPI
#define CONST const
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned int UINT;
typedef unsigned long ULONG;
typedef char CHAR;
typedef char TCHAR;
typedef void VOID;
...
#endif /* !defined _WINDOWS */
...
unsigned long WINAPI S4Startup(
VOID
);
unsigned long WINAPI S4Cleanup(
VOID
);
...
The problem is that g++ 4.6.1 complains about lines of code where typedefed VOID is used:
sense4.h:375:9: error: ‘<anonymous>’ has incomplete type
sense4.h:376:1: error: invalid use of ‘VOID {aka void}’
sense4.h:383:9: error: ‘<anonymous>’ has incomplete type
sense4.h:384:1: error: invalid use of ‘VOID {aka void}’
Is there anything I can do without changing the 'sense.h' include file to make my project compile with g++?
Update 1
I found out that the section 18 of C++ Standard Core Language Closed Issues, Revision 30 states:
If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
Can a typedef to void be used instead of the type void in the parameter list?
Rationale: The IS is already clear that this is not allowed.
Quick summary: The code is not valid C++, though there's some lack of clarity about whether it should be. Using void rather than VOID, or just using empty parentheses, will avoid the error.
I think this is a bug in g++.
I thought this was a bug in g++. I'm now convinced that it isn't, though I argue that it would be better to make this a warning rather than a fatal error.
Normally in C++, a function with no parameters is declared with empty parentheses:
int foo();
As a concession to C compatibility, C++ also allows a C-style prototype, using void to indicate that the function has no parameters (since empty parentheses mean something else in C):
int bar(void);
g++'s interpretation seems to be that the void in this syntax here doesn't refer to the incomplete type void; rather, it treats it as a special syntax with a distinct use of the keyword.
I think you'll need to modify the header file to get g++ to accept it.
gcc accepts it as valid C, but that's not helpful if you need to #include it from a C++ source file -- unless you write a C wrapper and invoke it from your C++ code, which might be an acceptable workaround.
(Incidentally, I hate typedefs like that. What's the purpose of typedef void VOID;? Did the author think void was too confusing? I suspect it's for compatibility with very old C compilers that didn't support the void keyword, but the need for that is long past.)
Here's the relevant description from the latest draft of the ISO C++ 2011 standard (8.3.5 [dcl.fct]):
The parameter-declaration-clause determines the arguments that can
be specified, and their processing, when the function is called. [ ...
] If the parameter-declaration-clause is empty, the function takes
no arguments. The parameter list (void) is equivalent to the empty
parameter list. Except for this special case, void shall not be a
parameter type (though types derived from void, such as void*,
can).
This implies that the void keyword in int bar(void); does refer to the type void. Since a typedef name is a synonym for the named type, int bar(VOID); should be equally legal. It would make the most sense for a typedef name like VOID to be accepted in place of void, but the wording of the standard actually refers to the keyword void, not to the type.
The whole purpose of permitting (void) is C compatibility. Just to add to the confusion, the 1990 ISO C standard requires the void keyword; the 1999 and 2011 C standards changed the wording, allowing a typedef instead. The response to C++ Defect Report #577 confirms that the current wording requires the void keyword, and proposes a change that will permit a typedef -- but that change is not yet in any ISO C++ standard. It will probably appear in the first Technical Corrigendum for C++ 2011, whenever it's published.
Thanks to another.anon.coward for finding the existing gcc bug report. I've added an overly verbose comment suggesting that the code is valid and the error message should not be produced -- and a later comment conceding that the code is invalid, but that a warning would be more appropriate than a fatal error.
In the meantime, I suggest contacting the provider of this sense4.h header file. If they intended it to #included only from C code, there's no real problem with it (other than the IMHO poor style); otherwise, they might consider using #ifdef __cplusplus, declaring the functions with (void) in C and with () in C++. And you could go ahead and make that change yourself. Whether g++ should accept the code or not, with a few changes it would be valid C, valid C++, acceptable to both gcc and g++, and better style.
If you've read this far and you're still awake, I'm impressed.

Understanding MAKEINTRESOURCEW definition

Looking at the Windows SDK, I found this #define directive for MAKEINTRESOURCEW:
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
Can someone explain to me what the heck that means? For example, what would be the value of MAKEINTRESOURCEW(0)? (1)? (-1)?
The result of this macro will be pointer to long string with value equal to given parameter. You can see it by reading precompiler output (see /P C++ compiler options). All casting is required to compile this macro result, when LP[w]WSTR pointer is required, both in Win32 and x64 configurations.
Some Windows API, like LoadIcon, expect string pointer as their parameter. Possibly, these functions test the pointer value, and if it is less than some maximum, they interpret it as resource index, and not as string (problems of ugly C-style interface). So, this macro allows to pass WORD as string, without changing its value, with appropriate casting.
For the most part, it leaves the value unchanged, but converts it from an int to a pointer so it's acceptable to functions that expect to see a pointer. The intermediate casts widen the input int to the same size as a pointer, while ensuring against it's being sign extended. In case you care, ULONG_PTR is not a "ULONG POINTER" like you might guess -- rather, it's an unsigned long the same size as a pointer. Back before 64-bit programming became a concern, the definition was something like:
#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
Nowadays, they use ULONG_PTR, which is a 32-bit unsigned long for a 32-bit target, and a 64-bit unsigned long for a 64-bit target.
That's a macro that casts an argument i to a word, then casts that result to a pointer to an unsigned long, then again to a long pointer to a wide-character string.
Like other users said - it just casts an integer into a "pointer to a string".
The reason for this is the following: At the ancient times of Windows 3.0 people tried to be minimalistic as much as possible.
It was assumed that resources in the executable can have either string identifier or integer. Hence when you try to access such a resource - you specify one of the above, and the function distinguish what you meant automatically (by checking if the provided "pointer" looks like a valid pointer).
Since the function could not receive a "variable argument type" - they decided to make it receive LPCTSTR (or similar), whereas the actual parameter passed may be integer.
Another example from Windows API: A pointer to the window procedure. Every window has a window procedure (accessed via GetWindowLong with GWL_WNDPROC flag.
However sometimes it's just an integer which specifies what "kind" of a window is that.
Then there's a CallWindowProc which knows to distinguish those cases.

Low level keyboard input from Windows

What win32 calls can be used to detect key press events globally (not just for 1 window, I'd like to get a message EVERY time a key is pressed), from a windows service?
You want to use Win32 Hooks. In particular a keyboard hook.
You can read more about it here
The type of hook you want is WH_KEYBOARD and you can set it via the Win32 API SetWindowsHookEx.
Basically windows will call a function in a dll that you create everytime a key is pressed in any application system wide.
The hook will call your function which will have this interface:
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
);
More information about this callback here.
With windows hooks you can not only track system wide events across all processes, but you can also filter them and stop them altogether.
Take a look at the hooks you can set with SetWindowHookEx:
http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx
However, unless you are running an "interactive" service, you won't have access to the desktop (and you shouldn't be running an interactive service because it won't work right in newer versions of Windows). You will have to look into the session and desktop management APIs in order to access the desktop/console.
Check out the Raw Input API in MSDN:
http://msdn.microsoft.com/en-us/library/ms645536(VS.85).aspx
It allows you to get input from keyboards (among other things) without messing around with global hooks. Global hooks should only be used as a last resort as they may introduce unintended consequences.
The only drawback to using Raw Input is that it may not properly receive keystrokes which are generated by software.
Just use the native function GetKeyState, or GetAsyncKeyState, or GetKeyboardState from user32 DLL.
You can read about each function I mentioned above in the msdn site:
h ttp://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx
for the GetKeyState, and
h ttp://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v=vs.85).aspx
for the GetAsyncKeyState, and
h ttp://msdn.microsoft.com/en-us/library/windows/desktop/ms646299(v=vs.85).aspx
for the GetKeyboardState.
If you program in C# then:
Your code must include the following line out of any class, struct or enum declaration:
using System.Runtime.InteropServices;
Then in the class that has the method where you want to detect the keys, define one of three functions above for your choice, or what works and what not.
[DllImport("user32.dll")]
static uint GetKeyState(byte virtualKeyCode);
//or
[DllImport("user32.dll")]
static uint GetAsyncKeyState(byte virtualKeyCode);
//or
[DllImport("user32.dll")]
static uint GetKeyboardState(byte[] virtualKeyCodes);
//NOTE: The length of the byte array parameter must be always 256 bytes!
If you dislike uint as return type, you can also change it to int.
If the native functions always return 1 as true or 0 as false, then you can change their return type to bool instead, but if you do so, then I think you should add another line of code above the native function definition, which is:
[MarshalAs(UnmanagedType.Bool)]
OR you can add the following line in the middle of the native function definition (below the line where the DllImport word is, and above the line, where the 'extern' word is):
[return: MarshalAs(UnmanagedType.Bool)]
Pinvoke site offers better definition for these functions, so you don't have to use integers to mention a particular key of your keyboard, but more understandable enum.
The following link leads to the definition of the GetKeyState in C#:
h ttp://www.pinvoke.net/default.aspx/user32.getkeystate
The following link leads to the definition of the GetAsyncKeyState in C#
h ttp://www.pinvoke.net/default.aspx/user32.getasynckeystate
The following link leads to the definition of the GetKeyboardState in C#
h ttp://www.pinvoke.net/default.aspx/user32.getkeyboardstate
To detect which key is held down (at any time, anywhere) then call GetKeyState or GetAsyncKeyState function, in the single parameter, mention the key you want to detect and then add: & 0x8000, or & 0x80 after the call.
If the mentioned key is held down, then the return value of the expression is not zero, but otherwise it is zero.
According to the returned integer of the expression, you can determine which key held down or not.
Note that if you put code inside if statement with that expression != 0 as enter condition, which is inside a loop, the code in that if statement will be executed more than once, actually many times, when you held down that key. If you want some code to be executed once When you press a key and then release it, then the following code is a trick that achieves this goal:
while (boolean exression that will return false when you want to quit this loop)
{
if (boolean expression that will return true when particular key is **held down**) //This boolean expression calls either GetKeyState or GetAsyncKeyState with the & 0x8000 or & 0x80 after the call, and then != 0 to check for **held down** key
while (true) //It's purpose is to wait for the same key that was held down to be released. After code execution, it will encounter the break keyword that will finish him, even though that his enter condition is true.
if (boolean expression that will return true when the **same** particular key is **NOT** held down! (NOT held down, means that at that time, that key was released). You can copy the same condition from the first if statement, and just change **!=**, which is next to 0, to **==**, or instead add brackets to the condition '(' and ')', and in left of '(' add '!').
{
//Put here the code that you want to execute once, when paticular key was pressed and then released.
break; //the while (true), which is the only way to get out of it
}
}
If you are implementing this in a .net application i'd recommend GlobalKeyboardHook, Otherwise i'd look at it's source and take what you need since it is implementing the DLLImport functions mentioned above.

Resources