- Updated API files
- Better headers and prototype checking
- Prototype checking now called --prototype instead of --headers
- New options --headers-{duplicated,misplaced} for
  duplicated/misplaced functions checking of the headers.
- Minor bug fixes.

diff --git a/tools/winapi_check/modules.dat b/tools/winapi_check/modules.dat
index e40f151..e1d3892 100644
--- a/tools/winapi_check/modules.dat
+++ b/tools/winapi_check/modules.dat
@@ -145,14 +145,21 @@
 
 dlls/ole32
 
-% dlls/ole32/ole2nls.spec
-
-dlls/ole32
-
 % dlls/ole32/ole32.spec
 
 dlls/ole32
 
+% dlls/ole32/ole2conv.spec
+
+% dlls/ole32/ole2nls.spec
+
+dlls/ole32
+ole
+
+% dlls/ole32/ole2prox.spec
+
+% dlls/ole32/ole2thk.spec
+
 % dlls/ole32/storage.spec
 
 dlls/ole32
@@ -258,6 +265,11 @@
 memory
 windows
 
+% dlls/user/ddeml.spec
+
+dlls/user
+misc
+
 % dlls/user/user.spec
 
 controls
@@ -393,10 +405,6 @@
 
 % if1632/comm.spec
 
-% if1632/ddeml.spec
-
-misc
-
 % if1632/dispdib.spec
 
 graphics
@@ -414,16 +422,6 @@
 scheduler
 win32
 
-% if1632/ole2conv.spec
-
-% if1632/ole2nls.spec
-
-ole
-
-% if1632/ole2prox.spec
-
-% if1632/ole2thk.spec
-
 % if1632/system.spec
 
 misc
