1 /* -*-C-*- -------------------------------------------------------------
3 | -------------------------------------------------------------------- |
4 | Purpose: Perl gateway to wine API calls |
6 ----------------------------------------------------------------------*/
22 /* API return type constants */
32 /* max arguments for a function call */
35 extern unsigned long perl_call_wine
40 unsigned int *last_error,
44 /* Thunk type definitions */
65 BYTE arg_types[MAX_ARGS];
69 #error You must implement the callback thunk for your CPU
72 /*--------------------------------------------------------------
73 | This contains most of the machine instructions necessary to
74 | implement the thunk. All the thunk does is turn around and
75 | call function callback_bridge(), which is defined in
78 | The data from this static thunk can just be copied directly
79 | into the thunk allocated dynamically below. That fills in
80 | most of it, but a couple values need to be filled in after
81 | the allocation, at run time:
83 | 1) The pointer to the thunk's data area, which we
84 | don't know yet, because we haven't allocated it
87 | 2) The address of the function to call. We know the
88 | address of the function [callback_bridge()], but
89 | the value filled into the thunk is an address
90 | relative to the thunk itself, so we can't fill it
91 | in until we've allocated the actual thunk.
92 --------------------------------------------------------------*/
93 static const struct thunk thunk_template =
95 /* pushl %ebp */ 0x55,
96 /* movl %esp,%ebp */ { 0x89, 0xe5 },
97 /* leal 8(%ebp),%edx */ { 0x8d, 0x55, 0x08 },
98 /* pushl %edx */ 0x52,
99 /* pushl (data addr) */ 0x68, NULL,
100 /* pushl (nb_args) */ 0x6a, 0,
101 /* pushl (code ref) */ 0x68, NULL,
102 /* call (func) */ 0xe8, NULL,
104 /* ret $arg_size */ 0xc2, 0,
105 /* arg_types */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
109 /*----------------------------------------------------------------------
110 | Function: convert_value |
111 | -------------------------------------------------------------------- |
112 | Purpose: Convert a C value to a Perl value |
114 | Parameters: type -- constant specifying type of value |
115 | val -- value to convert |
117 | Returns: Perl SV * |
118 ----------------------------------------------------------------------*/
119 static SV *convert_value( enum ret_type type, unsigned long val )
123 case RET_VOID: return &PL_sv_undef;
124 case RET_INT: return sv_2mortal( newSViv ((int) val ));
125 case RET_WORD: return sv_2mortal( newSViv ((int) val & 0xffff ));
126 case RET_PTR: return sv_2mortal( newSViv ((int) val ));
127 case RET_STR: return sv_2mortal( newSVpv ((char *) val, 0 ));
129 croak ("Bad return type %d", type);
134 /*----------------------------------------------------------------------
135 | Function: callback_bridge |
136 | -------------------------------------------------------------------- |
137 | Purpose: Central pass-through point for Wine API callbacks |
139 | Wine API callback thunks are set up so that they call this |
140 | function, which turns around and calls the user's declared |
141 | Perl callback sub. |
143 | Parameters: data -- pointer to thunk data area |
144 | args -- array of args passed from Wine API to callback |
146 | Returns: Whatever the Perl sub returns |
147 ----------------------------------------------------------------------*/
148 static int callback_bridge( SV *callback_ref, int nb_args, BYTE arg_types[], unsigned long args[] )
156 /* Perl/C interface voodoo */
162 /* Push args on stack, according to type */
163 for (i = 0; i < nb_args; i++)
165 sv = convert_value (arg_types[i], args[i]);
171 n = perl_call_sv (callback_ref, G_SCALAR);
173 /* Nab return value */
183 /* [todo] Pass through Perl sub return value */
188 /*----------------------------------------------------------------------
192 ----------------------------------------------------------------------*/
193 MODULE = wine PACKAGE = wine
196 # --------------------------------------------------------------------
197 # Function: call_wine_API
198 # --------------------------------------------------------------------
199 # Purpose: Call perl_call_wine(), which calls a wine API function
201 # Parameters: function -- API function to call
202 # ret_type -- return type
203 # debug -- debug flag
204 # ... -- args to pass to API function
206 # Returns: list containing 2 elements: the last error code and the
207 # value returned by the API function
208 # --------------------------------------------------------------------
210 call_wine_API(function, ret_type, debug, ...)
211 unsigned long function;
218 /*--------------------------------------------------------------
219 | Begin call_wine_API
220 --------------------------------------------------------------*/
231 int n_args = (items - n_fixed);
232 struct arg args[MAX_ARGS+1];
233 unsigned long f_args[MAX_ARGS+1];
235 unsigned int last_error = 0xdeadbeef;
240 if (n_args > MAX_ARGS) croak("Too many arguments");
242 /*--------------------------------------------------------------
243 | Prepare function args
244 --------------------------------------------------------------*/
247 fprintf( stderr, " [wine.xs/call_wine_API()]\n");
249 for (i = 0; (i < n_args); i++)
251 sv = ST (n_fixed + i);
257 /*--------------------------------------------------------------
259 --------------------------------------------------------------*/
264 /*--------------------------------------------------------------
265 | Integer ref -- pass address of value
266 --------------------------------------------------------------*/
269 args[i].ival = SvIV (sv);
270 f_args[i] = (unsigned long) &(args[i].ival);
273 fprintf( stderr, " [RV->IV] 0x%lx\n", f_args[i]);
277 /*--------------------------------------------------------------
278 | Number ref -- convert and pass address of value
279 --------------------------------------------------------------*/
282 args[i].ival = (unsigned long) SvNV (sv);
283 f_args[i] = (unsigned long) &(args[i].ival);
286 fprintf( stderr, " [RV->NV] 0x%lx\n", f_args[i]);
290 /*--------------------------------------------------------------
291 | String ref -- pass pointer
292 --------------------------------------------------------------*/
295 f_args[i] = (unsigned long) ((char *) SvPV (sv, PL_na));
298 fprintf( stderr, " [RV->PV] 0x%lx\n", f_args[i]);
303 /*--------------------------------------------------------------
305 --------------------------------------------------------------*/
309 /*--------------------------------------------------------------
310 | Integer -- pass value
311 --------------------------------------------------------------*/
314 f_args[i] = (unsigned long) SvIV (sv);
317 fprintf( stderr, " [IV] %ld (0x%lx)\n", f_args[i], f_args[i]);
321 /*--------------------------------------------------------------
322 | Number -- convert and pass value
323 --------------------------------------------------------------*/
326 f_args[i] = (unsigned long) SvNV (sv);
329 fprintf( stderr, " [NV] %ld (0x%lx)\n", f_args[i], f_args[i]);
333 /*--------------------------------------------------------------
334 | String -- pass pointer to copy
335 --------------------------------------------------------------*/
339 if ((args[i].pval = malloc( n+2 )))
341 memcpy (args[i].pval, p, n);
342 ((char *)(args[i].pval))[n] = 0; /* add final NULL */
343 ((char *)(args[i].pval))[n+1] = 0; /* and another one for Unicode too */
344 f_args[i] = (unsigned long) args[i].pval;
347 fprintf( stderr, " [PV] 0x%lx\n", f_args[i]);
355 /*--------------------------------------------------------------
357 --------------------------------------------------------------*/
358 r = perl_call_wine( (FARPROC)function, n_args, f_args, &last_error, debug );
360 /*--------------------------------------------------------------
361 | Handle modified parameter values
363 | There are four possibilities for parameter values:
367 | 3) ref to integer value
368 | 4) ref to string value
370 | In cases 1 and 2, the intent is that the values won't be
371 | modified, because they're not passed by ref. So we leave
374 | In case 4, the address of the actual string buffer has
375 | already been passed to the wine API function, which had
376 | opportunity to modify it if it wanted to. So again, we
377 | don't have anything to do here.
379 | The case we need to handle is case 3. For integers passed
380 | by ref, we created a local containing the initial value,
381 | and passed its address to the wine API function, which
382 | (potentially) modified it. Now we have to copy the
383 | (potentially) new value back to the Perl variable passed
384 | in, using sv_setiv(). (Which will take fewer lines of code
385 | to do than it took lines of comment to describe ...)
386 --------------------------------------------------------------*/
387 for (i = 0; (i < n_args); i++)
389 sv = ST (n_fixed + i);
392 if (SvROK (sv) && (sv = SvRV (sv)) && SvIOK (sv))
394 sv_setiv (sv, args[i].ival);
398 /*--------------------------------------------------------------
399 | Put appropriate return value on the stack for Perl to pick
401 --------------------------------------------------------------*/
403 if (last_error != 0xdeadbeef) PUSHs(sv_2mortal(newSViv(last_error)));
404 else PUSHs( &PL_sv_undef );
405 PUSHs (convert_value (ret_type, r));
407 /*--------------------------------------------------------------
408 | Free up allocated memory
409 --------------------------------------------------------------*/
410 for (i = 0; (i < n_args); i++)
412 if (args[i].pval) free(args[i].pval);
416 # --------------------------------------------------------------------
417 # Function: load_library
418 # --------------------------------------------------------------------
419 # Purpose: Load a Wine library
421 # Parameters: module -- module (dll) to load
423 # Returns: module handle
424 # --------------------------------------------------------------------
431 ST(0) = newSViv( (I32)LoadLibraryA(module) );
435 # --------------------------------------------------------------------
436 # Function: get_proc_address
437 # --------------------------------------------------------------------
438 # Purpose: Retrive a function address
440 # Parameters: module -- module handle
441 # --------------------------------------------------------------------
443 get_proc_address(module,func)
444 unsigned long module;
449 ST(0) = newSViv( (I32)GetProcAddress( (HMODULE)module, func ) );
453 # --------------------------------------------------------------------
454 # Function: alloc_thunk
455 # --------------------------------------------------------------------
456 # Purpose: Allocate a thunk for a wine API callback
458 # This is used when a Wine API function is called from Perl, and
459 # that API function takes a callback as one of its parameters.
461 # The Wine API function, of course, must be passed the address of
462 # a C function as the callback. But if the API is called from Perl,
463 # we want the user to be able to specify a Perl sub as the callback,
464 # and have control returned there each time the callback is called.
466 # This function takes a code ref to a Perl sub as one of its
467 # arguments. It then creates a unique C function (a thunk) on the
468 # fly, which can be passed to the Wine API function as its callback.
470 # The thunk has its own data area (as thunks are wont to do); one
471 # of the things stashed there is aforementioned Perl code ref. So
472 # the sequence of events is as follows:
474 # 1) From Perl, user calls alloc_callback(), passing a ref
475 # to a Perl sub to use as the callback.
477 # 2) alloc_callback() calls this routine. This routine
478 # creates a thunk, and stashes the above code ref in
479 # it. This function then returns a pointer to the thunk
482 # 3) From Perl, user calls Wine API function. As the parameter
483 # which is supposed to be the address of the callback, the
484 # user passes the pointer to the thunk allocated above.
486 # 4) The Wine API function gets called. It periodically calls
487 # the callback, which executes the thunk.
489 # 5) Each time the thunk is executed, it calls callback_bridge()
490 # (defined in winetest.c).
492 # 6) callback_bridge() fishes the Perl code ref out of the
493 # thunk data area and calls the Perl callback.
495 # Voila. The Perl callback gets called each time the Wine API
496 # function calls its callback.
498 # Parameters: [todo] Parameters ...
500 # Returns: Pointer to thunk
501 # --------------------------------------------------------------------
511 /* Allocate the thunk */
512 if (!(thunk = malloc( sizeof(*thunk) ))) croak( "Out of memory" );
514 (*thunk) = thunk_template;
515 thunk->args_ptr = thunk->arg_types;
516 thunk->nb_args = items - 1;
517 thunk->code_ref = SvRV (ST (0));
518 thunk->func = (void *)((char *) callback_bridge - (char *) &thunk->leave);
519 thunk->arg_size = thunk->nb_args * sizeof(int);
521 /* Stash callback arg types */
522 for (i = 1; i < items; i++) thunk->arg_types[i - 1] = SvIV (ST (i));
524 /*--------------------------------------------------------------
525 | Push the address of the thunk on the stack for return
527 | [todo] We need to free up the memory allocated somehow ...
528 --------------------------------------------------------------*/
529 ST (0) = newSViv ((I32) thunk);