Author Topic: Concept: Runtime DLL Calls  (Read 3941 times)

0 Members and 1 Guest are viewing this topic.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Concept: Runtime DLL Calls
« on: March 26, 2021, 08:45:28 am »
Recently I pushed a bug fix to GitHub that would allow us to have Windows applications in Vista and higher be DPI aware. I accomplished this using LoadLibrary, a function in the WinAPI that allows for linking a library at runtime rather than at compilation. You then use GetProcAddress to find the address of the function that you are wanting to use from the DLL. You can call the function from that DLL at runtime by calling that address. This allowed me to not have to link the user32.dll library in the _NEWIMAGE function but instead just call it at runtime by finding the DLL and the function. So, since that worked so well, I've made some code here that I think could inspire others who are interested in DLL usage in the Windows environment to try some new things:

Code: C++: [Select]
  1. //this code would be saved as runtimecall.h
  2. long runtimeCall(LPCSTR dllName, LPCSTR processName){
  3.     FARPROC runtime;
  4.     HMODULE dllLoad = LoadLibrary(TEXT(dllName));
  5.     if(dllLoad != NULL){
  6.             runtime = GetProcAddress(dllLoad, processName);
  7.             if(NULL != runtime){
  8.                 return (runtime) ();
  9.                 FreeLibrary(dllLoad);
  10.             }
  11.             else{
  12.                 return -807;
  13.                 FreeLibrary(dllLoad);
  14.             }
  15.     }
  16.     else{
  17.         return -808;
  18.     }
  19. }

And an example of the code's usage:
Code: QB64: [Select]
  1.  
  2. Declare CustomType Library "runtimecall"
  3.     Function runtimeCall& (dllName As String, processName As String)
  4.  
  5.     Sub SetLastError (ByVal dwErrCode As Long)
  6.  
  7. Call SetLastError(85)
  8. Print runtimeCall("kernel32.dll", "GetLastError")

 
Screenshot 2021-03-26 084516.png


Obviously, if you want to pass parameters to the functions then you would need to change the function in the header and in the BAS code but this is just a concept showing a familiar WinAPI function being called using runtime linking rather than linking during compilation.
« Last Edit: March 26, 2021, 09:08:32 am by SpriggsySpriggs »
Shuwatch!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Concept: Runtime DLL Calls
« Reply #1 on: March 26, 2021, 11:43:59 am »
So it looks like this snippet creates a dll in the local folder, and once created any further iterations of the routine spot it and exit. So to modify the dll you'd have to remove it, right?

This is promising. I like everything about this post except the tag line: "If you're API and you know it clap your hands." The cadence is off by one-syllable. The "you" needs to be removed. Other than that, great coding!

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Concept: Runtime DLL Calls
« Reply #2 on: March 26, 2021, 12:08:59 pm »
@Pete This doesn't create a DLL. It simply finds the DLL and then calls the function from that DLL. As for my tagline, you're supposed to pronounce "API" as "appy" (in this case).
« Last Edit: March 26, 2021, 12:11:06 pm by SpriggsySpriggs »
Shuwatch!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Concept: Runtime DLL Calls
« Reply #3 on: March 26, 2021, 12:53:34 pm »
LOL@API sounds like happy. That one went over my head like a roof on a short bus. Steve(tm)

So something like finding and calling the function in GDI32.DLL for printing a photo, instead of having to call the entire library? Oh, better still, what if I wanted to check the print page number box in the WordPad page setup dialog box, without calling up the dialog box; possible with this approach?

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Concept: Runtime DLL Calls
« Reply #4 on: March 26, 2021, 12:59:22 pm »
@Pete I'm not quite sure. It would have to be tailored for each case. In my case, I didn't need any parameters. But yes, you can call a function in GDI32. You'd just need to know the parameters and edit the header and bas accordingly. I'd be happy to assist you when you get to a certain point.
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Concept: Runtime DLL Calls
« Reply #5 on: March 26, 2021, 04:51:15 pm »
A new version that has taken as much C++ code and moved it to QB64, leaving behind only what can't be done directly in QB64:

Code: C++: [Select]
  1. //this would be saved as altruntimecall.h
  2. long __runtimeCall(FARPROC funccall){
  3.     return (funccall) ();
  4. }

Code: QB64: [Select]
  1.  
  2.     Sub SetLastError (ByVal dwErrCode As Long)
  3.  
  4. Call SetLastError(85)
  5.  
  6. Print runtimeCall("kernel32", "GetLastError")
  7.  
  8. Function runtimeCall& (dllName As String, processName As String)
  9.         Function LoadLibrary%& (lpLibFileName As String)
  10.         Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
  11.         Function FreeLibrary%% (ByVal hLibModule As _Offset)
  12.     End Declare
  13.     Declare CustomType Library "altruntimecall"
  14.         Function dllCall& Alias "__runtimeCall" (ByVal funccall As _Offset)
  15.     End Declare
  16.     Dim As _Offset runtime 'FARPROC
  17.     Dim As _Offset dllLoad: dllLoad = LoadLibrary(dllName)
  18.     Dim As _Byte freelib
  19.     If dllLoad <> 0 Then
  20.         runtime = GetProcAddress(dllLoad, processName)
  21.         If 0 <> runtime Then
  22.             runtimeCall = dllCall(runtime)
  23.             freelib = FreeLibrary(dllLoad)
  24.             Exit Function
  25.         Else
  26.             runtimeCall = -807
  27.             freelib = FreeLibrary(dllLoad)
  28.             Exit Function
  29.         End If
  30.     Else
  31.         runtimeCall = -808
  32.         freelib = FreeLibrary(dllLoad)
  33.         Exit Function
  34.     End If
Shuwatch!