diff --git a/tools/winapi_check/modules.pm b/tools/winapi_check/modules.pm
index 2018533..e1d2cb4 100644
--- a/tools/winapi_check/modules.pm
+++ b/tools/winapi_check/modules.pm
@@ -52,6 +52,11 @@
 
 	if(/^%\s+(.*?)$/) {
 	    $spec_file = $1;
+	   
+	    if(!-f "$wine_dir/$spec_file") {
+		$$output->write("$module_file: $spec_file: file ($spec_file) doesn't exist or is no file\n");
+	    } 
+
 	    if($wine_dir eq ".") {
 		$all_spec_files{$spec_file}--;
 	    } else {
diff --git a/tools/winapi_check/nativeapi.dat b/tools/winapi_check/nativeapi.dat
index 8a3de0f..6e0c0af 100644
--- a/tools/winapi_check/nativeapi.dat
+++ b/tools/winapi_check/nativeapi.dat
@@ -16,6 +16,7 @@
 _xmknod
 _xstat
 abs
+accept
 access
 acos
 asctime
@@ -26,14 +27,18 @@
 atof
 atoi
 atol
+bind
 bsearch
 bzero
 calloc
 ceil
 cfgetospeed
 chmod
+clock
 close
 closedir
+closesocket
+connect
 cos
 cosh
 ctime
@@ -66,23 +71,39 @@
 fread
 free
 frexp
+freopen
+fscanf
 fseek
 fsetpos
 fsync
+ftell
 ftruncate
 fwrite
+getc
 getcwd
 getenv
+gethostbyaddr
+gethostbyname
+gethostname
 getlogin
 getnetbyname
+getpeername
 getpid
 getpwuid
+gets
+getservbyname
+getsockname
 gettimeofday
 getuid
 gmtime
+htonl
+htons
 hypot
+inet_addr
 inet_network
+inet_ntoa
 ioctl
+ioctlsocket
 isalnum
 isalpha
 isatty
@@ -102,6 +123,7 @@
 labs
 ldexp
 ldiv
+listen
 localtime
 log
 log10
@@ -121,6 +143,8 @@
 mprotect
 msync
 munmap
+ntohl
+ntohs
 open
 opendir
 perror
@@ -128,6 +152,7 @@
 poll
 pow
 printf
+putc
 putchar
 putenv
 puts
@@ -137,19 +162,25 @@
 read
 readdir
 realloc
+recv
+recvfrom
 remove
 rename
 rmdir
 select
+send
+sendto
 setbuf
 setlocale
 setsid
+setsockopt
 settimeofday
 setvbuf
 shmat
 shmctl
 shmdt
 shmget
+shutdown
 sigaction
 sigaddset
 sigaltstack
@@ -160,6 +191,7 @@
 sin
 sinh
 sleep
+socket
 snprintf
 sprintf
 sqrt
diff --git a/tools/winapi_check/win32/opengl32.api b/tools/winapi_check/win32/opengl32.api
index 7e874ee..fd8d7d8 100644
--- a/tools/winapi_check/win32/opengl32.api
+++ b/tools/winapi_check/win32/opengl32.api
@@ -1,3 +1,8 @@
+%double
+
+GLclampd
+GLdouble
+
 %long
 
 BOOL
@@ -6,9 +11,7 @@
 GLbitfield
 GLboolean
 GLbyte
-GLclampd
 GLclampf
-GLdouble
 GLenum
 GLfloat
 GLint
diff --git a/tools/winapi_check/winapi.pm b/tools/winapi_check/winapi.pm
index c91cdab..cc96b70 100644
--- a/tools/winapi_check/winapi.pm
+++ b/tools/winapi_check/winapi.pm
@@ -215,6 +215,7 @@
     my $output = \${$self->{OUTPUT}};
     my $function_arguments = \%{$self->{FUNCTION_ARGUMENTS}};
     my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
+    my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
     my $function_stub = \%{$self->{FUNCTION_STUB}};
     my $function_module = \%{$self->{FUNCTION_MODULE}};
     my $modules = \%{$self->{MODULES}};
@@ -256,6 +257,7 @@
 	    $ordinal = $1;
 
 	    # FIXME: Internal name existing more than once not handled properly
+	    $$function_external_name{$internal_name} = $external_name;
 	    $$function_arguments{$internal_name} = $arguments;
 	    $$function_calling_convention{$internal_name} = $calling_convention;
 	    if(!$$function_module{$internal_name}) {
@@ -571,6 +573,15 @@
     return $$function_calling_convention{$name};
 }
 
+sub function_external_name {
+    my $self = shift;
+    my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
+
+    my $name = shift;
+
+    return $$function_external_name{$name};
+}
+
 sub is_function {
     my $self = shift;
     my $function_calling_convention = \%{$self->{FUNCTION_CALLING_CONVENTION}};
diff --git a/tools/winapi_check/winapi_check b/tools/winapi_check/winapi_check
index 75e6aa2..f517dfa 100755
--- a/tools/winapi_check/winapi_check
+++ b/tools/winapi_check/winapi_check
@@ -1,6 +1,16 @@
 #!/usr/bin/perl -w
 
-# Copyright 1999 Patrik Stridvall
+# Copyright 1999-2000 Patrik Stridvall
+
+# Note that winapi_check are using heuristics quite heavily.
+# So always remember that:
+#
+# "Heuristics are bug ridden by definition. 
+#  If they didn't have bugs, then they'd be algorithms."
+#
+# In other words, reported bugs are only potential bugs not
+# real bugs, so they are called issues rather than bugs.
+#
 
 use strict;
 
@@ -92,6 +102,7 @@
 
 my $win16api = 'winapi'->new($options, $output, "win16", "$winapi_check_dir/win16");
 my $win32api = 'winapi'->new($options, $output, "win32", "$winapi_check_dir/win32");
+my @winapis = ($win16api, $win32api);
 
 if($options->global) {
     'winapi'->read_all_spec_files($modules, $wine_dir, $current_dir, \&file_type, $win16api, $win32api);
@@ -176,12 +187,49 @@
 	    my $linkage = shift;
 	    my $return_type = shift;
 	    my $calling_convention = shift;
-	    my $name = shift;
-	    my $refarguments = shift;
-	    my @arguments = @$refarguments;
+	    my $internal_name = shift;
+	    my $refargument_types = shift;
+	    my @argument_types = @$refargument_types;
+	    my $refargument_names = shift;
+	    my @argument_names = @$refargument_names;
 	    my $statements = shift;
-	    
-	    $declared_functions{$name}++;
+
+	    foreach my $winapi (@winapis) {
+		my $module = $winapi->function_module($internal_name);
+		if(!defined($module)) { next }
+
+		my $external_name = $winapi->function_external_name($internal_name);
+		# 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";
+		} 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 $found_preprocessor = sub {
@@ -221,13 +269,15 @@
 	my $return_type = shift;
 	my $calling_convention = shift;
 	my $internal_name = shift;
-	my $external_name = $internal_name;
 	my $refargument_types = shift;
 	my @argument_types = @$refargument_types;
 	my $refargument_names = shift;
 	my @argument_names = @$refargument_names;
 	my $statements = shift;
 
+	my $external_name16 = $win16api->function_external_name($internal_name);
+	my $external_name32 = $win32api->function_external_name($internal_name);
+
 	if($options->global) {
 	    $win16api->found_type($return_type) if $options->win16;
 	    $win32api->found_type($return_type) if $options->win32;
@@ -242,40 +292,7 @@
 	
 	if($file_type ne "application") {
 	    my $module16 = $win16api->function_module($internal_name);
-	    if(!defined($module16)) {
-		if($internal_name =~ /^(.*?)_(.*?)$/) {
-		    my $module2 = lc($1);
-		    my $name2 = $2;
-		    if($win16api->is_module($module2)) {
-			$module16 = $win16api->function_module($name2);
-			if(defined($module16)) {
-			    if(uc($module16) !~ /\U$module2\E/) {
-				$external_name = $name2;
-			    } else {
-				$module16 = undef;
-			    }
-			}
-		    }
-		}
-	    }
-
 	    my $module32 = $win32api->function_module($internal_name);
-	    if(!defined($module32)) {
-		if($internal_name =~ /^(.*?)_(.*?)$/) {
-		    my $module2 = lc($1);
-		    my $name2 = $2;
-		    if($win32api->is_module($module2)) {
-			$module32 = $win32api->function_module($name2);
-			if(defined($module32)) {
-			    if(uc($module32) =~ /\U$module2\E/) {
-				$external_name = $name2;
-			    } else {
-				$module32 = undef;
-			    }
-			}
-		    }
-		}
-	    }
 
 	    my $function = 'winapi_function'->new;
 	    $functions{$internal_name} = $function;
@@ -285,7 +302,8 @@
 	    $function->file($file);
 	    $function->return_type($return_type); 
 	    $function->calling_convention($calling_convention);
-	    $function->external_name($external_name);
+	    $function->external_name16($external_name16);
+	    $function->external_name32($external_name32);
 	    $function->internal_name($internal_name);
 	    $function->argument_types([@argument_types]);
 	    $function->argument_names([@argument_names]);
@@ -337,25 +355,43 @@
 		}
 	    }
 
-	    if($options->local && $options->headers) {
-		if(!$declared_functions{$internal_name}) {
-		    if($options->win16 && $options->report_module($module16)) {
-			&$output16("no prototype");
+	    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(!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)?$/))
+			{
+			    &$output16("no prototype");
+			}
 		    }
-		    if($options->win32 && $options->report_module($module32)) {
-			&$output32("no prototype");
+		}
+
+		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) || ($external_name32 !~ /^Dll(?:
+			   Install|CanUnloadNow|GetClassObject|GetVersion|
+			   RegisterServer|RegisterServerEx|UnregisterServer)|DriverProc$/x && 
+			   $internal_name !~ /^COMCTL32_Str/ &&
+			   $internal_name !~ /^(?:\Q$module32\E|wine)_(?:\Q$external_name32\E|\d+)$/))
+			{
+			    &$output32("no prototype");
+			}
 		    }
-		} 
+		}
 	    }
 
 	    if($options->local && $options->argument) {
 		if($options->win16 && $options->report_module($module16)) {
 		  winapi_local::check_function $options, $output16,
-		    $return_type, $calling_convention, $external_name, $internal_name, [@argument_types], $win16api;
+		    $return_type, $calling_convention, $external_name16, $internal_name, [@argument_types], $win16api;
 		}	
 		if($options->win32 && $options->report_module($module32)) {
 		  winapi_local::check_function $options, $output32,
-		    $return_type, $calling_convention, $external_name, $internal_name, [@argument_types], $win32api;
+		    $return_type, $calling_convention, $external_name32, $internal_name, [@argument_types], $win32api;
 		}
 	    }
 
