/*
* $Id: d99fa85bf5f85cbfcb922c2c8631d8bbc120e8bf $
*
* Originally distributed under LPGL 2.1 (or later) by the Wine project.
*
* Modified for use with MPlayer, detailed CVS changelog at
* http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
*
* File now distributed as part of VLC media player with no modifications.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*/
/***********************************************************
Win32 emulation code. Functions that emulate
responses from corresponding Win32 API calls.
Since we are not going to be able to load
virtually any DLL, we can only implement this
much, adding needed functions with each new codec.
Basic principle of implementation: it's not good
for DLL to know too much about its environment.
************************************************************/
#include "config.h"
#ifdef MPLAYER
#ifdef USE_QTX_CODECS
#define QTX
#endif
#define REALPLAYER
//#define LOADLIB_TRY_NATIVE
#endif
#ifdef QTX
#define PSEUDO_SCREEN_WIDTH /*640*/800
#define PSEUDO_SCREEN_HEIGHT /*480*/600
#endif
#include "wine/winbase.h"
#include "wine/winreg.h"
#include "wine/winnt.h"
#include "wine/winerror.h"
#include "wine/debugtools.h"
#include "wine/module.h"
#include "wine/winuser.h"
#include <stdio.h>
#include "win32.h"
#include "registry.h"
#include "loader.h"
#include "com.h"
#include "ext.h"
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include <errno.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <time.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/timeb.h>
#ifdef HAVE_KSTAT
#include <kstat.h>
#endif
#if HAVE_VSSCANF
int vsscanf( const char *str, const char *format, va_list ap);
#else
/* system has no vsscanf. try to provide one */
static int vsscanf( const char *str, const char *format, va_list ap)
{
long p1 = va_arg(ap, long);
long p2 = va_arg(ap, long);
long p3 = va_arg(ap, long);
long p4 = va_arg(ap, long);
long p5 = va_arg(ap, long);
return sscanf(str, format, p1, p2, p3, p4, p5);
}
#endif
static char* def_path = WIN32_PATH;
static void do_cpuid(unsigned int ax, unsigned int *regs)
{
__asm__ __volatile__
(
"pushl %%ebx; pushl %%ecx; pushl %%edx;"
".byte 0x0f, 0xa2;"
"movl %%eax, (%2);"
"movl %%ebx, 4(%2);"
"movl %%ecx, 8(%2);"
"movl %%edx, 12(%2);"
"popl %%edx; popl %%ecx; popl %%ebx;"
: "=a" (ax)
: "0" (ax), "S" (regs)
);
}
static unsigned int c_localcount_tsc()
{
int a;
__asm__ __volatile__
(
"rdtsc\n\t"
:"=a"(a)
:
:"edx"
);
return a;
}
static void c_longcount_tsc(long long* z)
{
__asm__ __volatile__
(
"pushl %%ebx\n\t"
"movl %%eax, %%ebx\n\t"
"rdtsc\n\t"
"movl %%eax, 0(%%ebx)\n\t"
"movl %%edx, 4(%%ebx)\n\t"
"popl %%ebx\n\t"
::"a"(z)
:"edx"
);
}
static unsigned int c_localcount_notsc()
{
struct timeval tv;
unsigned limit=~0;
limit/=1000000;
gettimeofday(&tv, 0);
return limit*tv.tv_usec;
}
static void c_longcount_notsc(long long* z)
{
struct timeval tv;
unsigned long long result;
unsigned limit=~0;
if(!z)return;
limit/=1000000;
gettimeofday(&tv, 0);
result=tv.tv_sec;
result<<=32;
result+=limit*tv.tv_usec;
*z=result;
}
static unsigned int localcount_stub(void);
static void longcount_stub(long long*);
static unsigned int (*localcount)()=localcount_stub;
static void (*longcount)(long long*)=longcount_stub;
static pthread_mutex_t memmut;
static unsigned int localcount_stub(void)
{
unsigned int regs[4];
do_cpuid(1, regs);
if ((regs[3] & 0x00000010) != 0)
{
localcount=c_localcount_tsc;
longcount=c_longcount_tsc;
}
else
{
localcount=c_localcount_notsc;
longcount=c_longcount_notsc;
}
return localcount();
}
static void longcount_stub(long long* z)
{
unsigned int regs[4];
do_cpuid(1, regs);
if ((regs[3] & 0x00000010) != 0)
{
localcount=c_localcount_tsc;
longcount=c_longcount_tsc;
}
else
{
localcount=c_localcount_notsc;
longcount=c_longcount_notsc;
}
longcount(z);
}
#ifdef MPLAYER
#include "../mp_msg.h"
#endif
int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
//#define DETAILED_OUT
static inline void dbgprintf(char* fmt, ...)
{
#ifdef DETAILED_OUT
if(LOADER_DEBUG)
{
FILE* f;
va_list va;
va_start(va, fmt);
f=fopen("./log", "a");
vprintf(fmt, va);
fflush(stdout);
if(f)
{
vfprintf(f, fmt, va);
fsync(fileno(f));
fclose(f);
}
va_end(va);
}
#endif
#ifdef MPLAYER
if (verbose > 2)
{
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
// mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
va_end(va);
}
fflush(stdout);
#endif
}
char export_names[300][32]={
"name1",
//"name2",
//"name3"
};
//#define min(x,y) ((x)<(y)?(x):(y))
void destroy_event(void* event);
struct th_list_t;
typedef struct th_list_t{
int id;
void* thread;
struct th_list_t* next;
struct th_list_t* prev;
} th_list;
// have to be cleared by GARBAGE COLLECTOR
static unsigned char* heap=NULL;
static int heap_counter=0;
static tls_t* g_tls=NULL;
static th_list* list=NULL;
static void test_heap(void)
{
int offset=0;
if(heap==0)
return;
while(offset<heap_counter)
{
if(*(int*)(heap+offset)!=0x433476)
{
printf("Heap corruption at address %d\n", offset);
return;
}
offset+=8+*(int*)(heap+offset+4);
}
for(;offset<min(offset+1000, 20000000); offset++)
if(heap[offset]!=0xCC)
{
printf("Free heap corruption at address %d\n", offset);
}
}
#undef MEMORY_DEBUG
#ifdef MEMORY_DEBUG
static void* my_mreq(int size, int to_zero)
{
static int test=0;
test++;
if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
// test_heap();
if(heap==NULL)
{
heap=malloc(20000000);
memset(heap, 0xCC,20000000);
}
if(heap==0)
{
printf("No enough memory\n");
return 0;
}
if(heap_counter+size>20000000)
{
printf("No enough memory\n");
return 0;
}
*(int*)(heap+heap_counter)=0x433476;
heap_counter+=4;
*(int*)(heap+heap_counter)=size;
heap_counter+=4;
printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
if(to_zero)
memset(heap+heap_counter, 0, size);
else
memset(heap+heap_counter, 0xcc, size); // make crash reproducable
heap_counter+=size;
return heap+heap_counter-size;
}
static int my_release(char* memory)
{
// test_heap();
if(memory==NULL)
{
printf("ERROR: free(0)\n");
return 0;
}
if(*(int*)(memory-8)!=0x433476)
{
printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
return 0;
}
printf("Freed %d bytes of memory\n", *(int*)(memory-4));
// memset(memory-8, *(int*)(memory-4), 0xCC);
return 0;
}
#else
#define GARBAGE
typedef struct alloc_header_t alloc_header;
struct alloc_header_t
{
// let's keep allocated data 16 byte aligned
alloc_header* prev;
alloc_header* next;
long deadbeef;
long size;
long type;
long reserved1;
long reserved2;
long reserved3;
};
#ifdef GARBAGE
static alloc_header* last_alloc = NULL;
static int alccnt = 0;
#endif
#define
评论1