More convenient and dynamic call of DLL export functions

Source: Internet
Author: User

Original link: http://www.titilima.cn /? Action = show & id = 275

In general, the method for dynamically calling the DLL export function is:

  1. Use typedef to define the function pointer type for the target function.
  2. Use getprocaddress to obtain the function pointer.
  3. Use the function pointer for calling.

However, if you want to call too many functions, this method will inevitably be cumbersome-there are too many typedef, too many getprocaddress and too many function pointers. In this article, we will provide a general solution to make these dynamic calls easier.

Let's take a look at the Declaration of this function:

  1. Bool _ cdecl dllcall (
  2. Pctstr lpszdll, // name of the DLL where the target function is located
  3. Pcstr lpszfunc, // target function name
  4. Int argc, // number of parameters to be called
  5. Pvoid Pret, // return value of function call
  6. ...
  7. );

Take messageboxa as an example. The usage is as follows:

  1. Int ret;
  2. Dllcall (_ T ("user32.dll"), "messageboxa", 4, & ret,
  3. Null, "Hello, world! "," Hello ", mb_iconinformation | mb_yesno );

Replace messageboxindirecta with the following parameter:

  1. Msgboxparamsa Param;
  2. Zeromemory (memory M, sizeof (msgboxparamsa ));
  3. Param. cbsize = sizeof (msgboxparamsa );
  4. Param. dwlanguageid = getsystemdefaultlangid ();
  5. Param. dwstyle = mb_iconinformation;
  6. Param. lpszcaption = "hello ";
  7. Param. lpsztext = "Hello, world ";
  8. Int ret;
  9. Dllcall (_ T ("user32.dll"), "messageboxindirecta", 1, & ret, ¶ M );

The implementation principle is to dynamically generate assembly code, which is similar to the following:

  1. _ Declspec (naked) DWORD _ cdecl dllcallproc (void)
  2. {
  3. _ ASM
  4. {
  5. Push argn
  6. ...
  7. Push arg2
  8. Push arg1
  9. Call proc
  10. RET
  11. };
  12. }

The code for dllcall is listed below, which is similar to the implementation of all variable parameter functions (such as sprintf.

  1. Bool _ cdecl dllcall (
  2. Pctstr lpszdll,
  3. Pcstr lpszfunc,
  4. Int argc,
  5. Pvoid Pret,
  6. ...)
  7. {
  8. Va_list Arglist;
  9. Int ret;
  10. Va_start (Arglist, Pret );
  11. Ret = vdllcall (lpszdll, lpszfunc, argc, Pret, Arglist );
  12. Va_end (Arglist );
  13. Return ret;
  14. }

The most critical is the vdllcall code, as shown below:

  1. # Pragma pack (push, 1)
  2. Typedef struct {
  3. Byte op;
  4. Dword_ptr dwvalue;
  5. } Opcode, * popcode;
  6. # Pragma pack (POP)
  7. Typedef DWORD (_ cdecl * dllcall) (void );
  8. Bool _ cdecl vdllcall (
  9. Pctstr lpszdll,
  10. Pcstr lpszfunc,
  11. Int argc,
  12. Pvoid Pret,
  13. Va_list Arglist)
  14. {
  15. Hmodule hdll = loadlibrary (lpszdll );
  16. If (null = hdll)
  17. Return false;
  18. Farproc proc = getprocaddress (hdll, lpszfunc );
  19. If (null = proc)
  20. Return false;
  21. Handle hheap = getprocessheap ();
  22. Popcode P = (popcode) heapalloc (hheap, 0, sizeof (opcode) * (argc + 2 ));
  23. Int I;
  24. For (I = argc-1; I> = 0; -- I)
  25. {
  26. // Push Arg [I]
  27. P [I]. Op = 0x68;
  28. P [I]. dwvalue = va_arg (Arglist, dword_ptr );
  29. }
  30. // Call proc
  31. P [argc]. Op = 0xe8;
  32. P [argc]. dwvalue = (int_ptr) proc-(int_ptr) & P [argc + 1];
  33. // RET
  34. P [argc + 1]. Op = 0xc3;
  35. P [argc + 1]. dwvalue = 0x90909090; // NOP
  36. Dllcall PFN = (dllcall) P;
  37. DWORD ret = PFN ();
  38. Heapfree (hheap, 0, P );
  39. Freelibrary (hdll );
  40. If (null! = Pret)
  41. * (Pdword) Pret = ret;
  42. Return true;
  43. }

The pointer P is the call code generated dynamically, and is finally converted to the dllcall type function pointer for calling.

Finally, four points need to be added:

  1. Dllcall is only applicable to _ stdcall calling the agreed target function.
  2. This vdllcall code is only applicable to x86 CPUs. If it is used in the wince environment (such as arm or mips cpu), you need to rewrite the dynamic calling assembly code as appropriate.
  3. The argc parameter refers to the number of actual pressure stack parameters, rather than the number of parameters called by C language. For example, if the API function windowfrompoint has only one parameter in the function declaration, the stack is actually pressed by point: X and point: Y respectively. In this case, set argc to 2.
  4. The returned value of dllcall only obtains eax. If some functions return a large structure larger than 4 bytes, the returned value is not what you want.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.