1 /* -*-C-*- --------------------------------------------------------------------
3 | ---------------------------------------------------------------------------- |
4 | Purpose: Perl gateway to wine API calls |
6 ------------------------------------------------------------------------------*/
18 /* API return type constants */
27 /* max arguments for a function call */
30 extern unsigned long perl_call_wine
35 unsigned int *last_error,
39 /* Thunk type definitions */
60 BYTE arg_types[MAX_ARGS];
64 #error You must implement the callback thunk for your CPU
67 /*--------------------------------------------------------------
68 | This contains most of the machine instructions necessary to
69 | implement the thunk. All the thunk does is turn around and
70 | call function callback_bridge(), which is defined in
73 | The data from this static thunk can just be copied directly
74 | into the thunk allocated dynamically below. That fills in
75 | most of it, but a couple values need to be filled in after
76 | the allocation, at run time:
78 | 1) The pointer to the thunk's data area, which we
79 | don't know yet, because we haven't allocated it
82 | 2) The address of the function to call. We know the
83 | address of the function [callback_bridge()], but
84 | the value filled into the thunk is an address
85 | relative to the thunk itself, so we can't fill it
86 | in until we've allocated the actual thunk.
87 --------------------------------------------------------------*/
88 static const struct thunk thunk_template =
90 /* pushl %ebp */ 0x55,
91 /* movl %esp,%ebp */ { 0x89, 0xe5 },
92 /* leal 8(%ebp),%edx */ { 0x8d, 0x55, 0x08 },
93 /* pushl %edx */ 0x52,
94 /* pushl (data addr) */ 0x68, NULL,
95 /* pushl (nb_args) */ 0x6a, 0,
96 /* pushl (code ref) */ 0x68, NULL,
97 /* call (func) */ 0xe8, NULL,
99 /* ret $arg_size */ 0xc2, 0,
100 /* arg_types */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
104 /*----------------------------------------------------------------------
105 | Function: convert_value |
106 | -------------------------------------------------------------------- |
107 | Purpose: Convert a C value to a Perl value |
109 | Parameters: type -- constant specifying type of value |
110 | val -- value to convert |
112 | Returns: Perl SV * |
113 ----------------------------------------------------------------------*/
114 static SV *convert_value( enum ret_type type, unsigned long val )
118 case RET_VOID: return &PL_sv_undef;
119 case RET_INT: return sv_2mortal( newSViv ((int) val ));
120 case RET_WORD: return sv_2mortal( newSViv ((int) val & 0xffff ));
121 case RET_PTR: return sv_2mortal( newSVpv ((char *) val, 0 ));
124 croak ("Bad return type %d", type);
130 /*----------------------------------------------------------------------
131 | Function: callback_bridge |
132 | -------------------------------------------------------------------- |
133 | Purpose: Central pass-through point for Wine API callbacks |
135 | Wine API callback thunks are set up so that they call this |
136 | function, which turns around and calls the user's declared |
137 | Perl callback sub. |
139 | Parameters: data -- pointer to thunk data area |
140 | args -- array of args passed from Wine API to callback |
142 | Returns: Whatever the Perl sub returns |
143 ----------------------------------------------------------------------*/
144 static int callback_bridge( SV *callback_ref, int nb_args, BYTE arg_types[], unsigned long args[] )
152 /* Perl/C interface voodoo */
158 /* Push args on stack, according to type */
159 for (i = 0; i < nb_args; i++)
161 sv = convert_value (arg_types[i], args[i]);
167 n = perl_call_sv (callback_ref, G_SCALAR);
169 /* Nab return value */
179 /* [todo] Pass through Perl sub return value */
184 /*----------------------------------------------------------------------
188 ----------------------------------------------------------------------*/
189 MODULE = wine PACKAGE = wine
192 # --------------------------------------------------------------------
193 # Function: call_wine_API
194 # --------------------------------------------------------------------
195 # Purpose: Call perl_call_wine(), which calls a wine API function
197 # Parameters: function -- API function to call
198 # ret_type -- return type
199 # debug -- debug flag
200 # ... -- args to pass to API function
202 # Returns: list containing 2 elements: the last error code and the
203 # value returned by the API function
204 # --------------------------------------------------------------------
206 call_wine_API(function, ret_type, debug, ...)
207 unsigned long function;
214 /*--------------------------------------------------------------
215 | Begin call_wine_API
216 --------------------------------------------------------------*/
227 int n_args = (items - n_fixed);
228 struct arg args[MAX_ARGS+1];
229 unsigned long f_args[MAX_ARGS+1];
231 unsigned int last_error = 0xdeadbeef;
236 if (n_args > MAX_ARGS) croak("Too many arguments");
238 /*--------------------------------------------------------------
239 | Prepare function args
240 --------------------------------------------------------------*/
243 fprintf( stderr, " [wine.xs/call_wine_API()]\n");
245 for (i = 0; (i < n_args); i++)
247 sv = ST (n_fixed + i);
253 /*--------------------------------------------------------------
255 --------------------------------------------------------------*/
260 /*--------------------------------------------------------------
261 | Integer ref -- pass address of value
262 --------------------------------------------------------------*/
265 args[i].ival = SvIV (sv);
266 f_args[i] = (unsigned long) &(args[i].ival);
269 fprintf( stderr, " [RV->IV] 0x%lx\n", f_args[i]);
273 /*--------------------------------------------------------------
274 | Number ref -- convert and pass address of value
275 --------------------------------------------------------------*/
278 args[i].ival = (unsigned long) SvNV (sv);
279 f_args[i] = (unsigned long) &(args[i].ival);
282 fprintf( stderr, " [RV->NV] 0x%lx\n", f_args[i]);
286 /*--------------------------------------------------------------
287 | String ref -- pass pointer
288 --------------------------------------------------------------*/
291 f_args[i] = (unsigned long) ((char *) SvPV (sv, PL_na));
294 fprintf( stderr, " [RV->PV] 0x%lx\n", f_args[i]);
299 /*--------------------------------------------------------------
301 --------------------------------------------------------------*/
305 /*--------------------------------------------------------------
306 | Integer -- pass value
307 --------------------------------------------------------------*/
310 f_args[i] = (unsigned long) SvIV (sv);
313 fprintf( stderr, " [IV] %ld (0x%lx)\n", f_args[i], f_args[i]);
317 /*--------------------------------------------------------------
318 | Number -- convert and pass value
319 --------------------------------------------------------------*/
322 f_args[i] = (unsigned long) SvNV (sv);
325 fprintf( stderr, " [NV] %ld (0x%lx)\n", f_args[i], f_args[i]);
329 /*--------------------------------------------------------------
330 | String -- pass pointer to copy
331 --------------------------------------------------------------*/
335 if ((args[i].pval = malloc( n+2 )))
337 memcpy (args[i].pval, p, n);
338 ((char *)(args[i].pval))[n] = 0; /* add final NULL */
339 ((char *)(args[i].pval))[n+1] = 0; /* and another one for Unicode too */
340 f_args[i] = (unsigned long) args[i].pval;
343 fprintf( stderr, " [PV] 0x%lx\n", f_args[i]);
351 /*--------------------------------------------------------------
353 --------------------------------------------------------------*/
354 r = perl_call_wine( (FARPROC)function, n_args, f_args, &last_error, debug );
356 /*--------------------------------------------------------------
357 | Handle modified parameter values
359 | There are four possibilities for parameter values:
363 | 3) ref to integer value
364 | 4) ref to string value
366 | In cases 1 and 2, the intent is that the values won't be
367 | modified, because they're not passed by ref. So we leave
370 | In case 4, the address of the actual string buffer has
371 | already been passed to the wine API function, which had
372 | opportunity to modify it if it wanted to. So again, we
373 | don't have anything to do here.
375 | The case we need to handle is case 3. For integers passed
376 | by ref, we created a local containing the initial value,
377 | and passed its address to the wine API function, which
378 | (potentially) modified it. Now we have to copy the
379 | (potentially) new value back to the Perl variable passed
380 | in, using sv_setiv(). (Which will take fewer lines of code
381 | to do than it took lines of comment to describe ...)
382 --------------------------------------------------------------*/
383 for (i = 0; (i < n_args); i++)
385 sv = ST (n_fixed + i);
388 if (SvROK (sv) && (sv = SvRV (sv)) && SvIOK (sv))
390 sv_setiv (sv, args[i].ival);
394 /*--------------------------------------------------------------
395 | Put appropriate return value on the stack for Perl to pick
397 --------------------------------------------------------------*/
399 if (last_error != 0xdeadbeef) PUSHs(sv_2mortal(newSViv(last_error)));
400 else PUSHs( &PL_sv_undef );
401 PUSHs (convert_value (ret_type, r));
403 /*--------------------------------------------------------------
404 | Free up allocated memory
405 --------------------------------------------------------------*/
406 for (i = 0; (i < n_args); i++)
408 if (args[i].pval) free(args[i].pval);
412 # --------------------------------------------------------------------
413 # Function: load_library
414 # --------------------------------------------------------------------
415 # Purpose: Load a Wine library
417 # Parameters: module -- module (dll) to load
419 # Returns: module handle
420 # --------------------------------------------------------------------
427 ST(0) = newSViv( (I32)LoadLibraryA(module) );
431 # --------------------------------------------------------------------
432 # Function: get_proc_address
433 # --------------------------------------------------------------------
434 # Purpose: Retrive a function address
436 # Parameters: module -- module handle
437 # --------------------------------------------------------------------
439 get_proc_address(module,func)
440 unsigned long module;
445 ST(0) = newSViv( (I32)GetProcAddress( (HMODULE)module, func ) );
449 # --------------------------------------------------------------------
450 # Function: alloc_thunk
451 # --------------------------------------------------------------------
452 # Purpose: Allocate a thunk for a wine API callback
454 # This is used when a Wine API function is called from Perl, and
455 # that API function takes a callback as one of its parameters.
457 # The Wine API function, of course, must be passed the address of
458 # a C function as the callback. But if the API is called from Perl,
459 # we want the user to be able to specify a Perl sub as the callback,
460 # and have control returned there each time the callback is called.
462 # This function takes a code ref to a Perl sub as one of its
463 # arguments. It then creates a unique C function (a thunk) on the
464 # fly, which can be passed to the Wine API function as its callback.
466 # The thunk has its own data area (as thunks are wont to do); one
467 # of the things stashed there is aforementioned Perl code ref. So
468 # the sequence of events is as follows:
470 # 1) From Perl, user calls alloc_callback(), passing a ref
471 # to a Perl sub to use as the callback.
473 # 2) alloc_callback() calls this routine. This routine
474 # creates a thunk, and stashes the above code ref in
475 # it. This function then returns a pointer to the thunk
478 # 3) From Perl, user calls Wine API function. As the parameter
479 # which is supposed to be the address of the callback, the
480 # user passes the pointer to the thunk allocated above.
482 # 4) The Wine API function gets called. It periodically calls
483 # the callback, which executes the thunk.
485 # 5) Each time the thunk is executed, it calls callback_bridge()
486 # (defined in winetest.c).
488 # 6) callback_bridge() fishes the Perl code ref out of the
489 # thunk data area and calls the Perl callback.
491 # Voila. The Perl callback gets called each time the Wine API
492 # function calls its callback.
494 # Parameters: [todo] Parameters ...
496 # Returns: Pointer to thunk
497 # --------------------------------------------------------------------
507 /* Allocate the thunk */
508 if (!(thunk = malloc( sizeof(*thunk) ))) croak( "Out of memory" );
510 (*thunk) = thunk_template;
511 thunk->args_ptr = thunk->arg_types;
512 thunk->nb_args = items - 1;
513 thunk->code_ref = SvRV (ST (0));
514 thunk->func = (void *)((char *) callback_bridge - (char *) &thunk->leave);
515 thunk->arg_size = thunk->nb_args * sizeof(int);
517 /* Stash callback arg types */
518 for (i = 1; i < items; i++) thunk->arg_types[i - 1] = SvIV (ST (i));
520 /*--------------------------------------------------------------
521 | Push the address of the thunk on the stack for return
523 | [todo] We need to free up the memory allocated somehow ...
524 --------------------------------------------------------------*/
525 ST (0) = newSViv ((I32) thunk);