1 # --------------------------------------------------------------------
4 # Purpose: Module to supply wrapper around and support for gateway to
5 # Windows API functions
7 # Copyright 2001 John F Sturtz for Codeweavers
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public
11 # License as published by the Free Software Foundation; either
12 # version 2.1 of the License, or (at your option) any later version.
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # Lesser General Public License for more details.
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with this library; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 # --------------------------------------------------------------------
27 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD
28 %return_types %prototypes %loaded_modules);
34 # Items to export into callers namespace by default. Note: do not export
35 # names by default without a very good reason. Use EXPORT_OK instead.
36 # Do not simply export all your public functions/methods/constants.
43 bootstrap wine $VERSION;
47 $wine::debug = defined($ENV{WINETEST_DEBUG}) ? $ENV{WINETEST_DEBUG} : 1;
52 # --------------------------------------------------------------
53 # | Return-type constants |
55 # | [todo] I think there's a way to define these in a C |
56 # | header file, so that both the C functions in the |
57 # | XS module and the Perl routines in the .pm have |
58 # | access to them. But I haven't worked it out |
60 # --------------------------------------------------------------
63 "int" => 1, "long" => 1,
66 "str" => 4, "wstr" => 4
70 # ------------------------------------------------------------------------
72 # | -------------------------------------------------------------------- |
73 # | Purpose: Used to catch calls to undefined routines |
75 # | Any routine which is called and not defined is assumed to be |
76 # | a call to the Wine API function of the same name. We trans- |
77 # | late it into a call to the call() subroutine, with FUNCTION |
78 # | set to the function invoked and all other args passed thru. |
79 # ------------------------------------------------------------------------
82 # --------------------------------------------------------------
83 # | Figure out who we are |
84 # --------------------------------------------------------------
85 my ($pkg, $func) = (split /::/, $AUTOLOAD)[0,1];
87 # --------------------------------------------------------------
88 # | Any function that is in the @EXPORT array is passed thru |
89 # | to AutoLoader to pick up the appropriate XS extension |
90 # --------------------------------------------------------------
91 if (grep ($_ eq $func, @EXPORT))
93 $AutoLoader::AUTOLOAD = $AUTOLOAD;
94 goto &AutoLoader::AUTOLOAD;
97 # --------------------------------------------------------------
99 # --------------------------------------------------------------
101 if ($func eq 'DESTROY');
103 # --------------------------------------------------------------
104 # | Otherwise, assume any undefined method is the name of a |
105 # | wine API call, and all the args are to be passed through |
106 # --------------------------------------------------------------
107 if (defined($prototypes{$func}))
109 return call( $func, @_ );
111 die "Function '$func' not declared";
116 # ------------------------------------------------------------------------
118 # | -------------------------------------------------------------------- |
119 # | Purpose: Call a wine API function |
121 # | Usage: call FUNCTION, [ARGS ...]
123 # | Returns: value returned by API function called |
124 # ------------------------------------------------------------------------
127 my ($function,@args) = @_;
128 my ($module,$funcptr,$ret_type,$arg_types) = @{$prototypes{$function}};
132 my $handle = $loaded_modules{$module};
133 $funcptr = get_proc_address( $handle, $function ) or die "Could not get address for $module.$function";
134 ${$prototypes{$function}}[1] = $funcptr;
137 if ($wine::debug > 1)
139 print STDERR "==== Call $function(";
142 print STDERR " ", +(ref () ? ("(" . ${$_} . ")") : "$_");
144 print STDERR " " if (scalar @args);
148 # Check and translate args before call
150 if (defined($arg_types)) {
151 my @arg_types = @$arg_types;
153 if($#args != $#arg_types) {
154 die "$function: Wrong number of arguments, expected " .
155 ($#arg_types + 1) . ", got " . ($#args + 1) . "\n";
158 while (defined(my $arg = shift @args) &&
159 defined(my $arg_type = shift @arg_types))
161 if($arg_type == 1 || $arg_type == 2) { # int || word
170 # Now call call_wine_API(), which will turn around and call
171 # the appropriate wine API function.
172 my ($err,$r) = call_wine_API( $funcptr, $ret_type, $wine::debug-1, @args2 );
174 if ($wine::debug > 1)
176 print STDERR "==== Ret $function()";
177 if (defined($r)) { printf STDERR " ret=0x%x", $r; }
178 if (defined($err)) { printf STDERR " err=%d", $err; }
182 # Pass the return value back
188 # ----------------------------------------------------------------------
189 # | Subroutine: declare
190 # ----------------------------------------------------------------------
193 my ($module, %list) = @_;
196 if (defined($loaded_modules{$module}))
198 $handle = $loaded_modules{$module};
202 $handle = load_library($module) or die "Could not load '$module'";
203 $loaded_modules{$module} = $handle;
206 foreach $func (keys %list)
208 if(ref($list{$func}) eq "ARRAY") {
209 my ($return_type, $argument_types) = @{$list{$func}};
211 my $ret_type = $return_types{$return_type};
212 my $arg_types = [map { $return_types{$_} } @$argument_types];
214 $prototypes{$func} = [ $module, 0, $ret_type, $arg_types ];
216 my $ret_type = $return_types{$list{$func}};
218 $prototypes{$func} = [ $module, 0, $ret_type ];
224 # ------------------------------------------------------------------------
225 # | Sub: alloc_callback |
226 # | -------------------------------------------------------------------- |
227 # | Purpose: Allocate a thunk for a Wine API callback function. |
229 # | Basically a thin wrapper over alloc_thunk(); see wine.xs for |
232 # | Usage: alloc_callback SUB_REF, [ ARGS_TYPES ... ] |
234 # | Returns: Pointer to thunk allocated (as an integer value) |
236 # | The returned value is just a raw pointer to a block of memory |
237 # | allocated by the C code (cast into a Perl integer). It isn't |
238 # | really suitable for anything but to be passed to a wine API |
240 # ------------------------------------------------------------------------
241 sub alloc_callback($@)
243 # ----------------------------------------------
246 # | [todo] Check arg types |
247 # ----------------------------------------------
249 my @callback_arg_types = @_;
252 # [todo] Some way of specifying args passed to callback
254 # --------------------------------------------------------------
255 # | Convert arg types to integers |
256 # --------------------------------------------------------------
257 map { $_ = $return_types{$_} } @callback_arg_types;
259 # --------------------------------------------------------------
260 # | Pass thru to alloc_thunk() |
261 # --------------------------------------------------------------
262 return alloc_thunk ($sub_ref, @callback_arg_types);
265 # Autoload methods go after =cut, and are processed by the autosplit program.
271 # ------------------------------------------------------------------------
272 # | pod documentation |
275 # ------------------------------------------------------------------------
279 wine - Perl extension for calling wine API functions
285 wine::declare( "kernel32",
286 SetLastError => ["void", ["int"]],
287 GetLastError => ["int", []] );
288 SetLastError( 1234 );
289 printf "%d\n", GetLastError();
294 This module provides a gateway for calling Win32 API functions from
297 =head1 CALLING WIN32 API FUNCTIONS
299 The functions you want to call must first be declared by calling
300 the wine::declare method. The first argument is the name of the
301 module containing the APIs, and the next argument is a list of
302 function names and their return and argument types. For instance:
304 wine::declare( "kernel32",
305 SetLastError => ["void", ["int"]],
306 GetLastError => ["int", []] );
308 declares that the functions SetLastError and GetLastError are
309 contained in the kernel32 dll.
311 Once you have done that you can call the functions directly just
312 like native Perl functions:
314 SetLastError( $some_error );
316 The supported return types are:
334 =head1 $wine::err VARIABLE
336 In the Win32 API, an integer error code is maintained which always
337 contains the status of the last API function called. In C code,
338 it is accessed via the GetLastError() function. From a Perl script,
339 it can be accessed via the package global $wine::err. For example:
341 GlobalGetAtomNameA ($atom, \$buf, -1);
342 if ($wine::err == 234)
347 Wine returns 234 (ERROR_MORE_DATA) from the GlobalGetAtomNameA()
348 API function in this case because the buffer length passed is -1
349 (hardly enough room to store anything in ...)
351 If the called API didn't set the last error code, $wine:;err is
354 =head1 $wine::debug VARIABLE
356 This variable can be set to 1 to enable debugging of the API calls,
357 which will print a lot of information about what's going on inside the
358 wine package while calling an API function.
360 =head1 OTHER USEFUL FUNCTIONS
362 The bundle that includes the wine extension also includes a module of
363 plain ol' Perl subroutines which are useful for interacting with wine
364 API functions. Currently supported functions are:
368 =item hd BUF [, LENGTH]
370 Dump a formatted hex dump to STDOUT. BUF is a string containing
371 the buffer to dump; LENGTH is the length to dump (length (BUF) if
372 omitted). This is handy because wine often writes a null character
373 into the middle of a buffer, thinking that the next piece of code to
374 look at the buffer will be a piece of C code that will regard it as
375 a string terminator. Little does it know that the buffer is going
376 to be returned to a Perl script, which may not ...
380 Generate and return a wide-character (Unicode) string from the given
385 Return the length of the given wide-character string
387 =item assert CONDITION
389 Print a message if the assertion fails (i.e., CONDITION is false),
390 or do nothing quietly if it is true. The message includes the script
391 name and line number of the assertion that failed.
399 John F Sturtz, jsturtz@codeweavers.com