From be4c25600b5ab5e65c614222e92bbdac9a27617f Mon Sep 17 00:00:00 2001 From: arpi Date: Sun, 24 Nov 2002 21:45:23 +0000 Subject: - qtx (quicktime's macos emulation layer) debugging/emulation environment :) - some fixes in loadlibrary, to allow multiple loads/lookups git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8270 b3059339-0415-0410-9bf9-f77b7e298cf2 --- loader/module.c | 408 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 403 insertions(+), 5 deletions(-) (limited to 'loader/module.c') diff --git a/loader/module.c b/loader/module.c index b532c06def..81a699d09c 100644 --- a/loader/module.c +++ b/loader/module.c @@ -3,6 +3,13 @@ * * Copyright 1995 Alexandre Julliard */ + +// define for quicktime calls debugging and/or MacOS-level emulation: +//#define EMU_QTX_API + +// define for quicktime debugging (verbose logging): +//#define DEBUG_QTX_API + #include "config.h" #include @@ -15,13 +22,15 @@ #include #include - #include "wine/windef.h" #include "wine/winerror.h" #include "wine/heap.h" #include "wine/module.h" #include "wine/pe_image.h" #include "wine/debugtools.h" + +#undef HAVE_LIBDL + #ifdef HAVE_LIBDL #include #include "wine/elfdll.h" @@ -29,6 +38,12 @@ #include "win32.h" #include "driver.h" +#ifdef EMU_QTX_API +#include "wrapper.h" +static int report_func(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags); +static int report_func_ret(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags); +#endif + //#undef TRACE //#define TRACE printf @@ -43,7 +58,8 @@ WINE_MODREF* MODULE_FindModule(LPCSTR m) TRACE("Module %s request\n", m); if(list==NULL) return NULL; - while(strcmp(m, list->wm->filename)) +// while(strcmp(m, list->wm->filename)) + while(!strstr(list->wm->filename, m)) { TRACE("%s: %x\n", list->wm->filename, list->wm->module); list=list->prev; @@ -295,6 +311,17 @@ static WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD fl /* decrement the dependencies through the MODULE_FreeLibrary call. */ pwm->refCount++; +#ifdef EMU_QTX_API + if(strstr(libname,"QuickTime.qts")){ + void** ptr=0x62b75ca4; + fprintf(stderr,"QuickTime.qts entrypoint patched!!! old=%p\n",ptr[0]); + report_entry = report_func; + report_ret = report_func_ret; + wrapper_target=ptr[0]; + ptr[0]=wrapper; + } +#endif + SetLastError( err ); /* restore last error */ return pwm; } @@ -344,6 +371,10 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags) SetLastError(ERROR_INVALID_PARAMETER); return 0; } + + wm=MODULE_FindModule(libname); + if(wm) return wm->module; + // if(fs_installed==0) // install_fs(); @@ -472,6 +503,337 @@ FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function ) return MODULE_GetProcAddress( hModule, function, TRUE ); } +#ifdef DEBUG_QTX_API + +struct ComponentParameters { + unsigned char flags; /* call modifiers: sync/async, deferred, immed, etc */ + unsigned char paramSize; /* size in bytes of actual parameters passed to this call */ + short what; /* routine selector, negative for Component management calls */ + long params[1]; /* actual parameters for the indicated routine */ +}; +typedef struct ComponentParameters ComponentParameters; + +static char* component_func(int what){ +switch(what){ +case -1: return "kComponentOpenSelect"; +case -2: return "kComponentCloseSelect"; +case -3: return "kComponentCanDoSelect"; +case -4: return "kComponentVersionSelect"; +case -5: return "kComponentRegisterSelect"; +case -6: return "kComponentTargetSelect"; +case -7: return "kComponentUnregisterSelect"; +} +return "???"; +} + +static char* component_func_type(int type,int what){ +if(type==1) switch(what){ +case 0: return "kImageCodecGetCodecInfoSelect"; +case 1: return "kImageCodecGetCompressionTimeSelect"; +case 5: return "kImageCodecPreDecompressSelect"; +case 6: return "kImageCodecBandDecompressSelect"; +case 0x12: return "kImageCodecDisposeMemorySelect"; +case 0x10: return "kImageCodecIsImageDescriptionEquivalentSelect"; +case 0x14: return "kImageCodecNewImageBufferMemorySelect"; +case 0x28: return "kImageCodecRequestGammaLevelSelect"; +} +return "???"; +} + + +static int c_level=0; + +static int dump_component(char* name,int type,void* _orig, ComponentParameters *params,void** glob){ + int ( *orig)(ComponentParameters *params, void** glob) = _orig; + int ret,i; + + if(params->what<0) + fprintf(stderr,"%*sComponentCall: %s flags=0x%X size=%d what=%d %s\n",3*c_level,"",name,params->flags, params->paramSize, params->what, component_func(params->what)); + else + 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_type(type,params->what)); + + for(i=0;iparamSize/4;i++) + fprintf(stderr,"%*s param[%d] = 0x%X\n",3*c_level,"",i,params->params[i]); + + ++c_level; + ret=orig(params,glob); + --c_level; + + if(ret>=0x1000) + fprintf(stderr,"%*s return=0x%X\n",3*c_level,"",ret); + else + fprintf(stderr,"%*s return=%d\n",3*c_level,"",ret); + return ret; +} + +#define DECL_COMPONENT(sname,name,type) \ + static void* real_ ## sname = NULL; \ + static int fake_ ## sname(ComponentParameters *params,void** glob){ \ + return dump_component(name,type,real_ ## sname, params, glob); \ + } + +#include "qt_comp.h" + +#undef DECL_COMPONENT + +#include "qt_fv.h" + +#endif + +#ifdef EMU_QTX_API + +static u_int32_t ret_array[4096]; +static int ret_i=0; + +static int report_func(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags) +{ +#ifdef DEBUG_QTX_API + int i; + int* dptr; + void* pwrapper=NULL; + void* pptr=NULL; + char* pname=NULL; + int plen=-1; + // find the code: + + dptr=0x62b67ae0;dptr+=2*((reg->eax>>16)&255); +// printf("FUNC: flag=%d ptr=%p\n",dptr[0],dptr[1]); + if(dptr[0]&255){ + dptr=dptr[1];dptr+=4*(reg->eax&65535); +// printf("FUNC: ptr2=%p eax=%p edx=%p\n",dptr[1],dptr[0],dptr[2]); + pwrapper=dptr[1]; pptr=dptr[0]; plen=dptr[2]; + } else { + pwrapper=0x62924910; + switch(dptr[1]){ + case 0x629248d0: + dptr=0x62b672c0;dptr+=2*(reg->eax&65535); +// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]); + pptr=dptr[0]; plen=dptr[1]; + break; + case 0x62924e40: + dptr=0x62b67c70;dptr+=2*(reg->eax&65535); +// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]); + pptr=dptr[0]; plen=dptr[1]; + break; + case 0x62924e60: + dptr=0x62b68108;if(reg->eax&0x8000) dptr+=2*(reg->eax|0xffff0000); else dptr+=2*(reg->eax&65535); +// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]); + pptr=dptr[0]; plen=dptr[1]; + break; + case 0x62924e80: + dptr=0x62b68108;if(reg->eax&0x8000) dptr+=2*(reg->eax|0xffff0000); else dptr+=2*(reg->eax&65535); +// printf("FUNC: ptr2=%p eax=%p edx=%p\n",0x62924910,dptr[0],dptr[1]); + pptr=dptr[0]; plen=dptr[1]; + break; + default: + printf("FUNC: unknown ptr & psize!\n"); + pwrapper=dptr[1]; + } + } + + for(i=0;qt_fv_list[i].name;i++){ + if(qt_fv_list[i].id==reg->eax){ + pname=qt_fv_list[i].name; + break; + } + } + + printf("FUNC[%X/%s]: wrapper=%p func=%p len=%d\n",reg->eax, + pname?pname:"???",pwrapper,pptr,plen); + + printf("FUNC: caller=%p ebx=%p\n",((u_int32_t *)stack_base)[0],reg->ebx); + + if(pname) + printf("%*sENTER(%d): %s(",ret_i*2,"",ret_i,pname); + else + printf("%*sENTER(%d): %X(",ret_i*2,"",ret_i,reg->eax); + for (i=0;i=0x20 && fcc[0]<128 && + fcc[1]>=0x20 && fcc[1]<128 && + fcc[2]>=0x20 && fcc[2]<128 && + fcc[3]>=0x20 && fcc[3]<128) printf("='%c%c%c%c'",fcc[3],fcc[2],fcc[1],fcc[0]); + else if(val>=8 && val<65536) printf("=%d",val); + } + printf(")\n"); + fflush(stdout); + +#endif + +#if 1 + // emulate some functions: + switch(reg->eax){ + // memory management: + case 0x150011: //NewPtrClear + case 0x150012: //NewPtrSysClear + reg->eax=malloc(((u_int32_t *)stack_base)[1]); + memset(reg->eax,0,((u_int32_t *)stack_base)[1]); +#ifdef DEBUG_QTX_API + printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax); +#endif + return 1; + case 0x15000F: //NewPtr + case 0x150010: //NewPtrSys + reg->eax=malloc(((u_int32_t *)stack_base)[1]); +#ifdef DEBUG_QTX_API + printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax); +#endif + return 1; + case 0x15002f: //DisposePtr + if(((u_int32_t *)stack_base)[1]>=0x60000000) + printf("WARNING! Invalid Ptr handle!\n"); + else + free(((u_int32_t *)stack_base)[1]); + reg->eax=0; +#ifdef DEBUG_QTX_API + printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax); +#endif + return 1; + // mutexes: + case 0x1d0033: //QTMLCreateMutex + reg->eax=0xdeadbabe; +#ifdef DEBUG_QTX_API + printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax); +#endif + return 1; + case 0x1d0034: //QTMLDestroyMutex + case 0x1d0035: //QTMLGrabMutex + case 0x1d0036: //QTMLReturnMutex + case 0x1d003d: //QTMLTryGrabMutex + reg->eax=0; +#ifdef DEBUG_QTX_API + printf("%*sLEAVE(%d): EMULATED! 0x%X\n",ret_i*2,"",ret_i, reg->eax); +#endif + return 1; + } +#endif + +#if 0 + switch(reg->eax){ +// case 0x00010000: +// printf("FUNC: ImageCodecInitialize/ImageCodecGetCodecInfo(ci=%p,&icap=%p)\n",((u_int32_t *)stack_base)[1],((u_int32_t *)stack_base)[4]); +// break; + case 0x00010003: + printf("FUNC: CountComponents(&desc=%p)\n",((u_int32_t *)stack_base)[1]); + break; + case 0x00010004: + printf("FUNC: FindNextComponent(prev=%p,&desc=%p)\n",((u_int32_t *)stack_base)[1],((u_int32_t *)stack_base)[2]); + break; + case 0x00010007: + printf("FUNC: OpenComponent(prev=%p)\n",((u_int32_t *)stack_base)[1]); + break; + case 0x0003008b: + printf("FUNC: QTNewGWorldFromPtr(&pts=%p,fourcc=%.4s,&rect=%p,x1=%p,x2=%p,x3=%p,plane=%p,stride=%d)\n", + ((u_int32_t *)stack_base)[1], + &(((u_int32_t *)stack_base)[2]), + ((u_int32_t *)stack_base)[3], + ((u_int32_t *)stack_base)[4], + ((u_int32_t *)stack_base)[5], + ((u_int32_t *)stack_base)[6], + ((u_int32_t *)stack_base)[7], + ((u_int32_t *)stack_base)[8]); + break; + case 0x001c0018: + printf("FUNC: GetGWorldPixMap(gworld=%p)\n",((u_int32_t *)stack_base)[1]); + break; + case 0x00110001: + printf("FUNC: Gestalt(fourcc=%.4s, &ret=%p)\n",&(((u_int32_t *)stack_base)[1]),((u_int32_t *)stack_base)[2]); + break; + default: { + int i; + for(i=0;qt_fv_list[i].name;i++){ + if(qt_fv_list[i].id==reg->eax){ + printf("FUNC: %s\n",qt_fv_list[i].name); + break; + } + } + } + } + + // print stack/reg information + printf("ENTER(%d) stack = %d bytes @ %p\n" + "eax = 0x%08x edx = 0x%08x ebx = 0x%08x ecx = 0x%08x\n" + "esp = 0x%08x ebp = 0x%08x esi = 0x%08x edi = 0x%08x\n" + "flags = 0x%08x\n", ret_i, + stack_size, stack_base, + reg->eax, reg->edx, reg->ebx, reg->ecx, + reg->esp, reg->ebp, reg->esi, reg->edi, + *flags); +#endif + + // save ret addr: + ret_array[ret_i]=((u_int32_t *)stack_base)[0]; + ++ret_i; + +#if 0 + // print first 7 longs in the stack (return address, arg[1], arg[2] ... ) + printf("stack[] = { "); + for (i=0;i<7;i++) { + printf("%08x ", ((u_int32_t *)stack_base)[i]); + } + printf("}\n\n"); +#endif + +// // mess with function parameters +// ((u_int32_t *)stack_base)[1] = 0x66554433; + +// // mess with return address... +// reg->eax = 0x11223344; + return 0; +} + +static int report_func_ret(void *stack_base, int stack_size, reg386_t *reg, u_int32_t *flags) +{ + int i; + short err; + + // restore ret addr: + --ret_i; + ((u_int32_t *)stack_base)[0]=ret_array[ret_i]; + +#ifdef DEBUG_QTX_API + +#if 1 + printf("%*sLEAVE(%d): 0x%X",ret_i*2,"",ret_i, reg->eax); + err=reg->eax; + if(err && (reg->eax>>16)==0) printf(" = %d",err); + printf("\n"); + fflush(stdout); +#else + // print stack/reg information + printf("LEAVE(%d) stack = %d bytes @ %p\n" + "eax = 0x%08x edx = 0x%08x ebx = 0x%08x ecx = 0x%08x\n" + "esp = 0x%08x ebp = 0x%08x esi = 0x%08x edi = 0x%08x\n" + "flags = 0x%08x\n", ret_i, + stack_size, stack_base, + reg->eax, reg->edx, reg->ebx, reg->ecx, + reg->esp, reg->ebp, reg->esi, reg->edi, + *flags); +#endif + +#if 0 + // print first 7 longs in the stack (return address, arg[1], arg[2] ... ) + printf("stack[] = { "); + for (i=0;i<7;i++) { + printf("%08x ", ((u_int32_t *)stack_base)[i]); + } + printf("}\n\n"); +#endif + +#endif + +// // mess with function parameters +// ((u_int32_t *)stack_base)[1] = 0x66554433; + +// // mess with return address... +// reg->eax = 0x11223344; + return 0; +} + +#endif + /*********************************************************************** * MODULE_GetProcAddress (internal) */ @@ -484,10 +846,17 @@ FARPROC MODULE_GetProcAddress( // WINE_MODREF *wm=local_wm; FARPROC retproc; +#ifdef DEBUG_QTX_API if (HIWORD(function)) - TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function); + fprintf(stderr,"XXX GetProcAddress(%08lx,%s)\n",(DWORD)hModule,function); else - TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function); + fprintf(stderr,"XXX GetProcAddress(%08lx,%p)\n",(DWORD)hModule,function); +#endif + +// TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function); +// else +// TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function); + if (!wm) { SetLastError(ERROR_INVALID_HANDLE); return (FARPROC)0; @@ -497,7 +866,7 @@ FARPROC MODULE_GetProcAddress( case MODULE32_PE: retproc = PE_FindExportedFunction( wm, function, snoop ); if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND); - return retproc; + break; #ifdef HAVE_LIBDL case MODULE32_ELF: retproc = (FARPROC) dlsym( (void*) wm->module, function); @@ -509,6 +878,35 @@ FARPROC MODULE_GetProcAddress( SetLastError(ERROR_INVALID_HANDLE); return (FARPROC)0; } + +#ifdef EMU_QTX_API + if (HIWORD(function) && retproc){ + +#ifdef DEBUG_QTX_API +#define DECL_COMPONENT(sname,name,type) \ + if(!strcmp(function,name)){ \ + fprintf(stderr,name "dispatcher catched -> %p\n",retproc); \ + real_ ## sname = retproc; retproc = fake_ ## sname; \ + } +#include "qt_comp.h" +#undef DECL_COMPONENT +#endif + + if(!strcmp(function,"theQuickTimeDispatcher") +// || !strcmp(function,"_CallComponentFunctionWithStorage") +// || !strcmp(function,"_CallComponent") + ){ + fprintf(stderr,"theQuickTimeDispatcher catched -> %p\n",retproc); + report_entry = report_func; + report_ret = report_func_ret; + wrapper_target=retproc; + retproc=wrapper; + } + + } +#endif + + return retproc; } static int acounter = 0; -- cgit v1.2.3