Ok, found the error by logging the Com_Printf stuff to a file:


Code:
// include/functions.h
#if COD_VERSION == COD2_1_3
    static FILE *f = NULL;
    //static Com_Printf_t Com_Printf = (Com_Printf_t)0x0431EE0;
    static int Com_Printf(const char *format, ...) {
        if (f == NULL) {
            f = fopen("C:\\libcod.txt", "w+"); // start the Link with +dedicated 1 as Administrator for write permissions
            //fclose(f);
        }
        fprintf(f, "%s", format);
        fflush(f);
    }
#else
Output:
Code:
DllMain()
[PLUGIN LOADED]
DllMain()
DllMain()
Already started!
[THREAD DETACH]
DllMain()
[THREAD DETACH]
DllMain()

Here starts the unloading:

DllMain()
[THREAD DETACH]
DllMain()
[THREAD DETACH]
DllMain()
DllMain()
DllMain()
[PLUGIN UNLOADED]
For some reason the DllMain()/DLL_PROCESS_ATTACH is called twice. Fixed it with a simple static variable:

Code:
static int isStarted = 0;
DWORD WINAPI MyThread(LPVOID)
{
    if (isStarted) {
        Com_Printf("Already started!\n");
        return NULL;
    }
    isStarted = 1;
    Com_Printf("[PLUGIN LOADED]\n");
    #if COD_VERSION == COD2_1_3
        cracking_hook_call(0x46E7BF, (int)Scr_GetCustomFunction);
        cracking_hook_call(0x46EA03, (int)Scr_GetCustomMethod);
    #endif

    return 0;
}
Now it's working fine, but the manual injecting is a bit annoying (because the dedi server will crash because of missing functions on start). Gotta look for some LD_PRELOAD replacement for Windows.