diff --git a/tools/winapi_check/winapi_function.pm b/tools/winapi_check/winapi_function.pm
index fa166ca..50a52b5 100644
--- a/tools/winapi_check/winapi_function.pm
+++ b/tools/winapi_check/winapi_function.pm
@@ -66,15 +66,26 @@
     return $$calling_convention;
 }
 
-sub external_name {
+sub external_name16 {
     my $self = shift;
-    my $external_name = \${$self->{EXTERNAL_NAME}};
+    my $external_name16 = \${$self->{EXTERNAL_NAME16}};
 
     local $_ = shift;
 
-    if(defined($_)) { $$external_name = $_; }
+    if(defined($_)) { $$external_name16 = $_; }
     
-    return $$external_name;
+    return $$external_name16;
+}
+
+sub external_name32 {
+    my $self = shift;
+    my $external_name32 = \${$self->{EXTERNAL_NAME32}};
+
+    local $_ = shift;
+
+    if(defined($_)) { $$external_name32 = $_; }
+    
+    return $$external_name32;
 }
 
 sub internal_name {
diff --git a/tools/winapi_check/winapi_local.pm b/tools/winapi_check/winapi_local.pm
index 576c572..5dd90a4 100644
--- a/tools/winapi_check/winapi_local.pm
+++ b/tools/winapi_check/winapi_local.pm
@@ -13,23 +13,23 @@
     my @argument_types = @$refargument_types;
     my $winapi = shift;
 
-    my $module = $winapi->function_module($external_name);
+    my $module = $winapi->function_module($internal_name);
        
     if($winapi->name eq "win16") {
-	my $name16 = $external_name;
+	my $name16 = $internal_name;
 	$name16 =~ s/16$//;
-	if($name16 ne $external_name && $winapi->function_stub($name16)) {
+	if($name16 ne $internal_name && $winapi->function_stub($name16)) {
 	    if($options->implemented) {
 		&$output("function implemented but declared as stub in .spec file");
 	    }
 	    return;
-	} elsif($winapi->function_stub($external_name)) {
+	} elsif($winapi->function_stub($internal_name)) {
 	    if($options->implemented_win32) {
 		&$output("32-bit variant of function implemented but declared as stub in .spec file");
 	    }
 	    return;
 	}
-    } elsif($winapi->function_stub($external_name)) {
+    } elsif($winapi->function_stub($internal_name)) {
 	if($options->implemented) {
 	    &$output("function implemented but declared as stub in .spec file");
 	}
@@ -80,8 +80,8 @@
 	}
     }
 
-    my $declared_calling_convention = $winapi->function_calling_convention($external_name);
-    my @declared_argument_kinds = split(/\s+/, $winapi->function_arguments($external_name));
+    my $declared_calling_convention = $winapi->function_calling_convention($internal_name);
+    my @declared_argument_kinds = split(/\s+/, $winapi->function_arguments($internal_name));
 
     if($declared_calling_convention =~ /^register|interrupt$/) {
 	push @declared_argument_kinds, "ptr";
@@ -112,7 +112,7 @@
     }
 
     if($#argument_types != -1 && $argument_types[$#argument_types] eq "CONTEXT *" &&
-       $external_name !~ /^(Get|Set)ThreadContext$/) # FIXME: Kludge
+       $internal_name !~ /^(Get|Set)ThreadContext$/) # FIXME: Kludge
     {
 	$#argument_types--;
     }
diff --git a/tools/winapi_check/winapi_options.pm b/tools/winapi_check/winapi_options.pm
index 533a793..5c90f91 100644
--- a/tools/winapi_check/winapi_options.pm
+++ b/tools/winapi_check/winapi_options.pm
@@ -61,7 +61,7 @@
     "calling-convention" => { default => 0, parent => "local", description => "calling convention checking" },
     "misplaced" => { default => 1, parent => "local", description => "check for misplaced functions" },
     "statements"  => { default => 0, parent => "local", description => "check for statements inconsistances" },
-    "cross-call" => { default => 0, parent => "statements", description => "check for cross calling functions" },
+    "cross-call" => { default => 0, parent => "statements",  description => "check for cross calling functions" },
     "cross-call-win32-win16" => { 
 	default => 0, parent => "cross-call", description => "check for cross calls between win32 and win16"
      },
@@ -71,13 +71,16 @@
     "debug-messages" => { default => 0, parent => "statements", description => "check for debug messages inconsistances" },
     "documentation" => { default => 1, parent => "local", description => "check for documentation inconsistances\n" },
     "documentation-width" => { default => 0, parent => "documentation", description => "check for documentation width inconsistances\n" },
+    "prototype" => { default => 0, parent => ["local", "headers"], description => "prototype checking" },
 
     "global" => { default => 1, description => "global checking" },
-    "declared" => { default => 1, parent => "global", description => "declared checking" }, 
+    "declared" => { default => 1, parent => "global", description => "declared checking" },
     "implemented" => { default => 1, parent => "global", 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-duplicated" => { default => 0, parent => "headers", description => "duplicated function declarations checking" },
+    "headers-misplaced" => { default => 0, parent => "headers", description => "misplaced function declarations checking" },
     "stubs" => { default => 0, parent => "global", description => "stubs checking" }
 );
 
@@ -106,6 +109,8 @@
     my $module = \${$self->{MODULE}};
     my $global = \${$self->{GLOBAL}};
 
+    my @files;
+
     if($wine_dir eq ".") {
 	$$global = 1;
     } else {
@@ -151,8 +156,16 @@
 	    if(defined($option)) {
 		my $key = $$option{key};
 		my $parser = $$option{parser};
-		my $parent = $$option{parent};
 		my $refvalue = \${$self->{$key}};
+		my @parents = ();
+		
+		if(defined($$option{parent})) {
+		    if(ref($$option{parent}) eq "ARRAY") {
+			@parents = @{$$option{parent}};
+		    } else {
+			@parents = $$option{parent};
+		    }
+		}
 
 		if(defined($parser)) { 
 		    $$refvalue = &$parser($prefix,$value);
@@ -167,12 +180,23 @@
 		}
 
 		if((ref($$refvalue) eq "HASH" && $$refvalue->{active}) || $$refvalue) {
-		    while(defined($parent)) {
-			my $parentkey = $options{$parent}{key};
-			my $refparentvalue = \${$self->{$parentkey}};
-			
-			$$refparentvalue = 1;
-			$parent = $options{$parent}{parent};
+		    while($#parents >= 0) {
+			my @old_parents = @parents;
+			@parents = ();
+			foreach my $parent (@old_parents) {
+			    my $parentkey = $options{$parent}{key};
+			    my $refparentvalue = \${$self->{$parentkey}};
+			    
+			    $$refparentvalue = 1;
+
+			    if(defined($options{$parent}{parent})) {
+				if(ref($options{$parent}{parent}) eq "ARRAY") {
+				    push @parents, @{$options{$parent}{parent}};
+				} else {
+				    push @parents, $options{$parent}{parent};
+				}
+			    }
+			}
 		    }
 		}
 		next;
@@ -201,7 +225,7 @@
 		return undef;
 	    }
 
-	    push @$c_files, $_;
+	    push @files, $_;
 	}
     }
 
@@ -209,30 +233,56 @@
 	return $self;
     }
 
