Several additions and bug fixes.

diff --git a/tools/winapi/config.pm b/tools/winapi/config.pm
index 9b46378..6e7aa8e 100644
--- a/tools/winapi/config.pm
+++ b/tools/winapi/config.pm
@@ -12,7 +12,7 @@
     &file_absolutize &file_normalize
     &file_type &files_filter
     &file_skip &files_skip 
-    &get_spec_files
+    &get_c_files &get_h_files &get_spec_files
 );
 @EXPORT_OK = qw(
     $current_dir $wine_dir $winapi_dir $winapi_check_dir
@@ -98,20 +98,27 @@
     return $_;
 }
 
-sub get_spec_files {
-    $output->progress("$wine_dir: searching for *.spec");
+sub _get_files {
+    my $extension = shift;
+    my $type = shift;
 
-    my @spec_files = map {
+    $output->progress("$wine_dir: searching for *.$extension");
+
+    my @files = map {
 	s%^\./%%;
 	s%^$wine_dir/%%;
-	if(file_type($_) eq "winelib") {
+	if(file_type($_) eq $type) {
 	    $_;
 	} else {
 	    ();
 	}
-    } split(/\n/, `find $wine_dir -name \\*.spec`);
+    } split(/\n/, `find $wine_dir -name \\*.$extension`);
 
-    return @spec_files;
+    return @files;
 }
 
+sub get_c_files { return _get_files("c", @_); }
+sub get_h_files { return _get_files("h", @_); }
+sub get_spec_files { return _get_files("spec", @_); }
+
 1;
diff --git a/tools/winapi/output.pm b/tools/winapi/output.pm
index 6234d6c..1b46172 100644
--- a/tools/winapi/output.pm
+++ b/tools/winapi/output.pm
@@ -34,11 +34,13 @@
 
     my $progress = \${$self->{PROGRESS}};
     my $last_progress = \${$self->{LAST_PROGRESS}};
+    my $last_time = \${$self->{LAST_TIME}};
     my $progress_count = \${$self->{PROGRESS_COUNT}};
     my $prefix = \${$self->{PREFIX}};
 
     $$progress = "";
     $$last_progress = "";
+    $$last_time = 0;
     $$progress_count = 0;
     $$prefix = "";
 
@@ -107,10 +109,26 @@
 sub progress {
     my $self = shift;
     my $progress = \${$self->{PROGRESS}};
+    my $last_time = \${$self->{LAST_TIME}};
 
     $$progress = shift;
 
     $self->update_progress;
+    $$last_time = 0;
+}
+
+sub lazy_progress {
+    my $self = shift;
+    my $progress = \${$self->{PROGRESS}};
+    my $last_time = \${$self->{LAST_TIME}};
+
+    $$progress = shift;
+
+    my $time = time();
+    if($time - $$last_time > 0) {
+	$self->update_progress;
+    	$$last_time = $time;
+    }
 }
 
 sub prefix {
diff --git a/tools/winapi/setup.pm b/tools/winapi/setup.pm
index 15d2e16..9c0961f 100644
--- a/tools/winapi/setup.pm
+++ b/tools/winapi/setup.pm
@@ -50,9 +50,7 @@
 	exit 1;
     }
 
-    push @INC, ($winapi_check_dir, $winapi_dir) if $tool eq "winapi_check";
-    push @INC, ($winapi_dir, $winapi_check_dir) if $tool eq "winapi_extract";
-    push @INC, ($winapi_dir, $winapi_check_dir) if $tool eq "winapi_fixup";
+    push @INC, ($winapi_dir, $winapi_check_dir);
 }
 
 1;
diff --git a/tools/winapi/winapi_extract b/tools/winapi/winapi_extract
index 981a4b4..3680bdb 100755
--- a/tools/winapi/winapi_extract
+++ b/tools/winapi/winapi_extract
@@ -55,7 +55,7 @@
 {
     local $_;
 
-    foreach my $spec_file (get_spec_files) {
+    foreach my $spec_file (get_spec_files("winelib")) {
 	my $module;
 	my $type;
 
@@ -177,13 +177,15 @@
     }
 }
 
-my @files = files_skip($options->c_files);
+my @c_files = $options->c_files;
+@c_files = files_skip(@c_files);
+@c_files = files_filter("winelib", @c_files);
 
 my $progress_output;
 my $progress_current = 0;
-my $progress_max = scalar(@files);
+my $progress_max = scalar(@c_files);
 
-foreach my $file (@files) {
+foreach my $file (@c_files) {
     my %functions;
 
     $progress_current++;
diff --git a/tools/winapi_check/modules.pm b/tools/winapi_check/modules.pm
index 1252422..34f338e 100644
--- a/tools/winapi_check/modules.pm
+++ b/tools/winapi_check/modules.pm
@@ -133,6 +133,10 @@
     my $dir = $file;
     $dir =~ s/\/[^\/]*$//;
 
+    if($dir =~ m%^include%) {
+	return 1;
+    }
+
     foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
 	if($$spec_file2module{$spec_file} eq $module) {
 	    return 1;
diff --git a/tools/winapi_check/output.pm b/tools/winapi_check/output.pm
deleted file mode 100644
index c6347ee..0000000
--- a/tools/winapi_check/output.pm
+++ /dev/null
@@ -1,114 +0,0 @@
-package output;
-
-use strict;
-
-my $stdout_isatty = -t STDOUT;
-my $stderr_isatty = -t STDERR;
-
-sub new {
-    my $proto = shift;
-    my $class = ref($proto) || $proto;
-    my $self  = {};
-    bless ($self, $class);
-
-    my $progress = \${$self->{PROGRESS}};
-    my $last_progress = \${$self->{LAST_PROGRESS}};
-    my $progress_count = \${$self->{PROGRESS_COUNT}};
-    my $prefix = \${$self->{PREFIX}};
-
-    $$progress = "";
-    $$last_progress = "";
-    $$progress_count = 0;
-    $$prefix = "";
-
-    return $self;
-}
-
-
-sub show_progress {
-    my $self = shift;
-    my $progress = \${$self->{PROGRESS}};
-    my $last_progress = \${$self->{LAST_PROGRESS}};
-    my $progress_count = \${$self->{PROGRESS_COUNT}};
-
-    $$progress_count++;
-
-    if($$progress_count > 0 && $$progress && $stderr_isatty) {
-	print STDERR $$progress;
-	$$last_progress = $$progress;
-    }
-}
-
-sub hide_progress  {
-    my $self = shift;
-    my $progress = \${$self->{PROGRESS}};
-    my $last_progress = \${$self->{LAST_PROGRESS}};
-    my $progress_count = \${$self->{PROGRESS_COUNT}};
-
-    $$progress_count--;
-
-    if($$last_progress && $stderr_isatty) {
-	my $message;
-	for (1..length($$last_progress)) {
-	    $message .= " ";
-	}
-	print STDERR $message;
-	undef $$last_progress;
-    }
-}
-
-sub update_progress {
-    my $self = shift;
-    my $progress = \${$self->{PROGRESS}};
-    my $last_progress = \${$self->{LAST_PROGRESS}};
-    
-    my $prefix = "";
-    my $suffix = "";
-    if($$last_progress) {
-	for (1..length($$last_progress)) {
-	    $prefix .= "";
-	}
-	
-	my $diff = length($$last_progress)-length($$progress);
-	if($diff > 0) {
-	    for (1..$diff) {
-		$suffix .= " ";
-	    }
-	    for (1..$diff) {
-		$suffix .= "";
-	    }
-	}
-    }
-    print STDERR $prefix . $$progress . $suffix;
-    $$last_progress = $$progress;
-}
-
-sub progress {
-    my $self = shift;
-    my $progress = \${$self->{PROGRESS}};
-
-    $$progress = shift;
-
-    $self->update_progress;
-}
-
-sub prefix {
-    my $self = shift;
-    my $prefix = \${$self->{PREFIX}};
-
-    $$prefix = shift;
-}
-
-sub write {
-    my $self = shift;
-
-    my $message = shift;
-
-    my $prefix = \${$self->{PREFIX}};
-
-    $self->hide_progress if $stdout_isatty;
-    print $$prefix . $message;
-    $self->show_progress if $stdout_isatty;
-}
-
-1;
diff --git a/tools/winapi_check/win32/msvcrt.api b/tools/winapi_check/win32/msvcrt.api
index 6399e02..3549303 100644
--- a/tools/winapi_check/win32/msvcrt.api
+++ b/tools/winapi_check/win32/msvcrt.api
@@ -14,8 +14,6 @@
 WCHAR
 int
 long
-size_t
-time_t
 unsigned int
 unsigned long
 
@@ -56,7 +54,6 @@
 char *
 char **
 char ***
-double *
 exception *
 int *
 jmp_buf
@@ -66,13 +63,12 @@
 struct _timeb *
 struct _utimbuf *
 struct _wfinddata_t *
-struct tm *
 terminate_function
-time_t *
 type_info *
 unexpected_function
 unsigned char *
 unsigned int *
+unsigned long *
 va_list
 void *
 
diff --git a/tools/winapi_check/win32/ole32.api b/tools/winapi_check/win32/ole32.api
index cae3612..1540f51 100644
--- a/tools/winapi_check/win32/ole32.api
+++ b/tools/winapi_check/win32/ole32.api
@@ -84,7 +84,6 @@
 REFIID
 SNB
 STGMEDIUM *
-WCHAR *
 WORD *
 void *
 void **
diff --git a/tools/winapi_check/win32/shell32.api b/tools/winapi_check/win32/shell32.api
index 483c0e5..6f23aca 100644
--- a/tools/winapi_check/win32/shell32.api
+++ b/tools/winapi_check/win32/shell32.api
@@ -89,6 +89,10 @@
 REFIID
 UINT *
 
+%ptr # --forbidden
+
+int *
+
 %str
 
 LPCSTR
diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm
index fd681cb..e58e1fe 100644
--- a/tools/winapi_check/winapi.pm
+++ b/tools/winapi_check/winapi.pm
@@ -26,6 +26,10 @@
     $$name = shift;
     my $path = shift;
 
+    if($$options->progress) {
+	$$output->progress("$path: searching for *.api");
+    }
+
     my @files = map {
 	s%^\./%%;
 	$_; 
@@ -33,6 +37,11 @@
   
     foreach my $file (@files) {
 	my $module = $file;
+
+	if($$options->progress) {
+	    $$output->lazy_progress("$file");
+	}
+
 	$module =~ s/.*?\/([^\/]*?)\.api$/$1/;
 	$self->parse_api_file($file,$module);
     }   
@@ -289,7 +298,7 @@
     my $module_file;
 
     if($$options->progress) {
-	$$output->progress("$file");
+	$$output->lazy_progress("$file");
     }
 
     open(IN, "< $file") || die "$file: $!\n";
@@ -585,24 +594,6 @@
     return sort(keys(%$translate_argument));
 }
 
-sub found_type {
-    my $self = shift;
-    my $type_found = \%{$self->{TYPE_FOUND}};
-
-    my $name = shift;
-
-    $$type_found{$name}++;
-}
-
-sub type_found {
-    my $self = shift;
-    my $type_found= \%{$self->{TYPE_FOUND}};
-
-    my $name = shift;
-
-    return $$type_found{$name};
-}
-
 sub is_allowed_type_format {
     my $self = shift;
     my $type_format = \%{$self->{TYPE_FORMAT}};
@@ -734,13 +725,6 @@
     return sort(keys(%{$$function_stub{$module}}));
 }
 
-sub all_internal_functions_found {
-    my $self = shift;
-    my $function_found = \%{$self->{FUNCTION_FOUND}};
-
-    return sort(keys(%$function_found));
-}
-
 sub function_internal_ordinal {
     my $self = shift;
     my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
@@ -892,24 +876,6 @@
     return $$function_stub{$module}{$name};
 }
 
-sub found_internal_function {
-    my $self = shift;
-    my $function_found = \%{$self->{FUNCTION_FOUND}};
-
-    my $name = shift;
-
-    $$function_found{$name}++;
-}
-
-sub internal_function_found {
-    my $self = shift;
-    my $function_found = \%{$self->{FUNCTION_FOUND}};
-
-    my $name = shift;
-
-    return $$function_found{$name};
-}
-
 ########################################################################
 # class methods
 #
diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check
index 9f24692..22d2ee9 100755
--- a/tools/winapi_check/winapi_check
+++ b/tools/winapi_check/winapi_check
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 
-# Copyright 1999-2000 Patrik Stridvall
+# Copyright 1999-2001 Patrik Stridvall
 
 # Note that winapi_check are using heuristics quite heavily.
 # So always remember that:
@@ -20,10 +20,8 @@
 }
 
 use config qw(
-    &file_absolutize &file_normalize
-    &file_type &files_filter
-    &file_skip &files_skip 
-    &get_spec_files
+    &file_type &files_filter &files_skip
+    &get_h_files	      
     $current_dir $wine_dir $winapi_dir $winapi_check_dir
 );
 use modules;
@@ -66,31 +64,42 @@
 
 my $nativeapi = 'nativeapi'->new($options, $output, "$winapi_check_dir/nativeapi.dat", "$wine_dir/configure.in", "$wine_dir/include/config.h.in");
 
-my %includes;
+my %declared_functions;
+
+my %include2info;
 {   
-    my @files = map {
-	s/^.\/(.*)$/$1/;
-	$_; 
-    } split(/\n/, `find . -name \\*.h`);
-    
+    my @files = get_h_files("winelib");
+
+    my $progress_current = 0;
+    my $progress_max = scalar(@files);   
+
     foreach my $file (@files) {
+	$progress_current++;
+	if($options->progress) {
+	    $output->lazy_progress("$file: file $progress_current of $progress_max");
+	}
+
 	my $file_dir = $file;
-	if(!($file_dir =~ s/(.*?)\/[^\/]*$/$1/)) {
+	if(!($file_dir =~ s%(.*?)/[^/]+$%$1%)) {
 	    $file_dir = ".";
 	}
-   
-	$includes{$file} = { name => $file };
 
-	open(IN, "< $file");
+	$include2info{$file} = { name => $file };
+
+	open(IN, "< $wine_dir/$file");
 	while(<IN>) {
 	    if(/^\s*\#\s*include\s*\"(.*?)\"/) {
 		my $header = $1;
-		if(-e "$file_dir/$header") {
-		    $includes{$file}{includes}{"$file_dir/$header"}++;
-		} elsif(-e "$file_dir/../$header") { # FIXME: This is not correct
-		    $includes{$file}{includes}{"$file_dir/../$header"}++; # FIXME: This is not correct
+		if(-e "$wine_dir/$file_dir/$header") {
+		    $include2info{$file}{includes}{"$file_dir/$header"}++;
+		} elsif(-e "$wine_dir/$file_dir/../$header") {
+		    if($file_dir =~ m%^(.*?)/[^/]+$%) {
+			$include2info{$file}{includes}{"$1/$header"}++;
+		    } else {
+			$include2info{$file}{includes}{"$header"}++;
+		    }
 		} elsif(-e "$wine_dir/include/$header") {
-		    $includes{$file}{includes}{"include/$header"}++;
+		    $include2info{$file}{includes}{"include/$header"}++;
 		} else {
 		    $output->write("$file: #include \"$header\" is not a local include\n");
 		}
@@ -102,18 +111,20 @@
     my @files2 = ("acconfig.h", "poppack.h", "pshpack1.h", "pshpack2.h", "pshpack4.h", "pshpack8.h",
                   "storage.h", "ver.h");
     foreach my $file2 (@files2) {
-	$includes{"include/$file2"}{used}++;
+	$include2info{"include/$file2"}{used}++;
     }    
 }
 
-my %declared_functions;
+my @c_files = $options->c_files;
+@c_files = files_skip(@c_files);
+@c_files = files_filter("winelib", @c_files);
 
-my @c_files = files_skip($options->c_files);
-my @h_files = files_skip($options->h_files);
+my @h_files = $options->h_files;
+@h_files = files_skip(@h_files);
+@h_files = files_filter("winelib", @h_files);
 
-my $progress_output;
-my $progress_current=0;
-my $progress_max=scalar(@c_files);
+my $progress_current = 0;
+my $progress_max = scalar(@c_files);
 
 if($options->headers) {
     $progress_max += scalar(@h_files);
@@ -125,77 +136,52 @@
 	if($options->progress) {
 	    $output->progress("$file: file $progress_current of $progress_max");
 	}
-	
+
 	my $found_function = sub {
 	    my $function = shift;
 
-	    my $documentation_line = $function->documentation_line;
-	    my $documentation = $function->documentation;
+	    $output->prefix($function->prefix);
+
 	    my $function_line = $function->function_line;
-	    my $linkage = $function->linkage;
-	    my $return_type = $function->return_type;
-	    my $calling_convention = $function->calling_convention;
 	    my $internal_name = $function->internal_name;
-	    my @argument_types = @{$function->argument_types};
-	    my @argument_names = @{$function->argument_names};
-	    my @argument_documentations = @{$function->argument_documentations};
 	    my $statements = $function->statements;
-	    
-	    foreach my $winapi (@winapis) {
-		my $module = $winapi->function_internal_module($internal_name);
-		if(!defined($module)) { next }
 
-		# FIXME: Not correct
-		my $external_name = $winapi->function_external_name($internal_name);
+	    if($options->headers_misplaced &&
+	       !($function->is_win16 && $function->is_win32) &&
+	       (($function->is_win16 && $file =~ /^include\/[^\/]*$/) ||
+		($function->is_win32 && $file =~ /^include\/wine\/[^\/]*$/)))
+	    {
+		$output->write("declaration misplaced\n");
+	    }
 
-		if(defined($external_name)) {
-		    $external_name = (split(/\s*&\s*/, $external_name))[0];
-		}
-
-		# FIXME: Kludge because of the THUNK variants
-		if(!defined($external_name)) {
-		    next;
-		}
-
-		my $output_function = sub {
-		    my $message = shift;
-
-		    $output->write("$file: $module: $return_type ");
-		    $output->write("$calling_convention ") if $calling_convention;
-		    $output->write("$internal_name(" . join(",", @argument_types) . "): $message\n");
-		};
-		
-		if(!defined($declared_functions{$winapi->name}{$external_name})) {
-		    $declared_functions{$winapi->name}{$external_name} = "$file";
+	    if(!defined($statements)) {
+		my $previous_function = $declared_functions{$internal_name};
+		if(!defined($previous_function)) {
+		    $declared_functions{$internal_name} = $function;
 		} elsif($options->headers_duplicated) {
-		    my $message = "declared more than once";
-		    if($file ne $declared_functions{$winapi->name}{$external_name}) {
-			$message .= ", first declaration in '" . $declared_functions{$winapi->name}{$external_name} . "'";
-		    }
-	            &$output_function("$message");
-		}
-
-		if($options->headers_misplaced) {
-		    if($file =~ /^include\/[^\/]*$/ && $winapi->name eq "win16") {
-			&$output_function("declaration misplaced");
-		    } elsif($file =~ /^include\/wine\/[^\/]*$/ && $winapi->name eq "win32") {
-			&$output_function("declaration misplaced");
-		    }
+		    my $file = $previous_function->file;
+		    my $function_line = $previous_function->function_line;
+		    $output->write("duplicate declaration (first declaration at $file:$function_line)\n");
 		}
 	    }
 	};
-	
+
 	my $found_preprocessor = sub {
 	    my $directive = shift;
 	    my $argument = shift;
 	};
-	
+
         winapi_parser::parse_c_file $options, $output, $file, $found_function, $found_preprocessor;
     }
 }
 
+my %module2functions = ();
+my %type_found = ();
+
 foreach my $file (@c_files) {
     my %functions = ();
+    my @includes = ();
+    my %needed_includes = ();
 
     my $file_module16 = $modules->allowed_modules_in_file("$current_dir/$file");
     my $file_module32 = $modules->allowed_modules_in_file("$current_dir/$file");
@@ -210,14 +196,16 @@
 	$file_dir = ".";
     }
    
-    my $file_type = file_type($file);
-
     my $found_function = sub {
 	my $function = shift;
 
+	$output->prefix($function->prefix);
+
 	my $internal_name = $function->internal_name;
 	$functions{$internal_name} = $function;
 
+	my $declared_function = $declared_functions{$internal_name};
+
 	my $documentation_line = $function->documentation_line;
 	my $documentation = $function->documentation;
 	my $linkage = $function->linkage;
@@ -228,41 +216,36 @@
 	my @argument_documentations = @{$function->argument_documentations};
 	my $statements = $function->statements;
 
+	my $module16 = $function->module16;
+	my $module32 = $function->module32;
+
 	my $external_name16 = $function->external_name16;
 	my $external_name32 = $function->external_name32;
 
-	if($options->global) {
-	    $win16api->found_type($return_type) if $options->win16;
-	    $win32api->found_type($return_type) if $options->win32;
-	    for my $argument (@argument_types) {
-		$win16api->found_type($argument) if $options->win16;
-		$win32api->found_type($argument) if $options->win32;
+	foreach my $module ($function->modules) {
+	    $module2functions{$module}{$internal_name} = $function;
+	    for my $type ($return_type, @argument_types) {
+		$type_found{$module}{$type}++;
 	    }
 	}
 
-	if($options->declared) {
-	    $win16api->found_internal_function($internal_name) if $options->win16;
-	    $win32api->found_internal_function($internal_name) if $options->win32;
+	foreach my $module ($function->modules) {
+	    $modules->found_module_in_dir($module, $file_dir);
 	}
 
-	if($file_type eq "winelib") {
-	    my $module16 = $function->module16;
-	    my $module32 = $function->module32;
-
-	    foreach my $module ($function->modules) {
-		$modules->found_module_in_dir($module, $file_dir);
+	if($options->shared) {
+	    if($win16api->is_shared_internal_function($internal_name) || 
+	       $win32api->is_shared_internal_function($internal_name)) 
+	    {
+		$output->write("is shared between Win16 and Win32\n");
 	    }
+	}
 
-	    $output->prefix("$file: " . $function->prefix);
+	if(defined($declared_function)) {
+	    $needed_includes{$declared_function->file}++;
+	}
 
-	    if($options->shared) {
-		if($win16api->is_shared_internal_function($internal_name) || 
-		   $win32api->is_shared_internal_function($internal_name)) 
-		{
-		    $output->write("is shared between Win16 and Win32\n");
-		}
-	    }
-
+	if(1) {
 	    # FIXME: Not correct
 	    if(defined($external_name16)) {
 		$external_name16 = (split(/\s*&\s*/, $external_name16))[0];
@@ -307,20 +290,15 @@
 
 	    if($options->local && $options->headers && $options->prototype) {
 		if($options->win16 && $options->report_module($module16)) {
-		    if(!defined($external_name16) || (!$nativeapi->is_function($external_name16) && 
-		       !defined($declared_functions{$win16api->name}{$external_name16})))
+		    if(!$nativeapi->is_function($internal_name) && 
+		       !defined($declared_functions{$internal_name}))
 		    {
-			if(!defined($external_name16) || ($external_name16 !~ /^DllEntryPoint$/ &&
-			    $internal_name !~ /^I(?:Malloc|Storage)16_fn/ &&
-			    $internal_name !~ /^(?:\Q$module16\E|THUNK|WIN16)_\Q$external_name16\E(?:16)?$/))
-			{
-			    $output->write("no prototype\n");
-			}
+			$output->write("no prototype\n");
 		    }
 		}
 
 		if($options->win32 && $options->report_module($module32)) {
-		    if(!defined($external_name32) || (!$nativeapi->is_function($external_name32) && 						          !defined($declared_functions{$win32api->name}{$external_name32})))
+		    if(!defined($external_name32) || (!$nativeapi->is_function($external_name32) && 						          !defined($declared_functions{$external_name32})))
 		    {
 			if(!defined($external_name32) || ($external_name32 !~ /^Dll(?:
 			   Install|CanUnloadNow|GetClassObject|GetVersion|
@@ -379,17 +357,15 @@
 	$nativeapi->found_conditional($_);
 
 	if($options->config) {
-	    if($file_type ne "application") {
-		if(!$nativeapi->is_conditional($_)) {
-		    if(/^HAVE_/ && !/^HAVE_(IPX|MESAGL|BUGGY_MESAGL|WINE_CONSTRUCTOR)$/)
-		    {
-			$output->write("$file: $_ is not declared as a conditional\n");
-		    }
-		} else {
-		    $conditional++;
-		    if(!$config) {
-			$output->write("$file: conditional $_ used but config.h is not included\n");
-		    }
+	    if(!$nativeapi->is_conditional($_)) {
+		if(/^HAVE_/ && !/^HAVE_(IPX|MESAGL|BUGGY_MESAGL|WINE_CONSTRUCTOR)$/)
+		{
+		    $output->write("$file: $_ is not declared as a conditional\n");
+		}
+	    } else {
+		$conditional++;
+		if(!$config) {
+		    $output->write("$file: conditional $_ used but config.h is not included\n");
 		}
 	    }
 	}
@@ -407,21 +383,41 @@
 		my $check_protection;
 		my $check_local;
 		if($argument =~ /^<(.*?)>$/) {
-		   $header = $1;
-		   if($file_type ne "application") {
-		       $check_protection = 1;
-		   } else {
-		       $check_protection = 0;
-		   }
-		   $check_local = 0;
-		} elsif($argument =~ /^"(.*?)"$/) {
-		   $header = $1;
-		   $check_protection = 0;
-		   $check_local = 1;
+		    $header = $1;
+		    $check_protection = 1;
+		    $check_local = 0;
+		} elsif($argument =~ /^\"(.*?)\"$/) {
+		    $header = $1;
+		    $check_protection = 0;
+		    $check_local = 1;
+		} else {
+		    $output->write("$file: #$directive $argument: is unparsable\n");
+
+		    $header = undef;
+		    $check_protection = 0;
+		    $check_local = 0;
 		}
 
-		if($check_protection) {
-		    if((-e "$wine_dir/include/$header" || -e "$file_dir/$header")) {
+		if(defined($header)) {
+		    if(-e "$wine_dir/include/$header") {
+			push @includes, "include/$header";
+		    } elsif(-e "$file_dir/$header") {
+			push @includes, "$file_dir/$header";
+		    } elsif(-e "$file_dir/../$header") {
+			if($file_dir =~ m%^(.*?)/[^/]+$%) {
+			    push @includes, "$1/$header";
+			} else {
+			    push @includes, "$header";
+			}
+		    } elsif($header eq "controls.h") { # FIXME: Kludge
+			push @includes, "dlls/user/controls.h";
+		    } elsif($check_local) {
+			$output->write("$file: #include \"$header\": file not found\n");
+		    }
+		}
+
+		if($check_protection && $header) {
+		    if((-e "$wine_dir/include/$header" || -e "$wine_dir/$file_dir/$header")) {
 			if($header !~ /^ctype.h$/) {
 			    $output->write("$file: #include \<$header\> is a local include\n");
 			}
@@ -448,26 +444,40 @@
 		    }
 		}
 
-		if($check_local) {
+		if($check_local && $header) {
 		    if(-e "$file_dir/$header") {
-			$includes{"$file_dir/$header"}{used}++;
-			foreach my $name (keys(%{$includes{"$file_dir/$header"}{includes}})) {
-			    $includes{$name}{used}++;
+			if($file_dir ne ".") {
+			    $include2info{"$file_dir/$header"}{used}++;
+			    foreach my $name (keys(%{$include2info{"$file_dir/$header"}{includes}})) {
+				$include2info{$name}{used}++;
+			    }
+			} else {
+			    $include2info{"$header"}{used}++;
+			    foreach my $name (keys(%{$include2info{"$header"}{includes}})) {
+				$include2info{$name}{used}++;
+			    }
 			}
-		    } elsif(-e "$file_dir/../$header") { # FIXME: Kludge
-			$includes{"$file_dir/../$header"}{used}++; # FIXME: This is not correct
-			foreach my $name (keys(%{$includes{"$file_dir/../$header"}{includes}})) { # FIXME: This is not correct
-			    $includes{$name}{used}++;
+		    } elsif(-e "$wine_dir/$file_dir/../$header") {
+			if($file_dir =~ m%^(.*?)/[^/]+$%) {
+			    $include2info{"$1/$header"}{used}++;
+			    foreach my $name (keys(%{$include2info{"$1/$header"}{includes}})) {
+				$include2info{$name}{used}++;
+			    }
+			} else {
+			    $include2info{"$header"}{used}++;
+			    foreach my $name (keys(%{$include2info{"$header"}{includes}})) {
+				$include2info{$name}{used}++;
+			    }
 			}
 		    } elsif($header eq "controls.h") { # FIXME: Kludge
-			$includes{"dlls/user/$header"}{used}++;
-			foreach my $name (keys(%{$includes{"dlls/user/$header"}{includes}})) {
-			    $includes{$name}{used}++;
+			$include2info{"dlls/user/$header"}{used}++;
+			foreach my $name (keys(%{$include2info{"dlls/user/$header"}{includes}})) {
+			    $include2info{$name}{used}++;
 			}
 		    } elsif(-e "$wine_dir/include/$header") {
-			$includes{"include/$header"}{used}++;
-			foreach my $name (keys(%{$includes{"include/$header"}{includes}})) {
-			    $includes{$name}{used}++;
+			$include2info{"include/$header"}{used}++;
+			foreach my $name (keys(%{$include2info{"include/$header"}{includes}})) {
+			    $include2info{$name}{used}++;
 			}
 		    } else {
 			$output->write("$file: #include \"$header\" is not a local include\n");
@@ -481,10 +491,32 @@
     
     if($options->config_unnessary) {
 	if($config && $conditional == 0) {
-	    $output->write("$file: includes config.h but do not use any conditionals\n");
+	    $output->write("$file: include2info config.h but do not use any conditionals\n");
 	}
     }
 
+    if($options->headers_needed) {
+	my %includes2;
+	foreach my $include (@includes) {
+	    $includes2{$include}++;
+	    foreach my $include (keys(%{$include2info{$include}{includes}})) {
+		$includes2{$include}++;
+	    }
+	}
+	foreach my $needed_include (sort(keys(%needed_includes))) {
+	    my $found = 0;
+	    foreach my $include (sort(keys(%includes2))) {
+		if($needed_include eq $include) {
+		    $found = 1;
+		}
+	    }
+	    if(!$found) {
+		$output->write("$file: file '$needed_include' needed but not included\n");
+	    }
+	}
+    }
+	
+
     winapi_local::check_file $options, $output, $file, \%functions;
 }
 
@@ -523,8 +555,14 @@
 	    if($options->declared) {
 		foreach my $winapi (@winapis) {
 		    if(!$winapi->is_module($module)) { next; }
+		    my $functions = $module2functions{$module};
 		    foreach my $internal_name ($winapi->all_internal_functions_in_module($module)) {
-			if(!$winapi->internal_function_found($internal_name)) {
+			my $function = $functions->{$internal_name};
+			if(!defined($function) && !$nativeapi->is_function($internal_name) &&
+			   !($module eq "user" && $internal_name =~
+			     /^(?:GlobalAddAtomA|GlobalDeleteAtom|GlobalFindAtomA|
+				GlobalGetAtomNameA|lstrcmpiA)$/x))
+			{
 			    $output->write("*.c: $module: $internal_name: " .
 					   "function declared but not implemented or declared external\n");
 			}
@@ -538,9 +576,9 @@
 if($options->global) {
     winapi_documentation::report_documentation $options, $output;
 
-    if($options->headers) {
-	foreach my $name (sort(keys(%includes))) {
-	    if(!$includes{$name}{used}) {
+    if($options->headers_unused) {
+	foreach my $name (sort(keys(%include2info))) {
+	    if(!$include2info{$name}{used}) {
 		if($options->include) {
 		    $output->write("*.c: $name: include file is never used\n");
 		}
@@ -548,8 +586,8 @@
 	}
     }
 
-    winapi_global::check $options, $output, $win16api, $nativeapi if $options->win16;
-    winapi_global::check $options, $output, $win32api, $nativeapi if $options->win32;
+    winapi_global::check $options, $output, $win16api, $nativeapi, \%type_found if $options->win16;
+    winapi_global::check $options, $output, $win32api, $nativeapi, \%type_found if $options->win32;
 
     $modules->global_report;
     $nativeapi->global_report;
diff --git a/tools/winapi_check/winapi_function.pm b/tools/winapi_check/winapi_function.pm
index b43f7ab..a43ff57 100644
--- a/tools/winapi_check/winapi_function.pm
+++ b/tools/winapi_check/winapi_function.pm
@@ -22,6 +22,13 @@
 }
 
 ########################################################################
+# is_win
+#
+
+sub is_win16 { my $self = shift; return defined($self->_module($win16api, @_)); }
+sub is_win32 { my $self = shift; return defined($self->_module($win32api, @_)); }
+
+########################################################################
 # external_name
 #
 
@@ -190,6 +197,7 @@
     my $module32 = $self->module32;
 
     my $file = $self->file;
+    my $function_line = $self->function_line;
     my $return_type = $self->return_type;
     my $internal_name = $self->internal_name;
     my $calling_convention = $self->calling_convention;
@@ -208,7 +216,12 @@
 	push @modules, $module;
 	$used{$module}++;
     }
-    $prefix .= "$file: ";
+    $prefix .= "$file:";
+    if(defined($function_line)) {
+	$prefix .= "$function_line: ";
+    } else {
+	$prefix .= "<>: ";
+    }
     if($#modules >= 0) {
 	$prefix .= join(" & ", @modules) . ": ";
     } else {
diff --git a/tools/winapi_check/winapi_global.pm b/tools/winapi_check/winapi_global.pm
index b926101..7249062 100644
--- a/tools/winapi_check/winapi_global.pm
+++ b/tools/winapi_check/winapi_global.pm
@@ -7,12 +7,13 @@
     my $output = shift;
     my $winapi = shift;
     my $nativeapi = shift;
+    my $type_found = shift;
 
     my $winver = $winapi->name;
 
     if($options->argument) {
 	foreach my $type ($winapi->all_declared_types) {
-	    if(!$winapi->type_found($type) && !$winapi->is_limited_type($type) && $type ne "CONTEXT86 *") {
+	    if(!$$type_found{$type} && !$winapi->is_limited_type($type) && $type ne "CONTEXT86 *") {
 		$output->write("*.c: $winver: ");
 		$output->write("type ($type) not used\n");
 	    }
diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm
index e137f00..21b9f2a 100644
--- a/tools/winapi_check/winapi_options.pm
+++ b/tools/winapi_check/winapi_options.pm
@@ -118,9 +118,12 @@
     "implemented" => { default => 0, parent => "local", description => "implemented checking" },
     "implemented-win32" => { default => 0, parent => "implemented", description => "implemented as win32 checking" },
     "include" => { default => 1, parent => "global", description => "include checking" },
-    "headers" => { default => 0, parent => "global", description => "headers checking" },
+
+    "headers" => { default => 0, description => "headers checking" },
     "headers-duplicated" => { default => 0, parent => "headers", description => "duplicated function declarations checking" },
     "headers-misplaced" => { default => 0, parent => "headers", description => "misplaced function declarations checking" },
+    "headers-needed" => { default => 1, parent => "headers", description => "headers needed checking" },
+    "headers-unused" => { default => 0, parent => "headers", description => "headers unused checking" },
 );
 
 my %short_options = (
@@ -147,6 +150,7 @@
     my $h_files = \@{$self->{H_FILES}};
     my $module = \${$self->{MODULE}};
     my $global = \${$self->{GLOBAL}};
+    my $headers = \${$self->{HEADERS}};
 
     my @files;
 
@@ -285,11 +289,14 @@
 	}
     }
 
+    if($#h_files >= 0) {
+	$$headers = 1;
+    }
+
     if($#c_files == -1 && $#h_files == -1 &&
        ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir)))
     {
 	@paths = ".";
-	push @h_files, "$wine_dir/include";
     } else {
 	$$global = 0;
     }
@@ -308,8 +315,8 @@
 	} split(/\n/, `$c_command`));
     }
 
-    if($#h_files != -1) {
-	my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
+    if($#paths != -1 || $#h_files != -1) {
+	my $h_command = "find " . join(" ", @paths, @h_files) . " -name \\*.h";
 	my %found;
 
 	@$h_files = sort(map {
diff --git a/tools/winapi_check/winapi_parser.pm b/tools/winapi_check/winapi_parser.pm
index 3ecda04..8e99f83 100644
--- a/tools/winapi_check/winapi_parser.pm
+++ b/tools/winapi_check/winapi_parser.pm
@@ -62,8 +62,9 @@
 
 	$function->file($file);
 	$function->debug_channels([@$debug_channels]);
-	$function->documentation($documentation);
 	$function->documentation_line($documentation_line);
+	$function->documentation($documentation);
+	$function->function_line($function_line);
 	$function->linkage($linkage);
 	$function->return_type($return_type); 
 	$function->calling_convention($calling_convention);
@@ -255,8 +256,8 @@
 	    if($internal_name && $level == 0) {
 		&$function_end;
 	    }
-	    next;	    
-	} elsif(/(extern\s+|static\s+)?((struct\s+|union\s+|enum\s+)?\w+((\s*\*)+\s*|\s+))
+	    next;
+	} elsif(/(extern\s+|static\s+)?((struct\s+|union\s+|enum\s+|signed\s+|unsigned\s+)?\w+((\s*\*)+\s*|\s+))
             ((__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK)\s+)?
 	    (\w+(\(\w+\))?)\s*\(([^\)]*)\)\s*(\{|\;)/sx)
         {