Handle generic column width changes.
[wine] / programs / winetest / include / wine.pm
1 # --------------------------------------------------------------------
2 # Module:      wine.pm
3 #
4 # Purpose: Module to supply wrapper around and support for gateway to
5 #          Windows API functions
6 #
7 # Copyright 2001 John F Sturtz for Codeweavers
8 #
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.
13 #
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.
18 #
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 # --------------------------------------------------------------------
23
24 package wine;
25
26 use strict;
27 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD
28             %return_types %prototypes %loaded_modules);
29
30 require Exporter;
31
32 @ISA = qw(Exporter);
33
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.
37 @EXPORT = qw(
38              AUTOLOAD
39              alloc_callback
40             );
41
42 $VERSION = '0.01';
43 bootstrap wine $VERSION;
44
45 # Global variables
46 $wine::err = 0;
47 $wine::debug = defined($ENV{WINETEST_DEBUG}) ? $ENV{WINETEST_DEBUG} : 1;
48
49 %loaded_modules = ();
50
51
52 # --------------------------------------------------------------
53 # | Return-type constants                                      |
54 # |                                                            |
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       |
59 # |         yet ...                                            |
60 # --------------------------------------------------------------
61 %return_types = (
62     "void" => 0,
63     "int" => 1, "long" => 1,
64     "word" => 2,
65     "ptr" => 3,
66     "str" => 4, "wstr" => 4
67 );
68
69
70 # ------------------------------------------------------------------------
71 # | Sub:       AUTOLOAD                                                  |
72 # | -------------------------------------------------------------------- |
73 # | Purpose:   Used to catch calls to undefined routines                 |
74 # |                                                                      |
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 # ------------------------------------------------------------------------
80 sub AUTOLOAD
81 {
82     # --------------------------------------------------------------
83     # | Figure out who we are                                      |
84     # --------------------------------------------------------------
85     my ($pkg, $func) = (split /::/, $AUTOLOAD)[0,1];
86
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))
92     {
93         $AutoLoader::AUTOLOAD = $AUTOLOAD;
94         goto &AutoLoader::AUTOLOAD;
95     }
96
97     # --------------------------------------------------------------
98     # | Ignore this                                                |
99     # --------------------------------------------------------------
100     return
101         if ($func eq 'DESTROY');
102
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}))
108     {
109         return call( $func, @_ );
110     }
111     die "Function '$func' not declared";
112 } # End AUTOLOAD
113
114
115
116 # ------------------------------------------------------------------------
117 # | Sub:         call                                                    |
118 # | -------------------------------------------------------------------- |
119 # | Purpose:     Call a wine API function                                |
120 # |                                                                      |
121 # | Usage:       call FUNCTION, [ARGS ...]
122 # |                                                                      |
123 # | Returns:     value returned by API function called                   |
124 # ------------------------------------------------------------------------
125 sub call($@)
126 {
127     my ($function,@args) = @_;
128     my ($module,$funcptr,$ret_type,$arg_types) = @{$prototypes{$function}};
129
130     unless ($funcptr)
131     {
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;
135     }
136
137     if ($wine::debug > 1)
138     {
139         print STDERR "==== Call $function(";
140         for (@args)
141         {
142             print STDERR " ", +(ref () ? ("(" . ${$_} . ")") : "$_");
143         }
144         print STDERR " " if (scalar @args);
145         print STDERR ")\n";
146     }
147
148     # Check and translate args before call
149     my @args2;
150     if (defined($arg_types)) {
151         my @arg_types = @$arg_types;
152
153         if($#args != $#arg_types) {
154             die "$function: Wrong number of arguments, expected " .
155                 ($#arg_types + 1) . ", got " . ($#args + 1) . "\n";
156         }
157
158         while (defined(my $arg = shift @args) &&
159                defined(my $arg_type = shift @arg_types))
160         {
161             if($arg_type == 1 || $arg_type == 2) { # int || word
162                 $arg = int($arg);
163             }
164             push @args2, $arg;
165         }
166     } else {
167         @args2 = @args;
168     }
169
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 );
173
174     if ($wine::debug > 1)
175     {
176         print STDERR "==== Ret  $function()";
177         if (defined($r)) { printf STDERR " ret=0x%x", $r; }
178         if (defined($err)) { printf STDERR " err=%d", $err; }
179         print STDERR "\n";
180     }
181
182     # Pass the return value back
183     $wine::err = $err;
184     return ($r);
185 }
186
187
188 # ----------------------------------------------------------------------
189 # | Subroutine:  declare
190 # ----------------------------------------------------------------------
191 sub declare($%)
192 {
193     my ($module, %list) = @_;
194     my ($handle, $func);
195
196     if (defined($loaded_modules{$module}))
197     {
198         $handle = $loaded_modules{$module};
199     }
200     else
201     {
202         $handle = load_library($module) or die "Could not load '$module'";
203         $loaded_modules{$module} = $handle;
204     }
205
206     foreach $func (keys %list)
207     {
208         if(ref($list{$func}) eq "ARRAY") {
209             my ($return_type, $argument_types) = @{$list{$func}};
210
211             my $ret_type = $return_types{$return_type};
212             my $arg_types = [map { $return_types{$_} } @$argument_types];
213
214             $prototypes{$func} = [ $module, 0, $ret_type, $arg_types ];
215         } else {
216             my $ret_type = $return_types{$list{$func}};
217
218             $prototypes{$func} = [ $module, 0, $ret_type ];
219         }
220     }
221 }
222
223
224 # ------------------------------------------------------------------------
225 # | Sub:         alloc_callback                                          |
226 # | -------------------------------------------------------------------- |
227 # | Purpose:     Allocate a thunk for a Wine API callback function.      |
228 # |                                                                      |
229 # |     Basically a thin wrapper over alloc_thunk(); see wine.xs for     |
230 # |     details ...                                                      |
231 # |                                                                      |
232 # | Usage:       alloc_callback SUB_REF, [ ARGS_TYPES ... ]              |
233 # |                                                                      |
234 # | Returns:     Pointer to thunk allocated (as an integer value)        |
235 # |                                                                      |
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      |
239 # |     function ...                                                     |
240 # ------------------------------------------------------------------------
241 sub alloc_callback($@)
242 {
243     # ----------------------------------------------
244     # | Locals                                     |
245     # |                                            |
246     # | [todo]  Check arg types                    |
247     # ----------------------------------------------
248     my  $sub_ref            = shift;
249     my  @callback_arg_types = @_;
250
251     # [todo]  Check args
252     # [todo]  Some way of specifying args passed to callback
253
254     # --------------------------------------------------------------
255     # | Convert arg types to integers                              |
256     # --------------------------------------------------------------
257     map { $_ = $return_types{$_} } @callback_arg_types;
258
259     # --------------------------------------------------------------
260     # | Pass thru to alloc_thunk()                                 |
261     # --------------------------------------------------------------
262     return alloc_thunk ($sub_ref, @callback_arg_types);
263 }
264
265 # Autoload methods go after =cut, and are processed by the autosplit program.
266 1;
267 __END__
268
269
270
271 # ------------------------------------------------------------------------
272 # | pod documentation                                                    |
273 # |                                                                      |
274 # |                                                                      |
275 # ------------------------------------------------------------------------
276
277 =head1 NAME
278
279 wine - Perl extension for calling wine API functions
280
281 =head1 SYNOPSIS
282
283     use wine;
284
285     wine::declare( "kernel32",
286                    SetLastError => ["void", ["int"]],
287                    GetLastError => ["int", []] );
288     SetLastError( 1234 );
289     printf "%d\n", GetLastError();
290
291
292 =head1 DESCRIPTION
293
294 This module provides a gateway for calling Win32 API functions from
295 a Perl script.
296
297 =head1 CALLING WIN32 API FUNCTIONS
298
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:
303
304     wine::declare( "kernel32",
305                    SetLastError => ["void", ["int"]],
306                    GetLastError => ["int", []] );
307
308 declares that the functions SetLastError and GetLastError are
309 contained in the kernel32 dll.
310
311 Once you have done that you can call the functions directly just
312 like native Perl functions:
313
314   SetLastError( $some_error );
315
316 The supported return types are:
317
318 =over 4
319
320 =item void
321
322 =item word
323
324 =item long
325
326 =item ptr
327
328 =item str
329
330 =item wstr
331
332 =back
333
334 =head1 $wine::err VARIABLE
335
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:
340
341     GlobalGetAtomNameA ($atom, \$buf, -1);
342     if ($wine::err == 234)
343     {
344         ...
345     }
346
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 ...)
350
351 If the called API didn't set the last error code, $wine:;err is
352 undefined.
353
354 =head1 $wine::debug VARIABLE
355
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.
359
360 =head1 OTHER USEFUL FUNCTIONS
361
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:
365
366 =over 4
367
368 =item hd BUF [, LENGTH]
369
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 ...
377
378 =item wc STR
379
380 Generate and return a wide-character (Unicode) string from the given
381 ASCII string
382
383 =item wclen WSTR
384
385 Return the length of the given wide-character string
386
387 =item assert CONDITION
388
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.
392
393 =back
394
395
396
397 =head1 AUTHOR
398
399 John F Sturtz, jsturtz@codeweavers.com
400
401 =head1 SEE ALSO
402
403 wine documentation
404
405 =cut