Dynamische DLL-Aufrufe
-
Hey, ja danke. Ich habe was im Netz gefunden, unter http://www.codeguru.com/dll/CallDll.shtml, da dachte ich auch eine Lösung gefunden zu haben, aber beide Beispiele funktionieren nicht so wenn man sie einfach kopiert. Das erste Beispiel habe ich zum folgenden abgewandelt, das wird auch richtig kompiliert, nur beim Funktionsaufruf stürzt es ab. Mein Beispiel (ich verwende Borland C++ Builder 4):
#include <windows.h> #include <string.h> #include <fstream.h> #pragma hdrstop #include <condefs.h> #include <commctrl.h> typedef struct { DWORD dwARG[10]; } STACK; typedef VOID (*PFDLL) (STACK); #pragma argsused int main(int argc, char* argv[]) { printf("Loading the DLL...\n"); HINSTANCE hDll = LoadLibrary("xxx.dll"); if(hDll == NULL) { printf("Das scheissding ist NULL!!\n"); } printf("Loading the Procedure...\n"); PFDLL pfFunc = (PFDLL) GetProcAddress(hDll, "DllFunction1"); printf("Okay. Initializing the parameters NOW..."); STACK args; DWORD dwRet; char szBuf[] = "hello world jajaja"; args.dwARG[0] = 12; args.dwARG[1] = 4; args.dwARG[2] = (DWORD) szBuf; args.dwARG[3] = NULL; printf("Done\n"); printf("Executing..."); (pfFunc) (args); printf("Done\n\n"); return 0; }
auch anstatt STACK einfach ein DWORD-array zu nehmen brachte nichts. Das zweite Beispiel kompiliert er gar nicht
Die XXX.DLL die ich Aufrufe sieht so aus:
#include <vcl.h> #include <windows.h> #include <string.h> #include <fstream.h> #pragma hdrstop #include <condefs.h> #include <commctrl.h> #define DLLEXPORT __declspec(dllexport) #pragma hdrstop int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) { return 1; } BOOL WINAPI LibMain(HINSTANCE hDllInst, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; } DLLEXPORT void DllFunction1(int a, int b, LPSTR message) { char x[255]; sprintf(x, "%d + %d = %d", a, b, a + b); MessageBox(NULL, message, x, MB_SETFOREGROUND); }
ich weis der DLL-code ist schrott (hab ich mit C++Builder-Code und einem Forenbeispiel gemixt ;)), ich habe auch noch nie eine eigene DLL geschrieben, und brauche sie eigentlich auch nur zum testen. Ich versuche, die Funktion "DllFunction1" aufzurufen, mit zwei int und einem char* als Parameter.
Könnt ihr mir helfen???
danke & gruss,
~cp code_pilot
-
Ach krass, ich habe ein Programm das läuft geproggt! Ich glaube meine DLL war wohl falsch programmiert, denn nach diesem Forenbeitrag http://www.c-plusplus.net/forum/viewtopic.php?t=45777 ging es auch bei meinem
Könnt ihr das mal ggf. auch mit anderen DLLs testen (und den entsprechenden Parametern)??? Mein funktionierender Code:
#include <windows.h> #include <string.h> #include <fstream.h> #pragma hdrstop #include <condefs.h> #include <commctrl.h> typedef struct { DWORD dwARG[10]; } STACK; typedef DWORD (*PFDLL) (STACK); typedef VOID (*TEST) (int, int, char*); //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { printf("Loading the DLL...\n"); HINSTANCE hDll = LoadLibrary("C:\\WINNT\\SYSTEM32\\USER32.dll"); if(hDll == NULL) { printf("Das scheissding ist NULL!!\n"); } printf("Loading the Procedure...\n"); PFDLL pfFunc = (PFDLL) GetProcAddress(hDll, "MessageBoxA"); printf("Okay. Initializing the parameters NOW..."); STACK args; DWORD dwRet; char szBuf1[] = "hello world jajaja"; char szBuf2[] = "das ist ein test"; args.dwARG[0] = 0; args.dwARG[1] = (DWORD) szBuf1; args.dwARG[2] = (DWORD) szBuf2; args.dwARG[3] = 16; printf("Done\n"); printf("Executing..."); (pfFunc) (args); printf("Done\n\n"); return 0; }
wäre cool wenn ihr das mal mit anderen DLLs stesten würdet (z.B. selbstgeschriebenen) und mir dann berichtet, ob es funktioniert hat.
grüsse
~cp code_pilot
-
ok
-
Hmmm, aber was ist nun wenn ich eine Funktion aufrufe, die einen Zeiger als Parameter benötigt?? Also z.B. GetUserNameA aus advapi32.dll? Da stürzt mein Programm jetzt immer ab
... wisst ihr wie man das umgehen kann? denn das array ist doch eigentlich ein Zeiger ...
danke & gruss,
~cp code_pilot
-
das geht nicht. was soll denn der scheiss?
-
rènèsè schrieb:
das geht nicht. was soll denn der scheiss?
wie was soll der scheiss? Ich suche nur eine Lösung und keine dummen Bemerkungen ...
-
wo genau stürzt er den ab? (debugger)
-
flenders schrieb:
wo genau stürzt er den ab? (debugger)
hi! Ja er stürzt da ab, wo die Funktion aufgerufen wird, also bei
(pfFunc) (args);
Die Meldung: In Projekt dll_test.exe ist eine Exception der Klasse EAccessViolation aufgetreten, mit Zugriffsverletzung bei Adresse 77DC3E56. Lesen von Adresse 000000FF.
Hmmm ... hilft euch das vielleicht weiter?
grüsse,
~cp code_pilot
-
Ist der return value von GetProcAddress - also pfFunc - ungleich NULL? Falls nicht -> GetLastError()
-
die funktion stürzt natürlich ab, weil die "args" falsch sind.
-
Seltsam, seltsam!
Jetzt habe ich es mal mit der KERNEL32.DLL Funktion GetCurrentDirectoryA probiert, parameter sind ein char* und ein long. Funktioniert einwandfrei, ich erhalte keinen Fehler und der Pfad des aktuellen Verzeichnisses wird in den dynamisch übergebenen char* geschrieben. Hmmm ... aber mit sowas wie GetUserNameA aus der ADVAPI32.DLL geht es nicht. Kann das vielleicht sein, das Windows NT4 dafür zu alt ist??@flenders: Nee, weil er ja abstürzt sobald die funktion aufgerufen wird. Kein Rückgabewert.
@stack: Wieso? Die Funktion holt sich die entsprechenden Parameter aus dem Speicher,sonst hätte es ja mit MessageBoxA oder GetCurrentDirectoryA auch nicht geklappt.
Gruss,
code_pilot
-
Ist dein Buffer auch groß genug (UNLEN + 1)?
( http://msdn.microsoft.com/library/en-us/sysinfo/base/getusername.asp )
Zeig mal deinen Code, wie du das ganze jetzt aufrufst
-
flenders schrieb:
Zeig mal deinen Code, wie du das ganze jetzt aufrufst
Hi flenders!
Ja der Code steht unten (leider etwas vermackt, weil ich da soviel dran rumgetestet habe). Naja, ich lege die Parameter ganz einfach fest, indem ich dem programm sage, ob der Parameter numerisch (long) oder ein string (char*) ist (also n oder s eingeben) und kann dann noch einen Wert eingeben. Naja probier's aus#include <windows.h> #include <string.h> #include <fstream.h> #include <conio.h> #pragma hdrstop #include <condefs.h> #include <commctrl.h> typedef struct { void *dwARG[10]; } STACK; //typedef struct { void *dwARG[10]; } STACK; typedef DWORD (*PFDLL) (STACK); //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { char dllpath[MAXPATH+1]; char funcname[1024+1]; char type[1+1]; char ftype[1+1]; char tmpdata_str[10][255]; int maxval = 0; //STACK* args = new STACK; STACK args; /* int x = 5; char* bla = "hallo"; int* ptr_x = &x; args->dwARG[0] = (int*) ptr_x; args->dwARG[0] = (char*) bla; */ memset(&args, 0, sizeof(STACK)); DWORD dwRet; printf("DLL Tester\n\n"); printf("Enter DLL filename: "); gets(dllpath); if(strcmp(dllpath, "") == 0) { strcpy(dllpath, "c:\\winnt\\system32\\kernel32.dll"); //strcpy(dllpath, "c:\\winnt\\system32\\advapi32.dll"); //strcpy(dllpath, "c:\\winnt\\system32\\user32.dll"); //return -1; } printf("Enter function to call: "); gets(funcname); if(strcmp(funcname, "") == 0) { strcpy(funcname, "GetComputerNameA"); //strcpy(funcname, "GetCurrentDirectoryA"); //strcpy(funcname, "CopyFileA"); //strcpy(funcname, "MessageBoxA"); //return -1; } while(1) { printf("Return value of the function (n/s): "); gets(ftype); if(strcmp(ftype, "n") == 0 || strcmp(ftype, "s") == 0) break; } for(int i=0;i<10;i++) { printf("Data type %i (n/s): ", i); gets(type); if(strcmp(type, "") == 0) break; maxval++; if(strcmp(type, "n") == 0) { printf("Numerical value: "); gets(tmpdata_str[i]); args.dwARG[i] = (long*) atoi(tmpdata_str[i]); //printf ("\t%d\n", bla); //int bin_doof = atoi(tmpdata_str[i]); //int* ptr_int = (int*) args->dwARG; //args[i] = (DWORD) atoi(tmpdata_str[i]); } else if(strcmp(type, "s") == 0) { printf("String value: "); gets(tmpdata_str[i]); args.dwARG[i] = (char*) tmpdata_str[i]; //memcpy(&(args->dwARG[i]), tmpdata_str[i], sizeof(DWORD)); //args.dwARG[i] = (DWORD) tmpdata_str[i]; //args[i] = (DWORD) tmpdata_str[i]; } else { printf("Unknown type, try again.\n"); i--; maxval--; } } /* printf("Values of stack:\n"); for(int i=0;i<maxval-1;i++) { printf("\n%d => %s %d", i, (char*) args.dwARG[i], (int) args.dwARG[i]); } */ printf("\nOk, ready to run, press any key...\n"); getch(); /* strcpy(ftype, "n"); strcpy(dllpath, "c:\\winnt\\system32\\advapi32.dll"); strcpy(funcname, "GetUserNameA"); DWORD test = (DWORD) "Hello World"; args.dwARG[0] = &test ; args.dwARG[1] = (DWORD*) 255; */ /* strcpy(dllpath, "c:\\winnt\\system32\\user32.dll"); strcpy(funcname, "MessageBoxA"); char *test = "Hello World"; int n1 = 0; int n2 = 48; args.dwARG[0] = (DWORD) 0 ; args.dwARG[1] = (DWORD*) test; args.dwARG[2] = (DWORD*) test; args.dwARG[3] = (DWORD*) 48; */ printf("Loading the DLL...\n"); HINSTANCE hDll = LoadLibrary(dllpath); if(hDll == NULL) { printf("ERROR: DLL not found!\n"); getch(); return -1; } printf("Loading the Procedure...\n"); PFDLL pfFunc = (PFDLL) GetProcAddress(hDll, funcname); if(pfFunc == NULL) { printf("ERROR: Function not found!\n"); getch(); return -1; } printf("Okay. Initializing the parameters NOW..."); /* char szBuf1[] = "hello world jajaja"; char szBuf2[] = "das ist ein test"; args.dwARG[0] = 0; args.dwARG[1] = (DWORD) szBuf1; args.dwARG[2] = (DWORD) szBuf2; args.dwARG[3] = 68; */ printf("Done\n"); printf("Executing..."); dwRet = 0; if(strcmp(ftype, "n") == 0) { dwRet = (pfFunc) (args); printf("Done\n\n"); printf("Return value: %d", (int) dwRet); } else { dwRet = (pfFunc) (args); printf("Done\n\n"); printf("Return value: %s", (char*) dwRet); } /* printf("Values of stack:\n"); for(int i=0;i<maxval;i++) { printf("\n%d => %s %d", i, (char*) &args.dwARG[i], (int) args.dwARG[i]); } */ maxval=2; printf("Values of stack:\n"); for(int i=0;i<10;i++) { printf("%s\n", tmpdata_str[i]); } getch(); printf("\nGoodbye ;)...\n\n"); return 0; }