Results 1 to 10 of 10

Thread: DLL Help needed (scar++ related)

  1. #1
    Join Date
    Dec 2007
    Location
    Somewhere in Idaho
    Posts
    480
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default DLL Help needed (scar++ related)

    Ok, I have ran into a snag with Scar++, I want to put a alright plugin loader into it, but the problem is that data types in delphi plugins don't always convert straight over.

    So here is where I am at, if you can figure out how to do this I would be much appreciative.

    What you need is Wizzup's Plugin from the SRL SVN. Put it in the same folder. Here is the program I have so far.

    Code:
    #include <iostream>
    #include <windows.h>
    
    using namespace std;
    
    typedef long (*fcount)() __attribute((stdcall)); 
    typedef long (*finfo)(int, void**, char**) __attribute((stdcall));
    typedef POINT*& (*tpa)(HDC) __attribute((stdcall));
    
    fcount GetFunctionCount;
    finfo GetFunctionInfo;
    
    int main()
    {
       long count;
       HINSTANCE inst = LoadLibrary("WizzyPlugin.dll");
       GetFunctionCount = (fcount)GetProcAddress(inst,"GetFunctionCount");
       GetFunctionInfo = (finfo)GetProcAddress(inst,"GetFunctionInfo");
    
       tpa CreateTPAFromBMP;
       void* funcAddr;
       char* junk = new char[512];
       POINT* points;
    
       GetFunctionInfo(33, &funcAddr, &junk);
       CreateTPAFromBMP = (tpa)funcAddr;
    
    cerr << "Failed after here!\n";
    cerr << notJunk << endl;
    
       HDC dc = GetDC(GetDesktopWindow());
    
    cerr << "got the correct dc\n";
    
       points = CreateTPAFromBMP(dc);
       
       return 0;
    }
    Well, thats what I have so far. If you know how to get further I would be very grateful.

  2. #2
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    All types will convert over evenly. Delphi has no different types than any other language, unless a user defines them.

    However, what is most likely the problem is that you don't declare the function pointer right. It should be something like:

    Code:
    int (*get_procnum)(void)
    int (*get_procaddr)(long, void*, char*)
    The functions inside the DLL should be 'stdcall', not 'pascal' or 'cdecl' (which C++ happens to be). So they should be found. ALSO, when in windows, stdcall decorates the functions like:

    Code:
    _name@x
    Where x = number of bytes in arguments. (On 32bit, void == sizeof(int)) So the symbols in the Delphi DLL would be (I think):

    Code:
    _GetFunctionCount@0
    _GetFunctionInfo@12

    EDIT: Wait, I saw what was at the top with the function pointers... But... WHAT THE FUCK is going on with those typedefs?
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  3. #3
    Join Date
    Dec 2007
    Location
    Somewhere in Idaho
    Posts
    480
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    All types will convert over evenly. Delphi has no different types than any other language, unless a user defines them.

    However, what is most likely the problem is that you don't declare the function pointer right. It should be something like:

    Code:
    int (*get_procnum)(void)
    int (*get_procaddr)(long, void*, char*)
    The functions inside the DLL should be 'stdcall', not 'pascal' or 'cdecl' (which C++ happens to be). So they should be found. ALSO, when in windows, stdcall decorates the functions like:

    Code:
    _name@x
    Where x = number of bytes in arguments. (On 32bit, void == sizeof(int)) So the symbols in the Delphi DLL would be (I think):

    Code:
    _GetFunctionCount@0
    _GetFunctionInfo@12

    EDIT: Wait, I saw what was at the top with the function pointers... But... WHAT THE FUCK is going on with those typedefs?
    :P Yep I was a couple a steps ahead of you. using typedefs makes it much easier to convert from a void* (which is returned by GetFunctionInfo) to a function pointer of your choice. It just makes it more readable. As for the stdcall. Well, g++ has a weird way to make functions stdcall it is __attribute((stdcall)); Yes, it is different from most other compilers, but it's what I got.

    However, I don't have a perfect knowledge of C++, pascal, and windows DLLs. This much I know for certain.

    1. The returned pointer is pointing to the correct location. This method that I just used works for other functions (like smart)

    2. stdcall is working correctly, again, smart was used to test this method and It came out fine.

    What I don't know.

    1. Why it crashes, perhaps c++ was supposed to handle creating and allocating the array rather then the delphi dll. That is one of my suspicions.

    Anyways, if you can get a working declaration that runs CreateTPAfromBMP I would be more then happy to see the implementation.

  4. #4
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    No, I understand what typedef's are for. But you didn't specify a replacement type (because the space makes the type "long" whether it be anywhere in your code, refer to the function pointers you made up).
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  5. #5
    Join Date
    Dec 2007
    Location
    Somewhere in Idaho
    Posts
    480
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    No, I understand what typedef's are for. But you didn't specify a replacement type (because the space makes the type "long" whether it be anywhere in your code, refer to the function pointers you made up).
    Trust me, that is correct, it wouldn't compile if it wasn't. The way you declare a function pointer is long (*NameOfFunctionPointer)(int arguments); Don't blame me for the strange syntax, that is just how it is. The replacement type is in the parenthesis

    If you still don't believe me, take out the call to the new function, do a loop on Get function info (make sure you allocate memory for the new functions name) and print out all the names of the functions. It works, trust me.

  6. #6
    Join Date
    Feb 2006
    Location
    Berkeley, CA
    Posts
    1,837
    Mentioned
    52 Post(s)
    Quoted
    60 Post(s)

    Default

    I wrote it in a class a while back, shouldn't be too hard to modify. The class pretty much works like SCAR, e.g. loads all plugins from a folder. Then the user must get method addresses out of the class via their name and assign that value to the proper pointer definition.

    Code:
    #ifndef PLUGINS_H
    #define PLUGINS_H
    
    #include "Utils.h"
    #include <windows.h>
    #include <string>
    #include <vector>
    #include <map>
    
    #define EXPORT __declspec(dllexport)
    
    class PluginLoader {
        
    public:
        EXPORT PluginLoader(const char* pluginDir);
        EXPORT ~PluginLoader();
        EXPORT void* getMethodAddress(const char* name);
        
    private:
        std::vector<HINSTANCE> handles;
        std::map<const char*, void*, strCmp> addrs;
        
    };
    
    #endif
    Code:
    #include "Plugins.h"
    #include <iostream>
    
    using namespace std;
    
    typedef long (*GetFunctionInfo)(int index, void** address, char** def) __attribute__((stdcall));
    typedef long (*GetFunctionCount)() __attribute__((stdcall));
    
    void lower(char* str) {
        while (*str != 0) {
            *str = (char) tolower(*str);
            *str++;
        }
    }
    
    PluginLoader::PluginLoader(const char* pluginDir) {
        cout << "Loading plugins from " << pluginDir << "\n";
        int dirlen = strlen(pluginDir);
        char search[MAX_PATH];
        char temp[MAX_PATH];
        strcpy(search, pluginDir);
        strcat(search, "/*.dll");
        HANDLE find;
        WIN32_FIND_DATA file;
        find = FindFirstFile(search, &file);
        if (find != INVALID_HANDLE_VALUE) {
            do {
                strcpy(temp, pluginDir);
                strcat(temp, "/");
                strcat(temp, file.cFileName);
                cout << "Loading " << file.cFileName << "\n";
                HINSTANCE inst = LoadLibrary(temp);
                if (inst) {
                    handles.push_back(inst);
                    GetFunctionCount count = (GetFunctionCount)GetProcAddress(inst,"GetFunctionCount");
                    GetFunctionInfo info = (GetFunctionInfo)GetProcAddress(inst,"GetFunctionInfo");
                    if (count != 0 && info != 0) {
                        long functions = count();
                        for (int i = 0; i < functions; i++) {
                            try {
                                void* address;
                                char* def = (char*)malloc(512);
                                if (info(i,&address,&def) == -1) break;
                                char* ref = def; 
                                lower(def);
                                while (*def == ' ') def++;
                                while (*def != ' ') def++;
                                while (*def == ' ') def++;
                                char* start = def;
                                while ((*def != ' ') && (*def != '(') && (*def != ':') && (*def != ';')) def++;
                                *def = 0;
                                char* name = (char*)malloc(def - start + 1);
                                strcpy(name, start);
                                addrs[name] = address;
                                cout << "\t" << name << "\n";
                                free(ref);
                            } catch (...) {
                                cout << "Error loading function index " << i << " from " << file.cFileName << "\n";
                            }
                        }
                    }
                }
            } while (FindNextFile(find, &file));
            cout << "Done loading plugins!\n";
            FindClose(find);
        } 
    }
    
    PluginLoader::~PluginLoader() {
        while (!handles.empty()) {
            FreeLibrary(handles.back());
            handles.pop_back();
        }
        map<const char*, void*>::iterator it;
        for (it = addrs.begin(); it != addrs.end(); it++) {
            free((void*)(it->first));
        }
        addrs.clear();
    }
    
    void* PluginLoader::getMethodAddress(const char* name) {
        char* lowerName;
        lowerName = (char*)malloc(strlen(name)+1);
        strcpy(lowerName, name);
        lower(lowerName);
        if (addrs.end() != addrs.find(lowerName))
            return addrs[lowerName];
        return 0;
    }

  7. #7
    Join Date
    Dec 2007
    Location
    Somewhere in Idaho
    Posts
    480
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Quote Originally Posted by BenLand100 View Post
    I wrote it in a class a while back, shouldn't be too hard to modify. The class pretty much works like SCAR, e.g. loads all plugins from a folder. Then the user must get method addresses out of the class via their name and assign that value to the proper pointer definition.

    Code:
    #ifndef PLUGINS_H
    #define PLUGINS_H
    
    #include "Utils.h"
    #include <windows.h>
    #include <string>
    #include <vector>
    #include <map>
    
    #define EXPORT __declspec(dllexport)
    
    class PluginLoader {
        
    public:
        EXPORT PluginLoader(const char* pluginDir);
        EXPORT ~PluginLoader();
        EXPORT void* getMethodAddress(const char* name);
        
    private:
        std::vector<HINSTANCE> handles;
        std::map<const char*, void*, strCmp> addrs;
        
    };
    
    #endif
    Code:
    #include "Plugins.h"
    #include <iostream>
    
    using namespace std;
    
    typedef long (*GetFunctionInfo)(int index, void** address, char** def) __attribute__((stdcall));
    typedef long (*GetFunctionCount)() __attribute__((stdcall));
    
    void lower(char* str) {
        while (*str != 0) {
            *str = (char) tolower(*str);
            *str++;
        }
    }
    
    PluginLoader::PluginLoader(const char* pluginDir) {
        cout << "Loading plugins from " << pluginDir << "\n";
        int dirlen = strlen(pluginDir);
        char search[MAX_PATH];
        char temp[MAX_PATH];
        strcpy(search, pluginDir);
        strcat(search, "/*.dll");
        HANDLE find;
        WIN32_FIND_DATA file;
        find = FindFirstFile(search, &file);
        if (find != INVALID_HANDLE_VALUE) {
            do {
                strcpy(temp, pluginDir);
                strcat(temp, "/");
                strcat(temp, file.cFileName);
                cout << "Loading " << file.cFileName << "\n";
                HINSTANCE inst = LoadLibrary(temp);
                if (inst) {
                    handles.push_back(inst);
                    GetFunctionCount count = (GetFunctionCount)GetProcAddress(inst,"GetFunctionCount");
                    GetFunctionInfo info = (GetFunctionInfo)GetProcAddress(inst,"GetFunctionInfo");
                    if (count != 0 && info != 0) {
                        long functions = count();
                        for (int i = 0; i < functions; i++) {
                            try {
                                void* address;
                                char* def = (char*)malloc(512);
                                if (info(i,&address,&def) == -1) break;
                                char* ref = def; 
                                lower(def);
                                while (*def == ' ') def++;
                                while (*def != ' ') def++;
                                while (*def == ' ') def++;
                                char* start = def;
                                while ((*def != ' ') && (*def != '(') && (*def != ':') && (*def != ';')) def++;
                                *def = 0;
                                char* name = (char*)malloc(def - start + 1);
                                strcpy(name, start);
                                addrs[name] = address;
                                cout << "\t" << name << "\n";
                                free(ref);
                            } catch (...) {
                                cout << "Error loading function index " << i << " from " << file.cFileName << "\n";
                            }
                        }
                    }
                }
            } while (FindNextFile(find, &file));
            cout << "Done loading plugins!\n";
            FindClose(find);
        } 
    }
    
    PluginLoader::~PluginLoader() {
        while (!handles.empty()) {
            FreeLibrary(handles.back());
            handles.pop_back();
        }
        map<const char*, void*>::iterator it;
        for (it = addrs.begin(); it != addrs.end(); it++) {
            free((void*)(it->first));
        }
        addrs.clear();
    }
    
    void* PluginLoader::getMethodAddress(const char* name) {
        char* lowerName;
        lowerName = (char*)malloc(strlen(name)+1);
        strcpy(lowerName, name);
        lower(lowerName);
        if (addrs.end() != addrs.find(lowerName))
            return addrs[lowerName];
        return 0;
    }
    Aye, Indeed this program is loosely (very loosely) based on that class (it was a big help for me to understand how pascal dlls works). It is just that, for some reason, I can't write a function pointer definition to get the TPoint arrays to be returned from the function. I suspect that the function tries to write where it has no rights to write, but I am not sure.

  8. #8
    Join Date
    Dec 2006
    Location
    Banville
    Posts
    3,914
    Mentioned
    12 Post(s)
    Quoted
    98 Post(s)

    Default

    What you say? All DLL same.

    And I assume what a point would be is what it is already declared as in C++. Its just two integers glued together (So you can probably assume that whatever you declare, as long as it is two integers together in a struct, is right.)
    The jealous temper of mankind, ever more disposed to censure than
    to praise the work of others, has constantly made the pursuit of new
    methods and systems no less perilous than the search after unknown
    lands and seas.

  9. #9
    Join Date
    Dec 2007
    Location
    Somewhere in Idaho
    Posts
    480
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Quote Originally Posted by R0b0t1 View Post
    What you say? All DLL same.

    And I assume what a point would be is what it is already declared as in C++. Its just two integers glued together (So you can probably assume that whatever you declare, as long as it is two integers together in a struct, is right.)
    Ok, try it and see if it works. It didn't work for me, but maybe I was somehow doing it wrong.

  10. #10
    Join Date
    May 2006
    Location
    Amsterdam
    Posts
    3,620
    Mentioned
    5 Post(s)
    Quoted
    0 Post(s)

    Default

    Not quite sure, but if you want to pass a TPointArray to a C++ dll you probably need to do it like em.. Make one of the parameters a var to a TPoint, have a length parameter and then..
    You do like "RandomMethod(TPA[0], Length(TPA));

    Now you should have the pointer to the first element..

    Not quite sure if this is what you mean xD..

    EDIT: I see your problem, a returning TPA.. Well now you have to find out how Delphi stores Array's.. >.<
    Verrekte Koekwous

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Replies: 28
    Last Post: 06-22-2006, 04:27 PM
  2. my test results (not rs or scar related) =)
    By phantombmx in forum News and General
    Replies: 16
    Last Post: 04-28-2006, 02:47 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •