Handle ascii & unicode drag and drop structures in DragQueryFileA &
[wine] / tools / bug_report.pl
1 #!/usr/bin/perl
2 ##Wine Quick Debug Report Maker Thingy (WQDRMK)
3 ## Copyright (c) 1998-1999 Adam Sacarny
4 ##Do not say this is yours without my express permisson, or I will
5 ##hunt you down and kill you like the savage animal I am.
6 ##
7 ## Improvements by Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
8 ## (c) 2000
9 ##
10 ## This library is free software; you can redistribute it and/or
11 ## modify it under the terms of the GNU Lesser General Public
12 ## License as published by the Free Software Foundation; either
13 ## version 2.1 of the License, or (at your option) any later version.
14 ##
15 ## This library is distributed in the hope that it will be useful,
16 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ## Lesser General Public License for more details.
19 ##
20 ## You should have received a copy of the GNU Lesser General Public
21 ## License along with this library; if not, write to the Free Software
22 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 ##
24 ##Changelog:
25 ##August 29, 1999 - Work around for debugger exit (or lack thereof)
26 ##                - Should now put debugging output in correct place
27 ##April 19, 1999 - Much nicer way to select wine's location
28 ##               - Option to disable creation of a debugging output
29 ##               - Now places debugging output where it was started
30 ##April 4, 1999 - Sanity check for file locations/wine strippedness
31 ##              - Various code cleanups/fixes
32 ##March 21, 1999 - Bash 2.0 STDERR workaround (Thanks Ryan Cumming!)
33 ##March 1, 1999 - Check for stripped build
34 ##February 3, 1999 - Fix to chdir to the program's directory
35 ##February 1, 1999 - Cleaned up code
36 ##January 26, 1999 - Fixed various bugs...
37 ##                 - Made newbie mode easier
38 ##January 25, 1999 - Initial Release
39 ## -------------------------------------------
40 ##| IRCNET/UNDERNET: jazzfan AOL: Jazzrock12  |
41 ##| E-MAIL: magicbox@bestweb.net ICQ: 19617831|
42 ##|   Utah Jazz Page @ http://www.gojazz.net  |
43 ##|  Wine Builds @ http://www.gojazz.net/wine |
44 ## -------------------------------------------
45 sub do_var {
46         $var=$_[0];
47         $var =~ s/\t//g;
48         return $var;
49 }
50 open STDERR, ">&SAVEERR"; open STDERR, ">&STDOUT";
51 $ENV{'SHELL'}="/bin/bash";
52 $var0 = qq{
53         What is your level of WINE expertise? 1-newbie 2-intermediate 3-advanced
54
55         1 - Makes a debug report as defined in the WINE documentation. Best
56             for new WINE users. If you're not sure what -debugmsg is, then
57             use this mode.
58         2 - Makes a debug report that is more customizable (Example: you can
59             choose what -debugmsg 's to use). You are asked more questions in
60             this mode. May intimidate newbies.
61         3 - Just like 2, but not corner cutting. Assumes you know what you're
62             doing so it leaves out the long descriptions.
63 };
64 print do_var($var0)."\n";
65 until ($debuglevel >= 1 and $debuglevel <= 3) {
66         print "Enter your level of WINE expertise (1-3): ";
67         $debuglevel=<STDIN>;
68         chomp $debuglevel;
69 }
70
71 if ($debuglevel < 3) {
72         $var1 = qq{
73         This program will make a debug report for WINE developers. It generates
74         two files. The first one has everything asked for by the bugreports guide;
75         the second has *all* of the debug output, which can go to thousands of
76         lines.
77         To (hopefully) get the bug fixed, report it to the project
78         bug tracking system at http://bugs.winehq.com.
79         Attach the first file to the bug description.
80         Also include detailed description of the problem. The developers
81         might ask you for "the last X lines from the report". If so, just
82         provide the output of the following command:
83             gzip -d (output file) | tail -n (X) > outfile
84         If you do not want to create one of the files, just specify "no file".
85         };
86         print do_var($var1);
87 } elsif ($debuglevel =~ 3) {
88         $var2 = qq{
89         This program will output to two files:
90         1. Formatted debug report you might want to post to the newsgroup
91         2. File with ALL the debug output (It will later be compressed with
92         gzip, so leave off the trailing .gz)
93         If you do not want to create one of the files, just type in "no file"
94         and I'll skip it.
95         };
96         print do_var($var2);
97 }
98
99 print "\nFilename for the formatted debug report: ";
100 $outfile=<STDIN>;
101 chomp $outfile;
102 $var23 = qq{
103 I don't think you typed in the right filename. Let's try again.
104 };
105 while ($outfile =~ /^(\s)*$/) {
106         print do_var($var23);
107         $outfile=<STDIN>;
108         chomp $outfile;
109 }
110
111 print "Filename for full debug output: ";
112 $dbgoutfile=<STDIN>;
113 chomp $dbgoutfile;
114 while ($dbgoutfile =~ /^(\s)*$/) {
115         print do_var($var23);
116         $dbgoutfile=<STDIN>;
117         chomp $dbgoutfile;
118 }
119
120 $var31 = qq{
121 Since you will only be creating the formatted report, I will need a
122 temporary place to put the full output.
123 You may not enter "no file" for this.
124 Enter the filename for the temporary file:
125 };
126 if ($outfile ne "no file" and $dbgoutfile eq "no file") {
127         print do_var($var31);
128         $tmpoutfile=<STDIN>;
129         chomp $tmpoutfile;
130         while (($tmpoutfile =~ /^(\s)*$/) or ($tmpoutfile eq "no file")) {
131                 print do_var($var23);
132                 $tmpoutfile=<STDIN>;
133                 chomp $tmpoutfile;
134         }
135 }
136
137 $whereis=`whereis wine`;
138 chomp $whereis;
139 print "\nWhere is your copy of Wine located?\n\n";
140 $whereis =~ s/^wine\: //;
141 @locations = split(/\s/,$whereis);
142 print "1 - Unlisted (I'll prompt you for a new location\n";
143 print "2 - Unsure (I'll use #3, that's probably it)\n";
144 $i=2;
145 foreach $location (@locations) {
146         $i++;
147         print "$i - $location\n";
148 }
149 print "\n";
150 sub select_wineloc {
151         do
152                 {
153                 print "Enter the number that corresponds to Wine's location: ";
154                 $wineloc=<STDIN>;
155                 chomp $wineloc;
156                 }
157         while ( ! ( $wineloc >=1 and $wineloc <= 2+@locations ) );
158         if ($wineloc == 1) {
159                 $var25 = qq{
160                 Enter the full path to wine (Example: /usr/bin/wine):
161                 };
162                 $var26 = qq{
163                 Please enter the full path to wine. A full path is the
164                 directories leading up to a program's location, and then the
165                 program. For example, if you had the program "wine" in the
166                 directory "/usr/bin", you would type in "/usr/bin/wine". Now
167                 try:
168                 };
169                 print do_var($var25) if $debuglevel == 3;
170                 print do_var($var26) if $debuglevel < 3;
171                 $wineloc=<STDIN>;
172                 chomp $wineloc;
173                 while ($wineloc =~ /^(\s)*$/) {
174                         print do_var($var23);
175                         $wineloc=<STDIN>;
176                         chomp $wineloc;
177                 }
178         }
179         elsif ($wineloc == 2) {
180                 $wineloc=$locations[0];
181         }
182         else {
183                 $wineloc=$locations[$wineloc-3];
184         }
185 }
186 &select_wineloc;
187 print "Checking if $wineloc is stripped...\n";
188 $ifstrip = `nm $wineloc 2>&1`;
189 while ($ifstrip =~ /no symbols/) {
190         $var24 = qq{
191         Your wine is stripped! You probably downloaded it off of the internet.
192         If you have another location of wine that may be used, enter it now.
193         Otherwise, hit control-c and download an unstripped version, then re-run
194         this script. Note: stripped versions make useless debug reports
195         };
196         print do_var($var24);
197         &select_wineloc;
198         $ifstrip = `nm $wineloc 2>&1`;
199 }
200 while ($ifstrip =~ /not recognized/) {
201         $var26 = qq{
202         Looks like you gave me something that isn't a wine binary (It could be a
203         text file). Try again.
204         };
205         print do_var($var26);
206         &select_wineloc;
207         print "Checking if $wineloc is stripped...\n";
208         $ifstrip = `nm $wineloc 2>&1`;
209 }
210
211 print "\nWhat version of windows are you using with wine?\n\n".
212       "0 - None\n".
213       "1 - Windows 3.x\n".
214       "2 - Windows 95\n".
215       "3 - Windows 98\n".
216       "4 - Windows NT 3.5x\n".
217       "5 - Windows NT4.x\n".
218       "6 - Windows 2000\n".
219       "7 - Other\n\n";
220 do
221         {
222         print "Enter the number that corresponds to your windows version: ";
223         $winver=<STDIN>;
224         chomp $winver;
225         }
226 until ($winver >= 0 and $winver <= 7);
227 if ($winver =~ 0) {
228         $winver="None Installed";
229 } elsif ($winver =~ 1) {
230         $winver="Windows 3.x";
231 } elsif ($winver =~ 2) {
232         $winver="Windows 95";
233 } elsif ($winver =~ 3) {
234         $winver="Windows 98";
235 } elsif ($winver =~ 4) {
236         $winver="Windows NT 3.5x";
237 } elsif ($winver =~ 5) {
238         $winver="Windows NT 4.x";
239 } elsif ($winver =~ 6) {
240         $winver="Windows NT 5.x";
241 } elsif ($winver =~ 7) {
242         print "What version of Windows are you using? ";
243         $winver=<STDIN>;
244         chomp $winver;
245 }
246 if ($debuglevel < 3) {
247         $var7 = qq{
248         Enter the full path to the program you want to run. Remember what you
249         were told before - a full path is the directories leading up to the
250         program and then the program's name, like /dos/windows/sol.exe, not
251         sol.exe:
252         };
253         print do_var($var7);
254 }
255 if ($debuglevel =~ 3) {
256         $var8 = qq{
257         Enter the full path to the program you want to run (Example:
258         /dos/windows/sol.exe, NOT sol.exe):
259         };
260         print do_var($var8);
261 }
262 $program=<STDIN>;
263 chomp $program;
264 while ($program =~ /^(\s)*$/) {
265         print do_var($var23);
266         $program=<STDIN>;
267         chomp $program;
268 }
269 $program =~ s/\"//g;
270 $var9 = qq{
271 Enter the name, version, and manufacturer of the program (Example:
272 Netscape Navigator 4.5):
273 };
274 print do_var($var9);
275 $progname=<STDIN>;
276 chomp $progname;
277 $var10 = qq{
278 Enter 0 if your program is 16 bit (Windows 3.x), 1 if your program is 32
279 bit (Windows 9x, NT3.x and up), or 2 if you are unsure:
280 };
281 print do_var($var10);
282 $progbits=<STDIN>;
283 chomp $progbits;
284 until ($progbits == 0 or $progbits == 1 or $progbits == 2) {
285         print "You must enter 0, 1 or 2!\n";
286         $progbits=<STDIN>;
287         chomp $progbits
288 }
289 if ($progbits =~ 0) {
290         $progbits=Win16
291 } elsif ($progbits =~ 1) {
292         $progbits=Win32
293 } else {
294         $progbits = "Unsure"
295 }
296 if ($debuglevel > 1) {
297         if ($debuglevel =~ 2) {
298                 $var11 = qq{
299                 Enter any extra debug options. Default is +relay - If you don't
300                 know what options to use, just hit enter, and I'll use those (Example, the
301                 developer tells you to re-run with -debugmsg +dosfs,+module you would type
302                 in +dosfs,+module). Hit enter if you're not sure what to do:
303                 };
304                 print do_var($var11);
305         } elsif ($debuglevel =~ 3) {
306                 $var12 = qq{
307                 Enter any debug options you would like to use. Just enter parts after
308                 -debugmsg. Default is +relay:
309                 };
310                 print do_var($var12);
311         }
312         $debugopts=<STDIN>;
313         chomp $debugopts;
314         if ($debugopts =~ /-debugmsg /) {
315                 ($crap, $debugopts) = split / /,$debugopts;
316         }
317         if ($debugopts =~ /^\s*$/) {
318                 $debugopts="+relay";
319         }
320 } elsif ($debuglevel =~ 1) {
321         $debugopts = "+relay";
322 }
323 if ($debuglevel > 1) {
324         if ($debuglevel =~ 2) {
325                 $var13 = qq{
326                 How many trailing lines of debugging info do you want to include in the report
327                 you're going to submit (First file)? If a developer asks you to include
328                 the last 1000 lines, enter 1000 here. Default is 200, which is reached by
329                 pressing enter. (If you're not sure, just hit enter):
330                 };
331                 print do_var($var13);
332         } elsif ($debuglevel =~ 3) {
333                 $var14 = qq{
334                 Enter how many lines of trailing debugging output you want in your nice
335                 formatted report. Default is 200:
336                 };
337                 print do_var($var14);
338         }
339         $lastnlines=<STDIN>;
340         chomp $lastnlines;
341         if ($lastnlines =~ /^\s*$/) {
342         $lastnlines=200;
343         }
344 } elsif ($debuglevel =~ 1) {
345         $lastnlines=200;
346 }
347 if ($debuglevel > 1) {
348         $var15 = qq{
349         Enter any extra options you want to pass to WINE.
350         };
351         print do_var($var15);
352         $extraops=<STDIN>;
353         chomp $extraops;
354 } elsif ($debuglevel =~ 1) {
355         $extraops=" ";
356 }
357
358 print "\nEnter the name of your distribution (Example: Redhat 6.1): ";
359 $dist=<STDIN>;
360 chomp $dist;
361
362 if ($debuglevel > 1) {
363         if ($debuglevel =~ 2) {
364                 $var16 = qq{
365                 When you ran ./configure to build wine, were there any special options
366                 you used to do so (Example: --enable-dll)? If you didn't use any special
367                 options or didn't compile WINE on your own, just hit enter:
368                 };
369                 print do_var($var16);
370         } elsif ($debuglevel =~ 3) {
371                 $var17 = qq{
372                 Enter any special options you used when running ./configure for WINE
373                 (Default is none, use if you didn't compile wine yourself):
374                 };
375                 print do_var($var17);
376         }
377         $configopts=<STDIN>;
378         chomp $configopts;
379         if ($configopts =~ /^\s*$/) {
380         $configopts="None";
381         }
382 } elsif ($debuglevel =~ 1) {
383         $configopts="None";
384 }
385 if ($debuglevel > 1) {
386         if ($debuglevel =~ 2) {
387                 $var18 = qq{
388                 Is your wine version CVS or from a .tar.gz file? As in... did you download it
389                 off a website/ftpsite or did you/have you run cvs on it to update it?
390                 For CVS: YYMMDD, where YY is the year (99), MM is the month (01), and DD
391                 is the day (14), that you last updated it (Example: 990114).
392                 For tar.gz: Just hit enter and I'll figure out the version for you:
393                 };
394                 print do_var($var18);
395         } elsif ($debuglevel =~ 3) {
396                 $var19 = qq{
397                 Is your wine from CVS? Enter the last CVS update date for it here, in
398                 YYMMDD form (If it's from a tarball, just hit enter):
399                 };
400                 print do_var($var19);
401         }
402         $winever=<STDIN>;
403         chomp $winever;
404         if ($winever =~ /[0-9]+/) {
405                 $winever .= " CVS";
406         }
407         else {
408                 $winever = `$wineloc -v 2>&1`;
409                 chomp $winever;
410         }
411 } elsif ($debuglevel =~ 1) {
412         $winever=`$wineloc -v 2>&1`;
413         chomp $winever;
414 }
415 $gccver=`gcc -v 2>&1`;
416 ($leftover,$gccver) = split /\n/,$gccver;
417 chomp $gccver;
418 $cpu=`uname -m`;
419 chomp $cpu;
420 $kernelver=`uname -r`;
421 chomp $kernelver;
422 $ostype=`uname -s`;
423 chomp $ostype;
424 $wineneeds=`ldd $wineloc`;
425 if ($debuglevel < 3) {
426         $var20 = qq{
427         OK, now I'm going to run WINE. I will close it for you once the wine
428         debugger comes up. NOTE: You won't see ANY debug messages. Don't
429         worry, they are being output to a file. Since there are so many, it's
430         not a good idea to have them all output to a terminal (Speed slowdown
431         mainly).
432         WINE will still run much slower than normal, because there will be so
433         many debug messages being output to file.
434         };
435         print do_var($var20);
436 } elsif ($debuglevel =~ 3) {
437         $var21 = qq{
438         OK, now it's time to run WINE. I will close down WINE for you after
439         the debugger is finished doing its thing.
440         };
441         print do_var($var21);
442 }
443 $bashver=qw("/bin/bash -version");
444 if ($bashver =~ /2\./) { $outflags = "2>" }
445 else { $outflags = ">\&" }
446 print "Hit enter to start wine!\n";
447 $blank=<STDIN>;
448 $dir=$program;
449 $dir=~m#(.*)/#;
450 $dir=$1;
451 use Cwd;
452 $nowdir=getcwd;
453 chdir($dir);
454 if (!($outfile =~ /\//) and $outfile ne "no file") {
455         $outfile = "$nowdir/$outfile";
456 }
457 if (!($dbgoutfile =~ /\//) and $dbgoutfile ne "no file") {
458         $dbgoutfile = "$nowdir/$dbgoutfile";
459 }
460 if (!($tmpoutfile =~ /\//)) {
461         $tmpoutfile = "$nowdir/$tmpoutfile";
462 }
463 $SIG{CHLD}=$SIG{CLD}=sub { wait };
464 if ($dbgoutfile ne "no file") {
465         unlink("$dbgoutfile");
466         if ($pid=fork()) {
467         }
468         elsif (defined $pid) {
469                 close(0);close(1);close(2);
470                 exec "echo quit | $wineloc -debugmsg $debugopts $extraops \"$program\" > $dbgoutfile 2>&1";
471         }
472         else {
473                 die "couldn't fork";
474         }
475         while (kill(0, $pid)) {
476                 sleep(5);
477                 $last = `tail -n 5 $dbgoutfile | grep Wine-dbg`;
478                 if ($last =~ /Wine-dbg/) {
479                         kill "TERM", $pid;
480                         break;
481                 }
482         }
483         if ($outfile ne "no file") {
484                 $lastlines=`tail -n $lastnlines $dbgoutfile`;
485                 system("gzip $dbgoutfile");
486                 &generate_outfile;
487         }
488         else {
489                 system("gzip $dbgoutfile");
490         }
491 }
492 elsif ($outfile ne "no file" and $dbgoutfile eq "no file") {
493         if ($pid=fork()) {
494         }
495         elsif (defined $pid) {
496                 close(0);close(1);close(2);
497                 exec "echo quit | $wineloc -debugmsg $debugopts $extraops \"$program\" 2>&1| tee $tmpoutfile | tail -n $lastnlines > $outfile";
498         }
499         else {
500                 die "couldn't fork";
501         }
502         print "$outfile $tmpoutfile";
503         while (kill(0, $pid)) {
504                 sleep(5);
505                 $last = `tail -n 5 $tmpoutfile | grep Wine-dbg`;
506                 if ($last =~ /Wine-dbg/) {
507                         kill "TERM", $pid;
508                         break;
509                 }
510         }
511         unlink($tmpoutfile);
512         open(OUTFILE, "$outfile");
513         while (<OUTFILE>) {
514                 $lastlines .= $_;
515         }
516         close(OUTFILE);
517         unlink($outfile);
518         &generate_outfile;
519 }
520 else {
521         $var27 = qq{
522         I guess you don't want me to make any debugging output. I'll send
523         it to your terminal. This will be a *lot* of output -- hit enter to
524         continue, control-c to quit.
525         Repeat: this will be a lot of output!
526         };
527         print do_var($var27);
528         $blah=<STDIN>;
529         system("$wineloc -debugmsg $debugmsg $extraops \"$program\"");
530 }
531 sub generate_outfile {
532 open(OUTFILE,">$outfile");
533 print OUTFILE <<EOM;
534 Auto-generated debug report by Wine Quick Debug Report Maker Thingy:
535 WINE Version:                $winever
536 Windows Version:             $winver
537 Distribution:                $dist
538 Kernel Version:              $kernelver
539 OS Type:                     $ostype
540 CPU:                         $cpu
541 GCC Version:                 $gccver
542 Program:                     $progname
543 Program Type:                $progbits
544 Debug Options:               -debugmsg $debugopts
545 Other Extra Commands Passed: $extraops
546 Extra ./configure Commands:  $configopts
547 Wine Dependencies:
548 $wineneeds
549 Last $lastnlines lines of debug output follows:
550 $lastlines
551 I have a copy of the full debug report, if it is needed.
552 Thank you!
553 EOM
554 }
555 $var22 = qq{
556 Great! We're finished making the debug report. Do whatever with it.
557 };
558 $var28 = qq{
559 The filename for the formatted report is:
560 $outfile
561 };
562 $var29 = qq{
563 The filename for the compressed full debug is:
564 $dbgoutfile.gz
565 Note that it is $dbgoutfile.gz, since I compressed it with gzip for you.
566 };
567 $var30 = qq{
568 Having problems with the script?
569 Submit a bug report to Wine bugtracking system at http://bugs.winehq.com or
570 tell the wine newsgroup (comp.emulators.ms-windows.wine).
571 };
572 print do_var($var22);
573 print do_var($var28) if $outfile ne "no file";
574 print do_var($var29) if $dbgoutfile ne "no file";
575 print do_var($var30);