Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

module.c

00001 /*
00002  * Modules
00003  *
00004  * Copyright 1995 Alexandre Julliard
00005  *
00006  * Modified for use with MPlayer, detailed CVS changelog at
00007  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
00008  * $Id: module.c 11593 2005-06-28 18:02:01Z courmisch $
00009  *
00010  */
00011 
00012 // define for quicktime calls debugging and/or MacOS-level emulation:
00013 #define EMU_QTX_API
00014 
00015 // define for quicktime debugging (verbose logging):
00016 //#define DEBUG_QTX_API
00017 
00018 #include "config.h"
00019 
00020 #include <assert.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <unistd.h>
00027 #include <sys/mman.h>
00028 #include <inttypes.h>
00029 
00030 #include "wine/windef.h"
00031 #include "wine/winerror.h"
00032 #include "wine/heap.h"
00033 #include "wine/module.h"
00034 #include "wine/pe_image.h"
00035 #include "wine/debugtools.h"
00036 
00037 #undef HAVE_LIBDL
00038 
00039 #ifdef HAVE_LIBDL
00040 #include <dlfcn.h>
00041 #include "wine/elfdll.h"
00042 #endif
00043 #include "win32.h"
00044 #include "driver.h"
00045 
00046 #ifdef EMU_QTX_API
00047 #include "wrapper.h"
00048 static int report_func(void *stack_base, int stack_size, reg386_t *reg, uint32_t *flags);
00049 static int report_func_ret(void *stack_base, int stack_size, reg386_t *reg, uint32_t *flags);
00050 #endif
00051 
00052 //#undef TRACE
00053 //#define TRACE printf
00054 
00055 //WINE_MODREF *local_wm=NULL;
00056 modref_list* local_wm=NULL;
00057 
00058 HANDLE SegptrHeap;
00059 
00060 WINE_MODREF* MODULE_FindModule(LPCSTR m)
00061 {
00062     modref_list* list=local_wm;
00063     TRACE("FindModule: Module %s request\n", m);
00064     if(list==NULL)
00065         return NULL;
00066 //    while(strcmp(m, list->wm->filename))
00067     while(!strstr(list->wm->filename, m))
00068     {
00069         TRACE("%s: %x\n", list->wm->filename, list->wm->module);
00070         list=list->prev;
00071         if(list==NULL)
00072             return NULL;
00073     }
00074     TRACE("Resolved to %s\n", list->wm->filename);
00075     return list->wm;
00076 }
00077 
00078 static void MODULE_RemoveFromList(WINE_MODREF *mod)
00079 {
00080     modref_list* list=local_wm;
00081     if(list==0)
00082         return;
00083     if(mod==0)
00084         return;
00085     if((list->prev==NULL)&&(list->next==NULL))
00086     {
00087         free(list);
00088         local_wm=NULL;
00089 //      uninstall_fs();
00090         return;
00091     }
00092     for(;list;list=list->prev)
00093     {
00094         if(list->wm==mod)
00095         {
00096             if(list->prev)
00097                 list->prev->next=list->next;
00098             if(list->next)
00099                 list->next->prev=list->prev;
00100             if(list==local_wm)
00101                 local_wm=list->prev;
00102             free(list);
00103             return;
00104         }
00105     }
00106 
00107 }
00108 
00109 WINE_MODREF *MODULE32_LookupHMODULE(HMODULE m)
00110 {
00111     modref_list* list=local_wm;
00112     TRACE("LookupHMODULE: Module %X request\n", m);
00113     if(list==NULL)
00114     {
00115         TRACE("LookupHMODULE failed\n");
00116         return NULL;
00117     }
00118     while(m!=list->wm->module)
00119     {
00120 //      printf("Checking list %X wm %X module %X\n",
00121 //      list, list->wm, list->wm->module);
00122         list=list->prev;
00123         if(list==NULL)
00124         {
00125             TRACE("LookupHMODULE failed\n");
00126             return NULL;
00127         }
00128     }
00129     TRACE("LookupHMODULE hit %p\n", list->wm);
00130     return list->wm;
00131 }
00132 
00133 /*************************************************************************
00134  *              MODULE_InitDll
00135  */
00136 static WIN_BOOL MODULE_InitDll( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
00137 {
00138     WIN_BOOL retv = TRUE;
00139 
00140     static LPCSTR typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH",
00141                                  "THREAD_ATTACH", "THREAD_DETACH" };
00142     assert( wm );
00143 
00144 
00145     /* Skip calls for modules loaded with special load flags */
00146 
00147     if (    ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
00148          || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )
00149         return TRUE;
00150 
00151 
00152     TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved );
00153 
00154     /* Call the initialization routine */
00155     switch ( wm->type )
00156     {
00157     case MODULE32_PE:
00158         retv = PE_InitDLL( wm, type, lpReserved );
00159         break;
00160 
00161     case MODULE32_ELF:
00162         /* no need to do that, dlopen() already does */
00163         break;
00164 
00165     default:
00166         ERR("wine_modref type %d not handled.\n", wm->type );
00167         retv = FALSE;
00168         break;
00169     }
00170 
00171     /* The state of the module list may have changed due to the call
00172        to PE_InitDLL. We cannot assume that this module has not been
00173        deleted.  */
00174     TRACE("(%p,%s,%p) - RETURN %d\n", wm, typeName[type], lpReserved, retv );
00175 
00176     return retv;
00177 }
00178 
00179 /*************************************************************************
00180  *              MODULE_DllProcessAttach
00181  *
00182  * Send the process attach notification to all DLLs the given module
00183  * depends on (recursively). This is somewhat complicated due to the fact that
00184  *
00185  * - we have to respect the module dependencies, i.e. modules implicitly
00186  *   referenced by another module have to be initialized before the module
00187  *   itself can be initialized
00188  *
00189  * - the initialization routine of a DLL can itself call LoadLibrary,
00190  *   thereby introducing a whole new set of dependencies (even involving
00191  *   the 'old' modules) at any time during the whole process
00192  *
00193  * (Note that this routine can be recursively entered not only directly
00194  *  from itself, but also via LoadLibrary from one of the called initialization
00195  *  routines.)
00196  *
00197  * Furthermore, we need to rearrange the main WINE_MODREF list to allow
00198  * the process *detach* notifications to be sent in the correct order.
00199  * This must not only take into account module dependencies, but also
00200  * 'hidden' dependencies created by modules calling LoadLibrary in their
00201  * attach notification routine.
00202  *
00203  * The strategy is rather simple: we move a WINE_MODREF to the head of the
00204  * list after the attach notification has returned.  This implies that the
00205  * detach notifications are called in the reverse of the sequence the attach
00206  * notifications *returned*.
00207  *
00208  * NOTE: Assumes that the process critical section is held!
00209  *
00210  */
00211 static WIN_BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
00212 {
00213     WIN_BOOL retv = TRUE;
00214     int i;
00215     assert( wm );
00216 
00217     /* prevent infinite recursion in case of cyclical dependencies */
00218     if (    ( wm->flags & WINE_MODREF_MARKER )
00219          || ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) )
00220         return retv;
00221 
00222     TRACE("(%s,%p) - START\n", wm->modname, lpReserved );
00223 
00224     /* Tag current MODREF to prevent recursive loop */
00225     wm->flags |= WINE_MODREF_MARKER;
00226 
00227     /* Recursively attach all DLLs this one depends on */
00228 /*    for ( i = 0; retv && i < wm->nDeps; i++ )
00229         if ( wm->deps[i] )
00230             retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved );
00231 */
00232     /* Call DLL entry point */
00233 
00234     //local_wm=wm;
00235     if(local_wm)
00236     {
00237         local_wm->next = (modref_list*) malloc(sizeof(modref_list));
00238         local_wm->next->prev=local_wm;
00239         local_wm->next->next=NULL;
00240         local_wm->next->wm=wm;
00241         local_wm=local_wm->next;
00242     }
00243     else
00244     {
00245         local_wm = (modref_list*)malloc(sizeof(modref_list));
00246         local_wm->next=local_wm->prev=NULL;
00247         local_wm->wm=wm;
00248     }
00249     /* Remove recursion flag */
00250     wm->flags &= ~WINE_MODREF_MARKER;
00251 
00252     if ( retv )
00253     {
00254         retv = MODULE_InitDll( wm, DLL_PROCESS_ATTACH, lpReserved );
00255         if ( retv )
00256             wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
00257     }
00258 
00259 
00260     TRACE("(%s,%p) - END\n", wm->modname, lpReserved );
00261 
00262     return retv;
00263 }
00264 
00265 /*************************************************************************
00266  *              MODULE_DllProcessDetach
00267  *
00268  * Send DLL process detach notifications.  See the comment about calling
00269  * sequence at MODULE_DllProcessAttach.  Unless the bForceDetach flag
00270  * is set, only DLLs with zero refcount are notified.
00271  */
00272 static void MODULE_DllProcessDetach( WINE_MODREF* wm, WIN_BOOL bForceDetach, LPVOID lpReserved )
00273 {
00274     //    WINE_MODREF *wm=local_wm;
00275     modref_list* l = local_wm;
00276     wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED;
00277     MODULE_InitDll( wm, DLL_PROCESS_DETACH, lpReserved );
00278 /*    while (l)
00279     {
00280         modref_list* f = l;
00281         l = l->next;
00282         free(f);
00283     }
00284     local_wm = 0;*/
00285 }
00286 
00287 /***********************************************************************
00288  *      MODULE_LoadLibraryExA   (internal)
00289  *
00290  * Load a PE style module according to the load order.
00291  *
00292  * The HFILE parameter is not used and marked reserved in the SDK. I can
00293  * only guess that it should force a file to be mapped, but I rather
00294  * ignore the parameter because it would be extremely difficult to
00295  * integrate this with different types of module represenations.
00296  *
00297  */
00298 static WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
00299 {
00300         DWORD err = GetLastError();
00301         WINE_MODREF *pwm;
00302         int i;
00303 //      module_loadorder_t *plo;
00304 
00305         SetLastError( ERROR_FILE_NOT_FOUND );
00306         TRACE("Trying native dll '%s'\n", libname);
00307         pwm = PE_LoadLibraryExA(libname, flags);
00308 #ifdef HAVE_LIBDL
00309         if(!pwm)
00310         {
00311             TRACE("Trying ELF dll '%s'\n", libname);
00312             pwm=(WINE_MODREF*)ELFDLL_LoadLibraryExA(libname, flags);
00313         }
00314 #endif
00315 //              printf("0x%08x\n", pwm);
00316 //              break;
00317         if(pwm)
00318         {
00319                 /* Initialize DLL just loaded */
00320                 TRACE("Loaded module '%s' at 0x%08x, \n", libname, pwm->module);
00321                 /* Set the refCount here so that an attach failure will */
00322                 /* decrement the dependencies through the MODULE_FreeLibrary call. */
00323                 pwm->refCount++;
00324 
00325                 SetLastError( err );  /* restore last error */
00326                 return pwm;
00327         }
00328 
00329 
00330         WARN("Failed to load module '%s'; error=0x%08lx, \n", libname, GetLastError());
00331         return NULL;
00332 }
00333 
00334 /***********************************************************************
00335  *           MODULE_FreeLibrary
00336  *
00337  * NOTE: Assumes that the process critical section is held!
00338  */
00339 static WIN_BOOL MODULE_FreeLibrary( WINE_MODREF *wm )
00340 {
00341     TRACE("(%s) - START\n", wm->modname );
00342 
00343     /* Recursively decrement reference counts */
00344     //MODULE_DecRefCount( wm );
00345 
00346     /* Call process detach notifications */
00347     MODULE_DllProcessDetach( wm, FALSE, NULL );
00348 
00349     PE_UnloadLibrary(wm);
00350 
00351     TRACE("END\n");
00352 
00353     return TRUE;
00354 }
00355 
00356 /***********************************************************************
00357  *           LoadLibraryExA   (KERNEL32)
00358  */
00359 HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
00360 {
00361         WINE_MODREF *wm = 0;
00362         char* listpath[] = { "", "", "/usr/lib/win32", "/usr/local/lib/win32", 0 };
00363         extern char* def_path;
00364         char path[512];
00365         char checked[2000];
00366         int i = -1;
00367 
00368         checked[0] = 0;
00369         if(!libname)
00370         {
00371                 SetLastError(ERROR_INVALID_PARAMETER);
00372                 return 0;
00373         }
00374 
00375         wm=MODULE_FindModule(libname);
00376         if(wm) return wm->module;
00377 
00378 //      if(fs_installed==0)
00379 //          install_fs();
00380 
00381         while (wm == 0 && listpath[++i])
00382         {
00383             if (i < 2)
00384             {
00385                 if (i == 0)
00386                     /* check just original file name */
00387                     strncpy(path, libname, 511);
00388                 else
00389                     /* check default user path */
00390                     strncpy(path, def_path, 300);
00391             }
00392             else if (strcmp(def_path, listpath[i]))
00393                 /* path from the list */
00394                 strncpy(path, listpath[i], 300);
00395             else
00396                 continue;
00397 
00398             if (i > 0)
00399             {
00400                 strcat(path, "/");
00401                 strncat(path, libname, 100);
00402             }
00403             path[511] = 0;
00404             wm = MODULE_LoadLibraryExA( path, hfile, flags );
00405 
00406             if (!wm)
00407             {
00408                 if (checked[0])
00409                     strcat(checked, ", ");
00410                 strcat(checked, path);
00411                 checked[1500] = 0;
00412 
00413             }
00414         }
00415         if ( wm )
00416         {
00417                 if ( !MODULE_DllProcessAttach( wm, NULL ) )
00418                 {
00419                         WARN_(module)("Attach failed for module '%s', \n", libname);
00420                         MODULE_FreeLibrary(wm);
00421                         SetLastError(ERROR_DLL_INIT_FAILED);
00422                         MODULE_RemoveFromList(wm);
00423                         wm = NULL;
00424                 }
00425         }
00426 
00427         if (!wm)
00428             printf("Win32 LoadLibrary failed to load: %s\n", checked);
00429 
00430         if (strstr(libname,"vp31vfw.dll") && wm)
00431         {
00432             int i;
00433 
00434           // sse hack moved from patch dll into runtime patching
00435           if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10001000) {
00436             fprintf(stderr, "VP3 DLL found\n");
00437             for (i=0;i<18;i++) ((char*)0x10004bd6)[i]=0x90;
00438           }
00439         }
00440 
00441         // remove a few divs in the VP codecs that make trouble
00442         if (strstr(libname,"vp5vfw.dll") && wm)
00443         {
00444           int i;
00445           if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10003930) {
00446             for (i=0;i<3;i++) ((char*)0x10004e86)[i]=0x90;
00447             for (i=0;i<3;i++) ((char*)0x10005a23)[i]=0x90;
00448             for (i=0;i<3;i++) ((char*)0x10005bff)[i]=0x90;
00449           } else {
00450             fprintf(stderr, "Unsupported VP5 version\n");
00451             return 0;
00452           }
00453         }
00454 
00455         if (strstr(libname,"vp6vfw.dll") && wm)
00456         {
00457           int i;
00458           if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10003ef0) {
00459             // looks like VP 6.1.0.2
00460             for (i=0;i<6;i++) ((char*)0x10007268)[i]=0x90;
00461             for (i=0;i<6;i++) ((char*)0x10007e83)[i]=0x90;
00462             for (i=0;i<6;i++) ((char*)0x1000806a)[i]=0x90;
00463           } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10004120) {
00464             // looks like VP 6.2.0.10
00465             for (i=0;i<6;i++) ((char*)0x10007688)[i]=0x90;
00466             for (i=0;i<6;i++) ((char*)0x100082c3)[i]=0x90;
00467             for (i=0;i<6;i++) ((char*)0x100084aa)[i]=0x90;
00468           } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10003e70) {
00469             // looks like VP 6.0.7.3
00470             for (i=0;i<6;i++) ((char*)0x10007559)[i]=0x90;
00471             for (i=0;i<6;i++) ((char*)0x100081c3)[i]=0x90;
00472             for (i=0;i<6;i++) ((char*)0x1000839e)[i]=0x90;
00473           } else {
00474             fprintf(stderr, "Unsupported VP6 version\n");
00475             return 0;
00476           }
00477         }
00478 
00479         // Windows Media Video 9 Advanced
00480         if (strstr(libname,"wmvadvd.dll") && wm)
00481         {
00482           // The codec calls IsRectEmpty with coords 0,0,0,0 => result is 0
00483           // but it really wants the rectangle to be not empty
00484           if (PE_FindExportedFunction(wm, "CreateInstance", TRUE)==(void*)0x08c4b812) {
00485             // Dll version is 10.0.0.3645
00486             *((char*)0x08c48b0f)=0xeb; // Jump always, ignoring IsRectEmpty result
00487           } else {
00488             fprintf(stderr, "Unsupported WMVA version\n");
00489             return 0;
00490           }
00491         }
00492 
00493         if (strstr(libname,"QuickTime.qts") && wm)
00494         {
00495             void** ptr;
00496             void *dispatch_addr;
00497             int i;
00498 
00499 //          dispatch_addr = GetProcAddress(wm->module, "theQuickTimeDispatcher", TRUE);
00500             dispatch_addr = PE_FindExportedFunction(wm, "theQuickTimeDispatcher", TRUE);
00501             if (dispatch_addr == (void *)0x62924c30)
00502             {
00503                 fprintf(stderr, "QuickTime5 DLLs found\n");
00504                 ptr = (void **)0x62b75ca4; // dispatch_ptr
00505                 for (i=0;i<5;i++)  ((char*)0x6299e842)[i]=0x90; // make_new_region ?
00506                 for (i=0;i<28;i++) ((char*)0x6299e86d)[i]=0x90; // call__call_CreateCompatibleDC ?
00507                 for (i=0;i<5;i++)  ((char*)0x6299e898)[i]=0x90; // jmp_to_call_loadbitmap ?
00508                 for (i=0;i<9;i++)  ((char*)0x6299e8ac)[i]=0x90; // call__calls_OLE_shit ?
00509                 for (i=0;i<106;i++) ((char*)0x62a61b10)[i]=0x90; // disable threads
00510 #if 0
00511                 /* CreateThread callers */
00512                 for (i=0;i<5;i++) ((char*)0x629487c5)[i]=0x90;
00513                 for (i=0;i<5;i++) ((char*)0x6294b275)[i]=0x90;
00514                 for (i=0;i<5;i++) ((char*)0x629a24b1)[i]=0x90;
00515                 for (i=0;i<5;i++) ((char*)0x629afc5a)[i]=0x90;
00516                 for (i=0;i<5;i++) ((char*)0x62af799c)[i]=0x90;
00517                 for (i=0;i<5;i++) ((char*)0x62af7efe)[i]=0x90;
00518                 for (i=0;i<5;i++) ((char*)0x62afa33e)[i]=0x90;
00519 #endif
00520 
00521 #if 0
00522                 /* TerminateQTML fix */
00523                 for (i=0;i<47;i++) ((char*)0x62afa3b8)[i]=0x90; // terminate thread
00524                 for (i=0;i<47;i++) ((char*)0x62af7f78)[i]=0x90; // terminate thread
00525                 for (i=0;i<77;i++) ((char*)0x629a13d5)[i]=0x90;
00526                 ((char *)0x6288e0ae)[0] = 0xc3; // font/dc remover
00527                 for (i=0;i<24;i++) ((char*)0x6287a1ad)[i]=0x90; // destroy window
00528 #endif
00529             } else if (dispatch_addr == (void *)0x6693b330)
00530             {
00531                 fprintf(stderr, "QuickTime6 DLLs found\n");
00532                 ptr = (void **)0x66bb9524; // dispatcher_ptr
00533                 for (i=0;i<5;i++)  ((char *)0x66a730cc)[i]=0x90; // make_new_region
00534                 for (i=0;i<28;i++) ((char *)0x66a730f7)[i]=0x90; // call__call_CreateCompatibleDC
00535                 for (i=0;i<5;i++)  ((char *)0x66a73122)[i]=0x90; // jmp_to_call_loadbitmap
00536                 for (i=0;i<9;i++)  ((char *)0x66a73131)[i]=0x90; // call__calls_OLE_shit
00537                 for (i=0;i<96;i++) ((char *)0x66aac852)[i]=0x90; // disable threads
00538             } else if (dispatch_addr == (void *)0x6693c3e0)
00539             {
00540                 fprintf(stderr, "QuickTime6.3 DLLs found\n");
00541                 ptr = (void **)0x66bca01c; // dispatcher_ptr
00542                 for (i=0;i<5;i++)  ((char *)0x66a68f6c)[i]=0x90; // make_new_region
00543                 for (i=0;i<28;i++) ((char *)0x66a68f97)[i]=0x90; // call__call_CreateCompatibleDC
00544                 for (i=0;i<5;i++)  ((char *)0x66a68fc2)[i]=0x90; // jmp_to_call_loadbitmap
00545                 for (i=0;i<9;i++)  ((char *)0x66a68fd1)[i]=0x90; // call__calls_OLE_shit
00546                 for (i=0;i<96;i++) ((char *)0x66ab4722)[i]=0x90; // disable threads
00547             } else
00548             {
00549                 fprintf(stderr, "Unsupported QuickTime version (%p)\n",
00550                     dispatch_addr);
00551                 return 0;
00552             }
00553 
00554             fprintf(stderr,"QuickTime.qts patched!!! old entry=%p\n",ptr[0]);
00555 
00556 #ifdef EMU_QTX_API
00557             report_entry = report_func;
00558             report_ret   = report_func_ret;
00559             wrapper_target=ptr[0];
00560             ptr[0]=wrapper;
00561 #endif
00562         }
00563 
00564         return wm ? wm->module : 0;
00565 }
00566 
00567 
00568 /***********************************************************************
00569  *           LoadLibraryA         (KERNEL32)
00570  */
00571 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
00572         return LoadLibraryExA(libname,0,0);
00573 }
00574 
00575 /***********************************************************************
00576  *           FreeLibrary
00577  */
00578 WIN_BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
00579 {
00580     WIN_BOOL retv = FALSE;
00581     WINE_MODREF *wm;
00582 
00583     wm=MODULE32_LookupHMODULE(hLibModule);
00584 
00585     if ( !wm || !hLibModule )
00586     {
00587         SetLastError( ERROR_INVALID_HANDLE );
00588         return 0;
00589     }
00590     else
00591         retv = MODULE_FreeLibrary( wm );
00592 
00593     MODULE_RemoveFromList(wm);
00594 
00595     /* garbage... */
00596     if (local_wm == NULL) my_garbagecollection();
00597 
00598     return retv;
00599 }
00600 
00601 /***********************************************************************
00602  *           MODULE_DecRefCount
00603  *
00604  * NOTE: Assumes that the process critical section is held!
00605  */
00606 static void MODULE_DecRefCount( WINE_MODREF *wm )
00607 {
00608     int i;
00609 
00610     if ( wm->flags & WINE_MODREF_MARKER )
00611         return;
00612 
00613     if ( wm->refCount <= 0 )
00614         return;
00615 
00616     --wm->refCount;
00617     TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount );
00618 
00619     if ( wm->refCount == 0 )
00620     {
00621         wm->flags |= WINE_MODREF_MARKER;
00622 
00623         for ( i = 0; i < wm->nDeps; i++ )
00624             if ( wm->deps[i] )
00625                 MODULE_DecRefCount( wm->deps[i] );
00626 
00627         wm->flags &= ~WINE_MODREF_MARKER;
00628     }
00629 }
00630 
00631 /***********************************************************************
00632  *           GetProcAddress             (KERNEL32.257)
00633  */
00634 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
00635 {
00636     return MODULE_GetProcAddress( hModule, function, TRUE );
00637 }
00638 
00639 #ifdef DEBUG_QTX_API
00640 
00641 /* 
00642 http://lists.apple.com/archives/quicktime-api/2003/Jan/msg00278.html
00643 */
00644 
00645 struct ComponentParameters {
00646     unsigned char                   flags;                      /* call modifiers: sync/async, deferred, immed, etc */
00647     unsigned char                   paramSize;                  /* size in bytes of actual parameters passed to this call */
00648     short                           what;                       /* routine selector, negative for Component management calls */
00649     long                            params[1];                  /* actual parameters for the indicated routine */
00650 };
00651 typedef struct ComponentParameters      ComponentParameters;
00652 
00653 static char* component_func(int what){
00654 if (what < 0) // Range 0: Standard Component Calls
00655 switch(what){
00656 case -1: return "kComponentOpenSelect";
00657 case -2: return "kComponentCloseSelect";
00658 case -3: return "kComponentCanDoSelect";
00659 case -4: return "kComponentVersionSelect";
00660 case -5: return "kComponentRegisterSelect";
00661 case -6: return "kComponentTargetSelect";
00662 case -7: return "kComponentUnregisterSelect";
00663 }
00664 
00665 if (what >= 0 && what <= 0xff) // Range 1: Generic codecs
00666 switch(what & 0xff){
00667 case 0: return "kImageCodecGetCodecInfoSelect";
00668 case 1: return "kImageCodecGetCompressionTimeSelect";
00669 case 2: return "kImageCodecGetMaxCompressionSizeSelect";
00670 case 3: return "kImageCodecPreCompressSelect";
00671 case 4: return "kImageCodecBandCompressSelect";
00672 case 5: return "kImageCodecPreDecompressSelect";
00673 case 6: return "kImageCodecBandDecompressSelect";
00674 case 7: return "kImageCodecBusySelect";
00675 // finish this list from the above URL
00676 case 0x10: return "kImageCodecIsImageDescriptionEquivalentSelect";
00677 case 0x12: return "kImageCodecDisposeMemorySelect";
00678 case 0x14: return "kImageCodecNewImageBufferMemorySelect";
00679 case 0x28: return "kImageCodecRequestGammaLevelSelect";
00680 }
00681 
00682 //if (what >= 0x100 && what <= 0x1ff) // Range 2: Specific to QT Photo JPEG codecs
00683 
00684 if (what >= 0x200 && what <= 0x2ff) // Range 3: Base Decompressor
00685 switch(what & 0xff){
00686 case 0: return "Preflight";
00687 case 1: return "Initialize";
00688 case 2: return "BeginBand";
00689 case 3: return "DrawBand";
00690 case 4: return "EndBand";
00691 case 5: return "QueueStarting";
00692 case 6: return "QueueStopping";
00693 }
00694 
00695 return "???";
00696 }
00697 
00698 static int c_level=0;
00699 
00700 static int dump_component(char* name,int type,void* _orig, ComponentParameters *params,void** glob){
00701     int ( *orig)(ComponentParameters *params, void** glob) = _orig;
00702     int ret,i;
00703 
00704     fprintf(stderr,"%*sComponentCall: %s  flags=0x%X  size=%d  what=0x%X %s\n",3*c_level,"",name,params->flags, params->paramSize, params->what, component_func(params->what));
00705 
00706     for(i=0;i<params->paramSize/4;i++)
00707         fprintf(stderr,"%*s param[%d] = 0x%X\n",3*c_level,"",i,params->params[i]);
00708 
00709     ++c_level;
00710     ret=orig(params,glob);
00711     --c_level;
00712     
00713     if(ret>=0x1000)
00714         fprintf(stderr,"%*s return=0x%X\n",3*c_level,"",ret);
00715     else
00716         fprintf(stderr,"%*s return=%d\n",3*c_level,"",ret);
00717     return ret;
00718 }
00719 
00720 #define DECL_COMPONENT(sname,name,type) \
00721     static void* real_ ## sname = NULL; \
00722     static int fake_ ## sname(ComponentParameters *params,void** glob){ \
00723         return dump_component(name,type,real_ ## sname, params, glob); \
00724     }
00725 
00726 #include "qt_comp.h"
00727 
00728 #undef DECL_COMPONENT
00729 
00730 #include "qt_fv.h"
00731 
00732 #endif
00733 
00734 #ifdef EMU_QTX_API
00735 
00736 static uint32_t ret_array[4096];
00737 static int ret_i=0;
00738 
00739 static int report_func(void *stack_base, int stack_size, reg386_t *reg, uint32_t *flags)
00740 {
00741 #ifdef DEBUG_QTX_API
00742   int i;
00743   int* dptr;
00744   void* pwrapper=NULL;
00745   void* pptr=NULL;
00746   char* pname=NULL;
00747   int plen=-1;
00748   // find the code:
00749   
00750   dptr=0x62b67ae0;dptr+=2*((reg->eax>>16)&255);
00751 //  printf("FUNC: flag=%d ptr=%p\n",dptr[0],dptr[1]);
00752   if(dptr[0]&255){
00753       dptr=dptr[1];dptr+=4*(reg->eax&65535);
00754 //      printf("FUNC: ptr2=%p  eax=%p  edx=%p\n",dptr[1],dptr[0],dptr[2]);
00755       pwrapper=dptr[1]; pptr=dptr[0]; plen=dptr[2]; 
00756   } else {
00757       pwrapper=0x62924910;
00758       switch(dptr[1]){
00759       case 0x629248d0:
00760           dptr=0x62b672c0;dptr+=2*(reg->eax&65535);
00761 //          printf("FUNC: ptr2=%p  eax=%p  edx=%p\n",0x62924910,dptr[0],dptr[1]);
00762           pptr=dptr[0]; plen=dptr[1]; 
00763           break;
00764       case 0x62924e40:
00765           dptr=0x62b67c70;dptr+=2*(reg->eax&65535);
00766 //          printf("FUNC: ptr2=%p  eax=%p  edx=%p\n",0x62924910,dptr[0],dptr[1]);
00767           pptr=dptr[0]; plen=dptr[1]; 
00768           break;
00769       case 0x62924e60:
00770           dptr=0x62b68108;if(reg->eax&0x8000) dptr+=2*(reg->eax|0xffff0000); else dptr+=2*(reg->eax&65535);
00771 //          printf("FUNC: ptr2=%p  eax=%p  edx=%p\n",0x62924910,dptr[0],dptr[1]);
00772           pptr=dptr[0]; plen=dptr[1]; 
00773           break;
00774       case 0x62924e80:
00775           dptr=0x62b68108;if(reg->eax&0x8000) dptr+=2*(reg->eax|0xffff0000); else dptr+=2*(reg->eax&65535);
00776 //          printf("FUNC: ptr2=%p  eax=%p  edx=%p\n",0x62924910,dptr[0],dptr[1]);
00777           pptr=dptr[0]; plen=dptr[1]; 
00778           break;
00779       default:
00780           printf("FUNC: unknown ptr & psize!\n");
00781           pwrapper=dptr[1];
00782       }
00783   }
00784 
00785   for(i=0;qt_fv_list[i].name;i++){
00786           if(qt_fv_list[i].id==reg->eax){
00787               pname=qt_fv_list[i].name;
00788               break;
00789           }
00790   }
00791 
00792   printf("FUNC[%X/%s]: wrapper=%p  func=%p  len=%d\n",reg->eax,
00793       pname?pname:"???",pwrapper,pptr,plen);
00794 
00795   printf("FUNC: caller=%p  ebx=%p\n",((uint32_t *)stack_base)[0],reg->ebx);
00796 
00797   if(pname)
00798       printf("%*sENTER(%d): %s(",ret_i*2,"",ret_i,pname);
00799   else
00800       printf("%*sENTER(%d): %X(",ret_i*2,"",ret_i,reg->eax);
00801   for (i=0;i<plen/4;i++){
00802     unsigned int val=((uint32_t *)stack_base)[1+i];
00803     unsigned char* fcc=&val;
00804     printf("%s0x%X", i?", ":"",val);
00805     if(fcc[0]>=0x20 && fcc[0]<128 &&
00806        fcc[1]>=0x20 && fcc[1]<128 &&
00807        fcc[2]>=0x20 && fcc[2]<128 &&
00808        fcc[3]>=0x20 && fcc[3]<128) printf("='%c%c%c%c'",fcc[3],fcc[2],fcc[1],fcc[0]);
00809     else if(val>=8 && val<65536) printf("=%d",val);
00810   }
00811   printf(")\n");
00812   fflush(stdout);
00813 
00814 #endif
00815   
00816 #if 1
00817   // emulate some functions:
00818   switch(reg->eax){
00819   // memory management:
00820   case 0x150011: //NewPtrClear
00821   case 0x150012: //NewPtrSysClear
00822       reg->eax=(uint32_t)malloc(((uint32_t *)stack_base)[1]);
00823       memset((void *)reg->eax,0,((uint32_t *)stack_base)[1]);
00824 #ifdef DEBUG_QTX_API
00825       printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
00826 #endif
00827       return 1;
00828   case 0x15000F: //NewPtr
00829   case 0x150010: //NewPtrSys
00830       reg->eax=(uint32_t)malloc(((uint32_t *)stack_base)[1]);
00831 #ifdef DEBUG_QTX_API
00832       printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
00833 #endif
00834       return 1;
00835   case 0x15002f: //DisposePtr
00836       if(((uint32_t *)stack_base)[1]>=0x60000000)
00837           printf("WARNING! Invalid Ptr handle!\n");
00838       else
00839           free((void *)((uint32_t *)stack_base)[1]);
00840       reg->eax=0;
00841 #ifdef DEBUG_QTX_API
00842       printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
00843 #endif
00844       return 1;
00845   // mutexes:
00846   case 0x1d0033: //QTMLCreateMutex
00847       reg->eax=0xdeadbabe;
00848 #ifdef DEBUG_QTX_API
00849       printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
00850 #endif
00851       return 1;
00852   case 0x1d0034: //QTMLDestroyMutex
00853   case 0x1d0035: //QTMLGrabMutex
00854   case 0x1d0036: //QTMLReturnMutex
00855   case 0x1d003d: //QTMLTryGrabMutex
00856       reg->eax=0;
00857 #ifdef DEBUG_QTX_API
00858       printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax);
00859 #endif
00860       return 1;
00861   }
00862 #endif
00863 
00864 #if 0
00865   switch(reg->eax){
00866 //  case 0x00010000:
00867 //      printf("FUNC: ImageCodecInitialize/ImageCodecGetCodecInfo(ci=%p,&icap=%p)\n",((uint32_t *)stack_base)[1],((uint32_t *)stack_base)[4]);
00868 //      break;
00869   case 0x00010003:
00870       printf("FUNC: CountComponents(&desc=%p)\n",((uint32_t *)stack_base)[1]);
00871       break;
00872   case 0x00010004:
00873       printf("FUNC: FindNextComponent(prev=%p,&desc=%p)\n",((uint32_t *)stack_base)[1],((uint32_t *)stack_base)[2]);
00874       break;
00875   case 0x00010007:
00876       printf("FUNC: OpenComponent(prev=%p)\n",((uint32_t *)stack_base)[1]);
00877       break;
00878   case 0x0003008b:
00879       printf("FUNC: QTNewGWorldFromPtr(&pts=%p,fourcc=%.4s,&rect=%p,x1=%p,x2=%p,x3=%p,plane=%p,stride=%d)\n",
00880           ((uint32_t *)stack_base)[1],
00881           &(((uint32_t *)stack_base)[2]),
00882           ((uint32_t *)stack_base)[3],
00883           ((uint32_t *)stack_base)[4],
00884           ((uint32_t *)stack_base)[5],
00885           ((uint32_t *)stack_base)[6],
00886           ((uint32_t *)stack_base)[7],
00887           ((uint32_t *)stack_base)[8]);
00888       break;
00889   case 0x001c0018:
00890       printf("FUNC: GetGWorldPixMap(gworld=%p)\n",((uint32_t *)stack_base)[1]);
00891       break;
00892   case 0x00110001:
00893       printf("FUNC: Gestalt(fourcc=%.4s, &ret=%p)\n",&(((uint32_t *)stack_base)[1]),((uint32_t *)stack_base)[2]);
00894       break;
00895   default: {
00896       int i;
00897       for(i=0;qt_fv_list[i].name;i++){
00898           if(qt_fv_list[i].id==reg->eax){
00899               printf("FUNC: %s\n",qt_fv_list[i].name);
00900               break;
00901           }
00902       }
00903       }
00904   }
00905 
00906   // print stack/reg information 
00907   printf("ENTER(%d) stack = %d bytes @ %p\n"
00908          "eax = 0x%08x edx = 0x%08x ebx = 0x%08x ecx = 0x%08x\n"
00909          "esp = 0x%08x ebp = 0x%08x esi = 0x%08x edi = 0x%08x\n"
00910          "flags = 0x%08x\n", ret_i,
00911          stack_size, stack_base,
00912          reg->eax, reg->edx, reg->ebx, reg->ecx,
00913          reg->esp, reg->ebp, reg->esi, reg->edi,
00914          *flags);
00915 #endif
00916 
00917   // save ret addr:
00918   ret_array[ret_i]=((uint32_t *)stack_base)[0];
00919   ++ret_i;
00920 
00921 #if 0
00922   // print first 7 longs in the stack (return address, arg[1], arg[2] ... ) 
00923   printf("stack[] = { ");
00924   for (i=0;i<7;i++) {
00925     printf("%08x ", ((uint32_t *)stack_base)[i]);
00926   }
00927   printf("}\n\n");
00928 #endif
00929   
00930 //  // mess with function parameters 
00931 //  ((uint32_t *)stack_base)[1] = 0x66554433;
00932 
00933 //  // mess with return address...
00934 //  reg->eax = 0x11223344;
00935     return 0;
00936 }
00937 
00938 static int report_func_ret(void *stack_base, int stack_size, reg386_t *reg, uint32_t *flags)
00939 {
00940   int i;
00941   short err;
00942 
00943   // restore ret addr:
00944   --ret_i;
00945   ((uint32_t *)stack_base)[0]=ret_array[ret_i];
00946 
00947 #ifdef DEBUG_QTX_API
00948 
00949 #if 1
00950   printf("%*sLEAVE(%d): 0x%X",ret_i*2,"",ret_i, reg->eax);
00951   err=reg->eax;
00952   if(err && (reg->eax>>16)==0) printf(" = %d",err);
00953   printf("\n");
00954   fflush(stdout);
00955 #else
00956   // print stack/reg information 
00957   printf("LEAVE(%d) stack = %d bytes @ %p\n"
00958          "eax = 0x%08x edx = 0x%08x ebx = 0x%08x ecx = 0x%08x\n"
00959          "esp = 0x%08x ebp = 0x%08x esi = 0x%08x edi = 0x%08x\n"
00960          "flags = 0x%08x\n", ret_i,
00961          stack_size, stack_base,
00962          reg->eax, reg->edx, reg->ebx, reg->ecx,
00963          reg->esp, reg->ebp, reg->esi, reg->edi,
00964          *flags);
00965 #endif
00966 
00967 #if 0
00968   // print first 7 longs in the stack (return address, arg[1], arg[2] ... ) 
00969   printf("stack[] = { ");
00970   for (i=0;i<7;i++) {
00971     printf("%08x ", ((uint32_t *)stack_base)[i]);
00972   }
00973   printf("}\n\n");
00974 #endif
00975 
00976 #endif
00977   
00978 //  // mess with function parameters 
00979 //  ((uint32_t *)stack_base)[1] = 0x66554433;
00980 
00981 //  // mess with return address...
00982 //  reg->eax = 0x11223344;
00983     return 0;
00984 }
00985 
00986 #endif
00987 
00988 /***********************************************************************
00989  *           MODULE_GetProcAddress              (internal)
00990  */
00991 FARPROC MODULE_GetProcAddress(
00992         HMODULE hModule,        /* [in] current module handle */
00993         LPCSTR function,        /* [in] function to be looked up */
00994         WIN_BOOL snoop )
00995 {
00996     WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
00997 //    WINE_MODREF *wm=local_wm;
00998     FARPROC     retproc;
00999 
01000 #ifdef DEBUG_QTX_API
01001     if (HIWORD(function))
01002         fprintf(stderr,"XXX GetProcAddress(%08lx,%s)\n",(DWORD)hModule,function);
01003     else
01004         fprintf(stderr,"XXX GetProcAddress(%08lx,%p)\n",(DWORD)hModule,function);
01005 #endif
01006 
01007 //      TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function);
01008 //    else
01009 //      TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function);
01010 
01011     if (!wm) {
01012         SetLastError(ERROR_INVALID_HANDLE);
01013         return (FARPROC)0;
01014     }
01015     switch (wm->type)
01016     {
01017     case MODULE32_PE:
01018         retproc = PE_FindExportedFunction( wm, function, snoop );
01019         if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
01020         break;
01021 #ifdef HAVE_LIBDL
01022     case MODULE32_ELF:
01023         retproc = (FARPROC) dlsym( (void*) wm->module, function);
01024         if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
01025         return retproc;
01026 #endif
01027     default:
01028         ERR("wine_modref type %d not handled.\n",wm->type);
01029         SetLastError(ERROR_INVALID_HANDLE);
01030         return (FARPROC)0;
01031     }
01032 
01033 #ifdef EMU_QTX_API
01034     if (HIWORD(function) && retproc){
01035 
01036 #ifdef DEBUG_QTX_API
01037 #define DECL_COMPONENT(sname,name,type) \
01038     if(!strcmp(function,name)){ \
01039         fprintf(stderr,name "dispatcher catched -> %p\n",retproc); \
01040         real_ ## sname = retproc; retproc = fake_ ## sname; \
01041     }
01042 #include "qt_comp.h"
01043 #undef DECL_COMPONENT
01044 #endif
01045 
01046     if(!strcmp(function,"theQuickTimeDispatcher")
01047 //      || !strcmp(function,"_CallComponentFunctionWithStorage")
01048 //      || !strcmp(function,"_CallComponent")
01049       ){
01050         fprintf(stderr,"theQuickTimeDispatcher catched -> %p\n",retproc);
01051       report_entry = report_func;
01052       report_ret   = report_func_ret;
01053       wrapper_target=(void(*)(void))retproc;
01054       retproc=(FARPROC)wrapper;
01055     }
01056 
01057     }
01058 #endif
01059 
01060     return retproc;
01061 }
01062 
01063 static int acounter = 0;
01064 void CodecAlloc(void)
01065 {
01066     acounter++;
01067     //printf("**************CODEC ALLOC %d\n", acounter);
01068 }
01069 
01070 void CodecRelease(void)
01071 {
01072     acounter--;
01073     //printf("**************CODEC RELEASE %d\n", acounter);
01074     if (acounter == 0)
01075     {
01076         for (;;)
01077         {
01078             modref_list* list = local_wm;
01079             if (!local_wm)
01080                 break;
01081             //printf("CODECRELEASE %p\n", list);
01082             MODULE_FreeLibrary(list->wm);
01083             MODULE_RemoveFromList(list->wm);
01084             if (local_wm == NULL)
01085                 my_garbagecollection();
01086         }
01087     }
01088 }

Generated on Tue Dec 20 10:14:21 2005 for vlc-0.8.4a by  doxygen 1.4.2