-    my $c_paths;
-    if($#$c_files == -1 || ($#$c_files == 0 && $$c_files[0] eq $wine_dir)) {
-	$c_paths = ".";
+    my @paths = ();
+    my @c_files = ();
+    my @h_files = ();
+    foreach my $file (@files) {
+	if($file =~ /\.c$/) {
+	    push @c_files, $file;
+	} elsif($file =~ /\.h$/) {
+	    push @h_files, $file;
+	} else {
+	    push @paths, $file;
+	}
+    }
+
+    if($#c_files == -1 && $#h_files == -1 &&
+       ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir)))
+    {
+	@paths = ".";
+	push @h_files, "$wine_dir/include";
     } else {
-	$c_paths = join(" ", @$c_files);
 	$$global = 0;
     }
 
-    my $h_paths = "$wine_dir/include $wine_dir/include/wine";
+    if($#paths != -1 || $#c_files != -1) {
+	my $c_command = "find " . join(" ", @paths, @c_files) . " -name \\*.c";
+	my %found;
+	@$c_files = sort(map {
+	    s/^\.\/(.*)$/$1/;
+	    if(defined($found{$_}) || /glue\.c|spec\.c$/) {
+		();
+	    } else {
+		$found{$_}++;
+		$_;
+	    }
+	} split(/\n/, `$c_command`));
+    }
 
-    @$c_files = sort(map {
-	s/^.\/(.*)$/$1/;
-	if(/glue\.c|spec\.c$/) {
-	    ();
-	} else {
-	    $_;
-	}
-    } split(/\n/, `find $c_paths -name \\*.c`));
+    if($#h_files != -1) {
+	my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
+	my %found;
 
-    @$h_files = sort(map {
-	s/^.\/(.*)$/$1/;
-	$_;
-    } split(/\n/, `find $h_paths -name \\*.h`));
-
+	@$h_files = sort(map {
+	    s/^\.\/(.*)$/$1/;
+	    if(defined($found{$_})) {
+		();
+	    } else {
+		$found{$_}++;
+		$_;
+	    }
+	} split(/\n/, `$h_command`));
+    }
     return $self;
 }