| /* | |
| * Perl interpreter for running Wine tests | |
| * | |
| * Copyright 2001 John F Sturtz for Codeweavers | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library 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 | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include <assert.h> | |
| #include <stdio.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include <EXTERN.h> | |
| #include <perl.h> | |
| static FARPROC pGetLastError; | |
| /*---------------------------------------------------------------------- | |
| | Function: call_wine_func | | |
| | -------------------------------------------------------------------- | | |
| | Purpose: Call a wine API function, passing in appropriate number | | |
| | of args | | |
| | | | |
| | Parameters: proc -- function to call | | |
| | n_args -- array of args | | |
| | a -- array of args | | |
| | | | |
| | Returns: return value from API function called | | |
| ----------------------------------------------------------------------*/ | |
| static unsigned long call_wine_func | |
| ( | |
| FARPROC proc, | |
| int n_args, | |
| unsigned long *a | |
| ) | |
| { | |
| /* Locals */ | |
| unsigned long rc; | |
| /* Begin call_wine_func */ | |
| /*-------------------------------------------------------------- | |
| | Now we need to call the function with the appropriate number | |
| | of arguments | |
| | | |
| | Anyone who can think of a better way to do this is welcome to | |
| | come forth with it ... | |
| --------------------------------------------------------------*/ | |
| switch (n_args) | |
| { | |
| case 0: rc = proc (); break; | |
| case 1: rc = proc (a[0]); break; | |
| case 2: rc = proc (a[0], a[1]); break; | |
| case 3: rc = proc (a[0], a[1], a[2]); break; | |
| case 4: rc = proc (a[0], a[1], a[2], a[3]); break; | |
| case 5: rc = proc (a[0], a[1], a[2], a[3], a[4]); break; | |
| case 6: rc = proc (a[0], a[1], a[2], a[3], a[4], a[5]); break; | |
| case 7: rc = proc (a[0], a[1], a[2], a[3], a[4], a[5], a[6]); break; | |
| case 8: rc = proc (a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break; | |
| case 9: rc = proc (a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); break; | |
| case 10: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9] ); break; | |
| case 11: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9], a[10] ); break; | |
| case 12: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9], a[10], a[11] ); break; | |
| case 13: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9], a[10], a[11], a[12] ); break; | |
| case 14: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9], a[10], a[11], a[12], a[13] ); break; | |
| case 15: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9], a[10], a[11], a[12], a[13], a[14] ); break; | |
| case 16: rc = proc( a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], | |
| a[9], a[10], a[11], a[12], a[13], a[14], a[15] ); break; | |
| default: | |
| fprintf( stderr, "%d args not supported\n", n_args ); | |
| rc = 0; | |
| break; | |
| } | |
| /*-------------------------------------------------------------- | |
| | Return value from func | |
| --------------------------------------------------------------*/ | |
| return (rc); | |
| } | |
| /*---------------------------------------------------------------------- | |
| | Function: perl_call_wine | |
| | -------------------------------------------------------------------- | |
| | Purpose: Fetch and call a wine API function from a library | |
| | | |
| | Parameters: | |
| | | |
| | proc -- function address | |
| | n_args -- number of args | |
| | args -- args | |
| | last_error -- returns the last error code | |
| | debug -- debug flag | |
| | | |
| | Returns: Return value from API function called | |
| ----------------------------------------------------------------------*/ | |
| unsigned long perl_call_wine | |
| ( | |
| FARPROC proc, | |
| int n_args, | |
| unsigned long *args, | |
| unsigned int *last_error, | |
| int debug | |
| ) | |
| { | |
| unsigned long ret; | |
| DWORD error, old_error; | |
| if (debug > 1) | |
| { | |
| int i; | |
| fprintf(stderr," perl_call_wine(func=%p", proc); | |
| for (i = 0; i < n_args; i++) fprintf( stderr, ",0x%lx", args[i] ); | |
| fprintf( stderr, ")\n" ); | |
| } | |
| /* special case to allow testing GetLastError without messing up the last error code */ | |
| if (proc == pGetLastError) | |
| ret = call_wine_func (proc, n_args, args); | |
| else | |
| { | |
| old_error = GetLastError(); | |
| SetLastError( 0xdeadbeef ); | |
| ret = call_wine_func (proc, n_args, args); | |
| error = GetLastError(); | |
| if (error != 0xdeadbeef) *last_error = error; | |
| else SetLastError( old_error ); | |
| } | |
| return ret; | |
| } | |
| /* perl extension initialisation */ | |
| static void xs_init(pTHX) | |
| { | |
| extern void boot_wine(CV *cv); | |
| newXS("wine::bootstrap", boot_wine,__FILE__); | |
| } | |
| /* main function */ | |
| int main( int argc, char **argv, char **envp ) | |
| { | |
| PerlInterpreter *perl; | |
| int status; | |
| envp = environ; /* envp is not valid (yet) in Winelib */ | |
| pGetLastError = GetProcAddress( GetModuleHandleA("kernel32"), "GetLastError" ); | |
| assert( pGetLastError ); | |
| if (!(perl = perl_alloc ())) | |
| { | |
| fprintf( stderr, "Could not allocate perl interpreter\n" ); | |
| exit(1); | |
| } | |
| perl_construct (perl); | |
| status = perl_parse( perl, xs_init, argc, argv, envp ); | |
| if (!status) status = perl_run(perl); | |
| perl_destruct (perl); | |
| perl_free (perl); | |
| exit( status ); | |
| } |