C# dll export function with parameters [duplicate] - c#

How exactly does RunDll32 call a function, without knowing the number/types of arguments that the function can take?
Does it have a built-in compiler or something of the sort?

RunDll32 is pretty much a thin wrapper that calls LoadLibrary to load the given DLL, calls GetProcAddress to get the function address of the desired function, and then calls the function.
It can't call just any exported function in the DLL, though—it assumes that the function has a very specific function signature of the following:
void CALLBACK
EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
where CALLBACK is a macro that expands to the __stdcall calling convention. See this knowledge base article for a more detailed description.
If your DLL's function does not have the correct signature or calling convention, lots of badness will ensue. See What can go wrong when you mismatch the calling convention? for lots of gory details. Fortunately (or perhaps unfortunately), RunDll32 is written in such a way to ameliorate those types of errors, but that still doesn't mean it's a good idea. Do not use RunDll32 to call functions that do not have the correct signature. It's just a ticking time bomb waiting to go off in the next version of Windows.

It can't call just any function, it can only call function specifically written to be called. Hence, there is no magic.

Related

Differences in methods to call unmanaged C++ dll from C#

I am calling some unmanaged C functions (in an external dll) from C#. I have 2 different methods to do so, and I am not sure of the differences between the 2 (other than the amount of code)
Method #1
[DllImport("PComm32.dll",CallingConvention=CallingConvention.StdCall, EntryPoint ="PmacSelect")]
public static extern int PmacSelect(IntPtr intPtr);
int device = PmacSelect(IntPrt.Zero);
Method #2
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int PmacSelect(IntPrt intptr);
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
public PmacSelect PmacSelectFunction;
private IntPtr pDll = LoadLibrary("PComm32");
IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "PmacSelect"); //find the function in the loaded pcomm32 dll
PmacSelectFunction = (PmacSelect)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,type(PmacSelect));
int device = PmacSelectFunction(IntPrt.Zero);
Both methods work, and call the PmacSelect Function located in the PComm32.dll file.
My question is what are the functional differences between the 2 methods?
Method #1 must rely on windows managing the DLL in the background for me as needed? Could windows load and unload the dll without my knowledge? I dont really care if it does, as long as it automatically loads is when I call a function in the dll.
Method #2 The DLL is loaded explicitly when I call LoadLibrary. Does the library remain in memory until I free it?
I'll give you answers, but you seem to already understand what is going on.
My question is what are the functional differences between the 2 methods?
There is no functional difference between the two methods. In the first method (which you should use if at all possible), the DotNet framework is handling everything for you. Under the hood, it is doing exactly what you're doing manually: Calling LoadLibrary, GetProcAddress, and at some point, FreeLibrary. Those are the steps to calling a function in a DLL.
Method #1 must rely on windows managing the DLL in the background for me as needed? Could windows load and unload the dll without my knowledge?
Yes, that's exactly right, although I wouldn't say it is without your knowledge. You are telling it to do that when you write [DllImport("PComm32.dll"...)].
Method #2 The DLL is loaded explicitly when I call LoadLibrary. Does the library remain in memory until I free it?
Again, yes, you understand what is happening.
Since you seem to answered your own questions and I've merely confirmed your answers, let you give you the reasons why you should (almost) always use #1:
It works just as well
It is easier to use and easier to read / maintain
There is no value in doing it the hard way (#2)
I can only think of one reason that you would ever want to bother with the second method: If you needed to be able to replace the DLL, on the fly, with a newer version or something, without quitting your application, then you would want the fine grain control over when the DLL is unloaded (so that the file can be replaced).
That is unlikely to be a requirement except in very special cases.
Bottom Line: If you're using C#, you accept the fact that you are giving control to the framework in exchange for being able to focus on the work, and not worry about things like DLL or memory management. The DotNet framework is your friend, let it do the heavy lifting for you, and focus your efforts on the rest of the code.
When you pinvoke with DllImport, LoadLibrary ends up getting called for you, and the exported function is (hopefully) found in the EAT. Basically in your second example you're doing the same thing as a typedef + GetModuleHandle & GetProcAddress for c/c++.
The only reason I could think to use your second method, would be if the DllMain of your unmanaged module executes code upon attachment to a process, which you might depending on the scenario want to have specific timing control over when that module gets loaded into your process.

Implicit Linking and FreeLibrary in C#

I just found out I could unload DLL which is implicit linking with the function FreeLibrary() in C#. I remember I couldn't do this in C++, but it works well in my simple test project. I wonder if this would be okay in my real projects too. Is it safe to use this method?
Fairly vague, I'll have to assume you talk about DLLs that got loaded through pinvoke. Yes, there is no protection against calling FreeLibrary() twice. Works in C++ as well btw for a DLL that's loaded explicitly. Not for implicitly loaded DLLs, they get a reference count of "infinity".
The pinvoke marshaller uses LoadLibrary() under the hood, happens when the very first [DllImport] function gets executed. The OS loader simply keeps a reference count, every LoadLibrary() call increments it and FreeLibrary() decrements. When it reaches 0 then it gets unloaded. So if you pinvoke LoadLibrary() yourself and call FreeLibrary() twice then the DLL does get unloaded. The virtual address space formerly used by the memory-mapped file that maps the code in the DLL is released and can be used again by subsequent allocations.
Safe, no, that's not a word that jumps to mind. When you accidentally call an entrypoint in the DLL then your program is going to behave very poorly. The pinvoke marshaller cannot do anything about it, the stub for the native method was already generated. Odds for an AccessViolationException are decent but not guaranteed. Arbitrary code execution is technically possible.
The only truly safe way to do this is to ensure that the AppDomain that contains the pinvoke code is unloaded. You get no help with this, just a rule you have to implement yourself.

Performance benefit for storing platform invoke in delegate?

OpenTK does bindings to OpenGL by first defining a delegate with a matching signature to some target C function:
[System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void Uniform1f(Int32 location, Single v0);
internal static Uniform1f glUniform1f;
And then it assigns a value to glUniform1f that is returned from a platform specific OpenGL GetProcAddress function.
If I don't use OpenTK's approach, and instead just pinvoke the function using DllImport, will my code perform slower? (in otherwords, is there any performance benefit for using a delegate).
No, if anything, there will be a performance hit (although incredibly insignificant in most cases) because you are using a delegate.
Remember, a delegate is a reference to a method. Every time it's called, that reference has to be derefrenced. Compare this to a method call that's compiled into your code; the runtime knows exactly where it has to go as the method reference is baked into the IL.
Note that delegate performance has improved significantly since .NET 3.0. With the introduction of LINQ, delegates were going to be used extremely heavily, and with them being that ubiquitous, they have to be fast.
A possible reason you are seeing delegates being used is because the DLL that contains the unmanaged code needs to be determined at runtime (perhaps because of naming issues, processor-specific builds distributed together under different names, etc.).
In this case, an call is made to the unmanaged LoadLibrary Windows API function, followed by a call to the unmanaged GetProcAddress Windows API function.
Once the function poitner has been retreived, it is passed to the GetDelegateForFunctionPointer method on the Marshal class in order to get the delegate.

Performance of Calling Unmanaged .dll from C#

How long is the typical overhead added by calling a .dll written in C++ from a C# application using the following syntax?
[DllImport("abc.dll", EntryPoint = "xcFoo", CallingConvention = CallingConvention.Cdecl)]
public extern static Result Foo(out IntPtr session,
[MarshalAs(UnmanagedType.FunctionPtr)]ObjectCallback callback,
UInt64 turnKey,
string serverAddress,
string userId,
string password);
Is there a more efficient way to do it?
Check out this article on how to improve interop performance. What to do and what best to avoid.
http://msdn.microsoft.com/en-us/library/ms998551.aspx
Are you talking about the overhead of invoking the native method? If so, I dont think it is significant at all, as there are a lot of such calls in the .NET framework class libraries.
Now, whether the overhead is significant for your scenario can only be answered by doing performance measurements, and comparing them against what you expect.
The marshalling into the native method will cost three memory allocations from the NT heap, which is not so bad. It's the delegate back that gets worrysome.
A good method to check this sort of thing is throw in a break point where you make calls. Don't know when the library is loaded, so maybe only check the break point on the second call (unless loading cost is your main concern). Then open up the disassembly window in visual studio and see how many lines there are before your dll function is being invoked.
i know this question is old but ive managed to call native functions blazingly fast with not only using calli CIL instruction but also with special trick, but ofc you need to handle pinnig and/or marshalling arguments yourself if you deal with complex types including strings..

What does GetModuleHandle() do in this code?

Edited........
sorry Sir I was referring this piece of code from Stephen Toub's article..
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
Can some one explain this to me in short...??
In short this code initializes a key logger. The passed in parmeter, proc, is a callback function that will be called on every key press.
The using statement just ensures immediate calls to dispose() on the declared variables (curProcess and curModule) when they leave scope, thus properly releasing resources in a expedient manner rather than waiting for the garbage collector to release them which may take a while.
SetWindowsHookEx is a win32 api call that allows you to register a callback to be called when a specific OS level event occurs. In this case the first parameter, WH_KEYBOARD_LL, specifies that you would like to register for low level keyboard events. The second parameter is the callback (a Delegate in .Net) that will be called. The third parameter is a windows handle (a pointer managed by the OS) to the module where the callback is located, in this case the main .exe for the process. Note that a process has multiple modules (exe's or dll's) loaded at any given time. The last parameter is the thread id that you would like to monitor; because 0 is passed in, the callback will be called for any key events for any window opened on the OS.
More info here about SetWindowsHookEx
GetModuleHandle() is a Windows API which in simple word returns you the handle of the loaded DLL or EXE.
You can see the detailed description of this API at this link
Straight From MSDN:
The GetModuleHandle function returns a handle to a mapped module without incrementing its reference count. Therefore, use care when passing the handle to the FreeLibrary function, because doing so can cause a DLL module to be unmapped prematurely.
This function must be used carefully in a multithreaded application. There is no guarantee that the module handle remains valid between the time this function returns the handle and the time it is used. For example, a thread retrieves a module handle, but before it uses the handle, a second thread frees the module. If the system loads another module, it could reuse the module handle that was recently freed. Therefore, first thread would have a handle to a module different than the one intended.
First as a general point for questions on Windows library functions, you should consider searching MSDN. Here is the MSDN page for GetModuleHandle(), it contains much of the relevant information.
To your question (and anyone more familiar with the Windows API feel free to correct me), a "module" is a sort of catch-all term for a program in Windows, usually specifically referring to either an executable(.exe) or a library(.dll). A "handle" is a term referring to a pointer. GetModuleHandle() returns a pointer (handle) to the specific program (module). As Pavel commented, both are very broad terms.
As for the code snippet you posted:
It's getting the current running process, as well as the current module (obvious.)
It is then calling SetWindowsHookEx (refer to the MSDN for more information) which takes in the event to hook (In this case, low level Keyboard events.), a procedure to call (proc) when the hooked event happens, and a pointer to the current program.
Refer to Hooks on the MSDN for more information on hooking.
Essentially the message of this post is make more use of the MSDN, it's a pretty solid piece of documentation :)

Categories

Resources